[NTOS:EX]
[reactos.git] / reactos / ntoskrnl / ex / sysinfo.c
index 21190b5..b9fed78 100644 (file)
@@ -17,6 +17,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;
 LIST_ENTRY ExpFirmwareTableProviderListHead;
@@ -219,7 +222,7 @@ ExLockUserBuffer(
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
         ExFreePoolWithTag(Mdl, TAG_MDL);
-        return _SEH2_GetExceptionCode();
+        _SEH2_YIELD(return _SEH2_GetExceptionCode());
     }
     _SEH2_END;
 
@@ -809,6 +812,10 @@ QSI_DEF(SystemProcessInformation)
         {
             SpiCurrent = (PSYSTEM_PROCESS_INFORMATION) Current;
 
+            /* Lock the Process */
+            KeEnterCriticalRegion();
+            ExAcquirePushLockShared(&Process->ProcessLock);
+
             if ((Process->ProcessExiting) &&
                 (Process->Pcb.Header.SignalState) &&
                 !(Process->ActiveThreads) &&
@@ -818,6 +825,10 @@ QSI_DEF(SystemProcessInformation)
                         Process, Process->ImageFileName, Process->UniqueProcessId);
                 CurrentSize = 0;
                 ImageNameMaximumLength = 0;
+
+                /* Unlock the Process */
+                ExReleasePushLockShared(&Process->ProcessLock);
+                KeLeaveCriticalRegion();
                 goto Skip;
             }
 
@@ -952,6 +963,10 @@ QSI_DEF(SystemProcessInformation)
                 ProcessImageName = NULL;
             }
 
+            /* Unlock the Process */
+            ExReleasePushLockShared(&Process->ProcessLock);
+            KeLeaveCriticalRegion();
+
             /* Handle idle process entry */
 Skip:
             if (Process == PsIdleProcess) Process = NULL;
@@ -1167,119 +1182,131 @@ QSI_DEF(SystemNonPagedPoolInformation)
 /* Class 16 - Handle Information */
 QSI_DEF(SystemHandleInformation)
 {
-    PEPROCESS Process;
-    PEPROCESS SystemProcess;
-    ULONG CurrentSize;
-    ULONG NumberOfHandles = 0;
-    ULONG Index;
-
-    PSYSTEM_HANDLE_INFORMATION HandleInformation =
-        (PSYSTEM_HANDLE_INFORMATION) Buffer;
+    PSYSTEM_HANDLE_INFORMATION HandleInformation;
+    PLIST_ENTRY NextTableEntry;
+    PHANDLE_TABLE HandleTable;
+    PHANDLE_TABLE_ENTRY HandleTableEntry;
+    EXHANDLE Handle;
+    ULONG Index = 0;
+    NTSTATUS Status;
+    PMDL Mdl;
+    PAGED_CODE();
 
     DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
 
-    if (Size < sizeof(SYSTEM_HANDLE_INFORMATION))
+    /* Set initial required buffer size */
+    *ReqSize = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION, Handles);
+
+    /* Check user's buffer size */
+    if (Size < *ReqSize)
     {
-        *ReqSize = sizeof(SYSTEM_HANDLE_INFORMATION);
         return STATUS_INFO_LENGTH_MISMATCH;
     }
 
-    /* First Calc Size from Count. */
-    SystemProcess = PsGetNextProcess(NULL);
-    Process = SystemProcess;
-
-    do
+    /* We need to lock down the memory */
+    Status = ExLockUserBuffer(Buffer,
+                              Size,
+                              ExGetPreviousMode(),
+                              IoWriteAccess,
+                              (PVOID*)&HandleInformation,
+                              &Mdl);
+    if (!NT_SUCCESS(Status))
     {
-        NumberOfHandles += ObGetProcessHandleCount(Process);
-        Process = PsGetNextProcess(Process);
-
-        if ((Process == SystemProcess) || (Process == NULL)) break;
+        DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status);
+        return Status;
     }
-    while ((Process != SystemProcess) && (Process != NULL));
-
-    if (Process != NULL) ObDereferenceObject(Process);
 
-    CurrentSize = sizeof(SYSTEM_HANDLE_INFORMATION) +
-                         ((sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO) * NumberOfHandles) -
-                         (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO)));
+    /* Reset of count of handles */
+    HandleInformation->NumberOfHandles = 0;
 
-    HandleInformation->NumberOfHandles = NumberOfHandles;
-
-    *ReqSize = CurrentSize;
-
-    if (CurrentSize > Size) return STATUS_INFO_LENGTH_MISMATCH;
-
-    /* Now get Handles from all processes. */
-    SystemProcess = PsGetNextProcess(NULL);
-    Process = SystemProcess;
+    /* Enter a critical region */
+    KeEnterCriticalRegion();
 
-    Index = 0;
+    /* Acquire the handle table lock */
+    ExAcquirePushLockShared(&HandleTableListLock);
 
-    do
+    /* Enumerate all system handles */
+    for (NextTableEntry = HandleTableListHead.Flink;
+         NextTableEntry != &HandleTableListHead;
+         NextTableEntry = NextTableEntry->Flink)
     {
-        PHANDLE_TABLE_ENTRY HandleTableEntry;
-        EXHANDLE Handle;
-
-        /* Enter a critical region */
-        KeEnterCriticalRegion();
+        /* Get current handle table */
+        HandleTable = CONTAINING_RECORD(NextTableEntry, HANDLE_TABLE, HandleTableList);
 
         /* Set the initial value and loop the entries */
         Handle.Value = 0;
-        while ((HandleTableEntry = ExpLookupHandleTableEntry(Process->ObjectTable, Handle)))
+        while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle)))
         {
             /* Validate the entry */
-            if ((HandleTableEntry) &&
-                (HandleTableEntry->Object) &&
+            if ((HandleTableEntry->Object) &&
                 (HandleTableEntry->NextFreeTableEntry != -2))
             {
+                /* Increase of count of handles */
+                ++HandleInformation->NumberOfHandles;
+
                 /* Lock the entry */
-                if (ExpLockHandleTableEntry(Process->ObjectTable, HandleTableEntry))
+                if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
                 {
-                    POBJECT_HEADER ObjectHeader;
+                    /* Increase required buffer size */
+                    *ReqSize += sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO);
 
-                    ObjectHeader = (POBJECT_HEADER)(((ULONG_PTR) HandleTableEntry->Object) & ~OBJ_HANDLE_ATTRIBUTES);
+                    /* Check user's buffer size */
+                    if (*ReqSize > Size)
+                    {
+                        Status = STATUS_INFO_LENGTH_MISMATCH;
+                    }
+                    else
+                    {
+                        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;
+                        /* Filling handle information */
+                        HandleInformation->Handles[Index].UniqueProcessId =
+                            (USHORT)(ULONG_PTR) HandleTable->UniqueProcessId;
 
-                    /* Unlock it */
-                    ExUnlockHandleTableEntry(Process->ObjectTable, HandleTableEntry);
+                        HandleInformation->Handles[Index].CreatorBackTraceIndex = 0;
+
+#if 0 /* FIXME!!! Type field currupted */
+                        HandleInformation->Handles[Index].ObjectTypeIndex =
+                            (UCHAR) ObjectHeader->Type->Index;
+#else
+                        HandleInformation->Handles[Index].ObjectTypeIndex = 0;
+#endif
+
+                        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;
+                    }
 
-                    ++Index;
+                    /* Unlock it */
+                    ExUnlockHandleTableEntry(HandleTable, HandleTableEntry);
                 }
             }
 
             /* Go to the next entry */
             Handle.Value += sizeof(HANDLE);
         }
-
-        /* Leave the critical region and return callback result */
-        KeLeaveCriticalRegion();
-
-        Process = PsGetNextProcess(Process);
-
-        if ((Process == SystemProcess) || (Process == NULL)) break;
     }
-    while ((Process != SystemProcess) && (Process != NULL));
 
-    if (Process != NULL) ObDereferenceObject(Process);
+    /* Release the lock */
+    ExReleasePushLockShared(&HandleTableListLock);
 
-    return STATUS_SUCCESS;
+    /* Leave the critical region */
+    KeLeaveCriticalRegion();
 
-}
-/*
-SSI_DEF(SystemHandleInformation)
-{
+    /* Release the locked user buffer */
+    ExUnlockUserBuffer(Mdl);
 
-    return STATUS_SUCCESS;
+    return Status;
 }
-*/
 
 /* Class 17 -  Information */
 QSI_DEF(SystemObjectInformation)