ole32: Avoid calling QueryContinueDrag recursively.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48569
Signed-off-by: Roman Pišl <rpisl@seznam.cz>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
(cherry picked from commit 808d8b87a0)
Signed-off-by: Michael Stefaniuc <mstefani@winehq.org>
stable
Roman Pišl 2020-02-17 23:59:38 +01:00 committed by Michael Stefaniuc
parent d715810b3f
commit 0d85e007b9
2 changed files with 52 additions and 10 deletions

View File

@ -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;
}
/***

View File

@ -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();