X-Git-Url: http://git.jankratochvil.net/?p=reactos.git;a=blobdiff_plain;f=ntoskrnl%2Fcm%2Fregistry.c;fp=ntoskrnl%2Fcm%2Fregistry.c;h=8b7769e1f4d0580358e9f10336809177fc9eed5c;hp=d0d9c1dc7ea1caf0044463dd379a9416e3afa70f;hb=e3ed2d773259cc445c7ff8181ebd934931365328;hpb=d378c68f5a9bb25c9e671dacd482d2e25d211df3 diff --git a/ntoskrnl/cm/registry.c b/ntoskrnl/cm/registry.c index d0d9c1d..8b7769e 100644 --- a/ntoskrnl/cm/registry.c +++ b/ntoskrnl/cm/registry.c @@ -11,17 +11,22 @@ * Created 22/05/98 */ +#ifdef WIN32_REGDBG +#include "cm_win32.h" +#else #include #include #include #include #include #include +#include #define NDEBUG #include #include "cm.h" +#endif /* ------------------------------------------------- File Statics */ @@ -29,6 +34,14 @@ POBJECT_TYPE CmiKeyType = NULL; PREGISTRY_HIVE CmiVolatileHive = NULL; KSPIN_LOCK CmiKeyListLock; +LIST_ENTRY CmiHiveListHead; +ERESOURCE CmiHiveListLock; + +volatile BOOLEAN CmiHiveSyncEnabled = FALSE; +volatile BOOLEAN CmiHiveSyncPending = FALSE; +KDPC CmiHiveSyncDpc; +KTIMER CmiHiveSyncTimer; + static PKEY_OBJECT CmiRootKey = NULL; static PKEY_OBJECT CmiMachineKey = NULL; static PKEY_OBJECT CmiUserKey = NULL; @@ -38,6 +51,7 @@ static GENERIC_MAPPING CmiKeyMapping = {KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS}; + VOID CmiCheckKey(BOOLEAN Verbose, HANDLE Key); @@ -45,6 +59,12 @@ CmiCheckKey(BOOLEAN Verbose, static NTSTATUS CmiCreateCurrentControlSetLink(VOID); +static VOID STDCALL +CmiHiveSyncDpcRoutine(PKDPC Dpc, + PVOID DeferredContext, + PVOID SystemArgument1, + PVOID SystemArgument2); + /* FUNCTIONS ****************************************************************/ VOID @@ -65,58 +85,58 @@ CmiCheckSubKeys(BOOLEAN Verbose, Index = 0; while (TRUE) { - BufferSize = sizeof(KEY_NODE_INFORMATION) + 4096; - KeyInfo = ExAllocatePool(PagedPool, BufferSize); - - Status = NtEnumerateKey(Key, - Index, - KeyNodeInformation, - KeyInfo, - BufferSize, - &ResultSize); + BufferSize = sizeof(KEY_NODE_INFORMATION) + 4096; + KeyInfo = ExAllocatePool(PagedPool, BufferSize); + + Status = NtEnumerateKey(Key, + Index, + KeyNodeInformation, + KeyInfo, + BufferSize, + &ResultSize); if (!NT_SUCCESS(Status)) - { - ExFreePool(KeyInfo); - if (Status == STATUS_NO_MORE_ENTRIES) - Status = STATUS_SUCCESS; - break; - } + { + ExFreePool(KeyInfo); + if (Status == STATUS_NO_MORE_ENTRIES) + Status = STATUS_SUCCESS; + break; + } wcsncpy(Name, - KeyInfo->Name, - KeyInfo->NameLength / sizeof(WCHAR)); + KeyInfo->Name, + KeyInfo->NameLength / sizeof(WCHAR)); if (Verbose) - { - DbgPrint("Key: %S\n", Name); - } + { + DbgPrint("Key: %S\n", Name); + } /* FIXME: Check info. */ ExFreePool(KeyInfo); - wcscpy(KeyBuffer, L"\\Registry\\"); - wcscat(KeyBuffer, Name); + wcscpy(KeyBuffer, L"\\Registry\\"); + wcscat(KeyBuffer, Name); - RtlInitUnicodeString(&KeyPath, KeyBuffer); + RtlInitUnicodeString(&KeyPath, KeyBuffer); - InitializeObjectAttributes(&ObjectAttributes, - &KeyPath, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); + InitializeObjectAttributes(&ObjectAttributes, + &KeyPath, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); - Status = NtOpenKey(&SubKey, - KEY_ALL_ACCESS, - &ObjectAttributes); + Status = NtOpenKey(&SubKey, + KEY_ALL_ACCESS, + &ObjectAttributes); - assert(NT_SUCCESS(Status)); - - CmiCheckKey(Verbose, SubKey); - - NtClose(SubKey); + assert(NT_SUCCESS(Status)); - Index++; + CmiCheckKey(Verbose, SubKey); + + NtClose(SubKey); + + Index++; } assert(NT_SUCCESS(Status)); @@ -137,37 +157,37 @@ CmiCheckValues(BOOLEAN Verbose, Index = 0; while (TRUE) { - BufferSize = sizeof(KEY_NODE_INFORMATION) + 4096; - ValueInfo = ExAllocatePool(PagedPool, BufferSize); - - Status = NtEnumerateValueKey(Key, - Index, - KeyNodeInformation, - ValueInfo, - BufferSize, - &ResultSize); + BufferSize = sizeof(KEY_NODE_INFORMATION) + 4096; + ValueInfo = ExAllocatePool(PagedPool, BufferSize); + + Status = NtEnumerateValueKey(Key, + Index, + KeyNodeInformation, + ValueInfo, + BufferSize, + &ResultSize); if (!NT_SUCCESS(Status)) - { - ExFreePool(ValueInfo); - if (Status == STATUS_NO_MORE_ENTRIES) - Status = STATUS_SUCCESS; - break; - } + { + ExFreePool(ValueInfo); + if (Status == STATUS_NO_MORE_ENTRIES) + Status = STATUS_SUCCESS; + break; + } wcsncpy(Name, - ValueInfo->Name, - ValueInfo->NameLength / sizeof(WCHAR)); + ValueInfo->Name, + ValueInfo->NameLength / sizeof(WCHAR)); if (Verbose) - { - DbgPrint("Value: %S\n", Name); - } + { + DbgPrint("Value: %S\n", Name); + } /* FIXME: Check info. */ ExFreePool(ValueInfo); - Index++; + Index++; } assert(NT_SUCCESS(Status)); @@ -196,7 +216,7 @@ CmiCheckByName(BOOLEAN Verbose, wcscpy(KeyPathBuffer, L"\\Registry\\"); wcscat(KeyPathBuffer, KeyName); - RtlInitUnicodeString(&KeyPath, KeyPathBuffer); + RtlInitUnicodeString(&KeyPath, KeyPathBuffer); InitializeObjectAttributes(&ObjectAttributes, &KeyPath, @@ -211,11 +231,11 @@ CmiCheckByName(BOOLEAN Verbose, if (CHECKED) { if (!NT_SUCCESS(Status)) - { + { DbgPrint("KeyPath %wZ Status: %.08x", KeyPath, Status); DbgPrint("KeyPath %S Status: %.08x", KeyPath.Buffer, Status); assert(NT_SUCCESS(Status)); - } + } } CmiCheckKey(Verbose, Key); @@ -244,7 +264,7 @@ CmInitializeRegistry(VOID) PKEY_OBJECT NewKey; HANDLE KeyHandle; NTSTATUS Status; - + /* Initialize the Key object type */ CmiKeyType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); assert(CmiKeyType); @@ -267,11 +287,15 @@ CmInitializeRegistry(VOID) CmiKeyType->DuplicationNotify = NULL; RtlInitUnicodeString(&CmiKeyType->TypeName, L"Key"); + /* Initialize the hive list */ + InitializeListHead(&CmiHiveListHead); + ExInitializeResourceLite(&CmiHiveListLock); + /* Build volatile registry store */ Status = CmiCreateRegistryHive(NULL, &CmiVolatileHive, FALSE); assert(NT_SUCCESS(Status)); - /* Build the Root Key Object */ + /* Create '\Registry' key. */ RtlInitUnicodeString(&RootKeyName, REG_ROOT_KEY_NAME); InitializeObjectAttributes(&ObjectAttributes, &RootKeyName, 0, NULL, NULL); Status = ObCreateObject(&RootKeyHandle, @@ -303,7 +327,7 @@ CmInitializeRegistry(VOID) /* Create initial predefined symbolic links */ - /* HKEY_LOCAL_MACHINE */ + /* Create '\Registry\Machine' key. */ Status = ObCreateObject(&KeyHandle, STANDARD_RIGHTS_REQUIRED, NULL, @@ -330,7 +354,7 @@ CmInitializeRegistry(VOID) CmiAddKeyToList(CmiRootKey, NewKey); CmiMachineKey = NewKey; - /* HKEY_USERS */ + /* Create '\Registry\User' key. */ Status = ObCreateObject(&KeyHandle, STANDARD_RIGHTS_REQUIRED, NULL, @@ -357,7 +381,7 @@ CmInitializeRegistry(VOID) CmiAddKeyToList(CmiRootKey, NewKey); CmiUserKey = NewKey; - /* Create '\\Registry\\Machine\\HARDWARE' key. */ + /* Create '\Registry\Machine\HARDWARE' key. */ Status = ObCreateObject(&KeyHandle, STANDARD_RIGHTS_REQUIRED, NULL, @@ -384,7 +408,7 @@ CmInitializeRegistry(VOID) CmiAddKeyToList(CmiMachineKey, NewKey); CmiHardwareKey = NewKey; - /* Create '\\Registry\\Machine\\HARDWARE\\DESCRIPTION' key. */ + /* Create '\Registry\Machine\HARDWARE\DESCRIPTION' key. */ Status = ObCreateObject(&KeyHandle, STANDARD_RIGHTS_REQUIRED, NULL, @@ -410,7 +434,7 @@ CmInitializeRegistry(VOID) memcpy(NewKey->Name, "DESCRIPTION", strlen("DESCRIPTION")); CmiAddKeyToList(CmiHardwareKey, NewKey); - /* Create '\\Registry\\Machine\\HARDWARE\\DEVICEMAP' key. */ + /* Create '\Registry\Machine\HARDWARE\DEVICEMAP' key. */ Status = ObCreateObject(&KeyHandle, STANDARD_RIGHTS_REQUIRED, NULL, @@ -436,7 +460,7 @@ CmInitializeRegistry(VOID) memcpy(NewKey->Name, "DEVICEMAP", strlen("DEVICEMAP")); CmiAddKeyToList(CmiHardwareKey,NewKey); - /* Create '\\Registry\\Machine\\HARDWARE\\RESOURCEMAP' key. */ + /* Create '\Registry\Machine\HARDWARE\RESOURCEMAP' key. */ Status = ObCreateObject(&KeyHandle, STANDARD_RIGHTS_REQUIRED, NULL, @@ -472,13 +496,21 @@ CmInit2(PCHAR CommandLine) { PCHAR p1, p2; ULONG PiceStart; + NTSTATUS Status; - /* FIXME: Store current command line */ + /* FIXME: Store system start options */ - /* Create the 'CurrentControlSet' link. */ - CmiCreateCurrentControlSetLink(); + /* Create the 'CurrentControlSet' link. */ + Status = CmiCreateCurrentControlSetLink(); +#ifndef WIN32_REGDBG + if (!NT_SUCCESS(Status)) + { + KeBugCheck(CONFIG_INITIALIZATION_FAILED); + } +#endif + /* Set PICE 'Start' value to 1, if PICE debugging is enabled */ PiceStart = 4; p1 = (PCHAR)CommandLine; @@ -500,14 +532,18 @@ CmInit2(PCHAR CommandLine) } p1 = p2; } - - RtlWriteRegistryValue(RTL_REGISTRY_SERVICES, - L"\\Pice", - L"Start", - REG_DWORD, - &PiceStart, - sizeof(ULONG)); - +#ifndef WIN32_REGDBG + Status = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES, + L"\\Pice", + L"Start", + REG_DWORD, + &PiceStart, + sizeof(ULONG)); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(CONFIG_INITIALIZATION_FAILED); + } +#endif } @@ -588,12 +624,12 @@ CmiCreateCurrentControlSetLink(VOID) RtlInitUnicodeStringFromLiteral(&LinkValue, L"SymbolicLinkValue"); - Status=NtSetValueKey(KeyHandle, - &LinkValue, - 0, - REG_LINK, - (PVOID)TargetNameBuffer, - TargetNameLength); + Status = NtSetValueKey(KeyHandle, + &LinkValue, + 0, + REG_LINK, + (PVOID)TargetNameBuffer, + TargetNameLength); if (!NT_SUCCESS(Status)) { DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status); @@ -619,11 +655,15 @@ CmiConnectHive(PWSTR FileName, HANDLE KeyHandle; NTSTATUS Status; - DPRINT("Called. FileName %S\n", FullName); + DPRINT("CmiConnectHive(%S, %S, %s, %p, %d) - Called.\n", FileName, FullName, KeyName, Parent, CreateNew); Status = CmiCreateRegistryHive(FileName, &RegistryHive, CreateNew); if (!NT_SUCCESS(Status)) - return(Status); + { + DPRINT1("CmiCreateRegistryHive() failed (Status %lx)\n", Status); + KeBugCheck(0); + return(Status); + } RtlInitUnicodeString(&uKeyName, FullName); @@ -639,7 +679,12 @@ CmiConnectHive(PWSTR FileName, CmiKeyType, (PVOID*)&NewKey); if (!NT_SUCCESS(Status)) - return(Status); + { + DPRINT1("ObCreateObject() failed (Status %lx)\n", Status); + KeBugCheck(0); + CmiRemoveRegistryHive(RegistryHive); + return(Status); + } NewKey->RegistryHive = RegistryHive; NewKey->BlockOffset = RegistryHive->HiveHeader->RootKeyCell; @@ -651,9 +696,9 @@ CmiConnectHive(PWSTR FileName, if ((NewKey->SubKeys == NULL) && (NewKey->KeyCell->NumberOfSubKeys != 0)) { - /* FIXME: Cleanup from CmiCreateRegistryHive() */ DPRINT("NumberOfSubKeys %d\n", NewKey->KeyCell->NumberOfSubKeys); ZwClose(NewKey); + CmiRemoveRegistryHive(RegistryHive); return(STATUS_INSUFFICIENT_RESOURCES); } @@ -662,11 +707,11 @@ CmiConnectHive(PWSTR FileName, if ((NewKey->Name == NULL) && (strlen(KeyName) != 0)) { - /* FIXME: Cleanup from CmiCreateRegistryHive() */ DPRINT("strlen(KeyName) %d\n", strlen(KeyName)); if (NewKey->SubKeys != NULL) ExFreePool(NewKey->SubKeys); ZwClose(NewKey); + CmiRemoveRegistryHive(RegistryHive); return(STATUS_INSUFFICIENT_RESOURCES); } @@ -697,23 +742,25 @@ CmiInitializeHive(PWSTR FileName, if (!NT_SUCCESS(Status)) { - DPRINT("Status %.08x\n", Status); #if 0 +#ifdef WIN32_REGDBG WCHAR AltFileName[MAX_PATH]; CPRINT("WARNING! Registry file %S not found\n", FileName); + //DPRINT("Status %.08x\n", Status); wcscpy(AltFileName, FileName); wcscat(AltFileName, L".alt"); + DPRINT("Attempting to connect the alternative hive %S\n", AltFileName); /* Try to connect the alternative hive */ Status = CmiConnectHive(AltFileName, FullName, KeyName, Parent, TRUE); - if (!NT_SUCCESS(Status)) - { - CPRINT("WARNING! Alternative registry file %S not found\n", AltFileName); - DPRINT("Status %.08x\n", Status); - } + if (!NT_SUCCESS(Status)) { + CPRINT("WARNING! Alternative registry file %S not found\n", AltFileName); + //DPRINT("Status %.08x\n", Status); + } +#endif #endif } @@ -726,39 +773,166 @@ CmiInitializeHive(PWSTR FileName, NTSTATUS CmiInitHives(BOOLEAN SetUpBoot) { + PKEY_VALUE_PARTIAL_INFORMATION ValueInfo; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING KeyName; + UNICODE_STRING ValueName; + HANDLE KeyHandle; + NTSTATUS Status; + WCHAR ConfigPath[MAX_PATH]; + + ULONG BufferSize; + ULONG ResultSize; + PWSTR EndPtr; + + DPRINT("CmiInitHives() called\n"); + if (SetUpBoot == TRUE) + { + RtlInitUnicodeStringFromLiteral(&KeyName, + L"\\Registry\\Machine\\HARDWARE"); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtOpenKey(&KeyHandle, + KEY_ALL_ACCESS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtOpenKey() failed (Status %lx)\n", Status); + return(Status); + } + + RtlInitUnicodeStringFromLiteral(&ValueName, + L"InstallPath"); + + BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096; + ValueInfo = ExAllocatePool(PagedPool, + BufferSize); + if (ValueInfo == NULL) + { + NtClose(KeyHandle); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Status = NtQueryValueKey(KeyHandle, + &ValueName, + KeyValuePartialInformation, + ValueInfo, + BufferSize, + &ResultSize); + NtClose(KeyHandle); + if (ValueInfo == NULL) + { + ExFreePool(ValueInfo); + return(Status); + } + + RtlCopyMemory(ConfigPath, + ValueInfo->Data, + ValueInfo->DataLength); + ConfigPath[ValueInfo->DataLength / sizeof(WCHAR)] = (WCHAR)0; + ExFreePool(ValueInfo); + } + else + { + wcscpy(ConfigPath, L"\\SystemRoot"); + } + wcscat(ConfigPath, L"\\system32\\config"); + + DPRINT("ConfigPath: %S\n", ConfigPath); + + EndPtr = ConfigPath + wcslen(ConfigPath); + CmiDoVerify = TRUE; - /* FIXME: Delete temporary \Registry\Machine\System */ + /* FIXME: Save boot log */ + + /* FIXME: Rename \Registry\Machine\System */ /* Connect the SYSTEM hive */ - /* FIXME: Don't overwrite the existing 'System' hive yet */ -// Status = CmiInitializeHive(SYSTEM_REG_FILE, REG_SYSTEM_KEY_NAME, "System", CmiMachineKey); +// Status = CmiInitializeHive(SYSTEM_REG_FILE, REG_SYSTEM_KEY_NAME, "System", CmiMachineKey, SetUpBoot); // assert(NT_SUCCESS(Status)); + /* FIXME: Synchronize old and new system hive (??) */ + + /* FIXME: Delete old system hive */ + /* Connect the SOFTWARE hive */ - Status = CmiInitializeHive(SOFTWARE_REG_FILE, REG_SOFTWARE_KEY_NAME, "Software", CmiMachineKey, SetUpBoot); - //assert(NT_SUCCESS(Status)); + wcscpy(EndPtr, REG_SOFTWARE_FILE_NAME); + DPRINT1("ConfigPath: %S\n", ConfigPath); + + Status = CmiInitializeHive(ConfigPath, + REG_SOFTWARE_KEY_NAME, + "Software", + CmiMachineKey, + SetUpBoot); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status); + return(Status); + } /* Connect the SAM hive */ - Status = CmiInitializeHive(SAM_REG_FILE,REG_SAM_KEY_NAME, "Sam", CmiMachineKey, SetUpBoot); - //assert(NT_SUCCESS(Status)); + wcscpy(EndPtr, REG_SAM_FILE_NAME); + DPRINT1("ConfigPath: %S\n", ConfigPath); + + Status = CmiInitializeHive(ConfigPath, + REG_SAM_KEY_NAME, + "Sam", + CmiMachineKey, + SetUpBoot); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status); + return(Status); + } /* Connect the SECURITY hive */ - Status = CmiInitializeHive(SEC_REG_FILE, REG_SEC_KEY_NAME, "Security", CmiMachineKey, SetUpBoot); - //assert(NT_SUCCESS(Status)); + wcscpy(EndPtr, REG_SEC_FILE_NAME); + DPRINT1("ConfigPath: %S\n", ConfigPath); + Status = CmiInitializeHive(ConfigPath, + REG_SEC_KEY_NAME, + "Security", + CmiMachineKey, + SetUpBoot); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status); + return(Status); + } /* Connect the DEFAULT hive */ - Status = CmiInitializeHive(USER_REG_FILE, REG_USER_KEY_NAME, ".Default", CmiUserKey, SetUpBoot); - //assert(NT_SUCCESS(Status)); + wcscpy(EndPtr, REG_USER_FILE_NAME); + DPRINT1("ConfigPath: %S\n", ConfigPath); + + Status = CmiInitializeHive(ConfigPath, + REG_USER_KEY_NAME, + ".Default", + CmiUserKey, + SetUpBoot); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status); + return(Status); + } /* FIXME : initialize standards symbolic links */ // CmiCheckRegistry(TRUE); + /* Start automatic hive synchronization */ + KeInitializeDpc(&CmiHiveSyncDpc, + CmiHiveSyncDpcRoutine, + NULL); + KeInitializeTimer(&CmiHiveSyncTimer); + CmiHiveSyncEnabled = TRUE; + DPRINT("CmiInitHives() done\n"); return(STATUS_SUCCESS); @@ -768,12 +942,135 @@ CmiInitHives(BOOLEAN SetUpBoot) VOID CmShutdownRegistry(VOID) { - DPRINT("CmShutdownRegistry() called\n"); + PREGISTRY_HIVE Hive; + PLIST_ENTRY Entry; + + DPRINT1("CmShutdownRegistry() called\n"); + + /* Stop automatic hive synchronization */ + CmiHiveSyncEnabled = FALSE; + + /* Acquire hive list lock exclusively */ + ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE); + + Entry = CmiHiveListHead.Flink; + while (Entry != &CmiHiveListHead) + { + Hive = CONTAINING_RECORD(Entry, REGISTRY_HIVE, HiveList); + + if (IsPermanentHive(Hive)) + { + /* Acquire hive resource exclusively */ + ExAcquireResourceExclusiveLite(&Hive->HiveResource, + TRUE); + + /* Flush non-volatile hive */ + CmiFlushRegistryHive(Hive); + + /* Dereference file */ + ObDereferenceObject(Hive->FileObject); + Hive->FileObject = NULL; + + /* Release hive resource */ + ExReleaseResourceLite(&Hive->HiveResource); + } + + Entry = Entry->Flink; + } + + /* Release hive list lock */ + ExReleaseResourceLite(&CmiHiveListLock); + + DPRINT1("CmShutdownRegistry() done\n"); +} + + +VOID STDCALL +CmiHiveSyncRoutine(PVOID DeferredContext) +{ + PREGISTRY_HIVE Hive; + PLIST_ENTRY Entry; + + DPRINT1("CmiHiveSyncRoutine() called\n"); + + CmiHiveSyncPending = FALSE; + + /* Acquire hive list lock exclusively */ + ExAcquireResourceExclusiveLite(&CmiHiveListLock, TRUE); + + Entry = CmiHiveListHead.Flink; + while (Entry != &CmiHiveListHead) + { + Hive = CONTAINING_RECORD(Entry, REGISTRY_HIVE, HiveList); + + if (IsPermanentHive(Hive)) + { + /* Acquire hive resource exclusively */ + ExAcquireResourceExclusiveLite(&Hive->HiveResource, + TRUE); + + /* Flush non-volatile hive */ + CmiFlushRegistryHive(Hive); + + /* Release hive resource */ + ExReleaseResourceLite(&Hive->HiveResource); + } + + Entry = Entry->Flink; + } + + /* Release hive list lock */ + ExReleaseResourceLite(&CmiHiveListLock); + + DPRINT("DeferredContext %x\n", DeferredContext); + ExFreePool(DeferredContext); +} + + +static VOID STDCALL +CmiHiveSyncDpcRoutine(PKDPC Dpc, + PVOID DeferredContext, + PVOID SystemArgument1, + PVOID SystemArgument2) +{ + PWORK_QUEUE_ITEM WorkQueueItem; + + WorkQueueItem = ExAllocatePool(NonPagedPool, + sizeof(WORK_QUEUE_ITEM)); + if (WorkQueueItem == NULL) + { + DbgPrint("Failed to allocate work item\n"); + return; + } + + ExInitializeWorkItem(WorkQueueItem, + CmiHiveSyncRoutine, + WorkQueueItem); + + DPRINT("DeferredContext %x\n", WorkQueueItem); + ExQueueWorkItem(WorkQueueItem, + CriticalWorkQueue); +} + + +VOID +CmiSyncHives(VOID) +{ + LARGE_INTEGER Timeout; + + DPRINT("CmiSyncHives() called\n"); + + if (CmiHiveSyncEnabled == FALSE || + CmiHiveSyncPending == TRUE) + return; + + CmiHiveSyncPending = TRUE; + - /* Note: - * Don't call UNIMPLEMENTED() here since this function is - * called by NtShutdownSystem(). - */ + Timeout.QuadPart = -50000000LL; + KeSetTimer(&CmiHiveSyncTimer, + Timeout, + &CmiHiveSyncDpc); } /* EOF */