[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