[PATCH] dlls/ntdll: Add handle count to NtQuerySystemInformation (try 2)

Austin Lund austin.lund at gmail.com
Tue Jun 21 06:00:55 CDT 2011


---
 dlls/ntdll/nt.c         |  109 +++++++++++++++++++++++++++++++++++++++++++---
 dlls/ntdll/tests/info.c |    8 +---
 2 files changed, 103 insertions(+), 14 deletions(-)

diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
index f9302c1..b460aaa 100644
--- a/dlls/ntdll/nt.c
+++ b/dlls/ntdll/nt.c
@@ -1655,18 +1655,111 @@ NTSTATUS WINAPI NtQuerySystemInformation(
         break;
     case SystemHandleInformation:
         {
-            SYSTEM_HANDLE_INFORMATION shi;
+            SYSTEM_HANDLE_INFORMATION *shi;
+            HANDLE hSnap = 0;
+            int handle_count,  process_handles, i;
+            process_id_t pid;
 
-            memset(&shi, 0, sizeof(shi));
-            len = sizeof(shi);
+            FIXME("info_class SYSTEM_HANDLE_INFORMATION partial implementation\n");
 
-            if ( Length >= len)
+            SERVER_START_REQ( create_snapshot )
             {
-                if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
-                else memcpy( SystemInformation, &shi, len);
+                req->flags = SNAP_PROCESS;
+                req->attributes = 0;
+                if (!(ret = wine_server_call( req )))
+                    hSnap = wine_server_ptr_handle( reply->handle );
             }
-            else ret = STATUS_INFO_LENGTH_MISMATCH;
-            FIXME("info_class SYSTEM_HANDLE_INFORMATION\n");
+            SERVER_END_REQ;
+
+            if (hSnap == 0) return ret;
+
+            handle_count = 0;
+
+            for (;;)
+            {
+                SERVER_START_REQ( next_process )
+                {
+                    req->handle = wine_server_obj_handle( hSnap );
+                    req->reset = 0;
+                    ret = wine_server_call( req );
+                    process_handles = reply->handles;
+                }
+                SERVER_END_REQ;
+
+                if (ret == STATUS_SUCCESS)
+                    handle_count += process_handles;
+                else break;
+            }
+
+            if (ret != STATUS_NO_MORE_FILES)
+            {
+                NtClose(hSnap);
+                return ret;
+            }
+
+            len = sizeof(ULONG) + handle_count*sizeof(SYSTEM_HANDLE_ENTRY);
+
+            if (len > Length)
+            {
+                NtClose(hSnap);
+                ret = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
+            shi = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
+            if (shi == NULL)
+            {
+                NtClose(hSnap);
+                ret = STATUS_NO_MEMORY;
+                break;
+            }
+
+            SERVER_START_REQ( next_process )
+            {
+                req->handle = wine_server_obj_handle( hSnap );
+                req->reset = 1;
+                ret = wine_server_call( req );
+                process_handles = reply->handles;
+                pid = reply->pid;
+            }
+            SERVER_END_REQ;
+
+            for (;;)
+            {
+                if (ret != STATUS_SUCCESS) break;
+
+                for (i = 0; i < process_handles; i++)
+                {
+                    shi->Handle[shi->Count + i].OwnerPid = pid;
+                }
+                shi->Count += process_handles;
+
+                SERVER_START_REQ( next_process )
+                {
+                    req->handle = wine_server_obj_handle( hSnap );
+                    req->reset = 0;
+                    ret = wine_server_call( req );
+                    process_handles = reply->handles;
+                    pid = reply->pid;
+                }
+                SERVER_END_REQ;
+            }
+
+            NtClose(hSnap);
+
+            if (ret != STATUS_NO_MORE_FILES)
+            {
+                RtlFreeHeap(GetProcessHeap(), 0, shi);
+                break;
+            }
+
+            if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
+            else
+            {
+                memcpy(SystemInformation, shi, len);
+                ret = STATUS_SUCCESS;
+            }
+            RtlFreeHeap(GetProcessHeap(), 0, shi);
         }
         break;
     case SystemCacheInformation:
diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c
index 2d5c94f..f82bdfd 100644
--- a/dlls/ntdll/tests/info.c
+++ b/dlls/ntdll/tests/info.c
@@ -468,7 +468,7 @@ static void test_query_handle(void)
 
     /* Request the needed length : a SystemInformationLength greater than one struct sets ReturnLength */
     status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
-    todo_wine ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
+    ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
 
     SystemInformationLength = ReturnLength;
     shi = HeapReAlloc(GetProcessHeap(), 0, shi , SystemInformationLength);
@@ -480,11 +480,7 @@ static void test_query_handle(void)
 
         /* Check if we have some return values */
         trace("Number of Handles : %d\n", shi->Count);
-        todo_wine
-        {
-            /* our implementation is a stub for now */
-            ok( shi->Count > 1, "Expected more than 1 handles, got (%d)\n", shi->Count);
-        }
+        ok( shi->Count > 1, "Expected more than 1 handles, got (%d)\n", shi->Count);
     }
     HeapFree( GetProcessHeap(), 0, shi);
 }
-- 
1.7.4.1




More information about the wine-patches mailing list