-- v7: win32u: Get rid of the rawinput thread data and buffer. server: Fix rawinput buffer sizes and alignment on WoW64. server: Move rawinput message conversion from win32u. server: Stop using hardware_msg_data in rawinput_message. server: Combine HID usage page and usage together. server: Stop using union rawinput in hw_input_t. dinput/tests: Add more tests for HID rawinput buffer. dinput/tests: Add a helper to wait on HID input reads. user32/tests: Rewrite the rawinput buffer test with keyboard input. user32/tests: Run rawinput device tests in the separate desktop.
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 | 466 ++++++++++++++++++++------------------ 1 file changed, 241 insertions(+), 225 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 7179ed93bf0..3b2d31c14bd 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -1897,334 +1897,350 @@ 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_INPUT, &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_INPUT, &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()); - - 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()); - - 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); + 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); + rawinput_size = sizeof(RAWINPUTHEADER) + sizeof(RAWKEYBOARD); + 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 = create_foreground_window( TRUE ); + SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)rawinputbuffer_wndproc );
- 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(); - - 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 );
- 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); + + 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" ); + }
- 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); + + /* 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" ); + + 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 */ + + 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" );
-#undef HEADER_FIELD + 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 +5550,7 @@ static void test_input_desktop( char **argv )
test_RegisterRawInputDevices(); test_GetRawInputData(); + test_GetRawInputBuffer();
ok_ret( 1, SetCursorPos( pos.x, pos.y ) ); } @@ -5601,7 +5618,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/win32u/message.c | 12 +++++------- server/protocol.def | 11 +++++++++-- server/queue.c | 19 ++++++++++--------- server/trace.c | 32 ++++++++------------------------ 4 files changed, 32 insertions(+), 42 deletions(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 0cd20684b4e..08222fd460f 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -3549,16 +3549,14 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r { case WM_INPUT: case WM_INPUT_DEVICE_CHANGE: - req->input.hw.rawinput.type = rawinput->header.dwType; switch (rawinput->header.dwType) { case RIM_TYPEHID: - req->input.hw.rawinput.hid.device = HandleToUlong( rawinput->header.hDevice ); - req->input.hw.rawinput.hid.param = rawinput->header.wParam; - req->input.hw.rawinput.hid.usage_page = hid_usage_page; - req->input.hw.rawinput.hid.usage = hid_usage; - req->input.hw.rawinput.hid.count = rawinput->data.hid.dwCount; - req->input.hw.rawinput.hid.length = rawinput->data.hid.dwSizeHid; + req->input.hw.wparam = rawinput->header.wParam; + req->input.hw.hid.device = HandleToUlong( rawinput->header.hDevice ); + req->input.hw.hid.usage = MAKELONG(hid_usage, hid_usage_page); + req->input.hw.hid.count = rawinput->data.hid.dwCount; + req->input.hw.hid.length = rawinput->data.hid.dwSizeHid; wine_server_add_data( req, rawinput->data.hid.bRawData, rawinput->data.hid.dwCount * rawinput->data.hid.dwSizeHid ); break; diff --git a/server/protocol.def b/server/protocol.def index 5d60e7fcda3..29461c80af2 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -360,8 +360,15 @@ typedef union { int type; /* INPUT_HARDWARE */ unsigned int msg; /* message code */ - lparam_t lparam; /* message param */ - union rawinput rawinput;/* rawinput message data */ + lparam_t wparam; /* parameters */ + lparam_t lparam; /* parameters */ + struct + { + unsigned int device; /* rawinput device index */ + unsigned int usage; /* HID device usage */ + unsigned int count; /* HID report count */ + unsigned int length; /* HID report length */ + } hid; } hw; } hw_input_t;
diff --git a/server/queue.c b/server/queue.c index cd913ae03e5..cc4472ba2a5 100644 --- a/server/queue.c +++ b/server/queue.c @@ -2129,13 +2129,8 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ raw_msg.source = source; raw_msg.time = get_tick_count(); raw_msg.message = input->hw.msg; - - if (input->hw.rawinput.type == RIM_TYPEHID) - { - raw_msg.hid_report = get_req_data(); - report_size = input->hw.rawinput.hid.length * input->hw.rawinput.hid.count; - } - + raw_msg.hid_report = get_req_data(); + report_size = input->hw.hid.length * input->hw.hid.count; if (report_size != get_req_data_size()) { set_error( STATUS_INVALID_PARAMETER ); @@ -2143,8 +2138,14 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ }
msg_data = &raw_msg.data; - msg_data->size = sizeof(*msg_data) + report_size; - msg_data->rawinput = input->hw.rawinput; + msg_data->size = sizeof(*msg_data) + report_size; + msg_data->rawinput.hid.type = RIM_TYPEHID; + msg_data->rawinput.hid.device = input->hw.hid.device; + msg_data->rawinput.hid.param = input->hw.wparam; + msg_data->rawinput.hid.usage_page = HIWORD(input->hw.hid.usage); + msg_data->rawinput.hid.usage = LOWORD(input->hw.hid.usage); + msg_data->rawinput.hid.count = input->hw.hid.count; + msg_data->rawinput.hid.length = input->hw.hid.length;
enum_processes( queue_rawinput_message, &raw_msg ); return; diff --git a/server/trace.c b/server/trace.c index 1b65d2b977e..3bcfc700519 100644 --- a/server/trace.c +++ b/server/trace.c @@ -421,29 +421,6 @@ static void dump_irp_params( const char *prefix, const irp_params_t *data ) } }
-static void dump_rawinput( const char *prefix, const union rawinput *rawinput ) -{ - switch (rawinput->type) - { - case RIM_TYPEMOUSE: - fprintf( stderr, "%s{type=MOUSE,x=%d,y=%d,data=%08x}", prefix, rawinput->mouse.x, - rawinput->mouse.y, rawinput->mouse.data ); - break; - case RIM_TYPEKEYBOARD: - fprintf( stderr, "%s{type=KEYBOARD,message=%04x,vkey=%04hx,scan=%04hx}", prefix, - rawinput->kbd.message, rawinput->kbd.vkey, rawinput->kbd.scan ); - break; - case RIM_TYPEHID: - fprintf( stderr, "%s{type=HID,device=%04x,param=%04x,page=%04hx,usage=%04hx,count=%u,length=%u}", - prefix, rawinput->hid.device, rawinput->hid.param, rawinput->hid.usage_page, - rawinput->hid.usage, rawinput->hid.count, rawinput->hid.length ); - break; - default: - fprintf( stderr, "%s{type=%04x}", prefix, rawinput->type ); - break; - } -} - static void dump_hw_input( const char *prefix, const hw_input_t *input ) { switch (input->type) @@ -463,12 +440,19 @@ static void dump_hw_input( const char *prefix, const hw_input_t *input ) break; case INPUT_HARDWARE: fprintf( stderr, "%s{type=HARDWARE,msg=%04x", prefix, input->hw.msg ); + dump_uint64( ",wparam=", &input->hw.wparam ); dump_uint64( ",lparam=", &input->hw.lparam ); switch (input->hw.msg) { case WM_INPUT: + fprintf( stderr, "%s{type=HID,device=%04x,usage=%04x,count=%u,length=%u}", + prefix, input->hw.hid.device, input->hw.hid.usage, + input->hw.hid.count, input->hw.hid.length ); + break; case WM_INPUT_DEVICE_CHANGE: - dump_rawinput( ",rawinput=", &input->hw.rawinput ); + fprintf( stderr, "%s{type=HID,device=%04x,usage=%04x}", + prefix, input->hw.hid.device, input->hw.hid.usage ); + break; } fputc( '}', stderr ); break;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/rawinput.c | 3 +-- server/protocol.def | 6 ++---- server/queue.c | 14 +++++++------- server/trace.c | 4 ++-- 4 files changed, 12 insertions(+), 15 deletions(-)
diff --git a/dlls/win32u/rawinput.c b/dlls/win32u/rawinput.c index e6c442c6ba6..3ea29f2da77 100644 --- a/dlls/win32u/rawinput.c +++ b/dlls/win32u/rawinput.c @@ -899,8 +899,7 @@ BOOL WINAPI NtUserRegisterRawInputDevices( const RAWINPUTDEVICE *devices, UINT d
for (i = 0; i < device_count; ++i) { - server_devices[i].usage_page = registered_devices[i].usUsagePage; - server_devices[i].usage = registered_devices[i].usUsage; + server_devices[i].usage = MAKELONG(registered_devices[i].usUsage, registered_devices[i].usUsagePage); server_devices[i].flags = registered_devices[i].dwFlags; server_devices[i].target = wine_server_user_handle( registered_devices[i].hwndTarget ); } diff --git a/server/protocol.def b/server/protocol.def index 29461c80af2..97713e0ac91 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -301,8 +301,7 @@ union rawinput int type; /* RIM_TYPEHID */ unsigned int device; /* rawinput device index */ unsigned int param; /* rawinput message param */ - unsigned short usage_page;/* HID usage page */ - unsigned short usage; /* HID usage */ + unsigned int usage; /* HID device usage */ unsigned int count; /* HID report count */ unsigned int length; /* HID report length */ } hid; @@ -885,8 +884,7 @@ typedef struct
struct rawinput_device { - unsigned short usage_page; - unsigned short usage; + unsigned int usage; unsigned int flags; user_handle_t target; }; diff --git a/server/queue.c b/server/queue.c index cc4472ba2a5..dad51e06ceb 100644 --- a/server/queue.c +++ b/server/queue.c @@ -35,6 +35,7 @@ #include "winuser.h" #include "winternl.h" #include "ntuser.h" +#include "hidusage.h"
#include "handle.h" #include "file.h" @@ -1637,13 +1638,13 @@ static user_handle_t find_hardware_message_window( struct desktop *desktop, stru return win; }
-static struct rawinput_device *find_rawinput_device( struct process *process, unsigned short usage_page, unsigned short usage ) +static struct rawinput_device *find_rawinput_device( struct process *process, unsigned int usage ) { struct rawinput_device *device, *end;
for (device = process->rawinput_devices, end = device + process->rawinput_device_count; device != end; device++) { - if (device->usage_page != usage_page || device->usage != usage) continue; + if (device->usage != usage) continue; return device; }
@@ -1808,7 +1809,7 @@ static int queue_rawinput_message( struct process* process, void *arg ) else if (raw_msg->data.rawinput.type == RIM_TYPEKEYBOARD) device = process->rawinput_kbd; else - device = find_rawinput_device( process, raw_msg->data.rawinput.hid.usage_page, raw_msg->data.rawinput.hid.usage ); + device = find_rawinput_device( process, raw_msg->data.rawinput.hid.usage ); if (!device) return 0;
if (raw_msg->message == WM_INPUT_DEVICE_CHANGE && !(device->flags & RIDEV_DEVNOTIFY)) return 0; @@ -2142,8 +2143,7 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ msg_data->rawinput.hid.type = RIM_TYPEHID; msg_data->rawinput.hid.device = input->hw.hid.device; msg_data->rawinput.hid.param = input->hw.wparam; - msg_data->rawinput.hid.usage_page = HIWORD(input->hw.hid.usage); - msg_data->rawinput.hid.usage = LOWORD(input->hw.hid.usage); + msg_data->rawinput.hid.usage = input->hw.hid.usage; msg_data->rawinput.hid.count = input->hw.hid.count; msg_data->rawinput.hid.length = input->hw.hid.length;
@@ -3506,6 +3506,6 @@ DECL_HANDLER(update_rawinput_devices) process->rawinput_device_count = device_count; memcpy( process->rawinput_devices, devices, size );
- process->rawinput_mouse = find_rawinput_device( process, 1, 2 ); - process->rawinput_kbd = find_rawinput_device( process, 1, 6 ); + process->rawinput_mouse = find_rawinput_device( process, MAKELONG(HID_USAGE_GENERIC_MOUSE, HID_USAGE_PAGE_GENERIC) ); + process->rawinput_kbd = find_rawinput_device( process, MAKELONG(HID_USAGE_GENERIC_KEYBOARD, HID_USAGE_PAGE_GENERIC) ); } diff --git a/server/trace.c b/server/trace.c index 3bcfc700519..8ad6ffe57fc 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1341,8 +1341,8 @@ static void dump_varargs_rawinput_devices(const char *prefix, data_size_t size ) while (size >= sizeof(*device)) { device = cur_data; - fprintf( stderr, "{usage_page=%04x,usage=%04x,flags=%08x,target=%08x}", - device->usage_page, device->usage, device->flags, device->target ); + fprintf( stderr, "{usage=%04x,flags=%08x,target=%08x}", + device->usage, device->flags, device->target ); size -= sizeof(*device); remove_data( sizeof(*device) ); if (size) fputc( ',', stderr );
From: Rémi Bernon rbernon@codeweavers.com
--- server/protocol.def | 2 +- server/queue.c | 79 +++++++++++++++++++++------------------------ 2 files changed, 38 insertions(+), 43 deletions(-)
diff --git a/server/protocol.def b/server/protocol.def index 97713e0ac91..419cf763063 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -300,7 +300,7 @@ union rawinput { int type; /* RIM_TYPEHID */ unsigned int device; /* rawinput device index */ - unsigned int param; /* rawinput message param */ + unsigned int wparam; /* rawinput message wparam */ unsigned int usage; /* HID device usage */ unsigned int count; /* HID report count */ unsigned int length; /* HID report length */ diff --git a/server/queue.c b/server/queue.c index dad51e06ceb..07870f98711 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1789,7 +1789,9 @@ struct rawinput_message struct hw_msg_source source; unsigned int time; unsigned int message; - struct hardware_msg_data data; + lparam_t info; + unsigned int flags; + union rawinput rawinput; const void *hid_report; };
@@ -1800,16 +1802,17 @@ static int queue_rawinput_message( struct process* process, void *arg ) const struct rawinput_device *device = NULL; struct desktop *target_desktop = NULL, *desktop = NULL; struct thread *target_thread = NULL, *foreground = NULL; + struct hardware_msg_data *msg_data; struct message *msg; data_size_t report_size; int wparam = RIM_INPUT;
- if (raw_msg->data.rawinput.type == RIM_TYPEMOUSE) + if (raw_msg->rawinput.type == RIM_TYPEMOUSE) device = process->rawinput_mouse; - else if (raw_msg->data.rawinput.type == RIM_TYPEKEYBOARD) + else if (raw_msg->rawinput.type == RIM_TYPEKEYBOARD) device = process->rawinput_kbd; else - device = find_rawinput_device( process, raw_msg->data.rawinput.hid.usage ); + device = find_rawinput_device( process, raw_msg->rawinput.hid.usage ); if (!device) return 0;
if (raw_msg->message == WM_INPUT_DEVICE_CHANGE && !(device->flags & RIDEV_DEVNOTIFY)) return 0; @@ -1829,23 +1832,24 @@ static int queue_rawinput_message( struct process* process, void *arg ) wparam = RIM_INPUTSINK; }
- if (raw_msg->data.rawinput.type != RIM_TYPEHID || !raw_msg->hid_report) report_size = 0; - else report_size = raw_msg->data.size - sizeof(raw_msg->data); - - if (!(msg = alloc_hardware_message( raw_msg->data.info, raw_msg->source, raw_msg->time, report_size ))) - goto done; + if (raw_msg->rawinput.type != RIM_TYPEHID || !raw_msg->hid_report) report_size = 0; + else report_size = raw_msg->rawinput.hid.count * raw_msg->rawinput.hid.length;
+ if (!(msg = alloc_hardware_message( raw_msg->info, raw_msg->source, raw_msg->time, report_size ))) goto done; msg->win = device->target; msg->msg = raw_msg->message; msg->wparam = wparam; msg->lparam = 0; - memcpy( msg->data, &raw_msg->data, sizeof(raw_msg->data) ); - if (report_size) memcpy( (struct hardware_msg_data *)msg->data + 1, raw_msg->hid_report, report_size );
- if (raw_msg->message == WM_INPUT_DEVICE_CHANGE && raw_msg->data.rawinput.type == RIM_TYPEHID) + msg_data = msg->data; + msg_data->flags = raw_msg->flags; + msg_data->rawinput = raw_msg->rawinput; + if (report_size) memcpy( msg_data + 1, raw_msg->hid_report, report_size ); + + if (raw_msg->message == WM_INPUT_DEVICE_CHANGE && raw_msg->rawinput.type == RIM_TYPEHID) { - msg->wparam = raw_msg->data.rawinput.hid.param; - msg->lparam = raw_msg->data.rawinput.hid.device; + msg->wparam = raw_msg->rawinput.hid.wparam; + msg->lparam = raw_msg->rawinput.hid.device; }
queue_hardware_message( desktop, msg, 1 ); @@ -1924,14 +1928,12 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons raw_msg.time = time; raw_msg.message = WM_INPUT;
- msg_data = &raw_msg.data; - msg_data->info = input->mouse.info; - msg_data->size = sizeof(*msg_data); - msg_data->flags = flags; - msg_data->rawinput.type = RIM_TYPEMOUSE; - msg_data->rawinput.mouse.x = x - desktop->cursor.x; - msg_data->rawinput.mouse.y = y - desktop->cursor.y; - msg_data->rawinput.mouse.data = input->mouse.data; + raw_msg.info = input->mouse.info; + raw_msg.flags = flags; + raw_msg.rawinput.type = RIM_TYPEMOUSE; + raw_msg.rawinput.mouse.x = x - desktop->cursor.x; + raw_msg.rawinput.mouse.y = y - desktop->cursor.y; + raw_msg.rawinput.mouse.data = input->mouse.data;
enum_processes( queue_rawinput_message, &raw_msg ); release_object( foreground ); @@ -2062,14 +2064,12 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c raw_msg.time = time; raw_msg.message = WM_INPUT;
- msg_data = &raw_msg.data; - msg_data->info = input->kbd.info; - msg_data->size = sizeof(*msg_data); - msg_data->flags = input->kbd.flags; - msg_data->rawinput.type = RIM_TYPEKEYBOARD; - msg_data->rawinput.kbd.message = message_code; - msg_data->rawinput.kbd.vkey = vkey; - msg_data->rawinput.kbd.scan = input->kbd.scan; + raw_msg.info = input->kbd.info; + raw_msg.flags = input->kbd.flags; + raw_msg.rawinput.type = RIM_TYPEKEYBOARD; + raw_msg.rawinput.kbd.message = message_code; + raw_msg.rawinput.kbd.vkey = vkey; + raw_msg.rawinput.kbd.scan = input->kbd.scan;
enum_processes( queue_rawinput_message, &raw_msg ); release_object( foreground ); @@ -2117,10 +2117,8 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ unsigned int origin, const hw_input_t *input ) { struct hw_msg_source source = { IMDT_UNAVAILABLE, origin }; - struct hardware_msg_data *msg_data; struct rawinput_message raw_msg; struct message *msg; - data_size_t report_size = 0;
switch (input->hw.msg) { @@ -2131,21 +2129,18 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ raw_msg.time = get_tick_count(); raw_msg.message = input->hw.msg; raw_msg.hid_report = get_req_data(); - report_size = input->hw.hid.length * input->hw.hid.count; - if (report_size != get_req_data_size()) + if (input->hw.hid.length * input->hw.hid.count != get_req_data_size()) { set_error( STATUS_INVALID_PARAMETER ); return; }
- msg_data = &raw_msg.data; - msg_data->size = sizeof(*msg_data) + report_size; - msg_data->rawinput.hid.type = RIM_TYPEHID; - msg_data->rawinput.hid.device = input->hw.hid.device; - msg_data->rawinput.hid.param = input->hw.wparam; - msg_data->rawinput.hid.usage = input->hw.hid.usage; - msg_data->rawinput.hid.count = input->hw.hid.count; - msg_data->rawinput.hid.length = input->hw.hid.length; + raw_msg.rawinput.hid.type = RIM_TYPEHID; + raw_msg.rawinput.hid.device = input->hw.hid.device; + raw_msg.rawinput.hid.wparam = input->hw.wparam; + raw_msg.rawinput.hid.usage = input->hw.hid.usage; + raw_msg.rawinput.hid.count = input->hw.hid.count; + raw_msg.rawinput.hid.length = input->hw.hid.length;
enum_processes( queue_rawinput_message, &raw_msg ); return;
From: Rémi Bernon rbernon@codeweavers.com
Appending the entire RAWMOUSE / RAWKEYBOARD / RAWHID + report structs after the hardware message data, instead of using a custom intermediate structure. --- dlls/user32/tests/input.c | 11 +-- dlls/win32u/rawinput.c | 127 +++++---------------------- server/protocol.def | 32 ++----- server/queue.c | 180 +++++++++++++++++++++++++++++++------- tools/make_requests | 2 +- 5 files changed, 175 insertions(+), 177 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 3b2d31c14bd..2f3a7fffe0a 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -1915,7 +1915,6 @@ static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wpara
size = sizeof(buffer); 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" );
@@ -1958,9 +1957,8 @@ static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wpara * it needs one more byte to return success */ 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" ); + if (is_wow64) 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 */ @@ -1999,7 +1997,6 @@ static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wpara size = sizeof(rawinput); rawinput_size = sizeof(RAWINPUTHEADER) + sizeof(RAWKEYBOARD); 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 ); @@ -2013,7 +2010,6 @@ static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wpara { 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() ); @@ -2170,7 +2166,6 @@ static void test_GetRawInputBuffer(void)
size = 0; ok_ret( 0, GetRawInputBuffer( NULL, &size, sizeof(RAWINPUTHEADER) ) ); - todo_wine ok_eq( rawinput_size, size, UINT, "%u" );
size = sizeof(buffer); @@ -2212,9 +2207,7 @@ static void test_GetRawInputBuffer(void) /* rawinput buffer survives registered device changes */
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; @@ -2230,9 +2223,7 @@ static void test_GetRawInputBuffer(void) 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; diff --git a/dlls/win32u/rawinput.c b/dlls/win32u/rawinput.c index 3ea29f2da77..524d1b820b2 100644 --- a/dlls/win32u/rawinput.c +++ b/dlls/win32u/rawinput.c @@ -73,125 +73,40 @@ static struct rawinput_thread_data *get_rawinput_thread_data(void) return data; }
-static bool rawinput_from_hardware_message( RAWINPUT *rawinput, const struct hardware_msg_data *msg_data ) +static BOOL rawinput_from_hardware_message( RAWINPUT *rawinput, const struct hardware_msg_data *msg_data ) { - SIZE_T size; + SIZE_T size = msg_data->size - sizeof(*msg_data); + if (sizeof(RAWINPUTHEADER) + size > rawinput->header.dwSize) return FALSE; + + rawinput->header.dwType = msg_data->rawinput.type; + rawinput->header.dwSize = sizeof(RAWINPUTHEADER) + size; + rawinput->header.hDevice = UlongToHandle( msg_data->rawinput.device ); + rawinput->header.wParam = msg_data->rawinput.wparam;
- rawinput->header.dwType = msg_data->rawinput.type; if (msg_data->rawinput.type == RIM_TYPEMOUSE) { - static const unsigned int button_flags[] = - { - 0, /* MOUSEEVENTF_MOVE */ - RI_MOUSE_LEFT_BUTTON_DOWN, /* MOUSEEVENTF_LEFTDOWN */ - RI_MOUSE_LEFT_BUTTON_UP, /* MOUSEEVENTF_LEFTUP */ - RI_MOUSE_RIGHT_BUTTON_DOWN, /* MOUSEEVENTF_RIGHTDOWN */ - RI_MOUSE_RIGHT_BUTTON_UP, /* MOUSEEVENTF_RIGHTUP */ - RI_MOUSE_MIDDLE_BUTTON_DOWN, /* MOUSEEVENTF_MIDDLEDOWN */ - RI_MOUSE_MIDDLE_BUTTON_UP, /* MOUSEEVENTF_MIDDLEUP */ - }; - unsigned int i; - - rawinput->header.dwSize = FIELD_OFFSET(RAWINPUT, data) + sizeof(RAWMOUSE); - rawinput->header.hDevice = WINE_MOUSE_HANDLE; - rawinput->header.wParam = 0; - - rawinput->data.mouse.usFlags = MOUSE_MOVE_RELATIVE; - rawinput->data.mouse.usButtonFlags = 0; - rawinput->data.mouse.usButtonData = 0; - for (i = 1; i < ARRAY_SIZE(button_flags); ++i) - { - if (msg_data->flags & (1 << i)) - rawinput->data.mouse.usButtonFlags |= button_flags[i]; - } - if (msg_data->flags & MOUSEEVENTF_WHEEL) - { - rawinput->data.mouse.usButtonFlags |= RI_MOUSE_WHEEL; - rawinput->data.mouse.usButtonData = msg_data->rawinput.mouse.data; - } - if (msg_data->flags & MOUSEEVENTF_HWHEEL) - { - rawinput->data.mouse.usButtonFlags |= RI_MOUSE_HORIZONTAL_WHEEL; - rawinput->data.mouse.usButtonData = msg_data->rawinput.mouse.data; - } - if (msg_data->flags & MOUSEEVENTF_XDOWN) - { - if (msg_data->rawinput.mouse.data == XBUTTON1) - rawinput->data.mouse.usButtonFlags |= RI_MOUSE_BUTTON_4_DOWN; - else if (msg_data->rawinput.mouse.data == XBUTTON2) - rawinput->data.mouse.usButtonFlags |= RI_MOUSE_BUTTON_5_DOWN; - } - if (msg_data->flags & MOUSEEVENTF_XUP) - { - if (msg_data->rawinput.mouse.data == XBUTTON1) - rawinput->data.mouse.usButtonFlags |= RI_MOUSE_BUTTON_4_UP; - else if (msg_data->rawinput.mouse.data == XBUTTON2) - rawinput->data.mouse.usButtonFlags |= RI_MOUSE_BUTTON_5_UP; - } - - rawinput->data.mouse.ulRawButtons = 0; - rawinput->data.mouse.lLastX = msg_data->rawinput.mouse.x; - rawinput->data.mouse.lLastY = msg_data->rawinput.mouse.y; - rawinput->data.mouse.ulExtraInformation = msg_data->info; + if (size != sizeof(RAWMOUSE)) return FALSE; + rawinput->data.mouse = *(RAWMOUSE *)(msg_data + 1); } else if (msg_data->rawinput.type == RIM_TYPEKEYBOARD) { - rawinput->header.dwSize = FIELD_OFFSET(RAWINPUT, data) + sizeof(RAWKEYBOARD); - rawinput->header.hDevice = WINE_KEYBOARD_HANDLE; - rawinput->header.wParam = 0; - - rawinput->data.keyboard.MakeCode = msg_data->rawinput.kbd.scan; - rawinput->data.keyboard.Flags = (msg_data->flags & KEYEVENTF_KEYUP) ? RI_KEY_BREAK : RI_KEY_MAKE; - if (msg_data->flags & KEYEVENTF_EXTENDEDKEY) - rawinput->data.keyboard.Flags |= RI_KEY_E0; - rawinput->data.keyboard.Reserved = 0; - - switch (msg_data->rawinput.kbd.vkey) - { - case VK_LSHIFT: - case VK_RSHIFT: - rawinput->data.keyboard.VKey = VK_SHIFT; - rawinput->data.keyboard.Flags &= ~RI_KEY_E0; - break; - - case VK_LCONTROL: - case VK_RCONTROL: - rawinput->data.keyboard.VKey = VK_CONTROL; - break; - - case VK_LMENU: - case VK_RMENU: - rawinput->data.keyboard.VKey = VK_MENU; - break; - - default: - rawinput->data.keyboard.VKey = msg_data->rawinput.kbd.vkey; - break; - } - - rawinput->data.keyboard.Message = msg_data->rawinput.kbd.message; - rawinput->data.keyboard.ExtraInformation = msg_data->info; + if (size != sizeof(RAWKEYBOARD)) return FALSE; + rawinput->data.keyboard = *(RAWKEYBOARD *)(msg_data + 1); } else if (msg_data->rawinput.type == RIM_TYPEHID) { - size = msg_data->size - sizeof(*msg_data); - if (size > rawinput->header.dwSize - sizeof(*rawinput)) return false; - - rawinput->header.dwSize = FIELD_OFFSET( RAWINPUT, data.hid.bRawData ) + size; - rawinput->header.hDevice = ULongToHandle( msg_data->rawinput.hid.device ); - rawinput->header.wParam = 0; - - rawinput->data.hid.dwCount = msg_data->rawinput.hid.count; - rawinput->data.hid.dwSizeHid = msg_data->rawinput.hid.length; - memcpy( rawinput->data.hid.bRawData, msg_data + 1, size ); + RAWHID *hid = (RAWHID *)(msg_data + 1); + if (size < offsetof(RAWHID, bRawData[0])) return FALSE; + if (size != offsetof(RAWHID, bRawData[hid->dwCount * hid->dwSizeHid])) return FALSE; + memcpy( &rawinput->data.hid, msg_data + 1, size ); } else { FIXME( "Unhandled rawinput type %#x.\n", msg_data->rawinput.type ); - return false; + return FALSE; }
- return true; + return TRUE; }
struct device @@ -621,10 +536,10 @@ UINT WINAPI NtUserGetRawInputBuffer( RAWINPUT *data, UINT *data_size, UINT heade int i;
if (NtCurrentTeb()->WowTebOffset) - rawinput_size = sizeof(RAWINPUT64); + rawinput_size = sizeof(RAWINPUTHEADER64); else - rawinput_size = sizeof(RAWINPUT); - overhead = rawinput_size - sizeof(RAWINPUT); + rawinput_size = sizeof(RAWINPUTHEADER); + overhead = rawinput_size - sizeof(RAWINPUTHEADER);
if (header_size != sizeof(RAWINPUTHEADER)) { diff --git a/server/protocol.def b/server/protocol.def index 419cf763063..7360bb51fe7 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -279,32 +279,12 @@ struct hw_msg_source unsigned int origin; /* source origin (IMO_* values) */ };
-union rawinput +struct rawinput { - int type; - struct - { - int type; /* RIM_TYPEKEYBOARD */ - unsigned int message; /* message generated by this rawinput event */ - unsigned short vkey; /* virtual key code */ - unsigned short scan; /* scan code */ - } kbd; - struct - { - int type; /* RIM_TYPEMOUSE */ - int x; /* x coordinate */ - int y; /* y coordinate */ - unsigned int data; /* mouse data */ - } mouse; - struct - { - int type; /* RIM_TYPEHID */ - unsigned int device; /* rawinput device index */ - unsigned int wparam; /* rawinput message wparam */ - unsigned int usage; /* HID device usage */ - unsigned int count; /* HID report count */ - unsigned int length; /* HID report length */ - } hid; + int type; /* rawinput data type (RIM_* values) */ + unsigned int device; /* rawinput device pseudo-handle */ + unsigned int wparam; /* wparam of the WM_INPUT* message */ + unsigned int usage; /* HID device usage */ };
struct hardware_msg_data @@ -315,7 +295,7 @@ struct hardware_msg_data unsigned int hw_id; /* unique id */ unsigned int flags; /* hook flags */ struct hw_msg_source source; /* message source */ - union rawinput rawinput; /* rawinput message data */ + struct rawinput rawinput; /* rawinput message data */ };
struct callback_msg_data diff --git a/server/queue.c b/server/queue.c index 07870f98711..e3aa0f685ca 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1782,6 +1782,116 @@ static struct thread *get_foreground_thread( struct desktop *desktop, user_handl return NULL; }
+/* user32 reserves 1 & 2 for winemouse and winekeyboard, + * keep this in sync with user_private.h */ +#define WINE_MOUSE_HANDLE 1 +#define WINE_KEYBOARD_HANDLE 2 + +static void rawmouse_init( struct rawinput *header, RAWMOUSE *rawmouse, int x, int y, unsigned int flags, + unsigned int buttons, lparam_t info ) +{ + static const unsigned int button_flags[] = + { + 0, /* MOUSEEVENTF_MOVE */ + RI_MOUSE_LEFT_BUTTON_DOWN, /* MOUSEEVENTF_LEFTDOWN */ + RI_MOUSE_LEFT_BUTTON_UP, /* MOUSEEVENTF_LEFTUP */ + RI_MOUSE_RIGHT_BUTTON_DOWN, /* MOUSEEVENTF_RIGHTDOWN */ + RI_MOUSE_RIGHT_BUTTON_UP, /* MOUSEEVENTF_RIGHTUP */ + RI_MOUSE_MIDDLE_BUTTON_DOWN, /* MOUSEEVENTF_MIDDLEDOWN */ + RI_MOUSE_MIDDLE_BUTTON_UP, /* MOUSEEVENTF_MIDDLEUP */ + }; + unsigned int i; + + header->type = RIM_TYPEMOUSE; + header->device = WINE_MOUSE_HANDLE; + header->wparam = 0; + header->usage = MAKELONG(HID_USAGE_GENERIC_MOUSE, HID_USAGE_PAGE_GENERIC); + + rawmouse->usFlags = MOUSE_MOVE_RELATIVE; + rawmouse->usButtonFlags = 0; + rawmouse->usButtonData = 0; + for (i = 1; i < ARRAY_SIZE(button_flags); ++i) + { + if (flags & (1 << i)) rawmouse->usButtonFlags |= button_flags[i]; + } + if (flags & MOUSEEVENTF_WHEEL) + { + rawmouse->usButtonFlags |= RI_MOUSE_WHEEL; + rawmouse->usButtonData = buttons; + } + if (flags & MOUSEEVENTF_HWHEEL) + { + rawmouse->usButtonFlags |= RI_MOUSE_HORIZONTAL_WHEEL; + rawmouse->usButtonData = buttons; + } + if (flags & MOUSEEVENTF_XDOWN) + { + if (buttons == XBUTTON1) rawmouse->usButtonFlags |= RI_MOUSE_BUTTON_4_DOWN; + if (buttons == XBUTTON2) rawmouse->usButtonFlags |= RI_MOUSE_BUTTON_5_DOWN; + } + if (flags & MOUSEEVENTF_XUP) + { + if (buttons == XBUTTON1) rawmouse->usButtonFlags |= RI_MOUSE_BUTTON_4_UP; + if (buttons == XBUTTON2) rawmouse->usButtonFlags |= RI_MOUSE_BUTTON_5_UP; + } + + rawmouse->ulRawButtons = 0; + rawmouse->lLastX = x; + rawmouse->lLastY = y; + rawmouse->ulExtraInformation = info; +} + +static void rawkeyboard_init( struct rawinput *rawinput, RAWKEYBOARD *keyboard, unsigned short scan, unsigned short vkey, + unsigned int flags, unsigned int message, lparam_t info ) +{ + rawinput->type = RIM_TYPEKEYBOARD; + rawinput->device = WINE_KEYBOARD_HANDLE; + rawinput->wparam = 0; + rawinput->usage = MAKELONG(HID_USAGE_GENERIC_KEYBOARD, HID_USAGE_PAGE_GENERIC); + + keyboard->MakeCode = scan; + keyboard->Flags = (flags & KEYEVENTF_KEYUP) ? RI_KEY_BREAK : RI_KEY_MAKE; + if (flags & KEYEVENTF_EXTENDEDKEY) keyboard->Flags |= RI_KEY_E0; + keyboard->Reserved = 0; + + switch (vkey) + { + case VK_LSHIFT: + case VK_RSHIFT: + keyboard->VKey = VK_SHIFT; + keyboard->Flags &= ~RI_KEY_E0; + break; + + case VK_LCONTROL: + case VK_RCONTROL: + keyboard->VKey = VK_CONTROL; + break; + + case VK_LMENU: + case VK_RMENU: + keyboard->VKey = VK_MENU; + break; + + default: + keyboard->VKey = vkey; + break; + } + + keyboard->Message = message; + keyboard->ExtraInformation = info; +} + +static void rawhid_init( struct rawinput *rawinput, RAWHID *hid, const hw_input_t *input ) +{ + rawinput->type = RIM_TYPEHID; + rawinput->device = input->hw.hid.device; + rawinput->wparam = input->hw.wparam; + rawinput->usage = input->hw.hid.usage; + + hid->dwCount = input->hw.hid.count; + hid->dwSizeHid = input->hw.hid.length; +} + struct rawinput_message { struct thread *foreground; @@ -1789,30 +1899,48 @@ struct rawinput_message struct hw_msg_source source; unsigned int time; unsigned int message; - lparam_t info; unsigned int flags; - union rawinput rawinput; - const void *hid_report; + struct rawinput rawinput; + union + { + RAWKEYBOARD keyboard; + RAWMOUSE mouse; + RAWHID hid; + } data; + const void *hid_report; };
/* check if process is supposed to receive a WM_INPUT message and eventually queue it */ static int queue_rawinput_message( struct process* process, void *arg ) { - const struct rawinput_message* raw_msg = arg; + const struct rawinput_message *raw_msg = arg; const struct rawinput_device *device = NULL; struct desktop *target_desktop = NULL, *desktop = NULL; struct thread *target_thread = NULL, *foreground = NULL; struct hardware_msg_data *msg_data; struct message *msg; - data_size_t report_size; + data_size_t report_size = 0, data_size = 0; int wparam = RIM_INPUT; + lparam_t info = 0;
if (raw_msg->rawinput.type == RIM_TYPEMOUSE) + { device = process->rawinput_mouse; + data_size = sizeof(raw_msg->data.mouse); + info = raw_msg->data.mouse.ulExtraInformation; + } else if (raw_msg->rawinput.type == RIM_TYPEKEYBOARD) + { device = process->rawinput_kbd; + data_size = sizeof(raw_msg->data.keyboard); + info = raw_msg->data.keyboard.ExtraInformation; + } else - device = find_rawinput_device( process, raw_msg->rawinput.hid.usage ); + { + device = find_rawinput_device( process, raw_msg->rawinput.usage ); + data_size = offsetof(RAWHID, bRawData[0]); + report_size = raw_msg->data.hid.dwCount * raw_msg->data.hid.dwSizeHid; + } if (!device) return 0;
if (raw_msg->message == WM_INPUT_DEVICE_CHANGE && !(device->flags & RIDEV_DEVNOTIFY)) return 0; @@ -1832,10 +1960,7 @@ static int queue_rawinput_message( struct process* process, void *arg ) wparam = RIM_INPUTSINK; }
- if (raw_msg->rawinput.type != RIM_TYPEHID || !raw_msg->hid_report) report_size = 0; - else report_size = raw_msg->rawinput.hid.count * raw_msg->rawinput.hid.length; - - if (!(msg = alloc_hardware_message( raw_msg->info, raw_msg->source, raw_msg->time, report_size ))) goto done; + if (!(msg = alloc_hardware_message( info, raw_msg->source, raw_msg->time, data_size + report_size ))) goto done; msg->win = device->target; msg->msg = raw_msg->message; msg->wparam = wparam; @@ -1844,12 +1969,13 @@ static int queue_rawinput_message( struct process* process, void *arg ) msg_data = msg->data; msg_data->flags = raw_msg->flags; msg_data->rawinput = raw_msg->rawinput; - if (report_size) memcpy( msg_data + 1, raw_msg->hid_report, report_size ); + memcpy( msg_data + 1, &raw_msg->data, data_size ); + if (report_size) memcpy( (char *)(msg_data + 1) + data_size, raw_msg->hid_report, report_size );
if (raw_msg->message == WM_INPUT_DEVICE_CHANGE && raw_msg->rawinput.type == RIM_TYPEHID) { - msg->wparam = raw_msg->rawinput.hid.wparam; - msg->lparam = raw_msg->rawinput.hid.device; + msg->wparam = raw_msg->rawinput.wparam; + msg->lparam = raw_msg->rawinput.device; }
queue_hardware_message( desktop, msg, 1 ); @@ -1927,13 +2053,9 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons raw_msg.source = source; raw_msg.time = time; raw_msg.message = WM_INPUT; - - raw_msg.info = input->mouse.info; - raw_msg.flags = flags; - raw_msg.rawinput.type = RIM_TYPEMOUSE; - raw_msg.rawinput.mouse.x = x - desktop->cursor.x; - raw_msg.rawinput.mouse.y = y - desktop->cursor.y; - raw_msg.rawinput.mouse.data = input->mouse.data; + raw_msg.flags = flags; + rawmouse_init( &raw_msg.rawinput, &raw_msg.data.mouse, x - desktop->cursor.x, y - desktop->cursor.y, + raw_msg.flags, input->mouse.data, input->mouse.info );
enum_processes( queue_rawinput_message, &raw_msg ); release_object( foreground ); @@ -2063,13 +2185,9 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c raw_msg.source = source; raw_msg.time = time; raw_msg.message = WM_INPUT; - - raw_msg.info = input->kbd.info; - raw_msg.flags = input->kbd.flags; - raw_msg.rawinput.type = RIM_TYPEKEYBOARD; - raw_msg.rawinput.kbd.message = message_code; - raw_msg.rawinput.kbd.vkey = vkey; - raw_msg.rawinput.kbd.scan = input->kbd.scan; + raw_msg.flags = input->kbd.flags; + rawkeyboard_init( &raw_msg.rawinput, &raw_msg.data.keyboard, input->kbd.scan, vkey, + raw_msg.flags, message_code, input->kbd.info );
enum_processes( queue_rawinput_message, &raw_msg ); release_object( foreground ); @@ -2134,13 +2252,7 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ set_error( STATUS_INVALID_PARAMETER ); return; } - - raw_msg.rawinput.hid.type = RIM_TYPEHID; - raw_msg.rawinput.hid.device = input->hw.hid.device; - raw_msg.rawinput.hid.wparam = input->hw.wparam; - raw_msg.rawinput.hid.usage = input->hw.hid.usage; - raw_msg.rawinput.hid.count = input->hw.hid.count; - raw_msg.rawinput.hid.length = input->hw.hid.length; + rawhid_init( &raw_msg.rawinput, &raw_msg.data.hid, input );
enum_processes( queue_rawinput_message, &raw_msg ); return; diff --git a/tools/make_requests b/tools/make_requests index 77b5ab331f4..e3eaaf45b6f 100755 --- a/tools/make_requests +++ b/tools/make_requests @@ -57,7 +57,7 @@ my %formats = "context_t" => [ 1720, 8 ], "cursor_pos_t" => [ 24, 8 ], "debug_event_t" => [ 160, 8 ], - "message_data_t" => [ 56, 8 ], + "message_data_t" => [ 48, 8 ], "pe_image_info_t" => [ 88, 8 ], "property_data_t" => [ 16, 8 ], "select_op_t" => [ 264, 8 ],
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/user32/tests/input.c | 3 -- dlls/win32u/rawinput.c | 103 ++++---------------------------------- server/protocol.def | 4 +- server/queue.c | 96 ++++++++++++++++++++++------------- 4 files changed, 75 insertions(+), 131 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 2f3a7fffe0a..03910ce4b46 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -1924,12 +1924,9 @@ static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wpara if (is_wow64) { 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 diff --git a/dlls/win32u/rawinput.c b/dlls/win32u/rawinput.c index 524d1b820b2..e4f43091b9b 100644 --- a/dlls/win32u/rawinput.c +++ b/dlls/win32u/rawinput.c @@ -42,7 +42,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(rawinput);
#ifdef _WIN64 typedef RAWINPUTHEADER RAWINPUTHEADER64; -typedef RAWINPUT RAWINPUT64; #else typedef struct { @@ -51,17 +50,6 @@ typedef struct ULONGLONG hDevice; ULONGLONG wParam; } RAWINPUTHEADER64; - -typedef struct -{ - RAWINPUTHEADER64 header; - union - { - RAWMOUSE mouse; - RAWKEYBOARD keyboard; - RAWHID hid; - } data; -} RAWINPUT64; #endif
static struct rawinput_thread_data *get_rawinput_thread_data(void) @@ -529,104 +517,35 @@ UINT WINAPI NtUserGetRawInputDeviceInfo( HANDLE handle, UINT command, void *data */ UINT WINAPI NtUserGetRawInputBuffer( RAWINPUT *data, UINT *data_size, UINT header_size ) { - unsigned int count = 0, remaining, rawinput_size, next_size, overhead; - struct rawinput_thread_data *thread_data; - struct hardware_msg_data *msg_data; - RAWINPUT *rawinput; - int i; + UINT count;
- if (NtCurrentTeb()->WowTebOffset) - rawinput_size = sizeof(RAWINPUTHEADER64); - else - rawinput_size = sizeof(RAWINPUTHEADER); - overhead = rawinput_size - sizeof(RAWINPUTHEADER); + TRACE( "data %p, data_size %p, header_size %u\n", data, data_size, header_size );
if (header_size != sizeof(RAWINPUTHEADER)) { - WARN( "Invalid structure size %u.\n", header_size ); RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); - return ~0u; + return -1; }
if (!data_size) { RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); - return ~0u; + return -1; }
- if (!data) - { - TRACE( "data %p, data_size %p (%u), header_size %u\n", data, data_size, *data_size, header_size ); - SERVER_START_REQ( get_rawinput_buffer ) - { - req->rawinput_size = rawinput_size; - req->buffer_size = 0; - if (wine_server_call( req )) return ~0u; - *data_size = reply->next_size; - } - SERVER_END_REQ; - return 0; - } + /* with old WOW64 mode we didn't go through the WOW64 thunks, patch the header size here */ + if (NtCurrentTeb()->WowTebOffset) header_size = sizeof(RAWINPUTHEADER64);
- if (!(thread_data = get_rawinput_thread_data())) return ~0u; - rawinput = thread_data->buffer; - - /* first RAWINPUT block in the buffer is used for WM_INPUT message data */ - msg_data = (struct hardware_msg_data *)NEXTRAWINPUTBLOCK(rawinput); SERVER_START_REQ( get_rawinput_buffer ) { - req->rawinput_size = rawinput_size; - req->buffer_size = *data_size; - wine_server_set_reply( req, msg_data, RAWINPUT_BUFFER_SIZE - rawinput->header.dwSize ); - if (wine_server_call( req )) return ~0u; - next_size = reply->next_size; - count = reply->count; + req->header_size = header_size; + if ((req->read_data = !!data)) wine_server_set_reply( req, data, *data_size ); + if (!wine_server_call_err( req )) count = reply->count; + else count = -1; + *data_size = reply->next_size; } SERVER_END_REQ;
- remaining = *data_size; - for (i = 0; i < count; ++i) - { - data->header.dwSize = remaining; - if (!rawinput_from_hardware_message( data, msg_data )) break; - if (overhead) - { - /* Under WoW64, GetRawInputBuffer always gives 64-bit RAWINPUT structs. */ - RAWINPUT64 *ri64 = (RAWINPUT64 *)data; - memmove( (char *)&data->data + overhead, &data->data, - data->header.dwSize - sizeof(RAWINPUTHEADER) ); - ri64->header.dwSize += overhead; - - /* Need to copy wParam before hDevice so it's not overwritten. */ - ri64->header.wParam = data->header.wParam; -#ifdef _WIN64 - ri64->header.hDevice = data->header.hDevice; -#else - ri64->header.hDevice = HandleToULong(data->header.hDevice); -#endif - } - remaining -= data->header.dwSize; - data = NEXTRAWINPUTBLOCK(data); - msg_data = (struct hardware_msg_data *)((char *)msg_data + msg_data->size); - } - - if (!next_size) - { - if (!count) - *data_size = 0; - else - next_size = rawinput_size; - } - - if (next_size && *data_size <= next_size) - { - RtlSetLastWin32Error( ERROR_INSUFFICIENT_BUFFER ); - *data_size = next_size; - count = ~0u; - } - - TRACE( "data %p, data_size %p (%u), header_size %u, count %u\n", - data, data_size, *data_size, header_size, count ); return count; }
diff --git a/server/protocol.def b/server/protocol.def index 7360bb51fe7..60604812622 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3768,8 +3768,8 @@ struct handle_info
/* Batch read rawinput message data */ @REQ(get_rawinput_buffer) - data_size_t rawinput_size; /* size of RAWINPUT structure */ - data_size_t buffer_size; /* size of output buffer */ + data_size_t header_size; /* size of RAWINPUTHEADER structure */ + int read_data; /* read the rawinput buffer data */ @REPLY data_size_t next_size; /* minimum size to get next message data */ unsigned int count; diff --git a/server/queue.c b/server/queue.c index e3aa0f685ca..6f38227aa84 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1866,7 +1866,6 @@ static void rawkeyboard_init( struct rawinput *rawinput, RAWKEYBOARD *keyboard, case VK_RCONTROL: keyboard->VKey = VK_CONTROL; break; - case VK_LMENU: case VK_RMENU: keyboard->VKey = VK_MENU; @@ -3541,52 +3540,81 @@ DECL_HANDLER(get_cursor_history)
DECL_HANDLER(get_rawinput_buffer) { + const size_t align = is_machine_64bit( current->process->machine ) ? 7 : 3; + data_size_t buffer_size = get_reply_max_size() & ~align; struct thread_input *input = current->queue->input; - data_size_t size = 0, next_size = 0, pos = 0; - struct list *ptr; - char *buf, *tmp; - int count = 0, buf_size = 16 * sizeof(struct hardware_msg_data); + struct message *msg, *next_msg; + int count = 0; + char *buffer;
- if (!req->buffer_size) buf = NULL; - else if (!(buf = mem_alloc( buf_size ))) return; + if (req->header_size != sizeof(RAWINPUTHEADER)) + { + set_error( STATUS_INVALID_PARAMETER ); + return; + }
- ptr = list_head( &input->msg_list ); - while (ptr) + if (!req->read_data) { - struct message *msg = LIST_ENTRY( ptr, struct message, entry ); - struct hardware_msg_data *data = msg->data; - data_size_t extra_size = data->size - sizeof(*data); + LIST_FOR_EACH_ENTRY( msg, &input->msg_list, struct message, entry ) + { + if (msg->msg == WM_INPUT) + { + struct hardware_msg_data *msg_data = msg->data; + data_size_t size = msg_data->size - sizeof(*msg_data); + reply->next_size = sizeof(RAWINPUTHEADER) + size; + break; + } + }
- ptr = list_next( &input->msg_list, ptr ); - if (msg->msg != WM_INPUT) continue; + } + else if ((buffer = mem_alloc( buffer_size ))) + { + size_t total_size = 0, next_size = 0; + + reply->next_size = get_reply_max_size();
- next_size = req->rawinput_size + extra_size; - if (size + next_size > req->buffer_size) break; - if (pos + data->size > get_reply_max_size()) break; - if (pos + data->size > buf_size) + LIST_FOR_EACH_ENTRY_SAFE( msg, next_msg, &input->msg_list, struct message, entry ) { - buf_size += buf_size / 2 + extra_size; - if (!(tmp = realloc( buf, buf_size ))) + if (msg->msg == WM_INPUT) { - free( buf ); - set_error( STATUS_NO_MEMORY ); - return; + RAWINPUT *rawinput = (RAWINPUT *)(buffer + total_size); + struct hardware_msg_data *msg_data = msg->data; + data_size_t data_size = msg_data->size - sizeof(*msg_data); + + if (total_size + sizeof(RAWINPUTHEADER) + data_size > buffer_size) + { + next_size = sizeof(RAWINPUTHEADER) + data_size; + break; + } + + rawinput->header.dwSize = sizeof(RAWINPUTHEADER) + data_size; + rawinput->header.dwType = msg_data->rawinput.type; + rawinput->header.hDevice = UlongToHandle(msg_data->rawinput.device); + rawinput->header.wParam = msg_data->rawinput.wparam; + memcpy( &rawinput->header + 1, msg_data + 1, data_size ); + + total_size += (rawinput->header.dwSize + align) & ~align; + list_remove( &msg->entry ); + free_message( msg ); + count++; } - buf = tmp; }
- memcpy( buf + pos, data, data->size ); - list_remove( &msg->entry ); - free_message( msg ); + if (!next_size) + { + if (count) next_size = sizeof(RAWINPUT); + else reply->next_size = 0; + }
- size += next_size; - pos += sizeof(*data) + extra_size; - count++; - } + if (next_size && get_reply_max_size() <= next_size) + { + set_error( STATUS_BUFFER_TOO_SMALL ); + reply->next_size = next_size; + }
- reply->next_size = next_size; - reply->count = count; - set_reply_data_ptr( buf, pos ); + reply->count = count; + set_reply_data_ptr( buffer, total_size ); + } }
DECL_HANDLER(update_rawinput_devices)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/ntuser_private.h | 12 +-- dlls/win32u/rawinput.c | 142 ++++++++++++++--------------------- 2 files changed, 57 insertions(+), 97 deletions(-)
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 11bb7f4baf6..3b6cab5bdc9 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -38,16 +38,6 @@ enum system_timer_id SYSTEM_TIMER_KEY_REPEAT = 0xfff0, };
-struct rawinput_thread_data -{ - UINT hw_id; /* current rawinput message id */ - RAWINPUT buffer[1]; /* rawinput message data buffer */ -}; - -/* on windows the buffer capacity is quite large as well, enough to */ -/* hold up to 10s of 1kHz mouse rawinput events */ -#define RAWINPUT_BUFFER_SIZE (512 * 1024) - struct user_object { HANDLE handle; @@ -133,7 +123,7 @@ struct user_thread_info MSG key_repeat_msg; /* Last WM_KEYDOWN message to repeat */ HKL kbd_layout; /* Current keyboard layout */ UINT kbd_layout_id; /* Current keyboard layout ID */ - struct rawinput_thread_data *rawinput; /* RawInput thread local data / buffer */ + struct hardware_msg_data *rawinput; /* Current rawinput message data */ UINT spy_indent; /* Current spy indent */ BOOL clipping_cursor; /* thread is currently clipping */ DWORD clipping_reset; /* time when clipping was last reset */ diff --git a/dlls/win32u/rawinput.c b/dlls/win32u/rawinput.c index e4f43091b9b..1120ce053aa 100644 --- a/dlls/win32u/rawinput.c +++ b/dlls/win32u/rawinput.c @@ -52,51 +52,6 @@ typedef struct } RAWINPUTHEADER64; #endif
-static struct rawinput_thread_data *get_rawinput_thread_data(void) -{ - struct user_thread_info *thread_info = get_user_thread_info(); - struct rawinput_thread_data *data = thread_info->rawinput; - if (data) return data; - data = thread_info->rawinput = calloc( 1, RAWINPUT_BUFFER_SIZE + sizeof(struct user_thread_info) ); - return data; -} - -static BOOL rawinput_from_hardware_message( RAWINPUT *rawinput, const struct hardware_msg_data *msg_data ) -{ - SIZE_T size = msg_data->size - sizeof(*msg_data); - if (sizeof(RAWINPUTHEADER) + size > rawinput->header.dwSize) return FALSE; - - rawinput->header.dwType = msg_data->rawinput.type; - rawinput->header.dwSize = sizeof(RAWINPUTHEADER) + size; - rawinput->header.hDevice = UlongToHandle( msg_data->rawinput.device ); - rawinput->header.wParam = msg_data->rawinput.wparam; - - if (msg_data->rawinput.type == RIM_TYPEMOUSE) - { - if (size != sizeof(RAWMOUSE)) return FALSE; - rawinput->data.mouse = *(RAWMOUSE *)(msg_data + 1); - } - else if (msg_data->rawinput.type == RIM_TYPEKEYBOARD) - { - if (size != sizeof(RAWKEYBOARD)) return FALSE; - rawinput->data.keyboard = *(RAWKEYBOARD *)(msg_data + 1); - } - else if (msg_data->rawinput.type == RIM_TYPEHID) - { - RAWHID *hid = (RAWHID *)(msg_data + 1); - if (size < offsetof(RAWHID, bRawData[0])) return FALSE; - if (size != offsetof(RAWHID, bRawData[hid->dwCount * hid->dwSizeHid])) return FALSE; - memcpy( &rawinput->data.hid, msg_data + 1, size ); - } - else - { - FIXME( "Unhandled rawinput type %#x.\n", msg_data->rawinput.type ); - return FALSE; - } - - return TRUE; -} - struct device { HANDLE file; @@ -552,69 +507,83 @@ UINT WINAPI NtUserGetRawInputBuffer( RAWINPUT *data, UINT *data_size, UINT heade /********************************************************************** * NtUserGetRawInputData (win32u.@) */ -UINT WINAPI NtUserGetRawInputData( HRAWINPUT rawinput, UINT command, void *data, UINT *data_size, UINT header_size ) +UINT WINAPI NtUserGetRawInputData( HRAWINPUT handle, UINT command, void *data, UINT *data_size, UINT header_size ) { - struct rawinput_thread_data *thread_data; - UINT size; - - TRACE( "rawinput %p, command %#x, data %p, data_size %p, header_size %u.\n", - rawinput, command, data, data_size, header_size ); + struct user_thread_info *thread_info = get_user_thread_info(); + struct hardware_msg_data *msg_data; + RAWINPUT *rawinput = data; + UINT size = 0;
- if (!(thread_data = get_rawinput_thread_data())) - { - RtlSetLastWin32Error( ERROR_OUTOFMEMORY ); - return ~0u; - } + TRACE( "handle %p, command %#x, data %p, data_size %p, header_size %u.\n", + handle, command, data, data_size, header_size );
- if (!rawinput || thread_data->hw_id != (UINT_PTR)rawinput) + if (!(msg_data = thread_info->rawinput) || msg_data->hw_id != (UINT_PTR)handle) { RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); - return ~0u; + return -1; }
if (header_size != sizeof(RAWINPUTHEADER)) { WARN( "Invalid structure size %u.\n", header_size ); RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); - return ~0u; - } - - switch (command) - { - case RID_INPUT: - size = thread_data->buffer->header.dwSize; - break; - - case RID_HEADER: - size = sizeof(RAWINPUTHEADER); - break; - - default: - RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); - return ~0u; + return -1; } + if (command != RID_HEADER && command != RID_INPUT) goto failed; + if (command == RID_INPUT) size = msg_data->size - sizeof(*msg_data);
if (!data) { - *data_size = size; + *data_size = sizeof(RAWINPUTHEADER) + size; return 0; }
- if (*data_size < size) + if (*data_size < sizeof(RAWINPUTHEADER) + size) { RtlSetLastWin32Error( ERROR_INSUFFICIENT_BUFFER ); - return ~0u; + return -1; + } + + rawinput->header.dwType = msg_data->rawinput.type; + rawinput->header.dwSize = sizeof(RAWINPUTHEADER) + msg_data->size - sizeof(*msg_data); + rawinput->header.hDevice = UlongToHandle( msg_data->rawinput.device ); + rawinput->header.wParam = msg_data->rawinput.wparam; + if (command == RID_HEADER) return sizeof(RAWINPUTHEADER); + + if (msg_data->rawinput.type == RIM_TYPEMOUSE) + { + if (size != sizeof(RAWMOUSE)) goto failed; + rawinput->data.mouse = *(RAWMOUSE *)(msg_data + 1); + } + else if (msg_data->rawinput.type == RIM_TYPEKEYBOARD) + { + if (size != sizeof(RAWKEYBOARD)) goto failed; + rawinput->data.keyboard = *(RAWKEYBOARD *)(msg_data + 1); + } + else if (msg_data->rawinput.type == RIM_TYPEHID) + { + RAWHID *hid = (RAWHID *)(msg_data + 1); + if (size < offsetof(RAWHID, bRawData[0])) goto failed; + if (size != offsetof(RAWHID, bRawData[hid->dwCount * hid->dwSizeHid])) goto failed; + memcpy( &rawinput->data.hid, msg_data + 1, size ); + } + else + { + FIXME( "Unhandled rawinput type %#x.\n", msg_data->rawinput.type ); + goto failed; } - memcpy( data, thread_data->buffer, size ); - return size; + + return rawinput->header.dwSize; + +failed: + WARN( "Invalid command %u or data size %u.\n", command, size ); + RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); + return -1; }
BOOL process_rawinput_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data ) { - struct rawinput_thread_data *thread_data; - - if (!(thread_data = get_rawinput_thread_data())) - return FALSE; + struct user_thread_info *thread_info = get_user_thread_info();
if (msg->message == WM_INPUT_DEVICE_CHANGE) { @@ -624,9 +593,10 @@ BOOL process_rawinput_message( MSG *msg, UINT hw_id, const struct hardware_msg_d } else { - thread_data->buffer->header.dwSize = RAWINPUT_BUFFER_SIZE; - if (!rawinput_from_hardware_message( thread_data->buffer, msg_data )) return FALSE; - thread_data->hw_id = hw_id; + struct hardware_msg_data *tmp; + if (!(tmp = realloc( thread_info->rawinput, msg_data->size ))) return FALSE; + memcpy( tmp, msg_data, msg_data->size ); + thread_info->rawinput = tmp; msg->lParam = (LPARAM)hw_id; }
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=142672
Your paranoid android.
=== w8 (32 bit report) ===
dinput: device8.c:2007: Test failed: got pointer_up_count 2 device8.c:2008: Test failed: got pointer_leave_count 2 device8.c:2016: Test failed: MsgWaitForMultipleObjects returned 0x102 device8.c:2021: Test failed: got pointer_up_count 0 device8.c:2023: Test failed: got pointer_leave_count 0
=== 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.
=== w10pro64 (32 bit report) ===
user32: input.c:3955: Test failed: layered 2: button_down_hwnd_todo 0 (missing): LL_HOOK_MOUSE msg 0, point (0,0), data 0, flags 0, time 0, extra 0 input.c:3955: Test failed: layered 2: button_down_hwnd_todo 1 (missing): MSG_TEST_WIN hwnd 000D02DC, WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032 input.c:3961: Test failed: layered 2: button_up_hwnd_todo 1: got MSG_TEST_WIN hwnd 000D02DC, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032 input.c:3961: Test failed: layered 2: button_up_hwnd_todo 2 (spurious): got MSG_TEST_WIN hwnd 000D02DC, msg WM_LBUTTONUP, wparam 0, lparam 0x320032
=== w11pro64 (32 bit report) ===
user32: input.c:3961: Test failed: layered 5: button_up_hwnd_todo 0: got MSG_TEST_WIN hwnd 00100218, msg WM_LBUTTONUP, wparam 0, lparam 0x320032 input.c:3961: Test failed: layered 5: button_up_hwnd_todo 1 (missing): MSG_TEST_WIN hwnd 00100218, WM_LBUTTONUP, wparam 0, lparam 0x320032
Test failures are the usual ones (user32:sysparams on Windows, the usual spurious nsi crash on Linux)