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)
30 /* GLOBALS ****************************************************************/
32 static FAST_MUTEX UuidMutex
;
33 static ULARGE_INTEGER UuidLastTime
;
34 static ULONG UuidSequence
;
35 static BOOLEAN UuidSequenceInitialized
= FALSE
;
36 static BOOLEAN UuidSequenceChanged
= FALSE
;
37 static UCHAR UuidSeed
[SEED_BUFFER_SIZE
];
38 static ULONG UuidCount
;
42 /* FUNCTIONS ****************************************************************/
49 ExInitializeFastMutex(&UuidMutex
);
51 KeQuerySystemTime((PLARGE_INTEGER
)&UuidLastTime
);
52 UuidLastTime
.QuadPart
+= TICKS_15_OCT_1582_TO_1601
;
54 UuidCount
= TICKS_PER_CLOCK_TICK
;
55 RtlZeroMemory(UuidSeed
, SEED_BUFFER_SIZE
);
59 #define VALUE_BUFFER_SIZE 256
62 ExpLoadUuidSequence(PULONG Sequence
)
64 UCHAR ValueBuffer
[VALUE_BUFFER_SIZE
];
65 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
66 OBJECT_ATTRIBUTES ObjectAttributes
;
72 RtlInitUnicodeString(&Name
,
73 L
"\\Registry\\Machine\\Software\\Microsoft\\Rpc");
74 InitializeObjectAttributes(&ObjectAttributes
,
79 Status
= ZwOpenKey(&KeyHandle
,
82 if (!NT_SUCCESS(Status
))
84 DPRINT("ZwOpenKey() failed (Status %lx)\n", Status
);
88 RtlInitUnicodeString(&Name
,
89 L
"UuidSequenceNumber");
91 ValueInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)ValueBuffer
;
92 Status
= ZwQueryValueKey(KeyHandle
,
94 KeyValuePartialInformation
,
99 if (!NT_SUCCESS(Status
))
101 DPRINT("ZwQueryValueKey() failed (Status %lx)\n", Status
);
105 *Sequence
= *((PULONG
)ValueInfo
->Data
);
107 DPRINT("Loaded sequence %lx\n", *Sequence
);
109 return STATUS_SUCCESS
;
111 #undef VALUE_BUFFER_SIZE
115 ExpSaveUuidSequence(PULONG Sequence
)
117 OBJECT_ATTRIBUTES ObjectAttributes
;
122 RtlInitUnicodeString(&Name
,
123 L
"\\Registry\\Machine\\Software\\Microsoft\\Rpc");
124 InitializeObjectAttributes(&ObjectAttributes
,
126 OBJ_CASE_INSENSITIVE
,
129 Status
= ZwOpenKey(&KeyHandle
,
132 if (!NT_SUCCESS(Status
))
134 DPRINT("ZwOpenKey() failed (Status %lx)\n", Status
);
138 RtlInitUnicodeString(&Name
,
139 L
"UuidSequenceNumber");
140 Status
= ZwSetValueKey(KeyHandle
,
147 if (!NT_SUCCESS(Status
))
149 DPRINT("ZwSetValueKey() failed (Status %lx)\n", Status
);
157 ExpGetRandomUuidSequence(PULONG Sequence
)
159 LARGE_INTEGER Counter
;
160 LARGE_INTEGER Frequency
;
163 Counter
= KeQueryPerformanceCounter(&Frequency
);
164 Value
= Counter
.u
.LowPart
^ Counter
.u
.HighPart
;
166 *Sequence
= *Sequence
^ Value
;
168 DPRINT("Sequence %lx\n", *Sequence
);
173 ExpCreateUuids(PULARGE_INTEGER Time
,
178 * Generate time element of the UUID. Account for going faster
179 * than our clock as well as the clock going backwards.
183 KeQuerySystemTime((PLARGE_INTEGER
)Time
);
184 Time
->QuadPart
+= TICKS_15_OCT_1582_TO_1601
;
186 if (Time
->QuadPart
> UuidLastTime
.QuadPart
)
192 if (Time
->QuadPart
< UuidLastTime
.QuadPart
)
195 UuidSequenceChanged
= TRUE
;
200 if (UuidCount
< TICKS_PER_CLOCK_TICK
)
207 UuidLastTime
.QuadPart
= Time
->QuadPart
;
208 Time
->QuadPart
+= UuidCount
;
210 *Range
= 10000; /* What does this mean? Ticks per millisecond?*/
212 return STATUS_SUCCESS
;
232 NtAllocateUuids(OUT PULARGE_INTEGER Time
,
237 ULARGE_INTEGER IntTime
;
243 ExAcquireFastMutex(&UuidMutex
);
245 if (!UuidSequenceInitialized
)
247 Status
= ExpLoadUuidSequence(&UuidSequence
);
248 if (NT_SUCCESS(Status
))
254 ExpGetRandomUuidSequence(&UuidSequence
);
257 UuidSequenceInitialized
= TRUE
;
258 UuidSequenceChanged
= TRUE
;
261 Status
= ExpCreateUuids(&IntTime
,
264 if (!NT_SUCCESS(Status
))
266 ExReleaseFastMutex(&UuidMutex
);
270 if (UuidSequenceChanged
)
272 Status
= ExpSaveUuidSequence(&UuidSequence
);
273 if (NT_SUCCESS(Status
))
274 UuidSequenceChanged
= FALSE
;
277 ExReleaseFastMutex(&UuidMutex
);
279 Time
->QuadPart
= IntTime
.QuadPart
;
281 *Sequence
= UuidSequence
;
287 return STATUS_SUCCESS
;
295 NtSetUuidSeed(IN PUCHAR Seed
)
299 RtlCopyMemory(UuidSeed
,
302 return STATUS_SUCCESS
;