ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

uuid.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS kernel
00004  * FILE:            ntoskrnl/ex/uuid.c
00005  * PURPOSE:         UUID generator
00006  *
00007  * PROGRAMMERS:     Eric Kohl
00008                     Thomas Weidenmueller
00009  */
00010 
00011 /* INCLUDES *****************************************************************/
00012 
00013 #include <ntoskrnl.h>
00014 #define NDEBUG
00015 #include <debug.h>
00016 
00017 #define SEED_BUFFER_SIZE 6
00018 
00019 /* Number of 100ns ticks per clock tick. To be safe, assume that the clock
00020    resolution is at least 1000 * 100 * (1/1000000) = 1/10 of a second */
00021 #define TICKS_PER_CLOCK_TICK 1000
00022 #define SECSPERDAY  86400
00023 #define TICKSPERSEC 10000000
00024 
00025 /* UUID system time starts at October 15, 1582 */
00026 #define SECS_15_OCT_1582_TO_1601  ((17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY)
00027 #define TICKS_15_OCT_1582_TO_1601 ((ULONGLONG)SECS_15_OCT_1582_TO_1601 * TICKSPERSEC)
00028 
00029 #if defined (ALLOC_PRAGMA)
00030 #pragma alloc_text(INIT, ExpInitUuids)
00031 #endif
00032 
00033 
00034 /* GLOBALS ****************************************************************/
00035 
00036 static FAST_MUTEX UuidMutex;
00037 static ULARGE_INTEGER UuidLastTime;
00038 static ULONG UuidSequence;
00039 static BOOLEAN UuidSequenceInitialized = FALSE;
00040 static BOOLEAN UuidSequenceChanged = FALSE;
00041 static UCHAR UuidSeed[SEED_BUFFER_SIZE];
00042 static ULONG UuidCount;
00043 static LARGE_INTEGER LuidIncrement;
00044 static LARGE_INTEGER LuidValue;
00045 
00046 /* FUNCTIONS ****************************************************************/
00047 
00048 VOID
00049 INIT_FUNCTION
00050 NTAPI
00051 ExpInitUuids(VOID)
00052 {
00053     ExInitializeFastMutex(&UuidMutex);
00054 
00055     KeQuerySystemTime((PLARGE_INTEGER)&UuidLastTime);
00056     UuidLastTime.QuadPart += TICKS_15_OCT_1582_TO_1601;
00057 
00058     UuidCount = TICKS_PER_CLOCK_TICK;
00059     RtlZeroMemory(UuidSeed, SEED_BUFFER_SIZE);
00060 }
00061 
00062 
00063 #define VALUE_BUFFER_SIZE 256
00064 
00065 static NTSTATUS
00066 ExpLoadUuidSequence(PULONG Sequence)
00067 {
00068     UCHAR ValueBuffer[VALUE_BUFFER_SIZE];
00069     PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
00070     OBJECT_ATTRIBUTES ObjectAttributes;
00071     UNICODE_STRING Name;
00072     HANDLE KeyHandle;
00073     ULONG ValueLength;
00074     NTSTATUS Status;
00075 
00076     RtlInitUnicodeString(&Name,
00077         L"\\Registry\\Machine\\Software\\Microsoft\\Rpc");
00078     InitializeObjectAttributes(&ObjectAttributes,
00079                                &Name,
00080                                OBJ_CASE_INSENSITIVE,
00081                                NULL,
00082                                NULL);
00083     Status = ZwOpenKey(&KeyHandle,
00084                        KEY_QUERY_VALUE,
00085                        &ObjectAttributes);
00086     if (!NT_SUCCESS(Status))
00087     {
00088         DPRINT("ZwOpenKey() failed (Status %lx)\n", Status);
00089         return Status;
00090     }
00091 
00092     RtlInitUnicodeString(&Name, L"UuidSequenceNumber");
00093 
00094     ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
00095     Status = ZwQueryValueKey(KeyHandle,
00096                              &Name,
00097                              KeyValuePartialInformation,
00098                              ValueBuffer,
00099                              VALUE_BUFFER_SIZE,
00100                              &ValueLength);
00101     ZwClose(KeyHandle);
00102     if (!NT_SUCCESS(Status))
00103     {
00104         DPRINT("ZwQueryValueKey() failed (Status %lx)\n", Status);
00105         return Status;
00106     }
00107 
00108     *Sequence = *((PULONG)ValueInfo->Data);
00109 
00110     DPRINT("Loaded sequence %lx\n", *Sequence);
00111 
00112     return STATUS_SUCCESS;
00113 }
00114 #undef VALUE_BUFFER_SIZE
00115 
00116 
00117 static NTSTATUS
00118 ExpSaveUuidSequence(PULONG Sequence)
00119 {
00120     OBJECT_ATTRIBUTES ObjectAttributes;
00121     UNICODE_STRING Name;
00122     HANDLE KeyHandle;
00123     NTSTATUS Status;
00124 
00125     RtlInitUnicodeString(&Name,
00126         L"\\Registry\\Machine\\Software\\Microsoft\\Rpc");
00127     InitializeObjectAttributes(&ObjectAttributes,
00128                                &Name,
00129                                OBJ_CASE_INSENSITIVE,
00130                                NULL,
00131                                NULL);
00132     Status = ZwOpenKey(&KeyHandle,
00133                        KEY_SET_VALUE,
00134                        &ObjectAttributes);
00135     if (!NT_SUCCESS(Status))
00136     {
00137         DPRINT("ZwOpenKey() failed (Status %lx)\n", Status);
00138         return Status;
00139     }
00140 
00141     RtlInitUnicodeString(&Name, L"UuidSequenceNumber");
00142     Status = ZwSetValueKey(KeyHandle,
00143                            &Name,
00144                            0,
00145                            REG_DWORD,
00146                            Sequence,
00147                            sizeof(ULONG));
00148     ZwClose(KeyHandle);
00149     if (!NT_SUCCESS(Status))
00150     {
00151         DPRINT("ZwSetValueKey() failed (Status %lx)\n", Status);
00152     }
00153 
00154     return Status;
00155 }
00156 
00157 
00158 static VOID
00159 ExpGetRandomUuidSequence(PULONG Sequence)
00160 {
00161     LARGE_INTEGER Counter;
00162     LARGE_INTEGER Frequency;
00163     ULONG Value;
00164 
00165     Counter = KeQueryPerformanceCounter(&Frequency);
00166     Value = Counter.u.LowPart ^ Counter.u.HighPart;
00167 
00168     *Sequence = *Sequence ^ Value;
00169 
00170     DPRINT("Sequence %lx\n", *Sequence);
00171 }
00172 
00173 
00174 static NTSTATUS
00175 ExpCreateUuids(PULARGE_INTEGER Time,
00176                PULONG Range,
00177                PULONG Sequence)
00178 {
00179     /*
00180     * Generate time element of the UUID. Account for going faster
00181     * than our clock as well as the clock going backwards.
00182     */
00183     while (1)
00184     {
00185         KeQuerySystemTime((PLARGE_INTEGER)Time);
00186         Time->QuadPart += TICKS_15_OCT_1582_TO_1601;
00187 
00188         if (Time->QuadPart > UuidLastTime.QuadPart)
00189         {
00190             UuidCount = 0;
00191             break;
00192         }
00193 
00194         if (Time->QuadPart < UuidLastTime.QuadPart)
00195         {
00196             (*Sequence)++;
00197             UuidSequenceChanged = TRUE;
00198             UuidCount = 0;
00199             break;
00200         }
00201 
00202         if (UuidCount < TICKS_PER_CLOCK_TICK)
00203         {
00204             UuidCount++;
00205             break;
00206         }
00207     }
00208 
00209     UuidLastTime.QuadPart = Time->QuadPart;
00210     Time->QuadPart += UuidCount;
00211 
00212     *Range = 10000; /* What does this mean? Ticks per millisecond?*/
00213 
00214     return STATUS_SUCCESS;
00215 }
00216 
00217 VOID
00218 INIT_FUNCTION
00219 NTAPI
00220 ExpInitLuid(VOID)
00221 {
00222     LUID DummyLuidValue = SYSTEM_LUID;
00223 
00224     LuidValue.u.HighPart = DummyLuidValue.HighPart;
00225     LuidValue.u.LowPart = DummyLuidValue.LowPart;
00226     LuidIncrement.QuadPart = 1;
00227 }
00228 
00229 
00230 NTSTATUS
00231 NTAPI
00232 ExpAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
00233 {
00234     LARGE_INTEGER NewLuid, PrevLuid;
00235 
00236     /* atomically increment the luid */
00237     do
00238     {
00239         PrevLuid = LuidValue;
00240         NewLuid = RtlLargeIntegerAdd(PrevLuid,
00241                                      LuidIncrement);
00242     } while(ExInterlockedCompareExchange64(&LuidValue.QuadPart,
00243                                            &NewLuid.QuadPart,
00244                                            &PrevLuid.QuadPart,
00245                                            NULL) != PrevLuid.QuadPart);
00246 
00247     LocallyUniqueId->LowPart = NewLuid.u.LowPart;
00248     LocallyUniqueId->HighPart = NewLuid.u.HighPart;
00249 
00250     return STATUS_SUCCESS;
00251 }
00252 
00253 
00254 /*
00255  * @implemented
00256  */
00257 NTSTATUS NTAPI
00258 NtAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
00259 {
00260     LUID NewLuid;
00261     KPROCESSOR_MODE PreviousMode;
00262     NTSTATUS Status;
00263 
00264     PAGED_CODE();
00265 
00266     PreviousMode = ExGetPreviousMode();
00267 
00268     if(PreviousMode != KernelMode)
00269     {
00270         _SEH2_TRY
00271         {
00272             ProbeForWrite(LocallyUniqueId,
00273                           sizeof(LUID),
00274                           sizeof(ULONG));
00275         }
00276         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00277         {
00278             _SEH2_YIELD(return _SEH2_GetExceptionCode());
00279         }
00280         _SEH2_END;
00281     }
00282 
00283     Status = ExpAllocateLocallyUniqueId(&NewLuid);
00284 
00285     _SEH2_TRY
00286     {
00287         *LocallyUniqueId = NewLuid;
00288     }
00289     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00290     {
00291         Status = _SEH2_GetExceptionCode();
00292     }
00293     _SEH2_END;
00294 
00295     return Status;
00296 }
00297 
00298 /*
00299  * @unimplemented
00300  */
00301 NTSTATUS
00302 NTAPI
00303 ExUuidCreate(OUT UUID *Uuid)
00304 {
00305     UNIMPLEMENTED;
00306     return FALSE;
00307 }
00308 
00309 /*
00310  * @unimplemented
00311  */
00312 NTSTATUS
00313 NTAPI
00314 NtAllocateUuids(OUT PULARGE_INTEGER Time,
00315                 OUT PULONG Range,
00316                 OUT PULONG Sequence,
00317                 OUT PUCHAR Seed)
00318 {
00319     ULARGE_INTEGER IntTime;
00320     ULONG IntRange;
00321     NTSTATUS Status;
00322 
00323     PAGED_CODE();
00324 
00325     ExAcquireFastMutex(&UuidMutex);
00326 
00327     if (!UuidSequenceInitialized)
00328     {
00329         Status = ExpLoadUuidSequence(&UuidSequence);
00330         if (NT_SUCCESS(Status))
00331         {
00332             UuidSequence++;
00333         }
00334         else
00335         {
00336             ExpGetRandomUuidSequence(&UuidSequence);
00337         }
00338 
00339         UuidSequenceInitialized = TRUE;
00340         UuidSequenceChanged = TRUE;
00341     }
00342 
00343     Status = ExpCreateUuids(&IntTime,
00344                             &IntRange,
00345                             &UuidSequence);
00346     if (!NT_SUCCESS(Status))
00347     {
00348         ExReleaseFastMutex(&UuidMutex);
00349         return Status;
00350     }
00351 
00352     if (UuidSequenceChanged)
00353     {
00354         Status = ExpSaveUuidSequence(&UuidSequence);
00355         if (NT_SUCCESS(Status))
00356             UuidSequenceChanged = FALSE;
00357     }
00358 
00359     ExReleaseFastMutex(&UuidMutex);
00360 
00361     Time->QuadPart = IntTime.QuadPart;
00362     *Range = IntRange;
00363     *Sequence = UuidSequence;
00364 
00365     RtlCopyMemory(Seed,
00366                   UuidSeed,
00367                   SEED_BUFFER_SIZE);
00368 
00369     return STATUS_SUCCESS;
00370 }
00371 
00372 
00373 /*
00374  * @implemented
00375  */
00376 NTSTATUS
00377 NTAPI
00378 NtSetUuidSeed(IN PUCHAR Seed)
00379 {
00380     PAGED_CODE();
00381 
00382     RtlCopyMemory(UuidSeed,
00383                   Seed,
00384                   SEED_BUFFER_SIZE);
00385     return STATUS_SUCCESS;
00386 }
00387 
00388 /* EOF */

Generated on Sun May 27 2012 04:25:26 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.