diff --git a/dlls/user32/clipboard.c b/dlls/user32/clipboard.c index 47647845ee1d872a011c49e089bab8abc9fa3c63..915c370ea62f8da2b8ade231b2fb20b404f38239 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 8f5b7aa7f1e183850a14c662157829effc74414c..6576eb901c9920cae72bc40134944f99a1b5e2a4 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 7b92706eaea4e7271dec3f7f4a1de92eb56cdf34..423892531c61899b97629ccdc39cf91f8537b82b 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,24 +162,57 @@ static int get_seqno( struct clipboard *clipboard ) } -DECL_HANDLER(set_clipboard_info) +/* 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 ); - reply->old_clipboard = clipboard->open_win; - reply->old_owner = clipboard->owner_win; - reply->old_viewer = clipboard->viewer; - - if (req->flags & SET_CB_OPEN) + if (clipboard->open_thread && clipboard->open_win != win) { - if (!open_clipboard( clipboard, req->clipboard )) return; + set_error( STATUS_WAS_LOCKED ); + return; } - else if (req->flags & SET_CB_CLOSE) + 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) { - if (!close_clipboard( clipboard )) return; + 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(); + + if (!clipboard) return; + + reply->old_clipboard = clipboard->open_win; + reply->old_owner = clipboard->owner_win; + reply->old_viewer = clipboard->viewer; if (req->flags & SET_CB_RELOWNER) { diff --git a/server/protocol.def b/server/protocol.def index 8f285488229170b9375e5d220b9694fef8633785..4b800de59f74f2f56f00d3097efe2484bced0d17 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 d55b7e7ee1346403f35f4c48cf4454e4c57c8525..4f0055c26f47dda7329da7e527509082dab40da5 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 4d8a2eb818511b774254cf3980c7aabaa94133cb..dea9dce2f12bffbaa698f4cee361f12ab135969d 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",