mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 17:56:00 +00:00
[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:
parent
8d682ab52c
commit
933cb2d66d
9 changed files with 689 additions and 59 deletions
614
rostests/apitests/user32/AttachThreadInput.c
Normal file
614
rostests/apitests/user32/AttachThreadInput.c
Normal 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);
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
list(APPEND SOURCE
|
list(APPEND SOURCE
|
||||||
|
AttachThreadInput.c
|
||||||
helper.c
|
helper.c
|
||||||
DeferWindowPos.c
|
DeferWindowPos.c
|
||||||
desktop.c
|
desktop.c
|
||||||
|
|
|
@ -42,11 +42,11 @@ LRESULT CALLBACK DWPTestProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar
|
||||||
{
|
{
|
||||||
WINDOWPOS* pwp = (WINDOWPOS*)lParam;
|
WINDOWPOS* pwp = (WINDOWPOS*)lParam;
|
||||||
ok(wParam==0,"expected wParam=0\n");
|
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;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
record_message(iwnd, message, SENT, 0,0);
|
RECOND_MESSAGE(iwnd, message, SENT, 0,0);
|
||||||
}
|
}
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ static void FlushMessages()
|
||||||
{
|
{
|
||||||
int iwnd = get_iwnd(msg.hwnd);
|
int iwnd = get_iwnd(msg.hwnd);
|
||||||
if(!(msg.message > WM_USER || !iwnd || IsDWmMsg(msg.message) || IseKeyMsg(msg.message)))
|
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 );
|
DispatchMessageA( &msg );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ static void set_default_pos()
|
||||||
SetWindowPos(hWnd4, 0, 250,250,200,200, SWP_NOOWNERZORDER|SWP_SHOWWINDOW|SWP_NOACTIVATE);
|
SetWindowPos(hWnd4, 0, 250,250,200,200, SWP_NOOWNERZORDER|SWP_SHOWWINDOW|SWP_NOACTIVATE);
|
||||||
SetActiveWindow(hWnd4);
|
SetActiveWindow(hWnd4);
|
||||||
FlushMessages();
|
FlushMessages();
|
||||||
empty_message_cache();
|
EMPTY_CACHE();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Test_DWP_Error(HWND hWnd, HWND hWnd2)
|
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");
|
ok_windowpos(hWnd2, 70, 80, 250, 260, "Window 2");
|
||||||
|
|
||||||
FlushMessages();
|
FlushMessages();
|
||||||
empty_message_cache();
|
EMPTY_CACHE();
|
||||||
}
|
}
|
||||||
|
|
||||||
MSG_ENTRY move1_chain[]={
|
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(hWnd1, 0, 10,20,100,100,0);
|
||||||
SetWindowPos(hWnd2, 0, 10,20,100,100,0);
|
SetWindowPos(hWnd2, 0, 10,20,100,100,0);
|
||||||
FlushMessages();
|
FlushMessages();
|
||||||
empty_message_cache();
|
EMPTY_CACHE();
|
||||||
|
|
||||||
/* move hWnd1 */
|
/* move hWnd1 */
|
||||||
hdwp = BeginDeferWindowPos(1);
|
hdwp = BeginDeferWindowPos(1);
|
||||||
|
|
|
@ -48,11 +48,11 @@ LRESULT CALLBACK OwnerTestProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lP
|
||||||
{
|
{
|
||||||
WINDOWPOS* pwp = (WINDOWPOS*)lParam;
|
WINDOWPOS* pwp = (WINDOWPOS*)lParam;
|
||||||
ok(wParam==0,"expected wParam=0\n");
|
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;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
record_message(iwnd, message, SENT, 0,0);
|
RECOND_MESSAGE(iwnd, message, SENT, 0,0);
|
||||||
}
|
}
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ static void FlushMessages()
|
||||||
{
|
{
|
||||||
int iwnd = get_iwnd(msg.hwnd);
|
int iwnd = get_iwnd(msg.hwnd);
|
||||||
if(!(msg.message > WM_USER || !iwnd || IsDWmMsg(msg.message) || IseKeyMsg(msg.message)))
|
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 );
|
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);
|
SetWindowPos(hWnd2, 0, 0,0,0,0, SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_SHOWWINDOW);
|
||||||
|
|
||||||
FlushMessages();
|
FlushMessages();
|
||||||
empty_message_cache();
|
EMPTY_CACHE();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void destroy_test_window()
|
static void destroy_test_window()
|
||||||
|
|
|
@ -38,11 +38,11 @@ LRESULT CALLBACK SysParamsTestProc(HWND hWnd, UINT message, WPARAM wParam, LPARA
|
||||||
{
|
{
|
||||||
WINDOWPOS* pwp = (WINDOWPOS*)lParam;
|
WINDOWPOS* pwp = (WINDOWPOS*)lParam;
|
||||||
ok(wParam==0,"expected wParam=0\n");
|
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;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
record_message(iwnd, message, SENT, 0,0);
|
RECOND_MESSAGE(iwnd, message, SENT, 0,0);
|
||||||
}
|
}
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ static void FlushMessages()
|
||||||
{
|
{
|
||||||
int iwnd = get_iwnd(msg.hwnd);
|
int iwnd = get_iwnd(msg.hwnd);
|
||||||
if(!(msg.message > WM_USER || !iwnd || IsDWmMsg(msg.message) || IseKeyMsg(msg.message)))
|
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 );
|
DispatchMessageA( &msg );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
ok(0, "Got unexpected WM_SYSTIMER in the winproc. wParam=%d\n", wParam);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
record_message(iwnd, message, SENT, 0,0);
|
RECOND_MESSAGE(iwnd, message, SENT, 0,0);
|
||||||
}
|
}
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
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)
|
static LRESULT CALLBACK MouseLLHookProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
LRESULT ret;
|
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);
|
ret = CallNextHookEx(hMouseHookLL, nCode, wParam, lParam);
|
||||||
if(ignore_mousell)
|
if(ignore_mousell)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -68,7 +68,7 @@ static LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
MOUSEHOOKSTRUCT *hs = (MOUSEHOOKSTRUCT*) lParam;
|
MOUSEHOOKSTRUCT *hs = (MOUSEHOOKSTRUCT*) lParam;
|
||||||
LRESULT ret;
|
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);
|
ret = CallNextHookEx(hMouseHook, nCode, wParam, lParam);
|
||||||
if(ignore_mouse)
|
if(ignore_mouse)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -86,12 +86,12 @@ static void FlushMessages()
|
||||||
{
|
{
|
||||||
if(msg.message == WM_SYSTIMER)
|
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)
|
if(ignore_timer)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if(!(msg.message > WM_USER || !iwnd || IsDWmMsg(msg.message) || IseKeyMsg(msg.message)))
|
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 );
|
DispatchMessageA( &msg );
|
||||||
}
|
}
|
||||||
|
@ -265,7 +265,7 @@ void Test_TrackMouseEvent()
|
||||||
MOVE_CURSOR(0,0);
|
MOVE_CURSOR(0,0);
|
||||||
create_test_windows();
|
create_test_windows();
|
||||||
FlushMessages();
|
FlushMessages();
|
||||||
empty_message_cache();
|
EMPTY_CACHE();
|
||||||
|
|
||||||
/* the mouse moves over hwnd2 */
|
/* the mouse moves over hwnd2 */
|
||||||
MOVE_CURSOR(220,220);
|
MOVE_CURSOR(220,220);
|
||||||
|
|
|
@ -11,10 +11,11 @@
|
||||||
#include "helper.h"
|
#include "helper.h"
|
||||||
#include <undocuser.h>
|
#include <undocuser.h>
|
||||||
|
|
||||||
MSG_ENTRY last_post_message;
|
MSG_CACHE default_cache = {
|
||||||
MSG_ENTRY message_cache[100];
|
#ifdef _MSC_VER
|
||||||
static int message_cache_size = 0;
|
0
|
||||||
|
#endif
|
||||||
|
};
|
||||||
MSG_ENTRY empty_chain[]= {{0,0}};
|
MSG_ENTRY empty_chain[]= {{0,0}};
|
||||||
|
|
||||||
static char* get_msg_name(UINT msg)
|
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_SETTINGCHANGE: return "WM_SETTINGCHANGE";
|
||||||
case WM_GETICON: return "WM_GETICON";
|
case WM_GETICON: return "WM_GETICON";
|
||||||
case WM_SETICON: return "WM_SETICON";
|
case WM_SETICON: return "WM_SETICON";
|
||||||
|
case WM_KEYDOWN: return "WM_KEYDOWN";
|
||||||
|
case WM_KEYUP: return "WM_KEYUP";
|
||||||
default: return NULL;
|
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(cache, 0, sizeof(MSG_CACHE));
|
||||||
memset(message_cache, 0, sizeof(message_cache));
|
|
||||||
message_cache_size = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sprintf_msg_entry(char* buffer, MSG_ENTRY* msg)
|
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;
|
int i;
|
||||||
char buff[100];
|
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)("%d: %s\n", i, buff);
|
||||||
}
|
}
|
||||||
trace_(file,line)("\n");
|
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;
|
int i = 0;
|
||||||
char buffGot[100], buffExp[100];
|
char buffGot[100], buffExp[100];
|
||||||
|
@ -132,9 +133,9 @@ void compare_cache(const char* file, int line, MSG_ENTRY *msg_chain)
|
||||||
|
|
||||||
while(1)
|
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);
|
sprintf_msg_entry(buffExp, msg_chain);
|
||||||
ok_(file,line)(same,"%d: got %s, expected %s\n",i, buffGot, buffExp);
|
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++;
|
msg_chain++;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(i>message_cache_size)
|
if(i > cache->count)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
@ -154,46 +155,46 @@ void compare_cache(const char* file, int line, MSG_ENTRY *msg_chain)
|
||||||
if(got_error )
|
if(got_error )
|
||||||
{
|
{
|
||||||
trace_(file,line)("The complete list of messages got is:\n");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do not report a post message a second time */
|
/* do not report a post message a second time */
|
||||||
if(type == SENT &&
|
if(type == SENT &&
|
||||||
last_post_message.iwnd == iwnd &&
|
cache->last_post_message.iwnd == iwnd &&
|
||||||
last_post_message.msg == message &&
|
cache->last_post_message.msg == message &&
|
||||||
last_post_message.param1 == param1 &&
|
cache->last_post_message.param1 == param1 &&
|
||||||
last_post_message.param2 == param2)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
message_cache[message_cache_size].iwnd = iwnd;
|
cache->message_cache[cache->count].iwnd = iwnd;
|
||||||
message_cache[message_cache_size].msg = message;
|
cache->message_cache[cache->count].msg = message;
|
||||||
message_cache[message_cache_size].type = type;
|
cache->message_cache[cache->count].type = type;
|
||||||
message_cache[message_cache_size].param1 = param1;
|
cache->message_cache[cache->count].param1 = param1;
|
||||||
message_cache[message_cache_size].param2 = param2;
|
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
|
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)
|
ATOM RegisterSimpleClass(WNDPROC lpfnWndProc, LPCWSTR lpszClassName)
|
||||||
|
|
|
@ -16,13 +16,21 @@ typedef struct _MSG_ENTRY
|
||||||
int param2;
|
int param2;
|
||||||
} MSG_ENTRY;
|
} 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_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);
|
ATOM RegisterSimpleClass(WNDPROC lpfnWndProc, LPCWSTR lpszClassName);
|
||||||
|
|
||||||
/* filter messages that are affected by dwm */
|
/* filter messages that are affected by dwm */
|
||||||
|
@ -44,10 +52,14 @@ static inline BOOL IseKeyMsg(UINT msg)
|
||||||
return (msg == WM_KEYUP || msg == WM_KEYDOWN);
|
return (msg == WM_KEYUP || msg == WM_KEYDOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define COMPARE_CACHE(...) compare_cache(__FILE__, __LINE__, ##__VA_ARGS__)
|
#define COMPARE_CACHE(msg_chain) compare_cache(&default_cache, __FILE__, __LINE__, msg_chain)
|
||||||
#define TRACE_CACHE() trace_cache(__FILE__, __LINE__)
|
#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) \
|
#define EXPECT_QUEUE_STATUS(expected, notexpected) \
|
||||||
{ \
|
{ \
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#define STANDALONE
|
#define STANDALONE
|
||||||
#include "wine/test.h"
|
#include "wine/test.h"
|
||||||
|
|
||||||
|
extern void func_AttachThreadInput(void);
|
||||||
extern void func_DeferWindowPos(void);
|
extern void func_DeferWindowPos(void);
|
||||||
extern void func_desktop(void);
|
extern void func_desktop(void);
|
||||||
extern void func_GetIconInfo(void);
|
extern void func_GetIconInfo(void);
|
||||||
|
@ -24,6 +25,7 @@ extern void func_wsprintf(void);
|
||||||
|
|
||||||
const struct test winetest_testlist[] =
|
const struct test winetest_testlist[] =
|
||||||
{
|
{
|
||||||
|
{ "AttachThreadInput", func_AttachThreadInput },
|
||||||
{ "desktop", func_desktop },
|
{ "desktop", func_desktop },
|
||||||
{ "DeferWindowPos", func_DeferWindowPos },
|
{ "DeferWindowPos", func_DeferWindowPos },
|
||||||
{ "GetIconInfo", func_GetIconInfo },
|
{ "GetIconInfo", func_GetIconInfo },
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue