If the window does not render the delayed-rendering clipboard formats before it is destroyed, then they should be removed from the clipboard, including the derived formats added by CloseClipboard().
Signed-off-by: Francois Gouget fgouget@codeweavers.com --- Currently Wine fails to remove the derived formats (e.g. CF_TEXT in the case of CF_UNICODETEXT), and ends up creating circular references in the CloseClipboard() call. In turn this causes GetClipboardData() to go into an infinite recursive loop and to crash. This usually happens in explorer.exe on desktop environments that have a clipboard manager. https://bugs.winehq.org/show_bug.cgi?id=51496 --- dlls/user32/tests/clipboard.c | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+)
diff --git a/dlls/user32/tests/clipboard.c b/dlls/user32/tests/clipboard.c index f351a6a29a8..8515ba5b88a 100644 --- a/dlls/user32/tests/clipboard.c +++ b/dlls/user32/tests/clipboard.c @@ -949,6 +949,48 @@ static void test_synthesized(void) r = CloseClipboard(); ok(r, "gle %d\n", GetLastError()); DestroyWindow( hwnd ); + + /* Check what happens to the delayed rendering clipboard formats when the + * owner window is destroyed. + */ + hwnd = CreateWindowA( "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL ); + SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)renderer_winproc ); + + r = open_clipboard(hwnd); + ok(r, "gle %d\n", GetLastError()); + r = EmptyClipboard(); + ok(r, "gle %d\n", GetLastError()); + SetClipboardData( CF_UNICODETEXT, NULL ); + r = CloseClipboard(); + ok(r, "gle %d\n", GetLastError()); + + r = open_clipboard(NULL); + ok(r, "gle %d\n", GetLastError()); + count = CountClipboardFormats(); + ok(count == 4, "count %u\n", count ); + + DestroyWindow( hwnd ); + + /* CF_UNICODETEXT and derivatives, CF_TEXT + CF_OEMTEXT, should be gone */ + count = CountClipboardFormats(); + todo_wine ok(count == 1, "count %u\n", count ); + cf = EnumClipboardFormats( 0 ); + ok(cf == CF_LOCALE, "unexpected clipboard format %u\n", cf); + + r = CloseClipboard(); + ok(r, "gle %d\n", GetLastError()); + + r = open_clipboard(NULL); + ok(r, "gle %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + data = (void*)1; if (broken(1)) /* FIXME Crashes in Wine */ + data = GetClipboardData( CF_TEXT ); + ok(GetLastError() == 0xdeadbeef, "unexpected last error %d\n", GetLastError()); + todo_wine ok(!data, "GetClipboardData() should have returned NULL\n"); + + r = CloseClipboard(); + ok(r, "gle %d\n", GetLastError()); }
static DWORD WINAPI clipboard_render_data_thread(void *param)