Author: arty
Date: Thu Jun 29 07:48:43 2006
New Revision: 22684
URL:
http://svn.reactos.org/svn/reactos?rev=22684&view=rev
Log:
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
Modified:
trunk/reactos/ntoskrnl/cm/cm.h
trunk/reactos/ntoskrnl/cm/import.c
trunk/reactos/ntoskrnl/cm/registry.c
trunk/reactos/ntoskrnl/cm/regobj.c
Modified: trunk/reactos/ntoskrnl/cm/cm.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/cm.h?rev=22684…
==============================================================================
--- trunk/reactos/ntoskrnl/cm/cm.h (original)
+++ trunk/reactos/ntoskrnl/cm/cm.h Thu Jun 29 07:48:43 2006
@@ -358,6 +358,9 @@
/* 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 */
Modified: trunk/reactos/ntoskrnl/cm/import.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/import.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/cm/import.c (original)
+++ trunk/reactos/ntoskrnl/cm/import.c Thu Jun 29 07:48:43 2006
@@ -142,6 +142,8 @@
/* Acquire hive list lock exclusively */
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 @@
if (!NT_SUCCESS(Status))
{
DPRINT1 ("CmiConnectHive(%wZ) failed (Status %lx)\n", &KeyName,
Status);
-// CmiRemoveRegistryHive(RegistryHive);
return FALSE;
}
Modified: trunk/reactos/ntoskrnl/cm/registry.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/registry.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/cm/registry.c (original)
+++ trunk/reactos/ntoskrnl/cm/registry.c Thu Jun 29 07:48:43 2006
@@ -36,6 +36,7 @@
KTIMER CmiWorkerTimer;
LIST_ENTRY CmiKeyObjectListHead;
+LIST_ENTRY CmiConnectedHiveList;
ULONG CmiTimer = 0;
volatile BOOLEAN CmiHiveSyncEnabled = FALSE;
@@ -385,6 +386,7 @@
/* Initialize the key object list */
InitializeListHead(&CmiKeyObjectListHead);
+ InitializeListHead(&CmiConnectedHiveList);
/* Initialize the worker timer */
KeInitializeTimerEx(&CmiWorkerTimer, SynchronizationTimer);
@@ -694,92 +696,94 @@
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;
-
- 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))
- {
+ 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("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 @@
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 ("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;
- }
-
- CmiAddKeyToList (ParentKey, NewKey);
- ObDereferenceObject (ParentKey);
-
- VERIFY_KEY_OBJECT(NewKey);
-
- /* Note: Do not dereference NewKey here! */
-
- return STATUS_SUCCESS;
+ 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);
+
+ 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);
+
+ VERIFY_KEY_OBJECT(NewKey);
+
+ /* We're holding a pointer to the parent key .. We must keep it
+ * referenced */
+ /* Note: Do not dereference NewKey here! */
+
+ return STATUS_SUCCESS;
}
@@ -845,9 +835,8 @@
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,68 +864,47 @@
(PVOID*)&KeyObject,
NULL);
ZwClose (KeyHandle);
+
if (!NT_SUCCESS(Status))
{
DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status);
return Status;
}
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;
}
Modified: trunk/reactos/ntoskrnl/cm/regobj.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/regobj.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/cm/regobj.c (original)
+++ trunk/reactos/ntoskrnl/cm/regobj.c Thu Jun 29 07:48:43 2006
@@ -462,7 +462,7 @@
ExReleaseResourceLite(&CmiRegistryLock);
KeLeaveCriticalRegion();
- DPRINT("CmiObjectParse: %s\n", FoundObject->Name);
+ //DPRINT("CmiObjectParse: %s\n", FoundObject->Name);
*Path = EndPtr;
@@ -492,9 +492,9 @@
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
- //if (!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject)))
- {
- // DPRINT1("Key not found in parent list ???\n");
+ if (!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject)))
+ {
+ DPRINT1("Key not found in parent list ???\n");
}
RemoveEntryList(&KeyObject->ListEntry);
@@ -526,7 +526,7 @@
if (KeyObject->NumberOfSubKeys)
{
- //KEBUGCHECK(REGISTRY_ERROR);
+ KEBUGCHECK(REGISTRY_ERROR);
}
if (KeyObject->SizeOfSubKeys)