Commit 808d8b87 authored by Roman Pišl's avatar Roman Pišl Committed by Alexandre Julliard

ole32: Avoid calling QueryContinueDrag recursively.

parent 3c49e3e4
...@@ -62,6 +62,7 @@ typedef struct tagTrackerWindowInfo ...@@ -62,6 +62,7 @@ typedef struct tagTrackerWindowInfo
DWORD dwOKEffect; DWORD dwOKEffect;
DWORD* pdwEffect; DWORD* pdwEffect;
BOOL trackingDone; BOOL trackingDone;
BOOL inTrackCall;
HRESULT returnValue; HRESULT returnValue;
BOOL escPressed; BOOL escPressed;
...@@ -766,6 +767,7 @@ HRESULT WINAPI DoDragDrop ( ...@@ -766,6 +767,7 @@ HRESULT WINAPI DoDragDrop (
trackerInfo.dwOKEffect = dwOKEffect; trackerInfo.dwOKEffect = dwOKEffect;
trackerInfo.pdwEffect = pdwEffect; trackerInfo.pdwEffect = pdwEffect;
trackerInfo.trackingDone = FALSE; trackerInfo.trackingDone = FALSE;
trackerInfo.inTrackCall = FALSE;
trackerInfo.escPressed = FALSE; trackerInfo.escPressed = FALSE;
trackerInfo.curTargetHWND = 0; trackerInfo.curTargetHWND = 0;
trackerInfo.curDragTarget = 0; trackerInfo.curDragTarget = 0;
...@@ -2285,6 +2287,13 @@ static void OLEDD_TrackStateChange(TrackerWindowInfo* trackerInfo) ...@@ -2285,6 +2287,13 @@ static void OLEDD_TrackStateChange(TrackerWindowInfo* trackerInfo)
POINT pt; 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 * Get the handle of the window under the mouse
*/ */
pt.x = trackerInfo->curMousePos.x; pt.x = trackerInfo->curMousePos.x;
...@@ -2329,6 +2338,8 @@ static void OLEDD_TrackStateChange(TrackerWindowInfo* trackerInfo) ...@@ -2329,6 +2338,8 @@ static void OLEDD_TrackStateChange(TrackerWindowInfo* trackerInfo)
} }
else else
drag_end( trackerInfo ); drag_end( trackerInfo );
trackerInfo->inTrackCall = FALSE;
} }
/*** /***
......
...@@ -260,6 +260,7 @@ struct method_call call_lists[][30] = ...@@ -260,6 +260,7 @@ struct method_call call_lists[][30] =
}; };
static int droptarget_refs; static int droptarget_refs;
static int test_reentrance;
/* helper macros to make tests a bit leaner */ /* 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) #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( ...@@ -359,7 +360,34 @@ static HRESULT WINAPI DropSource_QueryContinueDrag(
BOOL fEscapePressed, BOOL fEscapePressed,
DWORD grfKeyState) 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( static HRESULT WINAPI DropSource_GiveFeedback(
...@@ -701,17 +729,20 @@ static void test_DoDragDrop(void) ...@@ -701,17 +729,20 @@ static void test_DoDragDrop(void)
GetWindowRect(hwnd, &rect); GetWindowRect(hwnd, &rect);
ok(SetCursorPos(rect.left+50, rect.top+50), "SetCursorPos failed\n"); 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; for (seq = 0; seq < ARRAY_SIZE(call_lists); seq++)
trace("%d\n", seq); {
call_ptr = call_lists[seq]; DWORD effect_in;
effect_in = call_ptr->set_param; trace("%d\n", seq);
call_ptr++; call_ptr = call_lists[seq];
effect_in = call_ptr->set_param;
hr = DoDragDrop(&DataObject, &DropSource, effect_in, &effect); call_ptr++;
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(); OleUninitialize();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment