[NTOSKRNL]

- Update CM_KEY_CONTROL_BLOCK to match win2k3 SP2 symbols
- Implement KeyCachedInformation and KeyFlagsInformation cases in CmQueryKey

svn path=/trunk/; revision=61572
This commit is contained in:
Timo Kreuzer 2014-01-07 23:51:56 +00:00
parent e5813955cb
commit 8d73b77251
2 changed files with 258 additions and 82 deletions

View file

@ -1304,6 +1304,162 @@ Quickie:
return Status;
}
static
NTSTATUS
CmpQueryKeyDataFromCache(
_In_ PCM_KEY_CONTROL_BLOCK Kcb,
_Out_ PKEY_CACHED_INFORMATION KeyCachedInfo,
_In_ ULONG Length,
_Out_ PULONG ResultLength)
{
PCM_KEY_NODE Node;
ULONG SubKeyCount;
PHHIVE KeyHive;
HCELL_INDEX KeyCell;
USHORT NameLength;
PAGED_CODE();
/* Get the hive and cell index */
KeyHive = Kcb->KeyHash.KeyHive;
KeyCell = Kcb->KeyHash.KeyCell;
#if DBG
/* Get the cell node */
Node = HvGetCell(KeyHive, KeyCell);
if (Node != NULL)
{
ASSERT(Node->ValueList.Count == Kcb->ValueCache.Count);
if (!(Kcb->ExtFlags & CM_KCB_INVALID_CACHED_INFO))
{
SubKeyCount = Node->SubKeyCounts[0] + Node->SubKeyCounts[1];
if (Kcb->ExtFlags & CM_KCB_NO_SUBKEY)
{
ASSERT(SubKeyCount == 0);
}
else if (Kcb->ExtFlags & CM_KCB_SUBKEY_ONE)
{
ASSERT(SubKeyCount == 1);
}
else if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT)
{
ASSERT(SubKeyCount == Kcb->IndexHint->Count);
}
else
{
ASSERT(SubKeyCount == Kcb->SubKeyCount);
}
}
ASSERT(Node->LastWriteTime.QuadPart == Kcb->KcbLastWriteTime.QuadPart);
ASSERT(Node->MaxNameLen == Kcb->KcbMaxNameLen);
ASSERT(Node->MaxValueNameLen == Kcb->KcbMaxValueNameLen);
ASSERT(Node->MaxValueDataLen == Kcb->KcbMaxValueDataLen);
/* Release the cell */
HvReleaseCell(KeyHive, KeyCell);
}
#endif // DBG
/* Make sure we have a name block */
if (Kcb->NameBlock == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Check for compressed name */
if (Kcb->NameBlock->Compressed)
{
/* Calculate the name size */
NameLength = CmpCompressedNameSize(Kcb->NameBlock->NameHash.Name,
Kcb->NameBlock->NameHash.NameLength);
}
else
{
/* Use the stored name size */
NameLength = Kcb->NameBlock->NameHash.NameLength;
}
/* Validate buffer length (we do not copy the name!) */
*ResultLength = sizeof(KeyCachedInfo);
if (Length < *ResultLength)
{
return STATUS_BUFFER_TOO_SMALL;
}
/* Fill the structure */
KeyCachedInfo->LastWriteTime = Kcb->KcbLastWriteTime;
KeyCachedInfo->TitleIndex = 0;
KeyCachedInfo->NameLength = NameLength;
KeyCachedInfo->Values = Kcb->ValueCache.Count;
KeyCachedInfo->MaxNameLen = Kcb->KcbMaxNameLen;
KeyCachedInfo->MaxValueNameLen = Kcb->KcbMaxValueNameLen;
KeyCachedInfo->MaxValueDataLen = Kcb->KcbMaxValueDataLen;
/* Check the ExtFlags for what we have */
if (Kcb->ExtFlags & CM_KCB_INVALID_CACHED_INFO)
{
/* Cache is not valid, do a full lookup */
DPRINT1("Kcb cache incoherency detected, kcb = %p\n", Kcb);
/* Get the cell node */
Node = HvGetCell(KeyHive, KeyCell);
if (Node == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Calculate number of subkeys */
KeyCachedInfo->SubKeys = Node->SubKeyCounts[0] + Node->SubKeyCounts[1];
/* Release the cell */
HvReleaseCell(KeyHive, KeyCell);
}
else if (Kcb->ExtFlags & CM_KCB_NO_SUBKEY)
{
/* There are no subkeys */
KeyCachedInfo->SubKeys = 0;
}
else if (Kcb->ExtFlags & CM_KCB_SUBKEY_ONE)
{
/* There is exactly one subley */
KeyCachedInfo->SubKeys = 1;
}
else if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT)
{
/* Get the number of subkeys from the subkey hint */
KeyCachedInfo->SubKeys = Kcb->IndexHint->Count;
}
else
{
/* No subkey hint, use the key count field */
KeyCachedInfo->SubKeys = Kcb->SubKeyCount;
}
return STATUS_SUCCESS;
}
static
NTSTATUS
CmpQueryFlagsInformation(
_In_ PCM_KEY_CONTROL_BLOCK Kcb,
_Out_ PKEY_USER_FLAGS_INFORMATION KeyFlagsInfo,
_In_ ULONG Length,
_In_ PULONG ResultLength)
{
/* Validate the buffer size */
*ResultLength = sizeof(*KeyFlagsInfo);
if (Length < *ResultLength)
{
return STATUS_BUFFER_TOO_SMALL;
}
/* Copy the user flags */
KeyFlagsInfo->UserFlags = Kcb->KcbUserFlags;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CmQueryKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
@ -1362,10 +1518,24 @@ CmQueryKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
}
break;
/* Unsupported classes for now */
case KeyNameInformation:
case KeyCachedInformation:
/* Call the internal API */
Status = CmpQueryKeyDataFromCache(Kcb,
KeyInformation,
Length,
ResultLength);
break;
case KeyFlagsInformation:
/* Call the internal API */
Status = CmpQueryFlagsInformation(Kcb,
KeyInformation,
Length,
ResultLength);
break;
/* Unsupported class for now */
case KeyNameInformation:
/* Print message and fail */
DPRINT1("Unsupported class: %d!\n", KeyInformationClass);

View file

@ -49,7 +49,7 @@
#define CM_KCB_INVALID_SIGNATURE '4FmC'
//
// CM_KEY_CONTROL_BLOCK Flags
// CM_KEY_CONTROL_BLOCK ExtFlags
//
#define CM_KCB_NO_SUBKEY 0x01
#define CM_KCB_SUBKEY_ONE 0x02
@ -253,8 +253,7 @@ typedef struct _CM_NAME_CONTROL_BLOCK
typedef struct _CM_KEY_CONTROL_BLOCK
{
ULONG Signature;
USHORT RefCount;
USHORT Flags;
ULONG RefCount;
struct
{
ULONG ExtFlags:8;
@ -295,6 +294,13 @@ typedef struct _CM_KEY_CONTROL_BLOCK
USHORT KcbMaxNameLen;
USHORT KcbMaxValueNameLen;
ULONG KcbMaxValueDataLen;
struct
{
ULONG KcbUserFlags : 4;
ULONG KcbVirtControlFlags : 4;
ULONG KcbDebug : 8;
ULONG Flags : 16;
};
ULONG InDelayClose;
} CM_KEY_CONTROL_BLOCK, *PCM_KEY_CONTROL_BLOCK;