Author: ion
Date: Mon May 14 22:12:57 2007
New Revision: 26780
URL:
http://svn.reactos.org/svn/reactos?rev=26780&view=rev
Log:
- 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.
Modified:
trunk/reactos/ntoskrnl/cm/cm.h
trunk/reactos/ntoskrnl/cm/ntfunc.c
trunk/reactos/ntoskrnl/cm/regfile.c
trunk/reactos/ntoskrnl/config/cm.h
trunk/reactos/ntoskrnl/config/cmapi.c
Modified: trunk/reactos/ntoskrnl/cm/cm.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/cm.h?rev=26780…
==============================================================================
--- trunk/reactos/ntoskrnl/cm/cm.h (original)
+++ trunk/reactos/ntoskrnl/cm/cm.h Mon May 14 22:12:57 2007
@@ -221,17 +221,17 @@
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
@@ -300,6 +300,14 @@
IN ULONG Type,
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,
Modified: trunk/reactos/ntoskrnl/cm/ntfunc.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/ntfunc.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/cm/ntfunc.c (original)
+++ trunk/reactos/ntoskrnl/cm/ntfunc.c Mon May 14 22:12:57 2007
@@ -786,13 +786,13 @@
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 @@
return Status;
}
-
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
NtQueryKey(IN HANDLE KeyHandle,
- 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;
-
- PAGED_CODE();
-
- DPRINT("NtQueryKey(KH 0x%p KIC %x KI 0x%p L %d RL 0x%p)\n",
- KeyHandle,
- KeyInformationClass,
- KeyInformation,
- Length,
- 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))
- {
- return Status;
- }
-
- 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);
+ IN KEY_INFORMATION_CLASS KeyInformationClass,
+ OUT PVOID KeyInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength)
+{
+ NTSTATUS Status;
+ PKEY_OBJECT KeyObject;
+ REG_QUERY_KEY_INFORMATION QueryKeyInfo;
+ REG_POST_OPERATION_INFORMATION PostOperationInfo;
+ 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;
+
+ /* Setup the callback */
+ PostOperationInfo.Object = (PVOID)KeyObject;
+ QueryKeyInfo.Object = (PVOID)KeyObject;
+ QueryKeyInfo.KeyInformationClass = KeyInformationClass;
+ QueryKeyInfo.KeyInformation = KeyInformation;
+ QueryKeyInfo.Length = Length;
+ QueryKeyInfo.ResultLength = ResultLength;
+
+ /* Do the callback */
+ Status = CmiCallRegisteredCallbacks(RegNtPreQueryKey, &QueryKeyInfo);
+ if (NT_SUCCESS(Status))
+ {
+ /* Call the internal API */
+ Status = CmQueryKey(KeyObject,
+ KeyInformationClass,
+ KeyInformation,
+ Length,
+ ResultLength);
+
+ /* Do the post callback */
+ PostOperationInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostQueryKey, &PostOperationInfo);
+ }
+
+ /* Dereference and return status */
+ ObDereferenceObject(KeyObject);
+ return Status;
}
NTSTATUS
@@ -1371,6 +1197,7 @@
CmiCallRegisteredCallbacks(RegNtPostQueryValueKey, &PostOperationInfo);
}
+ /* Dereference and return status */
ObDereferenceObject(KeyObject);
return Status;
}
Modified: trunk/reactos/ntoskrnl/cm/regfile.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/regfile.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/cm/regfile.c (original)
+++ trunk/reactos/ntoskrnl/cm/regfile.c Mon May 14 22:12:57 2007
@@ -124,32 +124,27 @@
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 @@
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 @@
ULONG
-CmiGetMaxValueNameLength(PEREGISTRY_HIVE RegistryHive,
+CmiGetMaxValueNameLength(PHHIVE Hive,
PCM_KEY_NODE KeyCell)
{
PVALUE_LIST_CELL ValueListCell;
@@ -225,12 +215,12 @@
}
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 @@
ULONG
-CmiGetMaxValueDataLength(PEREGISTRY_HIVE RegistryHive,
+CmiGetMaxValueDataLength(PHHIVE Hive,
PCM_KEY_NODE KeyCell)
{
PVALUE_LIST_CELL ValueListCell;
@@ -272,11 +262,11 @@
}
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)))
{
Modified: trunk/reactos/ntoskrnl/config/cm.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cm.h?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/config/cm.h (original)
+++ trunk/reactos/ntoskrnl/config/cm.h Mon May 14 22:12:57 2007
@@ -675,6 +675,16 @@
};
} 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 @@
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
///////////////////////////////////////////////////////////////////////////////
Modified: trunk/reactos/ntoskrnl/config/cmapi.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmapi.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/config/cmapi.c (original)
+++ trunk/reactos/ntoskrnl/config/cmapi.c Mon May 14 22:12:57 2007
@@ -624,3 +624,296 @@
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;
+}