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