diff --git a/dlls/user32/win.c b/dlls/user32/win.c index 850f0ba5e47..7c128252719 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -461,18 +461,23 @@ static void update_window_state( HWND hwnd ) * * Retrieve the window text from the server. */ -static void get_server_window_text( HWND hwnd, LPWSTR text, INT count ) +static data_size_t get_server_window_text( HWND hwnd, WCHAR *text, data_size_t count ) { - size_t len = 0; + data_size_t len = 0, needed = 0; SERVER_START_REQ( get_window_text ) { req->handle = wine_server_user_handle( hwnd ); - wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) ); - if (!wine_server_call_err( req )) len = wine_server_reply_size(reply); + if (count) wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) ); + if (!wine_server_call_err( req )) + { + needed = reply->length; + len = wine_server_reply_size(reply); + } } SERVER_END_REQ; - text[len / sizeof(WCHAR)] = 0; + if (text) text[len / sizeof(WCHAR)] = 0; + return needed; } @@ -2875,7 +2880,13 @@ BOOL WINAPI DECLSPEC_HOTPATCH SetWindowTextW( HWND hwnd, LPCWSTR lpString ) */ INT WINAPI GetWindowTextLengthA( HWND hwnd ) { - return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 ); + CPINFO info; + + if (WIN_IsCurrentProcess( hwnd )) return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 ); + + /* when window belongs to other process, don't send a message */ + GetCPInfo( CP_ACP, &info ); + return get_server_window_text( hwnd, NULL, 0 ) * info.MaxCharSize; } /******************************************************************* @@ -2883,7 +2894,10 @@ INT WINAPI GetWindowTextLengthA( HWND hwnd ) */ INT WINAPI GetWindowTextLengthW( HWND hwnd ) { - return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 ); + if (WIN_IsCurrentProcess( hwnd )) return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 ); + + /* when window belongs to other process, don't send a message */ + return get_server_window_text( hwnd, NULL, 0 ); } diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 6aee918145e..564ae921a0c 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -3703,7 +3703,9 @@ struct get_window_text_request struct get_window_text_reply { struct reply_header __header; + data_size_t length; /* VARARG(text,unicode_str); */ + char __pad_12[4]; }; @@ -6509,6 +6511,6 @@ union generic_reply struct terminate_job_reply terminate_job_reply; }; -#define SERVER_PROTOCOL_VERSION 551 +#define SERVER_PROTOCOL_VERSION 552 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index 1673ae38d9f..9fb155bd124 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2659,6 +2659,7 @@ enum coords_relative @REQ(get_window_text) user_handle_t handle; /* handle to the window */ @REPLY + data_size_t length; /* total length in WCHARs */ VARARG(text,unicode_str); /* window text */ @END diff --git a/server/request.h b/server/request.h index f69ff16a99f..3e6183b018c 100644 --- a/server/request.h +++ b/server/request.h @@ -1772,7 +1772,8 @@ C_ASSERT( FIELD_OFFSET(struct get_window_rectangles_reply, client) == 40 ); C_ASSERT( sizeof(struct get_window_rectangles_reply) == 56 ); C_ASSERT( FIELD_OFFSET(struct get_window_text_request, handle) == 12 ); C_ASSERT( sizeof(struct get_window_text_request) == 16 ); -C_ASSERT( sizeof(struct get_window_text_reply) == 8 ); +C_ASSERT( FIELD_OFFSET(struct get_window_text_reply, length) == 8 ); +C_ASSERT( sizeof(struct get_window_text_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct set_window_text_request, handle) == 12 ); C_ASSERT( sizeof(struct set_window_text_request) == 16 ); C_ASSERT( FIELD_OFFSET(struct get_windows_offset_request, from) == 12 ); diff --git a/server/trace.c b/server/trace.c index ac15ba9bf70..44004adb53c 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3233,7 +3233,8 @@ static void dump_get_window_text_request( const struct get_window_text_request * static void dump_get_window_text_reply( const struct get_window_text_reply *req ) { - dump_varargs_unicode_str( " text=", cur_size ); + fprintf( stderr, " length=%u", req->length ); + dump_varargs_unicode_str( ", text=", cur_size ); } static void dump_set_window_text_request( const struct set_window_text_request *req ) diff --git a/server/window.c b/server/window.c index 9560f934879..4a1a27877db 100644 --- a/server/window.c +++ b/server/window.c @@ -2398,9 +2398,8 @@ DECL_HANDLER(get_window_text) if (win && win->text) { - data_size_t len = strlenW( win->text ) * sizeof(WCHAR); - if (len > get_reply_max_size()) len = get_reply_max_size(); - set_reply_data( win->text, len ); + reply->length = strlenW( win->text ); + set_reply_data( win->text, min( reply->length * sizeof(WCHAR), get_reply_max_size() )); } }