diff --git a/reactos/ntoskrnl/cm/cm.h b/reactos/ntoskrnl/cm/cm.h index 6d32f401835..be309722efd 100644 --- a/reactos/ntoskrnl/cm/cm.h +++ b/reactos/ntoskrnl/cm/cm.h @@ -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 */ diff --git a/reactos/ntoskrnl/cm/import.c b/reactos/ntoskrnl/cm/import.c index a9da467013c..b0b23d1078f 100644 --- a/reactos/ntoskrnl/cm/import.c +++ b/reactos/ntoskrnl/cm/import.c @@ -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; } diff --git a/reactos/ntoskrnl/cm/registry.c b/reactos/ntoskrnl/cm/registry.c index 83ffecdb364..66ad3a19fac 100644 --- a/reactos/ntoskrnl/cm/registry.c +++ b/reactos/ntoskrnl/cm/registry.c @@ -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; } diff --git a/reactos/ntoskrnl/cm/regobj.c b/reactos/ntoskrnl/cm/regobj.c index 8f4e8cbe46f..290f1d5232c 100644 --- a/reactos/ntoskrnl/cm/regobj.c +++ b/reactos/ntoskrnl/cm/regobj.c @@ -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)