[NTOSKRNL]

Implement NtQueryOpenSubKeys.

svn path=/trunk/; revision=48902
This commit is contained in:
Eric Kohl 2010-09-26 11:37:40 +00:00
parent c23c9c81ca
commit db53bf24cb
3 changed files with 177 additions and 2 deletions

View file

@ -4,6 +4,7 @@
* FILE: ntoskrnl/config/cmapi.c
* PURPOSE: Configuration Manager - Internal Registry APIs
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Eric Kohl
*/
/* INCLUDES ******************************************************************/
@ -1814,3 +1815,86 @@ CmUnloadKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
ULONG
NTAPI
CmCountOpenSubKeys(IN PCM_KEY_CONTROL_BLOCK RootKcb,
IN BOOLEAN RemoveEmptyCacheEntries)
{
PCM_KEY_HASH Entry;
PCM_KEY_CONTROL_BLOCK CachedKcb;
PCM_KEY_CONTROL_BLOCK ParentKcb;
USHORT ParentKeyCount;
USHORT j;
ULONG i;
ULONG SubKeys = 0;
DPRINT("CmCountOpenSubKeys() called\n");
/* The root key is the only referenced key. There are no refereced sub keys. */
if (RootKcb->RefCount == 1)
{
DPRINT("open sub keys: 0\n");
return 0;
}
/* Enumerate all hash lists */
for (i = 0; i < CmpHashTableSize; i++)
{
/* Get the first cache entry */
Entry = CmpCacheTable[i].Entry;
/* Enumerate all cache entries */
while (Entry)
{
/* Get the KCB of the current cache entry */
CachedKcb = CONTAINING_RECORD(Entry, CM_KEY_CONTROL_BLOCK, KeyHash);
/* Check keys only that are subkeys to our root key */
if (CachedKcb->TotalLevels > RootKcb->TotalLevels)
{
/* Calculate the number of parent keys to the root key */
ParentKeyCount = CachedKcb->TotalLevels - RootKcb->TotalLevels;
/* Find a parent key that could be the root key */
ParentKcb = CachedKcb;
for (j = 0; j < ParentKeyCount; j++)
{
ParentKcb = ParentKcb->ParentKcb;
}
/* Check whether the parent is the root key */
if (ParentKcb == RootKcb)
{
DPRINT("Found a sub key \n");
DPRINT("RefCount = %u\n", CachedKcb->RefCount);
if (CachedKcb->RefCount > 0)
{
/* Count the current hash entry if it is in use */
SubKeys++;
}
else if ((CachedKcb->RefCount == 0) && (RemoveEmptyCacheEntries == TRUE))
{
/* Remove the current key from the delayed close list */
CmpRemoveFromDelayedClose(CachedKcb);
/* Remove the current cache entry */
CmpCleanUpKcbCacheWithLock(CachedKcb, TRUE);
/* Restart, because the hash list has changed */
Entry = CmpCacheTable[i].Entry;
continue;
}
}
}
/* Get the next cache entry */
Entry = Entry->NextHash;
}
}
DPRINT("open sub keys: %u\n", SubKeys);
return SubKeys;
}

View file

@ -4,6 +4,7 @@
* FILE: ntoskrnl/config/cmapi.c
* PURPOSE: Configuration Manager - Internal Registry APIs
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Eric Kohl
*/
/* INCLUDES ******************************************************************/
@ -1015,8 +1016,91 @@ NTAPI
NtQueryOpenSubKeys(IN POBJECT_ATTRIBUTES TargetKey,
OUT PULONG HandleCount)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
KPROCESSOR_MODE PreviousMode;
PCM_KEY_BODY KeyBody = NULL;
HANDLE KeyHandle;
NTSTATUS Status;
DPRINT("NtQueryOpenSubKeys()\n");
PAGED_CODE();
/* Get the processor mode */
PreviousMode = KeGetPreviousMode();
if (PreviousMode != KernelMode)
{
/* Prepare to probe parameters */
_SEH2_TRY
{
/* Probe target key */
ProbeForRead(TargetKey,
sizeof(OBJECT_ATTRIBUTES),
sizeof(ULONG));
/* Probe handle count */
ProbeForWriteUlong(HandleCount);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Return the exception code */
_SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
}
/* Open a handle to the key */
Status = ObOpenObjectByName(TargetKey,
CmpKeyObjectType,
PreviousMode,
NULL,
KEY_READ,
NULL,
&KeyHandle);
if (NT_SUCCESS(Status))
{
/* Reference the key object */
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_READ,
CmpKeyObjectType,
PreviousMode,
(PVOID *)&KeyBody,
NULL);
/* Close the handle */
NtClose(KeyHandle);
}
/* Fail, if the key object could not be referenced */
if (!NT_SUCCESS(Status))
return Status;
/* Lock the registry exclusively */
CmpLockRegistryExclusive();
/* Fail, if we did not open a hive root key */
if (KeyBody->KeyControlBlock->KeyCell !=
KeyBody->KeyControlBlock->KeyHive->BaseBlock->RootCell)
{
DPRINT("Error: Key is not a hive root key!\n");
CmpUnlockRegistry();
ObDereferenceObject(KeyBody);
return STATUS_INVALID_PARAMETER;
}
/* Call the internal API */
*HandleCount = CmCountOpenSubKeys(KeyBody->KeyControlBlock,
FALSE);
/* Unlock the registry */
CmpUnlockRegistry();
/* Dereference the key object */
ObDereferenceObject(KeyBody);
DPRINT("Done.\n");
return Status;
}
NTSTATUS

View file

@ -1501,6 +1501,13 @@ CmUnloadKey(
IN ULONG Flags
);
ULONG
NTAPI
CmCountOpenSubKeys(
IN PCM_KEY_CONTROL_BLOCK RootKcb,
IN BOOLEAN RemoveEmptyCacheEntries
);
//
// Startup and Shutdown
//