Roman Pišl : ole32: Avoid calling QueryContinueDrag recursively.

Alexandre Julliard julliard at winehq.org
Tue Feb 18 16:13:46 CST 2020


Module: wine
Branch: master
Commit: 808d8b87a040e4de44e2691d3a9e29f871616ca0
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=808d8b87a040e4de44e2691d3a9e29f871616ca0

Author: Roman Pišl <rpisl at seznam.cz>
Date:   Mon Feb 17 23:59:38 2020 +0100

ole32: Avoid calling QueryContinueDrag recursively.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48569
Signed-off-by: Roman Pišl <rpisl at seznam.cz>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ole32/ole2.c           | 11 ++++++++++
 dlls/ole32/tests/dragdrop.c | 53 +++++++++++++++++++++++++++++++++++----------
 2 files changed, 53 insertions(+), 11 deletions(-)

diff --git a/dlls/ole32/ole2.c b/dlls/ole32/ole2.c
index 757458ad20..6653fac342 100644
--- a/dlls/ole32/ole2.c
+++ b/dlls/ole32/ole2.c
@@ -62,6 +62,7 @@ typedef struct tagTrackerWindowInfo
   DWORD        dwOKEffect;
   DWORD*       pdwEffect;
   BOOL       trackingDone;
+  BOOL         inTrackCall;
   HRESULT      returnValue;
 
   BOOL       escPressed;
@@ -766,6 +767,7 @@ HRESULT WINAPI DoDragDrop (
   trackerInfo.dwOKEffect        = dwOKEffect;
   trackerInfo.pdwEffect         = pdwEffect;
   trackerInfo.trackingDone      = FALSE;
+  trackerInfo.inTrackCall       = FALSE;
   trackerInfo.escPressed        = FALSE;
   trackerInfo.curTargetHWND     = 0;
   trackerInfo.curDragTarget     = 0;
@@ -2284,6 +2286,13 @@ static void OLEDD_TrackStateChange(TrackerWindowInfo* trackerInfo)
   HWND   hwndNewTarget = 0;
   POINT pt;
 
+  /*
+   * This method may be called from QueryContinueDrag again,
+   * (i.e. by running message loop) so avoid recursive call chain.
+   */
+  if (trackerInfo->inTrackCall) return;
+  trackerInfo->inTrackCall = TRUE;
+
   /*
    * Get the handle of the window under the mouse
    */
@@ -2329,6 +2338,8 @@ static void OLEDD_TrackStateChange(TrackerWindowInfo* trackerInfo)
   }
   else
     drag_end( trackerInfo );
+
+  trackerInfo->inTrackCall = FALSE;
 }
 
 /***
diff --git a/dlls/ole32/tests/dragdrop.c b/dlls/ole32/tests/dragdrop.c
index 77e47d723d..62ac15d8fc 100644
--- a/dlls/ole32/tests/dragdrop.c
+++ b/dlls/ole32/tests/dragdrop.c
@@ -260,6 +260,7 @@ struct method_call call_lists[][30] =
 };
 
 static int droptarget_refs;
+static int test_reentrance;
 
 /* helper macros to make tests a bit leaner */
 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
@@ -359,7 +360,34 @@ static HRESULT WINAPI DropSource_QueryContinueDrag(
     BOOL fEscapePressed,
     DWORD grfKeyState)
 {
-    return check_expect(DS_QueryContinueDrag, 0, NULL);
+    HRESULT hr = check_expect(DS_QueryContinueDrag, 0, NULL);
+    if (test_reentrance)
+    {
+        MSG msg;
+        BOOL r;
+        int num = 0;
+
+        HWND hwnd = GetCapture();
+        ok(hwnd != 0, "Expected capture window\n");
+
+        /* send some fake events that should be ignored */
+        r = PostMessageA(hwnd, WM_MOUSEMOVE, 0, 0);
+        r &= PostMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
+        r &= PostMessageA(hwnd, WM_LBUTTONUP, 0, 0);
+        r &= PostMessageA(hwnd, WM_KEYDOWN, VK_ESCAPE, 0);
+        ok(r, "Unable to post messages\n");
+
+        /* run the message loop for this thread */
+        while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
+        {
+            TranslateMessage(&msg);
+            DispatchMessageA(&msg);
+            num++;
+        }
+
+        ok(num >= 4, "Expected at least 4 messages but %d were processed\n", num);
+    }
+    return hr;
 }
 
 static HRESULT WINAPI DropSource_GiveFeedback(
@@ -701,17 +729,20 @@ static void test_DoDragDrop(void)
     GetWindowRect(hwnd, &rect);
     ok(SetCursorPos(rect.left+50, rect.top+50), "SetCursorPos failed\n");
 
-    for (seq = 0; seq < ARRAY_SIZE(call_lists); seq++)
+    for (test_reentrance = 0; test_reentrance < 2; test_reentrance++)
     {
-        DWORD effect_in;
-        trace("%d\n", seq);
-        call_ptr = call_lists[seq];
-        effect_in = call_ptr->set_param;
-        call_ptr++;
-
-        hr = DoDragDrop(&DataObject, &DropSource, effect_in, &effect);
-        check_expect(DoDragDrop_ret, hr, NULL);
-        check_expect(DoDragDrop_effect_out, effect, NULL);
+        for (seq = 0; seq < ARRAY_SIZE(call_lists); seq++)
+        {
+            DWORD effect_in;
+            trace("%d\n", seq);
+            call_ptr = call_lists[seq];
+            effect_in = call_ptr->set_param;
+            call_ptr++;
+
+            hr = DoDragDrop(&DataObject, &DropSource, effect_in, &effect);
+            check_expect(DoDragDrop_ret, hr, NULL);
+            check_expect(DoDragDrop_effect_out, effect, NULL);
+        }
     }
 
     OleUninitialize();




More information about the wine-cvs mailing list