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