wintrust: Use helper function for setting confidence in SoftpubCheckCert.
[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 UINT (WINAPI *pSendInput) (UINT, INPUT*, size_t);
64 static int (WINAPI *pGetMouseMovePointsEx) (UINT, LPMOUSEMOVEPOINT, LPMOUSEMOVEPOINT, int, DWORD);
65
66 #define MAXKEYEVENTS 6
67 #define MAXKEYMESSAGES MAXKEYEVENTS /* assuming a key event generates one
68                                        and only one message */
69
70 /* keyboard message names, sorted as their value */
71 static const char *MSGNAME[]={"WM_KEYDOWN", "WM_KEYUP", "WM_CHAR","WM_DEADCHAR",
72     "WM_SYSKEYDOWN", "WM_SYSKEYUP", "WM_SYSCHAR", "WM_SYSDEADCHAR" ,"WM_KEYLAST"};
73
74 /* keyevents, add more as needed */
75 typedef enum KEVtag
76 {  ALTDOWN = 1, ALTUP, XDOWN, XUP, SHIFTDOWN, SHIFTUP, CTRLDOWN, CTRLUP } KEV;
77 /* matching VK's */
78 static const int GETVKEY[]={0, VK_MENU, VK_MENU, 'X', 'X', VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL};
79 /* matching scan codes */
80 static const int GETSCAN[]={0, 0x38, 0x38, 0x2D, 0x2D, 0x2A, 0x2A, 0x1D, 0x1D };
81 /* matching updown events */
82 static const int GETFLAGS[]={0, 0, KEYEVENTF_KEYUP, 0, KEYEVENTF_KEYUP, 0, KEYEVENTF_KEYUP, 0, KEYEVENTF_KEYUP};
83 /* matching descriptions */
84 static const char *getdesc[]={"", "+alt","-alt","+X","-X","+shift","-shift","+ctrl","-ctrl"};
85
86 /* The MSVC headers ignore our NONAMELESSUNION requests so we have to define our own type */
87 typedef struct
88 {
89     DWORD type;
90     union
91     {
92         MOUSEINPUT      mi;
93         KEYBDINPUT      ki;
94         HARDWAREINPUT   hi;
95     } u;
96 } TEST_INPUT;
97
98 #define ADDTOINPUTS(kev) \
99 inputs[evtctr].type = INPUT_KEYBOARD; \
100     ((TEST_INPUT*)inputs)[evtctr].u.ki.wVk = GETVKEY[ kev]; \
101     ((TEST_INPUT*)inputs)[evtctr].u.ki.wScan = GETSCAN[ kev]; \
102     ((TEST_INPUT*)inputs)[evtctr].u.ki.dwFlags = GETFLAGS[ kev]; \
103     ((TEST_INPUT*)inputs)[evtctr].u.ki.dwExtraInfo = 0; \
104     ((TEST_INPUT*)inputs)[evtctr].u.ki.time = ++timetag; \
105     if( kev) evtctr++;
106
107 typedef struct {
108     UINT    message;
109     WPARAM  wParam;
110     LPARAM  lParam;
111 } KMSG;
112
113 /*******************************************
114  * add new test sets here
115  * the software will make all combinations of the
116  * keyevent defined here
117  */
118 static const struct {
119     int nrkev;
120     KEV keydwn[MAXKEYEVENTS];
121     KEV keyup[MAXKEYEVENTS];
122 } testkeyset[]= {
123     { 2, { ALTDOWN, XDOWN }, { ALTUP, XUP}},
124     { 3, { ALTDOWN, XDOWN , SHIFTDOWN}, { ALTUP, XUP, SHIFTUP}},
125     { 3, { ALTDOWN, XDOWN , CTRLDOWN}, { ALTUP, XUP, CTRLUP}},
126     { 3, { SHIFTDOWN, XDOWN , CTRLDOWN}, { SHIFTUP, XUP, CTRLUP}},
127     { 0 } /* mark the end */
128 };
129
130 /**********************adapted from input.c **********************************/
131
132 static BYTE InputKeyStateTable[256];
133 static BYTE AsyncKeyStateTable[256];
134 static BYTE TrackSysKey = 0; /* determine whether ALT key up will cause a WM_SYSKEYUP
135                          or a WM_KEYUP message */
136
137 static void init_function_pointers(void)
138 {
139     HMODULE hdll = GetModuleHandleA("user32");
140
141 #define GET_PROC(func) \
142     p ## func = (void*)GetProcAddress(hdll, #func); \
143     if(!p ## func) \
144       trace("GetProcAddress(%s) failed\n", #func);
145
146     GET_PROC(SendInput)
147     GET_PROC(GetMouseMovePointsEx)
148
149 #undef GET_PROC
150 }
151
152 static int KbdMessage( KEV kev, WPARAM *pwParam, LPARAM *plParam )
153 {
154     UINT message;
155     int VKey = GETVKEY[kev];
156     WORD flags;
157
158     flags = LOBYTE(GETSCAN[kev]);
159     if (GETFLAGS[kev] & KEYEVENTF_EXTENDEDKEY) flags |= KF_EXTENDED;
160
161     if (GETFLAGS[kev] & KEYEVENTF_KEYUP )
162     {
163         message = WM_KEYUP;
164         if( (InputKeyStateTable[VK_MENU] & 0x80) && (
165                 (VKey == VK_MENU) || (VKey == VK_CONTROL) ||
166                  !(InputKeyStateTable[VK_CONTROL] & 0x80))) {
167             if(  TrackSysKey == VK_MENU || /* <ALT>-down/<ALT>-up sequence */
168                     (VKey != VK_MENU)) /* <ALT>-down...<something else>-up */
169                 message = WM_SYSKEYUP;
170                 TrackSysKey = 0;
171         }
172         InputKeyStateTable[VKey] &= ~0x80;
173         flags |= KF_REPEAT | KF_UP;
174     }
175     else
176     {
177         if (InputKeyStateTable[VKey] & 0x80) flags |= KF_REPEAT;
178         if (!(InputKeyStateTable[VKey] & 0x80)) InputKeyStateTable[VKey] ^= 0x01;
179         InputKeyStateTable[VKey] |= 0x80;
180         AsyncKeyStateTable[VKey] |= 0x80;
181
182         message = WM_KEYDOWN;
183         if( (InputKeyStateTable[VK_MENU] & 0x80) &&
184                 !(InputKeyStateTable[VK_CONTROL] & 0x80)) {
185             message = WM_SYSKEYDOWN;
186             TrackSysKey = VKey;
187         }
188     }
189
190     if (InputKeyStateTable[VK_MENU] & 0x80) flags |= KF_ALTDOWN;
191
192     if( plParam) *plParam = MAKELPARAM( 1, flags );
193     if( pwParam) *pwParam = VKey;
194     return message;
195 }
196
197 /****************************** end copy input.c ****************************/
198
199 /*
200  * . prepare the keyevents for SendInputs
201  * . calculate the "expected" messages
202  * . Send the events to our window
203  * . retrieve the messages from the input queue
204  * . verify
205  */
206 static void do_test( HWND hwnd, int seqnr, const KEV td[] )
207 {
208     INPUT inputs[MAXKEYEVENTS];
209     KMSG expmsg[MAXKEYEVENTS];
210     MSG msg;
211     char buf[100];
212     UINT evtctr=0;
213     int kmctr, i;
214
215     buf[0]='\0';
216     TrackSysKey=0; /* see input.c */
217     for( i = 0; i < MAXKEYEVENTS; i++) {
218         ADDTOINPUTS(td[i])
219         strcat(buf, getdesc[td[i]]);
220         if(td[i])
221             expmsg[i].message = KbdMessage(td[i], &(expmsg[i].wParam), &(expmsg[i].lParam)); /* see queue_kbd_event() */
222         else
223             expmsg[i].message = 0;
224     }
225     for( kmctr = 0; kmctr < MAXKEYEVENTS && expmsg[kmctr].message; kmctr++)
226         ;
227     assert( evtctr <= MAXKEYEVENTS );
228     assert( evtctr == pSendInput(evtctr, &inputs[0], sizeof(INPUT)));
229     i = 0;
230     if (winetest_debug > 1)
231         trace("======== key stroke sequence #%d: %s =============\n",
232             seqnr + 1, buf);
233     while( PeekMessage(&msg,hwnd,WM_KEYFIRST,WM_KEYLAST,PM_REMOVE) ) {
234         if (winetest_debug > 1)
235             trace("message[%d] %-15s wParam %04lx lParam %08lx time %x\n", i,
236                   MSGNAME[msg.message - WM_KEYFIRST], msg.wParam, msg.lParam, msg.time);
237         if( i < kmctr ) {
238             ok( msg.message == expmsg[i].message &&
239                     msg.wParam == expmsg[i].wParam &&
240                     msg.lParam == expmsg[i].lParam,
241                     "wrong message! expected:\n"
242                     "message[%d] %-15s wParam %04lx lParam %08lx\n",i,
243                     MSGNAME[(expmsg[i]).message - WM_KEYFIRST],
244                     expmsg[i].wParam, expmsg[i].lParam );
245         }
246         i++;
247     }
248     if (winetest_debug > 1)
249         trace("%d messages retrieved\n", i);
250     ok( i == kmctr, "message count is wrong: got %d expected: %d\n", i, kmctr);
251 }
252
253 /* test all combinations of the specified key events */
254 static void TestASet( HWND hWnd, int nrkev, const KEV kevdwn[], const KEV kevup[] )
255 {
256     int i,j,k,l,m,n;
257     static int count=0;
258     KEV kbuf[MAXKEYEVENTS];
259     assert( nrkev==2 || nrkev==3);
260     for(i=0;i<MAXKEYEVENTS;i++) kbuf[i]=0;
261     /* two keys involved gives 4 test cases */
262     if(nrkev==2) {
263         for(i=0;i<nrkev;i++) {
264             for(j=0;j<nrkev;j++) {
265                 kbuf[0] = kevdwn[i];
266                 kbuf[1] = kevdwn[1-i];
267                 kbuf[2] = kevup[j];
268                 kbuf[3] = kevup[1-j];
269                 do_test( hWnd, count++, kbuf);
270             }
271         }
272     }
273     /* three keys involved gives 36 test cases */
274     if(nrkev==3){
275         for(i=0;i<nrkev;i++){
276             for(j=0;j<nrkev;j++){
277                 if(j==i) continue;
278                 for(k=0;k<nrkev;k++){
279                     if(k==i || k==j) continue;
280                     for(l=0;l<nrkev;l++){
281                         for(m=0;m<nrkev;m++){
282                             if(m==l) continue;
283                             for(n=0;n<nrkev;n++){
284                                 if(n==l ||n==m) continue;
285                                 kbuf[0] = kevdwn[i];
286                                 kbuf[1] = kevdwn[j];
287                                 kbuf[2] = kevdwn[k];
288                                 kbuf[3] = kevup[l];
289                                 kbuf[4] = kevup[m];
290                                 kbuf[5] = kevup[n];
291                                 do_test( hWnd, count++, kbuf);
292                             }
293                         }
294                     }
295                 }
296             }
297         }
298     }
299 }
300
301 /* test each set specified in the global testkeyset array */
302 static void TestSysKeys( HWND hWnd)
303 {
304     int i;
305     for(i=0; testkeyset[i].nrkev;i++)
306         TestASet( hWnd, testkeyset[i].nrkev, testkeyset[i].keydwn,
307                 testkeyset[i].keyup);
308 }
309
310 static LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam,
311         LPARAM lParam )
312 {
313     switch (msg) {
314         case WM_USER:
315             SetFocus(hWnd);
316             /* window has focus, now do the test */
317             if( hWnd == hWndTest) TestSysKeys( hWnd);
318             /* finished :-) */
319             break;
320
321         case WM_DESTROY:
322             PostQuitMessage( 0 );
323             break;
324
325         default:
326             return( DefWindowProcA( hWnd, msg, wParam, lParam ) );
327     }
328
329     return 0;
330 }
331
332 static void test_Input_whitebox(void)
333 {
334     MSG msg;
335     WNDCLASSA  wclass;
336     HANDLE hInstance = GetModuleHandleA( NULL );
337
338     wclass.lpszClassName = "InputSysKeyTestClass";
339     wclass.style         = CS_HREDRAW | CS_VREDRAW;
340     wclass.lpfnWndProc   = WndProc;
341     wclass.hInstance     = hInstance;
342     wclass.hIcon         = LoadIconA( 0, (LPSTR)IDI_APPLICATION );
343     wclass.hCursor       = LoadCursorA( NULL, IDC_ARROW);
344     wclass.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1);
345     wclass.lpszMenuName = 0;
346     wclass.cbClsExtra    = 0;
347     wclass.cbWndExtra    = 0;
348     assert (RegisterClassA( &wclass ));
349     /* create the test window that will receive the keystrokes */
350     assert ( hWndTest = CreateWindowA( wclass.lpszClassName, "InputSysKeyTest",
351                 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 100, 100,
352                 NULL, NULL, hInstance, NULL) );
353     ShowWindow( hWndTest, SW_SHOW);
354     UpdateWindow( hWndTest);
355
356     /* flush pending messages */
357     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
358
359     SendMessageA(hWndTest, WM_USER, 0, 0);
360     DestroyWindow(hWndTest);
361 }
362
363 static void empty_message_queue(void) {
364     MSG msg;
365     while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
366         TranslateMessage(&msg);
367         DispatchMessage(&msg);
368     }
369 }
370
371 struct transition_s {
372     WORD wVk;
373     BYTE before_state;
374     BYTE optional;
375 };
376
377 typedef enum {
378     sent=0x1,
379     posted=0x2,
380     parent=0x4,
381     wparam=0x8,
382     lparam=0x10,
383     defwinproc=0x20,
384     beginpaint=0x40,
385     optional=0x80,
386     hook=0x100,
387     winevent_hook=0x200
388 } msg_flags_t;
389
390 struct message {
391     UINT message;          /* the WM_* code */
392     msg_flags_t flags;     /* message props */
393     WPARAM wParam;         /* expected value of wParam */
394     LPARAM lParam;         /* expected value of lParam */
395 };
396
397 struct sendinput_test_s {
398     WORD wVk;
399     DWORD dwFlags;
400     BOOL _todo_wine;
401     struct transition_s expected_transitions[MAXKEYEVENTS+1];
402     struct message expected_messages[MAXKEYMESSAGES+1];
403 } sendinput_test[] = {
404     /* test ALT+F */
405     {VK_LMENU, 0, 0, {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {0}},
406         {{WM_SYSKEYDOWN, hook|wparam, VK_LMENU}, {WM_SYSKEYDOWN}, {0}}},
407     {'F', 0, 0, {{'F', 0x00}, {0}},
408         {{WM_SYSKEYDOWN, hook}, {WM_SYSKEYDOWN},
409         {WM_SYSCHAR},
410         {WM_SYSCOMMAND}, {0}}},
411     {'F', KEYEVENTF_KEYUP, 0, {{'F', 0x80}, {0}},
412         {{WM_SYSKEYUP, hook}, {WM_SYSKEYUP}, {0}}},
413     {VK_LMENU, KEYEVENTF_KEYUP, 0, {{VK_MENU, 0x80}, {VK_LMENU, 0x80}, {0}},
414         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
415
416     /* test CTRL+O */
417     {VK_LCONTROL, 0, 0, {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}},
418         {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {0}}},
419     {'O', 0, 0, {{'O', 0x00}, {0}},
420         {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {WM_CHAR}, {0}}},
421     {'O', KEYEVENTF_KEYUP, 0, {{'O', 0x80}, {0}},
422         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
423     {VK_LCONTROL, KEYEVENTF_KEYUP, 0, {{VK_CONTROL, 0x80}, {VK_LCONTROL, 0x80}, {0}},
424         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
425
426     /* test ALT+CTRL+X */
427     {VK_LMENU, 0, 0, {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {0}},
428         {{WM_SYSKEYDOWN, hook}, {WM_SYSKEYDOWN}, {0}}},
429     {VK_LCONTROL, 0, 0, {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}},
430         {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {0}}},
431     {'X', 0, 0, {{'X', 0x00}, {0}},
432         {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {0}}},
433     {'X', KEYEVENTF_KEYUP, 0, {{'X', 0x80}, {0}},
434         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
435     {VK_LCONTROL, KEYEVENTF_KEYUP, 0, {{VK_CONTROL, 0x80}, {VK_LCONTROL, 0x80}, {0}},
436         {{WM_SYSKEYUP, hook}, {WM_SYSKEYUP}, {0}}},
437     {VK_LMENU, KEYEVENTF_KEYUP, 0, {{VK_MENU, 0x80}, {VK_LMENU, 0x80}, {0}},
438         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
439
440     /* test SHIFT+A */
441     {VK_LSHIFT, 0, 0, {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00}, {0}},
442         {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {0}}},
443     {'A', 0, 0, {{'A', 0x00}, {0}},
444         {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {WM_CHAR}, {0}}},
445     {'A', KEYEVENTF_KEYUP, 0, {{'A', 0x80}, {0}},
446         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
447     {VK_LSHIFT, KEYEVENTF_KEYUP, 0, {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80}, {0}},
448         {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}},
449     /* test L-SHIFT & R-SHIFT: */
450     /* RSHIFT == LSHIFT */
451     {VK_RSHIFT, 0, 0,
452      /* recent windows versions (>= w2k3) correctly report an RSHIFT transition */
453        {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00, TRUE}, {VK_RSHIFT, 0x00, TRUE}, {0}},
454         {{WM_KEYDOWN, hook|wparam, VK_RSHIFT},
455         {WM_KEYDOWN}, {0}}},
456     {VK_RSHIFT, KEYEVENTF_KEYUP, 0,
457        {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80, TRUE}, {VK_RSHIFT, 0x80, TRUE}, {0}},
458         {{WM_KEYUP, hook, hook|wparam, VK_RSHIFT},
459         {WM_KEYUP}, {0}}},
460
461     /* LSHIFT | KEYEVENTF_EXTENDEDKEY == RSHIFT */
462     {VK_LSHIFT, KEYEVENTF_EXTENDEDKEY, 0,
463         {{VK_SHIFT, 0x00}, {VK_RSHIFT, 0x00}, {0}},
464         {{WM_KEYDOWN, hook|wparam|lparam, VK_LSHIFT, LLKHF_EXTENDED},
465         {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}},
466     {VK_LSHIFT, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 0,
467         {{VK_SHIFT, 0x80}, {VK_RSHIFT, 0x80}, {0}},
468         {{WM_KEYUP, hook|wparam|lparam, VK_LSHIFT, LLKHF_UP|LLKHF_EXTENDED},
469         {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}},
470     /* RSHIFT | KEYEVENTF_EXTENDEDKEY == RSHIFT */
471     {VK_RSHIFT, KEYEVENTF_EXTENDEDKEY, 0,
472         {{VK_SHIFT, 0x00}, {VK_RSHIFT, 0x00}, {0}},
473         {{WM_KEYDOWN, hook|wparam|lparam, VK_RSHIFT, LLKHF_EXTENDED},
474         {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}},
475     {VK_RSHIFT, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 0,
476         {{VK_SHIFT, 0x80}, {VK_RSHIFT, 0x80}, {0}},
477         {{WM_KEYUP, hook|wparam|lparam, VK_RSHIFT, LLKHF_UP|LLKHF_EXTENDED},
478         {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}},
479
480     /* Note about wparam for hook with generic key (VK_SHIFT, VK_CONTROL, VK_MENU):
481        win2k  - sends to hook whatever we generated here
482        winXP+ - Attempts to convert key to L/R key but not always correct
483     */
484     /* SHIFT == LSHIFT */
485     {VK_SHIFT, 0, 0,
486         {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00}, {0}},
487         {{WM_KEYDOWN, hook/* |wparam */|lparam, VK_SHIFT, 0},
488         {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}},
489     {VK_SHIFT, KEYEVENTF_KEYUP, 0,
490         {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80}, {0}},
491         {{WM_KEYUP, hook/*|wparam*/|lparam, VK_SHIFT, LLKHF_UP},
492         {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}},
493     /* SHIFT | KEYEVENTF_EXTENDEDKEY == RSHIFT */
494     {VK_SHIFT, KEYEVENTF_EXTENDEDKEY, 0,
495         {{VK_SHIFT, 0x00}, {VK_RSHIFT, 0x00}, {0}},
496         {{WM_KEYDOWN, hook/*|wparam*/|lparam, VK_SHIFT, LLKHF_EXTENDED},
497         {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}},
498     {VK_SHIFT, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 0,
499         {{VK_SHIFT, 0x80}, {VK_RSHIFT, 0x80}, {0}},
500         {{WM_KEYUP, hook/*|wparam*/|lparam, VK_SHIFT, LLKHF_UP|LLKHF_EXTENDED},
501         {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}},
502
503     /* test L-CONTROL & R-CONTROL: */
504     /* RCONTROL == LCONTROL */
505     {VK_RCONTROL, 0, 0,
506         {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}},
507         {{WM_KEYDOWN, hook|wparam, VK_RCONTROL},
508         {WM_KEYDOWN, wparam|lparam, VK_CONTROL, 0}, {0}}},
509     {VK_RCONTROL, KEYEVENTF_KEYUP, 0,
510         {{VK_CONTROL, 0x80}, {VK_LCONTROL, 0x80}, {0}},
511         {{WM_KEYUP, hook|wparam, VK_RCONTROL},
512         {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP}, {0}}},
513     /* LCONTROL | KEYEVENTF_EXTENDEDKEY == RCONTROL */
514     {VK_LCONTROL, KEYEVENTF_EXTENDEDKEY, 0,
515         {{VK_CONTROL, 0x00}, {VK_RCONTROL, 0x00}, {0}},
516         {{WM_KEYDOWN, hook|wparam|lparam, VK_LCONTROL, LLKHF_EXTENDED},
517         {WM_KEYDOWN, wparam|lparam, VK_CONTROL, KF_EXTENDED}, {0}}},
518     {VK_LCONTROL, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 0,
519         {{VK_CONTROL, 0x80}, {VK_RCONTROL, 0x80}, {0}},
520         {{WM_KEYUP, hook|wparam|lparam, VK_LCONTROL, LLKHF_UP|LLKHF_EXTENDED},
521         {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP|KF_EXTENDED}, {0}}},
522     /* RCONTROL | KEYEVENTF_EXTENDEDKEY == RCONTROL */
523     {VK_RCONTROL, KEYEVENTF_EXTENDEDKEY, 0,
524         {{VK_CONTROL, 0x00}, {VK_RCONTROL, 0x00}, {0}},
525         {{WM_KEYDOWN, hook|wparam|lparam, VK_RCONTROL, LLKHF_EXTENDED},
526         {WM_KEYDOWN, wparam|lparam, VK_CONTROL, KF_EXTENDED}, {0}}},
527     {VK_RCONTROL, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 0,
528         {{VK_CONTROL, 0x80}, {VK_RCONTROL, 0x80}, {0}},
529         {{WM_KEYUP, hook|wparam|lparam, VK_RCONTROL, LLKHF_UP|LLKHF_EXTENDED},
530         {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP|KF_EXTENDED}, {0}}},
531     /* CONTROL == LCONTROL */
532     {VK_CONTROL, 0, 0,
533         {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}},
534         {{WM_KEYDOWN, hook/*|wparam, VK_CONTROL*/},
535         {WM_KEYDOWN, wparam|lparam, VK_CONTROL, 0}, {0}}},
536     {VK_CONTROL, KEYEVENTF_KEYUP, 0,
537         {{VK_CONTROL, 0x80}, {VK_LCONTROL, 0x80}, {0}},
538         {{WM_KEYUP, hook/*|wparam, VK_CONTROL*/},
539         {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP}, {0}}},
540     /* CONTROL | KEYEVENTF_EXTENDEDKEY == RCONTROL */
541     {VK_CONTROL, KEYEVENTF_EXTENDEDKEY, 0,
542         {{VK_CONTROL, 0x00}, {VK_RCONTROL, 0x00}, {0}},
543         {{WM_KEYDOWN, hook/*|wparam*/|lparam, VK_CONTROL, LLKHF_EXTENDED},
544         {WM_KEYDOWN, wparam|lparam, VK_CONTROL, KF_EXTENDED}, {0}}},
545     {VK_CONTROL, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 0,
546         {{VK_CONTROL, 0x80}, {VK_RCONTROL, 0x80}, {0}},
547         {{WM_KEYUP, hook/*|wparam*/|lparam, VK_CONTROL, LLKHF_UP|LLKHF_EXTENDED},
548         {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP|KF_EXTENDED}, {0}}},
549
550     /* test L-MENU & R-MENU: */
551     /* RMENU == LMENU */
552     {VK_RMENU, 0, 0,
553         {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {0}},
554         {{WM_SYSKEYDOWN, hook|wparam, VK_RMENU},
555         {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0}, {0}}},
556     {VK_RMENU, KEYEVENTF_KEYUP, 1,
557         {{VK_MENU, 0x80}, {VK_LMENU, 0x80}, {0}},
558         {{WM_KEYUP, hook|wparam, VK_RMENU},
559         {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP},
560         {WM_SYSCOMMAND}, {0}}},
561     /* LMENU | KEYEVENTF_EXTENDEDKEY == RMENU */
562     {VK_LMENU, KEYEVENTF_EXTENDEDKEY, 0,
563         {{VK_MENU, 0x00}, {VK_RMENU, 0x00}, {0}},
564         {{WM_SYSKEYDOWN, hook|wparam|lparam, VK_LMENU, LLKHF_EXTENDED},
565         {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, KF_EXTENDED}, {0}}},
566     {VK_LMENU, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 1,
567         {{VK_MENU, 0x80}, {VK_RMENU, 0x80}, {0}},
568         {{WM_KEYUP, hook|wparam|lparam, VK_LMENU, LLKHF_UP|LLKHF_EXTENDED},
569         {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP|KF_EXTENDED},
570         {WM_SYSCOMMAND}, {0}}},
571     /* RMENU | KEYEVENTF_EXTENDEDKEY == RMENU */
572     {VK_RMENU, KEYEVENTF_EXTENDEDKEY, 0,
573         {{VK_MENU, 0x00}, {VK_RMENU, 0x00}, {0}},
574         {{WM_SYSKEYDOWN, hook|wparam|lparam, VK_RMENU, LLKHF_EXTENDED},
575         {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, KF_EXTENDED}, {0}}},
576     {VK_RMENU, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 1,
577         {{VK_MENU, 0x80}, {VK_RMENU, 0x80}, {0}},
578         {{WM_KEYUP, hook|wparam|lparam, VK_RMENU, LLKHF_UP|LLKHF_EXTENDED},
579         {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP|KF_EXTENDED},
580         {WM_SYSCOMMAND}, {0}}},
581     /* MENU == LMENU */
582     {VK_MENU, 0, 0,
583         {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {0}},
584         {{WM_SYSKEYDOWN, hook/*|wparam, VK_MENU*/},
585         {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0}, {0}}},
586     {VK_MENU, KEYEVENTF_KEYUP, 1,
587         {{VK_MENU, 0x80}, {VK_LMENU, 0x80}, {0}},
588         {{WM_KEYUP, hook/*|wparam, VK_MENU*/},
589         {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP},
590         {WM_SYSCOMMAND}, {0}}},
591     /* MENU | KEYEVENTF_EXTENDEDKEY == RMENU */
592     {VK_MENU, KEYEVENTF_EXTENDEDKEY, 0,
593         {{VK_MENU, 0x00}, {VK_RMENU, 0x00}, {0}},
594         {{WM_SYSKEYDOWN, hook/*|wparam*/|lparam, VK_MENU, LLKHF_EXTENDED},
595         {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, KF_EXTENDED}, {0}}},
596     {VK_MENU, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 1,
597         {{VK_MENU, 0x80}, {VK_RMENU, 0x80}, {0}},
598         {{WM_KEYUP, hook/*|wparam*/|lparam, VK_MENU, LLKHF_UP|LLKHF_EXTENDED},
599         {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP|KF_EXTENDED},
600         {WM_SYSCOMMAND}, {0}}},
601
602     /* test LSHIFT & RSHIFT */
603     {VK_LSHIFT, 0, 0,
604         {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00}, {0}},
605         {{WM_KEYDOWN, hook|wparam|lparam, VK_LSHIFT, 0},
606         {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}},
607     {VK_RSHIFT, KEYEVENTF_EXTENDEDKEY, 0,
608         {{VK_RSHIFT, 0x00}, {0}},
609         {{WM_KEYDOWN, hook|wparam|lparam, VK_RSHIFT, LLKHF_EXTENDED},
610         {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}},
611     {VK_RSHIFT, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 0,
612         {{VK_RSHIFT, 0x80}, {0}},
613         {{WM_KEYUP, hook|wparam|lparam, VK_RSHIFT, LLKHF_UP|LLKHF_EXTENDED},
614         {WM_KEYUP, optional}, {0}}},
615     {VK_LSHIFT, KEYEVENTF_KEYUP, 0,
616         {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80}, {0}},
617         {{WM_KEYUP, hook|wparam, VK_LSHIFT},
618         {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}},
619
620     {0, 0, 0, {{0}}, {{0}}} /* end */
621 };
622
623 static struct message sent_messages[MAXKEYMESSAGES];
624 static UINT sent_messages_cnt;
625
626 /* Verify that only specified key state transitions occur */
627 static void compare_and_check(int id, BYTE *ks1, BYTE *ks2, struct sendinput_test_s *test)
628 {
629     int i, failcount = 0;
630     struct transition_s *t = test->expected_transitions;
631     UINT actual_cnt = 0;
632     const struct message *expected = test->expected_messages;
633
634     while (t->wVk) {
635         int matched = ((ks1[t->wVk]&0x80) == (t->before_state&0x80)
636                        && (ks2[t->wVk]&0x80) == (~t->before_state&0x80));
637
638         if (!matched && test->_todo_wine)
639         {
640             failcount++;
641             todo_wine {
642                 ok(matched, "%02d: %02x from %02x -> %02x "
643                    "instead of %02x -> %02x\n", id, t->wVk,
644                    ks1[t->wVk]&0x80, ks2[t->wVk]&0x80, t->before_state,
645                    ~t->before_state&0x80);
646             }
647         } else {
648             ok(matched || t->optional, "%02d: %02x from %02x -> %02x "
649                "instead of %02x -> %02x\n", id, t->wVk,
650                ks1[t->wVk]&0x80, ks2[t->wVk]&0x80, t->before_state,
651                ~t->before_state&0x80);
652         }
653         ks2[t->wVk] = ks1[t->wVk]; /* clear the match */
654         t++;
655     }
656     for (i = 0; i < 256; i++)
657         if (ks2[i] != ks1[i] && test->_todo_wine)
658         {
659             failcount++;
660             todo_wine
661                 ok(FALSE, "%02d: %02x from %02x -> %02x unexpected\n", id, i, ks1[i], ks2[i]);
662         }
663         else
664             ok(ks2[i] == ks1[i], "%02d: %02x from %02x -> %02x unexpected\n",
665                id, i, ks1[i], ks2[i]);
666
667     while (expected->message && actual_cnt < sent_messages_cnt)
668     {
669         const struct message *actual = &sent_messages[actual_cnt];
670
671         if (expected->message == actual->message)
672         {
673             ok((expected->flags & hook) == (actual->flags & hook),
674                "%x/%x: the msg 0x%04x should have been sent by a hook\n",
675                test->wVk, test->dwFlags, expected->message);
676
677             if (expected->flags & wparam)
678             {
679                 if (expected->wParam != actual->wParam && test->_todo_wine)
680                 {
681                     failcount++;
682                     todo_wine
683                         ok(FALSE, "%x/%x: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
684                            test->wVk, test->dwFlags, expected->message, expected->wParam, actual->wParam);
685                 }
686                 else
687                     ok(expected->wParam == actual->wParam,
688                        "%x/%x: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
689                        test->wVk, test->dwFlags, expected->message, expected->wParam, actual->wParam);
690             }
691             if (expected->flags & lparam)
692             {
693                 if (expected->lParam != actual->lParam && test->_todo_wine)
694                 {
695                     failcount++;
696                     todo_wine
697                         ok(FALSE, "%x/%x: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
698                            test->wVk, test->dwFlags, expected->message, expected->lParam, actual->lParam);
699                 }
700                 else
701                     ok(expected->lParam == actual->lParam,
702                        "%x/%x: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
703                        test->wVk, test->dwFlags, expected->message, expected->lParam, actual->lParam);
704             }
705         }
706         else if (expected->flags & optional)
707         {
708             expected++;
709             continue;
710         }
711         else if (test->_todo_wine)
712         {
713             failcount++;
714             todo_wine
715             ok(FALSE,
716                "%x/%x: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
717                test->wVk, test->dwFlags, expected->message, actual->message);
718         }
719         else
720             ok(FALSE,
721                "%x/%x: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
722                test->wVk, test->dwFlags, expected->message, actual->message);
723
724         actual_cnt++;
725         expected++;
726     }
727     /* skip all optional trailing messages */
728     while (expected->message && (expected->flags & optional))
729         expected++;
730
731
732     if (expected->message || actual_cnt < sent_messages_cnt)
733     {
734         if (test->_todo_wine)
735         {
736             failcount++;
737             todo_wine
738                 ok(FALSE, "%x/%x: the msg sequence is not complete: expected %04x - actual %04x\n",
739                    test->wVk, test->dwFlags, expected->message, sent_messages[actual_cnt].message);
740         }
741         else
742             ok(FALSE, "%x/%x: the msg sequence is not complete: expected %04x - actual %04x\n",
743                test->wVk, test->dwFlags, expected->message, sent_messages[actual_cnt].message);
744     }
745
746     if( test->_todo_wine && !failcount) /* succeeded yet marked todo */
747         todo_wine
748             ok(TRUE, "%x/%x: marked \"todo_wine\" but succeeds\n", test->wVk, test->dwFlags);
749
750     sent_messages_cnt = 0;
751 }
752
753 /* WndProc2 checks that we get at least the messages specified */
754 static LRESULT CALLBACK WndProc2(HWND hWnd, UINT Msg, WPARAM wParam,
755                                    LPARAM lParam)
756 {
757     if (winetest_debug > 1) trace("MSG:  %8x W:%8lx L:%8lx\n", Msg, wParam, lParam);
758
759     if (Msg != WM_PAINT &&
760         Msg != WM_NCPAINT &&
761         Msg != WM_SYNCPAINT &&
762         Msg != WM_ERASEBKGND &&
763         Msg != WM_NCHITTEST &&
764         Msg != WM_GETTEXT &&
765         Msg != WM_GETICON &&
766         Msg != WM_DEVICECHANGE)
767     {
768         sent_messages[sent_messages_cnt].message = Msg;
769         sent_messages[sent_messages_cnt].flags = 0;
770         sent_messages[sent_messages_cnt].wParam = wParam;
771         sent_messages[sent_messages_cnt++].lParam = HIWORD(lParam) & (KF_UP|KF_EXTENDED);
772     }
773     return DefWindowProc(hWnd, Msg, wParam, lParam);
774 }
775
776 static LRESULT CALLBACK hook_proc(int code, WPARAM wparam, LPARAM lparam)
777 {
778     KBDLLHOOKSTRUCT *hook_info = (KBDLLHOOKSTRUCT *)lparam;
779
780     if (code == HC_ACTION)
781     {
782         sent_messages[sent_messages_cnt].message = wparam;
783         sent_messages[sent_messages_cnt].flags = hook;
784         sent_messages[sent_messages_cnt].wParam = hook_info->vkCode;
785         sent_messages[sent_messages_cnt++].lParam = hook_info->flags & (LLKHF_UP|LLKHF_EXTENDED);
786
787 if(0) /* For some reason not stable on Wine */
788 {
789         if (wparam == WM_KEYDOWN || wparam == WM_SYSKEYDOWN)
790             ok(!(GetAsyncKeyState(hook_info->vkCode) & 0x8000), "key %x should be up\n", hook_info->vkCode);
791         else if (wparam == WM_KEYUP || wparam == WM_SYSKEYUP)
792             ok(GetAsyncKeyState(hook_info->vkCode) & 0x8000, "key %x should be down\n", hook_info->vkCode);
793 }
794
795         if (winetest_debug > 1)
796             trace("Hook:   w=%lx vk:%8x sc:%8x fl:%8x %lx\n", wparam,
797                   hook_info->vkCode, hook_info->scanCode, hook_info->flags, hook_info->dwExtraInfo);
798     }
799     return CallNextHookEx( 0, code, wparam, lparam );
800 }
801 static void test_Input_blackbox(void)
802 {
803     TEST_INPUT i;
804     int ii;
805     BYTE ks1[256], ks2[256];
806     LONG_PTR prevWndProc;
807     HWND window;
808     HHOOK hook;
809
810     if (!pSendInput)
811     {
812         skip("SendInput is not available\n");
813         return;
814     }
815
816     window = CreateWindow("Static", NULL, WS_POPUP|WS_HSCROLL|WS_VSCROLL
817         |WS_VISIBLE, 0, 0, 200, 60, NULL, NULL,
818         NULL, NULL);
819     ok(window != NULL, "error: %d\n", (int) GetLastError());
820
821     hook = SetWindowsHookExA(WH_KEYBOARD_LL, hook_proc, GetModuleHandleA( NULL ), 0);
822
823     /* must process all initial messages, otherwise X11DRV_KeymapNotify unsets
824      * key state set by SendInput(). */
825     empty_message_queue();
826
827     prevWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, (LONG_PTR) WndProc2);
828     ok(prevWndProc != 0 || (prevWndProc == 0 && GetLastError() == 0),
829        "error: %d\n", (int) GetLastError());
830
831     i.type = INPUT_KEYBOARD;
832     i.u.ki.time = 0;
833     i.u.ki.dwExtraInfo = 0;
834
835     for (ii = 0; ii < sizeof(sendinput_test)/sizeof(struct sendinput_test_s)-1;
836          ii++) {
837         GetKeyboardState(ks1);
838         i.u.ki.wScan = ii+1 /* useful for debugging */;
839         i.u.ki.dwFlags = sendinput_test[ii].dwFlags;
840         i.u.ki.wVk = sendinput_test[ii].wVk;
841         pSendInput(1, (INPUT*)&i, sizeof(TEST_INPUT));
842         empty_message_queue();
843         GetKeyboardState(ks2);
844         compare_and_check(ii, ks1, ks2, &sendinput_test[ii]);
845     }
846
847     empty_message_queue();
848     DestroyWindow(window);
849     UnhookWindowsHookEx(hook);
850 }
851
852 static void test_keynames(void)
853 {
854     int i, len;
855     char buff[256];
856
857     for (i = 0; i < 512; i++)
858     {
859         strcpy(buff, "----");
860         len = GetKeyNameTextA(i << 16, buff, sizeof(buff));
861         ok(len || !buff[0], "%d: Buffer is not zeroed\n", i);
862     }
863 }
864
865 static POINT pt_old, pt_new;
866 static BOOL clipped;
867 #define STEP 20
868
869 static LRESULT CALLBACK hook_proc1( int code, WPARAM wparam, LPARAM lparam )
870 {
871     MSLLHOOKSTRUCT *hook = (MSLLHOOKSTRUCT *)lparam;
872     POINT pt, pt1;
873
874     if (code == HC_ACTION)
875     {
876         /* This is our new cursor position */
877         pt_new = hook->pt;
878         /* Should return previous position */
879         GetCursorPos(&pt);
880         ok(pt.x == pt_old.x && pt.y == pt_old.y, "GetCursorPos: (%d,%d)\n", pt.x, pt.y);
881
882         /* Should set new position until hook chain is finished. */
883         pt.x = pt_old.x + STEP;
884         pt.y = pt_old.y + STEP;
885         SetCursorPos(pt.x, pt.y);
886         GetCursorPos(&pt1);
887         if (clipped)
888             ok(pt1.x == pt_old.x && pt1.y == pt_old.y, "Wrong set pos: (%d,%d)\n", pt1.x, pt1.y);
889         else
890             ok(pt1.x == pt.x && pt1.y == pt.y, "Wrong set pos: (%d,%d)\n", pt1.x, pt1.y);
891     }
892     return CallNextHookEx( 0, code, wparam, lparam );
893 }
894
895 static LRESULT CALLBACK hook_proc2( int code, WPARAM wparam, LPARAM lparam )
896 {
897     MSLLHOOKSTRUCT *hook = (MSLLHOOKSTRUCT *)lparam;
898     POINT pt;
899
900     if (code == HC_ACTION)
901     {
902         ok(hook->pt.x == pt_new.x && hook->pt.y == pt_new.y,
903            "Wrong hook coords: (%d %d) != (%d,%d)\n", hook->pt.x, hook->pt.y, pt_new.x, pt_new.y);
904
905         /* Should match position set above */
906         GetCursorPos(&pt);
907         if (clipped)
908             ok(pt.x == pt_old.x && pt.y == pt_old.y, "GetCursorPos: (%d,%d)\n", pt.x, pt.y);
909         else
910             ok(pt.x == pt_old.x +STEP && pt.y == pt_old.y +STEP, "GetCursorPos: (%d,%d)\n", pt.x, pt.y);
911     }
912     return CallNextHookEx( 0, code, wparam, lparam );
913 }
914
915 static void test_mouse_ll_hook(void)
916 {
917     HWND hwnd;
918     HHOOK hook1, hook2;
919     POINT pt_org, pt;
920     RECT rc;
921
922     GetCursorPos(&pt_org);
923     hwnd = CreateWindow("static", "Title", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
924                         10, 10, 200, 200, NULL, NULL, NULL, NULL);
925     SetCursorPos(100, 100);
926
927     hook2 = SetWindowsHookExA(WH_MOUSE_LL, hook_proc2, GetModuleHandleA(0), 0);
928     hook1 = SetWindowsHookExA(WH_MOUSE_LL, hook_proc1, GetModuleHandleA(0), 0);
929
930     GetCursorPos(&pt_old);
931     mouse_event(MOUSEEVENTF_MOVE, -STEP,  0, 0, 0);
932     GetCursorPos(&pt_old);
933     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);
934     mouse_event(MOUSEEVENTF_MOVE, +STEP,  0, 0, 0);
935     GetCursorPos(&pt_old);
936     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);
937     mouse_event(MOUSEEVENTF_MOVE,  0, -STEP, 0, 0);
938     GetCursorPos(&pt_old);
939     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);
940     mouse_event(MOUSEEVENTF_MOVE,  0, +STEP, 0, 0);
941     GetCursorPos(&pt_old);
942     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);
943
944     SetRect(&rc, 50, 50, 151, 151);
945     ClipCursor(&rc);
946     clipped = TRUE;
947
948     SetCursorPos(40, 40);
949     GetCursorPos(&pt_old);
950     ok(pt_old.x == 50 && pt_old.y == 50, "Wrong new pos: (%d,%d)\n", pt_new.x, pt_new.y);
951     SetCursorPos(160, 160);
952     GetCursorPos(&pt_old);
953     ok(pt_old.x == 150 && pt_old.y == 150, "Wrong new pos: (%d,%d)\n", pt_new.x, pt_new.y);
954     mouse_event(MOUSEEVENTF_MOVE, +STEP, +STEP, 0, 0);
955     GetCursorPos(&pt_old);
956     ok(pt_old.x == 150 && pt_old.y == 150, "Wrong new pos: (%d,%d)\n", pt_new.x, pt_new.y);
957
958     clipped = FALSE;
959     pt_new.x = pt_new.y = 150;
960     ClipCursor(NULL);
961     UnhookWindowsHookEx(hook1);
962
963     /* Now check that mouse buttons do not change mouse position
964        if we don't have MOUSEEVENTF_MOVE flag specified. */
965
966     /* We reusing the same hook callback, so make it happy */
967     pt_old.x = pt_new.x - STEP;
968     pt_old.y = pt_new.y - STEP;
969     mouse_event(MOUSEEVENTF_LEFTUP, 123, 456, 0, 0);
970     GetCursorPos(&pt);
971     ok(pt.x == pt_new.x && pt.y == pt_new.y, "Position changed: (%d,%d)\n", pt.x, pt.y);
972     mouse_event(MOUSEEVENTF_RIGHTUP, 456, 123, 0, 0);
973     GetCursorPos(&pt);
974     ok(pt.x == pt_new.x && pt.y == pt_new.y, "Position changed: (%d,%d)\n", pt.x, pt.y);
975
976     mouse_event(MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE, 123, 456, 0, 0);
977     GetCursorPos(&pt);
978     ok(pt.x == pt_new.x && pt.y == pt_new.y, "Position changed: (%d,%d)\n", pt.x, pt.y);
979     mouse_event(MOUSEEVENTF_RIGHTUP | MOUSEEVENTF_ABSOLUTE, 456, 123, 0, 0);
980     GetCursorPos(&pt);
981     ok(pt.x == pt_new.x && pt.y == pt_new.y, "Position changed: (%d,%d)\n", pt.x, pt.y);
982
983     UnhookWindowsHookEx(hook2);
984     DestroyWindow(hwnd);
985     SetCursorPos(pt_org.x, pt_org.y);
986 }
987
988 static void test_GetMouseMovePointsEx(void)
989 {
990 #define BUFLIM  64
991 #define MYERROR 0xdeadbeef
992     int count, retval;
993     MOUSEMOVEPOINT in;
994     MOUSEMOVEPOINT out[200];
995     POINT point;
996
997     /* Get a valid content for the input struct */
998     if(!GetCursorPos(&point)) {
999         skip("GetCursorPos() failed with error %u\n", GetLastError());
1000         return;
1001     }
1002     memset(&in, 0, sizeof(MOUSEMOVEPOINT));
1003     in.x = point.x;
1004     in.y = point.y;
1005
1006     /* test first parameter
1007      * everything different than sizeof(MOUSEMOVEPOINT)
1008      * is expected to fail with ERROR_INVALID_PARAMETER
1009      */
1010     SetLastError(MYERROR);
1011     retval = pGetMouseMovePointsEx(0, &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1012     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1013     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1014        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1015
1016     SetLastError(MYERROR);
1017     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)-1, &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1018     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1019     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1020        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1021
1022     SetLastError(MYERROR);
1023     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)+1, &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1024     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1025     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1026        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1027
1028     /* test second and third parameter
1029      */
1030     SetLastError(MYERROR);
1031     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), NULL, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1032     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1033     ok(GetLastError() == ERROR_NOACCESS || GetLastError() == MYERROR,
1034        "expected error ERROR_NOACCESS, got %u\n", GetLastError());
1035
1036     SetLastError(MYERROR);
1037     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, NULL, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1038     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1039     ok(ERROR_NOACCESS == GetLastError(),
1040        "expected error ERROR_NOACCESS, got %u\n", GetLastError());
1041
1042     SetLastError(MYERROR);
1043     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), NULL, NULL, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1044     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1045     ok(ERROR_NOACCESS == GetLastError(),
1046        "expected error ERROR_NOACCESS, got %u\n", GetLastError());
1047
1048     SetLastError(MYERROR);
1049     count = 0;
1050     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, NULL, count, GMMP_USE_DISPLAY_POINTS);
1051     todo_wine {
1052     ok(retval == count, "expected GetMouseMovePointsEx to succeed, got %d\n", retval);
1053     ok(MYERROR == GetLastError(),
1054        "expected error %d, got %u\n", MYERROR, GetLastError());
1055     }
1056
1057     /* test fourth parameter
1058      * a value higher than 64 is expected to fail with ERROR_INVALID_PARAMETER
1059      */
1060     SetLastError(MYERROR);
1061     count = -1;
1062     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, out, count, GMMP_USE_DISPLAY_POINTS);
1063     ok(retval == count, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1064     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1065        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1066
1067     SetLastError(MYERROR);
1068     count = 0;
1069     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, out, count, GMMP_USE_DISPLAY_POINTS);
1070     todo_wine {
1071     ok(retval == count, "expected GetMouseMovePointsEx to succeed, got %d\n", retval);
1072     ok(MYERROR == GetLastError(),
1073        "expected error %d, got %u\n", MYERROR, GetLastError());
1074     }
1075
1076     SetLastError(MYERROR);
1077     count = BUFLIM;
1078     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, out, count, GMMP_USE_DISPLAY_POINTS);
1079     todo_wine {
1080     ok((0 <= retval) && (retval <= count), "expected GetMouseMovePointsEx to succeed, got %d\n", retval);
1081     ok(MYERROR == GetLastError(),
1082        "expected error %d, got %u\n", MYERROR, GetLastError());
1083     }
1084
1085     SetLastError(MYERROR);
1086     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, out, BUFLIM+1, GMMP_USE_DISPLAY_POINTS);
1087     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1088     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1089        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1090
1091     /* it was not possible to force an error with the fifth parameter on win2k */
1092
1093     /* test combinations of wrong parameters to see which error wins */
1094     SetLastError(MYERROR);
1095     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)-1, NULL, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1096     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1097     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1098        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1099
1100     SetLastError(MYERROR);
1101     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)-1, &in, NULL, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1102     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1103     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1104        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1105
1106     SetLastError(MYERROR);
1107     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), NULL, out, BUFLIM+1, GMMP_USE_DISPLAY_POINTS);
1108     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1109     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1110        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1111
1112     SetLastError(MYERROR);
1113     retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, NULL, BUFLIM+1, GMMP_USE_DISPLAY_POINTS);
1114     ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1115     ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR,
1116        "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1117
1118 #undef BUFLIM
1119 #undef MYERROR
1120 }
1121
1122 static void test_key_map(void)
1123 {
1124     HKL kl = GetKeyboardLayout(0);
1125     UINT kL, kR, s, sL;
1126     int i;
1127     static const UINT numpad_collisions[][2] = {
1128         { VK_NUMPAD0, VK_INSERT },
1129         { VK_NUMPAD1, VK_END },
1130         { VK_NUMPAD2, VK_DOWN },
1131         { VK_NUMPAD3, VK_NEXT },
1132         { VK_NUMPAD4, VK_LEFT },
1133         { VK_NUMPAD6, VK_RIGHT },
1134         { VK_NUMPAD7, VK_HOME },
1135         { VK_NUMPAD8, VK_UP },
1136         { VK_NUMPAD9, VK_PRIOR },
1137     };
1138
1139     s  = MapVirtualKeyEx(VK_SHIFT,  MAPVK_VK_TO_VSC, kl);
1140     ok(s != 0, "MapVirtualKeyEx(VK_SHIFT) should return non-zero\n");
1141     sL = MapVirtualKeyEx(VK_LSHIFT, MAPVK_VK_TO_VSC, kl);
1142     ok(s == sL, "%x != %x\n", s, sL);
1143
1144     kL = MapVirtualKeyEx(0x2a, MAPVK_VSC_TO_VK, kl);
1145     ok(kL == VK_SHIFT, "Scan code -> vKey = %x (not VK_SHIFT)\n", kL);
1146     kR = MapVirtualKeyEx(0x36, MAPVK_VSC_TO_VK, kl);
1147     ok(kR == VK_SHIFT, "Scan code -> vKey = %x (not VK_SHIFT)\n", kR);
1148
1149     kL = MapVirtualKeyEx(0x2a, MAPVK_VSC_TO_VK_EX, kl);
1150     ok(kL == VK_LSHIFT, "Scan code -> vKey = %x (not VK_LSHIFT)\n", kL);
1151     kR = MapVirtualKeyEx(0x36, MAPVK_VSC_TO_VK_EX, kl);
1152     ok(kR == VK_RSHIFT, "Scan code -> vKey = %x (not VK_RSHIFT)\n", kR);
1153
1154     /* test that MAPVK_VSC_TO_VK prefers the non-numpad vkey if there's ambiguity */
1155     for (i = 0; i < sizeof(numpad_collisions)/sizeof(numpad_collisions[0]); i++)
1156     {
1157         UINT numpad_scan = MapVirtualKeyEx(numpad_collisions[i][0],  MAPVK_VK_TO_VSC, kl);
1158         UINT other_scan  = MapVirtualKeyEx(numpad_collisions[i][1],  MAPVK_VK_TO_VSC, kl);
1159
1160         /* do they really collide for this layout? */
1161         if (numpad_scan && other_scan == numpad_scan)
1162         {
1163             UINT vkey = MapVirtualKeyEx(numpad_scan, MAPVK_VSC_TO_VK, kl);
1164             ok(vkey != numpad_collisions[i][0],
1165                "Got numpad vKey %x for scan code %x when there was another choice\n",
1166                vkey, numpad_scan);
1167         }
1168     }
1169 }
1170
1171 static void test_ToUnicode(void)
1172 {
1173     WCHAR wStr[2];
1174     BYTE state[256];
1175     const BYTE SC_RETURN = 0x1c, SC_TAB = 0x0f;
1176     const BYTE HIGHEST_BIT = 0x80;
1177     int i, ret;
1178     for(i=0; i<256; i++)
1179         state[i]=0;
1180
1181     SetLastError(0xdeadbeef);
1182     ret = ToUnicode(VK_RETURN, SC_RETURN, state, wStr, 2, 0);
1183     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1184     {
1185         skip("ToUnicode is not implemented\n");
1186         return;
1187     }
1188
1189     ok(ret == 1, "ToUnicode for Return key didn't return 1 (was %i)\n", ret);
1190     if(ret == 1)
1191         ok(wStr[0]=='\r', "ToUnicode for CTRL + Return was %i (expected 13)\n", wStr[0]);
1192     state[VK_CONTROL] |= HIGHEST_BIT;
1193     state[VK_LCONTROL] |= HIGHEST_BIT;
1194
1195     ret = ToUnicode(VK_TAB, SC_TAB, state, wStr, 2, 0);
1196     todo_wine ok(ret == 0, "ToUnicode for CTRL + Tab didn't return 0 (was %i)\n", ret);
1197
1198     ret = ToUnicode(VK_RETURN, SC_RETURN, state, wStr, 2, 0);
1199     ok(ret == 1, "ToUnicode for CTRL + Return didn't return 1 (was %i)\n", ret);
1200     if(ret == 1)
1201         ok(wStr[0]=='\n', "ToUnicode for CTRL + Return was %i (expected 10)\n", wStr[0]);
1202
1203     state[VK_SHIFT] |= HIGHEST_BIT;
1204     state[VK_LSHIFT] |= HIGHEST_BIT;
1205     ret = ToUnicode(VK_RETURN, SC_RETURN, state, wStr, 2, 0);
1206     todo_wine ok(ret == 0, "ToUnicode for CTRL + SHIFT + Return didn't return 0 (was %i)\n", ret);
1207 }
1208
1209 START_TEST(input)
1210 {
1211     init_function_pointers();
1212
1213     if (!pSendInput)
1214         skip("SendInput is not available\n");
1215     else
1216         test_Input_whitebox();
1217
1218     test_Input_blackbox();
1219     test_keynames();
1220     test_mouse_ll_hook();
1221     test_key_map();
1222     test_ToUnicode();
1223
1224     if(pGetMouseMovePointsEx)
1225         test_GetMouseMovePointsEx();
1226     else
1227         skip("GetMouseMovePointsEx is not available\n");
1228 }