ReactOS 0.4.15-dev-7961-gdcf9eb0
AttachThreadInput.c File Reference
#include "precomp.h"
Include dependency graph for AttachThreadInput.c:

Go to the source code of this file.

Classes

struct  THREAD_DATA
 

Macros

#define EXPECT_FOREGROUND(expected)
 
#define EXPECT_ACTIVE(expected)
 

Functions

static int get_iwnd (HWND hWnd)
 
LRESULT CALLBACK TestProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 
static void FlushMessages ()
 
static DWORD WINAPI thread_proc (void *param)
 
BOOL CreateTestThread (int i, WCHAR *Desktop)
 
static LRESULT CALLBACK MouseLLHookProc (int nCode, WPARAM wParam, LPARAM lParam)
 
LRESULT CALLBACK KbdLLHookProc (int nCode, WPARAM wParam, LPARAM lParam)
 
BOOLEAN InitThreads ()
 
static void cleanup_attachments ()
 
void Test_SimpleParameters ()
 
void Test_Focus ()
 
void Test_UnaffectedMessages ()
 
void Test_SendInput ()
 
 START_TEST (AttachThreadInput)
 

Variables

static THREAD_DATA data [6]
 
static HHOOK hMouseHookLL = NULL
 
static HHOOK hKbdHookLL = NULL
 

Macro Definition Documentation

◆ EXPECT_ACTIVE

#define EXPECT_ACTIVE (   expected)
Value:
"Expected hwnd%d to be active, got hwnd%d\n", \
static int get_iwnd(HWND hWnd)
#define ok(value,...)
Definition: atltest.h:57
BOOL expected
Definition: store.c:2063
HWND WINAPI GetActiveWindow(void)
Definition: winpos.c:138

Definition at line 31 of file AttachThreadInput.c.

◆ EXPECT_FOREGROUND

#define EXPECT_FOREGROUND (   expected)
Value:
"Expected hwnd%d at the foreground, got hwnd%d\n", \
HWND WINAPI GetForegroundWindow(void)
Definition: ntwrapper.h:392

Definition at line 27 of file AttachThreadInput.c.

Function Documentation

◆ cleanup_attachments()

static void cleanup_attachments ( )
static

Definition at line 205 of file AttachThreadInput.c.

206{
207 int i,j;
208 BOOL ret;
209
210 for(i = 0; i< 4; i++)
211 {
212 for(j = 0; j< 4; j++)
213 {
215 ok(ret==0, "expected AttachThreadInput to fail\n");
216 }
217 }
218}
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
static TfClientId tid
int ret
BOOL WINAPI AttachThreadInput(_In_ DWORD, _In_ DWORD, _In_ BOOL)

Referenced by START_TEST().

◆ CreateTestThread()

BOOL CreateTestThread ( int  i,
WCHAR Desktop 
)

Definition at line 117 of file AttachThreadInput.c.

118{
119 DWORD ret;
120
121 data[i].StartEvent = CreateEventW(NULL, 0, 0, NULL);
122 data[i].Desktop = Desktop;
123 data[i].hThread = CreateThread(NULL, 0, thread_proc, &data[i], 0, &data[i].tid);
124 if(!data[i].hThread) goto fail;
127 if(ret == WAIT_TIMEOUT)
128 {
129fail:
130 win_skip("child thread failed to initialize\n");
131 return FALSE;
132 }
133 return TRUE;
134}
static DWORD WINAPI thread_proc(void *param)
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:739
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
unsigned long DWORD
Definition: ntddk_ex.h:95
HANDLE hThread
Definition: wizard.c:28
#define win_skip
Definition: test.h:160
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
HANDLE StartEvent
Definition: thmsvc.c:26

Referenced by InitThreads(), and Test_SimpleParameters().

◆ FlushMessages()

static void FlushMessages ( )
static

Definition at line 59 of file AttachThreadInput.c.

60{
61 MSG msg;
63
64 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
65 {
66 int iwnd = get_iwnd(msg.hwnd);
67 if( iwnd >= 0 && msg.message > 0 && msg.message < WM_APP && msg.message != WM_TIMER)
68 record_message(&data[0].cache, iwnd, msg.message, POST, msg.wParam,0);
70 }
71
72 /* Use SendMessage to sync with the other queues */
74 ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
76 ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
78 ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
80 ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
81}
#define msg(x)
Definition: auth_time.c:54
HWND hWnd
Definition: settings.c:17
#define WM_APP
Definition: eventvwr.h:73
GLuint res
Definition: glext.h:9613
void record_message(MSG_CACHE *cache, int iwnd, UINT message, MSG_TYPE type, int param1, int param2)
Definition: msgtrace.c:179
@ POST
Definition: msgtrace.h:7
Definition: cache.c:49
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
LONG_PTR LRESULT
Definition: windef.h:209
#define ERROR_TIMEOUT
Definition: winerror.h:941
LRESULT WINAPI DispatchMessageA(_In_ const MSG *)
#define SendMessageTimeout
Definition: winuser.h:5845
#define WM_TIMER
Definition: winuser.h:1742
#define PM_REMOVE
Definition: winuser.h:1196
#define PeekMessage
Definition: winuser.h:5830
#define SMTO_NORMAL
Definition: winuser.h:1225

Referenced by Test_Focus(), Test_SendInput(), and Test_UnaffectedMessages().

◆ get_iwnd()

static int get_iwnd ( HWND  hWnd)
static

Definition at line 39 of file AttachThreadInput.c.

40{
41 if(hWnd == data[0].hWnd) return 0;
42 else if(hWnd == data[1].hWnd) return 1;
43 else if(hWnd == data[2].hWnd) return 2;
44 else if(hWnd == data[3].hWnd) return 3;
45 else if(hWnd == data[4].hWnd) return 4;
46 else return -1;
47}

Referenced by FlushMessages(), TestProc(), and thread_proc().

◆ InitThreads()

BOOLEAN InitThreads ( )

Definition at line 162 of file AttachThreadInput.c.

163{
164 /* Create a LL hook that drops any physical keyboard and mouse action
165 and prevent the user from interfering with the test results */
166 if(!IsDebuggerPresent())
167 {
169 ok(hMouseHookLL!=NULL,"failed to set hook\n");
171 ok(hKbdHookLL!=NULL,"failed to set hook\n");
172 }
173
174 /* create test clases */
175 RegisterSimpleClass(TestProc, L"TestClass");
176
177 memset(&data[0], 0, sizeof(data[0]));
178
179 data[0].tid = GetCurrentThreadId();
180
181 /* create test window */
182 data[0].hWnd = CreateWindowW(L"TestClass", L"test", WS_OVERLAPPEDWINDOW,
183 100, 100, 500, 500, NULL, NULL, 0, NULL);
184 if(!data[0].hWnd)
185 {
186 win_skip("CreateWindowW failed\n");
187 return FALSE;
188 }
189
190 /* create thread1(same desktop) */
191 if(!CreateTestThread(1, NULL)) return FALSE;
192
193 /* create thread2(same desktop) */
194 if(!CreateTestThread(2, NULL)) return FALSE;
195
196 /* create thread3(different desktop) */
197 if(!CreateTestThread(3, L"ThreadTestDesktop")) return FALSE;
198
199 /* create thread4(different desktop) */
200 if(!CreateTestThread(4, L"ThreadTestDesktop")) return FALSE;
201
202 return TRUE;
203}
LRESULT CALLBACK KbdLLHookProc(int nCode, WPARAM wParam, LPARAM lParam)
static HHOOK hMouseHookLL
BOOL CreateTestThread(int i, WCHAR *Desktop)
static LRESULT CALLBACK MouseLLHookProc(int nCode, WPARAM wParam, LPARAM lParam)
static HHOOK hKbdHookLL
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
#define L(x)
Definition: ntvdm.h:50
#define WS_OVERLAPPEDWINDOW
Definition: pedump.c:637
#define TestProc(n)
Definition: queuetest.c:15
#define memset(x, y, z)
Definition: compat.h:39
static __inline ATOM RegisterSimpleClass(WNDPROC lpfnWndProc, LPCWSTR lpszClassName)
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
BOOL WINAPI IsDebuggerPresent(void)
Definition: debugger.c:580
HHOOK WINAPI SetWindowsHookExW(_In_ int, _In_ HOOKPROC, _In_opt_ HINSTANCE, _In_ DWORD)
#define WH_MOUSE_LL
Definition: winuser.h:44
#define WH_KEYBOARD_LL
Definition: winuser.h:43
#define CreateWindowW(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4316

