Author: dchapyshev Date: Thu Sep 1 16:39:54 2016 New Revision: 72530
URL: http://svn.reactos.org/svn/reactos?rev=72530&view=rev Log: [NTOS:EX] - Use all handles enumeration in system instead of enumeration for each process See issue 11906 for more details.
Modified: trunk/reactos/ntoskrnl/ex/sysinfo.c
Modified: trunk/reactos/ntoskrnl/ex/sysinfo.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/sysinfo.c?rev=7... ============================================================================== --- trunk/reactos/ntoskrnl/ex/sysinfo.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ex/sysinfo.c [iso-8859-1] Thu Sep 1 16:39:54 2016 @@ -16,6 +16,9 @@
/* The maximum size of an environment value (in bytes) */ #define MAX_ENVVAL_SIZE 1024 + +extern LIST_ENTRY HandleTableListHead; +extern EX_PUSH_LOCK HandleTableListLock;
FAST_MUTEX ExpEnvironmentLock; ERESOURCE ExpFirmwareTableResource; @@ -1168,53 +1171,25 @@ QSI_DEF(SystemHandleInformation) { PSYSTEM_HANDLE_INFORMATION HandleInformation; - KPROCESSOR_MODE PreviousMode; - PEPROCESS Process; - PEPROCESS SystemProcess; - ULONG CurrentSize; - ULONG NumberOfHandles = 0; - ULONG Index; + ULONG Index = 0; NTSTATUS Status; PMDL Mdl;
DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
+ /* Set initial required buffer size */ + *ReqSize = sizeof(SYSTEM_HANDLE_INFORMATION); + /* Check user's buffer size */ - if (Size < sizeof(SYSTEM_HANDLE_INFORMATION)) - { - *ReqSize = sizeof(SYSTEM_HANDLE_INFORMATION); - return STATUS_INFO_LENGTH_MISMATCH; - } - - /* Retrieve needed buffer size to hold the list of handles */ - SystemProcess = PsGetNextProcess(NULL); - Process = SystemProcess; - - do - { - NumberOfHandles += ObGetProcessHandleCount(Process); - Process = PsGetNextProcess(Process); - } - while ((Process != SystemProcess) && (Process != NULL)); - - /* Dereference the process which was referenced by PsGetNextProcess */ - if (Process != NULL) ObDereferenceObject(Process); - - /* Calculate the current size of all handles */ - CurrentSize = sizeof(SYSTEM_HANDLE_INFORMATION) + - ((sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO) * NumberOfHandles) - - (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO))); - - *ReqSize = CurrentSize; - - /* Check user's buffer size */ - if (CurrentSize > Size) return STATUS_INFO_LENGTH_MISMATCH; + if (Size < *ReqSize) + { + return STATUS_INFO_LENGTH_MISMATCH; + }
/* We need to lock down the memory */ - PreviousMode = ExGetPreviousMode(); Status = ExLockUserBuffer(Buffer, Size, - PreviousMode, + ExGetPreviousMode(), IoWriteAccess, (PVOID*)&HandleInformation, &Mdl); @@ -1224,91 +1199,111 @@ return Status; }
- /* Initialization of count of handles */ - HandleInformation->NumberOfHandles = NumberOfHandles; - - /* Now get handles from all processes. */ - SystemProcess = PsGetNextProcess(NULL); - Process = SystemProcess; - - Index = 0; - - do - { - PHANDLE_TABLE_ENTRY HandleTableEntry; - EXHANDLE Handle; - - /* Enter a critical region */ - KeEnterCriticalRegion(); - - _SEH2_TRY - { - /* Set the initial value and loop the entries */ - Handle.Value = 0; - while ((HandleTableEntry = ExpLookupHandleTableEntry(Process->ObjectTable, Handle))) + _SEH2_TRY + { + PLIST_ENTRY NextTableEntry; + + /* Enumerate all system handles */ + for (NextTableEntry = HandleTableListHead.Flink; + NextTableEntry != &HandleTableListHead; + NextTableEntry = NextTableEntry->Flink) + { + PHANDLE_TABLE HandleTable; + + /* Enter a critical region */ + KeEnterCriticalRegion(); + + /* Acquire the handle table lock */ + ExAcquirePushLockExclusive(&HandleTableListLock); + + /* Get current handle table */ + HandleTable = CONTAINING_RECORD(NextTableEntry, HANDLE_TABLE, HandleTableList); + + _SEH2_TRY { - /* Validate the entry */ - if ((HandleTableEntry->Object) && - (HandleTableEntry->NextFreeTableEntry != -2)) + PHANDLE_TABLE_ENTRY HandleTableEntry; + EXHANDLE Handle; + + /* Set the initial value and loop the entries */ + Handle.Value = 0; + while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle))) { - /* Lock the entry */ - if (ExpLockHandleTableEntry(Process->ObjectTable, HandleTableEntry)) + /* Validate the entry */ + if ((HandleTableEntry->Object) && + (HandleTableEntry->NextFreeTableEntry != -2)) { - _SEH2_TRY + /* Increase of count of handles */ + ++HandleInformation->NumberOfHandles; + + /* Increase required buffer size */ + *ReqSize += sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO); + + /* Check user's buffer size */ + if (*ReqSize > Size) { - POBJECT_HEADER ObjectHeader = ObpGetHandleObject(HandleTableEntry); - - /* Filling handle information */ - HandleInformation->Handles[Index].UniqueProcessId = - (USHORT)(ULONG_PTR) Process->UniqueProcessId; - - HandleInformation->Handles[Index].CreatorBackTraceIndex = 0; - - HandleInformation->Handles[Index].ObjectTypeIndex = - (UCHAR) ObjectHeader->Type->Index; - - HandleInformation->Handles[Index].HandleAttributes = - HandleTableEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES; - - HandleInformation->Handles[Index].HandleValue = - (USHORT)(ULONG_PTR) Handle.GenericHandleOverlay; - - HandleInformation->Handles[Index].Object = &ObjectHeader->Body; - - HandleInformation->Handles[Index].GrantedAccess = - HandleTableEntry->GrantedAccess; - - ++Index; + /* It is correct? How it is correct to leave the enclosed SEH blocks? */ + _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH); } - _SEH2_FINALLY + + /* Lock the entry */ + if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry)) { - /* Unlock it */ - ExUnlockHandleTableEntry(Process->ObjectTable, HandleTableEntry); + _SEH2_TRY + { + POBJECT_HEADER ObjectHeader = ObpGetHandleObject(HandleTableEntry); + + /* Filling handle information */ + HandleInformation->Handles[Index].UniqueProcessId = + (USHORT)(ULONG_PTR) HandleTable->UniqueProcessId; + + HandleInformation->Handles[Index].CreatorBackTraceIndex = 0; + + HandleInformation->Handles[Index].ObjectTypeIndex = + (UCHAR) ObjectHeader->Type->Index; + + HandleInformation->Handles[Index].HandleAttributes = + HandleTableEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES; + + HandleInformation->Handles[Index].HandleValue = + (USHORT)(ULONG_PTR) Handle.GenericHandleOverlay; + + HandleInformation->Handles[Index].Object = &ObjectHeader->Body; + + HandleInformation->Handles[Index].GrantedAccess = + HandleTableEntry->GrantedAccess; + + ++Index; + } + _SEH2_FINALLY + { + /* Unlock it */ + ExUnlockHandleTableEntry(HandleTable, HandleTableEntry); + } + _SEH2_END; } - _SEH2_END; } + + /* Go to the next entry */ + Handle.Value += sizeof(HANDLE); } - - /* Go to the next entry */ - Handle.Value += sizeof(HANDLE); } - } - _SEH2_FINALLY - { - /* Leave the critical region */ - KeLeaveCriticalRegion(); - } - _SEH2_END; - - Process = PsGetNextProcess(Process); - } - while ((Process != SystemProcess) && (Process != NULL)); - - /* Dereference the process which was referenced by PsGetNextProcess */ - if (Process != NULL) ObDereferenceObject(Process); - - /* Release the locked user buffer */ - ExUnlockUserBuffer(Mdl); + _SEH2_FINALLY + { + /* Release the lock */ + ExReleasePushLockExclusive(&HandleTableListLock); + + /* Leave the critical region */ + KeLeaveCriticalRegion(); + } + _SEH2_END; + } + } + _SEH2_FINALLY + { + /* Release the locked user buffer */ + ExUnlockUserBuffer(Mdl); + } + _SEH2_END;
return STATUS_SUCCESS; }