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
17 #include <ddk/ntddk.h>
21 #include <internal/pool.h>
22 #include <internal/registry.h>
23 #include <reactos/bugcodes.h>
26 #include <internal/debug.h>
31 /* ------------------------------------------------- File Statics */
33 POBJECT_TYPE CmiKeyType = NULL;
34 PREGISTRY_HIVE CmiVolatileHive = NULL;
35 KSPIN_LOCK CmiKeyListLock;
37 LIST_ENTRY CmiHiveListHead;
38 ERESOURCE CmiHiveListLock;
40 volatile BOOLEAN CmiHiveSyncEnabled = FALSE;
41 volatile BOOLEAN CmiHiveSyncPending = FALSE;
43 KTIMER CmiHiveSyncTimer;
45 static PKEY_OBJECT CmiRootKey = NULL;
46 static PKEY_OBJECT CmiMachineKey = NULL;
47 static PKEY_OBJECT CmiUserKey = NULL;
48 static PKEY_OBJECT CmiHardwareKey = NULL;
50 static GENERIC_MAPPING CmiKeyMapping =
51 {KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS};
56 CmiCheckKey(BOOLEAN Verbose,
60 CmiCreateCurrentControlSetLink(VOID);
63 CmiHiveSyncDpcRoutine(PKDPC Dpc,
64 PVOID DeferredContext,
65 PVOID SystemArgument1,
66 PVOID SystemArgument2);
68 /* FUNCTIONS ****************************************************************/
71 CmiCheckSubKeys(BOOLEAN Verbose,
74 OBJECT_ATTRIBUTES ObjectAttributes;
75 PKEY_NODE_INFORMATION KeyInfo;
76 WCHAR KeyBuffer[MAX_PATH];
77 UNICODE_STRING KeyPath;
88 BufferSize = sizeof(KEY_NODE_INFORMATION) + 4096;
89 KeyInfo = ExAllocatePool(PagedPool, BufferSize);
91 Status = NtEnumerateKey(Key,
97 if (!NT_SUCCESS(Status))
100 if (Status == STATUS_NO_MORE_ENTRIES)
101 Status = STATUS_SUCCESS;
107 KeyInfo->NameLength / sizeof(WCHAR));
111 DbgPrint("Key: %S\n", Name);
114 /* FIXME: Check info. */
118 wcscpy(KeyBuffer, L"\\Registry\\");
119 wcscat(KeyBuffer, Name);
121 RtlInitUnicodeString(&KeyPath, KeyBuffer);
123 InitializeObjectAttributes(&ObjectAttributes,
125 OBJ_CASE_INSENSITIVE,
129 Status = NtOpenKey(&SubKey,
133 assert(NT_SUCCESS(Status));
135 CmiCheckKey(Verbose, SubKey);
142 assert(NT_SUCCESS(Status));
147 CmiCheckValues(BOOLEAN Verbose,
150 PKEY_NODE_INFORMATION ValueInfo;
151 WCHAR Name[MAX_PATH];
160 BufferSize = sizeof(KEY_NODE_INFORMATION) + 4096;
161 ValueInfo = ExAllocatePool(PagedPool, BufferSize);
163 Status = NtEnumerateValueKey(Key,
169 if (!NT_SUCCESS(Status))
171 ExFreePool(ValueInfo);
172 if (Status == STATUS_NO_MORE_ENTRIES)
173 Status = STATUS_SUCCESS;
179 ValueInfo->NameLength / sizeof(WCHAR));
183 DbgPrint("Value: %S\n", Name);
186 /* FIXME: Check info. */
188 ExFreePool(ValueInfo);
193 assert(NT_SUCCESS(Status));
198 CmiCheckKey(BOOLEAN Verbose,
201 CmiCheckValues(Verbose, Key);
202 CmiCheckSubKeys(Verbose, Key);
207 CmiCheckByName(BOOLEAN Verbose,
210 OBJECT_ATTRIBUTES ObjectAttributes;
211 WCHAR KeyPathBuffer[MAX_PATH];
212 UNICODE_STRING KeyPath;
216 wcscpy(KeyPathBuffer, L"\\Registry\\");
217 wcscat(KeyPathBuffer, KeyName);
219 RtlInitUnicodeString(&KeyPath, KeyPathBuffer);
221 InitializeObjectAttributes(&ObjectAttributes,
223 OBJ_CASE_INSENSITIVE,
227 Status = NtOpenKey(&Key,
233 if (!NT_SUCCESS(Status))
235 DbgPrint("KeyPath %wZ Status: %.08x", KeyPath, Status);
236 DbgPrint("KeyPath %S Status: %.08x", KeyPath.Buffer, Status);
237 assert(NT_SUCCESS(Status));
241 CmiCheckKey(Verbose, Key);
248 CmiCheckRegistry(BOOLEAN Verbose)
251 DbgPrint("Checking registry internals\n");
253 CmiCheckByName(Verbose, L"Machine");
254 CmiCheckByName(Verbose, L"User");
259 CmInitializeRegistry(VOID)
261 OBJECT_ATTRIBUTES ObjectAttributes;
262 UNICODE_STRING RootKeyName;
263 HANDLE RootKeyHandle;
268 /* Initialize the Key object type */
269 CmiKeyType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
271 CmiKeyType->TotalObjects = 0;
272 CmiKeyType->TotalHandles = 0;
273 CmiKeyType->MaxObjects = LONG_MAX;
274 CmiKeyType->MaxHandles = LONG_MAX;
275 CmiKeyType->PagedPoolCharge = 0;
276 CmiKeyType->NonpagedPoolCharge = sizeof(KEY_OBJECT);
277 CmiKeyType->Mapping = &CmiKeyMapping;
278 CmiKeyType->Dump = NULL;
279 CmiKeyType->Open = NULL;
280 CmiKeyType->Close = NULL;
281 CmiKeyType->Delete = CmiObjectDelete;
282 CmiKeyType->Parse = CmiObjectParse;
283 CmiKeyType->Security = NULL;
284 CmiKeyType->QueryName = NULL;
285 CmiKeyType->OkayToClose = NULL;
286 CmiKeyType->Create = CmiObjectCreate;
287 CmiKeyType->DuplicationNotify = NULL;
288 RtlInitUnicodeString(&CmiKeyType->TypeName, L"Key");
290 /* Initialize the hive list */
291 InitializeListHead(&CmiHiveListHead);
292 ExInitializeResourceLite(&CmiHiveListLock);
294 /* Build volatile registry store */
295 Status = CmiCreateRegistryHive(NULL, &CmiVolatileHive, FALSE);
296 assert(NT_SUCCESS(Status));
298 /* Create '\Registry' key. */
299 RtlInitUnicodeString(&RootKeyName, REG_ROOT_KEY_NAME);
300 InitializeObjectAttributes(&ObjectAttributes, &RootKeyName, 0, NULL, NULL);
301 Status = ObCreateObject(&RootKeyHandle,
302 STANDARD_RIGHTS_REQUIRED,
306 assert(NT_SUCCESS(Status));
308 Status = ObReferenceObjectByHandle(RootKeyHandle,
309 STANDARD_RIGHTS_REQUIRED,
312 (PVOID *) &CmiRootKey,
314 assert(NT_SUCCESS(Status));
315 CmiRootKey->RegistryHive = CmiVolatileHive;
316 NewKey->BlockOffset = CmiVolatileHive->HiveHeader->RootKeyCell;
317 NewKey->KeyCell = CmiGetBlock(CmiVolatileHive, NewKey->BlockOffset, NULL);
318 CmiRootKey->Flags = 0;
319 CmiRootKey->NumberOfSubKeys = 0;
320 CmiRootKey->SubKeys = NULL;
321 CmiRootKey->SizeOfSubKeys = 0;
322 CmiRootKey->Name = ExAllocatePool(PagedPool, strlen("Registry"));
323 CmiRootKey->NameSize = strlen("Registry");
324 memcpy(CmiRootKey->Name, "Registry", strlen("Registry"));
326 KeInitializeSpinLock(&CmiKeyListLock);
328 /* Create initial predefined symbolic links */
330 /* Create '\Registry\Machine' key. */
331 Status = ObCreateObject(&KeyHandle,
332 STANDARD_RIGHTS_REQUIRED,
336 assert(NT_SUCCESS(Status));
337 Status = CmiAddSubKey(CmiVolatileHive,
341 wcslen(L"Machine") * sizeof(WCHAR),
345 assert(NT_SUCCESS(Status));
346 NewKey->RegistryHive = CmiVolatileHive;
348 NewKey->NumberOfSubKeys = 0;
349 NewKey->SubKeys = NULL;
350 NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
351 NewKey->Name = ExAllocatePool(PagedPool, strlen("Machine"));
352 NewKey->NameSize = strlen("Machine");
353 memcpy(NewKey->Name, "Machine", strlen("Machine"));
354 CmiAddKeyToList(CmiRootKey, NewKey);
355 CmiMachineKey = NewKey;
357 /* Create '\Registry\User' key. */
358 Status = ObCreateObject(&KeyHandle,
359 STANDARD_RIGHTS_REQUIRED,
363 assert(NT_SUCCESS(Status));
364 Status = CmiAddSubKey(CmiVolatileHive,
368 wcslen(L"User") * sizeof(WCHAR),
372 assert(NT_SUCCESS(Status));
373 NewKey->RegistryHive = CmiVolatileHive;
375 NewKey->NumberOfSubKeys = 0;
376 NewKey->SubKeys = NULL;
377 NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
378 NewKey->Name = ExAllocatePool(PagedPool, strlen("User"));
379 NewKey->NameSize = strlen("User");
380 memcpy(NewKey->Name, "User", strlen("User"));
381 CmiAddKeyToList(CmiRootKey, NewKey);
384 /* Create '\Registry\Machine\HARDWARE' key. */
385 Status = ObCreateObject(&KeyHandle,
386 STANDARD_RIGHTS_REQUIRED,
390 assert(NT_SUCCESS(Status));
391 Status = CmiAddSubKey(CmiVolatileHive,
395 wcslen(L"HARDWARE") * sizeof(WCHAR),
399 assert(NT_SUCCESS(Status));
400 NewKey->RegistryHive = CmiVolatileHive;
402 NewKey->NumberOfSubKeys = 0;
403 NewKey->SubKeys = NULL;
404 NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
405 NewKey->Name = ExAllocatePool(PagedPool, strlen("HARDWARE"));
406 NewKey->NameSize = strlen("HARDWARE");
407 memcpy(NewKey->Name, "HARDWARE", strlen("HARDWARE"));
408 CmiAddKeyToList(CmiMachineKey, NewKey);
409 CmiHardwareKey = NewKey;
411 /* Create '\Registry\Machine\HARDWARE\DESCRIPTION' key. */
412 Status = ObCreateObject(&KeyHandle,
413 STANDARD_RIGHTS_REQUIRED,
417 assert(NT_SUCCESS(Status));
418 Status = CmiAddSubKey(CmiVolatileHive,
422 wcslen(L"DESCRIPTION") * sizeof(WCHAR),
426 assert(NT_SUCCESS(Status));
427 NewKey->RegistryHive = CmiVolatileHive;
429 NewKey->NumberOfSubKeys = 0;
430 NewKey->SubKeys = NULL;
431 NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
432 NewKey->Name = ExAllocatePool(PagedPool, strlen("DESCRIPTION"));
433 NewKey->NameSize = strlen("DESCRIPTION");
434 memcpy(NewKey->Name, "DESCRIPTION", strlen("DESCRIPTION"));
435 CmiAddKeyToList(CmiHardwareKey, NewKey);
437 /* Create '\Registry\Machine\HARDWARE\DEVICEMAP' key. */
438 Status = ObCreateObject(&KeyHandle,
439 STANDARD_RIGHTS_REQUIRED,
443 assert(NT_SUCCESS(Status));
444 Status = CmiAddSubKey(CmiVolatileHive,
448 wcslen(L"DEVICEMAP") * sizeof(WCHAR),
452 assert(NT_SUCCESS(Status));
453 NewKey->RegistryHive = CmiVolatileHive;
455 NewKey->NumberOfSubKeys = 0;
456 NewKey->SubKeys = NULL;
457 NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
458 NewKey->Name = ExAllocatePool(PagedPool, strlen("DEVICEMAP"));
459 NewKey->NameSize = strlen("DEVICEMAP");
460 memcpy(NewKey->Name, "DEVICEMAP", strlen("DEVICEMAP"));
461 CmiAddKeyToList(CmiHardwareKey,NewKey);
463 /* Create '\Registry\Machine\HARDWARE\RESOURCEMAP' key. */
464 Status = ObCreateObject(&KeyHandle,
465 STANDARD_RIGHTS_REQUIRED,
469 assert(NT_SUCCESS(Status));
470 Status = CmiAddSubKey(CmiVolatileHive,
474 wcslen(L"RESOURCEMAP") * sizeof(WCHAR),
478 assert(NT_SUCCESS(Status));
479 NewKey->RegistryHive = CmiVolatileHive;
481 NewKey->NumberOfSubKeys = 0;
482 NewKey->SubKeys = NULL;
483 NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
484 NewKey->Name = ExAllocatePool(PagedPool, strlen("RESOURCEMAP"));
485 NewKey->NameSize = strlen("RESOURCEMAP");
486 memcpy(NewKey->Name, "RESOURCEMAP", strlen("RESOURCEMAP"));
487 CmiAddKeyToList(CmiHardwareKey, NewKey);
489 /* FIXME: create remaining structure needed for default handles */
490 /* FIXME: load volatile registry data from ROSDTECT */
495 CmInit2(PCHAR CommandLine)
501 /* FIXME: Store system start options */
505 /* Create the 'CurrentControlSet' link. */
506 Status = CmiCreateCurrentControlSetLink();
508 if (!NT_SUCCESS(Status))
510 KeBugCheck(CONFIG_INITIALIZATION_FAILED);
514 /* Set PICE 'Start' value to 1, if PICE debugging is enabled */
516 p1 = (PCHAR)CommandLine;
517 while (p1 && (p2 = strchr(p1, '/')))
520 if (_strnicmp(p2, "DEBUGPORT", 9) == 0)
526 if (_strnicmp(p2, "PICE", 4) == 0)
536 Status = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,
542 if (!NT_SUCCESS(Status))
544 KeBugCheck(CONFIG_INITIALIZATION_FAILED);
551 CmiCreateCurrentControlSetLink(VOID)
553 RTL_QUERY_REGISTRY_TABLE QueryTable[5];
554 WCHAR TargetNameBuffer[80];
555 ULONG TargetNameLength;
556 UNICODE_STRING LinkName;
557 UNICODE_STRING LinkValue;
563 OBJECT_ATTRIBUTES ObjectAttributes;
566 DPRINT("CmiCreateCurrentControlSetLink() called\n");
568 RtlZeroMemory(&QueryTable, sizeof(QueryTable));
570 QueryTable[0].Name = L"Current";
571 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
572 QueryTable[0].EntryContext = &CurrentSet;
574 QueryTable[1].Name = L"Default";
575 QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
576 QueryTable[1].EntryContext = &DefaultSet;
578 QueryTable[2].Name = L"Failed";
579 QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
580 QueryTable[2].EntryContext = &Failed;
582 QueryTable[3].Name = L"LastKnownGood";
583 QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
584 QueryTable[3].EntryContext = &LastKnownGood;
586 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
587 L"\\Registry\\Machine\\SYSTEM\\Select",
591 if (!NT_SUCCESS(Status))
596 DPRINT("Current %ld Default %ld\n", CurrentSet, DefaultSet);
598 swprintf(TargetNameBuffer,
599 L"\\Registry\\Machine\\SYSTEM\\ControlSet%03lu",
601 TargetNameLength = wcslen(TargetNameBuffer) * sizeof(WCHAR);
603 DPRINT("Link target '%S'\n", TargetNameBuffer);
605 RtlInitUnicodeStringFromLiteral(&LinkName,
606 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
607 InitializeObjectAttributes(&ObjectAttributes,
609 OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_OPENLINK,
612 Status = NtCreateKey(&KeyHandle,
613 KEY_ALL_ACCESS | KEY_CREATE_LINK,
617 REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
619 if (!NT_SUCCESS(Status))
621 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
625 RtlInitUnicodeStringFromLiteral(&LinkValue,
626 L"SymbolicLinkValue");
627 Status = NtSetValueKey(KeyHandle,
631 (PVOID)TargetNameBuffer,
633 if (!NT_SUCCESS(Status))
635 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
645 CmiConnectHive(PWSTR FileName,
651 OBJECT_ATTRIBUTES ObjectAttributes;
652 PREGISTRY_HIVE RegistryHive = NULL;
653 UNICODE_STRING uKeyName;
658 DPRINT("CmiConnectHive(%S, %S, %s, %p, %d) - Called.\n", FileName, FullName, KeyName, Parent, CreateNew);
660 Status = CmiCreateRegistryHive(FileName, &RegistryHive, CreateNew);
661 if (!NT_SUCCESS(Status))
663 DPRINT1("CmiCreateRegistryHive() failed (Status %lx)\n", Status);
668 RtlInitUnicodeString(&uKeyName, FullName);
670 InitializeObjectAttributes(&ObjectAttributes,
676 Status = ObCreateObject(&KeyHandle,
677 STANDARD_RIGHTS_REQUIRED,
681 if (!NT_SUCCESS(Status))
683 DPRINT1("ObCreateObject() failed (Status %lx)\n", Status);
685 CmiRemoveRegistryHive(RegistryHive);
689 NewKey->RegistryHive = RegistryHive;
690 NewKey->BlockOffset = RegistryHive->HiveHeader->RootKeyCell;
691 NewKey->KeyCell = CmiGetBlock(RegistryHive, NewKey->BlockOffset, NULL);
693 NewKey->NumberOfSubKeys = 0;
694 NewKey->SubKeys = ExAllocatePool(PagedPool,
695 NewKey->KeyCell->NumberOfSubKeys * sizeof(DWORD));
697 if ((NewKey->SubKeys == NULL) && (NewKey->KeyCell->NumberOfSubKeys != 0))
699 DPRINT("NumberOfSubKeys %d\n", NewKey->KeyCell->NumberOfSubKeys);
701 CmiRemoveRegistryHive(RegistryHive);
702 return(STATUS_INSUFFICIENT_RESOURCES);
705 NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
706 NewKey->Name = ExAllocatePool(PagedPool, strlen(KeyName));
708 if ((NewKey->Name == NULL) && (strlen(KeyName) != 0))
710 DPRINT("strlen(KeyName) %d\n", strlen(KeyName));
711 if (NewKey->SubKeys != NULL)
712 ExFreePool(NewKey->SubKeys);
714 CmiRemoveRegistryHive(RegistryHive);
715 return(STATUS_INSUFFICIENT_RESOURCES);
718 NewKey->NameSize = strlen(KeyName);
719 memcpy(NewKey->Name, KeyName, strlen(KeyName));
720 CmiAddKeyToList(Parent, NewKey);
722 VERIFY_KEY_OBJECT(NewKey);
724 return(STATUS_SUCCESS);
729 CmiInitializeHive(PWSTR FileName,
737 DPRINT("CmiInitializeHive(%s) called\n", KeyName);
739 /* Try to connect the hive */
740 //Status = CmiConnectHive(FileName, FullName, KeyName, Parent, FALSE);
741 Status = CmiConnectHive(FileName, FullName, KeyName, Parent, CreateNew);
743 if (!NT_SUCCESS(Status))
747 WCHAR AltFileName[MAX_PATH];
749 CPRINT("WARNING! Registry file %S not found\n", FileName);
750 //DPRINT("Status %.08x\n", Status);
752 wcscpy(AltFileName, FileName);
753 wcscat(AltFileName, L".alt");
755 DPRINT("Attempting to connect the alternative hive %S\n", AltFileName);
756 /* Try to connect the alternative hive */
757 Status = CmiConnectHive(AltFileName, FullName, KeyName, Parent, TRUE);
759 if (!NT_SUCCESS(Status)) {
760 CPRINT("WARNING! Alternative registry file %S not found\n", AltFileName);
761 //DPRINT("Status %.08x\n", Status);
767 DPRINT("CmiInitializeHive() done\n");
774 CmiInitHives(BOOLEAN SetUpBoot)
776 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
777 OBJECT_ATTRIBUTES ObjectAttributes;
778 UNICODE_STRING KeyName;
779 UNICODE_STRING ValueName;
784 WCHAR ConfigPath[MAX_PATH];
791 DPRINT("CmiInitHives() called\n");
793 if (SetUpBoot == TRUE)
795 RtlInitUnicodeStringFromLiteral(&KeyName,
796 L"\\Registry\\Machine\\HARDWARE");
797 InitializeObjectAttributes(&ObjectAttributes,
799 OBJ_CASE_INSENSITIVE,
802 Status = NtOpenKey(&KeyHandle,
805 if (!NT_SUCCESS(Status))
807 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
811 RtlInitUnicodeStringFromLiteral(&ValueName,
814 BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096;
815 ValueInfo = ExAllocatePool(PagedPool,
817 if (ValueInfo == NULL)
820 return(STATUS_INSUFFICIENT_RESOURCES);
823 Status = NtQueryValueKey(KeyHandle,
825 KeyValuePartialInformation,
830 if (ValueInfo == NULL)
832 ExFreePool(ValueInfo);
836 RtlCopyMemory(ConfigPath,
838 ValueInfo->DataLength);
839 ConfigPath[ValueInfo->DataLength / sizeof(WCHAR)] = (WCHAR)0;
840 ExFreePool(ValueInfo);
844 wcscpy(ConfigPath, L"\\SystemRoot");
846 wcscat(ConfigPath, L"\\system32\\config");
848 DPRINT("ConfigPath: %S\n", ConfigPath);
850 EndPtr = ConfigPath + wcslen(ConfigPath);
854 /* FIXME: Save boot log */
856 /* FIXME: Rename \Registry\Machine\System */
858 /* Connect the SYSTEM hive */
859 // Status = CmiInitializeHive(SYSTEM_REG_FILE, REG_SYSTEM_KEY_NAME, "System", CmiMachineKey, SetUpBoot);
860 // assert(NT_SUCCESS(Status));
862 /* FIXME: Synchronize old and new system hive (??) */
864 /* FIXME: Delete old system hive */
866 /* Connect the SOFTWARE hive */
867 wcscpy(EndPtr, REG_SOFTWARE_FILE_NAME);
868 DPRINT1("ConfigPath: %S\n", ConfigPath);
870 Status = CmiInitializeHive(ConfigPath,
871 REG_SOFTWARE_KEY_NAME,
875 if (!NT_SUCCESS(Status))
877 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
881 /* Connect the SAM hive */
882 wcscpy(EndPtr, REG_SAM_FILE_NAME);
883 DPRINT1("ConfigPath: %S\n", ConfigPath);
885 Status = CmiInitializeHive(ConfigPath,
890 if (!NT_SUCCESS(Status))
892 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
896 /* Connect the SECURITY hive */
897 wcscpy(EndPtr, REG_SEC_FILE_NAME);
898 DPRINT1("ConfigPath: %S\n", ConfigPath);
899 Status = CmiInitializeHive(ConfigPath,
904 if (!NT_SUCCESS(Status))
906 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
910 /* Connect the DEFAULT hive */
911 wcscpy(EndPtr, REG_USER_FILE_NAME);
912 DPRINT1("ConfigPath: %S\n", ConfigPath);
914 Status = CmiInitializeHive(ConfigPath,
919 if (!NT_SUCCESS(Status))
921 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
925 /* FIXME : initialize standards symbolic links */
927 // CmiCheckRegistry(TRUE);
929 /* Start automatic hive synchronization */
930 KeInitializeDpc(&CmiHiveSyncDpc,
931 CmiHiveSyncDpcRoutine,
933 KeInitializeTimer(&CmiHiveSyncTimer);
934 CmiHiveSyncEnabled = TRUE;
936 DPRINT("CmiInitHives() done\n");
938 return(STATUS_SUCCESS);
943 CmShutdownRegistry(VOID)
948 DPRINT1("CmShutdownRegistry() called\n");
950 /* Stop automatic hive synchronization */
951 CmiHiveSyncEnabled = FALSE;
953 /* Acquire hive list lock exclusively */
954 ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
956 Entry = CmiHiveListHead.Flink;
957 while (Entry != &CmiHiveListHead)
959 Hive = CONTAINING_RECORD(Entry, REGISTRY_HIVE, HiveList);
961 if (IsPermanentHive(Hive))
963 /* Acquire hive resource exclusively */
964 ExAcquireResourceExclusiveLite(&Hive->HiveResource,
967 /* Flush non-volatile hive */
968 CmiFlushRegistryHive(Hive);
970 /* Dereference file */
971 ObDereferenceObject(Hive->FileObject);
972 Hive->FileObject = NULL;
974 /* Release hive resource */
975 ExReleaseResourceLite(&Hive->HiveResource);
978 Entry = Entry->Flink;
981 /* Release hive list lock */
982 ExReleaseResourceLite(&CmiHiveListLock);
984 DPRINT1("CmShutdownRegistry() done\n");
989 CmiHiveSyncRoutine(PVOID DeferredContext)
994 DPRINT1("CmiHiveSyncRoutine() called\n");
996 CmiHiveSyncPending = FALSE;
998 /* Acquire hive list lock exclusively */
999 ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE);
1001 Entry = CmiHiveListHead.Flink;
1002 while (Entry != &CmiHiveListHead)
1004 Hive = CONTAINING_RECORD(Entry, REGISTRY_HIVE, HiveList);
1006 if (IsPermanentHive(Hive))
1008 /* Acquire hive resource exclusively */
1009 ExAcquireResourceExclusiveLite(&Hive->HiveResource,
1012 /* Flush non-volatile hive */
1013 CmiFlushRegistryHive(Hive);
1015 /* Release hive resource */
1016 ExReleaseResourceLite(&Hive->HiveResource);
1019 Entry = Entry->Flink;
1022 /* Release hive list lock */
1023 ExReleaseResourceLite(&CmiHiveListLock);
1025 DPRINT("DeferredContext %x\n", DeferredContext);
1026 ExFreePool(DeferredContext);
1031 CmiHiveSyncDpcRoutine(PKDPC Dpc,
1032 PVOID DeferredContext,
1033 PVOID SystemArgument1,
1034 PVOID SystemArgument2)
1036 PWORK_QUEUE_ITEM WorkQueueItem;
1038 WorkQueueItem = ExAllocatePool(NonPagedPool,
1039 sizeof(WORK_QUEUE_ITEM));
1040 if (WorkQueueItem == NULL)
1042 DbgPrint("Failed to allocate work item\n");
1046 ExInitializeWorkItem(WorkQueueItem,
1050 DPRINT("DeferredContext %x\n", WorkQueueItem);
1051 ExQueueWorkItem(WorkQueueItem,
1059 LARGE_INTEGER Timeout;
1061 DPRINT("CmiSyncHives() called\n");
1063 if (CmiHiveSyncEnabled == FALSE ||
1064 CmiHiveSyncPending == TRUE)
1067 CmiHiveSyncPending = TRUE;
1070 Timeout.QuadPart = -50000000LL;
1071 KeSetTimer(&CmiHiveSyncTimer,