From 934cae8069e345d6594032c408a6ede7eedb1b83 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Mon, 14 May 2007 06:40:40 +0000 Subject: [PATCH] - Implement NtEnumerateValueKey as a simpler wrapper. - Implement CmEnumerateValueKey. Simply calls already-existing Value Cache routines (CmpGetValueListFromCache, CmpGetValueKeyFromCache and CmpQueryKeyValueData) to do all the work. svn path=/trunk/; revision=26778 --- reactos/ntoskrnl/cm/cm.h | 25 ++- reactos/ntoskrnl/cm/ntfunc.c | 306 +++++--------------------------- reactos/ntoskrnl/config/cm.h | 22 +++ reactos/ntoskrnl/config/cmapi.c | 105 +++++++++++ 4 files changed, 189 insertions(+), 269 deletions(-) diff --git a/reactos/ntoskrnl/cm/cm.h b/reactos/ntoskrnl/cm/cm.h index 46cda5af3a7..088e6db7ac3 100644 --- a/reactos/ntoskrnl/cm/cm.h +++ b/reactos/ntoskrnl/cm/cm.h @@ -284,6 +284,23 @@ CmQueryValueKey(IN PKEY_OBJECT KeyObject, IN ULONG Length, IN PULONG ResultLength); +NTSTATUS +NTAPI +CmEnumerateValueKey(IN PKEY_OBJECT KeyObject, + IN ULONG Index, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + IN PVOID KeyValueInformation, + IN ULONG Length, + IN PULONG ResultLength); + +NTSTATUS +NTAPI +CmSetValueKey(IN PKEY_OBJECT KeyObject, + IN PUNICODE_STRING ValueName, + IN ULONG Type, + IN PVOID Data, + IN ULONG DataSize); + NTSTATUS CmiAllocateHashTableCell(IN PEREGISTRY_HIVE RegistryHive, OUT PHASH_TABLE_CELL *HashBlock, @@ -304,14 +321,6 @@ CmiAddKeyToHashTable(PEREGISTRY_HIVE RegistryHive, PCM_KEY_NODE NewKeyCell, HCELL_INDEX NKBOffset); -NTSTATUS -NTAPI -CmSetValueKey(IN PKEY_OBJECT KeyObject, - IN PUNICODE_STRING ValueName, - IN ULONG Type, - IN PVOID Data, - IN ULONG DataSize); - NTSTATUS CmiRemoveKeyFromHashTable(PEREGISTRY_HIVE RegistryHive, PHASH_TABLE_CELL HashBlock, diff --git a/reactos/ntoskrnl/cm/ntfunc.c b/reactos/ntoskrnl/cm/ntfunc.c index 066442a6d0e..231c32e1c13 100644 --- a/reactos/ntoskrnl/cm/ntfunc.c +++ b/reactos/ntoskrnl/cm/ntfunc.c @@ -830,277 +830,61 @@ NtEnumerateKey(IN HANDLE KeyHandle, return(Status); } - -NTSTATUS STDCALL +NTSTATUS +NTAPI NtEnumerateValueKey(IN HANDLE KeyHandle, - IN ULONG Index, - IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, - OUT PVOID KeyValueInformation, - IN ULONG Length, - OUT PULONG ResultLength) + IN ULONG Index, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + OUT PVOID KeyValueInformation, + IN ULONG Length, + OUT PULONG ResultLength) { - NTSTATUS Status; - PKEY_OBJECT KeyObject; - PEREGISTRY_HIVE RegistryHive; - PCM_KEY_NODE KeyCell; - PCM_KEY_VALUE ValueCell; - PVOID DataCell; - ULONG NameSize, DataSize; - REG_ENUMERATE_VALUE_KEY_INFORMATION EnumerateValueKeyInfo; - REG_POST_OPERATION_INFORMATION PostOperationInfo; - PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation; - PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation; - PKEY_VALUE_FULL_INFORMATION ValueFullInformation; + NTSTATUS Status; + PKEY_OBJECT KeyObject; + REG_ENUMERATE_VALUE_KEY_INFORMATION EnumerateValueKeyInfo; + REG_POST_OPERATION_INFORMATION PostOperationInfo; + PAGED_CODE(); - PAGED_CODE(); + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + KEY_QUERY_VALUE, + CmpKeyObjectType, + ExGetPreviousMode(), + (PVOID *)&KeyObject, + NULL); + if (!NT_SUCCESS(Status)) return Status; - DPRINT("KH 0x%p I %d KVIC %x KVI 0x%p L %d RL 0x%p\n", - KeyHandle, - Index, - KeyValueInformationClass, - KeyValueInformation, - Length, - ResultLength); + /* Setup the callback */ + PostOperationInfo.Object = (PVOID)KeyObject; + EnumerateValueKeyInfo.Object = (PVOID)KeyObject; + EnumerateValueKeyInfo.Index = Index; + EnumerateValueKeyInfo.KeyValueInformationClass = KeyValueInformationClass; + EnumerateValueKeyInfo.KeyValueInformation = KeyValueInformation; + EnumerateValueKeyInfo.Length = Length; + EnumerateValueKeyInfo.ResultLength = ResultLength; - /* Verify that the handle is valid and is a registry key */ - Status = ObReferenceObjectByHandle(KeyHandle, - KEY_QUERY_VALUE, - CmpKeyObjectType, - ExGetPreviousMode(), - (PVOID *) &KeyObject, - NULL); - - if (!NT_SUCCESS(Status)) + /* Do the callback */ + Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateValueKey, + &EnumerateValueKeyInfo); + if (NT_SUCCESS(Status)) { - return Status; + /* Call the internal API */ + Status = CmEnumerateValueKey(KeyObject, + Index, + KeyValueInformationClass, + KeyValueInformation, + Length, + ResultLength); + + /* Do the post callback */ + PostOperationInfo.Status = Status; + CmiCallRegisteredCallbacks(RegNtPostEnumerateValueKey, &PostOperationInfo); } - PostOperationInfo.Object = (PVOID)KeyObject; - EnumerateValueKeyInfo.Object = (PVOID)KeyObject; - EnumerateValueKeyInfo.Index = Index; - EnumerateValueKeyInfo.KeyValueInformationClass = KeyValueInformationClass; - EnumerateValueKeyInfo.KeyValueInformation = KeyValueInformation; - EnumerateValueKeyInfo.Length = Length; - EnumerateValueKeyInfo.ResultLength = ResultLength; - - Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateValueKey, &EnumerateValueKeyInfo); - if (!NT_SUCCESS(Status)) - { - PostOperationInfo.Status = Status; - CmiCallRegisteredCallbacks(RegNtPostEnumerateValueKey, &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; - - /* Get Value block of interest */ - Status = CmiGetValueFromKeyByIndex(RegistryHive, - KeyCell, - Index, - &ValueCell); - - if (!NT_SUCCESS(Status)) - { - ExReleaseResourceLite(&CmpRegistryLock); - KeLeaveCriticalRegion(); - ObDereferenceObject(KeyObject); - PostOperationInfo.Status = Status; - CmiCallRegisteredCallbacks(RegNtPostEnumerateValueKey, &PostOperationInfo); - return Status; - } - - if (ValueCell != NULL) - { - switch (KeyValueInformationClass) - { - case KeyValueBasicInformation: - NameSize = ValueCell->NameSize; - if (ValueCell->Flags & REG_VALUE_NAME_PACKED) - { - NameSize *= sizeof(WCHAR); - } - - *ResultLength = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]) + NameSize; - - if (Length < FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0])) - { - Status = STATUS_BUFFER_TOO_SMALL; - } - else - { - ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION) - KeyValueInformation; - ValueBasicInformation->TitleIndex = 0; - ValueBasicInformation->Type = ValueCell->DataType; - ValueBasicInformation->NameLength = NameSize; - - if (Length - FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]) < - NameSize) - { - NameSize = Length - FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]); - Status = STATUS_BUFFER_OVERFLOW; - CHECKPOINT; - } - - if (ValueCell->Flags & REG_VALUE_NAME_PACKED) - { - CmiCopyPackedName(ValueBasicInformation->Name, - ValueCell->Name, - NameSize / sizeof(WCHAR)); - } - else - { - RtlCopyMemory(ValueBasicInformation->Name, - ValueCell->Name, - NameSize); - } - } - break; - - case KeyValuePartialInformation: - DataSize = ValueCell->DataSize & REG_DATA_SIZE_MASK; - - *ResultLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + - DataSize; - - if (Length < FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0])) - { - Status = STATUS_BUFFER_TOO_SMALL; - } - else - { - ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION) - KeyValueInformation; - ValuePartialInformation->TitleIndex = 0; - ValuePartialInformation->Type = ValueCell->DataType; - ValuePartialInformation->DataLength = ValueCell->DataSize & REG_DATA_SIZE_MASK; - - if (Length - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) < - DataSize) - { - DataSize = Length - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]); - Status = STATUS_BUFFER_OVERFLOW; - CHECKPOINT; - } - - if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET)) - { - DataCell = HvGetCell (&RegistryHive->Hive, ValueCell->DataOffset); - RtlCopyMemory(ValuePartialInformation->Data, - DataCell, - DataSize); - } - else - { - RtlCopyMemory(ValuePartialInformation->Data, - &ValueCell->DataOffset, - DataSize); - } - } - break; - - case KeyValueFullInformation: - NameSize = ValueCell->NameSize; - if (ValueCell->Flags & REG_VALUE_NAME_PACKED) - { - NameSize *= sizeof(WCHAR); - } - DataSize = ValueCell->DataSize & REG_DATA_SIZE_MASK; - - *ResultLength = ROUND_UP(FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, - Name[0]) + NameSize, sizeof(PVOID)) + DataSize; - - if (Length < FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0])) - { - Status = STATUS_BUFFER_TOO_SMALL; - } - else - { - ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION) - KeyValueInformation; - ValueFullInformation->TitleIndex = 0; - ValueFullInformation->Type = ValueCell->DataType; - ValueFullInformation->NameLength = NameSize; - ValueFullInformation->DataOffset = - (ULONG_PTR)ValueFullInformation->Name - - (ULONG_PTR)ValueFullInformation + - ValueFullInformation->NameLength; - ValueFullInformation->DataOffset = - ROUND_UP(ValueFullInformation->DataOffset, sizeof(PVOID)); - ValueFullInformation->DataLength = ValueCell->DataSize & REG_DATA_SIZE_MASK; - - if (Length < ValueFullInformation->DataOffset) - { - NameSize = Length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]); - DataSize = 0; - Status = STATUS_BUFFER_OVERFLOW; - CHECKPOINT; - } - else if (Length - ValueFullInformation->DataOffset < DataSize) - { - DataSize = Length - ValueFullInformation->DataOffset; - Status = STATUS_BUFFER_OVERFLOW; - CHECKPOINT; - } - - if (ValueCell->Flags & REG_VALUE_NAME_PACKED) - { - CmiCopyPackedName(ValueFullInformation->Name, - ValueCell->Name, - NameSize / sizeof(WCHAR)); - } - else - { - RtlCopyMemory(ValueFullInformation->Name, - ValueCell->Name, - NameSize); - } - - if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET)) - { - DataCell = HvGetCell (&RegistryHive->Hive, ValueCell->DataOffset); - RtlCopyMemory((PCHAR) ValueFullInformation - + ValueFullInformation->DataOffset, - DataCell, DataSize); - } - else - { - RtlCopyMemory((PCHAR) ValueFullInformation - + ValueFullInformation->DataOffset, - &ValueCell->DataOffset, DataSize); - } - } - break; - - default: - DPRINT1("Not handling 0x%x\n", KeyValueInformationClass); - break; - } - } - else - { - Status = STATUS_UNSUCCESSFUL; - } - - ExReleaseResourceLite(&CmpRegistryLock); - KeLeaveCriticalRegion(); - ObDereferenceObject(KeyObject); - PostOperationInfo.Status = Status; - CmiCallRegisteredCallbacks(RegNtPostEnumerateValueKey, &PostOperationInfo); - - return Status; + ObDereferenceObject(KeyObject); + return Status; } - NTSTATUS STDCALL NtFlushKey(IN HANDLE KeyHandle) { diff --git a/reactos/ntoskrnl/config/cm.h b/reactos/ntoskrnl/config/cm.h index b899c71c4b0..71df11623e9 100644 --- a/reactos/ntoskrnl/config/cm.h +++ b/reactos/ntoskrnl/config/cm.h @@ -769,6 +769,28 @@ CmpQueryKeyValueData( OUT PNTSTATUS Status ); +VALUE_SEARCH_RETURN_TYPE +NTAPI +CmpGetValueListFromCache( + IN PKEY_OBJECT KeyObject, + OUT PCELL_DATA *CellData, + OUT BOOLEAN *IndexIsCached, + OUT PHCELL_INDEX ValueListToRelease +); + +VALUE_SEARCH_RETURN_TYPE +NTAPI +CmpGetValueKeyFromCache( + IN PKEY_OBJECT KeyObject, + IN PCELL_DATA CellData, + IN ULONG Index, + OUT PCM_CACHED_VALUE **CachedValue, + OUT PCM_KEY_VALUE *Value, + IN BOOLEAN IndexIsCached, + OUT BOOLEAN *ValueIsCached, + OUT PHCELL_INDEX CellToRelease +); + // // Registry Validation Functions // diff --git a/reactos/ntoskrnl/config/cmapi.c b/reactos/ntoskrnl/config/cmapi.c index f690045460e..da5e1e5aa76 100644 --- a/reactos/ntoskrnl/config/cmapi.c +++ b/reactos/ntoskrnl/config/cmapi.c @@ -519,3 +519,108 @@ CmQueryValueKey(IN PKEY_OBJECT KeyObject, KeLeaveCriticalRegion(); return Status; } + +NTSTATUS +NTAPI +CmEnumerateValueKey(IN PKEY_OBJECT KeyObject, + IN ULONG Index, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + IN PVOID KeyValueInformation, + IN ULONG Length, + IN PULONG ResultLength) +{ + NTSTATUS Status; + PHHIVE Hive; + PCM_KEY_NODE Parent; + HCELL_INDEX CellToRelease = HCELL_NIL, CellToRelease2 = HCELL_NIL; + VALUE_SEARCH_RETURN_TYPE Result; + BOOLEAN IndexIsCached, ValueIsCached = FALSE; + PCELL_DATA CellData; + PCM_CACHED_VALUE *CachedValue; + PCM_KEY_VALUE ValueData; + PAGED_CODE(); + + /* 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; + } + + /* Make sure the index is valid */ + //if (Index >= KeyObject->ValueCache.Count) + if (Index >= KeyObject->KeyCell->ValueList.Count) + { + /* Release the cell and fail */ + HvReleaseCell(Hive, KeyObject->KeyCellOffset); + Status = STATUS_NO_MORE_ENTRIES; + goto Quickie; + } + + /* Find the value list */ + Result = CmpGetValueListFromCache(KeyObject, + &CellData, + &IndexIsCached, + &CellToRelease); + if (Result != SearchSuccess) + { + /* Sanity check */ + ASSERT(CellData == NULL); + + /* Release the cell and fail */ + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Quickie; + } + + /* Now get the key value */ + Result = CmpGetValueKeyFromCache(KeyObject, + CellData, + Index, + &CachedValue, + &ValueData, + IndexIsCached, + &ValueIsCached, + &CellToRelease2); + if (Result != SearchSuccess) + { + /* Sanity check */ + ASSERT(CellToRelease2 == HCELL_NIL); + + /* Release the cells and fail */ + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Quickie; + } + + /* Query the information requested */ + Result = CmpQueryKeyValueData(KeyObject, + CachedValue, + ValueData, + ValueIsCached, + KeyValueInformationClass, + KeyValueInformation, + Length, + ResultLength, + &Status); + +Quickie: + /* If we have a cell to release, do so */ + if (CellToRelease != HCELL_NIL) HvReleaseCell(Hive, CellToRelease); + + /* Release the parent cell */ + HvReleaseCell(Hive, KeyObject->KeyCellOffset); + + /* If we have a cell to release, do so */ + if (CellToRelease2 != HCELL_NIL) HvReleaseCell(Hive, CellToRelease2); + + /* Release hive lock */ + ExReleaseResourceLite(&CmpRegistryLock); + KeLeaveCriticalRegion(); + return Status; +}