Use a list to store linked hives.

Enable enumeration of linked hive root keys.
Patch partially written by Filip Navara.

svn path=/trunk/; revision=7510
This commit is contained in:
Eric Kohl 2004-01-08 15:02:45 +00:00
parent f35801a5a9
commit 0dd0b373bc
5 changed files with 307 additions and 158 deletions

View file

@ -199,7 +199,13 @@ typedef struct _KEY_CELL
/*
* Hash record
*
* HashValue :
* KeyOffset:
* The least significant bit is used to distinguish
* between real key offsets and pointers to registry hives:
* 0 : offset
* 1 : pointer to registry hive
*
* HashValue:
* packed name: four letters of value's name
* otherwise: Zero!
*/
@ -297,6 +303,18 @@ typedef struct _REGISTRY_HIVE
#define IsUsedCell(Cell)(Cell->CellSize < 0)
typedef struct _HIVE_LINK
{
LIST_ENTRY Entry;
PREGISTRY_HIVE ParentKeyRegistryHive;
BLOCK_OFFSET ParentKeyCellOffset;
PREGISTRY_HIVE SubKeyRegistryHive;
BLOCK_OFFSET SubKeyCellOffset;
} HIVE_LINK, *PHIVE_LINK;
/* KEY_OBJECT.Flags */
/* When set, the key is scheduled for deletion, and all
@ -352,6 +370,7 @@ extern PREGISTRY_HIVE CmiVolatileHive;
extern POBJECT_TYPE CmiKeyType;
extern KSPIN_LOCK CmiKeyListLock;
extern LIST_ENTRY CmiHiveLinkListHead;
extern LIST_ENTRY CmiHiveListHead;
extern ERESOURCE CmiHiveListLock;
@ -472,12 +491,13 @@ CmiGetMaxValueDataLength(IN PREGISTRY_HIVE RegistryHive,
IN PKEY_CELL KeyCell);
NTSTATUS
CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive,
IN PKEY_CELL KeyCell,
OUT PKEY_CELL *SubKeyCell,
OUT BLOCK_OFFSET *BlockOffset,
CmiScanForSubKey(IN PREGISTRY_HIVE ParentKeyRegistryHive,
IN PKEY_CELL ParentKeyCell,
OUT PREGISTRY_HIVE *SubKeyRegistryHive,
OUT PKEY_CELL *SubKeyCell,
OUT BLOCK_OFFSET *SubKeyCellOffset,
IN PUNICODE_STRING KeyName,
IN ACCESS_MASK DesiredAccess,
IN ACCESS_MASK DesiredAccess,
IN ULONG Attributes);
NTSTATUS
@ -521,22 +541,23 @@ CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive,
IN PUNICODE_STRING ValueName);
NTSTATUS
CmiAllocateHashTableCell(IN PREGISTRY_HIVE RegistryHive,
OUT PHASH_TABLE_CELL *HashBlock,
OUT BLOCK_OFFSET *HBOffset,
IN ULONG HashTableSize);
CmiAllocateHashTableCell(IN PREGISTRY_HIVE RegistryHive,
OUT PHASH_TABLE_CELL *HashCell,
OUT BLOCK_OFFSET *HBOffset,
IN ULONG HashTableSize);
PKEY_CELL
CmiGetKeyFromHashByIndex(PREGISTRY_HIVE RegistryHive,
PHASH_TABLE_CELL HashBlock,
ULONG Index);
PHASH_TABLE_CELL HashCell,
ULONG Index);
NTSTATUS
CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive,
PHASH_TABLE_CELL HashCell,
BLOCK_OFFSET HashCellOffset,
PKEY_CELL NewKeyCell,
BLOCK_OFFSET NKBOffset);
PKEY_CELL ParentKeyCell,
BLOCK_OFFSET ParentKeyCellOffset,
PREGISTRY_HIVE NewKeyRegistryHive,
PKEY_CELL NewKeyCell,
BLOCK_OFFSET NewKeyCellOffset);
NTSTATUS
CmiRemoveKeyFromHashTable(PREGISTRY_HIVE RegistryHive,

View file

@ -275,7 +275,7 @@ NtEnumerateKey(IN HANDLE KeyHandle,
PKEY_OBJECT KeyObject;
PREGISTRY_HIVE RegistryHive;
PKEY_CELL KeyCell, SubKeyCell;
PHASH_TABLE_CELL HashTableBlock;
PHASH_TABLE_CELL HashTableCell;
PKEY_BASIC_INFORMATION BasicInformation;
PKEY_NODE_INFORMATION NodeInformation;
PKEY_FULL_INFORMATION FullInformation;
@ -317,38 +317,17 @@ NtEnumerateKey(IN HANDLE KeyHandle,
/* Get pointer to SubKey */
if (Index >= KeyCell->NumberOfSubKeys)
{
if (RegistryHive == CmiVolatileHive)
if (Index >= KeyObject->NumberOfSubKeys)
{
ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
KeLeaveCriticalRegion();
KeLeaveCriticalRegion();
ObDereferenceObject(KeyObject);
DPRINT("No more volatile entries\n");
return(STATUS_NO_MORE_ENTRIES);
}
else
{
ULONG i;
PKEY_OBJECT CurKey = NULL;
/* Search volatile keys */
for (i = 0; i < KeyObject->NumberOfSubKeys; i++)
{
CurKey = KeyObject->SubKeys[i];
if (CurKey->RegistryHive == CmiVolatileHive)
{
if (Index-- == KeyCell->NumberOfSubKeys)
break;
}
}
if (Index >= KeyCell->NumberOfSubKeys)
{
ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
KeLeaveCriticalRegion();
ObDereferenceObject(KeyObject);
DPRINT("No more non-volatile entries\n");
return(STATUS_NO_MORE_ENTRIES);
}
SubKeyCell = CurKey->KeyCell;
SubKeyCell = KeyObject->SubKeys[Index]->KeyCell;
}
}
else
@ -356,25 +335,27 @@ NtEnumerateKey(IN HANDLE KeyHandle,
if (KeyCell->HashTableOffset == (BLOCK_OFFSET)-1)
{
ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
KeLeaveCriticalRegion();
KeLeaveCriticalRegion();
ObDereferenceObject(KeyObject);
return(STATUS_NO_MORE_ENTRIES);
}
HashTableBlock = CmiGetCell (RegistryHive, KeyCell->HashTableOffset, NULL);
if (HashTableBlock == NULL)
HashTableCell = CmiGetCell (RegistryHive, KeyCell->HashTableOffset, NULL);
if (HashTableCell == NULL)
{
DPRINT("CmiGetBlock() failed\n");
ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
KeLeaveCriticalRegion();
KeLeaveCriticalRegion();
ObDereferenceObject(KeyObject);
return STATUS_UNSUCCESSFUL;
}
SubKeyCell = CmiGetKeyFromHashByIndex(RegistryHive,
HashTableBlock,
HashTableCell,
Index);
}
DPRINT("SubKeyCell %p\n", SubKeyCell);
if (SubKeyCell == NULL)
{
ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);

