mirror of
https://github.com/reactos/reactos.git
synced 2024-10-04 16:36:11 +00:00
- Make CmiGetMaxClassLength, CmiGetMaxNameLength, CmiGetMaxValueDataLength, CmiGetMaxValueNameLength use PHHIVE and PCM_KEY_NODE instead of PKEY_OBJECT or PERGSITRY_HIVE/PCM_KEY_NDOE so they're consistent.
- Implement NtQueryKey as a simple wrapper around CmQueryKey. - Implement CmQueryKey based on previous code, and handle only the classes that the previous code handled, through CmpQueryKeyData. - The CmiGetMax* routines will be depreated soon since they're a perf hit and we should be reading the key node's values instead. svn path=/trunk/; revision=26780
This commit is contained in:
parent
934cae8069
commit
64f4f03b95
|
@ -221,17 +221,17 @@ ULONG
|
|||
CmiGetNumberOfSubKeys(PKEY_OBJECT KeyObject);
|
||||
|
||||
ULONG
|
||||
CmiGetMaxNameLength(IN PKEY_OBJECT KeyObject);
|
||||
CmiGetMaxNameLength(IN PHHIVE RegistryHive, IN PCM_KEY_NODE KeyCell);
|
||||
|
||||
ULONG
|
||||
CmiGetMaxClassLength(IN PKEY_OBJECT KeyObject);
|
||||
CmiGetMaxClassLength(IN PHHIVE RegistryHive, IN PCM_KEY_NODE KeyCell);
|
||||
|
||||
ULONG
|
||||
CmiGetMaxValueNameLength(IN PEREGISTRY_HIVE RegistryHive,
|
||||
CmiGetMaxValueNameLength(IN PHHIVE RegistryHive,
|
||||
IN PCM_KEY_NODE KeyCell);
|
||||
|
||||
ULONG
|
||||
CmiGetMaxValueDataLength(IN PEREGISTRY_HIVE RegistryHive,
|
||||
CmiGetMaxValueDataLength(IN PHHIVE RegistryHive,
|
||||
IN PCM_KEY_NODE KeyCell);
|
||||
|
||||
NTSTATUS
|
||||
|
@ -301,6 +301,14 @@ CmSetValueKey(IN PKEY_OBJECT KeyObject,
|
|||
IN PVOID Data,
|
||||
IN ULONG DataSize);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CmQueryKey(IN PKEY_OBJECT KeyObject,
|
||||
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,
|
||||
|
|
|
@ -786,13 +786,13 @@ NtEnumerateKey(IN HANDLE KeyHandle,
|
|||
sizeof(WCHAR);
|
||||
FullInformation->ClassLength = SubKeyCell->ClassSize;
|
||||
FullInformation->SubKeys = CmiGetNumberOfSubKeys(KeyObject); //SubKeyCell->SubKeyCounts;
|
||||
FullInformation->MaxNameLen = CmiGetMaxNameLength(KeyObject);
|
||||
FullInformation->MaxClassLen = CmiGetMaxClassLength(KeyObject);
|
||||
FullInformation->MaxNameLen = CmiGetMaxNameLength(&RegistryHive->Hive, SubKeyCell);
|
||||
FullInformation->MaxClassLen = CmiGetMaxClassLength(&RegistryHive->Hive, SubKeyCell);
|
||||
FullInformation->Values = SubKeyCell->ValueList.Count;
|
||||
FullInformation->MaxValueNameLen =
|
||||
CmiGetMaxValueNameLength(RegistryHive, SubKeyCell);
|
||||
CmiGetMaxValueNameLength(&RegistryHive->Hive, SubKeyCell);
|
||||
FullInformation->MaxValueDataLen =
|
||||
CmiGetMaxValueDataLength(RegistryHive, SubKeyCell);
|
||||
CmiGetMaxValueDataLength(&RegistryHive->Hive, SubKeyCell);
|
||||
|
||||
if (Length - FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]) < ClassSize)
|
||||
{
|
||||
|
@ -1094,232 +1094,58 @@ openkey_cleanup:
|
|||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtQueryKey(IN HANDLE KeyHandle,
|
||||
IN KEY_INFORMATION_CLASS KeyInformationClass,
|
||||
OUT PVOID KeyInformation,
|
||||
IN ULONG Length,
|
||||
OUT PULONG ResultLength)
|
||||
IN KEY_INFORMATION_CLASS KeyInformationClass,
|
||||
OUT PVOID KeyInformation,
|
||||
IN ULONG Length,
|
||||
OUT PULONG ResultLength)
|
||||
{
|
||||
PKEY_BASIC_INFORMATION BasicInformation;
|
||||
PKEY_NODE_INFORMATION NodeInformation;
|
||||
PKEY_FULL_INFORMATION FullInformation;
|
||||
PEREGISTRY_HIVE RegistryHive;
|
||||
PVOID ClassCell;
|
||||
PKEY_OBJECT KeyObject;
|
||||
PCM_KEY_NODE KeyCell;
|
||||
ULONG NameSize, ClassSize;
|
||||
NTSTATUS Status;
|
||||
REG_QUERY_KEY_INFORMATION QueryKeyInfo;
|
||||
REG_POST_OPERATION_INFORMATION PostOperationInfo;
|
||||
NTSTATUS Status;
|
||||
PKEY_OBJECT KeyObject;
|
||||
REG_QUERY_KEY_INFORMATION QueryKeyInfo;
|
||||
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;
|
||||
|
||||
DPRINT("NtQueryKey(KH 0x%p KIC %x KI 0x%p L %d RL 0x%p)\n",
|
||||
KeyHandle,
|
||||
KeyInformationClass,
|
||||
KeyInformation,
|
||||
Length,
|
||||
ResultLength);
|
||||
/* Setup the callback */
|
||||
PostOperationInfo.Object = (PVOID)KeyObject;
|
||||
QueryKeyInfo.Object = (PVOID)KeyObject;
|
||||
QueryKeyInfo.KeyInformationClass = KeyInformationClass;
|
||||
QueryKeyInfo.KeyInformation = KeyInformation;
|
||||
QueryKeyInfo.Length = Length;
|
||||
QueryKeyInfo.ResultLength = ResultLength;
|
||||
|
||||
/* 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))
|
||||
/* Do the callback */
|
||||
Status = CmiCallRegisteredCallbacks(RegNtPreQueryKey, &QueryKeyInfo);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
/* Call the internal API */
|
||||
Status = CmQueryKey(KeyObject,
|
||||
KeyInformationClass,
|
||||
KeyInformation,
|
||||
Length,
|
||||
ResultLength);
|
||||
|
||||
/* Do the post callback */
|
||||
PostOperationInfo.Status = Status;
|
||||
CmiCallRegisteredCallbacks(RegNtPostQueryKey, &PostOperationInfo);
|
||||
}
|
||||
|
||||
PostOperationInfo.Object = (PVOID)KeyObject;
|
||||
QueryKeyInfo.Object = (PVOID)KeyObject;
|
||||
QueryKeyInfo.KeyInformationClass = KeyInformationClass;
|
||||
QueryKeyInfo.KeyInformation = KeyInformation;
|
||||
QueryKeyInfo.Length = Length;
|
||||
QueryKeyInfo.ResultLength = ResultLength;
|
||||
|
||||
Status = CmiCallRegisteredCallbacks(RegNtPreQueryKey, &QueryKeyInfo);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
PostOperationInfo.Status = Status;
|
||||
CmiCallRegisteredCallbacks(RegNtPostQueryKey, &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;
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
switch (KeyInformationClass)
|
||||
{
|
||||
case KeyBasicInformation:
|
||||
NameSize = KeyObject->Name.Length;
|
||||
|
||||
*ResultLength = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]);
|
||||
|
||||
/* Check size of buffer */
|
||||
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 = KeyCell->LastWriteTime.u.LowPart;
|
||||
BasicInformation->LastWriteTime.u.HighPart = KeyCell->LastWriteTime.u.HighPart;
|
||||
BasicInformation->TitleIndex = 0;
|
||||
BasicInformation->NameLength = KeyObject->Name.Length;
|
||||
|
||||
if (Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]) <
|
||||
NameSize)
|
||||
{
|
||||
NameSize = Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]);
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
CHECKPOINT;
|
||||
}
|
||||
|
||||
RtlCopyMemory(BasicInformation->Name,
|
||||
KeyObject->Name.Buffer,
|
||||
NameSize);
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyNodeInformation:
|
||||
NameSize = KeyObject->Name.Length;
|
||||
ClassSize = KeyCell->ClassSize;
|
||||
|
||||
*ResultLength = FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) +
|
||||
NameSize + ClassSize;
|
||||
|
||||
/* Check size of buffer */
|
||||
if (Length < *ResultLength)
|
||||
{
|
||||
Status = STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fill buffer with requested info */
|
||||
NodeInformation = (PKEY_NODE_INFORMATION) KeyInformation;
|
||||
NodeInformation->LastWriteTime.u.LowPart = KeyCell->LastWriteTime.u.LowPart;
|
||||
NodeInformation->LastWriteTime.u.HighPart = KeyCell->LastWriteTime.u.HighPart;
|
||||
NodeInformation->TitleIndex = 0;
|
||||
NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) +
|
||||
KeyObject->Name.Length;
|
||||
NodeInformation->ClassLength = KeyCell->ClassSize;
|
||||
NodeInformation->NameLength = KeyObject->Name.Length;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
RtlCopyMemory(NodeInformation->Name,
|
||||
KeyObject->Name.Buffer,
|
||||
NameSize);
|
||||
|
||||
if (ClassSize != 0)
|
||||
{
|
||||
ClassCell = HvGetCell (&KeyObject->RegistryHive->Hive,
|
||||
KeyCell->ClassNameOffset);
|
||||
RtlCopyMemory (NodeInformation->Name + KeyObject->Name.Length,
|
||||
ClassCell,
|
||||
ClassSize);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyFullInformation:
|
||||
ClassSize = KeyCell->ClassSize;
|
||||
|
||||
*ResultLength = FIELD_OFFSET(KEY_FULL_INFORMATION, Class) +
|
||||
ClassSize;
|
||||
|
||||
/* Check size of buffer */
|
||||
if (Length < FIELD_OFFSET(KEY_FULL_INFORMATION, Class))
|
||||
{
|
||||
Status = STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fill buffer with requested info */
|
||||
FullInformation = (PKEY_FULL_INFORMATION) KeyInformation;
|
||||
FullInformation->LastWriteTime.u.LowPart = KeyCell->LastWriteTime.u.LowPart;
|
||||
FullInformation->LastWriteTime.u.HighPart = KeyCell->LastWriteTime.u.HighPart;
|
||||
FullInformation->TitleIndex = 0;
|
||||
FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR);
|
||||
FullInformation->ClassLength = KeyCell->ClassSize;
|
||||
FullInformation->SubKeys = CmiGetNumberOfSubKeys(KeyObject); //KeyCell->SubKeyCounts;
|
||||
FullInformation->MaxNameLen = CmiGetMaxNameLength(KeyObject);
|
||||
FullInformation->MaxClassLen = CmiGetMaxClassLength(KeyObject);
|
||||
FullInformation->Values = KeyCell->ValueList.Count;
|
||||
FullInformation->MaxValueNameLen =
|
||||
CmiGetMaxValueNameLength(RegistryHive, KeyCell);
|
||||
FullInformation->MaxValueDataLen =
|
||||
CmiGetMaxValueDataLength(RegistryHive, KeyCell);
|
||||
|
||||
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)
|
||||
{
|
||||
ClassCell = HvGetCell (&KeyObject->RegistryHive->Hive,
|
||||
KeyCell->ClassNameOffset);
|
||||
RtlCopyMemory (FullInformation->Class,
|
||||
ClassCell, ClassSize);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyNameInformation:
|
||||
case KeyCachedInformation:
|
||||
case KeyFlagsInformation:
|
||||
DPRINT1("Key information class 0x%x not yet implemented!\n", KeyInformationClass);
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINT1("Not handling 0x%x\n", KeyInformationClass);
|
||||
Status = STATUS_INVALID_INFO_CLASS;
|
||||
break;
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&CmpRegistryLock);
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
PostOperationInfo.Status = Status;
|
||||
CmiCallRegisteredCallbacks(RegNtPostQueryKey, &PostOperationInfo);
|
||||
|
||||
ObDereferenceObject(KeyObject);
|
||||
|
||||
return(Status);
|
||||
/* Dereference and return status */
|
||||
ObDereferenceObject(KeyObject);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -1371,6 +1197,7 @@ NtQueryValueKey(IN HANDLE KeyHandle,
|
|||
CmiCallRegisteredCallbacks(RegNtPostQueryValueKey, &PostOperationInfo);
|
||||
}
|
||||
|
||||
/* Dereference and return status */
|
||||
ObDereferenceObject(KeyObject);
|
||||
return Status;
|
||||
}
|
||||
|
|
|
@ -124,32 +124,27 @@ CmiGetNumberOfSubKeys(PKEY_OBJECT KeyObject)
|
|||
|
||||
|
||||
ULONG
|
||||
CmiGetMaxNameLength(PKEY_OBJECT KeyObject)
|
||||
CmiGetMaxNameLength(PHHIVE Hive,
|
||||
PCM_KEY_NODE KeyCell)
|
||||
{
|
||||
PHASH_TABLE_CELL HashBlock;
|
||||
PCM_KEY_NODE CurSubKeyCell;
|
||||
PCM_KEY_NODE KeyCell;
|
||||
ULONG MaxName;
|
||||
ULONG NameSize;
|
||||
ULONG i;
|
||||
ULONG Storage;
|
||||
|
||||
VERIFY_KEY_OBJECT(KeyObject);
|
||||
|
||||
KeyCell = KeyObject->KeyCell;
|
||||
VERIFY_KEY_CELL(KeyCell);
|
||||
|
||||
MaxName = 0;
|
||||
for (Storage = HvStable; Storage < HvMaxStorageType; Storage++)
|
||||
{
|
||||
if (KeyCell->SubKeyLists[Storage] != HCELL_NULL)
|
||||
{
|
||||
HashBlock = HvGetCell (&KeyObject->RegistryHive->Hive, KeyCell->SubKeyLists[Storage]);
|
||||
HashBlock = HvGetCell (Hive, KeyCell->SubKeyLists[Storage]);
|
||||
ASSERT(HashBlock->Id == REG_HASH_TABLE_CELL_ID);
|
||||
|
||||
for (i = 0; i < KeyCell->SubKeyCounts[Storage]; i++)
|
||||
{
|
||||
CurSubKeyCell = HvGetCell (&KeyObject->RegistryHive->Hive,
|
||||
CurSubKeyCell = HvGetCell (Hive,
|
||||
HashBlock->Table[i].KeyOffset);
|
||||
NameSize = CurSubKeyCell->NameSize;
|
||||
if (CurSubKeyCell->Flags & REG_KEY_NAME_PACKED)
|
||||
|
@ -167,32 +162,27 @@ CmiGetMaxNameLength(PKEY_OBJECT KeyObject)
|
|||
|
||||
|
||||
ULONG
|
||||
CmiGetMaxClassLength(PKEY_OBJECT KeyObject)
|
||||
CmiGetMaxClassLength(PHHIVE Hive,
|
||||
PCM_KEY_NODE KeyCell)
|
||||
{
|
||||
PHASH_TABLE_CELL HashBlock;
|
||||
PCM_KEY_NODE CurSubKeyCell;
|
||||
PCM_KEY_NODE KeyCell;
|
||||
ULONG MaxClass;
|
||||
ULONG i;
|
||||
ULONG Storage;
|
||||
|
||||
VERIFY_KEY_OBJECT(KeyObject);
|
||||
|
||||
KeyCell = KeyObject->KeyCell;
|
||||
VERIFY_KEY_CELL(KeyCell);
|
||||
|
||||
MaxClass = 0;
|
||||
for (Storage = HvStable; Storage < HvMaxStorageType; Storage++)
|
||||
{
|
||||
if (KeyCell->SubKeyLists[Storage] != HCELL_NULL)
|
||||
{
|
||||
HashBlock = HvGetCell (&KeyObject->RegistryHive->Hive,
|
||||
HashBlock = HvGetCell (Hive,
|
||||
KeyCell->SubKeyLists[Storage]);
|
||||
ASSERT(HashBlock->Id == REG_HASH_TABLE_CELL_ID);
|
||||
|
||||
for (i = 0; i < KeyCell->SubKeyCounts[Storage]; i++)
|
||||
{
|
||||
CurSubKeyCell = HvGetCell (&KeyObject->RegistryHive->Hive,
|
||||
CurSubKeyCell = HvGetCell (Hive,
|
||||
HashBlock->Table[i].KeyOffset);
|
||||
|
||||
if (MaxClass < CurSubKeyCell->ClassSize)
|
||||
|
@ -208,7 +198,7 @@ CmiGetMaxClassLength(PKEY_OBJECT KeyObject)
|
|||
|
||||
|
||||
ULONG
|
||||
CmiGetMaxValueNameLength(PEREGISTRY_HIVE RegistryHive,
|
||||
CmiGetMaxValueNameLength(PHHIVE Hive,
|
||||
PCM_KEY_NODE KeyCell)
|
||||
{
|
||||
PVALUE_LIST_CELL ValueListCell;
|
||||
|
@ -225,12 +215,12 @@ CmiGetMaxValueNameLength(PEREGISTRY_HIVE RegistryHive,
|
|||
}
|
||||
|
||||
MaxValueName = 0;
|
||||
ValueListCell = HvGetCell (&RegistryHive->Hive,
|
||||
ValueListCell = HvGetCell (Hive,
|
||||
KeyCell->ValueList.List);
|
||||
|
||||
for (i = 0; i < KeyCell->ValueList.Count; i++)
|
||||
{
|
||||
CurValueCell = HvGetCell (&RegistryHive->Hive,
|
||||
CurValueCell = HvGetCell (Hive,
|
||||
ValueListCell->ValueOffset[i]);
|
||||
if (CurValueCell == NULL)
|
||||
{
|
||||
|
@ -256,7 +246,7 @@ CmiGetMaxValueNameLength(PEREGISTRY_HIVE RegistryHive,
|
|||
|
||||
|
||||
ULONG
|
||||
CmiGetMaxValueDataLength(PEREGISTRY_HIVE RegistryHive,
|
||||
CmiGetMaxValueDataLength(PHHIVE Hive,
|
||||
PCM_KEY_NODE KeyCell)
|
||||
{
|
||||
PVALUE_LIST_CELL ValueListCell;
|
||||
|
@ -272,11 +262,11 @@ CmiGetMaxValueDataLength(PEREGISTRY_HIVE RegistryHive,
|
|||
}
|
||||
|
||||
MaxValueData = 0;
|
||||
ValueListCell = HvGetCell (&RegistryHive->Hive, KeyCell->ValueList.List);
|
||||
ValueListCell = HvGetCell (Hive, KeyCell->ValueList.List);
|
||||
|
||||
for (i = 0; i < KeyCell->ValueList.Count; i++)
|
||||
{
|
||||
CurValueCell = HvGetCell (&RegistryHive->Hive,
|
||||
CurValueCell = HvGetCell (Hive,
|
||||
ValueListCell->ValueOffset[i]);
|
||||
if ((MaxValueData < (LONG)(CurValueCell->DataSize & REG_DATA_SIZE_MASK)))
|
||||
{
|
||||
|
|
|
@ -675,6 +675,16 @@ typedef struct _KEY_VALUE_INFORMATION
|
|||
};
|
||||
} KEY_VALUE_INFORMATION, *PKEY_VALUE_INFORMATION;
|
||||
|
||||
typedef struct _KEY_INFORMATION
|
||||
{
|
||||
union
|
||||
{
|
||||
KEY_BASIC_INFORMATION KeyBasicInformation;
|
||||
KEY_FULL_INFORMATION KeyFullInformation;
|
||||
KEY_NODE_INFORMATION KeyNodeInformation;
|
||||
};
|
||||
} KEY_INFORMATION, *PKEY_INFORMATION;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BUGBUG Old Hive Stuff for Temporary Support
|
||||
|
@ -718,6 +728,10 @@ extern KTIMER CmiWorkerTimer;
|
|||
VOID NTAPI CmiWorkerThread(IN PVOID Param);
|
||||
PVOID NTAPI CmpRosGetHardwareHive(OUT PULONG Length);
|
||||
NTSTATUS CmiCallRegisteredCallbacks(IN REG_NOTIFY_CLASS Argument1, IN PVOID Argument2);
|
||||
ULONG CmiGetMaxNameLength(IN PHHIVE RegistryHive, IN PCM_KEY_NODE KeyCell);
|
||||
ULONG CmiGetMaxClassLength(IN PHHIVE RegistryHive, IN PCM_KEY_NODE KeyCell);
|
||||
ULONG CmiGetMaxValueNameLength(IN PHHIVE RegistryHive, IN PCM_KEY_NODE KeyCell);
|
||||
ULONG CmiGetMaxValueDataLength(IN PHHIVE RegistryHive, IN PCM_KEY_NODE KeyCell);
|
||||
VOID CmiSyncHives(VOID);
|
||||
#define HIVE_NO_FILE 0x00000002
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -624,3 +624,296 @@ Quickie:
|
|||
KeLeaveCriticalRegion();
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CmpQueryKeyData(IN PHHIVE Hive,
|
||||
IN PCM_KEY_NODE Node,
|
||||
IN KEY_INFORMATION_CLASS KeyInformationClass,
|
||||
IN OUT PVOID KeyInformation,
|
||||
IN ULONG Length,
|
||||
IN OUT PULONG ResultLength)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG Size, SizeLeft, MinimumSize;
|
||||
PKEY_INFORMATION Info = (PKEY_INFORMATION)KeyInformation;
|
||||
USHORT NameLength;
|
||||
|
||||
/* Check if the value is compressed */
|
||||
if (Node->Flags & VALUE_COMP_NAME)
|
||||
{
|
||||
/* Get the compressed name size */
|
||||
NameLength = CmpCompressedNameSize(Node->Name, Node->NameLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the real size */
|
||||
NameLength = Node->NameLength;
|
||||
}
|
||||
|
||||
/* Check what kind of information is being requested */
|
||||
switch (KeyInformationClass)
|
||||
{
|
||||
/* Basic information */
|
||||
case KeyBasicInformation:
|
||||
|
||||
/* This is the size we need */
|
||||
Size = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name) + NameLength;
|
||||
|
||||
/* And this is the minimum we can work with */
|
||||
MinimumSize = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name);
|
||||
|
||||
/* Let the caller know and assume success */
|
||||
*ResultLength = Size;
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
/* Check if the bufer we got is too small */
|
||||
if (Length < MinimumSize)
|
||||
{
|
||||
/* Let the caller know and fail */
|
||||
Status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy the basic information */
|
||||
Info->KeyBasicInformation.LastWriteTime = Node->LastWriteTime;
|
||||
Info->KeyBasicInformation.TitleIndex = 0;
|
||||
Info->KeyBasicInformation.NameLength = NameLength;
|
||||
|
||||
/* Only the name is left */
|
||||
SizeLeft = Length - MinimumSize;
|
||||
Size = NameLength;
|
||||
|
||||
/* Check if we don't have enough space for the name */
|
||||
if (SizeLeft < Size)
|
||||
{
|
||||
/* Truncate the name we'll return, and tell the caller */
|
||||
Size = SizeLeft;
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
/* Check if this is a compressed key */
|
||||
if (Node->Flags & KEY_COMP_NAME)
|
||||
{
|
||||
/* Copy the compressed name */
|
||||
CmpCopyCompressedName(Info->KeyBasicInformation.Name,
|
||||
SizeLeft,
|
||||
Node->Name,
|
||||
Node->NameLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, copy the raw name */
|
||||
RtlCopyMemory(Info->KeyBasicInformation.Name,
|
||||
Node->Name,
|
||||
Size);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Node information */
|
||||
case KeyNodeInformation:
|
||||
|
||||
/* Calculate the size we need */
|
||||
Size = FIELD_OFFSET(KEY_NODE_INFORMATION, Name) +
|
||||
NameLength +
|
||||
Node->ClassLength;
|
||||
|
||||
/* And the minimum size we can support */
|
||||
MinimumSize = FIELD_OFFSET(KEY_NODE_INFORMATION, Name);
|
||||
|
||||
/* Return the size to the caller and assume succes */
|
||||
*ResultLength = Size;
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
/* Check if the caller's buffer is too small */
|
||||
if (Length < MinimumSize)
|
||||
{
|
||||
/* Let them know, and fail */
|
||||
Status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy the basic information */
|
||||
Info->KeyNodeInformation.LastWriteTime = Node->LastWriteTime;
|
||||
Info->KeyNodeInformation.TitleIndex = 0;
|
||||
Info->KeyNodeInformation.ClassLength = Node->ClassLength;
|
||||
Info->KeyNodeInformation.NameLength = NameLength;
|
||||
|
||||
/* Now the name is left */
|
||||
SizeLeft = Length - MinimumSize;
|
||||
Size = NameLength;
|
||||
|
||||
/* Check if the name can fit entirely */
|
||||
if (SizeLeft < Size)
|
||||
{
|
||||
/* It can't, we'll have to truncate. Tell the caller */
|
||||
Size = SizeLeft;
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
/* Check if the key node name is compressed */
|
||||
if (Node->Flags & KEY_COMP_NAME)
|
||||
{
|
||||
/* Copy the compressed name */
|
||||
CmpCopyCompressedName(Info->KeyNodeInformation.Name,
|
||||
SizeLeft,
|
||||
Node->Name,
|
||||
Node->NameLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It isn't, so copy the raw name */
|
||||
RtlCopyMemory(Info->KeyNodeInformation.Name,
|
||||
Node->Name,
|
||||
Size);
|
||||
}
|
||||
|
||||
/* Check if the node has a class */
|
||||
if (Node->ClassLength > 0)
|
||||
{
|
||||
/* It does. We don't support these yet */
|
||||
ASSERTMSG("Classes not supported\n", FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It doesn't, so set offset to -1, not 0! */
|
||||
Info->KeyNodeInformation.ClassOffset = 0xFFFFFFFF;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Full information requsted */
|
||||
case KeyFullInformation:
|
||||
|
||||
/* This is the size we need */
|
||||
Size = FIELD_OFFSET(KEY_FULL_INFORMATION, Class) +
|
||||
Node->ClassLength;
|
||||
|
||||
/* This is what we can work with */
|
||||
MinimumSize = FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
|
||||
|
||||
/* Return it to caller and assume success */
|
||||
*ResultLength = Size;
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
/* Check if the caller's buffer is to small */
|
||||
if (Length < MinimumSize)
|
||||
{
|
||||
/* Let them know and fail */
|
||||
Status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now copy all the basic information */
|
||||
Info->KeyFullInformation.LastWriteTime = Node->LastWriteTime;
|
||||
Info->KeyFullInformation.TitleIndex = 0;
|
||||
Info->KeyFullInformation.ClassLength = Node->ClassLength;
|
||||
Info->KeyFullInformation.SubKeys = Node->SubKeyCounts[HvStable] +
|
||||
Node->SubKeyCounts[HvVolatile];
|
||||
Info->KeyFullInformation.Values = Node->ValueList.Count;
|
||||
Info->KeyFullInformation.MaxNameLen = CmiGetMaxNameLength(Hive, Node);
|
||||
Info->KeyFullInformation.MaxClassLen = CmiGetMaxClassLength(Hive, Node);
|
||||
Info->KeyFullInformation.MaxValueNameLen = CmiGetMaxValueNameLength(Hive, Node);
|
||||
Info->KeyFullInformation.MaxValueDataLen = CmiGetMaxValueDataLength(Hive, Node);
|
||||
DPRINT("%d %d %d %d\n",
|
||||
CmiGetMaxNameLength(Hive, Node),
|
||||
CmiGetMaxValueDataLength(Hive, Node),
|
||||
CmiGetMaxValueNameLength(Hive, Node),
|
||||
CmiGetMaxClassLength(Hive, Node));
|
||||
//Info->KeyFullInformation.MaxNameLen = Node->MaxNameLen;
|
||||
//Info->KeyFullInformation.MaxClassLen = Node->MaxClassLen;
|
||||
//Info->KeyFullInformation.MaxValueNameLen = Node->MaxValueNameLen;
|
||||
//Info->KeyFullInformation.MaxValueDataLen = Node->MaxValueDataLen;
|
||||
|
||||
/* Check if we have a class */
|
||||
if (Node->ClassLength > 0)
|
||||
{
|
||||
/* We do, but we currently don't support this */
|
||||
ASSERTMSG("Classes not supported\n", FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We don't have a class, so set offset to -1, not 0! */
|
||||
Info->KeyNodeInformation.ClassOffset = 0xFFFFFFFF;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Any other class that got sent here is invalid! */
|
||||
default:
|
||||
|
||||
/* Set failure code */
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CmQueryKey(IN PKEY_OBJECT KeyObject,
|
||||
IN KEY_INFORMATION_CLASS KeyInformationClass,
|
||||
IN PVOID KeyInformation,
|
||||
IN ULONG Length,
|
||||
IN PULONG ResultLength)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PHHIVE Hive;
|
||||
PCM_KEY_NODE Parent;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Check what class we got */
|
||||
switch (KeyInformationClass)
|
||||
{
|
||||
/* Typical information */
|
||||
case KeyFullInformation:
|
||||
case KeyBasicInformation:
|
||||
case KeyNodeInformation:
|
||||
|
||||
/* Call the internal API */
|
||||
Status = CmpQueryKeyData(Hive,
|
||||
Parent,
|
||||
KeyInformationClass,
|
||||
KeyInformation,
|
||||
Length,
|
||||
ResultLength);
|
||||
break;
|
||||
|
||||
/* Unsupported classes for now */
|
||||
case KeyNameInformation:
|
||||
case KeyCachedInformation:
|
||||
case KeyFlagsInformation:
|
||||
|
||||
/* Print message and fail */
|
||||
DPRINT1("Unsupported class: %d!\n", KeyInformationClass);
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
|
||||
/* Illegal classes */
|
||||
default:
|
||||
|
||||
/* Print message and fail */
|
||||
DPRINT1("Unsupported class: %d!\n", KeyInformationClass);
|
||||
Status = STATUS_INVALID_INFO_CLASS;
|
||||
break;
|
||||
}
|
||||
|
||||
Quickie:
|
||||
/* Release hive lock */
|
||||
ExReleaseResourceLite(&CmpRegistryLock);
|
||||
KeLeaveCriticalRegion();
|
||||
return Status;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue