From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/tests/device8.c | 149 ++++++++++++++++++++++++++++++++ dlls/dinput/tests/dinput_test.h | 4 +- dlls/dinput/tests/hid.c | 6 +- 3 files changed, 155 insertions(+), 4 deletions(-)
diff --git a/dlls/dinput/tests/device8.c b/dlls/dinput/tests/device8.c index 7423d6c6ae7..e3cd75f7c08 100644 --- a/dlls/dinput/tests/device8.c +++ b/dlls/dinput/tests/device8.c @@ -1618,6 +1618,149 @@ cleanup: localized = old_localized; }
+static UINT mouse_move_count; + +static LRESULT CALLBACK mouse_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + if (msg == WM_MOUSEMOVE) + { + ok( wparam == 0, "got wparam %#Ix\n", wparam ); + ok( LOWORD(lparam) - 107 <= 2, "got LOWORD(lparam) %u\n", LOWORD(lparam) ); + ok( HIWORD(lparam) - 107 <= 2, "got HIWORD(lparam) %u\n", HIWORD(lparam) ); + mouse_move_count++; + } + return DefWindowProcA( hwnd, msg, wparam, lparam ); +} + +static void test_hid_mouse(void) +{ +#include "psh_hid_macros.h" + const unsigned char report_desc[] = + { + USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), + USAGE(1, HID_USAGE_GENERIC_MOUSE), + COLLECTION(1, Application), + USAGE(1, HID_USAGE_GENERIC_POINTER), + COLLECTION(1, Physical), + REPORT_ID(1, 1), + + USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON), + USAGE_MINIMUM(1, 1), + USAGE_MAXIMUM(1, 2), + LOGICAL_MINIMUM(1, 0), + LOGICAL_MAXIMUM(1, 1), + REPORT_SIZE(1, 1), + REPORT_COUNT(1, 8), + INPUT(1, Data|Var|Abs), + + USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), + USAGE(1, HID_USAGE_GENERIC_X), + USAGE(1, HID_USAGE_GENERIC_Y), + REPORT_SIZE(1, 16), + REPORT_COUNT(1, 2), + LOGICAL_MINIMUM(2, -10), + LOGICAL_MAXIMUM(2, +10), + INPUT(1, Data|Var|Rel), + END_COLLECTION, + END_COLLECTION, + }; + C_ASSERT(sizeof(report_desc) < MAX_HID_DESCRIPTOR_LEN); +#include "pop_hid_macros.h" + + const HID_DEVICE_ATTRIBUTES attributes = + { + .Size = sizeof(HID_DEVICE_ATTRIBUTES), + .VendorID = LOWORD(EXPECT_VIDPID), + .ProductID = 0x0002, + .VersionNumber = 0x0100, + }; + struct hid_device_desc desc = + { + .caps = { .InputReportByteLength = 6 }, + .attributes = attributes, + .use_report_id = 1, + }; + struct hid_expect single_move[] = + { + { + .code = IOCTL_HID_READ_REPORT, + .report_buf = {1,0x00,0x08,0x00,0x08,0x00}, + }, + }; + + WCHAR device_path[MAX_PATH]; + HANDLE file; + POINT pos; + DWORD res; + HWND hwnd; + BOOL ret; + + winetest_push_context( "mouse "); + + desc.report_descriptor_len = sizeof(report_desc); + memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) ); + fill_context( desc.context, ARRAY_SIZE(desc.context) ); + + if (!hid_device_start_( &desc, 1, 5000 /* needs a long timeout on Win7 */ )) goto done; + + swprintf( device_path, MAX_PATH, L"\\?\hid#vid_%04x&pid_%04x", desc.attributes.VendorID, + desc.attributes.ProductID ); + ret = find_hid_device_path( device_path ); + ok( ret, "Failed to find HID device matching %s\n", debugstr_w( device_path ) ); + + + /* windows doesn't let us open HID mouse devices */ + + file = CreateFileW( device_path, FILE_READ_ACCESS | FILE_WRITE_ACCESS, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); + todo_wine + ok( file == INVALID_HANDLE_VALUE, "CreateFileW succeeded\n" ); + todo_wine + ok( GetLastError() == ERROR_ACCESS_DENIED, "got error %lu\n", GetLastError() ); + CloseHandle( file ); + + file = CreateFileW( L"\\?\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}", 0, 0, + NULL, OPEN_EXISTING, 0, NULL ); + ok( file != INVALID_HANDLE_VALUE, "CreateFile failed, error %lu\n", GetLastError() ); + + + /* check basic mouse input injection to window message */ + + SetCursorPos( 100, 100 ); + hwnd = create_foreground_window( TRUE ); + SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)mouse_wndproc ); + + GetCursorPos( &pos ); + ok( pos.x == 100, "got x %lu\n", pos.x ); + ok( pos.y == 100, "got y %lu\n", pos.y ); + + mouse_move_count = 0; + bus_send_hid_input( file, &desc, single_move, sizeof(single_move) ); + + res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_MOUSEMOVE ); + todo_wine + ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res ); + msg_wait_for_events( 0, NULL, 5 ); /* process pending messages */ + todo_wine + ok( mouse_move_count == 1, "got mouse_move_count %u\n", mouse_move_count ); + + GetCursorPos( &pos ); + todo_wine + ok( (ULONG)pos.x - 107 <= 2, "got x %lu\n", pos.x ); + todo_wine + ok( (ULONG)pos.y - 107 <= 2, "got y %lu\n", pos.y ); + + DestroyWindow( hwnd ); + + + CloseHandle( file ); + +done: + hid_device_stop( &desc, 1 ); + + winetest_pop_context(); +} + static void test_dik_codes( IDirectInputDevice8W *device, HANDLE event, HWND hwnd, DWORD version ) { static const struct key2dik @@ -2371,5 +2514,11 @@ START_TEST(device8) test_keyboard_events(); test_appdata_property();
+ if (!bus_device_start()) goto done; + + test_hid_mouse(); + +done: + bus_device_stop(); dinput_test_exit(); } diff --git a/dlls/dinput/tests/dinput_test.h b/dlls/dinput/tests/dinput_test.h index b53978bbe97..e13ba2421d2 100644 --- a/dlls/dinput/tests/dinput_test.h +++ b/dlls/dinput/tests/dinput_test.h @@ -51,11 +51,13 @@ extern const WCHAR expect_path_end[]; extern HINSTANCE instance; extern BOOL localized; /* object names get translated */
-BOOL hid_device_start( struct hid_device_desc *desc, UINT count ); +#define hid_device_start( a, b ) hid_device_start_( a, b, 1000 ) +BOOL hid_device_start_( struct hid_device_desc *desc, UINT count, DWORD timeout ); void hid_device_stop( struct hid_device_desc *desc, UINT count ); BOOL bus_device_start(void); void bus_device_stop(void);
+BOOL find_hid_device_path( WCHAR *device_path ); void cleanup_registry_keys(void);
#define dinput_test_init() dinput_test_init_( __FILE__, __LINE__ ) diff --git a/dlls/dinput/tests/hid.c b/dlls/dinput/tests/hid.c index 0a28fda6f99..e5f6ea4640d 100644 --- a/dlls/dinput/tests/hid.c +++ b/dlls/dinput/tests/hid.c @@ -553,7 +553,7 @@ void bus_device_stop(void) ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND, "Failed to delete file, error %lu\n", GetLastError() ); }
-static BOOL find_hid_device_path( WCHAR *device_path ) +BOOL find_hid_device_path( WCHAR *device_path ) { char buffer[FIELD_OFFSET( SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath[MAX_PATH] )] = {0}; SP_DEVICE_INTERFACE_DATA iface = {sizeof(SP_DEVICE_INTERFACE_DATA)}; @@ -735,7 +735,7 @@ void hid_device_stop( struct hid_device_desc *desc, UINT count ) } }
-BOOL hid_device_start( struct hid_device_desc *desc, UINT count ) +BOOL hid_device_start_( struct hid_device_desc *desc, UINT count, DWORD timeout ) { HANDLE control; DWORD ret, i; @@ -754,7 +754,7 @@ BOOL hid_device_start( struct hid_device_desc *desc, UINT count )
for (i = 0; i < count; ++i) { - ret = WaitForSingleObject( device_added, 1000 ); + ret = WaitForSingleObject( device_added, timeout ); todo_wine_if(i > 0) ok( !ret, "WaitForSingleObject returned %#lx\n", ret ); }