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