mirror of
https://github.com/reactos/reactos.git
synced 2025-04-26 16:40:27 +00:00
- 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
This commit is contained in:
parent
3ecce0a306
commit
934cae8069
4 changed files with 189 additions and 269 deletions
|
@ -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,
|
||||
|
|
|
@ -830,8 +830,8 @@ NtEnumerateKey(IN HANDLE KeyHandle,
|
|||
return(Status);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtEnumerateValueKey(IN HANDLE KeyHandle,
|
||||
IN ULONG Index,
|
||||
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
|
||||
|
@ -841,27 +841,10 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
|
|||
{
|
||||
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;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DPRINT("KH 0x%p I %d KVIC %x KVI 0x%p L %d RL 0x%p\n",
|
||||
KeyHandle,
|
||||
Index,
|
||||
KeyValueInformationClass,
|
||||
KeyValueInformation,
|
||||
Length,
|
||||
ResultLength);
|
||||
|
||||
/* Verify that the handle is valid and is a registry key */
|
||||
Status = ObReferenceObjectByHandle(KeyHandle,
|
||||
KEY_QUERY_VALUE,
|
||||
|
@ -869,12 +852,9 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
|
|||
ExGetPreviousMode(),
|
||||
(PVOID *)&KeyObject,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Setup the callback */
|
||||
PostOperationInfo.Object = (PVOID)KeyObject;
|
||||
EnumerateValueKeyInfo.Object = (PVOID)KeyObject;
|
||||
EnumerateValueKeyInfo.Index = Index;
|
||||
|
@ -883,224 +863,28 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
|
|||
EnumerateValueKeyInfo.Length = Length;
|
||||
EnumerateValueKeyInfo.ResultLength = ResultLength;
|
||||
|
||||
Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateValueKey, &EnumerateValueKeyInfo);
|
||||
if (!NT_SUCCESS(Status))
|
||||
/* Do the callback */
|
||||
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,
|
||||
/* Call the internal API */
|
||||
Status = CmEnumerateValueKey(KeyObject,
|
||||
Index,
|
||||
&ValueCell);
|
||||
KeyValueInformationClass,
|
||||
KeyValueInformation,
|
||||
Length,
|
||||
ResultLength);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExReleaseResourceLite(&CmpRegistryLock);
|
||||
KeLeaveCriticalRegion();
|
||||
ObDereferenceObject(KeyObject);
|
||||
/* Do the post callback */
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtFlushKey(IN HANDLE KeyHandle)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue