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 RootKey->NameSize = strlen("Registry");
315 RootKey->Name = ExAllocatePool(PagedPool, RootKey->NameSize);
316 RtlCopyMemory(RootKey->Name, "Registry", RootKey->NameSize);
318 KeInitializeSpinLock(&CmiKeyListLock);
320 /* Create '\Registry\Machine' key. */
321 Status = ObCreateObject(&KeyHandle,
322 STANDARD_RIGHTS_REQUIRED,
325 (PVOID*)&MachineKey);
326 assert(NT_SUCCESS(Status));
327 Status = CmiAddSubKey(CmiVolatileHive,
331 wcslen(L"Machine") * sizeof(WCHAR),
335 assert(NT_SUCCESS(Status));
336 MachineKey->RegistryHive = CmiVolatileHive;
337 MachineKey->Flags = 0;
338 MachineKey->NumberOfSubKeys = 0;
339 MachineKey->SubKeys = NULL;
340 MachineKey->SizeOfSubKeys = MachineKey->KeyCell->NumberOfSubKeys;
341 MachineKey->NameSize = strlen("Machine");
342 MachineKey->Name = ExAllocatePool(PagedPool, MachineKey->NameSize);
343 RtlCopyMemory(MachineKey->Name, "Machine", MachineKey->NameSize);
344 CmiAddKeyToList(RootKey, MachineKey);
346 /* Create '\Registry\User' key. */
347 Status = ObCreateObject(&KeyHandle,
348 STANDARD_RIGHTS_REQUIRED,
352 assert(NT_SUCCESS(Status));
353 Status = CmiAddSubKey(CmiVolatileHive,
357 wcslen(L"User") * sizeof(WCHAR),
361 assert(NT_SUCCESS(Status));
362 UserKey->RegistryHive = CmiVolatileHive;
364 UserKey->NumberOfSubKeys = 0;
365 UserKey->SubKeys = NULL;
366 UserKey->SizeOfSubKeys = UserKey->KeyCell->NumberOfSubKeys;
367 UserKey->NameSize = strlen("User");
368 UserKey->Name = ExAllocatePool(PagedPool, UserKey->NameSize);
369 RtlCopyMemory(UserKey->Name, "User", UserKey->NameSize);
370 CmiAddKeyToList(RootKey, UserKey);
375 CmInit2(PCHAR CommandLine)
381 /* FIXME: Store system start options */
385 /* Create the 'CurrentControlSet' link. */
386 Status = CmiCreateCurrentControlSetLink();
387 if (!NT_SUCCESS(Status))
389 KeBugCheck(CONFIG_INITIALIZATION_FAILED);
392 /* Set PICE 'Start' value to 1, if PICE debugging is enabled */
394 p1 = (PCHAR)CommandLine;
395 while (p1 && (p2 = strchr(p1, '/')))
398 if (_strnicmp(p2, "DEBUGPORT", 9) == 0)
404 if (_strnicmp(p2, "PICE", 4) == 0)
414 Status = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,
420 if (!NT_SUCCESS(Status))
422 KeBugCheck(CONFIG_INITIALIZATION_FAILED);
428 CmiCreateCurrentControlSetLink(VOID)
430 RTL_QUERY_REGISTRY_TABLE QueryTable[5];
431 WCHAR TargetNameBuffer[80];
432 ULONG TargetNameLength;
433 UNICODE_STRING LinkName;
434 UNICODE_STRING LinkValue;
440 OBJECT_ATTRIBUTES ObjectAttributes;
443 DPRINT("CmiCreateCurrentControlSetLink() called\n");
445 RtlZeroMemory(&QueryTable, sizeof(QueryTable));
447 QueryTable[0].Name = L"Current";
448 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
449 QueryTable[0].EntryContext = &CurrentSet;
451 QueryTable[1].Name = L"Default";
452 QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
453 QueryTable[1].EntryContext = &DefaultSet;
455 QueryTable[2].Name = L"Failed";
456 QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
457 QueryTable[2].EntryContext = &Failed;
459 QueryTable[3].Name = L"LastKnownGood";
460 QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
461 QueryTable[3].EntryContext = &LastKnownGood;
463 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
464 L"\\Registry\\Machine\\SYSTEM\\Select",
468 if (!NT_SUCCESS(Status))
473 DPRINT("Current %ld Default %ld\n", CurrentSet, DefaultSet);
475 swprintf(TargetNameBuffer,
476 L"\\Registry\\Machine\\SYSTEM\\ControlSet%03lu",
478 TargetNameLength = wcslen(TargetNameBuffer) * sizeof(WCHAR);
480 DPRINT("Link target '%S'\n", TargetNameBuffer);
482 RtlInitUnicodeStringFromLiteral(&LinkName,
483 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
484 InitializeObjectAttributes(&ObjectAttributes,
486 OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_OPENLINK,
489 Status = NtCreateKey(&KeyHandle,
490 KEY_ALL_ACCESS | KEY_CREATE_LINK,
494 REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
496 if (!NT_SUCCESS(Status))
498 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
502 RtlInitUnicodeStringFromLiteral(&LinkValue,
503 L"SymbolicLinkValue");
504 Status = NtSetValueKey(KeyHandle,
508 (PVOID)TargetNameBuffer,
510 if (!NT_SUCCESS(Status))
512 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
522 CmiConnectHive(PREGISTRY_HIVE RegistryHive,
523 PUNICODE_STRING KeyName)
525 OBJECT_ATTRIBUTES ObjectAttributes;
526 UNICODE_STRING ParentKeyName;
527 PKEY_OBJECT ParentKey;
533 DPRINT("CmiConnectHive(%p, %wZ) called.\n",
534 RegistryHive, KeyName);
536 SubName = wcsrchr (KeyName->Buffer, L'\\');
539 return STATUS_UNSUCCESSFUL;
542 ParentKeyName.Length = (USHORT)(SubName - KeyName->Buffer) * sizeof(WCHAR);
543 ParentKeyName.MaximumLength = ParentKeyName.Length + sizeof(WCHAR);
544 ParentKeyName.Buffer = ExAllocatePool (NonPagedPool,
545 ParentKeyName.MaximumLength);
546 RtlCopyMemory (ParentKeyName.Buffer,
548 ParentKeyName.Length);
549 ParentKeyName.Buffer[ParentKeyName.Length / sizeof(WCHAR)] = 0;
552 Status = ObReferenceObjectByName (&ParentKeyName,
553 OBJ_CASE_INSENSITIVE,
555 STANDARD_RIGHTS_REQUIRED,
560 RtlFreeUnicodeString (&ParentKeyName);
561 if (!NT_SUCCESS(Status))
563 DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status);
567 InitializeObjectAttributes(&ObjectAttributes,
573 Status = ObCreateObject(&KeyHandle,
574 STANDARD_RIGHTS_REQUIRED,
578 if (!NT_SUCCESS(Status))
580 DPRINT1 ("ObCreateObject() failed (Status %lx)\n", Status);
581 ObDereferenceObject (ParentKey);
585 NewKey->RegistryHive = RegistryHive;
586 NewKey->BlockOffset = RegistryHive->HiveHeader->RootKeyCell;
587 NewKey->KeyCell = CmiGetBlock(RegistryHive, NewKey->BlockOffset, NULL);
589 NewKey->NumberOfSubKeys = 0;
590 NewKey->SubKeys = ExAllocatePool(PagedPool,
591 NewKey->KeyCell->NumberOfSubKeys * sizeof(ULONG));
593 if ((NewKey->SubKeys == NULL) && (NewKey->KeyCell->NumberOfSubKeys != 0))
595 DPRINT("NumberOfSubKeys %d\n", NewKey->KeyCell->NumberOfSubKeys);
597 ObDereferenceObject (ParentKey);
598 return(STATUS_INSUFFICIENT_RESOURCES);
601 NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
602 NewKey->NameSize = wcslen (SubName);
603 NewKey->Name = ExAllocatePool(PagedPool, NewKey->NameSize);
605 if ((NewKey->Name == NULL) && (NewKey->NameSize != 0))
607 DPRINT("NewKey->NameSize %d\n", NewKey->NameSize);
608 if (NewKey->SubKeys != NULL)
609 ExFreePool(NewKey->SubKeys);
611 ObDereferenceObject (ParentKey);
612 return(STATUS_INSUFFICIENT_RESOURCES);
615 wcstombs (NewKey->Name,
619 CmiAddKeyToList (ParentKey, NewKey);
620 ObDereferenceObject (ParentKey);
622 VERIFY_KEY_OBJECT(NewKey);
624 return(STATUS_SUCCESS);
629 CmiInitializeSystemHive (PWSTR FileName,
630 PUNICODE_STRING KeyName)
632 OBJECT_ATTRIBUTES ObjectAttributes;
633 UNICODE_STRING ControlSetKeyName;
634 UNICODE_STRING ControlSetLinkName;
635 UNICODE_STRING ControlSetValueName;
638 PREGISTRY_HIVE RegistryHive;
640 Status = CmiCreateRegistryHive (FileName,
643 if (!NT_SUCCESS(Status))
645 DPRINT1 ("CmiCreateRegistryHive() failed (Status %lx)\n", Status);
649 Status = CmiConnectHive (RegistryHive,
651 if (!NT_SUCCESS(Status))
653 DPRINT1 ("CmiConnectHive() failed (Status %lx)\n", Status);
654 CmiRemoveRegistryHive (RegistryHive);
658 /* Create 'ControlSet001' key */
659 RtlInitUnicodeStringFromLiteral (&ControlSetKeyName,
660 L"\\Registry\\Machine\\SYSTEM\\ControlSet001");
661 InitializeObjectAttributes (&ObjectAttributes,
663 OBJ_CASE_INSENSITIVE,
666 Status = NtCreateKey (&KeyHandle,
671 REG_OPTION_NON_VOLATILE,
673 if (!NT_SUCCESS(Status))
675 DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status);
680 /* Link 'CurrentControlSet' to 'ControlSet001' key */
681 RtlInitUnicodeStringFromLiteral (&ControlSetLinkName,
682 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
683 InitializeObjectAttributes (&ObjectAttributes,
685 OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_OPENLINK,
688 Status = NtCreateKey (&KeyHandle,
689 KEY_ALL_ACCESS | KEY_CREATE_LINK,
693 REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
695 if (!NT_SUCCESS(Status))
697 DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status);
701 RtlInitUnicodeStringFromLiteral (&ControlSetValueName,
702 L"SymbolicLinkValue");
703 Status = NtSetValueKey (KeyHandle,
704 &ControlSetValueName,
707 (PVOID)ControlSetKeyName.Buffer,
708 ControlSetKeyName.Length);
709 if (!NT_SUCCESS(Status))
711 DPRINT1 ("NtSetValueKey() failed (Status %lx)\n", Status);
715 return STATUS_SUCCESS;
720 CmiInitializeHive(PWSTR FileName,
721 PUNICODE_STRING KeyName,
724 PREGISTRY_HIVE RegistryHive;
727 DPRINT("CmiInitializeHive(%s) called\n", KeyName);
729 Status = CmiCreateRegistryHive(FileName,
732 if (!NT_SUCCESS(Status))
734 DPRINT1("CmiCreateRegistryHive() failed (Status %lx)\n", Status);
736 /* FIXME: Try to load the backup hive */
742 /* Connect the hive */
743 Status = CmiConnectHive(RegistryHive,
745 if (!NT_SUCCESS(Status))
747 DPRINT1("CmiConnectHive() failed (Status %lx)\n", Status);
748 CmiRemoveRegistryHive(RegistryHive);
752 DPRINT("CmiInitializeHive() done\n");
754 return(STATUS_SUCCESS);
759 CmiInitHives(BOOLEAN SetupBoot)
761 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
762 OBJECT_ATTRIBUTES ObjectAttributes;
763 UNICODE_STRING KeyName;
764 UNICODE_STRING ValueName;
769 WCHAR ConfigPath[MAX_PATH];
776 DPRINT("CmiInitHives() called\n");
778 if (SetupBoot == TRUE)
780 RtlInitUnicodeStringFromLiteral(&KeyName,
781 L"\\Registry\\Machine\\HARDWARE");
782 InitializeObjectAttributes(&ObjectAttributes,
784 OBJ_CASE_INSENSITIVE,
787 Status = NtOpenKey(&KeyHandle,
790 if (!NT_SUCCESS(Status))
792 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
796 RtlInitUnicodeStringFromLiteral(&ValueName,
799 BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096;
800 ValueInfo = ExAllocatePool(PagedPool,
802 if (ValueInfo == NULL)
805 return(STATUS_INSUFFICIENT_RESOURCES);
808 Status = NtQueryValueKey(KeyHandle,
810 KeyValuePartialInformation,
815 if (ValueInfo == NULL)
817 ExFreePool(ValueInfo);
821 RtlCopyMemory(ConfigPath,
823 ValueInfo->DataLength);
824 ConfigPath[ValueInfo->DataLength / sizeof(WCHAR)] = (WCHAR)0;
825 ExFreePool(ValueInfo);
829 wcscpy(ConfigPath, L"\\SystemRoot");
831 wcscat(ConfigPath, L"\\system32\\config");
833 DPRINT("ConfigPath: %S\n", ConfigPath);
835 EndPtr = ConfigPath + wcslen(ConfigPath);
839 /* FIXME: Save boot log */
841 /* Connect the SYSTEM hive only if it has been created */
842 if (SetupBoot == TRUE)
844 wcscpy(EndPtr, REG_SYSTEM_FILE_NAME);
845 DPRINT ("ConfigPath: %S\n", ConfigPath);
847 RtlInitUnicodeString (&KeyName,
848 REG_SYSTEM_KEY_NAME);
849 Status = CmiInitializeSystemHive (ConfigPath,
851 if (!NT_SUCCESS(Status))
853 DPRINT1("CmiInitializeSystemHive() failed (Status %lx)\n", Status);
858 /* Connect the SOFTWARE hive */
859 wcscpy(EndPtr, REG_SOFTWARE_FILE_NAME);
860 DPRINT ("ConfigPath: %S\n", ConfigPath);
862 RtlInitUnicodeString (&KeyName,
863 REG_SOFTWARE_KEY_NAME);
864 Status = CmiInitializeHive(ConfigPath,
867 if (!NT_SUCCESS(Status))
869 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
873 /* Connect the SAM hive */
874 wcscpy(EndPtr, REG_SAM_FILE_NAME);
875 DPRINT ("ConfigPath: %S\n", ConfigPath);
877 RtlInitUnicodeString (&KeyName,
879 Status = CmiInitializeHive(ConfigPath,
882 if (!NT_SUCCESS(Status))
884 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
888 /* Connect the SECURITY hive */
889 wcscpy(EndPtr, REG_SEC_FILE_NAME);
890 DPRINT ("ConfigPath: %S\n", ConfigPath);
892 RtlInitUnicodeString (&KeyName,
894 Status = CmiInitializeHive(ConfigPath,
897 if (!NT_SUCCESS(Status))
899 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
903 /* Connect the DEFAULT hive */
904 wcscpy(EndPtr, REG_USER_FILE_NAME);
905 DPRINT ("ConfigPath: %S\n", ConfigPath);
907 RtlInitUnicodeString (&KeyName,
909 Status = CmiInitializeHive(ConfigPath,
912 if (!NT_SUCCESS(Status))
914 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
918 // CmiCheckRegistry(TRUE);
920 /* Start automatic hive synchronization */
921 KeInitializeDpc(&CmiHiveSyncDpc,
922 CmiHiveSyncDpcRoutine,
924 KeInitializeTimer(&CmiHiveSyncTimer);
925 CmiHiveSyncEnabled = TRUE;
927 DPRINT("CmiInitHives() done\n");
929 return(STATUS_SUCCESS);
934 CmShutdownRegistry(VOID)
939 DPRINT1("CmShutdownRegistry() called\n");
941 /* Stop automatic hive synchronization */
942 CmiHiveSyncEnabled = FALSE;
944 /* Acquire hive list lock exclusively */
945 ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
947 Entry = CmiHiveListHead.Flink;
948 while (Entry != &CmiHiveListHead)
950 Hive = CONTAINING_RECORD(Entry, REGISTRY_HIVE, HiveList);
952 if (!IsVolatileHive(Hive))
954 /* Acquire hive resource exclusively */
955 ExAcquireResourceExclusiveLite(&Hive->HiveResource,
958 /* Flush non-volatile hive */
959 CmiFlushRegistryHive(Hive);
961 /* Release hive resource */
962 ExReleaseResourceLite(&Hive->HiveResource);
965 Entry = Entry->Flink;
968 /* Release hive list lock */
969 ExReleaseResourceLite(&CmiHiveListLock);
971 DPRINT1("CmShutdownRegistry() done\n");
976 CmiHiveSyncRoutine(PVOID DeferredContext)
981 DPRINT("CmiHiveSyncRoutine() called\n");
983 CmiHiveSyncPending = FALSE;
985 /* Acquire hive list lock exclusively */
986 ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
988 Entry = CmiHiveListHead.Flink;
989 while (Entry != &CmiHiveListHead)
991 Hive = CONTAINING_RECORD(Entry, REGISTRY_HIVE, HiveList);
993 if (!IsVolatileHive(Hive))
995 /* Acquire hive resource exclusively */
996 ExAcquireResourceExclusiveLite(&Hive->HiveResource,
999 /* Flush non-volatile hive */
1000 CmiFlushRegistryHive(Hive);
1002 /* Release hive resource */
1003 ExReleaseResourceLite(&Hive->HiveResource);
1006 Entry = Entry->Flink;
1009 /* Release hive list lock */
1010 ExReleaseResourceLite(&CmiHiveListLock);
1012 DPRINT("DeferredContext %x\n", DeferredContext);
1013 ExFreePool(DeferredContext);
1015 DPRINT("CmiHiveSyncRoutine() done\n");
1020 CmiHiveSyncDpcRoutine(PKDPC Dpc,
1021 PVOID DeferredContext,
1022 PVOID SystemArgument1,
1023 PVOID SystemArgument2)
1025 PWORK_QUEUE_ITEM WorkQueueItem;
1027 WorkQueueItem = ExAllocatePool(NonPagedPool,
1028 sizeof(WORK_QUEUE_ITEM));
1029 if (WorkQueueItem == NULL)
1031 DbgPrint("Failed to allocate work item\n");
1035 ExInitializeWorkItem(WorkQueueItem,
1039 DPRINT("DeferredContext %x\n", WorkQueueItem);
1040 ExQueueWorkItem(WorkQueueItem,
1048 LARGE_INTEGER Timeout;
1050 DPRINT("CmiSyncHives() called\n");
1052 if (CmiHiveSyncEnabled == FALSE ||
1053 CmiHiveSyncPending == TRUE)
1056 CmiHiveSyncPending = TRUE;
1059 Timeout.QuadPart = -50000000LL;
1060 KeSetTimer(&CmiHiveSyncTimer,