Store the window caption text in the server.
Maintain a paint count separately for each window.
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 41dba2e..b83ca78 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -1325,15 +1325,6 @@
-struct inc_queue_paint_count_request
-{
- struct request_header __header;
- void* id;
- int incr;
-};
-
-
-
struct set_queue_mask_request
{
struct request_header __header;
@@ -1721,6 +1712,33 @@
+struct get_window_text_request
+{
+ struct request_header __header;
+ user_handle_t handle;
+ /* VARARG(text,unicode_str); */
+};
+
+
+
+struct set_window_text_request
+{
+ struct request_header __header;
+ user_handle_t handle;
+ /* VARARG(text,unicode_str); */
+};
+
+
+
+struct inc_window_paint_count_request
+{
+ struct request_header __header;
+ user_handle_t handle;
+ int incr;
+};
+
+
+
struct get_windows_offset_request
{
struct request_header __header;
@@ -1875,7 +1893,6 @@
REQ_get_atom_name,
REQ_init_atom_table,
REQ_get_msg_queue,
- REQ_inc_queue_paint_count,
REQ_set_queue_mask,
REQ_get_queue_status,
REQ_wait_input_idle,
@@ -1906,6 +1923,9 @@
REQ_get_window_tree,
REQ_set_window_rectangles,
REQ_get_window_rectangles,
+ REQ_get_window_text,
+ REQ_set_window_text,
+ REQ_inc_window_paint_count,
REQ_get_windows_offset,
REQ_set_window_property,
REQ_remove_window_property,
@@ -2020,7 +2040,6 @@
struct get_atom_name_request get_atom_name;
struct init_atom_table_request init_atom_table;
struct get_msg_queue_request get_msg_queue;
- struct inc_queue_paint_count_request inc_queue_paint_count;
struct set_queue_mask_request set_queue_mask;
struct get_queue_status_request get_queue_status;
struct wait_input_idle_request wait_input_idle;
@@ -2051,6 +2070,9 @@
struct get_window_tree_request get_window_tree;
struct set_window_rectangles_request set_window_rectangles;
struct get_window_rectangles_request get_window_rectangles;
+ struct get_window_text_request get_window_text;
+ struct set_window_text_request set_window_text;
+ struct inc_window_paint_count_request inc_window_paint_count;
struct get_windows_offset_request get_windows_offset;
struct set_window_property_request set_window_property;
struct remove_window_property_request remove_window_property;
@@ -2058,6 +2080,6 @@
struct get_window_properties_request get_window_properties;
};
-#define SERVER_PROTOCOL_VERSION 63
+#define SERVER_PROTOCOL_VERSION 64
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/protocol.def b/server/protocol.def
index 5e6c8a0..e44ef52 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1188,13 +1188,6 @@
@END
-/* Increment the message queue paint count */
-@REQ(inc_queue_paint_count)
- void* id; /* thread id */
- int incr; /* increment (can be negative) */
-@END
-
-
/* Set the current message queue wakeup mask */
@REQ(set_queue_mask)
unsigned int wake_mask; /* wakeup bits mask */
@@ -1542,6 +1535,28 @@
@END
+/* Get the window text */
+@REQ(get_window_text)
+ user_handle_t handle; /* handle to the window */
+@REPLY
+ VARARG(text,unicode_str); /* window text */
+@END
+
+
+/* Set the window text */
+@REQ(set_window_text)
+ user_handle_t handle; /* handle to the window */
+ VARARG(text,unicode_str); /* window text */
+@END
+
+
+/* Increment the window paint count */
+@REQ(inc_window_paint_count)
+ user_handle_t handle; /* handle to the window */
+ int incr; /* increment (can be negative) */
+@END
+
+
/* Get the coordinates offset between two windows */
@REQ(get_windows_offset)
user_handle_t from; /* handle to the first window */
diff --git a/server/queue.c b/server/queue.c
index c1c0e78..76da322 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -175,7 +175,7 @@
}
/* get the current thread queue, creating it if needed */
-inline struct msg_queue *get_current_queue(void)
+inline static struct msg_queue *get_current_queue(void)
{
struct msg_queue *queue = current->queue;
if (!queue) queue = create_msg_queue( current );
@@ -598,6 +598,23 @@
return timer;
}
+
+/* increment (or decrement if 'incr' is negative) the queue paint count */
+void inc_queue_paint_count( struct thread *thread, int incr )
+{
+ struct msg_queue *queue = thread->queue;
+
+ assert( queue );
+
+ if ((queue->paint_count += incr) < 0) queue->paint_count = 0;
+
+ if (queue->paint_count)
+ set_queue_bits( queue, QS_PAINT );
+ else
+ clear_queue_bits( queue, QS_PAINT );
+}
+
+
/* remove all messages and timers belonging to a certain window */
void queue_cleanup_window( struct thread *thread, user_handle_t win )
{
@@ -644,30 +661,6 @@
}
-/* increment the message queue paint count */
-DECL_HANDLER(inc_queue_paint_count)
-{
- struct msg_queue *queue;
- struct thread *thread = get_thread_from_id( req->id );
-
- if (!thread) return;
-
- if ((queue = thread->queue))
- {
- if ((queue->paint_count += req->incr) < 0) queue->paint_count = 0;
-
- if (queue->paint_count)
- set_queue_bits( queue, QS_PAINT );
- else
- clear_queue_bits( queue, QS_PAINT );
- }
- else set_error( STATUS_INVALID_PARAMETER );
-
- release_object( thread );
-
-}
-
-
/* set the current message queue wakeup mask */
DECL_HANDLER(set_queue_mask)
{
diff --git a/server/request.h b/server/request.h
index 2d1204f..87c224e 100644
--- a/server/request.h
+++ b/server/request.h
@@ -168,7 +168,6 @@
DECL_HANDLER(get_atom_name);
DECL_HANDLER(init_atom_table);
DECL_HANDLER(get_msg_queue);
-DECL_HANDLER(inc_queue_paint_count);
DECL_HANDLER(set_queue_mask);
DECL_HANDLER(get_queue_status);
DECL_HANDLER(wait_input_idle);
@@ -199,6 +198,9 @@
DECL_HANDLER(get_window_tree);
DECL_HANDLER(set_window_rectangles);
DECL_HANDLER(get_window_rectangles);
+DECL_HANDLER(get_window_text);
+DECL_HANDLER(set_window_text);
+DECL_HANDLER(inc_window_paint_count);
DECL_HANDLER(get_windows_offset);
DECL_HANDLER(set_window_property);
DECL_HANDLER(remove_window_property);
@@ -312,7 +314,6 @@
(req_handler)req_get_atom_name,
(req_handler)req_init_atom_table,
(req_handler)req_get_msg_queue,
- (req_handler)req_inc_queue_paint_count,
(req_handler)req_set_queue_mask,
(req_handler)req_get_queue_status,
(req_handler)req_wait_input_idle,
@@ -343,6 +344,9 @@
(req_handler)req_get_window_tree,
(req_handler)req_set_window_rectangles,
(req_handler)req_get_window_rectangles,
+ (req_handler)req_get_window_text,
+ (req_handler)req_set_window_text,
+ (req_handler)req_inc_window_paint_count,
(req_handler)req_get_windows_offset,
(req_handler)req_set_window_property,
(req_handler)req_remove_window_property,
diff --git a/server/trace.c b/server/trace.c
index 012286b..5deb7ee 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1456,12 +1456,6 @@
fprintf( stderr, " handle=%d", req->handle );
}
-static void dump_inc_queue_paint_count_request( const struct inc_queue_paint_count_request *req )
-{
- fprintf( stderr, " id=%p,", req->id );
- fprintf( stderr, " incr=%d", req->incr );
-}
-
static void dump_set_queue_mask_request( const struct set_queue_mask_request *req )
{
fprintf( stderr, " wake_mask=%08x,", req->wake_mask );
@@ -1832,6 +1826,30 @@
dump_rectangle( req, &req->client );
}
+static void dump_get_window_text_request( const struct get_window_text_request *req )
+{
+ fprintf( stderr, " handle=%08x", req->handle );
+}
+
+static void dump_get_window_text_reply( const struct get_window_text_request *req )
+{
+ fprintf( stderr, " text=" );
+ cur_pos += dump_varargs_unicode_str( req );
+}
+
+static void dump_set_window_text_request( const struct set_window_text_request *req )
+{
+ fprintf( stderr, " handle=%08x,", req->handle );
+ fprintf( stderr, " text=" );
+ cur_pos += dump_varargs_unicode_str( req );
+}
+
+static void dump_inc_window_paint_count_request( const struct inc_window_paint_count_request *req )
+{
+ fprintf( stderr, " handle=%08x,", req->handle );
+ fprintf( stderr, " incr=%d", req->incr );
+}
+
static void dump_get_windows_offset_request( const struct get_windows_offset_request *req )
{
fprintf( stderr, " from=%08x,", req->from );
@@ -1988,7 +2006,6 @@
(dump_func)dump_get_atom_name_request,
(dump_func)dump_init_atom_table_request,
(dump_func)dump_get_msg_queue_request,
- (dump_func)dump_inc_queue_paint_count_request,
(dump_func)dump_set_queue_mask_request,
(dump_func)dump_get_queue_status_request,
(dump_func)dump_wait_input_idle_request,
@@ -2019,6 +2036,9 @@
(dump_func)dump_get_window_tree_request,
(dump_func)dump_set_window_rectangles_request,
(dump_func)dump_get_window_rectangles_request,
+ (dump_func)dump_get_window_text_request,
+ (dump_func)dump_set_window_text_request,
+ (dump_func)dump_inc_window_paint_count_request,
(dump_func)dump_get_windows_offset_request,
(dump_func)dump_set_window_property_request,
(dump_func)dump_remove_window_property_request,
@@ -2129,7 +2149,6 @@
(dump_func)dump_get_atom_name_reply,
(dump_func)0,
(dump_func)dump_get_msg_queue_reply,
- (dump_func)0,
(dump_func)dump_set_queue_mask_reply,
(dump_func)dump_get_queue_status_reply,
(dump_func)dump_wait_input_idle_reply,
@@ -2160,6 +2179,9 @@
(dump_func)dump_get_window_tree_reply,
(dump_func)0,
(dump_func)dump_get_window_rectangles_reply,
+ (dump_func)dump_get_window_text_reply,
+ (dump_func)0,
+ (dump_func)0,
(dump_func)dump_get_windows_offset_reply,
(dump_func)0,
(dump_func)dump_remove_window_property_reply,
@@ -2270,7 +2292,6 @@
"get_atom_name",
"init_atom_table",
"get_msg_queue",
- "inc_queue_paint_count",
"set_queue_mask",
"get_queue_status",
"wait_input_idle",
@@ -2301,6 +2322,9 @@
"get_window_tree",
"set_window_rectangles",
"get_window_rectangles",
+ "get_window_text",
+ "set_window_text",
+ "inc_window_paint_count",
"get_windows_offset",
"set_window_property",
"remove_window_property",
diff --git a/server/unicode.h b/server/unicode.h
index dc8f99f..c6b600d 100644
--- a/server/unicode.h
+++ b/server/unicode.h
@@ -7,6 +7,8 @@
#ifndef __WINE_SERVER_UNICODE_H
#define __WINE_SERVER_UNICODE_H
+#include <stdio.h>
+
#include "windef.h"
#include "wine/unicode.h"
#include "object.h"
diff --git a/server/user.h b/server/user.h
index d53cc53..5c6c4ce 100644
--- a/server/user.h
+++ b/server/user.h
@@ -11,6 +11,7 @@
struct thread;
struct window;
+struct msg_queue;
enum user_object
{
@@ -28,6 +29,7 @@
/* queue functions */
+extern void inc_queue_paint_count( struct thread *thread, int incr );
extern void queue_cleanup_window( struct thread *thread, user_handle_t win );
/* window functions */
diff --git a/server/window.c b/server/window.c
index 701c9e8..430e7c5 100644
--- a/server/window.c
+++ b/server/window.c
@@ -11,6 +11,7 @@
#include "thread.h"
#include "process.h"
#include "user.h"
+#include "unicode.h"
/* a window property */
struct property
@@ -47,6 +48,8 @@
unsigned int id; /* window id */
void* instance; /* creator instance */
void* user_data; /* user-specific data */
+ WCHAR *text; /* window caption text */
+ int paint_count; /* count of pending paints for this window */
int prop_inuse; /* number of in-use window properties */
int prop_alloc; /* number of allocated window properties */
struct property *properties; /* window properties array */
@@ -244,10 +247,12 @@
if (ptr->owner == win) ptr->owner = NULL;
}
- if (win->thread->queue) queue_cleanup_window( win->thread, win->handle );
+ if (win->paint_count) inc_queue_paint_count( win->thread, -win->paint_count );
+ queue_cleanup_window( win->thread, win->handle );
free_user_handle( win->handle );
destroy_properties( win );
unlink_window( win );
+ if (win->text) free( win->text );
memset( win, 0x55, sizeof(*win) );
free( win );
}
@@ -275,6 +280,8 @@
win->id = 0;
win->instance = NULL;
win->user_data = NULL;
+ win->text = NULL;
+ win->paint_count = 0;
win->prop_inuse = 0;
win->prop_alloc = 0;
win->properties = NULL;
@@ -563,6 +570,57 @@
}
+/* get the window text */
+DECL_HANDLER(get_window_text)
+{
+ struct window *win = get_window( req->handle );
+ size_t len = 0;
+
+ if (win && win->text)
+ {
+ len = strlenW( win->text ) * sizeof(WCHAR);
+ if (len > get_req_data_size(req)) len = get_req_data_size(req);
+ memcpy( get_req_data(req), win->text, len );
+ }
+ set_req_data_size( req, len );
+}
+
+
+/* set the window text */
+DECL_HANDLER(set_window_text)
+{
+ struct window *win = get_window( req->handle );
+
+ if (win)
+ {
+ WCHAR *text = NULL;
+ size_t len = get_req_data_size(req) / sizeof(WCHAR);
+ if (len)
+ {
+ if (!(text = mem_alloc( (len+1) * sizeof(WCHAR) ))) return;
+ memcpy( text, get_req_data(req), len * sizeof(WCHAR) );
+ text[len] = 0;
+ }
+ if (win->text) free( win->text );
+ win->text = text;
+ }
+}
+
+
+/* increment the window paint count */
+DECL_HANDLER(inc_window_paint_count)
+{
+ struct window *win = get_window( req->handle );
+
+ if (win)
+ {
+ int old = win->paint_count;
+ if ((win->paint_count += req->incr) < 0) win->paint_count = 0;
+ inc_queue_paint_count( win->thread, win->paint_count - old );
+ }
+}
+
+
/* get the coordinates offset between two windows */
DECL_HANDLER(get_windows_offset)
{
diff --git a/windows/defwnd.c b/windows/defwnd.c
index af998c9..b12c756 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -19,6 +19,7 @@
#include "winnls.h"
#include "wine/unicode.h"
#include "wine/winuser16.h"
+#include "wine/server.h"
#include "imm.h"
DEFAULT_DEBUG_CHANNEL(win);
@@ -71,13 +72,23 @@
if (!text) text = "";
count = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 );
- if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
- if (wndPtr->text) HeapFree(GetProcessHeap(), 0, wndPtr->text);
- if ((wndPtr->text = textW = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR))))
- MultiByteToWideChar( CP_ACP, 0, text, -1, wndPtr->text, count );
+ if (!(wndPtr = WIN_GetPtr( hwnd ))) return;
+ if ((textW = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR))))
+ {
+ if (wndPtr->text) HeapFree(GetProcessHeap(), 0, wndPtr->text);
+ wndPtr->text = textW;
+ MultiByteToWideChar( CP_ACP, 0, text, -1, textW, count );
+ SERVER_START_VAR_REQ( set_window_text, (count-1) * sizeof(WCHAR) )
+ {
+ req->handle = hwnd;
+ memcpy( server_data_ptr(req), textW, (count-1) * sizeof(WCHAR) );
+ SERVER_CALL();
+ }
+ SERVER_END_VAR_REQ;
+ }
else
ERR("Not enough memory for window text\n");
- WIN_ReleaseWndPtr( wndPtr );
+ WIN_ReleasePtr( wndPtr );
if (USER_Driver.pSetWindowText) USER_Driver.pSetWindowText( hwnd, textW );
}
@@ -99,7 +110,16 @@
if (!(wndPtr = WIN_GetPtr( hwnd ))) return;
if (wndPtr->text) HeapFree(GetProcessHeap(), 0, wndPtr->text);
if ((wndPtr->text = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR))))
- strcpyW( wndPtr->text, text );
+ {
+ strcpyW( wndPtr->text, text );
+ SERVER_START_VAR_REQ( set_window_text, (count-1) * sizeof(WCHAR) )
+ {
+ req->handle = hwnd;
+ memcpy( server_data_ptr(req), wndPtr->text, (count-1) * sizeof(WCHAR) );
+ SERVER_CALL();
+ }
+ SERVER_END_VAR_REQ;
+ }
else
ERR("Not enough memory for window text\n");
text = wndPtr->text;
diff --git a/windows/painting.c b/windows/painting.c
index 450d8af..fa579eb 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -50,10 +50,10 @@
*/
static void add_paint_count( HWND hwnd, int incr )
{
- SERVER_START_REQ( inc_queue_paint_count )
+ SERVER_START_REQ( inc_window_paint_count )
{
- req->id = (void *)GetWindowThreadProcessId( hwnd, NULL );
- req->incr = incr;
+ req->handle = hwnd;
+ req->incr = incr;
SERVER_CALL();
}
SERVER_END_REQ;
diff --git a/windows/win.c b/windows/win.c
index 469416e..e92f0bb 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -187,6 +187,30 @@
}
+/*******************************************************************
+ * get_server_window_text
+ *
+ * Retrieve the window text from the server.
+ */
+static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
+{
+ size_t len = (count - 1) * sizeof(WCHAR);
+ len = min( len, REQUEST_MAX_VAR_SIZE );
+ SERVER_START_VAR_REQ( get_window_text, len )
+ {
+ req->handle = hwnd;
+ if (!SERVER_CALL_ERR())
+ {
+ len = server_data_size(req);
+ memcpy( text, server_data_ptr(req), len );
+ }
+ else len = 0;
+ }
+ SERVER_END_VAR_REQ;
+ text[len / sizeof(WCHAR)] = 0;
+}
+
+
/***********************************************************************
* WIN_GetPtr
*
@@ -2240,20 +2264,41 @@
*/
INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
{
- return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
- (LPARAM)lpString );
+ WCHAR *buffer;
+
+ if (WIN_IsCurrentProcess( hwnd ))
+ return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
+
+ /* when window belongs to other process, don't send a message */
+ if (nMaxCount <= 0) return 0;
+ if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
+ get_server_window_text( hwnd, buffer, nMaxCount );
+ if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
+ lpString[nMaxCount-1] = 0;
+ HeapFree( GetProcessHeap(), 0, buffer );
+ return strlen(lpString);
}
+
/*******************************************************************
* InternalGetWindowText (USER32.@)
*/
INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
{
- WND *win = WIN_FindWndPtr( hwnd );
- if (!win) return 0;
- if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
- else lpString[0] = 0;
- WIN_ReleaseWndPtr( win );
+ WND *win;
+
+ if (nMaxCount <= 0) return 0;
+ if (!(win = WIN_GetPtr( hwnd ))) return 0;
+ if (win != WND_OTHER_PROCESS)
+ {
+ if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
+ else lpString[0] = 0;
+ WIN_ReleasePtr( win );
+ }
+ else
+ {
+ get_server_window_text( hwnd, lpString, nMaxCount );
+ }
return strlenW(lpString);
}
@@ -2263,8 +2308,13 @@
*/
INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
{
- return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
- (LPARAM)lpString );
+ if (WIN_IsCurrentProcess( hwnd ))
+ return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
+
+ /* when window belongs to other process, don't send a message */
+ if (nMaxCount <= 0) return 0;
+ get_server_window_text( hwnd, lpString, nMaxCount );
+ return strlenW(lpString);
}
@@ -2274,6 +2324,12 @@
*/
BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
{
+ if (!WIN_IsCurrentProcess( hwnd ))
+ {
+ FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
+ SetLastError( ERROR_ACCESS_DENIED );
+ return FALSE;
+ }
return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
}
@@ -2283,6 +2339,12 @@
*/
BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
{
+ if (!WIN_IsCurrentProcess( hwnd ))
+ {
+ FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
+ SetLastError( ERROR_ACCESS_DENIED );
+ return FALSE;
+ }
return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
}