Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenuuid.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
1.7.6.1
|