79f517f8548bdca830b3030dc16773658e9a8b32
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL - See COPYING in the top level directory
4 * PURPOSE: Test for AttachThreadInput
5 * PROGRAMMERS: Giannis Adamopoulos
10 #include <wine/test.h>
12 #include <undocuser.h>
14 #define DESKTOP_ALL_ACCESS 0x01ff
22 HANDLE QueueStatusEvent
;
23 DWORD LastQueueStatus
;
30 HHOOK hMouseHookLL
= NULL
;
31 HHOOK hKbdHookLL
= NULL
;
34 #define EXPECT_FOREGROUND(expected) ok(GetForegroundWindow() == expected, \
35 "Expected hwnd%d at the foreground, got hwnd%d\n", \
36 get_iwnd(expected), get_iwnd(GetForegroundWindow()));
38 #define EXPECT_ACTIVE(expected) ok(GetActiveWindow() == expected, \
39 "Expected hwnd%d to be active, got hwnd%d\n", \
40 get_iwnd(expected), get_iwnd(GetActiveWindow()));
46 static int get_iwnd(HWND hWnd
)
48 if(hWnd
== data
[0].hWnd
) return 0;
49 else if(hWnd
== data
[1].hWnd
) return 1;
50 else if(hWnd
== data
[2].hWnd
) return 2;
51 else if(hWnd
== data
[3].hWnd
) return 3;
52 else if(hWnd
== data
[4].hWnd
) return 4;
56 LRESULT CALLBACK
TestProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
58 int iwnd
= get_iwnd(hWnd
);
60 if(iwnd
>= 0 && message
> 0 && message
< WM_APP
&& message
!= WM_TIMER
)
61 record_message(&data
[iwnd
].cache
, iwnd
, message
, SENT
, wParam
,0);
63 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
66 static void FlushMessages()
71 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
))
73 int iwnd
= get_iwnd(msg
.hwnd
);
74 if( iwnd
>= 0 && msg
.message
> 0 && msg
.message
< WM_APP
&& msg
.message
!= WM_TIMER
)
75 record_message(&data
[0].cache
, iwnd
, msg
.message
, POST
, msg
.wParam
,0);
76 DispatchMessageA( &msg
);
79 /* Use SendMessage to sync with the other queues */
80 res
= SendMessageTimeout(data
[1].hWnd
, WM_APP
, 0,0, SMTO_NORMAL
, 1000, NULL
);
81 ok (res
!= ERROR_TIMEOUT
, "SendMessageTimeout timed out\n");
82 res
= SendMessageTimeout(data
[2].hWnd
, WM_APP
, 0,0, SMTO_NORMAL
, 1000, NULL
);
83 ok (res
!= ERROR_TIMEOUT
, "SendMessageTimeout timed out\n");
84 res
= SendMessageTimeout(data
[3].hWnd
, WM_APP
, 0,0, SMTO_NORMAL
, 1000, NULL
);
85 ok (res
!= ERROR_TIMEOUT
, "SendMessageTimeout timed out\n");
86 res
= SendMessageTimeout(data
[4].hWnd
, WM_APP
, 0,0, SMTO_NORMAL
, 1000, NULL
);
87 ok (res
!= ERROR_TIMEOUT
, "SendMessageTimeout timed out\n");
90 static DWORD WINAPI
thread_proc(void *param
)
92 THREAD_DATA
* current_data
= (THREAD_DATA
*)param
;
97 if(current_data
->Desktop
)
99 hdesk
= CreateDesktopW(current_data
->Desktop
, NULL
, NULL
, 0, DESKTOP_ALL_ACCESS
, NULL
);
100 SetThreadDesktop(hdesk
);
103 /* create test window */
104 current_data
->hWnd
= CreateWindowW(L
"TestClass", L
"test", WS_OVERLAPPEDWINDOW
,
105 100, 100, 500, 500, NULL
, NULL
, 0, NULL
);
106 SetEvent( current_data
->StartEvent
);
108 iwnd
= get_iwnd(current_data
->hWnd
);
110 /* Use MsgWaitForMultipleObjects to let the thread process apcs */
111 while( GetMessage(&msg
, 0,0,0) )
113 if(msg
.message
> 0 && msg
.message
< WM_APP
&& msg
.message
!= WM_TIMER
)
114 record_message(&data
[iwnd
].cache
, iwnd
, msg
.message
, POST
, msg
.wParam
,0);
115 DispatchMessage(&msg
);
124 BOOL
CreateTestThread(int i
, WCHAR
* Desktop
)
128 data
[i
].StartEvent
= CreateEventW(NULL
, 0, 0, NULL
);
129 data
[i
].Desktop
= Desktop
;
130 data
[i
].hThread
= CreateThread(NULL
, 0, thread_proc
, &data
[i
], 0, &data
[i
].tid
);
131 if(!data
[i
].hThread
) goto fail
;
132 ret
= WaitForSingleObject(data
[i
].StartEvent
, 1000);
133 CloseHandle(data
[i
].StartEvent
);
134 if(ret
== WAIT_TIMEOUT
)
137 win_skip("child thread failed to initialize\n");
143 static LRESULT CALLBACK
MouseLLHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
)
146 MSLLHOOKSTRUCT
* params
= (MSLLHOOKSTRUCT
*) lParam
;
148 ret
= CallNextHookEx(hMouseHookLL
, nCode
, wParam
, lParam
);
150 if((params
->flags
& LLKHF_INJECTED
) == 0)
156 LRESULT CALLBACK
KbdLLHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
)
159 KBDLLHOOKSTRUCT
* params
= (KBDLLHOOKSTRUCT
*) lParam
;
161 ret
= CallNextHookEx(hMouseHookLL
, nCode
, wParam
, lParam
);
163 if((params
->flags
& LLKHF_INJECTED
) == 0)
169 BOOLEAN
InitThreads()
171 /* Create a LL hook that drops any physical keyboard and mouse action
172 and prevent the user from interfering with the test results */
173 if(!IsDebuggerPresent())
175 hMouseHookLL
= SetWindowsHookExW(WH_MOUSE_LL
, MouseLLHookProc
, GetModuleHandleW( NULL
), 0);
176 ok(hMouseHookLL
!=NULL
,"failed to set hook\n");
177 hKbdHookLL
= SetWindowsHookExW(WH_KEYBOARD_LL
, KbdLLHookProc
, GetModuleHandleW( NULL
), 0);
178 ok(hKbdHookLL
!=NULL
,"failed to set hook\n");
181 /* create test clases */
182 RegisterSimpleClass(TestProc
, L
"TestClass");
184 memset(&data
[0], 0, sizeof(data
[0]));
186 data
[0].tid
= GetCurrentThreadId();
188 /* create test window */
189 data
[0].hWnd
= CreateWindowW(L
"TestClass", L
"test", WS_OVERLAPPEDWINDOW
,
190 100, 100, 500, 500, NULL
, NULL
, 0, NULL
);
193 win_skip("CreateWindowW failed\n");
197 /* create thread1(same desktop) */
198 if(!CreateTestThread(1, NULL
)) return FALSE
;
200 /* create thread2(same desktop) */
201 if(!CreateTestThread(2, NULL
)) return FALSE
;
203 /* ugly ros hack to bypass desktop crapiness */
204 if(!CreateTestThread(6, L
"ThreadTestDesktop")) return FALSE
;
206 /* create thread3(different desktop) */
207 if(!CreateTestThread(3, L
"ThreadTestDesktop")) return FALSE
;
209 /* create thread4(different desktop) */
210 if(!CreateTestThread(4, L
"ThreadTestDesktop")) return FALSE
;
215 static void cleanup_attachments()
220 for(i
= 0; i
< 4; i
++);
222 for(j
= 0; j
< 4; j
++);
224 ret
= AttachThreadInput(data
[i
].tid
,data
[j
].tid
, FALSE
);
225 ok(ret
==0, "expected AttachThreadInput to fail\n");
237 void Test_SimpleParameters()
240 /* FIXME: acording to msdn xp doesn't set last error but vista+ does*/
242 /* test wrong thread */
243 ret
= AttachThreadInput( 0, 1, TRUE
);
244 ok(ret
==0, "expected AttachThreadInput to fail\n");
246 /* test same thread */
247 ret
= AttachThreadInput( data
[1].tid
, data
[1].tid
, TRUE
);
248 ok(ret
==0, "expected AttachThreadInput to fail\n");
250 /* try to attach to a thread on another desktop*/
251 ret
= AttachThreadInput( data
[2].tid
,data
[3].tid
, TRUE
);
252 ok(ret
==0, "expected AttachThreadInput to fail\n");
254 AttachThreadInput( data
[2].tid
,data
[3].tid
, FALSE
);
256 /* test other desktop to this */
257 ret
= AttachThreadInput( data
[3].tid
,data
[2].tid
, TRUE
);
258 ok(ret
==0, "expected AttachThreadInput to fail\n");
260 AttachThreadInput( data
[3].tid
,data
[2].tid
, FALSE
);
262 /* attach two threads that are both in ThreadTestDesktop */
264 /* Attach thread 3 and 4 */
265 ret
= AttachThreadInput( data
[3].tid
,data
[4].tid
, TRUE
);
266 ok(ret
==1, "expected AttachThreadInput to succeed\n");
268 /* cleanup previous attachment */
269 ret
= AttachThreadInput( data
[3].tid
,data
[4].tid
, FALSE
);
270 ok(ret
==1, "expected AttachThreadInput to succeed\n");
274 /* Attach thread 1 and 2 */
275 ret
= AttachThreadInput( data
[1].tid
,data
[2].tid
, TRUE
);
276 ok(ret
==1, "expected AttachThreadInput to succeed\n");
278 /* attach already attached*/
279 ret
= AttachThreadInput( data
[1].tid
,data
[2].tid
, TRUE
);
280 ok(ret
==1, "expected AttachThreadInput to succeed\n");
282 /* attach in the opposite order */
283 ret
= AttachThreadInput( data
[2].tid
,data
[1].tid
, TRUE
);
284 ok(ret
==1, "expected AttachThreadInput to succeed\n");
286 /* Now try to detach 0 from 1 */
287 ret
= AttachThreadInput( data
[0].tid
,data
[1].tid
, FALSE
);
288 ok(ret
==0, "expected AttachThreadInput to fail\n");
290 /* also try to detach 3 from 2 */
291 ret
= AttachThreadInput( data
[3].tid
,data
[2].tid
, FALSE
);
292 ok(ret
==0, "expected AttachThreadInput to fail\n");
294 /* cleanup previous attachment */
295 ret
= AttachThreadInput( data
[1].tid
,data
[2].tid
, FALSE
);
296 ok(ret
==1, "expected AttachThreadInput to succeed\n");
298 ret
= AttachThreadInput( data
[2].tid
,data
[1].tid
, FALSE
);
299 ok(ret
==1, "expected AttachThreadInput to succeed\n");
301 ret
= AttachThreadInput( data
[1].tid
,data
[2].tid
, FALSE
);
302 ok(ret
==1, "expected AttachThreadInput to succeed\n");
305 /* test triple attach */
307 ret
= AttachThreadInput( data
[0].tid
, data
[1].tid
, TRUE
);
308 ok(ret
==1, "expected AttachThreadInput to succeed\n");
309 ret
= AttachThreadInput( data
[1].tid
, data
[2].tid
, TRUE
);
310 ok(ret
==1, "expected AttachThreadInput to succeed\n");
312 /* try to detach 2 and 0 */
313 ret
= AttachThreadInput( data
[0].tid
, data
[2].tid
, FALSE
);
314 ok(ret
==0, "expected AttachThreadInput to fail\n");
315 ret
= AttachThreadInput( data
[2].tid
, data
[0].tid
, FALSE
);
316 ok(ret
==0, "expected AttachThreadInput to fail\n");
318 /* try to to attach 0 to 2. it works! */
319 ret
= AttachThreadInput( data
[0].tid
, data
[2].tid
, TRUE
);
320 ok(ret
==1, "expected AttachThreadInput to succeed\n");
322 ret
= AttachThreadInput( data
[0].tid
, data
[2].tid
, FALSE
);
323 ok(ret
==1, "expected AttachThreadInput to succeed\n");
325 /* detach in inverse order */
326 ret
= AttachThreadInput( data
[0].tid
, data
[1].tid
, FALSE
);
327 ok(ret
==1, "expected AttachThreadInput to succeed\n");
328 ret
= AttachThreadInput( data
[1].tid
, data
[2].tid
, FALSE
);
329 ok(ret
==1, "expected AttachThreadInput to succeed\n");
332 /* test detaching in thread cleanup */
334 ret
= AttachThreadInput( data
[0].tid
, data
[1].tid
, TRUE
);
335 ok(ret
==1, "expected AttachThreadInput to succeed\n");
336 ret
= AttachThreadInput( data
[0].tid
, data
[1].tid
, TRUE
);
337 ok(ret
==1, "expected AttachThreadInput to succeed\n");
338 ret
= AttachThreadInput( data
[1].tid
, data
[2].tid
, TRUE
);
339 ok(ret
==1, "expected AttachThreadInput to succeed\n");
340 ret
= AttachThreadInput( data
[1].tid
, data
[2].tid
, TRUE
);
341 ok(ret
==1, "expected AttachThreadInput to succeed\n");
343 TerminateThread(data
[1].hThread
, 0);
345 ret
= AttachThreadInput( data
[0].tid
, data
[1].tid
, FALSE
);
346 ok(ret
==0, "expected AttachThreadInput to fail\n");
347 ret
= AttachThreadInput( data
[1].tid
, data
[2].tid
, FALSE
);
348 ok(ret
==0, "expected AttachThreadInput to fail\n");
350 /* Create Thread1 again */
351 CreateTestThread(1, NULL
);
356 void Test_Focus() //Focus Active Capture Foreground Capture
360 /* Window 1 is in the foreground */
361 SetForegroundWindow(data
[1].hWnd
);
362 SetActiveWindow(data
[0].hWnd
);
365 EXPECT_FOREGROUND(data
[1].hWnd
);
366 EXPECT_ACTIVE(data
[0].hWnd
);
368 /* attach thread 0 to 1 */
370 ret
= AttachThreadInput( data
[0].tid
, data
[1].tid
, TRUE
);
371 ok(ret
==1, "expected AttachThreadInput to succeed\n");
374 EXPECT_FOREGROUND(data
[1].hWnd
);
375 EXPECT_ACTIVE(data
[1].hWnd
);
377 ret
= AttachThreadInput( data
[0].tid
, data
[1].tid
, FALSE
);
378 ok(ret
==1, "expected AttachThreadInput to succeed\n");
381 EXPECT_FOREGROUND(data
[1].hWnd
);
384 SetForegroundWindow(data
[1].hWnd
);
385 SetActiveWindow(data
[0].hWnd
);
388 EXPECT_FOREGROUND(data
[1].hWnd
);
389 EXPECT_ACTIVE(data
[0].hWnd
);
391 /* attach thread 1 to 0 */
393 ret
= AttachThreadInput( data
[1].tid
, data
[0].tid
, TRUE
);
394 ok(ret
==1, "expected AttachThreadInput to succeed\n");
397 EXPECT_FOREGROUND(data
[1].hWnd
);
398 EXPECT_ACTIVE(data
[1].hWnd
);
400 ret
= AttachThreadInput( data
[1].tid
, data
[0].tid
, FALSE
);
401 ok(ret
==1, "expected AttachThreadInput to succeed\n");
404 /* Window 0 is in the foreground */
405 SetForegroundWindow(data
[0].hWnd
);
406 SetActiveWindow(data
[1].hWnd
);
409 EXPECT_FOREGROUND(data
[0].hWnd
);
410 EXPECT_ACTIVE(data
[0].hWnd
);
412 /* attach thread 0 to 1 */
414 ret
= AttachThreadInput( data
[0].tid
, data
[1].tid
, TRUE
);
415 ok(ret
==1, "expected AttachThreadInput to succeed\n");
418 EXPECT_FOREGROUND(data
[0].hWnd
);
419 EXPECT_ACTIVE(data
[0].hWnd
);
421 SetForegroundWindow(data
[0].hWnd
);
422 SetActiveWindow(data
[1].hWnd
);
425 EXPECT_FOREGROUND(data
[1].hWnd
);
426 EXPECT_ACTIVE(data
[1].hWnd
);
428 ret
= AttachThreadInput( data
[0].tid
, data
[1].tid
, FALSE
);
429 ok(ret
==1, "expected AttachThreadInput to succeed\n");
432 EXPECT_FOREGROUND(data
[1].hWnd
);
435 SetForegroundWindow(data
[0].hWnd
);
436 SetActiveWindow(data
[1].hWnd
);
439 EXPECT_FOREGROUND(data
[0].hWnd
);
440 EXPECT_ACTIVE(data
[0].hWnd
);
442 /* attach thread 1 to 0 */
444 ret
= AttachThreadInput( data
[1].tid
, data
[0].tid
, TRUE
);
445 ok(ret
==1, "expected AttachThreadInput to succeed\n");
448 EXPECT_FOREGROUND(data
[0].hWnd
);
449 EXPECT_ACTIVE(data
[0].hWnd
);
451 SetForegroundWindow(data
[0].hWnd
);
452 SetActiveWindow(data
[1].hWnd
);
455 EXPECT_FOREGROUND(data
[1].hWnd
);
456 EXPECT_ACTIVE(data
[1].hWnd
);
458 ret
= AttachThreadInput( data
[1].tid
, data
[0].tid
, FALSE
);
459 ok(ret
==1, "expected AttachThreadInput to succeed\n");
463 /* test some functions like PostMessage and SendMessage that shouldn't be affected */
464 void Test_UnaffectedMessages()
469 EMPTY_CACHE_(&data
[0].cache
);
470 EMPTY_CACHE_(&data
[1].cache
);
472 /* test that messages posted before and after attachment are unaffected
473 and that we don't receive a meassage from a window we shouldn't */
474 PostMessage(data
[0].hWnd
, WM_USER
, 0,0);
475 PostMessage(data
[1].hWnd
, WM_USER
, 1,0);
478 MSG_ENTRY Thread0_chain
[]={
479 {0,WM_USER
, POST
, 0, 0},
480 {0,WM_USER
, POST
, 2, 0},
482 MSG_ENTRY Thread1_chain
[]={
483 {1,WM_USER
, POST
, 1, 0},
484 {1,WM_USER
, POST
, 3, 0},
487 ret
= AttachThreadInput( data
[1].tid
, data
[0].tid
, TRUE
);
488 ok(ret
==1, "expected AttachThreadInput to succeed\n");
490 PostMessage(data
[0].hWnd
, WM_USER
, 2,0);
491 PostMessage(data
[1].hWnd
, WM_USER
, 3,0);
496 COMPARE_CACHE_(&data
[0].cache
, Thread0_chain
);
497 COMPARE_CACHE_(&data
[1].cache
, Thread1_chain
);
499 ret
= AttachThreadInput( data
[1].tid
, data
[0].tid
, FALSE
);
500 ok(ret
==1, "expected AttachThreadInput to succeed\n");
503 /* test messages send to the wrong thread */
504 res
= SendMessageTimeout(data
[0].hWnd
, WM_USER
, 0,0, SMTO_NORMAL
, 1000, NULL
);
505 ok (res
!= ERROR_TIMEOUT
, "SendMessageTimeout timed out\n");
506 res
= SendMessageTimeout(data
[1].hWnd
, WM_USER
, 1,0, SMTO_NORMAL
, 1000, NULL
);
507 ok (res
!= ERROR_TIMEOUT
, "SendMessageTimeout timed out\n");
510 MSG_ENTRY Thread0_chain
[]={
511 {0,WM_USER
, SENT
, 0, 0},
512 {0,WM_USER
, SENT
, 2, 0},
514 MSG_ENTRY Thread1_chain
[]={
515 {1,WM_USER
, SENT
, 1, 0},
516 {1,WM_USER
, SENT
, 3, 0},
517 {1,WM_MOUSEMOVE
, SENT
, 0, 0},
520 ret
= AttachThreadInput( data
[2].tid
, data
[1].tid
, TRUE
);
521 ok(ret
==1, "expected AttachThreadInput to succeed\n");
523 res
= SendMessageTimeout(data
[0].hWnd
, WM_USER
, 2,0, SMTO_NORMAL
, 1000, NULL
);
524 ok (res
!= ERROR_TIMEOUT
, "SendMessageTimeout timed out\n");
525 res
= SendMessageTimeout(data
[1].hWnd
, WM_USER
, 3,0, SMTO_NORMAL
, 1000, NULL
);
526 ok (res
!= ERROR_TIMEOUT
, "SendMessageTimeout timed out\n");
528 /* Try to send a fake input message */
529 res
= SendMessageTimeout(data
[1].hWnd
, WM_MOUSEMOVE
, 0,0, SMTO_NORMAL
, 1000, NULL
);
530 ok (res
!= ERROR_TIMEOUT
, "SendMessageTimeout timed out\n");
532 COMPARE_CACHE_(&data
[0].cache
, Thread0_chain
);
533 COMPARE_CACHE_(&data
[1].cache
, Thread1_chain
);
535 ret
= AttachThreadInput( data
[2].tid
, data
[1].tid
, FALSE
);
536 ok(ret
==1, "expected AttachThreadInput to succeed\n");
539 /* todo: test keyboard layout that shouldn't be affected */
542 void Test_SendInput()
544 MSG_ENTRY Thread1_chain
[]={
545 {1,WM_KEYDOWN
, POST
, VK_SHIFT
, 0},
546 {1,WM_KEYUP
, POST
, VK_SHIFT
, 0},
548 MSG_ENTRY Thread0_chain
[]={
549 {0,WM_KEYDOWN
, POST
, VK_SHIFT
, 0},
550 {0,WM_KEYUP
, POST
, VK_SHIFT
, 0},
555 /* First try sending input without attaching. It will go to the foreground */
557 SetForegroundWindow(data
[1].hWnd
);
558 SetActiveWindow(data
[0].hWnd
);
560 ok(GetForegroundWindow() == data
[1].hWnd
, "wrong foreground\n");
561 ok(GetActiveWindow() == data
[0].hWnd
, "wrong active\n");
564 EMPTY_CACHE_(&data
[0].cache
);
565 EMPTY_CACHE_(&data
[1].cache
);
567 keybd_event(VK_SHIFT
, 0,0,0);
568 keybd_event(VK_SHIFT
, 0,KEYEVENTF_KEYUP
,0);
572 COMPARE_CACHE_(&data
[0].cache
, empty_chain
);
573 COMPARE_CACHE_(&data
[1].cache
, Thread1_chain
);
576 /* Next attach and send input. It will go to the same thread as before */
578 ret
= AttachThreadInput( data
[1].tid
, data
[0].tid
, TRUE
);
579 ok(ret
==1, "expected AttachThreadInput to succeed\n");
582 EMPTY_CACHE_(&data
[0].cache
);
583 EMPTY_CACHE_(&data
[1].cache
);
585 keybd_event(VK_SHIFT
, 0,0,0);
586 keybd_event(VK_SHIFT
, 0,KEYEVENTF_KEYUP
,0);
590 COMPARE_CACHE_(&data
[0].cache
, empty_chain
);
591 COMPARE_CACHE_(&data
[1].cache
, Thread1_chain
);
594 /* Now set foregroung and active again. Input will go to thread 0 */
596 SetForegroundWindow(data
[1].hWnd
);
597 SetActiveWindow(data
[0].hWnd
);
600 EMPTY_CACHE_(&data
[0].cache
);
601 EMPTY_CACHE_(&data
[1].cache
);
603 keybd_event(VK_SHIFT
, 0,0,0);
604 keybd_event(VK_SHIFT
, 0,KEYEVENTF_KEYUP
,0);
608 COMPARE_CACHE_(&data
[0].cache
, Thread0_chain
);
609 COMPARE_CACHE_(&data
[1].cache
, empty_chain
);
611 ret
= AttachThreadInput( data
[1].tid
, data
[0].tid
, FALSE
);
612 ok(ret
==1, "expected AttachThreadInput to succeed\n");
615 /* Attach in the opposite order and send input */
617 ret
= AttachThreadInput( data
[0].tid
, data
[1].tid
, TRUE
);
618 ok(ret
==1, "expected AttachThreadInput to succeed\n");
621 EMPTY_CACHE_(&data
[0].cache
);
622 EMPTY_CACHE_(&data
[1].cache
);
624 keybd_event(VK_SHIFT
, 0,0,0);
625 keybd_event(VK_SHIFT
, 0,KEYEVENTF_KEYUP
,0);
629 COMPARE_CACHE_(&data
[0].cache
, Thread0_chain
);
630 COMPARE_CACHE_(&data
[1].cache
, empty_chain
);
633 /* Now set foregroung and active again. Input will go to thread 0 */
635 SetForegroundWindow(data
[1].hWnd
);
636 SetActiveWindow(data
[0].hWnd
);
639 EMPTY_CACHE_(&data
[0].cache
);
640 EMPTY_CACHE_(&data
[1].cache
);
642 keybd_event(VK_SHIFT
, 0,0,0);
643 keybd_event(VK_SHIFT
, 0,KEYEVENTF_KEYUP
,0);
647 COMPARE_CACHE_(&data
[0].cache
, Thread0_chain
);
648 COMPARE_CACHE_(&data
[1].cache
, empty_chain
);
650 ret
= AttachThreadInput( data
[0].tid
, data
[1].tid
, FALSE
);
651 ok(ret
==1, "expected AttachThreadInput to succeed\n");
655 START_TEST(AttachThreadInput
)
660 win_skip("skip Test_SimpleParameters that crash ros\n");
661 //Test_SimpleParameters();
662 //cleanup_attachments();
664 cleanup_attachments();
665 Test_UnaffectedMessages();
666 cleanup_attachments();
668 cleanup_attachments();
671 UnhookWindowsHookEx(hMouseHookLL
);
673 UnhookWindowsHookEx(hKbdHookLL
);
675 /* Stop all threads and exit gratefully */
676 PostThreadMessage(data
[1].tid
, WM_QUIT
,0,0);
677 PostThreadMessage(data
[2].tid
, WM_QUIT
,0,0);
678 PostThreadMessage(data
[3].tid
, WM_QUIT
,0,0);
679 PostThreadMessage(data
[4].tid
, WM_QUIT
,0,0);