mirror of
https://github.com/reactos/reactos.git
synced 2025-05-25 12:14:32 +00:00
[NTOSKRNL] Rewrite/fix our UUID generation implementation
So that it matches Windows behavior Also implement ExUuidCreate that will generate UUID version 1 The implementation is based on the RFC 4122
This commit is contained in:
parent
2d9673c68f
commit
eb8b481cd4
5 changed files with 327 additions and 165 deletions
|
@ -711,7 +711,11 @@ ExpInitSystemPhase1(VOID)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize UUIDs */
|
/* Initialize UUIDs */
|
||||||
ExpInitUuids();
|
if (ExpUuidInitialization() == FALSE)
|
||||||
|
{
|
||||||
|
DPRINT1("Executive: Uuid initialization failed\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize keyed events */
|
/* Initialize keyed events */
|
||||||
if (ExpInitializeKeyedEventImplementation() == FALSE)
|
if (ExpInitializeKeyedEventImplementation() == FALSE)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
* PURPOSE: UUID generator
|
* PURPOSE: UUID generator
|
||||||
* PROGRAMMERS: Eric Kohl
|
* PROGRAMMERS: Eric Kohl
|
||||||
* Thomas Weidenmueller
|
* Thomas Weidenmueller
|
||||||
|
* Pierre Schweitzer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
@ -25,75 +26,81 @@
|
||||||
#define SECS_15_OCT_1582_TO_1601 ((17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY)
|
#define SECS_15_OCT_1582_TO_1601 ((17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY)
|
||||||
#define TICKS_15_OCT_1582_TO_1601 ((ULONGLONG)SECS_15_OCT_1582_TO_1601 * TICKSPERSEC)
|
#define TICKS_15_OCT_1582_TO_1601 ((ULONGLONG)SECS_15_OCT_1582_TO_1601 * TICKSPERSEC)
|
||||||
|
|
||||||
|
/* 10000 in 100-ns model = 0,1 microsecond */
|
||||||
|
#define TIME_FRAME 10000
|
||||||
|
|
||||||
#if defined (ALLOC_PRAGMA)
|
#if defined (ALLOC_PRAGMA)
|
||||||
#pragma alloc_text(INIT, ExpInitUuids)
|
#pragma alloc_text(INIT, ExpUuidInitialization)
|
||||||
|
#pragma alloc_text(INIT, ExLuidInitialization)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* GLOBALS ****************************************************************/
|
/* GLOBALS ****************************************************************/
|
||||||
|
|
||||||
static FAST_MUTEX ExpUuidLock;
|
FAST_MUTEX ExpUuidLock;
|
||||||
static ULARGE_INTEGER UuidLastTime;
|
LARGE_INTEGER ExpUuidLastTimeAllocated;
|
||||||
static ULONG UuidSequence;
|
ULONG ExpUuidSequenceNumber = 0;
|
||||||
static BOOLEAN UuidSequenceInitialized = FALSE;
|
BOOLEAN ExpUuidSequenceNumberValid;
|
||||||
static BOOLEAN UuidSequenceChanged = FALSE;
|
BOOLEAN ExpUuidSequenceNumberNotSaved = FALSE;
|
||||||
static UCHAR UuidSeed[SEED_BUFFER_SIZE];
|
UUID_CACHED_VALUES_STRUCT ExpUuidCachedValues = {0ULL, 0xFFFFFFFF, 0, 0, { 0x80, 0x6E, 0x6F, 0x6E, 0x69, 0x63}};
|
||||||
static ULONG UuidCount;
|
BOOLEAN ExpUuidCacheValid = FALSE;
|
||||||
static LARGE_INTEGER LuidIncrement;
|
ULONG ExpLuidIncrement = 1;
|
||||||
static LARGE_INTEGER LuidValue;
|
LARGE_INTEGER ExpLuid = {.LowPart = 0x3e9, .HighPart = 0x0};
|
||||||
UUID_CACHED_VALUES_STRUCT ExpUuidCachedValues = { 0ULL, 0xFFFFFFFF, 0, 0, { 0x80, 0x6E, 0x6F, 0x6E, 0x69, 0x63 } };
|
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
VOID
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
BOOLEAN
|
||||||
INIT_FUNCTION
|
INIT_FUNCTION
|
||||||
NTAPI
|
NTAPI
|
||||||
ExpInitUuids(VOID)
|
ExpUuidInitialization(VOID)
|
||||||
{
|
{
|
||||||
ExInitializeFastMutex(&ExpUuidLock);
|
ExInitializeFastMutex(&ExpUuidLock);
|
||||||
|
|
||||||
KeQuerySystemTime((PLARGE_INTEGER)&UuidLastTime);
|
ExpUuidSequenceNumberValid = FALSE;
|
||||||
UuidLastTime.QuadPart += TICKS_15_OCT_1582_TO_1601;
|
KeQuerySystemTime(&ExpUuidLastTimeAllocated);
|
||||||
|
|
||||||
UuidCount = TICKS_PER_CLOCK_TICK;
|
return TRUE;
|
||||||
RtlZeroMemory(UuidSeed, SEED_BUFFER_SIZE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define VALUE_BUFFER_SIZE 256
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
#define VALUE_BUFFER_SIZE 20
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
ExpLoadUuidSequence(PULONG Sequence)
|
ExpUuidLoadSequenceNumber(PULONG Sequence)
|
||||||
{
|
{
|
||||||
UCHAR ValueBuffer[VALUE_BUFFER_SIZE];
|
UCHAR ValueBuffer[VALUE_BUFFER_SIZE];
|
||||||
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
|
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
UNICODE_STRING Name;
|
UNICODE_STRING KeyName, ValueName;
|
||||||
HANDLE KeyHandle;
|
HANDLE KeyHandle;
|
||||||
ULONG ValueLength;
|
ULONG ValueLength;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
RtlInitUnicodeString(&Name,
|
PAGED_CODE();
|
||||||
L"\\Registry\\Machine\\Software\\Microsoft\\Rpc");
|
|
||||||
|
RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\Software\\Microsoft\\Rpc");
|
||||||
|
RtlInitUnicodeString(&ValueName, L"UuidSequenceNumber");
|
||||||
|
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
&Name,
|
&KeyName,
|
||||||
OBJ_CASE_INSENSITIVE,
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
Status = ZwOpenKey(&KeyHandle,
|
Status = ZwOpenKey(&KeyHandle, GENERIC_READ, &ObjectAttributes);
|
||||||
KEY_QUERY_VALUE,
|
|
||||||
&ObjectAttributes);
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("ZwOpenKey() failed (Status %lx)\n", Status);
|
DPRINT("ZwOpenKey() failed (Status %lx)\n", Status);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlInitUnicodeString(&Name, L"UuidSequenceNumber");
|
|
||||||
|
|
||||||
ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
|
ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
|
||||||
Status = ZwQueryValueKey(KeyHandle,
|
Status = ZwQueryValueKey(KeyHandle,
|
||||||
&Name,
|
&ValueName,
|
||||||
KeyValuePartialInformation,
|
KeyValuePartialInformation,
|
||||||
ValueBuffer,
|
ValueBuffer,
|
||||||
VALUE_BUFFER_SIZE,
|
VALUE_BUFFER_SIZE,
|
||||||
|
@ -105,6 +112,11 @@ ExpLoadUuidSequence(PULONG Sequence)
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ValueInfo->Type != REG_DWORD || ValueInfo->DataLength != sizeof(DWORD))
|
||||||
|
{
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
*Sequence = *((PULONG)ValueInfo->Data);
|
*Sequence = *((PULONG)ValueInfo->Data);
|
||||||
|
|
||||||
DPRINT("Loaded sequence %lx\n", *Sequence);
|
DPRINT("Loaded sequence %lx\n", *Sequence);
|
||||||
|
@ -113,24 +125,29 @@ ExpLoadUuidSequence(PULONG Sequence)
|
||||||
}
|
}
|
||||||
#undef VALUE_BUFFER_SIZE
|
#undef VALUE_BUFFER_SIZE
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
ExpSaveUuidSequence(PULONG Sequence)
|
ExpUuidSaveSequenceNumber(PULONG Sequence)
|
||||||
{
|
{
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
UNICODE_STRING Name;
|
UNICODE_STRING KeyName, ValueName;
|
||||||
HANDLE KeyHandle;
|
HANDLE KeyHandle;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
RtlInitUnicodeString(&Name,
|
PAGED_CODE();
|
||||||
L"\\Registry\\Machine\\Software\\Microsoft\\Rpc");
|
|
||||||
|
RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\Software\\Microsoft\\Rpc");
|
||||||
|
RtlInitUnicodeString(&ValueName, L"UuidSequenceNumber");
|
||||||
|
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
&Name,
|
&KeyName,
|
||||||
OBJ_CASE_INSENSITIVE,
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
Status = ZwOpenKey(&KeyHandle,
|
Status = ZwOpenKey(&KeyHandle,
|
||||||
KEY_SET_VALUE,
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
&ObjectAttributes);
|
&ObjectAttributes);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -138,9 +155,8 @@ ExpSaveUuidSequence(PULONG Sequence)
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlInitUnicodeString(&Name, L"UuidSequenceNumber");
|
|
||||||
Status = ZwSetValueKey(KeyHandle,
|
Status = ZwSetValueKey(KeyHandle,
|
||||||
&Name,
|
&ValueName,
|
||||||
0,
|
0,
|
||||||
REG_DWORD,
|
REG_DWORD,
|
||||||
Sequence,
|
Sequence,
|
||||||
|
@ -154,98 +170,196 @@ ExpSaveUuidSequence(PULONG Sequence)
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
* Warning! This function must be called
|
||||||
|
* with ExpUuidLock held!
|
||||||
|
*/
|
||||||
static VOID
|
static VOID
|
||||||
ExpGetRandomUuidSequence(PULONG Sequence)
|
ExpUuidSaveSequenceNumberIf(VOID)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER Counter;
|
NTSTATUS Status;
|
||||||
LARGE_INTEGER Frequency;
|
|
||||||
ULONG Value;
|
|
||||||
|
|
||||||
Counter = KeQueryPerformanceCounter(&Frequency);
|
PAGED_CODE();
|
||||||
Value = Counter.u.LowPart ^ Counter.u.HighPart;
|
|
||||||
|
|
||||||
*Sequence = *Sequence ^ Value;
|
/* Only save sequence if it has to */
|
||||||
|
if (ExpUuidSequenceNumberNotSaved == TRUE)
|
||||||
DPRINT("Sequence %lx\n", *Sequence);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static NTSTATUS
|
|
||||||
ExpCreateUuids(PULARGE_INTEGER Time,
|
|
||||||
PULONG Range,
|
|
||||||
PULONG Sequence)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Generate time element of the UUID. Account for going faster
|
|
||||||
* than our clock as well as the clock going backwards.
|
|
||||||
*/
|
|
||||||
while (1)
|
|
||||||
{
|
{
|
||||||
KeQuerySystemTime((PLARGE_INTEGER)Time);
|
Status = ExpUuidSaveSequenceNumber(&ExpUuidSequenceNumber);
|
||||||
Time->QuadPart += TICKS_15_OCT_1582_TO_1601;
|
if (NT_SUCCESS(Status))
|
||||||
|
|
||||||
if (Time->QuadPart > UuidLastTime.QuadPart)
|
|
||||||
{
|
{
|
||||||
UuidCount = 0;
|
ExpUuidSequenceNumberNotSaved = FALSE;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Time->QuadPart < UuidLastTime.QuadPart)
|
|
||||||
{
|
|
||||||
(*Sequence)++;
|
|
||||||
UuidSequenceChanged = TRUE;
|
|
||||||
UuidCount = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UuidCount < TICKS_PER_CLOCK_TICK)
|
|
||||||
{
|
|
||||||
UuidCount++;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UuidLastTime.QuadPart = Time->QuadPart;
|
/*
|
||||||
Time->QuadPart += UuidCount;
|
* @implemented
|
||||||
|
* Warning! This function must be called
|
||||||
|
* with ExpUuidLock held!
|
||||||
|
*/
|
||||||
|
static NTSTATUS
|
||||||
|
ExpAllocateUuids(PULARGE_INTEGER Time,
|
||||||
|
PULONG Range,
|
||||||
|
PULONG Sequence)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
LARGE_INTEGER Counter, Frequency, CurrentTime, TimeDiff, ClockDiff;
|
||||||
|
|
||||||
*Range = 10000; /* What does this mean? Ticks per millisecond?*/
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Initialize sequence number */
|
||||||
|
if (!ExpUuidSequenceNumberValid)
|
||||||
|
{
|
||||||
|
/* Try to load sequence number */
|
||||||
|
Status = ExpUuidLoadSequenceNumber(&ExpUuidSequenceNumber);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
++ExpUuidSequenceNumber;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If we cannot, generate a "true" random */
|
||||||
|
Counter = KeQueryPerformanceCounter(&Frequency);
|
||||||
|
ExpUuidSequenceNumber ^= (ULONG_PTR)&Status ^ (ULONG_PTR)Sequence ^ Counter.LowPart ^ Counter.HighPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* It's valid and to be saved */
|
||||||
|
ExpUuidSequenceNumberValid = TRUE;
|
||||||
|
ExpUuidSequenceNumberNotSaved = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeQuerySystemTime(&CurrentTime);
|
||||||
|
TimeDiff.QuadPart = CurrentTime.QuadPart - ExpUuidLastTimeAllocated.QuadPart;
|
||||||
|
/* If time went backwards, change sequence (see RFC example) */
|
||||||
|
if (TimeDiff.QuadPart < 0)
|
||||||
|
{
|
||||||
|
++ExpUuidSequenceNumber;
|
||||||
|
TimeDiff.QuadPart = 2 * TIME_FRAME;
|
||||||
|
|
||||||
|
/* It's to be saved */
|
||||||
|
ExpUuidSequenceNumberNotSaved = TRUE;
|
||||||
|
ExpUuidLastTimeAllocated.QuadPart = CurrentTime.QuadPart - 2 * TIME_FRAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TimeDiff.QuadPart == 0)
|
||||||
|
{
|
||||||
|
return STATUS_RETRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If time diff > 0,1ms, squash it to reduce it to keep our clock resolution */
|
||||||
|
if (TimeDiff.HighPart > 0 || TimeDiff.QuadPart > TICKS_PER_CLOCK_TICK * TIME_FRAME)
|
||||||
|
{
|
||||||
|
TimeDiff.QuadPart = TICKS_PER_CLOCK_TICK * TIME_FRAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TimeDiff.HighPart < 0 || TimeDiff.QuadPart <= TIME_FRAME)
|
||||||
|
{
|
||||||
|
*Range = TimeDiff.QuadPart;
|
||||||
|
ClockDiff.QuadPart = 0LL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*Range = TIME_FRAME;
|
||||||
|
ClockDiff.QuadPart -= TIME_FRAME;
|
||||||
|
--ClockDiff.HighPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
Time->QuadPart = CurrentTime.QuadPart - *Range - ClockDiff.QuadPart;
|
||||||
|
ExpUuidLastTimeAllocated.QuadPart = CurrentTime.QuadPart - ClockDiff.QuadPart;
|
||||||
|
*Sequence = ExpUuidSequenceNumber;
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
/*
|
||||||
INIT_FUNCTION
|
* @implemented
|
||||||
NTAPI
|
* Warning! This function must be called
|
||||||
ExpInitLuid(VOID)
|
* with ExpUuidLock held!
|
||||||
|
*/
|
||||||
|
static NTSTATUS
|
||||||
|
ExpUuidGetValues(PUUID_CACHED_VALUES_STRUCT CachedValues)
|
||||||
{
|
{
|
||||||
LUID DummyLuidValue = SYSTEM_LUID;
|
NTSTATUS Status;
|
||||||
|
ULARGE_INTEGER Time;
|
||||||
|
ULONG Range;
|
||||||
|
ULONG Sequence;
|
||||||
|
|
||||||
LuidValue.u.HighPart = DummyLuidValue.HighPart;
|
PAGED_CODE();
|
||||||
LuidValue.u.LowPart = DummyLuidValue.LowPart;
|
|
||||||
LuidIncrement.QuadPart = 1;
|
/* Allocate UUIDs */
|
||||||
|
Status = ExpAllocateUuids(&Time, &Range, &Sequence);
|
||||||
|
if (Status == STATUS_RETRY)
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We need at least one UUID */
|
||||||
|
ASSERT(Range != 0);
|
||||||
|
|
||||||
|
/* Set up our internal cache
|
||||||
|
* See format_uuid_v1 in RFC4122 for magic values
|
||||||
|
*/
|
||||||
|
CachedValues->ClockSeqLow = Sequence;
|
||||||
|
CachedValues->ClockSeqHiAndReserved = (Sequence & 0x3F00) >> 8;
|
||||||
|
CachedValues->ClockSeqHiAndReserved |= 0x80;
|
||||||
|
CachedValues->AllocatedCount = Range;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Time is relative to UUID time
|
||||||
|
* And we set last time range for all the possibly
|
||||||
|
* returnable UUID
|
||||||
|
*/
|
||||||
|
Time.QuadPart += TICKS_15_OCT_1582_TO_1601;
|
||||||
|
CachedValues->Time = Time.QuadPart + (Range - 1);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
BOOLEAN
|
||||||
|
INIT_FUNCTION
|
||||||
|
NTAPI
|
||||||
|
ExLuidInitialization(VOID)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
ExAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
|
ExAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER NewLuid, PrevLuid;
|
LARGE_INTEGER PrevLuid;
|
||||||
|
LONGLONG NewLuid, CompLuid;
|
||||||
|
|
||||||
/* atomically increment the luid */
|
/* Atomically increment the luid */
|
||||||
do
|
PrevLuid.QuadPart = ExpLuid.QuadPart;
|
||||||
|
for (NewLuid = ExpLuid.QuadPart + ExpLuidIncrement; ;
|
||||||
|
NewLuid = PrevLuid.QuadPart + ExpLuidIncrement)
|
||||||
{
|
{
|
||||||
PrevLuid = LuidValue;
|
CompLuid = InterlockedCompareExchange64(&ExpLuid.QuadPart,
|
||||||
NewLuid = RtlLargeIntegerAdd(PrevLuid,
|
NewLuid,
|
||||||
LuidIncrement);
|
PrevLuid.QuadPart);
|
||||||
} while(ExInterlockedCompareExchange64(&LuidValue.QuadPart,
|
if (CompLuid == PrevLuid.QuadPart)
|
||||||
&NewLuid.QuadPart,
|
{
|
||||||
&PrevLuid.QuadPart,
|
break;
|
||||||
NULL) != PrevLuid.QuadPart);
|
}
|
||||||
|
|
||||||
LocallyUniqueId->LowPart = NewLuid.u.LowPart;
|
PrevLuid.QuadPart = CompLuid;
|
||||||
LocallyUniqueId->HighPart = NewLuid.u.HighPart;
|
}
|
||||||
|
|
||||||
|
LocallyUniqueId->LowPart = PrevLuid.LowPart;
|
||||||
|
LocallyUniqueId->HighPart = PrevLuid.HighPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -256,9 +370,7 @@ NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
NtAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
|
NtAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
|
||||||
{
|
{
|
||||||
LUID NewLuid;
|
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode;
|
||||||
NTSTATUS Status;
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Probe if user mode */
|
/* Probe if user mode */
|
||||||
|
@ -279,35 +391,91 @@ NtAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do the allocation */
|
/* Do the allocation */
|
||||||
ExAllocateLocallyUniqueId(&NewLuid);
|
ExAllocateLocallyUniqueId(LocallyUniqueId);
|
||||||
Status = STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
/* Write back LUID to caller */
|
|
||||||
_SEH2_TRY
|
|
||||||
{
|
|
||||||
*LocallyUniqueId = NewLuid;
|
|
||||||
}
|
|
||||||
_SEH2_EXCEPT(ExSystemExceptionFilter())
|
|
||||||
{
|
|
||||||
Status = _SEH2_GetExceptionCode();
|
|
||||||
}
|
|
||||||
_SEH2_END;
|
|
||||||
return Status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @unimplemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
ExUuidCreate(OUT UUID *Uuid)
|
ExUuidCreate(OUT UUID *Uuid)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
NTSTATUS Status;
|
||||||
return FALSE;
|
LONG AllocatedCount;
|
||||||
|
LARGE_INTEGER Time;
|
||||||
|
BOOLEAN Valid;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
/* Loop until we have an UUID to return */
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
/* Try to gather node values */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Time.QuadPart = ExpUuidCachedValues.Time;
|
||||||
|
|
||||||
|
RtlCopyMemory(&Uuid->Data4[0],
|
||||||
|
&ExpUuidCachedValues.NodeId[0],
|
||||||
|
SEED_BUFFER_SIZE);
|
||||||
|
Valid = ExpUuidCacheValid;
|
||||||
|
AllocatedCount = InterlockedDecrement(&ExpUuidCachedValues.AllocatedCount);
|
||||||
|
}
|
||||||
|
/* Loop till we can do it without being disturbed */
|
||||||
|
while (Time.QuadPart != ExpUuidCachedValues.Time);
|
||||||
|
|
||||||
|
/* We have more than an allocated UUID left, that's OK to return! */
|
||||||
|
if (AllocatedCount >= 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here, we're out of UUIDs, we need to allocate more
|
||||||
|
* We need to be alone to do it, so lock the mutex
|
||||||
|
*/
|
||||||
|
ExAcquireFastMutex(&ExpUuidLock);
|
||||||
|
if (Time.QuadPart == ExpUuidCachedValues.Time)
|
||||||
|
{
|
||||||
|
/* If allocation fails, bail out! */
|
||||||
|
Status = ExpUuidGetValues(&ExpUuidCachedValues);
|
||||||
|
if (Status != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
ExReleaseFastMutex(&ExpUuidLock);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save our current sequence if changed */
|
||||||
|
ExpUuidSaveSequenceNumberIf();
|
||||||
|
}
|
||||||
|
ExReleaseFastMutex(&ExpUuidLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Once here, we've got an UUID to return
|
||||||
|
* But, if our init wasn't sane, then, make
|
||||||
|
* sure it's only used locally
|
||||||
|
*/
|
||||||
|
if (!Valid)
|
||||||
|
{
|
||||||
|
Status = RPC_NT_UUID_LOCAL_ONLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set our timestamp - see RFC4211 */
|
||||||
|
Time.QuadPart -= AllocatedCount;
|
||||||
|
Uuid->Data1 = Time.LowPart;
|
||||||
|
Uuid->Data2 = Time.HighPart;
|
||||||
|
/* We also set the bit for GUIDv1 */
|
||||||
|
Uuid->Data3 = ((Time.HighPart >> 16) & 0x0FFF) | 0x1000;
|
||||||
|
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @unimplemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -317,7 +485,7 @@ NtAllocateUuids(OUT PULARGE_INTEGER Time,
|
||||||
OUT PUCHAR Seed)
|
OUT PUCHAR Seed)
|
||||||
{
|
{
|
||||||
ULARGE_INTEGER IntTime;
|
ULARGE_INTEGER IntTime;
|
||||||
ULONG IntRange;
|
ULONG IntRange, IntSequence;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode;
|
||||||
|
|
||||||
|
@ -352,40 +520,22 @@ NtAllocateUuids(OUT PULARGE_INTEGER Time,
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* During allocation we must be alone */
|
||||||
ExAcquireFastMutex(&ExpUuidLock);
|
ExAcquireFastMutex(&ExpUuidLock);
|
||||||
|
|
||||||
if (!UuidSequenceInitialized)
|
Status = ExpAllocateUuids(&IntTime,
|
||||||
{
|
&IntRange,
|
||||||
Status = ExpLoadUuidSequence(&UuidSequence);
|
&IntSequence);
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
UuidSequence++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ExpGetRandomUuidSequence(&UuidSequence);
|
|
||||||
}
|
|
||||||
|
|
||||||
UuidSequenceInitialized = TRUE;
|
|
||||||
UuidSequenceChanged = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = ExpCreateUuids(&IntTime,
|
|
||||||
&IntRange,
|
|
||||||
&UuidSequence);
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
ExReleaseFastMutex(&ExpUuidLock);
|
ExReleaseFastMutex(&ExpUuidLock);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UuidSequenceChanged)
|
/* If sequence number was changed, save it */
|
||||||
{
|
ExpUuidSaveSequenceNumberIf();
|
||||||
Status = ExpSaveUuidSequence(&UuidSequence);
|
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
UuidSequenceChanged = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Allocation done, so we can release */
|
||||||
ExReleaseFastMutex(&ExpUuidLock);
|
ExReleaseFastMutex(&ExpUuidLock);
|
||||||
|
|
||||||
/* Write back UUIDs to caller */
|
/* Write back UUIDs to caller */
|
||||||
|
@ -393,10 +543,10 @@ NtAllocateUuids(OUT PULARGE_INTEGER Time,
|
||||||
{
|
{
|
||||||
Time->QuadPart = IntTime.QuadPart;
|
Time->QuadPart = IntTime.QuadPart;
|
||||||
*Range = IntRange;
|
*Range = IntRange;
|
||||||
*Sequence = UuidSequence;
|
*Sequence = IntSequence;
|
||||||
|
|
||||||
RtlCopyMemory(Seed,
|
RtlCopyMemory(Seed,
|
||||||
UuidSeed,
|
&ExpUuidCachedValues.NodeId[0],
|
||||||
SEED_BUFFER_SIZE);
|
SEED_BUFFER_SIZE);
|
||||||
|
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
|
@ -453,7 +603,15 @@ NtSetUuidSeed(IN PUCHAR Seed)
|
||||||
|
|
||||||
/* Check for buffer validity and then copy it to our seed */
|
/* Check for buffer validity and then copy it to our seed */
|
||||||
ProbeForRead(Seed, SEED_BUFFER_SIZE, sizeof(UCHAR));
|
ProbeForRead(Seed, SEED_BUFFER_SIZE, sizeof(UCHAR));
|
||||||
RtlCopyMemory(UuidSeed, Seed, SEED_BUFFER_SIZE);
|
RtlCopyMemory(&ExpUuidCachedValues.NodeId[0], Seed, SEED_BUFFER_SIZE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* According to RFC 4122, UUID seed is based on MAC addresses
|
||||||
|
* If it is randomly set, then, it must have its multicast be set
|
||||||
|
* to be valid and avoid collisions
|
||||||
|
* Reflect it here
|
||||||
|
*/
|
||||||
|
ExpUuidCacheValid = ~(*Seed >> 7) & 1;
|
||||||
|
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,9 +236,14 @@ NTAPI
|
||||||
ExpInitializeCallbacks(VOID);
|
ExpInitializeCallbacks(VOID);
|
||||||
|
|
||||||
INIT_FUNCTION
|
INIT_FUNCTION
|
||||||
VOID
|
BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
ExpInitUuids(VOID);
|
ExpUuidInitialization(VOID);
|
||||||
|
|
||||||
|
INIT_FUNCTION
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
ExLuidInitialization(VOID);
|
||||||
|
|
||||||
INIT_FUNCTION
|
INIT_FUNCTION
|
||||||
VOID
|
VOID
|
||||||
|
|
|
@ -248,11 +248,6 @@ BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
SeInitSystem(VOID);
|
SeInitSystem(VOID);
|
||||||
|
|
||||||
INIT_FUNCTION
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
ExpInitLuid(VOID);
|
|
||||||
|
|
||||||
INIT_FUNCTION
|
INIT_FUNCTION
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
|
|
|
@ -97,7 +97,7 @@ SepInitializationPhase0(VOID)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
ExpInitLuid();
|
if (!ExLuidInitialization()) return FALSE;
|
||||||
if (!SepInitSecurityIDs()) return FALSE;
|
if (!SepInitSecurityIDs()) return FALSE;
|
||||||
if (!SepInitDACLs()) return FALSE;
|
if (!SepInitDACLs()) return FALSE;
|
||||||
if (!SepInitSDs()) return FALSE;
|
if (!SepInitSDs()) return FALSE;
|
||||||
|
|
Loading…
Reference in a new issue