Michael Müller : ntdll: Implement NtQuerySystemInformation(SystemExtendedHandleInformation).

Alexandre Julliard julliard at winehq.org
Mon Jun 7 15:02:05 CDT 2021


Module: wine
Branch: stable
Commit: dc85e950179173dbf5d46dade570ff8671770e94
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=dc85e950179173dbf5d46dade570ff8671770e94

Author: Michael Müller <michael at fds-team.de>
Date:   Wed Feb 17 22:59:15 2021 -0600

ntdll: Implement NtQuerySystemInformation(SystemExtendedHandleInformation).

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
(cherry picked from commit 835f5fff7150034139919801444b52a4c0186f44)
Signed-off-by: Michael Stefaniuc <mstefani at winehq.org>

---

 dlls/ntdll/tests/info.c  | 79 ++++++++++++++++++++++++++++++++++++++++++++++++
 dlls/ntdll/unix/system.c | 50 ++++++++++++++++++++++++++++++
 include/winternl.h       | 20 ++++++++++++
 3 files changed, 149 insertions(+)

diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c
index 4379d8a84c6..d003def5107 100644
--- a/dlls/ntdll/tests/info.c
+++ b/dlls/ntdll/tests/info.c
@@ -603,6 +603,84 @@ done:
     HeapFree( GetProcessHeap(), 0, shi);
 }
 
+static void test_query_handle_ex(void)
+{
+    SYSTEM_HANDLE_INFORMATION_EX *info = malloc(sizeof(SYSTEM_HANDLE_INFORMATION_EX));
+    ULONG size, expect_size;
+    NTSTATUS status;
+    unsigned int i;
+    HANDLE event;
+    BOOL found, ret;
+
+    event = CreateEventA(NULL, FALSE, FALSE, NULL);
+    ok(event != NULL, "failed to create event, error %u\n", GetLastError());
+    ret = SetHandleInformation(event, HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE,
+            HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE);
+    ok(ret, "got error %u\n", GetLastError());
+
+    size = 0;
+    status = pNtQuerySystemInformation(SystemExtendedHandleInformation, info, sizeof(SYSTEM_HANDLE_INFORMATION_EX), &size);
+    ok(status == STATUS_INFO_LENGTH_MISMATCH, "got %#x\n", status);
+    ok(size > sizeof(SYSTEM_HANDLE_INFORMATION_EX), "got size %u\n", size);
+
+    while (status == STATUS_INFO_LENGTH_MISMATCH)
+    {
+        info = realloc(info, size);
+        status = pNtQuerySystemInformation(SystemExtendedHandleInformation, info, size, &size);
+    }
+    ok(!status, "got %#x\n", status);
+    expect_size = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION_EX, Handles[info->NumberOfHandles]);
+    ok(size == expect_size, "expected size %u, got %u\n", expect_size, size);
+    ok(info->NumberOfHandles > 1, "got %Iu handles\n", info->NumberOfHandles);
+
+    found = FALSE;
+    for (i = 0; i < info->NumberOfHandles; ++i)
+    {
+        if (info->Handles[i].UniqueProcessId == GetCurrentProcessId()
+                && (HANDLE)info->Handles[i].HandleValue == event)
+        {
+            todo_wine ok(info->Handles[i].HandleAttributes == (OBJ_INHERIT | OBJ_PROTECT_CLOSE),
+                    "got flags %#x\n", info->Handles[i].HandleAttributes);
+            ok(info->Handles[i].GrantedAccess == EVENT_ALL_ACCESS, "got access %#x\n", info->Handles[i].GrantedAccess);
+            found = TRUE;
+        }
+        ok(!info->Handles[i].CreatorBackTraceIndex, "got backtrace index %u\n", info->Handles[i].CreatorBackTraceIndex);
+    }
+    ok(found, "event handle not found\n");
+
+    ret = SetHandleInformation(event, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0);
+    ok(ret, "got error %u\n", GetLastError());
+    CloseHandle(event);
+
+    status = pNtQuerySystemInformation(SystemExtendedHandleInformation, info, size, &size);
+    while (status == STATUS_INFO_LENGTH_MISMATCH)
+    {
+        info = realloc(info, size);
+        status = pNtQuerySystemInformation(SystemExtendedHandleInformation, info, size, &size);
+    }
+    ok(!status, "got %#x\n", status);
+    expect_size = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION_EX, Handles[info->NumberOfHandles]);
+    ok(size == expect_size, "expected size %u, got %u\n", expect_size, size);
+    ok(info->NumberOfHandles > 1, "got %Iu handles\n", info->NumberOfHandles);
+
+    found = FALSE;
+    for (i = 0; i < info->NumberOfHandles; ++i)
+    {
+        if (info->Handles[i].UniqueProcessId == GetCurrentProcessId()
+                && (HANDLE)info->Handles[i].HandleValue == event)
+        {
+            found = TRUE;
+            break;
+        }
+    }
+    ok(!found, "event handle found\n");
+
+    status = pNtQuerySystemInformation(SystemExtendedHandleInformation, NULL, sizeof(SYSTEM_HANDLE_INFORMATION_EX), &size);
+    ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status );
+
+    free(info);
+}
+
 static void test_query_cache(void)
 {
     NTSTATUS status;
@@ -2762,6 +2840,7 @@ START_TEST(info)
     test_query_procperf();
     test_query_module();
     test_query_handle();
+    test_query_handle_ex();
     test_query_cache();
     test_query_interrupt();
     test_time_adjustment();
diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c
index a889b2e020c..e2482f91041 100644
--- a/dlls/ntdll/unix/system.c
+++ b/dlls/ntdll/unix/system.c
@@ -2461,6 +2461,56 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class,
         break;
     }
 
