- 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:
Alex Ionescu 2007-05-14 18:12:57 +00:00
parent 934cae8069
commit 64f4f03b95
5 changed files with 382 additions and 250 deletions

View file

@ -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,

View file

@ -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;
}

View file

@ -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)))
{

View file

@ -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
///////////////////////////////////////////////////////////////////////////////

View file

@ -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;
}