Author: ekohl
Date: Sun Sep 26 11:37:40 2010
New Revision: 48902
URL:
http://svn.reactos.org/svn/reactos?rev=48902&view=rev
Log:
[NTOSKRNL]
Implement NtQueryOpenSubKeys.
Modified:
trunk/reactos/ntoskrnl/config/cmapi.c
trunk/reactos/ntoskrnl/config/ntapi.c
trunk/reactos/ntoskrnl/include/internal/cm.h
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 [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/config/cmapi.c [iso-8859-1] Sun Sep 26 11:37:40 2010
@@ -4,6 +4,7 @@
* FILE: ntoskrnl/config/cmapi.c
* PURPOSE: Configuration Manager - Internal Registry APIs
* PROGRAMMERS: Alex Ionescu (alex.ionescu(a)reactos.org)
+ * Eric Kohl
*/
/* INCLUDES ******************************************************************/
@@ -1814,3 +1815,86 @@
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;
+}
Modified: trunk/reactos/ntoskrnl/config/ntapi.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/ntapi.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/config/ntapi.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/config/ntapi.c [iso-8859-1] Sun Sep 26 11:37:40 2010
@@ -4,6 +4,7 @@
* FILE: ntoskrnl/config/cmapi.c
* PURPOSE: Configuration Manager - Internal Registry APIs
* PROGRAMMERS: Alex Ionescu (alex.ionescu(a)reactos.org)
+ * Eric Kohl
*/
/* INCLUDES ******************************************************************/
@@ -1015,8 +1016,91 @@
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
Modified: trunk/reactos/ntoskrnl/include/internal/cm.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/cm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/cm.h [iso-8859-1] Sun Sep 26 11:37:40 2010
@@ -1499,6 +1499,13 @@
CmUnloadKey(
IN PCM_KEY_CONTROL_BLOCK Kcb,
IN ULONG Flags
+);
+
+ULONG
+NTAPI
+CmCountOpenSubKeys(
+ IN PCM_KEY_CONTROL_BLOCK RootKcb,
+ IN BOOLEAN RemoveEmptyCacheEntries
);
//