Vincent Povirk : user32: Don't regard the clipboard as changed if we don' t own it.

Alexandre Julliard julliard at wine.codeweavers.com
Fri May 20 11:27:54 CDT 2016


Module: wine
Branch: master
Commit: b68e03f9c936708c9757e2e7c2be5011b50fe070
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=b68e03f9c936708c9757e2e7c2be5011b50fe070

Author: Vincent Povirk <vincent at 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 at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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;
 }
 




More information about the wine-cvs mailing list