Mostly split from https://gitlab.winehq.org/wine/wine/-/merge_requests/4946.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/user32/tests/input.c | 189 +++++++++++++++++++------------------- 1 file changed, 97 insertions(+), 92 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 02200fb37aa..7179ed93bf0 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -506,6 +506,42 @@ static inline BOOL is_mouse_message( UINT message ) return (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST); }
+#define create_foreground_window( a ) create_foreground_window_( __FILE__, __LINE__, a, 5 ) +HWND create_foreground_window_( const char *file, int line, BOOL fullscreen, UINT retries ) +{ + for (;;) + { + HWND hwnd; + BOOL ret; + + hwnd = CreateWindowW( L"static", NULL, WS_POPUP | (fullscreen ? 0 : WS_VISIBLE), + 100, 100, 200, 200, NULL, NULL, NULL, NULL ); + ok_(file, line)( hwnd != NULL, "CreateWindowW failed, error %lu\n", GetLastError() ); + + if (fullscreen) + { + HMONITOR hmonitor = MonitorFromWindow( hwnd, MONITOR_DEFAULTTOPRIMARY ); + MONITORINFO mi = {.cbSize = sizeof(MONITORINFO)}; + + ok_(file, line)( hmonitor != NULL, "MonitorFromWindow failed, error %lu\n", GetLastError() ); + ret = GetMonitorInfoW( hmonitor, &mi ); + ok_(file, line)( ret, "GetMonitorInfoW failed, error %lu\n", GetLastError() ); + ret = SetWindowPos( hwnd, 0, mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right - mi.rcMonitor.left, + mi.rcMonitor.bottom - mi.rcMonitor.top, SWP_FRAMECHANGED | SWP_SHOWWINDOW ); + ok_(file, line)( ret, "SetWindowPos failed, error %lu\n", GetLastError() ); + } + wait_messages( 100, FALSE ); + + if (GetForegroundWindow() == hwnd) return hwnd; + ok_(file, line)( retries > 0, "failed to create foreground window\n" ); + if (!retries--) return hwnd; + + ret = DestroyWindow( hwnd ); + ok_(file, line)( ret, "DestroyWindow failed, error %lu\n", GetLastError() ); + wait_messages( 0, FALSE ); + } +} + /* try to make sure pending X events have been processed before continuing */ static void empty_message_queue(void) { @@ -1727,116 +1763,75 @@ static void test_GetRawInputDeviceList(void)
static void test_GetRawInputData(void) { - UINT size; - UINT ret; + UINT size = 0;
/* Null raw input handle */ - SetLastError(0xdeadbeef); - ret = GetRawInputData(NULL, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); - ok(ret == ~0U, "Expect ret %u, got %u\n", ~0U, ret); - ok(GetLastError() == ERROR_INVALID_HANDLE, "GetRawInputData returned %08lx\n", GetLastError()); + SetLastError( 0xdeadbeef ); + ok_ret( (UINT)-1, GetRawInputData( NULL, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER) ) ); + ok_ret( ERROR_INVALID_HANDLE, GetLastError() ); }
static void test_RegisterRawInputDevices(void) { HWND hwnd; - RAWINPUTDEVICE raw_devices[2]; + RAWINPUTDEVICE raw_devices[2] = {0}; UINT count, raw_devices_count; - BOOL res; - - memset(raw_devices, 0, sizeof(raw_devices)); - raw_devices[0].usUsagePage = 0x01; - raw_devices[0].usUsage = 0x05; - raw_devices[1].usUsagePage = 0x01; - raw_devices[1].usUsage = 0x04; - - hwnd = CreateWindowExA(WS_EX_TOPMOST, "static", "dinput", WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, NULL, NULL); - ok(hwnd != NULL, "CreateWindowExA failed\n");
+ raw_devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC; + raw_devices[0].usUsage = HID_USAGE_GENERIC_GAMEPAD; + raw_devices[1].usUsagePage = HID_USAGE_PAGE_GENERIC; + raw_devices[1].usUsage = HID_USAGE_GENERIC_JOYSTICK;
- res = RegisterRawInputDevices(NULL, 0, 0); - ok(res == FALSE, "RegisterRawInputDevices succeeded\n"); + hwnd = create_foreground_window( FALSE );
+ SetLastError( 0xdeadbeef ); + ok_ret( 0, RegisterRawInputDevices( NULL, 0, 0 ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() );
- SetLastError(0xdeadbeef); - res = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), 0); - ok(res == FALSE, "RegisterRawInputDevices succeeded\n"); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "RegisterRawInputDevices returned %08lx\n", GetLastError()); + SetLastError( 0xdeadbeef ); + ok_ret( 0, RegisterRawInputDevices( raw_devices, ARRAY_SIZE( raw_devices ), 0 ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() );
- SetLastError(0xdeadbeef); - res = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE)); - ok(res == TRUE, "RegisterRawInputDevices failed\n"); - ok(GetLastError() == 0xdeadbeef, "RegisterRawInputDevices returned %08lx\n", GetLastError()); + ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE( raw_devices ), sizeof(RAWINPUTDEVICE) ) );
- SetLastError(0xdeadbeef); - count = GetRegisteredRawInputDevices(NULL, NULL, 0); - ok(count == ~0U, "GetRegisteredRawInputDevices returned %u\n", count); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRegisteredRawInputDevices unexpected error %08lx\n", GetLastError()); + SetLastError( 0xdeadbeef ); + ok_ret( (UINT)-1, GetRegisteredRawInputDevices( NULL, NULL, 0 ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() );
- SetLastError(0xdeadbeef); - raw_devices_count = 0; - count = GetRegisteredRawInputDevices(NULL, &raw_devices_count, 0); - ok(count == ~0U, "GetRegisteredRawInputDevices returned %u\n", count); - ok(raw_devices_count == 0, "Unexpected registered devices count: %u\n", raw_devices_count); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRegisteredRawInputDevices unexpected error %08lx\n", GetLastError()); + SetLastError( 0xdeadbeef ); + ok_ret( (UINT)-1, GetRegisteredRawInputDevices( NULL, &raw_devices_count, 0 ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() );
- SetLastError(0xdeadbeef); raw_devices_count = 0; - count = GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE)); - ok(count == 0, "GetRegisteredRawInputDevices returned %u\n", count); - ok(raw_devices_count == 2, "Unexpected registered devices count: %u\n", raw_devices_count); - ok(GetLastError() == 0xdeadbeef, "GetRegisteredRawInputDevices unexpected error %08lx\n", GetLastError()); + ok_ret( 0, GetRegisteredRawInputDevices( NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE) ) ); + ok_eq( 2, raw_devices_count, UINT, "%u" );
- SetLastError(0xdeadbeef); + SetLastError( 0xdeadbeef ); raw_devices_count = 0; - count = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE)); + count = GetRegisteredRawInputDevices( raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE) ); if (broken(count == 0) /* depends on windows versions */) - win_skip("Ignoring GetRegisteredRawInputDevices success\n"); + win_skip( "Ignoring GetRegisteredRawInputDevices success\n" ); else { - ok(count == ~0U, "GetRegisteredRawInputDevices returned %u\n", count); - ok(raw_devices_count == 0, "Unexpected registered devices count: %u\n", raw_devices_count); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRegisteredRawInputDevices unexpected error %08lx\n", GetLastError()); + ok_eq( -1, count, int, "%d" ); + ok_eq( 0, raw_devices_count, UINT, "%u" ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() ); }
- SetLastError(0xdeadbeef); + SetLastError( 0xdeadbeef ); raw_devices_count = 1; - count = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE)); - ok(count == ~0U, "GetRegisteredRawInputDevices returned %u\n", count); - ok(raw_devices_count == 2, "Unexpected registered devices count: %u\n", raw_devices_count); - ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetRegisteredRawInputDevices unexpected error %08lx\n", GetLastError()); + ok_ret( (UINT)-1, GetRegisteredRawInputDevices( raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE) ) ); + ok_eq( 2, raw_devices_count, UINT, "%u" ); + ok_ret( ERROR_INSUFFICIENT_BUFFER, GetLastError() );
- SetLastError(0xdeadbeef); - memset(raw_devices, 0, sizeof(raw_devices)); + memset( raw_devices, 0, sizeof(raw_devices) ); raw_devices_count = ARRAY_SIZE(raw_devices); - count = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE)); - ok(count == 2, "GetRegisteredRawInputDevices returned %u\n", count); - ok(raw_devices_count == 2, "Unexpected registered devices count: %u\n", raw_devices_count); - ok(GetLastError() == 0xdeadbeef, "GetRegisteredRawInputDevices unexpected error %08lx\n", GetLastError()); - ok(raw_devices[0].usUsagePage == 0x01, "Unexpected usage page: %x\n", raw_devices[0].usUsagePage); - ok(raw_devices[0].usUsage == 0x04, "Unexpected usage: %x\n", raw_devices[0].usUsage); - ok(raw_devices[1].usUsagePage == 0x01, "Unexpected usage page: %x\n", raw_devices[1].usUsagePage); - ok(raw_devices[1].usUsage == 0x05, "Unexpected usage: %x\n", raw_devices[1].usUsage); - - /* RIDEV_REMOVE requires hwndTarget == NULL */ - raw_devices[0].dwFlags = RIDEV_REMOVE; - raw_devices[0].hwndTarget = hwnd; - raw_devices[1].dwFlags = RIDEV_REMOVE; - raw_devices[1].hwndTarget = hwnd; - - SetLastError(0xdeadbeef); - res = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE)); - ok(res == FALSE, "RegisterRawInputDevices succeeded\n"); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "RegisterRawInputDevices returned %08lx\n", GetLastError()); - - raw_devices[0].hwndTarget = 0; - raw_devices[1].hwndTarget = 0; - - SetLastError(0xdeadbeef); - res = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE)); - ok(res == TRUE, "RegisterRawInputDevices failed\n"); - ok(GetLastError() == 0xdeadbeef, "RegisterRawInputDevices returned %08lx\n", GetLastError()); - + ok_ret( 2, GetRegisteredRawInputDevices( raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE) ) ); + ok_eq( 2, raw_devices_count, UINT, "%u" ); + ok_eq( HID_USAGE_PAGE_GENERIC, raw_devices[0].usUsagePage, USHORT, "%#x" ); + ok_eq( HID_USAGE_GENERIC_JOYSTICK, raw_devices[0].usUsage, USHORT, "%#x" ); + ok_eq( HID_USAGE_PAGE_GENERIC, raw_devices[1].usUsagePage, USHORT, "%#x" ); + ok_eq( HID_USAGE_GENERIC_GAMEPAD, raw_devices[1].usUsage, USHORT, "%#x" );
/* RIDEV_INPUTSINK requires hwndTarget != NULL */ raw_devices[0].dwFlags = RIDEV_INPUTSINK; @@ -1845,19 +1840,28 @@ static void test_RegisterRawInputDevices(void) raw_devices[1].hwndTarget = 0;
SetLastError(0xdeadbeef); - res = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE)); - ok(res == FALSE, "RegisterRawInputDevices failed\n"); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "RegisterRawInputDevices returned %08lx\n", GetLastError()); + ok_ret( 0, RegisterRawInputDevices( raw_devices, ARRAY_SIZE( raw_devices ), sizeof(RAWINPUTDEVICE) ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() );
raw_devices[0].hwndTarget = hwnd; raw_devices[1].hwndTarget = hwnd; + ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE( raw_devices ), sizeof(RAWINPUTDEVICE) ) ); + + /* RIDEV_REMOVE requires hwndTarget == NULL */ + raw_devices[0].dwFlags = RIDEV_REMOVE; + raw_devices[0].hwndTarget = hwnd; + raw_devices[1].dwFlags = RIDEV_REMOVE; + raw_devices[1].hwndTarget = hwnd;
SetLastError(0xdeadbeef); - res = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE)); - ok(res == TRUE, "RegisterRawInputDevices succeeded\n"); - ok(GetLastError() == 0xdeadbeef, "RegisterRawInputDevices returned %08lx\n", GetLastError()); + ok_ret( 0, RegisterRawInputDevices( raw_devices, ARRAY_SIZE( raw_devices ), sizeof(RAWINPUTDEVICE) ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() );
- DestroyWindow(hwnd); + raw_devices[0].hwndTarget = 0; + raw_devices[1].hwndTarget = 0; + ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE( raw_devices ), sizeof(RAWINPUTDEVICE) ) ); + + ok_ret( 1, DestroyWindow( hwnd ) ); }
static int rawinputbuffer_wndproc_count; @@ -5528,6 +5532,9 @@ static void test_input_desktop( char **argv )
test_keyboard_ll_hook_blocking();
+ test_RegisterRawInputDevices(); + test_GetRawInputData(); + ok_ret( 1, SetCursorPos( pos.x, pos.y ) ); }
@@ -5594,9 +5601,7 @@ START_TEST(input) test_attach_input(); test_GetKeyState(); test_OemKeyScan(); - test_GetRawInputData(); test_GetRawInputBuffer(); - test_RegisterRawInputDevices(); test_rawinput(argv[0]); test_DefRawInputProc();
From: Rémi Bernon rbernon@codeweavers.com
This should be more reliable than mouse moves and it exhibits more issues with the rawinput buffer struct sizes on new WoW64. --- dlls/user32/tests/input.c | 479 ++++++++++++++++++++------------------ 1 file changed, 257 insertions(+), 222 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 7179ed93bf0..aed459de86f 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -1897,334 +1897,369 @@ typedef struct } RAWINPUT64; #endif
-static int rawinput_buffer_mouse_x(void *buffer, size_t index) -{ - if (is_wow64) return ((RAWINPUT64 *)buffer)[index].data.mouse.lLastX; - return ((RAWINPUT *)buffer)[index].data.mouse.lLastX; -} - static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - UINT i, size, count, rawinput_size, iteration = rawinputbuffer_wndproc_count++; - RAWINPUT ri; - char buffer[16 * sizeof(RAWINPUT64)]; - MSG message; - - if (is_wow64) rawinput_size = sizeof(RAWINPUT64); - else rawinput_size = sizeof(RAWINPUT); - if (msg == WM_INPUT) { - SetLastError(0xdeadbeef); - count = GetRawInputBuffer(NULL, NULL, sizeof(RAWINPUTHEADER)); - ok(count == ~0U, "GetRawInputBuffer succeeded\n"); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError()); + UINT i, size, rawinput_size, iteration = rawinputbuffer_wndproc_count++; + char buffer[16 * sizeof(RAWINPUT64)]; + RAWINPUT64 *rawbuffer64 = (RAWINPUT64 *)buffer; + RAWINPUT *rawbuffer = (RAWINPUT *)buffer; + HRAWINPUT handle = (HRAWINPUT)lparam; + RAWINPUT rawinput = {{0}};
- size = sizeof(buffer); - count = GetRawInputBuffer(NULL, &size, sizeof(RAWINPUTHEADER)); - ok(count == 0, "GetRawInputBuffer returned %u\n", count); - ok(size == rawinput_size, "GetRawInputBuffer returned unexpected size: %u\n", size); + winetest_push_context( "%u", iteration ); + + if (is_wow64) rawinput_size = sizeof(RAWINPUTHEADER64) + sizeof(RAWKEYBOARD); + else rawinput_size = sizeof(RAWINPUTHEADER) + sizeof(RAWKEYBOARD);
size = sizeof(buffer); - memset(buffer, 0, sizeof(buffer)); - count = GetRawInputBuffer((RAWINPUT*)buffer, &size, sizeof(RAWINPUTHEADER)); - ok(count == 3, "GetRawInputBuffer returned %u\n", count); - ok(size == sizeof(buffer), "GetRawInputBuffer returned unexpected size: %u\n", size); + memset( buffer, 0, sizeof(buffer) ); + todo_wine_if(is_wow64 && iteration == 1) + ok_ret( 3, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER)) ); + ok_eq( sizeof(buffer), size, UINT, "%u" );
for (i = 0; i < 3; ++i) { + winetest_push_context( "%u", i ); if (is_wow64) { - const RAWINPUT64 *data = &((RAWINPUT64 *)buffer)[i]; - ok(data->header.dwType == RIM_TYPEMOUSE, "Unexpected rawinput type: %lu\n", data->header.dwType); - ok(data->header.dwSize == sizeof(*data), "Unexpected rawinput size: %lu\n", data->header.dwSize); - todo_wine_if (wparam) - ok(data->header.wParam == wparam, "Unexpected wparam: %#I64x\n", data->header.wParam); + RAWINPUT64 *rawinput = (RAWINPUT64 *)(buffer + i * rawinput_size); + flaky_wine_if(is_wow64) + ok_eq( RIM_TYPEKEYBOARD, rawinput->header.dwType, UINT, "%u" ); + flaky_wine_if(is_wow64) + ok_eq( rawinput_size, rawinput->header.dwSize, UINT, "%u" ); + ok_eq( wparam, rawinput->header.wParam, WPARAM, "%Iu" ); + flaky_wine_if(is_wow64) + ok_eq( i + 2, rawinput->data.keyboard.MakeCode, WPARAM, "%Iu" ); } else { - const RAWINPUT *data = &((RAWINPUT *)buffer)[i]; - ok(data->header.dwType == RIM_TYPEMOUSE, "Unexpected rawinput type: %lu\n", data->header.dwType); - ok(data->header.dwSize == sizeof(*data), "Unexpected rawinput size: %lu\n", data->header.dwSize); - todo_wine_if (wparam) - ok(data->header.wParam == wparam, "Unexpected wparam: %#Ix\n", data->header.wParam); + RAWINPUT *rawinput = (RAWINPUT *)(buffer + i * rawinput_size); + ok_eq( RIM_TYPEKEYBOARD, rawinput->header.dwType, UINT, "%u" ); + ok_eq( rawinput_size, rawinput->header.dwSize, UINT, "%u" ); + ok_eq( wparam, rawinput->header.wParam, WPARAM, "%Iu" ); + ok_eq( i + 2, rawinput->data.keyboard.MakeCode, WPARAM, "%Iu" ); } + winetest_pop_context(); }
- ok(rawinput_buffer_mouse_x(buffer, 0) == 2, "Unexpected rawinput data: %d\n", rawinput_buffer_mouse_x(buffer, 0)); - ok(rawinput_buffer_mouse_x(buffer, 1) == 3, "Unexpected rawinput data: %d\n", rawinput_buffer_mouse_x(buffer, 1)); - ok(rawinput_buffer_mouse_x(buffer, 2) == 4, "Unexpected rawinput data: %d\n", rawinput_buffer_mouse_x(buffer, 2)); - /* the first event should be removed by the next GetRawInputBuffer call * and the others should do another round through the message loop but not more */ if (iteration == 0) { - mouse_event(MOUSEEVENTF_MOVE, 5, 0, 0, 0); - mouse_event(MOUSEEVENTF_MOVE, 6, 0, 0, 0); - mouse_event(MOUSEEVENTF_MOVE, 2, 0, 0, 0); - mouse_event(MOUSEEVENTF_MOVE, 3, 0, 0, 0); - mouse_event(MOUSEEVENTF_MOVE, 4, 0, 0, 0); + keybd_event( 'X', 5, 0, 0 ); + keybd_event( 'X', 6, KEYEVENTF_KEYUP, 0 ); + keybd_event( 'X', 2, KEYEVENTF_KEYUP, 0 ); + keybd_event( 'X', 3, 0, 0 ); + keybd_event( 'X', 4, KEYEVENTF_KEYUP, 0 );
/* even though rawinput_size is the minimum required size, * it needs one more byte to return success */ - size = rawinput_size + 1; - memset(buffer, 0, sizeof(buffer)); - count = GetRawInputBuffer((RAWINPUT*)buffer, &size, sizeof(RAWINPUTHEADER)); - ok(count == 1, "GetRawInputBuffer returned %u\n", count); - ok(rawinput_buffer_mouse_x(buffer, 0) == 5, "Unexpected rawinput data: %d\n", rawinput_buffer_mouse_x(buffer, 0)); + size = sizeof(rawinput) + 1; + memset( buffer, 0, sizeof(buffer) ); + todo_wine_if(is_wow64) + ok_ret( 1, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) ); + if (is_wow64) todo_wine ok_eq( 5, rawbuffer64->data.keyboard.MakeCode, WPARAM, "%Iu" ); + else ok_eq( 5, rawbuffer->data.keyboard.MakeCode, WPARAM, "%Iu" );
/* peek the messages now, they should still arrive in the correct order */ - while (PeekMessageA(&message, 0, WM_INPUT, WM_INPUT, PM_REMOVE)) DispatchMessageA(&message); + winetest_pop_context(); + wait_messages( 0, FALSE ); + winetest_push_context( "%u", iteration ); + + /* reading the message data now should fail, the data + * from the first message has been overwritten. */ + SetLastError( 0xdeadbeef ); + size = sizeof(rawinput); + ok_ret( (UINT)-1, GetRawInputData( handle, RID_HEADER, &rawinput, &size, sizeof(RAWINPUTHEADER) ) ); + ok_ret( ERROR_INVALID_HANDLE, GetLastError() ); } - - /* reading the message data now should fail on the second iteration, the data - * from the first message has been overwritten. */ - size = sizeof(ri); - memset(&ri, 0, sizeof(ri)); - SetLastError(0xdeadbeef); - count = GetRawInputData((HRAWINPUT)lparam, RID_HEADER, &ri, &size, sizeof(RAWINPUTHEADER)); - if (iteration == 1) + else { - SetLastError(0xdeadbeef); - count = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &ri, &size, 0); - ok(count == ~0u, "GetRawInputData returned %d\n", count); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputData returned %08lx\n", GetLastError()); + SetLastError( 0xdeadbeef ); + ok_ret( (UINT)-1, GetRawInputData( handle, RID_HEADER, &rawinput, &size, 0) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() );
- SetLastError(0xdeadbeef); - count = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER) + 1); - ok(count == ~0u, "GetRawInputData returned %d\n", count); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputData returned %08lx\n", GetLastError()); + SetLastError( 0xdeadbeef ); + ok_ret( (UINT)-1, GetRawInputData( handle, RID_HEADER, &rawinput, &size, sizeof(RAWINPUTHEADER) + 1 ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() );
- SetLastError(0xdeadbeef); + SetLastError( 0xdeadbeef ); size = 0; - count = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER)); - ok(count == ~0U, "GetRawInputData succeeded\n"); - ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetRawInputData returned %08lx\n", GetLastError()); + ok_ret( (UINT)-1, GetRawInputData( handle, RID_HEADER, &rawinput, &size, sizeof(RAWINPUTHEADER) ) ); + ok_ret( ERROR_INSUFFICIENT_BUFFER, GetLastError() );
- SetLastError(0xdeadbeef); - size = sizeof(ri); - count = GetRawInputData((HRAWINPUT)lparam, 0, &ri, &size, sizeof(RAWINPUTHEADER)); - ok(count == ~0U, "GetRawInputData succeeded\n"); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputData returned %08lx\n", GetLastError()); + size = sizeof(RAWINPUTHEADER); + rawinput_size = sizeof(RAWINPUTHEADER) + sizeof(RAWKEYBOARD); + ok_ret( sizeof(RAWINPUTHEADER), GetRawInputData( handle, RID_HEADER, &rawinput, &size, sizeof(RAWINPUTHEADER) ) ); + ok_eq( rawinput_size, rawinput.header.dwSize, UINT, "%u" ); + ok_eq( RIM_TYPEKEYBOARD, rawinput.header.dwType, UINT, "%u" );
- SetLastError(0xdeadbeef); - size = sizeof(ri); - count = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER)); - ok(count == sizeof(ri), "GetRawInputData failed\n"); - ok(ri.data.mouse.lLastX == 6, "Unexpected rawinput data: %ld\n", ri.data.mouse.lLastX); - ok(GetLastError() == 0xdeadbeef, "GetRawInputData returned %08lx\n", GetLastError());
- SetLastError(0xdeadbeef); + SetLastError( 0xdeadbeef ); + ok_ret( (UINT)-1, GetRawInputData( handle, RID_INPUT, &rawinput, &size, 0) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() ); + + SetLastError( 0xdeadbeef ); + ok_ret( (UINT)-1, GetRawInputData( handle, RID_INPUT, &rawinput, &size, sizeof(RAWINPUTHEADER) + 1 ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() ); + + SetLastError( 0xdeadbeef ); + size = 0; + ok_ret( (UINT)-1, GetRawInputData( handle, RID_INPUT, &rawinput, &size, sizeof(RAWINPUTHEADER) ) ); + ok_ret( ERROR_INSUFFICIENT_BUFFER, GetLastError() ); + + SetLastError( 0xdeadbeef ); + size = sizeof(rawinput); + ok_ret( (UINT)-1, GetRawInputData( handle, 0, &rawinput, &size, sizeof(RAWINPUTHEADER) ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() ); + + SetLastError( 0xdeadbeef ); + size = sizeof(rawinput); + ok_ret( rawinput_size, GetRawInputData( handle, RID_INPUT, &rawinput, &size, sizeof(RAWINPUTHEADER) ) ); + todo_wine_if(is_wow64) + ok_eq( 6, rawinput.data.keyboard.MakeCode, UINT, "%u" ); + + SetLastError( 0xdeadbeef ); size = sizeof(buffer); if (sizeof(void *) == 8) { - count = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER32)); - ok(count == ~0u, "GetRawInputData returned %d\n", count); + ok_ret( (UINT)-1, GetRawInputData( handle, RID_INPUT, &rawinput, &size, sizeof(RAWINPUTHEADER32) ) ); ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputData returned %08lx\n", GetLastError()); } + else if (is_wow64) + { + todo_wine + ok_ret( rawinput_size, GetRawInputData( handle, RID_INPUT, &rawinput, &size, sizeof(RAWINPUTHEADER64) ) ); + todo_wine + ok_eq( 6, rawinput.data.keyboard.MakeCode, UINT, "%u" ); + todo_wine + ok_ret( 0xdeadbeef, GetLastError() ); + } else { - count = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER64)); - if (is_wow64) - { - todo_wine ok(count == sizeof(ri), "GetRawInputData returned %d\n", count); - ok(ri.data.mouse.lLastX == 6, "Unexpected rawinput data: %ld\n", ri.data.mouse.lLastX); - todo_wine ok(GetLastError() == 0xdeadbeef, "GetRawInputData returned %08lx\n", GetLastError()); - } - else - { - ok(count == ~0u, "GetRawInputData returned %d\n", count); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputData returned %08lx\n", GetLastError()); - } + ok_ret( (UINT)-1, GetRawInputData( handle, RID_INPUT, &rawinput, &size, sizeof(RAWINPUTHEADER64) ) ); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputData returned %08lx\n", GetLastError()); } } - else - { - ok(count == ~0U, "GetRawInputData succeeded\n"); - ok(GetLastError() == ERROR_INVALID_HANDLE, "GetRawInputData returned %08lx\n", GetLastError()); - }
+ winetest_pop_context(); return 0; }
- return DefWindowProcA(hwnd, msg, wparam, lparam); + return DefWindowProcW( hwnd, msg, wparam, lparam ); }
static void test_GetRawInputBuffer(void) { - unsigned int size, count, rawinput_size, header_size, scan_code; + unsigned int size, rawinput_size, header_size; RAWINPUTDEVICE raw_devices[1]; char buffer[16 * sizeof(RAWINPUT64)]; + RAWINPUT64 *rawbuffer64 = (RAWINPUT64 *)buffer; + RAWINPUT *rawbuffer = (RAWINPUT *)buffer; HWND hwnd; - BOOL ret; - POINT pt; - -#define HEADER_FIELD(field) (is_wow64 ? ((RAWINPUT64 *)buffer)->header.field : ((RAWINPUT *)buffer)->header.field)
- if (is_wow64) rawinput_size = sizeof(RAWINPUT64); - else rawinput_size = sizeof(RAWINPUT); + if (is_wow64) rawinput_size = sizeof(RAWINPUTHEADER64) + sizeof(RAWMOUSE); + else rawinput_size = sizeof(RAWINPUTHEADER) + sizeof(RAWMOUSE);
- SetCursorPos(300, 300); - GetCursorPos(&pt); - ok(pt.x == 300 && pt.y == 300, "Unexpected cursor position pos %ldx%ld\n", pt.x, pt.y); - - hwnd = CreateWindowA("static", "static", WS_VISIBLE | WS_POPUP, - 100, 100, 100, 100, 0, NULL, NULL, NULL); - SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)rawinputbuffer_wndproc); - ok(hwnd != 0, "CreateWindow failed\n"); - empty_message_queue(); + hwnd = create_foreground_window( TRUE ); + SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)rawinputbuffer_wndproc );
- raw_devices[0].usUsagePage = 0x01; - raw_devices[0].usUsage = 0x02; + raw_devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC; + raw_devices[0].usUsage = HID_USAGE_GENERIC_MOUSE; raw_devices[0].dwFlags = RIDEV_INPUTSINK; raw_devices[0].hwndTarget = hwnd; + ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE( raw_devices ), sizeof(RAWINPUTDEVICE) ) );
- SetLastError(0xdeadbeef); - ret = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE)); - ok(ret, "RegisterRawInputDevices failed\n"); - ok(GetLastError() == 0xdeadbeef, "RegisterRawInputDevices returned %08lx\n", GetLastError()); - - SetLastError(0xdeadbeef); - count = GetRawInputBuffer(NULL, NULL, sizeof(RAWINPUTHEADER)); - ok(count == ~0U, "GetRawInputBuffer succeeded\n"); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputBuffer returned %08lx\n", GetLastError()); + /* check basic error cases */
+ SetLastError( 0xdeadbeef ); + ok_ret( (UINT)-1, GetRawInputBuffer( NULL, NULL, sizeof(RAWINPUTHEADER) ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() ); + SetLastError( 0xdeadbeef ); size = sizeof(buffer); - count = GetRawInputBuffer(NULL, &size, sizeof(RAWINPUTHEADER)); - ok(count == 0U, "GetRawInputBuffer returned %u\n", count); - ok(size == 0U, "GetRawInputBuffer returned unexpected size: %u\n", size); + ok_ret( (UINT)-1, GetRawInputBuffer( rawbuffer, &size, 0 ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() );
- size = 0; - count = GetRawInputBuffer((RAWINPUT*)buffer, &size, sizeof(RAWINPUTHEADER)); - ok(count == 0U, "GetRawInputBuffer returned %u\n", count); - ok(size == 0U, "GetRawInputBuffer returned unexpected size: %u\n", size); + /* valid calls, but no input */
- SetLastError(0xdeadbeef); size = sizeof(buffer); - count = GetRawInputBuffer((RAWINPUT*)buffer, &size, 0); - ok(count == ~0U, "GetRawInputBuffer succeeded\n"); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputBuffer returned %08lx\n", GetLastError()); - + ok_ret( 0, GetRawInputBuffer( NULL, &size, sizeof(RAWINPUTHEADER) ) ); + ok_eq( 0, size, UINT, "%u" ); + size = 0; + ok_ret( 0, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) ); + ok_eq( 0, size, UINT, "%u" ); size = sizeof(buffer); - count = GetRawInputBuffer((RAWINPUT*)buffer, &size, sizeof(RAWINPUTHEADER)); - ok(count == 0U, "GetRawInputBuffer returned %u\n", count); - ok(size == 0U, "GetRawInputBuffer returned unexpected size: %u\n", size); + ok_ret( 0, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) ); + ok_eq( 0, size, UINT, "%u" );
- mouse_event(MOUSEEVENTF_MOVE, 5, 0, 0, 0);
- SetLastError(0xdeadbeef); - size = 0; - count = GetRawInputBuffer((RAWINPUT*)buffer, &size, sizeof(RAWINPUTHEADER)); - ok(count == ~0U, "GetRawInputBuffer succeeded\n"); - ok(size == rawinput_size, "GetRawInputBuffer returned unexpected size: %u\n", size); - ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetRawInputBuffer returned %08lx\n", GetLastError()); + mouse_event( MOUSEEVENTF_MOVE, 5, 0, 0, 0 );
- size = 0; - count = GetRawInputBuffer(NULL, &size, sizeof(RAWINPUTHEADER)); - ok(count == 0, "GetRawInputBuffer returned %u\n", count); - ok(size == rawinput_size, "GetRawInputBuffer returned unexpected size: %u\n", size); + /* invalid calls with input */
- SetLastError(0xdeadbeef); + SetLastError( 0xdeadbeef ); + size = 0; + ok_ret( (UINT)-1, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) ); + ok_eq( rawinput_size, size, UINT, "%u" ); + ok_ret( ERROR_INSUFFICIENT_BUFFER, GetLastError() ); + SetLastError( 0xdeadbeef ); size = sizeof(buffer); - count = GetRawInputBuffer((RAWINPUT*)buffer, &size, 0); - ok(count == ~0U, "GetRawInputBuffer succeeded\n"); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputBuffer returned %08lx\n", GetLastError()); - - SetLastError(0xdeadbeef); + ok_ret( (UINT)-1, GetRawInputBuffer( rawbuffer, &size, 0 ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() ); + SetLastError( 0xdeadbeef ); size = sizeof(buffer); - count = GetRawInputBuffer((RAWINPUT*)buffer, &size, sizeof(RAWINPUTHEADER) + 1); - ok(count == ~0U, "GetRawInputBuffer succeeded\n"); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputBuffer returned %08lx\n", GetLastError()); + ok_ret( (UINT)-1, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) + 1 ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() );
/* the function returns 64-bit RAWINPUT structures on WoW64, but still * forbids sizeof(RAWINPUTHEADER) from the wrong architecture */ - SetLastError(0xdeadbeef); + SetLastError( 0xdeadbeef ); size = sizeof(buffer); header_size = (sizeof(void *) == 8 ? sizeof(RAWINPUTHEADER32) : sizeof(RAWINPUTHEADER64)); - count = GetRawInputBuffer((RAWINPUT*)buffer, &size, header_size); - ok(count == ~0U, "GetRawInputBuffer succeeded\n"); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputBuffer returned %08lx\n", GetLastError()); - - size = sizeof(buffer); - memset(buffer, 0, sizeof(buffer)); - count = GetRawInputBuffer((RAWINPUT*)buffer, &size, sizeof(RAWINPUTHEADER)); - ok(count == 1U, "GetRawInputBuffer returned %u\n", count); - ok(size == sizeof(buffer), "GetRawInputBuffer returned unexpected size: %u\n", size); - ok(HEADER_FIELD(dwType) == RIM_TYPEMOUSE, "Unexpected rawinput dwType: %ld\n", HEADER_FIELD(dwType)); - ok(HEADER_FIELD(wParam) == 0 || HEADER_FIELD(wParam) == 1, "Expected wparam 0 or 1, got %Iu\n", (WPARAM)HEADER_FIELD(wParam)); - ok(rawinput_buffer_mouse_x(buffer, 0) == 5, "Unexpected rawinput data: %d\n", rawinput_buffer_mouse_x(buffer, 0)); + ok_ret( (UINT)-1, GetRawInputBuffer( rawbuffer, &size, header_size ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() );
/* NOTE: calling with size == rawinput_size returns an error, */ /* BUT it fills the buffer nonetheless and empties the internal buffer (!!) */ - mouse_event(MOUSEEVENTF_MOVE, 5, 0, 0, 0);
- SetLastError(0xdeadbeef); + size = 0; + ok_ret( 0, GetRawInputBuffer( NULL, &size, sizeof(RAWINPUTHEADER) ) ); + ok_eq( rawinput_size, size, UINT, "%u" ); + + SetLastError( 0xdeadbeef ); size = rawinput_size; - memset(buffer, 0, sizeof(buffer)); - count = GetRawInputBuffer((RAWINPUT*)buffer, &size, sizeof(RAWINPUTHEADER)); - ok(count == ~0U, "GetRawInputBuffer succeeded\n"); - ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetRawInputBuffer returned %08lx\n", GetLastError()); - ok(rawinput_buffer_mouse_x(buffer, 0) == 5, "Unexpected rawinput data: %d\n", rawinput_buffer_mouse_x(buffer, 0)); + memset( buffer, 0, sizeof(buffer) ); + ok_ret( (UINT)-1, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) ); + ok_ret( ERROR_INSUFFICIENT_BUFFER, GetLastError() ); + if (is_wow64) ok_eq( 5, rawbuffer64->data.mouse.lLastX, UINT, "%u" ); + else ok_eq( 5, rawbuffer->data.mouse.lLastX, UINT, "%u" ); + + /* no more data to read */
size = sizeof(buffer); - count = GetRawInputBuffer((RAWINPUT*)buffer, &size, sizeof(RAWINPUTHEADER)); - ok(count == 0U, "GetRawInputBuffer returned %u\n", count); + ok_ret( 0, GetRawInputBuffer( NULL, &size, sizeof(RAWINPUTHEADER) ) ); + ok_eq( 0, size, UINT, "%u" );
- rawinputbuffer_wndproc_count = 0; - mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0); - mouse_event(MOUSEEVENTF_MOVE, 2, 0, 0, 0); - mouse_event(MOUSEEVENTF_MOVE, 3, 0, 0, 0); - mouse_event(MOUSEEVENTF_MOVE, 4, 0, 0, 0); - empty_message_queue(); - ok(rawinputbuffer_wndproc_count == 2, "Spurious WM_INPUT messages\n"); + /* rawinput_size + 1 succeeds */ + + mouse_event( MOUSEEVENTF_MOVE, 5, 0, 0, 0 ); + + size = rawinput_size + 1; + memset( buffer, 0, sizeof(buffer) ); + ok_ret( 1, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) ); + ok_eq( rawinput_size + 1, size, UINT, "%u" ); + if (is_wow64) + { + ok_eq( RIM_TYPEMOUSE, rawbuffer64->header.dwType, UINT, "%#x" ); + ok_eq( 0, rawbuffer64->header.wParam, WPARAM, "%Iu" ); + ok_eq( 5, rawbuffer64->data.mouse.lLastX, UINT, "%u" ); + } + else + { + ok_eq( RIM_TYPEMOUSE, rawbuffer->header.dwType, UINT, "%#x" ); + ok_eq( 0, rawbuffer->header.wParam, WPARAM, "%Iu" ); + ok_eq( 5, rawbuffer->data.mouse.lLastX, UINT, "%u" ); + } + + size = sizeof(buffer); + ok_ret( 0, GetRawInputBuffer( NULL, &size, sizeof(RAWINPUTHEADER) ) ); + ok_eq( 0, size, UINT, "%u" );
raw_devices[0].dwFlags = RIDEV_REMOVE; raw_devices[0].hwndTarget = 0; - - SetLastError(0xdeadbeef); - ret = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE)); - ok(ret, "RegisterRawInputDevices failed\n"); - ok(GetLastError() == 0xdeadbeef, "RegisterRawInputDevices returned %08lx\n", GetLastError()); + ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE) ) );
/* some keyboard tests to better check fields under wow64 */ - raw_devices[0].usUsagePage = 0x01; - raw_devices[0].usUsage = 0x06; + raw_devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC; + raw_devices[0].usUsage = HID_USAGE_GENERIC_KEYBOARD; raw_devices[0].dwFlags = RIDEV_INPUTSINK; raw_devices[0].hwndTarget = hwnd; + ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE) ) );
- SetLastError(0xdeadbeef); - ret = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE)); - ok(ret, "RegisterRawInputDevices failed\n"); - ok(GetLastError() == 0xdeadbeef, "RegisterRawInputDevices returned %08lx\n", GetLastError()); + keybd_event( 'X', 0x2d, 0, 0 ); + keybd_event( 'X', 0x2d, KEYEVENTF_KEYUP, 0 ); + + if (is_wow64) rawinput_size = sizeof(RAWINPUTHEADER64) + sizeof(RAWKEYBOARD); + else rawinput_size = sizeof(RAWINPUTHEADER) + sizeof(RAWKEYBOARD);
- keybd_event('X', 0x2d, 0, 0); - keybd_event('X', 0x2d, KEYEVENTF_KEYUP, 0); + size = 0; + ok_ret( 0, GetRawInputBuffer( NULL, &size, sizeof(RAWINPUTHEADER) ) ); + todo_wine + ok_eq( rawinput_size, size, UINT, "%u" );
size = sizeof(buffer); - memset(buffer, 0, sizeof(buffer)); - count = GetRawInputBuffer((RAWINPUT*)buffer, &size, sizeof(RAWINPUTHEADER)); - ok(count == 2U, "GetRawInputBuffer returned %u\n", count); - ok(size == sizeof(buffer), "GetRawInputBuffer returned unexpected size: %u\n", size); + memset( buffer, 0, sizeof(buffer) ); + ok_ret( 2, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) ); + ok_eq( sizeof(buffer), size, UINT, "%u" ); + if (is_wow64) + { + ok_eq( RIM_TYPEKEYBOARD, rawbuffer64->header.dwType, UINT, "%u" ); + ok_eq( 0, rawbuffer64->header.wParam, UINT, "%u" ); + ok_eq( 0x2d, rawbuffer64->data.keyboard.MakeCode, UINT, "%#x" ); + } + else + { + ok_eq( RIM_TYPEKEYBOARD, rawbuffer->header.dwType, UINT, "%u" ); + ok_eq( 0, rawbuffer->header.wParam, UINT, "%u" ); + ok_eq( 0x2d, rawbuffer->data.keyboard.MakeCode, UINT, "%#x" ); + } + + + /* test GetRawInputBuffer interaction with WM_INPUT messages */ + + rawinputbuffer_wndproc_count = 0; + keybd_event( 'X', 1, 0, 0 ); + keybd_event( 'X', 2, KEYEVENTF_KEYUP, 0 ); + keybd_event( 'X', 3, 0, 0 ); + keybd_event( 'X', 4, KEYEVENTF_KEYUP, 0 ); + wait_messages( 100, FALSE ); + ok_eq( 2, rawinputbuffer_wndproc_count, UINT, "%u" );
- ok(HEADER_FIELD(dwType) == RIM_TYPEKEYBOARD, "Unexpected rawinput dwType: %ld\n", HEADER_FIELD(dwType)); - ok(HEADER_FIELD(wParam) == 0 || HEADER_FIELD(wParam) == 1, "Expected wparam 0 or 1, got %Iu\n", (WPARAM)HEADER_FIELD(wParam)); - scan_code = is_wow64 ? ((RAWINPUT64 *)buffer)->data.keyboard.MakeCode : ((RAWINPUT *)buffer)->data.keyboard.MakeCode; - ok(scan_code == 0x2d, "Unexpected rawinput keyboard scan code: %x\n", scan_code); + keybd_event( 'X', 3, 0, 0 ); + keybd_event( 'X', 4, KEYEVENTF_KEYUP, 0 );
raw_devices[0].dwFlags = RIDEV_REMOVE; raw_devices[0].hwndTarget = 0; + ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE) ) );
- SetLastError(0xdeadbeef); - ret = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE)); - ok(ret, "RegisterRawInputDevices failed\n"); - ok(GetLastError() == 0xdeadbeef, "RegisterRawInputDevices returned %08lx\n", GetLastError());
- DestroyWindow(hwnd); + /* rawinput buffer survives registered device changes */
-#undef HEADER_FIELD + size = rawinput_size + 1; + todo_wine + ok_ret( 1, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) ); + todo_wine + ok_eq( rawinput_size + 1, size, UINT, "%u" ); + + raw_devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC; + raw_devices[0].usUsage = HID_USAGE_GENERIC_MOUSE; + raw_devices[0].dwFlags = RIDEV_INPUTSINK; + raw_devices[0].hwndTarget = hwnd; + ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE) ) ); + + if (is_wow64) rawinput_size = sizeof(RAWINPUTHEADER64) + sizeof(RAWMOUSE); + else rawinput_size = sizeof(RAWINPUTHEADER) + sizeof(RAWMOUSE); + + size = rawinput_size + 1; + ok_ret( 1, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) ); + ok_eq( rawinput_size + 1, size, UINT, "%u" ); + size = sizeof(buffer); + todo_wine + ok_ret( 0, GetRawInputBuffer( rawbuffer, &size, sizeof(RAWINPUTHEADER) ) ); + todo_wine + ok_eq( 0, size, UINT, "%u" ); + + raw_devices[0].dwFlags = RIDEV_REMOVE; + raw_devices[0].hwndTarget = 0; + ok_ret( 1, RegisterRawInputDevices( raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE) ) ); + + + ok_ret( 1, DestroyWindow( hwnd ) ); }
static BOOL rawinput_test_received_legacy; @@ -5534,6 +5569,7 @@ static void test_input_desktop( char **argv )
test_RegisterRawInputDevices(); test_GetRawInputData(); + test_GetRawInputBuffer();
ok_ret( 1, SetCursorPos( pos.x, pos.y ) ); } @@ -5601,7 +5637,6 @@ START_TEST(input) test_attach_input(); test_GetKeyState(); test_OemKeyScan(); - test_GetRawInputBuffer(); test_rawinput(argv[0]); test_DefRawInputProc();
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/tests/device8.c | 1 + dlls/dinput/tests/dinput_test.h | 5 ++ dlls/dinput/tests/driver_bus.c | 153 +++++++++++++++++++------------- dlls/dinput/tests/driver_hid.c | 1 + dlls/dinput/tests/driver_hid.h | 2 + dlls/dinput/tests/hid.c | 18 ++++ 6 files changed, 119 insertions(+), 61 deletions(-)
diff --git a/dlls/dinput/tests/device8.c b/dlls/dinput/tests/device8.c index d6d3a03b7bd..aa37679b0a7 100644 --- a/dlls/dinput/tests/device8.c +++ b/dlls/dinput/tests/device8.c @@ -1738,6 +1738,7 @@ static void test_hid_mouse(void)
mouse_move_count = 0; bus_send_hid_input( file, &desc, single_move, sizeof(single_move) ); + bus_wait_hid_input( file, &desc, 100 );
res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_MOUSEMOVE ); todo_wine diff --git a/dlls/dinput/tests/dinput_test.h b/dlls/dinput/tests/dinput_test.h index e13ba2421d2..e2438d6d2d1 100644 --- a/dlls/dinput/tests/dinput_test.h +++ b/dlls/dinput/tests/dinput_test.h @@ -108,6 +108,11 @@ void wait_hid_expect_( const char *file, int line, HANDLE device, struct hid_dev void send_hid_input_( const char *file, int line, HANDLE device, struct hid_device_desc *desc, struct hid_expect *expect, DWORD expect_size );
+#define wait_hid_input( a, b ) wait_hid_input_( __FILE__, __LINE__, a, NULL, b, FALSE ) +#define bus_wait_hid_input( a, b, c ) wait_hid_input_( __FILE__, __LINE__, a, b, c, FALSE ) +void wait_hid_input_( const char *file, int line, HANDLE device, struct hid_device_desc *desc, + DWORD timeout, BOOL todo ); + #define msg_wait_for_events( a, b, c ) msg_wait_for_events_( __FILE__, __LINE__, a, b, c ) DWORD msg_wait_for_events_( const char *file, int line, DWORD count, HANDLE *events, DWORD timeout );
diff --git a/dlls/dinput/tests/driver_bus.c b/dlls/dinput/tests/driver_bus.c index de6953694ce..cf42a1bcf6e 100644 --- a/dlls/dinput/tests/driver_bus.c +++ b/dlls/dinput/tests/driver_bus.c @@ -63,27 +63,13 @@ static void check_buffer_( int line, HID_XFER_PACKET *packet, struct hid_expect } }
-struct expect_queue +struct wait_queue { KSPIN_LOCK lock; - struct hid_expect *pos; - struct hid_expect *end; - struct hid_expect spurious; - struct hid_expect *buffer; IRP *pending_wait; - char context[64]; };
-static void expect_queue_init( struct expect_queue *queue ) -{ - KeInitializeSpinLock( &queue->lock ); - queue->buffer = ExAllocatePool( PagedPool, EXPECT_QUEUE_BUFFER_SIZE ); - RtlSecureZeroMemory( queue->buffer, EXPECT_QUEUE_BUFFER_SIZE ); - queue->pos = queue->buffer; - queue->end = queue->buffer; -} - -static void expect_queue_cleanup( struct expect_queue *queue ) +static void wait_queue_cleanup( struct wait_queue *queue ) { KIRQL irql; IRP *irp; @@ -101,7 +87,50 @@ static void expect_queue_cleanup( struct expect_queue *queue ) irp->IoStatus.Status = STATUS_DELETE_PENDING; IoCompleteRequest( irp, IO_NO_INCREMENT ); } +} + +static void wait_queue_unlock( struct wait_queue *queue, KIRQL irql, BOOL empty ) +{ + IRP *irp;
+ /* complete the pending wait IRP if the queue is now empty */ + if ((irp = empty ? queue->pending_wait : NULL)) + { + queue->pending_wait = NULL; + if (!IoSetCancelRoutine( irp, NULL )) irp = NULL; + } + + KeReleaseSpinLock( &queue->lock, irql ); + + if (irp) + { + irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest( irp, IO_NO_INCREMENT ); + } +} + +struct expect_queue +{ + struct wait_queue base; + struct hid_expect *pos; + struct hid_expect *end; + struct hid_expect spurious; + struct hid_expect *buffer; + char context[64]; +}; + +static void expect_queue_init( struct expect_queue *queue ) +{ + KeInitializeSpinLock( &queue->base.lock ); + queue->buffer = ExAllocatePool( PagedPool, EXPECT_QUEUE_BUFFER_SIZE ); + RtlSecureZeroMemory( queue->buffer, EXPECT_QUEUE_BUFFER_SIZE ); + queue->pos = queue->buffer; + queue->end = queue->buffer; +} + +static void expect_queue_cleanup( struct expect_queue *queue ) +{ + wait_queue_cleanup( &queue->base ); ExFreePool( queue->buffer ); }
@@ -115,7 +144,7 @@ static void expect_queue_reset( struct expect_queue *queue, void *buffer, unsign RtlSecureZeroMemory( missing, EXPECT_QUEUE_BUFFER_SIZE ); missing_end = missing;
- KeAcquireSpinLock( &queue->lock, &irql ); + KeAcquireSpinLock( &queue->base.lock, &irql ); tmp = queue->pos; while (tmp < queue->end) *missing_end++ = *tmp++;
@@ -125,7 +154,7 @@ static void expect_queue_reset( struct expect_queue *queue, void *buffer, unsign if (size) memcpy( queue->end, buffer, size ); queue->end = queue->end + size / sizeof(struct hid_expect); memcpy( context, queue->context, sizeof(context) ); - KeReleaseSpinLock( &queue->lock, irql ); + KeReleaseSpinLock( &queue->base.lock, irql );
tmp = missing; while (tmp != missing_end) @@ -150,7 +179,7 @@ static void expect_queue_reset( struct expect_queue *queue, void *buffer, unsign
static void WINAPI wait_cancel_routine( DEVICE_OBJECT *device, IRP *irp ) { - struct expect_queue *queue = irp->Tail.Overlay.DriverContext[0]; + struct wait_queue *queue = irp->Tail.Overlay.DriverContext[0]; KIRQL irql;
IoReleaseCancelSpinLock( irp->CancelIrql ); @@ -164,7 +193,7 @@ static void WINAPI wait_cancel_routine( DEVICE_OBJECT *device, IRP *irp ) IoCompleteRequest( irp, IO_NO_INCREMENT ); }
-static NTSTATUS expect_queue_add_pending_locked( struct expect_queue *queue, IRP *irp ) +static NTSTATUS wait_queue_add_pending_locked( struct wait_queue *queue, IRP *irp ) { if (queue->pending_wait) return STATUS_INVALID_PARAMETER;
@@ -184,9 +213,9 @@ static NTSTATUS expect_queue_add_pending( struct expect_queue *queue, IRP *irp ) NTSTATUS status; KIRQL irql;
- KeAcquireSpinLock( &queue->lock, &irql ); - status = expect_queue_add_pending_locked( queue, irp ); - KeReleaseSpinLock( &queue->lock, irql ); + KeAcquireSpinLock( &queue->base.lock, &irql ); + status = wait_queue_add_pending_locked( &queue->base, irp ); + KeReleaseSpinLock( &queue->base.lock, irql );
return status; } @@ -198,16 +227,16 @@ static NTSTATUS expect_queue_wait_pending( struct expect_queue *queue, IRP *irp IRP *pending; KIRQL irql;
- KeAcquireSpinLock( &queue->lock, &irql ); - if ((pending = queue->pending_wait)) + KeAcquireSpinLock( &queue->base.lock, &irql ); + if ((pending = queue->base.pending_wait)) { - queue->pending_wait = NULL; + queue->base.pending_wait = NULL; if (!IoSetCancelRoutine( pending, NULL )) pending = NULL; }
if (pending && queue->pos == queue->end) status = STATUS_SUCCESS; - else status = expect_queue_add_pending_locked( queue, irp ); - KeReleaseSpinLock( &queue->lock, irql ); + else status = wait_queue_add_pending_locked( &queue->base, irp ); + KeReleaseSpinLock( &queue->base.lock, irql );
if (pending) { @@ -225,10 +254,10 @@ static NTSTATUS expect_queue_wait( struct expect_queue *queue, IRP *irp ) KIRQL irql;
irp->IoStatus.Information = 0; - KeAcquireSpinLock( &queue->lock, &irql ); + KeAcquireSpinLock( &queue->base.lock, &irql ); if (queue->pos == queue->end) status = STATUS_SUCCESS; - else status = expect_queue_add_pending_locked( queue, irp ); - KeReleaseSpinLock( &queue->lock, irql ); + else status = wait_queue_add_pending_locked( &queue->base, irp ); + KeReleaseSpinLock( &queue->base.lock, irql );
return status; } @@ -240,14 +269,13 @@ static void expect_queue_next( struct expect_queue *queue, ULONG code, HID_XFER_ ULONG len = packet->reportBufferLen; BYTE *buf = packet->reportBuffer; BYTE id = packet->reportId; - IRP *irp = NULL; KIRQL irql;
missing = ExAllocatePool( PagedPool, EXPECT_QUEUE_BUFFER_SIZE ); RtlSecureZeroMemory( missing, EXPECT_QUEUE_BUFFER_SIZE ); missing_end = missing;
- KeAcquireSpinLock( &queue->lock, &irql ); + KeAcquireSpinLock( &queue->base.lock, &irql ); tmp = queue->pos; while (tmp < queue->end) { @@ -270,28 +298,12 @@ static void expect_queue_next( struct expect_queue *queue, ULONG code, HID_XFER_ queue->pos++; }
- if ((irp = queue->pending_wait)) - { - /* don't mark the IRP as pending if someone's already waiting */ - if (expect->ret_status == STATUS_PENDING) expect->ret_status = STATUS_SUCCESS; - - /* complete the pending wait IRP if the queue is now empty */ - if (queue->pos != queue->end) irp = NULL; - else - { - queue->pending_wait = NULL; - if (!IoSetCancelRoutine( irp, NULL )) irp = NULL; - } - } + /* don't mark the IRP as pending if someone's already waiting */ + if (expect->ret_status == STATUS_PENDING && queue->base.pending_wait) + expect->ret_status = STATUS_SUCCESS;
memcpy( context, queue->context, context_size ); - KeReleaseSpinLock( &queue->lock, irql ); - - if (irp) - { - irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest( irp, IO_NO_INCREMENT ); - } + wait_queue_unlock( &queue->base, irql, queue->pos == queue->end );
ok( tmp != &queue->spurious, "%s got spurious packet\n", context );
@@ -368,7 +380,7 @@ static void irp_queue_init( struct irp_queue *queue )
struct input_queue { - KSPIN_LOCK lock; + struct wait_queue base; BOOL is_polled; struct hid_expect *pos; struct hid_expect *end; @@ -379,7 +391,7 @@ struct input_queue
static void input_queue_init( struct input_queue *queue, BOOL is_polled ) { - KeInitializeSpinLock( &queue->lock ); + KeInitializeSpinLock( &queue->base.lock ); queue->is_polled = is_polled; queue->buffer = ExAllocatePool( PagedPool, EXPECT_QUEUE_BUFFER_SIZE ); RtlSecureZeroMemory( queue->buffer, EXPECT_QUEUE_BUFFER_SIZE ); @@ -391,6 +403,7 @@ static void input_queue_init( struct input_queue *queue, BOOL is_polled )
static void input_queue_cleanup( struct input_queue *queue ) { + wait_queue_cleanup( &queue->base ); ExFreePool( queue->buffer ); }
@@ -418,7 +431,7 @@ static NTSTATUS input_queue_read( struct input_queue *queue, IRP *irp ) NTSTATUS status; KIRQL irql;
- KeAcquireSpinLock( &queue->lock, &irql ); + KeAcquireSpinLock( &queue->base.lock, &irql ); if (input_queue_read_locked( queue, irp )) { irp_queue_push( &queue->completed, irp ); @@ -430,7 +443,7 @@ static NTSTATUS input_queue_read( struct input_queue *queue, IRP *irp ) irp_queue_push( &queue->pending, irp ); status = STATUS_PENDING; } - KeReleaseSpinLock( &queue->lock, irql ); + wait_queue_unlock( &queue->base, irql, queue->pos == queue->end );
return status; } @@ -441,7 +454,7 @@ static void input_queue_reset( struct input_queue *queue, void *in_buf, ULONG in KIRQL irql; IRP *irp;
- KeAcquireSpinLock( &queue->lock, &irql ); + KeAcquireSpinLock( &queue->base.lock, &irql ); remaining = queue->end - queue->pos; queue->pos = queue->buffer; queue->end = queue->buffer; @@ -453,13 +466,28 @@ static void input_queue_reset( struct input_queue *queue, void *in_buf, ULONG in input_queue_read_locked( queue, irp ); irp_queue_push( &queue->completed, irp ); } - KeReleaseSpinLock( &queue->lock, irql ); + wait_queue_unlock( &queue->base, irql, queue->pos == queue->end );
if (!queue->is_polled) ok( !remaining, "unread input\n" );
irp_queue_complete( &queue->completed, FALSE ); }
+/* wait for the input queue to empty */ +static NTSTATUS input_queue_wait( struct input_queue *queue, IRP *irp ) +{ + NTSTATUS status; + KIRQL irql; + + irp->IoStatus.Information = 0; + KeAcquireSpinLock( &queue->base.lock, &irql ); + if (queue->pos == queue->end) status = STATUS_SUCCESS; + else status = wait_queue_add_pending_locked( &queue->base, irp ); + KeReleaseSpinLock( &queue->base.lock, irql ); + + return status; +} + struct device { KSPIN_LOCK lock; @@ -1277,11 +1305,13 @@ static NTSTATUS pdo_handle_ioctl( struct phys_device *impl, IRP *irp, ULONG code if (in_size > EXPECT_QUEUE_BUFFER_SIZE) return STATUS_BUFFER_OVERFLOW; input_queue_reset( &impl->input_queue, in_buffer, in_size ); return STATUS_SUCCESS; + case IOCTL_WINETEST_HID_WAIT_INPUT: + return input_queue_wait( &impl->input_queue, irp ); case IOCTL_WINETEST_HID_SET_CONTEXT: if (in_size > sizeof(impl->expect_queue.context)) return STATUS_BUFFER_OVERFLOW; - KeAcquireSpinLock( &impl->expect_queue.lock, &irql ); + KeAcquireSpinLock( &impl->expect_queue.base.lock, &irql ); memcpy( impl->expect_queue.context, in_buffer, in_size ); - KeReleaseSpinLock( &impl->expect_queue.lock, irql ); + KeReleaseSpinLock( &impl->expect_queue.base.lock, irql ); return STATUS_SUCCESS; case IOCTL_WINETEST_REMOVE_DEVICE: KeAcquireSpinLock( &impl->base.lock, &irql ); @@ -1356,6 +1386,7 @@ static NTSTATUS fdo_ioctl( DEVICE_OBJECT *device, IRP *irp ) case IOCTL_WINETEST_HID_WAIT_EXPECT: case IOCTL_WINETEST_HID_SEND_INPUT: case IOCTL_WINETEST_HID_SET_CONTEXT: + case IOCTL_WINETEST_HID_WAIT_INPUT: if (in_size < sizeof(*desc)) status = STATUS_INVALID_PARAMETER; else if (!(device = find_child_device( impl, desc )) || !(pdo = pdo_from_DEVICE_OBJECT( device ))) diff --git a/dlls/dinput/tests/driver_hid.c b/dlls/dinput/tests/driver_hid.c index 5c1bda6871e..6903572b532 100644 --- a/dlls/dinput/tests/driver_hid.c +++ b/dlls/dinput/tests/driver_hid.c @@ -188,6 +188,7 @@ static NTSTATUS WINAPI driver_ioctl( DEVICE_OBJECT *device, IRP *irp ) case IOCTL_WINETEST_HID_WAIT_EXPECT: case IOCTL_WINETEST_HID_SEND_INPUT: case IOCTL_WINETEST_HID_SET_CONTEXT: + case IOCTL_WINETEST_HID_WAIT_INPUT: IoSkipCurrentIrpStackLocation( irp ); return IoCallDriver( ext->PhysicalDeviceObject, irp );
diff --git a/dlls/dinput/tests/driver_hid.h b/dlls/dinput/tests/driver_hid.h index a824e004dfa..743be1bb024 100644 --- a/dlls/dinput/tests/driver_hid.h +++ b/dlls/dinput/tests/driver_hid.h @@ -49,6 +49,7 @@ DEFINE_GUID(control_class,0xdeadbeef,0x29ef,0x4538,0xa5,0xfd,0xb6,0x95,0x73,0xa3 #define IOCTL_WINETEST_HID_SET_CONTEXT CTL_CODE(FILE_DEVICE_KEYBOARD, 0x803, METHOD_IN_DIRECT, FILE_ANY_ACCESS) #define IOCTL_WINETEST_CREATE_DEVICE CTL_CODE(FILE_DEVICE_KEYBOARD, 0x804, METHOD_IN_DIRECT, FILE_ANY_ACCESS) #define IOCTL_WINETEST_REMOVE_DEVICE CTL_CODE(FILE_DEVICE_KEYBOARD, 0x805, METHOD_IN_DIRECT, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_HID_WAIT_INPUT CTL_CODE(FILE_DEVICE_KEYBOARD, 0x806, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
struct hid_expect { @@ -173,6 +174,7 @@ static inline const char *debugstr_ioctl( ULONG code ) case IOCTL_WINETEST_HID_SET_EXPECT: return "IOCTL_WINETEST_HID_SET_EXPECT"; case IOCTL_WINETEST_HID_WAIT_EXPECT: return "IOCTL_WINETEST_HID_WAIT_EXPECT"; case IOCTL_WINETEST_HID_SEND_INPUT: return "IOCTL_WINETEST_HID_SEND_INPUT"; + case IOCTL_WINETEST_HID_WAIT_INPUT: return "IOCTL_WINETEST_HID_WAIT_INPUT"; case IOCTL_WINETEST_HID_SET_CONTEXT: return "IOCTL_WINETEST_HID_SET_CONTEXT"; case IOCTL_WINETEST_CREATE_DEVICE: return "IOCTL_WINETEST_CREATE_DEVICE"; case IOCTL_WINETEST_REMOVE_DEVICE: return "IOCTL_WINETEST_REMOVE_DEVICE"; diff --git a/dlls/dinput/tests/hid.c b/dlls/dinput/tests/hid.c index f5cc9c26f55..4dc3a60cdff 100644 --- a/dlls/dinput/tests/hid.c +++ b/dlls/dinput/tests/hid.c @@ -1001,6 +1001,24 @@ void send_hid_input_( const char *file, int line, HANDLE device, struct hid_devi ok_(file, line)( ret, "IOCTL_WINETEST_HID_SEND_INPUT failed, last error %lu\n", GetLastError() ); }
+void wait_hid_input_( const char *file, int line, HANDLE device, struct hid_device_desc *desc, + DWORD timeout, BOOL todo ) +{ + char buffer[sizeof(*desc)]; + SIZE_T size; + + if (desc) memcpy( buffer, desc, sizeof(*desc) ); + else memset( buffer, 0, sizeof(*desc) ); + size = sizeof(*desc); + + todo_wine_if(todo) { + BOOL ret = sync_ioctl_( file, line, device, IOCTL_WINETEST_HID_WAIT_INPUT, buffer, size, NULL, 0, timeout ); + ok_(file, line)( ret, "IOCTL_WINETEST_HID_WAIT_INPUT failed, last error %lu\n", GetLastError() ); + } + + set_hid_expect_( file, line, device, desc, NULL, 0 ); +} + static void test_hidp_get_input( HANDLE file, int report_id, ULONG report_len, PHIDP_PREPARSED_DATA preparsed ) { struct hid_expect expect[] =
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/tests/joystick8.c | 167 +++++++++++++++++++++++++++++++--- 1 file changed, 152 insertions(+), 15 deletions(-)
diff --git a/dlls/dinput/tests/joystick8.c b/dlls/dinput/tests/joystick8.c index 38e20072962..2932f7b3057 100644 --- a/dlls/dinput/tests/joystick8.c +++ b/dlls/dinput/tests/joystick8.c @@ -5208,13 +5208,13 @@ done: }
static HANDLE rawinput_device_added, rawinput_device_removed, rawinput_event; -static char wm_input_buf[1024]; -static UINT wm_input_len; +static UINT rawinput_len[64], rawbuffer_count[64], rawbuffer_size, rawinput_calls; +static char rawbuffer[1024]; +static RAWINPUT *rawinput; +static BOOL test_rawbuffer;
static LRESULT CALLBACK rawinput_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { - UINT size = sizeof(wm_input_buf); - if (msg == WM_INPUT_DEVICE_CHANGE) { if (wparam == GIDC_ARRIVAL) ReleaseSemaphore( rawinput_device_added, 1, NULL ); @@ -5222,8 +5222,22 @@ static LRESULT CALLBACK rawinput_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LP } if (msg == WM_INPUT) { - wm_input_len = GetRawInputData( (HRAWINPUT)lparam, RID_INPUT, (RAWINPUT *)wm_input_buf, - &size, sizeof(RAWINPUTHEADER) ); + UINT size = rawbuffer_size, i = rawinput_calls++; + + if (test_rawbuffer) + { + rawbuffer_count[i] = GetRawInputBuffer( rawinput, &size, sizeof(RAWINPUTHEADER) ); + ok( size == rawbuffer_size, "got size %u\n", size ); + } + else + { + rawinput_len[i] = GetRawInputData( (HRAWINPUT)lparam, RID_INPUT, rawinput, + &size, sizeof(RAWINPUTHEADER) ); + ok( size == rawbuffer_size, "got size %u\n", size ); + } + + rawinput = NEXTRAWINPUTBLOCK(rawinput); + rawbuffer_size = sizeof(rawbuffer) - ((char *)rawinput - rawbuffer); ReleaseSemaphore( rawinput_event, 1, NULL ); }
@@ -5300,11 +5314,11 @@ static void test_rawinput(void) }, { .code = IOCTL_HID_READ_REPORT, - .report_buf = {1,0x10,0x10,0x01,0x01,0x10,0x10,0x10,0x00}, + .report_buf = {1,0x10,0x10,0x01,0x01,0x10,0x10,0x10,0x01}, }, { .code = IOCTL_HID_READ_REPORT, - .report_buf = {1,0x10,0x10,0x01,0x01,0x10,0x10,0x10,0x00}, + .report_buf = {1,0x10,0x10,0x01,0x01,0x10,0x10,0x10,0x02}, }, { .code = IOCTL_HID_READ_REPORT, @@ -5315,11 +5329,11 @@ static void test_rawinput(void) .report_buf = {1,0x10,0x10,0x10,0xee,0x10,0x10,0x10,0x54}, }, }; - RAWINPUT *rawinput = (RAWINPUT *)wm_input_buf; RAWINPUTDEVICELIST raw_device_list[16]; RAWINPUTDEVICE raw_devices[16]; - ULONG i, res, device_count; + ULONG i, j, res, device_count, size; WCHAR path[MAX_PATH] = {0}; + char buffer[1024]; HANDLE file; UINT count; HWND hwnd; @@ -5454,7 +5468,7 @@ static void test_rawinput(void)
file = CreateFileW( path, FILE_READ_ACCESS | FILE_WRITE_ACCESS, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, - FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL ); + 0, NULL ); ok( file != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() );
for (i = 0; i < ARRAY_SIZE(injected_input); ++i) @@ -5462,7 +5476,14 @@ static void test_rawinput(void) winetest_push_context( "state[%ld]", i );
send_hid_input( file, &injected_input[i], sizeof(*injected_input) ); - + res = ReadFile( file, buffer, desc.caps.InputReportByteLength, &size, NULL ); + ok( res, "ReadFile failed, error %lu\n", GetLastError() ); + ok( size == desc.caps.InputReportByteLength, "got size %lu\n", size ); + + rawinput_calls = 0; + rawinput = (RAWINPUT *)rawbuffer; + rawbuffer_size = sizeof(rawbuffer); + memset( rawbuffer, 0, sizeof(rawbuffer) ); res = msg_wait_for_events( 1, &rawinput_event, 1000 ); ok( !res, "WaitForSingleObject returned %#lx\n", res );
@@ -5472,15 +5493,131 @@ static void test_rawinput(void) ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res ); res = msg_wait_for_events( 1, &rawinput_event, 10 ); ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res ); - - ok( wm_input_len == offsetof(RAWINPUT, data.hid.bRawData[desc.caps.InputReportByteLength]), - "got wm_input_len %u\n", wm_input_len ); + ok( rawinput_calls == 1, "got %u WM_INPUT messages\n", rawinput_calls ); + + rawinput = (RAWINPUT *)rawbuffer; + ok( rawinput->header.dwType == RIM_TYPEHID, "got dwType %lu\n", rawinput->header.dwType ); + ok( rawinput->header.dwSize == offsetof(RAWINPUT, data.hid.bRawData[desc.caps.InputReportByteLength * rawinput->data.hid.dwCount]), + "got header.dwSize %lu\n", rawinput->header.dwSize ); + ok( rawinput->header.hDevice != 0, "got hDevice %p\n", rawinput->header.hDevice ); + ok( rawinput->header.wParam == 0, "got wParam %#Ix\n", rawinput->header.wParam ); + ok( rawinput->data.hid.dwSizeHid == desc.caps.InputReportByteLength, "got dwSizeHid %lu\n", rawinput->data.hid.dwSizeHid ); + ok( rawinput->data.hid.dwCount == 1, "got dwCount %lu\n", rawinput->data.hid.dwCount ); ok( !memcmp( rawinput->data.hid.bRawData, injected_input[i].report_buf, desc.caps.InputReportByteLength ), "got unexpected report data\n" ); + ok( rawinput_len[0] == offsetof(RAWINPUT, data.hid.bRawData[desc.caps.InputReportByteLength * rawinput->data.hid.dwCount]), + "got rawinput_len[0] %u\n", rawinput_len[0] ); + + winetest_pop_context(); + } + + + /* test reading multiple reports with GetRawInputData */ + + send_hid_input( file, injected_input, sizeof(injected_input) ); + wait_hid_input( file, 5000 ); + send_hid_input( file, injected_input, sizeof(injected_input) ); + wait_hid_input( file, 5000 ); + send_hid_input( file, injected_input, sizeof(injected_input) ); + wait_hid_input( file, 5000 ); + Sleep( 100 ); + + rawinput_calls = 0; + rawinput = (RAWINPUT *)rawbuffer; + rawbuffer_size = sizeof(rawbuffer); + memset( rawbuffer, 0, sizeof(rawbuffer) ); + res = msg_wait_for_events( 1, &rawinput_event, 1000 ); + ok( !res, "WaitForSingleObject returned %#lx\n", res ); + ok( rawinput_calls >= 2, "got %u WM_INPUT messages\n", rawinput_calls ); + + rawinput = (RAWINPUT *)rawbuffer; + ok( rawinput->header.dwType == RIM_TYPEHID, "got dwType %lu\n", rawinput->header.dwType ); + ok( rawinput->header.dwSize == offsetof(RAWINPUT, data.hid.bRawData[desc.caps.InputReportByteLength * rawinput->data.hid.dwCount]), + "got header.dwSize %lu\n", rawinput->header.dwSize ); + ok( rawinput->header.hDevice != 0, "got hDevice %p\n", rawinput->header.hDevice ); + ok( rawinput->header.wParam == 0, "got wParam %#Ix\n", rawinput->header.wParam ); + ok( rawinput->data.hid.dwSizeHid == desc.caps.InputReportByteLength, "got dwSizeHid %lu\n", rawinput->data.hid.dwSizeHid ); + ok( rawinput->data.hid.dwCount == 1, "got dwCount %lu\n", rawinput->data.hid.dwCount ); + ok( rawinput_len[0] == offsetof(RAWINPUT, data.hid.bRawData[desc.caps.InputReportByteLength * rawinput->data.hid.dwCount]), + "got rawinput_len[0] %u\n", rawinput_len[0] ); + for (i = 0, j = 0; i < rawinput->data.hid.dwCount; i++, j++) + { + BYTE *report = rawinput->data.hid.bRawData + i * desc.caps.InputReportByteLength; + winetest_push_context( "%lu", i ); + ok( !memcmp( report, injected_input[j].report_buf, desc.caps.InputReportByteLength ), + "got unexpected report data\n" ); + winetest_pop_context(); + }
+ rawinput = NEXTRAWINPUTBLOCK(rawinput); + ok( rawinput->header.dwType == RIM_TYPEHID, "got dwType %lu\n", rawinput->header.dwType ); + ok( rawinput->header.dwSize == offsetof(RAWINPUT, data.hid.bRawData[desc.caps.InputReportByteLength * rawinput->data.hid.dwCount]), + "got header.dwSize %lu\n", rawinput->header.dwSize ); + ok( rawinput->header.hDevice != 0, "got hDevice %p\n", rawinput->header.hDevice ); + ok( rawinput->header.wParam == 0, "got wParam %#Ix\n", rawinput->header.wParam ); + ok( rawinput->data.hid.dwSizeHid == desc.caps.InputReportByteLength, "got dwSizeHid %lu\n", rawinput->data.hid.dwSizeHid ); + todo_wine + ok( rawinput->data.hid.dwCount >= 5 || broken(rawinput->data.hid.dwCount == 1), "got dwCount %lu\n", rawinput->data.hid.dwCount ); + ok( rawinput_len[1] == offsetof(RAWINPUT, data.hid.bRawData[desc.caps.InputReportByteLength * rawinput->data.hid.dwCount]), + "got rawinput_len[1] %u\n", rawinput_len[1] ); + for (i = 0; i < rawinput->data.hid.dwCount; i++, j++) + { + BYTE *report = rawinput->data.hid.bRawData + i * desc.caps.InputReportByteLength; + winetest_push_context( "%lu", i ); + ok( !memcmp( report, injected_input[j % ARRAY_SIZE(injected_input)].report_buf, desc.caps.InputReportByteLength ), + "got unexpected report data\n" ); winetest_pop_context(); }
+ + /* test reading multiple reports with GetRawInputBuffer */ + + send_hid_input( file, injected_input, sizeof(injected_input) ); + wait_hid_input( file, 5000 ); + send_hid_input( file, injected_input, sizeof(injected_input) ); + wait_hid_input( file, 5000 ); + send_hid_input( file, injected_input, sizeof(injected_input) ); + wait_hid_input( file, 5000 ); + Sleep( 100 ); + + test_rawbuffer = TRUE; + rawinput_calls = 0; + rawinput = (RAWINPUT *)rawbuffer; + rawbuffer_size = sizeof(rawbuffer); + memset( rawbuffer, 0, sizeof(rawbuffer) ); + res = msg_wait_for_events( 1, &rawinput_event, 1000 ); + ok( !res, "WaitForSingleObject returned %#lx\n", res ); + ok( rawinput_calls == 1, "got rawinput_calls %u\n", rawinput_calls ); + ok( rawbuffer_count[0] >= 2, "got rawbuffer_count %u\n", rawbuffer_count[0] ); + + rawinput = (RAWINPUT *)rawbuffer; + ok( rawinput->header.dwType == RIM_TYPEHID, "got dwType %lu\n", rawinput->header.dwType ); + ok( rawinput->header.dwSize == offsetof(RAWINPUT, data.hid.bRawData[desc.caps.InputReportByteLength * rawinput->data.hid.dwCount]), + "got header.dwSize %lu\n", rawinput->header.dwSize ); + ok( rawinput->header.hDevice != 0, "got hDevice %p\n", rawinput->header.hDevice ); + ok( rawinput->header.wParam == 0, "got wParam %#Ix\n", rawinput->header.wParam ); + ok( rawinput->data.hid.dwSizeHid == desc.caps.InputReportByteLength, "got dwSizeHid %lu\n", rawinput->data.hid.dwSizeHid ); + ok( rawinput->data.hid.dwCount >= 1, "got dwCount %lu\n", rawinput->data.hid.dwCount ); + + rawinput = NEXTRAWINPUTBLOCK(rawinput); + ok( rawinput->header.dwType == RIM_TYPEHID, "got dwType %lu\n", rawinput->header.dwType ); + ok( rawinput->header.dwSize == offsetof(RAWINPUT, data.hid.bRawData[desc.caps.InputReportByteLength * rawinput->data.hid.dwCount]), + "got header.dwSize %lu\n", rawinput->header.dwSize ); + ok( rawinput->header.hDevice != 0, "got hDevice %p\n", rawinput->header.hDevice ); + ok( rawinput->header.wParam == 0, "got wParam %#Ix\n", rawinput->header.wParam ); + ok( rawinput->data.hid.dwSizeHid == desc.caps.InputReportByteLength, "got dwSizeHid %lu\n", rawinput->data.hid.dwSizeHid ); + ok( rawinput->data.hid.dwCount >= 1, "got dwCount %lu\n", rawinput->data.hid.dwCount ); + + + raw_devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC; + raw_devices[0].usUsage = HID_USAGE_GENERIC_JOYSTICK; + raw_devices[0].dwFlags = RIDEV_REMOVE; + raw_devices[0].hwndTarget = 0; + count = ARRAY_SIZE(raw_devices); + ret = RegisterRawInputDevices( raw_devices, 1, sizeof(RAWINPUTDEVICE) ); + ok( ret, "RegisterRawInputDevices failed, error %lu\n", GetLastError() ); + + CloseHandle( rawinput_device_added ); CloseHandle( rawinput_device_removed ); CloseHandle( rawinput_event );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/tests/joystick8.c | 294 +++++++++++++++++++++++++++++++++- 1 file changed, 292 insertions(+), 2 deletions(-)
diff --git a/dlls/dinput/tests/joystick8.c b/dlls/dinput/tests/joystick8.c index 2932f7b3057..788f59549c2 100644 --- a/dlls/dinput/tests/joystick8.c +++ b/dlls/dinput/tests/joystick8.c @@ -49,6 +49,8 @@
#include "initguid.h"
+#define DESKTOP_ALL_ACCESS 0x01ff + DEFINE_GUID(GUID_action_mapping_1,0x00000001,0x0002,0x0003,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b); DEFINE_GUID(GUID_action_mapping_2,0x00010001,0x0002,0x0003,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b); DEFINE_GUID(GUID_map_other_device,0x00020001,0x0002,0x0003,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b); @@ -78,6 +80,48 @@ failed: return FALSE; }
+#define run_in_desktop( a, b, c ) run_in_desktop_( __FILE__, __LINE__, a, b, c ) +static void run_in_desktop_( const char *file, int line, char **argv, + const char *args, BOOL input ) +{ + const char *desktop_name = "WineTest Desktop"; + STARTUPINFOA startup = {.cb = sizeof(STARTUPINFOA)}; + PROCESS_INFORMATION info = {0}; + HDESK old_desktop, desktop; + char cmdline[MAX_PATH * 2]; + DWORD ret; + + old_desktop = OpenInputDesktop( 0, FALSE, DESKTOP_ALL_ACCESS ); + ok_(file, line)( !!old_desktop, "OpenInputDesktop failed, error %lu\n", GetLastError() ); + desktop = CreateDesktopA( desktop_name, NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL ); + ok_(file, line)( !!desktop, "CreateDesktopA failed, error %lu\n", GetLastError() ); + if (input) + { + ret = SwitchDesktop( desktop ); + ok_(file, line)( ret, "SwitchDesktop failed, error %lu\n", GetLastError() ); + } + + startup.lpDesktop = (char *)desktop_name; + sprintf( cmdline, "%s %s %s", argv[0], argv[1], args ); + ret = CreateProcessA( NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info ); + ok_(file, line)( ret, "CreateProcessA failed, error %lu\n", GetLastError() ); + if (!ret) return; + + wait_child_process( info.hProcess ); + CloseHandle( info.hThread ); + CloseHandle( info.hProcess ); + + if (input) + { + ret = SwitchDesktop( old_desktop ); + ok_(file, line)( ret, "SwitchDesktop failed, error %lu\n", GetLastError() ); + } + ret = CloseDesktop( desktop ); + ok_(file, line)( ret, "CloseDesktop failed, error %lu\n", GetLastError() ); + ret = CloseDesktop( old_desktop ); + ok_(file, line)( ret, "CloseDesktop failed, error %lu\n", GetLastError() ); +} + struct check_object_todo { BOOL type; @@ -5244,7 +5288,7 @@ static LRESULT CALLBACK rawinput_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LP return DefWindowProcW( hwnd, msg, wparam, lparam ); }
-static void test_rawinput(void) +static void test_rawinput( char **argv ) { #include "psh_hid_macros.h" static const unsigned char report_desc[] = @@ -5623,6 +5667,13 @@ static void test_rawinput(void) CloseHandle( rawinput_event ); CloseHandle( file );
+ /* test rawinput in a new, input and non-input desktop */ + strcpy( buffer, "test_rawinput_desktop " ); + WideCharToMultiByte( CP_ACP, 0, path, -1, buffer + 22, ARRAY_SIZE(buffer) - 22, NULL, NULL ); + run_in_desktop( argv, buffer, 0 ); + strcat( buffer, " input" ); + run_in_desktop( argv, buffer, 1 ); + done: hid_device_stop( &desc, 1 ); cleanup_registry_keys(); @@ -5630,8 +5681,247 @@ done: DestroyWindow( hwnd ); }
+struct rawinput_desktop_thread_params +{ + HANDLE file; + BOOL input; +}; + +static DWORD WINAPI test_rawinput_desktop_thread( void *args ) +{ + struct hid_device_desc desc = + { + .use_report_id = TRUE, + .caps = { .InputReportByteLength = 9 }, + .attributes = default_attributes, + }; + struct hid_expect injected_input = + { + .code = IOCTL_HID_READ_REPORT, + .report_buf = {1,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0}, + }; + RAWINPUTDEVICE rawdevice = {.usUsagePage = HID_USAGE_PAGE_GENERIC, .usUsage = HID_USAGE_GENERIC_JOYSTICK}; + struct rawinput_desktop_thread_params *params = args; + HDESK desktop, old_desktop, old_input = 0; + char buffer[1024]; + ULONG res, size; + HWND hwnd; + BOOL ret; + + winetest_push_context( "input %u", params->input ); + + /* non-input desktop thread may receive rawinput if its process is connected to the input desktop */ + old_desktop = GetThreadDesktop( GetCurrentThreadId() ); + ok( !!old_desktop, "GetThreadDesktop failed, error %lu\n", GetLastError() ); + desktop = CreateDesktopW( L"NonInput", NULL, NULL, 0, DESKTOP_ALL_ACCESS, 0 ); + ok( !!desktop, "CreateDesktopW failed, error %lu\n", GetLastError() ); + ret = SetThreadDesktop( desktop ); + ok( ret, "SetThreadDesktop failed, error %lu\n", GetLastError() ); + + if (params->input) + { + /* registering before switching desktop works, as window will then be foreground */ + ret = RegisterRawInputDevices( &rawdevice, 1, sizeof(RAWINPUTDEVICE) ); + ok( ret, "RegisterRawInputDevices failed, error %lu\n", GetLastError() ); + + /* input desktop thread will receive rawinput even if its process isn't connected to the input desktop */ + old_input = OpenInputDesktop( 0, FALSE, DESKTOP_ALL_ACCESS ); + ok( !!old_input, "OpenInputDesktop failed, error %lu\n", GetLastError() ); + ret = SwitchDesktop( desktop ); + ok( ret, "SwitchDesktop failed, error %lu\n", GetLastError() ); + } + + + hwnd = CreateWindowW( L"static", NULL, WS_POPUP | WS_VISIBLE, + 100, 100, 200, 200, NULL, NULL, NULL, NULL ); + ok( hwnd != NULL, "CreateWindowW failed, error %lu\n", GetLastError() ); + msg_wait_for_events( 0, NULL, 100 ); + + SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (ULONG_PTR)rawinput_wndproc ); + + if (!params->input) + { + /* non-input desktop, needs to force the window */ + rawdevice.hwndTarget = hwnd; + ret = RegisterRawInputDevices( &rawdevice, 1, sizeof(RAWINPUTDEVICE) ); + ok( ret, "RegisterRawInputDevices failed, error %lu\n", GetLastError() ); + } + + + send_hid_input( params->file, &injected_input, sizeof(injected_input) ); + res = ReadFile( params->file, buffer, desc.caps.InputReportByteLength, &size, NULL ); + ok( res, "ReadFile failed, error %lu\n", GetLastError() ); + ok( size == desc.caps.InputReportByteLength, "got size %lu\n", size ); + + rawinput_calls = 0; + rawinput = (RAWINPUT *)rawbuffer; + rawbuffer_size = sizeof(rawbuffer); + memset( rawbuffer, 0, sizeof(rawbuffer) ); + res = msg_wait_for_events( 1, &rawinput_event, 100 ); + todo_wine + ok( res == 0, "WaitForSingleObject returned %#lx\n", res ); + todo_wine + ok( rawinput_calls == 1, "got %u WM_INPUT messages\n", rawinput_calls ); + + rawinput = (RAWINPUT *)rawbuffer; + todo_wine + ok( rawinput->header.dwType == RIM_TYPEHID, "got dwType %lu\n", rawinput->header.dwType ); + todo_wine + ok( rawinput->header.dwSize == offsetof(RAWINPUT, data.hid.bRawData[desc.caps.InputReportByteLength * rawinput->data.hid.dwCount]), + "got header.dwSize %lu\n", rawinput->header.dwSize ); + todo_wine + ok( rawinput->header.hDevice != 0, "got hDevice %p\n", rawinput->header.hDevice ); + ok( rawinput->header.wParam == 0, "got wParam %#Ix\n", rawinput->header.wParam ); + todo_wine + ok( rawinput->data.hid.dwSizeHid == desc.caps.InputReportByteLength, "got dwSizeHid %lu\n", rawinput->data.hid.dwSizeHid ); + todo_wine + ok( rawinput->data.hid.dwCount >= 1, "got dwCount %lu\n", rawinput->data.hid.dwCount ); + + + DestroyWindow( hwnd ); + msg_wait_for_events( 0, NULL, 5 ); + + SetThreadDesktop( old_desktop ); + CloseDesktop( desktop ); + + if (old_input) + { + ret = SwitchDesktop( old_input ); + ok( ret, "SwitchDesktop failed, error %lu\n", GetLastError() ); + CloseDesktop( old_input ); + ok( ret, "CloseDesktop failed, error %lu\n", GetLastError() ); + } + + winetest_pop_context(); + + return 0; +} + +static void test_rawinput_desktop( const char *path, BOOL input ) +{ + struct hid_device_desc desc = + { + .use_report_id = TRUE, + .caps = { .InputReportByteLength = 9 }, + .attributes = default_attributes, + }; + struct hid_expect injected_input = + { + .code = IOCTL_HID_READ_REPORT, + .report_buf = {1,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0}, + }; + RAWINPUTDEVICE rawdevice = {.usUsagePage = HID_USAGE_PAGE_GENERIC, .usUsage = HID_USAGE_GENERIC_JOYSTICK}; + struct rawinput_desktop_thread_params params = {.input = !input}; + char buffer[1024]; + ULONG res, size; + HANDLE thread; + HDESK desktop; + HANDLE file; + HWND hwnd; + BOOL ret; + + winetest_push_context( "input %u", input ); + + desktop = GetThreadDesktop( GetCurrentThreadId() ); + ok( desktop != NULL, "GetThreadDesktop returned %p, error %lu\n", desktop, GetLastError() ); + + rawinput_device_added = CreateSemaphoreW( NULL, 0, LONG_MAX, NULL ); + ok( !!rawinput_device_added, "CreateSemaphoreW failed, error %lu\n", GetLastError() ); + rawinput_device_removed = CreateSemaphoreW( NULL, 0, LONG_MAX, NULL ); + ok( !!rawinput_device_removed, "CreateSemaphoreW failed, error %lu\n", GetLastError() ); + rawinput_event = CreateSemaphoreW( NULL, 0, LONG_MAX, NULL ); + ok( !!rawinput_event, "CreateSemaphoreW failed, error %lu\n", GetLastError() ); + + if (input) hwnd = create_foreground_window( FALSE ); + else /* non-input desktops cannot have foreground windows */ + { + hwnd = CreateWindowW( L"static", NULL, WS_POPUP | WS_VISIBLE, + 100, 100, 200, 200, NULL, NULL, NULL, NULL ); + ok( hwnd != NULL, "CreateWindowW failed, error %lu\n", GetLastError() ); + } + SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (ULONG_PTR)rawinput_wndproc ); + + file = CreateFileA( path, FILE_READ_ACCESS | FILE_WRITE_ACCESS, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + 0, NULL ); + ok( file != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() ); + + + /* non-input desktop don't receive WM_INPUT messages */ + + rawdevice.dwFlags = RIDEV_INPUTSINK; + rawdevice.hwndTarget = hwnd; + ret = RegisterRawInputDevices( &rawdevice, 1, sizeof(RAWINPUTDEVICE) ); + ok( ret, "RegisterRawInputDevices failed, error %lu\n", GetLastError() ); + + send_hid_input( file, &injected_input, sizeof(injected_input) ); + res = ReadFile( file, buffer, desc.caps.InputReportByteLength, &size, NULL ); + ok( res, "ReadFile failed, error %lu\n", GetLastError() ); + ok( size == desc.caps.InputReportByteLength, "got size %lu\n", size ); + + rawinput_calls = 0; + rawinput = (RAWINPUT *)rawbuffer; + rawbuffer_size = sizeof(rawbuffer); + memset( rawbuffer, 0, sizeof(rawbuffer) ); + res = msg_wait_for_events( 1, &rawinput_event, 100 ); + if (input) + { + todo_wine + ok( res == 0, "WaitForSingleObject returned %#lx\n", res ); + todo_wine + ok( rawinput_calls == 1, "got %u WM_INPUT messages\n", rawinput_calls ); + + rawinput = (RAWINPUT *)rawbuffer; + todo_wine + ok( rawinput->header.dwType == RIM_TYPEHID, "got dwType %lu\n", rawinput->header.dwType ); + todo_wine + ok( rawinput->header.dwSize == offsetof(RAWINPUT, data.hid.bRawData[desc.caps.InputReportByteLength * rawinput->data.hid.dwCount]), + "got header.dwSize %lu\n", rawinput->header.dwSize ); + todo_wine + ok( rawinput->header.hDevice != 0, "got hDevice %p\n", rawinput->header.hDevice ); + ok( rawinput->header.wParam == 0, "got wParam %#Ix\n", rawinput->header.wParam ); + todo_wine + ok( rawinput->data.hid.dwSizeHid == desc.caps.InputReportByteLength, "got dwSizeHid %lu\n", rawinput->data.hid.dwSizeHid ); + todo_wine + ok( rawinput->data.hid.dwCount >= 1, "got dwCount %lu\n", rawinput->data.hid.dwCount ); + } + else + { + ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res ); + ok( rawinput_calls == 0, "got %u WM_INPUT messages\n", rawinput_calls ); + } + + rawdevice.dwFlags = RIDEV_REMOVE; + rawdevice.hwndTarget = 0; + ret = RegisterRawInputDevices( &rawdevice, 1, sizeof(RAWINPUTDEVICE) ); + ok( ret, "RegisterRawInputDevices failed, error %lu\n", GetLastError() ); + + winetest_pop_context(); + + params.file = file; + thread = CreateThread( NULL, 0, test_rawinput_desktop_thread, ¶ms, 0, NULL ); + ok( thread != NULL, "CreateThread error %lu\n", GetLastError() ); + res = WaitForSingleObject( thread, 5000 ); + ok( res == WAIT_OBJECT_0, "WaitForSingleObject returned %lu, error %lu\n", res, GetLastError() ); + CloseHandle( thread ); + + CloseHandle( rawinput_device_added ); + CloseHandle( rawinput_device_removed ); + CloseHandle( rawinput_event ); + CloseHandle( file ); + + DestroyWindow( hwnd ); +} + START_TEST( joystick8 ) { + char **argv; + int argc; + + argc = winetest_get_mainargs( &argv ); + if (argc >= 3 && !strcmp( argv[2], "test_rawinput_desktop" )) + return test_rawinput_desktop( argv[3], argc > 4 && !strcmp( argv[4], "input" ) ); + dinput_test_init(); if (!bus_device_start()) goto done;
@@ -5652,7 +5942,7 @@ START_TEST( joystick8 )
test_many_axes_joystick(); test_driving_wheel_axes(); - test_rawinput(); + test_rawinput( argv ); test_windows_gaming_input(); }
From: Rémi Bernon rbernon@codeweavers.com
Looks like touches are automatically released if the device doesn't send updates regularly. --- dlls/dinput/tests/device8.c | 115 ++++++++++++++++++++++++++---------- 1 file changed, 85 insertions(+), 30 deletions(-)
diff --git a/dlls/dinput/tests/device8.c b/dlls/dinput/tests/device8.c index aa37679b0a7..db8ebbc1b31 100644 --- a/dlls/dinput/tests/device8.c +++ b/dlls/dinput/tests/device8.c @@ -1765,16 +1765,15 @@ done: }
static UINT pointer_enter_count; -static UINT pointer_down_count; static UINT pointer_up_count; -static UINT pointer_leave_count; +static HANDLE touchdown_event, touchleave_event;
static LRESULT CALLBACK touch_screen_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { if (msg == WM_POINTERENTER) pointer_enter_count++; - if (msg == WM_POINTERDOWN) pointer_down_count++; + if (msg == WM_POINTERDOWN) ReleaseSemaphore( touchdown_event, 1, NULL ); if (msg == WM_POINTERUP) pointer_up_count++; - if (msg == WM_POINTERLEAVE) pointer_leave_count++; + if (msg == WM_POINTERLEAVE) ReleaseSemaphore( touchleave_event, 1, NULL ); return DefWindowProcA( hwnd, msg, wparam, lparam ); }
@@ -1916,6 +1915,11 @@ static void test_hid_touch_screen(void) HWND hwnd; BOOL ret;
+ touchdown_event = CreateSemaphoreW( NULL, 0, LONG_MAX, NULL ); + ok( !!touchdown_event, "CreateSemaphoreW failed, error %lu\n", GetLastError() ); + touchleave_event = CreateSemaphoreW( NULL, 0, LONG_MAX, NULL ); + ok( !!touchleave_event, "CreateSemaphoreW failed, error %lu\n", GetLastError() ); + desc.report_descriptor_len = sizeof(report_desc); memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) ); desc.expect_size = sizeof(expect_max_count); @@ -1962,65 +1966,113 @@ static void test_hid_touch_screen(void) SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)touch_screen_wndproc );
- pointer_enter_count = pointer_down_count = pointer_up_count = pointer_leave_count = 0; + /* a single touch is automatically released if we don't send continuous updates */ + + pointer_enter_count = pointer_up_count = 0; bus_send_hid_input( file, &desc, &touch_single, sizeof(touch_single) );
res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_POINTER ); todo_wine ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res ); - msg_wait_for_events( 0, NULL, 5 ); /* process pending messages */ + + res = msg_wait_for_events( 1, &touchdown_event, 10 ); + todo_wine + ok( res == 0, "WaitForSingleObject returned %#lx\n", res ); + res = msg_wait_for_events( 1, &touchleave_event, 100 ); + todo_wine + ok( res == 0, "WaitForSingleObject returned %#lx\n", res ); todo_wine ok( pointer_enter_count == 1, "got pointer_enter_count %u\n", pointer_enter_count ); todo_wine - ok( pointer_down_count == 1, "got pointer_down_count %u\n", pointer_down_count ); + ok( pointer_up_count == 1, "got pointer_up_count %u\n", pointer_up_count ); + + + DestroyWindow( hwnd ); + + CloseHandle( file ); + hid_device_stop( &desc, 1 ); + + + /* create a polled device instead so updates are sent continuously */ + + desc.is_polled = TRUE; + desc.input_size = sizeof(touch_release); + memcpy( desc.input, &touch_release, sizeof(touch_release) ); + fill_context( desc.context, ARRAY_SIZE(desc.context) ); + + if (!hid_device_start( &desc, 1 )) goto done; + + swprintf( device_path, MAX_PATH, L"\\?\hid#vid_%04x&pid_%04x", desc.attributes.VendorID, + desc.attributes.ProductID ); + ret = find_hid_device_path( device_path ); + ok( ret, "Failed to find HID device matching %s\n", debugstr_w( device_path ) ); + + file = CreateFileW( L"\\?\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}", 0, 0, + NULL, OPEN_EXISTING, 0, NULL ); + ok( file != INVALID_HANDLE_VALUE, "CreateFile failed, error %lu\n", GetLastError() ); + + hwnd = create_foreground_window( TRUE ); + SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)touch_screen_wndproc ); + + + /* now the touch is continuously updated */ + + pointer_enter_count = pointer_up_count = 0; + bus_send_hid_input( file, &desc, &touch_single, sizeof(touch_single) ); + + res = msg_wait_for_events( 1, &touchdown_event, 100 ); + todo_wine + ok( res == 0, "WaitForSingleObject returned %#lx\n", res ); + res = msg_wait_for_events( 1, &touchleave_event, 100 ); + ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res ); + todo_wine + ok( pointer_enter_count == 1, "got pointer_enter_count %u\n", pointer_enter_count ); ok( pointer_up_count == 0, "got pointer_up_count %u\n", pointer_up_count ); - ok( pointer_leave_count == 0, "got pointer_leave_count %u\n", pointer_leave_count );
- pointer_enter_count = pointer_down_count = pointer_up_count = pointer_leave_count = 0; + pointer_enter_count = pointer_up_count = 0; bus_send_hid_input( file, &desc, &touch_release, sizeof(touch_release) );
- res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_POINTER ); + res = msg_wait_for_events( 1, &touchleave_event, 100 ); todo_wine - ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res ); - msg_wait_for_events( 0, NULL, 5 ); /* process pending messages */ + ok( res == 0, "WaitForSingleObject returned %#lx\n", res ); + res = msg_wait_for_events( 1, &touchdown_event, 10 ); + ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res ); ok( pointer_enter_count == 0, "got pointer_enter_count %u\n", pointer_enter_count ); - ok( pointer_down_count == 0, "got pointer_down_count %u\n", pointer_down_count ); todo_wine ok( pointer_up_count == 1, "got pointer_up_count %u\n", pointer_up_count ); - todo_wine - ok( pointer_leave_count == 1, "got pointer_leave_count %u\n", pointer_leave_count ); -
- pointer_enter_count = pointer_down_count = pointer_up_count = pointer_leave_count = 0; + pointer_enter_count = pointer_up_count = 0; bus_send_hid_input( file, &desc, &touch_multiple, sizeof(touch_multiple) );
- res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_POINTER ); + res = msg_wait_for_events( 1, &touchdown_event, 100 ); todo_wine - ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res ); - msg_wait_for_events( 0, NULL, 5 ); /* process pending messages */ + ok( res == 0, "WaitForSingleObject returned %#lx\n", res ); + res = msg_wait_for_events( 1, &touchdown_event, 100 ); todo_wine - ok( pointer_enter_count == 2, "got pointer_enter_count %u\n", pointer_enter_count ); + ok( res == 0, "WaitForSingleObject returned %#lx\n", res ); + res = msg_wait_for_events( 1, &touchleave_event, 10 ); + ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res ); todo_wine - ok( pointer_down_count == 2, "got pointer_down_count %u\n", pointer_down_count ); + ok( pointer_enter_count == 2, "got pointer_enter_count %u\n", pointer_enter_count ); ok( pointer_up_count == 0, "got pointer_up_count %u\n", pointer_up_count ); - ok( pointer_leave_count == 0, "got pointer_leave_count %u\n", pointer_leave_count );
- pointer_enter_count = pointer_down_count = pointer_up_count = pointer_leave_count = 0; + pointer_enter_count = pointer_up_count = 0; bus_send_hid_input( file, &desc, &touch_release, sizeof(touch_release) );
- res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_POINTER ); + res = msg_wait_for_events( 1, &touchleave_event, 100 ); todo_wine - ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res ); - msg_wait_for_events( 0, NULL, 5 ); /* process pending messages */ + ok( res == 0, "WaitForSingleObject returned %#lx\n", res ); + res = msg_wait_for_events( 1, &touchleave_event, 100 ); + todo_wine + ok( res == 0, "WaitForSingleObject returned %#lx\n", res ); + res = msg_wait_for_events( 1, &touchdown_event, 10 ); + ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res ); ok( pointer_enter_count == 0, "got pointer_enter_count %u\n", pointer_enter_count ); - ok( pointer_down_count == 0, "got pointer_down_count %u\n", pointer_down_count ); todo_wine ok( pointer_up_count == 2, "got pointer_up_count %u\n", pointer_up_count ); - todo_wine - ok( pointer_leave_count == 2, "got pointer_leave_count %u\n", pointer_leave_count );
DestroyWindow( hwnd ); @@ -2029,6 +2081,9 @@ static void test_hid_touch_screen(void)
done: hid_device_stop( &desc, 1 ); + + CloseHandle( touchdown_event ); + CloseHandle( touchleave_event ); }
static void test_dik_codes( IDirectInputDevice8W *device, HANDLE event, HWND hwnd, DWORD version )
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/tests/device8.c | 75 +++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+)
diff --git a/dlls/dinput/tests/device8.c b/dlls/dinput/tests/device8.c index db8ebbc1b31..c99bdd11bce 100644 --- a/dlls/dinput/tests/device8.c +++ b/dlls/dinput/tests/device8.c @@ -1909,7 +1909,11 @@ static void test_hid_touch_screen(void) .todo = TRUE, };
+ RAWINPUTDEVICE rawdevice = {.usUsagePage = HID_USAGE_PAGE_DIGITIZER, .usUsage = HID_USAGE_DIGITIZER_TOUCH_SCREEN}; + UINT rawbuffer_count, rawbuffer_size; WCHAR device_path[MAX_PATH]; + char rawbuffer[1024]; + RAWINPUT *rawinput; HANDLE file; DWORD res; HWND hwnd; @@ -1987,6 +1991,77 @@ static void test_hid_touch_screen(void) ok( pointer_up_count == 1, "got pointer_up_count %u\n", pointer_up_count );
+ /* test that we receive HID rawinput type with the touchscreen */ + + rawdevice.dwFlags = RIDEV_INPUTSINK; + rawdevice.hwndTarget = hwnd; + ret = RegisterRawInputDevices( &rawdevice, 1, sizeof(RAWINPUTDEVICE) ); + ok( ret, "RegisterRawInputDevices failed, error %lu\n", GetLastError() ); + + bus_send_hid_input( file, &desc, &touch_multiple, sizeof(touch_multiple) ); + res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_POINTER ); + todo_wine + ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res ); + bus_send_hid_input( file, &desc, &touch_release, sizeof(touch_release) ); + res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_POINTER ); + todo_wine + ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res ); + + memset( rawbuffer, 0, sizeof(rawbuffer) ); + rawinput = (RAWINPUT *)rawbuffer; + rawbuffer_size = sizeof(rawbuffer); + rawbuffer_count = GetRawInputBuffer( rawinput, &rawbuffer_size, sizeof(RAWINPUTHEADER) ); + ok( rawbuffer_count == 2, "got rawbuffer_count %u\n", rawbuffer_count ); + ok( rawbuffer_size == sizeof(rawbuffer), "got rawbuffer_size %u\n", rawbuffer_size ); + + rawinput = (RAWINPUT *)rawbuffer; + ok( rawinput->header.dwType == RIM_TYPEHID, "got dwType %lu\n", rawinput->header.dwType ); + ok( rawinput->header.dwSize == offsetof(RAWINPUT, data.hid.bRawData[desc.caps.InputReportByteLength * rawinput->data.hid.dwCount]), + "got header.dwSize %lu\n", rawinput->header.dwSize ); + ok( rawinput->header.hDevice != 0, "got hDevice %p\n", rawinput->header.hDevice ); + ok( rawinput->header.wParam == 0, "got wParam %#Ix\n", rawinput->header.wParam ); + ok( rawinput->data.hid.dwSizeHid == desc.caps.InputReportByteLength, "got dwSizeHid %lu\n", rawinput->data.hid.dwSizeHid ); + ok( rawinput->data.hid.dwCount == 1, "got dwCount %lu\n", rawinput->data.hid.dwCount ); + ok( !memcmp( rawinput->data.hid.bRawData, touch_multiple.report_buf, desc.caps.InputReportByteLength ), + "got unexpected report data\n" ); + + rawdevice.dwFlags = RIDEV_REMOVE; + rawdevice.hwndTarget = 0; + ret = RegisterRawInputDevices( &rawdevice, 1, sizeof(RAWINPUTDEVICE) ); + ok( ret, "RegisterRawInputDevices failed, error %lu\n", GetLastError() ); + + + /* test that we don't receive mouse rawinput type with the touchscreen */ + + memset( rawbuffer, 0, sizeof(rawbuffer) ); + rawdevice.usUsagePage = HID_USAGE_PAGE_GENERIC; + rawdevice.usUsage = HID_USAGE_GENERIC_MOUSE; + rawdevice.dwFlags = RIDEV_INPUTSINK; + rawdevice.hwndTarget = hwnd; + ret = RegisterRawInputDevices( &rawdevice, 1, sizeof(RAWINPUTDEVICE) ); + ok( ret, "RegisterRawInputDevices failed, error %lu\n", GetLastError() ); + + bus_send_hid_input( file, &desc, &touch_multiple, sizeof(touch_multiple) ); + res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_POINTER ); + todo_wine + ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res ); + bus_send_hid_input( file, &desc, &touch_release, sizeof(touch_release) ); + res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_POINTER ); + todo_wine + ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res ); + + rawinput = (RAWINPUT *)rawbuffer; + rawbuffer_size = sizeof(rawbuffer); + rawbuffer_count = GetRawInputBuffer( rawinput, &rawbuffer_size, sizeof(RAWINPUTHEADER) ); + ok( rawbuffer_count == 0, "got rawbuffer_count %u\n", rawbuffer_count ); + ok( rawbuffer_size == 0, "got rawbuffer_size %u\n", rawbuffer_size ); + + rawdevice.dwFlags = RIDEV_REMOVE; + rawdevice.hwndTarget = 0; + ret = RegisterRawInputDevices( &rawdevice, 1, sizeof(RAWINPUTDEVICE) ); + ok( ret, "RegisterRawInputDevices failed, error %lu\n", GetLastError() ); + + DestroyWindow( hwnd );
CloseHandle( file );
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=142716
Your paranoid android.
=== w8 (32 bit report) ===
dinput: device8.c:2014: Test failed: got rawbuffer_count 1 device8.c:2056: Test failed: got rawbuffer_count 1 device8.c:2057: Test failed: got rawbuffer_size 1024
=== w1064_tsign (64 bit report) ===
dinput: device8.c:2113: Test failed: WaitForSingleObject returned 0x102 device8.c:2131: Test failed: WaitForSingleObject returned 0 device8.c:2142: Test failed: WaitForSingleObject returned 0x102
=== w7u_2qxl (32 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w7u_adm (32 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w7u_el (32 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w8 (32 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w8adm (32 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w864 (32 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w1064v1507 (32 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w1064v1809 (32 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w1064_tsign (32 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w10pro64 (32 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w10pro64_en_AE_u8 (32 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w11pro64 (32 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w7pro64 (64 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w864 (64 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w1064v1507 (64 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w1064v1809 (64 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w1064_2qxl (64 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w1064_adm (64 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w1064_tsign (64 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w10pro64 (64 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w10pro64_ar (64 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w10pro64_ja (64 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w10pro64_zh_CN (64 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w11pro64_amd (64 bit report) ===
dinput: Fatal: test 'driver_bus' does not exist.
=== w7u_2qxl (32 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w7u_adm (32 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w7u_el (32 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w8 (32 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w8adm (32 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w864 (32 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w1064v1507 (32 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w1064v1809 (32 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w1064_tsign (32 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w10pro64 (32 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w10pro64_en_AE_u8 (32 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w11pro64 (32 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w7pro64 (64 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w864 (64 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w1064v1507 (64 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w1064v1809 (64 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w1064_2qxl (64 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w1064_adm (64 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w1064_tsign (64 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w10pro64 (64 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w10pro64_ar (64 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w10pro64_ja (64 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w10pro64_zh_CN (64 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w11pro64_amd (64 bit report) ===
dinput: Fatal: test 'driver_hid' does not exist.
=== w7u_2qxl (32 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w7u_adm (32 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w7u_el (32 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w8 (32 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w8adm (32 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w864 (32 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w1064v1507 (32 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w1064v1809 (32 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w1064_tsign (32 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w10pro64 (32 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w10pro64_en_AE_u8 (32 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w11pro64 (32 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w7pro64 (64 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w864 (64 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w1064v1507 (64 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w1064v1809 (64 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w1064_2qxl (64 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w1064_adm (64 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w1064_tsign (64 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w10pro64 (64 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w10pro64_ar (64 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w10pro64_ja (64 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w10pro64_zh_CN (64 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w11pro64_amd (64 bit report) ===
dinput: Fatal: test 'driver_hid_poll' does not exist.
=== w864 (32 bit report) ===
user32: input.c:1990: Test failed: 1: GetRawInputData returned 16, error -559038737 input.c:1991: Test failed: 1: GetLastError returned 3735928559, error -559038737
=== w1064v1507 (32 bit report) ===
user32: input.c:1990: Test failed: 1: GetRawInputData returned 16, error -559038737 input.c:1991: Test failed: 1: GetLastError returned 3735928559, error -559038737
=== w1064v1809 (32 bit report) ===
user32: input.c:1990: Test failed: 1: GetRawInputData returned 16, error -559038737 input.c:1991: Test failed: 1: GetLastError returned 3735928559, error -559038737
=== w1064_tsign (32 bit report) ===
user32: input.c:1990: Test failed: 1: GetRawInputData returned 16, error -559038737 input.c:1991: Test failed: 1: GetLastError returned 3735928559, error -559038737
=== w10pro64 (32 bit report) ===
user32: input.c:1990: Test failed: 1: GetRawInputData returned 16, error -559038737 input.c:1991: Test failed: 1: GetLastError returned 3735928559, error -559038737
=== w10pro64_en_AE_u8 (32 bit report) ===
user32: input.c:1990: Test failed: 1: GetRawInputData returned 16, error -559038737 input.c:1991: Test failed: 1: GetLastError returned 3735928559, error -559038737
=== w11pro64 (32 bit report) ===
user32: input.c:4012: Test failed: layered 4: button_up_hwnd_todo 0: got MSG_TEST_WIN hwnd 00050040, msg WM_LBUTTONUP, wparam 0, lparam 0x320032 input.c:4012: Test failed: layered 4: button_up_hwnd_todo 1 (missing): MSG_TEST_WIN hwnd 00050040, WM_LBUTTONUP, wparam 0, lparam 0x320032 input.c:1990: Test failed: 1: GetRawInputData returned 16, error -559038737 input.c:1991: Test failed: 1: GetLastError returned 3735928559, error -559038737