server: Implement wineserver call for SystemHandleInformation.
authorSebastian Lackner <sebastian@fds-team.de>
Thu, 24 Dec 2015 12:08:50 +0000 (13:08 +0100)
committerAlexandre Julliard <julliard@winehq.org>
Tue, 29 Dec 2015 16:51:59 +0000 (17:51 +0100)
Signed-off-by: Sebastian Lackner <sebastian@fds-team.de>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
dlls/ntdll/nt.c
dlls/ntdll/tests/info.c
include/wine/server_protocol.h
server/handle.c
server/protocol.def
server/request.h
server/trace.c

index 8ea1ddd053c9c06fca2960011a9b166884df895d..55255a83a41986decdf694efb1d81ed52c4ea191 100644 (file)
@@ -2004,18 +2004,51 @@ NTSTATUS WINAPI NtQuerySystemInformation(
         break;
     case SystemHandleInformation:
         {
-            SYSTEM_HANDLE_INFORMATION shi;
+            struct handle_info *info;
+            DWORD i, num_handles;
 
-            memset(&shi, 0, sizeof(shi));
-            len = sizeof(shi);
+            if (Length < sizeof(SYSTEM_HANDLE_INFORMATION))
+            {
+                ret = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
 
-            if ( Length >= len)
+            if (!SystemInformation)
             {
-                if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
-                else memcpy( SystemInformation, &shi, len);
+                ret = STATUS_ACCESS_VIOLATION;
+                break;
             }
-            else ret = STATUS_INFO_LENGTH_MISMATCH;
-            FIXME("info_class SYSTEM_HANDLE_INFORMATION\n");
+
+            num_handles = (Length - FIELD_OFFSET( SYSTEM_HANDLE_INFORMATION, Handle )) / sizeof(SYSTEM_HANDLE_ENTRY);
+            if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*info) * num_handles )))
+                return STATUS_NO_MEMORY;
+
+            SERVER_START_REQ( get_system_handles )
+            {
+                wine_server_set_reply( req, info, sizeof(*info) * num_handles );
+                if (!(ret = wine_server_call( req )))
+                {
+                    SYSTEM_HANDLE_INFORMATION *shi = SystemInformation;
+                    shi->Count = wine_server_reply_size( req ) / sizeof(*info);
+                    len = FIELD_OFFSET( SYSTEM_HANDLE_INFORMATION, Handle[shi->Count] );
+                    for (i = 0; i < shi->Count; i++)
+                    {
+                        memset( &shi->Handle[i], 0, sizeof(shi->Handle[i]) );
+                        shi->Handle[i].OwnerPid     = info[i].owner;
+                        shi->Handle[i].HandleValue  = info[i].handle;
+                        shi->Handle[i].AccessMask   = info[i].access;
+                        /* FIXME: Fill out ObjectType, HandleFlags, ObjectPointer */
+                    }
+                }
+                else if (ret == STATUS_BUFFER_TOO_SMALL)
+                {
+                    len = FIELD_OFFSET( SYSTEM_HANDLE_INFORMATION, Handle[reply->count] );
+                    ret = STATUS_INFO_LENGTH_MISMATCH;
+                }
+            }
+            SERVER_END_REQ;
+
+            RtlFreeHeap( GetProcessHeap(), 0, info );
         }
         break;
     case SystemCacheInformation:
index 3219dbb687f48c37baf8d2d36d492029568655ac..da509aac21690992c41c32c9965939717b597fd8 100644 (file)
@@ -487,7 +487,7 @@ static void test_query_handle(void)
     /* Request the needed length : a SystemInformationLength greater than one struct sets ReturnLength */
     ReturnLength = 0xdeadbeef;
     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);
     ok( ReturnLength != 0xdeadbeef, "Expected valid ReturnLength\n" );
 
     SystemInformationLength = ReturnLength;
@@ -503,13 +503,13 @@ static void test_query_handle(void)
     }
     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status );
     ExpectedLength = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION, Handle[shi->Count]);
-    todo_wine ok( ReturnLength == ExpectedLength || broken(ReturnLength == ExpectedLength - sizeof(DWORD)), /* Vista / 2008 */
-                  "Expected length %u, got %u\n", ExpectedLength, ReturnLength );
-    todo_wine ok( shi->Count > 1, "Expected more than 1 handle, got %u\n", shi->Count );
+    ok( ReturnLength == ExpectedLength || broken(ReturnLength == ExpectedLength - sizeof(DWORD)), /* Vista / 2008 */
+        "Expected length %u, got %u\n", ExpectedLength, ReturnLength );
+    ok( shi->Count > 1, "Expected more than 1 handle, got %u\n", shi->Count );
     for (i = 0, found = FALSE; i < shi->Count && !found; i++)
         found = (shi->Handle[i].OwnerPid == GetCurrentProcessId()) &&
                 ((HANDLE)(ULONG_PTR)shi->Handle[i].HandleValue == EventHandle);
-    todo_wine ok( found, "Expected to find event handle in handle list\n" );
+    ok( found, "Expected to find event handle in handle list\n" );
 
     CloseHandle(EventHandle);
 
index f0dc65a736cb640bfb161cd6fb9d6a88da41c8eb..2d8a7f7fe3df0b5c386d0800757c460ef5151b25 100644 (file)
@@ -4655,6 +4655,29 @@ struct get_security_object_reply
 };
 
 
+struct handle_info
+{
+    process_id_t owner;
+    obj_handle_t handle;
+    unsigned int access;
+};
+
+
+struct get_system_handles_request
+{
+    struct request_header __header;
+    char __pad_12[4];
+};
+struct get_system_handles_reply
+{
+    struct reply_header __header;
+    unsigned int    count;
+    /* VARARG(data,handle_infos); */
+    char __pad_12[4];
+};
+
+
+
 struct create_mailslot_request
 {
     struct request_header __header;
@@ -5560,6 +5583,7 @@ enum request
     REQ_set_token_default_dacl,
     REQ_set_security_object,
     REQ_get_security_object,
+    REQ_get_system_handles,
     REQ_create_mailslot,
     REQ_set_mailslot_info,
     REQ_create_directory,
@@ -5836,6 +5860,7 @@ union generic_request
     struct set_token_default_dacl_request set_token_default_dacl_request;
     struct set_security_object_request set_security_object_request;
     struct get_security_object_request get_security_object_request;
+    struct get_system_handles_request get_system_handles_request;
     struct create_mailslot_request create_mailslot_request;
     struct set_mailslot_info_request set_mailslot_info_request;
     struct create_directory_request create_directory_request;
@@ -6110,6 +6135,7 @@ union generic_reply
     struct set_token_default_dacl_reply set_token_default_dacl_reply;
     struct set_security_object_reply set_security_object_reply;
     struct get_security_object_reply get_security_object_reply;
+    struct get_system_handles_reply get_system_handles_reply;
     struct create_mailslot_reply create_mailslot_reply;
     struct set_mailslot_info_reply set_mailslot_info_reply;
     struct create_directory_reply create_directory_reply;
@@ -6154,6 +6180,6 @@ union generic_reply
     struct terminate_job_reply terminate_job_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 491
+#define SERVER_PROTOCOL_VERSION 492
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
index 5043ff70b7117ead702e3653d0e92834d1e8e86f..05d71bac3867ce3fe00571296f8947cce7caaf1a 100644 (file)
@@ -745,3 +745,59 @@ DECL_HANDLER(get_security_object)
 
     release_object( obj );
 }
+
+struct enum_handle_info
+{
+    unsigned int count;
+    struct handle_info *handle;
+};
+
+static int enum_handles( struct process *process, void *user )
+{
+    struct enum_handle_info *info = user;
+    struct handle_table *table = process->handles;
+    struct handle_entry *entry;
+    struct handle_info *handle;
+    unsigned int i;
+
+    if (!table)
+        return 0;
+
+    for (i = 0, entry = table->entries; i <= table->last; i++, entry++)
+    {
+        if (!entry->ptr) continue;
+        if (!info->handle)
+        {
+            info->count++;
+            continue;
+        }
+        assert( info->count );
+        handle = info->handle++;
+        handle->owner  = process->id;
+        handle->handle = index_to_handle(i);
+        handle->access = entry->access & ~RESERVED_ALL;
+        info->count--;
+    }
+
+    return 0;
+}
+
+DECL_HANDLER(get_system_handles)
+{
+    struct enum_handle_info info;
+    struct handle_info *handle;
+    data_size_t max_handles = get_reply_max_size() / sizeof(*handle);
+
+    info.handle = NULL;
+    info.count  = 0;
+    enum_processes( enum_handles, &info );
+    reply->count = info.count;
+
+    if (max_handles < info.count)
+        set_error( STATUS_BUFFER_TOO_SMALL );
+    else if ((handle = set_reply_data_size( info.count * sizeof(*handle) )))
+    {
+        info.handle = handle;
+        enum_processes( enum_handles, &info );
+    }
+}
index bfb9089e41ec1ba6d9c096f3530727c9889b9baf..ea5bd6152927c66d52ef73eac7188df0e45f84af 100644 (file)
@@ -3266,6 +3266,22 @@ enum coords_relative
     VARARG(sd,security_descriptor); /* retrieved security descriptor */
 @END
 
