From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/win32u/class.c | 52 +++++++++++++++++----------------- dlls/win32u/window.c | 8 +++++- include/wine/server_protocol.h | 36 ++++++++++++++++++++++- server/protocol.def | 16 +++++++++++ server/request.h | 12 ++++++++ server/trace.c | 23 +++++++++++++++ server/window.c | 21 ++++++++++++++ 7 files changed, 140 insertions(+), 28 deletions(-)
diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index b35618d80c2..3d7aad89338 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -630,8 +630,9 @@ static const WCHAR real_class_id_str[][MAX_ATOM_LEN + 1] = { INT WINAPI NtUserGetClassName( HWND hwnd, BOOL real, UNICODE_STRING *name ) { const WCHAR *basename = NULL; - CLASS *class; + DWORD real_class_id = 0; int ret = 0; + WND *wnd;
TRACE( "%p %x %p\n", hwnd, real, name );
@@ -641,49 +642,48 @@ INT WINAPI NtUserGetClassName( HWND hwnd, BOOL real, UNICODE_STRING *name ) return 0; }
- if (!(class = get_class_ptr( hwnd, FALSE ))) return 0; + if (!(wnd = get_win_ptr( hwnd ))) + { + RtlSetLastWin32Error( ERROR_INVALID_WINDOW_HANDLE ); + return 0; + }
- if (class == OBJ_OTHER_PROCESS) + if (wnd == WND_OTHER_PROCESS || wnd == WND_DESKTOP) { ATOM atom = 0;
- SERVER_START_REQ( set_class_info ) + SERVER_START_REQ( get_window_class_name ) { - req->window = wine_server_user_handle( hwnd ); - req->flags = 0; - req->extra_offset = -1; - req->extra_size = 0; + req->handle = wine_server_user_handle( hwnd ); if (!wine_server_call_err( req )) + { + real_class_id = reply->real_class_id; atom = reply->base_atom; + } } SERVER_END_REQ;
- return NtUserGetAtomName( atom, name ); + if (!real || (real && !real_class_id)) return NtUserGetAtomName( atom, name ); + wnd = NULL; } + else + real_class_id = wnd->real_class_id;
- if (real) + if (real && real_class_id) { - WND *wnd; - - if (!(wnd = get_win_ptr( hwnd ))) - { - RtlSetLastWin32Error( ERROR_INVALID_WINDOW_HANDLE ); - goto exit; - } - - if (wnd->real_class_id) - basename = real_class_id_str[wnd->real_class_id - 1]; - release_win_ptr(wnd); + assert(real_class_id <= ARRAY_SIZE(real_class_id_str)); + basename = real_class_id_str[real_class_id - 1]; + } + else + { + assert(wnd); + basename = (const WCHAR *)wnd->class->basename; } - - if (!basename) - basename = (const WCHAR *)class->basename;
ret = min( name->MaximumLength / sizeof(WCHAR) - 1, lstrlenW(basename) ); if (ret) memcpy( name->Buffer, basename, ret * sizeof(WCHAR) ); name->Buffer[ret] = 0; -exit: - release_class_ptr( class ); + if (wnd) release_win_ptr( wnd ); return ret; }
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index ae9a24125e5..c705be93c0d 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -4503,7 +4503,13 @@ static BOOL set_real_window_class_id( HWND hwnd, DWORD param )
if (!win->real_class_id) { - FIXME("Real class ID currently set in-process only.\n"); + SERVER_START_REQ( set_real_window_class_id ) + { + req->handle = wine_server_user_handle( hwnd ); + req->real_class_id = param; + wine_server_call( req ); + } + SERVER_END_REQ; win->real_class_id = param; } release_win_ptr( win ); diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index a392b532f4e..4fe1d20352b 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -5377,6 +5377,34 @@ struct set_window_layered_info_reply
+struct get_window_class_name_request +{ + struct request_header __header; + user_handle_t handle; +}; +struct get_window_class_name_reply +{ + struct reply_header __header; + atom_t base_atom; + unsigned int real_class_id; +}; + + + +struct set_real_window_class_id_request +{ + struct request_header __header; + user_handle_t handle; + unsigned int real_class_id; + char __pad_20[4]; +}; +struct set_real_window_class_id_reply +{ + struct reply_header __header; +}; + + + struct alloc_user_handle_request { struct request_header __header; @@ -5903,6 +5931,8 @@ enum request REQ_set_fd_eof_info, REQ_get_window_layered_info, REQ_set_window_layered_info, + REQ_get_window_class_name, + REQ_set_real_window_class_id, REQ_alloc_user_handle, REQ_free_user_handle, REQ_set_cursor, @@ -6194,6 +6224,8 @@ union generic_request struct set_fd_eof_info_request set_fd_eof_info_request; struct get_window_layered_info_request get_window_layered_info_request; struct set_window_layered_info_request set_window_layered_info_request; + struct get_window_class_name_request get_window_class_name_request; + struct set_real_window_class_id_request set_real_window_class_id_request; struct alloc_user_handle_request alloc_user_handle_request; struct free_user_handle_request free_user_handle_request; struct set_cursor_request set_cursor_request; @@ -6483,6 +6515,8 @@ union generic_reply struct set_fd_eof_info_reply set_fd_eof_info_reply; struct get_window_layered_info_reply get_window_layered_info_reply; struct set_window_layered_info_reply set_window_layered_info_reply; + struct get_window_class_name_reply get_window_class_name_reply; + struct set_real_window_class_id_reply set_real_window_class_id_reply; struct alloc_user_handle_reply alloc_user_handle_reply; struct free_user_handle_reply free_user_handle_reply; struct set_cursor_reply set_cursor_reply; @@ -6504,7 +6538,7 @@ union generic_reply
/* ### protocol_version begin ### */
-#define SERVER_PROTOCOL_VERSION 784 +#define SERVER_PROTOCOL_VERSION 785
/* ### protocol_version end ### */
diff --git a/server/protocol.def b/server/protocol.def index e9195df6b65..6654f0ba7aa 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3733,6 +3733,22 @@ struct handle_info @END
+/* Get class name atom/real class ID for a window. */ +@REQ(get_window_class_name) + user_handle_t handle; /* handle to the window */ +@REPLY + atom_t base_atom; /* Base class atom. */ + unsigned int real_class_id; /* Real window class ID value. */ +@END + + +/* Set real window class ID value for a window. */ +@REQ(set_real_window_class_id) + user_handle_t handle; /* handle to the window */ + unsigned int real_class_id; /* Real window class ID value. */ +@END + + /* Allocate an arbitrary user handle */ @REQ(alloc_user_handle) @REPLY diff --git a/server/request.h b/server/request.h index d6043c5fdc3..042268c16ea 100644 --- a/server/request.h +++ b/server/request.h @@ -386,6 +386,8 @@ DECL_HANDLER(set_fd_name_info); DECL_HANDLER(set_fd_eof_info); DECL_HANDLER(get_window_layered_info); DECL_HANDLER(set_window_layered_info); +DECL_HANDLER(get_window_class_name); +DECL_HANDLER(set_real_window_class_id); DECL_HANDLER(alloc_user_handle); DECL_HANDLER(free_user_handle); DECL_HANDLER(set_cursor); @@ -676,6 +678,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_set_fd_eof_info, (req_handler)req_get_window_layered_info, (req_handler)req_set_window_layered_info, + (req_handler)req_get_window_class_name, + (req_handler)req_set_real_window_class_id, (req_handler)req_alloc_user_handle, (req_handler)req_free_user_handle, (req_handler)req_set_cursor, @@ -2263,6 +2267,14 @@ C_ASSERT( FIELD_OFFSET(struct set_window_layered_info_request, color_key) == 16 C_ASSERT( FIELD_OFFSET(struct set_window_layered_info_request, alpha) == 20 ); C_ASSERT( FIELD_OFFSET(struct set_window_layered_info_request, flags) == 24 ); C_ASSERT( sizeof(struct set_window_layered_info_request) == 32 ); +C_ASSERT( FIELD_OFFSET(struct get_window_class_name_request, handle) == 12 ); +C_ASSERT( sizeof(struct get_window_class_name_request) == 16 ); +C_ASSERT( FIELD_OFFSET(struct get_window_class_name_reply, base_atom) == 8 ); +C_ASSERT( FIELD_OFFSET(struct get_window_class_name_reply, real_class_id) == 12 ); +C_ASSERT( sizeof(struct get_window_class_name_reply) == 16 ); +C_ASSERT( FIELD_OFFSET(struct set_real_window_class_id_request, handle) == 12 ); +C_ASSERT( FIELD_OFFSET(struct set_real_window_class_id_request, real_class_id) == 16 ); +C_ASSERT( sizeof(struct set_real_window_class_id_request) == 24 ); C_ASSERT( sizeof(struct alloc_user_handle_request) == 16 ); C_ASSERT( FIELD_OFFSET(struct alloc_user_handle_reply, handle) == 8 ); C_ASSERT( sizeof(struct alloc_user_handle_reply) == 16 ); diff --git a/server/trace.c b/server/trace.c index 55ccefa1746..9c7cb003bcc 100644 --- a/server/trace.c +++ b/server/trace.c @@ -4452,6 +4452,23 @@ static void dump_set_window_layered_info_request( const struct set_window_layere fprintf( stderr, ", flags=%08x", req->flags ); }
+static void dump_get_window_class_name_request( const struct get_window_class_name_request *req ) +{ + fprintf( stderr, " handle=%08x", req->handle ); +} + +static void dump_get_window_class_name_reply( const struct get_window_class_name_reply *req ) +{ + fprintf( stderr, " base_atom=%04x", req->base_atom ); + fprintf( stderr, ", real_class_id=%08x", req->real_class_id ); +} + +static void dump_set_real_window_class_id_request( const struct set_real_window_class_id_request *req ) +{ + fprintf( stderr, " handle=%08x", req->handle ); + fprintf( stderr, ", real_class_id=%08x", req->real_class_id ); +} + static void dump_alloc_user_handle_request( const struct alloc_user_handle_request *req ) { } @@ -4874,6 +4891,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_set_fd_eof_info_request, (dump_func)dump_get_window_layered_info_request, (dump_func)dump_set_window_layered_info_request, + (dump_func)dump_get_window_class_name_request, + (dump_func)dump_set_real_window_class_id_request, (dump_func)dump_alloc_user_handle_request, (dump_func)dump_free_user_handle_request, (dump_func)dump_set_cursor_request, @@ -5161,6 +5180,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { NULL, (dump_func)dump_get_window_layered_info_reply, NULL, + (dump_func)dump_get_window_class_name_reply, + NULL, (dump_func)dump_alloc_user_handle_reply, NULL, (dump_func)dump_set_cursor_reply, @@ -5448,6 +5469,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "set_fd_eof_info", "get_window_layered_info", "set_window_layered_info", + "get_window_class_name", + "set_real_window_class_id", "alloc_user_handle", "free_user_handle", "set_cursor", diff --git a/server/window.c b/server/window.c index 242e93f303a..62e1086a90c 100644 --- a/server/window.c +++ b/server/window.c @@ -92,6 +92,7 @@ struct window int prop_inuse; /* number of in-use window properties */ int prop_alloc; /* number of allocated window properties */ struct property *properties; /* window properties array */ + unsigned int real_class_id; /* Real window class ID. */ int nb_extra_bytes; /* number of extra bytes */ char *extra_bytes; /* extra bytes storage */ }; @@ -582,6 +583,7 @@ static struct window *create_window( struct window *parent, struct window *owner win->prop_inuse = 0; win->prop_alloc = 0; win->properties = NULL; + win->real_class_id = 0; win->nb_extra_bytes = 0; win->extra_bytes = NULL; win->window_rect = win->visible_rect = win->surface_rect = win->client_rect = empty_rect; @@ -3010,3 +3012,22 @@ DECL_HANDLER(set_window_layered_info) } else set_win32_error( ERROR_INVALID_WINDOW_HANDLE ); } + +/* Get class name atom/real class ID for a window. */ +DECL_HANDLER(get_window_class_name) +{ + struct window *win = get_window( req->handle ); + + if (!win) return; + reply->base_atom = get_class_atom(win->class); + reply->real_class_id = win->real_class_id; +} + +/* Set real window class ID value for a window. */ +DECL_HANDLER(set_real_window_class_id) +{ + struct window *win = get_window( req->handle ); + + if (!win) return; + win->real_class_id = req->real_class_id; +}