From 808d8b87a040e4de44e2691d3a9e29f871616ca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Pi=C5=A1l?= Date: Mon, 17 Feb 2020 23:59:38 +0100 Subject: [PATCH] ole32: Avoid calling QueryContinueDrag recursively. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48569 Signed-off-by: Roman Pišl Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/ole32/ole2.c | 11 ++++++++ dlls/ole32/tests/dragdrop.c | 51 +++++++++++++++++++++++++++++-------- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/dlls/ole32/ole2.c b/dlls/ole32/ole2.c index 757458ad204..6653fac3422 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 77e47d723db..62ac15d8fc7 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++; + 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); + hr = DoDragDrop(&DataObject, &DropSource, effect_in, &effect); + check_expect(DoDragDrop_ret, hr, NULL); + check_expect(DoDragDrop_effect_out, effect, NULL); + } } OleUninitialize();