[user32_apitest]

- Add support for logging messages in different threads
- Add several tests for AttachThreadInput

svn path=/trunk/; revision=57074
This commit is contained in:
Giannis Adamopoulos 2012-08-13 18:04:04 +00:00
parent 8d682ab52c
commit 933cb2d66d
9 changed files with 689 additions and 59 deletions

View file

@ -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 <windows.h>
#include <stdio.h>
#include <wine/test.h>
#include "helper.h"
#include <undocuser.h>
#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);
}

View file

@ -1,5 +1,6 @@
list(APPEND SOURCE
AttachThreadInput.c
helper.c
DeferWindowPos.c
desktop.c

View file

@ -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);

View file

@ -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()

View file

@ -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 );
}
}

View file

@ -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);

View file

@ -11,10 +11,11 @@
#include "helper.h"
#include <undocuser.h>
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)

View file

@ -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) \
{ \

View file

@ -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 },