1 /* Test Key event to Key message translation
2  *
3  * Copyright 2003 Rein Klazes
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19 
20 /* test whether the right type of messages:
21  * WM_KEYUP/DOWN vs WM_SYSKEYUP/DOWN  are sent in case of combined
22  * keystrokes.
23  *
24  * For instance <ALT>-X can be accomplished by
25  * the sequence ALT-KEY-DOWN, X-KEY-DOWN, ALT-KEY-UP, X-KEY-UP
26  * but also X-KEY-DOWN, ALT-KEY-DOWN, X-KEY-UP, ALT-KEY-UP
27  * Whether a KEY or a SYSKEY message is sent is not always clear, it is
28  * also not the same in WINNT as in WIN9X */
29 
30 /* NOTE that there will be test failures under WIN9X
31  * No applications are known to me that rely on this
32  * so I don't fix it */
33 
34 /* TODO:
35  * 1. extend it to the wm_command and wm_syscommand notifications
36  * 2. add some more tests with special cases like dead keys or right (alt) key
37  * 3. there is some adapted code from input.c in here. Should really
38  *    make that code exactly the same.
39  * 4. resolve the win9x case when there is a need or the testing frame work
40  *    offers a nice way.
41  * 5. The test app creates a window, the user should not take the focus
42  *    away during its short existence. I could do something to prevent that
43  *    if it is a problem.
44  *
45  */
46 
47 #ifndef __REACTOS__
48 #define _WIN32_WINNT 0x401
49 #define _WIN32_IE 0x0500
50 #endif
51 
52 #include <stdarg.h>
53 #include <assert.h>
54 
55 #include "windef.h"
56 #include "winbase.h"
57 #include "winuser.h"
58 #include "wingdi.h"
59 #include "winnls.h"
60 
61 #include "wine/test.h"
62 
63 #ifdef __REACTOS__
64 #include <reactos/undocuser.h>
65 #endif
66 
67 /* globals */
68 static HWND hWndTest;
69 static LONG timetag = 0x10000000;
70 
71 static struct {
72     LONG last_key_down;
73     LONG last_key_up;
74     LONG last_syskey_down;
75     LONG last_syskey_up;
76     LONG last_char;
77     LONG last_syschar;
78     LONG last_hook_down;
79     LONG last_hook_up;
80     LONG last_hook_syskey_down;
81     LONG last_hook_syskey_up;
82     BOOL expect_alt;
83     BOOL sendinput_broken;
84 } key_status;
85 
86 static UINT (WINAPI *pSendInput) (UINT, INPUT*, size_t);
87 static int (WINAPI *pGetMouseMovePointsEx) (UINT, LPMOUSEMOVEPOINT, LPMOUSEMOVEPOINT, int, DWORD);
88 static UINT (WINAPI *pGetRawInputDeviceList) (PRAWINPUTDEVICELIST, PUINT, UINT);
89 static int  (WINAPI *pGetWindowRgnBox)(HWND, LPRECT);
90 
91 #define MAXKEYEVENTS 12
92 #define MAXKEYMESSAGES MAXKEYEVENTS /* assuming a key event generates one
93                                        and only one message */
94 
95 /* keyboard message names, sorted as their value */
96 static const char *MSGNAME[]={"WM_KEYDOWN", "WM_KEYUP", "WM_CHAR","WM_DEADCHAR",
97     "WM_SYSKEYDOWN", "WM_SYSKEYUP", "WM_SYSCHAR", "WM_SYSDEADCHAR" ,"WM_KEYLAST"};
98 
99 /* keyevents, add more as needed */
100 typedef enum KEVtag
101 {  ALTDOWN = 1, ALTUP, XDOWN, XUP, SHIFTDOWN, SHIFTUP, CTRLDOWN, CTRLUP } KEV;
102 /* matching VK's */
103 static const int GETVKEY[]={0, VK_MENU, VK_MENU, 'X', 'X', VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL};
104 /* matching scan codes */
105 static const int GETSCAN[]={0, 0x38, 0x38, 0x2D, 0x2D, 0x2A, 0x2A, 0x1D, 0x1D };
106 /* matching updown events */
107 static const int GETFLAGS[]={0, 0, KEYEVENTF_KEYUP, 0, KEYEVENTF_KEYUP, 0, KEYEVENTF_KEYUP, 0, KEYEVENTF_KEYUP};
108 /* matching descriptions */
109 static const char *getdesc[]={"", "+alt","-alt","+X","-X","+shift","-shift","+ctrl","-ctrl"};
110 
111 /* The MSVC headers ignore our NONAMELESSUNION requests so we have to define our own type */
112 typedef struct
113 {
114     DWORD type;
115     union
116     {
117         MOUSEINPUT      mi;
118         KEYBDINPUT      ki;
119         HARDWAREINPUT   hi;
120     } u;
121 } TEST_INPUT;
122 
123 #define ADDTOINPUTS(kev) \
124 inputs[evtctr].type = INPUT_KEYBOARD; \
125     ((TEST_INPUT*)inputs)[evtctr].u.ki.wVk = GETVKEY[ kev]; \
126     ((TEST_INPUT*)inputs)[evtctr].u.ki.wScan = GETSCAN[ kev]; \
127     ((TEST_INPUT*)inputs)[evtctr].u.ki.dwFlags = GETFLAGS[ kev]; \
128     ((TEST_INPUT*)inputs)[evtctr].u.ki.dwExtraInfo = 0; \
129     ((TEST_INPUT*)inputs)[evtctr].u.ki.time = ++timetag; \
130     if( kev) evtctr++;
131 
132 typedef struct {
133     UINT    message;
134     WPARAM  wParam;
135     LPARAM  lParam;
136 } KMSG;
137 
138 /*******************************************
139  * add new test sets here
140  * the software will make all combinations of the
141  * keyevent defined here
142  */
143 static const struct {
144     int nrkev;
145     KEV keydwn[MAXKEYEVENTS];
146     KEV keyup[MAXKEYEVENTS];
147 } testkeyset[]= {
148     { 2, { ALTDOWN, XDOWN }, { ALTUP, XUP}},
149     { 3, { ALTDOWN, XDOWN , SHIFTDOWN}, { ALTUP, XUP, SHIFTUP}},
150     { 3, { ALTDOWN, XDOWN , CTRLDOWN}, { ALTUP, XUP, CTRLUP}},
151     { 3, { SHIFTDOWN, XDOWN , CTRLDOWN}, { SHIFTUP, XUP, CTRLUP}},
152     { 0 } /* mark the end */
153 };
154 
155 /**********************adapted from input.c **********************************/
156 
157 static BYTE InputKeyStateTable[256];
158 static BYTE AsyncKeyStateTable[256];
159 static BYTE TrackSysKey = 0; /* determine whether ALT key up will cause a WM_SYSKEYUP
160                          or a WM_KEYUP message */
161 
162 static void init_function_pointers(void)
163 {
164     HMODULE hdll = GetModuleHandleA("user32");
165 
166 #define GET_PROC(func) \
167     p ## func = (void*)GetProcAddress(hdll, #func); \
168     if(!p ## func) \
169       trace("GetProcAddress(%s) failed\n", #func);
170 
171     GET_PROC(SendInput)
172     GET_PROC(GetMouseMovePointsEx)
173     GET_PROC(GetRawInputDeviceList)
174     GET_PROC(GetWindowRgnBox)
175 
176 #undef GET_PROC
177 }
178 
179 static int KbdMessage( KEV kev, WPARAM *pwParam, LPARAM *plParam )
180 {
181     UINT message;
182     int VKey = GETVKEY[kev];
183     WORD flags;
184 
185     flags = LOBYTE(GETSCAN[kev]);
186     if (GETFLAGS[kev] & KEYEVENTF_EXTENDEDKEY) flags |= KF_EXTENDED;
187 
188     if (GETFLAGS[kev] & KEYEVENTF_KEYUP )
189     {
190         message = WM_KEYUP;
191         if( (InputKeyStateTable[VK_MENU] & 0x80) && (
192                 (VKey == VK_MENU) || (VKey == VK_CONTROL) ||
193                  !(InputKeyStateTable[VK_CONTROL] & 0x80))) {
194             if(  TrackSysKey == VK_MENU || /* <ALT>-down/<ALT>-up sequence */
195                     (VKey != VK_MENU)) /* <ALT>-down...<something else>-up */
196                 message = WM_SYSKEYUP;
197             TrackSysKey = 0;
198         }
199         InputKeyStateTable[VKey] &= ~0x80;
200         flags |= KF_REPEAT | KF_UP;
201     }
202     else
203     {
204         if (InputKeyStateTable[VKey] & 0x80) flags |= KF_REPEAT;
205         if (!(InputKeyStateTable[VKey] & 0x80)) InputKeyStateTable[VKey] ^= 0x01;
206         InputKeyStateTable[VKey] |= 0x80;
207         AsyncKeyStateTable[VKey] |= 0x80;
208 
209         message = WM_KEYDOWN;
210         if( (InputKeyStateTable[VK_MENU] & 0x80) &&
211                 !(InputKeyStateTable[VK_CONTROL] & 0x80)) {
212             message = WM_SYSKEYDOWN;
213             TrackSysKey = VKey;
214         }
215     }
216 
217     if (InputKeyStateTable[VK_MENU] & 0x80) flags |= KF_ALTDOWN;
218 
219     if( plParam) *plParam = MAKELPARAM( 1, flags );
220     if( pwParam) *pwParam = VKey;
221     return message;
222 }
223 
224 /****************************** end copy input.c ****************************/
225 
226 /*
227  * . prepare the keyevents for SendInputs
228  * . calculate the "expected" messages
229  * . Send the events to our window
230  * . retrieve the messages from the input queue
231  * . verify
232  */
233 static BOOL do_test( HWND hwnd, int seqnr, const KEV td[] )
234 {
235     INPUT inputs[MAXKEYEVENTS];
236     KMSG expmsg[MAXKEYEVENTS];
237     MSG msg;
238     char buf[100];
239     UINT evtctr=0;
240     int kmctr, i;
241 
242     buf[0]='\0';
243     TrackSysKey=0; /* see input.c */
244     for( i = 0; i < MAXKEYEVENTS; i++) {
245         ADDTOINPUTS(td[i])
246         strcat(buf, getdesc[td[i]]);
247         if(td[i])
248             expmsg[i].message = KbdMessage(td[i], &(expmsg[i].wParam), &(expmsg[i].lParam));
249         else
250             expmsg[i].message = 0;
251     }
252     for( kmctr = 0; kmctr < MAXKEYEVENTS && expmsg[kmctr].message; kmctr++)
253         ;
254     ok( evtctr <= MAXKEYEVENTS, "evtctr is above MAXKEYEVENTS\n" );
255     if( evtctr != pSendInput(evtctr, &inputs[0], sizeof(INPUT)))
256        ok (FALSE, "SendInput failed to send some events\n");
257     i = 0;
258     if (winetest_debug > 1)
259         trace("======== key stroke sequence #%d: %s =============\n",
260             seqnr + 1, buf);
261     while( PeekMessageA(&msg,hwnd,WM_KEYFIRST,WM_KEYLAST,PM_REMOVE) ) {
262         if (winetest_debug > 1)
263             trace("message[%d] %-15s wParam %04lx lParam %08lx time %x\n", i,
264                   MSGNAME[msg.message - WM_KEYFIRST], msg.wParam, msg.lParam, msg.time);
265         if( i < kmctr ) {
266             ok( msg.message == expmsg[i].message &&
267                 msg.wParam == expmsg[i].wParam &&
268                 msg.lParam == expmsg[i].lParam,
269                 "%u/%u: wrong message %x/%08lx/%08lx expected %s/%08lx/%08lx\n",
270                 seqnr, i, msg.message, msg.wParam, msg.lParam,
271                 MSGNAME[(expmsg[i]).message - WM_KEYFIRST], expmsg[i].wParam, expmsg[i].lParam );
272         }
273         i++;
274     }
275     if (winetest_debug > 1)
276         trace("%d messages retrieved\n", i);
277     if (!i && kmctr)
278     {
279         skip( "simulated keyboard input doesn't work\n" );
280         return FALSE;
281     }
282     ok( i == kmctr, "message count is wrong: got %d expected: %d\n", i, kmctr);
283     return TRUE;
284 }
285 
286 /* test all combinations of the specified key events */
287 static BOOL TestASet( HWND hWnd, int nrkev, const KEV kevdwn[], const KEV kevup[] )
288 {
289     int i,j,k,l,m,n;
290     static int count=0;
291     KEV kbuf[MAXKEYEVENTS];
292     assert( nrkev==2 || nrkev==3);
293     for(i=0;i<MAXKEYEVENTS;i++) kbuf[i]=0;
294     /* two keys involved gives 4 test cases */
295     if(nrkev==2) {
296         for(i=0;i<nrkev;i++) {
297             for(j=0;j<nrkev;j++) {
298                 kbuf[0] = kevdwn[i];
299                 kbuf[1] = kevdwn[1-i];
300                 kbuf[2] = kevup[j];
301                 kbuf[3] = kevup[1-j];
302                 if (!do_test( hWnd, count++, kbuf)) return FALSE;
303             }
304         }
305     }
306     /* three keys involved gives 36 test cases */
307     if(nrkev==3){
308         for(i=0;i<nrkev;i++){
309             for(j=0;j<nrkev;j++){
310                 if(j==i) continue;
311                 for(k=0;k<nrkev;k++){
312                     if(k==i || k==j) continue;
313                     for(l=0;l<nrkev;l++){
314                         for(m=0;m<nrkev;m++){
315                             if(m==l) continue;
316                             for(n=0;n<nrkev;n++){
317                                 if(n==l ||n==m) continue;
318                                 kbuf[0] = kevdwn[i];
319                                 kbuf[1] = kevdwn[j];
320                                 kbuf[2] = kevdwn[k];
321                                 kbuf[3] = kevup[l];
322                                 kbuf[4] = kevup[m];
323                                 kbuf[5] = kevup[n];
324                                 if (!do_test( hWnd, count++, kbuf)) return FALSE;
325                             }
326                         }
327                     }
328                 }
329             }
330         }
331     }
332     return TRUE;
333 }
334 
335 /* test each set specified in the global testkeyset array */
336 static void TestSysKeys( HWND hWnd)
337 {
338     int i;
339     for(i=0; testkeyset[i].nrkev;i++)
340         if (!TestASet( hWnd, testkeyset[i].nrkev, testkeyset[i].keydwn, testkeyset[i].keyup)) break;
341 }
342 
343 static LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam,
344         LPARAM lParam )
345 {
346     return DefWindowProcA( hWnd, msg, wParam, lParam );
347 }
348 
349 static void test_Input_whitebox(void)
350 {
351     MSG msg;
352     WNDCLASSA  wclass;
353     HANDLE hInstance = GetModuleHandleA( NULL );
354 
355     wclass.lpszClassName = "InputSysKeyTestClass";
356     wclass.style         = CS_HREDRAW | CS_VREDRAW;
357     wclass.lpfnWndProc   = WndProc;
358     wclass.hInstance     = hInstance;
359     wclass.hIcon         = LoadIconA( 0, (LPCSTR)IDI_APPLICATION );
360     wclass.hCursor       = LoadCursorA( NULL, (LPCSTR)IDC_ARROW );
361     wclass.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 );
362     wclass.lpszMenuName = 0;
363     wclass.cbClsExtra    = 0;
364     wclass.cbWndExtra    = 0;
365     RegisterClassA( &wclass );
366     /* create the test window that will receive the keystrokes */
367     hWndTest = CreateWindowA( wclass.lpszClassName, "InputSysKeyTest",
368                               WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 100, 100,
369                               NULL, NULL, hInstance, NULL);
370     assert( hWndTest );
371     ShowWindow( hWndTest, SW_SHOW);
372     SetWindowPos( hWndTest, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
373     SetForegroundWindow( hWndTest );
374     UpdateWindow( hWndTest);
375 
376     /* flush pending messages */
377     while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
378 
379     SetFocus( hWndTest );
380     TestSysKeys( hWndTest );
381     DestroyWindow(hWndTest);
382 }
383 
384 static inline BOOL is_keyboard_message( UINT message )
385 {
386     return (message >= WM_KEYFIRST && message <= WM_KEYLAST);
387 }
388 
389 static inline BOOL is_mouse_message( UINT message )
390 {
391     return (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST);
392 }
393 
394 /* try to make sure pending X events have been processed before continuing */
395 static void empty_message_queue(void)
396 {
397     MSG msg;
398     int diff = 200;
399     int min_timeout = 50;
400     DWORD time = GetTickCount() + diff;
401 
402     while (diff > 0)
403     {
404         if (MsgWaitForMultipleObjects(0, NULL, FALSE, min_timeout, QS_ALLINPUT) == WAIT_TIMEOUT) break;
405         while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
406         {
407             if (is_keyboard_message(msg.message) || is_mouse_message(msg.message))
408                 ok(msg.time != 0, "message %#x has time set to 0\n", msg.message);
409 
410             TranslateMessage(&msg);
411             DispatchMessageA(&msg);
412         }
413         diff = time - GetTickCount();
414     }
415 }
416 
417 struct transition_s {
418     WORD wVk;
419     BYTE before_state;
420     BYTE optional;
421 };
422 
423 typedef enum {
424     sent=0x1,
425     posted=0x2,
426     parent=0x4,
427     wparam=0x8,
428     lparam=0x10,
429     defwinproc=0x20,
430     beginpaint=0x40,
431     optional=0x80,
432     hook=0x100,
433     winevent_hook=0x200
434 } msg_flags_t;
435 
436 struct message {
437     UINT message;          /* the WM_* code */
438     msg_flags_t flags;     /* message props */
439     WPARAM wParam;         /* expected value of wParam */
440     LPARAM lParam;         /* expected value of lParam */
441 };
442 
443 static const struct sendinput_test_s {
444     WORD wVk;
445     DWORD dwFlags;
446     BOOL _todo_wine;
447     struct transition_s expected_transitions[MAXKEYEVENTS+1];
448     struct message expected_messages[MAXKEYMESSAGES+1];
449 } sendinput_test[] = {
450     /* test ALT+F */
451     /* 0 */
452     {VK_LMENU, 0, FALSE, {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {0}},
453         {{WM_SYSKEYDOWN, hook|wparam, VK_LMENU}, {WM_SYSKEYDOWN}, {0}}},
454     {'F', 0, FALSE, {{'F', 0x00}, {0}},
455         {{WM_SYSKEYDOWN, hook}, {WM_SYSKEYDOWN},
456         {WM_SYSCHAR},
457         {WM_SYSCOMMAND}, {0}}},
458     {'F', KEYEVENTF_KEYUP, FALSE, {{'F', 0x80}, {0}},
459         {{WM_SYSKEYUP, hook}, {WM_SYSKEYUP}, {0}}},
460     {VK_LMENU, KEYEVENTF_KEYUP, FALSE, {{VK_MENU, 0x80}, {VK_LMENU, 0x80}, {0}},
461         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
462 
463     /* test CTRL+O */
464     /* 4 */
465     {VK_LCONTROL, 0, FALSE, {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}},
466         {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {0}}},
467     {'O', 0, FALSE, {{'O', 0x00}, {0}},
468         {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {WM_CHAR}, {0}}},
469     {'O', KEYEVENTF_KEYUP, FALSE, {{'O', 0x80}, {0}},
470         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
471     {VK_LCONTROL, KEYEVENTF_KEYUP, FALSE, {{VK_CONTROL, 0x80}, {VK_LCONTROL, 0x80}, {0}},
472         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
473 
474     /* test ALT+CTRL+X */
475     /* 8 */
476     {VK_LMENU, 0, FALSE, {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {0}},
477         {{WM_SYSKEYDOWN, hook}, {WM_SYSKEYDOWN}, {0}}},
478     {VK_LCONTROL, 0, FALSE, {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}},
479         {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {0}}},
480     {'X', 0, FALSE, {{'X', 0x00}, {0}},
481         {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {0}}},
482     {'X', KEYEVENTF_KEYUP, FALSE, {{'X', 0x80}, {0}},
483         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
484     {VK_LCONTROL, KEYEVENTF_KEYUP, FALSE, {{VK_CONTROL, 0x80}, {VK_LCONTROL, 0x80}, {0}},
485         {{WM_SYSKEYUP, hook}, {WM_SYSKEYUP}, {0}}},
486     {VK_LMENU, KEYEVENTF_KEYUP, FALSE, {{VK_MENU, 0x80}, {VK_LMENU, 0x80}, {0}},
487         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
488 
489     /* test SHIFT+A */
490     /* 14 */
491     {VK_LSHIFT, 0, FALSE, {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00}, {0}},
492         {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {0}}},
493     {'A', 0, FALSE, {{'A', 0x00}, {0}},
494         {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {WM_CHAR}, {0}}},
495     {'A', KEYEVENTF_KEYUP, FALSE, {{'A', 0x80}, {0}},
496         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
497     {VK_LSHIFT, KEYEVENTF_KEYUP, FALSE, {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80}, {0}},
498         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
499     /* test L-SHIFT & R-SHIFT: */
500     /* RSHIFT == LSHIFT */
501     /* 18 */
502     {VK_RSHIFT, 0, FALSE,
503      /* recent windows versions (>= w2k3) correctly report an RSHIFT transition */
504        {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00, TRUE}, {VK_RSHIFT, 0x00, TRUE}, {0}},
505         {{WM_KEYDOWN, hook|wparam, VK_RSHIFT},
506         {WM_KEYDOWN}, {0}}},
507     {VK_RSHIFT, KEYEVENTF_KEYUP, FALSE,
508        {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80, TRUE}, {VK_RSHIFT, 0x80, TRUE}, {0}},
509         {{WM_KEYUP, hook, hook|wparam, VK_RSHIFT},
510         {WM_KEYUP}, {0}}},
511 
512     /* LSHIFT | KEYEVENTF_EXTENDEDKEY == RSHIFT */
513     /* 20 */
514     {VK_LSHIFT, KEYEVENTF_EXTENDEDKEY, FALSE,
515         {{VK_SHIFT, 0x00}, {VK_RSHIFT, 0x00}, {0}},
516         {{WM_KEYDOWN, hook|wparam|lparam, VK_LSHIFT, LLKHF_EXTENDED},
517         {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}},
518     {VK_LSHIFT, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, FALSE,
519         {{VK_SHIFT, 0x80}, {VK_RSHIFT, 0x80}, {0}},
520         {{WM_KEYUP, hook|wparam|lparam, VK_LSHIFT, LLKHF_UP|LLKHF_EXTENDED},
521         {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}},
522     /* RSHIFT | KEYEVENTF_EXTENDEDKEY == RSHIFT */
523     /* 22 */
524     {VK_RSHIFT, KEYEVENTF_EXTENDEDKEY, FALSE,
525         {{VK_SHIFT, 0x00}, {VK_RSHIFT, 0x00}, {0}},
526         {{WM_KEYDOWN, hook|wparam|lparam, VK_RSHIFT, LLKHF_EXTENDED},
527         {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}},
528     {VK_RSHIFT, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, FALSE,
529         {{VK_SHIFT, 0x80}, {VK_RSHIFT, 0x80}, {0}},
530         {{WM_KEYUP, hook|wparam|lparam, VK_RSHIFT, LLKHF_UP|LLKHF_EXTENDED},
531         {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}},
532 
533     /* Note about wparam for hook with generic key (VK_SHIFT, VK_CONTROL, VK_MENU):
534        win2k  - sends to hook whatever we generated here
535        winXP+ - Attempts to convert key to L/R key but not always correct
536     */
537     /* SHIFT == LSHIFT */
538     /* 24 */
539     {VK_SHIFT, 0, FALSE,
540         {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00}, {0}},
541         {{WM_KEYDOWN, hook/* |wparam */|lparam, VK_SHIFT, 0},
542         {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}},
543     {VK_SHIFT, KEYEVENTF_KEYUP, FALSE,
544         {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80}, {0}},
545         {{WM_KEYUP, hook/*|wparam*/|lparam, VK_SHIFT, LLKHF_UP},
546         {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}},
547     /* SHIFT | KEYEVENTF_EXTENDEDKEY == RSHIFT */
548     /* 26 */
549     {VK_SHIFT, KEYEVENTF_EXTENDEDKEY, FALSE,
550         {{VK_SHIFT, 0x00}, {VK_RSHIFT, 0x00}, {0}},
551         {{WM_KEYDOWN, hook/*|wparam*/|lparam, VK_SHIFT, LLKHF_EXTENDED},
552         {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}},
553     {VK_SHIFT, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, FALSE,
554         {{VK_SHIFT, 0x80}, {VK_RSHIFT, 0x80}, {0}},
555         {{WM_KEYUP, hook/*|wparam*/|lparam, VK_SHIFT, LLKHF_UP|LLKHF_EXTENDED},
556         {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}},
557 
558     /* test L-CONTROL & R-CONTROL: */
559     /* RCONTROL == LCONTROL */
560     /* 28 */
561     {VK_RCONTROL, 0, FALSE,
562         {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}},
563         {{WM_KEYDOWN, hook|wparam, VK_RCONTROL},
564         {WM_KEYDOWN, wparam|lparam, VK_CONTROL, 0}, {0}}},
565     {VK_RCONTROL, KEYEVENTF_KEYUP, FALSE,
566         {{VK_CONTROL, 0x80}, {VK_LCONTROL, 0x80}, {0}},
567         {{WM_KEYUP, hook|wparam, VK_RCONTROL},
568         {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP}, {0}}},
569     /* LCONTROL | KEYEVENTF_EXTENDEDKEY == RCONTROL */
570     /* 30 */
571     {VK_LCONTROL, KEYEVENTF_EXTENDEDKEY, FALSE,
572         {{VK_CONTROL, 0x00}, {VK_RCONTROL, 0x00}, {0}},
573         {{WM_KEYDOWN, hook|wparam|lparam, VK_LCONTROL, LLKHF_EXTENDED},
574         {WM_KEYDOWN, wparam|lparam, VK_CONTROL, KF_EXTENDED}, {0}}},
575     {VK_LCONTROL, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, FALSE,
576         {{VK_CONTROL, 0x80}, {VK_RCONTROL, 0x80}, {0}},
577         {{WM_KEYUP, hook|wparam|lparam, VK_LCONTROL, LLKHF_UP|LLKHF_EXTENDED},
578         {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP|KF_EXTENDED}, {0}}},
579     /* RCONTROL | KEYEVENTF_EXTENDEDKEY == RCONTROL */
580     /* 32 */
581     {VK_RCONTROL, KEYEVENTF_EXTENDEDKEY, FALSE,
582         {{VK_CONTROL, 0x00}, {VK_RCONTROL, 0x00}, {0}},
583         {{WM_KEYDOWN, hook|wparam|lparam, VK_RCONTROL, LLKHF_EXTENDED},
584         {WM_KEYDOWN, wparam|lparam, VK_CONTROL, KF_EXTENDED}, {0}}},
585     {VK_RCONTROL, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, FALSE,
586         {{VK_CONTROL, 0x80}, {VK_RCONTROL, 0x80}, {0}},
587         {{WM_KEYUP, hook|wparam|lparam, VK_RCONTROL, LLKHF_UP|LLKHF_EXTENDED},
588         {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP|KF_EXTENDED}, {0}}},
589     /* CONTROL == LCONTROL */
590     /* 34 */
591     {VK_CONTROL, 0, FALSE,
592         {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}},
593         {{WM_KEYDOWN, hook/*|wparam, VK_CONTROL*/},
594         {WM_KEYDOWN, wparam|lparam, VK_CONTROL, 0}, {0}}},
595     {VK_CONTROL, KEYEVENTF_KEYUP, FALSE,
596         {{VK_CONTROL, 0x80}, {VK_LCONTROL, 0x80}, {0}},
597         {{WM_KEYUP, hook/*|wparam, VK_CONTROL*/},
598         {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP}, {0}}},
599     /* CONTROL | KEYEVENTF_EXTENDEDKEY == RCONTROL */
600     /* 36 */
601     {VK_CONTROL, KEYEVENTF_EXTENDEDKEY, FALSE,
602         {{VK_CONTROL, 0x00}, {VK_RCONTROL, 0x00}, {0}},
603         {{WM_KEYDOWN, hook/*|wparam*/|lparam, VK_CONTROL, LLKHF_EXTENDED},
604         {WM_KEYDOWN, wparam|lparam, VK_CONTROL, KF_EXTENDED}, {0}}},
605     {VK_CONTROL, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, FALSE,
606         {{VK_CONTROL, 0x80}, {VK_RCONTROL, 0x80}, {0}},
607         {{WM_KEYUP, hook/*|wparam*/|lparam, VK_CONTROL, LLKHF_UP|LLKHF_EXTENDED},
608         {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP|KF_EXTENDED}, {0}}},
609 
610     /* test L-MENU & R-MENU: */
611     /* RMENU == LMENU */
612     /* 38 */
613     {VK_RMENU, 0, FALSE,
614         {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {VK_CONTROL, 0x00, 1}, {VK_LCONTROL, 0x01, 1}, {0}},
615         {{WM_SYSKEYDOWN, hook|wparam|optional, VK_LCONTROL},
616         {WM_SYSKEYDOWN, hook|wparam, VK_RMENU},
617         {WM_KEYDOWN, wparam|lparam|optional, VK_CONTROL, 0},
618         {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0}, {0}}},
619     {VK_RMENU, KEYEVENTF_KEYUP, TRUE,
620         {{VK_MENU, 0x80}, {VK_LMENU, 0x80}, {VK_CONTROL, 0x81, 1}, {VK_LCONTROL, 0x80, 1}, {0}},
621         {{WM_KEYUP, hook|wparam|optional, VK_LCONTROL},
622         {WM_KEYUP, hook|wparam, VK_RMENU},
623         {WM_SYSKEYUP, wparam|lparam|optional, VK_CONTROL, KF_UP},
624         {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP},
625         {WM_SYSCOMMAND, optional}, {0}}},
626     /* LMENU | KEYEVENTF_EXTENDEDKEY == RMENU */
627     /* 40 */
628     {VK_LMENU, KEYEVENTF_EXTENDEDKEY, FALSE,
629         {{VK_MENU, 0x00}, {VK_RMENU, 0x00}, {0}},
630         {{WM_SYSKEYDOWN, hook|wparam|lparam, VK_LMENU, LLKHF_EXTENDED},
631         {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, KF_EXTENDED}, {0}}},
632     {VK_LMENU, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, TRUE,
633         {{VK_MENU, 0x80}, {VK_RMENU, 0x80}, {0}},
634         {{WM_KEYUP, hook|wparam|lparam, VK_LMENU, LLKHF_UP|LLKHF_EXTENDED},
635         {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP|KF_EXTENDED},
636         {WM_SYSCOMMAND}, {0}}},
637     /* RMENU | KEYEVENTF_EXTENDEDKEY == RMENU */
638     /* 42 */
639     {VK_RMENU, KEYEVENTF_EXTENDEDKEY, FALSE,
640         {{VK_MENU, 0x00}, {VK_RMENU, 0x00}, {VK_CONTROL, 0x00, 1}, {VK_LCONTROL, 0x01, 1}, {0}},
641         {{WM_SYSKEYDOWN, hook|wparam|lparam|optional, VK_LCONTROL, 0},
642         {WM_SYSKEYDOWN, hook|wparam|lparam, VK_RMENU, LLKHF_EXTENDED},
643         {WM_KEYDOWN, wparam|lparam|optional, VK_CONTROL, 0},
644         {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, KF_EXTENDED}, {0}}},
645     {VK_RMENU, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, TRUE,
646         {{VK_MENU, 0x80}, {VK_RMENU, 0x80}, {VK_CONTROL, 0x81, 1}, {VK_LCONTROL, 0x80, 1}, {0}},
647         {{WM_KEYUP, hook|wparam|lparam|optional, VK_LCONTROL, LLKHF_UP},
648         {WM_KEYUP, hook|wparam|lparam, VK_RMENU, LLKHF_UP|LLKHF_EXTENDED},
649         {WM_SYSKEYUP, wparam|lparam|optional, VK_CONTROL, KF_UP},
650         {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP|KF_EXTENDED},
651         {WM_SYSCOMMAND, optional}, {0}}},
652     /* MENU == LMENU */
653     /* 44 */
654     {VK_MENU, 0, FALSE,
655         {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {0}},
656         {{WM_SYSKEYDOWN, hook/*|wparam, VK_MENU*/},
657         {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0}, {0}}},
658     {VK_MENU, KEYEVENTF_KEYUP, TRUE,
659         {{VK_MENU, 0x80}, {VK_LMENU, 0x80}, {0}},
660         {{WM_KEYUP, hook/*|wparam, VK_MENU*/},
661         {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP},
662         {WM_SYSCOMMAND}, {0}}},
663     /* MENU | KEYEVENTF_EXTENDEDKEY == RMENU */
664     /* 46 */
665     {VK_MENU, KEYEVENTF_EXTENDEDKEY, FALSE,
666         {{VK_MENU, 0x00}, {VK_RMENU, 0x00}, {VK_CONTROL, 0x00, 1}, {VK_LCONTROL, 0x01, 1}, {0}},
667         {{WM_SYSKEYDOWN, hook|wparam|lparam|optional, VK_CONTROL, 0},
668         {WM_SYSKEYDOWN, hook/*|wparam*/|lparam, VK_MENU, LLKHF_EXTENDED},
669         {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, KF_EXTENDED}, {0}}},
670     {VK_MENU, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, TRUE,
671         {{VK_MENU, 0x80}, {VK_RMENU, 0x80}, {VK_CONTROL, 0x81, 1}, {VK_LCONTROL, 0x80, 1}, {0}},
672         {{WM_KEYUP, hook|wparam|lparam|optional, VK_CONTROL, LLKHF_UP},
673         {WM_KEYUP, hook/*|wparam*/|lparam, VK_MENU, LLKHF_UP|LLKHF_EXTENDED},
674         {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP|KF_EXTENDED},
675         {WM_SYSCOMMAND}, {0}}},
676 
677     /* test LSHIFT & RSHIFT */
678     /* 48 */
679     {VK_LSHIFT, 0, FALSE,
680         {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00}, {0}},
681         {{WM_KEYDOWN, hook|wparam|lparam, VK_LSHIFT, 0},
682         {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}},
683     {VK_RSHIFT, KEYEVENTF_EXTENDEDKEY, FALSE,
684         {{VK_RSHIFT, 0x00}, {0}},
685         {{WM_KEYDOWN, hook|wparam|lparam, VK_RSHIFT, LLKHF_EXTENDED},
686         {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}},
687     {VK_RSHIFT, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, FALSE,
688         {{VK_RSHIFT, 0x80}, {0}},
689         {{WM_KEYUP, hook|wparam|lparam, VK_RSHIFT, LLKHF_UP|LLKHF_EXTENDED},
690         {WM_KEYUP, optional}, {0}}},
691     {VK_LSHIFT, KEYEVENTF_KEYUP, FALSE,
692         {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80}, {0}},
693         {{WM_KEYUP, hook|wparam, VK_LSHIFT},
694         {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}},
695 
696     {0, 0, FALSE, {{0}}, {{0}}} /* end */
697 };
698 
699 static struct message sent_messages[MAXKEYMESSAGES];
700 static UINT sent_messages_cnt;
701 
702 /* Verify that only specified key state transitions occur */
703 static void compare_and_check(int id, BYTE *ks1, BYTE *ks2, const struct sendinput_test_s *test)
704 {
705     int i, failcount = 0;
706     const struct transition_s *t = test->expected_transitions;
707     UINT actual_cnt = 0;
708     const struct message *expected = test->expected_messages;
709 
710     while (t->wVk) {
711         BOOL matched = ((ks1[t->wVk]&0x80) == (t->before_state&0x80)
712                        && (ks2[t->wVk]&0x80) == (~t->before_state&0x80));
713 
714         if (!matched && !t->optional && test->_todo_wine)
715         {
716             failcount++;
717             todo_wine {
718                 ok(matched, "%2d (%x/%x): %02x from %02x -> %02x "
719                    "instead of %02x -> %02x\n", id, test->wVk, test->dwFlags,
720                    t->wVk, ks1[t->wVk]&0x80, ks2[t->wVk]&0x80, t->before_state,
721                    ~t->before_state&0x80);
722             }
723         } else {
724             ok(matched || t->optional, "%2d (%x/%x): %02x from %02x -> %02x "
725                "instead of %02x -> %02x\n", id, test->wVk, test->dwFlags,
726                t->wVk, ks1[t->wVk]&0x80, ks2[t->wVk]&0x80, t->before_state,
727                ~t->before_state&0x80);
728         }
729         ks2[t->wVk] = ks1[t->wVk]; /* clear the match */
730         t++;
731     }
732     for (i = 0; i < 256; i++)
733         if (ks2[i] != ks1[i] && test->_todo_wine)
734         {
735             failcount++;
736             todo_wine
737                 ok(FALSE, "%2d (%x/%x): %02x from %02x -> %02x unexpected\n",
738                    id, test->wVk, test->dwFlags, i, ks1[i], ks2[i]);
739         }
740         else
741             ok(ks2[i] == ks1[i], "%2d (%x/%x): %02x from %02x -> %02x unexpected\n",
742                id, test->wVk, test->dwFlags, i, ks1[i], ks2[i]);
743 
744     while (expected->message && actual_cnt < sent_messages_cnt)
745     {
746         const struct message *actual = &sent_messages[actual_cnt];
747 
748         if (expected->message == actual->message)
749         {
750             if (expected->flags & wparam)
751             {
752                 if ((expected->flags & optional) && (expected->wParam != actual->wParam))
753                 {
754                     expected++;
755                     continue;
756                 }
757                 if (expected->wParam != actual->wParam && test->_todo_wine)
758                 {
759                     failcount++;
760                     todo_wine
761                         ok(FALSE, "%2d (%x/%x): in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
762                            id, test->wVk, test->dwFlags, expected->message, expected->wParam, actual->wParam);
763                 }
764                 else
765                     ok(expected->wParam == actual->wParam,
766                        "%2d (%x/%x): in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
767                        id, test->wVk, test->dwFlags, expected->message, expected->wParam, actual->wParam);
768             }
769             if (expected->flags & lparam)
770             {
771                 if (expected->lParam != actual->lParam && test->_todo_wine)
772                 {
773                     failcount++;
774                     todo_wine
775                         ok(FALSE, "%2d (%x/%x): in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
776                            id, test->wVk, test->dwFlags, expected->message, expected->lParam, actual->lParam);
777                 }
778                 else
779                     ok(expected->lParam == actual->lParam,
780                        "%2d (%x/%x): in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
781                        id, test->wVk, test->dwFlags, expected->message, expected->lParam, actual->lParam);
782             }
783             ok((expected->flags & hook) == (actual->flags & hook),
784                "%2d (%x/%x): the msg 0x%04x should have been sent by a hook\n",
785                id, test->wVk, test->dwFlags, expected->message);
786 
787         }
788         else if (expected->flags & optional)
789         {
790             expected++;
791             continue;
792         }
793         /* NT4 doesn't send SYSKEYDOWN/UP to hooks, only KEYDOWN/UP */
794         else if ((expected->flags & hook) &&
795                  (expected->message == WM_SYSKEYDOWN || expected->message == WM_SYSKEYUP) &&
796                  (actual->message == expected->message - 4))
797         {
798             ok((expected->flags & hook) == (actual->flags & hook),
799                "%2d (%x/%x): the msg 0x%04x should have been sent by a hook\n",
800                id, test->wVk, test->dwFlags, expected->message);
801         }
802         /* For VK_RMENU, at least localized Win2k/XP sends KEYDOWN/UP
803          * instead of SYSKEYDOWN/UP to the WNDPROC */
804         else if (test->wVk == VK_RMENU && !(expected->flags & hook) &&
805                  (expected->message == WM_SYSKEYDOWN || expected->message == WM_SYSKEYUP) &&
806                  (actual->message == expected->message - 4))
807         {
808             ok(expected->wParam == actual->wParam && expected->lParam == actual->lParam,
809                "%2d (%x/%x): the msg 0x%04x was expected, but got msg 0x%04x instead\n",
810                id, test->wVk, test->dwFlags, expected->message, actual->message);
811         }
812         else if (test->_todo_wine)
813         {
814             failcount++;
815             todo_wine
816             ok(FALSE,
817                "%2d (%x/%x): the msg 0x%04x was expected, but got msg 0x%04x instead\n",
818                id, test->wVk, test->dwFlags, expected->message, actual->message);
819         }
820         else
821             ok(FALSE,
822                "%2d (%x/%x): the msg 0x%04x was expected, but got msg 0x%04x instead\n",
823                id, test->wVk, test->dwFlags, expected->message, actual->message);
824 
825         actual_cnt++;
826         expected++;
827     }
828     /* skip all optional trailing messages */
829     while (expected->message && (expected->flags & optional))
830         expected++;
831 
832 
833     if (expected->message || actual_cnt < sent_messages_cnt)
834     {
835         if (test->_todo_wine)
836         {
837             failcount++;
838             todo_wine
839                 ok(FALSE, "%2d (%x/%x): the msg sequence is not complete: expected %04x - actual %04x\n",
840                    id, test->wVk, test->dwFlags, expected->message, sent_messages[actual_cnt].message);
841         }
842         else
843             ok(FALSE, "%2d (%x/%x): the msg sequence is not complete: expected %04x - actual %04x\n",
844                id, test->wVk, test->dwFlags, expected->message, sent_messages[actual_cnt].message);
845     }
846 
847     if( test->_todo_wine && !failcount) /* succeeded yet marked todo */
848         todo_wine
849             ok(TRUE, "%2d (%x/%x): marked \"todo_wine\" but succeeds\n", id, test->wVk, test->dwFlags);
850 
851     sent_messages_cnt = 0;
852 }
853 
854 /* WndProc2 checks that we get at least the messages specified */
855 static LRESULT CALLBACK WndProc2(HWND hWnd, UINT Msg, WPARAM wParam,
856                                    LPARAM lParam)
857 {
858     if (winetest_debug > 1) trace("MSG:  %8x W:%8lx L:%8lx\n", Msg, wParam, lParam);
859 
860     if (Msg != WM_PAINT &&
861         Msg != WM_NCPAINT &&
862         Msg != WM_SYNCPAINT &&
863         Msg != WM_ERASEBKGND &&
864         Msg != WM_NCHITTEST &&
865         Msg != WM_GETTEXT &&
866         Msg != WM_GETICON &&
867         Msg != WM_IME_SELECT &&
868         Msg != WM_DEVICECHANGE &&
869         Msg != WM_TIMECHANGE)
870     {
871         ok(sent_messages_cnt < MAXKEYMESSAGES, "Too many messages\n");
872         if (sent_messages_cnt < MAXKEYMESSAGES)
873         {
874             sent_messages[sent_messages_cnt].message = Msg;
875             sent_messages[sent_messages_cnt].flags = 0;
876             sent_messages[sent_messages_cnt].wParam = wParam;
877             sent_messages[sent_messages_cnt++].lParam = HIWORD(lParam) & (KF_UP|KF_EXTENDED);
878         }
879     }
880     return DefWindowProcA(hWnd, Msg, wParam, lParam);
881 }
882 
883 static LRESULT CALLBACK hook_proc(int code, WPARAM wparam, LPARAM lparam)
884 {
885     KBDLLHOOKSTRUCT *hook_info = (KBDLLHOOKSTRUCT *)lparam;
886 
887     if (code == HC_ACTION)
888     {
889         ok(sent_messages_cnt < MAXKEYMESSAGES, "Too many messages\n");
890         if (sent_messages_cnt < MAXKEYMESSAGES)
891         {
892             sent_messages[sent_messages_cnt].message = wparam;
893             sent_messages[sent_messages_cnt].flags = hook;
894             sent_messages[sent_messages_cnt].wParam = hook_info->vkCode;
895             sent_messages[sent_messages_cnt++].lParam = hook_info->flags & (LLKHF_UP|LLKHF_EXTENDED);
896         }
897 
898 if(0) /* For some reason not stable on Wine */
899 {
900         if (wparam == WM_KEYDOWN || wparam == WM_SYSKEYDOWN)
901             ok(!(GetAsyncKeyState(hook_info->vkCode) & 0x8000), "key %x should be up\n", hook_info->vkCode);
902         else if (wparam == WM_KEYUP || wparam == WM_SYSKEYUP)
903             ok(GetAsyncKeyState(hook_info->vkCode) & 0x8000, "key %x should be down\n", hook_info->vkCode);
904 }
905 
906         if (winetest_debug > 1)
907             trace("Hook:   w=%lx vk:%8x sc:%8x fl:%8x %lx\n", wparam,
908                   hook_info->vkCode, hook_info->scanCode, hook_info->flags, hook_info->dwExtraInfo);
909     }
910     return CallNextHookEx( 0, code, wparam, lparam );
911 }
912 static void test_Input_blackbox(void)
913 {
914     TEST_INPUT i;
915     int ii;
916     BYTE ks1[256], ks2[256];
917     LONG_PTR prevWndProc;
918     HWND window;
919     HHOOK hook;
920 
921     if (GetKeyboardLayout(0) != (HKL)(ULONG_PTR)0x04090409)
922     {
923         skip("Skipping Input_blackbox test on non-US keyboard\n");
924         return;
925     }
926     window = CreateWindowA("Static", NULL, WS_POPUP|WS_HSCROLL|WS_VSCROLL
927         |WS_VISIBLE, 0, 0, 200, 60, NULL, NULL,
928         NULL, NULL);
929     ok(window != NULL, "error: %d\n", (int) GetLastError());
930     SetWindowPos( window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
931     SetForegroundWindow( window );
932 
933     if (!(hook = SetWindowsHookExA(WH_KEYBOARD_LL, hook_proc, GetModuleHandleA( NULL ), 0)))
934     {
935         DestroyWindow(window);
936         win_skip("WH_KEYBOARD_LL is not supported\n");
937         return;
938     }
939 
940     /* must process all initial messages, otherwise X11DRV_KeymapNotify unsets
941      * key state set by SendInput(). */
942     empty_message_queue();
943 
944     prevWndProc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR) WndProc2);
945     ok(prevWndProc != 0 || GetLastError() == 0, "error: %d\n", (int) GetLastError());
946 
947     i.type = INPUT_KEYBOARD;
948     i.u.ki.time = 0;
949     i.u.ki.dwExtraInfo = 0;
950 
951     for (ii = 0; ii < sizeof(sendinput_test)/sizeof(struct sendinput_test_s)-1;
952          ii++) {
953         GetKeyboardState(ks1);
954         i.u.ki.wScan = ii+1 /* useful for debugging */;
955         i.u.ki.dwFlags = sendinput_test[ii].dwFlags;
956         i.u.ki.wVk = sendinput_test[ii].wVk;
957         pSendInput(1, (INPUT*)&i, sizeof(TEST_INPUT));
958         empty_message_queue();
959         GetKeyboardState(ks2);
960         if (!ii && sent_messages_cnt <= 1 && !memcmp( ks1, ks2, sizeof(ks1) ))
961         {
962             win_skip( "window doesn't receive the queued input\n" );
963             /* release the key */
964             i.u.ki.dwFlags |= KEYEVENTF_KEYUP;
965             pSendInput(1, (INPUT*)&i, sizeof(TEST_INPUT));
966             break;
967         }
968         compare_and_check(ii, ks1, ks2, &sendinput_test[ii]);
969     }
970 
971     empty_message_queue();
972     DestroyWindow(window);
973     UnhookWindowsHookEx(hook);
974 }
975 
976 static void reset_key_status(void)
977 {
978     key_status.last_key_down = -1;
979     key_status.last_key_up = -1;
980     key_status.last_syskey_down = -1;
981     key_status.last_syskey_up = -1;
982     key_status.last_char = -1;
983     key_status.last_syschar = -1;
984     key_status.last_hook_down = -1;
985     key_status.last_hook_up = -1;
986     key_status.last_hook_syskey_down = -1;
987     key_status.last_hook_syskey_up = -1;
988     key_status.expect_alt = FALSE;
989     key_status.sendinput_broken = FALSE;
990 }
991 
992 static void test_unicode_keys(HWND hwnd, HHOOK hook)
993 {
994     TEST_INPUT inputs[2];
995     MSG msg;
996 
997     /* init input data that never changes */
998     inputs[1].type = inputs[0].type = INPUT_KEYBOARD;
999     inputs[1].u.ki.dwExtraInfo = inputs[0].u.ki.dwExtraInfo = 0;
1000     inputs[1].u.ki.time = inputs[0].u.ki.time = 0;
1001 
1002     /* pressing & releasing a single unicode character */
1003     inputs[0].u.ki.wVk = 0;
1004     inputs[0].u.ki.wScan = 0x3c0;
1005     inputs[0].u.ki.dwFlags = KEYEVENTF_UNICODE;
1006 
1007     reset_key_status();
1008     pSendInput(1, (INPUT*)inputs, sizeof(INPUT));
1009     while(PeekMessageW(&msg, hwnd, 0, 0, PM_REMOVE)){
1010         if(msg.message == WM_KEYDOWN && msg.wParam == VK_PACKET){
1011             TranslateMessage(&msg);
1012         }
1013         DispatchMessageW(&msg);
1014     }
1015     if(!key_status.sendinput_broken){
1016         ok(key_status.last_key_down == VK_PACKET,
1017             "Last keydown msg should have been VK_PACKET[0x%04x] (was: 0x%x)\n", VK_PACKET, key_status.last_key_down);
1018         ok(key_status.last_char == 0x3c0,
1019             "Last char msg wparam should have been 0x3c0 (was: 0x%x)\n", key_status.last_char);
1020         if(hook)
1021             ok(key_status.last_hook_down == 0x3c0,
1022                 "Last hookdown msg should have been 0x3c0, was: 0x%x\n", key_status.last_hook_down);
1023     }
1024 
1025     inputs[1].u.ki.wVk = 0;
1026     inputs[1].u.ki.wScan = 0x3c0;
1027     inputs[1].u.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
1028 
1029     reset_key_status();
1030     pSendInput(1, (INPUT*)(inputs+1), sizeof(INPUT));
1031     while(PeekMessageW(&msg, hwnd, 0, 0, PM_REMOVE)){
1032         if(msg.message == WM_KEYDOWN && msg.wParam == VK_PACKET){
1033             TranslateMessage(&msg);
1034         }
1035         DispatchMessageW(&msg);
1036     }
1037     if(!key_status.sendinput_broken){
1038         ok(key_status.last_key_up == VK_PACKET,
1039             "Last keyup msg should have been VK_PACKET[0x%04x] (was: 0x%x)\n", VK_PACKET, key_status.last_key_up);
1040         if(hook)
1041             ok(key_status.last_hook_up == 0x3c0,
1042                 "Last hookup msg should have been 0x3c0, was: 0x%x\n", key_status.last_hook_up);
1043     }
1044 
1045     /* holding alt, pressing & releasing a unicode character, releasing alt */
1046     inputs[0].u.ki.wVk = VK_LMENU;
1047     inputs[0].u.ki.wScan = 0;
1048     inputs[0].u.ki.dwFlags = 0;
1049 
1050     inputs[1].u.ki.wVk = 0;
1051     inputs[1].u.ki.wScan = 0x3041;
1052     inputs[1].u.ki.dwFlags = KEYEVENTF_UNICODE;
1053 
1054     reset_key_status();
1055     key_status.expect_alt = TRUE;
1056     pSendInput(2, (INPUT*)inputs, sizeof(INPUT));
1057     while(PeekMessageW(&msg, hwnd, 0, 0, PM_REMOVE)){
1058         if(msg.message == WM_SYSKEYDOWN && msg.wParam == VK_PACKET){
1059             TranslateMessage(&msg);
1060         }
1061         DispatchMessageW(&msg);
1062     }
1063     if(!key_status.sendinput_broken){
1064         ok(key_status.last_syskey_down == VK_PACKET,
1065             "Last syskeydown msg should have been VK_PACKET[0x%04x] (was: 0x%x)\n", VK_PACKET, key_status.last_syskey_down);
1066         ok(key_status.last_syschar == 0x3041,
1067             "Last syschar msg should have been 0x3041 (was: 0x%x)\n", key_status.last_syschar);
1068         if(hook)
1069             ok(key_status.last_hook_syskey_down == 0x3041,
1070                 "Last hooksysdown msg should have been 0x3041, was: 0x%x\n", key_status.last_hook_syskey_down);
1071     }
1072 
1073     inputs[1].u.ki.wVk = 0;
1074     inputs[1].u.ki.wScan = 0x3041;
1075     inputs[1].u.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
1076 
1077     inputs[0].u.ki.wVk = VK_LMENU;
1078     inputs[0].u.ki.wScan = 0;
1079     inputs[0].u.ki.dwFlags = KEYEVENTF_KEYUP;
1080 
1081     reset_key_status();
1082     key_status.expect_alt = TRUE;
1083     pSendInput(2, (INPUT*)inputs, sizeof(INPUT));
1084     while(PeekMessageW(&msg, hwnd, 0, 0, PM_REMOVE)){
1085         if(msg.message == WM_SYSKEYDOWN && msg.wParam == VK_PACKET){
1086             TranslateMessage(&msg);
1087         }
1088         DispatchMessageW(&msg);
1089     }
1090     if(!key_status.sendinput_broken){
1091         ok(key_status.last_key_up == VK_PACKET,
1092             "Last keyup msg should have been VK_PACKET[0x%04x] (was: 0x%x)\n", VK_PACKET, key_status.last_key_up);
1093         if(hook)
1094             ok(key_status.last_hook_up == 0x3041,
1095                 "Last hook up msg should have been 0x3041, was: 0x%x\n", key_status.last_hook_up);
1096     }
1097 }
1098 
1099 static LRESULT CALLBACK unicode_wnd_proc( HWND hWnd, UINT msg, WPARAM wParam,
1100         LPARAM lParam )
1101 {
1102     switch(msg){
1103     case WM_KEYDOWN:
1104         key_status.last_key_down = wParam;
1105         break;
1106     case WM_SYSKEYDOWN:
1107         key_status.last_syskey_down = wParam;
1108         break;
1109     case WM_KEYUP:
1110         key_status.last_key_up = wParam;
1111         break;
1112     case WM_SYSKEYUP:
1113         key_status.last_syskey_up = wParam;
1114         break;
1115     case WM_CHAR:
1116         key_status.last_char = wParam;
1117         break;
1118     case WM_SYSCHAR:
1119         key_status.last_syschar = wParam;
1120         break;
1121     }
1122     return DefWindowProcW(hWnd, msg, wParam, lParam);
1123 }
1124 
1125 static LRESULT CALLBACK llkbd_unicode_hook(int nCode, WPARAM wParam, LPARAM lParam)
1126 {
1127     if(nCode == HC_ACTION){
1128         LPKBDLLHOOKSTRUCT info = (LPKBDLLHOOKSTRUCT)lParam;
1129         if(!info->vkCode){
1130             key_status.sendinput_broken = TRUE;
1131             win_skip("SendInput doesn't support unicode on this platform\n");
1132         }else{
1133             if(key_status.expect_alt){
1134                 ok(info->vkCode == VK_LMENU, "vkCode should have been VK_LMENU[0x%04x], was: 0x%x\n", VK_LMENU, info->vkCode);
1135                 key_status.expect_alt = FALSE;
1136             }else
1137                 ok(info->vkCode == VK_PACKET, "vkCode should have been VK_PACKET[0x%04x], was: 0x%x\n", VK_PACKET, info->vkCode);
1138         }
1139         switch(wParam){
1140         case WM_KEYDOWN:
1141             key_status.last_hook_down = info->scanCode;
1142             break;
1143         case WM_KEYUP:
1144             key_status.last_hook_up = info->scanCode;
1145             break;
1146         case WM_SYSKEYDOWN:
1147             key_status.last_hook_syskey_down = info->scanCode;
1148             break;
1149         case WM_SYSKEYUP:
1150             key_status.last_hook_syskey_up = info->scanCode;
1151             break;
1152         }
1153     }
1154     return CallNextHookEx(NULL, nCode, wParam, lParam);
1155 }
1156 
1157 static void test_Input_unicode(void)
1158 {
1159     WCHAR classNameW[] = {'I','n','p','u','t','U','n','i','c','o','d','e',
1160         'K','e','y','T','e','s','t','C','l','a','s','s',0};
1161     WCHAR windowNameW[] = {'I','n','p','u','t','U','n','i','c','o','d','e',
1162         'K','e','y','T','e','s','t',0};
1163     MSG msg;
1164     WNDCLASSW wclass;
1165     HANDLE hInstance = GetModuleHandleW(NULL);
1166     HHOOK hook;
1167     HMODULE hModuleImm32;
1168     BOOL (WINAPI *pImmDisableIME)(DWORD);
1169 
1170     wclass.lpszClassName = classNameW;
1171     wclass.style         = CS_HREDRAW | CS_VREDRAW;
1172     wclass.lpfnWndProc   = unicode_wnd_proc;
1173     wclass.hInstance     = hInstance;
1174     wclass.hIcon         = LoadIconW(0, (LPCWSTR)IDI_APPLICATION);
1175     wclass.hCursor       = LoadCursorW( NULL, (LPCWSTR)IDC_ARROW);
1176     wclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1177     wclass.lpszMenuName  = 0;
1178     wclass.cbClsExtra    = 0;
1179     wclass.cbWndExtra    = 0;
1180     if(!RegisterClassW(&wclass)){
1181         win_skip("Unicode functions not supported\n");
1182         return;
1183     }
1184 
1185     hModuleImm32 = LoadLibraryA("imm32.dll");
1186     if (hModuleImm32) {
1187         pImmDisableIME = (void *)GetProcAddress(hModuleImm32, "ImmDisableIME");
1188         if (pImmDisableIME)
1189             pImmDisableIME(0);
1190     }
1191     pImmDisableIME = NULL;
1192     FreeLibrary(hModuleImm32);
1193 
1194     /* create the test window that will receive the keystrokes */
1195     hWndTest = CreateWindowW(wclass.lpszClassName, windowNameW,
1196                              WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 100, 100,
1197                              NULL, NULL, hInstance, NULL);
1198 
1199     assert(hWndTest);
1200     assert(IsWindowUnicode(hWndTest));
1201 
1202     hook = SetWindowsHookExW(WH_KEYBOARD_LL, llkbd_unicode_hook, GetModuleHandleW(NULL), 0);
1203     if(!hook)
1204         win_skip("unable to set WH_KEYBOARD_LL hook\n");
1205 
1206     ShowWindow(hWndTest, SW_SHOW);
1207     SetWindowPos(hWndTest, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1208     SetForegroundWindow(hWndTest);
1209     UpdateWindow(hWndTest);
1210 
1211     /* flush pending messages */
1212     while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageW(&msg);
1213 
1214     SetFocus(hWndTest);
1215 
1216     test_unicode_keys(hWndTest, hook);
1217 
1218     if(hook)
1219         UnhookWindowsHookEx(hook);
1220     DestroyWindow(hWndTest);
1221 }
1222 
1223 static void test_keynames(void)
1224 {
1225     int i, len;
1226     char buff[256];
1227 
1228     for (i = 0; i < 512; i++)
1229     {
1230         strcpy(buff, "----");
1231         len = GetKeyNameTextA(i << 16, buff, sizeof(buff));
1232         ok(len || !buff[0], "%d: Buffer is not zeroed\n", i);
1233     }
1234 }
1235 
1236 static POINT pt_old, pt_new;
1237 static BOOL clipped;
1238 #define STEP 3
1239 
1240 static LRESULT CALLBACK hook_proc1( int code, WPARAM wparam, LPARAM lparam )
1241 {
1242     MSLLHOOKSTRUCT *hook = (MSLLHOOKSTRUCT *)lparam;
1243     POINT pt, pt1;
1244 
1245     if (code == HC_ACTION)
1246     {
1247         /* This is our new cursor position */
1248         pt_new = hook->pt;
1249         /* Should return previous position */
1250         GetCursorPos(&pt);
1251         ok(pt.x == pt_old.x && pt.y == pt_old.y, "GetCursorPos: (%d,%d)\n", pt.x, pt.y);
1252 
1253         /* Should set new position until hook chain is finished. */
1254         pt.x = pt_old.x + STEP;
1255         pt.y = pt_old.y + STEP;
1256         SetCursorPos(pt.x, pt.y);
1257         GetCursorPos(&pt1);
1258         if (clipped)
1259             ok(pt1.x == pt_old.x && pt1.y == pt_old.y, "Wrong set pos: (%d,%d)\n", pt1.x, pt1.y);
1260         else
1261             ok(pt1.x == pt.x && pt1.y == pt.y, "Wrong set pos: (%d,%d)\n", pt1.x, pt1.y);
1262     }
1263     return CallNextHookEx( 0, code, wparam, lparam );
1264 }
1265 
1266 static LRESULT CALLBACK hook_proc2( int code, WPARAM wparam, LPARAM lparam )
1267 {
1268     MSLLHOOKSTRUCT *hook = (MSLLHOOKSTRUCT *)lparam;
1269     POINT pt;
1270 
1271     if (code == HC_ACTION)
1272     {
1273         ok(hook->pt.x == pt_new.x && hook->pt.y == pt_new.y,
1274            "Wrong hook coords: (%d %d) != (%d,%d)\n", hook->pt.x, hook->pt.y, pt_new.x, pt_new.y);
1275 
1276         /* Should match position set above */
1277         GetCursorPos(&pt);
1278         if (clipped)
1279             ok(pt.x == pt_old.x && pt.y == pt_old.y, "GetCursorPos: (%d,%d)\n", pt.x, pt.y);
1280         else
1281             ok(pt.x == pt_old.x +STEP && pt.y == pt_old.y +STEP, "GetCursorPos: (%d,%d)\n", pt.x, pt.y);
1282     }
1283     return CallNextHookEx( 0, code, wparam, lparam );
1284 }
1285 
1286 static LRESULT CALLBACK hook_proc3( int code, WPARAM wparam, LPARAM lparam )
1287 {
1288     POINT pt;
1289 
1290     if (code == HC_ACTION)
1291     {
1292         /* MSLLHOOKSTRUCT does not seem to be reliable and contains different data on each run. */
1293         GetCursorPos(&pt);
1294         ok(pt.x == pt_old.x && pt.y == pt_old.y, "GetCursorPos: (%d,%d)\n", pt.x, pt.y);
1295     }
1296     return CallNextHookEx( 0, code, wparam, lparam );
1297 }
1298 
1299 static void test_mouse_ll_hook(void)
1300 {
1301     HWND hwnd;
1302     HHOOK hook1, hook2;
1303     POINT pt_org, pt;
1304     RECT rc;
1305 
1306     GetCursorPos(&pt_org);
1307     hwnd = CreateWindowA("static", "Title", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1308                         10, 10, 200, 200, NULL, NULL, NULL, NULL);
1309     SetCursorPos(100, 100);
1310 
1311     if (!(hook2 = SetWindowsHookExA(WH_MOUSE_LL, hook_proc2, GetModuleHandleA(0), 0)))
1312     {
1313         win_skip( "cannot set MOUSE_LL hook\n" );
1314         goto done;
1315     }
1316     hook1 = SetWindowsHookExA(WH_MOUSE_LL, hook_proc1, GetModuleHandleA(0), 0);
1317 
1318     GetCursorPos(&pt_old);
1319     mouse_event(MOUSEEVENTF_MOVE, -STEP,  0, 0, 0);
1320     GetCursorPos(&pt_old);
1321     ok(pt_old.x == pt_new.x && pt_old.y == pt_new.y, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
1322     mouse_event(MOUSEEVENTF_MOVE, +STEP,  0, 0, 0);
1323     GetCursorPos(&pt_old);
1324     ok(pt_old.x == pt_new.x && pt_old.y == pt_new.y, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
1325     mouse_event(MOUSEEVENTF_MOVE,  0, -STEP, 0, 0);
1326     GetCursorPos(&pt_old);
1327     ok(pt_old.x == pt_new.x && pt_old.y == pt_new.y, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
1328     mouse_event(MOUSEEVENTF_MOVE,  0, +STEP, 0, 0);
1329     GetCursorPos(&pt_old);
1330     ok(pt_old.x == pt_new.x && pt_old.y == pt_new.y, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
1331 
1332     SetRect(&rc, 50, 50, 151, 151);
1333     ClipCursor(&rc);
1334     clipped = TRUE;
1335 
1336     SetCursorPos(40, 40);
1337     GetCursorPos(&pt_old);
1338     ok(pt_old.x == 50 && pt_old.y == 50, "Wrong new pos: (%d,%d)\n", pt_new.x, pt_new.y);
1339     SetCursorPos(160, 160);
1340     GetCursorPos(&pt_old);
1341     ok(pt_old.x == 150 && pt_old.y == 150, "Wrong new pos: (%d,%d)\n", pt_new.x, pt_new.y);
1342     mouse_event(MOUSEEVENTF_MOVE, +STEP, +STEP, 0, 0);
1343     GetCursorPos(&pt_old);
1344     ok(pt_old.x == 150 && pt_old.y == 150, "Wrong new pos: (%d,%d)\n", pt_new.x, pt_new.y);
1345 
1346     clipped = FALSE;
1347     pt_new.x = pt_new.y = 150;
1348     ClipCursor(NULL);
1349     UnhookWindowsHookEx(hook1);
1350 
1351     /* Now check that mouse buttons do not change mouse position
1352        if we don't have MOUSEEVENTF_MOVE flag specified. */
1353 
1354     /* We reusing the same hook callback, so make it happy */
1355     pt_old.x = pt_new.x - STEP;
1356     pt_old.y = pt_new.y - STEP;
1357     mouse_event(MOUSEEVENTF_LEFTUP, 123, 456, 0, 0);
1358     GetCursorPos(&pt);
1359     ok(pt.x == pt_new.x && pt.y == pt_new.y, "Position changed: (%d,%d)\n", pt.x, pt.y);
1360     mouse_event(MOUSEEVENTF_RIGHTUP, 456, 123, 0, 0);
1361     GetCursorPos(&pt);
1362     ok(pt.x == pt_new.x && pt.y == pt_new.y, "Position changed: (%d,%d)\n", pt.x, pt.y);
1363 
1364     mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE, 123, 456, 0, 0);
1365     GetCursorPos(&pt);
1366     ok(pt.x == pt_new.x && pt.y == pt_new.y, "Position changed: (%d,%d)\n", pt.x, pt.y);
1367     mouse_event(MOUSEEVENTF_RIGHTUP | MOUSEEVENTF_ABSOLUTE, 456, 123, 0, 0);
1368     GetCursorPos(&pt);
1369     ok(pt.x == pt_new.x && pt.y == pt_new.y, "Position changed: (%d,%d)\n", pt.x, pt.y);
1370 
1371     UnhookWindowsHookEx(hook2);
1372     hook1 = SetWindowsHookExA(WH_MOUSE_LL, hook_proc3, GetModuleHandleA(0), 0);
1373 
1374     SetRect(&rc, 150, 150, 150, 150);
1375     ClipCursor(&rc);
1376     clipped = TRUE;
1377 
1378     SetCursorPos(140, 140);
1379     GetCursorPos(&pt_old);
1380     ok(pt_old.x == 150 && pt_old.y == 150, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
1381     SetCursorPos(160, 160);
1382     GetCursorPos(&pt_old);
1383     todo_wine
1384     ok(pt_old.x == 149 && pt_old.y == 149, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
1385     mouse_event(MOUSEEVENTF_MOVE, -STEP, -STEP, 0, 0);
1386     GetCursorPos(&pt_old);
1387     ok(pt_old.x == 150 && pt_old.y == 150, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
1388     mouse_event(MOUSEEVENTF_MOVE, +STEP, +STEP, 0, 0);
1389     GetCursorPos(&pt_old);
1390     todo_wine
1391     ok(pt_old.x == 149 && pt_old.y == 149, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
1392     mouse_event(MOUSEEVENTF_MOVE, 0, 0, 0, 0);
1393     GetCursorPos(&pt_old);
1394     ok(pt_old.x == 150 && pt_old.y == 150, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
1395     mouse_event(MOUSEEVENTF_MOVE, 0, 0, 0, 0);
1396     GetCursorPos(&pt_old);
1397     todo_wine
1398     ok(pt_old.x == 149 && pt_old.y == 149, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
1399 
1400     clipped = FALSE;
1401     ClipCursor(NULL);
1402 
1403     SetCursorPos(140, 140);
1404     SetRect(&rc, 150, 150, 150, 150);
1405     ClipCursor(&rc);
1406     GetCursorPos(&pt_old);
1407     ok(pt_old.x == 150 && pt_old.y == 150, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
1408     ClipCursor(NULL);
1409 
1410     SetCursorPos(160, 160);
1411     SetRect(&rc, 150, 150, 150, 150);
1412     ClipCursor(&rc);
1413     GetCursorPos(&pt_old);
1414     todo_wine
1415     ok(pt_old.x == 149 && pt_old.y == 149, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
1416     ClipCursor(NULL);
1417 
1418     SetCursorPos(150, 150);
1419     SetRect(&rc, 150, 150, 150, 150);
1420     ClipCursor(&rc);
1421     GetCursorPos(&pt_old);
1422     todo_wine
1423     ok(pt_old.x == 149 && pt_old.y == 149, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
1424     ClipCursor(NULL);
1425 
1426     UnhookWindowsHookEx(hook1);
1427 
1428 done:
1429     DestroyWindow(hwnd);
1430     SetCursorPos(pt_org.x, pt_org.y);
1431 }
1432 
1433 static void test_GetMouseMovePointsEx(void)
1434 {
1435 #define BUFLIM  64
1436 #define MYERROR 0xdeadbeef
1437     int count, retval;
1438     MOUSEMOVEPOINT in;
1439     MOUSEMOVEPOINT out[200];
1440     POINT point;
1441 
1442     /* Get a valid content for the input struct */
1443     if(!GetCursorPos(&point)) {
1444         win_skip("GetCursorPos() failed with error %u\n", GetLastError());
1445         return;
1446     }
1447     memset(&in, 0, sizeof(MOUSEMOVEPOINT));
1448     in.x = point.x;
1449     in.y = point.y;
1450 
1451     /* test first parameter
1452      * everything different than sizeof(MOUSEMOVEPOINT)
1453      * is expected to fail with ERROR_INVALID_PARAMETER
1454      */
1455     SetLastError(MYERROR);
1456     retval = pGetMouseMovePointsEx(0, &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1457     if (retval == ERROR_INVALID_PARAMETER)
1458     {
1459         win_skip( "GetMouseMovePointsEx broken on WinME\n" );
1460         return;
1461     }
1462     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1463     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1464        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1465 
1466     SetLastError(MYERROR);
1467     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)-1, &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1468     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1469     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1470        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1471 
1472     SetLastError(MYERROR);
1473     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)+1, &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1474     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1475     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1476        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1477 
1478     /* test second and third parameter
1479      */
1480     SetLastError(MYERROR);
1481     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), NULL, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1482     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1483     ok(GetLastError() == ERROR_NOACCESS || GetLastError() == MYERROR,
1484        "expected error ERROR_NOACCESS, got %u\n", GetLastError());
1485 
1486     SetLastError(MYERROR);
1487     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, NULL, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1488     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1489     ok(ERROR_NOACCESS == GetLastError(),
1490        "expected error ERROR_NOACCESS, got %u\n", GetLastError());
1491 
1492     SetLastError(MYERROR);
1493     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), NULL, NULL, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1494     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1495     ok(ERROR_NOACCESS == GetLastError(),
1496        "expected error ERROR_NOACCESS, got %u\n", GetLastError());
1497 
1498     SetLastError(MYERROR);
1499     count = 0;
1500     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, NULL, count, GMMP_USE_DISPLAY_POINTS);
1501     if (retval == -1)
1502         ok(GetLastError() == ERROR_POINT_NOT_FOUND, "unexpected error %u\n", GetLastError());
1503     else
1504         ok(retval == count, "expected GetMouseMovePointsEx to succeed, got %d\n", retval);
1505 
1506     /* test fourth parameter
1507      * a value higher than 64 is expected to fail with ERROR_INVALID_PARAMETER
1508      */
1509     SetLastError(MYERROR);
1510     count = -1;
1511     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, out, count, GMMP_USE_DISPLAY_POINTS);
1512     ok(retval == count, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1513     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1514        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1515 
1516     SetLastError(MYERROR);
1517     count = 0;
1518     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, out, count, GMMP_USE_DISPLAY_POINTS);
1519     if (retval == -1)
1520         ok(GetLastError() == ERROR_POINT_NOT_FOUND, "unexpected error %u\n", GetLastError());
1521     else
1522         ok(retval == count, "expected GetMouseMovePointsEx to succeed, got %d\n", retval);
1523 
1524     SetLastError(MYERROR);
1525     count = BUFLIM;
1526     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, out, count, GMMP_USE_DISPLAY_POINTS);
1527     if (retval == -1)
1528         ok(GetLastError() == ERROR_POINT_NOT_FOUND, "unexpected error %u\n", GetLastError());
1529     else
1530         ok((0 <= retval) && (retval <= count), "expected GetMouseMovePointsEx to succeed, got %d\n", retval);
1531 
1532     SetLastError(MYERROR);
1533     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, out, BUFLIM+1, GMMP_USE_DISPLAY_POINTS);
1534     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1535     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1536        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1537 
1538     /* it was not possible to force an error with the fifth parameter on win2k */
1539 
1540     /* test combinations of wrong parameters to see which error wins */
1541     SetLastError(MYERROR);
1542     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)-1, NULL, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1543     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1544     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1545        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1546 
1547     SetLastError(MYERROR);
1548     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)-1, &in, NULL, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1549     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1550     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1551        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1552 
1553     SetLastError(MYERROR);
1554     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), NULL, out, BUFLIM+1, GMMP_USE_DISPLAY_POINTS);
1555     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1556     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1557        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1558 
1559     SetLastError(MYERROR);
1560     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, NULL, BUFLIM+1, GMMP_USE_DISPLAY_POINTS);
1561     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1562     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1563        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1564 
1565 #undef BUFLIM
1566 #undef MYERROR
1567 }
1568 
1569 static void test_GetRawInputDeviceList(void)
1570 {
1571     RAWINPUTDEVICELIST devices[32];
1572     UINT ret, oret, devcount, odevcount;
1573     DWORD err;
1574 
1575     SetLastError(0xdeadbeef);
1576     ret = pGetRawInputDeviceList(NULL, NULL, 0);
1577     err = GetLastError();
1578     ok(ret == -1, "expected -1, got %d\n", ret);
1579     ok(err == ERROR_INVALID_PARAMETER, "expected 87, got %d\n", err);
1580 
1581     SetLastError(0xdeadbeef);
1582     ret = pGetRawInputDeviceList(NULL, NULL, sizeof(devices[0]));
1583     err = GetLastError();
1584     ok(ret == -1, "expected -1, got %d\n", ret);
1585     ok(err == ERROR_NOACCESS, "expected 998, got %d\n", err);
1586 
1587     devcount = 0;
1588     ret = pGetRawInputDeviceList(NULL, &devcount, sizeof(devices[0]));
1589     ok(ret == 0, "expected 0, got %d\n", ret);
1590     ok(devcount > 0, "expected non-zero\n");
1591 
1592     SetLastError(0xdeadbeef);
1593     devcount = 0;
1594     ret = pGetRawInputDeviceList(devices, &devcount, sizeof(devices[0]));
1595     err = GetLastError();
1596     ok(ret == -1, "expected -1, got %d\n", ret);
1597     ok(err == ERROR_INSUFFICIENT_BUFFER, "expected 122, got %d\n", err);
1598     ok(devcount > 0, "expected non-zero\n");
1599 
1600     /* devcount contains now the correct number of devices */
1601     ret = pGetRawInputDeviceList(devices, &devcount, sizeof(devices[0]));
1602     ok(ret > 0, "expected non-zero\n");
1603 
1604     /* check if variable changes from larger to smaller value */
1605     devcount = odevcount = sizeof(devices) / sizeof(devices[0]);
1606     oret = ret = pGetRawInputDeviceList(devices, &odevcount, sizeof(devices[0]));
1607     ok(ret > 0, "expected non-zero\n");
1608     ok(devcount == odevcount, "expected %d, got %d\n", devcount, odevcount);
1609     devcount = odevcount;
1610     odevcount = sizeof(devices) / sizeof(devices[0]);
1611     ret = pGetRawInputDeviceList(NULL, &odevcount, sizeof(devices[0]));
1612     ok(ret == 0, "expected 0, got %d\n", ret);
1613     ok(odevcount == oret, "expected %d, got %d\n", oret, odevcount);
1614 }
1615 
1616 static void test_key_map(void)
1617 {
1618     HKL kl = GetKeyboardLayout(0);
1619     UINT kL, kR, s, sL;
1620     int i;
1621     static const UINT numpad_collisions[][2] = {
1622         { VK_NUMPAD0, VK_INSERT },
1623         { VK_NUMPAD1, VK_END },
1624         { VK_NUMPAD2, VK_DOWN },
1625         { VK_NUMPAD3, VK_NEXT },
1626         { VK_NUMPAD4, VK_LEFT },
1627         { VK_NUMPAD6, VK_RIGHT },
1628         { VK_NUMPAD7, VK_HOME },
1629         { VK_NUMPAD8, VK_UP },
1630         { VK_NUMPAD9, VK_PRIOR },
1631     };
1632 
1633     s  = MapVirtualKeyExA(VK_SHIFT,  MAPVK_VK_TO_VSC, kl);
1634     ok(s != 0, "MapVirtualKeyEx(VK_SHIFT) should return non-zero\n");
1635     sL = MapVirtualKeyExA(VK_LSHIFT, MAPVK_VK_TO_VSC, kl);
1636     ok(s == sL || broken(sL == 0), /* win9x */
1637        "%x != %x\n", s, sL);
1638 
1639     kL = MapVirtualKeyExA(0x2a, MAPVK_VSC_TO_VK, kl);
1640     ok(kL == VK_SHIFT, "Scan code -> vKey = %x (not VK_SHIFT)\n", kL);
1641     kR = MapVirtualKeyExA(0x36, MAPVK_VSC_TO_VK, kl);
1642     ok(kR == VK_SHIFT, "Scan code -> vKey = %x (not VK_SHIFT)\n", kR);
1643 
1644     kL = MapVirtualKeyExA(0x2a, MAPVK_VSC_TO_VK_EX, kl);
1645     ok(kL == VK_LSHIFT || broken(kL == 0), /* win9x */
1646        "Scan code -> vKey = %x (not VK_LSHIFT)\n", kL);
1647     kR = MapVirtualKeyExA(0x36, MAPVK_VSC_TO_VK_EX, kl);
1648     ok(kR == VK_RSHIFT || broken(kR == 0), /* win9x */
1649        "Scan code -> vKey = %x (not VK_RSHIFT)\n", kR);
1650 
1651     /* test that MAPVK_VSC_TO_VK prefers the non-numpad vkey if there's ambiguity */
1652     for (i = 0; i < sizeof(numpad_collisions)/sizeof(numpad_collisions[0]); i++)
1653     {
1654         UINT numpad_scan = MapVirtualKeyExA(numpad_collisions[i][0],  MAPVK_VK_TO_VSC, kl);
1655         UINT other_scan  = MapVirtualKeyExA(numpad_collisions[i][1],  MAPVK_VK_TO_VSC, kl);
1656 
1657         /* do they really collide for this layout? */
1658         if (numpad_scan && other_scan == numpad_scan)
1659         {
1660             UINT vkey = MapVirtualKeyExA(numpad_scan, MAPVK_VSC_TO_VK, kl);
1661             ok(vkey != numpad_collisions[i][0],
1662                "Got numpad vKey %x for scan code %x when there was another choice\n",
1663                vkey, numpad_scan);
1664         }
1665     }
1666 }
1667 
1668 #define shift 1
1669 #define ctrl  2
1670 
1671 static const struct tounicode_tests
1672 {
1673     UINT vk;
1674     DWORD modifiers;
1675     WCHAR chr; /* if vk is 0, lookup vk using this char */
1676     int expect_ret;
1677     WCHAR expect_buf[4];
1678 } utests[] =
1679 {
1680     { 'A', 0, 0, 1, {'a',0}},
1681     { 'A', ctrl, 0, 1, {1, 0}},
1682     { 'A', shift|ctrl, 0, 1, {1, 0}},
1683     { VK_TAB, ctrl, 0, 0, {0}},
1684     { VK_TAB, shift|ctrl, 0, 0, {0}},
1685     { VK_RETURN, ctrl, 0, 1, {'\n', 0}},
1686     { VK_RETURN, shift|ctrl, 0, 0, {0}},
1687     { '4', ctrl, 0, 0, {0}},
1688     { '4', shift|ctrl, 0, 0, {0}},
1689     { 0, ctrl, '!', 0, {0}},
1690     { 0, ctrl, '\"', 0, {0}},
1691     { 0, ctrl, '#', 0, {0}},
1692     { 0, ctrl, '$', 0, {0}},
1693     { 0, ctrl, '%', 0, {0}},
1694     { 0, ctrl, '\'', 0, {0}},
1695     { 0, ctrl, '(', 0, {0}},
1696     { 0, ctrl, ')', 0, {0}},
1697     { 0, ctrl, '*', 0, {0}},
1698     { 0, ctrl, '+', 0, {0}},
1699     { 0, ctrl, ',', 0, {0}},
1700     { 0, ctrl, '-', 0, {0}},
1701     { 0, ctrl, '.', 0, {0}},
1702     { 0, ctrl, '/', 0, {0}},
1703     { 0, ctrl, ':', 0, {0}},
1704     { 0, ctrl, ';', 0, {0}},
1705     { 0, ctrl, '<', 0, {0}},
1706     { 0, ctrl, '=', 0, {0}},
1707     { 0, ctrl, '>', 0, {0}},
1708     { 0, ctrl, '?', 0, {0}},
1709     { 0, ctrl, '@', 1, {0}},
1710     { 0, ctrl, '[', 1, {0x1b}},
1711     { 0, ctrl, '\\', 1, {0x1c}},
1712     { 0, ctrl, ']', 1, {0x1d}},
1713     { 0, ctrl, '^', 1, {0x1e}},
1714     { 0, ctrl, '_', 1, {0x1f}},
1715     { 0, ctrl, '`', 0, {0}},
1716     { VK_SPACE, 0, 0, 1, {' ',0}},
1717     { VK_SPACE, shift, 0, 1, {' ',0}},
1718     { VK_SPACE, ctrl, 0, 1, {' ',0}},
1719 };
1720 
1721 static void test_ToUnicode(void)
1722 {
1723     WCHAR wStr[4];
1724     BYTE state[256];
1725     const BYTE SC_RETURN = 0x1c, SC_TAB = 0x0f, SC_A = 0x1e;
1726     const BYTE HIGHEST_BIT = 0x80;
1727     int i, ret;
1728     BOOL us_kbd = (GetKeyboardLayout(0) == (HKL)(ULONG_PTR)0x04090409);
1729 
1730     for(i=0; i<256; i++)
1731         state[i]=0;
1732 
1733     wStr[1] = 0xAA;
1734     SetLastError(0xdeadbeef);
1735     ret = ToUnicode(VK_RETURN, SC_RETURN, state, wStr, 4, 0);
1736     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1737     {
1738         win_skip("ToUnicode is not implemented\n");
1739         return;
1740     }
1741 
1742     ok(ret == 1, "ToUnicode for Return key didn't return 1 (was %i)\n", ret);
1743     if(ret == 1)
1744     {
1745         ok(wStr[0]=='\r', "ToUnicode for CTRL + Return was %i (expected 13)\n", wStr[0]);
1746         ok(wStr[1]==0 || broken(wStr[1]!=0) /* nt4 */,
1747            "ToUnicode didn't null-terminate the buffer when there was room.\n");
1748     }
1749 
1750     for (i = 0; i < sizeof(utests) / sizeof(utests[0]); i++)
1751     {
1752         UINT vk = utests[i].vk, mod = utests[i].modifiers, scan;
1753 
1754         if(!vk)
1755         {
1756             short vk_ret;
1757 
1758             if (!us_kbd) continue;
1759             vk_ret = VkKeyScanW(utests[i].chr);
1760             if (vk_ret == -1) continue;
1761             vk = vk_ret & 0xff;
1762             if (vk_ret & 0x100) mod |= shift;
1763             if (vk_ret & 0x200) mod |= ctrl;
1764         }
1765         scan = MapVirtualKeyW(vk, MAPVK_VK_TO_VSC);
1766 
1767         state[VK_SHIFT]   = state[VK_LSHIFT]   = (mod & shift) ? HIGHEST_BIT : 0;
1768         state[VK_CONTROL] = state[VK_LCONTROL] = (mod & ctrl) ? HIGHEST_BIT : 0;
1769 
1770         ret = ToUnicode(vk, scan, state, wStr, 4, 0);
1771         ok(ret == utests[i].expect_ret, "%d: got %d expected %d\n", i, ret, utests[i].expect_ret);
1772         if (ret)
1773             ok(!lstrcmpW(wStr, utests[i].expect_buf), "%d: got %s expected %s\n", i, wine_dbgstr_w(wStr),
1774                 wine_dbgstr_w(utests[i].expect_buf));
1775 
1776     }
1777     state[VK_SHIFT]   = state[VK_LSHIFT]   = 0;
1778     state[VK_CONTROL] = state[VK_LCONTROL] = 0;
1779 
1780     ret = ToUnicode(VK_TAB, SC_TAB, NULL, wStr, 4, 0);
1781     ok(ret == 0, "ToUnicode with NULL keystate didn't return 0 (was %i)\n", ret);
1782     ret = ToUnicode(VK_RETURN, SC_RETURN, NULL, wStr, 4, 0);
1783     ok(ret == 0, "ToUnicode with NULL keystate didn't return 0 (was %i)\n", ret);
1784     ret = ToUnicode('A', SC_A, NULL, wStr, 4, 0);
1785     ok(ret == 0, "ToUnicode with NULL keystate didn't return 0 (was %i)\n", ret);
1786     ret = ToUnicodeEx(VK_TAB, SC_TAB, NULL, wStr, 4, 0, GetKeyboardLayout(0));
1787     ok(ret == 0, "ToUnicodeEx with NULL keystate didn't return 0 (was %i)\n", ret);
1788     ret = ToUnicodeEx(VK_RETURN, SC_RETURN, NULL, wStr, 4, 0, GetKeyboardLayout(0));
1789     ok(ret == 0, "ToUnicodeEx with NULL keystate didn't return 0 (was %i)\n", ret);
1790     ret = ToUnicodeEx('A', SC_A, NULL, wStr, 4, 0, GetKeyboardLayout(0));
1791     ok(ret == 0, "ToUnicodeEx with NULL keystate didn't return 0 (was %i)\n", ret);
1792 }
1793 
1794 static void test_ToAscii(void)
1795 {
1796     WORD character;
1797     BYTE state[256];
1798     const BYTE SC_RETURN = 0x1c, SC_A = 0x1e;
1799     const BYTE HIGHEST_BIT = 0x80;
1800     int ret;
1801 
1802     memset(state, 0, sizeof(state));
1803 
1804     character = 0;
1805     ret = ToAscii(VK_RETURN, SC_RETURN, state, &character, 0);
1806     ok(ret == 1, "ToAscii for Return key didn't return 1 (was %i)\n", ret);
1807     ok(character == '\r', "ToAscii for Return was %i (expected 13)\n", character);
1808 
1809     character = 0;
1810     ret = ToAscii('A', SC_A, state, &character, 0);
1811     ok(ret == 1, "ToAscii for character 'A' didn't return 1 (was %i)\n", ret);
1812     ok(character == 'a', "ToAscii for character 'A' was %i (expected %i)\n", character, 'a');
1813 
1814     state[VK_CONTROL] |= HIGHEST_BIT;
1815     state[VK_LCONTROL] |= HIGHEST_BIT;
1816     character = 0;
1817     ret = ToAscii(VK_RETURN, SC_RETURN, state, &character, 0);
1818     ok(ret == 1, "ToAscii for CTRL + Return key didn't return 1 (was %i)\n", ret);
1819     ok(character == '\n', "ToAscii for CTRL + Return was %i (expected 10)\n", character);
1820 
1821     character = 0;
1822     ret = ToAscii('A', SC_A, state, &character, 0);
1823     ok(ret == 1, "ToAscii for CTRL + character 'A' didn't return 1 (was %i)\n", ret);
1824     ok(character == 1, "ToAscii for CTRL + character 'A' was %i (expected 1)\n", character);
1825 
1826     state[VK_SHIFT] |= HIGHEST_BIT;
1827     state[VK_LSHIFT] |= HIGHEST_BIT;
1828     ret = ToAscii(VK_RETURN, SC_RETURN, state, &character, 0);
1829     ok(ret == 0, "ToAscii for CTRL + Shift + Return key didn't return 0 (was %i)\n", ret);
1830 
1831     ret = ToAscii(VK_RETURN, SC_RETURN, NULL, &character, 0);
1832     ok(ret == 0, "ToAscii for NULL keystate didn't return 0 (was %i)\n", ret);
1833     ret = ToAscii('A', SC_A, NULL, &character, 0);
1834     ok(ret == 0, "ToAscii for NULL keystate didn't return 0 (was %i)\n", ret);
1835     ret = ToAsciiEx(VK_RETURN, SC_RETURN, NULL, &character, 0, GetKeyboardLayout(0));
1836     ok(ret == 0, "ToAsciiEx for NULL keystate didn't return 0 (was %i)\n", ret);
1837     ret = ToAsciiEx('A', SC_A, NULL, &character, 0, GetKeyboardLayout(0));
1838     ok(ret == 0, "ToAsciiEx for NULL keystate didn't return 0 (was %i)\n", ret);
1839 }
1840 
1841 static void test_get_async_key_state(void)
1842 {
1843     /* input value sanity checks */
1844     ok(0 == GetAsyncKeyState(1000000), "GetAsyncKeyState did not return 0\n");
1845     ok(0 == GetAsyncKeyState(-1000000), "GetAsyncKeyState did not return 0\n");
1846 }
1847 
1848 static void test_keyboard_layout_name(void)
1849 {
1850     BOOL ret;
1851     char klid[KL_NAMELENGTH];
1852 
1853     if (0) /* crashes on native system */
1854         ret = GetKeyboardLayoutNameA(NULL);
1855 
1856     SetLastError(0xdeadbeef);
1857     ret = GetKeyboardLayoutNameW(NULL);
1858     ok(!ret, "got %d\n", ret);
1859     ok(GetLastError() == ERROR_NOACCESS, "got %d\n", GetLastError());
1860 
1861     if (GetKeyboardLayout(0) != (HKL)(ULONG_PTR)0x04090409) return;
1862 
1863     klid[0] = 0;
1864     ret = GetKeyboardLayoutNameA(klid);
1865     ok(ret, "GetKeyboardLayoutNameA failed %u\n", GetLastError());
1866     ok(!strcmp(klid, "00000409"), "expected 00000409, got %s\n", klid);
1867 }
1868 
1869 static void test_key_names(void)
1870 {
1871     char buffer[40];
1872     WCHAR bufferW[40];
1873     int ret, prev;
1874     LONG lparam = 0x1d << 16;
1875 
1876     memset( buffer, 0xcc, sizeof(buffer) );
1877     ret = GetKeyNameTextA( lparam, buffer, sizeof(buffer) );
1878     ok( ret > 0, "wrong len %u for '%s'\n", ret, buffer );
1879     ok( ret == strlen(buffer), "wrong len %u for '%s'\n", ret, buffer );
1880 
1881     memset( buffer, 0xcc, sizeof(buffer) );
1882     prev = ret;
1883     ret = GetKeyNameTextA( lparam, buffer, prev );
1884     ok( ret == prev - 1, "wrong len %u for '%s'\n", ret, buffer );
1885     ok( ret == strlen(buffer), "wrong len %u for '%s'\n", ret, buffer );
1886 
1887     memset( buffer, 0xcc, sizeof(buffer) );
1888     ret = GetKeyNameTextA( lparam, buffer, 0 );
1889     ok( ret == 0, "wrong len %u for '%s'\n", ret, buffer );
1890     ok( buffer[0] == 0, "wrong string '%s'\n", buffer );
1891 
1892     memset( bufferW, 0xcc, sizeof(bufferW) );
1893     ret = GetKeyNameTextW( lparam, bufferW, sizeof(bufferW)/sizeof(WCHAR) );
1894     ok( ret > 0, "wrong len %u for %s\n", ret, wine_dbgstr_w(bufferW) );
1895     ok( ret == lstrlenW(bufferW), "wrong len %u for %s\n", ret, wine_dbgstr_w(bufferW) );
1896 
1897     memset( bufferW, 0xcc, sizeof(bufferW) );
1898     prev = ret;
1899     ret = GetKeyNameTextW( lparam, bufferW, prev );
1900     ok( ret == prev - 1, "wrong len %u for %s\n", ret, wine_dbgstr_w(bufferW) );
1901     ok( ret == lstrlenW(bufferW), "wrong len %u for %s\n", ret, wine_dbgstr_w(bufferW) );
1902 
1903     memset( bufferW, 0xcc, sizeof(bufferW) );
1904     ret = GetKeyNameTextW( lparam, bufferW, 0 );
1905     ok( ret == 0, "wrong len %u for %s\n", ret, wine_dbgstr_w(bufferW) );
1906     ok( bufferW[0] == 0xcccc, "wrong string %s\n", wine_dbgstr_w(bufferW) );
1907 }
1908 
1909 static void simulate_click(BOOL left, int x, int y)
1910 {
1911     INPUT input[2];
1912     UINT events_no;
1913 
1914     SetCursorPos(x, y);
1915     memset(input, 0, sizeof(input));
1916     input[0].type = INPUT_MOUSE;
1917     U(input[0]).mi.dx = x;
1918     U(input[0]).mi.dy = y;
1919     U(input[0]).mi.dwFlags = left ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN;
1920     input[1].type = INPUT_MOUSE;
1921     U(input[1]).mi.dx = x;
1922     U(input[1]).mi.dy = y;
1923     U(input[1]).mi.dwFlags = left ? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP;
1924     events_no = SendInput(2, input, sizeof(input[0]));
1925     ok(events_no == 2, "SendInput returned %d\n", events_no);
1926 }
1927 
1928 static BOOL wait_for_message( MSG *msg )
1929 {
1930     BOOL ret;
1931 
1932     for (;;)
1933     {
1934         ret = PeekMessageA(msg, 0, 0, 0, PM_REMOVE);
1935         if (ret)
1936         {
1937             if (msg->message == WM_PAINT) DispatchMessageA(msg);
1938             else break;
1939         }
1940         else if (MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT) == WAIT_TIMEOUT) break;
1941     }
1942     if (!ret) msg->message = 0;
1943     return ret;
1944 }
1945 
1946 static BOOL wait_for_event(HANDLE event, int timeout)
1947 {
1948     DWORD end_time = GetTickCount() + timeout;
1949     MSG msg;
1950 
1951     do {
1952         if(MsgWaitForMultipleObjects(1, &event, FALSE, timeout, QS_ALLINPUT) == WAIT_OBJECT_0)
1953             return TRUE;
1954         while(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
1955             DispatchMessageA(&msg);
1956         timeout = end_time - GetTickCount();
1957     }while(timeout > 0);
1958 
1959     return FALSE;
1960 }
1961 
1962 static WNDPROC def_static_proc;
1963 static DWORD hittest_no;
1964 static LRESULT WINAPI static_hook_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
1965 {
1966     if (msg == WM_NCHITTEST)
1967     {
1968         /* break infinite hittest loop */
1969         if(hittest_no > 50) return HTCLIENT;
1970         hittest_no++;
1971     }
1972 
1973     return def_static_proc(hwnd, msg, wp, lp);
1974 }
1975 
1976 struct thread_data
1977 {
1978     HANDLE start_event;
1979     HANDLE end_event;
1980     HWND win;
1981 };
1982 
1983 static DWORD WINAPI create_static_win(void *arg)
1984 {
1985     struct thread_data *thread_data = arg;
1986     HWND win;
1987 
1988     win = CreateWindowA("static", "static", WS_VISIBLE | WS_POPUP,
1989             100, 100, 100, 100, 0, NULL, NULL, NULL);
1990     ok(win != 0, "CreateWindow failed\n");
1991     def_static_proc = (void*)SetWindowLongPtrA(win,
1992             GWLP_WNDPROC, (LONG_PTR)static_hook_proc);
1993     thread_data->win = win;
1994 
1995     SetEvent(thread_data->start_event);
1996     wait_for_event(thread_data->end_event, 5000);
1997     return 0;
1998 }
1999 
2000 static void get_dc_region(RECT *region, HWND hwnd, DWORD flags)
2001 {
2002     int region_type;
2003     HRGN hregion;
2004     HDC hdc;
2005 
2006     hdc = GetDCEx(hwnd, 0, flags);
2007     ok(hdc != NULL, "GetDCEx failed\n");
2008     hregion = CreateRectRgn(40, 40, 60, 60);
2009     ok(hregion != NULL, "CreateRectRgn failed\n");
2010     GetRandomRgn(hdc, hregion, SYSRGN);
2011     region_type = GetRgnBox(hregion, region);
2012     ok(region_type == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", region_type);
2013     DeleteObject(hregion);
2014     ReleaseDC(hwnd, hdc);
2015 }
2016 
2017 static void test_Input_mouse(void)
2018 {
2019     BOOL got_button_down, got_button_up;
2020     HWND hwnd, button_win, static_win;
2021     struct thread_data thread_data;
2022     HANDLE thread;
2023     DWORD thread_id;
2024     WNDCLASSA wclass;
2025     POINT pt, pt_org;
2026     int region_type;
2027     HRGN hregion;
2028     RECT region;
2029     MSG msg;
2030     BOOL ret;
2031 
2032     SetLastError(0xdeadbeef);
2033     ret = GetCursorPos(NULL);
2034     ok(!ret, "GetCursorPos succeed\n");
2035     ok(GetLastError() == 0xdeadbeef || GetLastError() == ERROR_NOACCESS, "error %u\n", GetLastError());
2036 
2037     SetLastError(0xdeadbeef);
2038     ret = GetCursorPos(&pt_org);
2039     ok(ret, "GetCursorPos failed\n");
2040     ok(GetLastError() == 0xdeadbeef, "error %u\n", GetLastError());
2041 
2042     button_win = CreateWindowA("button", "button", WS_VISIBLE | WS_POPUP,
2043             100, 100, 100, 100, 0, NULL, NULL, NULL);
2044     ok(button_win != 0, "CreateWindow failed\n");
2045 
2046     pt.x = pt.y = 150;
2047     hwnd = WindowFromPoint(pt);
2048     if (hwnd != button_win)
2049     {
2050         skip("there's another window covering test window\n");
2051         DestroyWindow(button_win);
2052         return;
2053     }
2054 
2055     /* simple button click test */
2056     simulate_click(TRUE, 150, 150);
2057     got_button_down = got_button_up = FALSE;
2058     while (wait_for_message(&msg))
2059     {
2060         DispatchMessageA(&msg);
2061 
2062         if (msg.message == WM_LBUTTONDOWN)
2063         {
2064             got_button_down = TRUE;
2065         }
2066         else if (msg.message == WM_LBUTTONUP)
2067         {
2068             got_button_up = TRUE;
2069             break;
2070         }
2071     }
2072     ok(got_button_down, "expected WM_LBUTTONDOWN message\n");
2073     ok(got_button_up, "expected WM_LBUTTONUP message\n");
2074 
2075     /* click through HTTRANSPARENT child window */
2076     static_win = CreateWindowA("static", "static", WS_VISIBLE | WS_CHILD,
2077             0, 0, 100, 100, button_win, NULL, NULL, NULL);
2078     ok(static_win != 0, "CreateWindow failed\n");
2079     def_static_proc = (void*)SetWindowLongPtrA(static_win,
2080             GWLP_WNDPROC, (LONG_PTR)static_hook_proc);
2081     simulate_click(FALSE, 150, 150);
2082     hittest_no = 0;
2083     got_button_down = got_button_up = FALSE;
2084     while (wait_for_message(&msg))
2085     {
2086         DispatchMessageA(&msg);
2087 
2088         if (msg.message == WM_RBUTTONDOWN)
2089         {
2090             ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
2091             got_button_down = TRUE;
2092         }
2093         else if (msg.message == WM_RBUTTONUP)
2094         {
2095             ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
2096             got_button_up = TRUE;
2097             break;
2098         }
2099     }
2100     ok(hittest_no && hittest_no<50, "expected WM_NCHITTEST message\n");
2101     ok(got_button_down, "expected WM_RBUTTONDOWN message\n");
2102     ok(got_button_up, "expected WM_RBUTTONUP message\n");
2103     DestroyWindow(static_win);
2104 
2105     /* click through HTTRANSPARENT top-level window */
2106     static_win = CreateWindowA("static", "static", WS_VISIBLE | WS_POPUP,
2107             100, 100, 100, 100, 0, NULL, NULL, NULL);
2108     ok(static_win != 0, "CreateWindow failed\n");
2109     def_static_proc = (void*)SetWindowLongPtrA(static_win,
2110             GWLP_WNDPROC, (LONG_PTR)static_hook_proc);
2111     simulate_click(TRUE, 150, 150);
2112     hittest_no = 0;
2113     got_button_down = got_button_up = FALSE;
2114     while (wait_for_message(&msg))
2115     {
2116         DispatchMessageA(&msg);
2117 
2118         if (msg.message == WM_LBUTTONDOWN)
2119         {
2120             ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
2121             got_button_down = TRUE;
2122         }
2123         else if (msg.message == WM_LBUTTONUP)
2124         {
2125             ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
2126             got_button_up = TRUE;
2127             break;
2128         }
2129     }
2130     ok(hittest_no && hittest_no<50, "expected WM_NCHITTEST message\n");
2131     ok(got_button_down, "expected WM_LBUTTONDOWN message\n");
2132     ok(got_button_up, "expected WM_LBUTTONUP message\n");
2133     DestroyWindow(static_win);
2134 
2135     /* click on HTTRANSPARENT top-level window that belongs to other thread */
2136     thread_data.start_event = CreateEventA(NULL, FALSE, FALSE, NULL);
2137     ok(thread_data.start_event != NULL, "CreateEvent failed\n");
2138     thread_data.end_event = CreateEventA(NULL, FALSE, FALSE, NULL);
2139     ok(thread_data.end_event != NULL, "CreateEvent failed\n");
2140     thread = CreateThread(NULL, 0, create_static_win, &thread_data, 0, NULL);
2141     ok(thread != NULL, "CreateThread failed\n");
2142     hittest_no = 0;
2143     got_button_down = got_button_up = FALSE;
2144     WaitForSingleObject(thread_data.start_event, INFINITE);
2145     simulate_click(FALSE, 150, 150);
2146     while (wait_for_message(&msg))
2147     {
2148         DispatchMessageA(&msg);
2149 
2150         if (msg.message == WM_RBUTTONDOWN)
2151             got_button_down = TRUE;
2152         else if (msg.message == WM_RBUTTONUP)
2153             got_button_up = TRUE;
2154     }
2155     SetEvent(thread_data.end_event);
2156     WaitForSingleObject(thread, INFINITE);
2157     CloseHandle(thread);
2158     ok(hittest_no && hittest_no<50, "expected WM_NCHITTEST message\n");
2159     ok(!got_button_down, "unexpected WM_RBUTTONDOWN message\n");
2160     ok(!got_button_up, "unexpected WM_RBUTTONUP message\n");
2161 
2162     /* click on HTTRANSPARENT top-level window that belongs to other thread,
2163      * thread input queues are attached */
2164     thread = CreateThread(NULL, 0, create_static_win, &thread_data, 0, &thread_id);
2165     ok(thread != NULL, "CreateThread failed\n");
2166     hittest_no = 0;
2167     got_button_down = got_button_up = FALSE;
2168     WaitForSingleObject(thread_data.start_event, INFINITE);
2169     ok(AttachThreadInput(thread_id, GetCurrentThreadId(), TRUE),
2170             "AttachThreadInput failed\n");
2171     while (wait_for_message(&msg)) DispatchMessageA(&msg);
2172     SetWindowPos(thread_data.win, button_win, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
2173     simulate_click(TRUE, 150, 150);
2174     while (wait_for_message(&msg))
2175     {
2176         DispatchMessageA(&msg);
2177 
2178         if (msg.message == WM_LBUTTONDOWN)
2179             got_button_down = TRUE;
2180         else if (msg.message == WM_LBUTTONUP)
2181             got_button_up = TRUE;
2182     }
2183     SetEvent(thread_data.end_event);
2184     WaitForSingleObject(thread, INFINITE);
2185     todo_wine ok(hittest_no > 50, "expected loop with WM_NCHITTEST messages\n");
2186     ok(!got_button_down, "unexpected WM_LBUTTONDOWN message\n");
2187     ok(!got_button_up, "unexpected WM_LBUTTONUP message\n");
2188 
2189     /* click after SetCapture call */
2190     hwnd = CreateWindowA("button", "button", WS_VISIBLE | WS_POPUP,
2191             0, 0, 100, 100, 0, NULL, NULL, NULL);
2192     ok(hwnd != 0, "CreateWindow failed\n");
2193     SetCapture(button_win);
2194     got_button_down = got_button_up = FALSE;
2195     simulate_click(FALSE, 50, 50);
2196     while (wait_for_message(&msg))
2197     {
2198         DispatchMessageA(&msg);
2199 
2200         if (msg.message == WM_RBUTTONDOWN)
2201         {
2202             ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
2203             got_button_down = TRUE;
2204         }
2205         else if (msg.message == WM_RBUTTONUP)
2206         {
2207             ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
2208             got_button_up = TRUE;
2209             break;
2210         }
2211     }
2212     ok(got_button_down, "expected WM_RBUTTONDOWN message\n");
2213     ok(got_button_up, "expected WM_RBUTTONUP message\n");
2214     DestroyWindow(hwnd);
2215 
2216     /* click on child window after SetCapture call */
2217     hwnd = CreateWindowA("button", "button2", WS_VISIBLE | WS_CHILD,
2218             0, 0, 100, 100, button_win, NULL, NULL, NULL);
2219     ok(hwnd != 0, "CreateWindow failed\n");
2220     got_button_down = got_button_up = FALSE;
2221     simulate_click(TRUE, 150, 150);
2222     while (wait_for_message(&msg))
2223     {
2224         DispatchMessageA(&msg);
2225 
2226         if (msg.message == WM_LBUTTONDOWN)
2227         {
2228             ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
2229             got_button_down = TRUE;
2230         }
2231         else if (msg.message == WM_LBUTTONUP)
2232         {
2233             ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
2234             got_button_up = TRUE;
2235             break;
2236         }
2237     }
2238     ok(got_button_down, "expected WM_LBUTTONDOWN message\n");
2239     ok(got_button_up, "expected WM_LBUTTONUP message\n");
2240     DestroyWindow(hwnd);
2241     ok(ReleaseCapture(), "ReleaseCapture failed\n");
2242 
2243     wclass.style         = 0;
2244     wclass.lpfnWndProc   = WndProc;
2245     wclass.cbClsExtra    = 0;
2246     wclass.cbWndExtra    = 0;
2247     wclass.hInstance     = GetModuleHandleA(NULL);
2248     wclass.hIcon         = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
2249     wclass.hCursor       = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
2250     wclass.hbrBackground = CreateSolidBrush(RGB(128, 128, 128));
2251     wclass.lpszMenuName  = NULL;
2252     wclass.lpszClassName = "InputLayeredTestClass";
2253     RegisterClassA( &wclass );
2254 
2255     /* click through layered window with alpha channel / color key */
2256     hwnd = CreateWindowA(wclass.lpszClassName, "InputLayeredTest",
2257             WS_VISIBLE | WS_POPUP, 100, 100, 100, 100, button_win, NULL, NULL, NULL);
2258     ok(hwnd != NULL, "CreateWindowEx failed\n");
2259 
2260     static_win = CreateWindowA("static", "Title", WS_VISIBLE | WS_CHILD,
2261                           10, 10, 20, 20, hwnd, NULL, NULL, NULL);
2262     ok(static_win != NULL, "CreateWindowA failed %u\n", GetLastError());
2263 
2264     SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
2265     SetWindowLongA(hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
2266     ret = SetLayeredWindowAttributes(hwnd, 0, 255, LWA_ALPHA);
2267     ok(ret, "SetLayeredWindowAttributes failed\n");
2268     while (wait_for_message(&msg)) DispatchMessageA(&msg);
2269     Sleep(100);
2270 
2271     if (pGetWindowRgnBox)
2272     {
2273         region_type = pGetWindowRgnBox(hwnd, &region);
2274         ok(region_type == ERROR, "expected ERROR, got %d\n", region_type);
2275     }
2276 
2277     got_button_down = got_button_up = FALSE;
2278     simulate_click(TRUE, 150, 150);
2279     while (wait_for_message(&msg))
2280     {
2281         DispatchMessageA(&msg);
2282 
2283         if (msg.message == WM_LBUTTONDOWN)
2284         {
2285             ok(msg.hwnd == hwnd, "msg.hwnd = %p\n", msg.hwnd);
2286             got_button_down = TRUE;
2287         }
2288         else if (msg.message == WM_LBUTTONUP)
2289         {
2290             ok(msg.hwnd == hwnd, "msg.hwnd = %p\n", msg.hwnd);
2291             got_button_up = TRUE;
2292             break;
2293         }
2294     }
2295     ok(got_button_down, "expected WM_LBUTTONDOWN message\n");
2296     ok(got_button_up, "expected WM_LBUTTONUP message\n");
2297 
2298     ret = SetLayeredWindowAttributes(hwnd, 0, 0, LWA_ALPHA);
2299     ok(ret, "SetLayeredWindowAttributes failed\n");
2300     while (wait_for_message(&msg)) DispatchMessageA(&msg);
2301     Sleep(100);
2302 
2303     if (pGetWindowRgnBox)
2304     {
2305         region_type = pGetWindowRgnBox(hwnd, &region);
2306         ok(region_type == ERROR, "expected ERROR, got %d\n", region_type);
2307     }
2308 
2309     got_button_down = got_button_up = FALSE;
2310     simulate_click(TRUE, 150, 150);
2311     while (wait_for_message(&msg))
2312     {
2313         DispatchMessageA(&msg);
2314 
2315         if (msg.message == WM_LBUTTONDOWN)
2316         {
2317             todo_wine
2318             ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
2319             got_button_down = TRUE;
2320         }
2321         else if (msg.message == WM_LBUTTONUP)
2322         {
2323             todo_wine
2324             ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
2325             got_button_up = TRUE;
2326             break;
2327         }
2328     }
2329     ok(got_button_down || broken(!got_button_down), "expected WM_LBUTTONDOWN message\n");
2330     ok(got_button_up, "expected WM_LBUTTONUP message\n");
2331 
2332     ret = SetLayeredWindowAttributes(hwnd, RGB(0, 255, 0), 255, LWA_ALPHA | LWA_COLORKEY);
2333     ok(ret, "SetLayeredWindowAttributes failed\n");
2334     while (wait_for_message(&msg)) DispatchMessageA(&msg);
2335     Sleep(100);
2336 
2337     if (pGetWindowRgnBox)
2338     {
2339         region_type = pGetWindowRgnBox(hwnd, &region);
2340         ok(region_type == ERROR, "expected ERROR, got %d\n", region_type);
2341     }
2342 
2343     got_button_down = got_button_up = FALSE;
2344     simulate_click(TRUE, 150, 150);
2345     while (wait_for_message(&msg))
2346     {
2347         DispatchMessageA(&msg);
2348 
2349         if (msg.message == WM_LBUTTONDOWN)
2350         {
2351             ok(msg.hwnd == hwnd, "msg.hwnd = %p\n", msg.hwnd);
2352             got_button_down = TRUE;
2353         }
2354         else if (msg.message == WM_LBUTTONUP)
2355         {
2356             ok(msg.hwnd == hwnd, "msg.hwnd = %p\n", msg.hwnd);
2357             got_button_up = TRUE;
2358             break;
2359         }
2360     }
2361     ok(got_button_down, "expected WM_LBUTTONDOWN message\n");
2362     ok(got_button_up, "expected WM_LBUTTONUP message\n");
2363 
2364     ret = SetLayeredWindowAttributes(hwnd, RGB(128, 128, 128), 0, LWA_COLORKEY);
2365     ok(ret, "SetLayeredWindowAttributes failed\n");
2366     while (wait_for_message(&msg)) DispatchMessageA(&msg);
2367     Sleep(100);
2368 
2369     if (pGetWindowRgnBox)
2370     {
2371         region_type = pGetWindowRgnBox(hwnd, &region);
2372         ok(region_type == ERROR, "expected ERROR, got %d\n", region_type);
2373     }
2374 
2375     get_dc_region(&region, hwnd, DCX_PARENTCLIP);
2376     ok(region.left == 100 && region.top == 100 && region.right == 200 && region.bottom == 200,
2377        "expected region (100,100)-(200,200), got %s\n", wine_dbgstr_rect(&region));
2378     get_dc_region(&region, hwnd, DCX_WINDOW | DCX_USESTYLE);
2379     ok(region.left == 100 && region.top == 100 && region.right == 200 && region.bottom == 200,
2380        "expected region (100,100)-(200,200), got %s\n", wine_dbgstr_rect(&region));
2381     get_dc_region(&region, hwnd, DCX_USESTYLE);
2382     ok(region.left == 100 && region.top == 100 && region.right == 200 && region.bottom == 200,
2383        "expected region (100,100)-(200,200), got %s\n", wine_dbgstr_rect(&region));
2384     get_dc_region(&region, static_win, DCX_PARENTCLIP);
2385     ok(region.left == 100 && region.top == 100 && region.right == 200 && region.bottom == 200,
2386        "expected region (100,100)-(200,200), got %s\n", wine_dbgstr_rect(&region));
2387     get_dc_region(&region, static_win, DCX_WINDOW | DCX_USESTYLE);
2388     ok(region.left == 110 && region.top == 110 && region.right == 130 && region.bottom == 130,
2389        "expected region (110,110)-(130,130), got %s\n", wine_dbgstr_rect(&region));
2390     get_dc_region(&region, static_win, DCX_USESTYLE);
2391     ok(region.left == 100 && region.top == 100 && region.right == 200 && region.bottom == 200,
2392        "expected region (100,100)-(200,200), got %s\n", wine_dbgstr_rect(&region));
2393 
2394     got_button_down = got_button_up = FALSE;
2395     simulate_click(TRUE, 150, 150);
2396     while (wait_for_message(&msg))
2397     {
2398         DispatchMessageA(&msg);
2399 
2400         if (msg.message == WM_LBUTTONDOWN)
2401         {
2402             ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
2403             got_button_down = TRUE;
2404         }
2405         else if (msg.message == WM_LBUTTONUP)
2406         {
2407             ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
2408             got_button_up = TRUE;
2409             break;
2410         }
2411     }
2412     ok(got_button_down, "expected WM_LBUTTONDOWN message\n");
2413     ok(got_button_up, "expected WM_LBUTTONUP message\n");
2414 
2415     SetWindowLongA(hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED);
2416     while (wait_for_message(&msg)) DispatchMessageA(&msg);
2417     Sleep(100);
2418 
2419     if (pGetWindowRgnBox)
2420     {
2421         region_type = pGetWindowRgnBox(hwnd, &region);
2422         ok(region_type == ERROR, "expected ERROR, got %d\n", region_type);
2423     }
2424 
2425     got_button_down = got_button_up = FALSE;
2426     simulate_click(TRUE, 150, 150);
2427     while (wait_for_message(&msg))
2428     {
2429         DispatchMessageA(&msg);
2430 
2431         if (msg.message == WM_LBUTTONDOWN)
2432         {
2433             ok(msg.hwnd == hwnd, "msg.hwnd = %p\n", msg.hwnd);
2434             got_button_down = TRUE;
2435         }
2436         else if (msg.message == WM_LBUTTONUP)
2437         {
2438             ok(msg.hwnd == hwnd, "msg.hwnd = %p\n", msg.hwnd);
2439             got_button_up = TRUE;
2440             break;
2441         }
2442     }
2443     ok(got_button_down, "expected WM_LBUTTONDOWN message\n");
2444     ok(got_button_up, "expected WM_LBUTTONUP message\n");
2445 
2446     hregion = CreateRectRgn(0, 0, 10, 10);
2447     ok(hregion != NULL, "CreateRectRgn failed\n");
2448     ret = SetWindowRgn(hwnd, hregion, TRUE);
2449     ok(ret, "SetWindowRgn failed\n");
2450     DeleteObject(hregion);
2451     while (wait_for_message(&msg)) DispatchMessageA(&msg);
2452     Sleep(1000);
2453 
2454     if (pGetWindowRgnBox)
2455     {
2456         region_type = pGetWindowRgnBox(hwnd, &region);
2457         ok(region_type == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", region_type);
2458     }
2459 
2460     got_button_down = got_button_up = FALSE;
2461     simulate_click(TRUE, 150, 150);
2462     while (wait_for_message(&msg))
2463     {
2464         DispatchMessageA(&msg);
2465 
2466         if (msg.message == WM_LBUTTONDOWN)
2467         {
2468             ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
2469             got_button_down = TRUE;
2470         }
2471         else if (msg.message == WM_LBUTTONUP)
2472         {
2473             ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
2474             got_button_up = TRUE;
2475             break;
2476         }
2477     }
2478     ok(got_button_down, "expected WM_LBUTTONDOWN message\n");
2479     ok(got_button_up, "expected WM_LBUTTONUP message\n");
2480 
2481     DestroyWindow(static_win);
2482     DestroyWindow(hwnd);
2483     SetCursorPos(pt_org.x, pt_org.y);
2484 
2485     CloseHandle(thread_data.start_event);
2486     CloseHandle(thread_data.end_event);
2487     DestroyWindow(button_win);
2488 }
2489 
2490 
2491 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2492 {
2493     if (message == WM_USER+1)
2494     {
2495         HWND hwnd = (HWND)lParam;
2496         ok(GetFocus() == hwnd, "thread expected focus %p, got %p\n", hwnd, GetFocus());
2497         ok(GetActiveWindow() == hwnd, "thread expected active %p, got %p\n", hwnd, GetActiveWindow());
2498     }
2499     return DefWindowProcA(hwnd, message, wParam, lParam);
2500 }
2501 
2502 struct wnd_event
2503 {
2504     HWND hwnd;
2505     HANDLE wait_event;
2506     HANDLE start_event;
2507     DWORD attach_from;
2508     DWORD attach_to;
2509     BOOL setWindows;
2510 };
2511 
2512 static DWORD WINAPI thread_proc(void *param)
2513 {
2514     MSG msg;
2515     struct wnd_event *wnd_event = param;
2516     BOOL ret;
2517 
2518     if (wnd_event->wait_event)
2519     {
2520         ok(WaitForSingleObject(wnd_event->wait_event, INFINITE) == WAIT_OBJECT_0,
2521            "WaitForSingleObject failed\n");
2522         CloseHandle(wnd_event->wait_event);
2523     }
2524 
2525     if (wnd_event->attach_from)
2526     {
2527         ret = AttachThreadInput(wnd_event->attach_from, GetCurrentThreadId(), TRUE);
2528         ok(ret, "AttachThreadInput error %d\n", GetLastError());
2529     }
2530 
2531     if (wnd_event->attach_to)
2532     {
2533         ret = AttachThreadInput(GetCurrentThreadId(), wnd_event->attach_to, TRUE);
2534         ok(ret, "AttachThreadInput error %d\n", GetLastError());
2535     }
2536 
2537     wnd_event->hwnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW,
2538                                       100, 100, 200, 200, 0, 0, 0, NULL);
2539     ok(wnd_event->hwnd != 0, "Failed to create overlapped window\n");
2540 
2541     if (wnd_event->setWindows)
2542     {
2543         SetFocus(wnd_event->hwnd);
2544         SetActiveWindow(wnd_event->hwnd);
2545     }
2546 
2547     SetEvent(wnd_event->start_event);
2548 
2549     while (GetMessageA(&msg, 0, 0, 0))
2550     {
2551         TranslateMessage(&msg);
2552         DispatchMessageA(&msg);
2553     }
2554 
2555     return 0;
2556 }
2557 
2558 static void test_attach_input(void)
2559 {
2560     HANDLE hThread;
2561     HWND ourWnd, Wnd2;
2562     DWORD ret, tid;
2563     struct wnd_event wnd_event;
2564     WNDCLASSA cls;
2565 
2566     cls.style = 0;
2567     cls.lpfnWndProc = MsgCheckProcA;
2568     cls.cbClsExtra = 0;
2569     cls.cbWndExtra = 0;
2570     cls.hInstance = GetModuleHandleA(0);
2571     cls.hIcon = 0;
2572     cls.hCursor = LoadCursorW( NULL, (LPCWSTR)IDC_ARROW);
2573     cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2574     cls.lpszMenuName = NULL;
2575     cls.lpszClassName = "TestWindowClass";
2576     if(!RegisterClassA(&cls)) return;
2577 
2578     wnd_event.wait_event = NULL;
2579     wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL);
2580     wnd_event.attach_from = 0;
2581     wnd_event.attach_to = 0;
2582     wnd_event.setWindows = FALSE;
2583     if (!wnd_event.start_event)
2584     {
2585         win_skip("skipping interthread message test under win9x\n");
2586         return;
2587     }
2588 
2589     hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid);
2590     ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError());
2591 
2592     ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2593     CloseHandle(wnd_event.start_event);
2594 
2595     ourWnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
2596                             0, 0, 0, 0, 0, 0, 0, NULL);
2597     ok(ourWnd!= 0, "failed to create ourWnd window\n");
2598 
2599     Wnd2 = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
2600                             0, 0, 0, 0, 0, 0, 0, NULL);
2601     ok(Wnd2!= 0, "failed to create Wnd2 window\n");
2602 
2603     SetFocus(ourWnd);
2604     SetActiveWindow(ourWnd);
2605 
2606     ret = AttachThreadInput(GetCurrentThreadId(), tid, TRUE);
2607     ok(ret, "AttachThreadInput error %d\n", GetLastError());
2608 
2609     ok(GetActiveWindow() == ourWnd, "expected active %p, got %p\n", ourWnd, GetActiveWindow());
2610     ok(GetFocus() == ourWnd, "expected focus %p, got %p\n", ourWnd, GetFocus());
2611 
2612     SendMessageA(wnd_event.hwnd, WM_USER+1, 0, (LPARAM)ourWnd);
2613 
2614     ret = AttachThreadInput(GetCurrentThreadId(), tid, FALSE);
2615     ok(ret, "AttachThreadInput error %d\n", GetLastError());
2616     ok(GetActiveWindow() == ourWnd, "expected active %p, got %p\n", ourWnd, GetActiveWindow());
2617     ok(GetFocus() == ourWnd, "expected focus %p, got %p\n", ourWnd, GetFocus());
2618 
2619     SendMessageA(wnd_event.hwnd, WM_USER+1, 0, 0);
2620 
2621     ret = AttachThreadInput(GetCurrentThreadId(), tid, TRUE);
2622     ok(ret, "AttachThreadInput error %d\n", GetLastError());
2623 
2624     ok(GetActiveWindow() == ourWnd, "expected active %p, got %p\n", ourWnd, GetActiveWindow());
2625     ok(GetFocus() == ourWnd, "expected focus %p, got %p\n", ourWnd, GetFocus());
2626     SendMessageA(wnd_event.hwnd, WM_USER+1, 0, (LPARAM)ourWnd);
2627 
2628     SetActiveWindow(Wnd2);
2629     SetFocus(Wnd2);
2630     ok(GetActiveWindow() == Wnd2, "expected active %p, got %p\n", Wnd2, GetActiveWindow());
2631     ok(GetFocus() == Wnd2, "expected focus %p, got %p\n", Wnd2, GetFocus());
2632 
2633     SendMessageA(wnd_event.hwnd, WM_USER+1, 0, (LPARAM)Wnd2);
2634 
2635     ret = AttachThreadInput(GetCurrentThreadId(), tid, FALSE);
2636     ok(ret, "AttachThreadInput error %d\n", GetLastError());
2637     ok(GetActiveWindow() == Wnd2, "expected active %p, got %p\n", Wnd2, GetActiveWindow());
2638     ok(GetFocus() == Wnd2, "expected focus %p, got %p\n", Wnd2, GetFocus());
2639 
2640     SendMessageA(wnd_event.hwnd, WM_USER+1, 0, 0);
2641 
2642     ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0);
2643     ok(ret, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
2644 
2645     ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2646     CloseHandle(hThread);
2647 
2648     wnd_event.wait_event = NULL;
2649     wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL);
2650     wnd_event.attach_from = 0;
2651     wnd_event.attach_to = 0;
2652     wnd_event.setWindows = TRUE;
2653 
2654     hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid);
2655     ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError());
2656 
2657     ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2658     CloseHandle(wnd_event.start_event);
2659 
2660     SetFocus(ourWnd);
2661     SetActiveWindow(ourWnd);
2662 
2663     ret = AttachThreadInput(GetCurrentThreadId(), tid, TRUE);
2664     ok(ret, "AttachThreadInput error %d\n", GetLastError());
2665 
2666     ok(GetActiveWindow() == wnd_event.hwnd, "expected active %p, got %p\n", wnd_event.hwnd, GetActiveWindow());
2667     ok(GetFocus() == wnd_event.hwnd, "expected focus %p, got %p\n", wnd_event.hwnd, GetFocus());
2668 
2669     SendMessageA(wnd_event.hwnd, WM_USER+1, 0, (LPARAM)wnd_event.hwnd);
2670 
2671     ret = AttachThreadInput(GetCurrentThreadId(), tid, FALSE);
2672     ok(ret, "AttachThreadInput error %d\n", GetLastError());
2673 
2674     ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
2675     ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
2676 
2677     SendMessageA(wnd_event.hwnd, WM_USER+1, 0, (LPARAM)wnd_event.hwnd);
2678 
2679     ret = AttachThreadInput(GetCurrentThreadId(), tid, TRUE);
2680     ok(ret, "AttachThreadInput error %d\n", GetLastError());
2681 
2682     ok(GetActiveWindow() == wnd_event.hwnd, "expected active %p, got %p\n", wnd_event.hwnd, GetActiveWindow());
2683     ok(GetFocus() == wnd_event.hwnd, "expected focus %p, got %p\n", wnd_event.hwnd, GetFocus());
2684 
2685     SendMessageA(wnd_event.hwnd, WM_USER+1, 0, (LPARAM)wnd_event.hwnd);
2686 
2687     SetFocus(Wnd2);
2688     SetActiveWindow(Wnd2);
2689     ok(GetActiveWindow() == Wnd2, "expected active %p, got %p\n", Wnd2, GetActiveWindow());
2690     ok(GetFocus() == Wnd2, "expected focus %p, got %p\n", Wnd2, GetFocus());
2691 
2692     SendMessageA(wnd_event.hwnd, WM_USER+1, 0, (LPARAM)Wnd2);
2693 
2694     ret = AttachThreadInput(GetCurrentThreadId(), tid, FALSE);
2695     ok(ret, "AttachThreadInput error %d\n", GetLastError());
2696 
2697     ok(GetActiveWindow() == Wnd2, "expected active %p, got %p\n", Wnd2, GetActiveWindow());
2698     ok(GetFocus() == Wnd2, "expected focus %p, got %p\n", Wnd2, GetFocus());
2699 
2700     SendMessageA(wnd_event.hwnd, WM_USER+1, 0, 0);
2701 
2702     ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0);
2703     ok(ret, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
2704 
2705     ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2706     CloseHandle(hThread);
2707 
2708     wnd_event.wait_event = CreateEventW(NULL, 0, 0, NULL);
2709     wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL);
2710     wnd_event.attach_from = 0;
2711     wnd_event.attach_to = 0;
2712     wnd_event.setWindows = TRUE;
2713 
2714     hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid);
2715     ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError());
2716 
2717     SetLastError(0xdeadbeef);
2718     ret = AttachThreadInput(GetCurrentThreadId(), tid, TRUE);
2719     ok(!ret, "AttachThreadInput succeeded\n");
2720     ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef) /* <= Win XP */,
2721        "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2722 
2723     SetLastError(0xdeadbeef);
2724     ret = AttachThreadInput(tid, GetCurrentThreadId(), TRUE);
2725     ok(!ret, "AttachThreadInput succeeded\n");
2726     ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef) /* <= Win XP */,
2727        "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2728 
2729     SetEvent(wnd_event.wait_event);
2730 
2731     ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2732     CloseHandle(wnd_event.start_event);
2733 
2734     ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0);
2735     ok(ret, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
2736 
2737     ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2738     CloseHandle(hThread);
2739 
2740     wnd_event.wait_event = NULL;
2741     wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL);
2742     wnd_event.attach_from = GetCurrentThreadId();
2743     wnd_event.attach_to = 0;
2744     wnd_event.setWindows = FALSE;
2745 
2746     SetFocus(ourWnd);
2747     SetActiveWindow(ourWnd);
2748 
2749     hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid);
2750     ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError());
2751 
2752     ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2753     CloseHandle(wnd_event.start_event);
2754 
2755     ok(GetActiveWindow() == ourWnd, "expected active %p, got %p\n", ourWnd, GetActiveWindow());
2756     ok(GetFocus() == ourWnd, "expected focus %p, got %p\n", ourWnd, GetFocus());
2757 
2758     ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0);
2759     ok(ret, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
2760 
2761     ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2762     CloseHandle(hThread);
2763 
2764     wnd_event.wait_event = NULL;
2765     wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL);
2766     wnd_event.attach_from = 0;
2767     wnd_event.attach_to = GetCurrentThreadId();
2768     wnd_event.setWindows = FALSE;
2769 
2770     SetFocus(ourWnd);
2771     SetActiveWindow(ourWnd);
2772 
2773     hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid);
2774     ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError());
2775 
2776     ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2777     CloseHandle(wnd_event.start_event);
2778 
2779     ok(GetActiveWindow() == ourWnd, "expected active %p, got %p\n", ourWnd, GetActiveWindow());
2780     ok(GetFocus() == ourWnd, "expected focus %p, got %p\n", ourWnd, GetFocus());
2781 
2782     ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0);
2783     ok(ret, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
2784 
2785     ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2786     CloseHandle(hThread);
2787     DestroyWindow(ourWnd);
2788     DestroyWindow(Wnd2);
2789 }
2790 
2791 static DWORD WINAPI get_key_state_thread(void *arg)
2792 {
2793     HANDLE *semaphores = arg;
2794     DWORD result;
2795 
2796     ReleaseSemaphore(semaphores[0], 1, NULL);
2797     result = WaitForSingleObject(semaphores[1], 1000);
2798     ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
2799 
2800     result = GetKeyState('X');
2801     ok((result & 0x8000) || broken(!(result & 0x8000)), /* > Win 2003 */
2802        "expected that highest bit is set, got %x\n", result);
2803 
2804     ReleaseSemaphore(semaphores[0], 1, NULL);
2805     result = WaitForSingleObject(semaphores[1], 1000);
2806     ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
2807 
2808     result = GetKeyState('X');
2809     ok(!(result & 0x8000), "expected that highest bit is unset, got %x\n", result);
2810 
2811     return 0;
2812 }
2813 
2814 static void test_GetKeyState(void)
2815 {
2816     HANDLE semaphores[2];
2817     HANDLE thread;
2818     DWORD result;
2819     HWND hwnd;
2820 
2821     semaphores[0] = CreateSemaphoreA(NULL, 0, 1, NULL);
2822     ok(semaphores[0] != NULL, "CreateSemaphoreA failed %u\n", GetLastError());
2823     semaphores[1] = CreateSemaphoreA(NULL, 0, 1, NULL);
2824     ok(semaphores[1] != NULL, "CreateSemaphoreA failed %u\n", GetLastError());
2825 
2826     hwnd = CreateWindowA("static", "Title", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2827                          10, 10, 200, 200, NULL, NULL, NULL, NULL);
2828     ok(hwnd != NULL, "CreateWindowA failed %u\n", GetLastError());
2829 
2830     thread = CreateThread(NULL, 0, get_key_state_thread, semaphores, 0, NULL);
2831     ok(thread != NULL, "CreateThread failed %u\n", GetLastError());
2832     result = WaitForSingleObject(semaphores[0], 1000);
2833     ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
2834 
2835     SetFocus(hwnd);
2836     keybd_event('X', 0, 0, 0);
2837 
2838     ReleaseSemaphore(semaphores[1], 1, NULL);
2839     result = WaitForSingleObject(semaphores[0], 1000);
2840     ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
2841 
2842     keybd_event('X', 0, KEYEVENTF_KEYUP, 0);
2843 
2844     ReleaseSemaphore(semaphores[1], 1, NULL);
2845     result = WaitForSingleObject(thread, 1000);
2846     ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
2847     CloseHandle(thread);
2848 
2849     DestroyWindow(hwnd);
2850     CloseHandle(semaphores[0]);
2851     CloseHandle(semaphores[1]);
2852 }
2853 
2854 static void test_OemKeyScan(void)
2855 {
2856     DWORD ret, expect, vkey, scan;
2857     WCHAR oem, wchr;
2858     char oem_char;
2859 
2860     for (oem = 0; oem < 0x200; oem++)
2861     {
2862         ret = OemKeyScan( oem );
2863 
2864         oem_char = LOBYTE( oem );
2865         /* OemKeyScan returns -1 for any character that cannot be mapped,
2866          * whereas OemToCharBuff changes unmappable characters to question
2867          * marks. The ASCII characters 0-127, including the real question mark
2868          * character, are all mappable and are the same in all OEM codepages. */
2869         if (!OemToCharBuffW( &oem_char, &wchr, 1 ) || (wchr == '?' && oem_char < 0))
2870             expect = -1;
2871         else
2872         {
2873             vkey = VkKeyScanW( wchr );
2874             scan = MapVirtualKeyW( LOBYTE( vkey ), MAPVK_VK_TO_VSC );
2875             if (!scan)
2876                 expect = -1;
2877             else
2878             {
2879                 vkey &= 0xff00;
2880                 vkey <<= 8;
2881                 expect = vkey | scan;
2882             }
2883         }
2884         ok( ret == expect, "%04x: got %08x expected %08x\n", oem, ret, expect );
2885     }
2886 }
2887 
2888 START_TEST(input)
2889 {
2890     init_function_pointers();
2891 
2892     if (pSendInput)
2893     {
2894         test_Input_blackbox();
2895         test_Input_whitebox();
2896         test_Input_unicode();
2897         test_Input_mouse();
2898     }
2899     else win_skip("SendInput is not available\n");
2900 
2901     test_keynames();
2902     test_mouse_ll_hook();
2903     test_key_map();
2904     test_ToUnicode();
2905     test_ToAscii();
2906     test_get_async_key_state();
2907     test_keyboard_layout_name();
2908     test_key_names();
2909     test_attach_input();
2910     test_GetKeyState();
2911     test_OemKeyScan();
2912 
2913     if(pGetMouseMovePointsEx)
2914         test_GetMouseMovePointsEx();
2915     else
2916         win_skip("GetMouseMovePointsEx is not available\n");
2917 
2918     if(pGetRawInputDeviceList)
2919         test_GetRawInputDeviceList();
2920     else
2921         win_skip("GetRawInputDeviceList is not available\n");
2922 }
2923