* Created 22/05/98
*/
+#ifdef WIN32_REGDBG
+#include "cm_win32.h"
+#else
#include <ddk/ntddk.h>
#include <roscfg.h>
#include <limits.h>
#include <string.h>
#include <internal/pool.h>
#include <internal/registry.h>
+#include <reactos/bugcodes.h>
#define NDEBUG
#include <internal/debug.h>
#include "cm.h"
+#endif
/* ------------------------------------------------- File Statics */
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;
{KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS};
+
VOID
CmiCheckKey(BOOLEAN Verbose,
HANDLE Key);
static NTSTATUS
CmiCreateCurrentControlSetLink(VOID);
+static VOID STDCALL
+CmiHiveSyncDpcRoutine(PKDPC Dpc,
+ PVOID DeferredContext,
+ PVOID SystemArgument1,
+ PVOID SystemArgument2);
+
/* FUNCTIONS ****************************************************************/
VOID
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));
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));
wcscpy(KeyPathBuffer, L"\\Registry\\");
wcscat(KeyPathBuffer, KeyName);
- RtlInitUnicodeString(&KeyPath, KeyPathBuffer);
+ RtlInitUnicodeString(&KeyPath, KeyPathBuffer);
InitializeObjectAttributes(&ObjectAttributes,
&KeyPath,
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);
PKEY_OBJECT NewKey;
HANDLE KeyHandle;
NTSTATUS Status;
-
+
/* Initialize the Key object type */
CmiKeyType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
assert(CmiKeyType);
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,
/* Create initial predefined symbolic links */
- /* HKEY_LOCAL_MACHINE */
+ /* Create '\Registry\Machine' key. */
Status = ObCreateObject(&KeyHandle,
STANDARD_RIGHTS_REQUIRED,
NULL,
CmiAddKeyToList(CmiRootKey, NewKey);
CmiMachineKey = NewKey;
- /* HKEY_USERS */
+ /* Create '\Registry\User' key. */
Status = ObCreateObject(&KeyHandle,
STANDARD_RIGHTS_REQUIRED,
NULL,
CmiAddKeyToList(CmiRootKey, NewKey);
CmiUserKey = NewKey;
- /* Create '\\Registry\\Machine\\HARDWARE' key. */
+ /* Create '\Registry\Machine\HARDWARE' key. */
Status = ObCreateObject(&KeyHandle,
STANDARD_RIGHTS_REQUIRED,
NULL,
CmiAddKeyToList(CmiMachineKey, NewKey);
CmiHardwareKey = NewKey;
- /* Create '\\Registry\\Machine\\HARDWARE\\DESCRIPTION' key. */
+ /* Create '\Registry\Machine\HARDWARE\DESCRIPTION' key. */
Status = ObCreateObject(&KeyHandle,
STANDARD_RIGHTS_REQUIRED,
NULL,
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,
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,
{
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;
}
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
}
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);
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);
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;
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);
}
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);
}
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
}
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);
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 */