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