#include "cm.h"
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, CmInitHives)
+#pragma alloc_text(INIT, CmInitializeRegistry)
+#pragma alloc_text(INIT, CmInit2)
+#endif
+
+
/* GLOBALS ******************************************************************/
POBJECT_TYPE CmiKeyType = NULL;
PREGISTRY_HIVE CmiVolatileHive = NULL;
-KSPIN_LOCK CmiKeyListLock;
LIST_ENTRY CmiHiveListHead;
ERESOURCE CmiRegistryLock;
+KTIMER CmiWorkerTimer;
+LIST_ENTRY CmiKeyObjectListHead;
+ULONG CmiTimer = 0;
+
volatile BOOLEAN CmiHiveSyncEnabled = FALSE;
volatile BOOLEAN CmiHiveSyncPending = FALSE;
KDPC CmiHiveSyncDpc;
CmiCheckByName(Verbose, L"User");
}
+VOID STDCALL
+CmiWorkerThread(PVOID Param)
+{
+ NTSTATUS Status;
+ PLIST_ENTRY CurrentEntry;
+ PKEY_OBJECT CurrentKey;
+ ULONG Count;
+
-VOID INIT_FUNCTION
+ while (1)
+ {
+ Status = KeWaitForSingleObject(&CmiWorkerTimer,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ if (Status == STATUS_SUCCESS)
+ {
+ DPRINT("CmiWorkerThread\n");
+
+ /* Acquire hive lock */
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
+
+ CmiTimer++;
+
+ Count = 0;
+ CurrentEntry = CmiKeyObjectListHead.Blink;
+ while (CurrentEntry != &CmiKeyObjectListHead)
+ {
+ CurrentKey = CONTAINING_RECORD(CurrentEntry, KEY_OBJECT, ListEntry);
+ if (CurrentKey->TimeStamp + 120 > CmiTimer)
+ {
+ /* The object was accessed in the last 10min */
+ break;
+ }
+ if (1 == ObGetObjectPointerCount(CurrentKey) &&
+ !(CurrentKey->Flags & KO_MARKED_FOR_DELETE))
+ {
+ ObDereferenceObject(CurrentKey);
+ CurrentEntry = CmiKeyObjectListHead.Blink;
+ Count++;
+ }
+ else
+ {
+ CurrentEntry = CurrentEntry->Blink;
+ }
+ }
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+
+ DPRINT("Removed %d key objects\n", Count);
+
+ }
+ else
+ {
+ KEBUGCHECK(0);
+ }
+ }
+}
+
+VOID
+INIT_FUNCTION
+STDCALL
+CmInitHives(BOOLEAN SetupBoot)
+{
+ PCHAR BaseAddress;
+
+ /* Load Registry Hives. This one can be missing. */
+ if (CachedModules[SystemRegistry]) {
+ BaseAddress = (PCHAR)CachedModules[SystemRegistry]->ModStart;
+ CmImportSystemHive(BaseAddress,
+ CachedModules[SystemRegistry]->ModEnd - (ULONG_PTR)BaseAddress);
+ }
+
+ BaseAddress = (PCHAR)CachedModules[HardwareRegistry]->ModStart;
+ CmImportHardwareHive(BaseAddress,
+ CachedModules[HardwareRegistry]->ModEnd - (ULONG_PTR)BaseAddress);
+
+
+ /* Create dummy keys if no hardware hive was found */
+ CmImportHardwareHive (NULL, 0);
+
+ /* Initialize volatile registry settings */
+ if (SetupBoot == FALSE) CmInit2((PCHAR)KeLoaderBlock.CommandLine);
+}
+
+VOID
+INIT_FUNCTION
CmInitializeRegistry(VOID)
{
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE RootKeyHandle;
HANDLE KeyHandle;
NTSTATUS Status;
+ LARGE_INTEGER DueTime;
+ HANDLE ThreadHandle;
+ CLIENT_ID ThreadId;
+ OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
+ UNICODE_STRING Name;
+ DPRINT("Creating Registry Object Type\n");
+
/* Initialize the Key object type */
- CmiKeyType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
- ASSERT(CmiKeyType);
- CmiKeyType->Tag = TAG('R', 'e', 'g', 'K');
- CmiKeyType->TotalObjects = 0;
- CmiKeyType->TotalHandles = 0;
- CmiKeyType->PeakObjects = 0;
- CmiKeyType->PeakHandles = 0;
- CmiKeyType->PagedPoolCharge = 0;
- CmiKeyType->NonpagedPoolCharge = sizeof(KEY_OBJECT);
- CmiKeyType->Mapping = &CmiKeyMapping;
- CmiKeyType->Dump = NULL;
- CmiKeyType->Open = NULL;
- CmiKeyType->Close = NULL;
- CmiKeyType->Delete = CmiObjectDelete;
- CmiKeyType->Parse = CmiObjectParse;
- CmiKeyType->Security = CmiObjectSecurity;
- CmiKeyType->QueryName = CmiObjectQueryName;
- CmiKeyType->OkayToClose = NULL;
- CmiKeyType->Create = CmiObjectCreate;
- CmiKeyType->DuplicationNotify = NULL;
- RtlInitUnicodeString(&CmiKeyType->TypeName, L"Key");
-
- ObpCreateTypeObject (CmiKeyType);
+ RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
+ RtlInitUnicodeString(&Name, L"Key");
+ ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
+ ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(KEY_OBJECT);
+ ObjectTypeInitializer.GenericMapping = CmiKeyMapping;
+ ObjectTypeInitializer.PoolType = PagedPool;
+ ObjectTypeInitializer.ValidAccessMask = KEY_ALL_ACCESS;
+ ObjectTypeInitializer.UseDefaultObject = TRUE;
+ ObjectTypeInitializer.DeleteProcedure = CmiObjectDelete;
+ ObjectTypeInitializer.ParseProcedure = CmiObjectParse;
+ ObjectTypeInitializer.SecurityProcedure = CmiObjectSecurity;
+ ObjectTypeInitializer.QueryNameProcedure = CmiObjectQueryName;
+
+ ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &CmiKeyType);
/* Initialize the hive list */
InitializeListHead(&CmiHiveListHead);
/* Initialize registry lock */
ExInitializeResourceLite(&CmiRegistryLock);
+ /* Initialize the key object list */
+ InitializeListHead(&CmiKeyObjectListHead);
+
+ /* Initialize the worker timer */
+ KeInitializeTimerEx(&CmiWorkerTimer, SynchronizationTimer);
+
+ /* Initialize the worker thread */
+ Status = PsCreateSystemThread(&ThreadHandle,
+ THREAD_ALL_ACCESS,
+ NULL,
+ NULL,
+ &ThreadId,
+ CmiWorkerThread,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ KEBUGCHECK(0);
+ }
+
+ /* Start the timer */
+ DueTime.QuadPart = -1;
+ KeSetTimerEx(&CmiWorkerTimer, DueTime, 5000, NULL); /* 5sec */
+
/* Build volatile registry store */
Status = CmiCreateVolatileHive (&CmiVolatileHive);
ASSERT(NT_SUCCESS(Status));
-
+
InitializeListHead(&CmiCallbackHead);
ExInitializeFastMutex(&CmiCallbackLock);
ASSERT(NT_SUCCESS(Status));
Status = ObInsertObject(RootKey,
NULL,
- STANDARD_RIGHTS_REQUIRED,
+ KEY_ALL_ACCESS,
0,
NULL,
&RootKeyHandle);
RootKey->NumberOfSubKeys = 0;
RootKey->SubKeys = NULL;
RootKey->SizeOfSubKeys = 0;
+ InsertTailList(&CmiKeyObjectListHead, &RootKey->ListEntry);
Status = RtlpCreateUnicodeString(&RootKey->Name, L"Registry", NonPagedPool);
ASSERT(NT_SUCCESS(Status));
CmiVolatileHive->RootSecurityCell = RootSecurityCell;
#endif
- KeInitializeSpinLock(&CmiKeyListLock);
/* Create '\Registry\Machine' key. */
RtlInitUnicodeString(&KeyName,
RootKeyHandle,
NULL);
Status = ZwCreateKey(&KeyHandle,
- STANDARD_RIGHTS_REQUIRED,
+ KEY_ALL_ACCESS,
&ObjectAttributes,
0,
NULL,
RootKeyHandle,
NULL);
Status = ZwCreateKey(&KeyHandle,
- STANDARD_RIGHTS_REQUIRED,
+ KEY_ALL_ACCESS,
&ObjectAttributes,
0,
NULL,
MiniNT = TRUE;
else if (!_strnicmp(CommandLine, "DEBUGPORT=PICE", 14))
PiceStart = 1;
-
+
/* Add a space between the options */
if (Position != 0)
SystemStartOptions[Position++] = L' ';
RTL_QUERY_REGISTRY_TABLE QueryTable[5];
WCHAR TargetNameBuffer[80];
ULONG TargetNameLength;
- UNICODE_STRING LinkName;
- UNICODE_STRING LinkValue;
+ UNICODE_STRING LinkName = RTL_CONSTANT_STRING(
+ L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
+ UNICODE_STRING LinkValue = RTL_CONSTANT_STRING(L"SymbolicLinkValue");
ULONG CurrentSet;
ULONG DefaultSet;
ULONG Failed;
DPRINT("Link target '%S'\n", TargetNameBuffer);
- RtlRosInitUnicodeStringFromLiteral(&LinkName,
- L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
InitializeObjectAttributes(&ObjectAttributes,
&LinkName,
OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_OPENLINK,
return(Status);
}
- RtlRosInitUnicodeStringFromLiteral(&LinkValue,
- L"SymbolicLinkValue");
Status = ZwSetValueKey(KeyHandle,
&LinkValue,
0,
PKEY_OBJECT NewKey;
NTSTATUS Status;
PWSTR SubName;
+ UNICODE_STRING ObjectName;
+ OBJECT_CREATE_INFORMATION ObjectCreateInfo;
DPRINT("CmiConnectHive(%p, %p) called.\n",
KeyObjectAttributes, RegistryHive);
-
- Status = ObFindObject(KeyObjectAttributes,
- (PVOID*)&ParentKey,
- &RemainingPath,
- CmiKeyType);
+
+ /* Capture all the info */
+ DPRINT("Capturing Create Info\n");
+ Status = ObpCaptureObjectAttributes(KeyObjectAttributes,
+ KernelMode,
+ CmiKeyType,
+ &ObjectCreateInfo,
+ &ObjectName);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ Status = ObFindObject(&ObjectCreateInfo,
+ &ObjectName,
+ (PVOID*)&ParentKey,
+ &RemainingPath,
+ CmiKeyType);
+ ObpReleaseCapturedAttributes(&ObjectCreateInfo);
+ if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
if (!NT_SUCCESS(Status))
{
return Status;
0,
0,
(PVOID*)&NewKey);
+
if (!NT_SUCCESS(Status))
{
DPRINT1 ("ObCreateObject() failed (Status %lx)\n", Status);
RtlFreeUnicodeString(&RemainingPath);
return Status;
}
-
+ DPRINT("Inserting Key into Object Tree\n");
+ Status = ObInsertObject((PVOID)NewKey,
+ NULL,
+ KEY_ALL_ACCESS,
+ 0,
+ NULL,
+ NULL);
+DPRINT("Status %x\n", Status);
NewKey->RegistryHive = RegistryHive;
NewKey->KeyCellOffset = RegistryHive->HiveHeader->RootKeyOffset;
NewKey->KeyCell = CmiGetCell (RegistryHive, NewKey->KeyCellOffset, NULL);
NewKey->Flags = 0;
NewKey->NumberOfSubKeys = 0;
+ InsertTailList(&CmiKeyObjectListHead, &NewKey->ListEntry);
if (NewKey->KeyCell->NumberOfSubKeys != 0)
{
NewKey->SubKeys = ExAllocatePool(NonPagedPool,
PREGISTRY_HIVE Hive;
HANDLE KeyHandle;
NTSTATUS Status;
+ PLIST_ENTRY CurrentEntry;
+ PKEY_OBJECT CurrentKey;
DPRINT("CmiDisconnectHive() called\n");
return STATUS_INVALID_PARAMETER;
}
+ /* Acquire registry lock exclusively */
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
+
+ CurrentEntry = CmiKeyObjectListHead.Flink;
+ while (CurrentEntry != &CmiKeyObjectListHead)
+ {
+ CurrentKey = CONTAINING_RECORD(CurrentEntry, KEY_OBJECT, ListEntry);
+ if (1 == ObGetObjectPointerCount(CurrentKey) &&
+ !(CurrentKey->Flags & KO_MARKED_FOR_DELETE))
+ {
+ ObDereferenceObject(CurrentKey);
+ CurrentEntry = CmiKeyObjectListHead.Flink;
+ }
+ else
+ {
+ CurrentEntry = CurrentEntry->Flink;
+ }
+ }
+
if (ObGetObjectHandleCount (KeyObject) != 0 ||
ObGetObjectPointerCount (KeyObject) != 2)
{
- DPRINT1 ("Hive is still in use\n");
+ DPRINT1 ("Hive is still in use (hc %d, rc %d)\n", ObGetObjectHandleCount (KeyObject), ObGetObjectPointerCount (KeyObject));
ObDereferenceObject (KeyObject);
+
+ /* Release registry lock */
+ ExReleaseResourceLite (&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+
return STATUS_UNSUCCESSFUL;
}
*RegistryHive = Hive;
+ /* Release registry lock */
+ ExReleaseResourceLite (&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+
DPRINT ("CmiDisconnectHive() done\n");
return STATUS_SUCCESS;
CmiInitControlSetLink (VOID)
{
OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING ControlSetKeyName;
- UNICODE_STRING ControlSetLinkName;
- UNICODE_STRING ControlSetValueName;
+ UNICODE_STRING ControlSetKeyName = RTL_CONSTANT_STRING(
+ L"\\Registry\\Machine\\SYSTEM\\ControlSet001");
+ UNICODE_STRING ControlSetLinkName = RTL_CONSTANT_STRING(
+ L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
+ UNICODE_STRING ControlSetValueName = RTL_CONSTANT_STRING(L"SymbolicLinkValue");
HANDLE KeyHandle;
NTSTATUS Status;
/* Create 'ControlSet001' key */
- RtlRosInitUnicodeStringFromLiteral (&ControlSetKeyName,
- L"\\Registry\\Machine\\SYSTEM\\ControlSet001");
InitializeObjectAttributes (&ObjectAttributes,
&ControlSetKeyName,
OBJ_CASE_INSENSITIVE,
ZwClose (KeyHandle);
/* Link 'CurrentControlSet' to 'ControlSet001' key */
- RtlRosInitUnicodeStringFromLiteral (&ControlSetLinkName,
- L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
InitializeObjectAttributes (&ObjectAttributes,
&ControlSetLinkName,
OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_OPENLINK,
return Status;
}
- RtlRosInitUnicodeStringFromLiteral (&ControlSetValueName,
- L"SymbolicLinkValue");
Status = ZwSetValueKey (KeyHandle,
&ControlSetValueName,
0,
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING FileName;
- UNICODE_STRING KeyName;
- UNICODE_STRING ValueName;
+ UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\HARDWARE");
+ UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"InstallPath");
HANDLE KeyHandle;
NTSTATUS Status;
if (SetupBoot == TRUE)
{
- RtlRosInitUnicodeStringFromLiteral(&KeyName,
- L"\\Registry\\Machine\\HARDWARE");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
return(Status);
}
- RtlRosInitUnicodeStringFromLiteral(&ValueName,
- L"InstallPath");
-
BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096;
ValueInfo = ExAllocatePool(PagedPool,
BufferSize);
ExReleaseResourceLite(&CmiRegistryLock);
KeLeaveCriticalRegion();
- DPRINT("DeferredContext %x\n", DeferredContext);
+ DPRINT("DeferredContext 0x%p\n", DeferredContext);
ExFreePool(DeferredContext);
DPRINT("CmiHiveSyncRoutine() done\n");
CmiHiveSyncRoutine,
WorkQueueItem);
- DPRINT("DeferredContext %x\n", WorkQueueItem);
+ DPRINT("DeferredContext 0x%p\n", WorkQueueItem);
ExQueueWorkItem(WorkQueueItem,
CriticalWorkQueue);
}