mirror of
https://github.com/reactos/reactos.git
synced 2025-04-27 17:10:22 +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 ULONG Length,
|
||||||
IN PULONG ResultLength);
|
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
|
NTSTATUS
|
||||||
CmiAllocateHashTableCell(IN PEREGISTRY_HIVE RegistryHive,
|
CmiAllocateHashTableCell(IN PEREGISTRY_HIVE RegistryHive,
|
||||||
OUT PHASH_TABLE_CELL *HashBlock,
|
OUT PHASH_TABLE_CELL *HashBlock,
|
||||||
|
@ -304,14 +321,6 @@ CmiAddKeyToHashTable(PEREGISTRY_HIVE RegistryHive,
|
||||||
PCM_KEY_NODE NewKeyCell,
|
PCM_KEY_NODE NewKeyCell,
|
||||||
HCELL_INDEX NKBOffset);
|
HCELL_INDEX NKBOffset);
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
CmSetValueKey(IN PKEY_OBJECT KeyObject,
|
|
||||||
IN PUNICODE_STRING ValueName,
|
|
||||||
IN ULONG Type,
|
|
||||||
IN PVOID Data,
|
|
||||||
IN ULONG DataSize);
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CmiRemoveKeyFromHashTable(PEREGISTRY_HIVE RegistryHive,
|
CmiRemoveKeyFromHashTable(PEREGISTRY_HIVE RegistryHive,
|
||||||
PHASH_TABLE_CELL HashBlock,
|
PHASH_TABLE_CELL HashBlock,
|
||||||
|
|
|
@ -830,8 +830,8 @@ NtEnumerateKey(IN HANDLE KeyHandle,
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS STDCALL
|
NTAPI
|
||||||
NtEnumerateValueKey(IN HANDLE KeyHandle,
|
NtEnumerateValueKey(IN HANDLE KeyHandle,
|
||||||
IN ULONG Index,
|
IN ULONG Index,
|
||||||
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
|
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
|
||||||
|
@ -841,27 +841,10 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PKEY_OBJECT KeyObject;
|
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_ENUMERATE_VALUE_KEY_INFORMATION EnumerateValueKeyInfo;
|
||||||
REG_POST_OPERATION_INFORMATION PostOperationInfo;
|
REG_POST_OPERATION_INFORMATION PostOperationInfo;
|
||||||
PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation;
|
|
||||||
PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation;
|
|
||||||
PKEY_VALUE_FULL_INFORMATION ValueFullInformation;
|
|
||||||
|
|
||||||
PAGED_CODE();
|
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 */
|
/* Verify that the handle is valid and is a registry key */
|
||||||
Status = ObReferenceObjectByHandle(KeyHandle,
|
Status = ObReferenceObjectByHandle(KeyHandle,
|
||||||
KEY_QUERY_VALUE,
|
KEY_QUERY_VALUE,
|
||||||
|
@ -869,12 +852,9 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
|
||||||
ExGetPreviousMode(),
|
ExGetPreviousMode(),
|
||||||
(PVOID *)&KeyObject,
|
(PVOID *)&KeyObject,
|
||||||
NULL);
|
NULL);
|
||||||
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
/* Setup the callback */
|
||||||
{
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
PostOperationInfo.Object = (PVOID)KeyObject;
|
PostOperationInfo.Object = (PVOID)KeyObject;
|
||||||
EnumerateValueKeyInfo.Object = (PVOID)KeyObject;
|
EnumerateValueKeyInfo.Object = (PVOID)KeyObject;
|
||||||
EnumerateValueKeyInfo.Index = Index;
|
EnumerateValueKeyInfo.Index = Index;
|
||||||
|
@ -883,224 +863,28 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
|
||||||
EnumerateValueKeyInfo.Length = Length;
|
EnumerateValueKeyInfo.Length = Length;
|
||||||
EnumerateValueKeyInfo.ResultLength = ResultLength;
|
EnumerateValueKeyInfo.ResultLength = ResultLength;
|
||||||
|
|
||||||
Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateValueKey, &EnumerateValueKeyInfo);
|
/* Do the callback */
|
||||||
if (!NT_SUCCESS(Status))
|
Status = CmiCallRegisteredCallbacks(RegNtPreEnumerateValueKey,
|
||||||
|
&EnumerateValueKeyInfo);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
PostOperationInfo.Status = Status;
|
/* Call the internal API */
|
||||||
CmiCallRegisteredCallbacks(RegNtPostEnumerateValueKey, &PostOperationInfo);
|
Status = CmEnumerateValueKey(KeyObject,
|
||||||
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,
|
Index,
|
||||||
&ValueCell);
|
KeyValueInformationClass,
|
||||||
|
KeyValueInformation,
|
||||||
|
Length,
|
||||||
|
ResultLength);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
/* Do the post callback */
|
||||||
{
|
|
||||||
ExReleaseResourceLite(&CmpRegistryLock);
|
|
||||||
KeLeaveCriticalRegion();
|
|
||||||
ObDereferenceObject(KeyObject);
|
|
||||||
PostOperationInfo.Status = Status;
|
PostOperationInfo.Status = Status;
|
||||||
CmiCallRegisteredCallbacks(RegNtPostEnumerateValueKey, &PostOperationInfo);
|
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);
|
ObDereferenceObject(KeyObject);
|
||||||
PostOperationInfo.Status = Status;
|
|
||||||
CmiCallRegisteredCallbacks(RegNtPostEnumerateValueKey, &PostOperationInfo);
|
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS STDCALL
|
||||||
NtFlushKey(IN HANDLE KeyHandle)
|
NtFlushKey(IN HANDLE KeyHandle)
|
||||||
{
|
{
|
||||||
|
|
|
@ -769,6 +769,28 @@ CmpQueryKeyValueData(
|
||||||
OUT PNTSTATUS Status
|
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
|
// Registry Validation Functions
|
||||||
//
|
//
|
||||||
|
|
|
@ -519,3 +519,108 @@ CmQueryValueKey(IN PKEY_OBJECT KeyObject,
|
||||||
KeLeaveCriticalRegion();
|
KeLeaveCriticalRegion();
|
||||||
return Status;
|
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