From a28235c709bf60891502da748f804e236da2dc8e Mon Sep 17 00:00:00 2001 From: Giannis Adamopoulos Date: Thu, 24 Aug 2017 23:08:09 +0000 Subject: [PATCH] [USER32_APITEST] -Add a monster of a test to check if WM_DESTROYCLIPBOARD is blocking or not. Use a critical section while recording as we use a single message cache in two threads. After 50154, 50816, 50846 and 75616 changing back and forth, this test shows that 75616 is correct and making sure that it won't be changed again in the future, somehting that would break the ole clipboard. svn path=/trunk/; revision=75663 --- rostests/apitests/user32/CMakeLists.txt | 1 + rostests/apitests/user32/EmptyClipboard.c | 195 ++++++++++++++++++++++ rostests/apitests/user32/testlist.c | 2 + 3 files changed, 198 insertions(+) create mode 100644 rostests/apitests/user32/EmptyClipboard.c diff --git a/rostests/apitests/user32/CMakeLists.txt b/rostests/apitests/user32/CMakeLists.txt index bc4b7693189..3b758836d41 100644 --- a/rostests/apitests/user32/CMakeLists.txt +++ b/rostests/apitests/user32/CMakeLists.txt @@ -9,6 +9,7 @@ list(APPEND SOURCE DestroyCursorIcon.c DrawIconEx.c desktop.c + EmptyClipboard.c EnumDisplaySettings.c GetDCEx.c GetIconInfo.c diff --git a/rostests/apitests/user32/EmptyClipboard.c b/rostests/apitests/user32/EmptyClipboard.c new file mode 100644 index 00000000000..a7d0140bd7f --- /dev/null +++ b/rostests/apitests/user32/EmptyClipboard.c @@ -0,0 +1,195 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPL - See COPYING in the top level directory + * PURPOSE: Test for EmptyClipboard + * PROGRAMMERS: Giannis Adamopoulos + */ + +#include + +#include +#include + +#include +#include + +HWND hWnd1, hWnd2; + +CRITICAL_SECTION CritSect; + +/* FIXME: test for HWND_TOP, etc...*/ +static int get_iwnd(HWND hWnd) +{ + if(hWnd == hWnd1) return 1; + else if(hWnd2 && hWnd == hWnd2) return 2; + else return 0; +} + +LRESULT CALLBACK ClipTestProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int iwnd = get_iwnd(hWnd); + + if(message > WM_USER || !iwnd || IsDWmMsg(message) || IseKeyMsg(message)) + return DefWindowProc(hWnd, message, wParam, lParam); + + switch(message) + { + case WM_GETICON : + case WM_SETICON: + break; + case WM_DESTROYCLIPBOARD: + Sleep(1000); + default: + EnterCriticalSection(&CritSect); + RECORD_MESSAGE(iwnd, message, SENT, 0,0); + LeaveCriticalSection(&CritSect); + } + return DefWindowProc(hWnd, message, wParam, lParam); +} + +static void RecordAndDispatch(MSG* pmsg) +{ + int iwnd = get_iwnd(pmsg->hwnd); + if(!(pmsg->message > WM_USER || !iwnd || IsDWmMsg(pmsg->message) || IseKeyMsg(pmsg->message))) + { + EnterCriticalSection(&CritSect); + RECORD_MESSAGE(iwnd, pmsg->message, POST,0,0); + LeaveCriticalSection(&CritSect); + } + DispatchMessageA( pmsg ); +} + +static void FlushMessages() +{ + MSG msg; + while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) + RecordAndDispatch(&msg); +} + +static DWORD WINAPI ClipThread(PVOID Parameter) +{ + BOOL ret; + + hWnd2 = CreateWindowW(L"clipstest", L"clipstest", WS_OVERLAPPEDWINDOW, + 20, 20, 300, 300, NULL, NULL, 0, NULL); + + /* Get ownership of the clipboard and record the messages we get */ + ret = OpenClipboard(hWnd2); + ok (ret, "OpenClipboard failed\n"); + + EnterCriticalSection(&CritSect); + RECORD_MESSAGE(1, WM_DESTROYCLIPBOARD, MARKER,0,0); + LeaveCriticalSection(&CritSect); + + ret = EmptyClipboard(); + ok (ret, "EmptyClipboard failed\n"); + + EnterCriticalSection(&CritSect); + RECORD_MESSAGE(1, WM_DESTROYCLIPBOARD, MARKER,1,0); + LeaveCriticalSection(&CritSect); + + ret = CloseClipboard(); + ok (ret, "CloseClipboard failed\n"); + + /* Record if we got any post messages */ + FlushMessages(); + + /* Force the parent thread out of its loop */ + PostMessageW(hWnd1, WM_QUIT, 0, 0); + + return 0; +} + +MSG_ENTRY EmptyClipboard_chain[]={ + {1,WM_DESTROYCLIPBOARD, MARKER, 0}, + {1,WM_DESTROYCLIPBOARD, SENT}, + {1,WM_DESTROYCLIPBOARD, MARKER, 1}, + {0,0}}; + +void TestMessages() +{ + HANDLE hThread; + DWORD dwThread; + BOOL ret; + MSG msg; + + /* Initialize the test */ + InitializeCriticalSection(&CritSect); + + RegisterSimpleClass(ClipTestProc, L"clipstest"); + + hWnd2 = NULL; + hWnd1 = CreateWindowW(L"clipstest", L"clipstest", WS_OVERLAPPEDWINDOW, + 20, 20, 300, 300, NULL, NULL, 0, NULL); + ok (hWnd1 != NULL, "CreateWindowW failed\n"); + + EMPTY_CACHE(); + + /* Get ownership of the clipboard and record the messages we get */ + ret = OpenClipboard(hWnd1); + ok (ret, "OpenClipboard failed\n"); + + ret = EmptyClipboard(); + ok (ret, "EmptyClipboard failed\n"); + + ret = CloseClipboard(); + ok (ret, "CloseClipboard failed\n"); + + /* Record posted messages */ + FlushMessages(); + COMPARE_CACHE(empty_chain); + + /* Create the child thread and record messages till we get the WM_QUIT */ + hThread = CreateThread(NULL, 0, ClipThread, NULL, 0, &dwThread); + + while (GetMessage(&msg, 0, 0 ,0)) + RecordAndDispatch(&msg); + + COMPARE_CACHE(EmptyClipboard_chain); + + CloseHandle(hThread); +} + +void TestOwnership() +{ + BOOL ret; + HWND hWnd, hWndClipOwner; + + ret = OpenClipboard(NULL); + ok (ret, "OpenClipboard failed\n"); + + ret = EmptyClipboard(); + ok (ret, "EmptyClipboard failed\n"); + + ret = CloseClipboard(); + ok (ret, "CloseClipboard failed\n"); + + hWndClipOwner = GetClipboardOwner(); + ok (hWndClipOwner == NULL, "Expected NULL owner\n"); + + hWnd = CreateWindowW(L"static", L"static", WS_OVERLAPPEDWINDOW, 20, 20, 300, 300, NULL, NULL, 0, NULL); + ok (hWnd != 0 , "CreateWindowW failed\n"); + + ret = OpenClipboard(hWnd); + ok (ret, "OpenClipboard failed\n"); + + hWndClipOwner = GetClipboardOwner(); + ok (hWndClipOwner == NULL, "Expected NULL owner\n"); + + ret = EmptyClipboard(); + ok (ret, "EmptyClipboard failed\n"); + + ret = CloseClipboard(); + ok (ret, "CloseClipboard failed\n"); + + hWndClipOwner = GetClipboardOwner(); + ok (hWndClipOwner == hWnd, "Expected hWnd owner\n"); + + DestroyWindow(hWnd); +} + +START_TEST(EmptyClipboard) +{ + TestOwnership(); + TestMessages(); +} diff --git a/rostests/apitests/user32/testlist.c b/rostests/apitests/user32/testlist.c index 74db3909e2f..494137a8c02 100644 --- a/rostests/apitests/user32/testlist.c +++ b/rostests/apitests/user32/testlist.c @@ -11,6 +11,7 @@ extern void func_DeferWindowPos(void); extern void func_DestroyCursorIcon(void); extern void func_DrawIconEx(void); extern void func_desktop(void); +extern void func_EmptyClipboard(void); extern void func_EnumDisplaySettings(void); extern void func_GetDCEx(void); extern void func_GetIconInfo(void); @@ -50,6 +51,7 @@ const struct test winetest_testlist[] = { "DestroyCursorIcon", func_DestroyCursorIcon }, { "DrawIconEx", func_DrawIconEx }, { "desktop", func_desktop }, + { "EmptyClipboard", func_EmptyClipboard }, { "EnumDisplaySettings", func_EnumDisplaySettings }, { "GetDCEx", func_GetDCEx }, { "GetIconInfo", func_GetIconInfo }, -- 2.17.1