View file

@ -2262,19 +2262,21 @@ CmiGetMaxValueDataLength(PREGISTRY_HIVE RegistryHive,
NTSTATUS
CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive,
IN PKEY_CELL KeyCell,
CmiScanForSubKey(IN PREGISTRY_HIVE ParentKeyRegistryHive,
IN PKEY_CELL ParentKeyCell,
OUT PREGISTRY_HIVE *SubKeyRegistryHive,
OUT PKEY_CELL *SubKeyCell,
OUT BLOCK_OFFSET *BlockOffset,
OUT BLOCK_OFFSET *SubKeyCellOffset,
IN PUNICODE_STRING KeyName,
IN ACCESS_MASK DesiredAccess,
IN ULONG Attributes)
{
PHASH_TABLE_CELL HashBlock;
PHASH_TABLE_CELL HashCell;
PKEY_CELL CurSubKeyCell;
PHIVE_LINK HiveLink;
ULONG i;
VERIFY_KEY_CELL(KeyCell);
VERIFY_KEY_CELL(ParentKeyCell);
DPRINT("Scanning for sub key %wZ\n", KeyName);
@ -2283,66 +2285,116 @@ CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive,
*SubKeyCell = NULL;
/* The key does not have any subkeys */
if (KeyCell->HashTableOffset == (BLOCK_OFFSET)-1)
if (ParentKeyCell->HashTableOffset == (BLOCK_OFFSET)-1)
{
return STATUS_SUCCESS;
}
/* Get hash table */
HashBlock = CmiGetCell (RegistryHive, KeyCell->HashTableOffset, NULL);
if (HashBlock == NULL)
HashCell = CmiGetCell (ParentKeyRegistryHive, ParentKeyCell->HashTableOffset, NULL);
if (HashCell == NULL)
{
DPRINT("CmiGetBlock() failed\n");
return STATUS_UNSUCCESSFUL;
}
for (i = 0; (i < KeyCell->NumberOfSubKeys) && (i < HashBlock->HashTableSize); i++)
for (i = 0; (i < ParentKeyCell->NumberOfSubKeys) && (i < HashCell->HashTableSize); i++)
{
if (Attributes & OBJ_CASE_INSENSITIVE)
{
if (HashBlock->Table[i].KeyOffset != 0 &&
HashBlock->Table[i].KeyOffset != (ULONG_PTR)-1 &&
(HashBlock->Table[i].HashValue == 0 ||
CmiCompareHashI(KeyName, (PCHAR)&HashBlock->Table[i].HashValue)))
if (HashCell->Table[i].KeyOffset != 0 &&
HashCell->Table[i].KeyOffset != (ULONG_PTR)-1 &&
(HashCell->Table[i].HashValue == 0 ||
CmiCompareHashI(KeyName, (PCHAR)&HashCell->Table[i].HashValue)))
{
CurSubKeyCell = CmiGetCell (RegistryHive,
HashBlock->Table[i].KeyOffset,
NULL);
if (CurSubKeyCell == NULL)
if (HashCell->Table[i].KeyOffset & 1)
{
DPRINT("CmiGetBlock() failed\n");
return STATUS_UNSUCCESSFUL;
}
HiveLink = (PHIVE_LINK)(HashCell->Table[i].KeyOffset & ~1);
if (CmiCompareKeyNamesI(KeyName, CurSubKeyCell))
CurSubKeyCell = CmiGetCell (HiveLink->SubKeyRegistryHive,
HiveLink->SubKeyCellOffset,
NULL);
if (CurSubKeyCell == NULL)
{
DPRINT("CmiGetBlock() failed\n");
return STATUS_UNSUCCESSFUL;
}
if (CmiCompareKeyNamesI(KeyName, CurSubKeyCell))
{
*SubKeyRegistryHive = HiveLink->SubKeyRegistryHive;
*SubKeyCell = CurSubKeyCell;
*SubKeyCellOffset = HiveLink->SubKeyCellOffset;
break;
}
}
else
{
*SubKeyCell = CurSubKeyCell;
*BlockOffset = HashBlock->Table[i].KeyOffset;
break;
CurSubKeyCell = CmiGetCell (ParentKeyRegistryHive,
HashCell->Table[i].KeyOffset,
NULL);
if (CurSubKeyCell == NULL)
{
DPRINT("CmiGetBlock() failed\n");
return STATUS_UNSUCCESSFUL;
}
if (CmiCompareKeyNamesI(KeyName, CurSubKeyCell))
{
*SubKeyRegistryHive = ParentKeyRegistryHive;
*SubKeyCell = CurSubKeyCell;
*SubKeyCellOffset = HashCell->Table[i].KeyOffset;
break;
}
}
}
}
else
{
if (HashBlock->Table[i].KeyOffset != 0 &&
HashBlock->Table[i].KeyOffset != (ULONG_PTR) -1 &&
(HashBlock->Table[i].HashValue == 0 ||
CmiCompareHash(KeyName, (PCHAR)&HashBlock->Table[i].HashValue)))
if (HashCell->Table[i].KeyOffset != 0 &&
HashCell->Table[i].KeyOffset != (ULONG_PTR) -1 &&
(HashCell->Table[i].HashValue == 0 ||
CmiCompareHash(KeyName, (PCHAR)&HashCell->Table[i].HashValue)))
{
CurSubKeyCell = CmiGetCell (RegistryHive,
HashBlock->Table[i].KeyOffset,
NULL);
if (CurSubKeyCell == NULL)
if (HashCell->Table[i].KeyOffset & 1)
{
DPRINT("CmiGetBlock() failed\n");
return STATUS_UNSUCCESSFUL;
}
HiveLink = (PHIVE_LINK)(HashCell->Table[i].KeyOffset & ~1);
if (CmiCompareKeyNames(KeyName, CurSubKeyCell))
CurSubKeyCell = CmiGetCell (HiveLink->SubKeyRegistryHive,
HiveLink->SubKeyCellOffset,
NULL);
if (CurSubKeyCell == NULL)
{
DPRINT("CmiGetBlock() failed\n");
return STATUS_UNSUCCESSFUL;
}
if (CmiCompareKeyNames(KeyName, CurSubKeyCell))
{
*SubKeyRegistryHive = HiveLink->SubKeyRegistryHive;
*SubKeyCell = CurSubKeyCell;
*SubKeyCellOffset = HiveLink->SubKeyCellOffset;
break;
}
}
else
{
*SubKeyCell = CurSubKeyCell;
*BlockOffset = HashBlock->Table[i].KeyOffset;
break;
CurSubKeyCell = CmiGetCell (ParentKeyRegistryHive,
HashCell->Table[i].KeyOffset,
NULL);
if (CurSubKeyCell == NULL)
{
DPRINT("CmiGetBlock() failed\n");
return STATUS_UNSUCCESSFUL;
}
if (CmiCompareKeyNames(KeyName, CurSubKeyCell))
{
*SubKeyRegistryHive = ParentKeyRegistryHive;
*SubKeyCell = CurSubKeyCell;
*SubKeyCellOffset = HashCell->Table[i].KeyOffset;
break;
}
}
}
}
@ -2361,7 +2413,6 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive,
PUNICODE_STRING Class,
ULONG CreateOptions)
{
PHASH_TABLE_CELL HashBlock;
BLOCK_OFFSET NKBOffset;
PKEY_CELL NewKeyCell;
ULONG NewBlockSize;
@ -2478,69 +2529,19 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive,
return(Status);
}
if (ParentKeyCell->HashTableOffset == (ULONG_PTR) -1)
{
Status = CmiAllocateHashTableCell (RegistryHive,
&HashBlock,
&ParentKeyCell->HashTableOffset,
REG_INIT_HASH_TABLE_SIZE);
if (!NT_SUCCESS(Status))
{
return(Status);
}
}
else
{
HashBlock = CmiGetCell (RegistryHive,
ParentKeyCell->HashTableOffset,
NULL);
if (HashBlock == NULL)
{
DPRINT("CmiGetCell() failed\n");
return STATUS_UNSUCCESSFUL;
}
if (((ParentKeyCell->NumberOfSubKeys + 1) >= HashBlock->HashTableSize))
{
PHASH_TABLE_CELL NewHashBlock;
BLOCK_OFFSET HTOffset;
/* Reallocate the hash table cell */
Status = CmiAllocateHashTableCell (RegistryHive,
&NewHashBlock,
&HTOffset,
HashBlock->HashTableSize +
REG_EXTEND_HASH_TABLE_SIZE);
if (!NT_SUCCESS(Status))
{
return Status;
}
RtlZeroMemory(&NewHashBlock->Table[0],
sizeof(NewHashBlock->Table[0]) * NewHashBlock->HashTableSize);
RtlCopyMemory(&NewHashBlock->Table[0],
&HashBlock->Table[0],
sizeof(NewHashBlock->Table[0]) * HashBlock->HashTableSize);
CmiDestroyCell (RegistryHive,
HashBlock,
ParentKeyCell->HashTableOffset);
ParentKeyCell->HashTableOffset = HTOffset;
HashBlock = NewHashBlock;
}
}
Status = CmiAddKeyToHashTable(RegistryHive,
HashBlock,
ParentKeyCell->HashTableOffset,
Status = CmiAddKeyToHashTable(ParentKey->RegistryHive,
ParentKeyCell,
ParentKey->KeyCellOffset,
NULL,
NewKeyCell,
NKBOffset);
if (NT_SUCCESS(Status))
if (!NT_SUCCESS(Status))
{
ParentKeyCell->NumberOfSubKeys++;
return Status;
}
NtQuerySystemTime (&ParentKeyCell->LastWriteTime);
CmiMarkBlockDirty (RegistryHive, ParentKey->KeyCellOffset);
CmiMarkBlockDirty (ParentKey->RegistryHive, ParentKey->KeyCellOffset);
return(Status);
}
@ -3005,22 +3006,30 @@ CmiAllocateHashTableCell (IN PREGISTRY_HIVE RegistryHive,
PKEY_CELL
CmiGetKeyFromHashByIndex(PREGISTRY_HIVE RegistryHive,
PHASH_TABLE_CELL HashBlock,
PHASH_TABLE_CELL HashCell,
ULONG Index)
{
BLOCK_OFFSET KeyOffset;
PHIVE_LINK HiveLink;
PKEY_CELL KeyCell;
if (HashBlock == NULL)
if (HashCell == NULL)
return NULL;
if (IsPointerHive(RegistryHive))
if (HashCell->Table[Index].KeyOffset & 1)
{
KeyCell = (PKEY_CELL) HashBlock->Table[Index].KeyOffset;
HiveLink = (PHIVE_LINK)(HashCell->Table[Index].KeyOffset & ~1);
KeyCell = CmiGetCell (HiveLink->SubKeyRegistryHive,
HiveLink->SubKeyCellOffset,
NULL);
}
else if (IsPointerHive(RegistryHive))
{
KeyCell = (PKEY_CELL) HashCell->Table[Index].KeyOffset;
}
else
{
KeyOffset = HashBlock->Table[Index].KeyOffset;
KeyOffset = HashCell->Table[Index].KeyOffset;
KeyCell = CmiGetCell (RegistryHive, KeyOffset, NULL);
}
@ -3030,18 +3039,94 @@ CmiGetKeyFromHashByIndex(PREGISTRY_HIVE RegistryHive,
NTSTATUS
CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive,
PHASH_TABLE_CELL HashCell,
BLOCK_OFFSET HashCellOffset,
PKEY_CELL ParentKeyCell,
BLOCK_OFFSET ParentKeyCellOffset,
PREGISTRY_HIVE NewKeyRegistryHive,
PKEY_CELL NewKeyCell,
BLOCK_OFFSET NKBOffset)
BLOCK_OFFSET NewKeyCellOffset)
{
BLOCK_OFFSET HashCellOffset;
PHASH_TABLE_CELL HashCell;
ULONG i;
NTSTATUS Status;
if (ParentKeyCell->HashTableOffset == (ULONG_PTR) -1)
{
Status = CmiAllocateHashTableCell (RegistryHive,
&HashCell,
&ParentKeyCell->HashTableOffset,
REG_INIT_HASH_TABLE_SIZE);
if (!NT_SUCCESS(Status))
{
return(Status);
}
CmiMarkBlockDirty(RegistryHive, ParentKeyCellOffset);
}
else
{
HashCell = CmiGetCell (RegistryHive,
ParentKeyCell->HashTableOffset,
NULL);
if (HashCell == NULL)
{
DPRINT("CmiGetCell() failed\n");
return STATUS_UNSUCCESSFUL;
}
if (((ParentKeyCell->NumberOfSubKeys + 1) >= HashCell->HashTableSize))
{
PHASH_TABLE_CELL NewHashCell;
BLOCK_OFFSET NewHashCellOffset;
/* Reallocate the hash table cell */
Status = CmiAllocateHashTableCell (RegistryHive,
&NewHashCell,
&NewHashCellOffset,
HashCell->HashTableSize +
REG_EXTEND_HASH_TABLE_SIZE);
if (!NT_SUCCESS(Status))
{
return Status;
}
RtlZeroMemory(&NewHashCell->Table[0],
sizeof(NewHashCell->Table[0]) * NewHashCell->HashTableSize);
RtlCopyMemory(&NewHashCell->Table[0],
&HashCell->Table[0],
sizeof(NewHashCell->Table[0]) * HashCell->HashTableSize);
CmiDestroyCell (RegistryHive,
HashCell,
ParentKeyCell->HashTableOffset);
ParentKeyCell->HashTableOffset = NewHashCellOffset;
HashCell = NewHashCell;
CmiMarkBlockDirty(RegistryHive, ParentKeyCellOffset);
}
}
for (i = 0; i < HashCell->HashTableSize; i++)
{
if (HashCell->Table[i].KeyOffset == 0)
{
HashCell->Table[i].KeyOffset = NKBOffset;
if (NewKeyRegistryHive != NULL && NewKeyRegistryHive != RegistryHive)
{
PHIVE_LINK HiveLink;
HiveLink = ExAllocatePool (NonPagedPool, sizeof(HIVE_LINK));
if (HiveLink == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
InsertTailList (&CmiHiveLinkListHead, &HiveLink->Entry);
HiveLink->ParentKeyRegistryHive = RegistryHive;
HiveLink->ParentKeyCellOffset = ParentKeyCellOffset;
HiveLink->SubKeyRegistryHive = NewKeyRegistryHive;
HiveLink->SubKeyCellOffset = NewKeyCellOffset;
HashCell->Table[i].KeyOffset = (BLOCK_OFFSET)((ULONG)HiveLink | 1);
}
else
{
HashCell->Table[i].KeyOffset = NewKeyCellOffset;
}
HashCell->Table[i].HashValue = 0;
if (NewKeyCell->Flags & REG_KEY_NAME_PACKED)
{
@ -3050,6 +3135,8 @@ CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive,
min(NewKeyCell->NameSize, sizeof(ULONG)));
}
CmiMarkBlockDirty(RegistryHive, HashCellOffset);
ParentKeyCell->NumberOfSubKeys++;
CmiMarkBlockDirty(RegistryHive, ParentKeyCellOffset);
return STATUS_SUCCESS;
}
}

View file

@ -1,4 +1,4 @@
/* $Id: registry.c,v 1.116 2003/12/30 18:52:03 fireball Exp $
/* $Id: registry.c,v 1.117 2004/01/08 15:02:45 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -31,6 +31,7 @@ POBJECT_TYPE CmiKeyType = NULL;
PREGISTRY_HIVE CmiVolatileHive = NULL;
KSPIN_LOCK CmiKeyListLock;
LIST_ENTRY CmiHiveLinkListHead;
LIST_ENTRY CmiHiveListHead;
ERESOURCE CmiHiveListLock;
@ -281,6 +282,9 @@ CmInitializeRegistry(VOID)
ObpCreateTypeObject (CmiKeyType);
/* Initialize the hive link list */
InitializeListHead(&CmiHiveLinkListHead);
/* Initialize the hive list */
InitializeListHead(&CmiHiveListHead);
ExInitializeResourceLite(&CmiHiveListLock);
@ -596,12 +600,30 @@ CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = CmiAddKeyToHashTable(ParentKey->RegistryHive,
ParentKey->KeyCell,
ParentKey->KeyCellOffset,
NewKey->RegistryHive,
NewKey->KeyCell,
NewKey->KeyCellOffset);
if (!NT_SUCCESS(Status))
{
DPRINT1("CmiAddKeyToHashTable() failed (Status %lx)\n", Status);
if (NewKey->SubKeys != NULL)
{
ExFreePool (NewKey->SubKeys);
}
ObDereferenceObject (NewKey);
ObDereferenceObject (ParentKey);
return Status;
}
CmiAddKeyToList (ParentKey, NewKey);
ObDereferenceObject (ParentKey);
VERIFY_KEY_OBJECT(NewKey);
/* Note: Do not dereference NewKey here! */
ObDereferenceObject (NewKey);
ObDereferenceObject (ParentKey);
return STATUS_SUCCESS;
}
@ -614,6 +636,10 @@ CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes,
PKEY_OBJECT KeyObject;
PREGISTRY_HIVE Hive;
HANDLE KeyHandle;
PLIST_ENTRY Entry;
PHIVE_LINK HiveLink;
PKEY_CELL ParentKeyCell;
PHASH_TABLE_CELL HashCell;
NTSTATUS Status;
DPRINT("CmiDisconnectHive() called\n");
@ -663,10 +689,42 @@ CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes,
}
Hive = KeyObject->RegistryHive;
CmiRemoveKeyFromList (KeyObject);
/* Dereference KeyObject twice to delete it */
ObDereferenceObject (KeyObject);
/* Remove hive link and hash table entry */
Entry = CmiHiveLinkListHead.Flink;
while (Entry != &CmiHiveLinkListHead)
{
HiveLink = CONTAINING_RECORD(Entry, HIVE_LINK, Entry);
if (HiveLink->SubKeyRegistryHive == Hive &&
HiveLink->SubKeyCellOffset == KeyObject->KeyCellOffset)
{
ParentKeyCell = CmiGetCell (HiveLink->ParentKeyRegistryHive,
HiveLink->ParentKeyCellOffset,
NULL);
if (ParentKeyCell != NULL)
{
HashCell = CmiGetCell (HiveLink->ParentKeyRegistryHive,
ParentKeyCell->HashTableOffset,
NULL);
if (HashCell != NULL)
{
CmiRemoveKeyFromHashTable(HiveLink->ParentKeyRegistryHive,
HashCell,
(BLOCK_OFFSET)((ULONG)HiveLink | 1));
ParentKeyCell->NumberOfSubKeys--;
}
}
RemoveEntryList (Entry);
ExFreePool (Entry);
break;
}
Entry = Entry->Flink;
}
ObDereferenceObject (KeyObject);
*RegistryHive = Hive;

View file

@ -46,6 +46,7 @@ CmiObjectParse(PVOID ParsedObject,
UNICODE_STRING LinkPath;
UNICODE_STRING TargetPath;
UNICODE_STRING KeyName;
PREGISTRY_HIVE RegistryHive;
ParsedKey = ParsedObject;
@ -90,6 +91,7 @@ CmiObjectParse(PVOID ParsedObject,
{
Status = CmiScanForSubKey(ParsedKey->RegistryHive,
ParsedKey->KeyCell,
&RegistryHive,
&SubKeyCell,
&BlockOffset,
&KeyName,
@ -165,7 +167,7 @@ CmiObjectParse(PVOID ParsedObject,
FoundObject->Flags = 0;
FoundObject->KeyCell = SubKeyCell;
FoundObject->KeyCellOffset = BlockOffset;
FoundObject->RegistryHive = ParsedKey->RegistryHive;
FoundObject->RegistryHive = RegistryHive;
RtlCreateUnicodeString(&FoundObject->Name,
KeyName.Buffer);
CmiAddKeyToList(ParsedKey, FoundObject);