1 /* $Id: registry.c,v 1.96 2003/05/28 12:04:17 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
14 #include <ddk/ntddk.h>
18 #include <internal/pool.h>
19 #include <internal/registry.h>
20 #include <reactos/bugcodes.h>
23 #include <internal/debug.h>
27 /* GLOBALS ******************************************************************/
29 POBJECT_TYPE CmiKeyType
= NULL
;
30 PREGISTRY_HIVE CmiVolatileHive
= NULL
;
31 KSPIN_LOCK CmiKeyListLock
;
33 LIST_ENTRY CmiHiveListHead
;
34 ERESOURCE CmiHiveListLock
;
36 volatile BOOLEAN CmiHiveSyncEnabled
= FALSE
;
37 volatile BOOLEAN CmiHiveSyncPending
= FALSE
;
39 KTIMER CmiHiveSyncTimer
;
41 static GENERIC_MAPPING CmiKeyMapping
=
42 {KEY_READ
, KEY_WRITE
, KEY_EXECUTE
, KEY_ALL_ACCESS
};
47 CmiCheckKey(BOOLEAN Verbose
,
51 CmiCreateCurrentControlSetLink(VOID
);
54 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
55 PVOID DeferredContext
,
56 PVOID SystemArgument1
,
57 PVOID SystemArgument2
);
59 /* FUNCTIONS ****************************************************************/
62 CmiCheckSubKeys(BOOLEAN Verbose
,
65 OBJECT_ATTRIBUTES ObjectAttributes
;
66 PKEY_NODE_INFORMATION KeyInfo
;
67 WCHAR KeyBuffer
[MAX_PATH
];
68 UNICODE_STRING KeyPath
;
79 BufferSize
= sizeof(KEY_NODE_INFORMATION
) + 4096;
80 KeyInfo
= ExAllocatePool(PagedPool
, BufferSize
);
82 Status
= NtEnumerateKey(Key
,
88 if (!NT_SUCCESS(Status
))
91 if (Status
== STATUS_NO_MORE_ENTRIES
)
92 Status
= STATUS_SUCCESS
;
98 KeyInfo
->NameLength
/ sizeof(WCHAR
));
102 DbgPrint("Key: %S\n", Name
);
105 /* FIXME: Check info. */
109 wcscpy(KeyBuffer
, L
"\\Registry\\");
110 wcscat(KeyBuffer
, Name
);
112 RtlInitUnicodeString(&KeyPath
, KeyBuffer
);
114 InitializeObjectAttributes(&ObjectAttributes
,
116 OBJ_CASE_INSENSITIVE
,
120 Status
= NtOpenKey(&SubKey
,
124 assert(NT_SUCCESS(Status
));
126 CmiCheckKey(Verbose
, SubKey
);
133 assert(NT_SUCCESS(Status
));
138 CmiCheckValues(BOOLEAN Verbose
,
141 PKEY_NODE_INFORMATION ValueInfo
;
142 WCHAR Name
[MAX_PATH
];
151 BufferSize
= sizeof(KEY_NODE_INFORMATION
) + 4096;
152 ValueInfo
= ExAllocatePool(PagedPool
, BufferSize
);
154 Status
= NtEnumerateValueKey(Key
,
160 if (!NT_SUCCESS(Status
))
162 ExFreePool(ValueInfo
);
163 if (Status
== STATUS_NO_MORE_ENTRIES
)
164 Status
= STATUS_SUCCESS
;
170 ValueInfo
->NameLength
/ sizeof(WCHAR
));
174 DbgPrint("Value: %S\n", Name
);
177 /* FIXME: Check info. */
179 ExFreePool(ValueInfo
);
184 assert(NT_SUCCESS(Status
));
189 CmiCheckKey(BOOLEAN Verbose
,
192 CmiCheckValues(Verbose
, Key
);
193 CmiCheckSubKeys(Verbose
, Key
);
198 CmiCheckByName(BOOLEAN Verbose
,
201 OBJECT_ATTRIBUTES ObjectAttributes
;
202 WCHAR KeyPathBuffer
[MAX_PATH
];
203 UNICODE_STRING KeyPath
;
207 wcscpy(KeyPathBuffer
, L
"\\Registry\\");
208 wcscat(KeyPathBuffer
, KeyName
);
210 RtlInitUnicodeString(&KeyPath
, KeyPathBuffer
);
212 InitializeObjectAttributes(&ObjectAttributes
,
214 OBJ_CASE_INSENSITIVE
,
218 Status
= NtOpenKey(&Key
,
224 if (!NT_SUCCESS(Status
))
226 DbgPrint("KeyPath %wZ Status: %.08x", KeyPath
, Status
);
227 DbgPrint("KeyPath %S Status: %.08x", KeyPath
.Buffer
, Status
);
228 assert(NT_SUCCESS(Status
));
232 CmiCheckKey(Verbose
, Key
);
239 CmiCheckRegistry(BOOLEAN Verbose
)
242 DbgPrint("Checking registry internals\n");
244 CmiCheckByName(Verbose
, L
"Machine");
245 CmiCheckByName(Verbose
, L
"User");
250 CmInitializeRegistry(VOID
)
252 OBJECT_ATTRIBUTES ObjectAttributes
;
253 UNICODE_STRING RootKeyName
;
255 PKEY_OBJECT MachineKey
;
257 HANDLE RootKeyHandle
;
261 /* Initialize the Key object type */
262 CmiKeyType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
264 CmiKeyType
->TotalObjects
= 0;
265 CmiKeyType
->TotalHandles
= 0;
266 CmiKeyType
->MaxObjects
= LONG_MAX
;
267 CmiKeyType
->MaxHandles
= LONG_MAX
;
268 CmiKeyType
->PagedPoolCharge
= 0;
269 CmiKeyType
->NonpagedPoolCharge
= sizeof(KEY_OBJECT
);
270 CmiKeyType
->Mapping
= &CmiKeyMapping
;
271 CmiKeyType
->Dump
= NULL
;
272 CmiKeyType
->Open
= NULL
;
273 CmiKeyType
->Close
= NULL
;
274 CmiKeyType
->Delete
= CmiObjectDelete
;
275 CmiKeyType
->Parse
= CmiObjectParse
;
276 CmiKeyType
->Security
= CmiObjectSecurity
;
277 CmiKeyType
->QueryName
= NULL
;
278 CmiKeyType
->OkayToClose
= NULL
;
279 CmiKeyType
->Create
= CmiObjectCreate
;
280 CmiKeyType
->DuplicationNotify
= NULL
;
281 RtlInitUnicodeString(&CmiKeyType
->TypeName
, L
"Key");
283 /* Initialize the hive list */
284 InitializeListHead(&CmiHiveListHead
);
285 ExInitializeResourceLite(&CmiHiveListLock
);
287 /* Build volatile registry store */
288 Status
= CmiCreateRegistryHive(NULL
, &CmiVolatileHive
, FALSE
);
289 assert(NT_SUCCESS(Status
));
291 /* Create '\Registry' key. */
292 RtlInitUnicodeString(&RootKeyName
, REG_ROOT_KEY_NAME
);
293 InitializeObjectAttributes(&ObjectAttributes
, &RootKeyName
, 0, NULL
, NULL
);
294 Status
= ObCreateObject(&RootKeyHandle
,
295 STANDARD_RIGHTS_REQUIRED
,
299 assert(NT_SUCCESS(Status
));
300 Status
= ObReferenceObjectByHandle(RootKeyHandle
,
301 STANDARD_RIGHTS_REQUIRED
,
306 assert(NT_SUCCESS(Status
));
307 RootKey
->RegistryHive
= CmiVolatileHive
;
308 RootKey
->BlockOffset
= CmiVolatileHive
->HiveHeader
->RootKeyCell
;
309 RootKey
->KeyCell
= CmiGetBlock(CmiVolatileHive
, RootKey
->BlockOffset
, NULL
);
311 RootKey
->NumberOfSubKeys
= 0;
312 RootKey
->SubKeys
= NULL
;
313 RootKey
->SizeOfSubKeys
= 0;
314 Status
= RtlCreateUnicodeString(&RootKey
->Name
, L
"Registry");
315 assert(NT_SUCCESS(Status
));
317 KeInitializeSpinLock(&CmiKeyListLock
);
319 /* Create '\Registry\Machine' key. */
320 Status
= ObCreateObject(&KeyHandle
,
321 STANDARD_RIGHTS_REQUIRED
,
324 (PVOID
*)&MachineKey
);
325 assert(NT_SUCCESS(Status
));
326 Status
= CmiAddSubKey(CmiVolatileHive
,
330 wcslen(L
"Machine") * sizeof(WCHAR
),
334 assert(NT_SUCCESS(Status
));
335 MachineKey
->RegistryHive
= CmiVolatileHive
;
336 MachineKey
->Flags
= 0;
337 MachineKey
->NumberOfSubKeys
= 0;
338 MachineKey
->SubKeys
= NULL
;
339 MachineKey
->SizeOfSubKeys
= MachineKey
->KeyCell
->NumberOfSubKeys
;
340 Status
= RtlCreateUnicodeString(&MachineKey
->Name
, L
"Machine");
341 assert(NT_SUCCESS(Status
));
342 CmiAddKeyToList(RootKey
, MachineKey
);
344 /* Create '\Registry\User' key. */
345 Status
= ObCreateObject(&KeyHandle
,
346 STANDARD_RIGHTS_REQUIRED
,
350 assert(NT_SUCCESS(Status
));
351 Status
= CmiAddSubKey(CmiVolatileHive
,
355 wcslen(L
"User") * sizeof(WCHAR
),
359 assert(NT_SUCCESS(Status
));
360 UserKey
->RegistryHive
= CmiVolatileHive
;
362 UserKey
->NumberOfSubKeys
= 0;
363 UserKey
->SubKeys
= NULL
;
364 UserKey
->SizeOfSubKeys
= UserKey
->KeyCell
->NumberOfSubKeys
;
365 Status
= RtlCreateUnicodeString(&UserKey
->Name
, L
"User");
366 assert(NT_SUCCESS(Status
));
367 CmiAddKeyToList(RootKey
, UserKey
);
372 CmInit2(PCHAR CommandLine
)
378 /* FIXME: Store system start options */
382 /* Create the 'CurrentControlSet' link. */
383 Status
= CmiCreateCurrentControlSetLink();
384 if (!NT_SUCCESS(Status
))
386 KeBugCheck(CONFIG_INITIALIZATION_FAILED
);
389 /* Set PICE 'Start' value to 1, if PICE debugging is enabled */
391 p1
= (PCHAR
)CommandLine
;
392 while (p1
&& (p2
= strchr(p1
, '/')))
395 if (_strnicmp(p2
, "DEBUGPORT", 9) == 0)
401 if (_strnicmp(p2
, "PICE", 4) == 0)
411 Status
= RtlWriteRegistryValue(RTL_REGISTRY_SERVICES
,
417 if (!NT_SUCCESS(Status
))
419 KeBugCheck(CONFIG_INITIALIZATION_FAILED
);
425 CmiCreateCurrentControlSetLink(VOID
)
427 RTL_QUERY_REGISTRY_TABLE QueryTable
[5];
428 WCHAR TargetNameBuffer
[80];
429 ULONG TargetNameLength
;
430 UNICODE_STRING LinkName
;
431 UNICODE_STRING LinkValue
;
437 OBJECT_ATTRIBUTES ObjectAttributes
;
440 DPRINT("CmiCreateCurrentControlSetLink() called\n");
442 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
444 QueryTable
[0].Name
= L
"Current";
445 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
446 QueryTable
[0].EntryContext
= &CurrentSet
;
448 QueryTable
[1].Name
= L
"Default";
449 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
450 QueryTable
[1].EntryContext
= &DefaultSet
;
452 QueryTable
[2].Name
= L
"Failed";
453 QueryTable
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
454 QueryTable
[2].EntryContext
= &Failed
;
456 QueryTable
[3].Name
= L
"LastKnownGood";
457 QueryTable
[3].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
458 QueryTable
[3].EntryContext
= &LastKnownGood
;
460 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
461 L
"\\Registry\\Machine\\SYSTEM\\Select",
465 if (!NT_SUCCESS(Status
))
470 DPRINT("Current %ld Default %ld\n", CurrentSet
, DefaultSet
);
472 swprintf(TargetNameBuffer
,
473 L
"\\Registry\\Machine\\SYSTEM\\ControlSet%03lu",
475 TargetNameLength
= wcslen(TargetNameBuffer
) * sizeof(WCHAR
);
477 DPRINT("Link target '%S'\n", TargetNameBuffer
);
479 RtlInitUnicodeStringFromLiteral(&LinkName
,
480 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
481 InitializeObjectAttributes(&ObjectAttributes
,
483 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
486 Status
= NtCreateKey(&KeyHandle
,
487 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
491 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
493 if (!NT_SUCCESS(Status
))
495 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status
);
499 RtlInitUnicodeStringFromLiteral(&LinkValue
,
500 L
"SymbolicLinkValue");
501 Status
= NtSetValueKey(KeyHandle
,
505 (PVOID
)TargetNameBuffer
,
507 if (!NT_SUCCESS(Status
))
509 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
519 CmiConnectHive(PREGISTRY_HIVE RegistryHive
,
520 PUNICODE_STRING KeyName
)
522 OBJECT_ATTRIBUTES ObjectAttributes
;
523 UNICODE_STRING ParentKeyName
;
524 PKEY_OBJECT ParentKey
;
530 DPRINT("CmiConnectHive(%p, %wZ) called.\n",
531 RegistryHive
, KeyName
);
533 SubName
= wcsrchr (KeyName
->Buffer
, L
'\\');
536 return STATUS_UNSUCCESSFUL
;
539 ParentKeyName
.Length
= (USHORT
)(SubName
- KeyName
->Buffer
) * sizeof(WCHAR
);
540 ParentKeyName
.MaximumLength
= ParentKeyName
.Length
+ sizeof(WCHAR
);
541 ParentKeyName
.Buffer
= ExAllocatePool (NonPagedPool
,
542 ParentKeyName
.MaximumLength
);
543 RtlCopyMemory (ParentKeyName
.Buffer
,
545 ParentKeyName
.Length
);
546 ParentKeyName
.Buffer
[ParentKeyName
.Length
/ sizeof(WCHAR
)] = 0;
549 Status
= ObReferenceObjectByName (&ParentKeyName
,
550 OBJ_CASE_INSENSITIVE
,
552 STANDARD_RIGHTS_REQUIRED
,
557 RtlFreeUnicodeString (&ParentKeyName
);
558 if (!NT_SUCCESS(Status
))
560 DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status
);
564 InitializeObjectAttributes(&ObjectAttributes
,
570 Status
= ObCreateObject(&KeyHandle
,
571 STANDARD_RIGHTS_REQUIRED
,
575 if (!NT_SUCCESS(Status
))
577 DPRINT1 ("ObCreateObject() failed (Status %lx)\n", Status
);
578 ObDereferenceObject (ParentKey
);
582 NewKey
->RegistryHive
= RegistryHive
;
583 NewKey
->BlockOffset
= RegistryHive
->HiveHeader
->RootKeyCell
;
584 NewKey
->KeyCell
= CmiGetBlock(RegistryHive
, NewKey
->BlockOffset
, NULL
);
586 NewKey
->NumberOfSubKeys
= 0;
587 NewKey
->SubKeys
= ExAllocatePool(PagedPool
,
588 NewKey
->KeyCell
->NumberOfSubKeys
* sizeof(ULONG
));
590 if ((NewKey
->SubKeys
== NULL
) && (NewKey
->KeyCell
->NumberOfSubKeys
!= 0))
592 DPRINT("NumberOfSubKeys %d\n", NewKey
->KeyCell
->NumberOfSubKeys
);
594 ObDereferenceObject (ParentKey
);
595 return(STATUS_INSUFFICIENT_RESOURCES
);
598 Status
= RtlCreateUnicodeString(&NewKey
->Name
,
600 if (!NT_SUCCESS(Status
))
602 DPRINT1("RtlCreateUnicodeString() failed (Status %lx)\n", Status
);
603 if (NewKey
->SubKeys
!= NULL
)
604 ExFreePool(NewKey
->SubKeys
);
606 ObDereferenceObject (ParentKey
);
607 return STATUS_INSUFFICIENT_RESOURCES
;
610 CmiAddKeyToList (ParentKey
, NewKey
);
611 ObDereferenceObject (ParentKey
);
613 VERIFY_KEY_OBJECT(NewKey
);
615 return(STATUS_SUCCESS
);
620 CmiInitializeSystemHive (PWSTR FileName
,
621 PUNICODE_STRING KeyName
)
623 OBJECT_ATTRIBUTES ObjectAttributes
;
624 UNICODE_STRING ControlSetKeyName
;
625 UNICODE_STRING ControlSetLinkName
;
626 UNICODE_STRING ControlSetValueName
;
629 PREGISTRY_HIVE RegistryHive
;
631 Status
= CmiCreateRegistryHive (FileName
,
634 if (!NT_SUCCESS(Status
))
636 DPRINT1 ("CmiCreateRegistryHive() failed (Status %lx)\n", Status
);
640 Status
= CmiConnectHive (RegistryHive
,
642 if (!NT_SUCCESS(Status
))
644 DPRINT1 ("CmiConnectHive() failed (Status %lx)\n", Status
);
645 CmiRemoveRegistryHive (RegistryHive
);
649 /* Create 'ControlSet001' key */
650 RtlInitUnicodeStringFromLiteral (&ControlSetKeyName
,
651 L
"\\Registry\\Machine\\SYSTEM\\ControlSet001");
652 InitializeObjectAttributes (&ObjectAttributes
,
654 OBJ_CASE_INSENSITIVE
,
657 Status
= NtCreateKey (&KeyHandle
,
662 REG_OPTION_NON_VOLATILE
,
664 if (!NT_SUCCESS(Status
))
666 DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status
);
671 /* Link 'CurrentControlSet' to 'ControlSet001' key */
672 RtlInitUnicodeStringFromLiteral (&ControlSetLinkName
,
673 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
674 InitializeObjectAttributes (&ObjectAttributes
,
676 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
679 Status
= NtCreateKey (&KeyHandle
,
680 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
684 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
686 if (!NT_SUCCESS(Status
))
688 DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status
);
692 RtlInitUnicodeStringFromLiteral (&ControlSetValueName
,
693 L
"SymbolicLinkValue");
694 Status
= NtSetValueKey (KeyHandle
,
695 &ControlSetValueName
,
698 (PVOID
)ControlSetKeyName
.Buffer
,
699 ControlSetKeyName
.Length
);
700 if (!NT_SUCCESS(Status
))
702 DPRINT1 ("NtSetValueKey() failed (Status %lx)\n", Status
);
706 return STATUS_SUCCESS
;
711 CmiInitializeHive(PWSTR FileName
,
712 PUNICODE_STRING KeyName
,
715 PREGISTRY_HIVE RegistryHive
;
718 DPRINT("CmiInitializeHive(%s) called\n", KeyName
);
720 Status
= CmiCreateRegistryHive(FileName
,
723 if (!NT_SUCCESS(Status
))
725 DPRINT1("CmiCreateRegistryHive() failed (Status %lx)\n", Status
);
727 /* FIXME: Try to load the backup hive */
733 /* Connect the hive */
734 Status
= CmiConnectHive(RegistryHive
,
736 if (!NT_SUCCESS(Status
))
738 DPRINT1("CmiConnectHive() failed (Status %lx)\n", Status
);
739 CmiRemoveRegistryHive(RegistryHive
);
743 DPRINT("CmiInitializeHive() done\n");
745 return(STATUS_SUCCESS
);
750 CmiInitHives(BOOLEAN SetupBoot
)
752 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
753 OBJECT_ATTRIBUTES ObjectAttributes
;
754 UNICODE_STRING KeyName
;
755 UNICODE_STRING ValueName
;
760 WCHAR ConfigPath
[MAX_PATH
];
767 DPRINT("CmiInitHives() called\n");
769 if (SetupBoot
== TRUE
)
771 RtlInitUnicodeStringFromLiteral(&KeyName
,
772 L
"\\Registry\\Machine\\HARDWARE");
773 InitializeObjectAttributes(&ObjectAttributes
,
775 OBJ_CASE_INSENSITIVE
,
778 Status
= NtOpenKey(&KeyHandle
,
781 if (!NT_SUCCESS(Status
))
783 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status
);
787 RtlInitUnicodeStringFromLiteral(&ValueName
,
790 BufferSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 4096;
791 ValueInfo
= ExAllocatePool(PagedPool
,
793 if (ValueInfo
== NULL
)
796 return(STATUS_INSUFFICIENT_RESOURCES
);
799 Status
= NtQueryValueKey(KeyHandle
,
801 KeyValuePartialInformation
,
806 if (!NT_SUCCESS(Status
))
808 ExFreePool(ValueInfo
);
812 RtlCopyMemory(ConfigPath
,
814 ValueInfo
->DataLength
);
815 ConfigPath
[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = (WCHAR
)0;
816 ExFreePool(ValueInfo
);
820 wcscpy(ConfigPath
, L
"\\SystemRoot");
822 wcscat(ConfigPath
, L
"\\system32\\config");
824 DPRINT("ConfigPath: %S\n", ConfigPath
);
826 EndPtr
= ConfigPath
+ wcslen(ConfigPath
);
830 /* FIXME: Save boot log */
832 /* Connect the SYSTEM hive only if it has been created */
833 if (SetupBoot
== TRUE
)
835 wcscpy(EndPtr
, REG_SYSTEM_FILE_NAME
);
836 DPRINT ("ConfigPath: %S\n", ConfigPath
);
838 RtlInitUnicodeString (&KeyName
,
839 REG_SYSTEM_KEY_NAME
);
840 Status
= CmiInitializeSystemHive (ConfigPath
,
842 if (!NT_SUCCESS(Status
))
844 DPRINT1("CmiInitializeSystemHive() failed (Status %lx)\n", Status
);
849 /* Connect the SOFTWARE hive */
850 wcscpy(EndPtr
, REG_SOFTWARE_FILE_NAME
);
851 DPRINT ("ConfigPath: %S\n", ConfigPath
);
853 RtlInitUnicodeString (&KeyName
,
854 REG_SOFTWARE_KEY_NAME
);
855 Status
= CmiInitializeHive(ConfigPath
,
858 if (!NT_SUCCESS(Status
))
860 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
864 /* Connect the SAM hive */
865 wcscpy(EndPtr
, REG_SAM_FILE_NAME
);
866 DPRINT ("ConfigPath: %S\n", ConfigPath
);
868 RtlInitUnicodeString (&KeyName
,
870 Status
= CmiInitializeHive(ConfigPath
,
873 if (!NT_SUCCESS(Status
))
875 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
879 /* Connect the SECURITY hive */
880 wcscpy(EndPtr
, REG_SEC_FILE_NAME
);
881 DPRINT ("ConfigPath: %S\n", ConfigPath
);
883 RtlInitUnicodeString (&KeyName
,
885 Status
= CmiInitializeHive(ConfigPath
,
888 if (!NT_SUCCESS(Status
))
890 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
894 /* Connect the DEFAULT hive */
895 wcscpy(EndPtr
, REG_USER_FILE_NAME
);
896 DPRINT ("ConfigPath: %S\n", ConfigPath
);
898 RtlInitUnicodeString (&KeyName
,
900 Status
= CmiInitializeHive(ConfigPath
,
903 if (!NT_SUCCESS(Status
))
905 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
909 // CmiCheckRegistry(TRUE);
911 /* Start automatic hive synchronization */
912 KeInitializeDpc(&CmiHiveSyncDpc
,
913 CmiHiveSyncDpcRoutine
,
915 KeInitializeTimer(&CmiHiveSyncTimer
);
916 CmiHiveSyncEnabled
= TRUE
;
918 DPRINT("CmiInitHives() done\n");
920 return(STATUS_SUCCESS
);
925 CmShutdownRegistry(VOID
)
930 DPRINT1("CmShutdownRegistry() called\n");
932 /* Stop automatic hive synchronization */
933 CmiHiveSyncEnabled
= FALSE
;
935 /* Acquire hive list lock exclusively */
936 ExAcquireResourceExclusiveLite(&CmiHiveListLock
, TRUE
);
938 Entry
= CmiHiveListHead
.Flink
;
939 while (Entry
!= &CmiHiveListHead
)
941 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
943 if (!IsVolatileHive(Hive
))
945 /* Acquire hive resource exclusively */
946 ExAcquireResourceExclusiveLite(&Hive
->HiveResource
,
949 /* Flush non-volatile hive */
950 CmiFlushRegistryHive(Hive
);
952 /* Release hive resource */
953 ExReleaseResourceLite(&Hive
->HiveResource
);
956 Entry
= Entry
->Flink
;
959 /* Release hive list lock */
960 ExReleaseResourceLite(&CmiHiveListLock
);
962 DPRINT1("CmShutdownRegistry() done\n");
967 CmiHiveSyncRoutine(PVOID DeferredContext
)
972 DPRINT("CmiHiveSyncRoutine() called\n");
974 CmiHiveSyncPending
= FALSE
;
976 /* Acquire hive list lock exclusively */
977 ExAcquireResourceExclusiveLite(&CmiHiveListLock
, TRUE
);
979 Entry
= CmiHiveListHead
.Flink
;
980 while (Entry
!= &CmiHiveListHead
)
982 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
984 if (!IsVolatileHive(Hive
))
986 /* Acquire hive resource exclusively */
987 ExAcquireResourceExclusiveLite(&Hive
->HiveResource
,
990 /* Flush non-volatile hive */
991 CmiFlushRegistryHive(Hive
);
993 /* Release hive resource */
994 ExReleaseResourceLite(&Hive
->HiveResource
);
997 Entry
= Entry
->Flink
;
1000 /* Release hive list lock */
1001 ExReleaseResourceLite(&CmiHiveListLock
);
1003 DPRINT("DeferredContext %x\n", DeferredContext
);
1004 ExFreePool(DeferredContext
);
1006 DPRINT("CmiHiveSyncRoutine() done\n");
1011 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
1012 PVOID DeferredContext
,
1013 PVOID SystemArgument1
,
1014 PVOID SystemArgument2
)
1016 PWORK_QUEUE_ITEM WorkQueueItem
;
1018 WorkQueueItem
= ExAllocatePool(NonPagedPool
,
1019 sizeof(WORK_QUEUE_ITEM
));
1020 if (WorkQueueItem
== NULL
)
1022 DbgPrint("Failed to allocate work item\n");
1026 ExInitializeWorkItem(WorkQueueItem
,
1030 DPRINT("DeferredContext %x\n", WorkQueueItem
);
1031 ExQueueWorkItem(WorkQueueItem
,
1039 LARGE_INTEGER Timeout
;
1041 DPRINT("CmiSyncHives() called\n");
1043 if (CmiHiveSyncEnabled
== FALSE
||
1044 CmiHiveSyncPending
== TRUE
)
1047 CmiHiveSyncPending
= TRUE
;
1050 Timeout
.QuadPart
= -50000000LL;
1051 KeSetTimer(&CmiHiveSyncTimer
,