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=…
==============================================================================
--- 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;
 }