[NTOSKRNL] Rewrite/fix our UUID generation implementation
authorPierre Schweitzer <pierre@reactos.org>
Wed, 27 Feb 2019 20:12:32 +0000 (21:12 +0100)
committerPierre Schweitzer <pierre@reactos.org>
Fri, 1 Mar 2019 07:22:48 +0000 (08:22 +0100)
So that it matches Windows behavior
Also implement ExUuidCreate that will generate UUID version 1

The implementation is based on the RFC 4122

ntoskrnl/ex/init.c
ntoskrnl/ex/uuid.c
ntoskrnl/include/internal/ex.h
ntoskrnl/include/internal/se.h
ntoskrnl/se/semgr.c

index 10be805..1e31003 100644 (file)
@@ -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 */
     if (ExpInitializeKeyedEventImplementation() == FALSE)
 
     /* Initialize keyed events */
     if (ExpInitializeKeyedEventImplementation() == FALSE)
index 459b957..1f41bdb 100644 (file)
@@ -5,6 +5,7 @@
  * PURPOSE:         UUID generator
  * PROGRAMMERS:     Eric Kohl
  *                  Thomas Weidenmueller
  * PURPOSE:         UUID generator
  * PROGRAMMERS:     Eric Kohl
  *                  Thomas Weidenmueller
+ *                  Pierre Schweitzer
  */
 
 /* INCLUDES *****************************************************************/
  */
 
 /* INCLUDES *****************************************************************/
 #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 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)
 
+/* 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
 
 
 /* GLOBALS ****************************************************************/
 
 #endif
 
 
 /* GLOBALS ****************************************************************/
 
-static FAST_MUTEX ExpUuidLock;
-static ULARGE_INTEGER UuidLastTime;
-static ULONG UuidSequence;
-static BOOLEAN UuidSequenceInitialized = FALSE;
-static BOOLEAN UuidSequenceChanged = FALSE;
-static UCHAR UuidSeed[SEED_BUFFER_SIZE];
-static ULONG UuidCount;
-static LARGE_INTEGER LuidIncrement;
-static LARGE_INTEGER LuidValue;
-UUID_CACHED_VALUES_STRUCT ExpUuidCachedValues = { 0ULL, 0xFFFFFFFF, 0, 0, { 0x80, 0x6E, 0x6F, 0x6E, 0x69, 0x63 } };
+FAST_MUTEX ExpUuidLock;
+LARGE_INTEGER ExpUuidLastTimeAllocated;
+ULONG ExpUuidSequenceNumber = 0;
+BOOLEAN ExpUuidSequenceNumberValid;
+BOOLEAN ExpUuidSequenceNumberNotSaved = FALSE;
+UUID_CACHED_VALUES_STRUCT ExpUuidCachedValues = {0ULL, 0xFFFFFFFF, 0, 0, { 0x80, 0x6E, 0x6F, 0x6E, 0x69, 0x63}};
+BOOLEAN ExpUuidCacheValid = FALSE;
+ULONG ExpLuidIncrement = 1;
+LARGE_INTEGER ExpLuid = {.LowPart = 0x3e9, .HighPart = 0x0};
 
 /* FUNCTIONS ****************************************************************/
 
 
 /* FUNCTIONS ****************************************************************/
 
-VOID
+/*
+ * @implemented
+ */
+BOOLEAN
 INIT_FUNCTION
 NTAPI
 INIT_FUNCTION
 NTAPI
-ExpInitUuids(VOID)
+ExpUuidInitialization(VOID)
 {
     ExInitializeFastMutex(&ExpUuidLock);
 
 {
     ExInitializeFastMutex(&ExpUuidLock);
 
-    KeQuerySystemTime((PLARGE_INTEGER)&UuidLastTime);
-    UuidLastTime.QuadPart += TICKS_15_OCT_1582_TO_1601;
+    ExpUuidSequenceNumberValid = FALSE;
+    KeQuerySystemTime(&ExpUuidLastTimeAllocated);
 
 
-    UuidCount = TICKS_PER_CLOCK_TICK;
-    RtlZeroMemory(UuidSeed, SEED_BUFFER_SIZE);
+    return TRUE;
 }
 
 
 }
 
 
