- Implement CmpFindSubKeyByNumber and CmpDoFindSubKeyByNumber.

- Make NtEnumerateKey a simpler wrapper around CmEnumerateKey.
- Implement CmEnumerateKey by using the same API as previously, CmpQueryKeyData instead of duplicating code like the previous version did. Use CmpFindSubKeyByNumber to convert from index to key node.
- Remove CmiGetValueFromKeyByIndex, CmiGetKeyFromHashByIndex, CmiCopyPackedName: deprecated.

svn path=/trunk/; revision=26781
This commit is contained in:
Alex Ionescu 2007-05-14 19:35:58 +00:00
parent 64f4f03b95
commit 475bf24b50
6 changed files with 263 additions and 471 deletions

View file

@ -163,39 +163,6 @@ CmRegisterCallback(IN PEX_CALLBACK_FUNCTION Function,
NTSTATUS STDCALL
CmUnRegisterCallback(IN LARGE_INTEGER Cookie);
NTSTATUS STDCALL
CmpParseKey(IN PVOID ParsedObject,
IN PVOID ObjectType,
IN OUT PACCESS_STATE AccessState,
IN KPROCESSOR_MODE AccessMode,
IN ULONG Attributes,
IN OUT PUNICODE_STRING FullPath,
IN OUT PUNICODE_STRING RemainingName,
IN OUT PVOID Context OPTIONAL,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
OUT PVOID *NextObject);
VOID STDCALL
CmpDeleteKeyObject(PVOID DeletedObject);
NTSTATUS STDCALL
CmpSecurityMethod(PVOID ObjectBody,
SECURITY_OPERATION_CODE OperationCode,
PSECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR SecurityDescriptor,
PULONG BufferLength,
PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
POOL_TYPE PoolType,
PGENERIC_MAPPING GenericMapping);
NTSTATUS STDCALL
CmpQueryKeyName (PVOID ObjectBody,
IN BOOLEAN HasObjectName,
POBJECT_NAME_INFORMATION ObjectNameInfo,
ULONG Length,
PULONG ReturnLength,
IN KPROCESSOR_MODE PreviousMode);
VOID
CmiAddKeyToList(IN PKEY_OBJECT ParentKey,
IN PKEY_OBJECT NewKey);
@ -264,12 +231,6 @@ CmiScanKeyForValue(IN PEREGISTRY_HIVE RegistryHive,
OUT PCM_KEY_VALUE *ValueCell,
OUT HCELL_INDEX *VBOffset);
NTSTATUS
CmiGetValueFromKeyByIndex(IN PEREGISTRY_HIVE RegistryHive,
IN PCM_KEY_NODE KeyCell,
IN ULONG Index,
OUT PCM_KEY_VALUE *ValueCell);
NTSTATUS
NTAPI
CmDeleteValueKey(IN PKEY_OBJECT KeyControlBlock,
@ -309,6 +270,15 @@ CmQueryKey(IN PKEY_OBJECT KeyObject,
IN ULONG Length,
IN PULONG ResultLength);
NTSTATUS
NTAPI
CmEnumerateKey(IN PKEY_OBJECT KeyObject,
IN ULONG Index,
IN KEY_INFORMATION_CLASS KeyInformationClass,
IN PVOID KeyInformation,
IN ULONG Length,
IN PULONG ResultLength);
NTSTATUS
CmiAllocateHashTableCell(IN PEREGISTRY_HIVE RegistryHive,
OUT PHASH_TABLE_CELL *HashBlock,
@ -316,11 +286,6 @@ CmiAllocateHashTableCell(IN PEREGISTRY_HIVE RegistryHive,
IN ULONG HashTableSize,
IN HV_STORAGE_TYPE Storage);
PCM_KEY_NODE
CmiGetKeyFromHashByIndex(PEREGISTRY_HIVE RegistryHive,
PHASH_TABLE_CELL HashBlock,
ULONG Index);
NTSTATUS
CmiAddKeyToHashTable(PEREGISTRY_HIVE RegistryHive,
PHASH_TABLE_CELL HashCell,
@ -362,18 +327,9 @@ CmpFindSubKeyByName(
IN PUNICODE_STRING SearchName
);
VOID
CmiCopyPackedName(PWCHAR NameBuffer,
PUCHAR PackedNameBuffer,
ULONG PackedNameSize);
VOID
CmiSyncHives(VOID);
NTSTATUS
CmiCreateTempHive(PEREGISTRY_HIVE *RegistryHive);
NTSTATUS
CmiSaveTempHive (PEREGISTRY_HIVE Hive,
HANDLE FileHandle);
@ -389,45 +345,6 @@ CmFindObject(
IN PACCESS_STATE AccessState,
IN PVOID ParseContext
);
PVOID CMAPI
CmpAllocate(
ULONG Size,
BOOLEAN Paged);
VOID CMAPI
CmpFree(
PVOID Ptr);
BOOLEAN CMAPI
CmpFileRead(
PHHIVE RegistryHive,
ULONG FileType,
ULONGLONG FileOffset,
PVOID Buffer,
SIZE_T BufferLength);
BOOLEAN CMAPI
CmpFileWrite(
PHHIVE RegistryHive,
ULONG FileType,
ULONGLONG FileOffset,
PVOID Buffer,
SIZE_T BufferLength);
BOOLEAN CMAPI
CmpFileSetSize(
PHHIVE RegistryHive,
ULONG FileType,
ULONGLONG FileSize);
BOOLEAN CMAPI
CmpFileFlush(
PHHIVE RegistryHive,
ULONG FileType);
VOID
CmiCheckKey(BOOLEAN Verbose,
HANDLE Key);
NTSTATUS
NTAPI
@ -450,31 +367,6 @@ CmpInitHiveFromFile(IN PUNICODE_STRING HiveName,
IN OUT PBOOLEAN New,
IN ULONG CheckFlags);
#if 0
static __inline PVOID xHvGetCell(char *file, int line, PHHIVE Hive, HCELL_INDEX Cell)
{
DPRINT1("xHvGetCell @ %s:%d %x @ %x\n", file, line, Cell, Hive);
return HvGetCell(Hive, Cell);
}
static __inline VOID xHvFreeCell(char *file, int line, PHHIVE Hive, HCELL_INDEX Cell)
{
DPRINT1("xHvFreeCell @ %s:%d %x @ %x\n", file, line, Cell, Hive);
HvFreeCell(Hive, Cell);
}
static __inline HCELL_INDEX xHvAllocateCell(char *file, int line, PHHIVE Hive, SIZE_T Size)
{
HCELL_INDEX Offset = HvAllocateCell(Hive, Size);
DPRINT1("xHvAllocateCell @ %s:%d (%x) %x @ %x\n", file, line, Size, Offset, Hive);
return Offset;
}
#define HvGetCell(hive, cell) xHvGetCell(__FILE__, __LINE__, hive, cell)
#define HvFreeCell(hive, cell) xHvFreeCell(__FILE__, __LINE__, hive, cell)
#define HvAllocateCell(hive, size) xHvAllocateCell(__FILE__, __LINE__, hive, size)
#endif
// Some Ob definitions for debug messages in Cm
#define ObGetObjectPointerCount(x) OBJECT_TO_OBJECT_HEADER(x)->PointerCount
#define ObGetObjectHandleCount(x) OBJECT_TO_OBJECT_HEADER(x)->HandleCount

View file

@ -525,309 +525,60 @@ NtDeleteKey(IN HANDLE KeyHandle)
return Status;
}
NTSTATUS STDCALL
NTSTATUS
NTAPI
NtEnumerateKey(IN HANDLE KeyHandle,
IN ULONG Index,
IN KEY_INFORMATION_CLASS KeyInformationClass,
OUT PVOID KeyInformation,
IN ULONG Length,
OUT PULONG ResultLength)
IN ULONG Index,
IN KEY_INFORMATION_CLASS KeyInformationClass,
OUT PVOID KeyInformation,
IN ULONG Length,
OUT PULONG ResultLength)
{
PKEY_OBJECT KeyObject;
PEREGISTRY_HIVE RegistryHive;
PCM_KEY_NODE KeyCell, SubKeyCell;
PHASH_TABLE_CELL HashTableBlock;
PKEY_BASIC_INFORMATION BasicInformation;
PKEY_NODE_INFORMATION NodeInformation;
PKEY_FULL_INFORMATION FullInformation;
PVOID ClassCell;
ULONG NameSize, ClassSize;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo;
REG_POST_OPERATION_INFORMATION PostOperationInfo;
HV_STORAGE_TYPE Storage;
ULONG BaseIndex;
NTSTATUS Status;
PKEY_OBJECT KeyObject;
REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo;
REG_POST_OPERATION_INFORMATION PostOperationInfo;
PAGED_CODE();
PAGED_CODE();
/* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle,
(KeyInformationClass !=
KeyNameInformation) ?
KEY_QUERY_VALUE : 0,
CmpKeyObjectType,
ExGetPreviousMode(),
(PVOID *)&KeyObject,
NULL);
if (!NT_SUCCESS(Status)) return Status;
PreviousMode = ExGetPreviousMode();
/* Setup the callback */
PostOperationInfo.Object = (PVOID)KeyObject;
EnumerateKeyInfo.Object = (PVOID)KeyObject;
EnumerateKeyInfo.Index = Index;
EnumerateKeyInfo.KeyInformationClass = KeyInformationClass;
EnumerateKeyInfo.Length = Length;
EnumerateKeyInfo.ResultLength = ResultLength;
DPRINT("KH 0x%p I %d KIC %x KI 0x%p L %d RL 0x%p\n",
KeyHandle,
Index,
KeyInformationClass,
KeyInformation,
Length,
ResultLength);
/* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_ENUMERATE_SUB_KEYS,
CmpKeyObjectType,
PreviousMode,
(PVOID *) &KeyObject,
NULL);
if (!NT_SUCCESS(Status))
/* Do the callback */
Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateKey, &EnumerateKeyInfo);
if (NT_SUCCESS(Status))
{
DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status);
return(Status);
/* Call the internal API */
Status = CmEnumerateKey(KeyObject,
Index,
KeyInformationClass,
KeyInformation,
Length,
ResultLength);
/* Do the post callback */
PostOperationInfo.Status = Status;
CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
}
PostOperationInfo.Object = (PVOID)KeyObject;
EnumerateKeyInfo.Object = (PVOID)KeyObject;
EnumerateKeyInfo.Index = Index;
EnumerateKeyInfo.KeyInformationClass = KeyInformationClass;
EnumerateKeyInfo.Length = Length;
EnumerateKeyInfo.ResultLength = ResultLength;
Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateKey, &EnumerateKeyInfo);
if (!NT_SUCCESS(Status))
{
PostOperationInfo.Status = Status;
CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
ObDereferenceObject(KeyObject);
return Status;
}
/* Acquire hive lock */
KeEnterCriticalRegion();
ExAcquireResourceSharedLite(&CmpRegistryLock, TRUE);
VERIFY_KEY_OBJECT(KeyObject);
/* Get pointer to KeyCell */
KeyCell = KeyObject->KeyCell;
RegistryHive = KeyObject->RegistryHive;
/* Check for hightest possible sub key index */
if (Index >= KeyCell->SubKeyCounts[HvStable] +
KeyCell->SubKeyCounts[HvVolatile])
{
ExReleaseResourceLite(&CmpRegistryLock);
KeLeaveCriticalRegion();
PostOperationInfo.Status = STATUS_NO_MORE_ENTRIES;
CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
ObDereferenceObject(KeyObject);
DPRINT("No more volatile entries\n");
return STATUS_NO_MORE_ENTRIES;
}
/* Get pointer to SubKey */
if (Index >= KeyCell->SubKeyCounts[HvStable])
{
Storage = HvVolatile;
BaseIndex = Index - KeyCell->SubKeyCounts[HvStable];
}
else
{
Storage = HvStable;
BaseIndex = Index;
}
if (KeyCell->SubKeyLists[Storage] == HCELL_NULL)
{
ExReleaseResourceLite(&CmpRegistryLock);
KeLeaveCriticalRegion();
PostOperationInfo.Status = STATUS_NO_MORE_ENTRIES;
CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
ObDereferenceObject(KeyObject);
return STATUS_NO_MORE_ENTRIES;
}
ASSERT(KeyCell->SubKeyLists[Storage] != HCELL_NULL);
HashTableBlock = HvGetCell (&RegistryHive->Hive, KeyCell->SubKeyLists[Storage]);
SubKeyCell = CmiGetKeyFromHashByIndex(RegistryHive,
HashTableBlock,
BaseIndex);
Status = STATUS_SUCCESS;
switch (KeyInformationClass)
{
case KeyBasicInformation:
/* Check size of buffer */
NameSize = SubKeyCell->NameSize;
if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
{
NameSize *= sizeof(WCHAR);
}
*ResultLength = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]) + NameSize;
/*
* NOTE: It's perfetly valid to call NtEnumerateKey to get
* all the information but name. Actually the NT4 sound
* framework does that while querying parameters from registry.
* -- Filip Navara, 19/07/2004
*/
if (Length < FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]))
{
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
/* Fill buffer with requested info */
BasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation;
BasicInformation->LastWriteTime.u.LowPart = SubKeyCell->LastWriteTime.u.LowPart;
BasicInformation->LastWriteTime.u.HighPart = SubKeyCell->LastWriteTime.u.HighPart;
BasicInformation->TitleIndex = Index;
BasicInformation->NameLength = NameSize;
if (Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]) < NameSize)
{
NameSize = Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]);
Status = STATUS_BUFFER_OVERFLOW;
CHECKPOINT;
}
if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
{
CmiCopyPackedName(BasicInformation->Name,
SubKeyCell->Name,
NameSize / sizeof(WCHAR));
}
else
{
RtlCopyMemory(BasicInformation->Name,
SubKeyCell->Name,
NameSize);
}
}
break;
case KeyNodeInformation:
/* Check size of buffer */
NameSize = SubKeyCell->NameSize;
if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
{
NameSize *= sizeof(WCHAR);
}
ClassSize = SubKeyCell->ClassSize;
*ResultLength = FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) +
NameSize + ClassSize;
if (Length < FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]))
{
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
/* Fill buffer with requested info */
NodeInformation = (PKEY_NODE_INFORMATION) KeyInformation;
NodeInformation->LastWriteTime.u.LowPart = SubKeyCell->LastWriteTime.u.LowPart;
NodeInformation->LastWriteTime.u.HighPart = SubKeyCell->LastWriteTime.u.HighPart;
NodeInformation->TitleIndex = Index;
NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) + NameSize;
NodeInformation->ClassLength = SubKeyCell->ClassSize;
NodeInformation->NameLength = NameSize;
if (Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) < NameSize)
{
NameSize = Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]);
ClassSize = 0;
Status = STATUS_BUFFER_OVERFLOW;
CHECKPOINT;
}
else if (Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) -
NameSize < ClassSize)
{
ClassSize = Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) -
NameSize;
Status = STATUS_BUFFER_OVERFLOW;
CHECKPOINT;
}
if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
{
CmiCopyPackedName(NodeInformation->Name,
SubKeyCell->Name,
NameSize / sizeof(WCHAR));
}
else
{
RtlCopyMemory(NodeInformation->Name,
SubKeyCell->Name,
NameSize);
}
if (ClassSize != 0)
{
ClassCell = HvGetCell (&KeyObject->RegistryHive->Hive,
SubKeyCell->ClassNameOffset);
RtlCopyMemory (NodeInformation->Name + SubKeyCell->NameSize,
ClassCell,
ClassSize);
}
}
break;
case KeyFullInformation:
ClassSize = SubKeyCell->ClassSize;
*ResultLength = FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]) +
ClassSize;
/* Check size of buffer */
if (Length < FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]))
{
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
/* Fill buffer with requested info */
FullInformation = (PKEY_FULL_INFORMATION) KeyInformation;
FullInformation->LastWriteTime.u.LowPart = SubKeyCell->LastWriteTime.u.LowPart;
FullInformation->LastWriteTime.u.HighPart = SubKeyCell->LastWriteTime.u.HighPart;
FullInformation->TitleIndex = Index;
FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) -
sizeof(WCHAR);
FullInformation->ClassLength = SubKeyCell->ClassSize;
FullInformation->SubKeys = CmiGetNumberOfSubKeys(KeyObject); //SubKeyCell->SubKeyCounts;
FullInformation->MaxNameLen = CmiGetMaxNameLength(&RegistryHive->Hive, SubKeyCell);
FullInformation->MaxClassLen = CmiGetMaxClassLength(&RegistryHive->Hive, SubKeyCell);
FullInformation->Values = SubKeyCell->ValueList.Count;
FullInformation->MaxValueNameLen =
CmiGetMaxValueNameLength(&RegistryHive->Hive, SubKeyCell);
FullInformation->MaxValueDataLen =
CmiGetMaxValueDataLength(&RegistryHive->Hive, SubKeyCell);
if (Length - FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]) < ClassSize)
{
ClassSize = Length - FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]);
Status = STATUS_BUFFER_OVERFLOW;
CHECKPOINT;
}
if (ClassSize != 0)
{
ClassCell = HvGetCell (&KeyObject->RegistryHive->Hive,
SubKeyCell->ClassNameOffset);
RtlCopyMemory (FullInformation->Class,
ClassCell,
ClassSize);
}
}
break;
default:
DPRINT1("Not handling 0x%x\n", KeyInformationClass);
break;
}
ExReleaseResourceLite(&CmpRegistryLock);
KeLeaveCriticalRegion();
PostOperationInfo.Status = Status;
CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
ObDereferenceObject(KeyObject);
DPRINT("Returning status %x\n", Status);
return(Status);
/* Dereference and return status */
ObDereferenceObject(KeyObject);
return Status;
}
NTSTATUS

