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?rev... ============================================================================== --- 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@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?rev... ============================================================================== --- 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@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/c... ============================================================================== --- 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 );
//