3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * PURPOSE: UUID generator
6 * FILE: kernel/ex/uuid.c
9 /* INCLUDES *****************************************************************/
13 #include <internal/debug.h>
15 #define SEED_BUFFER_SIZE 6
17 /* Number of 100ns ticks per clock tick. To be safe, assume that the clock
18 resolution is at least 1000 * 100 * (1/1000000) = 1/10 of a second */
19 #define TICKS_PER_CLOCK_TICK 1000
20 #define SECSPERDAY 86400
21 #define TICKSPERSEC 10000000
23 /* UUID system time starts at October 15, 1582 */
24 #define SECS_15_OCT_1582_TO_1601 ((17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY)
25 #define TICKS_15_OCT_1582_TO_1601 ((ULONGLONG)SECS_15_OCT_1582_TO_1601 * TICKSPERSEC)
28 /* GLOBALS ****************************************************************/
30 static FAST_MUTEX UuidMutex
;
31 static LARGE_INTEGER UuidLastTime
;
32 static ULONG UuidSequence
;
33 static BOOLEAN UuidSequenceInitialized
= FALSE
;
34 static BOOLEAN UuidSequenceChanged
= FALSE
;
35 static UCHAR UuidSeed
[SEED_BUFFER_SIZE
];
36 static ULONG UuidCount
;
40 /* FUNCTIONS ****************************************************************/
45 ExInitializeFastMutex(&UuidMutex
);
47 KeQuerySystemTime((PLARGE_INTEGER
)&UuidLastTime
);
48 UuidLastTime
.QuadPart
+= TICKS_15_OCT_1582_TO_1601
;
50 UuidCount
= TICKS_PER_CLOCK_TICK
;
51 RtlZeroMemory(UuidSeed
, SEED_BUFFER_SIZE
);
55 #define VALUE_BUFFER_SIZE 256
58 ExpLoadUuidSequence(PULONG Sequence
)
60 UCHAR ValueBuffer
[VALUE_BUFFER_SIZE
];
61 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
62 OBJECT_ATTRIBUTES ObjectAttributes
;
68 RtlInitUnicodeString(&Name
,
69 L
"\\Registry\\Machine\\Software\\Microsoft\\Rpc");
70 InitializeObjectAttributes(&ObjectAttributes
,
75 Status
= NtOpenKey(&KeyHandle
,
78 if (!NT_SUCCESS(Status
))
80 DPRINT("NtOpenKey() failed (Status %lx)\n", Status
);
84 RtlInitUnicodeString(&Name
,
85 L
"UuidSequenceNumber");
87 ValueInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)ValueBuffer
;
88 Status
= NtQueryValueKey(KeyHandle
,
90 KeyValuePartialInformation
,
95 if (!NT_SUCCESS(Status
))
97 DPRINT("NtQueryValueKey() failed (Status %lx)\n", Status
);
101 *Sequence
= *((PULONG
)ValueInfo
->Data
);
103 DPRINT("Loaded sequence %lx\n", *Sequence
);
105 return STATUS_SUCCESS
;
107 #undef VALUE_BUFFER_SIZE
111 ExpSaveUuidSequence(PULONG Sequence
)
113 OBJECT_ATTRIBUTES ObjectAttributes
;
118 RtlInitUnicodeString(&Name
,
119 L
"\\Registry\\Machine\\Software\\Microsoft\\Rpc");
120 InitializeObjectAttributes(&ObjectAttributes
,
122 OBJ_CASE_INSENSITIVE
,
125 Status
= NtOpenKey(&KeyHandle
,
128 if (!NT_SUCCESS(Status
))
130 DPRINT("NtOpenKey() failed (Status %lx)\n", Status
);
134 RtlInitUnicodeString(&Name
,
135 L
"UuidSequenceNumber");
136 Status
= NtSetValueKey(KeyHandle
,
143 if (!NT_SUCCESS(Status
))
145 DPRINT("NtSetValueKey() failed (Status %lx)\n", Status
);
153 ExpGetRandomUuidSequence(PULONG Sequence
)
155 LARGE_INTEGER Counter
;
156 LARGE_INTEGER Frequency
;
159 Counter
= KeQueryPerformanceCounter(&Frequency
);
160 Value
= Counter
.u
.LowPart
^ Counter
.u
.HighPart
;
162 *Sequence
= *Sequence
^ Value
;
164 DPRINT("Sequence %lx\n", *Sequence
);
169 ExpCreateUuids(PULARGE_INTEGER Time
,
174 * Generate time element of the UUID. Account for going faster
175 * than our clock as well as the clock going backwards.
179 KeQuerySystemTime((PLARGE_INTEGER
)Time
);
180 Time
->QuadPart
+= TICKS_15_OCT_1582_TO_1601
;
182 if (Time
->QuadPart
> UuidLastTime
.QuadPart
)
188 if (Time
->QuadPart
< UuidLastTime
.QuadPart
)
191 UuidSequenceChanged
= TRUE
;
196 if (UuidCount
< TICKS_PER_CLOCK_TICK
)
203 UuidLastTime
.QuadPart
= Time
->QuadPart
;
204 Time
->QuadPart
+= UuidCount
;
206 *Range
= 10000; /* What does this mean? Ticks per millisecond?*/
208 return STATUS_SUCCESS
;
216 NtAllocateUuids(OUT PULARGE_INTEGER Time
,
221 ULARGE_INTEGER IntTime
;
225 ExAcquireFastMutex(&UuidMutex
);
227 if (!UuidSequenceInitialized
)
229 Status
= ExpLoadUuidSequence(&UuidSequence
);
230 if (NT_SUCCESS(Status
))
236 ExpGetRandomUuidSequence(&UuidSequence
);
239 UuidSequenceInitialized
= TRUE
;
240 UuidSequenceChanged
= TRUE
;
243 Status
= ExpCreateUuids(&IntTime
,
246 if (!NT_SUCCESS(Status
))
248 ExReleaseFastMutex(&UuidMutex
);
252 if (UuidSequenceChanged
)
254 Status
= ExpSaveUuidSequence(&UuidSequence
);
255 if (NT_SUCCESS(Status
))
256 UuidSequenceChanged
= FALSE
;
259 ExReleaseFastMutex(&UuidMutex
);
261 Time
->QuadPart
= IntTime
.QuadPart
;
263 *Sequence
= UuidSequence
;
269 return STATUS_SUCCESS
;
277 NtSetUuidSeed(IN PUCHAR Seed
)
279 RtlCopyMemory(UuidSeed
,
282 return STATUS_SUCCESS
;