user32: DrawState always uses real icon size for drawing.
[wine] / dlls / user32 / tests / input.c
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 #define _WIN32_WINNT 0x401
48 #define _WIN32_IE 0x0500
49
50 #include <stdarg.h>
51 #include <assert.h>
52
53 #include "windef.h"
54 #include "winbase.h"
55 #include "winuser.h"
56
57 #include "wine/test.h"
58
59 /* globals */
60 static HWND hWndTest;
61 static LONG timetag = 0x10000000;
62
63 static struct {
64     LONG last_key_down;
65     LONG last_key_up;
66     LONG last_syskey_down;
67     LONG last_syskey_up;
68     LONG last_char;
69     LONG last_syschar;
70     LONG last_hook_down;
71     LONG last_hook_up;
72     LONG last_hook_syskey_down;
73     LONG last_hook_syskey_up;
74     BOOL expect_alt;
75     BOOL sendinput_broken;
76 } key_status;
77
78 static UINT (WINAPI *pSendInput) (UINT, INPUT*, size_t);
79 static int (WINAPI *pGetMouseMovePointsEx) (UINT, LPMOUSEMOVEPOINT, LPMOUSEMOVEPOINT, int, DWORD);
80
81 #define MAXKEYEVENTS 12
82 #define MAXKEYMESSAGES MAXKEYEVENTS /* assuming a key event generates one
83                                        and only one message */
84
85 /* keyboard message names, sorted as their value */
86 static const char *MSGNAME[]={"WM_KEYDOWN", "WM_KEYUP", "WM_CHAR","WM_DEADCHAR",
87     "WM_SYSKEYDOWN", "WM_SYSKEYUP", "WM_SYSCHAR", "WM_SYSDEADCHAR" ,"WM_KEYLAST"};
88
89 /* keyevents, add more as needed */
90 typedef enum KEVtag
91 {  ALTDOWN = 1, ALTUP, XDOWN, XUP, SHIFTDOWN, SHIFTUP, CTRLDOWN, CTRLUP } KEV;
92 /* matching VK's */
93 static const int GETVKEY[]={0, VK_MENU, VK_MENU, 'X', 'X', VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL};
94 /* matching scan codes */
95 static const int GETSCAN[]={0, 0x38, 0x38, 0x2D, 0x2D, 0x2A, 0x2A, 0x1D, 0x1D };
96 /* matching updown events */
97 static const int GETFLAGS[]={0, 0, KEYEVENTF_KEYUP, 0, KEYEVENTF_KEYUP, 0, KEYEVENTF_KEYUP, 0, KEYEVENTF_KEYUP};
98 /* matching descriptions */
99 static const char *getdesc[]={"", "+alt","-alt","+X","-X","+shift","-shift","+ctrl","-ctrl"};
100
101 /* The MSVC headers ignore our NONAMELESSUNION requests so we have to define our own type */
102 typedef struct
103 {
104     DWORD type;
105     union
106     {
107         MOUSEINPUT      mi;
108         KEYBDINPUT      ki;
109         HARDWAREINPUT   hi;
110     } u;
111 } TEST_INPUT;
112
113 #define ADDTOINPUTS(kev) \
114 inputs[evtctr].type = INPUT_KEYBOARD; \
115     ((TEST_INPUT*)inputs)[evtctr].u.ki.wVk = GETVKEY[ kev]; \
116     ((TEST_INPUT*)inputs)[evtctr].u.ki.wScan = GETSCAN[ kev]; \
117     ((TEST_INPUT*)inputs)[evtctr].u.ki.dwFlags = GETFLAGS[ kev]; \
118     ((TEST_INPUT*)inputs)[evtctr].u.ki.dwExtraInfo = 0; \
119     ((TEST_INPUT*)inputs)[evtctr].u.ki.time = ++timetag; \
120     if( kev) evtctr++;
121
122 typedef struct {
123     UINT    message;
124     WPARAM  wParam;
125     LPARAM  lParam;
126 } KMSG;
127
128 /*******************************************
129  * add new test sets here
130  * the software will make all combinations of the
131  * keyevent defined here
132  */
133 static const struct {
134     int nrkev;
135     KEV keydwn[MAXKEYEVENTS];
136     KEV keyup[MAXKEYEVENTS];
137 } testkeyset[]= {
138     { 2, { ALTDOWN, XDOWN }, { ALTUP, XUP}},
139     { 3, { ALTDOWN, XDOWN , SHIFTDOWN}, { ALTUP, XUP, SHIFTUP}},
140     { 3, { ALTDOWN, XDOWN , CTRLDOWN}, { ALTUP, XUP, CTRLUP}},
141     { 3, { SHIFTDOWN, XDOWN , CTRLDOWN}, { SHIFTUP, XUP, CTRLUP}},
142     { 0 } /* mark the end */
143 };
144
145 /**********************adapted from input.c **********************************/
146
147 static BYTE InputKeyStateTable[256];
148 static BYTE AsyncKeyStateTable[256];
149 static BYTE TrackSysKey = 0; /* determine whether ALT key up will cause a WM_SYSKEYUP
150                          or a WM_KEYUP message */
151
152 static void init_function_pointers(void)
153 {
154     HMODULE hdll = GetModuleHandleA("user32");
155
156 #define GET_PROC(func) \
157     p ## func = (void*)GetProcAddress(hdll, #func); \
158     if(!p ## func) \
159       trace("GetProcAddress(%s) failed\n", #func);
160
161     GET_PROC(SendInput)
162     GET_PROC(GetMouseMovePointsEx)
163
164 #undef GET_PROC
165 }
166
167 static int KbdMessage( KEV kev, WPARAM *pwParam, LPARAM *plParam )
168 {
169     UINT message;
170     int VKey = GETVKEY[kev];
171     WORD flags;
172
173     flags = LOBYTE(GETSCAN[kev]);
174     if (GETFLAGS[kev] & KEYEVENTF_EXTENDEDKEY) flags |= KF_EXTENDED;
175
176     if (GETFLAGS[kev] & KEYEVENTF_KEYUP )
177     {
178         message = WM_KEYUP;
179         if( (InputKeyStateTable[VK_MENU] & 0x80) && (
180                 (VKey == VK_MENU) || (VKey == VK_CONTROL) ||
181                  !(InputKeyStateTable[VK_CONTROL] & 0x80))) {
182             if(  TrackSysKey == VK_MENU || /* <ALT>-down/<ALT>-up sequence */
183                     (VKey != VK_MENU)) /* <ALT>-down...<something else>-up */
184                 message = WM_SYSKEYUP;
185                 TrackSysKey = 0;
186         }
187         InputKeyStateTable[VKey] &= ~0x80;
188         flags |= KF_REPEAT | KF_UP;
189     }
190     else
191     {
192         if (InputKeyStateTable[VKey] & 0x80) flags |= KF_REPEAT;
193         if (!(InputKeyStateTable[VKey] & 0x80)) InputKeyStateTable[VKey] ^= 0x01;
194         InputKeyStateTable[VKey] |= 0x80;
195         AsyncKeyStateTable[VKey] |= 0x80;
196
197         message = WM_KEYDOWN;
198         if( (InputKeyStateTable[VK_MENU] & 0x80) &&
199                 !(InputKeyStateTable[VK_CONTROL] & 0x80)) {
200             message = WM_SYSKEYDOWN;
201             TrackSysKey = VKey;
202         }
203     }
204
205     if (InputKeyStateTable[VK_MENU] & 0x80) flags |= KF_ALTDOWN;
206
207     if( plParam) *plParam = MAKELPARAM( 1, flags );
208     if( pwParam) *pwParam = VKey;
209     return message;
210 }
211
212 /****************************** end copy input.c ****************************/
213
214 /*
215  * . prepare the keyevents for SendInputs
216  * . calculate the "expected" messages
217  * . Send the events to our window
218  * . retrieve the messages from the input queue
219  * . verify
220  */
221 static BOOL do_test( HWND hwnd, int seqnr, const KEV td[] )
222 {
223     INPUT inputs[MAXKEYEVENTS];
224     KMSG expmsg[MAXKEYEVENTS];
225     MSG msg;
226     char buf[100];
227     UINT evtctr=0;
228     int kmctr, i;
229
230     buf[0]='\0';
231     TrackSysKey=0; /* see input.c */
232     for( i = 0; i < MAXKEYEVENTS; i++) {
233         ADDTOINPUTS(td[i])
234         strcat(buf, getdesc[td[i]]);
235         if(td[i])
236             expmsg[i].message = KbdMessage(td[i], &(expmsg[i].wParam), &(expmsg[i].lParam)); /* see queue_kbd_event() */
237         else
238             expmsg[i].message = 0;
239     }
240     for( kmctr = 0; kmctr < MAXKEYEVENTS && expmsg[kmctr].message; kmctr++)
241         ;
242     assert( evtctr <= MAXKEYEVENTS );
243     assert( evtctr == pSendInput(evtctr, &inputs[0], sizeof(INPUT)));
244     i = 0;
245     if (winetest_debug > 1)
246         trace("======== key stroke sequence #%d: %s =============\n",
247             seqnr + 1, buf);
248     while( PeekMessage(&msg,hwnd,WM_KEYFIRST,WM_KEYLAST,PM_REMOVE) ) {
249         if (winetest_debug > 1)
250             trace("message[%d] %-15s wParam %04lx lParam %08lx time %x\n", i,
251                   MSGNAME[msg.message - WM_KEYFIRST], msg.wParam, msg.lParam, msg.time);
252         if( i < kmctr ) {
253             ok( msg.message == expmsg[i].message &&
254                 msg.wParam == expmsg[i].wParam &&
255                 msg.lParam == expmsg[i].lParam,
256                 "%u/%u: wrong message %x/%08lx/%08lx expected %s/%08lx/%08lx\n",
257                 seqnr, i, msg.message, msg.wParam, msg.lParam,
258                 MSGNAME[(expmsg[i]).message - WM_KEYFIRST], expmsg[i].wParam, expmsg[i].lParam );
259         }
260         i++;
261     }
262     if (winetest_debug > 1)
263         trace("%d messages retrieved\n", i);
264     if (!i && kmctr)
265     {
266         skip( "simulated keyboard input doesn't work\n" );
267         return FALSE;
268     }
269     ok( i == kmctr, "message count is wrong: got %d expected: %d\n", i, kmctr);
270     return TRUE;
271 }
272
273 /* test all combinations of the specified key events */
274 static BOOL TestASet( HWND hWnd, int nrkev, const KEV kevdwn[], const KEV kevup[] )
275 {
276     int i,j,k,l,m,n;
277     static int count=0;
278     KEV kbuf[MAXKEYEVENTS];
279     assert( nrkev==2 || nrkev==3);
280     for(i=0;i<MAXKEYEVENTS;i++) kbuf[i]=0;
281     /* two keys involved gives 4 test cases */
282     if(nrkev==2) {
283         for(i=0;i<nrkev;i++) {
284             for(j=0;j<nrkev;j++) {
285                 kbuf[0] = kevdwn[i];
286                 kbuf[1] = kevdwn[1-i];
287                 kbuf[2] = kevup[j];
288                 kbuf[3] = kevup[1-j];
289                 if (!do_test( hWnd, count++, kbuf)) return FALSE;
290             }
291         }
292     }
293     /* three keys involved gives 36 test cases */
294     if(nrkev==3){
295         for(i=0;i<nrkev;i++){
296             for(j=0;j<nrkev;j++){
297                 if(j==i) continue;
298                 for(k=0;k<nrkev;k++){
299                     if(k==i || k==j) continue;
300                     for(l=0;l<nrkev;l++){
301                         for(m=0;m<nrkev;m++){
302                             if(m==l) continue;
303                             for(n=0;n<nrkev;n++){
304                                 if(n==l ||n==m) continue;
305                                 kbuf[0] = kevdwn[i];
306                                 kbuf[1] = kevdwn[j];
307                                 kbuf[2] = kevdwn[k];
308                                 kbuf[3] = kevup[l];
309                                 kbuf[4] = kevup[m];
310                                 kbuf[5] = kevup[n];
311                                 if (!do_test( hWnd, count++, kbuf)) return FALSE;
312                             }
313                         }
314                     }
315                 }
316             }
317         }
318     }
319     return TRUE;
320 }
321
322 /* test each set specified in the global testkeyset array */
323 static void TestSysKeys( HWND hWnd)
324 {
325     int i;
326     for(i=0; testkeyset[i].nrkev;i++)
327         if (!TestASet( hWnd, testkeyset[i].nrkev, testkeyset[i].keydwn, testkeyset[i].keyup)) break;
328 }
329
330 static LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam,
331         LPARAM lParam )
332 {
333     return DefWindowProcA( hWnd, msg, wParam, lParam );
334 }
335
336 static void test_Input_whitebox(void)
337 {
338     MSG msg;
339     WNDCLASSA  wclass;
340     HANDLE hInstance = GetModuleHandleA( NULL );
341
342     wclass.lpszClassName = "InputSysKeyTestClass";
343     wclass.style         = CS_HREDRAW | CS_VREDRAW;
344     wclass.lpfnWndProc   = WndProc;
345     wclass.hInstance     = hInstance;
346     wclass.hIcon         = LoadIconA( 0, IDI_APPLICATION );
347     wclass.hCursor       = LoadCursorA( NULL, IDC_ARROW );
348     wclass.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 );
349     wclass.lpszMenuName = 0;
350     wclass.cbClsExtra    = 0;
351     wclass.cbWndExtra    = 0;
352     RegisterClassA( &wclass );
353     /* create the test window that will receive the keystrokes */
354     hWndTest = CreateWindowA( wclass.lpszClassName, "InputSysKeyTest",
355                               WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 100, 100,
356                               NULL, NULL, hInstance, NULL);
357     assert( hWndTest );
358     ShowWindow( hWndTest, SW_SHOW);
359     SetWindowPos( hWndTest, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
360     SetForegroundWindow( hWndTest );
361     UpdateWindow( hWndTest);
362
363     /* flush pending messages */
364     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
365
366     SetFocus( hWndTest );
367     TestSysKeys( hWndTest );
368     DestroyWindow(hWndTest);
369 }
370
371 /* try to make sure pending X events have been processed before continuing */
372 static void empty_message_queue(void)
373 {
374     MSG msg;
375     int diff = 200;
376     int min_timeout = 50;
377     DWORD time = GetTickCount() + diff;
378
379     while (diff > 0)
380     {
381         if (MsgWaitForMultipleObjects(0, NULL, FALSE, min_timeout, QS_ALLINPUT) == WAIT_TIMEOUT) break;
382         while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
383         {
384             TranslateMessage(&msg);
385             DispatchMessage(&msg);
386         }
387         diff = time - GetTickCount();
388     }
389 }
390
391 struct transition_s {
392     WORD wVk;
393     BYTE before_state;
394     BYTE optional;
395 };
396
397 typedef enum {
398     sent=0x1,
399     posted=0x2,
400     parent=0x4,
401     wparam=0x8,
402     lparam=0x10,
403     defwinproc=0x20,
404     beginpaint=0x40,
405     optional=0x80,
406     hook=0x100,
407     winevent_hook=0x200
408 } msg_flags_t;
409
410 struct message {
411     UINT message;          /* the WM_* code */
412     msg_flags_t flags;     /* message props */
413     WPARAM wParam;         /* expected value of wParam */
414     LPARAM lParam;         /* expected value of lParam */
415 };
416
417 struct sendinput_test_s {
418     WORD wVk;
419     DWORD dwFlags;
420     BOOL _todo_wine;
421     struct transition_s expected_transitions[MAXKEYEVENTS+1];
422     struct message expected_messages[MAXKEYMESSAGES+1];
423 } sendinput_test[] = {
424     /* test ALT+F */
425     /* 0 */
426     {VK_LMENU, 0, 0, {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {0}},
427         {{WM_SYSKEYDOWN, hook|wparam, VK_LMENU}, {WM_SYSKEYDOWN}, {0}}},
428     {'F', 0, 0, {{'F', 0x00}, {0}},
429         {{WM_SYSKEYDOWN, hook}, {WM_SYSKEYDOWN},
430         {WM_SYSCHAR},
431         {WM_SYSCOMMAND}, {0}}},
432     {'F', KEYEVENTF_KEYUP, 0, {{'F', 0x80}, {0}},
433         {{WM_SYSKEYUP, hook}, {WM_SYSKEYUP}, {0}}},
434     {VK_LMENU, KEYEVENTF_KEYUP, 0, {{VK_MENU, 0x80}, {VK_LMENU, 0x80}, {0}},
435         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
436
437     /* test CTRL+O */
438     /* 4 */
439     {VK_LCONTROL, 0, 0, {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}},
440         {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {0}}},
441     {'O', 0, 0, {{'O', 0x00}, {0}},
442         {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {WM_CHAR}, {0}}},
443     {'O', KEYEVENTF_KEYUP, 0, {{'O', 0x80}, {0}},
444         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
445     {VK_LCONTROL, KEYEVENTF_KEYUP, 0, {{VK_CONTROL, 0x80}, {VK_LCONTROL, 0x80}, {0}},
446         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
447
448     /* test ALT+CTRL+X */
449     /* 8 */
450     {VK_LMENU, 0, 0, {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {0}},
451         {{WM_SYSKEYDOWN, hook}, {WM_SYSKEYDOWN}, {0}}},
452     {VK_LCONTROL, 0, 0, {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}},
453         {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {0}}},
454     {'X', 0, 0, {{'X', 0x00}, {0}},
455         {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {0}}},
456     {'X', KEYEVENTF_KEYUP, 0, {{'X', 0x80}, {0}},
457         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
458     {VK_LCONTROL, KEYEVENTF_KEYUP, 0, {{VK_CONTROL, 0x80}, {VK_LCONTROL, 0x80}, {0}},
459         {{WM_SYSKEYUP, hook}, {WM_SYSKEYUP}, {0}}},
460     {VK_LMENU, KEYEVENTF_KEYUP, 0, {{VK_MENU, 0x80}, {VK_LMENU, 0x80}, {0}},
461         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
462
463     /* test SHIFT+A */
464     /* 14 */
465     {VK_LSHIFT, 0, 0, {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00}, {0}},
466         {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {0}}},
467     {'A', 0, 0, {{'A', 0x00}, {0}},
468         {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {WM_CHAR}, {0}}},
469     {'A', KEYEVENTF_KEYUP, 0, {{'A', 0x80}, {0}},
470         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
471     {VK_LSHIFT, KEYEVENTF_KEYUP, 0, {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80}, {0}},
472         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
473     /* test L-SHIFT & R-SHIFT: */
474     /* RSHIFT == LSHIFT */
475     /* 18 */
476     {VK_RSHIFT, 0, 0,
477      /* recent windows versions (>= w2k3) correctly report an RSHIFT transition */
478        {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00, TRUE}, {VK_RSHIFT, 0x00, TRUE}, {0}},
479         {{WM_KEYDOWN, hook|wparam, VK_RSHIFT},
480         {WM_KEYDOWN}, {0}}},
481     {VK_RSHIFT, KEYEVENTF_KEYUP, 0,
482        {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80, TRUE}, {VK_RSHIFT, 0x80, TRUE}, {0}},
483         {{WM_KEYUP, hook, hook|wparam, VK_RSHIFT},
484         {WM_KEYUP}, {0}}},
485
486     /* LSHIFT | KEYEVENTF_EXTENDEDKEY == RSHIFT */
487     /* 20 */
488     {VK_LSHIFT, KEYEVENTF_EXTENDEDKEY, 0,
489         {{VK_SHIFT, 0x00}, {VK_RSHIFT, 0x00}, {0}},
490         {{WM_KEYDOWN, hook|wparam|lparam, VK_LSHIFT, LLKHF_EXTENDED},
491         {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}},
492     {VK_LSHIFT, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 0,
493         {{VK_SHIFT, 0x80}, {VK_RSHIFT, 0x80}, {0}},
494         {{WM_KEYUP, hook|wparam|lparam, VK_LSHIFT, LLKHF_UP|LLKHF_EXTENDED},
495         {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}},
496     /* RSHIFT | KEYEVENTF_EXTENDEDKEY == RSHIFT */
497     /* 22 */
498     {VK_RSHIFT, KEYEVENTF_EXTENDEDKEY, 0,
499         {{VK_SHIFT, 0x00}, {VK_RSHIFT, 0x00}, {0}},
500         {{WM_KEYDOWN, hook|wparam|lparam, VK_RSHIFT, LLKHF_EXTENDED},
501         {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}},
502     {VK_RSHIFT, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 0,
503         {{VK_SHIFT, 0x80}, {VK_RSHIFT, 0x80}, {0}},
504         {{WM_KEYUP, hook|wparam|lparam, VK_RSHIFT, LLKHF_UP|LLKHF_EXTENDED},
505         {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}},
506
507     /* Note about wparam for hook with generic key (VK_SHIFT, VK_CONTROL, VK_MENU):
508        win2k  - sends to hook whatever we generated here
509        winXP+ - Attempts to convert key to L/R key but not always correct
510     */
511     /* SHIFT == LSHIFT */
512     /* 24 */
513     {VK_SHIFT, 0, 0,
514         {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00}, {0}},
515         {{WM_KEYDOWN, hook/* |wparam */|lparam, VK_SHIFT, 0},
516         {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}},
517     {VK_SHIFT, KEYEVENTF_KEYUP, 0,
518         {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80}, {0}},
519         {{WM_KEYUP, hook/*|wparam*/|lparam, VK_SHIFT, LLKHF_UP},
520         {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}},
521     /* SHIFT | KEYEVENTF_EXTENDEDKEY == RSHIFT */
522     /* 26 */
523     {VK_SHIFT, KEYEVENTF_EXTENDEDKEY, 0,
524         {{VK_SHIFT, 0x00}, {VK_RSHIFT, 0x00}, {0}},
525         {{WM_KEYDOWN, hook/*|wparam*/|lparam, VK_SHIFT, LLKHF_EXTENDED},
526         {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}},
527     {VK_SHIFT, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 0,
528         {{VK_SHIFT, 0x80}, {VK_RSHIFT, 0x80}, {0}},
529         {{WM_KEYUP, hook/*|wparam*/|lparam, VK_SHIFT, LLKHF_UP|LLKHF_EXTENDED},
530         {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}},
531
532     /* test L-CONTROL & R-CONTROL: */
533     /* RCONTROL == LCONTROL */
534     /* 28 */
535     {VK_RCONTROL, 0, 0,
536         {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}},
537         {{WM_KEYDOWN, hook|wparam, VK_RCONTROL},
538         {WM_KEYDOWN, wparam|lparam, VK_CONTROL, 0}, {0}}},
539     {VK_RCONTROL, KEYEVENTF_KEYUP, 0,
540         {{VK_CONTROL, 0x80}, {VK_LCONTROL, 0x80}, {0}},
541         {{WM_KEYUP, hook|wparam, VK_RCONTROL},
542         {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP}, {0}}},
543     /* LCONTROL | KEYEVENTF_EXTENDEDKEY == RCONTROL */
544     /* 30 */
545     {VK_LCONTROL, KEYEVENTF_EXTENDEDKEY, 0,
546         {{VK_CONTROL, 0x00}, {VK_RCONTROL, 0x00}, {0}},
547         {{WM_KEYDOWN, hook|wparam|lparam, VK_LCONTROL, LLKHF_EXTENDED},
548         {WM_KEYDOWN, wparam|lparam, VK_CONTROL, KF_EXTENDED}, {0}}},
549     {VK_LCONTROL, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 0,
550         {{VK_CONTROL, 0x80}, {VK_RCONTROL, 0x80}, {0}},
551         {{WM_KEYUP, hook|wparam|lparam, VK_LCONTROL, LLKHF_UP|LLKHF_EXTENDED},
552         {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP|KF_EXTENDED}, {0}}},
553     /* RCONTROL | KEYEVENTF_EXTENDEDKEY == RCONTROL */
554     /* 32 */
555     {VK_RCONTROL, KEYEVENTF_EXTENDEDKEY, 0,
556         {{VK_CONTROL, 0x00}, {VK_RCONTROL, 0x00}, {0}},
557         {{WM_KEYDOWN, hook|wparam|lparam, VK_RCONTROL, LLKHF_EXTENDED},
558         {WM_KEYDOWN, wparam|lparam, VK_CONTROL, KF_EXTENDED}, {0}}},
559     {VK_RCONTROL, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 0,
560         {{VK_CONTROL, 0x80}, {VK_RCONTROL, 0x80}, {0}},
561         {{WM_KEYUP, hook|wparam|lparam, VK_RCONTROL, LLKHF_UP|LLKHF_EXTENDED},
562         {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP|KF_EXTENDED}, {0}}},
563     /* CONTROL == LCONTROL */
564     /* 34 */
565     {VK_CONTROL, 0, 0,
566         {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}},
567         {{WM_KEYDOWN, hook/*|wparam, VK_CONTROL*/},
568         {WM_KEYDOWN, wparam|lparam, VK_CONTROL, 0}, {0}}},
569     {VK_CONTROL, KEYEVENTF_KEYUP, 0,
570         {{VK_CONTROL, 0x80}, {VK_LCONTROL, 0x80}, {0}},
571         {{WM_KEYUP, hook/*|wparam, VK_CONTROL*/},
572         {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP}, {0}}},
573     /* CONTROL | KEYEVENTF_EXTENDEDKEY == RCONTROL */
574     /* 36 */
575     {VK_CONTROL, KEYEVENTF_EXTENDEDKEY, 0,
576         {{VK_CONTROL, 0x00}, {VK_RCONTROL, 0x00}, {0}},
577         {{WM_KEYDOWN, hook/*|wparam*/|lparam, VK_CONTROL, LLKHF_EXTENDED},
578         {WM_KEYDOWN, wparam|lparam, VK_CONTROL, KF_EXTENDED}, {0}}},
579     {VK_CONTROL, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 0,
580         {{VK_CONTROL, 0x80}, {VK_RCONTROL, 0x80}, {0}},
581         {{WM_KEYUP, hook/*|wparam*/|lparam, VK_CONTROL, LLKHF_UP|LLKHF_EXTENDED},
582         {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP|KF_EXTENDED}, {0}}},
583
584     /* test L-MENU & R-MENU: */
585     /* RMENU == LMENU */
586     /* 38 */
587     {VK_RMENU, 0, 0,
588         {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {VK_CONTROL, 0x00, 1}, {VK_LCONTROL, 0x01, 1}, {0}},
589         {{WM_SYSKEYDOWN, hook|wparam|optional, VK_LCONTROL},
590         {WM_SYSKEYDOWN, hook|wparam, VK_RMENU},
591         {WM_KEYDOWN, wparam|lparam|optional, VK_CONTROL, 0},
592         {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0}, {0}}},
593     {VK_RMENU, KEYEVENTF_KEYUP, 1,
594         {{VK_MENU, 0x80}, {VK_LMENU, 0x80}, {VK_CONTROL, 0x81, 1}, {VK_LCONTROL, 0x80, 1}, {0}},
595         {{WM_KEYUP, hook|wparam|optional, VK_LCONTROL},
596         {WM_KEYUP, hook|wparam, VK_RMENU},
597         {WM_SYSKEYUP, wparam|lparam|optional, VK_CONTROL, KF_UP},
598         {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP},
599         {WM_SYSCOMMAND, optional}, {0}}},
600     /* LMENU | KEYEVENTF_EXTENDEDKEY == RMENU */
601     /* 40 */
602     {VK_LMENU, KEYEVENTF_EXTENDEDKEY, 0,
603         {{VK_MENU, 0x00}, {VK_RMENU, 0x00}, {0}},
604         {{WM_SYSKEYDOWN, hook|wparam|lparam, VK_LMENU, LLKHF_EXTENDED},
605         {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, KF_EXTENDED}, {0}}},
606     {VK_LMENU, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 1,
607         {{VK_MENU, 0x80}, {VK_RMENU, 0x80}, {0}},
608         {{WM_KEYUP, hook|wparam|lparam, VK_LMENU, LLKHF_UP|LLKHF_EXTENDED},
609         {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP|KF_EXTENDED},
610         {WM_SYSCOMMAND}, {0}}},
611     /* RMENU | KEYEVENTF_EXTENDEDKEY == RMENU */
612     /* 42 */
613     {VK_RMENU, KEYEVENTF_EXTENDEDKEY, 0,
614         {{VK_MENU, 0x00}, {VK_RMENU, 0x00}, {VK_CONTROL, 0x00, 1}, {VK_LCONTROL, 0x01, 1}, {0}},
615         {{WM_SYSKEYDOWN, hook|wparam|lparam|optional, VK_LCONTROL, 0},
616         {WM_SYSKEYDOWN, hook|wparam|lparam, VK_RMENU, LLKHF_EXTENDED},
617         {WM_KEYDOWN, wparam|lparam|optional, VK_CONTROL, 0},
618         {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, KF_EXTENDED}, {0}}},
619     {VK_RMENU, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 1,
620         {{VK_MENU, 0x80}, {VK_RMENU, 0x80}, {VK_CONTROL, 0x81, 1}, {VK_LCONTROL, 0x80, 1}, {0}},
621         {{WM_KEYUP, hook|wparam|lparam|optional, VK_LCONTROL, LLKHF_UP},
622         {WM_KEYUP, hook|wparam|lparam, VK_RMENU, LLKHF_UP|LLKHF_EXTENDED},
623         {WM_SYSKEYUP, wparam|lparam|optional, VK_CONTROL, KF_UP},
624         {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP|KF_EXTENDED},
625         {WM_SYSCOMMAND, optional}, {0}}},
626     /* MENU == LMENU */
627     /* 44 */
628     {VK_MENU, 0, 0,
629         {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {0}},
630         {{WM_SYSKEYDOWN, hook/*|wparam, VK_MENU*/},
631         {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0}, {0}}},
632     {VK_MENU, KEYEVENTF_KEYUP, 1,
633         {{VK_MENU, 0x80}, {VK_LMENU, 0x80}, {0}},
634         {{WM_KEYUP, hook/*|wparam, VK_MENU*/},
635         {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP},
636         {WM_SYSCOMMAND}, {0}}},
637     /* MENU | KEYEVENTF_EXTENDEDKEY == RMENU */
638     /* 46 */
639     {VK_MENU, KEYEVENTF_EXTENDEDKEY, 0,
640         {{VK_MENU, 0x00}, {VK_RMENU, 0x00}, {VK_CONTROL, 0x00, 1}, {VK_LCONTROL, 0x01, 1}, {0}},
641         {{WM_SYSKEYDOWN, hook|wparam|lparam|optional, VK_CONTROL, 0},
642         {WM_SYSKEYDOWN, hook/*|wparam*/|lparam, VK_MENU, LLKHF_EXTENDED},
643         {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, KF_EXTENDED}, {0}}},
644     {VK_MENU, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 1,
645         {{VK_MENU, 0x80}, {VK_RMENU, 0x80}, {VK_CONTROL, 0x81, 1}, {VK_LCONTROL, 0x80, 1}, {0}},
646         {{WM_KEYUP, hook|wparam|lparam|optional, VK_CONTROL, LLKHF_UP},
647         {WM_KEYUP, hook/*|wparam*/|lparam, VK_MENU, LLKHF_UP|LLKHF_EXTENDED},
648         {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP|KF_EXTENDED},
649         {WM_SYSCOMMAND}, {0}}},
650
651     /* test LSHIFT & RSHIFT */
652     /* 48 */
653     {VK_LSHIFT, 0, 0,
654         {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00}, {0}},
655         {{WM_KEYDOWN, hook|wparam|lparam, VK_LSHIFT, 0},
656         {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}},
657     {VK_RSHIFT, KEYEVENTF_EXTENDEDKEY, 0,
658         {{VK_RSHIFT, 0x00}, {0}},
659         {{WM_KEYDOWN, hook|wparam|lparam, VK_RSHIFT, LLKHF_EXTENDED},
660         {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}},
661     {VK_RSHIFT, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 0,
662         {{VK_RSHIFT, 0x80}, {0}},
663         {{WM_KEYUP, hook|wparam|lparam, VK_RSHIFT, LLKHF_UP|LLKHF_EXTENDED},
664         {WM_KEYUP, optional}, {0}}},
665     {VK_LSHIFT, KEYEVENTF_KEYUP, 0,
666         {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80}, {0}},
667         {{WM_KEYUP, hook|wparam, VK_LSHIFT},
668         {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}},
669
670     {0, 0, 0, {{0}}, {{0}}} /* end */
671 };
672
673 static struct message sent_messages[MAXKEYMESSAGES];
674 static UINT sent_messages_cnt;
675
676 /* Verify that only specified key state transitions occur */
677 static void compare_and_check(int id, BYTE *ks1, BYTE *ks2, struct sendinput_test_s *test)
678 {
679     int i, failcount = 0;
680     struct transition_s *t = test->expected_transitions;
681     UINT actual_cnt = 0;
682     const struct message *expected = test->expected_messages;
683
684     while (t->wVk) {
685         int matched = ((ks1[t->wVk]&0x80) == (t->before_state&0x80)
686                        && (ks2[t->wVk]&0x80) == (~t->before_state&0x80));
687
688         if (!matched && !t->optional && test->_todo_wine)
689         {
690             failcount++;
691             todo_wine {
692                 ok(matched, "%2d (%x/%x): %02x from %02x -> %02x "
693                    "instead of %02x -> %02x\n", id, test->wVk, test->dwFlags,
694                    t->wVk, ks1[t->wVk]&0x80, ks2[t->wVk]&0x80, t->before_state,
695                    ~t->before_state&0x80);
696             }
697         } else {
698             ok(matched || t->optional, "%2d (%x/%x): %02x from %02x -> %02x "
699                "instead of %02x -> %02x\n", id, test->wVk, test->dwFlags,
700                t->wVk, ks1[t->wVk]&0x80, ks2[t->wVk]&0x80, t->before_state,
701                ~t->before_state&0x80);
702         }
703         ks2[t->wVk] = ks1[t->wVk]; /* clear the match */
704         t++;
705     }
706     for (i = 0; i < 256; i++)
707         if (ks2[i] != ks1[i] && test->_todo_wine)
708         {
709             failcount++;
710             todo_wine
711                 ok(FALSE, "%2d (%x/%x): %02x from %02x -> %02x unexpected\n",
712                    id, test->wVk, test->dwFlags, i, ks1[i], ks2[i]);
713         }
714         else
715             ok(ks2[i] == ks1[i], "%2d (%x/%x): %02x from %02x -> %02x unexpected\n",
716                id, test->wVk, test->dwFlags, i, ks1[i], ks2[i]);
717
718     while (expected->message && actual_cnt < sent_messages_cnt)
719     {
720         const struct message *actual = &sent_messages[actual_cnt];
721
722         if (expected->message == actual->message)
723         {
724             if (expected->flags & wparam)
725             {
726                 if ((expected->flags & optional) && (expected->wParam != actual->wParam))
727                 {
728                     expected++;
729                     continue;
730                 }
731                 if (expected->wParam != actual->wParam && test->_todo_wine)
732                 {
733                     failcount++;
734                     todo_wine
735                         ok(FALSE, "%2d (%x/%x): in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
736                            id, test->wVk, test->dwFlags, expected->message, expected->wParam, actual->wParam);
737                 }
738                 else
739                     ok(expected->wParam == actual->wParam,
740                        "%2d (%x/%x): in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
741                        id, test->wVk, test->dwFlags, expected->message, expected->wParam, actual->wParam);
742             }
743             if (expected->flags & lparam)
744             {
745                 if (expected->lParam != actual->lParam && test->_todo_wine)
746                 {
747                     failcount++;
748                     todo_wine
749                         ok(FALSE, "%2d (%x/%x): in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
750                            id, test->wVk, test->dwFlags, expected->message, expected->lParam, actual->lParam);
751                 }
752                 else
753                     ok(expected->lParam == actual->lParam,
754                        "%2d (%x/%x): in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
755                        id, test->wVk, test->dwFlags, expected->message, expected->lParam, actual->lParam);
756             }
757             ok((expected->flags & hook) == (actual->flags & hook),
758                "%2d (%x/%x): the msg 0x%04x should have been sent by a hook\n",
759                id, test->wVk, test->dwFlags, expected->message);
760
761         }
762         else if (expected->flags & optional)
763         {
764             expected++;
765             continue;
766         }
767         /* NT4 doesn't send SYSKEYDOWN/UP to hooks, only KEYDOWN/UP */
768         else if ((expected->flags & hook) &&
769                  (expected->message == WM_SYSKEYDOWN || expected->message == WM_SYSKEYUP) &&
770                  (actual->message == expected->message - 4))
771         {
772             ok((expected->flags & hook) == (actual->flags & hook),
773                "%2d (%x/%x): the msg 0x%04x should have been sent by a hook\n",
774                id, test->wVk, test->dwFlags, expected->message);
775         }
776         /* For VK_RMENU, at least localized Win2k/XP sends KEYDOWN/UP
777          * instead of SYSKEYDOWN/UP to the WNDPROC */
778         else if (test->wVk == VK_RMENU && !(expected->flags & hook) &&
779                  (expected->message == WM_SYSKEYDOWN || expected->message == WM_SYSKEYUP) &&
780                  (actual->message == expected->message - 4))
781         {
782             ok(expected->wParam == actual->wParam && expected->lParam == actual->lParam,
783                "%2d (%x/%x): the msg 0x%04x was expected, but got msg 0x%04x instead\n",
784                id, test->wVk, test->dwFlags, expected->message, actual->message);
785         }
786         else if (test->_todo_wine)
787         {
788             failcount++;
789             todo_wine
790             ok(FALSE,
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
795             ok(FALSE,
796                "%2d (%x/%x): the msg 0x%04x was expected, but got msg 0x%04x instead\n",
797                id, test->wVk, test->dwFlags, expected->message, actual->message);
798
799         actual_cnt++;
800         expected++;
801     }
802     /* skip all optional trailing messages */
803     while (expected->message && (expected->flags & optional))
804         expected++;
805
806
807     if (expected->message || actual_cnt < sent_messages_cnt)
808     {
809         if (test->_todo_wine)
810         {
811             failcount++;
812             todo_wine
813                 ok(FALSE, "%2d (%x/%x): the msg sequence is not complete: expected %04x - actual %04x\n",
814                    id, test->wVk, test->dwFlags, expected->message, sent_messages[actual_cnt].message);
815         }
816         else
817             ok(FALSE, "%2d (%x/%x): the msg sequence is not complete: expected %04x - actual %04x\n",
818                id, test->wVk, test->dwFlags, expected->message, sent_messages[actual_cnt].message);
819     }
820
821     if( test->_todo_wine && !failcount) /* succeeded yet marked todo */
822         todo_wine
823             ok(TRUE, "%2d (%x/%x): marked \"todo_wine\" but succeeds\n", id, test->wVk, test->dwFlags);
824
825     sent_messages_cnt = 0;
826 }
827
828 /* WndProc2 checks that we get at least the messages specified */
829 static LRESULT CALLBACK WndProc2(HWND hWnd, UINT Msg, WPARAM wParam,
830                                    LPARAM lParam)
831 {
832     if (winetest_debug > 1) trace("MSG:  %8x W:%8lx L:%8lx\n", Msg, wParam, lParam);
833
834     if (Msg != WM_PAINT &&
835         Msg != WM_NCPAINT &&
836         Msg != WM_SYNCPAINT &&
837         Msg != WM_ERASEBKGND &&
838         Msg != WM_NCHITTEST &&
839         Msg != WM_GETTEXT &&
840         Msg != WM_GETICON &&
841         Msg != WM_IME_SELECT &&
842         Msg != WM_DEVICECHANGE &&
843         Msg != WM_TIMECHANGE)
844     {
845         ok(sent_messages_cnt < MAXKEYMESSAGES, "Too many messages\n");
846         if (sent_messages_cnt < MAXKEYMESSAGES)
847         {
848             sent_messages[sent_messages_cnt].message = Msg;
849             sent_messages[sent_messages_cnt].flags = 0;
850             sent_messages[sent_messages_cnt].wParam = wParam;
851             sent_messages[sent_messages_cnt++].lParam = HIWORD(lParam) & (KF_UP|KF_EXTENDED);
852         }
853     }
854     return DefWindowProc(hWnd, Msg, wParam, lParam);
855 }
856
857 static LRESULT CALLBACK hook_proc(int code, WPARAM wparam, LPARAM lparam)
858 {
859     KBDLLHOOKSTRUCT *hook_info = (KBDLLHOOKSTRUCT *)lparam;
860
861     if (code == HC_ACTION)
862     {
863         ok(sent_messages_cnt < MAXKEYMESSAGES, "Too many messages\n");
864         if (sent_messages_cnt < MAXKEYMESSAGES)
865         {
866             sent_messages[sent_messages_cnt].message = wparam;
867             sent_messages[sent_messages_cnt].flags = hook;
868             sent_messages[sent_messages_cnt].wParam = hook_info->vkCode;
869             sent_messages[sent_messages_cnt++].lParam = hook_info->flags & (LLKHF_UP|LLKHF_EXTENDED);
870         }
871
872 if(0) /* For some reason not stable on Wine */
873 {
874         if (wparam == WM_KEYDOWN || wparam == WM_SYSKEYDOWN)
875             ok(!(GetAsyncKeyState(hook_info->vkCode) & 0x8000), "key %x should be up\n", hook_info->vkCode);
876         else if (wparam == WM_KEYUP || wparam == WM_SYSKEYUP)
877             ok(GetAsyncKeyState(hook_info->vkCode) & 0x8000, "key %x should be down\n", hook_info->vkCode);
878 }
879
880         if (winetest_debug > 1)
881             trace("Hook:   w=%lx vk:%8x sc:%8x fl:%8x %lx\n", wparam,
882                   hook_info->vkCode, hook_info->scanCode, hook_info->flags, hook_info->dwExtraInfo);
883     }
884     return CallNextHookEx( 0, code, wparam, lparam );
885 }
886 static void test_Input_blackbox(void)
887 {
888     TEST_INPUT i;
889     int ii;
890     BYTE ks1[256], ks2[256];
891     LONG_PTR prevWndProc;
892     HWND window;
893     HHOOK hook;
894
895     if (GetKeyboardLayout(0) != (HKL)(ULONG_PTR)0x04090409)
896     {
897         skip("Skipping Input_blackbox test on non-US keyboard\n");
898         return;
899     }
900     window = CreateWindow("Static", NULL, WS_POPUP|WS_HSCROLL|WS_VSCROLL
901         |WS_VISIBLE, 0, 0, 200, 60, NULL, NULL,
902         NULL, NULL);
903     ok(window != NULL, "error: %d\n", (int) GetLastError());
904     SetWindowPos( window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
905     SetForegroundWindow( window );
906
907     hook = SetWindowsHookExA(WH_KEYBOARD_LL, hook_proc, GetModuleHandleA( NULL ), 0);
908
909     /* must process all initial messages, otherwise X11DRV_KeymapNotify unsets
910      * key state set by SendInput(). */
911     empty_message_queue();
912
913     prevWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, (LONG_PTR) WndProc2);
914     ok(prevWndProc != 0 || (prevWndProc == 0 && GetLastError() == 0),
915        "error: %d\n", (int) GetLastError());
916
917     i.type = INPUT_KEYBOARD;
918     i.u.ki.time = 0;
919     i.u.ki.dwExtraInfo = 0;
920
921     for (ii = 0; ii < sizeof(sendinput_test)/sizeof(struct sendinput_test_s)-1;
922          ii++) {
923         GetKeyboardState(ks1);
924         i.u.ki.wScan = ii+1 /* useful for debugging */;
925         i.u.ki.dwFlags = sendinput_test[ii].dwFlags;
926         i.u.ki.wVk = sendinput_test[ii].wVk;
927         pSendInput(1, (INPUT*)&i, sizeof(TEST_INPUT));
928         empty_message_queue();
929         GetKeyboardState(ks2);
930         if (!ii && sent_messages_cnt <= 1 && !memcmp( ks1, ks2, sizeof(ks1) ))
931         {
932             win_skip( "window doesn't receive the queued input\n" );
933             /* release the key */
934             i.u.ki.dwFlags |= KEYEVENTF_KEYUP;
935             pSendInput(1, (INPUT*)&i, sizeof(TEST_INPUT));
936             break;
937         }
938         compare_and_check(ii, ks1, ks2, &sendinput_test[ii]);
939     }
940
941     empty_message_queue();
942     DestroyWindow(window);
943     UnhookWindowsHookEx(hook);
944 }
945
946 static void reset_key_status(void)
947 {
948     key_status.last_key_down = -1;
949     key_status.last_key_up = -1;
950     key_status.last_syskey_down = -1;
951     key_status.last_syskey_up = -1;
952     key_status.last_char = -1;
953     key_status.last_syschar = -1;
954     key_status.last_hook_down = -1;
955     key_status.last_hook_up = -1;
956     key_status.last_hook_syskey_down = -1;
957     key_status.last_hook_syskey_up = -1;
958     key_status.expect_alt = FALSE;
959     key_status.sendinput_broken = FALSE;
960 }
961
962 static void test_unicode_keys(HWND hwnd, HHOOK hook)
963 {
964     TEST_INPUT inputs[2];
965     MSG msg;
966
967     /* init input data that never changes */
968     inputs[1].type = inputs[0].type = INPUT_KEYBOARD;
969     inputs[1].u.ki.dwExtraInfo = inputs[0].u.ki.dwExtraInfo = 0;
970     inputs[1].u.ki.time = inputs[0].u.ki.time = 0;
971
972     /* pressing & releasing a single unicode character */
973     inputs[0].u.ki.wVk = 0;
974     inputs[0].u.ki.wScan = 0x3c0;
975     inputs[0].u.ki.dwFlags = KEYEVENTF_UNICODE;
976
977     reset_key_status();
978     pSendInput(1, (INPUT*)inputs, sizeof(INPUT));
979     while(PeekMessageW(&msg, hwnd, 0, 0, PM_REMOVE)){
980         if(msg.message == WM_KEYDOWN && msg.wParam == VK_PACKET){
981             TranslateMessage(&msg);
982         }
983         DispatchMessageW(&msg);
984     }
985     if(!key_status.sendinput_broken){
986         ok(key_status.last_key_down == VK_PACKET,
987             "Last keydown msg should have been VK_PACKET[0x%04x] (was: 0x%x)\n", VK_PACKET, key_status.last_key_down);
988         ok(key_status.last_char == 0x3c0,
989             "Last char msg wparam should have been 0x3c0 (was: 0x%x)\n", key_status.last_char);
990         if(hook)
991             ok(key_status.last_hook_down == 0x3c0,
992                 "Last hookdown msg should have been 0x3c0, was: 0x%x\n", key_status.last_hook_down);
993     }
994
995     inputs[1].u.ki.wVk = 0;
996     inputs[1].u.ki.wScan = 0x3c0;
997     inputs[1].u.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
998
999     reset_key_status();
1000     pSendInput(1, (INPUT*)(inputs+1), sizeof(INPUT));
1001     while(PeekMessageW(&msg, hwnd, 0, 0, PM_REMOVE)){
1002         if(msg.message == WM_KEYDOWN && msg.wParam == VK_PACKET){
1003             TranslateMessage(&msg);
1004         }
1005         DispatchMessageW(&msg);
1006     }
1007     if(!key_status.sendinput_broken){
1008         ok(key_status.last_key_up == VK_PACKET,
1009             "Last keyup msg should have been VK_PACKET[0x%04x] (was: 0x%x)\n", VK_PACKET, key_status.last_key_up);
1010         if(hook)
1011             ok(key_status.last_hook_up == 0x3c0,
1012                 "Last hookup msg should have been 0x3c0, was: 0x%x\n", key_status.last_hook_up);
1013     }
1014
1015     /* holding alt, pressing & releasing a unicode character, releasing alt */
1016     inputs[0].u.ki.wVk = VK_LMENU;
1017     inputs[0].u.ki.wScan = 0;
1018     inputs[0].u.ki.dwFlags = 0;
1019
1020     inputs[1].u.ki.wVk = 0;
1021     inputs[1].u.ki.wScan = 0x3041;
1022     inputs[1].u.ki.dwFlags = KEYEVENTF_UNICODE;
1023
1024     reset_key_status();
1025     key_status.expect_alt = TRUE;
1026     pSendInput(2, (INPUT*)inputs, sizeof(INPUT));
1027     while(PeekMessageW(&msg, hwnd, 0, 0, PM_REMOVE)){
1028         if(msg.message == WM_SYSKEYDOWN && msg.wParam == VK_PACKET){
1029             TranslateMessage(&msg);
1030         }
1031         DispatchMessageW(&msg);
1032     }
1033     if(!key_status.sendinput_broken){
1034         ok(key_status.last_syskey_down == VK_PACKET,
1035             "Last syskeydown msg should have been VK_PACKET[0x%04x] (was: 0x%x)\n", VK_PACKET, key_status.last_syskey_down);
1036         ok(key_status.last_syschar == 0x3041,
1037             "Last syschar msg should have been 0x3041 (was: 0x%x)\n", key_status.last_syschar);
1038         if(hook)
1039             ok(key_status.last_hook_syskey_down == 0x3041,
1040                 "Last hooksysdown msg should have been 0x3041, was: 0x%x\n", key_status.last_hook_syskey_down);
1041     }
1042
1043     inputs[1].u.ki.wVk = 0;
1044     inputs[1].u.ki.wScan = 0x3041;
1045     inputs[1].u.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
1046
1047     inputs[0].u.ki.wVk = VK_LMENU;
1048     inputs[0].u.ki.wScan = 0;
1049     inputs[0].u.ki.dwFlags = KEYEVENTF_KEYUP;
1050
1051     reset_key_status();
1052     key_status.expect_alt = TRUE;
1053     pSendInput(2, (INPUT*)inputs, sizeof(INPUT));
1054     while(PeekMessageW(&msg, hwnd, 0, 0, PM_REMOVE)){
1055         if(msg.message == WM_SYSKEYDOWN && msg.wParam == VK_PACKET){
1056             TranslateMessage(&msg);
1057         }
1058         DispatchMessageW(&msg);
1059     }
1060     if(!key_status.sendinput_broken){
1061         ok(key_status.last_key_up == VK_PACKET,
1062             "Last keyup msg should have been VK_PACKET[0x%04x] (was: 0x%x)\n", VK_PACKET, key_status.last_key_up);
1063         if(hook)
1064             ok(key_status.last_hook_up == 0x3041,
1065                 "Last hook up msg should have been 0x3041, was: 0x%x\n", key_status.last_hook_up);
1066     }
1067 }
1068
1069 static LRESULT CALLBACK unicode_wnd_proc( HWND hWnd, UINT msg, WPARAM wParam,
1070         LPARAM lParam )
1071 {
1072     switch(msg){
1073     case WM_KEYDOWN:
1074         key_status.last_key_down = wParam;
1075         break;
1076     case WM_SYSKEYDOWN:
1077         key_status.last_syskey_down = wParam;
1078         break;
1079     case WM_KEYUP:
1080         key_status.last_key_up = wParam;
1081         break;
1082     case WM_SYSKEYUP:
1083         key_status.last_syskey_up = wParam;
1084         break;
1085     case WM_CHAR:
1086         key_status.last_char = wParam;
1087         break;
1088     case WM_SYSCHAR:
1089         key_status.last_syschar = wParam;
1090         break;
1091     }
1092     return DefWindowProcW(hWnd, msg, wParam, lParam);
1093 }
1094
1095 static LRESULT CALLBACK llkbd_unicode_hook(int nCode, WPARAM wParam, LPARAM lParam)
1096 {
1097     if(nCode == HC_ACTION){
1098         LPKBDLLHOOKSTRUCT info = (LPKBDLLHOOKSTRUCT)lParam;
1099         if(!info->vkCode){
1100             key_status.sendinput_broken = TRUE;
1101             win_skip("SendInput doesn't support unicode on this platform\n");
1102         }else{
1103             if(key_status.expect_alt){
1104                 ok(info->vkCode == VK_LMENU, "vkCode should have been VK_LMENU[0x%04x], was: 0x%x\n", VK_LMENU, info->vkCode);
1105                 key_status.expect_alt = FALSE;
1106             }else
1107                 ok(info->vkCode == VK_PACKET, "vkCode should have been VK_PACKET[0x%04x], was: 0x%x\n", VK_PACKET, info->vkCode);
1108         }
1109         switch(wParam){
1110         case WM_KEYDOWN:
1111             key_status.last_hook_down = info->scanCode;
1112             break;
1113         case WM_KEYUP:
1114             key_status.last_hook_up = info->scanCode;
1115             break;
1116         case WM_SYSKEYDOWN:
1117             key_status.last_hook_syskey_down = info->scanCode;
1118             break;
1119         case WM_SYSKEYUP:
1120             key_status.last_hook_syskey_up = info->scanCode;
1121             break;
1122         }
1123     }
1124     return CallNextHookEx(NULL, nCode, wParam, lParam);
1125 }
1126
1127 static void test_Input_unicode(void)
1128 {
1129     WCHAR classNameW[] = {'I','n','p','u','t','U','n','i','c','o','d','e',
1130         'K','e','y','T','e','s','t','C','l','a','s','s',0};
1131     WCHAR windowNameW[] = {'I','n','p','u','t','U','n','i','c','o','d','e',
1132         'K','e','y','T','e','s','t',0};
1133     MSG msg;
1134     WNDCLASSW wclass;
1135     HANDLE hInstance = GetModuleHandleW(NULL);
1136     HHOOK hook;
1137
1138     wclass.lpszClassName = classNameW;
1139     wclass.style         = CS_HREDRAW | CS_VREDRAW;
1140     wclass.lpfnWndProc   = unicode_wnd_proc;
1141     wclass.hInstance     = hInstance;
1142     wclass.hIcon         = LoadIcon(0, IDI_APPLICATION);
1143     wclass.hCursor       = LoadCursor( NULL, IDC_ARROW);
1144     wclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1145     wclass.lpszMenuName  = 0;
1146     wclass.cbClsExtra    = 0;
1147     wclass.cbWndExtra    = 0;
1148     if(!RegisterClassW(&wclass)){
1149         win_skip("Unicode functions not supported\n");
1150         return;
1151     }
1152     /* create the test window that will receive the keystrokes */
1153     hWndTest = CreateWindowW(wclass.lpszClassName, windowNameW,
1154                              WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 100, 100,
1155                              NULL, NULL, hInstance, NULL);
1156
1157     assert(hWndTest);
1158     assert(IsWindowUnicode(hWndTest));
1159
1160     hook = SetWindowsHookExW(WH_KEYBOARD_LL, llkbd_unicode_hook, GetModuleHandleW(NULL), 0);
1161     if(!hook)
1162         win_skip("unable to set WH_KEYBOARD_LL hook\n");
1163
1164     ShowWindow(hWndTest, SW_SHOW);
1165     SetWindowPos(hWndTest, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1166     SetForegroundWindow(hWndTest);
1167     UpdateWindow(hWndTest);
1168
1169     /* flush pending messages */
1170     while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageW(&msg);
1171
1172     SetFocus(hWndTest);
1173
1174     test_unicode_keys(hWndTest, hook);
1175
1176     if(hook)
1177         UnhookWindowsHookEx(hook);
1178     DestroyWindow(hWndTest);
1179 }
1180
1181 static void test_keynames(void)
1182 {
1183     int i, len;
1184     char buff[256];
1185
1186     for (i = 0; i < 512; i++)
1187     {
1188         strcpy(buff, "----");
1189         len = GetKeyNameTextA(i << 16, buff, sizeof(buff));
1190         ok(len || !buff[0], "%d: Buffer is not zeroed\n", i);
1191     }
1192 }
1193
1194 static POINT pt_old, pt_new;
1195 static BOOL clipped;
1196 #define STEP 3
1197
1198 static LRESULT CALLBACK hook_proc1( int code, WPARAM wparam, LPARAM lparam )
1199 {
1200     MSLLHOOKSTRUCT *hook = (MSLLHOOKSTRUCT *)lparam;
1201     POINT pt, pt1;
1202
1203     if (code == HC_ACTION)
1204     {
1205         /* This is our new cursor position */
1206         pt_new = hook->pt;
1207         /* Should return previous position */
1208         GetCursorPos(&pt);
1209         ok(pt.x == pt_old.x && pt.y == pt_old.y, "GetCursorPos: (%d,%d)\n", pt.x, pt.y);
1210
1211         /* Should set new position until hook chain is finished. */
1212         pt.x = pt_old.x + STEP;
1213         pt.y = pt_old.y + STEP;
1214         SetCursorPos(pt.x, pt.y);
1215         GetCursorPos(&pt1);
1216         if (clipped)
1217             ok(pt1.x == pt_old.x && pt1.y == pt_old.y, "Wrong set pos: (%d,%d)\n", pt1.x, pt1.y);
1218         else
1219             ok(pt1.x == pt.x && pt1.y == pt.y, "Wrong set pos: (%d,%d)\n", pt1.x, pt1.y);
1220     }
1221     return CallNextHookEx( 0, code, wparam, lparam );
1222 }
1223
1224 static LRESULT CALLBACK hook_proc2( int code, WPARAM wparam, LPARAM lparam )
1225 {
1226     MSLLHOOKSTRUCT *hook = (MSLLHOOKSTRUCT *)lparam;
1227     POINT pt;
1228
1229     if (code == HC_ACTION)
1230     {
1231         ok(hook->pt.x == pt_new.x && hook->pt.y == pt_new.y,
1232            "Wrong hook coords: (%d %d) != (%d,%d)\n", hook->pt.x, hook->pt.y, pt_new.x, pt_new.y);
1233
1234         /* Should match position set above */
1235         GetCursorPos(&pt);
1236         if (clipped)
1237             ok(pt.x == pt_old.x && pt.y == pt_old.y, "GetCursorPos: (%d,%d)\n", pt.x, pt.y);
1238         else
1239             ok(pt.x == pt_old.x +STEP && pt.y == pt_old.y +STEP, "GetCursorPos: (%d,%d)\n", pt.x, pt.y);
1240     }
1241     return CallNextHookEx( 0, code, wparam, lparam );
1242 }
1243
1244 static void test_mouse_ll_hook(void)
1245 {
1246     HWND hwnd;
1247     HHOOK hook1, hook2;
1248     POINT pt_org, pt;
1249     RECT rc;
1250
1251     GetCursorPos(&pt_org);
1252     hwnd = CreateWindow("static", "Title", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1253                         10, 10, 200, 200, NULL, NULL, NULL, NULL);
1254     SetCursorPos(100, 100);
1255
1256     if (!(hook2 = SetWindowsHookExA(WH_MOUSE_LL, hook_proc2, GetModuleHandleA(0), 0)))
1257     {
1258         win_skip( "cannot set MOUSE_LL hook\n" );
1259         goto done;
1260     }
1261     hook1 = SetWindowsHookExA(WH_MOUSE_LL, hook_proc1, GetModuleHandleA(0), 0);
1262
1263     GetCursorPos(&pt_old);
1264     mouse_event(MOUSEEVENTF_MOVE, -STEP,  0, 0, 0);
1265     GetCursorPos(&pt_old);
1266     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);
1267     mouse_event(MOUSEEVENTF_MOVE, +STEP,  0, 0, 0);
1268     GetCursorPos(&pt_old);
1269     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);
1270     mouse_event(MOUSEEVENTF_MOVE,  0, -STEP, 0, 0);
1271     GetCursorPos(&pt_old);
1272     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);
1273     mouse_event(MOUSEEVENTF_MOVE,  0, +STEP, 0, 0);
1274     GetCursorPos(&pt_old);
1275     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);
1276
1277     SetRect(&rc, 50, 50, 151, 151);
1278     ClipCursor(&rc);
1279     clipped = TRUE;
1280
1281     SetCursorPos(40, 40);
1282     GetCursorPos(&pt_old);
1283     ok(pt_old.x == 50 && pt_old.y == 50, "Wrong new pos: (%d,%d)\n", pt_new.x, pt_new.y);
1284     SetCursorPos(160, 160);
1285     GetCursorPos(&pt_old);
1286     ok(pt_old.x == 150 && pt_old.y == 150, "Wrong new pos: (%d,%d)\n", pt_new.x, pt_new.y);
1287     mouse_event(MOUSEEVENTF_MOVE, +STEP, +STEP, 0, 0);
1288     GetCursorPos(&pt_old);
1289     ok(pt_old.x == 150 && pt_old.y == 150, "Wrong new pos: (%d,%d)\n", pt_new.x, pt_new.y);
1290
1291     clipped = FALSE;
1292     pt_new.x = pt_new.y = 150;
1293     ClipCursor(NULL);
1294     UnhookWindowsHookEx(hook1);
1295
1296     /* Now check that mouse buttons do not change mouse position
1297        if we don't have MOUSEEVENTF_MOVE flag specified. */
1298
1299     /* We reusing the same hook callback, so make it happy */
1300     pt_old.x = pt_new.x - STEP;
1301     pt_old.y = pt_new.y - STEP;
1302     mouse_event(MOUSEEVENTF_LEFTUP, 123, 456, 0, 0);
1303     GetCursorPos(&pt);
1304     ok(pt.x == pt_new.x && pt.y == pt_new.y, "Position changed: (%d,%d)\n", pt.x, pt.y);
1305     mouse_event(MOUSEEVENTF_RIGHTUP, 456, 123, 0, 0);
1306     GetCursorPos(&pt);
1307     ok(pt.x == pt_new.x && pt.y == pt_new.y, "Position changed: (%d,%d)\n", pt.x, pt.y);
1308
1309     mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE, 123, 456, 0, 0);
1310     GetCursorPos(&pt);
1311     ok(pt.x == pt_new.x && pt.y == pt_new.y, "Position changed: (%d,%d)\n", pt.x, pt.y);
1312     mouse_event(MOUSEEVENTF_RIGHTUP | MOUSEEVENTF_ABSOLUTE, 456, 123, 0, 0);
1313     GetCursorPos(&pt);
1314     ok(pt.x == pt_new.x && pt.y == pt_new.y, "Position changed: (%d,%d)\n", pt.x, pt.y);
1315
1316     UnhookWindowsHookEx(hook2);
1317 done:
1318     DestroyWindow(hwnd);
1319     SetCursorPos(pt_org.x, pt_org.y);
1320 }
1321
1322 static void test_GetMouseMovePointsEx(void)
1323 {
1324 #define BUFLIM  64
1325 #define MYERROR 0xdeadbeef
1326     int count, retval;
1327     MOUSEMOVEPOINT in;
1328     MOUSEMOVEPOINT out[200];
1329     POINT point;
1330
1331     /* Get a valid content for the input struct */
1332     if(!GetCursorPos(&point)) {
1333         skip("GetCursorPos() failed with error %u\n", GetLastError());
1334         return;
1335     }
1336     memset(&in, 0, sizeof(MOUSEMOVEPOINT));
1337     in.x = point.x;
1338     in.y = point.y;
1339
1340     /* test first parameter
1341      * everything different than sizeof(MOUSEMOVEPOINT)
1342      * is expected to fail with ERROR_INVALID_PARAMETER
1343      */
1344     SetLastError(MYERROR);
1345     retval = pGetMouseMovePointsEx(0, &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1346     if (retval == ERROR_INVALID_PARAMETER)
1347     {
1348         win_skip( "GetMouseMovePointsEx broken on WinME\n" );
1349         return;
1350     }
1351     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1352     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1353        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1354
1355     SetLastError(MYERROR);
1356     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)-1, &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1357     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1358     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1359        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1360
1361     SetLastError(MYERROR);
1362     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)+1, &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1363     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1364     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1365        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1366
1367     /* test second and third parameter
1368      */
1369     SetLastError(MYERROR);
1370     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), NULL, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1371     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1372     ok(GetLastError() == ERROR_NOACCESS || GetLastError() == MYERROR,
1373        "expected error ERROR_NOACCESS, got %u\n", GetLastError());
1374
1375     SetLastError(MYERROR);
1376     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, NULL, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1377     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1378     ok(ERROR_NOACCESS == GetLastError(),
1379        "expected error ERROR_NOACCESS, got %u\n", GetLastError());
1380
1381     SetLastError(MYERROR);
1382     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), NULL, NULL, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1383     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1384     ok(ERROR_NOACCESS == GetLastError(),
1385        "expected error ERROR_NOACCESS, got %u\n", GetLastError());
1386
1387     SetLastError(MYERROR);
1388     count = 0;
1389     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, NULL, count, GMMP_USE_DISPLAY_POINTS);
1390     if (retval == -1)
1391         ok(GetLastError() == ERROR_POINT_NOT_FOUND, "unexpected error %u\n", GetLastError());
1392     else
1393         ok(retval == count, "expected GetMouseMovePointsEx to succeed, got %d\n", retval);
1394
1395     /* test fourth parameter
1396      * a value higher than 64 is expected to fail with ERROR_INVALID_PARAMETER
1397      */
1398     SetLastError(MYERROR);
1399     count = -1;
1400     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, out, count, GMMP_USE_DISPLAY_POINTS);
1401     ok(retval == count, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1402     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1403        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1404
1405     SetLastError(MYERROR);
1406     count = 0;
1407     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, out, count, GMMP_USE_DISPLAY_POINTS);
1408     if (retval == -1)
1409         ok(GetLastError() == ERROR_POINT_NOT_FOUND, "unexpected error %u\n", GetLastError());
1410     else
1411         ok(retval == count, "expected GetMouseMovePointsEx to succeed, got %d\n", retval);
1412
1413     SetLastError(MYERROR);
1414     count = BUFLIM;
1415     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, out, count, GMMP_USE_DISPLAY_POINTS);
1416     if (retval == -1)
1417         ok(GetLastError() == ERROR_POINT_NOT_FOUND, "unexpected error %u\n", GetLastError());
1418     else
1419         ok((0 <= retval) && (retval <= count), "expected GetMouseMovePointsEx to succeed, got %d\n", retval);
1420
1421     SetLastError(MYERROR);
1422     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, out, BUFLIM+1, GMMP_USE_DISPLAY_POINTS);
1423     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1424     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1425        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1426
1427     /* it was not possible to force an error with the fifth parameter on win2k */
1428
1429     /* test combinations of wrong parameters to see which error wins */
1430     SetLastError(MYERROR);
1431     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)-1, NULL, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1432     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1433     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1434        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1435
1436     SetLastError(MYERROR);
1437     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)-1, &in, NULL, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1438     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1439     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1440        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1441
1442     SetLastError(MYERROR);
1443     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), NULL, out, BUFLIM+1, GMMP_USE_DISPLAY_POINTS);
1444     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1445     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1446        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1447
1448     SetLastError(MYERROR);
1449     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, NULL, BUFLIM+1, GMMP_USE_DISPLAY_POINTS);
1450     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1451     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1452        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1453
1454 #undef BUFLIM
1455 #undef MYERROR
1456 }
1457
1458 static void test_key_map(void)
1459 {
1460     HKL kl = GetKeyboardLayout(0);
1461     UINT kL, kR, s, sL;
1462     int i;
1463     static const UINT numpad_collisions[][2] = {
1464         { VK_NUMPAD0, VK_INSERT },
1465         { VK_NUMPAD1, VK_END },
1466         { VK_NUMPAD2, VK_DOWN },
1467         { VK_NUMPAD3, VK_NEXT },
1468         { VK_NUMPAD4, VK_LEFT },
1469         { VK_NUMPAD6, VK_RIGHT },
1470         { VK_NUMPAD7, VK_HOME },
1471         { VK_NUMPAD8, VK_UP },
1472         { VK_NUMPAD9, VK_PRIOR },
1473     };
1474
1475     s  = MapVirtualKeyEx(VK_SHIFT,  MAPVK_VK_TO_VSC, kl);
1476     ok(s != 0, "MapVirtualKeyEx(VK_SHIFT) should return non-zero\n");
1477     sL = MapVirtualKeyEx(VK_LSHIFT, MAPVK_VK_TO_VSC, kl);
1478     ok(s == sL || broken(sL == 0), /* win9x */
1479        "%x != %x\n", s, sL);
1480
1481     kL = MapVirtualKeyEx(0x2a, MAPVK_VSC_TO_VK, kl);
1482     ok(kL == VK_SHIFT, "Scan code -> vKey = %x (not VK_SHIFT)\n", kL);
1483     kR = MapVirtualKeyEx(0x36, MAPVK_VSC_TO_VK, kl);
1484     ok(kR == VK_SHIFT, "Scan code -> vKey = %x (not VK_SHIFT)\n", kR);
1485
1486     kL = MapVirtualKeyEx(0x2a, MAPVK_VSC_TO_VK_EX, kl);
1487     ok(kL == VK_LSHIFT || broken(kL == 0), /* win9x */
1488        "Scan code -> vKey = %x (not VK_LSHIFT)\n", kL);
1489     kR = MapVirtualKeyEx(0x36, MAPVK_VSC_TO_VK_EX, kl);
1490     ok(kR == VK_RSHIFT || broken(kR == 0), /* win9x */
1491        "Scan code -> vKey = %x (not VK_RSHIFT)\n", kR);
1492
1493     /* test that MAPVK_VSC_TO_VK prefers the non-numpad vkey if there's ambiguity */
1494     for (i = 0; i < sizeof(numpad_collisions)/sizeof(numpad_collisions[0]); i++)
1495     {
1496         UINT numpad_scan = MapVirtualKeyEx(numpad_collisions[i][0],  MAPVK_VK_TO_VSC, kl);
1497         UINT other_scan  = MapVirtualKeyEx(numpad_collisions[i][1],  MAPVK_VK_TO_VSC, kl);
1498
1499         /* do they really collide for this layout? */
1500         if (numpad_scan && other_scan == numpad_scan)
1501         {
1502             UINT vkey = MapVirtualKeyEx(numpad_scan, MAPVK_VSC_TO_VK, kl);
1503             ok(vkey != numpad_collisions[i][0],
1504                "Got numpad vKey %x for scan code %x when there was another choice\n",
1505                vkey, numpad_scan);
1506         }
1507     }
1508 }
1509
1510 static void test_ToUnicode(void)
1511 {
1512     WCHAR wStr[2];
1513     BYTE state[256];
1514     const BYTE SC_RETURN = 0x1c, SC_TAB = 0x0f;
1515     const BYTE HIGHEST_BIT = 0x80;
1516     int i, ret;
1517     for(i=0; i<256; i++)
1518         state[i]=0;
1519
1520     SetLastError(0xdeadbeef);
1521     ret = ToUnicode(VK_RETURN, SC_RETURN, state, wStr, 2, 0);
1522     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1523     {
1524         win_skip("ToUnicode is not implemented\n");
1525         return;
1526     }
1527
1528     ok(ret == 1, "ToUnicode for Return key didn't return 1 (was %i)\n", ret);
1529     if(ret == 1)
1530         ok(wStr[0]=='\r', "ToUnicode for CTRL + Return was %i (expected 13)\n", wStr[0]);
1531     state[VK_CONTROL] |= HIGHEST_BIT;
1532     state[VK_LCONTROL] |= HIGHEST_BIT;
1533
1534     ret = ToUnicode(VK_TAB, SC_TAB, state, wStr, 2, 0);
1535     ok(ret == 0, "ToUnicode for CTRL + Tab didn't return 0 (was %i)\n", ret);
1536
1537     ret = ToUnicode(VK_RETURN, SC_RETURN, state, wStr, 2, 0);
1538     ok(ret == 1, "ToUnicode for CTRL + Return didn't return 1 (was %i)\n", ret);
1539     if(ret == 1)
1540         ok(wStr[0]=='\n', "ToUnicode for CTRL + Return was %i (expected 10)\n", wStr[0]);
1541
1542     state[VK_SHIFT] |= HIGHEST_BIT;
1543     state[VK_LSHIFT] |= HIGHEST_BIT;
1544     ret = ToUnicode(VK_TAB, SC_TAB, state, wStr, 2, 0);
1545     ok(ret == 0, "ToUnicode for CTRL + SHIFT + Tab didn't return 0 (was %i)\n", ret);
1546     ret = ToUnicode(VK_RETURN, SC_RETURN, state, wStr, 2, 0);
1547     todo_wine ok(ret == 0, "ToUnicode for CTRL + SHIFT + Return didn't return 0 (was %i)\n", ret);
1548 }
1549
1550 static void test_get_async_key_state(void)
1551 {
1552     /* input value sanity checks */
1553     ok(0 == GetAsyncKeyState(1000000), "GetAsyncKeyState did not return 0\n");
1554     ok(0 == GetAsyncKeyState(-1000000), "GetAsyncKeyState did not return 0\n");
1555 }
1556
1557 static void test_keyboard_layout_name(void)
1558 {
1559     BOOL ret;
1560     char klid[KL_NAMELENGTH];
1561
1562     if (GetKeyboardLayout(0) != (HKL)(ULONG_PTR)0x04090409) return;
1563
1564     klid[0] = 0;
1565     ret = GetKeyboardLayoutNameA(klid);
1566     ok(ret, "GetKeyboardLayoutNameA failed %u\n", GetLastError());
1567     ok(!strcmp(klid, "00000409"), "expected 00000409, got %s\n", klid);
1568 }
1569
1570 START_TEST(input)
1571 {
1572     init_function_pointers();
1573
1574     if (pSendInput)
1575     {
1576         test_Input_blackbox();
1577         test_Input_whitebox();
1578         test_Input_unicode();
1579     }
1580     else win_skip("SendInput is not available\n");
1581
1582     test_keynames();
1583     test_mouse_ll_hook();
1584     test_key_map();
1585     test_ToUnicode();
1586     test_get_async_key_state();
1587     test_keyboard_layout_name();
1588
1589     if(pGetMouseMovePointsEx)
1590         test_GetMouseMovePointsEx();
1591     else
1592         win_skip("GetMouseMovePointsEx is not available\n");
1593 }