-#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];
     PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
     OBJECT_ATTRIBUTES ObjectAttributes;
 {
     UCHAR ValueBuffer[VALUE_BUFFER_SIZE];
     PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
     OBJECT_ATTRIBUTES ObjectAttributes;
-    UNICODE_STRING Name;
+    UNICODE_STRING KeyName, ValueName;
     HANDLE KeyHandle;
     ULONG ValueLength;
     NTSTATUS Status;
 
     HANDLE KeyHandle;
     ULONG ValueLength;
     NTSTATUS Status;
 
-    RtlInitUnicodeString(&Name,
-        L"\\Registry\\Machine\\Software\\Microsoft\\Rpc");
+    PAGED_CODE();
+
+    RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\Software\\Microsoft\\Rpc");
+    RtlInitUnicodeString(&ValueName, L"UuidSequenceNumber");
+
     InitializeObjectAttributes(&ObjectAttributes,
     InitializeObjectAttributes(&ObjectAttributes,
-                               &Name,
-                               OBJ_CASE_INSENSITIVE,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                                NULL,
                                NULL);
                                NULL,
                                NULL);
-    Status = ZwOpenKey(&KeyHandle,
-                       KEY_QUERY_VALUE,
-                       &ObjectAttributes);
+    Status = ZwOpenKey(&KeyHandle, GENERIC_READ, &ObjectAttributes);
     if (!NT_SUCCESS(Status))
     {
         DPRINT("ZwOpenKey() failed (Status %lx)\n", Status);
         return Status;
     }
 
     if (!NT_SUCCESS(Status))
     {
         DPRINT("ZwOpenKey() failed (Status %lx)\n", Status);
         return Status;
     }
 
-    RtlInitUnicodeString(&Name, L"UuidSequenceNumber");
-
     ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
     Status = ZwQueryValueKey(KeyHandle,
     ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
     Status = ZwQueryValueKey(KeyHandle,
-                             &Name,
+                             &ValueName,
                              KeyValuePartialInformation,
                              ValueBuffer,
                              VALUE_BUFFER_SIZE,
                              KeyValuePartialInformation,
                              ValueBuffer,
                              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);
 
     DPRINT("Loaded sequence %lx\n", *Sequence);
     *Sequence = *((PULONG)ValueInfo->Data);
 
     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;
     NTSTATUS Status;
 
     HANDLE KeyHandle;
     NTSTATUS Status;
 
-    RtlInitUnicodeString(&Name,
-        L"\\Registry\\Machine\\Software\\Microsoft\\Rpc");
+    PAGED_CODE();
+
+    RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\Software\\Microsoft\\Rpc");
+    RtlInitUnicodeString(&ValueName, L"UuidSequenceNumber");
+
     InitializeObjectAttributes(&ObjectAttributes,
     InitializeObjectAttributes(&ObjectAttributes,
-                               &Name,
-                               OBJ_CASE_INSENSITIVE,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                                NULL,
                                NULL);
     Status = ZwOpenKey(&KeyHandle,
                                NULL,
                                NULL);
     Status = ZwOpenKey(&KeyHandle,
-                       KEY_SET_VALUE,
+                       GENERIC_READ | GENERIC_WRITE,
                        &ObjectAttributes);
     if (!NT_SUCCESS(Status))
     {
                        &ObjectAttributes);
     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,
                            REG_DWORD,
                            Sequence,
                            0,
                            REG_DWORD,
                            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;
-    LARGE_INTEGER Frequency;
-    ULONG Value;
-
-    Counter = KeQueryPerformanceCounter(&Frequency);
-    Value = Counter.u.LowPart ^ Counter.u.HighPart;
+    NTSTATUS Status;
 
 
-    *Sequence = *Sequence ^ Value;
+    PAGED_CODE();
 
 
-    DPRINT("Sequence %lx\n", *Sequence);
+    /* Only save sequence if it has to */
+    if (ExpUuidSequenceNumberNotSaved == TRUE)
+    {
+        Status = ExpUuidSaveSequenceNumber(&ExpUuidSequenceNumber);
+        if (NT_SUCCESS(Status))
+        {
+            ExpUuidSequenceNumberNotSaved = FALSE;
+        }
+    }
 }
 
 }
 
-
+/*
+ * @implemented
+ * Warning! This function must be called
+ * with ExpUuidLock held!
+ */
 static NTSTATUS
 static NTSTATUS
-ExpCreateUuids(PULARGE_INTEGER Time,
-               PULONG Range,
-               PULONG Sequence)
+ExpAllocateUuids(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);
-        Time->QuadPart += TICKS_15_OCT_1582_TO_1601;
+    NTSTATUS Status;
+    LARGE_INTEGER Counter, Frequency, CurrentTime, TimeDiff, ClockDiff;
 
 
-        if (Time->QuadPart > UuidLastTime.QuadPart)
-        {
-            UuidCount = 0;
-            break;
-        }
+    PAGED_CODE();
 
 
-        if (Time->QuadPart < UuidLastTime.QuadPart)
+    /* Initialize sequence number */
+    if (!ExpUuidSequenceNumberValid)
+    {
+        /* Try to load sequence number */
+        Status = ExpUuidLoadSequenceNumber(&ExpUuidSequenceNumber);
+        if (NT_SUCCESS(Status))
         {
         {
-            (*Sequence)++;
-            UuidSequenceChanged = TRUE;
-            UuidCount = 0;
-            break;
+            ++ExpUuidSequenceNumber;
         }
         }
-
-        if (UuidCount < TICKS_PER_CLOCK_TICK)
+        else
         {
         {
-            UuidCount++;
-            break;
+            /* 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;
     }
 
     }
 
-    UuidLastTime.QuadPart = Time->QuadPart;
-    Time->QuadPart += UuidCount;
+    /* 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;
+    }
 
 
-    *Range = 10000; /* What does this mean? Ticks per millisecond?*/
+    Time->QuadPart = CurrentTime.QuadPart - *Range - ClockDiff.QuadPart;
+    ExpUuidLastTimeAllocated.QuadPart = CurrentTime.QuadPart - ClockDiff.QuadPart;
+    *Sequence = ExpUuidSequenceNumber;
 
     return STATUS_SUCCESS;
 }
 
 
     return STATUS_SUCCESS;
 }
 
-VOID
-INIT_FUNCTION
-NTAPI
-ExpInitLuid(VOID)
+/*
+ * @implemented
+ * Warning! This function must be called
+ * with ExpUuidLock held!
+ */
+static NTSTATUS
+ExpUuidGetValues(PUUID_CACHED_VALUES_STRUCT CachedValues)
 {
 {
-    LUID DummyLuidValue = SYSTEM_LUID;
+    NTSTATUS Status;
+    ULARGE_INTEGER Time;
+    ULONG Range;
+    ULONG Sequence;
+
+    PAGED_CODE();
 
 
-    LuidValue.u.HighPart = DummyLuidValue.HighPart;
-    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
 NTAPI
 ExAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
 {
 VOID
 NTAPI
 ExAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
 {
-    LARGE_INTEGER NewLuid, PrevLuid;
+    LARGE_INTEGER PrevLuid;
+    LONGLONG NewLuid, CompLuid;
 
 
-    /* atomically increment the luid */
-    do
+    /* Atomically increment the luid */
+    PrevLuid.QuadPart = ExpLuid.QuadPart;
+    for (NewLuid = ExpLuid.QuadPart + ExpLuidIncrement; ;
+         NewLuid = PrevLuid.QuadPart + ExpLuidIncrement)
     {
     {
-        PrevLuid = LuidValue;
-        NewLuid = RtlLargeIntegerAdd(PrevLuid,
-                                     LuidIncrement);
-    } while(ExInterlockedCompareExchange64(&LuidValue.QuadPart,
-                                           &NewLuid.QuadPart,
-                                           &PrevLuid.QuadPart,
-                                           NULL) != PrevLuid.QuadPart);
-
-    LocallyUniqueId->LowPart = NewLuid.u.LowPart;
-    LocallyUniqueId->HighPart = NewLuid.u.HighPart;
+        CompLuid = InterlockedCompareExchange64(&ExpLuid.QuadPart,
+                                                NewLuid,
+                                                PrevLuid.QuadPart);
+        if (CompLuid == PrevLuid.QuadPart)
+        {
+            break;
+        }
+
+        PrevLuid.QuadPart = CompLuid;
+    }
+
+    LocallyUniqueId->LowPart = PrevLuid.LowPart;
+    LocallyUniqueId->HighPart = PrevLuid.HighPart;
 }
 
 
 }
 
 
@@ -256,9 +370,7 @@ NTSTATUS
 NTAPI
 NtAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
 {
 NTAPI
 NtAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
 {
-    LUID NewLuid;
     KPROCESSOR_MODE PreviousMode;
     KPROCESSOR_MODE PreviousMode;
-    NTSTATUS Status;
     PAGED_CODE();
 
     /* Probe if user mode */
     PAGED_CODE();
 
     /* Probe if user mode */
@@ -279,35 +391,91 @@ NtAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
     }
 
     /* Do the allocation */
     }
 
     /* Do the allocation */
-    ExAllocateLocallyUniqueId(&NewLuid);
-    Status = STATUS_SUCCESS;
-
-    /* Write back LUID to caller */
-    _SEH2_TRY
-    {
-        *LocallyUniqueId = NewLuid;
-    }
-    _SEH2_EXCEPT(ExSystemExceptionFilter())
-    {
-        Status = _SEH2_GetExceptionCode();
-    }
-    _SEH2_END;
-    return Status;
+    ExAllocateLocallyUniqueId(LocallyUniqueId);
+    return STATUS_SUCCESS;
 }
 
 /*
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 NTSTATUS
 NTAPI
 ExUuidCreate(OUT UUID *Uuid)
 {
  */
 NTSTATUS
 NTAPI
 ExUuidCreate(OUT UUID *Uuid)
 {
-    UNIMPLEMENTED;
-    return FALSE;
+    NTSTATUS Status;
+    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
 NTAPI
  */
 NTSTATUS
 NTAPI
@@ -317,7 +485,7 @@ NtAllocateUuids(OUT PULARGE_INTEGER Time,
                 OUT PUCHAR Seed)
 {
     ULARGE_INTEGER IntTime;
                 OUT PUCHAR Seed)
 {
     ULARGE_INTEGER IntTime;
-    ULONG IntRange;
+    ULONG IntRange, IntSequence;
     NTSTATUS Status;
     KPROCESSOR_MODE PreviousMode;
 
     NTSTATUS Status;
     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 = ExpLoadUuidSequence(&UuidSequence);
-        if (NT_SUCCESS(Status))
-        {
-            UuidSequence++;
-        }
-        else
-        {
-            ExpGetRandomUuidSequence(&UuidSequence);
-        }
-
-        UuidSequenceInitialized = TRUE;
-        UuidSequenceChanged = TRUE;
-    }
-
-    Status = ExpCreateUuids(&IntTime,
-                            &IntRange,
-                            &UuidSequence);
+    Status = ExpAllocateUuids(&IntTime,
+                              &IntRange,
+                              &IntSequence);
     if (!NT_SUCCESS(Status))
     {
         ExReleaseFastMutex(&ExpUuidLock);
         return Status;
     }
 
     if (!NT_SUCCESS(Status))
     {
         ExReleaseFastMutex(&ExpUuidLock);
         return Status;
     }
 
-    if (UuidSequenceChanged)
-    {
-        Status = ExpSaveUuidSequence(&UuidSequence);
-        if (NT_SUCCESS(Status))
-            UuidSequenceChanged = FALSE;
-    }
+    /* If sequence number was changed, save it */
+    ExpUuidSaveSequenceNumberIf();
 
 
+    /* Allocation done, so we can release */
     ExReleaseFastMutex(&ExpUuidLock);
 
     /* Write back UUIDs to caller */
     ExReleaseFastMutex(&ExpUuidLock);
 
     /* Write back UUIDs to caller */
@@ -393,10 +543,10 @@ NtAllocateUuids(OUT PULARGE_INTEGER Time,
     {
         Time->QuadPart = IntTime.QuadPart;
         *Range = IntRange;
     {
         Time->QuadPart = IntTime.QuadPart;
         *Range = IntRange;
-        *Sequence = UuidSequence;
+        *Sequence = IntSequence;
 
         RtlCopyMemory(Seed,
 
         RtlCopyMemory(Seed,
-                      UuidSeed,
+                      &ExpUuidCachedValues.NodeId[0],
                       SEED_BUFFER_SIZE);
 
         Status = STATUS_SUCCESS;
                       SEED_BUFFER_SIZE);
 
         Status = STATUS_SUCCESS;
@@ -453,7 +603,15 @@ NtSetUuidSeed(IN PUCHAR Seed)
 
         /* Check for buffer validity and then copy it to our seed */
         ProbeForRead(Seed, SEED_BUFFER_SIZE, sizeof(UCHAR));
 
         /* Check for buffer validity and then copy it to our seed */
         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;
     }
index 2072a6a..52e58bf 100644 (file)
@@ -236,9 +236,14 @@ NTAPI
 ExpInitializeCallbacks(VOID);
 
 INIT_FUNCTION
 ExpInitializeCallbacks(VOID);
 
 INIT_FUNCTION
-VOID
+BOOLEAN
+NTAPI
+ExpUuidInitialization(VOID);
+
+INIT_FUNCTION
+BOOLEAN
 NTAPI
 NTAPI
-ExpInitUuids(VOID);
+ExLuidInitialization(VOID);
 
 INIT_FUNCTION
 VOID
 
 INIT_FUNCTION
 VOID
index e2285fd..aec259c 100644 (file)
@@ -248,11 +248,6 @@ BOOLEAN
 NTAPI
 SeInitSystem(VOID);
 
 NTAPI
 SeInitSystem(VOID);
 
-INIT_FUNCTION
-VOID
-NTAPI
-ExpInitLuid(VOID);
-
 INIT_FUNCTION
 VOID
 NTAPI
 INIT_FUNCTION
 VOID
 NTAPI
index 3156e64..18768c7 100644 (file)
@@ -97,7 +97,7 @@ SepInitializationPhase0(VOID)
 {
     PAGED_CODE();
 
 {
     PAGED_CODE();
 
-    ExpInitLuid();
+    if (!ExLuidInitialization()) return FALSE;
     if (!SepInitSecurityIDs()) return FALSE;
     if (!SepInitDACLs()) return FALSE;
     if (!SepInitSDs()) return FALSE;
     if (!SepInitSecurityIDs()) return FALSE;
     if (!SepInitDACLs()) return FALSE;
     if (!SepInitSDs()) return FALSE;