mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
Fixed reference counting in CmiConnectHive and CmiDisconnectHive.
No longer need hacks to check reference counts. Deleted a ton of wierd code. Fixed bug where we allocated uninitialized memory for child nodes we never populated. Now reference counting mirrors pointers exactly: - Hold one reference for the parent key pointer - Hold one reference for the list entry in the connected hive list svn path=/trunk/; revision=22684
This commit is contained in:
parent
c6661f1f9e
commit
61cb74d018
4 changed files with 143 additions and 171 deletions
|
@ -358,6 +358,9 @@ typedef struct _KEY_OBJECT
|
|||
|
||||
/* Time stamp for the last access by the parse routine */
|
||||
ULONG TimeStamp;
|
||||
|
||||
/* List entry for connected hives */
|
||||
LIST_ENTRY HiveList;
|
||||
} KEY_OBJECT, *PKEY_OBJECT;
|
||||
|
||||
/* Bits 31-22 (top 10 bits) of the cell index is the directory index */
|
||||
|
|
|
@ -143,6 +143,8 @@ CmImportBinaryHive (PCHAR ChunkBase,
|
|||
KeEnterCriticalRegion();
|
||||
ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
|
||||
|
||||
DPRINT1("Adding new hive\n");
|
||||
|
||||
/* Add the new hive to the hive list */
|
||||
InsertTailList(&CmiHiveListHead, &Hive->HiveList);
|
||||
|
||||
|
@ -195,7 +197,6 @@ CmImportSystemHive(PCHAR ChunkBase,
|
|||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1 ("CmiConnectHive(%wZ) failed (Status %lx)\n", &KeyName, Status);
|
||||
// CmiRemoveRegistryHive(RegistryHive);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ ERESOURCE CmiRegistryLock;
|
|||
|
||||
KTIMER CmiWorkerTimer;
|
||||
LIST_ENTRY CmiKeyObjectListHead;
|
||||
LIST_ENTRY CmiConnectedHiveList;
|
||||
ULONG CmiTimer = 0;
|
||||
|
||||
volatile BOOLEAN CmiHiveSyncEnabled = FALSE;
|
||||
|
@ -385,6 +386,7 @@ CmInitializeRegistry(VOID)
|
|||
|
||||
/* Initialize the key object list */
|
||||
InitializeListHead(&CmiKeyObjectListHead);
|
||||
InitializeListHead(&CmiConnectedHiveList);
|
||||
|
||||
/* Initialize the worker timer */
|
||||
KeInitializeTimerEx(&CmiWorkerTimer, SynchronizationTimer);
|
||||
|
@ -694,92 +696,94 @@ CmiCreateCurrentControlSetLink(VOID)
|
|||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
|
||||
IN PREGISTRY_HIVE RegistryHive)
|
||||
{
|
||||
UNICODE_STRING RemainingPath;
|
||||
PKEY_OBJECT ParentKey;
|
||||
PKEY_OBJECT NewKey;
|
||||
NTSTATUS Status;
|
||||
PWSTR SubName;
|
||||
UNICODE_STRING ObjectName;
|
||||
OBJECT_CREATE_INFORMATION ObjectCreateInfo;
|
||||
UNICODE_STRING RemainingPath;
|
||||
PKEY_OBJECT ParentKey;
|
||||
PKEY_OBJECT NewKey;
|
||||
NTSTATUS Status;
|
||||
PWSTR SubName;
|
||||
UNICODE_STRING ObjectName;
|
||||
OBJECT_CREATE_INFORMATION ObjectCreateInfo;
|
||||
|
||||
DPRINT("CmiConnectHive(%p, %p) called.\n",
|
||||
KeyObjectAttributes, RegistryHive);
|
||||
|
||||
/* Capture all the info */
|
||||
DPRINT("Capturing Create Info\n");
|
||||
Status = ObpCaptureObjectAttributes(KeyObjectAttributes,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
&ObjectCreateInfo,
|
||||
&ObjectName);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("CmiConnectHive(%p, %p) called.\n",
|
||||
KeyObjectAttributes, RegistryHive);
|
||||
|
||||
/* Capture all the info */
|
||||
DPRINT("Capturing Create Info\n");
|
||||
Status = ObpCaptureObjectAttributes(KeyObjectAttributes,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
&ObjectCreateInfo,
|
||||
&ObjectName);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
Status = CmFindObject(&ObjectCreateInfo,
|
||||
&ObjectName,
|
||||
(PVOID*)&ParentKey,
|
||||
&RemainingPath,
|
||||
CmiKeyType,
|
||||
NULL,
|
||||
NULL);
|
||||
ObpReleaseCapturedAttributes(&ObjectCreateInfo);
|
||||
if (ObjectName.Buffer) ObpReleaseCapturedName(&ObjectName);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT ("RemainingPath %wZ\n", &RemainingPath);
|
||||
|
||||
if ((RemainingPath.Buffer == NULL) || (RemainingPath.Buffer[0] == 0))
|
||||
{
|
||||
ObDereferenceObject (ParentKey);
|
||||
RtlFreeUnicodeString(&RemainingPath);
|
||||
return STATUS_OBJECT_NAME_COLLISION;
|
||||
}
|
||||
|
||||
/* Ignore leading backslash */
|
||||
SubName = RemainingPath.Buffer;
|
||||
if (*SubName == L'\\')
|
||||
SubName++;
|
||||
|
||||
/* If RemainingPath contains \ we must return error
|
||||
because CmiConnectHive() can not create trees */
|
||||
if (wcschr (SubName, L'\\') != NULL)
|
||||
{
|
||||
ObDereferenceObject (ParentKey);
|
||||
RtlFreeUnicodeString(&RemainingPath);
|
||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
DPRINT("RemainingPath %wZ ParentKey %p\n",
|
||||
&RemainingPath, ParentKey);
|
||||
|
||||
Status = ObCreateObject(KernelMode,
|
||||
Status = CmFindObject(&ObjectCreateInfo,
|
||||
&ObjectName,
|
||||
(PVOID*)&ParentKey,
|
||||
&RemainingPath,
|
||||
CmiKeyType,
|
||||
NULL,
|
||||
KernelMode,
|
||||
NULL,
|
||||
sizeof(KEY_OBJECT),
|
||||
0,
|
||||
0,
|
||||
(PVOID*)&NewKey);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1 ("ObCreateObject() failed (Status %lx)\n", Status);
|
||||
ObDereferenceObject (ParentKey);
|
||||
RtlFreeUnicodeString(&RemainingPath);
|
||||
return Status;
|
||||
}
|
||||
NULL);
|
||||
/* Yields a new reference */
|
||||
ObpReleaseCapturedAttributes(&ObjectCreateInfo);
|
||||
|
||||
if (ObjectName.Buffer) ObpReleaseCapturedName(&ObjectName);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT ("RemainingPath %wZ\n", &RemainingPath);
|
||||
|
||||
if ((RemainingPath.Buffer == NULL) || (RemainingPath.Buffer[0] == 0))
|
||||
{
|
||||
ObDereferenceObject (ParentKey);
|
||||
RtlFreeUnicodeString(&RemainingPath);
|
||||
return STATUS_OBJECT_NAME_COLLISION;
|
||||
}
|
||||
|
||||
/* Ignore leading backslash */
|
||||
SubName = RemainingPath.Buffer;
|
||||
if (*SubName == L'\\')
|
||||
SubName++;
|
||||
|
||||
/* If RemainingPath contains \ we must return error
|
||||
because CmiConnectHive() can not create trees */
|
||||
if (wcschr (SubName, L'\\') != NULL)
|
||||
{
|
||||
ObDereferenceObject (ParentKey);
|
||||
RtlFreeUnicodeString(&RemainingPath);
|
||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
DPRINT("RemainingPath %wZ ParentKey %p\n",
|
||||
&RemainingPath, ParentKey);
|
||||
|
||||
Status = ObCreateObject(KernelMode,
|
||||
CmiKeyType,
|
||||
NULL,
|
||||
KernelMode,
|
||||
NULL,
|
||||
sizeof(KEY_OBJECT),
|
||||
0,
|
||||
0,
|
||||
(PVOID*)&NewKey);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1 ("ObCreateObject() failed (Status %lx)\n", Status);
|
||||
ObDereferenceObject (ParentKey);
|
||||
RtlFreeUnicodeString(&RemainingPath);
|
||||
return Status;
|
||||
}
|
||||
DPRINT("Inserting Key into Object Tree\n");
|
||||
Status = ObInsertObject((PVOID)NewKey,
|
||||
NULL,
|
||||
|
@ -787,56 +791,42 @@ CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
|
|||
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,
|
||||
NewKey->KeyCell->NumberOfSubKeys * sizeof(ULONG));
|
||||
if (NewKey->SubKeys == NULL)
|
||||
{
|
||||
DPRINT("ExAllocatePool() failed\n");
|
||||
ObDereferenceObject (NewKey);
|
||||
ObDereferenceObject (ParentKey);
|
||||
RtlFreeUnicodeString(&RemainingPath);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NewKey->SubKeys = 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;
|
||||
NewKey->SubKeys = NULL;
|
||||
InsertTailList(&CmiKeyObjectListHead, &NewKey->ListEntry);
|
||||
InsertTailList(&CmiConnectedHiveList, &NewKey->HiveList);
|
||||
|
||||
DPRINT ("SubName %S\n", SubName);
|
||||
DPRINT ("SubName %S\n", SubName);
|
||||
|
||||
Status = RtlpCreateUnicodeString(&NewKey->Name,
|
||||
SubName, NonPagedPool);
|
||||
RtlFreeUnicodeString(&RemainingPath);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("RtlpCreateUnicodeString() failed (Status %lx)\n", Status);
|
||||
if (NewKey->SubKeys != NULL)
|
||||
{
|
||||
ExFreePool (NewKey->SubKeys);
|
||||
}
|
||||
ObDereferenceObject (NewKey);
|
||||
ObDereferenceObject (ParentKey);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
Status = RtlpCreateUnicodeString(&NewKey->Name,
|
||||
SubName, NonPagedPool);
|
||||
RtlFreeUnicodeString(&RemainingPath);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("RtlpCreateUnicodeString() failed (Status %lx)\n", Status);
|
||||
if (NewKey->SubKeys != NULL)
|
||||
{
|
||||
ExFreePool (NewKey->SubKeys);
|
||||
}
|
||||
ObDereferenceObject (NewKey);
|
||||
ObDereferenceObject (ParentKey);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
CmiAddKeyToList (ParentKey, NewKey);
|
||||
ObDereferenceObject (ParentKey);
|
||||
CmiAddKeyToList (ParentKey, NewKey);
|
||||
|
||||
VERIFY_KEY_OBJECT(NewKey);
|
||||
VERIFY_KEY_OBJECT(NewKey);
|
||||
|
||||
/* Note: Do not dereference NewKey here! */
|
||||
/* We're holding a pointer to the parent key .. We must keep it
|
||||
* referenced */
|
||||
/* Note: Do not dereference NewKey here! */
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -845,9 +835,8 @@ CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes,
|
|||
OUT PREGISTRY_HIVE *RegistryHive)
|
||||
{
|
||||
PKEY_OBJECT KeyObject;
|
||||
PREGISTRY_HIVE Hive;
|
||||
HANDLE KeyHandle;
|
||||
NTSTATUS Status;
|
||||
NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PKEY_OBJECT CurrentKey;
|
||||
|
||||
|
@ -875,6 +864,7 @@ CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes,
|
|||
(PVOID*)&KeyObject,
|
||||
NULL);
|
||||
ZwClose (KeyHandle);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status);
|
||||
|
@ -882,61 +872,39 @@ CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes,
|
|||
}
|
||||
DPRINT ("KeyObject %p Hive %p\n", KeyObject, KeyObject->RegistryHive);
|
||||
|
||||
if (!(KeyObject->KeyCell->Flags & REG_KEY_ROOT_CELL))
|
||||
{
|
||||
DPRINT1 ("Key is not the Hive-Root-Key\n");
|
||||
ObDereferenceObject (KeyObject);
|
||||
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;
|
||||
}
|
||||
/* Find out if we represent a connected hive. */
|
||||
for( CurrentEntry = CmiConnectedHiveList.Flink;
|
||||
CurrentEntry != &CmiConnectedHiveList;
|
||||
CurrentEntry = CurrentEntry->Flink ) {
|
||||
CurrentKey = CONTAINING_RECORD(CurrentEntry, KEY_OBJECT, HiveList);
|
||||
if( CurrentKey == KeyObject ) {
|
||||
/* Remove the connected hive from the connected hive list */
|
||||
RemoveEntryList(CurrentEntry);
|
||||
/* found ourselves in the connected hive list */
|
||||
*RegistryHive = KeyObject->RegistryHive;
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
/* Release references captured in CmiConnectHive */
|
||||
ObDereferenceObject (KeyObject->ParentKey);
|
||||
ObDereferenceObject (KeyObject);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ObGetObjectHandleCount (KeyObject) != 0 ||
|
||||
ObGetObjectPointerCount (KeyObject) != 2)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
Hive = KeyObject->RegistryHive;
|
||||
|
||||
/* Dereference KeyObject twice to delete it */
|
||||
ObDereferenceObject (KeyObject);
|
||||
ObDereferenceObject (KeyObject);
|
||||
|
||||
*RegistryHive = Hive;
|
||||
|
||||
|
||||
/* Release registry lock */
|
||||
ExReleaseResourceLite (&CmiRegistryLock);
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
/* Release reference above */
|
||||
ObDereferenceObject (KeyObject);
|
||||
|
||||
DPRINT ("CmiDisconnectHive() done\n");
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -462,7 +462,7 @@ CmiObjectParse(IN PVOID ParsedObject,
|
|||
ExReleaseResourceLite(&CmiRegistryLock);
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
DPRINT("CmiObjectParse: %s\n", FoundObject->Name);
|
||||
//DPRINT("CmiObjectParse: %s\n", FoundObject->Name);
|
||||
|
||||
*Path = EndPtr;
|
||||
|
||||
|
@ -492,9 +492,9 @@ CmiObjectDelete(PVOID DeletedObject)
|
|||
KeEnterCriticalRegion();
|
||||
ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
|
||||
|
||||
//if (!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject)))
|
||||
if (!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject)))
|
||||
{
|
||||
// DPRINT1("Key not found in parent list ???\n");
|
||||
DPRINT1("Key not found in parent list ???\n");
|
||||
}
|
||||
|
||||
RemoveEntryList(&KeyObject->ListEntry);
|
||||
|
@ -526,7 +526,7 @@ CmiObjectDelete(PVOID DeletedObject)
|
|||
|
||||
if (KeyObject->NumberOfSubKeys)
|
||||
{
|
||||
//KEBUGCHECK(REGISTRY_ERROR);
|
||||
KEBUGCHECK(REGISTRY_ERROR);
|
||||
}
|
||||
|
||||
if (KeyObject->SizeOfSubKeys)
|
||||
|
|
Loading…
Reference in a new issue