Referenced by START_TEST().

◆ KbdLLHookProc()

LRESULT CALLBACK KbdLLHookProc ( int  nCode,
WPARAM  wParam,
LPARAM  lParam 
)

Definition at line 149 of file AttachThreadInput.c.

150{
151 LRESULT ret;
153
155
156 if((params->flags & LLKHF_INJECTED) == 0)
157 return TRUE;
158
159 return ret;
160}
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
GLenum const GLfloat * params
Definition: glext.h:5645
#define LLKHF_INJECTED
Definition: winuser.h:2646
LRESULT WINAPI CallNextHookEx(_In_opt_ HHOOK, _In_ int, _In_ WPARAM, _In_ LPARAM)

Referenced by InitThreads().

◆ MouseLLHookProc()

static LRESULT CALLBACK MouseLLHookProc ( int  nCode,
WPARAM  wParam,
LPARAM  lParam 
)
static

Definition at line 136 of file AttachThreadInput.c.

137{
138 LRESULT ret;
140
142
143 if((params->flags & LLKHF_INJECTED) == 0)
144 return TRUE;
145
146 return ret;
147}

Referenced by InitThreads().

◆ START_TEST()

START_TEST ( AttachThreadInput  )

Definition at line 654 of file AttachThreadInput.c.

655{
656 if(!InitThreads())
657 return;
658
661 Test_Focus();
667
668 if(hMouseHookLL)
670 if(hKbdHookLL)
672
673 /* Stop all threads and exit gratefully */
678}
void Test_UnaffectedMessages()
void Test_SendInput()
static void cleanup_attachments()
void Test_SimpleParameters()
void Test_Focus()
BOOLEAN InitThreads()
#define WM_QUIT
Definition: winuser.h:1623
#define PostThreadMessage
Definition: winuser.h:5833
BOOL WINAPI UnhookWindowsHookEx(_In_ HHOOK)

◆ Test_Focus()

void Test_Focus ( )

Definition at line 346 of file AttachThreadInput.c.

347{
348 BOOL ret;
349
350 trace("Thread hWnd0 0x%p hWnd1 0x%p\n",data[0].hWnd, data[1].hWnd);
351 /* Window 1 is in the foreground */
355
358
359 /* attach thread 0 to 1 */
360 {
362 ok(ret==1, "expected AttachThreadInput to succeed\n");
364
367
369 ok(ret==1, "expected AttachThreadInput to succeed\n");
370 }
371
373 EXPECT_ACTIVE(0);
374
378
381
382 /* attach thread 1 to 0 */
383 {
385 ok(ret==1, "expected AttachThreadInput to succeed\n");
387
390
392 ok(ret==1, "expected AttachThreadInput to succeed\n");
393 }
394
395 /* Window 0 is in the foreground */
399
402
403 /* attach thread 0 to 1 */
404 {
406 ok(ret==1, "expected AttachThreadInput to succeed\n");
408
411
415
418
420 ok(ret==1, "expected AttachThreadInput to succeed\n");
421 }
422
424 EXPECT_ACTIVE(0);
425
429
432
433 /* attach thread 1 to 0 */
434 {
436 ok(ret==1, "expected AttachThreadInput to succeed\n");
438
441
445
448
450 ok(ret==1, "expected AttachThreadInput to succeed\n");
451 }
452}
static void FlushMessages()
#define EXPECT_FOREGROUND(expected)
#define EXPECT_ACTIVE(expected)
#define trace
Definition: atltest.h:70
BOOL WINAPI SetForegroundWindow(_In_ HWND)
HWND WINAPI SetActiveWindow(_In_ HWND)

Referenced by START_TEST().

◆ Test_SendInput()

void Test_SendInput ( )

Definition at line 533 of file AttachThreadInput.c.

