3 * PROJECT: ReactOS Kernel
4 * COPYRIGHT: GPL - See COPYING in the top level directory
5 * FILE: ntoskrnl/cm/registry.c
6 * PURPOSE: Registry functions
8 * PROGRAMMERS: Hartmut Birr
19 #include <internal/debug.h>
23 #if defined (ALLOC_PRAGMA)
24 #pragma alloc_text(INIT, CmInitSystem1)
27 /* GLOBALS ******************************************************************/
29 extern BOOLEAN ExpInTextModeSetup
;
31 POBJECT_TYPE CmiKeyType
= NULL
;
32 PEREGISTRY_HIVE CmiVolatileHive
= NULL
;
34 LIST_ENTRY CmiHiveListHead
;
36 ERESOURCE CmiRegistryLock
;
38 KTIMER CmiWorkerTimer
;
39 LIST_ENTRY CmiKeyObjectListHead
;
40 LIST_ENTRY CmiConnectedHiveList
;
43 volatile BOOLEAN CmiHiveSyncEnabled
= FALSE
;
44 volatile BOOLEAN CmiHiveSyncPending
= FALSE
;
46 KTIMER CmiHiveSyncTimer
;
48 static GENERIC_MAPPING CmiKeyMapping
=
49 {KEY_READ
, KEY_WRITE
, KEY_EXECUTE
, KEY_ALL_ACCESS
};
54 CmiCheckKey(BOOLEAN Verbose
,
58 CmiCreateCurrentControlSetLink(VOID
);
61 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
62 PVOID DeferredContext
,
63 PVOID SystemArgument1
,
64 PVOID SystemArgument2
);
66 extern LIST_ENTRY CmiCallbackHead
;
67 extern FAST_MUTEX CmiCallbackLock
;
69 /* FUNCTIONS ****************************************************************/
72 CmiWorkerThread(PVOID Param
)
75 PLIST_ENTRY CurrentEntry
;
76 PKEY_OBJECT CurrentKey
;
82 Status
= KeWaitForSingleObject(&CmiWorkerTimer
,
87 if (Status
== STATUS_SUCCESS
)
89 DPRINT("CmiWorkerThread\n");
91 /* Acquire hive lock */
92 KeEnterCriticalRegion();
93 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
98 CurrentEntry
= CmiKeyObjectListHead
.Blink
;
99 while (CurrentEntry
!= &CmiKeyObjectListHead
)
101 CurrentKey
= CONTAINING_RECORD(CurrentEntry
, KEY_OBJECT
, ListEntry
);
102 if (CurrentKey
->TimeStamp
+ 120 > CmiTimer
)
104 /* The object was accessed in the last 10min */
107 if (1 == ObGetObjectPointerCount(CurrentKey
) &&
108 !(CurrentKey
->Flags
& KO_MARKED_FOR_DELETE
))
110 ObDereferenceObject(CurrentKey
);
111 CurrentEntry
= CmiKeyObjectListHead
.Blink
;
116 CurrentEntry
= CurrentEntry
->Blink
;
119 ExReleaseResourceLite(&CmiRegistryLock
);
120 KeLeaveCriticalRegion();
122 DPRINT("Removed %d key objects\n", Count
);
133 CmInit2(PCHAR CommandLine
)
136 BOOLEAN MiniNT
= FALSE
;
138 UNICODE_STRING TempString
;
140 /* Create the 'CurrentControlSet' link. */
141 Status
= CmiCreateCurrentControlSetLink();
142 if (!NT_SUCCESS(Status
))
143 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
146 * Write the system boot device to registry.
148 RtlCreateUnicodeStringFromAsciiz(&TempString
, KeLoaderBlock
->ArcBootDeviceName
);
149 Status
= RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
150 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control",
154 TempString
.MaximumLength
);
155 RtlFreeUnicodeString(&TempString
);
156 if (!NT_SUCCESS(Status
))
158 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
162 * Parse the system start options.
164 if (strstr(KeLoaderBlock
->LoadOptions
, "DEBUGPORT=PICE") != NULL
)
166 MiniNT
= strstr(KeLoaderBlock
->LoadOptions
, "MININT") != NULL
;
169 * Write the system start options to registry.
171 RtlCreateUnicodeStringFromAsciiz(&TempString
, KeLoaderBlock
->LoadOptions
);
172 Status
= RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
173 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control",
174 L
"SystemStartOptions",
177 TempString
.MaximumLength
);
178 RtlFreeUnicodeString(&TempString
);
179 if (!NT_SUCCESS(Status
))
181 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
185 * Create a CurrentControlSet\Control\MiniNT key that is used
186 * to detect WinPE/MiniNT systems.
190 Status
= RtlCreateRegistryKey(RTL_REGISTRY_CONTROL
, L
"MiniNT");
191 if (!NT_SUCCESS(Status
))
192 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
195 /* Set PICE 'Start' value to 1, if PICE debugging is enabled */
196 Status
= RtlWriteRegistryValue(
197 RTL_REGISTRY_SERVICES
,
203 if (!NT_SUCCESS(Status
))
204 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
211 CmInitHives(BOOLEAN SetupBoot
)
214 PLIST_ENTRY ListHead
, NextEntry
;
215 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
= NULL
;
217 /* Load Registry Hives. This one can be missing. */
218 BaseAddress
= KeLoaderBlock
->RegistryBase
;
221 CmImportSystemHive(BaseAddress
,
222 KeLoaderBlock
->RegistryLength
);
225 /* Loop the memory descriptors */
226 ListHead
= &KeLoaderBlock
->MemoryDescriptorListHead
;
227 NextEntry
= ListHead
->Flink
;
228 while (NextEntry
!= ListHead
)
230 /* Get the current block */
231 MdBlock
= CONTAINING_RECORD(NextEntry
,
232 MEMORY_ALLOCATION_DESCRIPTOR
,
235 /* Check if this is an registry block */
236 if (MdBlock
->MemoryType
== LoaderRegistryData
)
238 /* Check if it's not the SYSTEM hive that we already initialized */
239 if ((MdBlock
->BasePage
) != ((ULONG_PTR
)BaseAddress
>> PAGE_SHIFT
))
241 /* Hardware hive break out */
246 /* Go to the next block */
247 NextEntry
= MdBlock
->ListEntry
.Flink
;
250 /* We need a hardware hive */
253 BaseAddress
= (PCHAR
)(MdBlock
->BasePage
<< PAGE_SHIFT
);
254 CmImportHardwareHive(BaseAddress
,
255 MdBlock
->PageCount
<< PAGE_SHIFT
);
257 /* Create dummy keys if no hardware hive was found */
258 CmImportHardwareHive (NULL
, 0);
260 /* Initialize volatile registry settings */
261 if (SetupBoot
== FALSE
) CmInit2(KeLoaderBlock
->LoadOptions
);
269 OBJECT_ATTRIBUTES ObjectAttributes
;
270 UNICODE_STRING KeyName
;
273 PCM_KEY_SECURITY RootSecurityCell
;
275 HANDLE RootKeyHandle
;
278 LARGE_INTEGER DueTime
;
281 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
284 DPRINT("Creating Registry Object Type\n");
286 /* Initialize the Key object type */
287 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
288 RtlInitUnicodeString(&Name
, L
"Key");
289 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
290 ObjectTypeInitializer
.DefaultPagedPoolCharge
= sizeof(KEY_OBJECT
);
291 ObjectTypeInitializer
.GenericMapping
= CmiKeyMapping
;
292 ObjectTypeInitializer
.PoolType
= PagedPool
;
293 ObjectTypeInitializer
.ValidAccessMask
= KEY_ALL_ACCESS
;
294 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
295 ObjectTypeInitializer
.DeleteProcedure
= CmiObjectDelete
;
296 ObjectTypeInitializer
.ParseProcedure
= CmiObjectParse
;
297 ObjectTypeInitializer
.SecurityProcedure
= CmiObjectSecurity
;
298 ObjectTypeInitializer
.QueryNameProcedure
= CmiObjectQueryName
;
300 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &CmiKeyType
);
302 /* Initialize the hive list */
303 InitializeListHead(&CmiHiveListHead
);
305 /* Initialize registry lock */
306 ExInitializeResourceLite(&CmiRegistryLock
);
308 /* Initialize the key object list */
309 InitializeListHead(&CmiKeyObjectListHead
);
310 InitializeListHead(&CmiConnectedHiveList
);
312 /* Initialize the worker timer */
313 KeInitializeTimerEx(&CmiWorkerTimer
, SynchronizationTimer
);
315 /* Initialize the worker thread */
316 Status
= PsCreateSystemThread(&ThreadHandle
,
323 if (!NT_SUCCESS(Status
)) return FALSE
;
325 /* Start the timer */
326 DueTime
.QuadPart
= -1;
327 KeSetTimerEx(&CmiWorkerTimer
, DueTime
, 5000, NULL
); /* 5sec */
329 /* Build volatile registry store */
330 Status
= CmiCreateVolatileHive (&CmiVolatileHive
);
331 ASSERT(NT_SUCCESS(Status
));
333 InitializeListHead(&CmiCallbackHead
);
334 ExInitializeFastMutex(&CmiCallbackLock
);
336 /* Create '\Registry' key. */
337 RtlInitUnicodeString(&KeyName
, REG_ROOT_KEY_NAME
);
338 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, 0, NULL
, NULL
);
339 Status
= ObCreateObject(KernelMode
,
348 ASSERT(NT_SUCCESS(Status
));
349 Status
= ObInsertObject(RootKey
,
355 ASSERT(NT_SUCCESS(Status
));
356 RootKey
->RegistryHive
= CmiVolatileHive
;
357 RootKey
->KeyCellOffset
= CmiVolatileHive
->Hive
.HiveHeader
->RootCell
;
358 RootKey
->KeyCell
= HvGetCell (&CmiVolatileHive
->Hive
, RootKey
->KeyCellOffset
);
359 RootKey
->ParentKey
= RootKey
;
361 RootKey
->SubKeyCounts
= 0;
362 RootKey
->SubKeys
= NULL
;
363 RootKey
->SizeOfSubKeys
= 0;
364 InsertTailList(&CmiKeyObjectListHead
, &RootKey
->ListEntry
);
365 Status
= RtlpCreateUnicodeString(&RootKey
->Name
, L
"Registry", NonPagedPool
);
366 ASSERT(NT_SUCCESS(Status
));
369 Status
= CmiAllocateCell(CmiVolatileHive
,
370 0x10, //LONG CellSize,
371 (PVOID
*)&RootSecurityCell
,
372 &RootKey
->KeyCell
->SecurityKeyOffset
);
373 ASSERT(NT_SUCCESS(Status
));
375 /* Copy the security descriptor */
377 CmiVolatileHive
->RootSecurityCell
= RootSecurityCell
;
381 /* Create '\Registry\Machine' key. */
382 RtlInitUnicodeString(&KeyName
,
384 InitializeObjectAttributes(&ObjectAttributes
,
389 Status
= ZwCreateKey(&KeyHandle
,
396 ASSERT(NT_SUCCESS(Status
));
398 /* Create '\Registry\User' key. */
399 RtlInitUnicodeString(&KeyName
,
401 InitializeObjectAttributes(&ObjectAttributes
,
406 Status
= ZwCreateKey(&KeyHandle
,
413 ASSERT(NT_SUCCESS(Status
));
415 /* Import and Load Registry Hives */
416 CmInitHives(ExpInTextModeSetup
);
423 CmiCreateCurrentControlSetLink(VOID
)
425 RTL_QUERY_REGISTRY_TABLE QueryTable
[5];
426 WCHAR TargetNameBuffer
[80];
427 ULONG TargetNameLength
;
428 UNICODE_STRING LinkName
= RTL_CONSTANT_STRING(
429 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
430 UNICODE_STRING LinkValue
= RTL_CONSTANT_STRING(L
"SymbolicLinkValue");
436 OBJECT_ATTRIBUTES ObjectAttributes
;
439 DPRINT("CmiCreateCurrentControlSetLink() called\n");
441 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
443 QueryTable
[0].Name
= L
"Current";
444 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
445 QueryTable
[0].EntryContext
= &CurrentSet
;
447 QueryTable
[1].Name
= L
"Default";
448 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
449 QueryTable
[1].EntryContext
= &DefaultSet
;
451 QueryTable
[2].Name
= L
"Failed";
452 QueryTable
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
453 QueryTable
[2].EntryContext
= &Failed
;
455 QueryTable
[3].Name
= L
"LastKnownGood";
456 QueryTable
[3].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
457 QueryTable
[3].EntryContext
= &LastKnownGood
;
459 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
460 L
"\\Registry\\Machine\\SYSTEM\\Select",
464 if (!NT_SUCCESS(Status
))
469 DPRINT("Current %ld Default %ld\n", CurrentSet
, DefaultSet
);
471 swprintf(TargetNameBuffer
,
472 L
"\\Registry\\Machine\\SYSTEM\\ControlSet%03lu",
474 TargetNameLength
= wcslen(TargetNameBuffer
) * sizeof(WCHAR
);
476 DPRINT("Link target '%S'\n", TargetNameBuffer
);
478 InitializeObjectAttributes(&ObjectAttributes
,
480 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
483 Status
= ZwCreateKey(&KeyHandle
,
484 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
488 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
490 if (!NT_SUCCESS(Status
))
492 DPRINT1("ZwCreateKey() failed (Status %lx)\n", Status
);
496 Status
= ZwSetValueKey(KeyHandle
,
500 (PVOID
)TargetNameBuffer
,
502 if (!NT_SUCCESS(Status
))
504 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
513 CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
514 IN PEREGISTRY_HIVE RegistryHive
)
516 UNICODE_STRING RemainingPath
;
517 PKEY_OBJECT ParentKey
;
521 UNICODE_STRING ObjectName
;
522 OBJECT_CREATE_INFORMATION ObjectCreateInfo
;
524 DPRINT("CmiConnectHive(%p, %p) called.\n",
525 KeyObjectAttributes
, RegistryHive
);
527 /* Capture all the info */
528 DPRINT("Capturing Create Info\n");
529 Status
= ObpCaptureObjectAttributes(KeyObjectAttributes
,
535 if (!NT_SUCCESS(Status
))
537 DPRINT("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status
);
541 Status
= CmFindObject(&ObjectCreateInfo
,
548 /* Yields a new reference */
549 ObpReleaseCapturedAttributes(&ObjectCreateInfo
);
551 if (ObjectName
.Buffer
) ObpReleaseCapturedName(&ObjectName
);
552 if (!NT_SUCCESS(Status
))
557 DPRINT ("RemainingPath %wZ\n", &RemainingPath
);
559 if ((RemainingPath
.Buffer
== NULL
) || (RemainingPath
.Buffer
[0] == 0))
561 ObDereferenceObject (ParentKey
);
562 RtlFreeUnicodeString(&RemainingPath
);
563 return STATUS_OBJECT_NAME_COLLISION
;
566 /* Ignore leading backslash */
567 SubName
= RemainingPath
.Buffer
;
568 if (*SubName
== L
'\\')
571 /* If RemainingPath contains \ we must return error
572 because CmiConnectHive() can not create trees */
573 if (wcschr (SubName
, L
'\\') != NULL
)
575 ObDereferenceObject (ParentKey
);
576 RtlFreeUnicodeString(&RemainingPath
);
577 return STATUS_OBJECT_NAME_NOT_FOUND
;
580 DPRINT("RemainingPath %wZ ParentKey %p\n",
581 &RemainingPath
, ParentKey
);
583 Status
= ObCreateObject(KernelMode
,
593 if (!NT_SUCCESS(Status
))
595 DPRINT1 ("ObCreateObject() failed (Status %lx)\n", Status
);
596 ObDereferenceObject (ParentKey
);
597 RtlFreeUnicodeString(&RemainingPath
);
600 DPRINT("Inserting Key into Object Tree\n");
601 Status
= ObInsertObject((PVOID
)NewKey
,
607 DPRINT("Status %x\n", Status
);
609 NewKey
->SubKeyCounts
= 0;
610 NewKey
->SubKeys
= NULL
;
611 NewKey
->SizeOfSubKeys
= 0;
612 InsertTailList(&CmiKeyObjectListHead
, &NewKey
->ListEntry
);
614 DPRINT ("SubName %S\n", SubName
);
616 Status
= CmiAddSubKey(ParentKey
->RegistryHive
,
622 REG_OPTION_VOLATILE
);
623 if (!NT_SUCCESS(Status
))
625 DPRINT1("CmiAddSubKey() failed (Status %lx)\n", Status
);
626 ObDereferenceObject (NewKey
);
627 ObDereferenceObject (ParentKey
);
628 return STATUS_INSUFFICIENT_RESOURCES
;
631 NewKey
->KeyCellOffset
= RegistryHive
->Hive
.HiveHeader
->RootCell
;
632 NewKey
->KeyCell
= HvGetCell (&RegistryHive
->Hive
, NewKey
->KeyCellOffset
);
633 NewKey
->RegistryHive
= RegistryHive
;
635 Status
= RtlpCreateUnicodeString(&NewKey
->Name
,
636 SubName
, NonPagedPool
);
637 RtlFreeUnicodeString(&RemainingPath
);
638 if (!NT_SUCCESS(Status
))
640 DPRINT1("RtlpCreateUnicodeString() failed (Status %lx)\n", Status
);
641 ObDereferenceObject (NewKey
);
642 ObDereferenceObject (ParentKey
);
643 return STATUS_INSUFFICIENT_RESOURCES
;
647 ObReferenceObject (NewKey
);
649 CmiAddKeyToList (ParentKey
, NewKey
);
650 ObDereferenceObject (ParentKey
);
652 VERIFY_KEY_OBJECT(NewKey
);
654 /* We're holding a pointer to the parent key .. We must keep it
656 /* Note: Do not dereference NewKey here! */
658 return STATUS_SUCCESS
;
663 CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
664 OUT PEREGISTRY_HIVE
*RegistryHive
)
666 PKEY_OBJECT KeyObject
;
667 PEREGISTRY_HIVE Hive
;
669 NTSTATUS Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
670 PLIST_ENTRY CurrentEntry
;
671 PKEY_OBJECT CurrentKey
;
673 DPRINT("CmiDisconnectHive() called\n");
675 *RegistryHive
= NULL
;
677 Status
= ObOpenObjectByName (KeyObjectAttributes
,
681 STANDARD_RIGHTS_REQUIRED
,
684 if (!NT_SUCCESS(Status
))
686 DPRINT1 ("ObOpenObjectByName() failed (Status %lx)\n", Status
);
690 Status
= ObReferenceObjectByHandle (KeyHandle
,
691 STANDARD_RIGHTS_REQUIRED
,
698 if (!NT_SUCCESS(Status
))
700 DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status
);
703 DPRINT ("KeyObject %p Hive %p\n", KeyObject
, KeyObject
->RegistryHive
);
705 /* Acquire registry lock exclusively */
706 KeEnterCriticalRegion();
707 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
709 Hive
= KeyObject
->RegistryHive
;
711 CurrentEntry
= CmiKeyObjectListHead
.Flink
;
712 while (CurrentEntry
!= &CmiKeyObjectListHead
)
714 CurrentKey
= CONTAINING_RECORD(CurrentEntry
, KEY_OBJECT
, ListEntry
);
715 if (CurrentKey
->RegistryHive
== Hive
&&
716 1 == ObGetObjectPointerCount(CurrentKey
) &&
717 !(CurrentKey
->Flags
& KO_MARKED_FOR_DELETE
))
719 ObDereferenceObject(CurrentKey
);
720 CurrentEntry
= CmiKeyObjectListHead
.Flink
;
724 CurrentEntry
= CurrentEntry
->Flink
;
729 ObDereferenceObject (KeyObject
);
731 if (ObGetObjectHandleCount (KeyObject
) != 0 ||
732 ObGetObjectPointerCount (KeyObject
) != 2)
734 DPRINT1 ("Hive is still in use (hc %d, rc %d)\n", ObGetObjectHandleCount (KeyObject
), ObGetObjectPointerCount (KeyObject
));
735 ObDereferenceObject (KeyObject
);
737 /* Release registry lock */
738 ExReleaseResourceLite (&CmiRegistryLock
);
739 KeLeaveCriticalRegion();
741 return STATUS_UNSUCCESSFUL
;
744 /* Dereference KeyObject twice to delete it */
745 ObDereferenceObject (KeyObject
);
746 ObDereferenceObject (KeyObject
);
748 *RegistryHive
= Hive
;
750 /* Release registry lock */
751 ExReleaseResourceLite (&CmiRegistryLock
);
752 KeLeaveCriticalRegion();
754 /* Release reference above */
755 ObDereferenceObject (KeyObject
);
757 DPRINT ("CmiDisconnectHive() done\n");
764 CmiInitControlSetLink (VOID
)
766 OBJECT_ATTRIBUTES ObjectAttributes
;
767 UNICODE_STRING ControlSetKeyName
= RTL_CONSTANT_STRING(
768 L
"\\Registry\\Machine\\SYSTEM\\ControlSet001");
769 UNICODE_STRING ControlSetLinkName
= RTL_CONSTANT_STRING(
770 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
771 UNICODE_STRING ControlSetValueName
= RTL_CONSTANT_STRING(L
"SymbolicLinkValue");
775 /* Create 'ControlSet001' key */
776 InitializeObjectAttributes (&ObjectAttributes
,
778 OBJ_CASE_INSENSITIVE
,
781 Status
= ZwCreateKey (&KeyHandle
,
786 REG_OPTION_NON_VOLATILE
,
788 if (!NT_SUCCESS(Status
))
790 DPRINT1 ("ZwCreateKey() failed (Status %lx)\n", Status
);
795 /* Link 'CurrentControlSet' to 'ControlSet001' key */
796 InitializeObjectAttributes (&ObjectAttributes
,
798 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
801 Status
= ZwCreateKey (&KeyHandle
,
802 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
806 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
808 if (!NT_SUCCESS(Status
))
810 DPRINT1 ("ZwCreateKey() failed (Status %lx)\n", Status
);
814 Status
= ZwSetValueKey (KeyHandle
,
815 &ControlSetValueName
,
818 (PVOID
)ControlSetKeyName
.Buffer
,
819 ControlSetKeyName
.Length
);
820 if (!NT_SUCCESS(Status
))
822 DPRINT1 ("ZwSetValueKey() failed (Status %lx)\n", Status
);
826 return STATUS_SUCCESS
;
831 CmiInitHives(BOOLEAN SetupBoot
)
833 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
834 OBJECT_ATTRIBUTES ObjectAttributes
;
835 UNICODE_STRING FileName
;
836 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE");
837 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"InstallPath");
842 WCHAR ConfigPath
[MAX_PATH
];
849 DPRINT("CmiInitHives() called\n");
851 if (SetupBoot
== TRUE
)
853 InitializeObjectAttributes(&ObjectAttributes
,
855 OBJ_CASE_INSENSITIVE
,
858 Status
= ZwOpenKey(&KeyHandle
,
861 if (!NT_SUCCESS(Status
))
863 DPRINT1("ZwOpenKey() failed (Status %lx)\n", Status
);
867 BufferSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 4096;
868 ValueInfo
= ExAllocatePool(PagedPool
,
870 if (ValueInfo
== NULL
)
873 return(STATUS_INSUFFICIENT_RESOURCES
);
876 Status
= ZwQueryValueKey(KeyHandle
,
878 KeyValuePartialInformation
,
883 if (!NT_SUCCESS(Status
))
885 ExFreePool(ValueInfo
);
889 RtlCopyMemory(ConfigPath
,
891 ValueInfo
->DataLength
);
892 ConfigPath
[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = (WCHAR
)0;
893 ExFreePool(ValueInfo
);
897 wcscpy(ConfigPath
, L
"\\SystemRoot");
899 wcscat(ConfigPath
, L
"\\system32\\config");
901 DPRINT("ConfigPath: %S\n", ConfigPath
);
903 EndPtr
= ConfigPath
+ wcslen(ConfigPath
);
905 /* FIXME: Save boot log */
907 /* Connect the SYSTEM hive only if it has been created */
908 if (SetupBoot
== TRUE
)
910 wcscpy(EndPtr
, REG_SYSTEM_FILE_NAME
);
911 DPRINT ("ConfigPath: %S\n", ConfigPath
);
913 RtlInitUnicodeString (&KeyName
,
914 REG_SYSTEM_KEY_NAME
);
915 InitializeObjectAttributes(&ObjectAttributes
,
917 OBJ_CASE_INSENSITIVE
,
921 RtlInitUnicodeString (&FileName
,
923 Status
= CmiLoadHive (&ObjectAttributes
,
926 if (!NT_SUCCESS(Status
))
928 DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status
);
932 Status
= CmiInitControlSetLink ();
933 if (!NT_SUCCESS(Status
))
935 DPRINT1("CmiInitControlSetLink() failed (Status %lx)\n", Status
);
940 /* Connect the SOFTWARE hive */
941 wcscpy(EndPtr
, REG_SOFTWARE_FILE_NAME
);
942 RtlInitUnicodeString (&FileName
,
944 DPRINT ("ConfigPath: %S\n", ConfigPath
);
946 RtlInitUnicodeString (&KeyName
,
947 REG_SOFTWARE_KEY_NAME
);
948 InitializeObjectAttributes(&ObjectAttributes
,
950 OBJ_CASE_INSENSITIVE
,
954 Status
= CmiLoadHive (&ObjectAttributes
,
957 if (!NT_SUCCESS(Status
))
959 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
963 /* Connect the SAM hive */
964 wcscpy(EndPtr
, REG_SAM_FILE_NAME
);
965 RtlInitUnicodeString (&FileName
,
967 DPRINT ("ConfigPath: %S\n", ConfigPath
);
969 RtlInitUnicodeString (&KeyName
,
971 InitializeObjectAttributes(&ObjectAttributes
,
973 OBJ_CASE_INSENSITIVE
,
976 Status
= CmiLoadHive (&ObjectAttributes
,
979 if (!NT_SUCCESS(Status
))
981 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
985 /* Connect the SECURITY hive */
986 wcscpy(EndPtr
, REG_SEC_FILE_NAME
);
987 RtlInitUnicodeString (&FileName
,
989 DPRINT ("ConfigPath: %S\n", ConfigPath
);
991 RtlInitUnicodeString (&KeyName
,
993 InitializeObjectAttributes(&ObjectAttributes
,
995 OBJ_CASE_INSENSITIVE
,
998 Status
= CmiLoadHive (&ObjectAttributes
,
1001 if (!NT_SUCCESS(Status
))
1003 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
1007 /* Connect the DEFAULT hive */
1008 wcscpy(EndPtr
, REG_DEFAULT_USER_FILE_NAME
);
1009 RtlInitUnicodeString (&FileName
,
1011 DPRINT ("ConfigPath: %S\n", ConfigPath
);
1013 RtlInitUnicodeString (&KeyName
,
1014 REG_DEFAULT_USER_KEY_NAME
);
1015 InitializeObjectAttributes(&ObjectAttributes
,
1017 OBJ_CASE_INSENSITIVE
,
1020 Status
= CmiLoadHive (&ObjectAttributes
,
1023 if (!NT_SUCCESS(Status
))
1025 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
1029 // CmiCheckRegistry(TRUE);
1031 /* Start automatic hive synchronization */
1032 KeInitializeDpc(&CmiHiveSyncDpc
,
1033 CmiHiveSyncDpcRoutine
,
1035 KeInitializeTimer(&CmiHiveSyncTimer
);
1036 CmiHiveSyncEnabled
= TRUE
;
1038 DPRINT("CmiInitHives() done\n");
1040 return(STATUS_SUCCESS
);
1045 CmShutdownRegistry(VOID
)
1047 PEREGISTRY_HIVE Hive
;
1050 DPRINT("CmShutdownRegistry() called\n");
1052 /* Stop automatic hive synchronization */
1053 CmiHiveSyncEnabled
= FALSE
;
1055 /* Cancel pending hive synchronization */
1056 if (CmiHiveSyncPending
== TRUE
)
1058 KeCancelTimer(&CmiHiveSyncTimer
);
1059 CmiHiveSyncPending
= FALSE
;
1062 /* Acquire hive list lock exclusively */
1063 KeEnterCriticalRegion();
1064 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
1066 Entry
= CmiHiveListHead
.Flink
;
1067 while (Entry
!= &CmiHiveListHead
)
1069 Hive
= CONTAINING_RECORD(Entry
, EREGISTRY_HIVE
, HiveList
);
1071 if (!(IsNoFileHive(Hive
) || IsNoSynchHive(Hive
)))
1073 /* Flush non-volatile hive */
1074 CmiFlushRegistryHive(Hive
);
1077 Entry
= Entry
->Flink
;
1080 /* Release hive list lock */
1081 ExReleaseResourceLite(&CmiRegistryLock
);
1082 KeLeaveCriticalRegion();
1084 DPRINT("CmShutdownRegistry() done\n");
1089 CmiHiveSyncRoutine(PVOID DeferredContext
)
1091 PEREGISTRY_HIVE Hive
;
1094 DPRINT("CmiHiveSyncRoutine() called\n");
1096 CmiHiveSyncPending
= FALSE
;
1098 /* Acquire hive list lock exclusively */
1099 KeEnterCriticalRegion();
1100 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
1102 Entry
= CmiHiveListHead
.Flink
;
1103 while (Entry
!= &CmiHiveListHead
)
1105 Hive
= CONTAINING_RECORD(Entry
, EREGISTRY_HIVE
, HiveList
);
1107 if (!(IsNoFileHive(Hive
) || IsNoSynchHive(Hive
)))
1109 /* Flush non-volatile hive */
1110 CmiFlushRegistryHive(Hive
);
1113 Entry
= Entry
->Flink
;
1116 /* Release hive list lock */
1117 ExReleaseResourceLite(&CmiRegistryLock
);
1118 KeLeaveCriticalRegion();
1120 DPRINT("DeferredContext 0x%p\n", DeferredContext
);
1121 ExFreePool(DeferredContext
);
1123 DPRINT("CmiHiveSyncRoutine() done\n");
1128 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
1129 PVOID DeferredContext
,
1130 PVOID SystemArgument1
,
1131 PVOID SystemArgument2
)
1133 PWORK_QUEUE_ITEM WorkQueueItem
;
1135 WorkQueueItem
= ExAllocatePool(NonPagedPool
,
1136 sizeof(WORK_QUEUE_ITEM
));
1137 if (WorkQueueItem
== NULL
)
1139 DbgPrint("Failed to allocate work item\n");
1143 ExInitializeWorkItem(WorkQueueItem
,
1147 DPRINT("DeferredContext 0x%p\n", WorkQueueItem
);
1148 ExQueueWorkItem(WorkQueueItem
,
1156 LARGE_INTEGER Timeout
;
1158 DPRINT("CmiSyncHives() called\n");
1160 if (CmiHiveSyncEnabled
== FALSE
||
1161 CmiHiveSyncPending
== TRUE
)
1164 CmiHiveSyncPending
= TRUE
;
1166 Timeout
.QuadPart
= (LONGLONG
)-50000000;
1167 KeSetTimer(&CmiHiveSyncTimer
,