Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/user32/class.c | 1 + include/wine/server_protocol.h | 4 +++- server/class.c | 27 +++++++++++++++++++++++++-- server/protocol.def | 2 ++ server/request.h | 14 ++++++++------ server/trace.c | 2 ++ 6 files changed, 41 insertions(+), 9 deletions(-)
diff --git a/dlls/user32/class.c b/dlls/user32/class.c index ce2830fe25..2b2d07f888 100644 --- a/dlls/user32/class.c +++ b/dlls/user32/class.c @@ -487,6 +487,7 @@ static CLASS *CLASS_RegisterClass( LPCWSTR name, UINT basename_offset, HINSTANCE req->win_extra = winExtra; req->client_ptr = wine_server_client_ptr( classPtr ); req->atom = classPtr->atomName; + req->name_offset = basename_offset; if (!req->atom && name) wine_server_add_data( req, name, strlenW(name) * sizeof(WCHAR) ); ret = !wine_server_call_err( req ); classPtr->atomName = reply->atom; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 98dbcb7e61..5358af20b8 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -4475,6 +4475,8 @@ struct create_class_request struct request_header __header; int local; atom_t atom; + int name_offset; + int _pad; unsigned int style; mod_handle_t instance; int extra; @@ -6510,6 +6512,6 @@ union generic_reply struct terminate_job_reply terminate_job_reply; };
-#define SERVER_PROTOCOL_VERSION 553 +#define SERVER_PROTOCOL_VERSION 554
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/class.c b/server/class.c index cc6e52d9b1..d5f6712006 100644 --- a/server/class.c +++ b/server/class.c @@ -46,6 +46,7 @@ struct window_class int count; /* reference count */ int local; /* local class? */ atom_t atom; /* class atom */ + atom_t base_atom; /* base class atom for versioned class */ mod_handle_t instance; /* module instance */ unsigned int style; /* class style */ int win_extra; /* number of window extra bytes */ @@ -151,17 +152,35 @@ DECL_HANDLER(create_class) { struct window_class *class; struct unicode_str name = get_req_unicode_str(); - atom_t atom; + atom_t atom, base_atom;
if (name.len) { atom = add_global_atom( NULL, &name ); if (!atom) return; + if (req->name_offset && req->name_offset < name.len / sizeof(WCHAR)) + { + name.str += req->name_offset; + name.len -= req->name_offset * sizeof(WCHAR); + + base_atom = add_global_atom( NULL, &name ); + if (!base_atom) + { + release_global_atom( NULL, atom ); + return; + } + } + else + { + base_atom = atom; + grab_global_atom( NULL, atom ); + } } else { - atom = req->atom; + base_atom = atom = req->atom; if (!grab_global_atom( NULL, atom )) return; + grab_global_atom( NULL, base_atom ); }
class = find_class( current->process, atom, req->instance ); @@ -169,6 +188,7 @@ DECL_HANDLER(create_class) { set_win32_error( ERROR_CLASS_ALREADY_EXISTS ); release_global_atom( NULL, atom ); + release_global_atom( NULL, base_atom ); return; } if (req->extra < 0 || req->extra > 4096 || req->win_extra < 0 || req->win_extra > 4096) @@ -176,15 +196,18 @@ DECL_HANDLER(create_class) /* don't allow stupid values here */ set_error( STATUS_INVALID_PARAMETER ); release_global_atom( NULL, atom ); + release_global_atom( NULL, base_atom ); return; }
if (!(class = create_class( current->process, req->extra, req->local ))) { release_global_atom( NULL, atom ); + release_global_atom( NULL, base_atom ); return; } class->atom = atom; + class->base_atom = base_atom; class->instance = req->instance; class->style = req->style; class->win_extra = req->win_extra; diff --git a/server/protocol.def b/server/protocol.def index 99e7221c4b..032b03822b 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3144,6 +3144,8 @@ enum caret_state @REQ(create_class) int local; /* is it a local class? */ atom_t atom; /* class atom */ + int name_offset; /* base class name offset for specified atom */ + int _pad; unsigned int style; /* class style */ mod_handle_t instance; /* module instance */ int extra; /* number of extra class bytes */ diff --git a/server/request.h b/server/request.h index 2d55dfbd98..9cf81a1f09 100644 --- a/server/request.h +++ b/server/request.h @@ -2031,12 +2031,14 @@ C_ASSERT( FIELD_OFFSET(struct get_hook_info_reply, unicode) == 32 ); C_ASSERT( sizeof(struct get_hook_info_reply) == 40 ); C_ASSERT( FIELD_OFFSET(struct create_class_request, local) == 12 ); C_ASSERT( FIELD_OFFSET(struct create_class_request, atom) == 16 ); -C_ASSERT( FIELD_OFFSET(struct create_class_request, style) == 20 ); -C_ASSERT( FIELD_OFFSET(struct create_class_request, instance) == 24 ); -C_ASSERT( FIELD_OFFSET(struct create_class_request, extra) == 32 ); -C_ASSERT( FIELD_OFFSET(struct create_class_request, win_extra) == 36 ); -C_ASSERT( FIELD_OFFSET(struct create_class_request, client_ptr) == 40 ); -C_ASSERT( sizeof(struct create_class_request) == 48 ); +C_ASSERT( FIELD_OFFSET(struct create_class_request, name_offset) == 20 ); +C_ASSERT( FIELD_OFFSET(struct create_class_request, _pad) == 24 ); +C_ASSERT( FIELD_OFFSET(struct create_class_request, style) == 28 ); +C_ASSERT( FIELD_OFFSET(struct create_class_request, instance) == 32 ); +C_ASSERT( FIELD_OFFSET(struct create_class_request, extra) == 40 ); +C_ASSERT( FIELD_OFFSET(struct create_class_request, win_extra) == 44 ); +C_ASSERT( FIELD_OFFSET(struct create_class_request, client_ptr) == 48 ); +C_ASSERT( sizeof(struct create_class_request) == 56 ); C_ASSERT( FIELD_OFFSET(struct create_class_reply, atom) == 8 ); C_ASSERT( sizeof(struct create_class_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct destroy_class_request, atom) == 12 ); diff --git a/server/trace.c b/server/trace.c index e2980a3e31..999532a425 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3753,6 +3753,8 @@ static void dump_create_class_request( const struct create_class_request *req ) { fprintf( stderr, " local=%d", req->local ); fprintf( stderr, ", atom=%04x", req->atom ); + fprintf( stderr, ", name_offset=%d", req->name_offset ); + fprintf( stderr, ", _pad=%d", req->_pad ); fprintf( stderr, ", style=%08x", req->style ); dump_uint64( ", instance=", &req->instance ); fprintf( stderr, ", extra=%d", req->extra );
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) {
Nikolay Sivov nsivov@codeweavers.com writes:
@@ -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() ));
+}
This should go into class.c., though I'd suggest returning the atom in the existing set_class_info request instead.