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
) ObpFreeObjectNameBuffer(&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
);
601 DPRINT("Inserting Key into Object Tree\n");
602 Status
= ObInsertObject((PVOID
)NewKey
,
608 DPRINT("Status %x\n", Status
);
610 /* Free the create information */
611 ObpFreeAndReleaseCapturedAttributes(OBJECT_TO_OBJECT_HEADER(NewKey
)->ObjectCreateInfo
);
612 OBJECT_TO_OBJECT_HEADER(NewKey
)->ObjectCreateInfo
= NULL
;
615 NewKey
->SubKeyCounts
= 0;
616 NewKey
->SubKeys
= NULL
;
617 NewKey
->SizeOfSubKeys
= 0;
618 InsertTailList(&CmiKeyObjectListHead
, &NewKey
->ListEntry
);
620 DPRINT ("SubName %S\n", SubName
);
622 Status
= CmiAddSubKey(ParentKey
->RegistryHive
,
628 REG_OPTION_VOLATILE
);
629 if (!NT_SUCCESS(Status
))
631 DPRINT1("CmiAddSubKey() failed (Status %lx)\n", Status
);
632 ObDereferenceObject (NewKey
);
633 ObDereferenceObject (ParentKey
);
634 return STATUS_INSUFFICIENT_RESOURCES
;
637 NewKey
->KeyCellOffset
= RegistryHive
->Hive
.HiveHeader
->RootCell
;
638 NewKey
->KeyCell
= HvGetCell (&RegistryHive
->Hive
, NewKey
->KeyCellOffset
);
639 NewKey
->RegistryHive
= RegistryHive
;
641 Status
= RtlpCreateUnicodeString(&NewKey
->Name
,
642 SubName
, NonPagedPool
);
643 RtlFreeUnicodeString(&RemainingPath
);
644 if (!NT_SUCCESS(Status
))
646 DPRINT1("RtlpCreateUnicodeString() failed (Status %lx)\n", Status
);
647 ObDereferenceObject (NewKey
);
648 ObDereferenceObject (ParentKey
);
649 return STATUS_INSUFFICIENT_RESOURCES
;
653 ObReferenceObject (NewKey
);
655 CmiAddKeyToList (ParentKey
, NewKey
);
656 ObDereferenceObject (ParentKey
);
658 VERIFY_KEY_OBJECT(NewKey
);
660 /* We're holding a pointer to the parent key .. We must keep it
662 /* Note: Do not dereference NewKey here! */
664 return STATUS_SUCCESS
;
669 CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
670 OUT PEREGISTRY_HIVE
*RegistryHive
)
672 PKEY_OBJECT KeyObject
;
673 PEREGISTRY_HIVE Hive
;
675 NTSTATUS Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
676 PLIST_ENTRY CurrentEntry
;
677 PKEY_OBJECT CurrentKey
;
679 DPRINT("CmiDisconnectHive() called\n");
681 *RegistryHive
= NULL
;
683 Status
= ObOpenObjectByName (KeyObjectAttributes
,
687 STANDARD_RIGHTS_REQUIRED
,
690 if (!NT_SUCCESS(Status
))
692 DPRINT1 ("ObOpenObjectByName() failed (Status %lx)\n", Status
);
696 Status
= ObReferenceObjectByHandle (KeyHandle
,
697 STANDARD_RIGHTS_REQUIRED
,
704 if (!NT_SUCCESS(Status
))
706 DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status
);
709 DPRINT ("KeyObject %p Hive %p\n", KeyObject
, KeyObject
->RegistryHive
);
711 /* Acquire registry lock exclusively */
712 KeEnterCriticalRegion();
713 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
715 Hive
= KeyObject
->RegistryHive
;
717 CurrentEntry
= CmiKeyObjectListHead
.Flink
;
718 while (CurrentEntry
!= &CmiKeyObjectListHead
)
720 CurrentKey
= CONTAINING_RECORD(CurrentEntry
, KEY_OBJECT
, ListEntry
);
721 if (CurrentKey
->RegistryHive
== Hive
&&
722 1 == ObGetObjectPointerCount(CurrentKey
) &&
723 !(CurrentKey
->Flags
& KO_MARKED_FOR_DELETE
))
725 ObDereferenceObject(CurrentKey
);
726 CurrentEntry
= CmiKeyObjectListHead
.Flink
;
730 CurrentEntry
= CurrentEntry
->Flink
;
735 ObDereferenceObject (KeyObject
);
737 if (ObGetObjectHandleCount (KeyObject
) != 0 ||
738 ObGetObjectPointerCount (KeyObject
) != 2)
740 DPRINT1 ("Hive is still in use (hc %d, rc %d)\n", ObGetObjectHandleCount (KeyObject
), ObGetObjectPointerCount (KeyObject
));
741 ObDereferenceObject (KeyObject
);
743 /* Release registry lock */
744 ExReleaseResourceLite (&CmiRegistryLock
);
745 KeLeaveCriticalRegion();
747 return STATUS_UNSUCCESSFUL
;
750 /* Dereference KeyObject twice to delete it */
751 ObDereferenceObject (KeyObject
);
752 ObDereferenceObject (KeyObject
);
754 *RegistryHive
= Hive
;
756 /* Release registry lock */
757 ExReleaseResourceLite (&CmiRegistryLock
);
758 KeLeaveCriticalRegion();
760 /* Release reference above */
761 ObDereferenceObject (KeyObject
);
763 DPRINT ("CmiDisconnectHive() done\n");
770 CmiInitControlSetLink (VOID
)
772 OBJECT_ATTRIBUTES ObjectAttributes
;
773 UNICODE_STRING ControlSetKeyName
= RTL_CONSTANT_STRING(
774 L
"\\Registry\\Machine\\SYSTEM\\ControlSet001");
775 UNICODE_STRING ControlSetLinkName
= RTL_CONSTANT_STRING(
776 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
777 UNICODE_STRING ControlSetValueName
= RTL_CONSTANT_STRING(L
"SymbolicLinkValue");
781 /* Create 'ControlSet001' key */
782 InitializeObjectAttributes (&ObjectAttributes
,
784 OBJ_CASE_INSENSITIVE
,
787 Status
= ZwCreateKey (&KeyHandle
,
792 REG_OPTION_NON_VOLATILE
,
794 if (!NT_SUCCESS(Status
))
796 DPRINT1 ("ZwCreateKey() failed (Status %lx)\n", Status
);
801 /* Link 'CurrentControlSet' to 'ControlSet001' key */
802 InitializeObjectAttributes (&ObjectAttributes
,
804 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
807 Status
= ZwCreateKey (&KeyHandle
,
808 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
812 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
814 if (!NT_SUCCESS(Status
))
816 DPRINT1 ("ZwCreateKey() failed (Status %lx)\n", Status
);
820 Status
= ZwSetValueKey (KeyHandle
,
821 &ControlSetValueName
,
824 (PVOID
)ControlSetKeyName
.Buffer
,
825 ControlSetKeyName
.Length
);
826 if (!NT_SUCCESS(Status
))
828 DPRINT1 ("ZwSetValueKey() failed (Status %lx)\n", Status
);
832 return STATUS_SUCCESS
;
837 CmiInitHives(BOOLEAN SetupBoot
)
839 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
840 OBJECT_ATTRIBUTES ObjectAttributes
;
841 UNICODE_STRING FileName
;
842 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE");
843 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"InstallPath");
848 WCHAR ConfigPath
[MAX_PATH
];
855 DPRINT("CmiInitHives() called\n");
857 if (SetupBoot
== TRUE
)
859 InitializeObjectAttributes(&ObjectAttributes
,
861 OBJ_CASE_INSENSITIVE
,
864 Status
= ZwOpenKey(&KeyHandle
,
867 if (!NT_SUCCESS(Status
))
869 DPRINT1("ZwOpenKey() failed (Status %lx)\n", Status
);
873 BufferSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 4096;
874 ValueInfo
= ExAllocatePool(PagedPool
,
876 if (ValueInfo
== NULL
)
879 return(STATUS_INSUFFICIENT_RESOURCES
);
882 Status
= ZwQueryValueKey(KeyHandle
,
884 KeyValuePartialInformation
,
889 if (!NT_SUCCESS(Status
))
891 ExFreePool(ValueInfo
);
895 RtlCopyMemory(ConfigPath
,
897 ValueInfo
->DataLength
);
898 ConfigPath
[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = (WCHAR
)0;
899 ExFreePool(ValueInfo
);
903 wcscpy(ConfigPath
, L
"\\SystemRoot");
905 wcscat(ConfigPath
, L
"\\system32\\config");
907 DPRINT("ConfigPath: %S\n", ConfigPath
);
909 EndPtr
= ConfigPath
+ wcslen(ConfigPath
);
911 /* FIXME: Save boot log */
913 /* Connect the SYSTEM hive only if it has been created */
914 if (SetupBoot
== TRUE
)
916 wcscpy(EndPtr
, REG_SYSTEM_FILE_NAME
);
917 DPRINT ("ConfigPath: %S\n", ConfigPath
);
919 RtlInitUnicodeString (&KeyName
,
920 REG_SYSTEM_KEY_NAME
);
921 InitializeObjectAttributes(&ObjectAttributes
,
923 OBJ_CASE_INSENSITIVE
,
927 RtlInitUnicodeString (&FileName
,
929 Status
= CmiLoadHive (&ObjectAttributes
,
932 if (!NT_SUCCESS(Status
))
934 DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status
);
938 Status
= CmiInitControlSetLink ();
939 if (!NT_SUCCESS(Status
))
941 DPRINT1("CmiInitControlSetLink() failed (Status %lx)\n", Status
);
946 /* Connect the SOFTWARE hive */
947 wcscpy(EndPtr
, REG_SOFTWARE_FILE_NAME
);
948 RtlInitUnicodeString (&FileName
,
950 DPRINT ("ConfigPath: %S\n", ConfigPath
);
952 RtlInitUnicodeString (&KeyName
,
953 REG_SOFTWARE_KEY_NAME
);
954 InitializeObjectAttributes(&ObjectAttributes
,
956 OBJ_CASE_INSENSITIVE
,
960 Status
= CmiLoadHive (&ObjectAttributes
,
963 if (!NT_SUCCESS(Status
))
965 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
969 /* Connect the SAM hive */
970 wcscpy(EndPtr
, REG_SAM_FILE_NAME
);
971 RtlInitUnicodeString (&FileName
,
973 DPRINT ("ConfigPath: %S\n", ConfigPath
);
975 RtlInitUnicodeString (&KeyName
,
977 InitializeObjectAttributes(&ObjectAttributes
,
979 OBJ_CASE_INSENSITIVE
,
982 Status
= CmiLoadHive (&ObjectAttributes
,
985 if (!NT_SUCCESS(Status
))
987 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
991 /* Connect the SECURITY hive */
992 wcscpy(EndPtr
, REG_SEC_FILE_NAME
);
993 RtlInitUnicodeString (&FileName
,
995 DPRINT ("ConfigPath: %S\n", ConfigPath
);
997 RtlInitUnicodeString (&KeyName
,
999 InitializeObjectAttributes(&ObjectAttributes
,
1001 OBJ_CASE_INSENSITIVE
,
1004 Status
= CmiLoadHive (&ObjectAttributes
,
1007 if (!NT_SUCCESS(Status
))
1009 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
1013 /* Connect the DEFAULT hive */
1014 wcscpy(EndPtr
, REG_DEFAULT_USER_FILE_NAME
);
1015 RtlInitUnicodeString (&FileName
,
1017 DPRINT ("ConfigPath: %S\n", ConfigPath
);
1019 RtlInitUnicodeString (&KeyName
,
1020 REG_DEFAULT_USER_KEY_NAME
);
1021 InitializeObjectAttributes(&ObjectAttributes
,
1023 OBJ_CASE_INSENSITIVE
,
1026 Status
= CmiLoadHive (&ObjectAttributes
,
1029 if (!NT_SUCCESS(Status
))
1031 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
1035 // CmiCheckRegistry(TRUE);
1037 /* Start automatic hive synchronization */
1038 KeInitializeDpc(&CmiHiveSyncDpc
,
1039 CmiHiveSyncDpcRoutine
,
1041 KeInitializeTimer(&CmiHiveSyncTimer
);
1042 CmiHiveSyncEnabled
= TRUE
;
1044 DPRINT("CmiInitHives() done\n");
1046 return(STATUS_SUCCESS
);
1051 CmShutdownRegistry(VOID
)
1053 PEREGISTRY_HIVE Hive
;
1056 DPRINT("CmShutdownRegistry() called\n");
1058 /* Stop automatic hive synchronization */
1059 CmiHiveSyncEnabled
= FALSE
;
1061 /* Cancel pending hive synchronization */
1062 if (CmiHiveSyncPending
== TRUE
)
1064 KeCancelTimer(&CmiHiveSyncTimer
);
1065 CmiHiveSyncPending
= FALSE
;
1068 /* Acquire hive list lock exclusively */
1069 KeEnterCriticalRegion();
1070 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
1072 Entry
= CmiHiveListHead
.Flink
;
1073 while (Entry
!= &CmiHiveListHead
)
1075 Hive
= CONTAINING_RECORD(Entry
, EREGISTRY_HIVE
, HiveList
);
1077 if (!(IsNoFileHive(Hive
) || IsNoSynchHive(Hive
)))
1079 /* Flush non-volatile hive */
1080 CmiFlushRegistryHive(Hive
);
1083 Entry
= Entry
->Flink
;
1086 /* Release hive list lock */
1087 ExReleaseResourceLite(&CmiRegistryLock
);
1088 KeLeaveCriticalRegion();
1090 DPRINT("CmShutdownRegistry() done\n");
1095 CmiHiveSyncRoutine(PVOID DeferredContext
)
1097 PEREGISTRY_HIVE Hive
;
1100 DPRINT("CmiHiveSyncRoutine() called\n");
1102 CmiHiveSyncPending
= FALSE
;
1104 /* Acquire hive list lock exclusively */
1105 KeEnterCriticalRegion();
1106 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
1108 Entry
= CmiHiveListHead
.Flink
;
1109 while (Entry
!= &CmiHiveListHead
)
1111 Hive
= CONTAINING_RECORD(Entry
, EREGISTRY_HIVE
, HiveList
);
1113 if (!(IsNoFileHive(Hive
) || IsNoSynchHive(Hive
)))
1115 /* Flush non-volatile hive */
1116 CmiFlushRegistryHive(Hive
);
1119 Entry
= Entry
->Flink
;
1122 /* Release hive list lock */
1123 ExReleaseResourceLite(&CmiRegistryLock
);
1124 KeLeaveCriticalRegion();
1126 DPRINT("DeferredContext 0x%p\n", DeferredContext
);
1127 ExFreePool(DeferredContext
);
1129 DPRINT("CmiHiveSyncRoutine() done\n");
1134 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
1135 PVOID DeferredContext
,
1136 PVOID SystemArgument1
,
1137 PVOID SystemArgument2
)
1139 PWORK_QUEUE_ITEM WorkQueueItem
;
1141 WorkQueueItem
= ExAllocatePool(NonPagedPool
,
1142 sizeof(WORK_QUEUE_ITEM
));
1143 if (WorkQueueItem
== NULL
)
1145 DbgPrint("Failed to allocate work item\n");
1149 ExInitializeWorkItem(WorkQueueItem
,
1153 DPRINT("DeferredContext 0x%p\n", WorkQueueItem
);
1154 ExQueueWorkItem(WorkQueueItem
,
1162 LARGE_INTEGER Timeout
;
1164 DPRINT("CmiSyncHives() called\n");
1166 if (CmiHiveSyncEnabled
== FALSE
||
1167 CmiHiveSyncPending
== TRUE
)
1170 CmiHiveSyncPending
= TRUE
;
1172 Timeout
.QuadPart
= (LONGLONG
)-50000000;
1173 KeSetTimer(&CmiHiveSyncTimer
,