534{
535 MSG_ENTRY Thread1_chain[]={
536 {1,WM_KEYDOWN, POST, VK_SHIFT, 0},
537 {1,WM_KEYUP, POST, VK_SHIFT, 0},
538 {0,0}};
539 MSG_ENTRY Thread0_chain[]={
540 {0,WM_KEYDOWN, POST, VK_SHIFT, 0},
541 {0,WM_KEYUP, POST, VK_SHIFT, 0},
542 {0,0}};
543
544 BOOL ret;
545
546 //trace("Thread hWnd0 0x%p hWnd1 0x%p\n",data[0].hWnd, data[1].hWnd);
547
548 /* First try sending input without attaching. It will go to the foreground */
549 {
552
553 ok(GetForegroundWindow() == data[1].hWnd, "wrong foreground got 0x%p\n",GetForegroundWindow());
554 ok(GetActiveWindow() == data[0].hWnd, "wrong active got 0x%p\n",GetActiveWindow());
555
559
560 keybd_event(VK_SHIFT, 0,0,0);
562 Sleep(100);
564
566 COMPARE_CACHE_(&data[1].cache, Thread1_chain);
567 }
568
569 /* Next attach and send input. It will go to the same thread as before */
570 { // from to
572 ok(ret==1, "expected AttachThreadInput to succeed\n");
573
577
578 keybd_event(VK_SHIFT, 0,0,0);
580 Sleep(100);
582
584 COMPARE_CACHE_(&data[1].cache, Thread1_chain);
585 }
586
587 /* Now set foreground and active again. Input will go to thread 0 */
588 {
592
593 ok(GetForegroundWindow() == data[0].hWnd, "wrong foreground got 0x%p\n",GetForegroundWindow());
594 ok(GetActiveWindow() == data[0].hWnd, "wrong active got 0x%p\n",GetActiveWindow());
595
598
599 keybd_event(VK_SHIFT, 0,0,0);
601 Sleep(100);
603
604 COMPARE_CACHE_(&data[0].cache, Thread0_chain);
606
608 ok(ret==1, "expected AttachThreadInput to succeed\n");
609 }
610
611 /* Attach in the opposite order and send input */
612 {
614 ok(ret==1, "expected AttachThreadInput to succeed\n");
615
619
620 keybd_event(VK_SHIFT, 0,0,0);
622 Sleep(100);
624
625 COMPARE_CACHE_(&data[0].cache, Thread0_chain);
627 }
628
629 /* Now set foreground and active again. Input will go to thread 0 */
630 {
634
635 ok(GetForegroundWindow() == data[0].hWnd, "wrong foreground got 0x%p\n",GetForegroundWindow());
636 ok(GetActiveWindow() == data[0].hWnd, "wrong active got 0x%p\n",GetActiveWindow());
637
640
641 keybd_event(VK_SHIFT, 0,0,0);
643 Sleep(100);
645
646 COMPARE_CACHE_(&data[0].cache, Thread0_chain);
648
650 ok(ret==1, "expected AttachThreadInput to succeed\n");
651 }
652}
MSG_ENTRY empty_chain[]
Definition: msgtrace.c:20
#define COMPARE_CACHE_(cache, msg_chain)
Definition: msgtrace.h:62
#define EMPTY_CACHE_(cache)
Definition: msgtrace.h:64
Definition: msgtrace.h:15
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
#define WM_KEYUP
Definition: winuser.h:1716
VOID WINAPI keybd_event(_In_ BYTE, _In_ BYTE, _In_ DWORD, _In_ ULONG_PTR)
#define VK_SHIFT
Definition: winuser.h:2202
#define WM_KEYDOWN
Definition: winuser.h:1715
#define KEYEVENTF_KEYUP
Definition: winuser.h:1102

Referenced by START_TEST().

◆ Test_SimpleParameters()

void Test_SimpleParameters ( )

Definition at line 227 of file AttachThreadInput.c.

