From 475bf24b50a5c00be66a649ae7b62072a3a89bdd Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Mon, 14 May 2007 19:35:58 +0000 Subject: [PATCH] - 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 --- reactos/ntoskrnl/cm/cm.h | 126 +---------- reactos/ntoskrnl/cm/ntfunc.c | 341 ++++-------------------------- reactos/ntoskrnl/cm/regfile.c | 58 ----- reactos/ntoskrnl/config/cm.h | 8 + reactos/ntoskrnl/config/cmapi.c | 68 +++++- reactos/ntoskrnl/config/cmindex.c | 133 ++++++++++++ 6 files changed, 263 insertions(+), 471 deletions(-) diff --git a/reactos/ntoskrnl/cm/cm.h b/reactos/ntoskrnl/cm/cm.h index dacff7421bd..1791e671444 100644 --- a/reactos/ntoskrnl/cm/cm.h +++ b/reactos/ntoskrnl/cm/cm.h @@ -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 diff --git a/reactos/ntoskrnl/cm/ntfunc.c b/reactos/ntoskrnl/cm/ntfunc.c index efe06117f04..51de6499809 100644 --- a/reactos/ntoskrnl/cm/ntfunc.c +++ b/reactos/ntoskrnl/cm/ntfunc.c @@ -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 diff --git a/reactos/ntoskrnl/cm/regfile.c b/reactos/ntoskrnl/cm/regfile.c index cd137245199..7532421df8d 100644 --- a/reactos/ntoskrnl/cm/regfile.c +++ b/reactos/ntoskrnl/cm/regfile.c @@ -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) diff --git a/reactos/ntoskrnl/config/cm.h b/reactos/ntoskrnl/config/cm.h index 672969e0738..fe5f17218e0 100644 --- a/reactos/ntoskrnl/config/cm.h +++ b/reactos/ntoskrnl/config/cm.h @@ -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( diff --git a/reactos/ntoskrnl/config/cmapi.c b/reactos/ntoskrnl/config/cmapi.c index 77afbedd861..fd1bf9c568d 100644 --- a/reactos/ntoskrnl/config/cmapi.c +++ b/reactos/ntoskrnl/config/cmapi.c @@ -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; +} diff --git a/reactos/ntoskrnl/config/cmindex.c b/reactos/ntoskrnl/config/cmindex.c index 69d26f20b23..306b30a3bfe 100644 --- a/reactos/ntoskrnl/config/cmindex.c +++ b/reactos/ntoskrnl/config/cmindex.c @@ -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,