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 LARGE_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 ****************************************************************/
47 ExInitializeFastMutex(&UuidMutex
);
49 KeQuerySystemTime((PLARGE_INTEGER
)&UuidLastTime
);
50 UuidLastTime
.QuadPart
+= TICKS_15_OCT_1582_TO_1601
;
52 UuidCount
= TICKS_PER_CLOCK_TICK
;
53 RtlZeroMemory(UuidSeed
, SEED_BUFFER_SIZE
);
57 #define VALUE_BUFFER_SIZE 256
60 ExpLoadUuidSequence(PULONG Sequence
)
62 UCHAR ValueBuffer
[VALUE_BUFFER_SIZE
];
63 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
64 OBJECT_ATTRIBUTES ObjectAttributes
;
70 RtlInitUnicodeString(&Name
,
71 L
"\\Registry\\Machine\\Software\\Microsoft\\Rpc");
72 InitializeObjectAttributes(&ObjectAttributes
,
77 Status
= ZwOpenKey(&KeyHandle
,
80 if (!NT_SUCCESS(Status
))
82 DPRINT("ZwOpenKey() failed (Status %lx)\n", Status
);
86 RtlInitUnicodeString(&Name
,
87 L
"UuidSequenceNumber");
89 ValueInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)ValueBuffer
;
90 Status
= ZwQueryValueKey(KeyHandle
,
92 KeyValuePartialInformation
,
97 if (!NT_SUCCESS(Status
))
99 DPRINT("ZwQueryValueKey() failed (Status %lx)\n", Status
);
103 *Sequence
= *((PULONG
)ValueInfo
->Data
);
105 DPRINT("Loaded sequence %lx\n", *Sequence
);
107 return STATUS_SUCCESS
;
109 #undef VALUE_BUFFER_SIZE
113 ExpSaveUuidSequence(PULONG Sequence
)
115 OBJECT_ATTRIBUTES ObjectAttributes
;
120 RtlInitUnicodeString(&Name
,
121 L
"\\Registry\\Machine\\Software\\Microsoft\\Rpc");
122 InitializeObjectAttributes(&ObjectAttributes
,
124 OBJ_CASE_INSENSITIVE
,
127 Status
= ZwOpenKey(&KeyHandle
,
130 if (!NT_SUCCESS(Status
))
132 DPRINT("ZwOpenKey() failed (Status %lx)\n", Status
);
136 RtlInitUnicodeString(&Name
,
137 L
"UuidSequenceNumber");
138 Status
= ZwSetValueKey(KeyHandle
,
145 if (!NT_SUCCESS(Status
))
147 DPRINT("ZwSetValueKey() failed (Status %lx)\n", Status
);
155 ExpGetRandomUuidSequence(PULONG Sequence
)
157 LARGE_INTEGER Counter
;
158 LARGE_INTEGER Frequency
;
161 Counter
= KeQueryPerformanceCounter(&Frequency
);
162 Value
= Counter
.u
.LowPart
^ Counter
.u
.HighPart
;
164 *Sequence
= *Sequence
^ Value
;
166 DPRINT("Sequence %lx\n", *Sequence
);
171 ExpCreateUuids(PULARGE_INTEGER Time
,
176 * Generate time element of the UUID. Account for going faster
177 * than our clock as well as the clock going backwards.
181 KeQuerySystemTime((PLARGE_INTEGER
)Time
);
182 Time
->QuadPart
+= TICKS_15_OCT_1582_TO_1601
;
184 if (Time
->QuadPart
> UuidLastTime
.QuadPart
)
190 if (Time
->QuadPart
< UuidLastTime
.QuadPart
)
193 UuidSequenceChanged
= TRUE
;
198 if (UuidCount
< TICKS_PER_CLOCK_TICK
)
205 UuidLastTime
.QuadPart
= Time
->QuadPart
;
206 Time
->QuadPart
+= UuidCount
;
208 *Range
= 10000; /* What does this mean? Ticks per millisecond?*/
210 return STATUS_SUCCESS
;
218 NtAllocateUuids(OUT PULARGE_INTEGER Time
,
223 ULARGE_INTEGER IntTime
;
229 ExAcquireFastMutex(&UuidMutex
);
231 if (!UuidSequenceInitialized
)
233 Status
= ExpLoadUuidSequence(&UuidSequence
);
234 if (NT_SUCCESS(Status
))
240 ExpGetRandomUuidSequence(&UuidSequence
);
243 UuidSequenceInitialized
= TRUE
;
244 UuidSequenceChanged
= TRUE
;
247 Status
= ExpCreateUuids(&IntTime
,
250 if (!NT_SUCCESS(Status
))
252 ExReleaseFastMutex(&UuidMutex
);
256 if (UuidSequenceChanged
)
258 Status
= ExpSaveUuidSequence(&UuidSequence
);
259 if (NT_SUCCESS(Status
))
260 UuidSequenceChanged
= FALSE
;
263 ExReleaseFastMutex(&UuidMutex
);
265 Time
->QuadPart
= IntTime
.QuadPart
;
267 *Sequence
= UuidSequence
;
273 return STATUS_SUCCESS
;
281 NtSetUuidSeed(IN PUCHAR Seed
)
285 RtlCopyMemory(UuidSeed
,
288 return STATUS_SUCCESS
;