mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 11:02:16 +00:00
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:
parent
f35801a5a9
commit
0dd0b373bc
5 changed files with 307 additions and 158 deletions
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue