Module: wine Branch: master Commit: b68e03f9c936708c9757e2e7c2be5011b50fe070 URL: http://source.winehq.org/git/wine.git/?a=commit;h=b68e03f9c936708c9757e2e7c2...
Author: Vincent Povirk vincent@codeweavers.com Date: Wed May 18 14:23:47 2016 -0500
user32: Don't regard the clipboard as changed if we don't own it.
I ran into a situation where user32 will call EndClipboardUpdate even though the clipboard hasn't changed. It went something like this: * Program A acquires the clipboard and adds some delay-rendered data. * Program B requests data from the clipboard, causing program A to receive WM_RENDERFORMAT. * Program A calls SetClipboardData to fulfill the request, setting bCBHasChanged to TRUE. * Program C acquires the clipboard. * Program A opens the clipboard to enumerate the formats. When it closes the clipboard, EndClipboardUpdate is called.
Signed-off-by: Vincent Povirk vincent@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/user32/clipboard.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/dlls/user32/clipboard.c b/dlls/user32/clipboard.c index dec738a..4764784 100644 --- a/dlls/user32/clipboard.c +++ b/dlls/user32/clipboard.c @@ -178,6 +178,7 @@ INT WINAPI GetClipboardFormatNameA(UINT wFormat, LPSTR retStr, INT maxlen) BOOL WINAPI OpenClipboard( HWND hWnd ) { BOOL bRet; + UINT flags;
TRACE("(%p)...\n", hWnd);
@@ -185,10 +186,16 @@ BOOL WINAPI OpenClipboard( HWND hWnd ) { req->flags = SET_CB_OPEN; req->clipboard = wine_server_user_handle( hWnd ); - bRet = !wine_server_call( req ); + if ((bRet = !wine_server_call( req ))) + flags = reply->flags; } SERVER_END_REQ;
+ if (bRet && !(flags & CB_PROCESS)) + { + bCBHasChanged = FALSE; + } + TRACE(" returning %i\n", bRet);
return bRet; @@ -201,6 +208,7 @@ BOOL WINAPI OpenClipboard( HWND hWnd ) BOOL WINAPI CloseClipboard(void) { HWND viewer = 0; + UINT flags; BOOL ret;
TRACE("() Changed=%d\n", bCBHasChanged); @@ -210,18 +218,21 @@ BOOL WINAPI CloseClipboard(void) req->flags = SET_CB_CLOSE; if (bCBHasChanged) req->flags |= SET_CB_SEQNO; if ((ret = !wine_server_call_err( req ))) + { viewer = wine_server_ptr_handle( reply->old_viewer ); + flags = reply->flags; + } } SERVER_END_REQ;
if (!ret) return FALSE;
- if (bCBHasChanged) + if (bCBHasChanged && (flags & CB_PROCESS)) { USER_Driver->pEndClipboardUpdate(); - bCBHasChanged = FALSE; if (viewer) SendNotifyMessageW(viewer, WM_DRAWCLIPBOARD, (WPARAM) GetClipboardOwner(), 0); } + bCBHasChanged = FALSE; return TRUE; }