From 7258793169e34a1efc239f01b6e99b1d338a8b6f Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 22 Aug 2016 15:31:21 +0900 Subject: [PATCH] server: Add separate requests for opening and closing the clipboard. Signed-off-by: Alexandre Julliard --- dlls/user32/clipboard.c | 43 +++++++------------ include/wine/server_protocol.h | 40 +++++++++++++++--- server/clipboard.c | 76 +++++++++++++++++++--------------- server/protocol.def | 21 ++++++++-- server/request.h | 21 +++++++--- server/trace.c | 29 ++++++++++++- 6 files changed, 153 insertions(+), 77 deletions(-) diff --git a/dlls/user32/clipboard.c b/dlls/user32/clipboard.c index 47647845ee1..915c370ea62 100644 --- a/dlls/user32/clipboard.c +++ b/dlls/user32/clipboard.c @@ -172,33 +172,24 @@ INT WINAPI GetClipboardFormatNameA(UINT wFormat, LPSTR retStr, INT maxlen) /************************************************************************** * OpenClipboard (USER32.@) - * - * Note: Netscape uses NULL hWnd to open the clipboard. */ -BOOL WINAPI OpenClipboard( HWND hWnd ) +BOOL WINAPI OpenClipboard( HWND hwnd ) { - BOOL bRet; - UINT flags; + BOOL ret; - TRACE("(%p)...\n", hWnd); + TRACE( "%p\n", hwnd ); - SERVER_START_REQ( set_clipboard_info ) + SERVER_START_REQ( open_clipboard ) { - req->flags = SET_CB_OPEN; - req->clipboard = wine_server_user_handle( hWnd ); - if ((bRet = !wine_server_call( req ))) - flags = reply->flags; + req->window = wine_server_user_handle( hwnd ); + if ((ret = !wine_server_call( req ))) + { + if (!reply->owner) bCBHasChanged = FALSE; + } } SERVER_END_REQ; - if (bRet && !(flags & CB_PROCESS)) - { - bCBHasChanged = FALSE; - } - - TRACE(" returning %i\n", bRet); - - return bRet; + return ret; } @@ -208,26 +199,24 @@ BOOL WINAPI OpenClipboard( HWND hWnd ) BOOL WINAPI CloseClipboard(void) { HWND viewer = 0; - UINT flags; - BOOL ret; + BOOL ret, owner = FALSE; TRACE("() Changed=%d\n", bCBHasChanged); - SERVER_START_REQ( set_clipboard_info ) + SERVER_START_REQ( close_clipboard ) { - req->flags = SET_CB_CLOSE; - if (bCBHasChanged) req->flags |= SET_CB_SEQNO; + req->changed = bCBHasChanged; if ((ret = !wine_server_call_err( req ))) { - viewer = wine_server_ptr_handle( reply->old_viewer ); - flags = reply->flags; + viewer = wine_server_ptr_handle( reply->viewer ); + owner = reply->owner; } } SERVER_END_REQ; if (!ret) return FALSE; - if (bCBHasChanged && (flags & CB_PROCESS)) + if (bCBHasChanged && owner) { USER_Driver->pEndClipboardUpdate(); if (viewer) SendNotifyMessageW(viewer, WM_DRAWCLIPBOARD, (WPARAM) GetClipboardOwner(), 0); diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 8f5b7aa7f1e..6576eb901c9 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -4460,14 +4460,40 @@ struct set_class_info_reply +struct open_clipboard_request +{ + struct request_header __header; + user_handle_t window; +}; +struct open_clipboard_reply +{ + struct reply_header __header; + int owner; + char __pad_12[4]; +}; + + + +struct close_clipboard_request +{ + struct request_header __header; + int changed; +}; +struct close_clipboard_reply +{ + struct reply_header __header; + user_handle_t viewer; + int owner; +}; + + + struct set_clipboard_info_request { struct request_header __header; unsigned int flags; - user_handle_t clipboard; user_handle_t owner; user_handle_t viewer; - unsigned int seqno; }; struct set_clipboard_info_reply { @@ -4480,11 +4506,9 @@ struct set_clipboard_info_reply char __pad_28[4]; }; -#define SET_CB_OPEN 0x001 #define SET_CB_VIEWER 0x004 #define SET_CB_SEQNO 0x008 #define SET_CB_RELOWNER 0x010 -#define SET_CB_CLOSE 0x020 #define CB_OPEN 0x040 #define CB_OWNER 0x080 #define CB_PROCESS 0x100 @@ -5631,6 +5655,8 @@ enum request REQ_create_class, REQ_destroy_class, REQ_set_class_info, + REQ_open_clipboard, + REQ_close_clipboard, REQ_set_clipboard_info, REQ_empty_clipboard, REQ_open_token, @@ -5911,6 +5937,8 @@ union generic_request struct create_class_request create_class_request; struct destroy_class_request destroy_class_request; struct set_class_info_request set_class_info_request; + struct open_clipboard_request open_clipboard_request; + struct close_clipboard_request close_clipboard_request; struct set_clipboard_info_request set_clipboard_info_request; struct empty_clipboard_request empty_clipboard_request; struct open_token_request open_token_request; @@ -6189,6 +6217,8 @@ union generic_reply struct create_class_reply create_class_reply; struct destroy_class_reply destroy_class_reply; struct set_class_info_reply set_class_info_reply; + struct open_clipboard_reply open_clipboard_reply; + struct close_clipboard_reply close_clipboard_reply; struct set_clipboard_info_reply set_clipboard_info_reply; struct empty_clipboard_reply empty_clipboard_reply; struct open_token_reply open_token_reply; @@ -6250,6 +6280,6 @@ union generic_reply struct terminate_job_reply terminate_job_reply; }; -#define SERVER_PROTOCOL_VERSION 509 +#define SERVER_PROTOCOL_VERSION 510 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/clipboard.c b/server/clipboard.c index 7b92706eaea..423892531c6 100644 --- a/server/clipboard.c +++ b/server/clipboard.c @@ -137,31 +137,6 @@ void cleanup_clipboard_thread(struct thread *thread) release_object( winstation ); } -static int open_clipboard( struct clipboard *clipboard, user_handle_t win ) -{ - win = get_user_full_handle( win ); - if (clipboard->open_thread && clipboard->open_win != win) - { - set_error(STATUS_WAS_LOCKED); - return 0; - } - clipboard->open_win = win; - clipboard->open_thread = current; - return 1; -} - -static int close_clipboard( struct clipboard *clipboard ) -{ - if (clipboard->open_thread != current) - { - set_win32_error( ERROR_CLIPBOARD_NOT_OPEN ); - return 0; - } - clipboard->open_thread = NULL; - clipboard->open_win = 0; - return 1; -} - static int release_clipboard_owner( struct clipboard *clipboard, user_handle_t win ) { if ((clipboard->open_thread && clipboard->open_thread->process != current->process) || @@ -187,6 +162,48 @@ static int get_seqno( struct clipboard *clipboard ) } +/* open the clipboard */ +DECL_HANDLER(open_clipboard) +{ + struct clipboard *clipboard = get_process_clipboard(); + user_handle_t win; + + if (!clipboard) return; + win = get_user_full_handle( req->window ); + + if (clipboard->open_thread && clipboard->open_win != win) + { + set_error( STATUS_WAS_LOCKED ); + return; + } + clipboard->open_win = win; + clipboard->open_thread = current; + + reply->owner = (clipboard->owner_thread && clipboard->owner_thread->process == current->process); +} + + +/* close the clipboard */ +DECL_HANDLER(close_clipboard) +{ + struct clipboard *clipboard = get_process_clipboard(); + + if (!clipboard) return; + + if (clipboard->open_thread != current) + { + set_win32_error( ERROR_CLIPBOARD_NOT_OPEN ); + return; + } + if (req->changed) clipboard->seqno++; + clipboard->open_thread = NULL; + clipboard->open_win = 0; + + reply->viewer = clipboard->viewer; + reply->owner = (clipboard->owner_thread && clipboard->owner_thread->process == current->process); +} + + DECL_HANDLER(set_clipboard_info) { struct clipboard *clipboard = get_process_clipboard(); @@ -197,15 +214,6 @@ DECL_HANDLER(set_clipboard_info) reply->old_owner = clipboard->owner_win; reply->old_viewer = clipboard->viewer; - if (req->flags & SET_CB_OPEN) - { - if (!open_clipboard( clipboard, req->clipboard )) return; - } - else if (req->flags & SET_CB_CLOSE) - { - if (!close_clipboard( clipboard )) return; - } - if (req->flags & SET_CB_RELOWNER) { if (!release_clipboard_owner( clipboard, req->owner )) return; diff --git a/server/protocol.def b/server/protocol.def index 8f285488229..4b800de59f7 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3158,13 +3158,28 @@ enum caret_state #define SET_CLASS_EXTRA 0x0010 +/* Open the clipboard */ +@REQ(open_clipboard) + user_handle_t window; /* clipboard window */ +@REPLY + int owner; /* is the process already the owner? */ +@END + + +/* Close the clipboard */ +@REQ(close_clipboard) + int changed; /* did it change since the open? */ +@REPLY + user_handle_t viewer; /* first clipboard viewer */ + int owner; /* is the process already the owner? */ +@END + + /* Set/get clipboard information */ @REQ(set_clipboard_info) unsigned int flags; /* flags for fields to set (see below) */ - user_handle_t clipboard; /* clipboard window */ user_handle_t owner; /* clipboard owner */ user_handle_t viewer; /* first clipboard viewer */ - unsigned int seqno; /* change sequence number */ @REPLY unsigned int flags; /* status flags (see below) */ user_handle_t old_clipboard; /* old clipboard window */ @@ -3173,11 +3188,9 @@ enum caret_state unsigned int seqno; /* current sequence number */ @END -#define SET_CB_OPEN 0x001 #define SET_CB_VIEWER 0x004 #define SET_CB_SEQNO 0x008 #define SET_CB_RELOWNER 0x010 -#define SET_CB_CLOSE 0x020 #define CB_OPEN 0x040 #define CB_OWNER 0x080 #define CB_PROCESS 0x100 diff --git a/server/request.h b/server/request.h index d55b7e7ee13..4f0055c26f4 100644 --- a/server/request.h +++ b/server/request.h @@ -326,6 +326,8 @@ DECL_HANDLER(get_hook_info); DECL_HANDLER(create_class); DECL_HANDLER(destroy_class); DECL_HANDLER(set_class_info); +DECL_HANDLER(open_clipboard); +DECL_HANDLER(close_clipboard); DECL_HANDLER(set_clipboard_info); DECL_HANDLER(empty_clipboard); DECL_HANDLER(open_token); @@ -605,6 +607,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_create_class, (req_handler)req_destroy_class, (req_handler)req_set_class_info, + (req_handler)req_open_clipboard, + (req_handler)req_close_clipboard, (req_handler)req_set_clipboard_info, (req_handler)req_empty_clipboard, (req_handler)req_open_token, @@ -2010,12 +2014,19 @@ C_ASSERT( FIELD_OFFSET(struct set_class_info_reply, old_win_extra) == 20 ); C_ASSERT( FIELD_OFFSET(struct set_class_info_reply, old_instance) == 24 ); C_ASSERT( FIELD_OFFSET(struct set_class_info_reply, old_extra_value) == 32 ); C_ASSERT( sizeof(struct set_class_info_reply) == 40 ); +C_ASSERT( FIELD_OFFSET(struct open_clipboard_request, window) == 12 ); +C_ASSERT( sizeof(struct open_clipboard_request) == 16 ); +C_ASSERT( FIELD_OFFSET(struct open_clipboard_reply, owner) == 8 ); +C_ASSERT( sizeof(struct open_clipboard_reply) == 16 ); +C_ASSERT( FIELD_OFFSET(struct close_clipboard_request, changed) == 12 ); +C_ASSERT( sizeof(struct close_clipboard_request) == 16 ); +C_ASSERT( FIELD_OFFSET(struct close_clipboard_reply, viewer) == 8 ); +C_ASSERT( FIELD_OFFSET(struct close_clipboard_reply, owner) == 12 ); +C_ASSERT( sizeof(struct close_clipboard_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_request, flags) == 12 ); -C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_request, clipboard) == 16 ); -C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_request, owner) == 20 ); -C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_request, viewer) == 24 ); -C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_request, seqno) == 28 ); -C_ASSERT( sizeof(struct set_clipboard_info_request) == 32 ); +C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_request, owner) == 16 ); +C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_request, viewer) == 20 ); +C_ASSERT( sizeof(struct set_clipboard_info_request) == 24 ); C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_reply, flags) == 8 ); C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_reply, old_clipboard) == 12 ); C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_reply, old_owner) == 16 ); diff --git a/server/trace.c b/server/trace.c index 4d8a2eb8185..dea9dce2f12 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3734,13 +3734,32 @@ static void dump_set_class_info_reply( const struct set_class_info_reply *req ) dump_uint64( ", old_extra_value=", &req->old_extra_value ); } +static void dump_open_clipboard_request( const struct open_clipboard_request *req ) +{ + fprintf( stderr, " window=%08x", req->window ); +} + +static void dump_open_clipboard_reply( const struct open_clipboard_reply *req ) +{ + fprintf( stderr, " owner=%d", req->owner ); +} + +static void dump_close_clipboard_request( const struct close_clipboard_request *req ) +{ + fprintf( stderr, " changed=%d", req->changed ); +} + +static void dump_close_clipboard_reply( const struct close_clipboard_reply *req ) +{ + fprintf( stderr, " viewer=%08x", req->viewer ); + fprintf( stderr, ", owner=%d", req->owner ); +} + static void dump_set_clipboard_info_request( const struct set_clipboard_info_request *req ) { fprintf( stderr, " flags=%08x", req->flags ); - fprintf( stderr, ", clipboard=%08x", req->clipboard ); fprintf( stderr, ", owner=%08x", req->owner ); fprintf( stderr, ", viewer=%08x", req->viewer ); - fprintf( stderr, ", seqno=%08x", req->seqno ); } static void dump_set_clipboard_info_reply( const struct set_clipboard_info_reply *req ) @@ -4579,6 +4598,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_create_class_request, (dump_func)dump_destroy_class_request, (dump_func)dump_set_class_info_request, + (dump_func)dump_open_clipboard_request, + (dump_func)dump_close_clipboard_request, (dump_func)dump_set_clipboard_info_request, (dump_func)dump_empty_clipboard_request, (dump_func)dump_open_token_request, @@ -4855,6 +4876,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_create_class_reply, (dump_func)dump_destroy_class_reply, (dump_func)dump_set_class_info_reply, + (dump_func)dump_open_clipboard_reply, + (dump_func)dump_close_clipboard_reply, (dump_func)dump_set_clipboard_info_reply, NULL, (dump_func)dump_open_token_reply, @@ -5131,6 +5154,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "create_class", "destroy_class", "set_class_info", + "open_clipboard", + "close_clipboard", "set_clipboard_info", "empty_clipboard", "open_token",