From 933cb2d66d58e452121b090dcba7c82cf0dab780 Mon Sep 17 00:00:00 2001 From: Giannis Adamopoulos Date: Mon, 13 Aug 2012 18:04:04 +0000 Subject: [PATCH] [user32_apitest] - Add support for logging messages in different threads - Add several tests for AttachThreadInput svn path=/trunk/; revision=57074 --- rostests/apitests/user32/AttachThreadInput.c | 614 ++++++++++++++++++ rostests/apitests/user32/CMakeLists.txt | 1 + rostests/apitests/user32/DeferWindowPos.c | 12 +- rostests/apitests/user32/SetActiveWindow.c | 8 +- .../apitests/user32/SystemParametersInfo.c | 6 +- rostests/apitests/user32/TrackMouseEvent.c | 12 +- rostests/apitests/user32/helper.c | 67 +- rostests/apitests/user32/helper.h | 26 +- rostests/apitests/user32/testlist.c | 2 + 9 files changed, 689 insertions(+), 59 deletions(-) create mode 100644 rostests/apitests/user32/AttachThreadInput.c diff --git a/rostests/apitests/user32/AttachThreadInput.c b/rostests/apitests/user32/AttachThreadInput.c new file mode 100644 index 00000000000..c313779760b --- /dev/null +++ b/rostests/apitests/user32/AttachThreadInput.c @@ -0,0 +1,614 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPL - See COPYING in the top level directory + * PURPOSE: Test for AttachThreadInput + * PROGRAMMERS: Giannis Adamopoulos + */ + +#include +#include +#include +#include "helper.h" +#include + +#define DESKTOP_ALL_ACCESS 0x01ff + +typedef struct { + DWORD tid; + HANDLE hThread; + HWND hWnd; + WCHAR* Desktop; + HANDLE StartEvent; + HANDLE QueueStatusEvent; + DWORD LastQueueStatus; + + MSG_CACHE cache; +} THREAD_DATA; + +DWORD tidMouseMove; +THREAD_DATA data[5]; +HHOOK hMouseHookLL = NULL; +HHOOK hKbdHookLL = NULL; + + +#define EXPECT_FOREGROUND(expected) ok(GetForegroundWindow() == expected, \ + "Expected hwnd%d at the foreground, got hwnd%d\n", \ + get_iwnd(expected), get_iwnd(GetForegroundWindow())); + +#define EXPECT_ACTIVE(expected) ok(GetActiveWindow() == expected, \ + "Expected hwnd%d to be active, got hwnd%d\n", \ + get_iwnd(expected), get_iwnd(GetActiveWindow())); + +/* + * Helper functions + */ + +static int get_iwnd(HWND hWnd) +{ + if(hWnd == data[0].hWnd) return 0; + else if(hWnd == data[1].hWnd) return 1; + else if(hWnd == data[2].hWnd) return 2; + else if(hWnd == data[3].hWnd) return 3; + else if(hWnd == data[4].hWnd) return 4; + else return -1; +} + +LRESULT CALLBACK TestProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int iwnd = get_iwnd(hWnd); + + if(iwnd >= 0 && message > 0 && message < WM_APP && message != WM_TIMER) + record_message(&data[iwnd].cache, iwnd, message, SENT, wParam,0); + + return DefWindowProc(hWnd, message, wParam, lParam); +} + +static void FlushMessages() +{ + MSG msg; + + while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) + { + int iwnd = get_iwnd(msg.hwnd); + if( iwnd >= 0 && msg.message > 0 && msg.message < WM_APP && msg.message != WM_TIMER) + record_message(&data[0].cache, iwnd, msg.message, POST, msg.wParam,0); + DispatchMessageA( &msg ); + } + + /* Use SendMessage to sync with the other queues */ + SendMessage(data[1].hWnd, WM_APP, 0,0); + SendMessage(data[2].hWnd, WM_APP, 0,0); + SendMessage(data[3].hWnd, WM_APP, 0,0); + SendMessage(data[4].hWnd, WM_APP, 0,0); +} + +static DWORD WINAPI thread_proc(void *param) +{ + THREAD_DATA* current_data = (THREAD_DATA*)param; + MSG msg; + HDESK hdesk = NULL; + int iwnd; + + if(current_data->Desktop) + { + hdesk = CreateDesktopW(current_data->Desktop, NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL ); + SetThreadDesktop(hdesk); + ok(GetThreadDesktop(current_data->tid) == hdesk, "Thread in wrong desktop. Following results may be bogus!\n"); + } + + /* create test window */ + current_data->hWnd = CreateWindowW(L"TestClass", L"test", WS_OVERLAPPEDWINDOW, + 100, 100, 500, 500, NULL, NULL, 0, NULL); + SetEvent( current_data->StartEvent ); + + iwnd = get_iwnd(current_data->hWnd); + + /* Use MsgWaitForMultipleObjects to let the thread process apcs */ + while( GetMessage(&msg, 0,0,0) ) + { + if(msg.message > 0 && msg.message < WM_APP && msg.message != WM_TIMER ) + record_message(&data[iwnd].cache, iwnd, msg.message, POST, msg.wParam,0); + DispatchMessage(&msg); + } + + if(hdesk) + CloseDesktop(hdesk); + + return 0; +} + +BOOL CreateTestThread(int i, WCHAR* Desktop) +{ + DWORD ret; + + data[i].StartEvent = CreateEventW(NULL, 0, 0, NULL); + data[i].Desktop = Desktop; + data[i].hThread = CreateThread(NULL, 0, thread_proc, &data[i], 0, &data[i].tid); + if(!data[i].hThread) goto fail; + ret = WaitForSingleObject(data[i].StartEvent, 1000); + CloseHandle(data[i].StartEvent); + if(ret == WAIT_TIMEOUT) + { +fail: + win_skip("child thread failed to initialize\n"); + return FALSE; + } + return TRUE; +} + +static LRESULT CALLBACK MouseLLHookProc(int nCode, WPARAM wParam, LPARAM lParam) +{ + LRESULT ret; + MSLLHOOKSTRUCT* params = (MSLLHOOKSTRUCT*) lParam; + + ret = CallNextHookEx(hMouseHookLL, nCode, wParam, lParam); + + if((params->flags & LLKHF_INJECTED) == 0) + return TRUE; + + return ret; +} + +LRESULT CALLBACK KbdLLHookProc(int nCode, WPARAM wParam, LPARAM lParam) +{ + LRESULT ret; + KBDLLHOOKSTRUCT* params = (KBDLLHOOKSTRUCT*) lParam; + + ret = CallNextHookEx(hMouseHookLL, nCode, wParam, lParam); + + if((params->flags & LLKHF_INJECTED) == 0) + return TRUE; + + return ret; +} + +BOOLEAN InitThreads() +{ + /* Create a LL hook that drops any physical keyboard and mouse action + and prevent the user from interfering with the test results */ + if(!IsDebuggerPresent()) + { + hMouseHookLL = SetWindowsHookExW(WH_MOUSE_LL, MouseLLHookProc, GetModuleHandleW( NULL ), 0); + ok(hMouseHookLL!=NULL,"failed to set hook\n"); + hKbdHookLL = SetWindowsHookExW(WH_KEYBOARD_LL, KbdLLHookProc, GetModuleHandleW( NULL ), 0); + ok(hKbdHookLL!=NULL,"failed to set hook\n"); + } + + /* create test clases */ + RegisterSimpleClass(TestProc, L"TestClass"); + + memset(&data[0], 0, sizeof(data[0])); + + data[0].tid = GetCurrentThreadId(); + + /* create test window */ + data[0].hWnd = CreateWindowW(L"TestClass", L"test", WS_OVERLAPPEDWINDOW, + 100, 100, 500, 500, NULL, NULL, 0, NULL); + if(!data[0].hWnd) + { + win_skip("CreateWindowW failed\n"); + return FALSE; + } + + /* create thread1(same desktop) */ + if(!CreateTestThread(1, NULL)) return FALSE; + + /* create thread2(same desktop) */ + if(!CreateTestThread(2, NULL)) return FALSE; + + /* create thread3(different desktop) */ + if(!CreateTestThread(3, L"ThreadTestDesktop")) return FALSE; + + /* create thread4(different desktop) */ + if(!CreateTestThread(4, L"ThreadTestDesktop")) return FALSE; + + return TRUE; +} + + + + +/* + * The actual tests + */ + +void Test_SimpleParameters() +{ + BOOL ret; + /* FIXME: acording to msdn xp doesn't set last error but vista+ does*/ + + /* test wrong thread */ + ret = AttachThreadInput( 0, 1, TRUE); + ok(ret==0, "expected AttachThreadInput to fail\n"); + + /* test same thread */ + ret = AttachThreadInput( data[1].tid, data[1].tid, TRUE); + ok(ret==0, "expected AttachThreadInput to fail\n"); + + /* try to attach to a thread on another desktop*/ + ret = AttachThreadInput( data[2].tid,data[3].tid, TRUE); + ok(ret==0, "expected AttachThreadInput to fail\n"); + + /* test other desktop to this */ + ret = AttachThreadInput( data[3].tid,data[2].tid, TRUE); + ok(ret==0, "expected AttachThreadInput to fail\n"); + + /* attach two threads that are both in ThreadTestDesktop */ + { + /* Attach thread 3 and 4 */ + ret = AttachThreadInput( data[3].tid,data[4].tid, TRUE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + + /* cleanup previous attachment */ + ret = AttachThreadInput( data[3].tid,data[4].tid, FALSE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + } + + { + /* Attach thread 1 and 2 */ + ret = AttachThreadInput( data[1].tid,data[2].tid, TRUE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + + /* attach already attached*/ + ret = AttachThreadInput( data[1].tid,data[2].tid, TRUE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + + /* Now try to detach 0 from 1 */ + ret = AttachThreadInput( data[0].tid,data[1].tid, FALSE); + ok(ret==0, "expected AttachThreadInput to fail\n"); + + /* also try to detach 3 from 2 */ + ret = AttachThreadInput( data[2].tid,data[1].tid, FALSE); + ok(ret==0, "expected AttachThreadInput to fail\n"); + + /* cleanup previous attachment */ + ret = AttachThreadInput( data[1].tid,data[2].tid, FALSE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + } + + /*too bad this causes a crash in win32k */ +#if 0 + /* test triple attach */ + { + ret = AttachThreadInput( data[0].tid, data[1].tid, TRUE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + ret = AttachThreadInput( data[1].tid, data[2].tid, TRUE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + + /* try to detach 2 and 0 */ + ret = AttachThreadInput( data[0].tid, data[2].tid, FALSE); + ok(ret==0, "expected AttachThreadInput to fail\n"); + ret = AttachThreadInput( data[2].tid, data[0].tid, FALSE); + ok(ret==0, "expected AttachThreadInput to fail\n"); + + /* try to to attach 0 to 2. it works! */ + ret = AttachThreadInput( data[0].tid, data[2].tid, TRUE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + + ret = AttachThreadInput( data[0].tid, data[2].tid, FALSE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + + /* detach in inverse order */ + ret = AttachThreadInput( data[0].tid, data[1].tid, FALSE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + ret = AttachThreadInput( data[1].tid, data[2].tid, FALSE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + } +#endif +} + +void Test_Focus() //Focus Active Capture Foreground Capture +{ + BOOL ret; + + /* Window 1 is in the foreground */ + SetForegroundWindow(data[1].hWnd); + SetActiveWindow(data[0].hWnd); + FlushMessages(); + + EXPECT_FOREGROUND(data[1].hWnd); + EXPECT_ACTIVE(data[0].hWnd); + + /* attach thread 0 to 1 */ + { + ret = AttachThreadInput( data[0].tid, data[1].tid , TRUE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + FlushMessages(); + + EXPECT_FOREGROUND(data[1].hWnd); + EXPECT_ACTIVE(data[1].hWnd); + + ret = AttachThreadInput( data[0].tid, data[1].tid , FALSE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + } + + EXPECT_FOREGROUND(data[1].hWnd); + EXPECT_ACTIVE(0); + + SetForegroundWindow(data[1].hWnd); + SetActiveWindow(data[0].hWnd); + FlushMessages(); + + EXPECT_FOREGROUND(data[1].hWnd); + EXPECT_ACTIVE(data[0].hWnd); + + /* attach thread 1 to 0 */ + { + ret = AttachThreadInput( data[1].tid, data[0].tid , TRUE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + FlushMessages(); + + EXPECT_FOREGROUND(data[1].hWnd); + EXPECT_ACTIVE(data[1].hWnd); + + ret = AttachThreadInput( data[1].tid, data[0].tid , FALSE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + } + + /* Window 0 is in the foreground */ + SetForegroundWindow(data[0].hWnd); + SetActiveWindow(data[1].hWnd); + FlushMessages(); + + EXPECT_FOREGROUND(data[0].hWnd); + EXPECT_ACTIVE(data[0].hWnd); + + /* attach thread 0 to 1 */ + { + ret = AttachThreadInput( data[0].tid, data[1].tid , TRUE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + FlushMessages(); + + EXPECT_FOREGROUND(data[0].hWnd); + EXPECT_ACTIVE(data[0].hWnd); + + SetForegroundWindow(data[0].hWnd); + SetActiveWindow(data[1].hWnd); + FlushMessages(); + + EXPECT_FOREGROUND(data[1].hWnd); + EXPECT_ACTIVE(data[1].hWnd); + + ret = AttachThreadInput( data[0].tid, data[1].tid , FALSE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + } + + EXPECT_FOREGROUND(data[1].hWnd); + EXPECT_ACTIVE(0); + + SetForegroundWindow(data[0].hWnd); + SetActiveWindow(data[1].hWnd); + FlushMessages(); + + EXPECT_FOREGROUND(data[0].hWnd); + EXPECT_ACTIVE(data[0].hWnd); + + /* attach thread 1 to 0 */ + { + ret = AttachThreadInput( data[1].tid, data[0].tid , TRUE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + FlushMessages(); + + EXPECT_FOREGROUND(data[0].hWnd); + EXPECT_ACTIVE(data[0].hWnd); + + SetForegroundWindow(data[0].hWnd); + SetActiveWindow(data[1].hWnd); + FlushMessages(); + + EXPECT_FOREGROUND(data[1].hWnd); + EXPECT_ACTIVE(data[1].hWnd); + + ret = AttachThreadInput( data[1].tid, data[0].tid , FALSE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + } +} + +/* test some functions like PostMessage and SendMessage that shouldn't be affected */ +void Test_UnaffectedMessages() +{ + BOOL ret; + + EMPTY_CACHE_(&data[0].cache); + EMPTY_CACHE_(&data[1].cache); + + /* test that messages posted before and after attachment are unaffected + and that we don't receive a meassage from a window we shouldn't */ + PostMessage(data[0].hWnd, WM_USER, 0,0); + PostMessage(data[1].hWnd, WM_USER, 1,0); + + { + MSG_ENTRY Thread0_chain[]={ + {0,WM_USER, POST, 0, 0}, + {0,WM_USER, POST, 2, 0}, + {0,0}}; + MSG_ENTRY Thread1_chain[]={ + {1,WM_USER, POST, 1, 0}, + {1,WM_USER, POST, 3, 0}, + {0,0}}; + + ret = AttachThreadInput( data[1].tid, data[0].tid , TRUE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + + PostMessage(data[0].hWnd, WM_USER, 2,0); + PostMessage(data[1].hWnd, WM_USER, 3,0); + + FlushMessages(); + Sleep(100); + + COMPARE_CACHE_(&data[0].cache, Thread0_chain); + COMPARE_CACHE_(&data[1].cache, Thread1_chain); + + ret = AttachThreadInput( data[1].tid, data[0].tid , FALSE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + } + + /* test messages send to the wrong thread */ + SendMessage(data[0].hWnd, WM_USER, 0,0); + SendMessage(data[1].hWnd, WM_USER, 1,0); + + { + MSG_ENTRY Thread0_chain[]={ + {0,WM_USER, SENT, 0, 0}, + {0,WM_USER, SENT, 2, 0}, + {0,0}}; + MSG_ENTRY Thread1_chain[]={ + {1,WM_USER, SENT, 1, 0}, + {1,WM_USER, SENT, 3, 0}, + {1,WM_MOUSEMOVE, SENT, 0, 0}, + {0,0}}; + + ret = AttachThreadInput( data[2].tid, data[1].tid , TRUE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + + SendMessage(data[0].hWnd, WM_USER, 2,0); + SendMessage(data[1].hWnd, WM_USER, 3,0); + + /* Try to send a fake input message */ + SendMessage(data[1].hWnd, WM_MOUSEMOVE, 0,0); + + COMPARE_CACHE_(&data[0].cache, Thread0_chain); + COMPARE_CACHE_(&data[1].cache, Thread1_chain); + + ret = AttachThreadInput( data[2].tid, data[1].tid , FALSE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + } + + /* todo: test keyboard layout that shouldn't be affected */ +} + +void Test_SendInput() +{ + MSG_ENTRY Thread1_chain[]={ + {1,WM_KEYDOWN, POST, VK_SHIFT, 0}, + {1,WM_KEYUP, POST, VK_SHIFT, 0}, + {0,0}}; + MSG_ENTRY Thread0_chain[]={ + {0,WM_KEYDOWN, POST, VK_SHIFT, 0}, + {0,WM_KEYUP, POST, VK_SHIFT, 0}, + {0,0}}; + + BOOL ret; + + /* First try sending input without attaching. It will go to the foreground */ + { + SetForegroundWindow(data[1].hWnd); + SetActiveWindow(data[0].hWnd); + + ok(GetForegroundWindow() == data[1].hWnd, "wrong foreground\n"); + ok(GetActiveWindow() == data[0].hWnd, "wrong active\n"); + + FlushMessages(); + EMPTY_CACHE_(&data[0].cache); + EMPTY_CACHE_(&data[1].cache); + + keybd_event(VK_SHIFT, 0,0,0); + keybd_event(VK_SHIFT, 0,KEYEVENTF_KEYUP,0); + Sleep(100); + FlushMessages(); + + COMPARE_CACHE_(&data[0].cache, empty_chain); + COMPARE_CACHE_(&data[1].cache, Thread1_chain); + } + + /* Next attach and send input. It will go to the same thread as before */ + { + ret = AttachThreadInput( data[1].tid, data[0].tid , TRUE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + + FlushMessages(); + EMPTY_CACHE_(&data[0].cache); + EMPTY_CACHE_(&data[1].cache); + + keybd_event(VK_SHIFT, 0,0,0); + keybd_event(VK_SHIFT, 0,KEYEVENTF_KEYUP,0); + Sleep(100); + FlushMessages(); + + COMPARE_CACHE_(&data[0].cache, empty_chain); + COMPARE_CACHE_(&data[1].cache, Thread1_chain); + } + + /* Now set foregroung and active again. Input will go to thread 0 */ + { + SetForegroundWindow(data[1].hWnd); + SetActiveWindow(data[0].hWnd); + + FlushMessages(); + EMPTY_CACHE_(&data[0].cache); + EMPTY_CACHE_(&data[1].cache); + + keybd_event(VK_SHIFT, 0,0,0); + keybd_event(VK_SHIFT, 0,KEYEVENTF_KEYUP,0); + Sleep(100); + FlushMessages(); + + COMPARE_CACHE_(&data[0].cache, Thread0_chain); + COMPARE_CACHE_(&data[1].cache, empty_chain); + + ret = AttachThreadInput( data[1].tid, data[0].tid , FALSE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + } + + /* Attach in the opposite order and send input */ + { + ret = AttachThreadInput( data[0].tid, data[1].tid , TRUE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + + FlushMessages(); + EMPTY_CACHE_(&data[0].cache); + EMPTY_CACHE_(&data[1].cache); + + keybd_event(VK_SHIFT, 0,0,0); + keybd_event(VK_SHIFT, 0,KEYEVENTF_KEYUP,0); + Sleep(100); + FlushMessages(); + + COMPARE_CACHE_(&data[0].cache, Thread0_chain); + COMPARE_CACHE_(&data[1].cache, empty_chain); + } + + /* Now set foregroung and active again. Input will go to thread 0 */ + { + SetForegroundWindow(data[1].hWnd); + SetActiveWindow(data[0].hWnd); + + FlushMessages(); + EMPTY_CACHE_(&data[0].cache); + EMPTY_CACHE_(&data[1].cache); + + keybd_event(VK_SHIFT, 0,0,0); + keybd_event(VK_SHIFT, 0,KEYEVENTF_KEYUP,0); + Sleep(100); + FlushMessages(); + + COMPARE_CACHE_(&data[0].cache, Thread0_chain); + COMPARE_CACHE_(&data[1].cache, empty_chain); + + ret = AttachThreadInput( data[0].tid, data[1].tid , FALSE); + ok(ret==1, "expected AttachThreadInput to succeed\n"); + } +} + +START_TEST(AttachThreadInput) +{ + if(!InitThreads()) + return; + + Test_SimpleParameters(); + Test_Focus(); + Test_UnaffectedMessages(); + Test_SendInput(); + + if(hMouseHookLL) + UnhookWindowsHookEx(hMouseHookLL); + if(hKbdHookLL) + UnhookWindowsHookEx(hKbdHookLL); + + /* Stop all threads and exit gratefully */ + PostThreadMessage(data[1].tid, WM_QUIT,0,0); + PostThreadMessage(data[2].tid, WM_QUIT,0,0); + PostThreadMessage(data[3].tid, WM_QUIT,0,0); + PostThreadMessage(data[4].tid, WM_QUIT,0,0); +} + diff --git a/rostests/apitests/user32/CMakeLists.txt b/rostests/apitests/user32/CMakeLists.txt index a83c34bc59b..4613c22b638 100644 --- a/rostests/apitests/user32/CMakeLists.txt +++ b/rostests/apitests/user32/CMakeLists.txt @@ -1,5 +1,6 @@ list(APPEND SOURCE + AttachThreadInput.c helper.c DeferWindowPos.c desktop.c diff --git a/rostests/apitests/user32/DeferWindowPos.c b/rostests/apitests/user32/DeferWindowPos.c index b8468ff0674..65f28f01973 100644 --- a/rostests/apitests/user32/DeferWindowPos.c +++ b/rostests/apitests/user32/DeferWindowPos.c @@ -42,11 +42,11 @@ LRESULT CALLBACK DWPTestProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar { WINDOWPOS* pwp = (WINDOWPOS*)lParam; ok(wParam==0,"expected wParam=0\n"); - record_message(iwnd, message, SENT, get_iwnd(pwp->hwndInsertAfter), pwp->flags); + RECOND_MESSAGE(iwnd, message, SENT, get_iwnd(pwp->hwndInsertAfter), pwp->flags); break; } default: - record_message(iwnd, message, SENT, 0,0); + RECOND_MESSAGE(iwnd, message, SENT, 0,0); } return DefWindowProc(hWnd, message, wParam, lParam); } @@ -59,7 +59,7 @@ static void FlushMessages() { int iwnd = get_iwnd(msg.hwnd); if(!(msg.message > WM_USER || !iwnd || IsDWmMsg(msg.message) || IseKeyMsg(msg.message))) - record_message(iwnd, msg.message, POST,0,0); + RECOND_MESSAGE(iwnd, msg.message, POST,0,0); DispatchMessageA( &msg ); } } @@ -105,7 +105,7 @@ static void set_default_pos() SetWindowPos(hWnd4, 0, 250,250,200,200, SWP_NOOWNERZORDER|SWP_SHOWWINDOW|SWP_NOACTIVATE); SetActiveWindow(hWnd4); FlushMessages(); - empty_message_cache(); + EMPTY_CACHE(); } static void Test_DWP_Error(HWND hWnd, HWND hWnd2) @@ -248,7 +248,7 @@ static void Test_DWP_Error(HWND hWnd, HWND hWnd2) ok_windowpos(hWnd2, 70, 80, 250, 260, "Window 2"); FlushMessages(); - empty_message_cache(); + EMPTY_CACHE(); } MSG_ENTRY move1_chain[]={ @@ -299,7 +299,7 @@ static void Test_DWP_SimpleMsg(HWND hWnd1, HWND hWnd2) SetWindowPos(hWnd1, 0, 10,20,100,100,0); SetWindowPos(hWnd2, 0, 10,20,100,100,0); FlushMessages(); - empty_message_cache(); + EMPTY_CACHE(); /* move hWnd1 */ hdwp = BeginDeferWindowPos(1); diff --git a/rostests/apitests/user32/SetActiveWindow.c b/rostests/apitests/user32/SetActiveWindow.c index cfb7a38df31..f53bf135c57 100644 --- a/rostests/apitests/user32/SetActiveWindow.c +++ b/rostests/apitests/user32/SetActiveWindow.c @@ -48,11 +48,11 @@ LRESULT CALLBACK OwnerTestProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lP { WINDOWPOS* pwp = (WINDOWPOS*)lParam; ok(wParam==0,"expected wParam=0\n"); - record_message(iwnd, message, SENT, get_iwnd(pwp->hwndInsertAfter), pwp->flags); + RECOND_MESSAGE(iwnd, message, SENT, get_iwnd(pwp->hwndInsertAfter), pwp->flags); break; } default: - record_message(iwnd, message, SENT, 0,0); + RECOND_MESSAGE(iwnd, message, SENT, 0,0); } return DefWindowProc(hWnd, message, wParam, lParam); } @@ -65,7 +65,7 @@ static void FlushMessages() { int iwnd = get_iwnd(msg.hwnd); if(!(msg.message > WM_USER || !iwnd || IsDWmMsg(msg.message) || IseKeyMsg(msg.message))) - record_message(iwnd, msg.message, POST,0,0); + RECOND_MESSAGE(iwnd, msg.message, POST,0,0); DispatchMessageA( &msg ); } } @@ -86,7 +86,7 @@ static void set_default_zorder() SetWindowPos(hWnd2, 0, 0,0,0,0, SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_SHOWWINDOW); FlushMessages(); - empty_message_cache(); + EMPTY_CACHE(); } static void destroy_test_window() diff --git a/rostests/apitests/user32/SystemParametersInfo.c b/rostests/apitests/user32/SystemParametersInfo.c index 506ee89742d..5616665532a 100644 --- a/rostests/apitests/user32/SystemParametersInfo.c +++ b/rostests/apitests/user32/SystemParametersInfo.c @@ -38,11 +38,11 @@ LRESULT CALLBACK SysParamsTestProc(HWND hWnd, UINT message, WPARAM wParam, LPARA { WINDOWPOS* pwp = (WINDOWPOS*)lParam; ok(wParam==0,"expected wParam=0\n"); - record_message(iwnd, message, SENT, get_iwnd(pwp->hwndInsertAfter), pwp->flags); + RECOND_MESSAGE(iwnd, message, SENT, get_iwnd(pwp->hwndInsertAfter), pwp->flags); break; } default: - record_message(iwnd, message, SENT, 0,0); + RECOND_MESSAGE(iwnd, message, SENT, 0,0); } return DefWindowProc(hWnd, message, wParam, lParam); } @@ -55,7 +55,7 @@ static void FlushMessages() { int iwnd = get_iwnd(msg.hwnd); if(!(msg.message > WM_USER || !iwnd || IsDWmMsg(msg.message) || IseKeyMsg(msg.message))) - record_message(iwnd, msg.message, POST,0,0); + RECOND_MESSAGE(iwnd, msg.message, POST,0,0); DispatchMessageA( &msg ); } } diff --git a/rostests/apitests/user32/TrackMouseEvent.c b/rostests/apitests/user32/TrackMouseEvent.c index 03a31cdcc67..417ed6fd816 100644 --- a/rostests/apitests/user32/TrackMouseEvent.c +++ b/rostests/apitests/user32/TrackMouseEvent.c @@ -49,7 +49,7 @@ LRESULT CALLBACK TmeTestProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar ok(0, "Got unexpected WM_SYSTIMER in the winproc. wParam=%d\n", wParam); break; default: - record_message(iwnd, message, SENT, 0,0); + RECOND_MESSAGE(iwnd, message, SENT, 0,0); } return DefWindowProc(hWnd, message, wParam, lParam); } @@ -57,7 +57,7 @@ LRESULT CALLBACK TmeTestProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar static LRESULT CALLBACK MouseLLHookProc(int nCode, WPARAM wParam, LPARAM lParam) { LRESULT ret; - record_message(0, WH_MOUSE_LL, HOOK, wParam, 0); + RECOND_MESSAGE(0, WH_MOUSE_LL, HOOK, wParam, 0); ret = CallNextHookEx(hMouseHookLL, nCode, wParam, lParam); if(ignore_mousell) return TRUE; @@ -68,7 +68,7 @@ static LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) { MOUSEHOOKSTRUCT *hs = (MOUSEHOOKSTRUCT*) lParam; LRESULT ret; - record_message(get_iwnd(hs->hwnd), WH_MOUSE, HOOK, wParam, hs->wHitTestCode); + RECOND_MESSAGE(get_iwnd(hs->hwnd), WH_MOUSE, HOOK, wParam, hs->wHitTestCode); ret = CallNextHookEx(hMouseHook, nCode, wParam, lParam); if(ignore_mouse) return TRUE; @@ -86,12 +86,12 @@ static void FlushMessages() { if(msg.message == WM_SYSTIMER) { - record_message(iwnd, msg.message, POST,msg.wParam,0); + RECOND_MESSAGE(iwnd, msg.message, POST,msg.wParam,0); if(ignore_timer) continue; } else if(!(msg.message > WM_USER || !iwnd || IsDWmMsg(msg.message) || IseKeyMsg(msg.message))) - record_message(iwnd, msg.message, POST,0,0); + RECOND_MESSAGE(iwnd, msg.message, POST,0,0); } DispatchMessageA( &msg ); } @@ -265,7 +265,7 @@ void Test_TrackMouseEvent() MOVE_CURSOR(0,0); create_test_windows(); FlushMessages(); - empty_message_cache(); + EMPTY_CACHE(); /* the mouse moves over hwnd2 */ MOVE_CURSOR(220,220); diff --git a/rostests/apitests/user32/helper.c b/rostests/apitests/user32/helper.c index 7899913e490..c59a25694ad 100644 --- a/rostests/apitests/user32/helper.c +++ b/rostests/apitests/user32/helper.c @@ -11,10 +11,11 @@ #include "helper.h" #include -MSG_ENTRY last_post_message; -MSG_ENTRY message_cache[100]; -static int message_cache_size = 0; - +MSG_CACHE default_cache = { +#ifdef _MSC_VER + 0 +#endif +}; MSG_ENTRY empty_chain[]= {{0,0}}; static char* get_msg_name(UINT msg) @@ -48,6 +49,8 @@ static char* get_msg_name(UINT msg) case WM_SETTINGCHANGE: return "WM_SETTINGCHANGE"; case WM_GETICON: return "WM_GETICON"; case WM_SETICON: return "WM_SETICON"; + case WM_KEYDOWN: return "WM_KEYDOWN"; + case WM_KEYUP: return "WM_KEYUP"; default: return NULL; } } @@ -64,11 +67,9 @@ static char* get_hook_name(UINT id) } } -void empty_message_cache() +void empty_message_cache(MSG_CACHE* cache) { - memset(&last_post_message, 0, sizeof(last_post_message)); - memset(message_cache, 0, sizeof(message_cache)); - message_cache_size = 0; + memset(cache, 0, sizeof(MSG_CACHE)); } void sprintf_msg_entry(char* buffer, MSG_ENTRY* msg) @@ -111,20 +112,20 @@ void sprintf_msg_entry(char* buffer, MSG_ENTRY* msg) } } -void trace_cache(const char* file, int line) +void trace_cache(MSG_CACHE* cache, const char* file, int line) { int i; char buff[100]; - for (i=0; i < message_cache_size; i++) + for (i=0; i < cache->count; i++) { - sprintf_msg_entry(buff, &message_cache[i]); + sprintf_msg_entry(buff, &cache->message_cache[i]); trace_(file,line)("%d: %s\n", i, buff); } trace_(file,line)("\n"); } -void compare_cache(const char* file, int line, MSG_ENTRY *msg_chain) +void compare_cache(MSG_CACHE* cache, const char* file, int line, MSG_ENTRY *msg_chain) { int i = 0; char buffGot[100], buffExp[100]; @@ -132,9 +133,9 @@ void compare_cache(const char* file, int line, MSG_ENTRY *msg_chain) while(1) { - BOOL same = !memcmp(&message_cache[i],msg_chain, sizeof(MSG_ENTRY)); + BOOL same = !memcmp(&cache->message_cache[i],msg_chain, sizeof(MSG_ENTRY)); - sprintf_msg_entry(buffGot, &message_cache[i]); + sprintf_msg_entry(buffGot, &cache->message_cache[i]); sprintf_msg_entry(buffExp, msg_chain); ok_(file,line)(same,"%d: got %s, expected %s\n",i, buffGot, buffExp); @@ -145,7 +146,7 @@ void compare_cache(const char* file, int line, MSG_ENTRY *msg_chain) msg_chain++; else { - if(i>message_cache_size) + if(i > cache->count) break; } i++; @@ -154,46 +155,46 @@ void compare_cache(const char* file, int line, MSG_ENTRY *msg_chain) if(got_error ) { trace_(file,line)("The complete list of messages got is:\n"); - trace_cache(file,line); + trace_cache(cache, file,line); } - empty_message_cache(); + empty_message_cache(cache); } -void record_message(int iwnd, UINT message, MSG_TYPE type, int param1,int param2) +void record_message(MSG_CACHE* cache, int iwnd, UINT message, MSG_TYPE type, int param1,int param2) { - if(message_cache_size>=100) + if(cache->count >= 100) { return; } /* do not report a post message a second time */ if(type == SENT && - last_post_message.iwnd == iwnd && - last_post_message.msg == message && - last_post_message.param1 == param1 && - last_post_message.param2 == param2) + cache->last_post_message.iwnd == iwnd && + cache->last_post_message.msg == message && + cache->last_post_message.param1 == param1 && + cache->last_post_message.param2 == param2) { - memset(&last_post_message, 0, sizeof(last_post_message)); + memset(&cache->last_post_message, 0, sizeof(MSG_ENTRY)); return; } - message_cache[message_cache_size].iwnd = iwnd; - message_cache[message_cache_size].msg = message; - message_cache[message_cache_size].type = type; - message_cache[message_cache_size].param1 = param1; - message_cache[message_cache_size].param2 = param2; + cache->message_cache[cache->count].iwnd = iwnd; + cache->message_cache[cache->count].msg = message; + cache->message_cache[cache->count].type = type; + cache->message_cache[cache->count].param1 = param1; + cache->message_cache[cache->count].param2 = param2; - if(message_cache[message_cache_size].type == POST) + if(cache->message_cache[cache->count].type == POST) { - last_post_message = message_cache[message_cache_size]; + cache->last_post_message = cache->message_cache[cache->count]; } else { - memset(&last_post_message, 0, sizeof(last_post_message)); + memset(&cache->last_post_message, 0, sizeof(MSG_ENTRY)); } - message_cache_size++; + cache->count++; } ATOM RegisterSimpleClass(WNDPROC lpfnWndProc, LPCWSTR lpszClassName) diff --git a/rostests/apitests/user32/helper.h b/rostests/apitests/user32/helper.h index 246c1c914d1..5221c645d35 100644 --- a/rostests/apitests/user32/helper.h +++ b/rostests/apitests/user32/helper.h @@ -16,13 +16,21 @@ typedef struct _MSG_ENTRY int param2; } MSG_ENTRY; +typedef struct _MSG_CACHE +{ + MSG_ENTRY last_post_message; + MSG_ENTRY message_cache[100]; + int count; +} MSG_CACHE; extern MSG_ENTRY empty_chain[]; +extern MSG_CACHE default_cache; + +void record_message(MSG_CACHE* cache, int iwnd, UINT message, MSG_TYPE type, int param1,int param2); +void compare_cache(MSG_CACHE* cache, const char* file, int line, MSG_ENTRY *msg_chain); +void trace_cache(MSG_CACHE* cache, const char* file, int line); +void empty_message_cache(MSG_CACHE* cache); -void record_message(int iwnd, UINT message, MSG_TYPE type, int param1,int param2); -void compare_cache(const char* file, int line, MSG_ENTRY *msg_chain); -void trace_cache(const char* file, int line); -void empty_message_cache(); ATOM RegisterSimpleClass(WNDPROC lpfnWndProc, LPCWSTR lpszClassName); /* filter messages that are affected by dwm */ @@ -44,10 +52,14 @@ static inline BOOL IseKeyMsg(UINT msg) return (msg == WM_KEYUP || msg == WM_KEYDOWN); } -#define COMPARE_CACHE(...) compare_cache(__FILE__, __LINE__, ##__VA_ARGS__) -#define TRACE_CACHE() trace_cache(__FILE__, __LINE__) +#define COMPARE_CACHE(msg_chain) compare_cache(&default_cache, __FILE__, __LINE__, msg_chain) +#define TRACE_CACHE() trace_cache(&default_cache, __FILE__, __LINE__) +#define EMPTY_CACHE() empty_message_cache(&default_cache); +#define RECOND_MESSAGE(...) record_message(&default_cache, ##__VA_ARGS__); -#define EXPECT_ACTIVE(hwnd) ok(GetActiveWindow() == hwnd, "Expected %p to be the active window, not %p\n",hwnd,GetActiveWindow()) +#define COMPARE_CACHE_(cache, msg_chain) compare_cache(cache, __FILE__, __LINE__, msg_chain) +#define TRACE_CACHE_(cache) trace_cache(cache, __FILE__, __LINE__) +#define EMPTY_CACHE_(cache) empty_message_cache(cache); #define EXPECT_QUEUE_STATUS(expected, notexpected) \ { \ diff --git a/rostests/apitests/user32/testlist.c b/rostests/apitests/user32/testlist.c index 4202ab13649..6857b95b874 100644 --- a/rostests/apitests/user32/testlist.c +++ b/rostests/apitests/user32/testlist.c @@ -5,6 +5,7 @@ #define STANDALONE #include "wine/test.h" +extern void func_AttachThreadInput(void); extern void func_DeferWindowPos(void); extern void func_desktop(void); extern void func_GetIconInfo(void); @@ -24,6 +25,7 @@ extern void func_wsprintf(void); const struct test winetest_testlist[] = { + { "AttachThreadInput", func_AttachThreadInput }, { "desktop", func_desktop }, { "DeferWindowPos", func_DeferWindowPos }, { "GetIconInfo", func_GetIconInfo },