View file

@ -620,39 +620,6 @@ CmiRemoveSubKey(PEREGISTRY_HIVE RegistryHive,
return STATUS_SUCCESS;
}
NTSTATUS
CmiGetValueFromKeyByIndex(IN PEREGISTRY_HIVE RegistryHive,
IN PCM_KEY_NODE KeyCell,
IN ULONG Index,
OUT PCM_KEY_VALUE *ValueCell)
{
PVALUE_LIST_CELL ValueListCell;
PCM_KEY_VALUE CurValueCell;
*ValueCell = NULL;
if (KeyCell->ValueList.List == (HCELL_INDEX)-1)
{
return STATUS_NO_MORE_ENTRIES;
}
if (Index >= KeyCell->ValueList.Count)
{
return STATUS_NO_MORE_ENTRIES;
}
ValueListCell = HvGetCell (&RegistryHive->Hive, KeyCell->ValueList.List);
VERIFY_VALUE_LIST_CELL(ValueListCell);
CurValueCell = HvGetCell (&RegistryHive->Hive, ValueListCell->ValueOffset[Index]);
*ValueCell = CurValueCell;
return STATUS_SUCCESS;
}
NTSTATUS
CmiAllocateHashTableCell (IN PEREGISTRY_HIVE RegistryHive,
OUT PHASH_TABLE_CELL *HashBlock,
@ -686,20 +653,6 @@ CmiAllocateHashTableCell (IN PEREGISTRY_HIVE RegistryHive,
return Status;
}
PCM_KEY_NODE
CmiGetKeyFromHashByIndex(PEREGISTRY_HIVE RegistryHive,
PHASH_TABLE_CELL HashBlock,
ULONG Index)
{
HCELL_INDEX KeyOffset;
PCM_KEY_NODE KeyCell;
KeyOffset = HashBlock->Table[Index].KeyOffset;
KeyCell = HvGetCell (&RegistryHive->Hive, KeyOffset);
return KeyCell;
}
NTSTATUS
CmiAddKeyToHashTable(PEREGISTRY_HIVE RegistryHive,
PHASH_TABLE_CELL HashCell,
@ -744,17 +697,6 @@ CmiRemoveKeyFromHashTable(PEREGISTRY_HIVE RegistryHive,
return STATUS_UNSUCCESSFUL;
}
VOID
CmiCopyPackedName(PWCHAR NameBuffer,
PUCHAR PackedNameBuffer,
ULONG PackedNameSize)
{
ULONG i;
for (i = 0; i < PackedNameSize; i++)
NameBuffer[i] = (WCHAR)PackedNameBuffer[i];
}
NTSTATUS
CmiSaveTempHive (PEREGISTRY_HIVE Hive,
HANDLE FileHandle)

View file

@ -1115,6 +1115,14 @@ CmpFindSubKeyByName(
IN PUNICODE_STRING SearchName
);
HCELL_INDEX
NTAPI
CmpFindSubKeyByNumber(
IN PHHIVE Hive,
IN PCM_KEY_NODE Node,
IN ULONG Number
);
ULONG
NTAPI
CmpComputeHashKey(

View file

@ -640,7 +640,7 @@ CmpQueryKeyData(IN PHHIVE Hive,
USHORT NameLength;
/* Check if the value is compressed */
if (Node->Flags & VALUE_COMP_NAME)
if (Node->Flags & KEY_COMP_NAME)
{
/* Get the compressed name size */
NameLength = CmpCompressedNameSize(Node->Name, Node->NameLength);
@ -917,3 +917,69 @@ Quickie:
KeLeaveCriticalRegion();
return Status;
}
NTSTATUS
NTAPI
CmEnumerateKey(IN PKEY_OBJECT KeyObject,
IN ULONG Index,
IN KEY_INFORMATION_CLASS KeyInformationClass,
IN PVOID KeyInformation,
IN ULONG Length,
IN PULONG ResultLength)
{
NTSTATUS Status;
PHHIVE Hive;
PCM_KEY_NODE Parent, Child;
HCELL_INDEX ChildCell;
/* Acquire hive lock */
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
/* Get the hive and parent */
Hive = &KeyObject->RegistryHive->Hive;
Parent = (PCM_KEY_NODE)HvGetCell(Hive, KeyObject->KeyCellOffset);
if (!Parent)
{
/* Fail */
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Quickie;
}
/* Get the child cell */
ChildCell = CmpFindSubKeyByNumber(Hive, Parent, Index);
/* Release the parent cell */
HvReleaseCell(Hive, KeyObject->KeyCellOffset);
/* Check if we found the child */
if (ChildCell == HCELL_NIL)
{
/* We didn't, fail */
Status = STATUS_NO_MORE_ENTRIES;
goto Quickie;
}
/* Now get the actual child node */
Child = (PCM_KEY_NODE)HvGetCell(Hive, ChildCell);
if (!Child)
{
/* Fail */
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Quickie;
}
/* Query the data requested */
Status = CmpQueryKeyData(Hive,
Child,
KeyInformationClass,
KeyInformation,
Length,
ResultLength);
Quickie:
/* Release hive lock */
ExReleaseResourceLite(&CmpRegistryLock);
KeLeaveCriticalRegion();
return Status;
}

View file

@ -514,6 +514,139 @@ CmpComputeHashKey(IN ULONG Hash,
return Hash;
}
HCELL_INDEX
NTAPI
CmpDoFindSubKeyByNumber(IN PHHIVE Hive,
IN PCM_KEY_INDEX Index,
IN ULONG Number)
{
ULONG i;
HCELL_INDEX LeafCell = 0;
PCM_KEY_INDEX Leaf = NULL;
PCM_KEY_FAST_INDEX FastIndex;
HCELL_INDEX Result;
/* Check if this is a root */
if (Index->Signature == CM_KEY_INDEX_ROOT)
{
/* Loop the index */
for (i = 0; i < Index->Count; i++)
{
/* Check if this isn't the first iteration */
if (i)
{
/* Make sure we had something valid, and release it */
ASSERT(Leaf != NULL );
ASSERT(LeafCell == Index->List[i - 1]);
HvReleaseCell(Hive, LeafCell);
}
/* Get the leaf cell and the leaf for this index */
LeafCell = Index->List[i];
Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
if (!Leaf) return HCELL_NIL;
/* Check if the index may be inside it */
if (Number < Leaf->Count)
{
/* Check if this is a fast or hash leaf */
if ((Leaf->Signature == CM_KEY_FAST_LEAF) ||
(Leaf->Signature == CM_KEY_HASH_LEAF))
{
/* Get the fast index */
FastIndex = (PCM_KEY_FAST_INDEX)Leaf;
/* Look inside the list to get our actual cell */
Result = FastIndex->List[Number].Cell;
HvReleaseCell(Hive, LeafCell);
return Result;
}
else
{
/* Regular leaf, so just use the index directly */
Result = Leaf->List[Number];
/* Release and return it */
HvReleaseCell(Hive,LeafCell);
return Result;
}
}
else
{
/* Otherwise, skip this leaf */
Number = Number - Leaf->Count;
}
}
/* Should never get here */
ASSERT(FALSE);
}
/* If we got here, then the cell is in this index */
ASSERT(Number < Index->Count);
/* Check if we're a fast or hash leaf */
if ((Index->Signature == CM_KEY_FAST_LEAF) ||
(Index->Signature == CM_KEY_HASH_LEAF))
{
/* We are, get the fast index and get the cell from the list */
FastIndex = (PCM_KEY_FAST_INDEX)Index;
return FastIndex->List[Number].Cell;
}
else
{
/* We aren't, so use the index directly to grab the cell */
return Index->List[Number];
}
}
HCELL_INDEX
NTAPI
CmpFindSubKeyByNumber(IN PHHIVE Hive,
IN PCM_KEY_NODE Node,
IN ULONG Number)
{
PCM_KEY_INDEX Index;
HCELL_INDEX Result = HCELL_NIL;
/* Check if it's in the stable list */
if (Number < Node->SubKeyCounts[HvStable])
{
/* Get the actual key index */
Index = (PCM_KEY_INDEX)HvGetCell(Hive, Node->SubKeyLists[HvStable]);
if (!Index) return HCELL_NIL;
/* Do a search inside it */
Result = CmpDoFindSubKeyByNumber(Hive, Index, Number);
/* Release the cell and return the result */
HvReleaseCell(Hive, Node->SubKeyLists[HvStable]);
return Result;
}
else if (Hive->StorageTypeCount > HvVolatile)
{
/* It's in the volatile list */
Number = Number - Node->SubKeyCounts[HvStable];
if (Number < Node->SubKeyCounts[HvVolatile])
{
/* Get the actual key index */
Index = (PCM_KEY_INDEX)HvGetCell(Hive,
Node->SubKeyLists[HvVolatile]);
if (!Index) return HCELL_NIL;
/* Do a search inside it */
Result = CmpDoFindSubKeyByNumber(Hive, Index, Number);
/* Release the cell and return the result */
HvReleaseCell(Hive, Node->SubKeyLists[HvVolatile]);
return Result;
}
}
/* Nothing was found */
return HCELL_NIL;
}
HCELL_INDEX
NTAPI
CmpFindSubKeyByHash(IN PHHIVE Hive,