ReactOS 0.4.17-dev-116-ga4b6fe9
input.c
Go to the documentation of this file.
1/* Test Key event to Key message translation
2 *
3 * Copyright 2003 Rein Klazes
4 * Copyright 2019 Remi Bernon for CodeWeavers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21/* test whether the right type of messages:
22 * WM_KEYUP/DOWN vs WM_SYSKEYUP/DOWN are sent in case of combined
23 * keystrokes.
24 *
25 * For instance <ALT>-X can be accomplished by
26 * the sequence ALT-KEY-DOWN, X-KEY-DOWN, ALT-KEY-UP, X-KEY-UP
27 * but also X-KEY-DOWN, ALT-KEY-DOWN, X-KEY-UP, ALT-KEY-UP
28 * Whether a KEY or a SYSKEY message is sent is not always clear, it is
29 * also not the same in WINNT as in WIN9X */
30
31/* NOTE that there will be test failures under WIN9X
32 * No applications are known to me that rely on this
33 * so I don't fix it */
34
35/* TODO:
36 * 1. extend it to the wm_command and wm_syscommand notifications
37 * 2. add some more tests with special cases like dead keys or right (alt) key
38 * 3. there is some adapted code from input.c in here. Should really
39 * make that code exactly the same.
40 * 4. resolve the win9x case when there is a need or the testing frame work
41 * offers a nice way.
42 * 5. The test app creates a window, the user should not take the focus
43 * away during its short existence. I could do something to prevent that
44 * if it is a problem.
45 *
46 */
47
48#include <stdarg.h>
49#include <assert.h>
50
51#include "windef.h"
52#include "winbase.h"
53#include "wingdi.h"
54#include "winuser.h"
55#include "wingdi.h"
56#include "winnls.h"
57#include "winreg.h"
58#include "ddk/hidsdi.h"
59#include "imm.h"
60#include "kbd.h"
61
62#include "wine/test.h"
63#ifdef __REACTOS__
64/* printf with temp buffer allocation */
65const char *wine_dbg_sprintf( const char *format, ... )
66{
67 static const int max_size = 200;
68 static char buffer[256];
69 char *ret;
70 int len;
72
74 ret = buffer;
76 if (len == -1 || len >= max_size) ret[max_size-1] = 0;
78 return ret;
79}
80#endif
81
82#define check_member_( file, line, val, exp, fmt, member ) \
83 ok_(file, line)( (val).member == (exp).member, "got " #member " " fmt "\n", (val).member )
84#define check_member( val, exp, fmt, member ) \
85 check_member_( __FILE__, __LINE__, val, exp, fmt, member )
86
87static const char *debugstr_ok( const char *cond )
88{
89 int c, n = 0;
90 /* skip possible casts */
91 while ((c = *cond++))
92 {
93 if (c == '(') n++;
94 if (!n) break;
95 if (c == ')') n--;
96 }
97 if (!strchr( cond - 1, '(' )) return wine_dbg_sprintf( "got %s", cond - 1 );
98 return wine_dbg_sprintf( "%.*s returned", (int)strcspn( cond - 1, "( " ), cond - 1 );
99}
100
101#define ok_eq( e, r, t, f, ... ) \
102 do \
103 { \
104 t v = (r); \
105 ok( v == (e), "%s " f "\n", debugstr_ok( #r ), v, ##__VA_ARGS__ ); \
106 } while (0)
107#define ok_ne( e, r, t, f, ... ) \
108 do \
109 { \
110 t v = (r); \
111 ok( v != (e), "%s " f "\n", debugstr_ok( #r ), v, ##__VA_ARGS__ ); \
112 } while (0)
113#define ok_rect( e, r ) \
114 do \
115 { \
116 RECT v = (r); \
117 ok( EqualRect( &v, &(e) ), "%s %s\n", debugstr_ok(#r), wine_dbgstr_rect(&v) ); \
118 } while (0)
119#define ok_point( e, r ) \
120 do \
121 { \
122 POINT v = (r); \
123 ok( !memcmp( &v, &(e), sizeof(v) ), "%s %s\n", debugstr_ok(#r), wine_dbgstr_point(&v) ); \
124 } while (0)
125#define ok_ret( e, r ) ok_eq( e, r, UINT_PTR, "%Iu, error %ld", GetLastError() )
126
128{
133};
134
136{
138
139 union
140 {
141 struct
142 {
148 struct
149 {
150 UINT msg;
156 struct
157 {
158 UINT msg;
161 UINT flags;
165 struct
166 {
167 HWND hwnd;
169 RAWKEYBOARD kbd;
171 };
172
176};
177
178static const struct user_call empty_sequence[] = {{0}};
179static struct user_call current_sequence[1024];
181
182static const char *debugstr_wm( UINT msg )
183{
184 switch (msg)
185 {
186 case WM_CHAR: return "WM_CHAR";
187 case WM_KEYDOWN: return "WM_KEYDOWN";
188 case WM_KEYUP: return "WM_KEYUP";
189 case WM_SYSCHAR: return "WM_SYSCHAR";
190 case WM_SYSCOMMAND: return "WM_SYSCOMMAND";
191 case WM_SYSKEYDOWN: return "WM_SYSKEYDOWN";
192 case WM_SYSKEYUP: return "WM_SYSKEYUP";
193 case WM_MOUSEMOVE: return "WM_MOUSEMOVE";
194 case WM_LBUTTONDOWN: return "WM_LBUTTONDOWN";
195 case WM_LBUTTONUP: return "WM_LBUTTONUP";
196 case WM_LBUTTONDBLCLK: return "WM_LBUTTONDBLCLK";
197 case WM_NCHITTEST: return "WM_NCHITTEST";
198 }
199 return wine_dbg_sprintf( "%#x", msg );
200}
201
202static const char *debugstr_vk( UINT vkey )
203{
204 switch (vkey)
205 {
206 case VK_CONTROL: return "VK_CONTROL";
207 case VK_LCONTROL: return "VK_LCONTROL";
208 case VK_LMENU: return "VK_LMENU";
209 case VK_LSHIFT: return "VK_LSHIFT";
210 case VK_MENU: return "VK_MENU";
211 case VK_RCONTROL: return "VK_RCONTROL";
212 case VK_RMENU: return "VK_RMENU";
213 case VK_RSHIFT: return "VK_RSHIFT";
214 case VK_SHIFT: return "VK_SHIFT";
215 }
216
217 if (vkey >= '0' && vkey <= '9') return wine_dbg_sprintf( "%c", vkey );
218 if (vkey >= 'A' && vkey <= 'Z') return wine_dbg_sprintf( "%c", vkey );
219 return wine_dbg_sprintf( "%#x", vkey );
220}
221
222#define ok_call( a, b ) ok_call_( __FILE__, __LINE__, a, b )
223static int ok_call_( const char *file, int line, const struct user_call *expected, const struct user_call *received )
224{
225 int ret;
226
227 if ((ret = expected->func - received->func)) goto done;
228
229 switch (expected->func)
230 {
231 case MSG_TEST_WIN:
232 if ((ret = expected->message.hwnd - received->message.hwnd)) goto done;
233 if ((ret = expected->message.msg - received->message.msg)) goto done;
234 if ((ret = (expected->message.wparam - received->message.wparam))) goto done;
235 if ((ret = (expected->message.lparam - received->message.lparam))) goto done;
236 break;
237 case LL_HOOK_KEYBD:
238 if ((ret = expected->ll_hook_kbd.msg - received->ll_hook_kbd.msg)) goto done;
239 if ((ret = (expected->ll_hook_kbd.scan - received->ll_hook_kbd.scan))) goto done;
240 if ((ret = expected->ll_hook_kbd.vkey - received->ll_hook_kbd.vkey)) goto done;
241 if ((ret = (expected->ll_hook_kbd.flags - received->ll_hook_kbd.flags))) goto done;
242 if ((ret = (expected->ll_hook_kbd.extra - received->ll_hook_kbd.extra))) goto done;
243 break;
244 case LL_HOOK_MOUSE:
245 if ((ret = expected->ll_hook_ms.msg - received->ll_hook_ms.msg)) goto done;
246 if ((ret = expected->ll_hook_ms.point.x - received->ll_hook_ms.point.x)) goto done;
247 if ((ret = expected->ll_hook_ms.point.y - received->ll_hook_ms.point.y)) goto done;
248 if ((ret = (expected->ll_hook_ms.data - received->ll_hook_ms.data))) goto done;
249 if ((ret = (expected->ll_hook_ms.flags - received->ll_hook_ms.flags))) goto done;
250 if (0 && (ret = expected->ll_hook_ms.time - received->ll_hook_ms.time)) goto done;
251 if ((ret = (expected->ll_hook_ms.extra - received->ll_hook_ms.extra))) goto done;
252 break;
254 if ((ret = expected->raw_input.hwnd - received->raw_input.hwnd)) goto done;
255 if ((ret = expected->raw_input.code - received->raw_input.code)) goto done;
256 if ((ret = expected->raw_input.kbd.MakeCode - received->raw_input.kbd.MakeCode)) goto done;
257 if ((ret = expected->raw_input.kbd.Flags - received->raw_input.kbd.Flags)) goto done;
258 if ((ret = expected->raw_input.kbd.VKey - received->raw_input.kbd.VKey)) goto done;
259 if ((ret = expected->raw_input.kbd.Message - received->raw_input.kbd.Message)) goto done;
260 if ((ret = expected->raw_input.kbd.ExtraInformation - received->raw_input.kbd.ExtraInformation)) goto done;
261 break;
262 }
263
264done:
265 if (ret && broken( expected->broken )) return ret;
266
267 switch (received->func)
268 {
269 case MSG_TEST_WIN:
270 todo_wine_if( expected->todo || expected->todo_value )
271 ok_(file, line)( !ret, "got MSG_TEST_WIN hwnd %p, msg %s, wparam %#Ix, lparam %#Ix\n", received->message.hwnd,
272 debugstr_wm(received->message.msg), received->message.wparam, received->message.lparam );
273 return ret;
274 case LL_HOOK_KEYBD:
275 todo_wine_if( expected->todo || expected->todo_value )
276 ok_(file, line)( !ret, "got LL_HOOK_KEYBD msg %s scan %#x, vkey %s, flags %#x, extra %#Ix\n", debugstr_wm(received->ll_hook_kbd.msg),
277 received->ll_hook_kbd.scan, debugstr_vk(received->ll_hook_kbd.vkey), received->ll_hook_kbd.flags,
278 received->ll_hook_kbd.extra );
279 return ret;
280 case LL_HOOK_MOUSE:
281 todo_wine_if( expected->todo || expected->todo_value )
282 ok_(file, line)( !ret, "got LL_HOOK_MOUSE msg %s, point %s, data %#x, flags %#x, time %u, extra %#Ix\n", debugstr_wm(received->ll_hook_ms.msg),
283 wine_dbgstr_point(&received->ll_hook_ms.point), received->ll_hook_ms.data, received->ll_hook_ms.flags, received->ll_hook_ms.time,
284 received->ll_hook_ms.extra );
285 return ret;
287 todo_wine_if( expected->todo || expected->todo_value )
288 ok_(file, line)( !ret, "got WM_INPUT key hwnd %p, code %d, make_code %#x, flags %#x, vkey %s, message %s, extra %#lx\n",
289 received->raw_input.hwnd, received->raw_input.code, received->raw_input.kbd.MakeCode,
290 received->raw_input.kbd.Flags, debugstr_vk(received->raw_input.kbd.VKey),
291 debugstr_wm(received->raw_input.kbd.Message), received->raw_input.kbd.ExtraInformation );
292 return ret;
293 }
294
295 switch (expected->func)
296 {
297 case MSG_TEST_WIN:
298 todo_wine_if( expected->todo || expected->todo_value )
299 ok_(file, line)( !ret, "MSG_TEST_WIN hwnd %p, %s, wparam %#Ix, lparam %#Ix\n", expected->message.hwnd,
300 debugstr_wm(expected->message.msg), expected->message.wparam, expected->message.lparam );
301 break;
302 case LL_HOOK_KEYBD:
303 todo_wine_if( expected->todo || expected->todo_value )
304 ok_(file, line)( !ret, "LL_HOOK_KBD msg %s scan %#x, vkey %s, flags %#x, extra %#Ix\n", debugstr_wm(expected->ll_hook_kbd.msg),
305 expected->ll_hook_kbd.scan, debugstr_vk(expected->ll_hook_kbd.vkey), expected->ll_hook_kbd.flags,
306 expected->ll_hook_kbd.extra );
307 break;
308 case LL_HOOK_MOUSE:
309 todo_wine_if( expected->todo || expected->todo_value )
310 ok_(file, line)( !ret, "LL_HOOK_MOUSE msg %s, point %s, data %#x, flags %#x, time %u, extra %#Ix\n", debugstr_wm(received->ll_hook_ms.msg),
311 wine_dbgstr_point(&received->ll_hook_ms.point), received->ll_hook_ms.data, received->ll_hook_ms.flags, received->ll_hook_ms.time,
312 received->ll_hook_ms.extra );
313 return ret;
315 todo_wine_if( expected->todo || expected->todo_value )
316 ok_(file, line)( !ret, "got WM_INPUT key hwnd %p, code %d, make_code %#x, flags %#x, vkey %s, message %s, extra %#lx\n",
317 expected->raw_input.hwnd, expected->raw_input.code, expected->raw_input.kbd.MakeCode,
318 expected->raw_input.kbd.Flags, debugstr_vk(expected->raw_input.kbd.VKey),
319 debugstr_wm(expected->raw_input.kbd.Message), expected->raw_input.kbd.ExtraInformation );
320 return ret;
321 }
322
323 return 0;
324}
325
326#define ok_seq( a ) ok_seq_( __FILE__, __LINE__, a, #a )
327static void ok_seq_( const char *file, int line, const struct user_call *expected, const char *context )
328{
329 const struct user_call *received = current_sequence;
330 UINT i = 0, ret;
331
332 while (expected->func || received->func)
333 {
334 winetest_push_context( "%s %u%s%s", context, i++, !expected->func ? " (spurious)" : "",
335 !received->func ? " (missing)" : "" );
337 if (ret && expected->todo && expected->func &&
338 !strcmp( winetest_platform, "wine" ))
339 expected++;
340 else if (ret && broken(expected->broken))
341 expected++;
342 else
343 {
344 if (expected->func) expected++;
345 if (received->func) received++;
346 }
348 }
349
352}
353
356
358{
359 struct user_call call =
360 {
361 .func = LL_HOOK_KEYBD, .ll_hook_kbd =
362 {
363 .msg = msg, .scan = info->scanCode, .vkey = info->vkCode,
364 .flags = info->flags, .extra = info->dwExtraInfo
365 }
366 };
368 {
370 ok( index < ARRAY_SIZE(current_sequence), "got %lu calls\n", index );
371 current_sequence[index] = call;
372 }
373}
374
376{
377 struct user_call call =
378 {
379 .func = LL_HOOK_MOUSE, .ll_hook_ms =
380 {
381 .msg = msg, .point = info->pt, .data = info->mouseData, .flags = info->flags,
382 .time = info->time, .extra = info->dwExtraInfo
383 }
384 };
386 {
388 ok( index < ARRAY_SIZE(current_sequence), "got %lu calls\n", index );
389 current_sequence[index] = call;
390 }
391}
392
394{
395 RAWINPUT rawinput;
396 UINT size = sizeof(rawinput), ret;
397
398 ret = GetRawInputData( handle, RID_INPUT, &rawinput, &size, sizeof(RAWINPUTHEADER) );
399 ok_ne( ret, (UINT)-1, UINT, "%u" );
400
401 if (rawinput.header.dwType == RIM_TYPEKEYBOARD)
402 {
403 struct user_call call =
404 {
406 .raw_input = {.hwnd = hwnd, .code = GET_RAWINPUT_CODE_WPARAM(wparam), .kbd = rawinput.data.keyboard}
407 };
409 ok( index < ARRAY_SIZE(current_sequence), "got %lu calls\n", index );
410 if (!append_message_hwnd) call.message.hwnd = 0;
411 current_sequence[index] = call;
412 }
413}
414
416{
417 if (msg == WM_INPUT) append_rawinput_message( hwnd, wparam, (HRAWINPUT)lparam );
418 else if (!p_accept_message || p_accept_message( msg ))
419 {
420 struct user_call call = {.func = MSG_TEST_WIN, .message = {.hwnd = hwnd, .msg = msg, .wparam = wparam, .lparam = lparam}};
422 ok( index < ARRAY_SIZE(current_sequence), "got %lu calls\n", index );
423 if (!append_message_hwnd) call.message.hwnd = 0;
424 current_sequence[index] = call;
425 }
426}
427
429{
431 return DefWindowProcW( hwnd, msg, wparam, lparam );
432}
433
434/* globals */
435#define DESKTOP_ALL_ACCESS 0x01ff
436
437static BOOL (WINAPI *pEnableMouseInPointer)( BOOL );
438static BOOL (WINAPI *pIsMouseInPointerEnabled)(void);
439static BOOL (WINAPI *pGetCurrentInputMessageSource)( INPUT_MESSAGE_SOURCE *source );
440static BOOL (WINAPI *pGetPointerType)(UINT32, POINTER_INPUT_TYPE*);
441static BOOL (WINAPI *pGetPointerInfo)(UINT32, POINTER_INFO*);
442static BOOL (WINAPI *pGetPointerInfoHistory)(UINT32, UINT32*, POINTER_INFO*);
443static BOOL (WINAPI *pGetPointerFrameInfo)(UINT32, UINT32*, POINTER_INFO*);
444static BOOL (WINAPI *pGetPointerFrameInfoHistory)(UINT32, UINT32*, UINT32*, POINTER_INFO*);
445static int (WINAPI *pGetMouseMovePointsEx) (UINT, LPMOUSEMOVEPOINT, LPMOUSEMOVEPOINT, int, DWORD);
446static UINT (WINAPI *pGetRawInputDeviceList) (PRAWINPUTDEVICELIST, PUINT, UINT);
447static UINT (WINAPI *pGetRawInputDeviceInfoW) (HANDLE, UINT, void *, UINT *);
448static UINT (WINAPI *pGetRawInputDeviceInfoA) (HANDLE, UINT, void *, UINT *);
449static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
450static HKL (WINAPI *pLoadKeyboardLayoutEx)(HKL, const WCHAR *, UINT);
451
452/**********************adapted from input.c **********************************/
453
455
456static void init_function_pointers(void)
457{
458 HMODULE hdll = GetModuleHandleA("user32");
459
460#define GET_PROC(func) \
461 if (!(p ## func = (void*)GetProcAddress(hdll, #func))) \
462 trace("GetProcAddress(%s) failed\n", #func)
463
464 GET_PROC(EnableMouseInPointer);
465 GET_PROC(IsMouseInPointerEnabled);
466 GET_PROC(GetCurrentInputMessageSource);
467 GET_PROC(GetMouseMovePointsEx);
469 GET_PROC(GetPointerInfoHistory);
470 GET_PROC(GetPointerFrameInfo);
471 GET_PROC(GetPointerFrameInfoHistory);
477
478 hdll = GetModuleHandleA("kernel32");
480#undef GET_PROC
481
482 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 ))
483 is_wow64 = FALSE;
484}
485
486#define run_in_process( a, b ) run_in_process_( __FILE__, __LINE__, a, b )
487static void run_in_process_( const char *file, int line, char **argv, const char *args )
488{
489 STARTUPINFOA startup = {.cb = sizeof(STARTUPINFOA)};
491 char cmdline[MAX_PATH * 2];
492 DWORD ret;
493
494 sprintf( cmdline, "%s %s %s", argv[0], argv[1], args );
496 ok_(file, line)( ret, "CreateProcessA failed, error %lu\n", GetLastError() );
497 if (!ret) return;
498
499 wait_child_process( info.hProcess );
500 CloseHandle( info.hThread );
501 CloseHandle( info.hProcess );
502}
503
504#define run_in_desktop( a, b, c ) run_in_desktop_( __FILE__, __LINE__, a, b, c )
505static void run_in_desktop_( const char *file, int line, char **argv,
506 const char *args, BOOL input )
507{
508 const char *desktop_name = "WineTest Desktop";
509 STARTUPINFOA startup = {.cb = sizeof(STARTUPINFOA)};
511 HDESK old_desktop, desktop;
512 char cmdline[MAX_PATH * 2];
513 DWORD ret;
514
515 old_desktop = OpenInputDesktop( 0, FALSE, DESKTOP_ALL_ACCESS );
516 ok_(file, line)( !!old_desktop, "OpenInputDesktop failed, error %lu\n", GetLastError() );
517 desktop = CreateDesktopA( desktop_name, NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
518 ok_(file, line)( !!desktop, "CreateDesktopA failed, error %lu\n", GetLastError() );
519 if (input)
520 {
521 ret = SwitchDesktop( desktop );
522 ok_(file, line)( ret, "SwitchDesktop failed, error %lu\n", GetLastError() );
523 }
524
525 startup.lpDesktop = (char *)desktop_name;
526 sprintf( cmdline, "%s %s %s", argv[0], argv[1], args );
528 ok_(file, line)( ret, "CreateProcessA failed, error %lu\n", GetLastError() );
529 if (!ret) return;
530
531 wait_child_process( info.hProcess );
532 CloseHandle( info.hThread );
533 CloseHandle( info.hProcess );
534
535 if (input)
536 {
537 ret = SwitchDesktop( old_desktop );
538 ok_(file, line)( ret, "SwitchDesktop failed, error %lu\n", GetLastError() );
539 }
540 ret = CloseDesktop( desktop );
541 ok_(file, line)( ret, "CloseDesktop failed, error %lu\n", GetLastError() );
542 ret = CloseDesktop( old_desktop );
543 ok_(file, line)( ret, "CloseDesktop failed, error %lu\n", GetLastError() );
544}
545
546#define wait_messages( a, b ) msg_wait_for_events_( __FILE__, __LINE__, 0, NULL, a, b )
547#define msg_wait_for_events( a, b, c ) msg_wait_for_events_( __FILE__, __LINE__, a, b, c, FALSE )
548static DWORD msg_wait_for_events_( const char *file, int line, DWORD count, HANDLE *events, DWORD timeout, BOOL append_peeked )
549{
550 DWORD ret, end = GetTickCount() + min( timeout, 5000 );
551 MSG msg;
552
554 {
555 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ))
556 {
557 if (append_peeked) append_message( msg.hwnd, msg.message, msg.wParam, msg.lParam );
560 }
561 if (ret < count) return ret;
562 if (timeout >= 5000) continue;
563 if (end <= GetTickCount()) timeout = 0;
564 else timeout = end - GetTickCount();
565 }
566
567 if (timeout >= 5000) ok_(file, line)( 0, "MsgWaitForMultipleObjects returned %#lx\n", ret );
568 else ok_(file, line)( ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %#lx\n", ret );
569 return ret;
570}
571
573{
574 return (message >= WM_KEYFIRST && message <= WM_KEYLAST);
575}
576
578{
579 return (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST);
580}
581
582#define create_foreground_window( a ) create_foreground_window_( __FILE__, __LINE__, a, 5 )
584{
585 for (;;)
586 {
587 HWND hwnd;
588 BOOL ret;
589
590 hwnd = CreateWindowW( L"static", NULL, WS_POPUP | (fullscreen ? 0 : WS_VISIBLE),
591 100, 100, 200, 200, NULL, NULL, NULL, NULL );
592 ok_(file, line)( hwnd != NULL, "CreateWindowW failed, error %lu\n", GetLastError() );
593
594 if (fullscreen)
595 {
596 HMONITOR hmonitor = MonitorFromWindow( hwnd, MONITOR_DEFAULTTOPRIMARY );
597 MONITORINFO mi = {.cbSize = sizeof(MONITORINFO)};
598
599 ok_(file, line)( hmonitor != NULL, "MonitorFromWindow failed, error %lu\n", GetLastError() );
600 ret = GetMonitorInfoW( hmonitor, &mi );
601 ok_(file, line)( ret, "GetMonitorInfoW failed, error %lu\n", GetLastError() );
604 ok_(file, line)( ret, "SetWindowPos failed, error %lu\n", GetLastError() );
605 }
606 wait_messages( 100, FALSE );
607
608 if (GetForegroundWindow() == hwnd) return hwnd;
609 ok_(file, line)( retries > 0, "failed to create foreground window\n" );
610 if (!retries--) return hwnd;
611
613 ok_(file, line)( ret, "DestroyWindow failed, error %lu\n", GetLastError() );
614 wait_messages( 0, FALSE );
615 }
616}
617
618/* try to make sure pending X events have been processed before continuing */
619static void empty_message_queue(void)
620{
621 MSG msg;
622 int diff = 200;
623 int min_timeout = 50;
624 DWORD time = GetTickCount() + diff;
625
626 while (diff > 0)
627 {
628 if (MsgWaitForMultipleObjects(0, NULL, FALSE, min_timeout, QS_ALLINPUT) == WAIT_TIMEOUT) break;
629 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
630 {
631 if (is_keyboard_message(msg.message) || is_mouse_message(msg.message))
632 ok(msg.time != 0, "message %#x has time set to 0\n", msg.message);
633
636 }
637 diff = time - GetTickCount();
638 }
639}
640
642{
646 struct user_call expect[8];
652};
653
655{
656 KBDLLHOOKSTRUCT *hook_info = (KBDLLHOOKSTRUCT *)lparam;
657
658 if (code == HC_ACTION)
659 {
660 append_ll_hook_kbd( wparam, hook_info );
661
662if(0) /* For some reason not stable on Wine */
663{
665 ok(!(GetAsyncKeyState(hook_info->vkCode) & 0x8000), "key %lx should be up\n", hook_info->vkCode);
666 else if (wparam == WM_KEYUP || wparam == WM_SYSKEYUP)
667 ok(GetAsyncKeyState(hook_info->vkCode) & 0x8000, "key %lx should be down\n", hook_info->vkCode);
668}
669
670 if (winetest_debug > 1)
671 trace("Hook: w=%Ix vk:%8lx sc:%8lx fl:%8lx %Ix\n", wparam,
672 hook_info->vkCode, hook_info->scanCode, hook_info->flags, hook_info->dwExtraInfo);
673 }
674 return CallNextHookEx( 0, code, wparam, lparam );
675}
676
677#define check_keyboard_state( a, b ) check_keyboard_state_( __LINE__, a, b )
678static void check_keyboard_state_( int line, const BYTE expect_state[256], const BOOL todo_state[256] )
679{
680 BYTE state[256];
681 UINT i;
682
684 for (i = 0; i < ARRAY_SIZE(state); i++)
685 {
686 todo_wine_if( todo_state[i] )
687 ok_(__FILE__, line)( (expect_state[i] & 0x80) == (state[i] & 0x80),
688 "got %s: %#x\n", debugstr_vk( i ), state[i] );
689 }
690}
691
692#define check_keyboard_async( a, b ) check_keyboard_async_( __LINE__, a, b )
693static void check_keyboard_async_( int line, const BYTE expect_state[256], const BOOL todo_state[256] )
694{
695 UINT i;
696
697 /* TODO: figure out if the async state for vkey 0 provides any information and
698 * add it to the check. */
699 for (i = 1; i < 256; i++)
700 {
702 todo_wine_if( todo_state[i] )
703 ok_(__FILE__, line)( (expect_state[i] & 0x80) == (state & 0x80),
704 "async got %s: %#x\n", debugstr_vk( i ), state );
705 }
706}
707
708static void clear_keyboard_state( void )
709{
710 static BYTE empty_state[256] = {0};
712 BYTE lock_keys[] = {VK_NUMLOCK, VK_CAPITAL, VK_SCROLL};
713 UINT i;
714
715 for (i = 0; i < ARRAY_SIZE(lock_keys); ++i)
716 {
717 if (GetKeyState( lock_keys[i] ) & 0x0001)
718 {
719 input.ki.wVk = lock_keys[i];
720 SendInput( 1, &input, sizeof(input) );
721 input.ki.dwFlags = KEYEVENTF_KEYUP;
722 SendInput( 1, &input, sizeof(input) );
723 wait_messages( 5, FALSE );
726 }
727 }
728
729 SetKeyboardState( empty_state );
730}
731
732#define check_send_input_keyboard_test( a, b ) check_send_input_keyboard_test_( a, #a, b )
733static void check_send_input_keyboard_test_( const struct send_input_keyboard_test *test, const char *context, BOOL peeked )
734{
736 UINT i;
737
740
741 for (i = 0; test->vkey || test->scan; i++, test++)
742 {
743 winetest_push_context( "%u", i );
744
745 input.ki.wScan = test->flags & (KEYEVENTF_SCANCODE | KEYEVENTF_UNICODE) ? test->scan : (i + 1);
746 input.ki.dwFlags = test->flags;
747 input.ki.wVk = test->vkey;
748 ok_ret( 1, SendInput( 1, &input, sizeof(input) ) );
749 wait_messages( 5, peeked );
750
751 ok_seq( test->expect );
752 check_keyboard_state( test->expect_state, test->todo_state );
753 if (test->async) check_keyboard_async( test->expect_async, test->todo_async );
754
756 }
757
760}
761
763{
765}
766
768{
769 typedef struct
770 {
771 UINT64 pCharModifiers;
772 UINT64 pVkToWcharTable;
773 UINT64 pDeadKey;
774 UINT64 pKeyNames;
775 UINT64 pKeyNamesExt;
776 UINT64 pKeyNamesDead;
777 UINT64 pusVSCtoVK;
778 BYTE bMaxVSCtoVK;
779 UINT64 pVSCtoVK_E0;
780 UINT64 pVSCtoVK_E1;
781 DWORD fLocaleFlags;
782 } KBDTABLES64;
783
784 WCHAR layout_path[MAX_PATH] = {L"System\\CurrentControlSet\\Control\\Keyboard Layouts\\"}, value[MAX_PATH];
785 KBDTABLES *(CDECL *pKbdLayerDescriptor)(void);
786 DWORD value_size = sizeof(value), flags;
789
790 ok_ret( 1, GetKeyboardLayoutNameW( layout_path + wcslen(layout_path) ) );
792 ok_ret( 0, RegGetValueW( HKEY_LOCAL_MACHINE, layout_path, L"Layout File", RRF_RT_REG_SZ,
793 NULL, (void *)&value, &value_size) );
794
797 ok_ne( NULL, module, HMODULE, "%p" );
798 pKbdLayerDescriptor = (void *)GetProcAddress( module, "KbdLayerDescriptor" );
800 ok_ne( NULL, pKbdLayerDescriptor, void *, "%p" );
801 /* FIXME: Wine doesn't implement ALTGR behavior */
802 if (!pKbdLayerDescriptor) return FALSE;
803 tables = pKbdLayerDescriptor();
804 ok_ne( NULL, tables, KBDTABLES *, "%p" );
805 flags = is_wow64 ? ((KBDTABLES64 *)tables)->fLocaleFlags : tables->fLocaleFlags;
806 ok_ret( 1, FreeLibrary( module ) );
807
808 trace( "%s flags %#lx\n", debugstr_w(value), flags );
809 return !!(flags & KLLF_ALTGR);
810}
811
812static void get_test_scan( WORD vkey, WORD *scan, WCHAR *wch, WCHAR *wch_shift )
813{
815 BYTE state[256] = {0};
816
818 ok_ne( 0, *scan, WORD, "%#x" );
819 ok_ret( 1, ToUnicodeEx( vkey, *scan, state, wch, 1, 0, hkl ) );
820 state[VK_SHIFT] = 0x80;
821 ok_ret( 1, ToUnicodeEx( vkey, *scan, state, wch_shift, 1, 0, hkl ) );
822}
823
824static void test_SendInput_keyboard_messages( WORD vkey, WORD scan, WCHAR wch, WCHAR wch_shift, WCHAR wch_control, HKL hkl )
825{
826#define WIN_MSG(m, w, l, ...) {.func = MSG_TEST_WIN, .message = {.msg = m, .wparam = w, .lparam = l}, ## __VA_ARGS__}
827#define KBD_HOOK(m, s, v, f, ...) {.func = LL_HOOK_KEYBD, .ll_hook_kbd = {.msg = m, .scan = s, .vkey = v, .flags = f}, ## __VA_ARGS__}
828
829#define KEY_HOOK_(m, s, v, f, ...) KBD_HOOK( m, s, v, LLKHF_INJECTED | (m == WM_KEYUP || m == WM_SYSKEYUP ? LLKHF_UP : 0) | (f), ## __VA_ARGS__ )
830#define KEY_HOOK(m, s, v, ...) KEY_HOOK_( m, s, v, 0, ## __VA_ARGS__ )
831
832#define KEY_MSG_(m, s, v, f, ...) WIN_MSG( m, v, MAKELONG(1, (s) | (m == WM_KEYUP || m == WM_SYSKEYUP ? (KF_UP | KF_REPEAT) : 0) | (f)), ## __VA_ARGS__ )
833#define KEY_MSG(m, s, v, ...) KEY_MSG_( m, s, v, 0, ## __VA_ARGS__ )
834
835 struct send_input_keyboard_test lmenu_vkey[] =
836 {
837 {.vkey = VK_LMENU, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80},
838 .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_LMENU, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN), {0}}},
839 {
840 .vkey = vkey, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80, /*[vkey] = 0x80*/},
841 .expect =
842 {
843 KEY_HOOK_(WM_SYSKEYDOWN, 2, vkey, LLKHF_ALTDOWN, .todo_value = TRUE),
847 {0}
848 }
849 },
850 {.vkey = vkey, .flags = KEYEVENTF_KEYUP, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80},
851 .expect = {KEY_HOOK_(WM_SYSKEYUP, 3, vkey, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYUP, 3, vkey, KF_ALTDOWN), {0}}},
852 {.vkey = VK_LMENU, .flags = KEYEVENTF_KEYUP,
853 .expect = {KEY_HOOK(WM_KEYUP, 4, VK_LMENU), KEY_MSG(WM_KEYUP, 4, VK_MENU), {0}}},
854 {0},
855 };
856
857 struct send_input_keyboard_test lmenu_vkey_peeked[] =
858 {
859 {.vkey = VK_LMENU, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80},
860 .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_LMENU, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN), {0}}},
861 {
862 .vkey = vkey, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80, /*[vkey] = 0x80*/},
863 .expect =
864 {
865 KEY_HOOK_(WM_SYSKEYDOWN, 2, vkey, LLKHF_ALTDOWN, .todo_value = TRUE),
868 {0}
869 }
870 },
871 {.vkey = vkey, .flags = KEYEVENTF_KEYUP, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80},
872 .expect = {KEY_HOOK_(WM_SYSKEYUP, 3, vkey, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYUP, 3, vkey, KF_ALTDOWN), {0}}},
873 {.vkey = VK_LMENU, .flags = KEYEVENTF_KEYUP,
874 .expect = {KEY_HOOK(WM_KEYUP, 4, VK_LMENU), KEY_MSG(WM_KEYUP, 4, VK_MENU), {0}}},
875 {0},
876 };
877
878 struct send_input_keyboard_test lcontrol_vkey[] =
879 {
880 {.vkey = VK_LCONTROL, .expect_state = {[VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80},
881 .expect = {KEY_HOOK(WM_KEYDOWN, 1, VK_LCONTROL), KEY_MSG(WM_KEYDOWN, 1, VK_CONTROL), {0}}},
882 {.vkey = vkey, .expect_state = {[VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80, /*[vkey] = 0x80*/},
883 .expect = {KEY_HOOK(WM_KEYDOWN, 2, vkey), KEY_MSG(WM_KEYDOWN, 2, vkey), WIN_MSG(WM_CHAR, wch_control, MAKELONG(1, 2)), {0}}},
884 {.vkey = vkey, .flags = KEYEVENTF_KEYUP, .expect_state = {[VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80},
885 .expect = {KEY_HOOK(WM_KEYUP, 3, vkey), KEY_MSG(WM_KEYUP, 3, vkey), {0}}},
886 {.vkey = VK_LCONTROL, .flags = KEYEVENTF_KEYUP,
887 .expect = {KEY_HOOK(WM_KEYUP, 4, VK_LCONTROL), KEY_MSG(WM_KEYUP, 4, VK_CONTROL), {0}}},
888 {0},
889 };
890
891 struct send_input_keyboard_test lmenu_lcontrol_vkey[] =
892 {
893 {.vkey = VK_LMENU, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80},
894 .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_LMENU, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN), {0}}},
895 {.vkey = VK_LCONTROL, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80, [VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80},
897 {.vkey = vkey, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80, [VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80, /*[vkey] = 0x80*/},
898 .expect = {KEY_HOOK(WM_KEYDOWN, 3, vkey), KEY_MSG_(WM_KEYDOWN, 3, vkey, KF_ALTDOWN), {0}}},
899 {.vkey = vkey, .flags = KEYEVENTF_KEYUP, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80, [VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80},
900 .expect = {KEY_HOOK(WM_KEYUP, 4, vkey), KEY_MSG_(WM_KEYUP, 4, vkey, KF_ALTDOWN), {0}}},
901 {.vkey = VK_LCONTROL, .flags = KEYEVENTF_KEYUP, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80},
902 .expect = {KEY_HOOK_(WM_SYSKEYUP, 5, VK_LCONTROL, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYUP, 5, VK_CONTROL, KF_ALTDOWN), {0}}},
903 {.vkey = VK_LMENU, .flags = KEYEVENTF_KEYUP,
904 .expect = {KEY_HOOK(WM_KEYUP, 6, VK_LMENU), KEY_MSG(WM_KEYUP, 6, VK_MENU), {0}}},
905 {0},
906 };
907
908 struct send_input_keyboard_test shift_vkey[] =
909 {
910 {.vkey = VK_LSHIFT, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80},
911 .expect = {KEY_HOOK(WM_KEYDOWN, 1, VK_LSHIFT), KEY_MSG(WM_KEYDOWN, 1, VK_SHIFT), {0}}},
912 {.vkey = vkey, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80, /*[vkey] = 0x80*/},
913 .expect = {KEY_HOOK(WM_KEYDOWN, 2, vkey), KEY_MSG(WM_KEYDOWN, 2, vkey), WIN_MSG(WM_CHAR, wch_shift, MAKELONG(1, 2)), {0}}},
914 {.vkey = vkey, .flags = KEYEVENTF_KEYUP, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80},
915 .expect = {KEY_HOOK(WM_KEYUP, 3, vkey), KEY_MSG(WM_KEYUP, 3, vkey), {0}}},
916 {.vkey = VK_LSHIFT, .flags = KEYEVENTF_KEYUP,
917 .expect = {KEY_HOOK(WM_KEYUP, 4, VK_LSHIFT), KEY_MSG(WM_KEYUP, 4, VK_SHIFT), {0}}},
918 {0},
919 };
920
921 static const struct send_input_keyboard_test rshift[] =
922 {
923 {.vkey = VK_RSHIFT, .expect_state = {[VK_SHIFT] = 0x80, [VK_RSHIFT] = 0x80}, .todo_state = {[VK_RSHIFT] = TRUE, [VK_LSHIFT] = TRUE},
924 .expect = {KEY_HOOK_(WM_KEYDOWN, 1, VK_RSHIFT, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG(WM_KEYDOWN, 1, VK_SHIFT), {0}}},
925 {.vkey = VK_RSHIFT, .flags = KEYEVENTF_KEYUP, .expect_state = {0},
926 .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_RSHIFT, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG(WM_KEYUP, 2, VK_SHIFT), {0}}},
927 {0},
928 };
929 static const struct send_input_keyboard_test lshift_ext[] =
930 {
931 {.vkey = VK_LSHIFT, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_SHIFT] = 0x80, [VK_RSHIFT] = 0x80},
934 .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_LSHIFT, LLKHF_EXTENDED), KEY_MSG(WM_KEYUP, 2, VK_SHIFT), {0}}},
935 {0},
936 };
937 static const struct send_input_keyboard_test rshift_ext[] =
938 {
939 {.vkey = VK_RSHIFT, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_SHIFT] = 0x80, [VK_RSHIFT] = 0x80},
941 {.vkey = VK_RSHIFT, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, .expect_state = {0},
942 .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_RSHIFT, LLKHF_EXTENDED), KEY_MSG(WM_KEYUP, 2, VK_SHIFT), {0}}},
943 {0},
944 };
945 static const struct send_input_keyboard_test shift[] =
946 {
947 {.vkey = VK_SHIFT, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80},
948 .expect = {KEY_HOOK(WM_KEYDOWN, 1, VK_LSHIFT), KEY_MSG(WM_KEYDOWN, 1, VK_SHIFT), {0}}},
949 {.vkey = VK_SHIFT, .flags = KEYEVENTF_KEYUP,
950 .expect = {KEY_HOOK(WM_KEYUP, 2, VK_LSHIFT), KEY_MSG(WM_KEYUP, 2, VK_SHIFT), {0}}},
951 {0},
952 };
953 static const struct send_input_keyboard_test shift_ext[] =
954 {
955 {.vkey = VK_SHIFT, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_SHIFT] = 0x80, [VK_RSHIFT] = 0x80},
956 .expect = {KEY_HOOK_(WM_KEYDOWN, 1, VK_LSHIFT, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG(WM_KEYDOWN, 1, VK_SHIFT), {0}}},
958 .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_LSHIFT, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG(WM_KEYUP, 2, VK_SHIFT), {0}}},
959 {0},
960 };
961
962 static const struct send_input_keyboard_test rcontrol[] =
963 {
964 {.vkey = VK_RCONTROL, .expect_state = {[VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80},
965 .expect = {KEY_HOOK(WM_KEYDOWN, 1, VK_RCONTROL), KEY_MSG(WM_KEYDOWN, 1, VK_CONTROL), {0}}},
966 {.vkey = VK_RCONTROL, .flags = KEYEVENTF_KEYUP,
967 .expect = {KEY_HOOK(WM_KEYUP, 2, VK_RCONTROL), KEY_MSG(WM_KEYUP, 2, VK_CONTROL), {0}}},
968 {0},
969 };
970 static const struct send_input_keyboard_test lcontrol_ext[] =
971 {
972 {.vkey = VK_LCONTROL, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_CONTROL] = 0x80, [VK_RCONTROL] = 0x80},
976 {0},
977 };
978 static const struct send_input_keyboard_test rcontrol_ext[] =
979 {
980 {.vkey = VK_RCONTROL, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_CONTROL] = 0x80, [VK_RCONTROL] = 0x80},
984 {0},
985 };
986 static const struct send_input_keyboard_test control[] =
987 {
988 {.vkey = VK_CONTROL, .expect_state = {[VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80},
989 .expect = {KEY_HOOK(WM_KEYDOWN, 1, VK_LCONTROL), KEY_MSG(WM_KEYDOWN, 1, VK_CONTROL), {0}}},
990 {.vkey = VK_CONTROL, .flags = KEYEVENTF_KEYUP, .expect_state = {0},
991 .expect = {KEY_HOOK(WM_KEYUP, 2, VK_LCONTROL), KEY_MSG(WM_KEYUP, 2, VK_CONTROL), {0}}},
992 {0},
993 };
994 static const struct send_input_keyboard_test control_ext[] =
995 {
996 {.vkey = VK_CONTROL, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_CONTROL] = 0x80, [VK_RCONTROL] = 0x80},
1000 {0},
1001 };
1002
1003 static const struct send_input_keyboard_test rmenu[] =
1004 {
1005 {.vkey = VK_RMENU, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80},
1006 .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_RMENU, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN), {0}}},
1007 {.vkey = VK_RMENU, .flags = KEYEVENTF_KEYUP,
1008 .expect = {KEY_HOOK(WM_KEYUP, 2, VK_RMENU, .todo_value = TRUE), KEY_MSG(WM_SYSKEYUP, 2, VK_MENU), WIN_MSG(WM_SYSCOMMAND, SC_KEYMENU, 0), {0}}},
1009 {0},
1010 };
1011 static const struct send_input_keyboard_test lmenu_ext[] =
1012 {
1013 {.vkey = VK_LMENU, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_MENU] = 0x80, [VK_RMENU] = 0x80},
1015 {.vkey = VK_LMENU, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY,
1017 {0},
1018 };
1019 static const struct send_input_keyboard_test rmenu_ext[] =
1020 {
1021 {.vkey = VK_RMENU, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_MENU] = 0x80, [VK_RMENU] = 0x80},
1023 {.vkey = VK_RMENU, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY,
1025 {0},
1026 };
1027 static const struct send_input_keyboard_test menu[] =
1028 {
1029 {.vkey = VK_MENU, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80},
1030 .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_LMENU, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN), {0}}},
1031 {.vkey = VK_MENU, .flags = KEYEVENTF_KEYUP, .expect_state = {0},
1032 .expect = {KEY_HOOK(WM_KEYUP, 2, VK_LMENU, .todo_value = TRUE), KEY_MSG(WM_SYSKEYUP, 2, VK_MENU), WIN_MSG(WM_SYSCOMMAND, SC_KEYMENU, 0), {0}}},
1033 {0},
1034 };
1035 static const struct send_input_keyboard_test menu_ext[] =
1036 {
1037 {.vkey = VK_MENU, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_MENU] = 0x80, [VK_RMENU] = 0x80},
1039 {.vkey = VK_MENU, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY,
1041 {0},
1042 };
1043
1044 static const struct send_input_keyboard_test rmenu_peeked[] =
1045 {
1046 {.vkey = VK_RMENU, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80},
1047 .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_RMENU, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN), {0}}},
1048 {.vkey = VK_RMENU, .flags = KEYEVENTF_KEYUP,
1049 .expect = {KEY_HOOK(WM_KEYUP, 2, VK_RMENU, .todo_value = TRUE), KEY_MSG(WM_SYSKEYUP, 2, VK_MENU), {0}}},
1050 {0},
1051 };
1052 static const struct send_input_keyboard_test lmenu_ext_peeked[] =
1053 {
1054 {.vkey = VK_LMENU, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_MENU] = 0x80, [VK_RMENU] = 0x80},
1056 {.vkey = VK_LMENU, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY,
1057 .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_LMENU, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYUP, 2, VK_MENU, KF_EXTENDED), {0}}},
1058 {0},
1059 };
1060 static const struct send_input_keyboard_test rmenu_ext_peeked[] =
1061 {
1062 {.vkey = VK_RMENU, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_MENU] = 0x80, [VK_RMENU] = 0x80},
1064 {.vkey = VK_RMENU, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY,
1065 .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_RMENU, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYUP, 2, VK_MENU, KF_EXTENDED), {0}}},
1066 {0},
1067 };
1068 static const struct send_input_keyboard_test menu_peeked[] =
1069 {
1070 {.vkey = VK_MENU, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80},
1071 .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_LMENU, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN), {0}}},
1072 {.vkey = VK_MENU, .flags = KEYEVENTF_KEYUP, .expect_state = {0},
1073 .expect = {KEY_HOOK(WM_KEYUP, 2, VK_LMENU, .todo_value = TRUE), KEY_MSG(WM_SYSKEYUP, 2, VK_MENU), {0}}},
1074 {0},
1075 };
1076 static const struct send_input_keyboard_test menu_ext_peeked[] =
1077 {
1078 {.vkey = VK_MENU, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_MENU] = 0x80, [VK_RMENU] = 0x80},
1080 {.vkey = VK_MENU, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY,
1081 .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_RMENU, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYUP, 2, VK_MENU, KF_EXTENDED), {0}}},
1082 {0},
1083 };
1084
1085 struct send_input_keyboard_test rmenu_altgr[] =
1086 {
1087 {
1088 .vkey = VK_RMENU, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80, [VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80},
1089 .expect =
1090 {
1092 KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_RMENU, LLKHF_ALTDOWN, .todo_value = TRUE),
1095 {0}
1096 }
1097 },
1098 {
1099 .vkey = VK_RMENU, .flags = KEYEVENTF_KEYUP,
1100 .expect =
1101 {
1102 KEY_HOOK(WM_KEYUP, 0x21d, VK_LCONTROL),
1106 {0}
1107 }
1108 },
1109 {0},
1110 };
1111 struct send_input_keyboard_test rmenu_ext_altgr[] =
1112 {
1113 {
1114 .vkey = VK_RMENU, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_MENU] = 0x80, [VK_RMENU] = 0x80, [VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80},
1115 .expect =
1116 {
1121 {0}
1122 }
1123 },
1124 {
1126 .expect =
1127 {
1128 KEY_HOOK(WM_KEYUP, 0x21d, VK_LCONTROL),
1129 KEY_HOOK_(WM_KEYUP, 2, VK_RMENU, LLKHF_EXTENDED, .todo_value = TRUE),
1132 {0}
1133 }
1134 },
1135 {0},
1136 };
1137 struct send_input_keyboard_test menu_ext_altgr[] =
1138 {
1139 {
1140 .vkey = VK_MENU, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_MENU] = 0x80, [VK_RMENU] = 0x80, [VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80},
1141 .expect =
1142 {
1147 {0}
1148 }
1149 },
1150 {
1151 .vkey = VK_MENU, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY,
1152 .expect =
1153 {
1154 KEY_HOOK(WM_KEYUP, 0x21d, VK_LCONTROL),
1155 KEY_HOOK_(WM_KEYUP, 2, VK_RMENU, LLKHF_EXTENDED, .todo_value = TRUE),
1158 {0}
1159 }
1160 },
1161 {0},
1162 };
1163
1164 static const struct send_input_keyboard_test lrshift_ext[] =
1165 {
1166 {.vkey = VK_LSHIFT, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80},
1167 .expect = {KEY_HOOK(WM_KEYDOWN, 1, VK_LSHIFT), KEY_MSG(WM_KEYDOWN, 1, VK_SHIFT), {0}}},
1168 {.vkey = VK_RSHIFT, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80, [VK_RSHIFT] = 0x80},
1169 .expect = {KEY_HOOK_(WM_KEYDOWN, 2, VK_RSHIFT, LLKHF_EXTENDED), KEY_MSG_(WM_KEYDOWN, 2, VK_SHIFT, KF_REPEAT, .todo_value = TRUE), {0}}},
1170 {.vkey = VK_RSHIFT, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80},
1171 .expect = {KEY_HOOK_(WM_KEYUP, 3, VK_RSHIFT, LLKHF_EXTENDED), {0, .todo = TRUE}, {0}}},
1172 {.vkey = VK_LSHIFT, .flags = KEYEVENTF_KEYUP,
1173 .expect = {KEY_HOOK(WM_KEYUP, 4, VK_LSHIFT), KEY_MSG(WM_KEYUP, 4, VK_SHIFT), {0}}},
1174 {0},
1175 };
1176
1177 struct send_input_keyboard_test rshift_scan[] =
1178 {
1179 {.scan = 0x36, .flags = KEYEVENTF_SCANCODE, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80},
1180 .expect = {KEY_HOOK(WM_KEYDOWN, 0x36, VK_RSHIFT), KEY_MSG(WM_KEYDOWN, 0x36, VK_SHIFT), {0}}},
1181 {.scan = scan, .flags = KEYEVENTF_SCANCODE, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80, /*[vkey] = 0x80*/},
1182 .expect = {KEY_HOOK(WM_KEYDOWN, scan, vkey), KEY_MSG(WM_KEYDOWN, scan, vkey), WIN_MSG(WM_CHAR, wch_shift, MAKELONG(1, scan)), {0}}},
1183 {.scan = scan, .flags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80},
1184 .expect = {KEY_HOOK(WM_KEYUP, scan, vkey), KEY_MSG(WM_KEYUP, scan, vkey), {0}}},
1185 {.scan = 0x36, .flags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP,
1186 .expect = {KEY_HOOK(WM_KEYUP, 0x36, VK_RSHIFT), KEY_MSG(WM_KEYUP, 0x36, VK_SHIFT), {0}}},
1187 {0},
1188 };
1189
1190 struct send_input_keyboard_test rctrl_scan[] =
1191 {
1192 {.scan = 0xe01d, .flags = KEYEVENTF_SCANCODE, .expect_state = {[VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80},
1193 .expect = {KEY_HOOK(WM_KEYDOWN, 0x1d, VK_LCONTROL), KEY_MSG(WM_KEYDOWN, 0x1d, VK_CONTROL), {0}}},
1194 {.scan = 0xe01d, .flags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP,
1195 .expect = {KEY_HOOK(WM_KEYUP, 0x1d, VK_LCONTROL), KEY_MSG(WM_KEYUP, 0x1d, VK_CONTROL), {0}}},
1196 {.scan = 0x1d, .flags = KEYEVENTF_SCANCODE | KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_CONTROL] = 0x80, [VK_RCONTROL] = 0x80},
1197 .expect = {KEY_HOOK_(WM_KEYDOWN, 0x1d, VK_RCONTROL, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG(WM_KEYDOWN, 0x11d, VK_CONTROL), {0}}},
1198 {.scan = 0x1d, .flags = KEYEVENTF_SCANCODE | KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,
1199 .expect = {KEY_HOOK_(WM_KEYUP, 0x1d, VK_RCONTROL, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG(WM_KEYUP, 0x11d, VK_CONTROL), {0}}},
1200 {0},
1201 };
1202
1203 struct send_input_keyboard_test unicode[] =
1204 {
1205 {.scan = 0x3c0, .flags = KEYEVENTF_UNICODE, .expect_state = {[VK_PACKET] = 0x80},
1206 .expect = {KEY_HOOK(WM_KEYDOWN, 0x3c0, VK_PACKET), KEY_MSG(WM_KEYDOWN, 0, VK_PACKET, .todo_value = TRUE), WIN_MSG(WM_CHAR, 0x3c0, 1), {0}}},
1207 {.scan = 0x3c0, .flags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP,
1208 .expect = {KEY_HOOK(WM_KEYUP, 0x3c0, VK_PACKET, .todo_value = TRUE), KEY_MSG(WM_KEYUP, 0, VK_PACKET, .todo_value = TRUE), {0}}},
1209 {0},
1210 };
1211
1212 struct send_input_keyboard_test lmenu_unicode[] =
1213 {
1214 {.vkey = VK_LMENU, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80},
1215 .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_LMENU, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN), {0}}},
1216 {
1217 .scan = 0x3c0, .flags = KEYEVENTF_UNICODE, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80, [VK_PACKET] = 0x80},
1218 .expect =
1219 {
1220 KEY_HOOK_(WM_SYSKEYDOWN, 0x3c0, VK_PACKET, LLKHF_ALTDOWN, .todo_value = TRUE),
1221 KEY_MSG_(WM_SYSKEYDOWN, 0, VK_PACKET, KF_ALTDOWN, .todo_value = TRUE),
1222 WIN_MSG(WM_SYSCHAR, 0x3c0, MAKELONG(1, KF_ALTDOWN), .todo_value = TRUE),
1224 {0},
1225 },
1226 },
1227 {.scan = 0x3c0, .flags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80},
1228 .expect = {KEY_HOOK_(WM_SYSKEYUP, 0x3c0, VK_PACKET, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYUP, 0, VK_PACKET, KF_ALTDOWN, .todo_value = TRUE), {0}}},
1229 {.vkey = VK_LMENU, .flags = KEYEVENTF_KEYUP,
1230 .expect = {KEY_HOOK(WM_KEYUP, 4, VK_LMENU), KEY_MSG(WM_KEYUP, 4, VK_MENU), {0}}},
1231 {0},
1232 };
1233 struct send_input_keyboard_test lmenu_unicode_peeked[] =
1234 {
1235 {.vkey = VK_LMENU, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80},
1236 .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_LMENU, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN), {0}}},
1237 {
1238 .scan = 0x3c0, .flags = KEYEVENTF_UNICODE, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80, [VK_PACKET] = 0x80},
1239 .expect =
1240 {
1241 KEY_HOOK_(WM_SYSKEYDOWN, 0x3c0, VK_PACKET, LLKHF_ALTDOWN, .todo_value = TRUE),
1242 KEY_MSG_(WM_SYSKEYDOWN, 0, VK_PACKET, KF_ALTDOWN, .todo_value = TRUE),
1243 WIN_MSG(WM_SYSCHAR, 0x3c0, MAKELONG(1, KF_ALTDOWN), .todo_value = TRUE),
1244 {0},
1245 },
1246 },
1247 {.scan = 0x3c0, .flags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80},
1248 .expect = {KEY_HOOK_(WM_SYSKEYUP, 0x3c0, VK_PACKET, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYUP, 0, VK_PACKET, KF_ALTDOWN, .todo_value = TRUE), {0}}},
1249 {.vkey = VK_LMENU, .flags = KEYEVENTF_KEYUP,
1250 .expect = {KEY_HOOK(WM_KEYUP, 4, VK_LMENU), KEY_MSG(WM_KEYUP, 4, VK_MENU), {0}}},
1251 {0},
1252 };
1253
1254 struct send_input_keyboard_test unicode_vkey[] =
1255 {
1256#if defined(__REACTOS__) && defined(_MSC_VER)
1257 {.scan = 0x3c0, .vkey = vkey, .flags = KEYEVENTF_UNICODE, .expect_state = { 0 /*[vkey] = 0x80*/},
1258#else
1259 {.scan = 0x3c0, .vkey = vkey, .flags = KEYEVENTF_UNICODE, .expect_state = {/*[vkey] = 0x80*/},
1260#endif
1261 .expect = {KEY_HOOK(WM_KEYDOWN, 0xc0, vkey), KEY_MSG(WM_KEYDOWN, 0xc0, vkey), WIN_MSG(WM_CHAR, wch, MAKELONG(1, 0xc0)), {0}}},
1262 {.scan = 0x3c0, .vkey = vkey, .flags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP,
1263 .expect = {KEY_HOOK(WM_KEYUP, 0xc0, vkey), KEY_MSG(WM_KEYUP, 0xc0, vkey), {0}}},
1264 {0},
1265 };
1266
1267 struct send_input_keyboard_test unicode_vkey_ctrl[] =
1268 {
1269 {.scan = 0x3c0, .vkey = VK_CONTROL, .flags = KEYEVENTF_UNICODE, .expect_state = {[VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80},
1270 .expect = {KEY_HOOK(WM_KEYDOWN, 0xc0, VK_LCONTROL), KEY_MSG(WM_KEYDOWN, 0xc0, VK_CONTROL), {0}}},
1271 {.scan = 0x3c0, .vkey = VK_CONTROL, .flags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP,
1272 .expect = {KEY_HOOK(WM_KEYUP, 0xc0, VK_LCONTROL), KEY_MSG(WM_KEYUP, 0xc0, VK_CONTROL), {0}}},
1273 {0},
1274 };
1275
1276 struct send_input_keyboard_test unicode_vkey_packet[] =
1277 {
1278 {.scan = 0x3c0, .vkey = VK_PACKET, .flags = KEYEVENTF_UNICODE, .expect_state = {[VK_PACKET] = 0x80},
1279 .expect = {KEY_HOOK(WM_KEYDOWN, 0xc0, VK_PACKET), KEY_MSG(WM_KEYDOWN, 0, VK_PACKET, .todo_value = TRUE), WIN_MSG(WM_CHAR, 0xc0, 1), {0}}},
1280 {.scan = 0x3c0, .vkey = VK_PACKET, .flags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP,
1281 .expect = {KEY_HOOK(WM_KEYUP, 0xc0, VK_PACKET), KEY_MSG(WM_KEYUP, 0, VK_PACKET, .todo_value = TRUE), {0}}},
1282 {0},
1283 };
1284
1285 struct send_input_keyboard_test numpad_scan[] =
1286 {
1287 {.scan = 0x4b, .flags = KEYEVENTF_SCANCODE, .expect_state = {[VK_LEFT] = 0x80},
1288 .expect = {KEY_HOOK(WM_KEYDOWN, 0x4b, VK_LEFT), KEY_MSG(WM_KEYDOWN, 0x4b, VK_LEFT), {0}}},
1289 {.scan = 0x4b, .flags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP,
1290 .expect = {KEY_HOOK(WM_KEYUP, 0x4b, VK_LEFT), KEY_MSG(WM_KEYUP, 0x4b, VK_LEFT), {0}}},
1291 {0},
1292 };
1293
1294 struct send_input_keyboard_test numpad_scan_numlock[] =
1295 {
1296 {.scan = 0x45, .flags = KEYEVENTF_SCANCODE, .expect_state = {[VK_NUMLOCK] = 0x80},
1297 .expect = {KEY_HOOK(WM_KEYDOWN, 0x45, VK_NUMLOCK), KEY_MSG(WM_KEYDOWN, 0x45, VK_NUMLOCK), {0}}},
1298 {.scan = 0x45, .flags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP, .expect_state = {[VK_NUMLOCK] = 0x01},
1299 .expect = {KEY_HOOK(WM_KEYUP, 0x45, VK_NUMLOCK), KEY_MSG(WM_KEYUP, 0x45, VK_NUMLOCK), {0}}},
1300 {
1301 .scan = 0x4b, .flags = KEYEVENTF_SCANCODE,
1302 .expect_state = {[VK_NUMPAD4] = 0x80, [VK_NUMLOCK] = 0x01},
1303 .todo_state = {[VK_NUMPAD4] = TRUE, [VK_LEFT] = TRUE},
1304 .expect =
1305 {
1306 KEY_HOOK(WM_KEYDOWN, 0x4b, VK_NUMPAD4, .todo_value = TRUE),
1307 KEY_MSG(WM_KEYDOWN, 0x4b, VK_NUMPAD4, .todo_value = TRUE),
1308 WIN_MSG(WM_CHAR, '4', MAKELONG(1, 0x4b), .todo_value = TRUE),
1309 {0}
1310 }
1311 },
1312 {
1313 .scan = 0x4b, .flags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP, .expect_state = {[VK_NUMLOCK] = 0x01},
1314 .expect =
1315 {
1316 KEY_HOOK(WM_KEYUP, 0x4b, VK_NUMPAD4, .todo_value = TRUE),
1317 KEY_MSG(WM_KEYUP, 0x4b, VK_NUMPAD4, .todo_value = TRUE),
1318 {0}
1319 }
1320 },
1321 {0},
1322 };
1323
1324#undef WIN_MSG
1325#undef KBD_HOOK
1326#undef KEY_HOOK_
1327#undef KEY_HOOK
1328#undef KEY_MSG_
1329#undef KEY_MSG
1330
1331 BOOL altgr = keyboard_layout_has_altgr(), skip_altgr = FALSE;
1333 HHOOK hook;
1334 HWND hwnd;
1335
1336 /* on 32-bit with ALTGR keyboard, the CONTROL key is sent to the hooks without the
1337 * LLKHF_INJECTED flag, skip the tests to keep it simple */
1338 if (altgr && sizeof(void *) == 4 && !is_wow64) skip_altgr = TRUE;
1339
1340 hwnd = CreateWindowW( L"static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, NULL, NULL );
1341 ok_ne( NULL, hwnd, HWND, "%p" );
1342 wait_messages( 100, FALSE );
1343
1344 /* If we have had a spurious layout change, wch(_shift) may be incorrect. */
1345 if (GetKeyboardLayout( 0 ) != hkl)
1346 {
1347 win_skip( "Spurious keyboard layout changed detected (expected: %p got: %p)\n",
1348 hkl, GetKeyboardLayout( 0 ) );
1349 ok_ret( 1, DestroyWindow( hwnd ) );
1350 wait_messages( 100, FALSE );
1352 return;
1353 }
1354
1356 ok_ne( NULL, hook, HHOOK, "%p" );
1357
1360
1361 lmenu_vkey_peeked[1].expect_state[vkey] = 0x80;
1362 lmenu_vkey[1].expect_state[vkey] = 0x80;
1363 lcontrol_vkey[1].expect_state[vkey] = 0x80;
1364 lmenu_lcontrol_vkey[2].expect_state[vkey] = 0x80;
1365 shift_vkey[1].expect_state[vkey] = 0x80;
1366 rshift_scan[1].expect_state[vkey] = 0x80;
1367 unicode_vkey[0].expect_state[vkey] = 0x80;
1368
1369 /* test peeked messages */
1370 winetest_push_context( "peek" );
1371 check_send_input_keyboard_test( lmenu_vkey_peeked, TRUE );
1372 check_send_input_keyboard_test( lcontrol_vkey, TRUE );
1373 check_send_input_keyboard_test( lmenu_lcontrol_vkey, TRUE );
1374 check_send_input_keyboard_test( shift_vkey, TRUE );
1376 check_send_input_keyboard_test( lshift_ext, TRUE );
1377 check_send_input_keyboard_test( rshift_ext, TRUE );
1381 check_send_input_keyboard_test( lcontrol_ext, TRUE );
1382 check_send_input_keyboard_test( rcontrol_ext, TRUE );
1384 check_send_input_keyboard_test( control_ext, TRUE );
1385 if (skip_altgr) skip( "skipping rmenu_altgr test\n" );
1386 else if (altgr) check_send_input_keyboard_test( rmenu_altgr, TRUE );
1387 else check_send_input_keyboard_test( rmenu_peeked, TRUE );
1388 check_send_input_keyboard_test( lmenu_ext_peeked, TRUE );
1389 if (skip_altgr) skip( "skipping rmenu_ext_altgr test\n" );
1390 else if (altgr) check_send_input_keyboard_test( rmenu_ext_altgr, TRUE );
1391 else check_send_input_keyboard_test( rmenu_ext_peeked, TRUE );
1392 check_send_input_keyboard_test( menu_peeked, TRUE );
1393 if (skip_altgr) skip( "skipping menu_ext_altgr test\n" );
1394 else if (altgr) check_send_input_keyboard_test( menu_ext_altgr, TRUE );
1395 else check_send_input_keyboard_test( menu_ext_peeked, TRUE );
1396 check_send_input_keyboard_test( lrshift_ext, TRUE );
1397 check_send_input_keyboard_test( rshift_scan, TRUE );
1398 /* Skip on Korean layouts since they map the right control key to VK_HANJA */
1399 if (hkl == (HKL)0x04120412) skip( "skipping rctrl_scan test on Korean layout" );
1400 else check_send_input_keyboard_test( rctrl_scan, TRUE );
1402 check_send_input_keyboard_test( lmenu_unicode_peeked, TRUE );
1403 check_send_input_keyboard_test( unicode_vkey, TRUE );
1404 check_send_input_keyboard_test( unicode_vkey_ctrl, TRUE );
1405 check_send_input_keyboard_test( unicode_vkey_packet, TRUE );
1406 check_send_input_keyboard_test( numpad_scan, TRUE );
1407 check_send_input_keyboard_test( numpad_scan_numlock, TRUE );
1409
1410 wait_messages( 100, FALSE );
1412
1413 /* test received messages */
1415 ok_ne( 0, old_proc, LONG_PTR, "%#Ix" );
1416
1417 winetest_push_context( "receive" );
1419 check_send_input_keyboard_test( lcontrol_vkey, FALSE );
1420 check_send_input_keyboard_test( lmenu_lcontrol_vkey, FALSE );
1428 check_send_input_keyboard_test( lcontrol_ext, FALSE );
1429 check_send_input_keyboard_test( rcontrol_ext, FALSE );
1431 check_send_input_keyboard_test( control_ext, FALSE );
1432 if (skip_altgr) skip( "skipping rmenu_altgr test\n" );
1433 else if (altgr) check_send_input_keyboard_test( rmenu_altgr, FALSE );
1436 if (skip_altgr) skip( "skipping rmenu_ext_altgr test\n" );
1437 else if (altgr) check_send_input_keyboard_test( rmenu_ext_altgr, FALSE );
1438 else check_send_input_keyboard_test( rmenu_ext, FALSE );
1440 if (skip_altgr) skip( "skipping menu_ext_altgr test\n" );
1441 else if (altgr) check_send_input_keyboard_test( menu_ext_altgr, FALSE );
1442 else check_send_input_keyboard_test( menu_ext, FALSE );
1443 check_send_input_keyboard_test( lrshift_ext, FALSE );
1444 check_send_input_keyboard_test( rshift_scan, FALSE );
1445 /* Skip on Korean layouts since they map the right control key to VK_HANJA */
1446 if (hkl == (HKL)0x04120412) skip( "skipping rctrl_scan test on Korean layout" );
1447 else check_send_input_keyboard_test( rctrl_scan, FALSE );
1449 check_send_input_keyboard_test( lmenu_unicode, FALSE );
1450 check_send_input_keyboard_test( unicode_vkey, FALSE );
1451 check_send_input_keyboard_test( unicode_vkey_ctrl, FALSE );
1452 check_send_input_keyboard_test( unicode_vkey_packet, FALSE );
1453 check_send_input_keyboard_test( numpad_scan, FALSE );
1454 check_send_input_keyboard_test( numpad_scan_numlock, FALSE );
1456
1457 ok_ret( 1, DestroyWindow( hwnd ) );
1459
1460 wait_messages( 100, FALSE );
1463}
1464
1465static void test_keynames(void)
1466{
1467 int i, len;
1468 char buff[256];
1469
1470 for (i = 0; i < 512; i++)
1471 {
1472 strcpy(buff, "----");
1473 len = GetKeyNameTextA(i << 16, buff, sizeof(buff));
1474 ok(len || !buff[0], "%d: Buffer is not zeroed\n", i);
1475 }
1476}
1477
1479{
1480 return is_keyboard_message( msg ) || msg == WM_INPUT;
1481}
1482
1484{
1485#define WIN_MSG(m, w, l, ...) {.func = MSG_TEST_WIN, .message = {.msg = m, .wparam = w, .lparam = l}, ## __VA_ARGS__}
1486#define RAW_KEY(s, f, v, m, ...) {.func = RAW_INPUT_KEYBOARD, .raw_input.kbd = {.MakeCode = s, .Flags = f, .VKey = v, .Message = m}, ## __VA_ARGS__}
1487#define KEY_MSG(m, s, v, ...) WIN_MSG( m, v, MAKELONG(1, (s) | (m == WM_KEYUP || m == WM_SYSKEYUP ? (KF_UP | KF_REPEAT) : 0)), ## __VA_ARGS__ )
1488 struct send_input_keyboard_test raw_legacy[] =
1489 {
1490 {.vkey = vkey,
1491 .expect = {RAW_KEY(1, RI_KEY_MAKE, vkey, WM_KEYDOWN), KEY_MSG(WM_KEYDOWN, 1, vkey), WIN_MSG(WM_CHAR, wch, MAKELONG(1, 1)), {0}}},
1492 {.vkey = vkey, .flags = KEYEVENTF_KEYUP,
1493 .expect = {RAW_KEY(2, RI_KEY_BREAK, vkey, WM_KEYUP), KEY_MSG(WM_KEYUP, 2, vkey), {0}}},
1494 {0},
1495 };
1496 struct send_input_keyboard_test raw_nolegacy[] =
1497 {
1498 {.vkey = vkey, .async = TRUE, .expect = {RAW_KEY(1, RI_KEY_MAKE, vkey, WM_KEYDOWN), {0}}},
1499 {.vkey = vkey, .flags = KEYEVENTF_KEYUP, .expect = {RAW_KEY(2, RI_KEY_BREAK, vkey, WM_KEYUP), {0}}},
1500 {0},
1501 };
1502 struct send_input_keyboard_test raw_vk_packet_legacy[] =
1503 {
1504 {.vkey = VK_PACKET, .expect_state = {[VK_PACKET] = 0x80},
1505 .expect = {RAW_KEY(1, RI_KEY_MAKE, VK_PACKET, WM_KEYDOWN), KEY_MSG(WM_KEYDOWN, 1, VK_PACKET), {0, .todo = TRUE}}},
1506 {.vkey = VK_PACKET, .flags = KEYEVENTF_KEYUP,
1507 .expect = {RAW_KEY(2, RI_KEY_BREAK, VK_PACKET, WM_KEYUP), KEY_MSG(WM_KEYUP, 2, VK_PACKET), {0}}},
1508 {0},
1509 };
1510 struct send_input_keyboard_test raw_vk_packet_nolegacy[] =
1511 {
1512 {.vkey = VK_PACKET, .async = TRUE, .expect_async = {[VK_PACKET] = 0x80},
1513 .expect = {RAW_KEY(1, RI_KEY_MAKE, VK_PACKET, WM_KEYDOWN), {0}}},
1514 {.vkey = VK_PACKET, .flags = KEYEVENTF_KEYUP, .expect = {RAW_KEY(2, RI_KEY_BREAK, VK_PACKET, WM_KEYUP), {0}}},
1515 {0},
1516 };
1517 struct send_input_keyboard_test raw_unicode_legacy[] =
1518 {
1519 {.scan = 0x3c0, .flags = KEYEVENTF_UNICODE, .expect_state = {[VK_PACKET] = 0x80},
1520 .expect = {KEY_MSG(WM_KEYDOWN, 0, VK_PACKET, .todo_value = TRUE), WIN_MSG(WM_CHAR, 0x3c0, 1), {0}}},
1521 {.scan = 0x3c0, .flags = KEYEVENTF_KEYUP | KEYEVENTF_UNICODE,
1522 .expect = {KEY_MSG(WM_KEYUP, 0, VK_PACKET, .todo_value = TRUE), {0}}},
1523 {0},
1524 };
1525 struct send_input_keyboard_test raw_unicode_nolegacy[] =
1526 {
1527 {.scan = 0x3c0, .flags = KEYEVENTF_UNICODE, .async = TRUE, .expect_async = {[VK_PACKET] = 0x80}},
1528 {.scan = 0x3c0, .flags = KEYEVENTF_KEYUP | KEYEVENTF_UNICODE},
1529 {0},
1530 };
1531 struct send_input_keyboard_test raw_unicode_vkey_ctrl_legacy[] =
1532 {
1533 {.scan = 0x3c0, .vkey = VK_CONTROL, .flags = KEYEVENTF_UNICODE,
1534 .expect_state = {[VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80},
1535 .expect = {KEY_MSG(WM_KEYDOWN, 0xc0, VK_CONTROL), {0}}},
1536 {.scan = 0x3c0, .vkey = VK_CONTROL, .flags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP,
1537 .expect = {KEY_MSG(WM_KEYUP, 0xc0, VK_CONTROL), {0}}},
1538 {0},
1539 };
1540 struct send_input_keyboard_test raw_unicode_vkey_ctrl_nolegacy[] =
1541 {
1542 {.scan = 0x3c0, .vkey = VK_CONTROL, .flags = KEYEVENTF_UNICODE, .async = TRUE,
1543 .expect_async = {[VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80}},
1544 {.scan = 0x3c0, .vkey = VK_CONTROL, .flags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP},
1545 {0},
1546 };
1547#undef WIN_MSG
1548#undef RAW_KEY
1549#undef KEY_MSG
1550 RAWINPUTDEVICE rid = {.usUsagePage = HID_USAGE_PAGE_GENERIC, .usUsage = HID_USAGE_GENERIC_KEYBOARD};
1551 int receive;
1552 HWND hwnd;
1553
1554 raw_legacy[0].expect_state[vkey] = 0x80;
1555 raw_nolegacy[0].expect_async[vkey] = 0x80;
1556
1557 hwnd = CreateWindowW( L"static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, NULL, NULL );
1558 ok_ne( NULL, hwnd, HWND, "%p" );
1559 wait_messages( 100, FALSE );
1560
1561 /* If we have had a spurious layout change, wch may be incorrect. */
1562 if (GetKeyboardLayout( 0 ) != hkl)
1563 {
1564 win_skip( "Spurious keyboard layout changed detected (expected: %p got: %p)\n",
1565 hkl, GetKeyboardLayout( 0 ) );
1566 ok_ret( 1, DestroyWindow( hwnd ) );
1567 wait_messages( 100, FALSE );
1569 return;
1570 }
1571
1573
1574 for (receive = 0; receive <= 1; receive++)
1575 {
1576 winetest_push_context( receive ? "receive" : "peek" );
1577
1578 if (receive)
1579 {
1580 /* test received messages */
1582 ok_ne( 0, old_proc, LONG_PTR, "%#Ix" );
1583 }
1584
1585 rid.dwFlags = 0;
1586 ok_ret( 1, RegisterRawInputDevices( &rid, 1, sizeof(rid) ) );
1587
1588 /* get both WM_INPUT and legacy messages */
1589 check_send_input_keyboard_test( raw_legacy, !receive );
1590 check_send_input_keyboard_test( raw_vk_packet_legacy, !receive );
1591 /* no WM_INPUT message for unicode */
1592 check_send_input_keyboard_test( raw_unicode_legacy, !receive );
1593 check_send_input_keyboard_test( raw_unicode_vkey_ctrl_legacy, !receive );
1594
1595 rid.dwFlags = RIDEV_REMOVE;
1596 ok_ret( 1, RegisterRawInputDevices( &rid, 1, sizeof(rid) ) );
1597
1598 rid.dwFlags = RIDEV_NOLEGACY;
1599 ok_ret( 1, RegisterRawInputDevices( &rid, 1, sizeof(rid) ) );
1600
1601 /* get only WM_INPUT messages */
1602 check_send_input_keyboard_test( raw_nolegacy, !receive );
1603 check_send_input_keyboard_test( raw_vk_packet_nolegacy, !receive );
1604 /* no WM_INPUT message for unicode */
1605 check_send_input_keyboard_test( raw_unicode_nolegacy, !receive );
1606 check_send_input_keyboard_test( raw_unicode_vkey_ctrl_nolegacy, !receive );
1607
1608 rid.dwFlags = RIDEV_REMOVE;
1609 ok_ret( 1, RegisterRawInputDevices( &rid, 1, sizeof(rid) ) );
1610
1612 }
1613
1614 ok_ret( 1, DestroyWindow( hwnd ) );
1615 wait_messages( 100, FALSE );
1617
1619}
1620
1621static void test_GetMouseMovePointsEx( char **argv )
1622{
1623#define BUFLIM 64
1624#define MYERROR 0xdeadbeef
1625 int i, count, retval;
1626 MOUSEMOVEPOINT in;
1627 MOUSEMOVEPOINT out[200];
1628 POINT point;
1629 INPUT input;
1630
1631 /* Get a valid content for the input struct */
1632 if(!GetCursorPos(&point)) {
1633 win_skip("GetCursorPos() failed with error %lu\n", GetLastError());
1634 return;
1635 }
1636 memset(&in, 0, sizeof(MOUSEMOVEPOINT));
1637 in.x = point.x;
1638 in.y = point.y;
1639
1640 /* test first parameter
1641 * everything different than sizeof(MOUSEMOVEPOINT)
1642 * is expected to fail with ERROR_INVALID_PARAMETER
1643 */
1645 retval = pGetMouseMovePointsEx(0, &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1647 {
1648 win_skip( "GetMouseMovePointsEx broken on WinME\n" );
1649 return;
1650 }
1651 ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1653 "expected error ERROR_INVALID_PARAMETER, got %lu\n", GetLastError());
1654
1656 retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)-1, &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1657 ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1659 "expected error ERROR_INVALID_PARAMETER, got %lu\n", GetLastError());
1660
1662 retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)+1, &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1663 ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1665 "expected error ERROR_INVALID_PARAMETER, got %lu\n", GetLastError());
1666
1667 /* test second and third parameter
1668 */
1670 retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), NULL, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1671 ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1673 "expected error ERROR_NOACCESS, got %lu\n", GetLastError());
1674
1676 retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, NULL, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1677 ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1679 "expected error ERROR_NOACCESS, got %lu\n", GetLastError());
1680
1682 retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), NULL, NULL, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1683 ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1685 "expected error ERROR_NOACCESS, got %lu\n", GetLastError());
1686
1688 count = 0;
1689 retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, NULL, count, GMMP_USE_DISPLAY_POINTS);
1690 if (retval == -1)
1691 ok(GetLastError() == ERROR_POINT_NOT_FOUND, "unexpected error %lu\n", GetLastError());
1692 else
1693 ok(retval == count, "expected GetMouseMovePointsEx to succeed, got %d\n", retval);
1694
1695 /* test fourth parameter
1696 * a value higher than 64 is expected to fail with ERROR_INVALID_PARAMETER
1697 */
1699 count = -1;
1700 retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, out, count, GMMP_USE_DISPLAY_POINTS);
1701 ok(retval == count, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1703 "expected error ERROR_INVALID_PARAMETER, got %lu\n", GetLastError());
1704
1706 count = 0;
1707 retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, out, count, GMMP_USE_DISPLAY_POINTS);
1708 if (retval == -1)
1709 ok(GetLastError() == ERROR_POINT_NOT_FOUND, "unexpected error %lu\n", GetLastError());
1710 else
1711 ok(retval == count, "expected GetMouseMovePointsEx to succeed, got %d\n", retval);
1712
1714 count = BUFLIM;
1715 retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, out, count, GMMP_USE_DISPLAY_POINTS);
1716 if (retval == -1)
1717 ok(GetLastError() == ERROR_POINT_NOT_FOUND, "unexpected error %lu\n", GetLastError());
1718 else
1719 ok((0 <= retval) && (retval <= count), "expected GetMouseMovePointsEx to succeed, got %d\n", retval);
1720
1722 retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, out, BUFLIM+1, GMMP_USE_DISPLAY_POINTS);
1723 ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1725 "expected error ERROR_INVALID_PARAMETER, got %lu\n", GetLastError());
1726
1727 /* it was not possible to force an error with the fifth parameter on win2k */
1728
1729 /* test combinations of wrong parameters to see which error wins */
1731 retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)-1, NULL, out, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1732 ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1734 "expected error ERROR_INVALID_PARAMETER, got %lu\n", GetLastError());
1735
1737 retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)-1, &in, NULL, BUFLIM, GMMP_USE_DISPLAY_POINTS);
1738 ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1740 "expected error ERROR_INVALID_PARAMETER, got %lu\n", GetLastError());
1741
1743 retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), NULL, out, BUFLIM+1, GMMP_USE_DISPLAY_POINTS);
1744 ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1746 "expected error ERROR_INVALID_PARAMETER, got %lu\n", GetLastError());
1747
1749 retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, NULL, BUFLIM+1, GMMP_USE_DISPLAY_POINTS);
1750 ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval);
1752 "expected error ERROR_INVALID_PARAMETER, got %lu\n", GetLastError());
1753
1754 /* more than 64 to be sure we wrap around */
1755 for (i = 0; i < 67; i++)
1756 {
1757 in.x = i;
1758 in.y = i*2;
1759 SetCursorPos( in.x, in.y );
1760 }
1761
1763 retval = pGetMouseMovePointsEx( sizeof(MOUSEMOVEPOINT), &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS );
1764 ok( retval == 64, "expected to get 64 mouse move points but got %d\n", retval );
1765 ok( GetLastError() == MYERROR, "expected error to stay %x, got %lx\n", MYERROR, GetLastError() );
1766
1767 for (i = 0; i < retval; i++)
1768 {
1769 ok( out[i].x == in.x && out[i].y == in.y, "wrong position %d, expected %dx%d got %dx%d\n", i, in.x, in.y, out[i].x, out[i].y );
1770 in.x--;
1771 in.y -= 2;
1772 }
1773
1774 in.x = 1500;
1775 in.y = 1500;
1777 retval = pGetMouseMovePointsEx( sizeof(MOUSEMOVEPOINT), &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS );
1778 ok( retval == -1, "expected to get -1 but got %d\n", retval );
1779 ok( GetLastError() == ERROR_POINT_NOT_FOUND, "expected error to be set to %x, got %lx\n", ERROR_POINT_NOT_FOUND, GetLastError() );
1780
1781 /* make sure there's no deduplication */
1782 in.x = 6;
1783 in.y = 6;
1784 SetCursorPos( in.x, in.y );
1785 SetCursorPos( in.x, in.y );
1786 retval = pGetMouseMovePointsEx( sizeof(MOUSEMOVEPOINT), &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS );
1787 ok( retval == 64, "expected to get 64 mouse move points but got %d\n", retval );
1788 ok( out[0].x == 6 && out[0].y == 6, "expected cursor position to be 6x6 but got %d %d\n", out[0].x, out[0].y );
1789 ok( out[1].x == 6 && out[1].y == 6, "expected cursor position to be 6x6 but got %d %d\n", out[1].x, out[1].y );
1790
1791 /* make sure 2 events are distinguishable by their timestamps */
1792 in.x = 150;
1793 in.y = 75;
1794 SetCursorPos( 30, 30 );
1795 SetCursorPos( in.x, in.y );
1796 SetCursorPos( 150, 150 );
1797 Sleep( 3 );
1798 SetCursorPos( in.x, in.y );
1799
1800 retval = pGetMouseMovePointsEx( sizeof(MOUSEMOVEPOINT), &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS );
1801 ok( retval == 64, "expected to get 64 mouse move points but got %d\n", retval );
1802 ok( out[0].x == 150 && out[0].y == 75, "expected cursor position to be 150x75 but got %d %d\n", out[0].x, out[0].y );
1803 ok( out[1].x == 150 && out[1].y == 150, "expected cursor position to be 150x150 but got %d %d\n", out[1].x, out[1].y );
1804 ok( out[2].x == 150 && out[2].y == 75, "expected cursor position to be 150x75 but got %d %d\n", out[2].x, out[2].y );
1805
1806 in.time = out[2].time;
1807 retval = pGetMouseMovePointsEx( sizeof(MOUSEMOVEPOINT), &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS );
1808 ok( retval == 62, "expected to get 62 mouse move points but got %d\n", retval );
1809 ok( out[0].x == 150 && out[0].y == 75, "expected cursor position to be 150x75 but got %d %d\n", out[0].x, out[0].y );
1810 ok( out[1].x == 30 && out[1].y == 30, "expected cursor position to be 30x30 but got %d %d\n", out[1].x, out[1].y );
1811
1812 /* events created through other means should also be on the list with correct extra info */
1813 mouse_event( MOUSEEVENTF_MOVE, -13, 17, 0, 0xcafecafe );
1814 ok( GetCursorPos( &point ), "failed to get cursor position\n" );
1815 ok( in.x != point.x && in.y != point.y, "cursor didn't change position after mouse_event()\n" );
1816 in.time = 0;
1817 in.x = point.x;
1818 in.y = point.y;
1819 retval = pGetMouseMovePointsEx( sizeof(MOUSEMOVEPOINT), &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS );
1820 ok( retval == 64, "expected to get 64 mouse move points but got %d\n", retval );
1821 ok( out[0].dwExtraInfo == 0xcafecafe, "wrong extra info, got 0x%Ix expected 0xcafecafe\n", out[0].dwExtraInfo );
1822
1823 input.type = INPUT_MOUSE;
1824 memset( &input, 0, sizeof(input) );
1825 input.mi.dwFlags = MOUSEEVENTF_MOVE;
1826 input.mi.dwExtraInfo = 0xdeadbeef;
1827 input.mi.dx = -17;
1828 input.mi.dy = 13;
1829 SendInput( 1, (INPUT *)&input, sizeof(INPUT) );
1830 ok( GetCursorPos( &point ), "failed to get cursor position\n" );
1831 ok( in.x != point.x && in.y != point.y, "cursor didn't change position after mouse_event()\n" );
1832 in.time = 0;
1833 in.x = point.x;
1834 in.y = point.y;
1835 retval = pGetMouseMovePointsEx( sizeof(MOUSEMOVEPOINT), &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS );
1836 ok( retval == 64, "expected to get 64 mouse move points but got %d\n", retval );
1837 ok( out[0].dwExtraInfo == 0xdeadbeef, "wrong extra info, got 0x%Ix expected 0xdeadbeef\n", out[0].dwExtraInfo );
1838
1839 retval = pGetMouseMovePointsEx( sizeof(MOUSEMOVEPOINT), &in, out, BUFLIM, GMMP_USE_HIGH_RESOLUTION_POINTS );
1840 todo_wine ok( retval == 64, "expected to get 64 high resolution mouse move points but got %d\n", retval );
1841
1842 run_in_process( argv, "test_GetMouseMovePointsEx_process" );
1843#undef BUFLIM
1844#undef MYERROR
1845}
1846
1848{
1849 int retval;
1850 MOUSEMOVEPOINT in;
1851 MOUSEMOVEPOINT out[64], out2[64];
1852 POINT point;
1853 HDESK desk0, desk1;
1854 HWINSTA winstation0, winstation1;
1855
1856#ifdef __REACTOS__
1857 if (is_reactos())
1858 {
1859 ok(FALSE, "Broken on ReactOS\n");
1860 skip("Skipping test_GetMouseMovePointsEx_process due to CORE-20552\n");
1861 return;
1862 }
1863#endif
1864
1865 memset( out, 0, sizeof(out) );
1866 memset( out2, 0, sizeof(out2) );
1867
1868 /* move point history is shared between desktops within the same windowstation */
1869 ok( GetCursorPos( &point ), "failed to get cursor position\n" );
1870 in.time = 0;
1871 in.x = point.x;
1872 in.y = point.y;
1873 retval = pGetMouseMovePointsEx( sizeof(MOUSEMOVEPOINT), &in, out, ARRAY_SIZE(out), GMMP_USE_DISPLAY_POINTS );
1874 ok( retval == 64, "expected to get 64 mouse move points but got %d\n", retval );
1875
1877 ok( desk0 != NULL, "OpenInputDesktop has failed with %ld\n", GetLastError() );
1878 desk1 = CreateDesktopA( "getmousemovepointsex_test_desktop", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
1879 ok( desk1 != NULL, "CreateDesktopA failed with %ld\n", GetLastError() );
1880
1881 ok( SetThreadDesktop( desk1 ), "SetThreadDesktop failed!\n" );
1882 ok( SwitchDesktop( desk1 ), "SwitchDesktop failed\n" );
1883
1884 retval = pGetMouseMovePointsEx( sizeof(MOUSEMOVEPOINT), &in, out2, ARRAY_SIZE(out2), GMMP_USE_DISPLAY_POINTS );
1885 ok( retval == 64, "expected to get 64 mouse move points but got %d\n", retval );
1886
1887 ok( memcmp( out, out2, sizeof(out2) ) == 0, "expected to get exact same history on the new desktop\n" );
1888
1889 in.time = 0;
1890 in.x = 38;
1891 in.y = 27;
1892 SetCursorPos( in.x, in.y );
1893
1894 retval = pGetMouseMovePointsEx( sizeof(MOUSEMOVEPOINT), &in, out2, ARRAY_SIZE(out2), GMMP_USE_DISPLAY_POINTS );
1895 ok( retval == 64, "expected to get 64 mouse move points but got %d\n", retval );
1896
1897 ok( SetThreadDesktop( desk0 ), "SetThreadDesktop failed!\n" );
1898 ok( SwitchDesktop( desk0 ), "SwitchDesktop failed\n" );
1899
1900 retval = pGetMouseMovePointsEx( sizeof(MOUSEMOVEPOINT), &in, out, ARRAY_SIZE(out), GMMP_USE_DISPLAY_POINTS );
1901 ok( retval == 64, "expected to get 64 mouse move points but got %d\n", retval );
1902 ok( memcmp( out, out2, sizeof( out2 ) ) == 0, "expected to get exact same history on the old desktop\n" );
1903
1904 CloseDesktop( desk1 );
1905 CloseDesktop( desk0 );
1906
1907 /* non-default windowstations are non-interactive */
1908 winstation0 = GetProcessWindowStation();
1909 ok( winstation0 != NULL, "GetProcessWindowStation has failed with %ld\n", GetLastError() );
1911 ok( desk0 != NULL, "OpenInputDesktop has failed with %ld\n", GetLastError() );
1912 winstation1 = CreateWindowStationA( "test_winstation", 0, WINSTA_ALL_ACCESS, NULL );
1913
1914 if (winstation1 == NULL && GetLastError() == ERROR_ACCESS_DENIED)
1915 {
1916 win_skip("not enough privileges for CreateWindowStation\n");
1917 CloseDesktop( desk0 );
1918 CloseWindowStation( winstation0 );
1919 return;
1920 }
1921
1922 ok( winstation1 != NULL, "CreateWindowStationA has failed with %ld\n", GetLastError() );
1923 ok( SetProcessWindowStation( winstation1 ), "SetProcessWindowStation has failed\n" );
1924
1925 desk1 = CreateDesktopA( "getmousemovepointsex_test_desktop", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
1926 ok( desk1 != NULL, "CreateDesktopA failed with %ld\n", GetLastError() );
1927 ok( SetThreadDesktop( desk1 ), "SetThreadDesktop failed!\n" );
1928
1929 SetLastError( 0xDEADBEEF );
1930 retval = pGetMouseMovePointsEx( sizeof(MOUSEMOVEPOINT), &in, out, ARRAY_SIZE(out), GMMP_USE_DISPLAY_POINTS );
1931 todo_wine ok( retval == -1, "expected to get -1 mouse move points but got %d\n", retval );
1932 todo_wine ok( GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED got %ld\n", GetLastError() );
1933
1934 ok( SetProcessWindowStation( winstation0 ), "SetProcessWindowStation has failed\n" );
1935 ok( SetThreadDesktop( desk0 ), "SetThreadDesktop failed!\n" );
1936 CloseDesktop( desk1 );
1937 CloseWindowStation( winstation1 );
1938 CloseDesktop( desk0 );
1939 CloseWindowStation( winstation0 );
1940}
1941
1943{
1944 RAWINPUTDEVICELIST devices[32];
1945 UINT ret, oret, devcount, odevcount, i;
1946 DWORD err;
1947 BOOLEAN br;
1948
1949 SetLastError(0xdeadbeef);
1950 ret = pGetRawInputDeviceList(NULL, NULL, 0);
1951 err = GetLastError();
1952 ok(ret == -1, "expected -1, got %d\n", ret);
1953 ok(err == ERROR_INVALID_PARAMETER, "expected 87, got %ld\n", err);
1954
1955 SetLastError(0xdeadbeef);
1956 ret = pGetRawInputDeviceList(NULL, NULL, sizeof(devices[0]));
1957 err = GetLastError();
1958 ok(ret == -1, "expected -1, got %d\n", ret);
1959 ok(err == ERROR_NOACCESS, "expected 998, got %ld\n", err);
1960
1961 devcount = 0;
1962 ret = pGetRawInputDeviceList(NULL, &devcount, sizeof(devices[0]));
1963 ok(ret == 0, "expected 0, got %d\n", ret);
1964 ok(devcount > 0, "expected non-zero\n");
1965
1966 SetLastError(0xdeadbeef);
1967 devcount = 0;
1968 ret = pGetRawInputDeviceList(devices, &devcount, sizeof(devices[0]));
1969 err = GetLastError();
1970 ok(ret == -1, "expected -1, got %d\n", ret);
1971 ok(err == ERROR_INSUFFICIENT_BUFFER, "expected 122, got %ld\n", err);
1972 ok(devcount > 0, "expected non-zero\n");
1973
1974 /* devcount contains now the correct number of devices */
1975 ret = pGetRawInputDeviceList(devices, &devcount, sizeof(devices[0]));
1976 ok(ret > 0, "expected non-zero\n");
1977
1978 if (devcount)
1979 {
1980 RID_DEVICE_INFO info;
1981 UINT size;
1982
1983 SetLastError( 0xdeadbeef );
1984 ret = pGetRawInputDeviceInfoW( UlongToHandle( 0xdeadbeef ), RIDI_DEVICEINFO, NULL, NULL );
1985 ok( ret == ~0U, "GetRawInputDeviceInfoW returned %#x, expected ~0.\n", ret );
1986 ok( GetLastError() == ERROR_NOACCESS, "GetRawInputDeviceInfoW last error %#lx, expected 0xdeadbeef.\n", GetLastError() );
1987
1988 SetLastError( 0xdeadbeef );
1989 size = 0xdeadbeef;
1990 ret = pGetRawInputDeviceInfoW( UlongToHandle( 0xdeadbeef ), RIDI_DEVICEINFO, NULL, &size );
1991 ok( ret == ~0U, "GetRawInputDeviceInfoW returned %#x, expected ~0.\n", ret );
1992 ok( size == 0xdeadbeef, "GetRawInputDeviceInfoW returned size %#x, expected 0.\n", size );
1993 ok( GetLastError() == ERROR_INVALID_HANDLE, "GetRawInputDeviceInfoW last error %#lx, expected 0xdeadbeef.\n", GetLastError() );
1994
1995 SetLastError( 0xdeadbeef );
1996 size = 0xdeadbeef;
1997 ret = pGetRawInputDeviceInfoW( devices[0].hDevice, 0xdeadbeef, NULL, &size );
1998 ok( ret == ~0U, "GetRawInputDeviceInfoW returned %#x, expected ~0.\n", ret );
1999 ok( size == 0xdeadbeef, "GetRawInputDeviceInfoW returned size %#x, expected 0.\n", size );
2000 ok( GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputDeviceInfoW last error %#lx, expected 0xdeadbeef.\n", GetLastError() );
2001
2002 SetLastError( 0xdeadbeef );
2003 ret = pGetRawInputDeviceInfoW( devices[0].hDevice, RIDI_DEVICEINFO, &info, NULL );
2004 ok( ret == ~0U, "GetRawInputDeviceInfoW returned %#x, expected ~0.\n", ret );
2005 ok( GetLastError() == ERROR_NOACCESS, "GetRawInputDeviceInfoW last error %#lx, expected 0xdeadbeef.\n", GetLastError() );
2006
2007 SetLastError( 0xdeadbeef );
2008 size = 0;
2009 ret = pGetRawInputDeviceInfoW( devices[0].hDevice, RIDI_DEVICEINFO, &info, &size );
2010 ok( ret == ~0U, "GetRawInputDeviceInfoW returned %#x, expected ~0.\n", ret );
2011 ok( size == sizeof(info), "GetRawInputDeviceInfoW returned size %#x, expected %#Ix.\n", size, sizeof(info) );
2012 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetRawInputDeviceInfoW last error %#lx, expected 0xdeadbeef.\n", GetLastError() );
2013 }
2014
2015 for(i = 0; i < devcount; ++i)
2016 {
2017 WCHAR name[128];
2018 char nameA[128];
2019 UINT sz, len;
2020 RID_DEVICE_INFO info;
2021 HANDLE file;
2022 char *ppd;
2023
2024 /* get required buffer size */
2025 name[0] = '\0';
2026 sz = 5;
2027 ret = pGetRawInputDeviceInfoW(devices[i].hDevice, RIDI_DEVICENAME, name, &sz);
2028 ok(ret == -1, "GetRawInputDeviceInfo gave wrong failure: %ld\n", err);
2029 ok(sz > 5 && sz < ARRAY_SIZE(name), "Size should have been set and not too large (got: %u)\n", sz);
2030
2031 /* buffer size for RIDI_DEVICENAME is in CHARs, not BYTEs */
2032 ret = pGetRawInputDeviceInfoW(devices[i].hDevice, RIDI_DEVICENAME, name, &sz);
2033 ok(ret == sz, "GetRawInputDeviceInfo gave wrong return: %ld\n", err);
2034 len = lstrlenW(name);
2035 ok(len + 1 == ret, "GetRawInputDeviceInfo returned wrong length (name: %u, ret: %u)\n", len + 1, ret);
2036
2037 /* test A variant with same size */
2038 ret = pGetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICENAME, nameA, &sz);
2039 ok(ret == sz, "GetRawInputDeviceInfoA gave wrong return: %ld\n", err);
2040 len = strlen(nameA);
2041 ok(len + 1 == ret, "GetRawInputDeviceInfoA returned wrong length (name: %u, ret: %u)\n", len + 1, ret);
2042
2043 /* buffer size for RIDI_DEVICEINFO is in BYTEs */
2044 memset(&info, 0, sizeof(info));
2045 info.cbSize = sizeof(info);
2046 sz = sizeof(info) - 1;
2047 ret = pGetRawInputDeviceInfoW(devices[i].hDevice, RIDI_DEVICEINFO, &info, &sz);
2048 ok(ret == -1, "GetRawInputDeviceInfo gave wrong failure: %ld\n", err);
2049 ok(sz == sizeof(info), "GetRawInputDeviceInfo set wrong size\n");
2050
2051 ret = pGetRawInputDeviceInfoW(devices[i].hDevice, RIDI_DEVICEINFO, &info, &sz);
2052 ok(ret == sizeof(info), "GetRawInputDeviceInfo gave wrong return: %ld\n", err);
2053 ok(sz == sizeof(info), "GetRawInputDeviceInfo set wrong size\n");
2054 ok(info.dwType == devices[i].dwType, "GetRawInputDeviceInfo set wrong type: 0x%lx\n", info.dwType);
2055
2056 memset(&info, 0, sizeof(info));
2057 info.cbSize = sizeof(info);
2058 ret = pGetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICEINFO, &info, &sz);
2059 ok(ret == sizeof(info), "GetRawInputDeviceInfo gave wrong return: %ld\n", err);
2060 ok(sz == sizeof(info), "GetRawInputDeviceInfo set wrong size\n");
2061 ok(info.dwType == devices[i].dwType, "GetRawInputDeviceInfo set wrong type: 0x%lx\n", info.dwType);
2062
2063 /* setupapi returns an NT device path, but CreateFile() < Vista can't
2064 * understand that; so use the \\?\ prefix instead */
2065 name[1] = '\\';
2067 ok(file != INVALID_HANDLE_VALUE, "Failed to open %s, error %lu\n", wine_dbgstr_w(name), GetLastError());
2068
2069 sz = 0;
2070 ret = pGetRawInputDeviceInfoW(devices[i].hDevice, RIDI_PREPARSEDDATA, NULL, &sz);
2071 ok(ret == 0, "GetRawInputDeviceInfo gave wrong return: %u\n", ret);
2072 ok((info.dwType == RIM_TYPEHID && sz != 0) ||
2073 (info.dwType != RIM_TYPEHID && sz == 0),
2074 "Got wrong PPD size for type 0x%lx: %u\n", info.dwType, sz);
2075
2076 ppd = malloc(sz);
2077 ret = pGetRawInputDeviceInfoW(devices[i].hDevice, RIDI_PREPARSEDDATA, ppd, &sz);
2078 ok(ret == sz, "GetRawInputDeviceInfo gave wrong return: %u, should be %u\n", ret, sz);
2079
2080 if (file != INVALID_HANDLE_VALUE && ret == sz)
2081 {
2082 PHIDP_PREPARSED_DATA preparsed;
2083
2084 if (info.dwType == RIM_TYPEHID)
2085 {
2086 br = HidD_GetPreparsedData(file, &preparsed);
2087 ok(br == TRUE, "HidD_GetPreparsedData failed\n");
2088
2089 if (br)
2090 ok(!memcmp(preparsed, ppd, sz), "Expected to get same preparsed data\n");
2091 }
2092 else
2093 {
2094 /* succeeds on hardware, fails in some VMs */
2095 br = HidD_GetPreparsedData(file, &preparsed);
2096 ok(br == TRUE || broken(br == FALSE), "HidD_GetPreparsedData failed\n");
2097 }
2098
2099 if (br)
2100 HidD_FreePreparsedData(preparsed);
2101 }
2102
2103 free(ppd);
2104
2106 }
2107
2108 /* check if variable changes from larger to smaller value */
2109 devcount = odevcount = ARRAY_SIZE(devices);
2110 oret = ret = pGetRawInputDeviceList(devices, &odevcount, sizeof(devices[0]));
2111 ok(ret > 0, "expected non-zero\n");
2112 ok(devcount == odevcount, "expected %d, got %d\n", devcount, odevcount);
2113 devcount = odevcount;
2114 odevcount = ARRAY_SIZE(devices);
2115 ret = pGetRawInputDeviceList(NULL, &odevcount, sizeof(devices[0]));
2116 ok(ret == 0, "expected 0, got %d\n", ret);
2117 ok(odevcount == oret, "expected %d, got %d\n", oret, odevcount);
2118}
2119
2120static void test_GetRawInputData(void)
2121{
2122 UINT size = 0;
2123
2124 /* Null raw input handle */
2125 SetLastError( 0xdeadbeef );
2126 ok_ret( (UINT)-1, GetRawInputData( NULL, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER) ) );
2128}
2129
2131{
2132 HWND hwnd;
2133 RAWINPUTDEVICE raw_devices[2] = {0};
2134 UINT count, raw_devices_count;
2135 MSG msg;
2136
2137 raw_devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
2138 raw_devices[0].usUsage = HID_USAGE_GENERIC_GAMEPAD;
2139 raw_devices[1].usUsagePage = HID_USAGE_PAGE_GENERIC;
2140 raw_devices[1].usUsage = HID_USAGE_GENERIC_JOYSTICK;
2141
2143
2144 SetLastError( 0xdeadbeef );
2145 ok_ret( 0, RegisterRawInputDevices( NULL, 0, 0 ) );
2147
2148 SetLastError( 0xdeadbeef );
2149 ok_ret( 0, RegisterRawInputDevices( raw_devices, ARRAY_SIZE( raw_devices ), 0 ) );
2151
2152 ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE( raw_devices ), sizeof(RAWINPUTDEVICE) ) );
2153
2154 SetLastError( 0xdeadbeef );
2157
2158 SetLastError( 0xdeadbeef );
2159 ok_ret( (UINT)-1, GetRegisteredRawInputDevices( NULL, &raw_devices_count, 0 ) );
2161
2162 raw_devices_count = 0;
2163 ok_ret( 0, GetRegisteredRawInputDevices( NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE) ) );
2164 ok_eq( 2, raw_devices_count, UINT, "%u" );
2165
2166 SetLastError( 0xdeadbeef );
2167 raw_devices_count = 0;
2168 count = GetRegisteredRawInputDevices( raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE) );
2169 if (broken(count == 0) /* depends on windows versions */)
2170 win_skip( "Ignoring GetRegisteredRawInputDevices success\n" );
2171 else
2172 {
2173 ok_eq( -1, count, int, "%d" );
2174 ok_eq( 0, raw_devices_count, UINT, "%u" );
2176 }
2177
2178 SetLastError( 0xdeadbeef );
2179 raw_devices_count = 1;
2180 ok_ret( (UINT)-1, GetRegisteredRawInputDevices( raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE) ) );
2181 ok_eq( 2, raw_devices_count, UINT, "%u" );
2183
2184 memset( raw_devices, 0, sizeof(raw_devices) );
2185 raw_devices_count = ARRAY_SIZE(raw_devices);
2186 ok_ret( 2, GetRegisteredRawInputDevices( raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE) ) );
2187 ok_eq( 2, raw_devices_count, UINT, "%u" );
2188 ok_eq( HID_USAGE_PAGE_GENERIC, raw_devices[0].usUsagePage, USHORT, "%#x" );
2189 ok_eq( HID_USAGE_GENERIC_JOYSTICK, raw_devices[0].usUsage, USHORT, "%#x" );
2190 ok_eq( HID_USAGE_PAGE_GENERIC, raw_devices[1].usUsagePage, USHORT, "%#x" );
2191 ok_eq( HID_USAGE_GENERIC_GAMEPAD, raw_devices[1].usUsage, USHORT, "%#x" );
2192
2193 /* RIDEV_INPUTSINK requires hwndTarget != NULL */
2194 raw_devices[0].dwFlags = RIDEV_INPUTSINK;
2195 raw_devices[0].hwndTarget = 0;
2196 raw_devices[1].dwFlags = RIDEV_INPUTSINK;
2197 raw_devices[1].hwndTarget = 0;
2198
2199 SetLastError(0xdeadbeef);
2200 ok_ret( 0, RegisterRawInputDevices( raw_devices, ARRAY_SIZE( raw_devices ), sizeof(RAWINPUTDEVICE) ) );
2202
2203 raw_devices[0].hwndTarget = hwnd;
2204 raw_devices[1].hwndTarget = hwnd;
2205 ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE( raw_devices ), sizeof(RAWINPUTDEVICE) ) );
2206
2207 /* RIDEV_DEVNOTIFY send messages for any pre-existing device */
2208 raw_devices[0].dwFlags = RIDEV_DEVNOTIFY;
2209 raw_devices[0].hwndTarget = 0;
2210 raw_devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
2211 raw_devices[0].usUsage = HID_USAGE_GENERIC_MOUSE;
2212 raw_devices[1].dwFlags = RIDEV_DEVNOTIFY;
2213 raw_devices[1].hwndTarget = 0;
2214 raw_devices[1].usUsagePage = HID_USAGE_PAGE_GENERIC;
2215 raw_devices[1].usUsage = HID_USAGE_GENERIC_KEYBOARD;
2216
2217 ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE( raw_devices ), sizeof(RAWINPUTDEVICE) ) );
2218 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ))
2219 {
2220 ok_ne( WM_INPUT_DEVICE_CHANGE, msg.message, UINT, "%#x" );
2223 }
2224
2225 /* RIDEV_DEVNOTIFY send messages only to hwndTarget */
2226 raw_devices[0].hwndTarget = hwnd;
2227 raw_devices[1].hwndTarget = hwnd;
2228
2229 count = 0;
2230 ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE( raw_devices ), sizeof(RAWINPUTDEVICE) ) );
2231 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ))
2232 {
2233 if (msg.message == WM_INPUT_DEVICE_CHANGE) count++;
2236 }
2237 ok( count >= 2, "got %u messages\n", count );
2238
2239 count = 0;
2240 ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE( raw_devices ), sizeof(RAWINPUTDEVICE) ) );
2241 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ))
2242 {
2243 if (msg.message == WM_INPUT_DEVICE_CHANGE) count++;
2246 }
2247 ok( count >= 2, "got %u messages\n", count );
2248
2249 /* RIDEV_REMOVE requires hwndTarget == NULL */
2250 raw_devices[0].dwFlags = RIDEV_REMOVE;
2251 raw_devices[0].hwndTarget = hwnd;
2252 raw_devices[1].dwFlags = RIDEV_REMOVE;
2253 raw_devices[1].hwndTarget = hwnd;
2254
2255 SetLastError(0xdeadbeef);
2256 ok_ret( 0, RegisterRawInputDevices( raw_devices, ARRAY_SIZE( raw_devices ), sizeof(RAWINPUTDEVICE) ) );
2258
2259 raw_devices[0].hwndTarget = 0;
2260 raw_devices[1].hwndTarget = 0;
2261 ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE( raw_devices ), sizeof(RAWINPUTDEVICE) ) );
2262
2263 ok_ret( 1, DestroyWindow( hwnd ) );
2264}
2265
2267
2268typedef struct
2269{
2275
2276#ifdef _WIN64
2277typedef RAWINPUTHEADER RAWINPUTHEADER64;
2278typedef RAWINPUT RAWINPUT64;
2279#else
2280typedef struct
2281{
2287
2288typedef struct
2289{
2291 union {
2292 RAWMOUSE mouse;
2293 RAWKEYBOARD keyboard;
2294 RAWHID hid;
2296} RAWINPUT64;
2297#endif
2298
2300{
2301 if (msg == WM_INPUT)
2302 {
2303 UINT i, size, rawinput_size, iteration = rawinputbuffer_wndproc_count++;
2304 char buffer[16 * sizeof(RAWINPUT64)];
2305 RAWINPUT64 *rawbuffer64 = (RAWINPUT64 *)buffer;
2306 RAWINPUT *rawbuffer = (RAWINPUT *)buffer;
2307 HRAWINPUT handle = (HRAWINPUT)lparam;
2308 RAWINPUT rawinput = {{0}};
2309
2311
2312 if (is_wow64) rawinput_size = sizeof(RAWINPUTHEADER64) + sizeof(RAWKEYBOARD);
2313 else rawinput_size = sizeof(RAWINPUTHEADER) + sizeof(RAWKEYBOARD);
2314
2315 size = sizeof(buffer);
2316 memset( buffer, 0, sizeof(buffer) );
2317 ok_ret( 3, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER)) );
2318 ok_eq( sizeof(buffer), size, UINT, "%u" );
2319
2320 for (i = 0; i < 3; ++i)
2321 {
2322 winetest_push_context( "%u", i );
2323 if (is_wow64)
2324 {
2325 RAWINPUT64 *rawinput = (RAWINPUT64 *)(buffer + i * rawinput_size);
2326 ok_eq( RIM_TYPEKEYBOARD, rawinput->header.dwType, UINT, "%u" );
2327 ok_eq( rawinput_size, rawinput->header.dwSize, UINT, "%u" );
2328 ok_eq( wparam, rawinput->header.wParam, WPARAM, "%Iu" );
2329 ok_eq( i + 2, rawinput->data.keyboard.MakeCode, WPARAM, "%Iu" );
2330 }
2331 else
2332 {
2333 RAWINPUT *rawinput = (RAWINPUT *)(buffer + i * rawinput_size);
2334 ok_eq( RIM_TYPEKEYBOARD, rawinput->header.dwType, UINT, "%u" );
2335 ok_eq( rawinput_size, rawinput->header.dwSize, UINT, "%u" );
2336 ok_eq( wparam, rawinput->header.wParam, WPARAM, "%Iu" );
2337 ok_eq( i + 2, rawinput->data.keyboard.MakeCode, WPARAM, "%Iu" );
2338 }
2340 }
2341
2342 /* the first event should be removed by the next GetRawInputBuffer call
2343 * and the others should do another round through the message loop but not more */
2344 if (iteration == 0)
2345 {
2346 keybd_event( 'X', 5, 0, 0 );
2347 keybd_event( 'X', 6, KEYEVENTF_KEYUP, 0 );
2348 keybd_event( 'X', 2, KEYEVENTF_KEYUP, 0 );
2349 keybd_event( 'X', 3, 0, 0 );
2350 keybd_event( 'X', 4, KEYEVENTF_KEYUP, 0 );
2351
2352 /* even though rawinput_size is the minimum required size,
2353 * it needs one more byte to return success */
2354 size = sizeof(rawinput) + 1;
2355 memset( buffer, 0, sizeof(buffer) );
2356 ok_ret( 1, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) );
2357 if (is_wow64) ok_eq( 5, rawbuffer64->data.keyboard.MakeCode, WPARAM, "%Iu" );
2358 else ok_eq( 5, rawbuffer->data.keyboard.MakeCode, WPARAM, "%Iu" );
2359
2360 /* peek the messages now, they should still arrive in the correct order */
2362 wait_messages( 0, FALSE );
2364
2365 /* reading the message data now should fail, the data
2366 * from the first message has been overwritten. */
2367 SetLastError( 0xdeadbeef );
2368 size = sizeof(rawinput);
2369 ok_ret( (UINT)-1, GetRawInputData( handle, RID_HEADER, &rawinput, &size, sizeof(RAWINPUTHEADER) ) );
2371 }
2372 else
2373 {
2374 SetLastError( 0xdeadbeef );
2375 ok_ret( (UINT)-1, GetRawInputData( handle, RID_HEADER, &rawinput, &size, 0) );
2377
2378 SetLastError( 0xdeadbeef );
2379 ok_ret( (UINT)-1, GetRawInputData( handle, RID_HEADER, &rawinput, &size, sizeof(RAWINPUTHEADER) + 1 ) );
2381
2382 size = sizeof(RAWINPUTHEADER);
2383 rawinput_size = sizeof(RAWINPUTHEADER) + sizeof(RAWKEYBOARD);
2384 ok_ret( sizeof(RAWINPUTHEADER), GetRawInputData( handle, RID_HEADER, &rawinput, &size, sizeof(RAWINPUTHEADER) ) );
2385 ok_eq( rawinput_size, rawinput.header.dwSize, UINT, "%u" );
2386 ok_eq( RIM_TYPEKEYBOARD, rawinput.header.dwType, UINT, "%u" );
2387
2388
2389 SetLastError( 0xdeadbeef );
2390 ok_ret( (UINT)-1, GetRawInputData( handle, RID_INPUT, &rawinput, &size, 0) );
2392
2393 SetLastError( 0xdeadbeef );
2394 ok_ret( (UINT)-1, GetRawInputData( handle, RID_INPUT, &rawinput, &size, sizeof(RAWINPUTHEADER) + 1 ) );
2396
2397 SetLastError( 0xdeadbeef );
2398 size = 0;
2399 ok_ret( (UINT)-1, GetRawInputData( handle, RID_INPUT, &rawinput, &size, sizeof(RAWINPUTHEADER) ) );
2401
2402 SetLastError( 0xdeadbeef );
2403 size = sizeof(rawinput);
2404 ok_ret( (UINT)-1, GetRawInputData( handle, 0, &rawinput, &size, sizeof(RAWINPUTHEADER) ) );
2406
2407 SetLastError( 0xdeadbeef );
2408 size = sizeof(rawinput);
2409 ok_ret( rawinput_size, GetRawInputData( handle, RID_INPUT, &rawinput, &size, sizeof(RAWINPUTHEADER) ) );
2410 ok_eq( 6, rawinput.data.keyboard.MakeCode, UINT, "%u" );
2411
2412 SetLastError( 0xdeadbeef );
2413 size = sizeof(buffer);
2414 if (sizeof(void *) == 8)
2415 {
2416 ok_ret( (UINT)-1, GetRawInputData( handle, RID_INPUT, &rawinput, &size, sizeof(RAWINPUTHEADER32) ) );
2417 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputData returned %08lx\n", GetLastError());
2418 }
2419 else if (is_wow64)
2420 {
2421 todo_wine
2422 ok_ret( rawinput_size, GetRawInputData( handle, RID_INPUT, &rawinput, &size, sizeof(RAWINPUTHEADER64) ) );
2423 ok_eq( 6, rawinput.data.keyboard.MakeCode, UINT, "%u" );
2424 todo_wine
2425 ok_ret( 0xdeadbeef, GetLastError() );
2426 }
2427 else
2428 {
2429 ok_ret( (UINT)-1, GetRawInputData( handle, RID_INPUT, &rawinput, &size, sizeof(RAWINPUTHEADER64) ) );
2430 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputData returned %08lx\n", GetLastError());
2431 }
2432 }
2433
2435 return 0;
2436 }
2437
2438 return DefWindowProcW( hwnd, msg, wparam, lparam );
2439}
2440
2441static void test_GetRawInputBuffer(void)
2442{
2443 unsigned int size, rawinput_size, header_size;
2444 RAWINPUTDEVICE raw_devices[1];
2445 char buffer[16 * sizeof(RAWINPUT64)];
2446 RAWINPUT64 *rawbuffer64 = (RAWINPUT64 *)buffer;
2447 RAWINPUT *rawbuffer = (RAWINPUT *)buffer;
2448 DWORD t1, t2, t3, now, pos1, pos2;
2449 LPARAM extra_info1, extra_info2;
2450 INPUT_MESSAGE_SOURCE source;
2451 POINT pt;
2452 HWND hwnd;
2453 BOOL ret;
2454
2455 if (is_wow64) rawinput_size = sizeof(RAWINPUTHEADER64) + sizeof(RAWMOUSE);
2456 else rawinput_size = sizeof(RAWINPUTHEADER) + sizeof(RAWMOUSE);
2457
2460
2461 if (pGetCurrentInputMessageSource)
2462 {
2463 ret = pGetCurrentInputMessageSource( &source );
2464 ok( ret, "got error %lu.\n", GetLastError() );
2465 ok( !source.deviceType, "got %#x.\n", source.deviceType );
2466 ok( !source.originId, "got %#x.\n", source.originId );
2467 }
2468
2469 raw_devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
2470 raw_devices[0].usUsage = HID_USAGE_GENERIC_MOUSE;
2471 raw_devices[0].dwFlags = RIDEV_INPUTSINK;
2472 raw_devices[0].hwndTarget = hwnd;
2473 ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE( raw_devices ), sizeof(RAWINPUTDEVICE) ) );
2474
2475 /* check basic error cases */
2476
2477 SetLastError( 0xdeadbeef );
2478 ok_ret( (UINT)-1, GetRawInputBuffer( NULL, NULL, sizeof(RAWINPUTHEADER) ) );
2480 SetLastError( 0xdeadbeef );
2481 size = sizeof(buffer);
2482 ok_ret( (UINT)-1, GetRawInputBuffer( rawbuffer, &size, 0 ) );
2484
2485 /* valid calls, but no input */
2486 t1 = GetMessageTime();
2487 pos1 = GetMessagePos();
2488 extra_info1 = GetMessageExtraInfo();
2489 now = GetTickCount();
2490 ok( t1 <= now, "got %lu, %lu.\n", t1, now );
2491
2492 size = sizeof(buffer);
2493 ok_ret( 0, GetRawInputBuffer( NULL, &size, sizeof(RAWINPUTHEADER) ) );
2494 ok_eq( 0, size, UINT, "%u" );
2495 size = 0;
2496 ok_ret( 0, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) );
2497 ok_eq( 0, size, UINT, "%u" );
2498 size = sizeof(buffer);
2499 ok_ret( 0, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) );
2500 ok_eq( 0, size, UINT, "%u" );
2501
2502
2503 Sleep( 20 );
2504 mouse_event( MOUSEEVENTF_MOVE, 5, 0, 0, 0xdeadbeef );
2505 t2 = GetMessageTime();
2506 ok( t2 == t1, "got %lu, %lu.\n", t1, t2 );
2507 /* invalid calls with input */
2508
2509 SetLastError( 0xdeadbeef );
2510 size = 0;
2511 ok_ret( (UINT)-1, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) );
2512 ok_eq( rawinput_size, size, UINT, "%u" );
2514 t2 = GetMessageTime();
2515 ok( t2 == t1, "got %lu, %lu.\n", t1, t2 );
2516
2517 SetLastError( 0xdeadbeef );
2518 size = sizeof(buffer);
2519 ok_ret( (UINT)-1, GetRawInputBuffer( rawbuffer, &size, 0 ) );
2521 SetLastError( 0xdeadbeef );
2522 size = sizeof(buffer);
2523 ok_ret( (UINT)-1, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) + 1 ) );
2525
2526 /* the function returns 64-bit RAWINPUT structures on WoW64, but still
2527 * forbids sizeof(RAWINPUTHEADER) from the wrong architecture */
2528 SetLastError( 0xdeadbeef );
2529 size = sizeof(buffer);
2530 header_size = (sizeof(void *) == 8 ? sizeof(RAWINPUTHEADER32) : sizeof(RAWINPUTHEADER64));
2531 ok_ret( (UINT)-1, GetRawInputBuffer( rawbuffer, &size, header_size ) );
2533
2534
2535 /* NOTE: calling with size == rawinput_size returns an error, */
2536 /* BUT it fills the buffer nonetheless and empties the internal buffer (!!) */
2537
2538 Sleep( 20 );
2539 t2 = GetTickCount();
2540 size = 0;
2541 ok_ret( 0, GetRawInputBuffer( NULL, &size, sizeof(RAWINPUTHEADER) ) );
2542 ok_eq( rawinput_size, size, UINT, "%u" );
2543
2544 SetLastError( 0xdeadbeef );
2545 size = rawinput_size;
2546 memset( buffer, 0, sizeof(buffer) );
2547 ok_ret( (UINT)-1, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) );
2549 if (is_wow64) ok_eq( 5, rawbuffer64->data.mouse.lLastX, UINT, "%u" );
2550 else ok_eq( 5, rawbuffer->data.mouse.lLastX, UINT, "%u" );
2551
2552 t3 = GetMessageTime();
2553 pos2 = GetMessagePos();
2554 extra_info2 = GetMessageExtraInfo();
2555 ok( extra_info2 == extra_info1, "got %#Ix, %#Ix.\n", extra_info1, extra_info2 );
2556 GetCursorPos( &pt );
2557 ok( t3 > t1, "got %lu, %lu.\n", t1, t3 );
2558 ok( t3 < t2, "got %lu, %lu.\n", t2, t3 );
2559 ok( pos1 == pos2, "got pos1 (%ld, %ld), pos2 (%ld, %ld), pt (%ld %ld).\n",
2560 pos1 & 0xffff, pos1 >> 16, pos2 & 0xffff, pos2 >> 16, pt.x, pt.y );
2561 if (pGetCurrentInputMessageSource)
2562 {
2563 ret = pGetCurrentInputMessageSource( &source );
2564 ok( ret, "got error %lu.\n", GetLastError() );
2565 ok( !source.deviceType, "got %#x.\n", source.deviceType );
2566 ok( !source.originId, "got %#x.\n", source.originId );
2567 }
2568
2569 /* no more data to read */
2570
2571 size = sizeof(buffer);
2572 ok_ret( 0, GetRawInputBuffer( NULL, &size, sizeof(RAWINPUTHEADER) ) );
2573 ok_eq( 0, size, UINT, "%u" );
2574
2575
2576 /* rawinput_size + 1 succeeds */
2577 t1 = GetMessageTime();
2578 pos1 = GetMessagePos();
2579 extra_info1 = GetMessageExtraInfo();
2580 now = GetTickCount();
2581 ok( t1 <= now, "got %lu, %lu.\n", t1, now );
2582
2583 Sleep( 20 );
2584 mouse_event( MOUSEEVENTF_MOVE, 5, 0, 0, 0xfeedcafe );
2585
2586 t2 = GetMessageTime();
2587 ok( t2 == t1, "got %lu, %lu.\n", t1, t2 );
2588
2589 Sleep( 20 );
2590 t2 = GetTickCount();
2591
2592 size = rawinput_size + 1;
2593 memset( buffer, 0, sizeof(buffer) );
2594 ok_ret( 1, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) );
2595 ok_eq( rawinput_size + 1, size, UINT, "%u" );
2596 if (is_wow64)
2597 {
2598 ok_eq( RIM_TYPEMOUSE, rawbuffer64->header.dwType, UINT, "%#x" );
2599 ok_eq( 0, rawbuffer64->header.wParam, WPARAM, "%Iu" );
2600 ok_eq( 5, rawbuffer64->data.mouse.lLastX, UINT, "%u" );
2601 }
2602 else
2603 {
2604 ok_eq( RIM_TYPEMOUSE, rawbuffer->header.dwType, UINT, "%#x" );
2605 ok_eq( 0, rawbuffer->header.wParam, WPARAM, "%Iu" );
2606 ok_eq( 5, rawbuffer->data.mouse.lLastX, UINT, "%u" );
2607 }
2608
2609 size = sizeof(buffer);
2610 ok_ret( 0, GetRawInputBuffer( NULL, &size, sizeof(RAWINPUTHEADER) ) );
2611 ok_eq( 0, size, UINT, "%u" );
2612
2613 t3 = GetMessageTime();
2614 pos2 = GetMessagePos();
2615 extra_info2 = GetMessageExtraInfo();
2616 GetCursorPos(&pt);
2617 ok( extra_info2 == extra_info1, "got %#Ix, %#Ix.\n", extra_info1, extra_info2 );
2618 ok( t3 > t1, "got %lu, %lu.\n", t1, t3 );
2619 ok( t3 < t2, "got %lu, %lu.\n", t2, t3 );
2620 ok( pos1 == pos2, "got pos1 (%ld, %ld), pos2 (%ld, %ld), pt (%ld %ld).\n",
2621 pos1 & 0xffff, pos1 >> 16, pos2 & 0xffff, pos2 >> 16, pt.x, pt.y );
2622
2623 raw_devices[0].dwFlags = RIDEV_REMOVE;
2624 raw_devices[0].hwndTarget = 0;
2625 ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE) ) );
2626
2627
2628 /* some keyboard tests to better check fields under wow64 */
2629 raw_devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
2630 raw_devices[0].usUsage = HID_USAGE_GENERIC_KEYBOARD;
2631 raw_devices[0].dwFlags = RIDEV_INPUTSINK;
2632 raw_devices[0].hwndTarget = hwnd;
2633 ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE) ) );
2634
2635 keybd_event( 'X', 0x2d, 0, 0 );
2636 keybd_event( 'X', 0x2d, KEYEVENTF_KEYUP, 0 );
2637
2638 if (is_wow64) rawinput_size = sizeof(RAWINPUTHEADER64) + sizeof(RAWKEYBOARD);
2639 else rawinput_size = sizeof(RAWINPUTHEADER) + sizeof(RAWKEYBOARD);
2640
2641 size = 0;
2642 ok_ret( 0, GetRawInputBuffer( NULL, &size, sizeof(RAWINPUTHEADER) ) );
2643 ok_eq( rawinput_size, size, UINT, "%u" );
2644
2645 size = sizeof(buffer);
2646 memset( buffer, 0, sizeof(buffer) );
2647 ok_ret( 2, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) );
2648 ok_eq( sizeof(buffer), size, UINT, "%u" );
2649 if (is_wow64)
2650 {
2651 ok_eq( RIM_TYPEKEYBOARD, rawbuffer64->header.dwType, UINT, "%u" );
2652 ok_eq( 0, rawbuffer64->header.wParam, UINT, "%u" );
2653 ok_eq( 0x2d, rawbuffer64->data.keyboard.MakeCode, UINT, "%#x" );
2654 }
2655 else
2656 {
2657 ok_eq( RIM_TYPEKEYBOARD, rawbuffer->header.dwType, UINT, "%u" );
2658 ok_eq( 0, rawbuffer->header.wParam, UINT, "%u" );
2659 ok_eq( 0x2d, rawbuffer->data.keyboard.MakeCode, UINT, "%#x" );
2660 }
2661
2662
2663 /* test GetRawInputBuffer interaction with WM_INPUT messages */
2664
2666 keybd_event( 'X', 1, 0, 0 );
2667 keybd_event( 'X', 2, KEYEVENTF_KEYUP, 0 );
2668 keybd_event( 'X', 3, 0, 0 );
2669 keybd_event( 'X', 4, KEYEVENTF_KEYUP, 0 );
2670 wait_messages( 100, FALSE );
2672
2673 keybd_event( 'X', 3, 0, 0 );
2674 keybd_event( 'X', 4, KEYEVENTF_KEYUP, 0 );
2675
2676 raw_devices[0].dwFlags = RIDEV_REMOVE;
2677 raw_devices[0].hwndTarget = 0;
2678 ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE) ) );
2679
2680
2681 /* rawinput buffer survives registered device changes */
2682
2683 size = rawinput_size + 1;
2684 ok_ret( 1, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) );
2685 ok_eq( rawinput_size + 1, size, UINT, "%u" );
2686
2687 raw_devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
2688 raw_devices[0].usUsage = HID_USAGE_GENERIC_MOUSE;
2689 raw_devices[0].dwFlags = RIDEV_INPUTSINK;
2690 raw_devices[0].hwndTarget = hwnd;
2691 ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE) ) );
2692
2693 if (is_wow64) rawinput_size = sizeof(RAWINPUTHEADER64) + sizeof(RAWMOUSE);
2694 else rawinput_size = sizeof(RAWINPUTHEADER) + sizeof(RAWMOUSE);
2695
2696 size = rawinput_size + 1;
2697 ok_ret( 1, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) );
2698 ok_eq( rawinput_size + 1, size, UINT, "%u" );
2699 size = sizeof(buffer);
2700 ok_ret( 0, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) );
2701 ok_eq( 0, size, UINT, "%u" );
2702
2703 raw_devices[0].dwFlags = RIDEV_REMOVE;
2704 raw_devices[0].hwndTarget = 0;
2705 ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE) ) );
2706
2707
2708 ok_ret( 1, DestroyWindow( hwnd ) );
2709}
2710
2714
2716{
2717 UINT ret, raw_size;
2718 RAWINPUT raw;
2719
2720 if (msg == WM_INPUT)
2721 {
2723 ok(!rawinput_test_received_raw, "Unexpected spurious WM_INPUT message.\n");
2724 ok(wparam == RIM_INPUT || wparam == RIM_INPUTSINK, "Unexpected wparam: %Iu\n", wparam);
2725
2727 if (wparam == RIM_INPUT) rawinput_test_received_rawfg = TRUE;
2728
2729 ret = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, NULL, &raw_size, sizeof(RAWINPUTHEADER));
2730 ok(ret == 0, "GetRawInputData failed\n");
2731 ok(raw_size <= sizeof(raw), "Unexpected rawinput data size: %u\n", raw_size);
2732
2733 raw_size = sizeof(raw);
2734 ret = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &raw, &raw_size, sizeof(RAWINPUTHEADER));
2735 ok(ret > 0 && ret != (UINT)-1, "GetRawInputData failed\n");
2736 ok(raw.header.dwType == RIM_TYPEMOUSE, "Unexpected rawinput type: %lu\n", raw.header.dwType);
2737 ok(raw.header.dwSize == raw_size, "Expected size %u, got %lu\n", raw_size, raw.header.dwSize);
2739 ok(raw.header.wParam == wparam, "Expected wparam %Iu, got %Iu\n", wparam, raw.header.wParam);
2740
2741 ok(!(raw.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE), "Unexpected absolute rawinput motion\n");
2742 ok(!(raw.data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP), "Unexpected virtual desktop rawinput motion\n");
2743 }
2744
2746
2747 return DefWindowProcA(hwnd, msg, wparam, lparam);
2748}
2749
2751{
2761};
2762
2764{
2765 { FALSE, FALSE, 0, TRUE, FALSE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
2766 { TRUE, FALSE, 0, TRUE, TRUE, TRUE, /* todos: */ FALSE, FALSE, FALSE },
2767 { TRUE, TRUE, 0, TRUE, TRUE, TRUE, /* todos: */ FALSE, FALSE, FALSE },
2768 { TRUE, TRUE, RIDEV_NOLEGACY, FALSE, TRUE, TRUE, /* todos: */ FALSE, FALSE, FALSE },
2769
2770 /* same-process foreground tests */
2771 { TRUE, FALSE, 0, FALSE, FALSE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
2772 { TRUE, TRUE, 0, FALSE, TRUE, TRUE, /* todos: */ FALSE, FALSE, FALSE },
2773
2774 /* cross-process foreground tests */
2775 { TRUE, TRUE, 0, FALSE, FALSE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
2776 { TRUE, TRUE, RIDEV_INPUTSINK, FALSE, TRUE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
2777 { TRUE, TRUE, 0, FALSE, FALSE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
2778
2779 /* multi-process rawinput tests */
2780 { TRUE, TRUE, 0, FALSE, FALSE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
2781 { TRUE, TRUE, RIDEV_INPUTSINK, FALSE, TRUE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
2782 { TRUE, TRUE, RIDEV_INPUTSINK, FALSE, TRUE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
2783
2784 { TRUE, TRUE, RIDEV_EXINPUTSINK, FALSE, FALSE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
2785 { TRUE, TRUE, RIDEV_EXINPUTSINK, FALSE, TRUE, FALSE, /* todos: */ FALSE, TRUE, FALSE },
2786
2787 /* cross-desktop foreground tests */
2788 { TRUE, FALSE, 0, FALSE, FALSE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
2789 { TRUE, TRUE, 0, FALSE, TRUE, TRUE, /* todos: */ FALSE, FALSE, FALSE },
2790 { TRUE, TRUE, RIDEV_INPUTSINK, FALSE, FALSE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
2791};
2792
2793static void rawinput_test_process(void)
2794{
2795 RAWINPUTDEVICE raw_devices[1];
2796 HANDLE ready, start, done;
2797 DWORD ret;
2798 POINT pt;
2799 HWND hwnd = NULL;
2800 MSG msg;
2801 int i;
2802
2803 ready = OpenEventA(EVENT_ALL_ACCESS, FALSE, "rawinput_test_process_ready");
2804 ok(ready != 0, "OpenEventA failed, error: %lu\n", GetLastError());
2805
2806 start = OpenEventA(EVENT_ALL_ACCESS, FALSE, "rawinput_test_process_start");
2807 ok(start != 0, "OpenEventA failed, error: %lu\n", GetLastError());
2808
2809 done = OpenEventA(EVENT_ALL_ACCESS, FALSE, "rawinput_test_process_done");
2810 ok(done != 0, "OpenEventA failed, error: %lu\n", GetLastError());
2811
2812 for (i = 0; i < ARRAY_SIZE(rawinput_tests); ++i)
2813 {
2815 ResetEvent(ready);
2816
2817 switch (i)
2818 {
2819 case 6:
2820 case 7:
2821 case 8:
2822 case 9:
2823 case 10:
2824 case 11:
2825 case 12:
2826 case 13:
2827 case 16:
2828 GetCursorPos(&pt);
2829
2830 hwnd = CreateWindowA("static", "static", WS_VISIBLE | WS_POPUP,
2831 pt.x - 50, pt.y - 50, 100, 100, 0, NULL, NULL, NULL);
2833 ok(hwnd != 0, "CreateWindow failed\n");
2835
2836 /* FIXME: Try to workaround X11/Win32 focus inconsistencies and
2837 * make the window visible and foreground as hard as possible. */
2843
2844 if (i == 9 || i == 10 || i == 11 || i == 12)
2845 {
2846 raw_devices[0].usUsagePage = 0x01;
2847 raw_devices[0].usUsage = 0x02;
2848 raw_devices[0].dwFlags = i == 11 ? RIDEV_INPUTSINK : 0;
2849 raw_devices[0].hwndTarget = i == 11 ? hwnd : 0;
2850
2851 SetLastError(0xdeadbeef);
2852 ret = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE));
2853 ok(ret, "%d: RegisterRawInputDevices failed\n", i);
2854 ok(GetLastError() == 0xdeadbeef, "%d: RegisterRawInputDevices returned %08lx\n", i, GetLastError());
2855 }
2856
2860
2861 /* fallthrough */
2862 case 14:
2863 case 15:
2864 if (i != 8) mouse_event(MOUSEEVENTF_MOVE, 5, 0, 0, 0);
2866 break;
2867 }
2868
2869 SetEvent(start);
2870
2872 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2873
2874 ResetEvent(done);
2875
2876 if (i == 9 || i == 10 || i == 11 || i == 12)
2877 {
2878 raw_devices[0].dwFlags = RIDEV_REMOVE;
2879 raw_devices[0].hwndTarget = 0;
2880
2882 ok(rawinput_test_received_legacy, "%d: foreground process expected WM_MOUSEMOVE message\n", i);
2883 ok(rawinput_test_received_raw, "%d: foreground process expected WM_INPUT message\n", i);
2884 ok(rawinput_test_received_rawfg, "%d: foreground process expected RIM_INPUT message\n", i);
2885
2886 SetLastError(0xdeadbeef);
2887 ret = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE));
2888 ok(ret, "%d: RegisterRawInputDevices failed\n", i);
2889 ok(GetLastError() == 0xdeadbeef, "%d: RegisterRawInputDevices returned %08lx\n", i, GetLastError());
2890 }
2891
2892 if (hwnd) DestroyWindow(hwnd);
2893 }
2894
2896 CloseHandle(done);
2898 CloseHandle(ready);
2899}
2900
2902{
2903 HDESK desk;
2907};
2908
2910{
2912 RAWINPUTDEVICE raw_devices[1];
2913 DWORD ret;
2914 POINT pt;
2915 HWND hwnd = NULL;
2916 MSG msg;
2917 int i;
2918
2919 ok( SetThreadDesktop( params->desk ), "SetThreadDesktop failed\n" );
2920
2921 for (i = 14; i < ARRAY_SIZE(rawinput_tests); ++i)
2922 {
2924 ResetEvent(params->ready);
2925
2926 switch (i)
2927 {
2928 case 14:
2929 case 15:
2930 case 16:
2931 GetCursorPos(&pt);
2932
2933 hwnd = CreateWindowA("static", "static", WS_VISIBLE | WS_POPUP,
2934 pt.x - 50, pt.y - 50, 100, 100, 0, NULL, NULL, NULL);
2935 ok(hwnd != 0, "CreateWindow failed\n");
2938
2939 /* FIXME: Try to workaround X11/Win32 focus inconsistencies and
2940 * make the window visible and foreground as hard as possible. */
2946
2947 raw_devices[0].usUsagePage = 0x01;
2948 raw_devices[0].usUsage = 0x02;
2949 raw_devices[0].dwFlags = rawinput_tests[i].register_flags;
2950 raw_devices[0].hwndTarget = rawinput_tests[i].register_window ? hwnd : 0;
2951
2955
2956 SetLastError(0xdeadbeef);
2957 ret = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE));
2958 ok(ret, "%d: RegisterRawInputDevices failed\n", i);
2959 ok(GetLastError() == 0xdeadbeef, "%d: RegisterRawInputDevices returned %08lx\n", i, GetLastError());
2960 break;
2961 }
2962
2963 SetEvent(params->start);
2964
2966 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2967
2968 ResetEvent(params->done);
2969 if (hwnd) DestroyWindow(hwnd);
2970 }
2971
2972 return 0;
2973}
2974
2976{
2978 HANDLE thread;
2979 POINT pt;
2980 HWND hwnd = NULL;
2981 int i;
2982
2983 for (i = 0; i < 14; ++i)
2984 {
2986 ResetEvent(params->ready);
2987
2988 switch (i)
2989 {
2990 case 4:
2991 case 5:
2992 GetCursorPos(&pt);
2993
2994 hwnd = CreateWindowA("static", "static", WS_VISIBLE | WS_POPUP,
2995 pt.x - 50, pt.y - 50, 100, 100, 0, NULL, NULL, NULL);
2996 ok(hwnd != 0, "CreateWindow failed\n");
2998
2999 /* FIXME: Try to workaround X11/Win32 focus inconsistencies and
3000 * make the window visible and foreground as hard as possible. */
3006
3007 mouse_event(MOUSEEVENTF_MOVE, 5, 0, 0, 0);
3009 break;
3010 }
3011
3012 SetEvent(params->start);
3013
3015 ResetEvent(params->done);
3016 if (hwnd) DestroyWindow(hwnd);
3017 }
3018
3020 ok(thread != NULL, "CreateThread failed\n");
3023
3024 return 0;
3025}
3026
3027static void test_rawinput(const char* argv0)
3028{
3030 PROCESS_INFORMATION process_info;
3031 RAWINPUTDEVICE raw_devices[1];
3032 STARTUPINFOA startup_info;
3033 HANDLE thread, process_ready, process_start, process_done;
3034 DWORD ret;
3035 POINT pt, newpt;
3036 HWND hwnd;
3037 BOOL skipped;
3038 char path[MAX_PATH];
3039 int i;
3040
3041 params.desk = CreateDesktopA( "rawinput_test_desktop", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
3042 ok( params.desk != NULL, "CreateDesktopA failed, last error: %lu\n", GetLastError() );
3043
3044 params.ready = CreateEventA(NULL, FALSE, FALSE, NULL);
3045 ok(params.ready != NULL, "CreateEvent failed\n");
3046
3047 params.start = CreateEventA(NULL, FALSE, FALSE, NULL);
3048 ok(params.start != NULL, "CreateEvent failed\n");
3049
3051 ok(params.done != NULL, "CreateEvent failed\n");
3052
3054 ok(thread != NULL, "CreateThread failed\n");
3055
3056 process_ready = CreateEventA(NULL, FALSE, FALSE, "rawinput_test_process_ready");
3057 ok(process_ready != NULL, "CreateEventA failed\n");
3058
3059 process_start = CreateEventA(NULL, FALSE, FALSE, "rawinput_test_process_start");
3060 ok(process_start != NULL, "CreateEventA failed\n");
3061
3062 process_done = CreateEventA(NULL, FALSE, FALSE, "rawinput_test_process_done");
3063 ok(process_done != NULL, "CreateEventA failed\n");
3064
3065 memset(&startup_info, 0, sizeof(startup_info));
3066 startup_info.cb = sizeof(startup_info);
3067 startup_info.dwFlags = STARTF_USESHOWWINDOW;
3068 startup_info.wShowWindow = SW_SHOWNORMAL;
3069
3070 sprintf(path, "%s input rawinput_test", argv0);
3071 ret = CreateProcessA(NULL, path, NULL, NULL, TRUE, 0, NULL, NULL, &startup_info, &process_info );
3072 ok(ret, "CreateProcess \"%s\" failed err %lu.\n", path, GetLastError());
3073
3074 SetCursorPos(100, 100);
3076
3077 for (i = 0; i < ARRAY_SIZE(rawinput_tests); ++i)
3078 {
3079 GetCursorPos(&pt);
3080
3081 hwnd = CreateWindowA("static", "static", WS_VISIBLE | WS_POPUP,
3082 pt.x - 50, pt.y - 50, 100, 100, 0, NULL, NULL, NULL);
3083 ok(hwnd != 0, "CreateWindow failed\n");
3084 if (i != 14 && i != 15 && i != 16)
3087
3088 /* FIXME: Try to workaround X11/Win32 focus inconsistencies and
3089 * make the window visible and foreground as hard as possible. */
3095
3099
3100 raw_devices[0].usUsagePage = 0x01;
3101 raw_devices[0].usUsage = 0x02;
3102 raw_devices[0].dwFlags = rawinput_tests[i].register_flags;
3103 raw_devices[0].hwndTarget = rawinput_tests[i].register_window ? hwnd : 0;
3104
3105 if (!rawinput_tests[i].register_device)
3106 skipped = FALSE;
3107 else
3108 {
3109 SetLastError(0xdeadbeef);
3110 skipped = !RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE));
3111 if (rawinput_tests[i].register_flags == RIDEV_EXINPUTSINK && skipped)
3112 win_skip("RIDEV_EXINPUTSINK not supported\n");
3113 else
3114 ok(!skipped, "%d: RegisterRawInputDevices failed: %lu\n", i, GetLastError());
3115 }
3116
3117 SetEvent(params.ready);
3119 ResetEvent(params.start);
3120
3121 /* we need the main window to be over the other thread window, as although
3122 * it is in another desktop, it will receive the messages directly otherwise */
3123 switch (i)
3124 {
3125 case 14:
3126 case 15:
3128 hwnd = CreateWindowA("static", "static", WS_VISIBLE | WS_POPUP,
3129 pt.x - 50, pt.y - 50, 100, 100, 0, NULL, NULL, NULL);
3130 ok(hwnd != 0, "CreateWindow failed\n");
3134
3138 break;
3139 }
3140
3141 SetEvent(process_ready);
3142 WaitForSingleObject(process_start, INFINITE);
3143 ResetEvent(process_start);
3144
3145 if (i <= 3 || i == 8) mouse_event(MOUSEEVENTF_MOVE, 5, 0, 0, 0);
3147
3148 SetEvent(process_done);
3149 SetEvent(params.done);
3150
3152 if (!skipped)
3153 {
3154 todo_wine_if(rawinput_tests[i].todo_legacy)
3156 "%d: %sexpected WM_MOUSEMOVE message\n", i, rawinput_tests[i].expect_legacy ? "" : "un");
3157 todo_wine_if(rawinput_tests[i].todo_raw)
3159 "%d: %sexpected WM_INPUT message\n", i, rawinput_tests[i].expect_raw ? "" : "un");
3160 todo_wine_if(rawinput_tests[i].todo_rawfg)
3162 "%d: %sexpected RIM_INPUT message\n", i, rawinput_tests[i].expect_rawfg ? "" : "un");
3163 }
3164
3165 GetCursorPos(&newpt);
3166 ok((newpt.x - pt.x) == 5 || (newpt.x - pt.x) == 4, "%d: Unexpected cursor movement\n", i);
3167
3168 if (rawinput_tests[i].register_device)
3169 {
3170 raw_devices[0].dwFlags = RIDEV_REMOVE;
3171 raw_devices[0].hwndTarget = 0;
3172
3173 SetLastError(0xdeadbeef);
3174 ret = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE));
3175 ok(ret, "%d: RegisterRawInputDevices failed: %lu\n", i, GetLastError());
3176 }
3177
3179 }
3180
3181 SetEvent(process_ready);
3182 winetest_wait_child_process(process_info.hProcess);
3183 CloseHandle(process_info.hProcess);
3184 CloseHandle(process_info.hThread);
3185 CloseHandle(process_done);
3186 CloseHandle(process_start);
3187 CloseHandle(process_ready);
3188
3190
3191 CloseHandle(params.done);
3192 CloseHandle(params.start);
3193 CloseHandle(params.ready);
3195
3196 CloseDesktop(params.desk);
3197}
3198
3199static void test_DefRawInputProc(void)
3200{
3201 LRESULT ret;
3202
3203 SetLastError(0xdeadbeef);
3204 ret = DefRawInputProc(NULL, 0, sizeof(RAWINPUTHEADER));
3205 ok(!ret, "got %Id\n", ret);
3206 ok(GetLastError() == 0xdeadbeef, "got %ld\n", GetLastError());
3207 ret = DefRawInputProc(LongToPtr(0xcafe), 0xbeef, sizeof(RAWINPUTHEADER));
3208 ok(!ret, "got %Id\n", ret);
3209 ok(GetLastError() == 0xdeadbeef, "got %ld\n", GetLastError());
3210 ret = DefRawInputProc(NULL, 0, sizeof(RAWINPUTHEADER) - 1);
3211 ok(ret == -1, "got %Id\n", ret);
3212 ok(GetLastError() == 0xdeadbeef, "got %ld\n", GetLastError());
3213 ret = DefRawInputProc(NULL, 0, sizeof(RAWINPUTHEADER) + 1);
3214 ok(ret == -1, "got %Id\n", ret);
3215 ok(GetLastError() == 0xdeadbeef, "got %ld\n", GetLastError());
3216}
3217
3218static void test_key_map(void)
3219{
3220 HKL kl = GetKeyboardLayout(0);
3221 UINT kL, kR, s, sL;
3222 int i;
3223 static const UINT numpad_collisions[][2] = {
3224 { VK_NUMPAD0, VK_INSERT },
3225 { VK_NUMPAD1, VK_END },
3226 { VK_NUMPAD2, VK_DOWN },
3227 { VK_NUMPAD3, VK_NEXT },
3228 { VK_NUMPAD4, VK_LEFT },
3229 { VK_NUMPAD6, VK_RIGHT },
3230 { VK_NUMPAD7, VK_HOME },
3231 { VK_NUMPAD8, VK_UP },
3232 { VK_NUMPAD9, VK_PRIOR },
3233 };
3234
3236 ok(s != 0, "MapVirtualKeyEx(VK_SHIFT) should return non-zero\n");
3238 ok(s == sL || broken(sL == 0), /* win9x */
3239 "%x != %x\n", s, sL);
3240
3241 kL = MapVirtualKeyExA(0x2a, MAPVK_VSC_TO_VK, kl);
3242 ok(kL == VK_SHIFT, "Scan code -> vKey = %x (not VK_SHIFT)\n", kL);
3243 kR = MapVirtualKeyExA(0x36, MAPVK_VSC_TO_VK, kl);
3244 ok(kR == VK_SHIFT, "Scan code -> vKey = %x (not VK_SHIFT)\n", kR);
3245
3246 kL = MapVirtualKeyExA(0x2a, MAPVK_VSC_TO_VK_EX, kl);
3247 ok(kL == VK_LSHIFT || broken(kL == 0), /* win9x */
3248 "Scan code -> vKey = %x (not VK_LSHIFT)\n", kL);
3249 kR = MapVirtualKeyExA(0x36, MAPVK_VSC_TO_VK_EX, kl);
3250 ok(kR == VK_RSHIFT || broken(kR == 0), /* win9x */
3251 "Scan code -> vKey = %x (not VK_RSHIFT)\n", kR);
3252
3253 /* test that MAPVK_VSC_TO_VK prefers the non-numpad vkey if there's ambiguity */
3254 for (i = 0; i < ARRAY_SIZE(numpad_collisions); i++)
3255 {
3256 UINT numpad_scan = MapVirtualKeyExA(numpad_collisions[i][0], MAPVK_VK_TO_VSC, kl);
3257 UINT other_scan = MapVirtualKeyExA(numpad_collisions[i][1], MAPVK_VK_TO_VSC, kl);
3258
3259 /* do they really collide for this layout? */
3260 if (numpad_scan && other_scan == numpad_scan)
3261 {
3262 UINT vkey = MapVirtualKeyExA(numpad_scan, MAPVK_VSC_TO_VK, kl);
3263 ok(vkey != numpad_collisions[i][0],
3264 "Got numpad vKey %x for scan code %x when there was another choice\n",
3265 vkey, numpad_scan);
3266 }
3267 }
3268
3269 /* test the scan code prefixes of the right variant of a keys */
3271 ok(s >> 8 == 0x00, "Scan code prefixes should not be returned when not using MAPVK_VK_TO_VSC_EX %#1x\n", s >> 8);
3273 ok(s >> 8 == 0xE0 || broken(s == 0), "Scan code prefix for VK_RCONTROL should be 0xE0 when MAPVK_VK_TO_VSC_EX is set, was %#1x\n", s >> 8);
3275 ok(s >> 8 == 0xE0 || broken(s == 0), "Scan code prefix for VK_RMENU should be 0xE0 when MAPVK_VK_TO_VSC_EX is set, was %#1x\n", s >> 8);
3277 ok(s >> 8 == 0x00 || broken(s == 0), "The scan code shouldn't have a prefix, got %#1x\n", s >> 8);
3278}
3279
3280#define shift 1
3281#define ctrl 2
3282#define menu 4
3283
3284static const struct tounicode_tests
3285{
3288 WCHAR chr; /* if vk is 0, lookup vk using this char */
3291} utests[] =
3292{
3293 { 0, 0, 'a', 1, {'a',0}},
3294 { 0, shift, 'a', 1, {'A',0}},
3295 { 0, menu, 'a', 1, {'a',0}},
3296 { 0, shift|menu, 'a', 1, {'A',0}},
3297#if defined(__REACTOS__) && defined(_MSC_VER)
3298 { 0, shift|ctrl|menu, 'a', 0, {0}},
3299#else
3300 { 0, shift|ctrl|menu, 'a', 0, {}},
3301#endif
3302 { 0, ctrl, 'a', 1, {1, 0}},
3303 { 0, shift|ctrl, 'a', 1, {1, 0}},
3304#if defined(__REACTOS__) && defined(_MSC_VER)
3305 { VK_TAB, ctrl, 0, 0, {0}},
3306 { VK_TAB, shift|ctrl, 0, 0, {0}},
3307#else
3308 { VK_TAB, ctrl, 0, 0, {}},
3309 { VK_TAB, shift|ctrl, 0, 0, {}},
3310#endif
3311 { VK_RETURN, ctrl, 0, 1, {'\n', 0}},
3312#if defined(__REACTOS__) && defined(_MSC_VER)
3313 { VK_RETURN, shift|ctrl, 0, 0, {0}},
3314 { 0, ctrl, '4', 0, {0}},
3315 { 0, shift|ctrl, '4', 0, {0}},
3316 { 0, ctrl, '!', 0, {0}},
3317 { 0, ctrl, '\"', 0, {0}},
3318 { 0, ctrl, '#', 0, {0}},
3319 { 0, ctrl, '$', 0, {0}},
3320 { 0, ctrl, '%', 0, {0}},
3321 { 0, ctrl, '\'', 0, {0}},
3322 { 0, ctrl, '(', 0, {0}},
3323 { 0, ctrl, ')', 0, {0}},
3324 { 0, ctrl, '*', 0, {0}},
3325 { 0, ctrl, '+', 0, {0}},
3326 { 0, ctrl, ',', 0, {0}},
3327 { 0, ctrl, '-', 0, {0}},
3328 { 0, ctrl, '.', 0, {0}},
3329 { 0, ctrl, '/', 0, {0}},
3330 { 0, ctrl, ':', 0, {0}},
3331 { 0, ctrl, ';', 0, {0}},
3332 { 0, ctrl, '<', 0, {0}},
3333 { 0, ctrl, '=', 0, {0}},
3334 { 0, ctrl, '>', 0, {0}},
3335 { 0, ctrl, '?', 0, {0}},
3336#else
3337 { VK_RETURN, shift|ctrl, 0, 0, {}},
3338 { 0, ctrl, '4', 0, {}},
3339 { 0, shift|ctrl, '4', 0, {}},
3340 { 0, ctrl, '!', 0, {}},
3341 { 0, ctrl, '\"', 0, {}},
3342 { 0, ctrl, '#', 0, {}},
3343 { 0, ctrl, '$', 0, {}},
3344 { 0, ctrl, '%', 0, {}},
3345 { 0, ctrl, '\'', 0, {}},
3346 { 0, ctrl, '(', 0, {}},
3347 { 0, ctrl, ')', 0, {}},
3348 { 0, ctrl, '*', 0, {}},
3349 { 0, ctrl, '+', 0, {}},
3350 { 0, ctrl, ',', 0, {}},
3351 { 0, ctrl, '-', 0, {}},
3352 { 0, ctrl, '.', 0, {}},
3353 { 0, ctrl, '/', 0, {}},
3354 { 0, ctrl, ':', 0, {}},
3355 { 0, ctrl, ';', 0, {}},
3356 { 0, ctrl, '<', 0, {}},
3357 { 0, ctrl, '=', 0, {}},
3358 { 0, ctrl, '>', 0, {}},
3359 { 0, ctrl, '?', 0, {}},
3360#endif
3361 { 0, ctrl, '@', 1, {0}},
3362 { 0, ctrl, '[', 1, {0x1b}},
3363 { 0, ctrl, '\\', 1, {0x1c}},
3364 { 0, ctrl, ']', 1, {0x1d}},
3365 { 0, ctrl, '^', 1, {0x1e}},
3366 { 0, ctrl, '_', 1, {0x1f}},
3367#if defined(__REACTOS__) && defined(_MSC_VER)
3368 { 0, ctrl, '`', 0, {0}},
3369#else
3370 { 0, ctrl, '`', 0, {}},
3371#endif
3372 { VK_SPACE, 0, 0, 1, {' ',0}},
3373 { VK_SPACE, shift, 0, 1, {' ',0}},
3374 { VK_SPACE, ctrl, 0, 1, {' ',0}},
3376
3377static void test_ToUnicode(void)
3378{
3379 WCHAR wStr[4];
3380 BYTE state[256];
3381 const BYTE SC_RETURN = 0x1c, SC_TAB = 0x0f, SC_A = 0x1e;
3382 const BYTE HIGHEST_BIT = 0x80;
3383 int i, ret;
3384 BOOL us_kbd = (GetKeyboardLayout(0) == (HKL)(ULONG_PTR)0x04090409);
3385
3386 for(i=0; i<256; i++)
3387 state[i]=0;
3388
3389 wStr[1] = 0xAA;
3390 SetLastError(0xdeadbeef);
3391 ret = ToUnicode(VK_RETURN, SC_RETURN, state, wStr, 4, 0);
3393 {
3394 win_skip("ToUnicode is not implemented\n");
3395 return;
3396 }
3397
3398 ok(ret == 1, "ToUnicode for Return key didn't return 1 (was %i)\n", ret);
3399 if(ret == 1)
3400 {
3401 ok(wStr[0]=='\r', "ToUnicode for CTRL + Return was %i (expected 13)\n", wStr[0]);
3402 ok(wStr[1]==0 || broken(wStr[1]!=0) /* nt4 */,
3403 "ToUnicode didn't null-terminate the buffer when there was room.\n");
3404 }
3405
3406 for (i = 0; i < ARRAY_SIZE(utests); i++)
3407 {
3408 UINT vk = utests[i].vk, mod = utests[i].modifiers, scan;
3409
3410 if(!vk)
3411 {
3412 short vk_ret;
3413
3414 if (!us_kbd) continue;
3415 vk_ret = VkKeyScanW(utests[i].chr);
3416 if (vk_ret == -1) continue;
3417 vk = vk_ret & 0xff;
3418 if (vk_ret & 0x100) mod |= shift;
3419 if (vk_ret & 0x200) mod |= ctrl;
3420 }
3422
3423 state[VK_SHIFT] = state[VK_LSHIFT] = (mod & shift) ? HIGHEST_BIT : 0;
3424 state[VK_CONTROL] = state[VK_LCONTROL] = (mod & ctrl) ? HIGHEST_BIT : 0;
3425 state[VK_MENU] = state[VK_LMENU] = (mod & menu) ? HIGHEST_BIT : 0;
3426
3427 ret = ToUnicode(vk, scan, state, wStr, 4, 0);
3428 ok(ret == utests[i].expect_ret, "%d: got %d expected %d\n", i, ret, utests[i].expect_ret);
3429 if (ret)
3430 ok(!lstrcmpW(wStr, utests[i].expect_buf), "%d: got %s expected %s\n", i, wine_dbgstr_w(wStr),
3431 wine_dbgstr_w(utests[i].expect_buf));
3432
3433 }
3434 state[VK_SHIFT] = state[VK_LSHIFT] = 0;
3436
3437 ret = ToUnicode(VK_TAB, SC_TAB, NULL, wStr, 4, 0);
3438 ok(ret == 0, "ToUnicode with NULL keystate didn't return 0 (was %i)\n", ret);
3439 ret = ToUnicode(VK_RETURN, SC_RETURN, NULL, wStr, 4, 0);
3440 ok(ret == 0, "ToUnicode with NULL keystate didn't return 0 (was %i)\n", ret);
3441 ret = ToUnicode('A', SC_A, NULL, wStr, 4, 0);
3442 ok(ret == 0, "ToUnicode with NULL keystate didn't return 0 (was %i)\n", ret);
3443 ret = ToUnicodeEx(VK_TAB, SC_TAB, NULL, wStr, 4, 0, GetKeyboardLayout(0));
3444 ok(ret == 0, "ToUnicodeEx with NULL keystate didn't return 0 (was %i)\n", ret);
3445 ret = ToUnicodeEx(VK_RETURN, SC_RETURN, NULL, wStr, 4, 0, GetKeyboardLayout(0));
3446 ok(ret == 0, "ToUnicodeEx with NULL keystate didn't return 0 (was %i)\n", ret);
3447 ret = ToUnicodeEx('A', SC_A, NULL, wStr, 4, 0, GetKeyboardLayout(0));
3448 ok(ret == 0, "ToUnicodeEx with NULL keystate didn't return 0 (was %i)\n", ret);
3449}
3450
3451static void test_ToAscii(void)
3452{
3453 WCHAR wstr[16];
3454 char str[16];
3455 WORD character;
3456 BYTE state[256];
3457 const BYTE SC_RETURN = 0x1c, SC_A = 0x1e;
3458 const BYTE HIGHEST_BIT = 0x80;
3459 int ret, len;
3460 DWORD gle;
3461
3462 memset(state, 0, sizeof(state));
3463
3464 character = 0;
3465 ret = ToAscii(VK_RETURN, SC_RETURN, state, &character, 0);
3466 ok(ret == 1, "ToAscii for Return key didn't return 1 (was %i)\n", ret);
3467 ok(character == '\r', "ToAscii for Return was %i (expected 13)\n", character);
3468
3469 wstr[0] = 0;
3470 ret = ToUnicode('A', SC_A, state, wstr, ARRAY_SIZE(wstr), 0);
3471 ok(ret == 1, "ToUnicode(A) returned %i, expected 1\n", ret);
3472
3473 str[0] = '\0';
3474 len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, sizeof(str), NULL, NULL);
3475 gle = GetLastError();
3476 ok(len > 0, "Could not convert %s (gle %lu)\n", wine_dbgstr_w(wstr), gle);
3477
3478 character = 0;
3479 ret = ToAscii('A', SC_A, state, &character, 0);
3480 if (len == 1 || len == 2)
3481 ok(ret == 1, "ToAscii(A) returned %i, expected 1\n", ret);
3482 else
3483 /* ToAscii() can only return 2 chars => it fails if len > 2 */
3484 ok(ret == 0, "ToAscii(A) returned %i, expected 0\n", ret);
3485 switch ((ULONG_PTR)GetKeyboardLayout(0))
3486 {
3487 case 0x04090409: /* Qwerty */
3488 case 0x04070407: /* Qwertz */
3489 case 0x040c040c: /* Azerty */
3490 ok(lstrcmpW(wstr, L"a") == 0, "ToUnicode(A) returned %s\n", wine_dbgstr_w(wstr));
3491 ok(character == 'a', "ToAscii(A) returned char=%i, expected %i\n", character, 'a');
3492 break;
3493 /* Other keyboard layouts may or may not return 'a' */
3494 }
3495
3496 state[VK_CONTROL] |= HIGHEST_BIT;
3497 state[VK_LCONTROL] |= HIGHEST_BIT;
3498 character = 0;
3499 ret = ToAscii(VK_RETURN, SC_RETURN, state, &character, 0);
3500 ok(ret == 1, "ToAscii for CTRL + Return key didn't return 1 (was %i)\n", ret);
3501 ok(character == '\n', "ToAscii for CTRL + Return was %i (expected 10)\n", character);
3502
3503 character = 0;
3504 ret = ToAscii('A', SC_A, state, &character, 0);
3505 ok(ret == 1, "ToAscii for CTRL + character 'A' didn't return 1 (was %i)\n", ret);
3506 ok(character == 1, "ToAscii for CTRL + character 'A' was %i (expected 1)\n", character);
3507
3508 state[VK_SHIFT] |= HIGHEST_BIT;
3509 state[VK_LSHIFT] |= HIGHEST_BIT;
3510 ret = ToAscii(VK_RETURN, SC_RETURN, state, &character, 0);
3511 ok(ret == 0, "ToAscii for CTRL + Shift + Return key didn't return 0 (was %i)\n", ret);
3512
3513 ret = ToAscii(VK_RETURN, SC_RETURN, NULL, &character, 0);
3514 ok(ret == 0, "ToAscii for NULL keystate didn't return 0 (was %i)\n", ret);
3515 ret = ToAscii('A', SC_A, NULL, &character, 0);
3516 ok(ret == 0, "ToAscii for NULL keystate didn't return 0 (was %i)\n", ret);
3517 ret = ToAsciiEx(VK_RETURN, SC_RETURN, NULL, &character, 0, GetKeyboardLayout(0));
3518 ok(ret == 0, "ToAsciiEx for NULL keystate didn't return 0 (was %i)\n", ret);
3519 ret = ToAsciiEx('A', SC_A, NULL, &character, 0, GetKeyboardLayout(0));
3520 ok(ret == 0, "ToAsciiEx for NULL keystate didn't return 0 (was %i)\n", ret);
3521}
3522
3524{
3525 /* input value sanity checks */
3526 ok(0 == GetAsyncKeyState(1000000), "GetAsyncKeyState did not return 0\n");
3527 ok(0 == GetAsyncKeyState(-1000000), "GetAsyncKeyState did not return 0\n");
3528}
3529
3531{
3532 HKL *layouts;
3533
3535 ok_ne( 0, *count, UINT, "%u" );
3536 layouts = malloc( *count * sizeof(HKL) );
3537 ok_ne( NULL, layouts, void *, "%p" );
3538 *count = GetKeyboardLayoutList( *count, layouts );
3539 ok_ne( 0, *count, UINT, "%u" );
3540
3541 return layouts;
3542}
3543
3545{
3546 WCHAR klid[KL_NAMELENGTH], tmpklid[KL_NAMELENGTH], layout_path[MAX_PATH], value[5];
3547 HKL layout, tmplayout, *layouts, *layouts_preload;
3548 DWORD status, value_size, klid_size, type, id;
3549 int i, j;
3550 HKEY hkey;
3551 UINT len;
3552 BOOL ret;
3553
3554 if (0) /* crashes on native system */
3556
3557 SetLastError(0xdeadbeef);
3559 ok(!ret, "got %d\n", ret);
3560 ok(GetLastError() == ERROR_NOACCESS, "got %ld\n", GetLastError());
3561
3562 layout = GetKeyboardLayout(0);
3563 if (broken( layout == (HKL)0x040a0c0a ))
3564 {
3565 /* The testbot w7u_es has a broken layout configuration, its active layout is 040a:0c0a,
3566 * with 0c0a its user locale and 040a its layout langid. Its layout preload list contains
3567 * a 00000c0a layout but the system layouts OTOH only contains the standard 0000040a layout.
3568 * Later, after activating 0409:0409 layout, GetKeyboardLayoutNameW returns 00000c0a.
3569 */
3570 win_skip( "broken keyboard layout, skipping tests\n" );
3571 return;
3572 }
3573
3574 layouts = get_keyboard_layouts( &len );
3575 ok(layouts != NULL, "Could not allocate memory\n");
3576
3577 layouts_preload = calloc(1, sizeof(HKL));
3578 ok(layouts_preload != NULL, "Could not allocate memory\n");
3579
3580 if (!RegOpenKeyW( HKEY_CURRENT_USER, L"Keyboard Layout\\Preload", &hkey ))
3581 {
3582 i = 0;
3583 type = REG_SZ;
3584 klid_size = sizeof(klid);
3585 value_size = ARRAY_SIZE(value);
3586 while (!RegEnumValueW( hkey, i++, value, &value_size, NULL, &type, (void *)&klid, &klid_size ))
3587 {
3588 klid_size = sizeof(klid);
3589 value_size = ARRAY_SIZE(value);
3590 layouts_preload = realloc( layouts_preload, (i + 1) * sizeof(*layouts_preload) );
3591 ok(layouts_preload != NULL, "Could not allocate memory\n");
3592 layouts_preload[i - 1] = UlongToHandle( wcstoul( klid, NULL, 16 ) );
3593 layouts_preload[i] = 0;
3594
3595 id = (DWORD_PTR)layouts_preload[i - 1];
3596 if (id & 0x80000000) todo_wine_if(HIWORD(id) == 0xe001) ok((id & 0xf0000000) == 0xd0000000, "Unexpected preloaded keyboard layout high bits %#lx\n", id);
3597 else ok(!(id & 0xf0000000), "Unexpected preloaded keyboard layout high bits %#lx\n", id);
3598 }
3599
3600 RegCloseKey( hkey );
3601 }
3602
3603 if (!RegOpenKeyW( HKEY_CURRENT_USER, L"Keyboard Layout\\Substitutes", &hkey ))
3604 {
3605 for (i = 0; layouts_preload[i]; ++i)
3606 {
3607 type = REG_SZ;
3608 klid_size = sizeof(klid);
3609 swprintf( tmpklid, KL_NAMELENGTH, L"%08x", HandleToUlong( layouts_preload[i] ) );
3610 if (!RegQueryValueExW( hkey, tmpklid, NULL, &type, (void *)&klid, &klid_size ))
3611 {
3612 layouts_preload[i] = UlongToHandle( wcstoul( klid, NULL, 16 ) );
3613
3614 /* Substitute should contain the keyboard layout id, not the HKL high word */
3615 id = (DWORD_PTR)layouts_preload[i];
3616 ok(!(id & 0xf0000000), "Unexpected substitute keyboard layout high bits %#lx\n", id);
3617 }
3618 else
3619 {
3620 id = (DWORD_PTR)layouts_preload[i];
3621 ok(!(id & 0xf0000000), "Unexpected preloaded keyboard layout high bits %#lx\n", id);
3622 }
3623 }
3624
3625 RegCloseKey( hkey );
3626 }
3627
3628 for (i = len - 1; i >= 0; --i)
3629 {
3630 id = (DWORD_PTR)layouts[i];
3631
3632 winetest_push_context( "%08lx", id );
3633
3634 ActivateKeyboardLayout(layouts[i], 0);
3635
3636 tmplayout = GetKeyboardLayout(0);
3637 todo_wine_if(tmplayout != layouts[i])
3638 ok( tmplayout == layouts[i], "Failed to activate keyboard layout\n");
3639 if (tmplayout != layouts[i])
3640 {
3642 continue;
3643 }
3644
3646
3647 for (j = 0; layouts_preload[j]; ++j)
3648 {
3649#ifdef __REACTOS__
3650 swprintf( tmpklid, KL_NAMELENGTH, L"%08X", HandleToUlong(layouts_preload[j]) );
3651#else
3652 swprintf( tmpklid, KL_NAMELENGTH, L"%08X", layouts_preload[j] );
3653#endif
3654 if (!wcscmp( tmpklid, klid )) break;
3655 }
3656 ok(j < len, "Could not find keyboard layout %s in preload list\n", wine_dbgstr_w(klid));
3657
3658 if (id & 0x80000000)
3659 {
3660 todo_wine ok((id >> 28) == 0xf, "hkl high bits %#lx, expected 0xf\n", id >> 28);
3661
3662 value_size = sizeof(value);
3663 wcscpy(layout_path, L"System\\CurrentControlSet\\Control\\Keyboard Layouts\\");
3664 wcscat(layout_path, klid);
3665 status = RegGetValueW(HKEY_LOCAL_MACHINE, layout_path, L"Layout Id", RRF_RT_REG_SZ, NULL, (void *)&value, &value_size);
3666 todo_wine ok(!status, "RegGetValueW returned %lx\n", status);
3667 ok(value_size == 5 * sizeof(WCHAR), "RegGetValueW returned size %ld\n", value_size);
3668
3669 swprintf(tmpklid, KL_NAMELENGTH, L"%04X", (id >> 16) & 0x0fff);
3670 todo_wine ok(!wcsicmp(value, tmpklid), "RegGetValueW returned %s, expected %s\n", debugstr_w(value), debugstr_w(tmpklid));
3671 }
3672 else
3673 {
3674 swprintf(tmpklid, KL_NAMELENGTH, L"%08X", id >> 16);
3675 ok(!wcsicmp(klid, tmpklid), "GetKeyboardLayoutNameW returned %s, expected %s\n", debugstr_w(klid), debugstr_w(tmpklid));
3676 }
3677
3678 ActivateKeyboardLayout(layout, 0);
3679 tmplayout = LoadKeyboardLayoutW(klid, KLF_ACTIVATE);
3680
3681 /* The low word of HKL is the selected user lang and may be different as LoadKeyboardLayoutW also selects the default lang from the layout */
3682 ok(((UINT_PTR)tmplayout & ~0xffff) == ((UINT_PTR)layouts[i] & ~0xffff), "LoadKeyboardLayoutW returned %p, expected %p\n", tmplayout, layouts[i]);
3683
3684 /* The layout name only depends on the keyboard layout: the high word of HKL. */
3685 GetKeyboardLayoutNameW(tmpklid);
3686 ok(!wcsicmp(klid, tmpklid), "GetKeyboardLayoutNameW returned %s, expected %s\n", debugstr_w(tmpklid), debugstr_w(klid));
3687
3689 }
3690
3691 ActivateKeyboardLayout(layout, 0);
3692
3693 free(layouts);
3694 free(layouts_preload);
3695}
3696
3699static int got_setfocus;
3700
3702{
3703 ok( msg != WM_INPUTLANGCHANGEREQUEST, "got WM_INPUTLANGCHANGEREQUEST\n" );
3704
3705 if (msg == WM_SETFOCUS) got_setfocus = 1;
3706 if (msg == WM_INPUTLANGCHANGE)
3707 {
3708 HKL layout = GetKeyboardLayout( 0 );
3710 WCHAR klidW[64];
3711 UINT codepage;
3712 LCID lcid;
3713
3714 /* get keyboard layout lcid from its name, as the HKL might be aliased */
3715 GetKeyboardLayoutNameW( klidW );
3716 swscanf( klidW, L"%x", &lcid );
3717 lcid = LOWORD(lcid);
3718
3719 if (!(HIWORD(layout) & 0x8000)) ok( lcid == HIWORD(layout), "got lcid %#lx\n", lcid );
3720
3721 GetLocaleInfoA( lcid, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
3722 (char *)&codepage, sizeof(codepage) );
3724
3725 ok( !got_setfocus, "got WM_SETFOCUS before WM_INPUTLANGCHANGE\n" );
3726 ok( layout == expect_hkl, "got layout %p\n", layout );
3727 ok( wparam == info.ciCharset || broken(wparam == 0 && (HIWORD(layout) & 0x8000)),
3728 "got wparam %#Ix\n", wparam );
3729 ok( lparam == (LPARAM)expect_hkl, "got lparam %#Ix\n", lparam );
3731 }
3732
3733 return DefWindowProcW( hwnd, msg, wparam, lparam );
3734}
3735
3737{
3739 return 0;
3740}
3741
3743{
3744 HKL layout, tmp_layout, *layouts;
3745 HWND hwnd1, hwnd2;
3746 HANDLE thread;
3747 UINT i, count;
3748 DWORD ret;
3749
3750 layout = GetKeyboardLayout( 0 );
3751 if (broken( layout == (HKL)0x040a0c0a ))
3752 {
3753 /* The testbot w7u_es has a broken layout configuration, see test_keyboard_layout_name above. */
3754 win_skip( "broken keyboard layout, skipping tests\n" );
3755 return;
3756 }
3757
3759 ok( count > 0, "GetKeyboardLayoutList returned %d\n", count );
3760 layouts = malloc( count * sizeof(HKL) );
3761 ok( layouts != NULL, "Could not allocate memory\n" );
3762 count = GetKeyboardLayoutList( count, layouts );
3763 ok( count > 0, "GetKeyboardLayoutList returned %d\n", count );
3764
3765 hwnd1 = CreateWindowA( "static", "static", WS_VISIBLE | WS_POPUP,
3766 100, 100, 100, 100, 0, NULL, NULL, NULL );
3767 ok( !!hwnd1, "CreateWindow failed, error %lu\n", GetLastError() );
3769
3771
3772 for (i = 0; i < count; ++i)
3773 {
3774 BOOL broken_focus_activate = FALSE;
3775 HKL other_layout = layouts[i];
3776
3777 winetest_push_context( "%08x / %08x", (UINT)(UINT_PTR)layout, (UINT)(UINT_PTR)other_layout );
3778
3779 /* test WM_INPUTLANGCHANGE message */
3780
3781 change_hkl = 0;
3782 expect_hkl = other_layout;
3783 got_setfocus = 0;
3784 ActivateKeyboardLayout( other_layout, 0 );
3785 if (other_layout == layout) ok( change_hkl == 0, "got change_hkl %p\n", change_hkl );
3786 else todo_wine ok( change_hkl == other_layout, "got change_hkl %p\n", change_hkl );
3787 change_hkl = expect_hkl = 0;
3788
3789 tmp_layout = GetKeyboardLayout( 0 );
3790 todo_wine_if(layout != other_layout)
3791 ok( tmp_layout == other_layout, "got tmp_layout %p\n", tmp_layout );
3792
3793 /* changing the layout from another thread doesn't send the message */
3794
3796 ret = WaitForSingleObject( thread, 1000 );
3797 ok( !ret, "WaitForSingleObject returned %#lx\n", ret );
3799
3800 /* and has no immediate effect */
3801
3803 tmp_layout = GetKeyboardLayout( 0 );
3804 todo_wine_if(layout != other_layout)
3805 ok( tmp_layout == other_layout, "got tmp_layout %p\n", tmp_layout );
3806
3807 /* but the change only takes effect after focus changes */
3808
3809 hwnd2 = CreateWindowA( "static", "static", WS_VISIBLE | WS_POPUP,
3810 100, 100, 100, 100, 0, NULL, NULL, NULL );
3811 ok( !!hwnd2, "CreateWindow failed, error %lu\n", GetLastError() );
3812
3813 tmp_layout = GetKeyboardLayout( 0 );
3814 todo_wine_if(layout != other_layout)
3815 ok( tmp_layout == layout || broken(layout != other_layout && tmp_layout == other_layout) /* w7u */,
3816 "got tmp_layout %p\n", tmp_layout );
3817 if (broken(layout != other_layout && tmp_layout == other_layout))
3818 {
3819 win_skip( "Broken layout activation on focus change, skipping some tests\n" );
3820 broken_focus_activate = TRUE;
3821 }
3823
3824 /* only the focused window receives the WM_INPUTLANGCHANGE message */
3825
3826 ActivateKeyboardLayout( other_layout, 0 );
3827 ok( change_hkl == 0, "got change_hkl %p\n", change_hkl );
3828
3829 tmp_layout = GetKeyboardLayout( 0 );
3830 todo_wine_if(layout != other_layout)
3831 ok( tmp_layout == other_layout, "got tmp_layout %p\n", tmp_layout );
3832
3834 ret = WaitForSingleObject( thread, 1000 );
3835 ok( !ret, "WaitForSingleObject returned %#lx\n", ret );
3837
3838 tmp_layout = GetKeyboardLayout( 0 );
3839 todo_wine_if(layout != other_layout)
3840 ok( tmp_layout == other_layout, "got tmp_layout %p\n", tmp_layout );
3841
3842 /* changing focus is enough for the layout change to take effect */
3843
3844 change_hkl = 0;
3845 expect_hkl = layout;
3846 got_setfocus = 0;
3847 SetFocus( hwnd1 );
3848
3849 if (broken_focus_activate)
3850 {
3851 ok( got_setfocus == 1, "got got_setfocus %d\n", got_setfocus );
3852 ok( change_hkl == 0, "got change_hkl %p\n", change_hkl );
3853 got_setfocus = 0;
3854 ActivateKeyboardLayout( layout, 0 );
3855 }
3856
3857 if (other_layout == layout) ok( change_hkl == 0, "got change_hkl %p\n", change_hkl );
3858 else todo_wine ok( change_hkl == layout, "got change_hkl %p\n", change_hkl );
3859 change_hkl = expect_hkl = 0;
3860
3861 tmp_layout = GetKeyboardLayout( 0 );
3862 todo_wine_if(layout != other_layout)
3863 ok( tmp_layout == layout, "got tmp_layout %p\n", tmp_layout );
3864
3865 DestroyWindow( hwnd2 );
3867
3869 }
3870
3871 DestroyWindow( hwnd1 );
3872
3873 free( layouts );
3874}
3875
3876static void test_key_names(void)
3877{
3878 char buffer[40];
3879 WCHAR bufferW[40];
3880 int ret, prev;
3881 LONG lparam = 0x1d << 16;
3882
3883 memset( buffer, 0xcc, sizeof(buffer) );
3884 ret = GetKeyNameTextA( lparam, buffer, sizeof(buffer) );
3885 ok( ret > 0, "wrong len %u for '%s'\n", ret, buffer );
3886 ok( ret == strlen(buffer), "wrong len %u for '%s'\n", ret, buffer );
3887
3888 memset( buffer, 0xcc, sizeof(buffer) );
3889 prev = ret;
3890 ret = GetKeyNameTextA( lparam, buffer, prev );
3891 ok( ret == prev - 1, "wrong len %u for '%s'\n", ret, buffer );
3892 ok( ret == strlen(buffer), "wrong len %u for '%s'\n", ret, buffer );
3893
3894 memset( buffer, 0xcc, sizeof(buffer) );
3896 ok( ret == 0, "wrong len %u for '%s'\n", ret, buffer );
3897 ok( buffer[0] == 0, "wrong string '%s'\n", buffer );
3898
3899 memset( bufferW, 0xcc, sizeof(bufferW) );
3900 ret = GetKeyNameTextW( lparam, bufferW, ARRAY_SIZE(bufferW));
3901 ok( ret > 0, "wrong len %u for %s\n", ret, wine_dbgstr_w(bufferW) );
3902 ok( ret == lstrlenW(bufferW), "wrong len %u for %s\n", ret, wine_dbgstr_w(bufferW) );
3903
3904 memset( bufferW, 0xcc, sizeof(bufferW) );
3905 prev = ret;
3906 ret = GetKeyNameTextW( lparam, bufferW, prev );
3907 ok( ret == prev - 1, "wrong len %u for %s\n", ret, wine_dbgstr_w(bufferW) );
3908 ok( ret == lstrlenW(bufferW), "wrong len %u for %s\n", ret, wine_dbgstr_w(bufferW) );
3909
3910 memset( bufferW, 0xcc, sizeof(bufferW) );
3911 ret = GetKeyNameTextW( lparam, bufferW, 0 );
3912 ok( ret == 0, "wrong len %u for %s\n", ret, wine_dbgstr_w(bufferW) );
3913 ok( bufferW[0] == 0xcccc, "wrong string %s\n", wine_dbgstr_w(bufferW) );
3914}
3915
3916static void simulate_click(BOOL left, int x, int y)
3917{
3918 INPUT input[2];
3919 UINT events_no;
3920
3921 SetCursorPos(x, y);
3922 memset(input, 0, sizeof(input));
3923 input[0].type = INPUT_MOUSE;
3924 input[0].mi.dx = x;
3925 input[0].mi.dy = y;
3927 input[1].type = INPUT_MOUSE;
3928 input[1].mi.dx = x;
3929 input[1].mi.dy = y;
3931 events_no = SendInput(2, input, sizeof(input[0]));
3932 ok(events_no == 2, "SendInput returned %d\n", events_no);
3933}
3934
3936{
3937 DWORD end_time = GetTickCount() + timeout;
3938 MSG msg;
3939
3940 do {
3942 return TRUE;
3943 while(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
3945 timeout = end_time - GetTickCount();
3946 }while(timeout > 0);
3947
3948 return FALSE;
3949}
3950
3952{
3954 if (msg == WM_NCHITTEST) return HTTRANSPARENT;
3955 return DefWindowProcW( hwnd, msg, wparam, lparam );
3956}
3957
3959{
3963};
3964
3966{
3969
3970 params->hwnd = CreateWindowW( L"static", NULL, WS_VISIBLE | WS_POPUP, 0, 0, 100, 100, NULL, NULL, NULL, NULL );
3971 ok_ne( NULL, params->hwnd, HWND, "%p" );
3972 wait_messages( 100, FALSE );
3974 ok_ne( 0, old_proc, LONG_PTR, "%#Ix" );
3975
3976 ok_ret( 1, SetEvent( params->start_event ) );
3977 wait_for_event( params->end_event, 5000 );
3978
3979 ok_ret( 1, DestroyWindow( params->hwnd ) );
3980 wait_messages( 100, FALSE );
3981 return 0;
3982}
3983
3985{
3986 static DWORD last_x = 50, expect_x = 60;
3987
3988 if (msg == WM_MOUSEMOVE)
3989 {
3991 MapWindowPoints(hwnd, NULL, &pt, 1);
3992
3993 flaky
3994 if (pt.x != last_x) ok( pt.x == expect_x, "got unexpected WM_MOUSEMOVE x %ld, expected %ld\n", pt.x, expect_x );
3995
3996 expect_x = pt.x == 50 ? 60 : 50;
3997 last_x = pt.x;
3998 }
3999
4000 return DefWindowProcW(hwnd, msg, wparam, lparam);
4001}
4002
4004{
4006
4007 if (msg == WM_PAINT)
4008 {
4009 HBRUSH brush = CreateSolidBrush( RGB(50, 100, 255) );
4010 PAINTSTRUCT paint;
4011 RECT client_rect;
4012
4013 HDC hdc = BeginPaint( hwnd, &paint );
4014 GetClientRect( hwnd, &client_rect );
4015 FillRect( hdc, &client_rect, brush );
4016 EndPaint( hwnd, &paint );
4017
4018 DeleteObject( brush );
4019 return 0;
4020 }
4021
4022 return DefWindowProcW( hwnd, msg, wparam, lparam );
4023}
4024
4026{
4035};
4036
4038{
4039 MSLLHOOKSTRUCT *hook_info = (MSLLHOOKSTRUCT *)lparam;
4040 if (code == HC_ACTION) append_ll_hook_ms( wparam, hook_info );
4041 return CallNextHookEx( 0, code, wparam, lparam );
4042}
4043
4045{
4046 if (code == HC_ACTION)
4047 {
4048 MSLLHOOKSTRUCT *hook_info = (MSLLHOOKSTRUCT *)lparam;
4049 POINT pos, hook_pos = {40, 40};
4050
4051 ok( abs( hook_info->pt.x - 51 ) <= 1, "got x %ld\n", hook_info->pt.x );
4052 ok( abs( hook_info->pt.y - 49 ) <= 1, "got y %ld\n", hook_info->pt.y );
4053
4054 /* spuriously moves by 0 or 1 pixels on Windows */
4055 ok_ret( 1, GetCursorPos( &pos ) );
4056 ok( abs( pos.x - 51 ) <= 1, "got x %ld\n", pos.x );
4057 ok( abs( pos.y - 49 ) <= 1, "got y %ld\n", pos.y );
4058
4059 ok_ret( 1, SetCursorPos( 60, 60 ) );
4060 hook_info->pt = hook_pos;
4061 }
4062
4063 return CallNextHookEx( 0, code, wparam, lparam );
4064}
4065
4067{
4068 if (code == HC_ACTION)
4069 {
4070 MSLLHOOKSTRUCT *hook_info = (MSLLHOOKSTRUCT *)lparam;
4071 POINT pos, expect_pos = {60, 60}, hook_pos = {40, 40};
4072 ok_point( hook_pos, hook_info->pt );
4073 ok_ret( 1, GetCursorPos( &pos ) );
4074 ok_point( expect_pos, pos );
4075 }
4076
4077 return CallNextHookEx( 0, code, wparam, lparam );
4078}
4079
4081{
4082 return is_mouse_message( msg ) && msg != WM_MOUSEMOVE;
4083}
4084
4086{
4087#define WIN_MSG(m, h, w, l, ...) {.func = MSG_TEST_WIN, .message = {.msg = m, .hwnd = h, .wparam = w, .lparam = l}, ## __VA_ARGS__}
4088#define MS_HOOK(m, x, y, ...) {.func = LL_HOOK_MOUSE, .ll_hook_ms = {.msg = m, .point = {x, y}, .flags = 1}, ## __VA_ARGS__}
4089 struct user_call mouse_move[] =
4090 {
4091 MS_HOOK(WM_MOUSEMOVE, 40, 40),
4092 {0},
4093 };
4094 struct user_call button_down_hwnd[] =
4095 {
4096 MS_HOOK(WM_LBUTTONDOWN, 50, 50),
4097 WIN_MSG(WM_LBUTTONDOWN, (HWND)-1/*hwnd*/, 0x1, MAKELONG(50, 50)),
4098 {0},
4099 };
4100 struct user_call button_down_hwnd_todo[] =
4101 {
4102 MS_HOOK(WM_LBUTTONDOWN, 50, 50),
4103 WIN_MSG(WM_LBUTTONDOWN, (HWND)-1/*hwnd*/, 0x1, MAKELONG(50, 50), .todo = TRUE),
4104 {0/* placeholder for Wine spurious messages */},
4105 {0},
4106 };
4107 struct user_call button_up_hwnd[] =
4108 {
4109 MS_HOOK(WM_LBUTTONUP, 50, 50),
4110 WIN_MSG(WM_LBUTTONUP, (HWND)-1/*hwnd*/, 0, MAKELONG(50, 50)),
4111 {0},
4112 };
4113 struct user_call button_up_hwnd_todo[] =
4114 {
4115 MS_HOOK(WM_LBUTTONUP, 50, 50),
4116 WIN_MSG(WM_LBUTTONUP, (HWND)-1/*hwnd*/, 0, MAKELONG(50, 50), .todo = TRUE),
4117 {0/* placeholder for Wine spurious messages */},
4118 {0},
4119 };
4120 struct user_call button_down_no_message[] =
4121 {
4122 MS_HOOK(WM_LBUTTONDOWN, 50, 50),
4123 {.todo = TRUE /* spurious message on Wine */},
4124 {0},
4125 };
4126 struct user_call button_up_no_message[] =
4127 {
4128 MS_HOOK(WM_LBUTTONUP, 50, 50),
4129 {.todo = TRUE /* spurious message on Wine */},
4130 {0},
4131 };
4132#undef WIN_MSG
4133#undef MS_HOOK
4134 static const POINT expect_60x50 = {60, 50}, expect_50x50 = {50, 50};
4135
4136 static const struct layered_test
4137 {
4138 UINT color;
4139 UINT alpha;
4140 UINT flags;
4141 BOOL expect_click;
4142 }
4143 layered_tests[] =
4144 {
4145 {.flags = LWA_ALPHA, .expect_click = FALSE},
4146 {.alpha = 1, .flags = LWA_ALPHA, .expect_click = TRUE},
4147 {.color = RGB(0, 255, 0), .flags = LWA_COLORKEY, .expect_click = TRUE},
4148 {.color = RGB(50, 100, 255), .flags = LWA_COLORKEY, .expect_click = TRUE},
4149 {.color = RGB(0, 255, 0), .flags = LWA_COLORKEY | LWA_ALPHA, .expect_click = FALSE},
4150 {.color = RGB(0, 255, 0), .alpha = 1, .flags = LWA_COLORKEY | LWA_ALPHA, .expect_click = TRUE},
4151 {.color = RGB(50, 100, 255), .alpha = 1, .flags = LWA_COLORKEY | LWA_ALPHA, .expect_click = TRUE},
4152 };
4153
4155 ULONG_PTR old_proc, old_other_proc;
4156 RECT clip_rect = {55, 55, 55, 55};
4157 UINT dblclk_time, i;
4158 HWND hwnd, other;
4160 HANDLE thread;
4161 HHOOK hook, hook_setpos, hook_getpos;
4162 HRGN hregion;
4163 RECT region;
4164 POINT pt;
4165
4166 params.start_event = CreateEventA( NULL, FALSE, FALSE, NULL );
4167 ok( !!params.start_event, "CreateEvent failed\n" );
4168 params.end_event = CreateEventA( NULL, FALSE, FALSE, NULL );
4169 ok( !!params.end_event, "CreateEvent failed\n" );
4170
4171
4172 dblclk_time = GetDoubleClickTime();
4173 ok_eq( 500, dblclk_time, UINT, "%u" );
4174
4175 ok_ret( 1, SetCursorPos( 50, 50 ) );
4176 ok_ret( 1, SetDoubleClickTime( 1 ) );
4177
4178 hwnd = CreateWindowW( L"static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, NULL, NULL );
4179 ok_ne( NULL, hwnd, HWND, "%p" );
4180 wait_messages( 100, FALSE );
4181 trace( "hwnd %p\n", hwnd );
4182
4184 ok_ne( NULL, hook, HHOOK, "%p" );
4185
4186 /* test hooks only, WM_MOUSEMOVE messages are very brittle */
4189
4190 /* SetCursorPos or ClipCursor don't call mouse ll hooks */
4191 ok_ret( 1, SetCursorPos( 60, 60 ) );
4192 wait_messages( 5, FALSE );
4193 ok_ret( 1, ClipCursor( &clip_rect ) );
4194 wait_messages( 5, FALSE );
4195 ok_ret( 1, ClipCursor( NULL ) );
4196 wait_messages( 5, FALSE );
4197 ok_ret( 1, SetCursorPos( 50, 50 ) );
4198 wait_messages( 100, FALSE );
4200
4202 ok_ne( NULL, hook_getpos, HHOOK, "%p" );
4204 ok_ne( NULL, hook_setpos, HHOOK, "%p" );
4205
4206 mouse_event( MOUSEEVENTF_MOVE, 0, 0, 0, 0 );
4207 /* recent Windows versions don't call the hooks with no movement */
4209 {
4210 ok_seq( mouse_move );
4211 ok_ret( 1, SetCursorPos( 50, 50 ) );
4212 }
4214
4215 /* WH_MOUSE_LL hook is called even with 1 pixel moves */
4216 mouse_event( MOUSEEVENTF_MOVE, +1, -1, 0, 0 );
4217 ok_seq( mouse_move );
4218
4219 ok_ret( 1, UnhookWindowsHookEx( hook_getpos ) );
4220 ok_ret( 1, UnhookWindowsHookEx( hook_setpos ) );
4221
4222
4226
4227
4228 /* basic button messages */
4229
4231 ok_ne( 0, old_proc, LONG_PTR, "%#Ix" );
4232
4233 ok_ret( 1, SetCursorPos( 50, 50 ) );
4234 wait_messages( 100, FALSE );
4236
4237 mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 );
4238 wait_messages( 5, FALSE );
4239 button_down_hwnd[1].message.hwnd = hwnd;
4240 ok_seq( button_down_hwnd );
4241
4242 mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 );
4243 wait_messages( 5, FALSE );
4244 button_up_hwnd[1].message.hwnd = hwnd;
4245 ok_seq( button_up_hwnd );
4246 mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 );
4247 wait_messages( 5, FALSE );
4248 button_up_hwnd[1].message.hwnd = hwnd;
4249 ok_seq( button_up_hwnd );
4250
4251
4252 /* click through top-level window */
4253
4254 other = CreateWindowW( L"static", NULL, WS_VISIBLE | WS_POPUP, 0, 0, 100, 100, NULL, NULL, NULL, NULL );
4255 ok_ne( NULL, hwnd, HWND, "%p" );
4256 wait_messages( 100, FALSE );
4258
4260 ok_ne( 0, old_other_proc, LONG_PTR, "%#Ix" );
4261
4262 mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 );
4263 wait_messages( 5, FALSE );
4264 button_down_hwnd[1].message.hwnd = other;
4265 ok_seq( button_down_hwnd );
4266 mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 );
4267 wait_messages( 5, FALSE );
4268 button_up_hwnd[1].message.hwnd = other;
4269 ok_seq( button_up_hwnd );
4270
4271 ok_ret( 1, DestroyWindow( other ) );
4272 wait_messages( 0, FALSE );
4273
4274
4275 /* click through child window */
4276
4277 other = CreateWindowW( L"static", NULL, WS_VISIBLE | WS_CHILD, 0, 0, 100, 100, hwnd, NULL, NULL, NULL );
4278 ok_ne( NULL, hwnd, HWND, "%p" );
4279 wait_messages( 100, FALSE );
4281
4283 ok_ne( 0, old_other_proc, LONG_PTR, "%#Ix" );
4284
4285 mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 );
4286 wait_messages( 5, FALSE );
4287 button_down_hwnd[1].message.hwnd = other;
4288 ok_seq( button_down_hwnd );
4289 mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 );
4290 wait_messages( 5, FALSE );
4291 button_up_hwnd[1].message.hwnd = other;
4292 ok_seq( button_up_hwnd );
4293
4294 ok_ret( 1, DestroyWindow( other ) );
4295 wait_messages( 0, FALSE );
4296
4297
4298 /* click through HTTRANSPARENT top-level window */
4299
4300 other = CreateWindowW( L"static", NULL, WS_VISIBLE | WS_POPUP, 0, 0, 100, 100, NULL, NULL, NULL, NULL );
4301 ok_ne( NULL, hwnd, HWND, "%p" );
4302 wait_messages( 100, FALSE );
4304
4306 ok_ne( 0, old_other_proc, LONG_PTR, "%#Ix" );
4307
4308 mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 );
4309 wait_messages( 5, FALSE );
4310 button_down_hwnd_todo[1].message.hwnd = hwnd;
4311 ok_seq( button_down_hwnd_todo );
4312 mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 );
4313 wait_messages( 5, FALSE );
4314 button_up_hwnd_todo[1].message.hwnd = hwnd;
4315 ok_seq( button_up_hwnd_todo );
4316
4317 ok_ret( 1, DestroyWindow( other ) );
4318 wait_messages( 0, FALSE );
4319
4320
4321 /* click through HTTRANSPARENT child window */
4322
4323 other = CreateWindowW( L"static", NULL, WS_VISIBLE | WS_CHILD, 0, 0, 100, 100, hwnd, NULL, NULL, NULL );
4324 ok_ne( NULL, hwnd, HWND, "%p" );
4325 wait_messages( 100, FALSE );
4327
4329 ok_ne( 0, old_other_proc, LONG_PTR, "%#Ix" );
4330
4331 mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 );
4332 wait_messages( 5, FALSE );
4333 button_down_hwnd[1].message.hwnd = hwnd;
4334 ok_seq( button_down_hwnd );
4335 mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 );
4336 wait_messages( 5, FALSE );
4337 button_up_hwnd[1].message.hwnd = hwnd;
4338 ok_seq( button_up_hwnd );
4339
4340 ok_ret( 1, DestroyWindow( other ) );
4341 wait_messages( 0, FALSE );
4342
4343
4344 /* click on HTTRANSPARENT top-level window that belongs to other thread */
4345
4347 ok_ne( NULL, thread, HANDLE, "%p" );
4348
4349 ok_ret( 0, WaitForSingleObject( params.start_event, 5000 ) );
4350 ok_ret( 0, SendMessageW( params.hwnd, WM_USER, 0, 0 ) );
4351
4352 mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 );
4353 wait_messages( 5, FALSE );
4354 ok_seq( button_down_no_message );
4355 mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 );
4356 wait_messages( 5, FALSE );
4357 ok_seq( button_up_no_message );
4358
4359 ok_ret( 1, SetEvent( params.end_event ) );
4360 ok_ret( 0, WaitForSingleObject( thread, 5000 ) );
4361 ok_ret( 1, CloseHandle( thread ) );
4362 ResetEvent( params.start_event );
4363 ResetEvent( params.end_event );
4364
4365
4366 /* click on HTTRANSPARENT top-level window that belongs to other thread,
4367 * thread input queues are attached */
4368
4370 ok_ne( NULL, thread, HANDLE, "%p" );
4371
4372 ok_ret( 0, WaitForSingleObject( params.start_event, 5000 ) );
4374 ok_ret( 0, SendMessageW( params.hwnd, WM_USER, 0, 0 ) );
4375
4376 mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 );
4377 wait_messages( 5, FALSE );
4378 button_down_hwnd_todo[1].message.hwnd = hwnd;
4379 ok_seq( button_down_hwnd_todo );
4380 mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 );
4381 wait_messages( 5, FALSE );
4382 button_up_hwnd[1].message.hwnd = hwnd;
4383 ok_seq( button_up_hwnd );
4384
4386 ok_ret( 1, SetEvent( params.end_event ) );
4387 ok_ret( 0, WaitForSingleObject( thread, 5000 ) );
4388 ok_ret( 1, CloseHandle( thread ) );
4389 ResetEvent( params.start_event );
4390 ResetEvent( params.end_event );
4391
4392
4393 /* click on top-level window with SetCapture called for the underlying window */
4394
4395 other = CreateWindowW( L"static", NULL, WS_VISIBLE | WS_POPUP, 0, 0, 100, 100, NULL, NULL, NULL, NULL );
4396 ok_ne( NULL, hwnd, HWND, "%p" );
4397 wait_messages( 100, FALSE );
4399
4401 ok_ne( 0, old_other_proc, LONG_PTR, "%#Ix" );
4402
4403 SetCapture( hwnd );
4404
4405 mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 );
4406 wait_messages( 5, FALSE );
4407 button_down_hwnd[1].message.hwnd = hwnd;
4408 ok_seq( button_down_hwnd );
4409 mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 );
4410 wait_messages( 5, FALSE );
4411 button_up_hwnd[1].message.hwnd = hwnd;
4412 ok_seq( button_up_hwnd );
4413
4414 ok_ret( 1, DestroyWindow( other ) );
4415 wait_messages( 0, FALSE );
4416
4417 SetCapture( 0 );
4418
4419
4420 /* click through child window with SetCapture called for the underlying window */
4421
4422 other = CreateWindowW( L"static", NULL, WS_VISIBLE | WS_CHILD, 0, 0, 100, 100, hwnd, NULL, NULL, NULL );
4423 ok_ne( NULL, hwnd, HWND, "%p" );
4424 wait_messages( 100, FALSE );
4426
4428 ok_ne( 0, old_other_proc, LONG_PTR, "%#Ix" );
4429
4430 SetCapture( hwnd );
4431
4432 mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 );
4433 wait_messages( 5, FALSE );
4434 button_down_hwnd[1].message.hwnd = hwnd;
4435 ok_seq( button_down_hwnd );
4436 mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 );
4437 wait_messages( 5, FALSE );
4438 button_up_hwnd[1].message.hwnd = hwnd;
4439 ok_seq( button_up_hwnd );
4440
4441 ok_ret( 1, DestroyWindow( other ) );
4442 wait_messages( 0, FALSE );
4443
4444 SetCapture( 0 );
4445
4446
4447
4448 /* click through layered window with alpha channel / color key */
4449
4450 for (i = 0; i < ARRAY_SIZE(layered_tests); i++)
4451 {
4452 const struct layered_test *test = layered_tests + i;
4453 BOOL ret;
4454
4455 winetest_push_context( "layered %u", i );
4456
4457 other = CreateWindowW( L"static", NULL, WS_VISIBLE | WS_POPUP, 0, 0, 100, 100, NULL, NULL, NULL, NULL );
4458 ok_ne( NULL, other, HWND, "%p" );
4460 ok_ne( 0, old_other_proc, LONG_PTR, "%#Ix" );
4461 wait_messages( 100, FALSE );
4462
4463 ok_ret( ERROR, GetWindowRgnBox( other, &region ) );
4464
4465
4467 ret = SetLayeredWindowAttributes( other, test->color, test->alpha, test->flags );
4468 if (broken(!ret)) /* broken on Win7 probably because of the separate desktop */
4469 {
4470 win_skip("Skipping broken SetLayeredWindowAttributes tests\n");
4473 break;
4474 }
4475
4477 wait_messages( 5, FALSE );
4479
4480 mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 );
4481 wait_messages( 5, FALSE );
4482 button_down_hwnd_todo[1].message.hwnd = test->expect_click ? other : hwnd;
4483 button_down_hwnd_todo[1].todo = !test->expect_click;
4484 button_down_hwnd_todo[2].todo = !test->alpha && (test->flags & LWA_ALPHA);
4485 ok_seq( button_down_hwnd_todo );
4486 mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 );
4487 wait_messages( 5, FALSE );
4488 button_up_hwnd_todo[1].message.hwnd = test->expect_click ? other : hwnd;
4489 button_up_hwnd_todo[1].todo = !test->expect_click;
4490 button_up_hwnd_todo[2].todo = !test->alpha && (test->flags & LWA_ALPHA);
4491 ok_seq( button_up_hwnd_todo );
4492
4493
4494 /* removing the attribute isn't enough to get mouse input again? */
4495
4498 wait_messages( 5, FALSE );
4499
4500 mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 );
4501 wait_messages( 5, FALSE );
4502 button_down_hwnd_todo[1].message.hwnd = test->expect_click ? other : hwnd;
4503 button_down_hwnd_todo[1].todo = !test->expect_click;
4504 button_down_hwnd_todo[2].todo = !test->alpha && (test->flags & LWA_ALPHA);
4505 ok_seq( button_down_hwnd_todo );
4506 mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 );
4507 wait_messages( 5, FALSE );
4508 button_up_hwnd_todo[1].message.hwnd = test->expect_click ? other : hwnd;
4509 button_up_hwnd_todo[1].todo = !test->expect_click;
4510 button_up_hwnd_todo[2].todo = !test->alpha && (test->flags & LWA_ALPHA);
4511 ok_seq( button_up_hwnd_todo );
4512
4513 ok_ret( 1, DestroyWindow( other ) );
4514
4516 }
4517
4518
4519 /* click on top-level window with SetWindowRgn called */
4520
4521 other = CreateWindowW( L"static", NULL, WS_VISIBLE | WS_POPUP, 0, 0, 100, 100, NULL, NULL, NULL, NULL );
4522 ok_ne( NULL, hwnd, HWND, "%p" );
4523 wait_messages( 100, FALSE );
4525
4527 ok_ne( 0, old_other_proc, LONG_PTR, "%#Ix" );
4528
4529 hregion = CreateRectRgn( 0, 0, 10, 10 );
4530 ok_ne( NULL, hregion, HRGN, "%p" );
4531 ok_ret( 1, SetWindowRgn( other, hregion, TRUE ) );
4532 DeleteObject( hregion );
4533 ok_ret( SIMPLEREGION, GetWindowRgnBox( other, &region ) );
4534
4535 mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 );
4536 wait_messages( 5, FALSE );
4537 button_down_hwnd[1].message.hwnd = hwnd;
4538 ok_seq( button_down_hwnd );
4539 mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 );
4540 wait_messages( 5, FALSE );
4541 button_up_hwnd[1].message.hwnd = hwnd;
4542 ok_seq( button_up_hwnd );
4543
4544 ok_ret( 1, DestroyWindow( other ) );
4545 wait_messages( 0, FALSE );
4546
4547
4548 /* warm up test case by moving cursor and window a bit first */
4549 ok_ret( 1, SetCursorPos( 60, 50 ) );
4550 ok_ret( 1, SetWindowPos( hwnd, NULL, 10, 0, 0, 0, SWP_NOSIZE ) );
4551 wait_messages( 5, FALSE );
4552 ok_ret( 1, SetCursorPos( 50, 50 ) );
4553 ok_ret( 1, SetWindowPos( hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE ) );
4554 wait_messages( 5, FALSE );
4556
4557 ok_ret( 1, SetCursorPos( 60, 50 ) );
4558 ok_ret( 1, SetWindowPos( hwnd, NULL, 10, 0, 0, 0, SWP_NOSIZE ) );
4559 wait_messages( 5, FALSE );
4560 ok_ret( 1, GetCursorPos( &pt ) );
4561 ok_point( expect_60x50, pt );
4562
4563 ok_ret( 1, SetCursorPos( 50, 50 ) );
4564 ok_ret( 1, SetWindowPos( hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE ) );
4565 wait_messages( 5, FALSE );
4566 ok_ret( 1, GetCursorPos( &pt ) );
4567 ok_point( expect_50x50, pt );
4568
4569
4571
4572 wait_messages( 100, FALSE );
4576
4577
4578 ok_ret( 1, DestroyWindow( hwnd ) );
4579
4580 CloseHandle( params.start_event );
4581 CloseHandle( params.end_event );
4582
4583
4584 ok_ret( 1, SetDoubleClickTime( dblclk_time ) );
4585}
4586
4587
4589{
4590 if (message == WM_USER+1)
4591 {
4592 HWND hwnd = (HWND)lParam;
4593 ok(GetFocus() == hwnd, "thread expected focus %p, got %p\n", hwnd, GetFocus());
4594 ok(GetActiveWindow() == hwnd, "thread expected active %p, got %p\n", hwnd, GetActiveWindow());
4595 }
4597}
4598
4600{
4607};
4608
4610{
4611 MSG msg;
4612 struct wnd_event *wnd_event = param;
4613 BOOL ret;
4614
4615 if (wnd_event->wait_event)
4616 {
4618 "WaitForSingleObject failed\n");
4620 }
4621
4623 {
4625 ok(ret, "AttachThreadInput error %ld\n", GetLastError());
4626 }
4627
4628 if (wnd_event->attach_to)
4629 {
4631 ok(ret, "AttachThreadInput error %ld\n", GetLastError());
4632 }
4633
4634 wnd_event->hwnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW,
4635 100, 100, 200, 200, 0, 0, 0, NULL);
4636 ok(wnd_event->hwnd != 0, "Failed to create overlapped window\n");
4637
4638 if (wnd_event->setWindows)
4639 {
4642 }
4643
4645
4646 while (GetMessageA(&msg, 0, 0, 0))
4647 {
4650 }
4651
4652 return 0;
4653}
4654
4655static void test_attach_input(void)
4656{
4658 HWND ourWnd, Wnd2;
4659 DWORD ret, tid;
4660 struct wnd_event wnd_event;
4661 WNDCLASSA cls;
4662
4663 cls.style = 0;
4664 cls.lpfnWndProc = MsgCheckProcA;
4665 cls.cbClsExtra = 0;
4666 cls.cbWndExtra = 0;
4667 cls.hInstance = GetModuleHandleA(0);
4668 cls.hIcon = 0;
4669 cls.hCursor = LoadCursorW( NULL, (LPCWSTR)IDC_ARROW);
4670 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
4671 cls.lpszMenuName = NULL;
4672 cls.lpszClassName = "TestWindowClass";
4673 if(!RegisterClassA(&cls)) return;
4674
4678 wnd_event.attach_to = 0;
4681 {
4682 win_skip("skipping interthread message test under win9x\n");
4683 return;
4684 }
4685
4687 ok(hThread != NULL, "CreateThread failed, error %ld\n", GetLastError());
4688
4689 ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
4691
4692 ourWnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
4693 0, 0, 0, 0, 0, 0, 0, NULL);
4694 ok(ourWnd!= 0, "failed to create ourWnd window\n");
4695
4696 Wnd2 = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
4697 0, 0, 0, 0, 0, 0, 0, NULL);
4698 ok(Wnd2!= 0, "failed to create Wnd2 window\n");
4699
4700 SetFocus(ourWnd);
4701 SetActiveWindow(ourWnd);
4702
4704 ok(ret, "AttachThreadInput error %ld\n", GetLastError());
4705
4706 ok(GetActiveWindow() == ourWnd, "expected active %p, got %p\n", ourWnd, GetActiveWindow());
4707 ok(GetFocus() == ourWnd, "expected focus %p, got %p\n", ourWnd, GetFocus());
4708
4709 SendMessageA(wnd_event.hwnd, WM_USER+1, 0, (LPARAM)ourWnd);
4710
4712 ok(ret, "AttachThreadInput error %ld\n", GetLastError());
4713 ok(GetActiveWindow() == ourWnd, "expected active %p, got %p\n", ourWnd, GetActiveWindow());
4714 ok(GetFocus() == ourWnd, "expected focus %p, got %p\n", ourWnd, GetFocus());
4715
4717
4719 ok(ret, "AttachThreadInput error %ld\n", GetLastError());
4720
4721 ok(GetActiveWindow() == ourWnd, "expected active %p, got %p\n", ourWnd, GetActiveWindow());
4722 ok(GetFocus() == ourWnd, "expected focus %p, got %p\n", ourWnd, GetFocus());
4723 SendMessageA(wnd_event.hwnd, WM_USER+1, 0, (LPARAM)ourWnd);
4724
4725 SetActiveWindow(Wnd2);
4726 SetFocus(Wnd2);
4727 ok(GetActiveWindow() == Wnd2, "expected active %p, got %p\n", Wnd2, GetActiveWindow());
4728 ok(GetFocus() == Wnd2, "expected focus %p, got %p\n", Wnd2, GetFocus());
4729
4731
4733 ok(ret, "AttachThreadInput error %ld\n", GetLastError());
4734 ok(GetActiveWindow() == Wnd2, "expected active %p, got %p\n", Wnd2, GetActiveWindow());
4735 ok(GetFocus() == Wnd2, "expected focus %p, got %p\n", Wnd2, GetFocus());
4736
4738
4740 ok(ret, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
4741
4742 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
4744
4748 wnd_event.attach_to = 0;
4750
4752 ok(hThread != NULL, "CreateThread failed, error %ld\n", GetLastError());
4753
4754 ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
4756
4757 SetFocus(ourWnd);
4758 SetActiveWindow(ourWnd);
4759
4761 ok(ret, "AttachThreadInput error %ld\n", GetLastError());
4762
4763 ok(GetActiveWindow() == wnd_event.hwnd, "expected active %p, got %p\n", wnd_event.hwnd, GetActiveWindow());
4764 ok(GetFocus() == wnd_event.hwnd, "expected focus %p, got %p\n", wnd_event.hwnd, GetFocus());
4765
4767
4769 ok(ret, "AttachThreadInput error %ld\n", GetLastError());
4770
4771 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
4772 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
4773
4775
4777 ok(ret, "AttachThreadInput error %ld\n", GetLastError());
4778
4779 ok(GetActiveWindow() == wnd_event.hwnd, "expected active %p, got %p\n", wnd_event.hwnd, GetActiveWindow());
4780 ok(GetFocus() == wnd_event.hwnd, "expected focus %p, got %p\n", wnd_event.hwnd, GetFocus());
4781
4783
4784 SetFocus(Wnd2);
4785 SetActiveWindow(Wnd2);
4786 ok(GetActiveWindow() == Wnd2, "expected active %p, got %p\n", Wnd2, GetActiveWindow());
4787 ok(GetFocus() == Wnd2, "expected focus %p, got %p\n", Wnd2, GetFocus());
4788
4790
4792 ok(ret, "AttachThreadInput error %ld\n", GetLastError());
4793
4794 ok(GetActiveWindow() == Wnd2, "expected active %p, got %p\n", Wnd2, GetActiveWindow());
4795 ok(GetFocus() == Wnd2, "expected focus %p, got %p\n", Wnd2, GetFocus());
4796
4798
4800 ok(ret, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
4801
4802 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
4804
4808 wnd_event.attach_to = 0;
4810
4812 ok(hThread != NULL, "CreateThread failed, error %ld\n", GetLastError());
4813
4814 SetLastError(0xdeadbeef);
4816 ok(!ret, "AttachThreadInput succeeded\n");
4817 ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef) /* <= Win XP */,
4818 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
4819
4820 SetLastError(0xdeadbeef);
4822 ok(!ret, "AttachThreadInput succeeded\n");
4823 ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef) /* <= Win XP */,
4824 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
4825
4827
4828 ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
4830
4832 ok(ret, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
4833
4834 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
4836
4840 wnd_event.attach_to = 0;
4842
4843 SetFocus(ourWnd);
4844 SetActiveWindow(ourWnd);
4845
4847 ok(hThread != NULL, "CreateThread failed, error %ld\n", GetLastError());
4848
4849 ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
4851
4852 ok(GetActiveWindow() == ourWnd, "expected active %p, got %p\n", ourWnd, GetActiveWindow());
4853 ok(GetFocus() == ourWnd, "expected focus %p, got %p\n", ourWnd, GetFocus());
4854
4856 ok(ret, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
4857
4858 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
4860
4866
4867 SetFocus(ourWnd);
4868 SetActiveWindow(ourWnd);
4869
4871 ok(hThread != NULL, "CreateThread failed, error %ld\n", GetLastError());
4872
4873 ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
4875
4876 ok(GetActiveWindow() == ourWnd, "expected active %p, got %p\n", ourWnd, GetActiveWindow());
4877 ok(GetFocus() == ourWnd, "expected focus %p, got %p\n", ourWnd, GetFocus());
4878
4880 ok(ret, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
4881
4882 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
4884 DestroyWindow(ourWnd);
4885 DestroyWindow(Wnd2);
4886}
4887
4889{
4894};
4895
4897{
4898 /* 0: not peeking in thread, no msg queue: GetKeyState / GetKeyboardState miss key press */
4899 {FALSE, TRUE, FALSE, FALSE},
4900 /* 1: peeking on thread init, not in main: GetKeyState / GetKeyboardState catch key press */
4901 /* - GetKeyboardState misses key press if called before GetKeyState */
4902 /* - GetKeyboardState catches key press, if called after GetKeyState */
4903 { TRUE, FALSE, FALSE, FALSE},
4904 /* 2: peeking on thread init, and in main: GetKeyState / GetKeyboardState catch key press */
4905 { TRUE, TRUE, FALSE, FALSE},
4906
4907 /* same tests but with SetKeyboardState called in main thread */
4908 /* 3: not peeking in thread, no msg queue: GetKeyState / GetKeyboardState miss key press */
4909 {FALSE, TRUE, TRUE, FALSE},
4910 /* 4: peeking on thread init, not in main: GetKeyState / GetKeyboardState catch key press */
4911 /* - GetKeyboardState misses key press if called before GetKeyState */
4912 /* - GetKeyboardState catches key press, if called after GetKeyState */
4913 { TRUE, FALSE, TRUE, FALSE},
4914 /* 5: peeking on thread init, and in main: GetKeyState / GetKeyboardState catch key press */
4915 { TRUE, TRUE, TRUE, FALSE},
4916
4917 /* same tests but with SetKeyboardState called in other thread */
4918 /* 6: not peeking in thread, no msg queue: GetKeyState / GetKeyboardState miss key press */
4919 {FALSE, TRUE, TRUE, TRUE},
4920 /* 7: peeking on thread init, not in main: GetKeyState / GetKeyboardState catch key press */
4921 /* - GetKeyboardState misses key press if called before GetKeyState */
4922 /* - GetKeyboardState catches key press, if called after GetKeyState */
4923 { TRUE, FALSE, TRUE, TRUE},
4924 /* 8: peeking on thread init, and in main: GetKeyState / GetKeyboardState catch key press */
4925 { TRUE, TRUE, TRUE, TRUE},
4926};
4927
4929{
4932};
4933
4934#define check_get_keyboard_state(i, j, c, x) check_get_keyboard_state_(i, j, c, x, __LINE__)
4935static void check_get_keyboard_state_(int i, int j, int c, int x, int line)
4936{
4937 unsigned char keystate[256];
4938 BOOL ret;
4939
4940 memset(keystate, 0, sizeof(keystate));
4942 ok_(__FILE__, line)(ret, "GetKeyboardState failed, %lu\n", GetLastError());
4943 ok_(__FILE__, line)(!(keystate['X'] & 0x80) == !x, "%d:%d: expected that X keystate is %s\n", i, j, x ? "set" : "unset");
4944 ok_(__FILE__, line)(!(keystate['C'] & 0x80) == !c, "%d:%d: expected that C keystate is %s\n", i, j, c ? "set" : "unset");
4945
4946 /* calling it twice shouldn't change */
4947 memset(keystate, 0, sizeof(keystate));
4949 ok_(__FILE__, line)(ret, "GetKeyboardState failed, %lu\n", GetLastError());
4950 ok_(__FILE__, line)(!(keystate['X'] & 0x80) == !x, "%d:%d: expected that X keystate is %s\n", i, j, x ? "set" : "unset");
4951 ok_(__FILE__, line)(!(keystate['C'] & 0x80) == !c, "%d:%d: expected that C keystate is %s\n", i, j, c ? "set" : "unset");
4952}
4953
4954#define check_get_key_state(i, j, c, x) check_get_key_state_(i, j, c, x, __LINE__)
4955static void check_get_key_state_(int i, int j, int c, int x, int line)
4956{
4957 SHORT state;
4958
4959 state = GetKeyState('X');
4960 ok_(__FILE__, line)(!(state & 0x8000) == !x, "%d:%d: expected that X highest bit is %s, got %#x\n", i, j, x ? "set" : "unset", state);
4961 ok_(__FILE__, line)(!(state & 0x007e), "%d:%d: expected that X undefined bits are unset, got %#x\n", i, j, state);
4962
4963 state = GetKeyState('C');
4964 ok_(__FILE__, line)(!(state & 0x8000) == !c, "%d:%d: expected that C highest bit is %s, got %#x\n", i, j, c ? "set" : "unset", state);
4965 ok_(__FILE__, line)(!(state & 0x007e), "%d:%d: expected that C undefined bits are unset, got %#x\n", i, j, state);
4966}
4967
4969{
4972 HANDLE *semaphores = params->semaphores;
4973 DWORD result;
4974 BYTE keystate[256] = {0};
4975 BOOL has_queue;
4976 BOOL expect_x, expect_c;
4977 MSG msg;
4978 int i = params->index, j;
4979
4981 has_queue = test->peek_message || test->set_keyboard_state;
4982
4983 if (test->peek_message)
4984 {
4985 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
4986 ok(!is_keyboard_message(msg.message), "%d: PeekMessageA got keyboard message.\n", i);
4987 }
4988
4989 for (j = 0; j < 4; ++j)
4990 {
4991 /* initialization */
4992 ReleaseSemaphore(semaphores[0], 1, NULL);
4993 result = WaitForSingleObject(semaphores[1], 1000);
4994 ok(result == WAIT_OBJECT_0, "%d:%d: WaitForSingleObject returned %lu\n", i, j, result);
4995
4996 if (test->set_keyboard_state)
4997 {
4998 keystate['C'] = 0xff;
5000 }
5001
5002 /* key pressed */
5003 ReleaseSemaphore(semaphores[0], 1, NULL);
5004 result = WaitForSingleObject(semaphores[1], 1000);
5005 ok(result == WAIT_OBJECT_0, "%d:%d: WaitForSingleObject returned %lu\n", i, j, result);
5006
5007 if (test->set_keyboard_state) expect_x = TRUE;
5008 else if (!has_queue && j == 0) expect_x = FALSE;
5009 else expect_x = TRUE;
5010
5011 if (test->set_keyboard_state) expect_c = TRUE;
5012 else expect_c = FALSE;
5013
5014 check_get_keyboard_state(i, j, expect_c, FALSE);
5015 check_get_key_state(i, j, expect_c, expect_x);
5016 check_get_keyboard_state(i, j, expect_c, expect_x);
5017
5018 /* key released */
5019 ReleaseSemaphore(semaphores[0], 1, NULL);
5020 result = WaitForSingleObject(semaphores[1], 1000);
5021 ok(result == WAIT_OBJECT_0, "%d: WaitForSingleObject returned %lu\n", i, result);
5022
5023 check_get_keyboard_state(i, j, expect_c, expect_x);
5024 check_get_key_state(i, j, expect_c, FALSE);
5025 check_get_keyboard_state(i, j, expect_c, FALSE);
5026 }
5027
5028 return 0;
5029}
5030
5031static void test_GetKeyState(void)
5032{
5034 HANDLE thread;
5035 DWORD result;
5036 BYTE keystate[256] = {0};
5037 BOOL expect_x, expect_c;
5038 HWND hwnd;
5039 MSG msg;
5040 int i, j;
5041
5042 BOOL us_kbd = (GetKeyboardLayout(0) == (HKL)(ULONG_PTR)0x04090409);
5043 if (!us_kbd)
5044 {
5045 skip("skipping test with inconsistent results on non-us keyboard\n");
5046 return;
5047 }
5048
5049 params.semaphores[0] = CreateSemaphoreA(NULL, 0, 1, NULL);
5050 ok(params.semaphores[0] != NULL, "CreateSemaphoreA failed %lu\n", GetLastError());
5051 params.semaphores[1] = CreateSemaphoreA(NULL, 0, 1, NULL);
5052 ok(params.semaphores[1] != NULL, "CreateSemaphoreA failed %lu\n", GetLastError());
5053
5054 hwnd = CreateWindowA("static", "Title", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5055 10, 10, 200, 200, NULL, NULL, NULL, NULL);
5056 ok(hwnd != NULL, "CreateWindowA failed %lu\n", GetLastError());
5058
5059 for (i = 0; i < ARRAY_SIZE(get_key_state_tests); ++i)
5060 {
5062
5063 params.index = i;
5065 ok(thread != NULL, "CreateThread failed %lu\n", GetLastError());
5066
5067 for (j = 0; j < 4; ++j)
5068 {
5069 /* initialization */
5070 result = WaitForSingleObject(params.semaphores[0], 1000);
5071 ok(result == WAIT_OBJECT_0, "%d:%d: WaitForSingleObject returned %lu\n", i, j, result);
5072
5074 SetFocus(hwnd);
5076
5077 ReleaseSemaphore(params.semaphores[1], 1, NULL);
5078
5079 /* key pressed */
5080 result = WaitForSingleObject(params.semaphores[0], 1000);
5081 ok(result == WAIT_OBJECT_0, "%d:%d: WaitForSingleObject returned %lu\n", i, j, result);
5082
5083 keybd_event('X', 0, 0, 0);
5084 if (test->set_keyboard_state_main)
5085 {
5086 expect_c = TRUE;
5087 keystate['C'] = 0xff;
5089 }
5090 else expect_c = FALSE;
5091
5092 check_get_keyboard_state(i, j, expect_c, FALSE);
5093 check_get_key_state(i, j, expect_c, FALSE);
5094 check_get_keyboard_state(i, j, expect_c, FALSE);
5095
5096 if (test->peek_message_main) while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
5097
5098 if (test->peek_message_main) expect_x = TRUE;
5099 else expect_x = FALSE;
5100
5101 check_get_keyboard_state(i, j, expect_c, expect_x);
5102 check_get_key_state(i, j, expect_c, expect_x);
5103 check_get_keyboard_state(i, j, expect_c, expect_x);
5104
5105 ReleaseSemaphore(params.semaphores[1], 1, NULL);
5106
5107 /* key released */
5108 result = WaitForSingleObject(params.semaphores[0], 1000);
5109 ok(result == WAIT_OBJECT_0, "%d:%d: WaitForSingleObject returned %lu\n", i, j, result);
5110
5111 keybd_event('X', 0, KEYEVENTF_KEYUP, 0);
5112 if (test->set_keyboard_state_main)
5113 {
5114 expect_x = FALSE;
5115 keystate['C'] = 0x00;
5117 }
5118
5119 check_get_keyboard_state(i, j, FALSE, expect_x);
5120 check_get_key_state(i, j, FALSE, expect_x);
5121 check_get_keyboard_state(i, j, FALSE, expect_x);
5122
5123 if (test->peek_message_main) while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
5124
5128
5129 ReleaseSemaphore(params.semaphores[1], 1, NULL);
5130 }
5131
5133 ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", result);
5135 }
5136
5138 CloseHandle(params.semaphores[0]);
5139 CloseHandle(params.semaphores[1]);
5140}
5141
5142static void test_OemKeyScan(void)
5143{
5144 DWORD ret, expect, vkey, scan;
5145 WCHAR oem, wchr;
5146 char oem_char;
5147
5148 BOOL us_kbd = (GetKeyboardLayout(0) == (HKL)(ULONG_PTR)0x04090409);
5149 if (!us_kbd)
5150 {
5151 skip("skipping test with inconsistent results on non-us keyboard\n");
5152 return;
5153 }
5154
5155 for (oem = 0; oem < 0x200; oem++)
5156 {
5157 ret = OemKeyScan( oem );
5158
5159 oem_char = LOBYTE( oem );
5160 /* OemKeyScan returns -1 for any character that cannot be mapped,
5161 * whereas OemToCharBuff changes unmappable characters to question
5162 * marks. The ASCII characters 0-127, including the real question mark
5163 * character, are all mappable and are the same in all OEM codepages. */
5164 if (!OemToCharBuffW( &oem_char, &wchr, 1 ) || (wchr == '?' && oem_char < 0))
5165 expect = -1;
5166 else
5167 {
5168 vkey = VkKeyScanW( wchr );
5169 scan = MapVirtualKeyW( LOBYTE( vkey ), MAPVK_VK_TO_VSC );
5170 if (!scan)
5171 expect = -1;
5172 else
5173 {
5174 vkey &= 0xff00;
5175 vkey <<= 8;
5176 expect = vkey | scan;
5177 }
5178 }
5179 ok( ret == expect, "%04x: got %08lx expected %08lx\n", oem, ret, expect );
5180 }
5181}
5182
5183static INPUT_MESSAGE_SOURCE expect_src;
5184
5186{
5187 INPUT_MESSAGE_SOURCE source;
5188 MSG msg;
5189
5190 ok( pGetCurrentInputMessageSource( &source ), "GetCurrentInputMessageSource failed\n" );
5191 switch (message)
5192 {
5193 case WM_KEYDOWN:
5194 case WM_KEYUP:
5195 case WM_SYSKEYDOWN:
5196 case WM_SYSKEYUP:
5197 case WM_MOUSEMOVE:
5198 case WM_LBUTTONDOWN:
5199 case WM_LBUTTONUP:
5200 case WM_RBUTTONDOWN:
5201 case WM_RBUTTONUP:
5202 ok( source.deviceType == expect_src.deviceType || /* also accept system-generated WM_MOUSEMOVE */
5203 (message == WM_MOUSEMOVE && source.deviceType == IMDT_UNAVAILABLE),
5204 "%x: wrong deviceType %x/%x\n", message, source.deviceType, expect_src.deviceType );
5205 ok( source.originId == expect_src.originId ||
5206 (message == WM_MOUSEMOVE && source.originId == IMO_SYSTEM),
5207 "%x: wrong originId %x/%x\n", message, source.originId, expect_src.originId );
5208 SendMessageA( hwnd, WM_USER, 0, 0 );
5209 PostMessageA( hwnd, WM_USER, 0, 0 );
5211 ok( source.deviceType == expect_src.deviceType || /* also accept system-generated WM_MOUSEMOVE */
5212 (message == WM_MOUSEMOVE && source.deviceType == IMDT_UNAVAILABLE),
5213 "%x: wrong deviceType %x/%x\n", message, source.deviceType, expect_src.deviceType );
5214 ok( source.originId == expect_src.originId ||
5215 (message == WM_MOUSEMOVE && source.originId == IMO_SYSTEM),
5216 "%x: wrong originId %x/%x\n", message, source.originId, expect_src.originId );
5217 break;
5218 default:
5219 ok( source.deviceType == IMDT_UNAVAILABLE, "%x: wrong deviceType %x\n",
5220 message, source.deviceType );
5221 ok( source.originId == 0, "%x: wrong originId %x\n", message, source.originId );
5222 break;
5223 }
5224
5225 return DefWindowProcA( hwnd, message, wp, lp );
5226}
5227
5229{
5230 WNDCLASSA cls;
5231 INPUT inputs[2];
5232 HWND hwnd;
5233 RECT rc;
5234 MSG msg;
5235
5236 cls.style = 0;
5238 cls.cbClsExtra = 0;
5239 cls.cbWndExtra = 0;
5240 cls.hInstance = GetModuleHandleA(0);
5241 cls.hIcon = 0;
5243 cls.hbrBackground = 0;
5244 cls.lpszMenuName = NULL;
5245 cls.lpszClassName = "message source class";
5246 RegisterClassA(&cls);
5247 hwnd = CreateWindowA( cls.lpszClassName, "test", WS_OVERLAPPED, 0, 0, 100, 100,
5248 0, 0, 0, 0 );
5250 UpdateWindow( hwnd );
5252 SetFocus( hwnd );
5253
5254 inputs[0].type = INPUT_KEYBOARD;
5255 inputs[0].ki.dwExtraInfo = 0;
5256 inputs[0].ki.time = 0;
5257 inputs[0].ki.wVk = 0;
5258 inputs[0].ki.wScan = 0x3c0;
5259 inputs[0].ki.dwFlags = KEYEVENTF_UNICODE;
5260 inputs[1] = inputs[0];
5261 inputs[1].ki.dwFlags |= KEYEVENTF_KEYUP;
5262
5263 expect_src.deviceType = IMDT_UNAVAILABLE;
5264 expect_src.originId = IMO_UNAVAILABLE;
5265 SendMessageA( hwnd, WM_KEYDOWN, 0, 0 );
5266 SendMessageA( hwnd, WM_MOUSEMOVE, 0, 0 );
5267
5268 SendInput( 2, inputs, sizeof(INPUT) );
5269 while (PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ))
5270 {
5271 expect_src.deviceType = IMDT_KEYBOARD;
5272 expect_src.originId = IMO_INJECTED;
5275 }
5276 GetWindowRect( hwnd, &rc );
5277 simulate_click( TRUE, (rc.left + rc.right) / 2, (rc.top + rc.bottom) / 2 );
5278 simulate_click( FALSE, (rc.left + rc.right) / 2 + 1, (rc.top + rc.bottom) / 2 + 1 );
5279 while (PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ))
5280 {
5281 expect_src.deviceType = IMDT_MOUSE;
5282 expect_src.originId = IMO_INJECTED;
5285 }
5286
5287 expect_src.deviceType = IMDT_UNAVAILABLE;
5288 expect_src.originId = IMO_UNAVAILABLE;
5289 SendMessageA( hwnd, WM_KEYDOWN, 0, 0 );
5291 PostMessageA( hwnd, WM_KEYUP, 0, 0 );
5292 PostMessageA( hwnd, WM_LBUTTONUP, 0, 0 );
5293 while (PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ))
5294 {
5297 }
5298
5299 expect_src.deviceType = IMDT_UNAVAILABLE;
5300 expect_src.originId = IMO_SYSTEM;
5301 SetCursorPos( (rc.left + rc.right) / 2 - 1, (rc.top + rc.bottom) / 2 - 1 );
5302 while (PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ))
5303 {
5306 }
5307
5310}
5311
5313{
5315 ok(ret == FALSE, "Unregistering NULL Device Notification returned: %d\n", ret);
5316}
5317
5318static void test_SendInput( WORD vkey, WCHAR wch, HKL hkl )
5319{
5320 const struct user_call broken_sequence[] =
5321 {
5322 {.func = MSG_TEST_WIN, .message = {.msg = WM_KEYDOWN, .wparam = vkey, .lparam = MAKELONG(1, 0)}},
5323 {.func = MSG_TEST_WIN, .message = {.msg = WM_CHAR, .wparam = wch, .lparam = MAKELONG(1, 0)}},
5324 {.func = MSG_TEST_WIN, .message = {.msg = WM_KEYUP, .wparam = vkey, .lparam = MAKELONG(1, KF_UP | KF_REPEAT)}},
5325 {0}
5326 };
5327
5328 INPUT input[16];
5329 UINT res, i;
5330 HWND hwnd;
5331
5332 hwnd = CreateWindowW( L"static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, NULL, NULL );
5333 ok_ne( NULL, hwnd, HWND, "%p" );
5334 wait_messages( 100, FALSE );
5335
5336 /* If we have had a spurious layout change, wch may be incorrect. */
5337 if (GetKeyboardLayout( 0 ) != hkl)
5338 {
5339 win_skip( "Spurious keyboard layout changed detected (expected: %p got: %p)\n",
5340 hkl, GetKeyboardLayout( 0 ) );
5341 ok_ret( 1, DestroyWindow( hwnd ) );
5342 wait_messages( 100, FALSE );
5344 return;
5345 }
5346
5347 SetLastError( 0xdeadbeef );
5348 ok_ret( 0, SendInput( 0, NULL, 0 ) );
5350 SetLastError( 0xdeadbeef );
5351 ok_ret( 0, SendInput( 1, NULL, 0 ) );
5353 SetLastError( 0xdeadbeef );
5354 ok_ret( 0, SendInput( 1, NULL, sizeof(*input) ) );
5356 "GetLastError returned %#lx\n", GetLastError() );
5357 SetLastError( 0xdeadbeef );
5358 ok_ret( 0, SendInput( 0, input, sizeof(*input) ) );
5360 SetLastError( 0xdeadbeef );
5361 ok_ret( 0, SendInput( 0, NULL, sizeof(*input) ) );
5363
5364 memset( input, 0, sizeof(input) );
5365 SetLastError( 0xdeadbeef );
5366 ok_ret( 1, SendInput( 1, input, sizeof(*input) ) );
5367 ok_ret( 0xdeadbeef, GetLastError() );
5368 SetLastError( 0xdeadbeef );
5369 ok_ret( 16, SendInput( 16, input, sizeof(*input) ) );
5370 ok_ret( 0xdeadbeef, GetLastError() );
5371
5372 SetLastError( 0xdeadbeef );
5373 ok_ret( 0, SendInput( 1, input, 0 ) );
5375 SetLastError( 0xdeadbeef );
5376 ok_ret( 0, SendInput( 1, input, sizeof(*input) + 1 ) );
5378 SetLastError( 0xdeadbeef );
5379 ok_ret( 0, SendInput( 1, input, sizeof(*input) - 1 ) );
5381
5382 for (i = 0; i < ARRAY_SIZE(input); ++i) input[i].type = INPUT_KEYBOARD;
5383 SetLastError( 0xdeadbeef );
5384 ok_ret( 0, SendInput( 16, input, offsetof( INPUT, ki ) + sizeof(KEYBDINPUT) ) );
5386 SetLastError( 0xdeadbeef );
5387 ok_ret( 16, SendInput( 16, input, sizeof(*input) ) );
5388 ok_ret( 0xdeadbeef, GetLastError() );
5389
5390 for (i = 0; i < ARRAY_SIZE(input); ++i) input[i].type = INPUT_HARDWARE;
5391 SetLastError( 0xdeadbeef );
5392 ok_ret( 0, SendInput( 16, input, offsetof( INPUT, hi ) + sizeof(HARDWAREINPUT) ) );
5394
5395 wait_messages( 100, FALSE );
5398
5399 input[0].hi.uMsg = WM_KEYDOWN;
5400 input[0].hi.wParamL = 0;
5401 input[0].hi.wParamH = 'A';
5402 input[1].hi.uMsg = WM_KEYUP;
5403 input[1].hi.wParamL = 0;
5404 input[1].hi.wParamH = 'A' | 0xc000;
5405 SetLastError( 0xdeadbeef );
5406 res = SendInput( 16, input, sizeof(*input) );
5408 broken(res == 16 && GetLastError() == 0xdeadbeef) /* 32bit */,
5409 "SendInput returned %u, error %#lx\n", res, GetLastError() );
5410 wait_messages( 100, TRUE );
5412
5413 memset( input, 0, sizeof(input) );
5414 input[0].type = INPUT_HARDWARE;
5415 input[1].type = INPUT_KEYBOARD;
5416 input[1].ki.wVk = vkey;
5417 input[1].ki.dwFlags = 0;
5418 input[2].type = INPUT_KEYBOARD;
5419 input[2].ki.wVk = vkey;
5420 input[2].ki.dwFlags = KEYEVENTF_KEYUP;
5421 SetLastError( 0xdeadbeef );
5422 res = SendInput( 16, input, sizeof(*input) );
5424 broken(res == 16 && GetLastError() == 0xdeadbeef),
5425 "SendInput returned %u, error %#lx\n", res, GetLastError() );
5426 wait_messages( 100, TRUE );
5427 if (broken(res == 16)) ok_seq( broken_sequence );
5428 else ok_seq( empty_sequence );
5429
5430 for (i = 0; i < ARRAY_SIZE(input); ++i) input[i].type = INPUT_HARDWARE + 1;
5431 SetLastError( 0xdeadbeef );
5432 ok_ret( 16, SendInput( 16, input, sizeof(*input) ) );
5433 ok_ret( 0xdeadbeef, GetLastError() );
5434 wait_messages( 100, TRUE );
5436
5437 ok_ret( 1, DestroyWindow( hwnd ) );
5438 wait_messages( 100, FALSE );
5441}
5442
5443#define check_pointer_info( a, b ) check_pointer_info_( __LINE__, a, b )
5444static void check_pointer_info_( int line, const POINTER_INFO *actual, const POINTER_INFO *expected )
5445{
5446 check_member( *actual, *expected, "%#lx", pointerType );
5447 check_member( *actual, *expected, "%#x", pointerId );
5448 check_member( *actual, *expected, "%#x", frameId );
5449 check_member( *actual, *expected, "%#x", pointerFlags );
5450 check_member( *actual, *expected, "%p", sourceDevice );
5451 check_member( *actual, *expected, "%p", hwndTarget );
5452 check_member( *actual, *expected, "%+ld", ptPixelLocation.x );
5453 check_member( *actual, *expected, "%+ld", ptPixelLocation.y );
5454 check_member( *actual, *expected, "%+ld", ptHimetricLocation.x );
5455 check_member( *actual, *expected, "%+ld", ptHimetricLocation.y );
5456 check_member( *actual, *expected, "%+ld", ptPixelLocationRaw.x );
5457 check_member( *actual, *expected, "%+ld", ptPixelLocationRaw.y );
5458 check_member( *actual, *expected, "%+ld", ptHimetricLocationRaw.x );
5459 check_member( *actual, *expected, "%+ld", ptHimetricLocationRaw.y );
5460 check_member( *actual, *expected, "%lu", dwTime );
5461 check_member( *actual, *expected, "%u", historyCount );
5462 check_member( *actual, *expected, "%#x", InputData );
5463 check_member( *actual, *expected, "%#lx", dwKeyStates );
5464 check_member( *actual, *expected, "%I64u", PerformanceCount );
5465 check_member( *actual, *expected, "%#x", ButtonChangeType );
5466}
5467
5469{
5470 POINTER_INFO pointer_info;
5471 HWND hwnd;
5472 BOOL ret;
5473
5474 hwnd = CreateWindowW( L"test", L"test name", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200,
5475 200, 0, 0, NULL, 0 );
5476
5477 memset( &pointer_info, 0xcd, sizeof(pointer_info) );
5478 ret = pGetPointerInfo( 1, &pointer_info );
5479 ok( !ret, "GetPointerInfo succeeded\n" );
5480 ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
5481
5483
5484 return 0;
5485}
5486
5487static void test_GetPointerInfo( BOOL mouse_in_pointer_enabled )
5488{
5489 POINTER_INFO pointer_info[4], expect_pointer;
5490 void *invalid_ptr = (void *)0xdeadbeef;
5491 UINT32 entry_count, pointer_count;
5492 POINTER_INPUT_TYPE type;
5493 WNDCLASSW cls =
5494 {
5496 .hInstance = GetModuleHandleW( NULL ),
5497 .hbrBackground = GetStockObject( WHITE_BRUSH ),
5498 .lpszClassName = L"test",
5499 };
5500 HANDLE thread;
5501 ATOM class;
5502 DWORD res;
5503 HWND hwnd;
5504 BOOL ret;
5505
5506 if (!pGetPointerType)
5507 {
5508 todo_wine
5509 win_skip( "GetPointerType not found, skipping tests\n" );
5510 return;
5511 }
5512
5513 SetLastError( 0xdeadbeef );
5514 ret = pGetPointerType( 1, NULL );
5515 ok( !ret, "GetPointerType succeeded\n" );
5516 ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
5517 SetLastError( 0xdeadbeef );
5518 ret = pGetPointerType( 0xdead, &type );
5519 todo_wine
5520 ok( !ret, "GetPointerType succeeded\n" );
5521 todo_wine
5522 ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
5523 ret = pGetPointerType( 1, &type );
5524 ok( ret, "GetPointerType failed, error %lu\n", GetLastError() );
5525 ok( type == PT_MOUSE, " type %ld\n", type );
5526
5527 if (!pGetPointerInfo)
5528 {
5529 todo_wine
5530 win_skip( "GetPointerInfo not found, skipping tests\n" );
5531 return;
5532 }
5533
5534 class = RegisterClassW( &cls );
5535 ok( class, "RegisterClassW failed: %lu\n", GetLastError() );
5536
5537 ret = pGetPointerInfo( 1, invalid_ptr );
5538 ok( !ret, "GetPointerInfo succeeded\n" );
5539 todo_wine
5541 "got error %lu\n", GetLastError() );
5542
5543 memset( pointer_info, 0xcd, sizeof(pointer_info) );
5544 ret = pGetPointerInfo( 1, pointer_info );
5545 ok( !ret, "GetPointerInfo succeeded\n" );
5546 ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
5547
5548 SetCursorPos( 500, 500 ); /* avoid generating mouse message on window creation */
5549
5550 hwnd = CreateWindowW( L"test", L"test name", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200,
5551 200, 0, 0, NULL, 0 );
5553
5554 memset( pointer_info, 0xcd, sizeof(pointer_info) );
5555 ret = pGetPointerInfo( 1, pointer_info );
5556 ok( !ret, "GetPointerInfo succeeded\n" );
5557 ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
5558
5559 SetCursorPos( 200, 200 );
5561 mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 );
5563 mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 );
5565 mouse_event( MOUSEEVENTF_MOVE, 10, 10, 0, 0 );
5567
5568 memset( pointer_info, 0xcd, sizeof(pointer_info) );
5569 ret = pGetPointerInfo( 0xdead, pointer_info );
5570 ok( !ret, "GetPointerInfo succeeded\n" );
5571 ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
5572
5573 memset( pointer_info, 0xcd, sizeof(pointer_info) );
5574 ret = pGetPointerInfo( 1, pointer_info );
5575 todo_wine_if(mouse_in_pointer_enabled)
5576 ok( ret == mouse_in_pointer_enabled, "GetPointerInfo failed, error %lu\n", GetLastError() );
5577 if (!mouse_in_pointer_enabled)
5578 {
5579 ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
5580 return;
5581 }
5582
5583 todo_wine
5584 ok( pointer_info[0].pointerType == PT_MOUSE, "got pointerType %lu\n", pointer_info[0].pointerType );
5585 todo_wine
5586 ok( pointer_info[0].pointerId == 1, "got pointerId %u\n", pointer_info[0].pointerId );
5587 ok( !!pointer_info[0].frameId, "got frameId %u\n", pointer_info[0].frameId );
5588 todo_wine
5589 ok( pointer_info[0].pointerFlags == (0x20000 | POINTER_MESSAGE_FLAG_INRANGE | POINTER_MESSAGE_FLAG_PRIMARY),
5590 "got pointerFlags %#x\n", pointer_info[0].pointerFlags );
5591 todo_wine
5592 ok( pointer_info[0].sourceDevice == INVALID_HANDLE_VALUE || broken(!!pointer_info[0].sourceDevice) /* < w10 & 32bit */,
5593 "got sourceDevice %p\n", pointer_info[0].sourceDevice );
5594 todo_wine
5595 ok( pointer_info[0].hwndTarget == hwnd, "got hwndTarget %p\n", pointer_info[0].hwndTarget );
5596 ok( !!pointer_info[0].ptPixelLocation.x, "got ptPixelLocation %s\n", wine_dbgstr_point( &pointer_info[0].ptPixelLocation ) );
5597 ok( !!pointer_info[0].ptPixelLocation.y, "got ptPixelLocation %s\n", wine_dbgstr_point( &pointer_info[0].ptPixelLocation ) );
5598 ok( !!pointer_info[0].ptHimetricLocation.x, "got ptHimetricLocation %s\n", wine_dbgstr_point( &pointer_info[0].ptHimetricLocation ) );
5599 ok( !!pointer_info[0].ptHimetricLocation.y, "got ptHimetricLocation %s\n", wine_dbgstr_point( &pointer_info[0].ptHimetricLocation ) );
5600 ok( !!pointer_info[0].ptPixelLocationRaw.x, "got ptPixelLocationRaw %s\n", wine_dbgstr_point( &pointer_info[0].ptPixelLocationRaw ) );
5601 ok( !!pointer_info[0].ptPixelLocationRaw.y, "got ptPixelLocationRaw %s\n", wine_dbgstr_point( &pointer_info[0].ptPixelLocationRaw ) );
5602 ok( !!pointer_info[0].ptHimetricLocationRaw.x, "got ptHimetricLocationRaw %s\n", wine_dbgstr_point( &pointer_info[0].ptHimetricLocationRaw ) );
5603 ok( !!pointer_info[0].ptHimetricLocationRaw.y, "got ptHimetricLocationRaw %s\n", wine_dbgstr_point( &pointer_info[0].ptHimetricLocationRaw ) );
5604 ok( !!pointer_info[0].dwTime, "got dwTime %lu\n", pointer_info[0].dwTime );
5605 todo_wine
5606 ok( pointer_info[0].historyCount == 1, "got historyCount %u\n", pointer_info[0].historyCount );
5607 todo_wine
5608 ok( pointer_info[0].InputData == 0, "got InputData %u\n", pointer_info[0].InputData );
5609 todo_wine
5610 ok( pointer_info[0].dwKeyStates == 0, "got dwKeyStates %lu\n", pointer_info[0].dwKeyStates );
5611 ok( !!pointer_info[0].PerformanceCount, "got PerformanceCount %I64u\n", pointer_info[0].PerformanceCount );
5612 todo_wine
5613 ok( pointer_info[0].ButtonChangeType == 0, "got ButtonChangeType %u\n", pointer_info[0].ButtonChangeType );
5614
5616 res = WaitForSingleObject( thread, 5000 );
5617 ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() );
5618
5619 expect_pointer = pointer_info[0];
5620
5621 memset( pointer_info, 0xa5, sizeof(pointer_info) );
5622 entry_count = pointer_count = 2;
5623 if (!pGetPointerFrameInfo) ret = FALSE;
5624 else ret = pGetPointerFrameInfo( 1, &pointer_count, pointer_info );
5625 todo_wine_if(!pGetPointerFrameInfo)
5626 ok( ret, "GetPointerFrameInfo failed, error %lu\n", GetLastError() );
5627 todo_wine_if(!pGetPointerFrameInfo)
5628 ok( pointer_count == 1, "got pointer_count %u\n", pointer_count );
5629 todo_wine_if(!pGetPointerFrameInfo)
5630 check_pointer_info( &pointer_info[0], &expect_pointer );
5631 memset( pointer_info, 0xa5, sizeof(pointer_info) );
5632 entry_count = pointer_count = 2;
5633 if (!pGetPointerInfoHistory) ret = FALSE;
5634 else ret = pGetPointerInfoHistory( 1, &entry_count, pointer_info );
5635 todo_wine_if(!pGetPointerInfoHistory)
5636 ok( ret, "GetPointerInfoHistory failed, error %lu\n", GetLastError() );
5637 todo_wine_if(!pGetPointerInfoHistory)
5638 ok( entry_count == 1, "got entry_count %u\n", entry_count );
5639 todo_wine_if(!pGetPointerInfoHistory)
5640 check_pointer_info( &pointer_info[0], &expect_pointer );
5641 memset( pointer_info, 0xa5, sizeof(pointer_info) );
5642 entry_count = pointer_count = 2;
5643 if (!pGetPointerFrameInfoHistory) ret = FALSE;
5644 else ret = pGetPointerFrameInfoHistory( 1, &entry_count, &pointer_count, pointer_info );
5645 todo_wine_if(!pGetPointerFrameInfoHistory)
5646 ok( ret, "GetPointerFrameInfoHistory failed, error %lu\n", GetLastError() );
5647 todo_wine_if(!pGetPointerFrameInfoHistory)
5648 ok( entry_count == 1, "got pointer_count %u\n", pointer_count );
5649 todo_wine_if(!pGetPointerFrameInfoHistory)
5650 ok( pointer_count == 1, "got pointer_count %u\n", pointer_count );
5651 todo_wine_if(!pGetPointerFrameInfoHistory)
5652 check_pointer_info( &pointer_info[0], &expect_pointer );
5653
5655
5657 ok( ret, "UnregisterClassW failed: %lu\n", GetLastError() );
5658}
5659
5660static void test_EnableMouseInPointer( const char *arg )
5661{
5662 DWORD enable = strtoul( arg, 0, 10 );
5663 BOOL ret;
5664
5665 winetest_push_context( "enable %lu", enable );
5666
5667 ret = pEnableMouseInPointer( enable );
5668 todo_wine
5669 ok( ret, "EnableMouseInPointer failed, error %lu\n", GetLastError() );
5670
5671 SetLastError( 0xdeadbeef );
5672 ret = pEnableMouseInPointer( !enable );
5673 ok( !ret, "EnableMouseInPointer succeeded\n" );
5674 todo_wine
5675 ok( GetLastError() == ERROR_ACCESS_DENIED, "got error %lu\n", GetLastError() );
5676 ret = pIsMouseInPointerEnabled();
5678 ok( ret == enable, "IsMouseInPointerEnabled returned %u, error %lu\n", ret, GetLastError() );
5679
5680 ret = pEnableMouseInPointer( enable );
5681 todo_wine
5682 ok( ret, "EnableMouseInPointer failed, error %lu\n", GetLastError() );
5683 ret = pIsMouseInPointerEnabled();
5685 ok( ret == enable, "IsMouseInPointerEnabled returned %u, error %lu\n", ret, GetLastError() );
5686
5688
5690}
5691
5693{
5694 RECT *virtual_rect = (RECT *)lp;
5695 UnionRect( virtual_rect, virtual_rect, rect );
5696 return TRUE;
5697}
5698
5700{
5701 RECT rect = {0};
5703 return rect;
5704}
5705
5706static void test_ClipCursor_dirty( const char *arg )
5707{
5708 RECT rect, expect_rect = {1, 2, 3, 4};
5709
5710 /* check leaked clip rect from another desktop or process */
5711 ok_ret( 1, GetClipCursor( &rect ) );
5712 todo_wine_if( !strcmp( arg, "desktop" ) )
5714
5715 /* intentionally leaking clipping rect */
5716}
5717
5719{
5720 RECT rect, clip_rect, virtual_rect = get_virtual_screen_rect();
5721 HWND hwnd;
5722
5723 clip_rect.left = clip_rect.right = (virtual_rect.left + virtual_rect.right) / 2;
5724 clip_rect.top = clip_rect.bottom = (virtual_rect.top + virtual_rect.bottom) / 2;
5725
5726 /* creating a window doesn't reset clipping rect */
5727 hwnd = CreateWindowW( L"static", NULL, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0,
5728 NULL, NULL, NULL, NULL );
5729 ok( !!hwnd, "CreateWindowW failed, error %lu\n", GetLastError() );
5730 ok_ret( 1, GetClipCursor( &rect ) );
5731 ok_rect( clip_rect, rect );
5732
5733 /* setting a window foreground does, even from the same process */
5735 ok_ret( 1, GetClipCursor( &rect ) );
5736 ok_rect( virtual_rect, rect );
5737
5738 /* destroying the window doesn't reset the clipping rect */
5739 InflateRect( &clip_rect, +1, +1 );
5740 ok_ret( 1, ClipCursor( &clip_rect ) );
5741 ok_ret( 1, DestroyWindow( hwnd ) );
5742 ok_ret( 1, GetClipCursor( &rect ) );
5743 ok_rect( clip_rect, rect );
5744
5745 /* intentionally leaking clipping rect */
5746 return 0;
5747}
5748
5750{
5751 RECT rect, clip_rect, virtual_rect = get_virtual_screen_rect();
5752 HWND hwnd, tmp_hwnd;
5753 HANDLE thread;
5754
5755 clip_rect.left = clip_rect.right = (virtual_rect.left + virtual_rect.right) / 2;
5756 clip_rect.top = clip_rect.bottom = (virtual_rect.top + virtual_rect.bottom) / 2;
5757
5758 ok_ret( 1, GetClipCursor( &rect ) );
5759 ok_rect( clip_rect, rect );
5760
5761 /* creating an invisible window doesn't reset clip cursor */
5762 hwnd = CreateWindowW( L"static", NULL, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0,
5763 NULL, NULL, NULL, NULL );
5764 ok( !!hwnd, "CreateWindowW failed, error %lu\n", GetLastError() );
5765 ok_ret( 1, DestroyWindow( hwnd ) );
5766 ok_ret( 1, GetClipCursor( &rect ) );
5767 ok_rect( clip_rect, rect );
5768
5769 /* setting a window foreground, even invisible, resets it */
5770 hwnd = CreateWindowW( L"static", NULL, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0,
5771 NULL, NULL, NULL, NULL );
5772 ok( !!hwnd, "CreateWindowW failed, error %lu\n", GetLastError() );
5774 ok_ret( 1, GetClipCursor( &rect ) );
5775 ok_rect( virtual_rect, rect );
5776
5777 ok_ret( 1, ClipCursor( &clip_rect ) );
5778
5779 /* creating and setting another window foreground doesn't reset it */
5780 tmp_hwnd = CreateWindowW( L"static", NULL, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0,
5781 NULL, NULL, NULL, NULL );
5782 ok( !!tmp_hwnd, "CreateWindowW failed, error %lu\n", GetLastError() );
5783 ok_ret( 1, SetForegroundWindow( tmp_hwnd ) );
5784 ok_ret( 1, DestroyWindow( tmp_hwnd ) );
5785 ok_ret( 1, GetClipCursor( &rect ) );
5786 ok_rect( clip_rect, rect );
5787
5788 /* but changing foreground to another thread in the same process reset it */
5790 ok( !!thread, "CreateThread failed, error %lu\n", GetLastError() );
5791 msg_wait_for_events( 1, &thread, 5000 );
5792
5793 /* thread exit and foreground window destruction doesn't reset the clipping rect */
5794 InflateRect( &clip_rect, +1, +1 );
5795 ok_ret( 1, DestroyWindow( hwnd ) );
5796 ok_ret( 1, GetClipCursor( &rect ) );
5797 ok_rect( clip_rect, rect );
5798
5799 /* intentionally leaking clipping rect */
5800}
5801
5802static void test_ClipCursor_desktop( char **argv )
5803{
5804 RECT rect, clip_rect, virtual_rect = get_virtual_screen_rect();
5805
5806 ok_ret( 1, GetClipCursor( &rect ) );
5807 ok_rect( virtual_rect, rect );
5808
5809 /* ClipCursor clips rectangle to the virtual screen rect */
5810 clip_rect = virtual_rect;
5811 InflateRect( &clip_rect, +1, +1 );
5812 ok_ret( 1, ClipCursor( &clip_rect ) );
5813 ok_ret( 1, GetClipCursor( &rect ) );
5814 ok_rect( virtual_rect, rect );
5815
5816 clip_rect = virtual_rect;
5817 InflateRect( &clip_rect, -1, -1 );
5818 ok_ret( 1, ClipCursor( &clip_rect ) );
5819 ok_ret( 1, GetClipCursor( &rect ) );
5820 ok_rect( clip_rect, rect );
5821
5822 /* ClipCursor(NULL) resets to the virtual screen rect */
5823 ok_ret( 1, ClipCursor( NULL ) );
5824 ok_ret( 1, GetClipCursor( &rect ) );
5825 ok_rect( virtual_rect, rect );
5826
5827 clip_rect.left = clip_rect.right = (virtual_rect.left + virtual_rect.right) / 2;
5828 clip_rect.top = clip_rect.bottom = (virtual_rect.top + virtual_rect.bottom) / 2;
5829 ok_ret( 1, ClipCursor( &clip_rect ) );
5830 ok_ret( 1, GetClipCursor( &rect ) );
5831 ok_rect( clip_rect, rect );
5832
5833 /* ClipCursor rejects invalid rectangles */
5834 clip_rect.right -= 1;
5835 clip_rect.bottom -= 1;
5836 SetLastError( 0xdeadbeef );
5837 ok_ret( 0, ClipCursor( &clip_rect ) );
5838 todo_wine
5840
5841 /* which doesn't reset the previous clip rect */
5842 clip_rect.right += 1;
5843 clip_rect.bottom += 1;
5844 ok_ret( 1, GetClipCursor( &rect ) );
5845 ok_rect( clip_rect, rect );
5846
5847 /* running a process causes it to leak until foreground actually changes */
5848 run_in_process( argv, "test_ClipCursor_process" );
5849
5850 /* as foreground window is now transient, cursor clipping isn't reset */
5851 InflateRect( &clip_rect, +1, +1 );
5852 ok_ret( 1, GetClipCursor( &rect ) );
5853 ok_rect( clip_rect, rect );
5854
5855 /* intentionally leaking clipping rect */
5856}
5857
5858static void test_ClipCursor( char **argv )
5859{
5860 RECT rect, clip_rect = {1, 2, 3, 4}, virtual_rect = get_virtual_screen_rect();
5861
5862 ok_ret( 1, ClipCursor( &clip_rect ) );
5863
5864 /* running a new process doesn't reset clipping rectangle */
5865 run_in_process( argv, "test_ClipCursor_dirty process" );
5866
5867 /* running in a separate desktop, without switching desktop as well */
5868 run_in_desktop( argv, "test_ClipCursor_dirty desktop", 0 );
5869
5870 ok_ret( 1, GetClipCursor( &rect ) );
5871 ok_rect( clip_rect, rect );
5872
5873 /* running in a desktop and switching input resets the clipping rect */
5874 run_in_desktop( argv, "test_ClipCursor_desktop", 1 );
5875
5876 ok_ret( 1, GetClipCursor( &rect ) );
5877 todo_wine
5878 ok_rect( virtual_rect, rect );
5879 if (!EqualRect( &rect, &virtual_rect )) ok_ret( 1, ClipCursor( NULL ) );
5880}
5881
5882static void test_SetCursorPos(void)
5883{
5884 RECT clip_rect = {50, 50, 51, 51};
5885 POINT pos, expect_pos = {50, 50};
5886
5887 ok_ret( 0, GetCursorPos( NULL ) );
5889
5890 /* immediate cursor position updates */
5891 ok_ret( 1, SetCursorPos( 50, 50 ) );
5892 ok_ret( 1, GetCursorPos( &pos ) );
5893 ok_point( expect_pos, pos );
5894
5895 /* without MOUSEEVENTF_MOVE cursor doesn't move */
5896 mouse_event( MOUSEEVENTF_LEFTUP, 123, 456, 0, 0 );
5898 mouse_event( MOUSEEVENTF_RIGHTUP, 456, 123, 0, 0 );
5900 ok_ret( 1, GetCursorPos( &pos ) );
5901 ok_point( expect_pos, pos );
5902
5903 /* need to move by at least 3 pixels to update, but not consistent */
5904 mouse_event( MOUSEEVENTF_MOVE, -1, 0, 0, 0 );
5905 ok_ret( 1, GetCursorPos( &pos ) );
5906#ifdef __REACTOS__
5907 ok( abs( expect_pos.x - pos.x ) <= 2, "got pos %ld\n", pos.x );
5908 ok( abs( expect_pos.y - pos.y ) <= 2, "got pos %ld\n", pos.y );
5909#else
5910 todo_wine ok_point( expect_pos, pos );
5911#endif
5912 mouse_event( MOUSEEVENTF_MOVE, +1, 0, 0, 0 );
5913 ok_ret( 1, GetCursorPos( &pos ) );
5914#ifdef __REACTOS__
5915 ok( abs( expect_pos.x - pos.x ) <= 2, "got pos %ld\n", pos.x );
5916 ok( abs( expect_pos.y - pos.y ) <= 2, "got pos %ld\n", pos.y );
5917#else
5918 ok_point( expect_pos, pos );
5919#endif
5920
5921 /* spuriously moves by 1 or 2 pixels on Windows */
5922 expect_pos.x -= 2;
5923 mouse_event( MOUSEEVENTF_MOVE, -4, 0, 0, 0 );
5924 ok_ret( 1, GetCursorPos( &pos ) );
5925#ifdef __REACTOS__
5926 todo_wine ok( abs( expect_pos.x - pos.x ) <= 2, "got pos %ld\n", pos.x );
5927#else
5928 todo_wine ok( abs( expect_pos.x - pos.x ) <= 1, "got pos %ld\n", pos.x );
5929#endif
5930 expect_pos.x += 2;
5931 mouse_event( MOUSEEVENTF_MOVE, +4, 0, 0, 0 );
5932 ok_ret( 1, GetCursorPos( &pos ) );
5933#ifdef __REACTOS__
5934 ok( abs( expect_pos.x - pos.x ) <= 2, "got pos %ld\n", pos.x );
5935#else
5936 ok( abs( expect_pos.x - pos.x ) <= 1, "got pos %ld\n", pos.x );
5937#endif
5938
5939 /* test ClipCursor holding the cursor in place */
5940 expect_pos.x = expect_pos.y = 50;
5941 ok_ret( 1, SetCursorPos( 49, 51 ) );
5942 ok_ret( 1, ClipCursor( &clip_rect ) );
5943 ok_ret( 1, GetCursorPos( &pos ) );
5944 ok_point( expect_pos, pos );
5945 ok_ret( 1, SetCursorPos( 49, 49 ) );
5946 ok_ret( 1, GetCursorPos( &pos ) );
5947 ok_point( expect_pos, pos );
5948 ok_ret( 1, SetCursorPos( 50, 50 ) );
5949 ok_ret( 1, GetCursorPos( &pos ) );
5950 ok_point( expect_pos, pos );
5951 ok_ret( 1, SetCursorPos( 48, 48 ) );
5952 ok_ret( 1, GetCursorPos( &pos ) );
5953 ok_point( expect_pos, pos );
5954 ok_ret( 1, SetCursorPos( 51, 51 ) );
5955 ok_ret( 1, GetCursorPos( &pos ) );
5956 ok_point( expect_pos, pos );
5957 ok_ret( 1, SetCursorPos( 52, 52 ) );
5958 ok_ret( 1, GetCursorPos( &pos ) );
5959 ok_point( expect_pos, pos );
5960 ok_ret( 1, SetCursorPos( 49, 51 ) );
5961 ok_ret( 1, GetCursorPos( &pos ) );
5962 ok_point( expect_pos, pos );
5963 ok_ret( 1, SetCursorPos( 51, 49 ) );
5964 ok_ret( 1, GetCursorPos( &pos ) );
5965 ok_point( expect_pos, pos );
5966
5967 mouse_event( MOUSEEVENTF_MOVE, -1, 0, 0, 0 );
5968 ok_ret( 1, GetCursorPos( &pos ) );
5969 ok_point( expect_pos, pos );
5970 mouse_event( MOUSEEVENTF_MOVE, 0, +1, 0, 0 );
5971 ok_ret( 1, GetCursorPos( &pos ) );
5972 ok_point( expect_pos, pos );
5973 mouse_event( MOUSEEVENTF_MOVE, +1, 0, 0, 0 );
5974 ok_ret( 1, GetCursorPos( &pos ) );
5975 ok_point( expect_pos, pos );
5976 mouse_event( MOUSEEVENTF_MOVE, 0, -1, 0, 0 );
5977 ok_ret( 1, GetCursorPos( &pos ) );
5978 ok_point( expect_pos, pos );
5979
5980 /* weird behavior when ClipCursor rect is empty */
5981 clip_rect.right = clip_rect.bottom = 50;
5982 ok_ret( 1, SetCursorPos( 50, 50 ) );
5983 expect_pos.x = expect_pos.y = 49;
5984 ok_ret( 1, ClipCursor( &clip_rect ) );
5985 ok_ret( 1, GetCursorPos( &pos ) );
5986 todo_wine ok_point( expect_pos, pos );
5987 expect_pos.x = expect_pos.y = 50;
5988 ok_ret( 1, SetCursorPos( 49, 49 ) );
5989 ok_ret( 1, GetCursorPos( &pos ) );
5990 ok_point( expect_pos, pos );
5991 expect_pos.x = expect_pos.y = 49;
5992 ok_ret( 1, SetCursorPos( 50, 50 ) );
5993 ok_ret( 1, GetCursorPos( &pos ) );
5994 todo_wine ok_point( expect_pos, pos );
5995 expect_pos.x = expect_pos.y = 50;
5996 ok_ret( 1, SetCursorPos( 48, 48 ) );
5997 ok_ret( 1, GetCursorPos( &pos ) );
5998 ok_point( expect_pos, pos );
5999 expect_pos.x = expect_pos.y = 49;
6000 ok_ret( 1, SetCursorPos( 51, 51 ) );
6001 ok_ret( 1, GetCursorPos( &pos ) );
6002 todo_wine ok_point( expect_pos, pos );
6003 ok_ret( 1, SetCursorPos( 52, 52 ) );
6004 ok_ret( 1, GetCursorPos( &pos ) );
6005 todo_wine ok_point( expect_pos, pos );
6006 expect_pos.x = 50;
6007 expect_pos.y = 49;
6008 ok_ret( 1, SetCursorPos( 49, 51 ) );
6009 ok_ret( 1, GetCursorPos( &pos ) );
6010 todo_wine ok_point( expect_pos, pos );
6011 expect_pos.x = 49;
6012 expect_pos.y = 50;
6013 ok_ret( 1, SetCursorPos( 51, 49 ) );
6014 ok_ret( 1, GetCursorPos( &pos ) );
6015 todo_wine ok_point( expect_pos, pos );
6016
6017 expect_pos.x = 50;
6018 expect_pos.y = 49;
6019 mouse_event( MOUSEEVENTF_MOVE, -10, 0, 0, 0 );
6020 ok_ret( 1, GetCursorPos( &pos ) );
6021 todo_wine ok_point( expect_pos, pos );
6022 expect_pos.x = 49;
6023 expect_pos.y = 49;
6024 mouse_event( MOUSEEVENTF_MOVE, 0, +10, 0, 0 );
6025 ok_ret( 1, GetCursorPos( &pos ) );
6026 todo_wine ok_point( expect_pos, pos );
6027 expect_pos.x = 49;
6028 expect_pos.y = 50;
6029 mouse_event( MOUSEEVENTF_MOVE, +10, 0, 0, 0 );
6030 ok_ret( 1, GetCursorPos( &pos ) );
6031 todo_wine ok_point( expect_pos, pos );
6032 expect_pos.x = 50;
6033 expect_pos.y = 50;
6034 mouse_event( MOUSEEVENTF_MOVE, 0, -10, 0, 0 );
6035 ok_ret( 1, GetCursorPos( &pos ) );
6036 ok_point( expect_pos, pos );
6037
6038 ok_ret( 1, ClipCursor( NULL ) );
6039}
6040
6042
6044{
6045 if (code == HC_ACTION)
6046 {
6048 return -123;
6049 }
6050
6051 return CallNextHookEx( 0, code, wparam, lparam );
6052}
6053
6055{
6056 INPUT input = {.type = INPUT_KEYBOARD, .ki = {.wVk = VK_RETURN}};
6057 HHOOK hook;
6058 HWND hwnd;
6059
6060 hwnd = CreateWindowW( L"static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, NULL, NULL );
6061 ok_ne( NULL, hwnd, HWND, "%p" );
6062 wait_messages( 100, FALSE );
6064 ok_ne( NULL, hook, HHOOK, "%p" );
6067
6068 ok_ret( 1, SendInput( 1, &input, sizeof(input) ) );
6069 input.ki.dwFlags = KEYEVENTF_KEYUP;
6070 ok_ret( 1, SendInput( 1, &input, sizeof(input) ) );
6072
6075 ok_ret( 1, DestroyWindow( hwnd ) );
6076}
6077
6078static void test_LoadKeyboardLayoutEx( HKL orig_hkl )
6079{
6080 static const WCHAR test_layout_name[] = L"00000429";
6081 static const HKL test_hkl = (HKL)0x04290429;
6082
6083 HKL *new_layouts, *layouts, old_hkl, hkl;
6084 UINT i, j, len, new_len;
6085 WCHAR layout_name[64];
6086
6087 old_hkl = GetKeyboardLayout( 0 );
6088 ok_ne( 0, old_hkl, HKL, "%p" );
6089
6090 /* If we are dealing with a testbot setup that is prone to spurious
6091 * layout changes, layout activations in this test are likely to
6092 * not have the expected effect, invalidating the test assumptions. */
6093 if (orig_hkl != old_hkl)
6094 {
6095 win_skip( "Spurious keyboard layout changed detected (expected: %p got: %p)\n",
6096 orig_hkl, old_hkl );
6097 return;
6098 }
6099
6100 hkl = pLoadKeyboardLayoutEx( NULL, test_layout_name, 0 );
6101 ok_eq( 0, hkl, HKL, "%p" );
6102
6103 layouts = get_keyboard_layouts( &len );
6104 for (i = 0; i < len; i++) if (layouts[i] == test_hkl) break;
6105 if (i != len)
6106 {
6107 skip( "Test HKL is already loaded, skipping tests\n" );
6108 free( layouts );
6109 return;
6110 }
6111
6112 /* LoadKeyboardLayoutEx replaces loaded layouts, but will lose mixed layout / locale */
6113 for (i = 0, j = len; i < len; i++)
6114 {
6115 if (HIWORD(layouts[i]) != LOWORD(layouts[i])) continue;
6116 if (j == len) j = i;
6117 else break;
6118 }
6119 if (i == len) i = j;
6120 if (i == len)
6121 {
6122 skip( "Failed to find appropriate layouts, skipping tests\n" );
6123 free( layouts );
6124 return;
6125 }
6126
6127 trace( "using layouts %p / %p\n", layouts[i], layouts[j] );
6128
6129 ActivateKeyboardLayout( layouts[i], 0 );
6130 ok_eq( layouts[i], GetKeyboardLayout( 0 ), HKL, "%p" );
6131 ok_ret( 1, GetKeyboardLayoutNameW( layout_name ) );
6132
6133 /* LoadKeyboardLayoutEx replaces a currently loaded layout */
6134 hkl = pLoadKeyboardLayoutEx( layouts[i], test_layout_name, 0 );
6135 todo_wine
6136 ok_eq( test_hkl, hkl, HKL, "%p" );
6137 new_layouts = get_keyboard_layouts( &new_len );
6138 ok_eq( len, new_len, UINT, "%u" );
6139 todo_wine
6140 ok_eq( test_hkl, new_layouts[i], HKL, "%p" );
6141 new_layouts[i] = layouts[i];
6142 ok( !memcmp( new_layouts, layouts, len * sizeof(*layouts) ), "keyboard layouts changed\n" );
6143 free( new_layouts );
6144
6145 hkl = pLoadKeyboardLayoutEx( test_hkl, layout_name, 0 );
6146 ok_eq( layouts[i], hkl, HKL, "%p" );
6147 new_layouts = get_keyboard_layouts( &new_len );
6148 ok_eq( len, new_len, UINT, "%u" );
6149 ok( !memcmp( new_layouts, layouts, len * sizeof(*layouts) ), "keyboard layouts changed\n" );
6150 free( new_layouts );
6151
6152 if (j == i) skip( "Only one layout found, skipping tests\n" );
6153 else
6154 {
6155 /* it also works if a different layout is active */
6156 ActivateKeyboardLayout( layouts[j], 0 );
6157 ok_eq( layouts[j], GetKeyboardLayout( 0 ), HKL, "%p" );
6158
6159 hkl = pLoadKeyboardLayoutEx( layouts[i], test_layout_name, 0 );
6160 todo_wine
6161 ok_eq( test_hkl, hkl, HKL, "%p" );
6162 new_layouts = get_keyboard_layouts( &new_len );
6163 ok_eq( len, new_len, UINT, "%u" );
6164 todo_wine
6165 ok_eq( test_hkl, new_layouts[i], HKL, "%p" );
6166 new_layouts[i] = layouts[i];
6167 ok( !memcmp( new_layouts, layouts, len * sizeof(*layouts) ), "keyboard layouts changed\n" );
6168 free( new_layouts );
6169
6170 hkl = pLoadKeyboardLayoutEx( test_hkl, layout_name, 0 );
6171 ok_eq( layouts[i], hkl, HKL, "%p" );
6172 new_layouts = get_keyboard_layouts( &new_len );
6173 ok_eq( len, new_len, UINT, "%u" );
6174 ok( !memcmp( new_layouts, layouts, len * sizeof(*layouts) ), "keyboard layouts changed\n" );
6175 free( new_layouts );
6176 }
6177
6178 free( layouts );
6179 ActivateKeyboardLayout( old_hkl, 0 );
6180 ok_eq( old_hkl, GetKeyboardLayout( 0 ), HKL, "%p" );
6181}
6182
6183/* run the tests in a separate desktop to avoid interaction with other
6184 * tests, current desktop state, or user actions. */
6185static void test_input_desktop( char **argv )
6186{
6187 HKL hkl = GetKeyboardLayout( 0 );
6188 WCHAR wch, wch_shift;
6189 POINT pos;
6190 WORD scan;
6191
6192 trace( "hkl %p\n", hkl );
6193 ok_ret( 1, GetCursorPos( &pos ) );
6195
6196 get_test_scan( 'F', &scan, &wch, &wch_shift );
6197 test_SendInput( 'F', wch, hkl );
6198 test_SendInput_keyboard_messages( 'F', scan, wch, wch_shift, '\x06', hkl );
6200
6202
6207
6209
6210 ok_ret( 1, SetCursorPos( pos.x, pos.y ) );
6211}
6212
6213static void test_keyboard_layout(void)
6214{
6215 const CHAR *layout_name;
6216 LANGID lang_id;
6217 HKL hkl;
6218
6219 /* Test that the high word of the keyboard layout in CJK locale is the same as the low word,
6220 * even when IME is on */
6221 lang_id = PRIMARYLANGID(GetUserDefaultLCID());
6222 if (lang_id == LANG_CHINESE || lang_id == LANG_JAPANESE || lang_id == LANG_KOREAN)
6223 {
6225 ok(HIWORD(hkl) == LOWORD(hkl), "Got unexpected hkl %p.\n", hkl);
6226
6227 if (lang_id == LANG_CHINESE)
6228 layout_name = "00000804";
6229 else if (lang_id == LANG_JAPANESE)
6230 layout_name = "00000411";
6231 else if (lang_id == LANG_KOREAN)
6232 layout_name = "00000412";
6233 hkl = LoadKeyboardLayoutA(layout_name, 0);
6234 ok(HIWORD(hkl) == LOWORD(hkl), "Got unexpected hkl %p.\n", hkl);
6235 }
6236}
6237
6239{
6240 char **argv;
6241 int argc;
6242 POINT pos;
6243
6245 GetCursorPos( &pos );
6246
6247#ifdef __REACTOS__
6248 if (GetNTVersion() < _WIN32_WINNT_VISTA && !is_reactos()) {
6249 skip("The user32:input tests causes persistent input issues on WS03!\n");
6250 return;
6251 }
6252#endif
6254 if (argc >= 3 && !strcmp( argv[2], "rawinput_test" ))
6255 return rawinput_test_process();
6256 if (argc >= 3 && !strcmp( argv[2], "test_GetMouseMovePointsEx_process" ))
6258 if (argc >= 4 && !strcmp( argv[2], "test_EnableMouseInPointer" ))
6259 return test_EnableMouseInPointer( argv[3] );
6260 if (argc >= 4 && !strcmp( argv[2], "test_ClipCursor_dirty" ))
6261 return test_ClipCursor_dirty( argv[3] );
6262 if (argc >= 3 && !strcmp( argv[2], "test_ClipCursor_process" ))
6263 return test_ClipCursor_process();
6264 if (argc >= 3 && !strcmp( argv[2], "test_ClipCursor_desktop" ))
6265 return test_ClipCursor_desktop( argv );
6266 if (argc >= 3 && !strcmp( argv[2], "test_input_desktop" ))
6267 return test_input_desktop( argv );
6268
6269 run_in_desktop( argv, "test_input_desktop", 1 );
6270 test_keynames();
6271 test_key_map();
6273 test_ToAscii();
6282 test_rawinput(argv[0]);
6284
6285 if(pGetMouseMovePointsEx)
6287 else
6288 win_skip("GetMouseMovePointsEx is not available\n");
6289
6290 if(pGetRawInputDeviceList)
6292 else
6293 win_skip("GetRawInputDeviceList is not available\n");
6294
6295 if (pGetCurrentInputMessageSource)
6297 else
6298 win_skip("GetCurrentInputMessageSource is not available\n");
6299
6300 SetCursorPos( pos.x, pos.y );
6301
6302 if (pGetPointerType)
6304 else
6305 win_skip( "GetPointerType is not available\n" );
6306
6308
6309 if (!pEnableMouseInPointer)
6310 win_skip( "EnableMouseInPointer not found, skipping tests\n" );
6311 else
6312 {
6313 run_in_process( argv, "test_EnableMouseInPointer 0" );
6314 run_in_process( argv, "test_EnableMouseInPointer 1" );
6315 }
6316
6318}
BOOL fullscreen
Definition: 3dtext.c:43
std::map< E_MODULE, HMODULE > mod
Definition: LocaleTests.cpp:68
static int iteration
Definition: StackOverflow.c:18
@ lparam
Definition: SystemMenu.c:31
@ hook
Definition: SystemMenu.c:35
@ wparam
Definition: SystemMenu.c:30
#define expect(EXPECTED, GOT)
Definition: SystemMenu.c:483
unsigned char BOOLEAN
Definition: actypes.h:127
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
#define vsnprintf
Definition: acwin.h:106
static void startup(void)
#define GetNTVersion()
Definition: apitest.h:17
static int state
Definition: maze.c:121
#define InterlockedIncrement
Definition: armddk.h:53
static const char * wine_dbgstr_point(const POINT *ppt)
Definition: atltest.h:138
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
#define ok_(x1, x2)
Definition: atltest.h:61
#define msg(x)
Definition: auth_time.c:54
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:20
#define U(x)
Definition: wordpad.c:45
static INT max_size
Definition: history.c:51
static HANDLE thread
Definition: service.c:33
#define UlongToHandle(ul)
Definition: basetsd.h:91
#define HandleToUlong(h)
Definition: basetsd.h:73
#define LongToPtr(l)
Definition: basetsd.h:85
#define RegCloseKey(hKey)
Definition: registry.h:49
RECT rect
Definition: combotst.c:67
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
WORD ATOM
Definition: dimm.idl:113
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
LSTATUS WINAPI RegGetValueW(HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData)
Definition: reg.c:1931
LONG WINAPI RegOpenKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3268
LONG WINAPI RegEnumValueW(_In_ HKEY hKey, _In_ DWORD index, _Out_ LPWSTR value, _Inout_ PDWORD val_count, _Reserved_ PDWORD reserved, _Out_opt_ PDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ PDWORD count)
Definition: reg.c:2830
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
const char * wine_dbg_sprintf(const char *format,...)
Definition: compat.c:296
#define CDECL
Definition: compat.h:29
#define CloseHandle
Definition: compat.h:739
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define CP_ACP
Definition: compat.h:109
#define OPEN_EXISTING
Definition: compat.h:775
#define SetLastError(x)
Definition: compat.h:752
#define GetProcAddress(x, y)
Definition: compat.h:753
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define FreeLibrary(x)
Definition: compat.h:748
#define GetCurrentProcess()
Definition: compat.h:759
HANDLE HWND
Definition: compat.h:19
#define IsWow64Process
Definition: compat.h:760
#define MAX_PATH
Definition: compat.h:34
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define CreateFileW
Definition: compat.h:741
#define CALLBACK
Definition: compat.h:35
#define WideCharToMultiByte
Definition: compat.h:111
#define LoadLibraryW(x)
Definition: compat.h:747
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define FILE_SHARE_READ
Definition: compat.h:136
#define wcsicmp
Definition: compat.h:15
#define lstrlenW
Definition: compat.h:750
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4152
INT WINAPI GetLocaleInfoA(LCID lcid, LCTYPE lctype, LPSTR buffer, INT len)
Definition: locale.c:1609
LCID WINAPI GetUserDefaultLCID(void)
Definition: locale.c:1216
LCID lcid
Definition: locale.c:5656
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(const char *app_name, char *cmd_line, SECURITY_ATTRIBUTES *process_attr, SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags, void *env, const char *cur_dir, STARTUPINFOA *startup_info, PROCESS_INFORMATION *info)
Definition: process.c:686
ULONG WINAPI DECLSPEC_HOTPATCH GetTickCount(void)
Definition: sync.c:182
MonoAssembly int argc
Definition: metahost.c:107
unsigned short vk
Definition: console.c:118
_ACRTIMP int __cdecl swscanf(const wchar_t *, const wchar_t *,...)
Definition: scanf.c:438
_ACRTIMP __msvcrt_ulong __cdecl wcstoul(const wchar_t *, wchar_t **, int)
Definition: wcs.c:2912
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2983
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1972
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
#define va_end(v)
Definition: stdarg.h:28
#define va_start(v, l)
Definition: stdarg.h:26
_ACRTIMP __msvcrt_ulong __cdecl strtoul(const char *, char **, int)
Definition: string.c:1859
_ACRTIMP char *__cdecl strchr(const char *, int)
Definition: string.c:3286
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
_ACRTIMP size_t __cdecl strcspn(const char *, const char *)
Definition: string.c:3493
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
char * va_list
Definition: vadefs.h:50
#define swprintf
Definition: precomp.h:40
#define pt(x, y)
Definition: drawing.c:79
#define RGB(r, g, b)
Definition: precomp.h:67
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
r received
Definition: btrfs.c:3005
struct nls_table * tables
Definition: nls_base.c:22
#define INFINITE
Definition: serial.h:102
#define UlongToPtr(u)
Definition: config.h:106
static struct all_devices * devices
Definition: dsm_ctrl.c:48
POINTL point
Definition: edittest.c:50
#define ERROR(name)
Definition: error_private.h:53
static unsigned char buff[32768]
Definition: fatten.c:17
#define abs(i)
Definition: fconv.c:206
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
time_t now
Definition: finger.c:65
pKey DeleteObject()
GLuint start
Definition: gl.h:1545
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLclampf GLclampf GLclampf alpha
Definition: gl.h:1740
GLdouble s
Definition: gl.h:2039
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
struct _cl_event * event
Definition: glext.h:7739
GLdouble n
Definition: glext.h:7729
GLuint res
Definition: glext.h:9613
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLuint color
Definition: glext.h:6243
const GLubyte * c
Definition: glext.h:8905
GLuint index
Definition: glext.h:6031
GLenum const GLfloat * params
Definition: glext.h:5645
GLuint in
Definition: glext.h:9616
GLint left
Definition: glext.h:7726
GLbitfield flags
Definition: glext.h:7161
GLuint64EXT * result
Definition: glext.h:11304
GLboolean enable
Definition: glext.h:11120
GLfloat param
Definition: glext.h:5796
GLenum GLsizei len
Definition: glext.h:6722
GLenum GLenum GLenum input
Definition: glext.h:9031
GLuint id
Definition: glext.h:5910
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 const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
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 const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
HIDAPI BOOLEAN WINAPI HidD_GetPreparsedData(IN HANDLE HidDeviceObject, OUT PHIDP_PREPARSED_DATA *PreparsedData)
Definition: hid.c:290
HIDAPI BOOLEAN WINAPI HidD_FreePreparsedData(IN PHIDP_PREPARSED_DATA PreparsedData)
Definition: hid.c:139
struct _HIDP_PREPARSED_DATA * PHIDP_PREPARSED_DATA
Definition: hidpi.h:39
#define HID_USAGE_GENERIC_GAMEPAD
Definition: hidusage.h:35
#define HID_USAGE_GENERIC_MOUSE
Definition: hidusage.h:33
#define HID_USAGE_PAGE_GENERIC
Definition: hidusage.h:176
#define HID_USAGE_GENERIC_KEYBOARD
Definition: hidusage.h:36
#define HID_USAGE_GENERIC_JOYSTICK
Definition: hidusage.h:34
static TfClientId tid
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
#define LOBYTE(W)
Definition: jmemdos.c:487
#define KLLF_ALTGR
Definition: kbd.h:91
#define c
Definition: ke_i.h:80
#define debugstr_w
Definition: kernel32.h:32
#define wine_dbgstr_w
Definition: kernel32.h:34
#define REG_SZ
Definition: layer.c:22
USHORT LANGID
Definition: mui.h:9
const char * winetest_platform
int winetest_debug
#define win_skip
Definition: minitest.h:67
#define todo_wine_if(is_todo)
Definition: minitest.h:81
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl void winetest_pop_context(void)
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl winetest_push_context(const char *fmt,...) __WINE_PRINTF_ATTR(1
Definition: test.h:537
#define todo_wine
Definition: minitest.h:80
LONG_PTR LPARAM
Definition: minwindef.h:175
LONG_PTR LRESULT
Definition: minwindef.h:176
UINT_PTR WPARAM
Definition: minwindef.h:174
__u16 time
Definition: mkdosfs.c:8
#define sprintf
Definition: sprintf.c:45
HDC hdc
Definition: main.c:9
HANDLE events[2]
Definition: event.c:4
#define expect_rect(r, _left, _top, _right, _bottom)
Definition: combo.c:42
static HDC
Definition: imagelist.c:88
BOOL todo
Definition: filedlg.c:313
BOOL expected
Definition: store.c:2000
static va_list valist
Definition: printf.c:46
static DWORD thread_id
Definition: protocol.c:159
static WNDPROC old_proc
Definition: clipboard.c:236
#define KEY_MSG_(m, s, v, f,...)
static void test_key_names(void)
Definition: input.c:3876
static const char * debugstr_vk(UINT vkey)
Definition: input.c:202
static void test_keynames(void)
Definition: input.c:1465
#define ok_rect(e, r)
Definition: input.c:113
static void test_ClipCursor(char **argv)
Definition: input.c:5858
HWND create_foreground_window_(const char *file, int line, BOOL fullscreen, UINT retries)
Definition: input.c:583
static int ok_call_(const char *file, int line, const struct user_call *expected, const struct user_call *received)
Definition: input.c:223
static void test_UnregisterDeviceNotification(void)
Definition: input.c:5312
static void check_keyboard_async_(int line, const BYTE expect_state[256], const BOOL todo_state[256])
Definition: input.c:693
#define check_get_key_state(i, j, c, x)
Definition: input.c:4954
#define MS_HOOK(m, x, y,...)
static LRESULT CALLBACK mouse_layered_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
Definition: input.c:4003
static void test_ActivateKeyboardLayout(char **argv)
Definition: input.c:3742
static POINTER_INPUT_TYPE *static POINTER_INFO *static UINT32 POINTER_INFO *static UINT32 POINTER_INFO *static UINT32 UINT32 POINTER_INFO *static int
Definition: input.c:445
static const char * debugstr_ok(const char *cond)
Definition: input.c:87
static LRESULT WINAPI msg_source_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
Definition: input.c:5185
static HANDLE ll_keyboard_event
Definition: input.c:6041
static LRESULT CALLBACK ll_keyboard_event_wait(int code, WPARAM wparam, LPARAM lparam)
Definition: input.c:6043
static const struct tounicode_tests utests[]
static int got_setfocus
Definition: input.c:3699
static BOOL rawinput_test_received_raw
Definition: input.c:2712
static DWORD CALLBACK test_GetPointerInfo_thread(void *arg)
Definition: input.c:5468
static void append_ll_hook_ms(UINT msg, const MSLLHOOKSTRUCT *info)
Definition: input.c:375
#define ok_seq(a)
Definition: input.c:326
user_function
Definition: input.c:128
@ LL_HOOK_MOUSE
Definition: input.c:131
@ LL_HOOK_KEYBD
Definition: input.c:130
@ RAW_INPUT_KEYBOARD
Definition: input.c:132
@ MSG_TEST_WIN
Definition: input.c:129
static void append_ll_hook_kbd(UINT msg, const KBDLLHOOKSTRUCT *info)
Definition: input.c:357
static BOOL accept_keyboard_messages_raw(UINT msg)
Definition: input.c:1478
#define KEY_HOOK(m, s, v,...)
static void empty_message_queue(void)
Definition: input.c:619
static DWORD WINAPI get_key_state_thread(void *arg)
Definition: input.c:4968
static DWORD WINAPI rawinput_test_thread(void *arg)
Definition: input.c:2975
#define create_foreground_window(a)
Definition: input.c:582
static BOOL wait_for_event(HANDLE event, int timeout)
Definition: input.c:3935
static const char * debugstr_wm(UINT msg)
Definition: input.c:182
static BOOL accept_mouse_messages_nomove(UINT msg)
Definition: input.c:4080
static PUINT
Definition: input.c:446
#define ok_ret(e, r)
Definition: input.c:125
static void rawinput_test_process(void)
Definition: input.c:2793
static LRESULT CALLBACK ll_hook_kbd_proc(int code, WPARAM wparam, LPARAM lparam)
Definition: input.c:654
static LRESULT CALLBACK httransparent_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
Definition: input.c:3951
static LRESULT CALLBACK rawinput_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
Definition: input.c:2715
static BOOL is_mouse_message(UINT message)
Definition: input.c:577
static BOOL is_keyboard_message(UINT message)
Definition: input.c:572
static LRESULT CALLBACK append_message_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
Definition: input.c:428
struct rawinput_test rawinput_tests[]
Definition: input.c:2763
static void test_SendInput_raw_key_messages(WORD vkey, WORD wch, HKL hkl)
Definition: input.c:1483
static void check_get_key_state_(int i, int j, int c, int x, int line)
Definition: input.c:4955
static void test_keyboard_layout_name(void)
Definition: input.c:3544
static DWORD WINAPI thread_proc(void *param)
Definition: input.c:4609
static void test_ClipCursor_desktop(char **argv)
Definition: input.c:5802
static void init_function_pointers(void)
Definition: input.c:456
static LRESULT CALLBACK mouse_move_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
Definition: input.c:3984
#define check_keyboard_async(a, b)
Definition: input.c:692
#define MYERROR
static BOOL(* p_accept_message)(UINT msg)
Definition: input.c:355
static HKL expect_hkl
Definition: input.c:3697
static void run_in_desktop_(const char *file, int line, char **argv, const char *args, BOOL input)
Definition: input.c:505
static void test_input_message_source(void)
Definition: input.c:5228
static void test_attach_input(void)
Definition: input.c:4655
static void test_ClipCursor_dirty(const char *arg)
Definition: input.c:5706
static void check_get_keyboard_state_(int i, int j, int c, int x, int line)
Definition: input.c:4935
#define menu
Definition: input.c:3282
static void test_SetCursorPos(void)
Definition: input.c:5882
static BOOL is_wow64
Definition: input.c:454
#define check_keyboard_state(a, b)
Definition: input.c:677
static void test_GetRawInputBuffer(void)
Definition: input.c:2441
static void test_GetKeyState(void)
Definition: input.c:5031
static BOOL rawinput_test_received_legacy
Definition: input.c:2711
static void UINT *static void UINT *static PBOOL
Definition: input.c:449
struct get_key_state_test_desc get_key_state_tests[]
Definition: input.c:4896
static DWORD CALLBACK test_ActivateKeyboardLayout_thread_proc(void *arg)
Definition: input.c:3736
#define check_send_input_keyboard_test(a, b)
Definition: input.c:732
static void test_RegisterRawInputDevices(void)
Definition: input.c:2130
static BOOL append_message_hwnd
Definition: input.c:354
#define run_in_process(a, b)
Definition: input.c:486
static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
Definition: input.c:4588
static INPUT_MESSAGE_SOURCE expect_src
Definition: input.c:5183
static void test_keyboard_ll_hook_blocking(void)
Definition: input.c:6054
static DWORD WINAPI create_transparent_window_thread(void *arg)
Definition: input.c:3965
static void test_LoadKeyboardLayoutEx(HKL orig_hkl)
Definition: input.c:6078
#define ok_point(e, r)
Definition: input.c:119
static void test_SendInput_keyboard_messages(WORD vkey, WORD scan, WCHAR wch, WCHAR wch_shift, WCHAR wch_control, HKL hkl)
Definition: input.c:824
static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
Definition: input.c:2299
#define check_get_keyboard_state(i, j, c, x)
Definition: input.c:4934
static LRESULT CALLBACK ll_hook_setpos_proc(int code, WPARAM wparam, LPARAM lparam)
Definition: input.c:4044
static void test_GetRawInputDeviceList(void)
Definition: input.c:1942
static void clear_keyboard_state(void)
Definition: input.c:708
#define shift
Definition: input.c:3280
static void get_test_scan(WORD vkey, WORD *scan, WCHAR *wch, WCHAR *wch_shift)
Definition: input.c:812
static void test_SendInput(WORD vkey, WCHAR wch, HKL hkl)
Definition: input.c:5318
static HKL * get_keyboard_layouts(UINT *count)
Definition: input.c:3530
static LRESULT CALLBACK ll_hook_ms_proc(int code, WPARAM wparam, LPARAM lparam)
Definition: input.c:4037
static void test_keyboard_layout(void)
Definition: input.c:6213
static void test_EnableMouseInPointer(const char *arg)
Definition: input.c:5660
static BOOL rawinput_test_received_rawfg
Definition: input.c:2713
static void test_OemKeyScan(void)
Definition: input.c:5142
#define GET_PROC(func)
#define DESKTOP_ALL_ACCESS
Definition: input.c:435
#define KEY_HOOK_(m, s, v, f,...)
static void test_SendInput_mouse_messages(void)
Definition: input.c:4085
static BOOL CALLBACK get_virtual_screen_proc(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM lp)
Definition: input.c:5692
static void check_pointer_info_(int line, const POINTER_INFO *actual, const POINTER_INFO *expected)
Definition: input.c:5444
static HKL change_hkl
Definition: input.c:3698
static void ok_seq_(const char *file, int line, const struct user_call *expected, const char *context)
Definition: input.c:327
static void simulate_click(BOOL left, int x, int y)
Definition: input.c:3916
static LRESULT CALLBACK ll_hook_getpos_proc(int code, WPARAM wparam, LPARAM lparam)
Definition: input.c:4066
static void test_ClipCursor_process(void)
Definition: input.c:5749
#define wait_messages(a, b)
Definition: input.c:546
#define msg_wait_for_events(a, b, c)
Definition: input.c:547
static BOOL keyboard_layout_has_altgr(void)
Definition: input.c:767
static void test_GetRawInputData(void)
Definition: input.c:2120
static void check_keyboard_state_(int line, const BYTE expect_state[256], const BOOL todo_state[256])
Definition: input.c:678
#define ok_ne(e, r, t, f,...)
Definition: input.c:107
static BOOL accept_keyboard_messages_syscommand(UINT msg)
Definition: input.c:762
static void test_get_async_key_state(void)
Definition: input.c:3523
static LONG current_sequence_len
Definition: input.c:180
static struct user_call current_sequence[1024]
Definition: input.c:179
static int rawinputbuffer_wndproc_count
Definition: input.c:2266
static void run_in_process_(const char *file, int line, char **argv, const char *args)
Definition: input.c:487
#define check_pointer_info(a, b)
Definition: input.c:5443
#define check_member(val, exp, fmt, member)
Definition: input.c:84
static const struct user_call empty_sequence[]
Definition: input.c:178
static void append_rawinput_message(HWND hwnd, WPARAM wparam, HRAWINPUT handle)
Definition: input.c:393
#define ok_eq(e, r, t, f,...)
Definition: input.c:101
static DWORD WINAPI rawinput_test_desk_thread(void *arg)
Definition: input.c:2909
static void test_key_map(void)
Definition: input.c:3218
RECT get_virtual_screen_rect(void)
Definition: input.c:5699
static void test_ToAscii(void)
Definition: input.c:3451
static void test_ToUnicode(void)
Definition: input.c:3377
static LRESULT CALLBACK test_ActivateKeyboardLayout_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
Definition: input.c:3701
#define run_in_desktop(a, b, c)
Definition: input.c:504
static DWORD CALLBACK test_ClipCursor_thread(void *arg)
Definition: input.c:5718
static void test_DefRawInputProc(void)
Definition: input.c:3199
static POINTER_INPUT_TYPE *static POINTER_INFO *static UINT32 POINTER_INFO *static UINT32 POINTER_INFO *static UINT32 UINT32 POINTER_INFO *static LPMOUSEMOVEPOINT
Definition: input.c:445
static void test_rawinput(const char *argv0)
Definition: input.c:3027
#define WIN_MSG(m, w, l,...)
#define KEY_MSG(m, s, v,...)
static void test_input_desktop(char **argv)
Definition: input.c:6185
static void check_send_input_keyboard_test_(const struct send_input_keyboard_test *test, const char *context, BOOL peeked)
Definition: input.c:733
#define ctrl
Definition: input.c:3281
static void test_GetPointerInfo(BOOL mouse_in_pointer_enabled)
Definition: input.c:5487
static void append_message(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
Definition: input.c:415
static DWORD msg_wait_for_events_(const char *file, int line, DWORD count, HANDLE *events, DWORD timeout, BOOL append_peeked)
Definition: input.c:548
static void test_GetMouseMovePointsEx(char **argv)
Definition: input.c:1621
#define RAW_KEY(s, f, v, m,...)
static void test_GetMouseMovePointsEx_process(void)
Definition: input.c:1847
#define BUFLIM
static POINTER_INPUT_TYPE *static POINTER_INFO *static UINT32 POINTER_INFO *static UINT32 POINTER_INFO *static UINT32 UINT32 POINTER_INFO *static DWORD
Definition: input.c:445
static MONITORINFO mi
Definition: win.c:9400
#define min(a, b)
Definition: monoChain.cc:55
#define argv
Definition: mplay32.c:18
int other
Definition: msacm.c:1376
HKL hkl
Definition: msctf.idl:632
UINT_PTR HKL
Definition: msctf.idl:125
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
HMONITOR WINAPI MonitorFromWindow(HWND, DWORD)
unsigned int UINT
Definition: ndis.h:50
HANDLE hThread
Definition: wizard.c:28
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define BOOL
Definition: nt_native.h:43
#define MOUSE_MOVE_ABSOLUTE
Definition: ntddmou.h:68
#define MOUSE_VIRTUAL_DESKTOP
Definition: ntddmou.h:69
#define WINSTA_ALL_ACCESS
Definition: om.c:2279
#define LOWORD(l)
Definition: pedump.c:82
#define WS_CHILD
Definition: pedump.c:617
#define WS_OVERLAPPEDWINDOW
Definition: pedump.c:637
#define WS_OVERLAPPED
Definition: pedump.c:615
short WCHAR
Definition: pedump.c:58
#define WS_POPUP
Definition: pedump.c:616
#define WS_VISIBLE
Definition: pedump.c:620
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
char CHAR
Definition: pedump.c:57
struct _STARTUPINFOA STARTUPINFOA
#define err(...)
#define calloc
Definition: rosglue.h:14
#define test
Definition: rosglue.h:37
const WCHAR * str
#define offsetof(TYPE, MEMBER)
#define LANG_CHINESE
Definition: nls.h:42
DWORD LCID
Definition: nls.h:13
#define LANG_JAPANESE
Definition: nls.h:76
#define PRIMARYLANGID(l)
Definition: nls.h:16
#define LANG_KOREAN
Definition: nls.h:84
wcscat
wcscpy
strcpy
Definition: string.h:131
#define flaky_wine
Definition: test.h:165
int winetest_get_mainargs(char ***pargv)
void winetest_wait_child_process(HANDLE process)
#define flaky
Definition: test.h:164
#define wait_child_process
Definition: test.h:159
#define memset(x, y, z)
Definition: compat.h:39
#define _WIN32_WINNT_VISTA
Definition: sdkddkver.h:25
static PVOID hdll
Definition: shimdbg.c:126
static char argv0[MAX_PATH]
Definition: shlexec.c:49
DWORD dwTime
Definition: solitaire.cpp:27
TCHAR * cmdline
Definition: stretchblt.cpp:32
union RAWINPUT64::@1882 data
RAWMOUSE mouse
Definition: input.c:2292
RAWKEYBOARD keyboard
Definition: input.c:2293
RAWINPUTHEADER64 header
Definition: input.c:2290
RAWHID hid
Definition: input.c:2294
ULONG hDevice
Definition: input.c:2272
ULONG wParam
Definition: input.c:2273
DWORD dwType
Definition: input.c:2270
DWORD dwSize
Definition: input.c:2271
DWORD dwType
Definition: input.c:2282
ULONGLONG hDevice
Definition: input.c:2284
ULONGLONG wParam
Definition: input.c:2285
DWORD dwSize
Definition: input.c:2283
Definition: kbd.h:95
LONG y
Definition: windef.h:130
LONG x
Definition: windef.h:129
HBRUSH hbrBackground
Definition: winuser.h:3278
HICON hIcon
Definition: winuser.h:3276
HINSTANCE hInstance
Definition: winuser.h:3275
HCURSOR hCursor
Definition: winuser.h:3277
int cbWndExtra
Definition: winuser.h:3274
UINT style
Definition: winuser.h:3271
LPCSTR lpszMenuName
Definition: winuser.h:3279
LPCSTR lpszClassName
Definition: winuser.h:3280
WNDPROC lpfnWndProc
Definition: winuser.h:3272
int cbClsExtra
Definition: winuser.h:3273
WNDPROC lpfnWndProc
Definition: winuser.h:3285
Definition: match.c:390
Definition: inflate.c:139
Definition: http.c:7252
Definition: dialog.c:52
Definition: fci.c:127
Definition: format.c:58
BOOL set_keyboard_state_main
Definition: input.c:4892
Definition: parser.c:49
Definition: tftpd.h:60
Definition: name.c:39
BOOL register_window
Definition: input.c:2753
BOOL todo_raw
Definition: input.c:2759
BOOL todo_legacy
Definition: input.c:2758
BOOL expect_raw
Definition: input.c:2756
BOOL todo_rawfg
Definition: input.c:2760
BOOL expect_legacy
Definition: input.c:2755
BOOL expect_rawfg
Definition: input.c:2757
DWORD register_flags
Definition: input.c:2754
BOOL register_device
Definition: input.c:2752
BOOL todo_state[256]
Definition: input.c:648
struct user_call expect[8]
Definition: input.c:646
BOOL todo_async[256]
Definition: input.c:651
BYTE expect_async[256]
Definition: input.c:650
BYTE expect_state[256]
Definition: input.c:647
struct user_call expect[8]
Definition: input.c:4032
BOOL todo_state[256]
Definition: input.c:4034
BYTE expect_state[256]
Definition: input.c:4033
ULONG_PTR extra
Definition: input.c:4031
Definition: ps.c:97
KEYBDINPUT ki
Definition: winable.h:62
DWORD type
Definition: winable.h:59
ULONG_PTR dwExtraInfo
Definition: winuser.h:3920
DWORD dwFlags
Definition: winable.h:49
WORD wVk
Definition: winable.h:47
WORD wScan
Definition: winable.h:48
ULONG_PTR dwExtraInfo
Definition: winable.h:51
DWORD time
Definition: winable.h:50
RECT rcMonitor
Definition: winuser.h:3893
DWORD cbSize
Definition: winuser.h:3892
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
LONG right
Definition: windef.h:108
LONG bottom
Definition: windef.h:109
LONG top
Definition: windef.h:107
LONG left
Definition: windef.h:106
Definition: dhcpd.h:248
WCHAR expect_buf[4]
Definition: input.c:3290
DWORD modifiers
Definition: input.c:3287
int expect_ret
Definition: input.c:3289
UINT vkey
Definition: input.c:152
UINT data
Definition: input.c:160
UINT scan
Definition: input.c:151
HWND hwnd
Definition: input.c:143
UINT flags
Definition: input.c:153
struct user_call::@1876::@1879 ll_hook_kbd
BOOL broken
Definition: input.c:175
UINT_PTR extra
Definition: input.c:154
LPARAM lparam
Definition: input.c:146
struct user_call::@1876::@1880 ll_hook_ms
UINT time
Definition: input.c:162
POINT point
Definition: input.c:159
struct user_call::@1876::@1881 raw_input
UINT msg
Definition: input.c:144
struct user_call::@1876::@1878 message
WPARAM wparam
Definition: input.c:145
BOOL todo_value
Definition: input.c:174
BYTE code
Definition: input.c:168
BOOL todo
Definition: input.c:173
enum user_function func
Definition: input.c:137
RAWKEYBOARD kbd
Definition: input.c:169
DWORD attach_from
Definition: input.c:4604
HANDLE wait_event
Definition: input.c:4602
HWND hwnd
Definition: input.c:4601
HANDLE start_event
Definition: input.c:4603
BOOL setWindows
Definition: input.c:4606
DWORD attach_to
Definition: input.c:4605
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:726
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCSTR lpName OPTIONAL)
Definition: synch.c:573
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:587
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:669
HANDLE WINAPI DECLSPEC_HOTPATCH OpenEventA(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCSTR lpName)
Definition: synch.c:605
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:650
BOOL WINAPI DECLSPEC_HOTPATCH ReleaseSemaphore(IN HANDLE hSemaphore, IN LONG lReleaseCount, IN LPLONG lpPreviousCount)
Definition: synch.c:491
HANDLE WINAPI DECLSPEC_HOTPATCH CreateSemaphoreA(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL, IN LONG lInitialCount, IN LONG lMaximumCount, IN LPCSTR lpName OPTIONAL)
Definition: synchansi.c:44
#define GWLP_WNDPROC
Definition: treelist.c:66
#define DWORD_PTR
Definition: treelist.c:76
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
const char * LPCSTR
Definition: typedefs.h:52
const uint16_t * LPCWSTR
Definition: typedefs.h:57
PVOID HANDLE
Definition: typedefs.h:73
uint64_t ULONGLONG
Definition: typedefs.h:67
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define MAKELONG(a, b)
Definition: typedefs.h:249
uint32_t UINT32
Definition: typedefs.h:59
uint32_t ULONG
Definition: typedefs.h:59
#define HIWORD(l)
Definition: typedefs.h:247
Definition: pdh_main.c:96
static BOOL keystate[LAST_MODIFIER - FIRST_MODIFIER]
Definition: vnc.c:133
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
int retval
Definition: wcstombs.cpp:91
HDESK WINAPI CreateDesktopA(LPCSTR lpszDesktop, LPCSTR lpszDevice, LPDEVMODEA pDevmode, DWORD dwFlags, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa)
Definition: desktop.c:431
BOOL WINAPI UnregisterDeviceNotification(HDEVNOTIFY Handle)
Definition: resources.c:162
UINT WINAPI DECLSPEC_HOTPATCH GetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize, UINT cbSizeHeader)
Definition: stubs.c:299
UINT WINAPI DECLSPEC_HOTPATCH GetRegisteredRawInputDevices(PRAWINPUTDEVICE pRawInputDevices, PUINT puiNumDevices, UINT cbSize)
Definition: stubs.c:349
BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(PCRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize)
Definition: stubs.c:364
UINT WINAPI GetRawInputDeviceInfoA(HANDLE hDevice, UINT uiCommand, LPVOID pData, PUINT pcbSize)
Definition: stubs.c:257
UINT WINAPI GetRawInputDeviceInfoW(HANDLE hDevice, UINT uiCommand, LPVOID pData, PUINT pcbSize)
Definition: stubs.c:225
UINT WINAPI GetRawInputData(HRAWINPUT hRawInput, UINT uiCommand, LPVOID pData, PUINT pcbSize, UINT cbSizeHeader)
Definition: stubs.c:313
LRESULT WINAPI DefRawInputProc(PRAWINPUT *paRawInput, INT nInput, UINT cbSizeHeader)
Definition: stubs.c:283
UINT WINAPI GetRawInputDeviceList(PRAWINPUTDEVICELIST pRawInputDeviceList, PUINT puiNumDevices, UINT cbSize)
Definition: stubs.c:329
HKL WINAPI LoadKeyboardLayoutEx(HKL hklUnload, LPCWSTR pwszKLID, UINT Flags)
Definition: input.c:837
int WINAPI GetWindowRgnBox(HWND hWnd, LPRECT lprc)
Definition: paint.c:299
BOOL WINAPI GetPointerType(UINT32 id, POINTER_INPUT_TYPE *type)
Definition: misc.c:608
BOOL WINAPI GetPointerInfo(UINT32 id, POINTER_INFO *info)
Definition: misc.c:622
int codepage
Definition: win_iconv.c:156
#define INPUT_HARDWARE
Definition: winable.h:11
UINT WINAPI SendInput(UINT, LPINPUT, int)
Definition: ntwrapper.h:344
#define INPUT_KEYBOARD
Definition: winable.h:10
#define INPUT_MOUSE
Definition: winable.h:9
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define STARTF_USESHOWWINDOW
Definition: winbase.h:468
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
HWINSTA WINAPI GetProcessWindowStation(void)
Definition: ntwrapper.h:124
#define WAIT_OBJECT_0
Definition: winbase.h:383
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
void * arg
Definition: msvc.h:10
#define WINAPI
Definition: msvc.h:6
#define ERROR_POINT_NOT_FOUND
Definition: winerror.h:1017
#define ERROR_NOACCESS
Definition: winerror.h:902
HGDIOBJ WINAPI GetStockObject(_In_ int)
HRGN WINAPI CreateRectRgn(_In_ int, _In_ int, _In_ int, _In_ int)
#define WHITE_BRUSH
Definition: wingdi.h:902
#define SIMPLEREGION
Definition: wingdi.h:362
int WINAPI FillRect(HDC, LPCRECT, HBRUSH)
HBRUSH WINAPI CreateSolidBrush(_In_ COLORREF)
BOOL WINAPI TranslateCharsetInfo(_Inout_ PDWORD, _Out_ LPCHARSETINFO, _In_ DWORD)
#define TCI_SRCCODEPAGE
Definition: wingdi.h:962
#define LOCALE_IDEFAULTANSICODEPAGE
Definition: winnls.h:45
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_USER
Definition: winreg.h:11
#define RRF_RT_REG_SZ
Definition: winreg.h:58
#define SW_SHOWNORMAL
Definition: winuser.h:781
#define WM_PAINT
Definition: winuser.h:1648
HWND WINAPI GetFocus(void)
Definition: window.c:1863
HWND WINAPI SetCapture(_In_ HWND hWnd)
LRESULT WINAPI DispatchMessageA(_In_ const MSG *)
BOOL WINAPI GetKeyboardLayoutNameW(_Out_writes_(KL_NAMELENGTH) LPWSTR)
#define MOUSEEVENTF_ABSOLUTE
Definition: winuser.h:1205
#define SetWindowLongPtrA
Definition: winuser.h:5511
HWND WINAPI GetActiveWindow(void)
Definition: winpos.c:138
BOOL WINAPI SetDoubleClickTime(_In_ UINT)
HKL WINAPI GetKeyboardLayout(_In_ DWORD)
#define VK_NUMPAD3
Definition: winuser.h:2278
#define WM_INPUT_DEVICE_CHANGE
Definition: winuser.h:1739
#define WM_SYSCOMMAND
Definition: winuser.h:1769
BOOL WINAPI RedrawWindow(_In_opt_ HWND, _In_opt_ LPCRECT, _In_opt_ HRGN, _In_ UINT)
void WINAPI mouse_event(_In_ DWORD, _In_ DWORD, _In_ DWORD, _In_ DWORD, _In_ ULONG_PTR)
#define SC_KEYMENU
Definition: winuser.h:2632
#define VK_TAB
Definition: winuser.h:2235
#define WM_MOUSEFIRST
Definition: winuser.h:1802
#define SWP_FRAMECHANGED
Definition: winuser.h:1251
#define WM_QUIT
Definition: winuser.h:1651
BOOL WINAPI GetKeyboardLayoutNameA(_Out_writes_(KL_NAMELENGTH) LPSTR)
BOOL WINAPI SetKeyboardState(_In_reads_(256) LPBYTE)
BOOL WINAPI TranslateMessage(_In_ const MSG *)
#define WM_KEYUP
Definition: winuser.h:1744
HWND WINAPI CreateWindowExA(_In_ DWORD dwExStyle, _In_opt_ LPCSTR lpClassName, _In_opt_ LPCSTR lpWindowName, _In_ DWORD dwStyle, _In_ int X, _In_ int Y, _In_ int nWidth, _In_ int nHeight, _In_opt_ HWND hWndParent, _In_opt_ HMENU hMenu, _In_opt_ HINSTANCE hInstance, _In_opt_ LPVOID lpParam)
#define COLOR_WINDOW
Definition: winuser.h:929
BOOL WINAPI ShowWindow(_In_ HWND, _In_ int)
#define WM_MOUSELAST
Definition: winuser.h:1829
#define LLKHF_EXTENDED
Definition: winuser.h:2687
UINT WINAPI MapVirtualKeyExA(_In_ UINT, _In_ UINT, _In_opt_ HKL)
DWORD WINAPI GetMessagePos(void)
Definition: message.c:1351
BOOL WINAPI UnregisterClassA(_In_ LPCSTR, HINSTANCE)
BOOL WINAPI GetClipCursor(_Out_ LPRECT)
HWND WINAPI GetForegroundWindow(void)
Definition: ntwrapper.h:392
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
BOOL WINAPI SwitchDesktop(_In_ HDESK)
#define MOUSEEVENTF_LEFTUP
Definition: winuser.h:1196
#define HWND_TOPMOST
Definition: winuser.h:1219
BOOL WINAPI AttachThreadInput(_In_ DWORD, _In_ DWORD, _In_ BOOL)
#define KL_NAMELENGTH
Definition: winuser.h:122
#define VK_NUMPAD1
Definition: winuser.h:2276
int WINAPI GetKeyNameTextA(_In_ LONG lParam, _Out_writes_(cchSize) LPSTR lpString, _In_ int cchSize)
LRESULT WINAPI DefWindowProcA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
BOOL WINAPI SetThreadDesktop(_In_ HDESK)
#define GET_RAWINPUT_CODE_WPARAM(wParam)
Definition: winuser.h:2877
#define CreateWindowA(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4469
BOOL WINAPI GetWindowRect(_In_ HWND, _Out_ LPRECT)
HHOOK WINAPI SetWindowsHookExW(_In_ int, _In_ HOOKPROC, _In_opt_ HINSTANCE, _In_ DWORD)
BOOL WINAPI SetWindowPos(_In_ HWND, _In_opt_ HWND, _In_ int, _In_ int, _In_ int, _In_ int, _In_ UINT)
#define VK_NUMPAD2
Definition: winuser.h:2277
UINT WINAPI MapVirtualKeyExW(_In_ UINT, _In_ UINT, _In_opt_ HKL)
#define VK_SPACE
Definition: winuser.h:2255
#define KLF_ACTIVATE
Definition: winuser.h:111
int WINAPI SetWindowRgn(_In_ HWND, _In_opt_ HRGN, _In_ BOOL)
HDESK WINAPI OpenInputDesktop(_In_ DWORD, _In_ BOOL, _In_ DWORD)
LONG WINAPI SetWindowLongW(_In_ HWND, _In_ int, _In_ LONG)
LONG WINAPI GetWindowLongW(_In_ HWND, _In_ int)
#define VK_CAPITAL
Definition: winuser.h:2242
#define WM_LBUTTONDBLCLK
Definition: winuser.h:1806
int WINAPI ToAscii(_In_ UINT, _In_ UINT, _In_reads_opt_(256) CONST BYTE *, _Out_ LPWORD, _In_ UINT)
BOOL WINAPI ClipCursor(_In_opt_ LPCRECT)
#define SWP_NOMOVE
Definition: winuser.h:1255
#define MAPVK_VSC_TO_VK_EX
Definition: winuser.h:2394
#define VK_NUMPAD4
Definition: winuser.h:2279
#define KF_ALTDOWN
Definition: winuser.h:2485
#define VK_SCROLL
Definition: winuser.h:2316
ATOM WINAPI RegisterClassW(_In_ CONST WNDCLASSW *)
BOOL WINAPI SetForegroundWindow(_In_ HWND)
#define RIDEV_NOLEGACY
Definition: winuser.h:2963
#define KF_EXTENDED
Definition: winuser.h:2482
#define IDC_ARROW
Definition: winuser.h:695
#define WM_KEYFIRST
Definition: winuser.h:1742
#define VK_CONTROL
Definition: winuser.h:2239
BOOL WINAPI GetCursorPos(_Out_ LPPOINT)
Definition: cursoricon.c:3064
#define HC_ACTION
Definition: winuser.h:48
#define WM_NCHITTEST
Definition: winuser.h:1714
#define WM_RBUTTONUP
Definition: winuser.h:1808
#define VK_RSHIFT
Definition: winuser.h:2319
#define VK_UP
Definition: winuser.h:2261
LRESULT WINAPI SendMessageA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define WM_SETFOCUS
Definition: winuser.h:1641
#define QS_ALLINPUT
Definition: winuser.h:914
BOOL WINAPI EnumDisplayMonitors(_In_opt_ HDC, _In_opt_ LPCRECT, _In_ MONITORENUMPROC, _In_ LPARAM)
int WINAPI ToUnicode(_In_ UINT wVirtKey, _In_ UINT wScanCode, _In_reads_bytes_opt_(256) CONST BYTE *lpKeyState, _Out_writes_(cchBuff) LPWSTR pwszBuff, _In_ int cchBuff, _In_ UINT wFlags)
HWINSTA WINAPI CreateWindowStationA(_In_opt_ LPCSTR lpwinsta, _In_ DWORD dwFlags, _In_ ACCESS_MASK dwDesiredAccess, _In_opt_ LPSECURITY_ATTRIBUTES lpsa)
#define SWP_NOSIZE
Definition: winuser.h:1256
BOOL WINAPI CloseWindowStation(_In_ HWINSTA)
#define WM_MOUSEMOVE
Definition: winuser.h:1803
#define MOUSEEVENTF_RIGHTUP
Definition: winuser.h:1198
#define WM_INPUT
Definition: winuser.h:1740
#define RDW_ERASE
Definition: winuser.h:1222
_Check_return_ BOOL WINAPI GetKeyboardState(_Out_writes_(256) PBYTE lpKeyState)
#define VK_LSHIFT
Definition: winuser.h:2318
#define WM_LBUTTONDOWN
Definition: winuser.h:1804
BOOL WINAPI SetCursorPos(_In_ int, _In_ int)
Definition: cursoricon.c:3056
HCURSOR WINAPI LoadCursorW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
Definition: cursoricon.c:2474
#define VK_LCONTROL
Definition: winuser.h:2320
#define VK_NUMPAD0
Definition: winuser.h:2275
#define LLKHF_ALTDOWN
Definition: winuser.h:2689
DWORD WINAPI MsgWaitForMultipleObjects(_In_ DWORD nCount, _In_reads_opt_(nCount) CONST HANDLE *pHandles, _In_ BOOL fWaitAll, _In_ DWORD dwMilliseconds, _In_ DWORD dwWakeMask)
BOOL WINAPI SetProcessWindowStation(_In_ HWINSTA)
int WINAPI MapWindowPoints(_In_opt_ HWND hWndFrom, _In_opt_ HWND hWndTo, _Inout_updates_(cPoints) LPPOINT lpPoints, _In_ UINT cPoints)
UINT WINAPI GetDoubleClickTime(void)
Definition: ntwrapper.h:314
#define VK_NUMPAD6
Definition: winuser.h:2281
#define MAPVK_VSC_TO_VK
Definition: winuser.h:2392
#define VK_NEXT
Definition: winuser.h:2257
#define VK_RCONTROL
Definition: winuser.h:2321
#define WM_RBUTTONDOWN
Definition: winuser.h:1807
#define MOUSEEVENTF_MOVE
Definition: winuser.h:1194
#define KF_UP
Definition: winuser.h:2487
UINT WINAPI MapVirtualKeyW(_In_ UINT, _In_ UINT)
#define WH_MOUSE_LL
Definition: winuser.h:44
#define MOUSEEVENTF_LEFTDOWN
Definition: winuser.h:1195
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
#define WM_SYSCHAR
Definition: winuser.h:1749
ATOM WINAPI RegisterClassA(_In_ CONST WNDCLASSA *)
BOOL WINAPI OemToCharBuffW(_In_ LPCSTR lpszSrc, _Out_writes_(cchDstLength) LPWSTR lpszDst, _In_ DWORD cchDstLength)
#define VK_RETURN
Definition: winuser.h:2237
HWND WINAPI SetFocus(_In_opt_ HWND)
HKL WINAPI LoadKeyboardLayoutW(_In_ LPCWSTR, _In_ UINT)
BOOL WINAPI UnhookWindowsHookEx(_In_ HHOOK)
HWND WINAPI SetActiveWindow(_In_ HWND)
BOOL WINAPI PeekMessageW(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT, _In_ UINT)
int WINAPI GetKeyNameTextW(_In_ LONG lParam, _Out_writes_(cchSize) LPWSTR lpString, _In_ int cchSize)
UINT WINAPI GetKeyboardLayoutList(_In_ int nBuff, _Out_writes_to_opt_(nBuff, return) HKL FAR *lpList)
#define VK_RMENU
Definition: winuser.h:2323
#define VK_NUMPAD9
Definition: winuser.h:2284
#define RDW_ALLCHILDREN
Definition: winuser.h:1232
#define VK_END
Definition: winuser.h:2258
#define VK_HOME
Definition: winuser.h:2259
BOOL WINAPI EndPaint(_In_ HWND, _In_ const PAINTSTRUCT *)
#define PM_REMOVE
Definition: winuser.h:1207
#define RDW_FRAME
Definition: winuser.h:1223
BOOL WINAPI UpdateWindow(_In_ HWND)
#define SWP_SHOWWINDOW
Definition: winuser.h:1259
#define WM_SYSKEYUP
Definition: winuser.h:1748
#define RIDEV_INPUTSINK
Definition: winuser.h:2964
HKL WINAPI LoadKeyboardLayoutA(_In_ LPCSTR, _In_ UINT)
#define WH_KEYBOARD_LL
Definition: winuser.h:43
#define WS_EX_LAYERED
Definition: winuser.h:389
#define CreateWindowW(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4470
VOID WINAPI keybd_event(_In_ BYTE, _In_ BYTE, _In_ DWORD, _In_ ULONG_PTR)
#define WM_LBUTTONUP
Definition: winuser.h:1805
LONG WINAPI GetMessageTime(void)
Definition: message.c:1361
#define WM_CHAR
Definition: winuser.h:1745
LRESULT WINAPI CallNextHookEx(_In_opt_ HHOOK, _In_ int, _In_ WPARAM, _In_ LPARAM)
#define VK_LEFT
Definition: winuser.h:2260
#define KEYEVENTF_EXTENDEDKEY
Definition: winuser.h:1112
#define VK_NUMPAD7
Definition: winuser.h:2282
#define VK_RIGHT
Definition: winuser.h:2262
LRESULT WINAPI DispatchMessageW(_In_ const MSG *)
#define VK_DOWN
Definition: winuser.h:2263
#define MOUSEEVENTF_RIGHTDOWN
Definition: winuser.h:1197
#define HTTRANSPARENT
Definition: winuser.h:2509
int WINAPI ToUnicodeEx(_In_ UINT wVirtKey, _In_ UINT wScanCode, _In_reads_bytes_(256) CONST BYTE *lpKeyState, _Out_writes_(cchBuff) LPWSTR pwszBuff, _In_ int cchBuff, _In_ UINT wFlags, _In_opt_ HKL dwhkl)
#define VK_NUMLOCK
Definition: winuser.h:2315
struct tagMONITORINFO MONITORINFO
BOOL WINAPI PeekMessageA(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT, _In_ UINT)
#define KF_REPEAT
Definition: winuser.h:2486
#define WM_USER
Definition: winuser.h:1923
#define VK_SHIFT
Definition: winuser.h:2238
#define SW_SHOW
Definition: winuser.h:786
#define VK_PRIOR
Definition: winuser.h:2256
BOOL WINAPI UnregisterClassW(_In_ LPCWSTR, HINSTANCE)
#define MAPVK_VK_TO_VSC
Definition: winuser.h:2391
SHORT WINAPI GetAsyncKeyState(_In_ int)
#define WM_KEYDOWN
Definition: winuser.h:1743
BOOL WINAPI GetMonitorInfoW(_In_ HMONITOR, _Inout_ LPMONITORINFO)
#define VK_NUMPAD8
Definition: winuser.h:2283
BOOL WINAPI CloseDesktop(_In_ HDESK)
HKL WINAPI ActivateKeyboardLayout(_In_ HKL, _In_ UINT)
#define MAPVK_VK_TO_VSC_EX
Definition: winuser.h:2395
DWORD WINAPI OemKeyScan(_In_ WORD)
HDC WINAPI BeginPaint(_In_ HWND, _Out_ LPPAINTSTRUCT)
#define RIDEV_REMOVE
Definition: winuser.h:2960
BOOL WINAPI UnionRect(_Out_ LPRECT, _In_ LPCRECT, _In_ LPCRECT)
#define SetWindowLongPtrW
Definition: winuser.h:5512
BOOL WINAPI InflateRect(_Inout_ LPRECT, _In_ int, _In_ int)
BOOL WINAPI GetMessageA(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT)
#define WM_KEYLAST
Definition: winuser.h:1756
int WINAPI ToAsciiEx(_In_ UINT, _In_ UINT, _In_reads_opt_(256) CONST BYTE *, _Out_ LPWORD, _In_ UINT, _In_opt_ HKL)
SHORT WINAPI VkKeyScanW(_In_ WCHAR)
LPARAM WINAPI GetMessageExtraInfo(void)
Definition: message.c:1340
BOOL WINAPI DestroyWindow(_In_ HWND)
BOOL WINAPI PostMessageA(_In_opt_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
BOOL WINAPI EqualRect(_In_ LPCRECT, _In_ LPCRECT)
#define KEYEVENTF_KEYUP
Definition: winuser.h:1113
#define WM_SYSKEYDOWN
Definition: winuser.h:1747
#define VK_INSERT
Definition: winuser.h:2268
#define RDW_INVALIDATE
Definition: winuser.h:1225
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
HCURSOR WINAPI LoadCursorA(_In_opt_ HINSTANCE, _In_ LPCSTR)
Definition: cursoricon.c:2459
SHORT WINAPI GetKeyState(_In_ int)
#define VK_LMENU
Definition: winuser.h:2322
#define VK_MENU
Definition: winuser.h:2240
#define GWL_EXSTYLE
Definition: winuser.h:862
unsigned char BYTE
Definition: xxhash.c:193