mirror of
https://github.com/reactos/reactos.git
synced 2024-10-06 17:35:07 +00:00
- 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:
parent
64f4f03b95
commit
475bf24b50
|
@ -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
|
||||
|
|
|
@ -525,8 +525,8 @@ NtDeleteKey(IN HANDLE KeyHandle)
|
|||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtEnumerateKey(IN HANDLE KeyHandle,
|
||||
IN ULONG Index,
|
||||
IN KEY_INFORMATION_CLASS KeyInformationClass,
|
||||
|
@ -534,47 +534,24 @@ NtEnumerateKey(IN HANDLE KeyHandle,
|
|||
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;
|
||||
PKEY_OBJECT KeyObject;
|
||||
REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo;
|
||||
REG_POST_OPERATION_INFORMATION PostOperationInfo;
|
||||
HV_STORAGE_TYPE Storage;
|
||||
ULONG BaseIndex;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
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,
|
||||
(KeyInformationClass !=
|
||||
KeyNameInformation) ?
|
||||
KEY_QUERY_VALUE : 0,
|
||||
CmpKeyObjectType,
|
||||
PreviousMode,
|
||||
(PVOID *) &KeyObject,
|
||||
ExGetPreviousMode(),
|
||||
(PVOID *)&KeyObject,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status);
|
||||
return(Status);
|
||||
}
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Setup the callback */
|
||||
PostOperationInfo.Object = (PVOID)KeyObject;
|
||||
EnumerateKeyInfo.Object = (PVOID)KeyObject;
|
||||
EnumerateKeyInfo.Index = Index;
|
||||
|
@ -582,252 +559,26 @@ NtEnumerateKey(IN HANDLE KeyHandle,
|
|||
EnumerateKeyInfo.Length = Length;
|
||||
EnumerateKeyInfo.ResultLength = ResultLength;
|
||||
|
||||
/* Do the callback */
|
||||
Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateKey, &EnumerateKeyInfo);
|
||||
if (!NT_SUCCESS(Status))
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Call the internal API */
|
||||
Status = CmEnumerateKey(KeyObject,
|
||||
Index,
|
||||
KeyInformationClass,
|
||||
KeyInformation,
|
||||
Length,
|
||||
ResultLength);
|
||||
|
||||
/* Do the post callback */
|
||||
PostOperationInfo.Status = Status;
|
||||
CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
|
||||
}
|
||||
|
||||
/* Dereference and return status */
|
||||
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);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue