[PATCH 2/2] user32: Fix returned class name for other processes windows.

Nikolay Sivov nsivov at codeweavers.com
Mon Jun 11 02:42:35 CDT 2018


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/user32/class.c            | 18 ++++++++++--------
 include/wine/server_protocol.h | 18 +++++++++++++++++-
 server/atom.c                  | 25 +++++++++++++++++++++++++
 server/class.c                 |  5 +++++
 server/object.h                |  1 +
 server/protocol.def            |  8 ++++++++
 server/request.h               |  5 +++++
 server/trace.c                 | 13 +++++++++++++
 server/user.h                  |  1 +
 server/window.c                | 17 +++++++++++++++++
 10 files changed, 102 insertions(+), 9 deletions(-)

diff --git a/dlls/user32/class.c b/dlls/user32/class.c
index 2b2d07f888..69dc4477ca 100644
--- a/dlls/user32/class.c
+++ b/dlls/user32/class.c
@@ -1183,7 +1183,7 @@ INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
 INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
 {
     CLASS *class;
-    INT ret;
+    INT ret = 0;
 
     TRACE("%p %p %d\n", hwnd, buffer, count);
 
@@ -1193,15 +1193,17 @@ INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
 
     if (class == CLASS_OTHER_PROCESS)
     {
-        WCHAR tmpbuf[MAX_ATOM_LEN + 1];
-
-        ret = GlobalGetAtomNameW( GetClassLongW( hwnd, GCW_ATOM ), tmpbuf, MAX_ATOM_LEN + 1 );
-        if (ret)
+        SERVER_START_REQ( get_class_name )
         {
-            ret = min(count - 1, ret);
-            memcpy(buffer, tmpbuf, ret * sizeof(WCHAR));
-            buffer[ret] = 0;
+            req->handle = wine_server_user_handle( hwnd );
+            wine_server_set_reply( req, buffer, count * sizeof(WCHAR) );
+            if (!wine_server_call_err( req ))
+            {
+                ret = wine_server_reply_size( reply );
+                buffer[ret / sizeof(WCHAR)] = 0;
+            }
         }
+        SERVER_END_REQ;
     }
     else
     {
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 5358af20b8..879d361ab2 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -3503,6 +3503,19 @@ struct set_window_owner_reply
 
 
 
+struct get_class_name_request
+{
+    struct request_header __header;
+    user_handle_t  handle;
+};
+struct get_class_name_reply
+{
+    struct reply_header __header;
+    /* VARARG(name,unicode_str); */
+};
+
+
+
 struct get_window_info_request
 {
     struct request_header __header;
@@ -5793,6 +5806,7 @@ enum request
     REQ_destroy_window,
     REQ_get_desktop_window,
     REQ_set_window_owner,
+    REQ_get_class_name,
     REQ_get_window_info,
     REQ_set_window_info,
     REQ_set_parent,
@@ -6089,6 +6103,7 @@ union generic_request
     struct destroy_window_request destroy_window_request;
     struct get_desktop_window_request get_desktop_window_request;
     struct set_window_owner_request set_window_owner_request;
+    struct get_class_name_request get_class_name_request;
     struct get_window_info_request get_window_info_request;
     struct set_window_info_request set_window_info_request;
     struct set_parent_request set_parent_request;
@@ -6383,6 +6398,7 @@ union generic_reply
     struct destroy_window_reply destroy_window_reply;
     struct get_desktop_window_reply get_desktop_window_reply;
     struct set_window_owner_reply set_window_owner_reply;
+    struct get_class_name_reply get_class_name_reply;
     struct get_window_info_reply get_window_info_reply;
     struct set_window_info_reply set_window_info_reply;
     struct set_parent_reply set_parent_reply;
@@ -6512,6 +6528,6 @@ union generic_reply
     struct terminate_job_reply terminate_job_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 554
+#define SERVER_PROTOCOL_VERSION 555
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/atom.c b/server/atom.c
index 3ff75407d9..7e79195973 100644
--- a/server/atom.c
+++ b/server/atom.c
@@ -381,6 +381,31 @@ void release_global_atom( struct winstation *winstation, atom_t atom )
     }
 }
 
+/* get atom name */
+int get_atom_string( atom_t atom, WCHAR *name, unsigned short len )
+{
+    struct atom_table *table = get_table( 0, 0 );
+    int ret = 0;
+
+    *name = 0;
+
+    if (table)
+    {
+        struct atom_entry *entry;
+
+        if ((entry = get_atom_entry( table, atom )))
+        {
+            ret = len = min(len, entry->len);
+            memcpy(name, entry->str, len);
+            name[len / sizeof(WCHAR)] = 0;
+        }
+
+        release_object( table );
+    }
+
+    return ret;
+}
+
 /* add a global atom */
 DECL_HANDLER(add_atom)
 {
diff --git a/server/class.c b/server/class.c
index d5f6712006..4bb3aa1aad 100644
--- a/server/class.c
+++ b/server/class.c
@@ -142,6 +142,11 @@ atom_t get_class_atom( struct window_class *class )
     return class->atom;
 }
 
+atom_t get_base_class_atom( struct window_class *class )
+{
+    return class->base_atom;
+}
+
 client_ptr_t get_class_client_ptr( struct window_class *class )
 {
     return class->client_ptr;
diff --git a/server/object.h b/server/object.h
index b5c50e1cee..4c8d1a58fd 100644
--- a/server/object.h
+++ b/server/object.h
@@ -224,6 +224,7 @@ extern atom_t add_global_atom( struct winstation *winstation, const struct unico
 extern atom_t find_global_atom( struct winstation *winstation, const struct unicode_str *str );
 extern int grab_global_atom( struct winstation *winstation, atom_t atom );
 extern void release_global_atom( struct winstation *winstation, atom_t atom );
+extern int get_atom_string( atom_t atom, WCHAR *name, unsigned short len );
 
 /* directory functions */
 
diff --git a/server/protocol.def b/server/protocol.def
index 032b03822b..9027312f46 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -2515,6 +2515,14 @@ enum message_type
 @END
 
 
+/* Get window class name */
+ at REQ(get_class_name)
+    user_handle_t  handle;      /* handle to the window */
+ at REPLY
+    VARARG(name,unicode_str);   /* class name */
+ at END
+
+
 /* Get information from a window handle */
 @REQ(get_window_info)
     user_handle_t  handle;      /* handle to the window */
diff --git a/server/request.h b/server/request.h
index 9cf81a1f09..a693e2cf62 100644
--- a/server/request.h
+++ b/server/request.h
@@ -274,6 +274,7 @@ DECL_HANDLER(create_window);
 DECL_HANDLER(destroy_window);
 DECL_HANDLER(get_desktop_window);
 DECL_HANDLER(set_window_owner);
+DECL_HANDLER(get_class_name);
 DECL_HANDLER(get_window_info);
 DECL_HANDLER(set_window_info);
 DECL_HANDLER(set_parent);
@@ -569,6 +570,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
     (req_handler)req_destroy_window,
     (req_handler)req_get_desktop_window,
     (req_handler)req_set_window_owner,
+    (req_handler)req_get_class_name,
     (req_handler)req_get_window_info,
     (req_handler)req_set_window_info,
     (req_handler)req_set_parent,
@@ -1685,6 +1687,9 @@ C_ASSERT( sizeof(struct set_window_owner_request) == 24 );
 C_ASSERT( FIELD_OFFSET(struct set_window_owner_reply, full_owner) == 8 );
 C_ASSERT( FIELD_OFFSET(struct set_window_owner_reply, prev_owner) == 12 );
 C_ASSERT( sizeof(struct set_window_owner_reply) == 16 );
+C_ASSERT( FIELD_OFFSET(struct get_class_name_request, handle) == 12 );
+C_ASSERT( sizeof(struct get_class_name_request) == 16 );
+C_ASSERT( sizeof(struct get_class_name_reply) == 8 );
 C_ASSERT( FIELD_OFFSET(struct get_window_info_request, handle) == 12 );
 C_ASSERT( sizeof(struct get_window_info_request) == 16 );
 C_ASSERT( FIELD_OFFSET(struct get_window_info_reply, full_handle) == 8 );
diff --git a/server/trace.c b/server/trace.c
index 999532a425..6b38896f4c 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -3082,6 +3082,16 @@ static void dump_set_window_owner_reply( const struct set_window_owner_reply *re
     fprintf( stderr, ", prev_owner=%08x", req->prev_owner );
 }
 
+static void dump_get_class_name_request( const struct get_class_name_request *req )
+{
+    fprintf( stderr, " handle=%08x", req->handle );
+}
+
+static void dump_get_class_name_reply( const struct get_class_name_reply *req )
+{
+    dump_varargs_unicode_str( " name=", cur_size );
+}
+
 static void dump_get_window_info_request( const struct get_window_info_request *req )
 {
     fprintf( stderr, " handle=%08x", req->handle );
@@ -4693,6 +4703,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_destroy_window_request,
     (dump_func)dump_get_desktop_window_request,
     (dump_func)dump_set_window_owner_request,
+    (dump_func)dump_get_class_name_request,
     (dump_func)dump_get_window_info_request,
     (dump_func)dump_set_window_info_request,
     (dump_func)dump_set_parent_request,
@@ -4985,6 +4996,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
     NULL,
     (dump_func)dump_get_desktop_window_reply,
     (dump_func)dump_set_window_owner_reply,
+    (dump_func)dump_get_class_name_reply,
     (dump_func)dump_get_window_info_reply,
     (dump_func)dump_set_window_info_reply,
     (dump_func)dump_set_parent_reply,
@@ -5277,6 +5289,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
     "destroy_window",
     "get_desktop_window",
     "set_window_owner",
+    "get_class_name",
     "get_window_info",
     "set_window_info",
     "set_parent",
diff --git a/server/user.h b/server/user.h
index e7eecd4c6a..11db294fbb 100644
--- a/server/user.h
+++ b/server/user.h
@@ -175,6 +175,7 @@ extern void release_class( struct window_class *class );
 extern int is_desktop_class( struct window_class *class );
 extern int is_hwnd_message_class( struct window_class *class );
 extern atom_t get_class_atom( struct window_class *class );
+extern atom_t get_base_class_atom( struct window_class *class );
 extern client_ptr_t get_class_client_ptr( struct window_class *class );
 
 /* windows station functions */
diff --git a/server/window.c b/server/window.c
index 70812095d2..2223d38aeb 100644
--- a/server/window.c
+++ b/server/window.c
@@ -2049,6 +2049,23 @@ DECL_HANDLER(set_window_owner)
 }
 
 
+/* get class name for a window handle */
+DECL_HANDLER(get_class_name)
+{
+    struct window *win = get_window( req->handle );
+    WCHAR name[256];
+    atom_t atom;
+    int len;
+
+    if (!win) return;
+
+    atom = win->class ? get_base_class_atom( win->class ) : DESKTOP_ATOM;
+    len = get_atom_string(atom, name, 256);
+
+    set_reply_data( name, min( len, get_reply_max_size() ));
+}
+
+
 /* get information from a window handle */
 DECL_HANDLER(get_window_info)
 {
-- 
2.17.1




More information about the wine-devel mailing list