In the Windows kernel, you will see a thing called a LUID
, commonly pronounced /loo-id/. The kernel documentation says
The LUID structure is an opaque structure that specifies an identifier that is guaranteed to be unique on the local machine. For more information, see the reference page for LUID in the Microsoft Windows SDK documentation.
If you go to the Windows SDK documentation, you get
Describes a local identifier for an adapter.
Remarks
This structure is used by the ID3D12Device::GetAdapterLuid and GetSharedResourceAdapterLuid methods.
Somehow, the display driver folks took over the LUID
documentation and made it be all about display drivers. It’s as if the file system team had taken over the LARGE_INTEGER
documentation and made it say “The LARGE_INTEGER
structure holds the size of a file in bytes” because the GetFileSizeEx
function uses the LARGE_INTEGER
structure for that purpose.
Really, a LUID
is a structure that holds a 64-bit integer (broken into two 32-bit parts). The 64-bit integer is “locally unique”, in the sense that it will not match any other LUID
generated from the same system until the system is rebooted.
You can ask for a LUID
to be generated for you by calling AllocateLocallyUniqueId
.
Since LUID
s are only unique to the system, you probably shouldn’t send them to other systems (since they won’t be unique there). And since LUID
s lose uniqueness when the system reboots, you probably shouldn’t save them anywhere persistent, because they won’t make sense after a reboot. The purpose of a LUID
is to let the system identify things whose lifetimes do not extend beyond a reboot.
Some minor PTSD here .. LUID is defined as a struct of two 32-bit values, not a 64-bit int (or a union of those things like LARGE_INTEGER), so this can have an unexpected effect on packing and alignment when used in other structures, such as TOKEN_PRIVILEGES { DWORD count, LUID luid, DWORD attributes }
Once had some C# code working ok on 32-bit OS but crashing on 64-bit.. took a little while to pinpoint this.
<code>
The links to the kernel documentation and the SDK documentation go to the same place; I presume the latter is supposed to point somewhere else in the giant pile of documentation from Microsoft.
Thanks.
Can’t help but think that this could just be, more or less, somewhere in the kernel:
Making updates atomic is left as an exercise for the reader.
(note: I am not a kernel developer and haven’t touched C in 15 years)
That’s exactly how it’s done.
x.com/0gtweet/status/1829576931496669207
See Shawn’s comment about the type actually being defined as a pair of 32-bit integers. Depending on the platform, the compiler may or may not lay out such a struct identically to a single 64-bit integer.
Sometimes it’s important that IDs are not so easily guessable (not sure if that’s the case for LUID, but maybe).
This can be done using a 64-bit block cipher with a 64-bit block size operated in CTR mode: you just successively encrypt 0, 1, 2, … with the block cipher to get the LUIDs. (Actually you should start from a random initialization vector instead of 0, but.)
A 64-bit cipher is really weak however, so at the end of the day it might not be possible to make LUIDs cryptographically unpredictable. Edit: I confused the block...