3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/cm/registry.c
6 * PURPOSE: Registry functions
8 * PROGRAMMERS: Rex Jolliff
15 #include <internal/debug.h>
19 /* GLOBALS ******************************************************************/
21 POBJECT_TYPE CmiKeyType
= NULL
;
22 PREGISTRY_HIVE CmiVolatileHive
= NULL
;
23 KSPIN_LOCK CmiKeyListLock
;
25 LIST_ENTRY CmiHiveListHead
;
27 ERESOURCE CmiRegistryLock
;
29 volatile BOOLEAN CmiHiveSyncEnabled
= FALSE
;
30 volatile BOOLEAN CmiHiveSyncPending
= FALSE
;
32 KTIMER CmiHiveSyncTimer
;
34 static GENERIC_MAPPING CmiKeyMapping
=
35 {KEY_READ
, KEY_WRITE
, KEY_EXECUTE
, KEY_ALL_ACCESS
};
40 CmiCheckKey(BOOLEAN Verbose
,
44 CmiCreateCurrentControlSetLink(VOID
);
47 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
48 PVOID DeferredContext
,
49 PVOID SystemArgument1
,
50 PVOID SystemArgument2
);
52 extern LIST_ENTRY CmiCallbackHead
;
53 extern FAST_MUTEX CmiCallbackLock
;
55 /* FUNCTIONS ****************************************************************/
58 CmiCheckSubKeys(BOOLEAN Verbose
,
61 OBJECT_ATTRIBUTES ObjectAttributes
;
62 PKEY_NODE_INFORMATION KeyInfo
;
63 WCHAR KeyBuffer
[MAX_PATH
];
64 UNICODE_STRING KeyPath
;
75 BufferSize
= sizeof(KEY_NODE_INFORMATION
) + 4096;
76 KeyInfo
= ExAllocatePool(PagedPool
, BufferSize
);
78 Status
= ZwEnumerateKey(Key
,
84 if (!NT_SUCCESS(Status
))
87 if (Status
== STATUS_NO_MORE_ENTRIES
)
88 Status
= STATUS_SUCCESS
;
94 KeyInfo
->NameLength
/ sizeof(WCHAR
));
98 DbgPrint("Key: %S\n", Name
);
101 /* FIXME: Check info. */
105 wcscpy(KeyBuffer
, L
"\\Registry\\");
106 wcscat(KeyBuffer
, Name
);
108 RtlInitUnicodeString(&KeyPath
, KeyBuffer
);
110 InitializeObjectAttributes(&ObjectAttributes
,
112 OBJ_CASE_INSENSITIVE
,
116 Status
= ZwOpenKey(&SubKey
,
120 ASSERT(NT_SUCCESS(Status
));
122 CmiCheckKey(Verbose
, SubKey
);
129 ASSERT(NT_SUCCESS(Status
));
134 CmiCheckValues(BOOLEAN Verbose
,
137 PKEY_NODE_INFORMATION ValueInfo
;
138 WCHAR Name
[MAX_PATH
];
147 BufferSize
= sizeof(KEY_NODE_INFORMATION
) + 4096;
148 ValueInfo
= ExAllocatePool(PagedPool
, BufferSize
);
150 Status
= ZwEnumerateValueKey(Key
,
156 if (!NT_SUCCESS(Status
))
158 ExFreePool(ValueInfo
);
159 if (Status
== STATUS_NO_MORE_ENTRIES
)
160 Status
= STATUS_SUCCESS
;
166 ValueInfo
->NameLength
/ sizeof(WCHAR
));
170 DbgPrint("Value: %S\n", Name
);
173 /* FIXME: Check info. */
175 ExFreePool(ValueInfo
);
180 ASSERT(NT_SUCCESS(Status
));
185 CmiCheckKey(BOOLEAN Verbose
,
188 CmiCheckValues(Verbose
, Key
);
189 CmiCheckSubKeys(Verbose
, Key
);
194 CmiCheckByName(BOOLEAN Verbose
,
197 OBJECT_ATTRIBUTES ObjectAttributes
;
198 WCHAR KeyPathBuffer
[MAX_PATH
];
199 UNICODE_STRING KeyPath
;
203 wcscpy(KeyPathBuffer
, L
"\\Registry\\");
204 wcscat(KeyPathBuffer
, KeyName
);
206 RtlInitUnicodeString(&KeyPath
, KeyPathBuffer
);
208 InitializeObjectAttributes(&ObjectAttributes
,
210 OBJ_CASE_INSENSITIVE
,
214 Status
= ZwOpenKey(&Key
,
220 if (!NT_SUCCESS(Status
))
222 DbgPrint("KeyPath %wZ Status: %.08x", KeyPath
, Status
);
223 DbgPrint("KeyPath %S Status: %.08x", KeyPath
.Buffer
, Status
);
224 ASSERT(NT_SUCCESS(Status
));
228 CmiCheckKey(Verbose
, Key
);
235 CmiCheckRegistry(BOOLEAN Verbose
)
238 DbgPrint("Checking registry internals\n");
240 CmiCheckByName(Verbose
, L
"Machine");
241 CmiCheckByName(Verbose
, L
"User");
246 CmInitializeRegistry(VOID
)
248 OBJECT_ATTRIBUTES ObjectAttributes
;
249 UNICODE_STRING KeyName
;
252 PSECURITY_CELL RootSecurityCell
;
254 HANDLE RootKeyHandle
;
258 /* Initialize the Key object type */
259 CmiKeyType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
261 CmiKeyType
->Tag
= TAG('R', 'e', 'g', 'K');
262 CmiKeyType
->TotalObjects
= 0;
263 CmiKeyType
->TotalHandles
= 0;
264 CmiKeyType
->PeakObjects
= 0;
265 CmiKeyType
->PeakHandles
= 0;
266 CmiKeyType
->PagedPoolCharge
= 0;
267 CmiKeyType
->NonpagedPoolCharge
= sizeof(KEY_OBJECT
);
268 CmiKeyType
->Mapping
= &CmiKeyMapping
;
269 CmiKeyType
->Dump
= NULL
;
270 CmiKeyType
->Open
= NULL
;
271 CmiKeyType
->Close
= NULL
;
272 CmiKeyType
->Delete
= CmiObjectDelete
;
273 CmiKeyType
->Parse
= CmiObjectParse
;
274 CmiKeyType
->Security
= CmiObjectSecurity
;
275 CmiKeyType
->QueryName
= CmiObjectQueryName
;
276 CmiKeyType
->OkayToClose
= NULL
;
277 CmiKeyType
->Create
= CmiObjectCreate
;
278 CmiKeyType
->DuplicationNotify
= NULL
;
279 RtlInitUnicodeString(&CmiKeyType
->TypeName
, L
"Key");
281 ObpCreateTypeObject (CmiKeyType
);
283 /* Initialize the hive list */
284 InitializeListHead(&CmiHiveListHead
);
286 /* Initialize registry lock */
287 ExInitializeResourceLite(&CmiRegistryLock
);
289 /* Build volatile registry store */
290 Status
= CmiCreateVolatileHive (&CmiVolatileHive
);
291 ASSERT(NT_SUCCESS(Status
));
293 InitializeListHead(&CmiCallbackHead
);
294 ExInitializeFastMutex(&CmiCallbackLock
);
296 /* Create '\Registry' key. */
297 RtlInitUnicodeString(&KeyName
, REG_ROOT_KEY_NAME
);
298 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, 0, NULL
, NULL
);
299 Status
= ObCreateObject(KernelMode
,
308 ASSERT(NT_SUCCESS(Status
));
309 Status
= ObInsertObject(RootKey
,
311 STANDARD_RIGHTS_REQUIRED
,
315 ASSERT(NT_SUCCESS(Status
));
316 RootKey
->RegistryHive
= CmiVolatileHive
;
317 RootKey
->KeyCellOffset
= CmiVolatileHive
->HiveHeader
->RootKeyOffset
;
318 RootKey
->KeyCell
= CmiGetCell (CmiVolatileHive
, RootKey
->KeyCellOffset
, NULL
);
319 RootKey
->ParentKey
= RootKey
;
321 RootKey
->NumberOfSubKeys
= 0;
322 RootKey
->SubKeys
= NULL
;
323 RootKey
->SizeOfSubKeys
= 0;
324 Status
= RtlpCreateUnicodeString(&RootKey
->Name
, L
"Registry", NonPagedPool
);
325 ASSERT(NT_SUCCESS(Status
));
328 Status
= CmiAllocateCell(CmiVolatileHive
,
329 0x10, //LONG CellSize,
330 (PVOID
*)&RootSecurityCell
,
331 &RootKey
->KeyCell
->SecurityKeyOffset
);
332 ASSERT(NT_SUCCESS(Status
));
334 /* Copy the security descriptor */
336 CmiVolatileHive
->RootSecurityCell
= RootSecurityCell
;
339 KeInitializeSpinLock(&CmiKeyListLock
);
341 /* Create '\Registry\Machine' key. */
342 RtlInitUnicodeString(&KeyName
,
344 InitializeObjectAttributes(&ObjectAttributes
,
349 Status
= ZwCreateKey(&KeyHandle
,
350 STANDARD_RIGHTS_REQUIRED
,
356 ASSERT(NT_SUCCESS(Status
));
358 /* Create '\Registry\User' key. */
359 RtlInitUnicodeString(&KeyName
,
361 InitializeObjectAttributes(&ObjectAttributes
,
366 Status
= ZwCreateKey(&KeyHandle
,
367 STANDARD_RIGHTS_REQUIRED
,
373 ASSERT(NT_SUCCESS(Status
));
378 CmInit2(PCHAR CommandLine
)
381 BOOLEAN MiniNT
= FALSE
;
382 PWCHAR SystemBootDevice
;
383 PWCHAR SystemStartOptions
;
387 /* Create the 'CurrentControlSet' link. */
388 Status
= CmiCreateCurrentControlSetLink();
389 if (!NT_SUCCESS(Status
))
390 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
393 * Parse the system boot device.
396 SystemBootDevice
= ExAllocatePool(PagedPool
,
397 (strlen(CommandLine
) + 1) * sizeof(WCHAR
));
398 if (SystemBootDevice
== NULL
)
400 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
403 while (*CommandLine
!= 0 && *CommandLine
!= ' ')
404 SystemBootDevice
[Position
++] = *(CommandLine
++);
405 SystemBootDevice
[Position
++] = 0;
408 * Write the system boot device to registry.
410 Status
= RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
411 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control",
415 Position
* sizeof(WCHAR
));
416 if (!NT_SUCCESS(Status
))
418 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
422 * Parse the system start options.
425 SystemStartOptions
= SystemBootDevice
;
426 while ((CommandLine
= strchr(CommandLine
, '/')) != NULL
)
428 /* Skip over the slash */
431 /* Special options */
432 if (!_strnicmp(CommandLine
, "MININT", 6))
434 else if (!_strnicmp(CommandLine
, "DEBUGPORT=PICE", 14))
437 /* Add a space between the options */
439 SystemStartOptions
[Position
++] = L
' ';
441 /* Copy the command */
442 while (*CommandLine
!= 0 && *CommandLine
!= ' ')
443 SystemStartOptions
[Position
++] = *(CommandLine
++);
445 SystemStartOptions
[Position
++] = 0;
448 * Write the system start options to registry.
450 Status
= RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
451 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control",
452 L
"SystemStartOptions",
455 Position
* sizeof(WCHAR
));
456 if (!NT_SUCCESS(Status
))
458 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
462 * Create a CurrentControlSet\Control\MiniNT key that is used
463 * to detect WinPE/MiniNT systems.
467 Status
= RtlCreateRegistryKey(RTL_REGISTRY_CONTROL
, L
"MiniNT");
468 if (!NT_SUCCESS(Status
))
469 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
472 /* Set PICE 'Start' value to 1, if PICE debugging is enabled */
473 Status
= RtlWriteRegistryValue(
474 RTL_REGISTRY_SERVICES
,
480 if (!NT_SUCCESS(Status
))
481 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
483 ExFreePool(SystemBootDevice
);
488 CmiCreateCurrentControlSetLink(VOID
)
490 RTL_QUERY_REGISTRY_TABLE QueryTable
[5];
491 WCHAR TargetNameBuffer
[80];
492 ULONG TargetNameLength
;
493 UNICODE_STRING LinkName
;
494 UNICODE_STRING LinkValue
;
500 OBJECT_ATTRIBUTES ObjectAttributes
;
503 DPRINT("CmiCreateCurrentControlSetLink() called\n");
505 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
507 QueryTable
[0].Name
= L
"Current";
508 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
509 QueryTable
[0].EntryContext
= &CurrentSet
;
511 QueryTable
[1].Name
= L
"Default";
512 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
513 QueryTable
[1].EntryContext
= &DefaultSet
;
515 QueryTable
[2].Name
= L
"Failed";
516 QueryTable
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
517 QueryTable
[2].EntryContext
= &Failed
;
519 QueryTable
[3].Name
= L
"LastKnownGood";
520 QueryTable
[3].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
521 QueryTable
[3].EntryContext
= &LastKnownGood
;
523 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
524 L
"\\Registry\\Machine\\SYSTEM\\Select",
528 if (!NT_SUCCESS(Status
))
533 DPRINT("Current %ld Default %ld\n", CurrentSet
, DefaultSet
);
535 swprintf(TargetNameBuffer
,
536 L
"\\Registry\\Machine\\SYSTEM\\ControlSet%03lu",
538 TargetNameLength
= wcslen(TargetNameBuffer
) * sizeof(WCHAR
);
540 DPRINT("Link target '%S'\n", TargetNameBuffer
);
542 RtlRosInitUnicodeStringFromLiteral(&LinkName
,
543 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
544 InitializeObjectAttributes(&ObjectAttributes
,
546 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
549 Status
= ZwCreateKey(&KeyHandle
,
550 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
554 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
556 if (!NT_SUCCESS(Status
))
558 DPRINT1("ZwCreateKey() failed (Status %lx)\n", Status
);
562 RtlRosInitUnicodeStringFromLiteral(&LinkValue
,
563 L
"SymbolicLinkValue");
564 Status
= ZwSetValueKey(KeyHandle
,
568 (PVOID
)TargetNameBuffer
,
570 if (!NT_SUCCESS(Status
))
572 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
582 CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
583 IN PREGISTRY_HIVE RegistryHive
)
585 UNICODE_STRING RemainingPath
;
586 PKEY_OBJECT ParentKey
;
591 DPRINT("CmiConnectHive(%p, %p) called.\n",
592 KeyObjectAttributes
, RegistryHive
);
594 Status
= ObFindObject(KeyObjectAttributes
,
598 if (!NT_SUCCESS(Status
))
603 DPRINT ("RemainingPath %wZ\n", &RemainingPath
);
605 if ((RemainingPath
.Buffer
== NULL
) || (RemainingPath
.Buffer
[0] == 0))
607 ObDereferenceObject (ParentKey
);
608 RtlFreeUnicodeString(&RemainingPath
);
609 return STATUS_OBJECT_NAME_COLLISION
;
612 /* Ignore leading backslash */
613 SubName
= RemainingPath
.Buffer
;
614 if (*SubName
== L
'\\')
617 /* If RemainingPath contains \ we must return error
618 because CmiConnectHive() can not create trees */
619 if (wcschr (SubName
, L
'\\') != NULL
)
621 ObDereferenceObject (ParentKey
);
622 RtlFreeUnicodeString(&RemainingPath
);
623 return STATUS_OBJECT_NAME_NOT_FOUND
;
626 DPRINT("RemainingPath %wZ ParentKey %p\n",
627 &RemainingPath
, ParentKey
);
629 Status
= ObCreateObject(KernelMode
,
638 if (!NT_SUCCESS(Status
))
640 DPRINT1 ("ObCreateObject() failed (Status %lx)\n", Status
);
641 ObDereferenceObject (ParentKey
);
642 RtlFreeUnicodeString(&RemainingPath
);
646 NewKey
->RegistryHive
= RegistryHive
;
647 NewKey
->KeyCellOffset
= RegistryHive
->HiveHeader
->RootKeyOffset
;
648 NewKey
->KeyCell
= CmiGetCell (RegistryHive
, NewKey
->KeyCellOffset
, NULL
);
650 NewKey
->NumberOfSubKeys
= 0;
651 if (NewKey
->KeyCell
->NumberOfSubKeys
!= 0)
653 NewKey
->SubKeys
= ExAllocatePool(NonPagedPool
,
654 NewKey
->KeyCell
->NumberOfSubKeys
* sizeof(ULONG
));
655 if (NewKey
->SubKeys
== NULL
)
657 DPRINT("ExAllocatePool() failed\n");
658 ObDereferenceObject (NewKey
);
659 ObDereferenceObject (ParentKey
);
660 RtlFreeUnicodeString(&RemainingPath
);
661 return STATUS_INSUFFICIENT_RESOURCES
;
666 NewKey
->SubKeys
= NULL
;
669 DPRINT ("SubName %S\n", SubName
);
671 Status
= RtlpCreateUnicodeString(&NewKey
->Name
,
672 SubName
, NonPagedPool
);
673 RtlFreeUnicodeString(&RemainingPath
);
674 if (!NT_SUCCESS(Status
))
676 DPRINT1("RtlpCreateUnicodeString() failed (Status %lx)\n", Status
);
677 if (NewKey
->SubKeys
!= NULL
)
679 ExFreePool (NewKey
->SubKeys
);
681 ObDereferenceObject (NewKey
);
682 ObDereferenceObject (ParentKey
);
683 return STATUS_INSUFFICIENT_RESOURCES
;
686 CmiAddKeyToList (ParentKey
, NewKey
);
687 ObDereferenceObject (ParentKey
);
689 VERIFY_KEY_OBJECT(NewKey
);
691 /* Note: Do not dereference NewKey here! */
693 return STATUS_SUCCESS
;
698 CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
699 OUT PREGISTRY_HIVE
*RegistryHive
)
701 PKEY_OBJECT KeyObject
;
706 DPRINT("CmiDisconnectHive() called\n");
708 *RegistryHive
= NULL
;
710 Status
= ObOpenObjectByName (KeyObjectAttributes
,
714 STANDARD_RIGHTS_REQUIRED
,
717 if (!NT_SUCCESS(Status
))
719 DPRINT1 ("ObOpenObjectByName() failed (Status %lx)\n", Status
);
723 Status
= ObReferenceObjectByHandle (KeyHandle
,
724 STANDARD_RIGHTS_REQUIRED
,
730 if (!NT_SUCCESS(Status
))
732 DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status
);
735 DPRINT ("KeyObject %p Hive %p\n", KeyObject
, KeyObject
->RegistryHive
);
737 if (!(KeyObject
->KeyCell
->Flags
& REG_KEY_ROOT_CELL
))
739 DPRINT1 ("Key is not the Hive-Root-Key\n");
740 ObDereferenceObject (KeyObject
);
741 return STATUS_INVALID_PARAMETER
;
744 if (ObGetObjectHandleCount (KeyObject
) != 0 ||
745 ObGetObjectPointerCount (KeyObject
) != 2)
747 DPRINT1 ("Hive is still in use\n");
748 ObDereferenceObject (KeyObject
);
749 return STATUS_UNSUCCESSFUL
;
752 Hive
= KeyObject
->RegistryHive
;
754 /* Dereference KeyObject twice to delete it */
755 ObDereferenceObject (KeyObject
);
756 ObDereferenceObject (KeyObject
);
758 *RegistryHive
= Hive
;
760 DPRINT ("CmiDisconnectHive() done\n");
762 return STATUS_SUCCESS
;
767 CmiInitControlSetLink (VOID
)
769 OBJECT_ATTRIBUTES ObjectAttributes
;
770 UNICODE_STRING ControlSetKeyName
;
771 UNICODE_STRING ControlSetLinkName
;
772 UNICODE_STRING ControlSetValueName
;
776 /* Create 'ControlSet001' key */
777 RtlRosInitUnicodeStringFromLiteral (&ControlSetKeyName
,
778 L
"\\Registry\\Machine\\SYSTEM\\ControlSet001");
779 InitializeObjectAttributes (&ObjectAttributes
,
781 OBJ_CASE_INSENSITIVE
,
784 Status
= ZwCreateKey (&KeyHandle
,
789 REG_OPTION_NON_VOLATILE
,
791 if (!NT_SUCCESS(Status
))
793 DPRINT1 ("ZwCreateKey() failed (Status %lx)\n", Status
);
798 /* Link 'CurrentControlSet' to 'ControlSet001' key */
799 RtlRosInitUnicodeStringFromLiteral (&ControlSetLinkName
,
800 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
801 InitializeObjectAttributes (&ObjectAttributes
,
803 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
806 Status
= ZwCreateKey (&KeyHandle
,
807 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
811 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
813 if (!NT_SUCCESS(Status
))
815 DPRINT1 ("ZwCreateKey() failed (Status %lx)\n", Status
);
819 RtlRosInitUnicodeStringFromLiteral (&ControlSetValueName
,
820 L
"SymbolicLinkValue");
821 Status
= ZwSetValueKey (KeyHandle
,
822 &ControlSetValueName
,
825 (PVOID
)ControlSetKeyName
.Buffer
,
826 ControlSetKeyName
.Length
);
827 if (!NT_SUCCESS(Status
))
829 DPRINT1 ("ZwSetValueKey() failed (Status %lx)\n", Status
);
833 return STATUS_SUCCESS
;
838 CmiInitHives(BOOLEAN SetupBoot
)
840 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
841 OBJECT_ATTRIBUTES ObjectAttributes
;
842 UNICODE_STRING FileName
;
843 UNICODE_STRING KeyName
;
844 UNICODE_STRING ValueName
;
849 WCHAR ConfigPath
[MAX_PATH
];
856 DPRINT("CmiInitHives() called\n");
858 if (SetupBoot
== TRUE
)
860 RtlRosInitUnicodeStringFromLiteral(&KeyName
,
861 L
"\\Registry\\Machine\\HARDWARE");
862 InitializeObjectAttributes(&ObjectAttributes
,
864 OBJ_CASE_INSENSITIVE
,
867 Status
= ZwOpenKey(&KeyHandle
,
870 if (!NT_SUCCESS(Status
))
872 DPRINT1("ZwOpenKey() failed (Status %lx)\n", Status
);
876 RtlRosInitUnicodeStringFromLiteral(&ValueName
,
879 BufferSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 4096;
880 ValueInfo
= ExAllocatePool(PagedPool
,
882 if (ValueInfo
== NULL
)
885 return(STATUS_INSUFFICIENT_RESOURCES
);
888 Status
= ZwQueryValueKey(KeyHandle
,
890 KeyValuePartialInformation
,
895 if (!NT_SUCCESS(Status
))
897 ExFreePool(ValueInfo
);
901 RtlCopyMemory(ConfigPath
,
903 ValueInfo
->DataLength
);
904 ConfigPath
[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = (WCHAR
)0;
905 ExFreePool(ValueInfo
);
909 wcscpy(ConfigPath
, L
"\\SystemRoot");
911 wcscat(ConfigPath
, L
"\\system32\\config");
913 DPRINT("ConfigPath: %S\n", ConfigPath
);
915 EndPtr
= ConfigPath
+ wcslen(ConfigPath
);
919 /* FIXME: Save boot log */
921 /* Connect the SYSTEM hive only if it has been created */
922 if (SetupBoot
== TRUE
)
924 wcscpy(EndPtr
, REG_SYSTEM_FILE_NAME
);
925 DPRINT ("ConfigPath: %S\n", ConfigPath
);
927 RtlInitUnicodeString (&KeyName
,
928 REG_SYSTEM_KEY_NAME
);
929 InitializeObjectAttributes(&ObjectAttributes
,
931 OBJ_CASE_INSENSITIVE
,
935 RtlInitUnicodeString (&FileName
,
937 Status
= CmiLoadHive (&ObjectAttributes
,
940 if (!NT_SUCCESS(Status
))
942 DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status
);
946 Status
= CmiInitControlSetLink ();
947 if (!NT_SUCCESS(Status
))
949 DPRINT1("CmiInitControlSetLink() failed (Status %lx)\n", Status
);
954 /* Connect the SOFTWARE hive */
955 wcscpy(EndPtr
, REG_SOFTWARE_FILE_NAME
);
956 RtlInitUnicodeString (&FileName
,
958 DPRINT ("ConfigPath: %S\n", ConfigPath
);
960 RtlInitUnicodeString (&KeyName
,
961 REG_SOFTWARE_KEY_NAME
);
962 InitializeObjectAttributes(&ObjectAttributes
,
964 OBJ_CASE_INSENSITIVE
,
968 Status
= CmiLoadHive (&ObjectAttributes
,
971 if (!NT_SUCCESS(Status
))
973 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
977 /* Connect the SAM hive */
978 wcscpy(EndPtr
, REG_SAM_FILE_NAME
);
979 RtlInitUnicodeString (&FileName
,
981 DPRINT ("ConfigPath: %S\n", ConfigPath
);
983 RtlInitUnicodeString (&KeyName
,
985 InitializeObjectAttributes(&ObjectAttributes
,
987 OBJ_CASE_INSENSITIVE
,
990 Status
= CmiLoadHive (&ObjectAttributes
,
993 if (!NT_SUCCESS(Status
))
995 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
999 /* Connect the SECURITY hive */
1000 wcscpy(EndPtr
, REG_SEC_FILE_NAME
);
1001 RtlInitUnicodeString (&FileName
,
1003 DPRINT ("ConfigPath: %S\n", ConfigPath
);
1005 RtlInitUnicodeString (&KeyName
,
1007 InitializeObjectAttributes(&ObjectAttributes
,
1009 OBJ_CASE_INSENSITIVE
,
1012 Status
= CmiLoadHive (&ObjectAttributes
,
1015 if (!NT_SUCCESS(Status
))
1017 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
1021 /* Connect the DEFAULT hive */
1022 wcscpy(EndPtr
, REG_DEFAULT_USER_FILE_NAME
);
1023 RtlInitUnicodeString (&FileName
,
1025 DPRINT ("ConfigPath: %S\n", ConfigPath
);
1027 RtlInitUnicodeString (&KeyName
,
1028 REG_DEFAULT_USER_KEY_NAME
);
1029 InitializeObjectAttributes(&ObjectAttributes
,
1031 OBJ_CASE_INSENSITIVE
,
1034 Status
= CmiLoadHive (&ObjectAttributes
,
1037 if (!NT_SUCCESS(Status
))
1039 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
1043 // CmiCheckRegistry(TRUE);
1045 /* Start automatic hive synchronization */
1046 KeInitializeDpc(&CmiHiveSyncDpc
,
1047 CmiHiveSyncDpcRoutine
,
1049 KeInitializeTimer(&CmiHiveSyncTimer
);
1050 CmiHiveSyncEnabled
= TRUE
;
1052 DPRINT("CmiInitHives() done\n");
1054 return(STATUS_SUCCESS
);
1059 CmShutdownRegistry(VOID
)
1061 PREGISTRY_HIVE Hive
;
1064 DPRINT("CmShutdownRegistry() called\n");
1066 /* Stop automatic hive synchronization */
1067 CmiHiveSyncEnabled
= FALSE
;
1069 /* Cancel pending hive synchronization */
1070 if (CmiHiveSyncPending
== TRUE
)
1072 KeCancelTimer(&CmiHiveSyncTimer
);
1073 CmiHiveSyncPending
= FALSE
;
1076 /* Acquire hive list lock exclusively */
1077 KeEnterCriticalRegion();
1078 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
1080 Entry
= CmiHiveListHead
.Flink
;
1081 while (Entry
!= &CmiHiveListHead
)
1083 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
1085 if (!(IsNoFileHive(Hive
) || IsNoSynchHive(Hive
)))
1087 /* Flush non-volatile hive */
1088 CmiFlushRegistryHive(Hive
);
1091 Entry
= Entry
->Flink
;
1094 /* Release hive list lock */
1095 ExReleaseResourceLite(&CmiRegistryLock
);
1096 KeLeaveCriticalRegion();
1098 DPRINT("CmShutdownRegistry() done\n");
1103 CmiHiveSyncRoutine(PVOID DeferredContext
)
1105 PREGISTRY_HIVE Hive
;
1108 DPRINT("CmiHiveSyncRoutine() called\n");
1110 CmiHiveSyncPending
= FALSE
;
1112 /* Acquire hive list lock exclusively */
1113 KeEnterCriticalRegion();
1114 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
1116 Entry
= CmiHiveListHead
.Flink
;
1117 while (Entry
!= &CmiHiveListHead
)
1119 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
1121 if (!(IsNoFileHive(Hive
) || IsNoSynchHive(Hive
)))
1123 /* Flush non-volatile hive */
1124 CmiFlushRegistryHive(Hive
);
1127 Entry
= Entry
->Flink
;
1130 /* Release hive list lock */
1131 ExReleaseResourceLite(&CmiRegistryLock
);
1132 KeLeaveCriticalRegion();
1134 DPRINT("DeferredContext %x\n", DeferredContext
);
1135 ExFreePool(DeferredContext
);
1137 DPRINT("CmiHiveSyncRoutine() done\n");
1142 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
1143 PVOID DeferredContext
,
1144 PVOID SystemArgument1
,
1145 PVOID SystemArgument2
)
1147 PWORK_QUEUE_ITEM WorkQueueItem
;
1149 WorkQueueItem
= ExAllocatePool(NonPagedPool
,
1150 sizeof(WORK_QUEUE_ITEM
));
1151 if (WorkQueueItem
== NULL
)
1153 DbgPrint("Failed to allocate work item\n");
1157 ExInitializeWorkItem(WorkQueueItem
,
1161 DPRINT("DeferredContext %x\n", WorkQueueItem
);
1162 ExQueueWorkItem(WorkQueueItem
,
1170 LARGE_INTEGER Timeout
;
1172 DPRINT("CmiSyncHives() called\n");
1174 if (CmiHiveSyncEnabled
== FALSE
||
1175 CmiHiveSyncPending
== TRUE
)
1178 CmiHiveSyncPending
= TRUE
;
1180 Timeout
.QuadPart
= (LONGLONG
)-50000000;
1181 KeSetTimer(&CmiHiveSyncTimer
,