228{
229 BOOL ret;
230 /* FIXME: acording to msdn xp doesn't set last error but vista+ does*/
231
232 /* test wrong thread */
233 ret = AttachThreadInput( 0, 1, TRUE);
234 ok(ret==0, "expected AttachThreadInput to fail\n");
235
236 /* test same thread */
238 ok(ret==0, "expected AttachThreadInput to fail\n");
239
240 /* try to attach to a thread on another desktop*/
242 ok(ret==0, "expected AttachThreadInput to fail\n");
243 if(ret == 1 )
245
246 /* test other desktop to this */
248 ok(ret==0, "expected AttachThreadInput to fail\n");
249 if(ret == 1 )
251
252 /* attach two threads that are both in ThreadTestDesktop */
253 {
254 /* Attach thread 3 and 4 */
256 ok(ret==1, "expected AttachThreadInput to succeed\n");
257
258 /* cleanup previous attachment */
260 ok(ret==1, "expected AttachThreadInput to succeed\n");
261 }
262
263 {
264 /* Attach thread 1 and 2 */
266 ok(ret==1, "expected AttachThreadInput to succeed\n");
267
268 /* attach already attached*/
270 ok(ret==1, "expected AttachThreadInput to succeed\n");
271
272 /* attach in the opposite order */
274 ok(ret==1, "expected AttachThreadInput to succeed\n");
275
276 /* Now try to detach 0 from 1 */
278 ok(ret==0, "expected AttachThreadInput to fail\n");
279
280 /* also try to detach 3 from 2 */
282 ok(ret==0, "expected AttachThreadInput to fail\n");
283
284 /* cleanup previous attachment */
286 ok(ret==1, "expected AttachThreadInput to succeed\n");
287
289 ok(ret==1, "expected AttachThreadInput to succeed\n");
290
292 ok(ret==1, "expected AttachThreadInput to succeed\n");
293 }
294
295 /* test triple attach */
296 {
298 ok(ret==1, "expected AttachThreadInput to succeed\n");
300 ok(ret==1, "expected AttachThreadInput to succeed\n");
301
302 /* try to detach 2 and 0 */
304 ok(ret==0, "expected AttachThreadInput to fail\n");
306 ok(ret==0, "expected AttachThreadInput to fail\n");
307
308 /* try to to attach 0 to 2. it works! */
310 ok(ret==1, "expected AttachThreadInput to succeed\n");
311
313 ok(ret==1, "expected AttachThreadInput to succeed\n");
314
315 /* detach in inverse order */
317 ok(ret==1, "expected AttachThreadInput to succeed\n");
319 ok(ret==1, "expected AttachThreadInput to succeed\n");
320 }
321
322 /* test detaching in thread cleanup */
323 {
325 ok(ret==1, "expected AttachThreadInput to succeed\n");
327 ok(ret==1, "expected AttachThreadInput to succeed\n");
329 ok(ret==1, "expected AttachThreadInput to succeed\n");
331 ok(ret==1, "expected AttachThreadInput to succeed\n");
332
334
336 ok(ret==0, "expected AttachThreadInput to fail\n");
338 ok(ret==0, "expected AttachThreadInput to fail\n");
339
340 /* Create Thread1 again */
342 }
343
344}
BOOL WINAPI TerminateThread(IN HANDLE hThread, IN DWORD dwExitCode)
Definition: thread.c:587

Referenced by START_TEST().

◆ Test_UnaffectedMessages()

void Test_UnaffectedMessages ( )

Definition at line 455 of file AttachThreadInput.c.

456{
457 BOOL ret;
458 LRESULT res;
459
462
463 /* test that messages posted before and after attachment are unaffected
464 and that we don't receive a meassage from a window we shouldn't */
465 PostMessage(data[0].hWnd, WM_USER, 0,0);
466 PostMessage(data[1].hWnd, WM_USER, 1,0);
467
468 {
469 MSG_ENTRY Thread0_chain[]={
470 {0,WM_USER, POST, 0, 0},
471 {0,WM_USER, POST, 2, 0},
472 {0,0}};
473 MSG_ENTRY Thread1_chain[]={
474 {1,WM_USER, POST, 1, 0},
475 {1,WM_USER, POST, 3, 0},
476 {0,0}};
477
479 ok(ret==1, "expected AttachThreadInput to succeed\n");
480
481 PostMessage(data[0].hWnd, WM_USER, 2,0);
482 PostMessage(data[1].hWnd, WM_USER, 3,0);
483
485 Sleep(100);
486
487 COMPARE_CACHE_(&data[0].cache, Thread0_chain);
488 COMPARE_CACHE_(&data[1].cache, Thread1_chain);
489
491 ok(ret==1, "expected AttachThreadInput to succeed\n");
492 }
493
494 /* test messages send to the wrong thread */
496 ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
498 ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
499
500 {
501 MSG_ENTRY Thread0_chain[]={
502 {0,WM_USER, SENT, 0, 0},
503 {0,WM_USER, SENT, 2, 0},
504 {0,0}};
505 MSG_ENTRY Thread1_chain[]={
506 {1,WM_USER, SENT, 1, 0},
507 {1,WM_USER, SENT, 3, 0},
508 {1,WM_MOUSEMOVE, SENT, 0, 0},
509 {0,0}};
510
512 ok(ret==1, "expected AttachThreadInput to succeed\n");
513
515 ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
517 ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
518
519 /* Try to send a fake input message */
521 ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
522
523 COMPARE_CACHE_(&data[0].cache, Thread0_chain);
524 COMPARE_CACHE_(&data[1].cache, Thread1_chain);
525
527 ok(ret==1, "expected AttachThreadInput to succeed\n");
528 }
529
530 /* todo: test keyboard layout that shouldn't be affected */
531}
@ SENT
Definition: msgtrace.h:6
#define WM_MOUSEMOVE
Definition: winuser.h:1775
#define PostMessage
Definition: winuser.h:5832
#define WM_USER
Definition: winuser.h:1895

