- Fix a mistake, led to usage of unitialized memory and then freeing it.
[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 KGUARDED_MUTEX CmpSelfHealQueueLock;
17 LIST_ENTRY CmpSelfHealQueueListHead;
18 PEPROCESS CmpSystemProcess;
19 BOOLEAN HvShutdownComplete;
20
21 /* FUNCTIONS *****************************************************************/
22
23 NTSTATUS
24 NTAPI
25 CmpInitHiveFromFile(IN PUNICODE_STRING HiveName,
26 IN ULONG HiveFlags,
27 OUT PCMHIVE *Hive,
28 IN OUT PBOOLEAN New,
29 IN ULONG CheckFlags)
30 {
31 ULONG HiveDisposition, LogDisposition;
32 HANDLE FileHandle = NULL, LogHandle = NULL;
33 NTSTATUS Status;
34 ULONG Operation, FileType;
35 PEREGISTRY_HIVE NewHive;
36 PAGED_CODE();
37
38 /* Assume failure */
39 *Hive = NULL;
40
41 /* Open or create the hive files */
42 Status = CmpOpenHiveFiles(HiveName,
43 L".LOG",
44 &FileHandle,
45 &LogHandle,
46 &HiveDisposition,
47 &LogDisposition,
48 *New,
49 FALSE,
50 TRUE,
51 NULL);
52 if (!NT_SUCCESS(Status)) return Status;
53
54 /* Check if we have a log handle */
55 FileType = (LogHandle) ? HFILE_TYPE_LOG : HFILE_TYPE_PRIMARY;
56
57 /* Check if we created or opened the hive */
58 if (HiveDisposition == FILE_CREATED)
59 {
60 /* Do a create operation */
61 Operation = HINIT_CREATE;
62 *New = TRUE;
63 }
64 else
65 {
66 /* Open it as a file */
67 Operation = HINIT_FILE;
68 *New = FALSE;
69 }
70
71 /* Check if we're sharing hives */
72 if (CmpShareSystemHives)
73 {
74 /* Then force using the primary hive */
75 FileType = HFILE_TYPE_PRIMARY;
76 if (LogHandle)
77 {
78 /* Get rid of the log handle */
79 ZwClose(LogHandle);
80 LogHandle = NULL;
81 }
82 }
83
84 /* Check if we're too late */
85 if (HvShutdownComplete)
86 {
87 /* Fail */
88 ZwClose(FileHandle);
89 if (LogHandle) ZwClose(LogHandle);
90 return STATUS_TOO_LATE;
91 }
92
93 /* Initialize the hive */
94 Status = CmpInitializeHive((PCMHIVE*)&NewHive,
95 Operation,
96 HiveFlags,
97 FileType,
98 NULL,
99 FileHandle,
100 LogHandle,
101 NULL,
102 HiveName,
103 0);
104 if (!NT_SUCCESS(Status))
105 {
106 /* Fail */
107 ZwClose(FileHandle);
108 if (LogHandle) ZwClose(LogHandle);
109 return Status;
110 }
111
112 /* Success, return hive */
113 *Hive = (PCMHIVE)NewHive;
114
115 /* ROS: Init root key cell and prepare the hive */
116 if (Operation == HINIT_CREATE) CmCreateRootNode(&NewHive->Hive, L"");
117 CmPrepareHive(&NewHive->Hive);
118
119 /* Duplicate the hive name */
120 NewHive->HiveFileName.Buffer = ExAllocatePoolWithTag(PagedPool,
121 HiveName->Length,
122 TAG_CM);
123 if (NewHive->HiveFileName.Buffer)
124 {
125 /* Copy the string */
126 RtlCopyMemory(NewHive->HiveFileName.Buffer,
127 HiveName->Buffer,
128 HiveName->Length);
129 NewHive->HiveFileName.Length = HiveName->Length;
130 NewHive->HiveFileName.MaximumLength = HiveName->MaximumLength;
131 }
132
133 /* ROS: Close the hive files */
134 ZwClose(FileHandle);
135 if (LogHandle) ZwClose(LogHandle);
136
137 /* Return success */
138 return STATUS_SUCCESS;
139 }
140
141 NTSTATUS
142 NTAPI
143 CmpSetSystemValues(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
144 {
145 OBJECT_ATTRIBUTES ObjectAttributes;
146 UNICODE_STRING KeyName, ValueName;
147 HANDLE KeyHandle;
148 NTSTATUS Status;
149 ASSERT(LoaderBlock != NULL);
150 if (ExpInTextModeSetup) return STATUS_SUCCESS;
151
152 /* Setup attributes for loader options */
153 RtlInitUnicodeString(&KeyName,
154 L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\"
155 L"Control");
156 InitializeObjectAttributes(&ObjectAttributes,
157 &KeyName,
158 OBJ_CASE_INSENSITIVE,
159 NULL,
160 NULL);
161 Status = NtOpenKey(&KeyHandle, KEY_WRITE, &ObjectAttributes);
162 if (!NT_SUCCESS(Status)) goto Quickie;
163
164 /* Key opened, now write to the key */
165 RtlInitUnicodeString(&KeyName, L"SystemStartOptions");
166 Status = NtSetValueKey(KeyHandle,
167 &KeyName,
168 0,
169 REG_SZ,
170 CmpLoadOptions.Buffer,
171 CmpLoadOptions.Length);
172 if (!NT_SUCCESS(Status)) goto Quickie;
173
174 /* Setup value name for system boot device */
175 RtlInitUnicodeString(&KeyName, L"SystemBootDevice");
176 RtlCreateUnicodeStringFromAsciiz(&ValueName, LoaderBlock->NtBootPathName);
177 Status = NtSetValueKey(KeyHandle,
178 &KeyName,
179 0,
180 REG_SZ,
181 ValueName.Buffer,
182 ValueName.Length);
183
184 Quickie:
185 /* Free the buffers */
186 RtlFreeUnicodeString(&ValueName);
187
188 /* Close the key and return */
189 NtClose(KeyHandle);
190
191 /* Return the status */
192 return Status;
193 }
194
195 NTSTATUS
196 NTAPI
197 CmpCreateControlSet(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
198 {
199 UNICODE_STRING ConfigName = RTL_CONSTANT_STRING(L"Control\\IDConfigDB");
200 UNICODE_STRING SelectName =
201 RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\Select");
202 UNICODE_STRING KeyName;
203 OBJECT_ATTRIBUTES ObjectAttributes;
204 CHAR ValueInfoBuffer[128];
205 PKEY_VALUE_FULL_INFORMATION ValueInfo;
206 CHAR Buffer[128];
207 WCHAR UnicodeBuffer[128];
208 HANDLE SelectHandle, KeyHandle, ConfigHandle = NULL, ProfileHandle = NULL;
209 HANDLE ParentHandle = NULL;
210 ULONG ControlSet, HwProfile;
211 ANSI_STRING TempString;
212 NTSTATUS Status;
213 ULONG ResultLength, Disposition;
214 PLOADER_PARAMETER_EXTENSION LoaderExtension;
215 PAGED_CODE();
216 if (ExpInTextModeSetup) return STATUS_SUCCESS;
217
218 /* Open the select key */
219 InitializeObjectAttributes(&ObjectAttributes,
220 &SelectName,
221 OBJ_CASE_INSENSITIVE,
222 NULL,
223 NULL);
224 Status = NtOpenKey(&SelectHandle, KEY_READ, &ObjectAttributes);
225 if (!NT_SUCCESS(Status)) return(Status);
226
227 /* Open the current value */
228 RtlInitUnicodeString(&KeyName, L"Current");
229 Status = NtQueryValueKey(SelectHandle,
230 &KeyName,
231 KeyValueFullInformation,
232 ValueInfoBuffer,
233 sizeof(ValueInfoBuffer),
234 &ResultLength);
235 NtClose(SelectHandle);
236 if (!NT_SUCCESS(Status)) return Status;
237
238 /* Get the actual value pointer, and get the control set ID */
239 ValueInfo = (PKEY_VALUE_FULL_INFORMATION)ValueInfoBuffer;
240 ControlSet = *(PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset);
241
242 /* Create the current control set key */
243 RtlInitUnicodeString(&KeyName,
244 L"\\Registry\\Machine\\System\\CurrentControlSet");
245 InitializeObjectAttributes(&ObjectAttributes,
246 &KeyName,
247 OBJ_CASE_INSENSITIVE,
248 NULL,
249 NULL);
250
251 Status = NtCreateKey(&KeyHandle,
252 KEY_CREATE_LINK,
253 &ObjectAttributes,
254 0,
255 NULL,
256 REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
257 &Disposition);
258 if (!NT_SUCCESS(Status)) return Status;
259
260 /* Sanity check */
261 ASSERT(Disposition == REG_CREATED_NEW_KEY);
262
263 /* Initialize the symbolic link name */
264 sprintf(Buffer,
265 "\\Registry\\Machine\\System\\ControlSet%03ld",
266 ControlSet);
267 RtlInitAnsiString(&TempString, Buffer);
268
269 /* Create a Unicode string out of it */
270 KeyName.MaximumLength = sizeof(UnicodeBuffer);
271 KeyName.Buffer = UnicodeBuffer;
272 Status = RtlAnsiStringToUnicodeString(&KeyName, &TempString, FALSE);
273
274 /* Set the value */
275 Status = NtSetValueKey(KeyHandle,
276 &CmSymbolicLinkValueName,
277 0,
278 REG_LINK,
279 KeyName.Buffer,
280 KeyName.Length);
281 if (!NT_SUCCESS(Status)) return Status;
282
283 /* Get the configuration database key */
284 InitializeObjectAttributes(&ObjectAttributes,
285 &ConfigName,
286 OBJ_CASE_INSENSITIVE,
287 KeyHandle,
288 NULL);
289 Status = NtOpenKey(&ConfigHandle, KEY_READ, &ObjectAttributes);
290 NtClose(KeyHandle);
291
292 /* Check if we don't have one */
293 if (!NT_SUCCESS(Status))
294 {
295 /* Cleanup and exit */
296 ConfigHandle = 0;
297 goto Cleanup;
298 }
299
300 /* Now get the current config */
301 RtlInitUnicodeString(&KeyName, L"CurrentConfig");
302 Status = NtQueryValueKey(ConfigHandle,
303 &KeyName,
304 KeyValueFullInformation,
305 ValueInfoBuffer,
306 sizeof(ValueInfoBuffer),
307 &ResultLength);
308
309 /* Set pointer to buffer */
310 ValueInfo = (PKEY_VALUE_FULL_INFORMATION)ValueInfoBuffer;
311
312 /* Check if we failed or got a non DWORD-value */
313 if (!(NT_SUCCESS(Status)) || (ValueInfo->Type != REG_DWORD)) goto Cleanup;
314
315 /* Get the hadware profile */
316 HwProfile = *(PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset);
317
318 /* Open the hardware profile key */
319 RtlInitUnicodeString(&KeyName,
320 L"\\Registry\\Machine\\System\\CurrentControlSet"
321 L"\\Hardware Profiles");
322 InitializeObjectAttributes(&ObjectAttributes,
323 &KeyName,
324 OBJ_CASE_INSENSITIVE,
325 NULL,
326 NULL);
327 Status = NtOpenKey(&ParentHandle, KEY_READ, &ObjectAttributes);
328 if (!NT_SUCCESS(Status))
329 {
330 /* Exit and clean up */
331 ParentHandle = 0;
332 goto Cleanup;
333 }
334
335 /* Build the profile name */
336 sprintf(Buffer, "%04ld", HwProfile);
337 RtlInitAnsiString(&TempString, Buffer);
338
339 /* Convert it to Unicode */
340 KeyName.MaximumLength = sizeof(UnicodeBuffer);
341 KeyName.Buffer = UnicodeBuffer;
342 Status = RtlAnsiStringToUnicodeString(&KeyName,
343 &TempString,
344 FALSE);
345 ASSERT(Status == STATUS_SUCCESS);
346
347 /* Open the associated key */
348 InitializeObjectAttributes(&ObjectAttributes,
349 &KeyName,
350 OBJ_CASE_INSENSITIVE,
351 ParentHandle,
352 NULL);
353 Status = NtOpenKey(&ProfileHandle,
354 KEY_READ | KEY_WRITE,
355 &ObjectAttributes);
356 if (!NT_SUCCESS (Status))
357 {
358 /* Cleanup and exit */
359 ProfileHandle = 0;
360 goto Cleanup;
361 }
362
363 /* Check if we have a loader block extension */
364 LoaderExtension = LoaderBlock->Extension;
365 if (LoaderExtension)
366 {
367 ASSERTMSG("ReactOS doesn't support NTLDR Profiles yet!\n", FALSE);
368 }
369
370 /* Create the current hardware profile key */
371 RtlInitUnicodeString(&KeyName,
372 L"\\Registry\\Machine\\System\\CurrentControlSet\\"
373 L"Hardware Profiles\\Current");
374 InitializeObjectAttributes(&ObjectAttributes,
375 &KeyName,
376 OBJ_CASE_INSENSITIVE,
377 NULL,
378 NULL);
379 Status = NtCreateKey(&KeyHandle,
380 KEY_CREATE_LINK,
381 &ObjectAttributes,
382 0,
383 NULL,
384 REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
385 &Disposition);
386 if (NT_SUCCESS(Status))
387 {
388 /* Sanity check */
389 ASSERT(Disposition == REG_CREATED_NEW_KEY);
390
391 /* Create the profile name */
392 sprintf(Buffer,
393 "\\Registry\\Machine\\System\\CurrentControlSet\\"
394 "Hardware Profiles\\%04ld",
395 HwProfile);
396 RtlInitAnsiString(&TempString, Buffer);
397
398 /* Convert it to Unicode */
399 KeyName.MaximumLength = sizeof(UnicodeBuffer);
400 KeyName.Buffer = UnicodeBuffer;
401 Status = RtlAnsiStringToUnicodeString(&KeyName,
402 &TempString,
403 FALSE);
404 ASSERT(STATUS_SUCCESS == Status);
405
406 /* Set it */
407 Status = NtSetValueKey(KeyHandle,
408 &CmSymbolicLinkValueName,
409 0,
410 REG_LINK,
411 KeyName.Buffer,
412 KeyName.Length);
413 NtClose(KeyHandle);
414 }
415
416 /* Close every opened handle */
417 Cleanup:
418 if (ConfigHandle) NtClose(ConfigHandle);
419 if (ProfileHandle) NtClose(ProfileHandle);
420 if (ParentHandle) NtClose(ParentHandle);
421
422 /* Return success */
423 return STATUS_SUCCESS;
424 }
425
426 BOOLEAN
427 NTAPI
428 CmpInitializeSystemHive(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
429 {
430 PVOID HiveBase;
431 ANSI_STRING LoadString;
432 PVOID Buffer;
433 ULONG Length;
434 NTSTATUS Status;
435 BOOLEAN Allocate;
436 UNICODE_STRING KeyName;
437 PEREGISTRY_HIVE SystemHive = NULL;
438 UNICODE_STRING HiveName = RTL_CONSTANT_STRING(L"SYSTEM");
439 PSECURITY_DESCRIPTOR SecurityDescriptor;
440 PAGED_CODE();
441
442 /* Setup the ansi string */
443 RtlInitAnsiString(&LoadString, LoaderBlock->LoadOptions);
444
445 /* Allocate the unicode buffer */
446 Length = LoadString.Length * sizeof(WCHAR) + sizeof(UNICODE_NULL);
447 Buffer = ExAllocatePoolWithTag(PagedPool, Length, TAG_CM);
448 if (!Buffer)
449 {
450 /* Fail */
451 KEBUGCHECKEX(BAD_SYSTEM_CONFIG_INFO, 3, 1, (ULONG_PTR)LoaderBlock, 0);
452 }
453
454 /* Setup the unicode string */
455 RtlInitEmptyUnicodeString(&CmpLoadOptions, Buffer, (USHORT)Length);
456
457 /* Add the load options and null-terminate */
458 RtlAnsiStringToUnicodeString(&CmpLoadOptions, &LoadString, FALSE);
459 CmpLoadOptions.Buffer[LoadString.Length] = UNICODE_NULL;
460 CmpLoadOptions.Length += sizeof(WCHAR);
461
462 /* Get the System Hive base address */
463 HiveBase = LoaderBlock->RegistryBase;
464 if (HiveBase)
465 {
466 /* Import it */
467 ((PHBASE_BLOCK)HiveBase)->Length = LoaderBlock->RegistryLength;
468 Status = CmpInitializeHive((PCMHIVE*)&SystemHive,
469 HINIT_MEMORY,
470 0, //HIVE_NOLAZYFLUSH,
471 HFILE_TYPE_LOG,
472 HiveBase,
473 NULL,
474 NULL,
475 NULL,
476 &HiveName,
477 2);
478 if (!NT_SUCCESS(Status)) return FALSE;
479 CmPrepareHive(&SystemHive->Hive);
480
481 /* Set the hive filename */
482 RtlCreateUnicodeString(&SystemHive->HiveFileName, SYSTEM_REG_FILE);
483
484 /* We imported, no need to create a new hive */
485 Allocate = FALSE;
486
487 /* Manually set the hive as volatile, if in Live CD mode */
488 if (CmpShareSystemHives) SystemHive->Hive.HiveFlags = HIVE_VOLATILE;
489 }
490 else
491 {
492 #if 0
493 /* Create it */
494 Status = CmpInitializeHive((PCMHIVE*)&SystemHive,
495 HINIT_CREATE,
496 HIVE_NOLAZYFLUSH,
497 HFILE_TYPE_LOG,
498 NULL,
499 NULL,
500 NULL,
501 NULL,
502 &HiveName,
503 0);
504 if (!NT_SUCCESS(Status)) return FALSE;
505 #endif
506
507 /* Tell CmpLinkHiveToMaster to allocate a hive */
508 Allocate = TRUE;
509 }
510
511 /* Save the boot type */
512 if (SystemHive) CmpBootType = SystemHive->Hive.HiveHeader->BootType;
513
514 /* Are we in self-healing mode? */
515 if (!CmSelfHeal)
516 {
517 /* Disable self-healing internally and check if boot type wanted it */
518 CmpSelfHeal = FALSE;
519 if (CmpBootType & 4)
520 {
521 /* We're disabled, so bugcheck */
522 KEBUGCHECKEX(BAD_SYSTEM_CONFIG_INFO,
523 3,
524 3,
525 (ULONG_PTR)SystemHive,
526 0);
527 }
528 }
529
530 /* Create the default security descriptor */
531 SecurityDescriptor = CmpHiveRootSecurityDescriptor();
532
533 /* Attach it to the system key */
534 RtlInitUnicodeString(&KeyName, REG_SYSTEM_KEY_NAME);
535 Status = CmpLinkHiveToMaster(&KeyName,
536 NULL,
537 (PCMHIVE)SystemHive,
538 Allocate,
539 SecurityDescriptor);
540
541 /* Free the security descriptor */
542 ExFreePool(SecurityDescriptor);
543 if (!NT_SUCCESS(Status)) return FALSE;
544
545 /* Add the hive to the hive list */
546 CmpMachineHiveList[3].CmHive = (PCMHIVE)SystemHive;
547
548 /* Success! */
549 return TRUE;
550 }
551
552 NTSTATUS
553 NTAPI
554 CmpCreateObjectTypes(VOID)
555 {
556 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
557 UNICODE_STRING Name;
558 GENERIC_MAPPING CmpKeyMapping = {KEY_READ,
559 KEY_WRITE,
560 KEY_EXECUTE,
561 KEY_ALL_ACCESS};
562 PAGED_CODE();
563
564 /* Initialize the Key object type */
565 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
566 RtlInitUnicodeString(&Name, L"Key");
567 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
568 ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(CM_KEY_BODY);
569 ObjectTypeInitializer.GenericMapping = CmpKeyMapping;
570 ObjectTypeInitializer.PoolType = PagedPool;
571 ObjectTypeInitializer.ValidAccessMask = KEY_ALL_ACCESS;
572 ObjectTypeInitializer.UseDefaultObject = TRUE;
573 ObjectTypeInitializer.DeleteProcedure = CmpDeleteKeyObject;
574 ObjectTypeInitializer.ParseProcedure = CmpParseKey;
575 ObjectTypeInitializer.SecurityProcedure = CmpSecurityMethod;
576 ObjectTypeInitializer.QueryNameProcedure = CmpQueryKeyName;
577 //ObjectTypeInitializer.CloseProcedure = CmpCloseKeyObject;
578 ObjectTypeInitializer.SecurityRequired = TRUE;
579
580 /* Create it */
581 return ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &CmpKeyObjectType);
582 }
583
584 BOOLEAN
585 NTAPI
586 CmpCreateRootNode(IN PHHIVE Hive,
587 IN PCWSTR Name,
588 OUT PHCELL_INDEX Index)
589 {
590 UNICODE_STRING KeyName;
591 PCM_KEY_NODE KeyCell;
592 LARGE_INTEGER SystemTime;
593 PAGED_CODE();
594
595 /* Initialize the node name and allocate it */
596 RtlInitUnicodeString(&KeyName, Name);
597 *Index = HvAllocateCell(Hive,
598 FIELD_OFFSET(CM_KEY_NODE, Name) +
599 CmpNameSize(Hive, &KeyName),
600 HvStable); // FIXME: , HCELL_NIL);
601 if (*Index == HCELL_NIL) return FALSE;
602
603 /* Set the cell index and get the data */
604 Hive->HiveHeader->RootCell = *Index;
605 KeyCell = (PCM_KEY_NODE)HvGetCell(Hive, *Index);
606 if (!KeyCell) return FALSE;
607
608 /* Setup the cell */
609 KeyCell->Signature = (USHORT)CM_KEY_NODE_SIGNATURE;;
610 KeyCell->Flags = KEY_HIVE_ENTRY | KEY_NO_DELETE;
611 KeQuerySystemTime(&SystemTime);
612 KeyCell->LastWriteTime = SystemTime;
613 KeyCell->Parent = HCELL_NIL;
614 KeyCell->SubKeyCounts[HvStable] = 0;
615 KeyCell->SubKeyCounts[HvVolatile] = 0;
616 KeyCell->SubKeyLists[HvStable] = HCELL_NIL;
617 KeyCell->SubKeyLists[HvVolatile] = HCELL_NIL;
618 KeyCell->ValueList.Count = 0;
619 KeyCell->ValueList.List = HCELL_NIL;
620 KeyCell->Security = HCELL_NIL;
621 KeyCell->Class = HCELL_NIL;
622 KeyCell->ClassLength = 0;
623 KeyCell->MaxNameLen = 0;
624 KeyCell->MaxClassLen = 0;
625 KeyCell->MaxValueNameLen = 0;
626 KeyCell->MaxValueDataLen = 0;
627
628 /* Copy the name (this will also set the length) */
629 KeyCell->NameLength = CmpCopyName(Hive, (PWCHAR)KeyCell->Name, &KeyName);
630
631 /* Check if the name was compressed */
632 if (KeyCell->NameLength < KeyName.Length)
633 {
634 /* Set the flag */
635 KeyCell->Flags |= KEY_COMP_NAME;
636 }
637
638 /* Return success */
639 HvReleaseCell(Hive, *Index);
640 return TRUE;
641 }
642
643 BOOLEAN
644 NTAPI
645 CmpCreateRegistryRoot(VOID)
646 {
647 UNICODE_STRING KeyName;
648 OBJECT_ATTRIBUTES ObjectAttributes;
649 #if 0
650 PCM_KEY_BODY RootKey;
651 #else
652 PKEY_OBJECT RootKey;
653 #endif
654 HCELL_INDEX RootIndex;
655 NTSTATUS Status;
656 PCM_KEY_NODE KeyCell;
657 PSECURITY_DESCRIPTOR SecurityDescriptor;
658 PCM_KEY_CONTROL_BLOCK Kcb;
659 PAGED_CODE();
660
661 /* Setup the root node */
662 if (!CmpCreateRootNode(&CmiVolatileHive->Hive, L"REGISTRY", &RootIndex))
663 {
664 /* We failed */
665 return FALSE;
666 }
667
668 /* Create '\Registry' key. */
669 RtlInitUnicodeString(&KeyName, L"\\Registry");
670 SecurityDescriptor = CmpHiveRootSecurityDescriptor();
671 InitializeObjectAttributes(&ObjectAttributes,
672 &KeyName,
673 OBJ_CASE_INSENSITIVE,
674 NULL,
675 NULL);
676 Status = ObCreateObject(KernelMode,
677 CmpKeyObjectType,
678 &ObjectAttributes,
679 KernelMode,
680 NULL,
681 sizeof(KEY_OBJECT),
682 0,
683 0,
684 (PVOID*)&RootKey);
685 ExFreePool(SecurityDescriptor);
686 if (!NT_SUCCESS(Status)) return FALSE;
687
688 /* Sanity check, and get the key cell */
689 ASSERT((&CmiVolatileHive->Hive)->ReleaseCellRoutine == NULL);
690 KeyCell = (PCM_KEY_NODE)HvGetCell(&CmiVolatileHive->Hive, RootIndex);
691 if (!KeyCell) return FALSE;
692
693 /* Create the KCB */
694 RtlInitUnicodeString(&KeyName, L"Registry");
695 Kcb = CmpCreateKeyControlBlock(&CmiVolatileHive->Hive,
696 RootIndex,
697 KeyCell,
698 NULL,
699 0,
700 &KeyName);
701 if (!Kcb) return FALSE;
702
703 /* Initialize the object */
704 #if 0
705 RootKey->Type = TAG('k', 'v', '0', '2';
706 RootKey->KeyControlBlock = Kcb;
707 RootKey->NotifyBlock = NULL;
708 RootKey->ProcessID = PsGetCurrentProcessId();
709 #else
710 RtlpCreateUnicodeString(&RootKey->Name, L"Registry", NonPagedPool);
711 RootKey->RegistryHive = CmiVolatileHive;
712 RootKey->KeyCellOffset = RootIndex;
713 RootKey->KeyCell = KeyCell;
714 RootKey->ParentKey = RootKey;
715 RootKey->Flags = 0;
716 RootKey->SubKeyCounts = 0;
717 RootKey->SubKeys = NULL;
718 RootKey->SizeOfSubKeys = 0;
719 #endif
720
721 /* Insert it into the object list head */
722 EnlistKeyBodyWithKCB(RootKey, 0);
723
724 /* Insert the key into the namespace */
725 Status = ObInsertObject(RootKey,
726 NULL,
727 KEY_ALL_ACCESS,
728 0,
729 NULL,
730 &CmpRegistryRootHandle);
731 if (!NT_SUCCESS(Status)) return FALSE;
732
733 /* Reference the key again so that we never lose it */
734 Status = ObReferenceObjectByHandle(CmpRegistryRootHandle,
735 KEY_READ,
736 NULL,
737 KernelMode,
738 (PVOID*)&RootKey,
739 NULL);
740 if (!NT_SUCCESS(Status)) return FALSE;
741
742 /* Completely sucessful */
743 return TRUE;
744 }
745
746 BOOLEAN
747 NTAPI
748 CmInitSystem1(VOID)
749 {
750 OBJECT_ATTRIBUTES ObjectAttributes;
751 UNICODE_STRING KeyName;
752 HANDLE KeyHandle;
753 NTSTATUS Status;
754 LARGE_INTEGER DueTime;
755 HANDLE ThreadHandle;
756 CLIENT_ID ThreadId;
757 PEREGISTRY_HIVE HardwareHive;
758 PVOID BaseAddress;
759 ULONG Length;
760 PSECURITY_DESCRIPTOR SecurityDescriptor;
761 PAGED_CODE();
762
763 /* Check if this is PE-boot */
764 if (InitIsWinPEMode)
765 {
766 /* Set registry to PE mode */
767 CmpMiniNTBoot = TRUE;
768 CmpShareSystemHives = TRUE;
769 }
770
771 /* Initialize the hive list and lock */
772 InitializeListHead(&CmpHiveListHead);
773 ExInitializePushLock((PVOID)&CmpHiveListHeadLock);
774 ExInitializePushLock((PVOID)&CmpLoadHiveLock);
775
776 /* Initialize registry lock */
777 ExInitializeResourceLite(&CmpRegistryLock);
778
779 /* Initialize the cache */
780 CmpInitializeCache();
781
782 /* Initialize allocation and delayed dereferencing */
783 CmpInitCmPrivateAlloc();
784 CmpInitCmPrivateDelayAlloc();
785 CmpInitDelayDerefKCBEngine();
786
787 /* Initialize callbacks */
788 CmpInitCallback();
789
790 /* Initialize self healing */
791 KeInitializeGuardedMutex(&CmpSelfHealQueueLock);
792 InitializeListHead(&CmpSelfHealQueueListHead);
793
794 /* Save the current process and lock the registry */
795 CmpSystemProcess = PsGetCurrentProcess();
796
797 #if 1
798 /* OLD CM: Initialize the key object list */
799 InitializeListHead(&CmiKeyObjectListHead);
800 InitializeListHead(&CmiConnectedHiveList);
801
802 /* OLD CM: Initialize the worker timer */
803 KeInitializeTimerEx(&CmiWorkerTimer, SynchronizationTimer);
804
805 /* OLD CM: Initialize the worker thread */
806 Status = PsCreateSystemThread(&ThreadHandle,
807 THREAD_ALL_ACCESS,
808 NULL,
809 NULL,
810 &ThreadId,
811 CmiWorkerThread,
812 NULL);
813 if (!NT_SUCCESS(Status)) return FALSE;
814
815 /* OLD CM: Start the timer */
816 DueTime.QuadPart = -1;
817 KeSetTimerEx(&CmiWorkerTimer, DueTime, 5000, NULL); /* 5sec */
818 #endif
819
820 /* Create the key object types */
821 Status = CmpCreateObjectTypes();
822 if (!NT_SUCCESS(Status))
823 {
824 /* Bugcheck */
825 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 1, Status, 0);
826 }
827
828 /* Build the master hive */
829 Status = CmpInitializeHive((PCMHIVE*)&CmiVolatileHive,
830 HINIT_CREATE,
831 HIVE_VOLATILE | HIVE_NO_FILE,
832 HFILE_TYPE_PRIMARY,
833 NULL,
834 NULL,
835 NULL,
836 NULL,
837 NULL,
838 0);
839 if (!NT_SUCCESS(Status))
840 {
841 /* Bugcheck */
842 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 2, Status, 0);
843 }
844
845 /* Create the \REGISTRY key node */
846 if (!CmpCreateRegistryRoot())
847 {
848 /* Bugcheck */
849 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 3, 0, 0);
850 }
851
852 /* Create the default security descriptor */
853 SecurityDescriptor = CmpHiveRootSecurityDescriptor();
854
855 /* Create '\Registry\Machine' key. */
856 RtlInitUnicodeString(&KeyName, L"\\REGISTRY\\MACHINE");
857 InitializeObjectAttributes(&ObjectAttributes,
858 &KeyName,
859 OBJ_CASE_INSENSITIVE,
860 NULL,
861 SecurityDescriptor);
862 Status = NtCreateKey(&KeyHandle,
863 KEY_READ | KEY_WRITE,
864 &ObjectAttributes,
865 0,
866 NULL,
867 0,
868 NULL);
869 if (!NT_SUCCESS(Status))
870 {
871 /* Bugcheck */
872 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 5, Status, 0);
873 }
874
875 /* Close the handle */
876 NtClose(KeyHandle);
877
878 /* Create '\Registry\User' key. */
879 RtlInitUnicodeString(&KeyName, L"\\REGISTRY\\USER");
880 InitializeObjectAttributes(&ObjectAttributes,
881 &KeyName,
882 OBJ_CASE_INSENSITIVE,
883 NULL,
884 SecurityDescriptor);
885 Status = NtCreateKey(&KeyHandle,
886 KEY_READ | KEY_WRITE,
887 &ObjectAttributes,
888 0,
889 NULL,
890 0,
891 NULL);
892 if (!NT_SUCCESS(Status))
893 {
894 /* Bugcheck */
895 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 6, Status, 0);
896 }
897
898 /* Close the handle */
899 NtClose(KeyHandle);
900
901 /* Initialize the system hive */
902 if (!CmpInitializeSystemHive(KeLoaderBlock))
903 {
904 /* Bugcheck */
905 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 7, 0, 0);
906 }
907
908 /* Create the 'CurrentControlSet' link. */
909 Status = CmpCreateControlSet(KeLoaderBlock);
910 if (!NT_SUCCESS(Status))
911 {
912 /* Bugcheck */
913 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 8, Status, 0);
914 }
915
916 /* Import the hardware hive (FIXME: We should create it from scratch) */
917 BaseAddress = CmpRosGetHardwareHive(&Length);
918 ((PHBASE_BLOCK)BaseAddress)->Length = Length;
919 Status = CmpInitializeHive((PCMHIVE*)&HardwareHive,
920 HINIT_MEMORY, //HINIT_CREATE,
921 HIVE_NO_FILE, //HIVE_VOLATILE,
922 HFILE_TYPE_PRIMARY,
923 BaseAddress, // NULL,
924 NULL,
925 NULL,
926 NULL,
927 NULL,
928 0);
929 CmPrepareHive(&HardwareHive->Hive);
930 if (!NT_SUCCESS(Status))
931 {
932 /* Bugcheck */
933 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 11, Status, 0);
934 }
935
936 /* Attach it to the machine key */
937 RtlInitUnicodeString(&KeyName, REG_HARDWARE_KEY_NAME);
938 Status = CmpLinkHiveToMaster(&KeyName,
939 NULL,
940 (PCMHIVE)HardwareHive,
941 FALSE,
942 SecurityDescriptor);
943 if (!NT_SUCCESS(Status))
944 {
945 /* Bugcheck */
946 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 12, Status, 0);
947 }
948
949 /* Fill out the Hardware key with the ARC Data from the Loader */
950 Status = CmpInitializeHardwareConfiguration(KeLoaderBlock);
951 if (!NT_SUCCESS(Status))
952 {
953 /* Bugcheck */
954 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 13, Status, 0);
955 }
956
957 /* Initialize machine-dependent information into the registry */
958 Status = CmpInitializeMachineDependentConfiguration(KeLoaderBlock);
959 if (!NT_SUCCESS(Status))
960 {
961 /* Bugcheck */
962 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 14, Status, 0);
963 }
964
965 /* Initialize volatile registry settings */
966 Status = CmpSetSystemValues(KeLoaderBlock);
967 if (!NT_SUCCESS(Status))
968 {
969 /* Bugcheck */
970 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 15, Status, 0);
971 }
972
973 /* Free the load options */
974 ExFreePool(CmpLoadOptions.Buffer);
975
976 /* If we got here, all went well */
977 return TRUE;
978 }