[PATCH] ole32: Avoid the failure of flushing the ole clipboard when the clipboard manager gets the data.
When ole has set the clipboard data, the clipboard manager may preempt this data (by sending a WM_RENDERFORMAT message). At this point the clipboard ownership may be occupied by the clipboard manager; resulting in a failure to flush the ole clipboard. Signed-off-by: Haoyang Chen <chenhaoyang(a)uniontech.com> --- dlls/ole32/clipboard.c | 2 ++ dlls/ole32/tests/clipboard.c | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/dlls/ole32/clipboard.c b/dlls/ole32/clipboard.c index e61b3076883..ebc498d52e7 100644 --- a/dlls/ole32/clipboard.c +++ b/dlls/ole32/clipboard.c @@ -2261,6 +2261,7 @@ HRESULT WINAPI OleFlushClipboard(void) HRESULT hr; ole_clipbrd *clipbrd; HWND wnd; + MSG msg; TRACE("()\n"); @@ -2273,6 +2274,7 @@ HRESULT WINAPI OleFlushClipboard(void) */ if (!clipbrd->src_data) return S_OK; + PeekMessageW(&msg, wnd, WM_RENDERFORMAT, WM_RENDERFORMAT, PM_REMOVE); if (!OpenClipboard(wnd)) return CLIPBRD_E_CANT_OPEN; SendMessageW(wnd, WM_RENDERALLFORMATS, 0, 0); diff --git a/dlls/ole32/tests/clipboard.c b/dlls/ole32/tests/clipboard.c index fd8f287680b..47700e7f3fd 100644 --- a/dlls/ole32/tests/clipboard.c +++ b/dlls/ole32/tests/clipboard.c @@ -1085,6 +1085,7 @@ static void test_set_clipboard_DRAWCLIPBOARD(void) HWND viewer; int ret; HANDLE thread; + int i; hr = DataObjectImpl_CreateText("data", &data); ok(hr == S_OK, "Failed to create data object: 0x%08x\n", hr); @@ -1120,6 +1121,15 @@ static void test_set_clipboard_DRAWCLIPBOARD(void) ret = SendMessageA( viewer, WM_USER, 0, 0 ); ok( ret == 2, "%u WM_DRAWCLIPBOARD received\n", ret ); + Sleep(500); + + for (i = 0; i < 10; i++) + { + hr = OleFlushClipboard(); + if (hr == S_OK) break; + Sleep(100); + } + ok(hr == S_OK, "got %08x\n", hr); clip_data = NULL; hr = OleFlushClipboard(); ok(hr == S_OK, "failed to flush clipboard, hr = 0x%08x\n", hr); -- 2.20.1
Hi, While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=90907 Your paranoid android. === debiant2 (32 bit WoW report) === ole32: clipboard.c:1053: Test failed: OleIsCurrentClipboard returned 0 clipboard.c:1053: Test failed: OleIsCurrentClipboard returned 1
Please ignore it, it needs more testing. 在 2021/5/20 下午3:07, Haoyang Chen 写道:
When ole has set the clipboard data, the clipboard manager may preempt this data (by sending a WM_RENDERFORMAT message). At this point the clipboard ownership may be occupied by the clipboard manager; resulting in a failure to flush the ole clipboard.
Signed-off-by: Haoyang Chen <chenhaoyang(a)uniontech.com> --- dlls/ole32/clipboard.c | 2 ++ dlls/ole32/tests/clipboard.c | 10 ++++++++++ 2 files changed, 12 insertions(+)
diff --git a/dlls/ole32/clipboard.c b/dlls/ole32/clipboard.c index e61b3076883..ebc498d52e7 100644 --- a/dlls/ole32/clipboard.c +++ b/dlls/ole32/clipboard.c @@ -2261,6 +2261,7 @@ HRESULT WINAPI OleFlushClipboard(void) HRESULT hr; ole_clipbrd *clipbrd; HWND wnd; + MSG msg;
TRACE("()\n");
@@ -2273,6 +2274,7 @@ HRESULT WINAPI OleFlushClipboard(void) */ if (!clipbrd->src_data) return S_OK;
+ PeekMessageW(&msg, wnd, WM_RENDERFORMAT, WM_RENDERFORMAT, PM_REMOVE); if (!OpenClipboard(wnd)) return CLIPBRD_E_CANT_OPEN;
SendMessageW(wnd, WM_RENDERALLFORMATS, 0, 0); diff --git a/dlls/ole32/tests/clipboard.c b/dlls/ole32/tests/clipboard.c index fd8f287680b..47700e7f3fd 100644 --- a/dlls/ole32/tests/clipboard.c +++ b/dlls/ole32/tests/clipboard.c @@ -1085,6 +1085,7 @@ static void test_set_clipboard_DRAWCLIPBOARD(void) HWND viewer; int ret; HANDLE thread; + int i;
hr = DataObjectImpl_CreateText("data", &data); ok(hr == S_OK, "Failed to create data object: 0x%08x\n", hr); @@ -1120,6 +1121,15 @@ static void test_set_clipboard_DRAWCLIPBOARD(void) ret = SendMessageA( viewer, WM_USER, 0, 0 ); ok( ret == 2, "%u WM_DRAWCLIPBOARD received\n", ret );
+ Sleep(500); + + for (i = 0; i < 10; i++) + { + hr = OleFlushClipboard(); + if (hr == S_OK) break; + Sleep(100); + } + ok(hr == S_OK, "got %08x\n", hr); clip_data = NULL; hr = OleFlushClipboard(); ok(hr == S_OK, "failed to flush clipboard, hr = 0x%08x\n", hr);
On Thu, 20 May 2021, Haoyang Chen wrote:
When ole has set the clipboard data, the clipboard manager may preempt this data (by sending a WM_RENDERFORMAT message). At this point the clipboard ownership may be occupied by the clipboard manager; resulting in a failure to flush the ole clipboard.
That's interesting. Could this explain all the ERROR_ACCESS_DENIED / CLIPBRD_E_CANT_OPEN errors we're getting, in ole32:clipboard and user32:clipboard? But why do these happen mostly on cw-rx460? And why would tinkering with the Radeon driver settings make a difference despite no setting being a clear culprit? [1] https://test.winehq.org/data/patterns.html#ole32:clipboard https://test.winehq.org/data/patterns.html#user32:clipboard But even if it only leads to a way to avoid rare errors like this one (not on cx-rx460) that would be good: https://test.winehq.org/data/d7fecebe93938bf1ef2349ac74413e28d6b8e153/win180... [1] For instance, starting from a situation where user32:clipboard fails systematically, it goes like this: - Reboot -> user32:clipboard still fails systematically - Turn off some setting -> no change (iirc) - Reboot -> failure rate falls to ~ 1/30 Okay, that means changing a feature only makes a difference after a reboot. - Turn feature back on -> still good, as expected - Reboot -> still good!!! -- Francois Gouget <fgouget(a)codeweavers.com>
participants (3)
-
Francois Gouget -
Haoyang Chen -
Marvin