1 /* $Id: registry.c,v 1.126 2004/09/13 11:46:07 ekohl Exp $
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
;
27 ERESOURCE CmiHiveListLock
;
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
= NtEnumerateKey(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
= NtOpenKey(&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
= NtEnumerateValueKey(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
= NtOpenKey(&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
->MaxObjects
= LONG_MAX
;
262 CmiKeyType
->MaxHandles
= LONG_MAX
;
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
);
282 ExInitializeResourceLite(&CmiHiveListLock
);
284 /* Build volatile registry store */
285 Status
= CmiCreateVolatileHive (&CmiVolatileHive
);
286 assert(NT_SUCCESS(Status
));
288 /* Create '\Registry' key. */
289 RtlInitUnicodeString(&KeyName
, REG_ROOT_KEY_NAME
);
290 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, 0, NULL
, NULL
);
291 Status
= ObCreateObject(KernelMode
,
300 assert(NT_SUCCESS(Status
));
301 Status
= ObInsertObject(RootKey
,
303 STANDARD_RIGHTS_REQUIRED
,
307 assert(NT_SUCCESS(Status
));
308 RootKey
->RegistryHive
= CmiVolatileHive
;
309 RootKey
->KeyCellOffset
= CmiVolatileHive
->HiveHeader
->RootKeyOffset
;
310 RootKey
->KeyCell
= CmiGetCell (CmiVolatileHive
, RootKey
->KeyCellOffset
, NULL
);
311 RootKey
->ParentKey
= RootKey
;
313 RootKey
->NumberOfSubKeys
= 0;
314 RootKey
->SubKeys
= NULL
;
315 RootKey
->SizeOfSubKeys
= 0;
316 Status
= RtlCreateUnicodeString(&RootKey
->Name
, L
"Registry");
317 assert(NT_SUCCESS(Status
));
320 Status
= CmiAllocateCell(CmiVolatileHive
,
321 0x10, //LONG CellSize,
322 (PVOID
*)&RootSecurityCell
,
323 &RootKey
->KeyCell
->SecurityKeyOffset
);
324 assert(NT_SUCCESS(Status
));
326 /* Copy the security descriptor */
328 CmiVolatileHive
->RootSecurityCell
= RootSecurityCell
;
331 KeInitializeSpinLock(&CmiKeyListLock
);
333 /* Create '\Registry\Machine' key. */
334 RtlInitUnicodeString(&KeyName
,
336 InitializeObjectAttributes(&ObjectAttributes
,
341 Status
= NtCreateKey(&KeyHandle
,
342 STANDARD_RIGHTS_REQUIRED
,
348 assert(NT_SUCCESS(Status
));
350 /* Create '\Registry\User' key. */
351 RtlInitUnicodeString(&KeyName
,
353 InitializeObjectAttributes(&ObjectAttributes
,
358 Status
= NtCreateKey(&KeyHandle
,
359 STANDARD_RIGHTS_REQUIRED
,
365 assert(NT_SUCCESS(Status
));
370 CmInit2(PCHAR CommandLine
)
373 BOOLEAN MiniNT
= FALSE
;
374 PWCHAR SystemBootDevice
;
375 PWCHAR SystemStartOptions
;
379 /* Create the 'CurrentControlSet' link. */
380 Status
= CmiCreateCurrentControlSetLink();
381 if (!NT_SUCCESS(Status
))
382 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
385 * Parse the system boot device.
388 SystemBootDevice
= ExAllocatePool(PagedPool
,
389 (strlen(CommandLine
) + 1) * sizeof(WCHAR
));
390 if (SystemBootDevice
== NULL
)
392 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
395 while (*CommandLine
!= 0 && *CommandLine
!= ' ')
396 SystemBootDevice
[Position
++] = *(CommandLine
++);
397 SystemBootDevice
[Position
++] = 0;
400 * Write the system boot device to registry.
402 Status
= RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
403 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control",
407 Position
* sizeof(WCHAR
));
408 if (!NT_SUCCESS(Status
))
410 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
414 * Parse the system start options.
417 SystemStartOptions
= SystemBootDevice
;
418 while ((CommandLine
= strchr(CommandLine
, '/')) != NULL
)
420 /* Skip over the slash */
423 /* Special options */
424 if (!_strnicmp(CommandLine
, "MININT", 6))
426 else if (!_strnicmp(CommandLine
, "DEBUGPORT=PICE", 14))
429 /* Add a space between the options */
431 SystemStartOptions
[Position
++] = L
' ';
433 /* Copy the command */
434 while (*CommandLine
!= 0 && *CommandLine
!= ' ')
435 SystemStartOptions
[Position
++] = *(CommandLine
++);
437 SystemStartOptions
[Position
++] = 0;
440 * Write the system start options to registry.
442 Status
= RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
443 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control",
444 L
"SystemStartOptions",
447 Position
* sizeof(WCHAR
));
448 if (!NT_SUCCESS(Status
))
450 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
454 * Create a CurrentControlSet\Control\MiniNT key that is used
455 * to detect WinPE/MiniNT systems.
459 Status
= RtlCreateRegistryKey(RTL_REGISTRY_CONTROL
, L
"MiniNT");
460 if (!NT_SUCCESS(Status
))
461 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
464 /* Set PICE 'Start' value to 1, if PICE debugging is enabled */
465 Status
= RtlWriteRegistryValue(
466 RTL_REGISTRY_SERVICES
,
472 if (!NT_SUCCESS(Status
))
473 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
475 ExFreePool(SystemBootDevice
);
480 CmiCreateCurrentControlSetLink(VOID
)
482 RTL_QUERY_REGISTRY_TABLE QueryTable
[5];
483 WCHAR TargetNameBuffer
[80];
484 ULONG TargetNameLength
;
485 UNICODE_STRING LinkName
;
486 UNICODE_STRING LinkValue
;
492 OBJECT_ATTRIBUTES ObjectAttributes
;
495 DPRINT("CmiCreateCurrentControlSetLink() called\n");
497 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
499 QueryTable
[0].Name
= L
"Current";
500 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
501 QueryTable
[0].EntryContext
= &CurrentSet
;
503 QueryTable
[1].Name
= L
"Default";
504 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
505 QueryTable
[1].EntryContext
= &DefaultSet
;
507 QueryTable
[2].Name
= L
"Failed";
508 QueryTable
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
509 QueryTable
[2].EntryContext
= &Failed
;
511 QueryTable
[3].Name
= L
"LastKnownGood";
512 QueryTable
[3].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
513 QueryTable
[3].EntryContext
= &LastKnownGood
;
515 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
516 L
"\\Registry\\Machine\\SYSTEM\\Select",
520 if (!NT_SUCCESS(Status
))
525 DPRINT("Current %ld Default %ld\n", CurrentSet
, DefaultSet
);
527 swprintf(TargetNameBuffer
,
528 L
"\\Registry\\Machine\\SYSTEM\\ControlSet%03lu",
530 TargetNameLength
= wcslen(TargetNameBuffer
) * sizeof(WCHAR
);
532 DPRINT("Link target '%S'\n", TargetNameBuffer
);
534 RtlRosInitUnicodeStringFromLiteral(&LinkName
,
535 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
536 InitializeObjectAttributes(&ObjectAttributes
,
538 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
541 Status
= NtCreateKey(&KeyHandle
,
542 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
546 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
548 if (!NT_SUCCESS(Status
))
550 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status
);
554 RtlRosInitUnicodeStringFromLiteral(&LinkValue
,
555 L
"SymbolicLinkValue");
556 Status
= NtSetValueKey(KeyHandle
,
560 (PVOID
)TargetNameBuffer
,
562 if (!NT_SUCCESS(Status
))
564 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
574 CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
575 IN PREGISTRY_HIVE RegistryHive
)
577 UNICODE_STRING RemainingPath
;
578 PKEY_OBJECT ParentKey
;
583 DPRINT("CmiConnectHive(%p, %p) called.\n",
584 KeyObjectAttributes
, RegistryHive
);
586 Status
= ObFindObject(KeyObjectAttributes
,
590 if (!NT_SUCCESS(Status
))
595 DPRINT ("RemainingPath %wZ\n", &RemainingPath
);
597 if ((RemainingPath
.Buffer
== NULL
) || (RemainingPath
.Buffer
[0] == 0))
599 ObDereferenceObject (ParentKey
);
600 RtlFreeUnicodeString(&RemainingPath
);
601 return STATUS_OBJECT_NAME_COLLISION
;
604 /* Ignore leading backslash */
605 SubName
= RemainingPath
.Buffer
;
606 if (*SubName
== L
'\\')
609 /* If RemainingPath contains \ we must return error
610 because CmiConnectHive() can not create trees */
611 if (wcschr (SubName
, L
'\\') != NULL
)
613 ObDereferenceObject (ParentKey
);
614 RtlFreeUnicodeString(&RemainingPath
);
615 return STATUS_OBJECT_NAME_NOT_FOUND
;
618 DPRINT("RemainingPath %wZ ParentKey %p\n",
619 &RemainingPath
, ParentKey
);
621 Status
= ObCreateObject(KernelMode
,
630 if (!NT_SUCCESS(Status
))
632 DPRINT1 ("ObCreateObject() failed (Status %lx)\n", Status
);
633 ObDereferenceObject (ParentKey
);
634 RtlFreeUnicodeString(&RemainingPath
);
638 NewKey
->RegistryHive
= RegistryHive
;
639 NewKey
->KeyCellOffset
= RegistryHive
->HiveHeader
->RootKeyOffset
;
640 NewKey
->KeyCell
= CmiGetCell (RegistryHive
, NewKey
->KeyCellOffset
, NULL
);
642 NewKey
->NumberOfSubKeys
= 0;
643 if (NewKey
->KeyCell
->NumberOfSubKeys
!= 0)
645 NewKey
->SubKeys
= ExAllocatePool(PagedPool
,
646 NewKey
->KeyCell
->NumberOfSubKeys
* sizeof(ULONG
));
647 if (NewKey
->SubKeys
== NULL
)
649 DPRINT("ExAllocatePool() failed\n");
650 ObDereferenceObject (NewKey
);
651 ObDereferenceObject (ParentKey
);
652 RtlFreeUnicodeString(&RemainingPath
);
653 return STATUS_INSUFFICIENT_RESOURCES
;
658 NewKey
->SubKeys
= NULL
;
661 DPRINT ("SubName %S\n", SubName
);
663 Status
= RtlCreateUnicodeString(&NewKey
->Name
,
665 RtlFreeUnicodeString(&RemainingPath
);
666 if (!NT_SUCCESS(Status
))
668 DPRINT1("RtlCreateUnicodeString() failed (Status %lx)\n", Status
);
669 if (NewKey
->SubKeys
!= NULL
)
671 ExFreePool (NewKey
->SubKeys
);
673 ObDereferenceObject (NewKey
);
674 ObDereferenceObject (ParentKey
);
675 return STATUS_INSUFFICIENT_RESOURCES
;
678 CmiAddKeyToList (ParentKey
, NewKey
);
679 ObDereferenceObject (ParentKey
);
681 VERIFY_KEY_OBJECT(NewKey
);
683 /* Note: Do not dereference NewKey here! */
685 return STATUS_SUCCESS
;
690 CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
691 OUT PREGISTRY_HIVE
*RegistryHive
)
693 PKEY_OBJECT KeyObject
;
698 DPRINT("CmiDisconnectHive() called\n");
700 *RegistryHive
= NULL
;
702 Status
= ObOpenObjectByName (KeyObjectAttributes
,
706 STANDARD_RIGHTS_REQUIRED
,
709 if (!NT_SUCCESS(Status
))
711 DPRINT1 ("ObOpenObjectByName() failed (Status %lx)\n", Status
);
715 Status
= ObReferenceObjectByHandle (KeyHandle
,
716 STANDARD_RIGHTS_REQUIRED
,
722 if (!NT_SUCCESS(Status
))
724 DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status
);
727 DPRINT ("KeyObject %p Hive %p\n", KeyObject
, KeyObject
->RegistryHive
);
729 if (!(KeyObject
->KeyCell
->Flags
& REG_KEY_ROOT_CELL
))
731 DPRINT1 ("Key is not the Hive-Root-Key\n");
732 ObDereferenceObject (KeyObject
);
733 return STATUS_INVALID_PARAMETER
;
736 if (ObGetObjectHandleCount (KeyObject
) != 0 ||
737 ObGetObjectPointerCount (KeyObject
) != 2)
739 DPRINT1 ("Hive is still in use\n");
740 ObDereferenceObject (KeyObject
);
741 return STATUS_UNSUCCESSFUL
;
744 Hive
= KeyObject
->RegistryHive
;
746 /* Dereference KeyObject twice to delete it */
747 ObDereferenceObject (KeyObject
);
748 ObDereferenceObject (KeyObject
);
750 *RegistryHive
= Hive
;
752 DPRINT ("CmiDisconnectHive() done\n");
754 return STATUS_SUCCESS
;
759 CmiInitControlSetLink (VOID
)
761 OBJECT_ATTRIBUTES ObjectAttributes
;
762 UNICODE_STRING ControlSetKeyName
;
763 UNICODE_STRING ControlSetLinkName
;
764 UNICODE_STRING ControlSetValueName
;
768 /* Create 'ControlSet001' key */
769 RtlRosInitUnicodeStringFromLiteral (&ControlSetKeyName
,
770 L
"\\Registry\\Machine\\SYSTEM\\ControlSet001");
771 InitializeObjectAttributes (&ObjectAttributes
,
773 OBJ_CASE_INSENSITIVE
,
776 Status
= NtCreateKey (&KeyHandle
,
781 REG_OPTION_NON_VOLATILE
,
783 if (!NT_SUCCESS(Status
))
785 DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status
);
790 /* Link 'CurrentControlSet' to 'ControlSet001' key */
791 RtlRosInitUnicodeStringFromLiteral (&ControlSetLinkName
,
792 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
793 InitializeObjectAttributes (&ObjectAttributes
,
795 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
798 Status
= NtCreateKey (&KeyHandle
,
799 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
803 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
805 if (!NT_SUCCESS(Status
))
807 DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status
);
811 RtlRosInitUnicodeStringFromLiteral (&ControlSetValueName
,
812 L
"SymbolicLinkValue");
813 Status
= NtSetValueKey (KeyHandle
,
814 &ControlSetValueName
,
817 (PVOID
)ControlSetKeyName
.Buffer
,
818 ControlSetKeyName
.Length
);
819 if (!NT_SUCCESS(Status
))
821 DPRINT1 ("NtSetValueKey() failed (Status %lx)\n", Status
);
825 return STATUS_SUCCESS
;
830 CmiInitHives(BOOLEAN SetupBoot
)
832 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
833 OBJECT_ATTRIBUTES ObjectAttributes
;
834 UNICODE_STRING FileName
;
835 UNICODE_STRING KeyName
;
836 UNICODE_STRING ValueName
;
841 WCHAR ConfigPath
[MAX_PATH
];
848 DPRINT("CmiInitHives() called\n");
850 if (SetupBoot
== TRUE
)
852 RtlRosInitUnicodeStringFromLiteral(&KeyName
,
853 L
"\\Registry\\Machine\\HARDWARE");
854 InitializeObjectAttributes(&ObjectAttributes
,
856 OBJ_CASE_INSENSITIVE
,
859 Status
= NtOpenKey(&KeyHandle
,
862 if (!NT_SUCCESS(Status
))
864 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status
);
868 RtlRosInitUnicodeStringFromLiteral(&ValueName
,
871 BufferSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 4096;
872 ValueInfo
= ExAllocatePool(PagedPool
,
874 if (ValueInfo
== NULL
)
877 return(STATUS_INSUFFICIENT_RESOURCES
);
880 Status
= NtQueryValueKey(KeyHandle
,
882 KeyValuePartialInformation
,
887 if (!NT_SUCCESS(Status
))
889 ExFreePool(ValueInfo
);
893 RtlCopyMemory(ConfigPath
,
895 ValueInfo
->DataLength
);
896 ConfigPath
[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = (WCHAR
)0;
897 ExFreePool(ValueInfo
);
901 wcscpy(ConfigPath
, L
"\\SystemRoot");
903 wcscat(ConfigPath
, L
"\\system32\\config");
905 DPRINT("ConfigPath: %S\n", ConfigPath
);
907 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 PREGISTRY_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(&CmiHiveListLock
, TRUE
);
1072 Entry
= CmiHiveListHead
.Flink
;
1073 while (Entry
!= &CmiHiveListHead
)
1075 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
1077 if (!(IsNoFileHive(Hive
) || IsNoSynchHive(Hive
)))
1079 /* Acquire hive resource exclusively */
1080 ExAcquireResourceExclusiveLite(&Hive
->HiveResource
,
1083 /* Flush non-volatile hive */
1084 CmiFlushRegistryHive(Hive
);
1086 /* Release hive resource */
1087 ExReleaseResourceLite(&Hive
->HiveResource
);
1090 Entry
= Entry
->Flink
;
1093 /* Release hive list lock */
1094 ExReleaseResourceLite(&CmiHiveListLock
);
1095 KeLeaveCriticalRegion();
1097 DPRINT("CmShutdownRegistry() done\n");
1102 CmiHiveSyncRoutine(PVOID DeferredContext
)
1104 PREGISTRY_HIVE Hive
;
1107 DPRINT("CmiHiveSyncRoutine() called\n");
1109 CmiHiveSyncPending
= FALSE
;
1111 /* Acquire hive list lock exclusively */
1112 KeEnterCriticalRegion();
1113 ExAcquireResourceExclusiveLite(&CmiHiveListLock
, TRUE
);
1115 Entry
= CmiHiveListHead
.Flink
;
1116 while (Entry
!= &CmiHiveListHead
)
1118 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
1120 if (!(IsNoFileHive(Hive
) || IsNoSynchHive(Hive
)))
1122 /* Acquire hive resource exclusively */
1123 ExAcquireResourceExclusiveLite(&Hive
->HiveResource
,
1126 /* Flush non-volatile hive */
1127 CmiFlushRegistryHive(Hive
);
1129 /* Release hive resource */
1130 ExReleaseResourceLite(&Hive
->HiveResource
);
1133 Entry
= Entry
->Flink
;
1136 /* Release hive list lock */
1137 ExReleaseResourceLite(&CmiHiveListLock
);
1138 KeLeaveCriticalRegion();
1140 DPRINT("DeferredContext %x\n", DeferredContext
);
1141 ExFreePool(DeferredContext
);
1143 DPRINT("CmiHiveSyncRoutine() done\n");
1148 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
1149 PVOID DeferredContext
,
1150 PVOID SystemArgument1
,
1151 PVOID SystemArgument2
)
1153 PWORK_QUEUE_ITEM WorkQueueItem
;
1155 WorkQueueItem
= ExAllocatePool(NonPagedPool
,
1156 sizeof(WORK_QUEUE_ITEM
));
1157 if (WorkQueueItem
== NULL
)
1159 DbgPrint("Failed to allocate work item\n");
1163 ExInitializeWorkItem(WorkQueueItem
,
1167 DPRINT("DeferredContext %x\n", WorkQueueItem
);
1168 ExQueueWorkItem(WorkQueueItem
,
1176 LARGE_INTEGER Timeout
;
1178 DPRINT("CmiSyncHives() called\n");
1180 if (CmiHiveSyncEnabled
== FALSE
||
1181 CmiHiveSyncPending
== TRUE
)
1184 CmiHiveSyncPending
= TRUE
;
1187 #if defined(__GNUC__)
1188 Timeout
.QuadPart
= -50000000LL;
1190 Timeout
.QuadPart
= -50000000;
1192 KeSetTimer(&CmiHiveSyncTimer
,