3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/cm/registry.c
6 * PURPOSE: Registry functions
7 * PROGRAMMERS: Rex Jolliff
16 #include <internal/debug.h>
20 /* GLOBALS ******************************************************************/
22 POBJECT_TYPE CmiKeyType
= NULL
;
23 PREGISTRY_HIVE CmiVolatileHive
= NULL
;
24 KSPIN_LOCK CmiKeyListLock
;
26 LIST_ENTRY CmiHiveListHead
;
28 ERESOURCE CmiRegistryLock
;
30 volatile BOOLEAN CmiHiveSyncEnabled
= FALSE
;
31 volatile BOOLEAN CmiHiveSyncPending
= FALSE
;
33 KTIMER CmiHiveSyncTimer
;
35 static GENERIC_MAPPING CmiKeyMapping
=
36 {KEY_READ
, KEY_WRITE
, KEY_EXECUTE
, KEY_ALL_ACCESS
};
41 CmiCheckKey(BOOLEAN Verbose
,
45 CmiCreateCurrentControlSetLink(VOID
);
48 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
49 PVOID DeferredContext
,
50 PVOID SystemArgument1
,
51 PVOID SystemArgument2
);
53 /* FUNCTIONS ****************************************************************/
56 CmiCheckSubKeys(BOOLEAN Verbose
,
59 OBJECT_ATTRIBUTES ObjectAttributes
;
60 PKEY_NODE_INFORMATION KeyInfo
;
61 WCHAR KeyBuffer
[MAX_PATH
];
62 UNICODE_STRING KeyPath
;
73 BufferSize
= sizeof(KEY_NODE_INFORMATION
) + 4096;
74 KeyInfo
= ExAllocatePool(PagedPool
, BufferSize
);
76 Status
= ZwEnumerateKey(Key
,
82 if (!NT_SUCCESS(Status
))
85 if (Status
== STATUS_NO_MORE_ENTRIES
)
86 Status
= STATUS_SUCCESS
;
92 KeyInfo
->NameLength
/ sizeof(WCHAR
));
96 DbgPrint("Key: %S\n", Name
);
99 /* FIXME: Check info. */
103 wcscpy(KeyBuffer
, L
"\\Registry\\");
104 wcscat(KeyBuffer
, Name
);
106 RtlInitUnicodeString(&KeyPath
, KeyBuffer
);
108 InitializeObjectAttributes(&ObjectAttributes
,
110 OBJ_CASE_INSENSITIVE
,
114 Status
= ZwOpenKey(&SubKey
,
118 ASSERT(NT_SUCCESS(Status
));
120 CmiCheckKey(Verbose
, SubKey
);
127 ASSERT(NT_SUCCESS(Status
));
132 CmiCheckValues(BOOLEAN Verbose
,
135 PKEY_NODE_INFORMATION ValueInfo
;
136 WCHAR Name
[MAX_PATH
];
145 BufferSize
= sizeof(KEY_NODE_INFORMATION
) + 4096;
146 ValueInfo
= ExAllocatePool(PagedPool
, BufferSize
);
148 Status
= ZwEnumerateValueKey(Key
,
154 if (!NT_SUCCESS(Status
))
156 ExFreePool(ValueInfo
);
157 if (Status
== STATUS_NO_MORE_ENTRIES
)
158 Status
= STATUS_SUCCESS
;
164 ValueInfo
->NameLength
/ sizeof(WCHAR
));
168 DbgPrint("Value: %S\n", Name
);
171 /* FIXME: Check info. */
173 ExFreePool(ValueInfo
);
178 ASSERT(NT_SUCCESS(Status
));
183 CmiCheckKey(BOOLEAN Verbose
,
186 CmiCheckValues(Verbose
, Key
);
187 CmiCheckSubKeys(Verbose
, Key
);
192 CmiCheckByName(BOOLEAN Verbose
,
195 OBJECT_ATTRIBUTES ObjectAttributes
;
196 WCHAR KeyPathBuffer
[MAX_PATH
];
197 UNICODE_STRING KeyPath
;
201 wcscpy(KeyPathBuffer
, L
"\\Registry\\");
202 wcscat(KeyPathBuffer
, KeyName
);
204 RtlInitUnicodeString(&KeyPath
, KeyPathBuffer
);
206 InitializeObjectAttributes(&ObjectAttributes
,
208 OBJ_CASE_INSENSITIVE
,
212 Status
= ZwOpenKey(&Key
,
218 if (!NT_SUCCESS(Status
))
220 DbgPrint("KeyPath %wZ Status: %.08x", KeyPath
, Status
);
221 DbgPrint("KeyPath %S Status: %.08x", KeyPath
.Buffer
, Status
);
222 ASSERT(NT_SUCCESS(Status
));
226 CmiCheckKey(Verbose
, Key
);
233 CmiCheckRegistry(BOOLEAN Verbose
)
236 DbgPrint("Checking registry internals\n");
238 CmiCheckByName(Verbose
, L
"Machine");
239 CmiCheckByName(Verbose
, L
"User");
244 CmInitializeRegistry(VOID
)
246 OBJECT_ATTRIBUTES ObjectAttributes
;
247 UNICODE_STRING KeyName
;
250 PSECURITY_CELL RootSecurityCell
;
252 HANDLE RootKeyHandle
;
256 /* Initialize the Key object type */
257 CmiKeyType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
259 CmiKeyType
->Tag
= TAG('R', 'e', 'g', 'K');
260 CmiKeyType
->TotalObjects
= 0;
261 CmiKeyType
->TotalHandles
= 0;
262 CmiKeyType
->PeakObjects
= 0;
263 CmiKeyType
->PeakHandles
= 0;
264 CmiKeyType
->PagedPoolCharge
= 0;
265 CmiKeyType
->NonpagedPoolCharge
= sizeof(KEY_OBJECT
);
266 CmiKeyType
->Mapping
= &CmiKeyMapping
;
267 CmiKeyType
->Dump
= NULL
;
268 CmiKeyType
->Open
= NULL
;
269 CmiKeyType
->Close
= NULL
;
270 CmiKeyType
->Delete
= CmiObjectDelete
;
271 CmiKeyType
->Parse
= CmiObjectParse
;
272 CmiKeyType
->Security
= CmiObjectSecurity
;
273 CmiKeyType
->QueryName
= CmiObjectQueryName
;
274 CmiKeyType
->OkayToClose
= NULL
;
275 CmiKeyType
->Create
= CmiObjectCreate
;
276 CmiKeyType
->DuplicationNotify
= NULL
;
277 RtlInitUnicodeString(&CmiKeyType
->TypeName
, L
"Key");
279 ObpCreateTypeObject (CmiKeyType
);
281 /* Initialize the hive list */
282 InitializeListHead(&CmiHiveListHead
);
284 /* Initialize registry lock */
285 ExInitializeResourceLite(&CmiRegistryLock
);
287 /* Build volatile registry store */
288 Status
= CmiCreateVolatileHive (&CmiVolatileHive
);
289 ASSERT(NT_SUCCESS(Status
));
291 /* Create '\Registry' key. */
292 RtlInitUnicodeString(&KeyName
, REG_ROOT_KEY_NAME
);
293 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, 0, NULL
, NULL
);
294 Status
= ObCreateObject(KernelMode
,
303 ASSERT(NT_SUCCESS(Status
));
304 Status
= ObInsertObject(RootKey
,
306 STANDARD_RIGHTS_REQUIRED
,
310 ASSERT(NT_SUCCESS(Status
));
311 RootKey
->RegistryHive
= CmiVolatileHive
;
312 RootKey
->KeyCellOffset
= CmiVolatileHive
->HiveHeader
->RootKeyOffset
;
313 RootKey
->KeyCell
= CmiGetCell (CmiVolatileHive
, RootKey
->KeyCellOffset
, NULL
);
314 RootKey
->ParentKey
= RootKey
;
316 RootKey
->NumberOfSubKeys
= 0;
317 RootKey
->SubKeys
= NULL
;
318 RootKey
->SizeOfSubKeys
= 0;
319 Status
= RtlCreateUnicodeString(&RootKey
->Name
, L
"Registry");
320 ASSERT(NT_SUCCESS(Status
));
323 Status
= CmiAllocateCell(CmiVolatileHive
,
324 0x10, //LONG CellSize,
325 (PVOID
*)&RootSecurityCell
,
326 &RootKey
->KeyCell
->SecurityKeyOffset
);
327 ASSERT(NT_SUCCESS(Status
));
329 /* Copy the security descriptor */
331 CmiVolatileHive
->RootSecurityCell
= RootSecurityCell
;
334 KeInitializeSpinLock(&CmiKeyListLock
);
336 /* Create '\Registry\Machine' key. */
337 RtlInitUnicodeString(&KeyName
,
339 InitializeObjectAttributes(&ObjectAttributes
,
344 Status
= ZwCreateKey(&KeyHandle
,
345 STANDARD_RIGHTS_REQUIRED
,
351 ASSERT(NT_SUCCESS(Status
));
353 /* Create '\Registry\User' key. */
354 RtlInitUnicodeString(&KeyName
,
356 InitializeObjectAttributes(&ObjectAttributes
,
361 Status
= ZwCreateKey(&KeyHandle
,
362 STANDARD_RIGHTS_REQUIRED
,
368 ASSERT(NT_SUCCESS(Status
));
373 CmInit2(PCHAR CommandLine
)
376 BOOLEAN MiniNT
= FALSE
;
377 PWCHAR SystemBootDevice
;
378 PWCHAR SystemStartOptions
;
382 /* Create the 'CurrentControlSet' link. */
383 Status
= CmiCreateCurrentControlSetLink();
384 if (!NT_SUCCESS(Status
))
385 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
388 * Parse the system boot device.
391 SystemBootDevice
= ExAllocatePool(PagedPool
,
392 (strlen(CommandLine
) + 1) * sizeof(WCHAR
));
393 if (SystemBootDevice
== NULL
)
395 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
398 while (*CommandLine
!= 0 && *CommandLine
!= ' ')
399 SystemBootDevice
[Position
++] = *(CommandLine
++);
400 SystemBootDevice
[Position
++] = 0;
403 * Write the system boot device to registry.
405 Status
= RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
406 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control",
410 Position
* sizeof(WCHAR
));
411 if (!NT_SUCCESS(Status
))
413 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
417 * Parse the system start options.
420 SystemStartOptions
= SystemBootDevice
;
421 while ((CommandLine
= strchr(CommandLine
, '/')) != NULL
)
423 /* Skip over the slash */
426 /* Special options */
427 if (!_strnicmp(CommandLine
, "MININT", 6))
429 else if (!_strnicmp(CommandLine
, "DEBUGPORT=PICE", 14))
432 /* Add a space between the options */
434 SystemStartOptions
[Position
++] = L
' ';
436 /* Copy the command */
437 while (*CommandLine
!= 0 && *CommandLine
!= ' ')
438 SystemStartOptions
[Position
++] = *(CommandLine
++);
440 SystemStartOptions
[Position
++] = 0;
443 * Write the system start options to registry.
445 Status
= RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
446 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control",
447 L
"SystemStartOptions",
450 Position
* sizeof(WCHAR
));
451 if (!NT_SUCCESS(Status
))
453 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
457 * Create a CurrentControlSet\Control\MiniNT key that is used
458 * to detect WinPE/MiniNT systems.
462 Status
= RtlCreateRegistryKey(RTL_REGISTRY_CONTROL
, L
"MiniNT");
463 if (!NT_SUCCESS(Status
))
464 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
467 /* Set PICE 'Start' value to 1, if PICE debugging is enabled */
468 Status
= RtlWriteRegistryValue(
469 RTL_REGISTRY_SERVICES
,
475 if (!NT_SUCCESS(Status
))
476 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
478 ExFreePool(SystemBootDevice
);
483 CmiCreateCurrentControlSetLink(VOID
)
485 RTL_QUERY_REGISTRY_TABLE QueryTable
[5];
486 WCHAR TargetNameBuffer
[80];
487 ULONG TargetNameLength
;
488 UNICODE_STRING LinkName
;
489 UNICODE_STRING LinkValue
;
495 OBJECT_ATTRIBUTES ObjectAttributes
;
498 DPRINT("CmiCreateCurrentControlSetLink() called\n");
500 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
502 QueryTable
[0].Name
= L
"Current";
503 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
504 QueryTable
[0].EntryContext
= &CurrentSet
;
506 QueryTable
[1].Name
= L
"Default";
507 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
508 QueryTable
[1].EntryContext
= &DefaultSet
;
510 QueryTable
[2].Name
= L
"Failed";
511 QueryTable
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
512 QueryTable
[2].EntryContext
= &Failed
;
514 QueryTable
[3].Name
= L
"LastKnownGood";
515 QueryTable
[3].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
516 QueryTable
[3].EntryContext
= &LastKnownGood
;
518 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
519 L
"\\Registry\\Machine\\SYSTEM\\Select",
523 if (!NT_SUCCESS(Status
))
528 DPRINT("Current %ld Default %ld\n", CurrentSet
, DefaultSet
);
530 swprintf(TargetNameBuffer
,
531 L
"\\Registry\\Machine\\SYSTEM\\ControlSet%03lu",
533 TargetNameLength
= wcslen(TargetNameBuffer
) * sizeof(WCHAR
);
535 DPRINT("Link target '%S'\n", TargetNameBuffer
);
537 RtlRosInitUnicodeStringFromLiteral(&LinkName
,
538 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
539 InitializeObjectAttributes(&ObjectAttributes
,
541 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
544 Status
= ZwCreateKey(&KeyHandle
,
545 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
549 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
551 if (!NT_SUCCESS(Status
))
553 DPRINT1("ZwCreateKey() failed (Status %lx)\n", Status
);
557 RtlRosInitUnicodeStringFromLiteral(&LinkValue
,
558 L
"SymbolicLinkValue");
559 Status
= ZwSetValueKey(KeyHandle
,
563 (PVOID
)TargetNameBuffer
,
565 if (!NT_SUCCESS(Status
))
567 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
577 CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
578 IN PREGISTRY_HIVE RegistryHive
)
580 UNICODE_STRING RemainingPath
;
581 PKEY_OBJECT ParentKey
;
586 DPRINT("CmiConnectHive(%p, %p) called.\n",
587 KeyObjectAttributes
, RegistryHive
);
589 Status
= ObFindObject(KeyObjectAttributes
,
593 if (!NT_SUCCESS(Status
))
598 DPRINT ("RemainingPath %wZ\n", &RemainingPath
);
600 if ((RemainingPath
.Buffer
== NULL
) || (RemainingPath
.Buffer
[0] == 0))
602 ObDereferenceObject (ParentKey
);
603 RtlFreeUnicodeString(&RemainingPath
);
604 return STATUS_OBJECT_NAME_COLLISION
;
607 /* Ignore leading backslash */
608 SubName
= RemainingPath
.Buffer
;
609 if (*SubName
== L
'\\')
612 /* If RemainingPath contains \ we must return error
613 because CmiConnectHive() can not create trees */
614 if (wcschr (SubName
, L
'\\') != NULL
)
616 ObDereferenceObject (ParentKey
);
617 RtlFreeUnicodeString(&RemainingPath
);
618 return STATUS_OBJECT_NAME_NOT_FOUND
;
621 DPRINT("RemainingPath %wZ ParentKey %p\n",
622 &RemainingPath
, ParentKey
);
624 Status
= ObCreateObject(KernelMode
,
633 if (!NT_SUCCESS(Status
))
635 DPRINT1 ("ObCreateObject() failed (Status %lx)\n", Status
);
636 ObDereferenceObject (ParentKey
);
637 RtlFreeUnicodeString(&RemainingPath
);
641 NewKey
->RegistryHive
= RegistryHive
;
642 NewKey
->KeyCellOffset
= RegistryHive
->HiveHeader
->RootKeyOffset
;
643 NewKey
->KeyCell
= CmiGetCell (RegistryHive
, NewKey
->KeyCellOffset
, NULL
);
645 NewKey
->NumberOfSubKeys
= 0;
646 if (NewKey
->KeyCell
->NumberOfSubKeys
!= 0)
648 NewKey
->SubKeys
= ExAllocatePool(NonPagedPool
,
649 NewKey
->KeyCell
->NumberOfSubKeys
* sizeof(ULONG
));
650 if (NewKey
->SubKeys
== NULL
)
652 DPRINT("ExAllocatePool() failed\n");
653 ObDereferenceObject (NewKey
);
654 ObDereferenceObject (ParentKey
);
655 RtlFreeUnicodeString(&RemainingPath
);
656 return STATUS_INSUFFICIENT_RESOURCES
;
661 NewKey
->SubKeys
= NULL
;
664 DPRINT ("SubName %S\n", SubName
);
666 Status
= RtlCreateUnicodeString(&NewKey
->Name
,
668 RtlFreeUnicodeString(&RemainingPath
);
669 if (!NT_SUCCESS(Status
))
671 DPRINT1("RtlCreateUnicodeString() failed (Status %lx)\n", Status
);
672 if (NewKey
->SubKeys
!= NULL
)
674 ExFreePool (NewKey
->SubKeys
);
676 ObDereferenceObject (NewKey
);
677 ObDereferenceObject (ParentKey
);
678 return STATUS_INSUFFICIENT_RESOURCES
;
681 CmiAddKeyToList (ParentKey
, NewKey
);
682 ObDereferenceObject (ParentKey
);
684 VERIFY_KEY_OBJECT(NewKey
);
686 /* Note: Do not dereference NewKey here! */
688 return STATUS_SUCCESS
;
693 CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
694 OUT PREGISTRY_HIVE
*RegistryHive
)
696 PKEY_OBJECT KeyObject
;
701 DPRINT("CmiDisconnectHive() called\n");
703 *RegistryHive
= NULL
;
705 Status
= ObOpenObjectByName (KeyObjectAttributes
,
709 STANDARD_RIGHTS_REQUIRED
,
712 if (!NT_SUCCESS(Status
))
714 DPRINT1 ("ObOpenObjectByName() failed (Status %lx)\n", Status
);
718 Status
= ObReferenceObjectByHandle (KeyHandle
,
719 STANDARD_RIGHTS_REQUIRED
,
725 if (!NT_SUCCESS(Status
))
727 DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status
);
730 DPRINT ("KeyObject %p Hive %p\n", KeyObject
, KeyObject
->RegistryHive
);
732 if (!(KeyObject
->KeyCell
->Flags
& REG_KEY_ROOT_CELL
))
734 DPRINT1 ("Key is not the Hive-Root-Key\n");
735 ObDereferenceObject (KeyObject
);
736 return STATUS_INVALID_PARAMETER
;
739 if (ObGetObjectHandleCount (KeyObject
) != 0 ||
740 ObGetObjectPointerCount (KeyObject
) != 2)
742 DPRINT1 ("Hive is still in use\n");
743 ObDereferenceObject (KeyObject
);
744 return STATUS_UNSUCCESSFUL
;
747 Hive
= KeyObject
->RegistryHive
;
749 /* Dereference KeyObject twice to delete it */
750 ObDereferenceObject (KeyObject
);
751 ObDereferenceObject (KeyObject
);
753 *RegistryHive
= Hive
;
755 DPRINT ("CmiDisconnectHive() done\n");
757 return STATUS_SUCCESS
;
762 CmiInitControlSetLink (VOID
)
764 OBJECT_ATTRIBUTES ObjectAttributes
;
765 UNICODE_STRING ControlSetKeyName
;
766 UNICODE_STRING ControlSetLinkName
;
767 UNICODE_STRING ControlSetValueName
;
771 /* Create 'ControlSet001' key */
772 RtlRosInitUnicodeStringFromLiteral (&ControlSetKeyName
,
773 L
"\\Registry\\Machine\\SYSTEM\\ControlSet001");
774 InitializeObjectAttributes (&ObjectAttributes
,
776 OBJ_CASE_INSENSITIVE
,
779 Status
= ZwCreateKey (&KeyHandle
,
784 REG_OPTION_NON_VOLATILE
,
786 if (!NT_SUCCESS(Status
))
788 DPRINT1 ("ZwCreateKey() failed (Status %lx)\n", Status
);
793 /* Link 'CurrentControlSet' to 'ControlSet001' key */
794 RtlRosInitUnicodeStringFromLiteral (&ControlSetLinkName
,
795 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
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 RtlRosInitUnicodeStringFromLiteral (&ControlSetValueName
,
815 L
"SymbolicLinkValue");
816 Status
= ZwSetValueKey (KeyHandle
,
817 &ControlSetValueName
,
820 (PVOID
)ControlSetKeyName
.Buffer
,
821 ControlSetKeyName
.Length
);
822 if (!NT_SUCCESS(Status
))
824 DPRINT1 ("ZwSetValueKey() failed (Status %lx)\n", Status
);
828 return STATUS_SUCCESS
;
833 CmiInitHives(BOOLEAN SetupBoot
)
835 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
836 OBJECT_ATTRIBUTES ObjectAttributes
;
837 UNICODE_STRING FileName
;
838 UNICODE_STRING KeyName
;
839 UNICODE_STRING ValueName
;
844 WCHAR ConfigPath
[MAX_PATH
];
851 DPRINT("CmiInitHives() called\n");
853 if (SetupBoot
== TRUE
)
855 RtlRosInitUnicodeStringFromLiteral(&KeyName
,
856 L
"\\Registry\\Machine\\HARDWARE");
857 InitializeObjectAttributes(&ObjectAttributes
,
859 OBJ_CASE_INSENSITIVE
,
862 Status
= ZwOpenKey(&KeyHandle
,
865 if (!NT_SUCCESS(Status
))
867 DPRINT1("ZwOpenKey() failed (Status %lx)\n", Status
);
871 RtlRosInitUnicodeStringFromLiteral(&ValueName
,
874 BufferSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 4096;
875 ValueInfo
= ExAllocatePool(PagedPool
,
877 if (ValueInfo
== NULL
)
880 return(STATUS_INSUFFICIENT_RESOURCES
);
883 Status
= ZwQueryValueKey(KeyHandle
,
885 KeyValuePartialInformation
,
890 if (!NT_SUCCESS(Status
))
892 ExFreePool(ValueInfo
);
896 RtlCopyMemory(ConfigPath
,
898 ValueInfo
->DataLength
);
899 ConfigPath
[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = (WCHAR
)0;
900 ExFreePool(ValueInfo
);
904 wcscpy(ConfigPath
, L
"\\SystemRoot");
906 wcscat(ConfigPath
, L
"\\system32\\config");
908 DPRINT("ConfigPath: %S\n", ConfigPath
);
910 EndPtr
= ConfigPath
+ wcslen(ConfigPath
);
914 /* FIXME: Save boot log */
916 /* Connect the SYSTEM hive only if it has been created */
917 if (SetupBoot
== TRUE
)
919 wcscpy(EndPtr
, REG_SYSTEM_FILE_NAME
);
920 DPRINT ("ConfigPath: %S\n", ConfigPath
);
922 RtlInitUnicodeString (&KeyName
,
923 REG_SYSTEM_KEY_NAME
);
924 InitializeObjectAttributes(&ObjectAttributes
,
926 OBJ_CASE_INSENSITIVE
,
930 RtlInitUnicodeString (&FileName
,
932 Status
= CmiLoadHive (&ObjectAttributes
,
935 if (!NT_SUCCESS(Status
))
937 DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status
);
941 Status
= CmiInitControlSetLink ();
942 if (!NT_SUCCESS(Status
))
944 DPRINT1("CmiInitControlSetLink() failed (Status %lx)\n", Status
);
949 /* Connect the SOFTWARE hive */
950 wcscpy(EndPtr
, REG_SOFTWARE_FILE_NAME
);
951 RtlInitUnicodeString (&FileName
,
953 DPRINT ("ConfigPath: %S\n", ConfigPath
);
955 RtlInitUnicodeString (&KeyName
,
956 REG_SOFTWARE_KEY_NAME
);
957 InitializeObjectAttributes(&ObjectAttributes
,
959 OBJ_CASE_INSENSITIVE
,
963 Status
= CmiLoadHive (&ObjectAttributes
,
966 if (!NT_SUCCESS(Status
))
968 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
972 /* Connect the SAM hive */
973 wcscpy(EndPtr
, REG_SAM_FILE_NAME
);
974 RtlInitUnicodeString (&FileName
,
976 DPRINT ("ConfigPath: %S\n", ConfigPath
);
978 RtlInitUnicodeString (&KeyName
,
980 InitializeObjectAttributes(&ObjectAttributes
,
982 OBJ_CASE_INSENSITIVE
,
985 Status
= CmiLoadHive (&ObjectAttributes
,
988 if (!NT_SUCCESS(Status
))
990 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
994 /* Connect the SECURITY hive */
995 wcscpy(EndPtr
, REG_SEC_FILE_NAME
);
996 RtlInitUnicodeString (&FileName
,
998 DPRINT ("ConfigPath: %S\n", ConfigPath
);
1000 RtlInitUnicodeString (&KeyName
,
1002 InitializeObjectAttributes(&ObjectAttributes
,
1004 OBJ_CASE_INSENSITIVE
,
1007 Status
= CmiLoadHive (&ObjectAttributes
,
1010 if (!NT_SUCCESS(Status
))
1012 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
1016 /* Connect the DEFAULT hive */
1017 wcscpy(EndPtr
, REG_DEFAULT_USER_FILE_NAME
);
1018 RtlInitUnicodeString (&FileName
,
1020 DPRINT ("ConfigPath: %S\n", ConfigPath
);
1022 RtlInitUnicodeString (&KeyName
,
1023 REG_DEFAULT_USER_KEY_NAME
);
1024 InitializeObjectAttributes(&ObjectAttributes
,
1026 OBJ_CASE_INSENSITIVE
,
1029 Status
= CmiLoadHive (&ObjectAttributes
,
1032 if (!NT_SUCCESS(Status
))
1034 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
1038 // CmiCheckRegistry(TRUE);
1040 /* Start automatic hive synchronization */
1041 KeInitializeDpc(&CmiHiveSyncDpc
,
1042 CmiHiveSyncDpcRoutine
,
1044 KeInitializeTimer(&CmiHiveSyncTimer
);
1045 CmiHiveSyncEnabled
= TRUE
;
1047 DPRINT("CmiInitHives() done\n");
1049 return(STATUS_SUCCESS
);
1054 CmShutdownRegistry(VOID
)
1056 PREGISTRY_HIVE Hive
;
1059 DPRINT("CmShutdownRegistry() called\n");
1061 /* Stop automatic hive synchronization */
1062 CmiHiveSyncEnabled
= FALSE
;
1064 /* Cancel pending hive synchronization */
1065 if (CmiHiveSyncPending
== TRUE
)
1067 KeCancelTimer(&CmiHiveSyncTimer
);
1068 CmiHiveSyncPending
= FALSE
;
1071 /* Acquire hive list lock exclusively */
1072 KeEnterCriticalRegion();
1073 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
1075 Entry
= CmiHiveListHead
.Flink
;
1076 while (Entry
!= &CmiHiveListHead
)
1078 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
1080 if (!(IsNoFileHive(Hive
) || IsNoSynchHive(Hive
)))
1082 /* Flush non-volatile hive */
1083 CmiFlushRegistryHive(Hive
);
1086 Entry
= Entry
->Flink
;
1089 /* Release hive list lock */
1090 ExReleaseResourceLite(&CmiRegistryLock
);
1091 KeLeaveCriticalRegion();
1093 DPRINT("CmShutdownRegistry() done\n");
1098 CmiHiveSyncRoutine(PVOID DeferredContext
)
1100 PREGISTRY_HIVE Hive
;
1103 DPRINT("CmiHiveSyncRoutine() called\n");
1105 CmiHiveSyncPending
= FALSE
;
1107 /* Acquire hive list lock exclusively */
1108 KeEnterCriticalRegion();
1109 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
1111 Entry
= CmiHiveListHead
.Flink
;
1112 while (Entry
!= &CmiHiveListHead
)
1114 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
1116 if (!(IsNoFileHive(Hive
) || IsNoSynchHive(Hive
)))
1118 /* Flush non-volatile hive */
1119 CmiFlushRegistryHive(Hive
);
1122 Entry
= Entry
->Flink
;
1125 /* Release hive list lock */
1126 ExReleaseResourceLite(&CmiRegistryLock
);
1127 KeLeaveCriticalRegion();
1129 DPRINT("DeferredContext %x\n", DeferredContext
);
1130 ExFreePool(DeferredContext
);
1132 DPRINT("CmiHiveSyncRoutine() done\n");
1137 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
1138 PVOID DeferredContext
,
1139 PVOID SystemArgument1
,
1140 PVOID SystemArgument2
)
1142 PWORK_QUEUE_ITEM WorkQueueItem
;
1144 WorkQueueItem
= ExAllocatePool(NonPagedPool
,
1145 sizeof(WORK_QUEUE_ITEM
));
1146 if (WorkQueueItem
== NULL
)
1148 DbgPrint("Failed to allocate work item\n");
1152 ExInitializeWorkItem(WorkQueueItem
,
1156 DPRINT("DeferredContext %x\n", WorkQueueItem
);
1157 ExQueueWorkItem(WorkQueueItem
,
1165 LARGE_INTEGER Timeout
;
1167 DPRINT("CmiSyncHives() called\n");
1169 if (CmiHiveSyncEnabled
== FALSE
||
1170 CmiHiveSyncPending
== TRUE
)
1173 CmiHiveSyncPending
= TRUE
;
1175 Timeout
.QuadPart
= (LONGLONG
)-50000000;
1176 KeSetTimer(&CmiHiveSyncTimer
,