+
+struct handle_info
+{
+    process_id_t owner;
+    obj_handle_t handle;
+    unsigned int access;
+};
+
+/* Return a list of all opened handles */
+@REQ(get_system_handles)
+@REPLY
+    unsigned int    count;        /* number of handles */
+    VARARG(data,handle_infos);    /* array of handle_infos */
+@END
+
+
 /* Create a mailslot */
 @REQ(create_mailslot)
     unsigned int   access;        /* wanted access rights */
index 9653f0c95620a05768056b30ed1252b09b013972..3f7b36bad366a086a3edf622ff4ba1cd454e9a84 100644 (file)
@@ -333,6 +333,7 @@ DECL_HANDLER(get_token_default_dacl);
 DECL_HANDLER(set_token_default_dacl);
 DECL_HANDLER(set_security_object);
 DECL_HANDLER(get_security_object);
+DECL_HANDLER(get_system_handles);
 DECL_HANDLER(create_mailslot);
 DECL_HANDLER(set_mailslot_info);
 DECL_HANDLER(create_directory);
@@ -608,6 +609,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
     (req_handler)req_set_token_default_dacl,
     (req_handler)req_set_security_object,
     (req_handler)req_get_security_object,
+    (req_handler)req_get_system_handles,
     (req_handler)req_create_mailslot,
     (req_handler)req_set_mailslot_info,
     (req_handler)req_create_directory,
@@ -2083,6 +2085,9 @@ C_ASSERT( FIELD_OFFSET(struct get_security_object_request, security_info) == 16
 C_ASSERT( sizeof(struct get_security_object_request) == 24 );
 C_ASSERT( FIELD_OFFSET(struct get_security_object_reply, sd_len) == 8 );
 C_ASSERT( sizeof(struct get_security_object_reply) == 16 );
+C_ASSERT( sizeof(struct get_system_handles_request) == 16 );
+C_ASSERT( FIELD_OFFSET(struct get_system_handles_reply, count) == 8 );
+C_ASSERT( sizeof(struct get_system_handles_reply) == 16 );
 C_ASSERT( FIELD_OFFSET(struct create_mailslot_request, access) == 12 );
 C_ASSERT( FIELD_OFFSET(struct create_mailslot_request, attributes) == 16 );
 C_ASSERT( FIELD_OFFSET(struct create_mailslot_request, rootdir) == 20 );
index 405a1c9621b87c7421992e9ec822198ea6e4e38a..c53af3cf1fd204e8755ab2de717cb74ff3e51f99 100644 (file)
@@ -1142,6 +1142,23 @@ static void dump_varargs_rawinput_devices(const char *prefix, data_size_t size )
     fputc( '}', stderr );
 }
 
+static void dump_varargs_handle_infos( const char *prefix, data_size_t size )
+{
+    const struct handle_info *handle;
+
+    fprintf( stderr, "%s{", prefix );
+    while (size >= sizeof(*handle))
+    {
+        handle = cur_data;
+        fprintf( stderr, "{owner=%04x,handle=%04x,access=%08x}",
+                 handle->owner, handle->handle, handle->access );
+        size -= sizeof(*handle);
+        remove_data( sizeof(*handle) );
+        if (size) fputc( ',', stderr );
+    }
+    fputc( '}', stderr );
+}
+
 typedef void (*dump_func)( const void *req );
 
 /* Everything below this line is generated automatically by tools/make_requests */
@@ -3838,6 +3855,16 @@ static void dump_get_security_object_reply( const struct get_security_object_rep
     dump_varargs_security_descriptor( ", sd=", cur_size );
 }
 
+static void dump_get_system_handles_request( const struct get_system_handles_request *req )
+{
+}
+
+static void dump_get_system_handles_reply( const struct get_system_handles_reply *req )
+{
+    fprintf( stderr, " count=%08x", req->count );
+    dump_varargs_handle_infos( ", data=", cur_size );
+}
+
 static void dump_create_mailslot_request( const struct create_mailslot_request *req )
 {
     fprintf( stderr, " access=%08x", req->access );
@@ -4501,6 +4528,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_set_token_default_dacl_request,
     (dump_func)dump_set_security_object_request,
     (dump_func)dump_get_security_object_request,
+    (dump_func)dump_get_system_handles_request,
     (dump_func)dump_create_mailslot_request,
     (dump_func)dump_set_mailslot_info_request,
     (dump_func)dump_create_directory_request,
@@ -4773,6 +4801,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
     NULL,
     NULL,
     (dump_func)dump_get_security_object_reply,
+    (dump_func)dump_get_system_handles_reply,
     (dump_func)dump_create_mailslot_reply,
     (dump_func)dump_set_mailslot_info_reply,
     (dump_func)dump_create_directory_reply,
@@ -5045,6 +5074,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
     "set_token_default_dacl",
     "set_security_object",
     "get_security_object",
+    "get_system_handles",
     "create_mailslot",
     "set_mailslot_info",
     "create_directory",