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 /* FUNCTIONS ****************************************************************/
55 CmiCheckSubKeys(BOOLEAN Verbose
,
58 OBJECT_ATTRIBUTES ObjectAttributes
;
59 PKEY_NODE_INFORMATION KeyInfo
;
60 WCHAR KeyBuffer
[MAX_PATH
];
61 UNICODE_STRING KeyPath
;
72 BufferSize
= sizeof(KEY_NODE_INFORMATION
) + 4096;
73 KeyInfo
= ExAllocatePool(PagedPool
, BufferSize
);
75 Status
= ZwEnumerateKey(Key
,
81 if (!NT_SUCCESS(Status
))
84 if (Status
== STATUS_NO_MORE_ENTRIES
)
85 Status
= STATUS_SUCCESS
;
91 KeyInfo
->NameLength
/ sizeof(WCHAR
));
95 DbgPrint("Key: %S\n", Name
);
98 /* FIXME: Check info. */
102 wcscpy(KeyBuffer
, L
"\\Registry\\");
103 wcscat(KeyBuffer
, Name
);
105 RtlInitUnicodeString(&KeyPath
, KeyBuffer
);
107 InitializeObjectAttributes(&ObjectAttributes
,
109 OBJ_CASE_INSENSITIVE
,
113 Status
= ZwOpenKey(&SubKey
,
117 ASSERT(NT_SUCCESS(Status
));
119 CmiCheckKey(Verbose
, SubKey
);
126 ASSERT(NT_SUCCESS(Status
));
131 CmiCheckValues(BOOLEAN Verbose
,
134 PKEY_NODE_INFORMATION ValueInfo
;
135 WCHAR Name
[MAX_PATH
];
144 BufferSize
= sizeof(KEY_NODE_INFORMATION
) + 4096;
145 ValueInfo
= ExAllocatePool(PagedPool
, BufferSize
);
147 Status
= ZwEnumerateValueKey(Key
,
153 if (!NT_SUCCESS(Status
))
155 ExFreePool(ValueInfo
);
156 if (Status
== STATUS_NO_MORE_ENTRIES
)
157 Status
= STATUS_SUCCESS
;
163 ValueInfo
->NameLength
/ sizeof(WCHAR
));
167 DbgPrint("Value: %S\n", Name
);
170 /* FIXME: Check info. */
172 ExFreePool(ValueInfo
);
177 ASSERT(NT_SUCCESS(Status
));
182 CmiCheckKey(BOOLEAN Verbose
,
185 CmiCheckValues(Verbose
, Key
);
186 CmiCheckSubKeys(Verbose
, Key
);
191 CmiCheckByName(BOOLEAN Verbose
,
194 OBJECT_ATTRIBUTES ObjectAttributes
;
195 WCHAR KeyPathBuffer
[MAX_PATH
];
196 UNICODE_STRING KeyPath
;
200 wcscpy(KeyPathBuffer
, L
"\\Registry\\");
201 wcscat(KeyPathBuffer
, KeyName
);
203 RtlInitUnicodeString(&KeyPath
, KeyPathBuffer
);
205 InitializeObjectAttributes(&ObjectAttributes
,
207 OBJ_CASE_INSENSITIVE
,
211 Status
= ZwOpenKey(&Key
,
217 if (!NT_SUCCESS(Status
))
219 DbgPrint("KeyPath %wZ Status: %.08x", KeyPath
, Status
);
220 DbgPrint("KeyPath %S Status: %.08x", KeyPath
.Buffer
, Status
);
221 ASSERT(NT_SUCCESS(Status
));
225 CmiCheckKey(Verbose
, Key
);
232 CmiCheckRegistry(BOOLEAN Verbose
)
235 DbgPrint("Checking registry internals\n");
237 CmiCheckByName(Verbose
, L
"Machine");
238 CmiCheckByName(Verbose
, L
"User");
243 CmInitializeRegistry(VOID
)
245 OBJECT_ATTRIBUTES ObjectAttributes
;
246 UNICODE_STRING KeyName
;
249 PSECURITY_CELL RootSecurityCell
;
251 HANDLE RootKeyHandle
;
255 /* Initialize the Key object type */
256 CmiKeyType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
258 CmiKeyType
->Tag
= TAG('R', 'e', 'g', 'K');
259 CmiKeyType
->TotalObjects
= 0;
260 CmiKeyType
->TotalHandles
= 0;
261 CmiKeyType
->PeakObjects
= 0;
262 CmiKeyType
->PeakHandles
= 0;
263 CmiKeyType
->PagedPoolCharge
= 0;
264 CmiKeyType
->NonpagedPoolCharge
= sizeof(KEY_OBJECT
);
265 CmiKeyType
->Mapping
= &CmiKeyMapping
;
266 CmiKeyType
->Dump
= NULL
;
267 CmiKeyType
->Open
= NULL
;
268 CmiKeyType
->Close
= NULL
;
269 CmiKeyType
->Delete
= CmiObjectDelete
;
270 CmiKeyType
->Parse
= CmiObjectParse
;
271 CmiKeyType
->Security
= CmiObjectSecurity
;
272 CmiKeyType
->QueryName
= CmiObjectQueryName
;
273 CmiKeyType
->OkayToClose
= NULL
;
274 CmiKeyType
->Create
= CmiObjectCreate
;
275 CmiKeyType
->DuplicationNotify
= NULL
;
276 RtlInitUnicodeString(&CmiKeyType
->TypeName
, L
"Key");
278 ObpCreateTypeObject (CmiKeyType
);
280 /* Initialize the hive list */
281 InitializeListHead(&CmiHiveListHead
);
283 /* Initialize registry lock */
284 ExInitializeResourceLite(&CmiRegistryLock
);
286 /* Build volatile registry store */
287 Status
= CmiCreateVolatileHive (&CmiVolatileHive
);
288 ASSERT(NT_SUCCESS(Status
));
290 /* Create '\Registry' key. */
291 RtlInitUnicodeString(&KeyName
, REG_ROOT_KEY_NAME
);
292 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, 0, NULL
, NULL
);
293 Status
= ObCreateObject(KernelMode
,
302 ASSERT(NT_SUCCESS(Status
));
303 Status
= ObInsertObject(RootKey
,
305 STANDARD_RIGHTS_REQUIRED
,
309 ASSERT(NT_SUCCESS(Status
));
310 RootKey
->RegistryHive
= CmiVolatileHive
;
311 RootKey
->KeyCellOffset
= CmiVolatileHive
->HiveHeader
->RootKeyOffset
;
312 RootKey
->KeyCell
= CmiGetCell (CmiVolatileHive
, RootKey
->KeyCellOffset
, NULL
);
313 RootKey
->ParentKey
= RootKey
;
315 RootKey
->NumberOfSubKeys
= 0;
316 RootKey
->SubKeys
= NULL
;
317 RootKey
->SizeOfSubKeys
= 0;
318 Status
= RtlCreateUnicodeString(&RootKey
->Name
, L
"Registry");
319 ASSERT(NT_SUCCESS(Status
));
322 Status
= CmiAllocateCell(CmiVolatileHive
,
323 0x10, //LONG CellSize,
324 (PVOID
*)&RootSecurityCell
,
325 &RootKey
->KeyCell
->SecurityKeyOffset
);
326 ASSERT(NT_SUCCESS(Status
));
328 /* Copy the security descriptor */
330 CmiVolatileHive
->RootSecurityCell
= RootSecurityCell
;
333 KeInitializeSpinLock(&CmiKeyListLock
);
335 /* Create '\Registry\Machine' key. */
336 RtlInitUnicodeString(&KeyName
,
338 InitializeObjectAttributes(&ObjectAttributes
,
343 Status
= ZwCreateKey(&KeyHandle
,
344 STANDARD_RIGHTS_REQUIRED
,
350 ASSERT(NT_SUCCESS(Status
));
352 /* Create '\Registry\User' key. */
353 RtlInitUnicodeString(&KeyName
,
355 InitializeObjectAttributes(&ObjectAttributes
,
360 Status
= ZwCreateKey(&KeyHandle
,
361 STANDARD_RIGHTS_REQUIRED
,
367 ASSERT(NT_SUCCESS(Status
));
372 CmInit2(PCHAR CommandLine
)
375 BOOLEAN MiniNT
= FALSE
;
376 PWCHAR SystemBootDevice
;
377 PWCHAR SystemStartOptions
;
381 /* Create the 'CurrentControlSet' link. */
382 Status
= CmiCreateCurrentControlSetLink();
383 if (!NT_SUCCESS(Status
))
384 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
387 * Parse the system boot device.
390 SystemBootDevice
= ExAllocatePool(PagedPool
,
391 (strlen(CommandLine
) + 1) * sizeof(WCHAR
));
392 if (SystemBootDevice
== NULL
)
394 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
397 while (*CommandLine
!= 0 && *CommandLine
!= ' ')
398 SystemBootDevice
[Position
++] = *(CommandLine
++);
399 SystemBootDevice
[Position
++] = 0;
402 * Write the system boot device to registry.
404 Status
= RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
405 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control",
409 Position
* sizeof(WCHAR
));
410 if (!NT_SUCCESS(Status
))
412 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
416 * Parse the system start options.
419 SystemStartOptions
= SystemBootDevice
;
420 while ((CommandLine
= strchr(CommandLine
, '/')) != NULL
)
422 /* Skip over the slash */
425 /* Special options */
426 if (!_strnicmp(CommandLine
, "MININT", 6))
428 else if (!_strnicmp(CommandLine
, "DEBUGPORT=PICE", 14))
431 /* Add a space between the options */
433 SystemStartOptions
[Position
++] = L
' ';
435 /* Copy the command */
436 while (*CommandLine
!= 0 && *CommandLine
!= ' ')
437 SystemStartOptions
[Position
++] = *(CommandLine
++);
439 SystemStartOptions
[Position
++] = 0;
442 * Write the system start options to registry.
444 Status
= RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
445 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control",
446 L
"SystemStartOptions",
449 Position
* sizeof(WCHAR
));
450 if (!NT_SUCCESS(Status
))
452 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
456 * Create a CurrentControlSet\Control\MiniNT key that is used
457 * to detect WinPE/MiniNT systems.
461 Status
= RtlCreateRegistryKey(RTL_REGISTRY_CONTROL
, L
"MiniNT");
462 if (!NT_SUCCESS(Status
))
463 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
466 /* Set PICE 'Start' value to 1, if PICE debugging is enabled */
467 Status
= RtlWriteRegistryValue(
468 RTL_REGISTRY_SERVICES
,
474 if (!NT_SUCCESS(Status
))
475 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
477 ExFreePool(SystemBootDevice
);
482 CmiCreateCurrentControlSetLink(VOID
)
484 RTL_QUERY_REGISTRY_TABLE QueryTable
[5];
485 WCHAR TargetNameBuffer
[80];
486 ULONG TargetNameLength
;
487 UNICODE_STRING LinkName
;
488 UNICODE_STRING LinkValue
;
494 OBJECT_ATTRIBUTES ObjectAttributes
;
497 DPRINT("CmiCreateCurrentControlSetLink() called\n");
499 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
501 QueryTable
[0].Name
= L
"Current";
502 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
503 QueryTable
[0].EntryContext
= &CurrentSet
;
505 QueryTable
[1].Name
= L
"Default";
506 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
507 QueryTable
[1].EntryContext
= &DefaultSet
;
509 QueryTable
[2].Name
= L
"Failed";
510 QueryTable
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
511 QueryTable
[2].EntryContext
= &Failed
;
513 QueryTable
[3].Name
= L
"LastKnownGood";
514 QueryTable
[3].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
515 QueryTable
[3].EntryContext
= &LastKnownGood
;
517 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
518 L
"\\Registry\\Machine\\SYSTEM\\Select",
522 if (!NT_SUCCESS(Status
))
527 DPRINT("Current %ld Default %ld\n", CurrentSet
, DefaultSet
);
529 swprintf(TargetNameBuffer
,
530 L
"\\Registry\\Machine\\SYSTEM\\ControlSet%03lu",
532 TargetNameLength
= wcslen(TargetNameBuffer
) * sizeof(WCHAR
);
534 DPRINT("Link target '%S'\n", TargetNameBuffer
);
536 RtlRosInitUnicodeStringFromLiteral(&LinkName
,
537 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
538 InitializeObjectAttributes(&ObjectAttributes
,
540 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
543 Status
= ZwCreateKey(&KeyHandle
,
544 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
548 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
550 if (!NT_SUCCESS(Status
))
552 DPRINT1("ZwCreateKey() failed (Status %lx)\n", Status
);
556 RtlRosInitUnicodeStringFromLiteral(&LinkValue
,
557 L
"SymbolicLinkValue");
558 Status
= ZwSetValueKey(KeyHandle
,
562 (PVOID
)TargetNameBuffer
,
564 if (!NT_SUCCESS(Status
))
566 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
576 CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
577 IN PREGISTRY_HIVE RegistryHive
)
579 UNICODE_STRING RemainingPath
;
580 PKEY_OBJECT ParentKey
;
585 DPRINT("CmiConnectHive(%p, %p) called.\n",
586 KeyObjectAttributes
, RegistryHive
);
588 Status
= ObFindObject(KeyObjectAttributes
,
592 if (!NT_SUCCESS(Status
))
597 DPRINT ("RemainingPath %wZ\n", &RemainingPath
);
599 if ((RemainingPath
.Buffer
== NULL
) || (RemainingPath
.Buffer
[0] == 0))
601 ObDereferenceObject (ParentKey
);
602 RtlFreeUnicodeString(&RemainingPath
);
603 return STATUS_OBJECT_NAME_COLLISION
;
606 /* Ignore leading backslash */
607 SubName
= RemainingPath
.Buffer
;
608 if (*SubName
== L
'\\')
611 /* If RemainingPath contains \ we must return error
612 because CmiConnectHive() can not create trees */
613 if (wcschr (SubName
, L
'\\') != NULL
)
615 ObDereferenceObject (ParentKey
);
616 RtlFreeUnicodeString(&RemainingPath
);
617 return STATUS_OBJECT_NAME_NOT_FOUND
;
620 DPRINT("RemainingPath %wZ ParentKey %p\n",
621 &RemainingPath
, ParentKey
);
623 Status
= ObCreateObject(KernelMode
,
632 if (!NT_SUCCESS(Status
))
634 DPRINT1 ("ObCreateObject() failed (Status %lx)\n", Status
);
635 ObDereferenceObject (ParentKey
);
636 RtlFreeUnicodeString(&RemainingPath
);
640 NewKey
->RegistryHive
= RegistryHive
;
641 NewKey
->KeyCellOffset
= RegistryHive
->HiveHeader
->RootKeyOffset
;
642 NewKey
->KeyCell
= CmiGetCell (RegistryHive
, NewKey
->KeyCellOffset
, NULL
);
644 NewKey
->NumberOfSubKeys
= 0;
645 if (NewKey
->KeyCell
->NumberOfSubKeys
!= 0)
647 NewKey
->SubKeys
= ExAllocatePool(NonPagedPool
,
648 NewKey
->KeyCell
->NumberOfSubKeys
* sizeof(ULONG
));
649 if (NewKey
->SubKeys
== NULL
)
651 DPRINT("ExAllocatePool() failed\n");
652 ObDereferenceObject (NewKey
);
653 ObDereferenceObject (ParentKey
);
654 RtlFreeUnicodeString(&RemainingPath
);
655 return STATUS_INSUFFICIENT_RESOURCES
;
660 NewKey
->SubKeys
= NULL
;
663 DPRINT ("SubName %S\n", SubName
);
665 Status
= RtlCreateUnicodeString(&NewKey
->Name
,
667 RtlFreeUnicodeString(&RemainingPath
);
668 if (!NT_SUCCESS(Status
))
670 DPRINT1("RtlCreateUnicodeString() failed (Status %lx)\n", Status
);
671 if (NewKey
->SubKeys
!= NULL
)
673 ExFreePool (NewKey
->SubKeys
);
675 ObDereferenceObject (NewKey
);
676 ObDereferenceObject (ParentKey
);
677 return STATUS_INSUFFICIENT_RESOURCES
;
680 CmiAddKeyToList (ParentKey
, NewKey
);
681 ObDereferenceObject (ParentKey
);
683 VERIFY_KEY_OBJECT(NewKey
);
685 /* Note: Do not dereference NewKey here! */
687 return STATUS_SUCCESS
;
692 CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
693 OUT PREGISTRY_HIVE
*RegistryHive
)
695 PKEY_OBJECT KeyObject
;
700 DPRINT("CmiDisconnectHive() called\n");
702 *RegistryHive
= NULL
;
704 Status
= ObOpenObjectByName (KeyObjectAttributes
,
708 STANDARD_RIGHTS_REQUIRED
,
711 if (!NT_SUCCESS(Status
))
713 DPRINT1 ("ObOpenObjectByName() failed (Status %lx)\n", Status
);
717 Status
= ObReferenceObjectByHandle (KeyHandle
,
718 STANDARD_RIGHTS_REQUIRED
,
724 if (!NT_SUCCESS(Status
))
726 DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status
);
729 DPRINT ("KeyObject %p Hive %p\n", KeyObject
, KeyObject
->RegistryHive
);
731 if (!(KeyObject
->KeyCell
->Flags
& REG_KEY_ROOT_CELL
))
733 DPRINT1 ("Key is not the Hive-Root-Key\n");
734 ObDereferenceObject (KeyObject
);
735 return STATUS_INVALID_PARAMETER
;
738 if (ObGetObjectHandleCount (KeyObject
) != 0 ||
739 ObGetObjectPointerCount (KeyObject
) != 2)
741 DPRINT1 ("Hive is still in use\n");
742 ObDereferenceObject (KeyObject
);
743 return STATUS_UNSUCCESSFUL
;
746 Hive
= KeyObject
->RegistryHive
;
748 /* Dereference KeyObject twice to delete it */
749 ObDereferenceObject (KeyObject
);
750 ObDereferenceObject (KeyObject
);
752 *RegistryHive
= Hive
;
754 DPRINT ("CmiDisconnectHive() done\n");
756 return STATUS_SUCCESS
;
761 CmiInitControlSetLink (VOID
)
763 OBJECT_ATTRIBUTES ObjectAttributes
;
764 UNICODE_STRING ControlSetKeyName
;
765 UNICODE_STRING ControlSetLinkName
;
766 UNICODE_STRING ControlSetValueName
;
770 /* Create 'ControlSet001' key */
771 RtlRosInitUnicodeStringFromLiteral (&ControlSetKeyName
,
772 L
"\\Registry\\Machine\\SYSTEM\\ControlSet001");
773 InitializeObjectAttributes (&ObjectAttributes
,
775 OBJ_CASE_INSENSITIVE
,
778 Status
= ZwCreateKey (&KeyHandle
,
783 REG_OPTION_NON_VOLATILE
,
785 if (!NT_SUCCESS(Status
))
787 DPRINT1 ("ZwCreateKey() failed (Status %lx)\n", Status
);
792 /* Link 'CurrentControlSet' to 'ControlSet001' key */
793 RtlRosInitUnicodeStringFromLiteral (&ControlSetLinkName
,
794 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
795 InitializeObjectAttributes (&ObjectAttributes
,
797 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
800 Status
= ZwCreateKey (&KeyHandle
,
801 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
805 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
807 if (!NT_SUCCESS(Status
))
809 DPRINT1 ("ZwCreateKey() failed (Status %lx)\n", Status
);
813 RtlRosInitUnicodeStringFromLiteral (&ControlSetValueName
,
814 L
"SymbolicLinkValue");
815 Status
= ZwSetValueKey (KeyHandle
,
816 &ControlSetValueName
,
819 (PVOID
)ControlSetKeyName
.Buffer
,
820 ControlSetKeyName
.Length
);
821 if (!NT_SUCCESS(Status
))
823 DPRINT1 ("ZwSetValueKey() failed (Status %lx)\n", Status
);
827 return STATUS_SUCCESS
;
832 CmiInitHives(BOOLEAN SetupBoot
)
834 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
835 OBJECT_ATTRIBUTES ObjectAttributes
;
836 UNICODE_STRING FileName
;
837 UNICODE_STRING KeyName
;
838 UNICODE_STRING ValueName
;
843 WCHAR ConfigPath
[MAX_PATH
];
850 DPRINT("CmiInitHives() called\n");
852 if (SetupBoot
== TRUE
)
854 RtlRosInitUnicodeStringFromLiteral(&KeyName
,
855 L
"\\Registry\\Machine\\HARDWARE");
856 InitializeObjectAttributes(&ObjectAttributes
,
858 OBJ_CASE_INSENSITIVE
,
861 Status
= ZwOpenKey(&KeyHandle
,
864 if (!NT_SUCCESS(Status
))
866 DPRINT1("ZwOpenKey() failed (Status %lx)\n", Status
);
870 RtlRosInitUnicodeStringFromLiteral(&ValueName
,
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
);
913 /* FIXME: Save boot log */
915 /* Connect the SYSTEM hive only if it has been created */
916 if (SetupBoot
== TRUE
)
918 wcscpy(EndPtr
, REG_SYSTEM_FILE_NAME
);
919 DPRINT ("ConfigPath: %S\n", ConfigPath
);
921 RtlInitUnicodeString (&KeyName
,
922 REG_SYSTEM_KEY_NAME
);
923 InitializeObjectAttributes(&ObjectAttributes
,
925 OBJ_CASE_INSENSITIVE
,
929 RtlInitUnicodeString (&FileName
,
931 Status
= CmiLoadHive (&ObjectAttributes
,
934 if (!NT_SUCCESS(Status
))
936 DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status
);
940 Status
= CmiInitControlSetLink ();
941 if (!NT_SUCCESS(Status
))
943 DPRINT1("CmiInitControlSetLink() failed (Status %lx)\n", Status
);
948 /* Connect the SOFTWARE hive */
949 wcscpy(EndPtr
, REG_SOFTWARE_FILE_NAME
);
950 RtlInitUnicodeString (&FileName
,
952 DPRINT ("ConfigPath: %S\n", ConfigPath
);
954 RtlInitUnicodeString (&KeyName
,
955 REG_SOFTWARE_KEY_NAME
);
956 InitializeObjectAttributes(&ObjectAttributes
,
958 OBJ_CASE_INSENSITIVE
,
962 Status
= CmiLoadHive (&ObjectAttributes
,
965 if (!NT_SUCCESS(Status
))
967 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
971 /* Connect the SAM hive */
972 wcscpy(EndPtr
, REG_SAM_FILE_NAME
);
973 RtlInitUnicodeString (&FileName
,
975 DPRINT ("ConfigPath: %S\n", ConfigPath
);
977 RtlInitUnicodeString (&KeyName
,
979 InitializeObjectAttributes(&ObjectAttributes
,
981 OBJ_CASE_INSENSITIVE
,
984 Status
= CmiLoadHive (&ObjectAttributes
,
987 if (!NT_SUCCESS(Status
))
989 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
993 /* Connect the SECURITY hive */
994 wcscpy(EndPtr
, REG_SEC_FILE_NAME
);
995 RtlInitUnicodeString (&FileName
,
997 DPRINT ("ConfigPath: %S\n", ConfigPath
);
999 RtlInitUnicodeString (&KeyName
,
1001 InitializeObjectAttributes(&ObjectAttributes
,
1003 OBJ_CASE_INSENSITIVE
,
1006 Status
= CmiLoadHive (&ObjectAttributes
,
1009 if (!NT_SUCCESS(Status
))
1011 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
1015 /* Connect the DEFAULT hive */
1016 wcscpy(EndPtr
, REG_DEFAULT_USER_FILE_NAME
);
1017 RtlInitUnicodeString (&FileName
,
1019 DPRINT ("ConfigPath: %S\n", ConfigPath
);
1021 RtlInitUnicodeString (&KeyName
,
1022 REG_DEFAULT_USER_KEY_NAME
);
1023 InitializeObjectAttributes(&ObjectAttributes
,
1025 OBJ_CASE_INSENSITIVE
,
1028 Status
= CmiLoadHive (&ObjectAttributes
,
1031 if (!NT_SUCCESS(Status
))
1033 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
1037 // CmiCheckRegistry(TRUE);
1039 /* Start automatic hive synchronization */
1040 KeInitializeDpc(&CmiHiveSyncDpc
,
1041 CmiHiveSyncDpcRoutine
,
1043 KeInitializeTimer(&CmiHiveSyncTimer
);
1044 CmiHiveSyncEnabled
= TRUE
;
1046 DPRINT("CmiInitHives() done\n");
1048 return(STATUS_SUCCESS
);
1053 CmShutdownRegistry(VOID
)
1055 PREGISTRY_HIVE Hive
;
1058 DPRINT("CmShutdownRegistry() called\n");
1060 /* Stop automatic hive synchronization */
1061 CmiHiveSyncEnabled
= FALSE
;
1063 /* Cancel pending hive synchronization */
1064 if (CmiHiveSyncPending
== TRUE
)
1066 KeCancelTimer(&CmiHiveSyncTimer
);
1067 CmiHiveSyncPending
= FALSE
;
1070 /* Acquire hive list lock exclusively */
1071 KeEnterCriticalRegion();
1072 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
1074 Entry
= CmiHiveListHead
.Flink
;
1075 while (Entry
!= &CmiHiveListHead
)
1077 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
1079 if (!(IsNoFileHive(Hive
) || IsNoSynchHive(Hive
)))
1081 /* Flush non-volatile hive */
1082 CmiFlushRegistryHive(Hive
);
1085 Entry
= Entry
->Flink
;
1088 /* Release hive list lock */
1089 ExReleaseResourceLite(&CmiRegistryLock
);
1090 KeLeaveCriticalRegion();
1092 DPRINT("CmShutdownRegistry() done\n");
1097 CmiHiveSyncRoutine(PVOID DeferredContext
)
1099 PREGISTRY_HIVE Hive
;
1102 DPRINT("CmiHiveSyncRoutine() called\n");
1104 CmiHiveSyncPending
= FALSE
;
1106 /* Acquire hive list lock exclusively */
1107 KeEnterCriticalRegion();
1108 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
1110 Entry
= CmiHiveListHead
.Flink
;
1111 while (Entry
!= &CmiHiveListHead
)
1113 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
1115 if (!(IsNoFileHive(Hive
) || IsNoSynchHive(Hive
)))
1117 /* Flush non-volatile hive */
1118 CmiFlushRegistryHive(Hive
);
1121 Entry
= Entry
->Flink
;
1124 /* Release hive list lock */
1125 ExReleaseResourceLite(&CmiRegistryLock
);
1126 KeLeaveCriticalRegion();
1128 DPRINT("DeferredContext %x\n", DeferredContext
);
1129 ExFreePool(DeferredContext
);
1131 DPRINT("CmiHiveSyncRoutine() done\n");
1136 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
1137 PVOID DeferredContext
,
1138 PVOID SystemArgument1
,
1139 PVOID SystemArgument2
)
1141 PWORK_QUEUE_ITEM WorkQueueItem
;
1143 WorkQueueItem
= ExAllocatePool(NonPagedPool
,
1144 sizeof(WORK_QUEUE_ITEM
));
1145 if (WorkQueueItem
== NULL
)
1147 DbgPrint("Failed to allocate work item\n");
1151 ExInitializeWorkItem(WorkQueueItem
,
1155 DPRINT("DeferredContext %x\n", WorkQueueItem
);
1156 ExQueueWorkItem(WorkQueueItem
,
1164 LARGE_INTEGER Timeout
;
1166 DPRINT("CmiSyncHives() called\n");
1168 if (CmiHiveSyncEnabled
== FALSE
||
1169 CmiHiveSyncPending
== TRUE
)
1172 CmiHiveSyncPending
= TRUE
;
1174 Timeout
.QuadPart
= (LONGLONG
)-50000000;
1175 KeSetTimer(&CmiHiveSyncTimer
,