Signed-off-by: Nikolay Sivov nsivov@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 */ +@REQ(get_class_name) + user_handle_t handle; /* handle to the window */ +@REPLY + VARARG(name,unicode_str); /* class name */ +@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) {