- Move CmpCreateRootNode and CmpCreateRegistryRoot to cmsysini.c as well, and add...
[reactos.git] / reactos / ntoskrnl / config / cmsysini.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/config/cmsysini.c
5 * PURPOSE: Configuration Manager - System Initialization Code
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "ntoskrnl.h"
12 #include "cm.h"
13 #define NDEBUG
14 #include "debug.h"
15
16 /* GLOBALS *******************************************************************/
17
18 HIVE_LIST_ENTRY CmpMachineHiveList[5];
19
20 UNICODE_STRING CmSymbolicLinkValueName =
21 RTL_CONSTANT_STRING(L"SymbolicLinkValue");
22
23 UNICODE_STRING CmpSystemStartOptions;
24 UNICODE_STRING CmpLoadOptions;
25
26 BOOLEAN CmpShareSystemHives;
27 BOOLEAN CmSelfHeal = TRUE;
28 BOOLEAN CmpSelfHeal = TRUE;
29 ULONG CmpBootType;
30
31 HANDLE CmpRegistryRootHandle;
32
33 extern BOOLEAN ExpInTextModeSetup;
34
35 /* FUNCTIONS *****************************************************************/
36
37 NTSTATUS
38 NTAPI
39 CmpSetSystemValues(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
40 {
41 OBJECT_ATTRIBUTES ObjectAttributes;
42 UNICODE_STRING KeyName, ValueName;
43 HANDLE KeyHandle;
44 NTSTATUS Status;
45 ASSERT(LoaderBlock != NULL);
46 if (ExpInTextModeSetup) return STATUS_SUCCESS;
47
48 /* Setup attributes for loader options */
49 RtlInitUnicodeString(&KeyName,
50 L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\"
51 L"Control");
52 InitializeObjectAttributes(&ObjectAttributes,
53 &KeyName,
54 OBJ_CASE_INSENSITIVE,
55 NULL,
56 NULL);
57 Status = NtOpenKey(&KeyHandle, KEY_WRITE, &ObjectAttributes);
58 if (!NT_SUCCESS(Status)) goto Quickie;
59
60 /* Key opened, now write to the key */
61 RtlInitUnicodeString(&KeyName, L"SystemStartOptions");
62 Status = NtSetValueKey(KeyHandle,
63 &KeyName,
64 0,
65 REG_SZ,
66 CmpSystemStartOptions.Buffer,
67 CmpSystemStartOptions.Length);
68 if (!NT_SUCCESS(Status)) goto Quickie;
69
70 /* Free the options now */
71 ExFreePool(CmpSystemStartOptions.Buffer);
72
73 /* Setup value name for system boot device */
74 RtlInitUnicodeString(&KeyName, L"SystemBootDevice");
75 RtlCreateUnicodeStringFromAsciiz(&ValueName, LoaderBlock->NtBootPathName);
76 Status = NtSetValueKey(KeyHandle,
77 &KeyName,
78 0,
79 REG_SZ,
80 ValueName.Buffer,
81 ValueName.Length);
82
83 Quickie:
84 /* Free the buffers */
85 RtlFreeUnicodeString(&ValueName);
86
87 /* Close the key and return */
88 NtClose(KeyHandle);
89
90 /* Return the status */
91 return Status;
92 }
93
94 NTSTATUS
95 NTAPI
96 CmpCreateControlSet(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
97 {
98 UNICODE_STRING ConfigName = RTL_CONSTANT_STRING(L"Control\\IDConfigDB");
99 UNICODE_STRING SelectName =
100 RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\Select");
101 UNICODE_STRING KeyName;
102 OBJECT_ATTRIBUTES ObjectAttributes;
103 CHAR ValueInfoBuffer[128];
104 PKEY_VALUE_FULL_INFORMATION ValueInfo;
105 CHAR Buffer[128];
106 WCHAR UnicodeBuffer[128];
107 HANDLE SelectHandle, KeyHandle, ConfigHandle = NULL, ProfileHandle = NULL;
108 HANDLE ParentHandle = NULL;
109 ULONG ControlSet, HwProfile;
110 ANSI_STRING TempString;
111 NTSTATUS Status;
112 ULONG ResultLength, Disposition;
113 PLOADER_PARAMETER_EXTENSION LoaderExtension;
114 PAGED_CODE();
115 if (ExpInTextModeSetup) return STATUS_SUCCESS;
116
117 /* Open the select key */
118 InitializeObjectAttributes(&ObjectAttributes,
119 &SelectName,
120 OBJ_CASE_INSENSITIVE,
121 NULL,
122 NULL);
123 Status = NtOpenKey(&SelectHandle, KEY_READ, &ObjectAttributes);
124 if (!NT_SUCCESS(Status)) return(Status);
125
126 /* Open the current value */
127 RtlInitUnicodeString(&KeyName, L"Current");
128 Status = NtQueryValueKey(SelectHandle,
129 &KeyName,
130 KeyValueFullInformation,
131 ValueInfoBuffer,
132 sizeof(ValueInfoBuffer),
133 &ResultLength);
134 NtClose(SelectHandle);
135 if (!NT_SUCCESS(Status)) return Status;
136
137 /* Get the actual value pointer, and get the control set ID */
138 ValueInfo = (PKEY_VALUE_FULL_INFORMATION)ValueInfoBuffer;
139 ControlSet = *(PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset);
140
141 /* Create the current control set key */
142 RtlInitUnicodeString(&KeyName,
143 L"\\Registry\\Machine\\System\\CurrentControlSet");
144 InitializeObjectAttributes(&ObjectAttributes,
145 &KeyName,
146 OBJ_CASE_INSENSITIVE,
147 NULL,
148 NULL);
149 Status = NtCreateKey(&KeyHandle,
150 KEY_CREATE_LINK,
151 &ObjectAttributes,
152 0,
153 NULL,
154 REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
155 &Disposition);
156 if (!NT_SUCCESS(Status)) return Status;
157
158 /* Sanity check */
159 ASSERT(Disposition == REG_CREATED_NEW_KEY);
160
161 /* Initialize the symbolic link name */
162 sprintf(Buffer,
163 "\\Registry\\Machine\\System\\ControlSet%03ld",
164 ControlSet);
165 RtlInitAnsiString(&TempString, Buffer);
166
167 /* Create a Unicode string out of it */
168 KeyName.MaximumLength = sizeof(UnicodeBuffer);
169 KeyName.Buffer = UnicodeBuffer;
170 Status = RtlAnsiStringToUnicodeString(&KeyName, &TempString, FALSE);
171
172 /* Set the value */
173 Status = NtSetValueKey(KeyHandle,
174 &CmSymbolicLinkValueName,
175 0,
176 REG_LINK,
177 KeyName.Buffer,
178 KeyName.Length);
179 if (!NT_SUCCESS(Status)) return Status;
180
181 /* Get the configuration database key */
182 InitializeObjectAttributes(&ObjectAttributes,
183 &ConfigName,
184 OBJ_CASE_INSENSITIVE,
185 KeyHandle,
186 NULL);
187 Status = NtOpenKey(&ConfigHandle, KEY_READ, &ObjectAttributes);
188 NtClose(KeyHandle);
189
190 /* Check if we don't have one */
191 if (!NT_SUCCESS(Status))
192 {
193 /* Cleanup and exit */
194 ConfigHandle = 0;
195 goto Cleanup;
196 }
197
198 /* Now get the current config */
199 RtlInitUnicodeString(&KeyName, L"CurrentConfig");
200 Status = NtQueryValueKey(ConfigHandle,
201 &KeyName,
202 KeyValueFullInformation,
203 ValueInfoBuffer,
204 sizeof(ValueInfoBuffer),
205 &ResultLength);
206
207 /* Set pointer to buffer */
208 ValueInfo = (PKEY_VALUE_FULL_INFORMATION)ValueInfoBuffer;
209
210 /* Check if we failed or got a non DWORD-value */
211 if (!(NT_SUCCESS(Status)) || (ValueInfo->Type != REG_DWORD)) goto Cleanup;
212
213 /* Get the hadware profile */
214 HwProfile = *(PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset);
215
216 /* Open the hardware profile key */
217 RtlInitUnicodeString(&KeyName,
218 L"\\Registry\\Machine\\System\\CurrentControlSet"
219 L"\\Hardware Profiles");
220 InitializeObjectAttributes(&ObjectAttributes,
221 &KeyName,
222 OBJ_CASE_INSENSITIVE,
223 NULL,
224 NULL);
225 Status = NtOpenKey(&ParentHandle, KEY_READ, &ObjectAttributes);
226 if (!NT_SUCCESS(Status))
227 {
228 /* Exit and clean up */
229 ParentHandle = 0;
230 goto Cleanup;
231 }
232
233 /* Build the profile name */
234 sprintf(Buffer, "%04ld", HwProfile);
235 RtlInitAnsiString(&TempString, Buffer);
236
237 /* Convert it to Unicode */
238 KeyName.MaximumLength = sizeof(UnicodeBuffer);
239 KeyName.Buffer = UnicodeBuffer;
240 Status = RtlAnsiStringToUnicodeString(&KeyName,
241 &TempString,
242 FALSE);
243 ASSERT(Status == STATUS_SUCCESS);
244
245 /* Open the associated key */
246 InitializeObjectAttributes(&ObjectAttributes,
247 &KeyName,
248 OBJ_CASE_INSENSITIVE,
249 ParentHandle,
250 NULL);
251 Status = NtOpenKey(&ProfileHandle,
252 KEY_READ | KEY_WRITE,
253 &ObjectAttributes);
254 if (!NT_SUCCESS (Status))
255 {
256 /* Cleanup and exit */
257 ProfileHandle = 0;
258 goto Cleanup;
259 }
260
261 /* Check if we have a loader block extension */
262 LoaderExtension = LoaderBlock->Extension;
263 if (LoaderExtension)
264 {
265 ASSERTMSG("ReactOS doesn't support NTLDR Profiles yet!\n", FALSE);
266 }
267
268 /* Create the current hardware profile key */
269 RtlInitUnicodeString(&KeyName,
270 L"\\Registry\\Machine\\System\\CurrentControlSet\\"
271 L"Hardware Profiles\\Current");
272 InitializeObjectAttributes(&ObjectAttributes,
273 &KeyName,
274 OBJ_CASE_INSENSITIVE,
275 NULL,
276 NULL);
277 Status = NtCreateKey(&KeyHandle,
278 KEY_CREATE_LINK,
279 &ObjectAttributes,
280 0,
281 NULL,
282 REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
283 &Disposition);
284 if (NT_SUCCESS(Status))
285 {
286 /* Sanity check */
287 ASSERT(Disposition == REG_CREATED_NEW_KEY);
288
289 /* Create the profile name */
290 sprintf(Buffer,
291 "\\Registry\\Machine\\System\\CurrentControlSet\\"
292 "Hardware Profiles\\%04ld",
293 HwProfile);
294 RtlInitAnsiString(&TempString, Buffer);
295
296 /* Convert it to Unicode */
297 KeyName.MaximumLength = sizeof(UnicodeBuffer);
298 KeyName.Buffer = UnicodeBuffer;
299 Status = RtlAnsiStringToUnicodeString(&KeyName,
300 &TempString,
301 FALSE);
302 ASSERT(STATUS_SUCCESS == Status);
303
304 /* Set it */
305 Status = NtSetValueKey(KeyHandle,
306 &CmSymbolicLinkValueName,
307 0,
308 REG_LINK,
309 KeyName.Buffer,
310 KeyName.Length);
311 NtClose(KeyHandle);
312 }
313
314 /* Close every opened handle */
315 Cleanup:
316 if (ConfigHandle) NtClose(ConfigHandle);
317 if (ProfileHandle) NtClose(ProfileHandle);
318 if (ParentHandle) NtClose(ParentHandle);
319
320 /* Return success */
321 return STATUS_SUCCESS;
322 }
323
324 BOOLEAN
325 NTAPI
326 CmpInitializeSystemHive(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
327 {
328 PVOID HiveBase;
329 ANSI_STRING LoadString;
330 PVOID Buffer;
331 ULONG Length;
332 NTSTATUS Status;
333 BOOLEAN Allocate;
334 UNICODE_STRING KeyName;
335 PEREGISTRY_HIVE SystemHive = NULL;
336 UNICODE_STRING HiveName = RTL_CONSTANT_STRING(L"SYSTEM");
337 PSECURITY_DESCRIPTOR SecurityDescriptor;
338 PAGED_CODE();
339
340 /* Setup the ansi string */
341 RtlInitAnsiString(&LoadString, LoaderBlock->LoadOptions);
342
343 /* Allocate the unicode buffer */
344 Length = LoadString.Length * sizeof(WCHAR) + sizeof(UNICODE_NULL);
345 Buffer = ExAllocatePoolWithTag(PagedPool, Length, 0);
346 if (!Buffer)
347 {
348 /* Fail */
349 KEBUGCHECKEX(BAD_SYSTEM_CONFIG_INFO, 3, 1, (ULONG_PTR)LoaderBlock, 0);
350 }
351
352 /* Setup the unicode string */
353 RtlInitEmptyUnicodeString(&CmpLoadOptions, Buffer, Length);
354
355 /* Add the load options and null-terminate */
356 RtlAnsiStringToUnicodeString(&CmpLoadOptions, &LoadString, FALSE);
357 CmpLoadOptions.Buffer[LoadString.Length] = UNICODE_NULL;
358 CmpLoadOptions.Length += sizeof(WCHAR);
359
360 /* Get the System Hive base address */
361 HiveBase = LoaderBlock->RegistryBase;
362 if (HiveBase)
363 {
364 /* Import it */
365 ((PHBASE_BLOCK)HiveBase)->Length = LoaderBlock->RegistryLength;
366 Status = CmpInitializeHive((PCMHIVE*)&SystemHive,
367 HINIT_MEMORY,
368 0, //HIVE_NOLAZYFLUSH,
369 HFILE_TYPE_LOG,
370 HiveBase,
371 NULL,
372 NULL,
373 NULL,
374 &HiveName,
375 2);
376 if (!NT_SUCCESS(Status)) return FALSE;
377 CmPrepareHive(&SystemHive->Hive);
378
379 /* Set the hive filename */
380 RtlCreateUnicodeString(&SystemHive->HiveFileName, SYSTEM_REG_FILE);
381
382 /* Set the log filename */
383 RtlCreateUnicodeString(&SystemHive->LogFileName, SYSTEM_LOG_FILE);
384
385 /* We imported, no need to create a new hive */
386 Allocate = FALSE;
387
388 /* Manually set the hive as volatile, if in Live CD mode */
389 if (CmpShareSystemHives) SystemHive->Hive.HiveFlags = HIVE_VOLATILE;
390 }
391 else
392 {
393 #if 0
394 /* Create it */
395 Status = CmpInitializeHive((PCMHIVE*)&SystemHive,
396 HINIT_CREATE,
397 HIVE_NOLAZYFLUSH,
398 HFILE_TYPE_LOG,
399 NULL,
400 NULL,
401 NULL,
402 NULL,
403 &HiveName,
404 0);
405 if (!NT_SUCCESS(Status)) return FALSE;
406 #endif
407
408 /* Tell CmpLinkHiveToMaster to allocate a hive */
409 Allocate = TRUE;
410 }
411
412 /* Save the boot type */
413 if (SystemHive) CmpBootType = SystemHive->Hive.HiveHeader->BootType;
414
415 /* Are we in self-healing mode? */
416 if (!CmSelfHeal)
417 {
418 /* Disable self-healing internally and check if boot type wanted it */
419 CmpSelfHeal = FALSE;
420 if (CmpBootType & 4)
421 {
422 /* We're disabled, so bugcheck */
423 KEBUGCHECKEX(BAD_SYSTEM_CONFIG_INFO,
424 3,
425 3,
426 (ULONG_PTR)SystemHive,
427 0);
428 }
429 }
430
431 /* Create the default security descriptor */
432 SecurityDescriptor = CmpHiveRootSecurityDescriptor();
433
434 /* Attach it to the system key */
435 RtlInitUnicodeString(&KeyName, REG_SYSTEM_KEY_NAME);
436 Status = CmpLinkHiveToMaster(&KeyName,
437 NULL,
438 (PCMHIVE)SystemHive,
439 Allocate,
440 SecurityDescriptor);
441
442 /* Free the security descriptor */
443 ExFreePool(SecurityDescriptor);
444 if (!NT_SUCCESS(Status)) return FALSE;
445
446 /* Add the hive to the hive list */
447 CmpMachineHiveList[3].CmHive = (PCMHIVE)SystemHive;
448
449 /* Success! */
450 return TRUE;
451 }
452
453 NTSTATUS
454 NTAPI
455 CmpCreateObjectTypes(VOID)
456 {
457 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
458 UNICODE_STRING Name;
459 GENERIC_MAPPING CmpKeyMapping = {KEY_READ,
460 KEY_WRITE,
461 KEY_EXECUTE,
462 KEY_ALL_ACCESS};
463 PAGED_CODE();
464
465 /* Initialize the Key object type */
466 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
467 RtlInitUnicodeString(&Name, L"Key");
468 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
469 ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(CM_KEY_BODY);
470 ObjectTypeInitializer.GenericMapping = CmpKeyMapping;
471 ObjectTypeInitializer.PoolType = PagedPool;
472 ObjectTypeInitializer.ValidAccessMask = KEY_ALL_ACCESS;
473 ObjectTypeInitializer.UseDefaultObject = TRUE;
474 ObjectTypeInitializer.DeleteProcedure = CmpDeleteKeyObject;
475 ObjectTypeInitializer.ParseProcedure = CmpParseKey;
476 ObjectTypeInitializer.SecurityProcedure = CmpSecurityMethod;
477 ObjectTypeInitializer.QueryNameProcedure = CmpQueryKeyName;
478 //ObjectTypeInitializer.CloseProcedure = CmpCloseKeyObject;
479 ObjectTypeInitializer.SecurityRequired = TRUE;
480
481 /* Create it */
482 return ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &CmpKeyObjectType);
483 }
484
485 BOOLEAN
486 NTAPI
487 CmpCreateRootNode(IN PHHIVE Hive,
488 IN PCWSTR Name,
489 OUT PHCELL_INDEX Index)
490 {
491 UNICODE_STRING KeyName;
492 PCM_KEY_NODE KeyCell;
493 LARGE_INTEGER SystemTime;
494 PAGED_CODE();
495
496 /* Initialize the node name and allocate it */
497 RtlInitUnicodeString(&KeyName, Name);
498 *Index = HvAllocateCell(Hive,
499 FIELD_OFFSET(CM_KEY_NODE, Name) +
500 CmpNameSize(Hive, &KeyName),
501 HvStable); // FIXME: , HCELL_NIL);
502 if (*Index == HCELL_NIL) return FALSE;
503
504 /* Set the cell index and get the data */
505 Hive->HiveHeader->RootCell = *Index;
506 KeyCell = (PCM_KEY_NODE)HvGetCell(Hive, *Index);
507 if (!KeyCell) return FALSE;
508
509 /* Setup the cell */
510 KeyCell->Signature = (USHORT)CM_KEY_NODE_SIGNATURE;;
511 KeyCell->Flags = KEY_HIVE_ENTRY | KEY_NO_DELETE;
512 KeQuerySystemTime(&SystemTime);
513 KeyCell->LastWriteTime = SystemTime;
514 KeyCell->Parent = HCELL_NIL;
515 KeyCell->SubKeyCounts[HvStable] = 0;
516 KeyCell->SubKeyCounts[HvVolatile] = 0;
517 KeyCell->SubKeyLists[HvStable] = HCELL_NIL;
518 KeyCell->SubKeyLists[HvVolatile] = HCELL_NIL;
519 KeyCell->ValueList.Count = 0;
520 KeyCell->ValueList.List = HCELL_NIL;
521 KeyCell->Security = HCELL_NIL;
522 KeyCell->Class = HCELL_NIL;
523 KeyCell->ClassLength = 0;
524 KeyCell->MaxNameLen = 0;
525 KeyCell->MaxClassLen = 0;
526 KeyCell->MaxValueNameLen = 0;
527 KeyCell->MaxValueDataLen = 0;
528
529 /* Copy the name (this will also set the length) */
530 KeyCell->NameLength = CmpCopyName(Hive, (PWCHAR)KeyCell->Name, &KeyName);
531
532 /* Check if the name was compressed */
533 if (KeyCell->NameLength < KeyName.Length)
534 {
535 /* Set the flag */
536 KeyCell->Flags |= KEY_COMP_NAME;
537 }
538
539 /* Return success */
540 HvReleaseCell(Hive, *Index);
541 return TRUE;
542 }
543
544 BOOLEAN
545 NTAPI
546 CmpCreateRegistryRoot(VOID)
547 {
548 UNICODE_STRING KeyName;
549 OBJECT_ATTRIBUTES ObjectAttributes;
550 #if 0
551 PCM_KEY_BODY RootKey;
552 #else
553 PKEY_OBJECT RootKey;
554 #endif
555 HCELL_INDEX RootIndex;
556 NTSTATUS Status;
557 PCM_KEY_NODE KeyCell;
558 PSECURITY_DESCRIPTOR SecurityDescriptor;
559 PCM_KEY_CONTROL_BLOCK Kcb;
560 PAGED_CODE();
561
562 /* Setup the root node */
563 if (!CmpCreateRootNode(&CmiVolatileHive->Hive, L"REGISTRY", &RootIndex))
564 {
565 /* We failed */
566 return FALSE;
567 }
568
569 /* Create '\Registry' key. */
570 RtlInitUnicodeString(&KeyName, L"\\Registry");
571 SecurityDescriptor = CmpHiveRootSecurityDescriptor();
572 InitializeObjectAttributes(&ObjectAttributes,
573 &KeyName,
574 OBJ_CASE_INSENSITIVE,
575 NULL,
576 NULL);
577 Status = ObCreateObject(KernelMode,
578 CmpKeyObjectType,
579 &ObjectAttributes,
580 KernelMode,
581 NULL,
582 sizeof(KEY_OBJECT),
583 0,
584 0,
585 (PVOID*)&RootKey);
586 ExFreePool(SecurityDescriptor);
587 if (!NT_SUCCESS(Status)) return FALSE;
588
589 /* Sanity check, and get the key cell */
590 ASSERT((&CmiVolatileHive->Hive)->ReleaseCellRoutine == NULL);
591 KeyCell = (PCM_KEY_NODE)HvGetCell(&CmiVolatileHive->Hive, RootIndex);
592 if (!KeyCell) return FALSE;
593
594 /* Create the KCB */
595 RtlInitUnicodeString(&KeyName, L"Registry");
596 Kcb = CmpCreateKeyControlBlock(&CmiVolatileHive->Hive,
597 RootIndex,
598 KeyCell,
599 NULL,
600 0,
601 &KeyName);
602 if (!Kcb) return FALSE;
603
604 /* Initialize the object */
605 #if 0
606 RootKey->Type = TAG('k', 'v', '0', '2';
607 RootKey->KeyControlBlock = Kcb;
608 RootKey->NotifyBlock = NULL;
609 RootKey->ProcessID = PsGetCurrentProcessId();
610 #else
611 RtlpCreateUnicodeString(&RootKey->Name, L"Registry", NonPagedPool);
612 RootKey->RegistryHive = CmiVolatileHive;
613 RootKey->KeyCellOffset = RootIndex;
614 RootKey->KeyCell = KeyCell;
615 RootKey->ParentKey = RootKey;
616 RootKey->Flags = 0;
617 RootKey->SubKeyCounts = 0;
618 RootKey->SubKeys = NULL;
619 RootKey->SizeOfSubKeys = 0;
620 #endif
621
622 /* Insert it into the object list head */
623 EnlistKeyBodyWithKCB(RootKey, 0);
624
625 /* Insert the key into the namespace */
626 Status = ObInsertObject(RootKey,
627 NULL,
628 KEY_ALL_ACCESS,
629 0,
630 NULL,
631 &CmpRegistryRootHandle);
632 if (!NT_SUCCESS(Status)) return FALSE;
633
634 /* Reference the key again so that we never lose it */
635 Status = ObReferenceObjectByHandle(CmpRegistryRootHandle,
636 KEY_READ,
637 NULL,
638 KernelMode,
639 (PVOID*)&RootKey,
640 NULL);
641 if (!NT_SUCCESS(Status)) return FALSE;
642
643 /* Completely sucessful */
644 return TRUE;
645 }