3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ex/uuid.c
6 * PURPOSE: UUID generator
8 * PROGRAMMERS: No programmer listed.
11 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
17 #define SEED_BUFFER_SIZE 6
19 /* Number of 100ns ticks per clock tick. To be safe, assume that the clock
20 resolution is at least 1000 * 100 * (1/1000000) = 1/10 of a second */
21 #define TICKS_PER_CLOCK_TICK 1000
22 #define SECSPERDAY 86400
23 #define TICKSPERSEC 10000000
25 /* UUID system time starts at October 15, 1582 */
26 #define SECS_15_OCT_1582_TO_1601 ((17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY)
27 #define TICKS_15_OCT_1582_TO_1601 ((ULONGLONG)SECS_15_OCT_1582_TO_1601 * TICKSPERSEC)
29 #if defined (ALLOC_PRAGMA)
30 #pragma alloc_text(INIT, ExpInitUuids)
34 /* GLOBALS ****************************************************************/
36 static FAST_MUTEX UuidMutex
;
37 static ULARGE_INTEGER UuidLastTime
;
38 static ULONG UuidSequence
;
39 static BOOLEAN UuidSequenceInitialized
= FALSE
;
40 static BOOLEAN UuidSequenceChanged
= FALSE
;
41 static UCHAR UuidSeed
[SEED_BUFFER_SIZE
];
42 static ULONG UuidCount
;
46 /* FUNCTIONS ****************************************************************/
53 ExInitializeFastMutex(&UuidMutex
);
55 KeQuerySystemTime((PLARGE_INTEGER
)&UuidLastTime
);
56 UuidLastTime
.QuadPart
+= TICKS_15_OCT_1582_TO_1601
;
58 UuidCount
= TICKS_PER_CLOCK_TICK
;
59 RtlZeroMemory(UuidSeed
, SEED_BUFFER_SIZE
);
63 #define VALUE_BUFFER_SIZE 256
66 ExpLoadUuidSequence(PULONG Sequence
)
68 UCHAR ValueBuffer
[VALUE_BUFFER_SIZE
];
69 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
70 OBJECT_ATTRIBUTES ObjectAttributes
;
76 RtlInitUnicodeString(&Name
,
77 L
"\\Registry\\Machine\\Software\\Microsoft\\Rpc");
78 InitializeObjectAttributes(&ObjectAttributes
,
83 Status
= ZwOpenKey(&KeyHandle
,
86 if (!NT_SUCCESS(Status
))
88 DPRINT("ZwOpenKey() failed (Status %lx)\n", Status
);
92 RtlInitUnicodeString(&Name
,
93 L
"UuidSequenceNumber");
95 ValueInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)ValueBuffer
;
96 Status
= ZwQueryValueKey(KeyHandle
,
98 KeyValuePartialInformation
,
103 if (!NT_SUCCESS(Status
))
105 DPRINT("ZwQueryValueKey() failed (Status %lx)\n", Status
);
109 *Sequence
= *((PULONG
)ValueInfo
->Data
);
111 DPRINT("Loaded sequence %lx\n", *Sequence
);
113 return STATUS_SUCCESS
;
115 #undef VALUE_BUFFER_SIZE
119 ExpSaveUuidSequence(PULONG Sequence
)
121 OBJECT_ATTRIBUTES ObjectAttributes
;
126 RtlInitUnicodeString(&Name
,
127 L
"\\Registry\\Machine\\Software\\Microsoft\\Rpc");
128 InitializeObjectAttributes(&ObjectAttributes
,
130 OBJ_CASE_INSENSITIVE
,
133 Status
= ZwOpenKey(&KeyHandle
,
136 if (!NT_SUCCESS(Status
))
138 DPRINT("ZwOpenKey() failed (Status %lx)\n", Status
);
142 RtlInitUnicodeString(&Name
,
143 L
"UuidSequenceNumber");
144 Status
= ZwSetValueKey(KeyHandle
,
151 if (!NT_SUCCESS(Status
))
153 DPRINT("ZwSetValueKey() failed (Status %lx)\n", Status
);
161 ExpGetRandomUuidSequence(PULONG Sequence
)
163 LARGE_INTEGER Counter
;
164 LARGE_INTEGER Frequency
;
167 Counter
= KeQueryPerformanceCounter(&Frequency
);
168 Value
= Counter
.u
.LowPart
^ Counter
.u
.HighPart
;
170 *Sequence
= *Sequence
^ Value
;
172 DPRINT("Sequence %lx\n", *Sequence
);
177 ExpCreateUuids(PULARGE_INTEGER Time
,
182 * Generate time element of the UUID. Account for going faster
183 * than our clock as well as the clock going backwards.
187 KeQuerySystemTime((PLARGE_INTEGER
)Time
);
188 Time
->QuadPart
+= TICKS_15_OCT_1582_TO_1601
;
190 if (Time
->QuadPart
> UuidLastTime
.QuadPart
)
196 if (Time
->QuadPart
< UuidLastTime
.QuadPart
)
199 UuidSequenceChanged
= TRUE
;
204 if (UuidCount
< TICKS_PER_CLOCK_TICK
)
211 UuidLastTime
.QuadPart
= Time
->QuadPart
;
212 Time
->QuadPart
+= UuidCount
;
214 *Range
= 10000; /* What does this mean? Ticks per millisecond?*/
216 return STATUS_SUCCESS
;
236 NtAllocateUuids(OUT PULARGE_INTEGER Time
,
241 ULARGE_INTEGER IntTime
;
247 ExAcquireFastMutex(&UuidMutex
);
249 if (!UuidSequenceInitialized
)
251 Status
= ExpLoadUuidSequence(&UuidSequence
);
252 if (NT_SUCCESS(Status
))
258 ExpGetRandomUuidSequence(&UuidSequence
);
261 UuidSequenceInitialized
= TRUE
;
262 UuidSequenceChanged
= TRUE
;
265 Status
= ExpCreateUuids(&IntTime
,
268 if (!NT_SUCCESS(Status
))
270 ExReleaseFastMutex(&UuidMutex
);
274 if (UuidSequenceChanged
)
276 Status
= ExpSaveUuidSequence(&UuidSequence
);
277 if (NT_SUCCESS(Status
))
278 UuidSequenceChanged
= FALSE
;
281 ExReleaseFastMutex(&UuidMutex
);
283 Time
->QuadPart
= IntTime
.QuadPart
;
285 *Sequence
= UuidSequence
;
291 return STATUS_SUCCESS
;
299 NtSetUuidSeed(IN PUCHAR Seed
)
303 RtlCopyMemory(UuidSeed
,
306 return STATUS_SUCCESS
;