+    case SystemExtendedHandleInformation:
+    {
+        struct handle_info *handle_info;
+        DWORD i, num_handles;
+
+        if (size < sizeof(SYSTEM_HANDLE_INFORMATION_EX))
+        {
+            ret = STATUS_INFO_LENGTH_MISMATCH;
+            break;
+        }
+
+        if (!info)
+        {
+            ret = STATUS_ACCESS_VIOLATION;
+            break;
+        }
+
+        num_handles = (size - FIELD_OFFSET( SYSTEM_HANDLE_INFORMATION_EX, Handles ))
+                      / sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX);
+        if (!(handle_info = malloc( sizeof(*handle_info) * num_handles ))) return STATUS_NO_MEMORY;
+
+        SERVER_START_REQ( get_system_handles )
+        {
+            wine_server_set_reply( req, handle_info, sizeof(*handle_info) * num_handles );
+            if (!(ret = wine_server_call( req )))
+            {
+                SYSTEM_HANDLE_INFORMATION_EX *shi = info;
+                shi->NumberOfHandles = wine_server_reply_size( req ) / sizeof(*handle_info);
+                len = FIELD_OFFSET( SYSTEM_HANDLE_INFORMATION_EX, Handles[shi->NumberOfHandles] );
+                for (i = 0; i < shi->NumberOfHandles; i++)
+                {
+                    memset( &shi->Handles[i], 0, sizeof(shi->Handles[i]) );
+                    shi->Handles[i].UniqueProcessId = handle_info[i].owner;
+                    shi->Handles[i].HandleValue     = handle_info[i].handle;
+                    shi->Handles[i].GrantedAccess   = handle_info[i].access;
+                    /* FIXME: Fill out Object, HandleAttributes, ObjectTypeIndex */
+                }
+            }
+            else if (ret == STATUS_BUFFER_TOO_SMALL)
+            {
+                len = FIELD_OFFSET( SYSTEM_HANDLE_INFORMATION_EX, Handles[reply->count] );
+                ret = STATUS_INFO_LENGTH_MISMATCH;
+            }
+        }
+        SERVER_END_REQ;
+
+        free( handle_info );
+        break;
+    }
+
     case SystemCacheInformation:
     {
         SYSTEM_CACHE_INFORMATION sci = { 0 };
diff --git a/include/winternl.h b/include/winternl.h
index a7b0e04aade..41d871e9bc6 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -1867,6 +1867,25 @@ typedef struct _SYSTEM_HANDLE_INFORMATION {
     SYSTEM_HANDLE_ENTRY Handle[1];
 } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
 
+typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
+{
+    void *Object;
+    ULONG_PTR UniqueProcessId;
+    ULONG_PTR HandleValue;
+    ULONG GrantedAccess;
+    USHORT CreatorBackTraceIndex;
+    USHORT ObjectTypeIndex;
+    ULONG HandleAttributes;
+    ULONG Reserved;
+} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX;
+
+typedef struct _SYSTEM_HANDLE_INFORMATION_EX
+{
+    ULONG_PTR NumberOfHandles;
+    ULONG_PTR Reserved;
+    SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1];
+} SYSTEM_HANDLE_INFORMATION_EX;
+
 /* System Information Class 0x15 */
 
 typedef struct _SYSTEM_CACHE_INFORMATION {
@@ -2244,6 +2263,7 @@ typedef struct _RTL_HANDLE_TABLE
 
 #define LOGONID_CURRENT    ((ULONG)-1)
 
+#define OBJ_PROTECT_CLOSE    0x00000001
 #define OBJ_INHERIT          0x00000002
 #define OBJ_PERMANENT        0x00000010
 #define OBJ_EXCLUSIVE        0x00000020




More information about the wine-cvs mailing list