Referenced by START_TEST().

◆ TestProc()

LRESULT CALLBACK TestProc ( HWND  hWnd,
UINT  message,
WPARAM  wParam,
LPARAM  lParam 
)

Definition at line 49 of file AttachThreadInput.c.

50{
51 int iwnd = get_iwnd(hWnd);
52
53 if(iwnd >= 0 && message > 0 && message < WM_APP && message != WM_TIMER)
54 record_message(&data[iwnd].cache, iwnd, message, SENT, wParam,0);
55
57}
#define DefWindowProc
Definition: ros2win.h:31
Definition: tftpd.h:60

◆ thread_proc()

static DWORD WINAPI thread_proc ( void param)
static

Definition at line 83 of file AttachThreadInput.c.

84{
85 THREAD_DATA* current_data = (THREAD_DATA*)param;
86 MSG msg;
87 HDESK hdesk = NULL;
88 int iwnd;
89
90 if(current_data->Desktop)
91 {
92 hdesk = CreateDesktopW(current_data->Desktop, NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
93 SetThreadDesktop(hdesk);
94 }
95
96 /* create test window */
97 current_data->hWnd = CreateWindowW(L"TestClass", L"test", WS_OVERLAPPEDWINDOW,
98 100, 100, 500, 500, NULL, NULL, 0, NULL);
99 SetEvent( current_data->StartEvent );
100
101 iwnd = get_iwnd(current_data->hWnd);
102
103 /* Use MsgWaitForMultipleObjects to let the thread process apcs */
104 while( GetMessage(&msg, 0,0,0) )
105 {
106 if(msg.message > 0 && msg.message < WM_APP && msg.message != WM_TIMER )
107 record_message(&data[iwnd].cache, iwnd, msg.message, POST, msg.wParam,0);
109 }
110
111 if(hdesk)
112 CloseDesktop(hdesk);
113
114 return 0;
115}
GLfloat param
Definition: glext.h:5796
#define DESKTOP_ALL_ACCESS
Definition: precomp.h:22
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
HDESK WINAPI CreateDesktopW(LPCWSTR lpszDesktop, LPCWSTR lpszDevice, LPDEVMODEW pDevmode, DWORD dwFlags, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa)
Definition: desktop.c:473
BOOL WINAPI SetThreadDesktop(_In_ HDESK)
#define GetMessage
Definition: winuser.h:5790
#define DispatchMessage
Definition: winuser.h:5765
BOOL WINAPI CloseDesktop(_In_ HDESK)

Referenced by CreateTestThread().

Variable Documentation

◆ data

THREAD_DATA data[6]
static

Definition at line 22 of file AttachThreadInput.c.

◆ hKbdHookLL

HHOOK hKbdHookLL = NULL
static

Definition at line 24 of file AttachThreadInput.c.

Referenced by InitThreads(), and START_TEST().

◆ hMouseHookLL

HHOOK hMouseHookLL = NULL
static

Definition at line 23 of file AttachThreadInput.c.

Referenced by InitThreads(), KbdLLHookProc(), MouseLLHookProc(), and START_TEST().