Instead of just updating the info.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/rawinput.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index d95d29d7656..e4e7bad508f 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -98,7 +98,7 @@ static struct device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface) { SP_DEVINFO_DATA device_data = {sizeof(device_data)}; SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail; - struct device *device; + struct device *device = NULL; UINT32 handle; HANDLE file; DWORD i, size, type; @@ -117,15 +117,6 @@ static struct device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface) return NULL; }
- for (i = 0; i < rawinput_devices_count; ++i) - { - if (rawinput_devices[i].handle == UlongToHandle(handle)) - { - TRACE("Updating device %x / %s\n", handle, debugstr_w(rawinput_devices[i].detail->DevicePath)); - return rawinput_devices + i; - } - } - if (!(detail = malloc(size))) { ERR("Failed to allocate memory.\n"); @@ -134,8 +125,6 @@ static struct device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface) detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); SetupDiGetDeviceInterfaceDetailW(set, iface, detail, size, NULL, NULL);
- TRACE("Found device %x / %s.\n", handle, debugstr_w(detail->DevicePath)); - file = CreateFileW(detail->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); if (file == INVALID_HANDLE_VALUE) @@ -145,8 +134,24 @@ static struct device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface) return NULL; }
- if (!array_reserve((void **)&rawinput_devices, &rawinput_devices_max, - rawinput_devices_count + 1, sizeof(*rawinput_devices))) + for (i = 0; i < rawinput_devices_count && !device; ++i) + if (rawinput_devices[i].handle == UlongToHandle(handle)) + device = rawinput_devices + i; + + if (device) + { + TRACE("Updating device %x / %s.\n", handle, debugstr_w(detail->DevicePath)); + HidD_FreePreparsedData(device->data); + CloseHandle(device->file); + free(device->detail); + } + else if (array_reserve((void **)&rawinput_devices, &rawinput_devices_max, + rawinput_devices_count + 1, sizeof(*rawinput_devices))) + { + device = &rawinput_devices[rawinput_devices_count++]; + TRACE("Adding device %x / %s.\n", handle, debugstr_w(detail->DevicePath)); + } + else { ERR("Failed to allocate memory.\n"); CloseHandle(file); @@ -154,7 +159,6 @@ static struct device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface) return NULL; }
- device = &rawinput_devices[rawinput_devices_count++]; device->detail = detail; device->file = file; device->handle = ULongToHandle(handle); @@ -226,8 +230,6 @@ static void find_devices(void)
device->info.dwType = RIM_TYPEMOUSE; device->info.u.mouse = mouse_info; - HidD_FreePreparsedData(device->data); - device->data = NULL; }
SetupDiDestroyDeviceInfoList(set); @@ -243,8 +245,6 @@ static void find_devices(void)
device->info.dwType = RIM_TYPEKEYBOARD; device->info.u.keyboard = keyboard_info; - HidD_FreePreparsedData(device->data); - device->data = NULL; }
SetupDiDestroyDeviceInfoList(set);
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/device.c | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index 7dc97781b6b..4d031ffcaa0 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -104,6 +104,43 @@ static NTSTATUS copy_packet_into_buffer(HID_XFER_PACKET *packet, BYTE* buffer, U return STATUS_BUFFER_OVERFLOW; }
+static void hid_device_send_input(DEVICE_OBJECT *device, HID_XFER_PACKET *packet) +{ + BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; + RAWINPUT *rawinput; + UCHAR *report, id; + ULONG data_size; + INPUT input; + + data_size = offsetof(RAWINPUT, data.hid.bRawData) + packet->reportBufferLen; + if (!(id = ext->u.pdo.preparsed_data->reports[0].reportID)) data_size += 1; + + if (!(rawinput = HeapAlloc(GetProcessHeap(), 0, data_size))) + { + ERR("Failed to allocate rawinput data!\n"); + return; + } + + rawinput->header.dwType = RIM_TYPEHID; + rawinput->header.dwSize = data_size; + rawinput->header.hDevice = ULongToHandle(ext->u.pdo.rawinput_handle); + rawinput->header.wParam = RIM_INPUT; + rawinput->data.hid.dwCount = 1; + rawinput->data.hid.dwSizeHid = data_size - offsetof(RAWINPUT, data.hid.bRawData); + + report = rawinput->data.hid.bRawData; + if (!id) *report++ = 0; + memcpy(report, packet->reportBuffer, packet->reportBufferLen); + + input.type = INPUT_HARDWARE; + input.u.hi.uMsg = WM_INPUT; + input.u.hi.wParamH = 0; + input.u.hi.wParamL = 0; + __wine_send_input(0, &input, rawinput); + + HeapFree(GetProcessHeap(), 0, rawinput); +} + static void HID_Device_processQueue(DEVICE_OBJECT *device) { IRP *irp; @@ -175,6 +212,7 @@ static DWORD CALLBACK hid_device_thread(void *args) if (irp_status.u.Status == STATUS_SUCCESS) { RingBuffer_Write(ext->u.pdo.ring_buffer, packet); + hid_device_send_input(device, packet); HID_Device_processQueue(device); }
@@ -215,6 +253,7 @@ static DWORD CALLBACK hid_device_thread(void *args) else packet->reportId = 0; RingBuffer_Write(ext->u.pdo.ring_buffer, packet); + hid_device_send_input(device, packet); HID_Device_processQueue(device); }
The RIM_TYPEHID messages will have to carry the variable length HID report.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- server/queue.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/server/queue.c b/server/queue.c index 5d65e030112..67c75395450 100644 --- a/server/queue.c +++ b/server/queue.c @@ -348,13 +348,13 @@ static int assign_thread_input( struct thread *thread, struct thread_input *new_
/* allocate a hardware message and its data */ static struct message *alloc_hardware_message( lparam_t info, struct hw_msg_source source, - unsigned int time ) + unsigned int time, data_size_t extra_len ) { struct hardware_msg_data *msg_data; struct message *msg;
if (!(msg = mem_alloc( sizeof(*msg) ))) return NULL; - if (!(msg_data = mem_alloc( sizeof(*msg_data) ))) + if (!(msg_data = mem_alloc( sizeof(*msg_data) + extra_len ))) { free( msg ); return NULL; @@ -363,9 +363,9 @@ static struct message *alloc_hardware_message( lparam_t info, struct hw_msg_sour msg->type = MSG_HARDWARE; msg->time = time; msg->data = msg_data; - msg->data_size = sizeof(*msg_data); + msg->data_size = sizeof(*msg_data) + extra_len;
- memset( msg_data, 0, sizeof(*msg_data) ); + memset( msg_data, 0, sizeof(*msg_data) + extra_len ); msg_data->info = info; msg_data->source = source; return msg; @@ -398,7 +398,7 @@ static void set_cursor_pos( struct desktop *desktop, int x, int y ) return; }
- if (!(msg = alloc_hardware_message( 0, source, get_tick_count() ))) return; + if (!(msg = alloc_hardware_message( 0, source, get_tick_count(), 0 ))) return;
msg->msg = WM_MOUSEMOVE; msg->x = x; @@ -1664,6 +1664,8 @@ struct rawinput_message unsigned int time; unsigned int message; struct hardware_msg_data data; + const void *extra; + data_size_t extra_len; };
/* check if process is supposed to receive a WM_INPUT message and eventually queue it */ @@ -1675,6 +1677,7 @@ static int queue_rawinput_message( struct process* process, void *arg ) struct desktop *target_desktop = NULL, *desktop = NULL; struct thread *target_thread = NULL, *foreground = NULL; struct message *msg; + struct hardware_msg_data *msg_data; int wparam = RIM_INPUT;
if (raw_msg->data.rawinput.type == RIM_TYPEMOUSE) @@ -1702,14 +1705,18 @@ static int queue_rawinput_message( struct process* process, void *arg ) wparam = RIM_INPUTSINK; }
- if (!(msg = alloc_hardware_message( raw_msg->data.info, raw_msg->source, raw_msg->time ))) + if (!(msg = alloc_hardware_message( raw_msg->data.info, raw_msg->source, raw_msg->time, raw_msg->extra_len ))) goto done; + msg_data = msg->data;
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) ); + + memcpy( msg_data, &raw_msg->data, sizeof(*msg_data) ); + if (raw_msg->extra_len && raw_msg->extra) + memcpy( msg_data + 1, raw_msg->extra, raw_msg->extra_len );
if (raw_msg->message == WM_INPUT_DEVICE_CHANGE && raw_msg->data.rawinput.type == RIM_TYPEHID) { @@ -1791,6 +1798,8 @@ 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.extra = NULL; + raw_msg.extra_len = 0;
msg_data = &raw_msg.data; msg_data->info = input->mouse.info; @@ -1816,7 +1825,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons if (!(flags & (1 << i))) continue; flags &= ~(1 << i);
- if (!(msg = alloc_hardware_message( input->mouse.info, source, time ))) return 0; + if (!(msg = alloc_hardware_message( input->mouse.info, source, time, 0 ))) return 0; msg_data = msg->data;
msg->win = get_user_full_handle( win ); @@ -1926,6 +1935,8 @@ 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.extra = NULL; + raw_msg.extra_len = 0;
msg_data = &raw_msg.data; msg_data->info = input->kbd.info; @@ -1945,7 +1956,7 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c return 0; }
- if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0; + if (!(msg = alloc_hardware_message( input->kbd.info, source, time, 0 ))) return 0; msg_data = msg->data;
msg->win = get_user_full_handle( win ); @@ -1993,6 +2004,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; + raw_msg.extra = NULL; + raw_msg.extra_len = 0;
msg_data = &raw_msg.data; msg_data->info = 0; @@ -2005,7 +2018,7 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ return; }
- if (!(msg = alloc_hardware_message( 0, source, get_tick_count() ))) return; + if (!(msg = alloc_hardware_message( 0, source, get_tick_count(), 0 ))) return;
msg->win = get_user_full_handle( win ); msg->msg = input->hw.msg;
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/message.c | 2 ++ dlls/user32/rawinput.c | 6 ++++-- server/protocol.def | 3 +++ server/queue.c | 16 +++++++++------- server/trace.c | 38 ++++++++++++++++++++------------------ tools/make_requests | 2 +- 6 files changed, 39 insertions(+), 28 deletions(-)
diff --git a/dlls/user32/message.c b/dlls/user32/message.c index 9af33c3291e..4d6057840fd 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -3293,6 +3293,8 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r 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.length = rawinput->data.hid.dwSizeHid; + wine_server_add_data( req, rawinput->data.hid.bRawData, rawinput->data.hid.dwSizeHid ); break; default: assert( 0 ); diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index e4e7bad508f..0b6880b61cc 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -564,7 +564,7 @@ UINT WINAPI DECLSPEC_HOTPATCH GetRawInputBuffer(RAWINPUT *data, UINT *data_size, struct hardware_msg_data *msg_data; struct rawinput_thread_data *thread_data; RAWINPUT *rawinput; - UINT count = 0, rawinput_size, next_size, overhead; + UINT count = 0, rawinput_size, msg_size, next_size, overhead; BOOL is_wow64; int i;
@@ -624,7 +624,9 @@ UINT WINAPI DECLSPEC_HOTPATCH GetRawInputBuffer(RAWINPUT *data, UINT *data_size, data->header.dwSize - sizeof(RAWINPUTHEADER)); data->header.dwSize += overhead; data = NEXTRAWINPUTBLOCK(data); - msg_data++; + msg_size = sizeof(*msg_data); + if (msg_data->rawinput.type == RIM_TYPEHID) msg_size += msg_data->rawinput.hid.length; + msg_data = (struct hardware_msg_data *)((char *)msg_data + msg_size); }
if (count == 0 && next_size == 0) *data_size = 0; diff --git a/server/protocol.def b/server/protocol.def index eaffa886f21..d24070e7b9a 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -302,6 +302,9 @@ union rawinput unsigned int param; /* rawinput message param */ unsigned short usage_page;/* HID usage page */ unsigned short usage; /* HID usage */ + unsigned int length; /* HID report length */ + int __pad; + /* followed by length bytes of HID report data */ } hid; };
diff --git a/server/queue.c b/server/queue.c index 67c75395450..3e79d253c7c 100644 --- a/server/queue.c +++ b/server/queue.c @@ -2004,8 +2004,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; - raw_msg.extra = NULL; - raw_msg.extra_len = 0; + raw_msg.extra = get_req_data(); + raw_msg.extra_len = get_req_data_size();
msg_data = &raw_msg.data; msg_data->info = 0; @@ -3308,16 +3308,18 @@ DECL_HANDLER(get_rawinput_buffer) { struct message *msg = LIST_ENTRY( ptr, struct message, entry ); struct hardware_msg_data *data = msg->data; + data_size_t hid_size = data->rawinput.type != RIM_TYPEHID ? 0 : data->rawinput.hid.length; + data_size_t data_size = sizeof(*data) + hid_size;
ptr = list_next( &input->msg_list, ptr ); if (msg->msg != WM_INPUT) continue;
- next_size = req->rawinput_size; + next_size = req->rawinput_size + hid_size; if (size + next_size > req->buffer_size) break; - if (cur + sizeof(*data) > buf + get_reply_max_size()) break; - if (cur + sizeof(*data) > buf + buf_size) + if (cur + data_size > buf + get_reply_max_size()) break; + if (cur + data_size > buf + buf_size) { - buf_size += buf_size / 2; + buf_size += buf_size / 2 + hid_size; if (!(tmp = realloc( buf, buf_size ))) { set_error( STATUS_NO_MEMORY ); @@ -3327,7 +3329,7 @@ DECL_HANDLER(get_rawinput_buffer) buf = tmp; }
- memcpy(cur, data, sizeof(*data)); + memcpy( cur, data, data_size ); list_remove( &msg->entry ); free_message( msg );
diff --git a/server/trace.c b/server/trace.c index e40f0769a35..e7950d29f3b 100644 --- a/server/trace.c +++ b/server/trace.c @@ -395,6 +395,22 @@ static void dump_irp_params( const char *prefix, const irp_params_t *data ) } }
+static void dump_varargs_bytes( const char *prefix, data_size_t size ) +{ + const unsigned char *data = cur_data; + data_size_t len = min( 1024, size ); + + fprintf( stderr, "%s{", prefix ); + while (len > 0) + { + fprintf( stderr, "%02x", *data++ ); + if (--len) fputc( ',', stderr ); + } + if (size > 1024) fprintf( stderr, "...(total %u)", size ); + fputc( '}', stderr ); + remove_data( size ); +} + static void dump_rawinput( const char *prefix, const union rawinput *rawinput ) { switch (rawinput->type) @@ -408,9 +424,11 @@ static void dump_rawinput( const char *prefix, const union rawinput *rawinput ) 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}", + fprintf( stderr, "%s{type=HID,device=%04x,param=%04x,page=%04hx,usage=%04hx,length=%u", prefix, rawinput->hid.device, rawinput->hid.param, rawinput->hid.usage_page, - rawinput->hid.usage ); + rawinput->hid.usage, rawinput->hid.length ); + dump_varargs_bytes( ",report=", rawinput->hid.length ); + fputc( '}', stderr ); break; default: fprintf( stderr, "%s{type=%04x}", prefix, rawinput->type ); @@ -586,22 +604,6 @@ static void dump_varargs_user_handles( const char *prefix, data_size_t size ) remove_data( size ); }
-static void dump_varargs_bytes( const char *prefix, data_size_t size ) -{ - const unsigned char *data = cur_data; - data_size_t len = min( 1024, size ); - - fprintf( stderr,"%s{", prefix ); - while (len > 0) - { - fprintf( stderr, "%02x", *data++ ); - if (--len) fputc( ',', stderr ); - } - if (size > 1024) fprintf( stderr, "...(total %u)", size ); - fputc( '}', stderr ); - remove_data( size ); -} - static void dump_varargs_string( const char *prefix, data_size_t size ) { fprintf( stderr, "%s"%.*s"", prefix, (int)size, (const char *)cur_data ); diff --git a/tools/make_requests b/tools/make_requests index a70b29df3d2..1c4e5977c8b 100755 --- a/tools/make_requests +++ b/tools/make_requests @@ -52,7 +52,7 @@ my %formats = "luid_t" => [ 8, 4, "&dump_luid" ], "generic_map_t" => [ 16, 4, "&dump_generic_map" ], "ioctl_code_t" => [ 4, 4, "&dump_ioctl_code" ], - "hw_input_t" => [ 32, 8, "&dump_hw_input" ], + "hw_input_t" => [ 40, 8, "&dump_hw_input" ], );
my @requests = ();
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=90256
Your paranoid android.
=== debiant2 (32 bit Chinese:China report) ===
user32: input.c:2160: Test failed: GetRawInputBuffer returned 4 input.c:2155: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2160: Test failed: GetRawInputBuffer returned 0 input.c:2161: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2162: Test failed: Unexpected rawinput data: 0 input.c:2163: Test failed: Unexpected rawinput data: 0 input.c:2164: Test failed: Unexpected rawinput data: 0 input.c:2222: Test failed: GetRawInputData succeeded input.c:2223: Test failed: GetRawInputData returned deadbeef input.c:2336: Test failed: Spurious WM_INPUT messages
=== debiant2 (64 bit WoW report) ===
user32: input.c:2155: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2160: Test failed: GetRawInputBuffer returned 0 input.c:2161: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2162: Test failed: Unexpected rawinput data: 0 input.c:2163: Test failed: Unexpected rawinput data: 0 input.c:2164: Test failed: Unexpected rawinput data: 0 input.c:2222: Test failed: GetRawInputData succeeded input.c:2223: Test failed: GetRawInputData returned deadbeef input.c:2336: Test failed: Spurious WM_INPUT messages
Rémi Bernon rbernon@codeweavers.com writes:
@@ -3308,16 +3308,18 @@ DECL_HANDLER(get_rawinput_buffer) { struct message *msg = LIST_ENTRY( ptr, struct message, entry ); struct hardware_msg_data *data = msg->data;
data_size_t hid_size = data->rawinput.type != RIM_TYPEHID ? 0 : data->rawinput.hid.length;
data_size_t data_size = sizeof(*data) + hid_size;
You can't trust the length passed by the client.
@@ -408,9 +424,11 @@ static void dump_rawinput( const char *prefix, const union rawinput *rawinput ) 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}",
fprintf( stderr, "%s{type=HID,device=%04x,param=%04x,page=%04hx,usage=%04hx,length=%u", prefix, rawinput->hid.device, rawinput->hid.param, rawinput->hid.usage_page,
rawinput->hid.usage );
rawinput->hid.usage, rawinput->hid.length );
dump_varargs_bytes( ",report=", rawinput->hid.length );
Same here.
The messages are of variable size and carry the corresponding HID report data after each RAWINPUT struct.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/message.c | 9 +++++++++ dlls/user32/rawinput.c | 31 +++++++++++++++++++++++++++++++ dlls/user32/user_private.h | 2 ++ server/queue.c | 1 + server/trace.c | 1 + 5 files changed, 44 insertions(+)
diff --git a/dlls/user32/message.c b/dlls/user32/message.c index 4d6057840fd..8a2abda9dfb 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -3254,6 +3254,14 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r hid_usage_page = ((USAGE *)rawinput->data.hid.bRawData)[0]; hid_usage = ((USAGE *)rawinput->data.hid.bRawData)[1]; } + if (input->u.hi.uMsg == WM_INPUT) + { + if (!rawinput_device_get_usages( rawinput->header.hDevice, &hid_usage_page, &hid_usage )) + { + WARN( "unable to get HID usages for device %p\n", rawinput->header.hDevice ); + return STATUS_INVALID_HANDLE; + } + } }
SERVER_START_REQ( send_hardware_message ) @@ -3283,6 +3291,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r req->input.hw.lparam = MAKELONG( input->u.hi.wParamL, input->u.hi.wParamH ); switch (input->u.hi.uMsg) { + case WM_INPUT: case WM_INPUT_DEVICE_CHANGE: req->input.hw.rawinput.type = rawinput->header.dwType; switch (rawinput->header.dwType) diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index 0b6880b61cc..a5f87b89e24 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -267,6 +267,21 @@ static struct device *find_device_from_handle(HANDLE handle) }
+BOOL rawinput_device_get_usages(HANDLE handle, USAGE *usage_page, USAGE *usage) +{ + struct device *device; + + *usage_page = *usage = 0; + + if (!(device = find_device_from_handle(handle))) return FALSE; + if (device->info.dwType != RIM_TYPEHID) return FALSE; + + *usage_page = device->info.u.hid.usUsagePage; + *usage = device->info.u.hid.usUsage; + return TRUE; +} + + struct rawinput_thread_data *rawinput_thread_data(void) { struct user_thread_info *thread_info = get_user_thread_info(); @@ -371,6 +386,22 @@ BOOL rawinput_from_hardware_message(RAWINPUT *rawinput, const struct hardware_ms rawinput->data.keyboard.Message = msg_data->rawinput.kbd.message; rawinput->data.keyboard.ExtraInformation = msg_data->info; } + else if (msg_data->rawinput.type == RIM_TYPEHID) + { + if (sizeof(*rawinput) + msg_data->rawinput.hid.length > RAWINPUT_BUFFER_SIZE) + { + ERR( "unexpectedly large hardware message dropped\n" ); + return FALSE; + } + + rawinput->header.dwSize = FIELD_OFFSET( RAWINPUT, data.hid.bRawData ) + msg_data->rawinput.hid.length; + rawinput->header.hDevice = ULongToHandle( msg_data->rawinput.hid.device ); + rawinput->header.wParam = 0; + + rawinput->data.hid.dwSizeHid = msg_data->rawinput.hid.length; + rawinput->data.hid.dwCount = 1; + memcpy( rawinput->data.hid.bRawData, msg_data + 1, msg_data->rawinput.hid.length ); + } else { FIXME("Unhandled rawinput type %#x.\n", msg_data->rawinput.type); diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index db082462f1b..ebf37bb971f 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -28,6 +28,7 @@ #include "winuser.h" #include "winreg.h" #include "winternl.h" +#include "hidusage.h" #include "wine/heap.h"
#define GET_WORD(ptr) (*(const WORD *)(ptr)) @@ -239,6 +240,7 @@ struct tagWND;
struct hardware_msg_data; extern BOOL rawinput_from_hardware_message(RAWINPUT *rawinput, const struct hardware_msg_data *msg_data); +extern BOOL rawinput_device_get_usages(HANDLE handle, USAGE *usage_page, USAGE *usage); extern struct rawinput_thread_data *rawinput_thread_data(void);
extern void keyboard_init(void) DECLSPEC_HIDDEN; diff --git a/server/queue.c b/server/queue.c index 3e79d253c7c..652f9060b2a 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1998,6 +1998,7 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_
switch (input->hw.msg) { + case WM_INPUT: case WM_INPUT_DEVICE_CHANGE: raw_msg.foreground = NULL; raw_msg.desktop = NULL; diff --git a/server/trace.c b/server/trace.c index e7950d29f3b..206469b1eb7 100644 --- a/server/trace.c +++ b/server/trace.c @@ -458,6 +458,7 @@ static void dump_hw_input( const char *prefix, const hw_input_t *input ) dump_uint64( ",lparam=", &input->hw.lparam ); switch (input->hw.msg) { + case WM_INPUT: case WM_INPUT_DEVICE_CHANGE: dump_rawinput( ",rawinput=", &input->hw.rawinput ); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=90257
Your paranoid android.
=== debiant2 (32 bit Chinese:China report) ===
user32: input.c:2160: Test failed: GetRawInputBuffer returned 4 input.c:2222: Test failed: GetRawInputData succeeded input.c:2223: Test failed: GetRawInputData returned deadbeef input.c:2336: Test failed: Spurious WM_INPUT messages
=== debiant2 (64 bit WoW report) ===
user32: input.c:2160: Test failed: GetRawInputBuffer returned 4 input.c:2155: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2160: Test failed: GetRawInputBuffer returned 0 input.c:2161: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2162: Test failed: Unexpected rawinput data: 0 input.c:2163: Test failed: Unexpected rawinput data: 0 input.c:2164: Test failed: Unexpected rawinput data: 0 input.c:2222: Test failed: GetRawInputData succeeded input.c:2223: Test failed: GetRawInputData returned deadbeef input.c:2336: Test failed: Spurious WM_INPUT messages
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=90253
Your paranoid android.
=== debiant2 (32 bit Chinese:China report) ===
user32: input.c:2160: Test failed: GetRawInputBuffer returned 4 input.c:2155: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2160: Test failed: GetRawInputBuffer returned 0 input.c:2161: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2162: Test failed: Unexpected rawinput data: 0 input.c:2163: Test failed: Unexpected rawinput data: 0 input.c:2164: Test failed: Unexpected rawinput data: 0 input.c:2222: Test failed: GetRawInputData succeeded input.c:2223: Test failed: GetRawInputData returned deadbeef input.c:2336: Test failed: Spurious WM_INPUT messages
=== debiant2 (64 bit WoW report) ===
user32: input.c:2160: Test failed: GetRawInputBuffer returned 4 input.c:2222: Test failed: GetRawInputData succeeded input.c:2223: Test failed: GetRawInputData returned deadbeef input.c:2336: Test failed: Spurious WM_INPUT messages
On 5/12/21 11:49 AM, Marvin wrote:
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=90253
Your paranoid android.
=== debiant2 (32 bit Chinese:China report) ===
user32: input.c:2160: Test failed: GetRawInputBuffer returned 4 input.c:2155: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2160: Test failed: GetRawInputBuffer returned 0 input.c:2161: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2162: Test failed: Unexpected rawinput data: 0 input.c:2163: Test failed: Unexpected rawinput data: 0 input.c:2164: Test failed: Unexpected rawinput data: 0 input.c:2222: Test failed: GetRawInputData succeeded input.c:2223: Test failed: GetRawInputData returned deadbeef input.c:2336: Test failed: Spurious WM_INPUT messages
=== debiant2 (64 bit WoW report) ===
user32: input.c:2160: Test failed: GetRawInputBuffer returned 4 input.c:2222: Test failed: GetRawInputData succeeded input.c:2223: Test failed: GetRawInputData returned deadbeef input.c:2336: Test failed: Spurious WM_INPUT messages
I think these as well as the failures on patch 3 and 4 (which are the same), are spurious failures. I'm not completely sure about the conditions to make it happen, but I suspect that it can if mouse motion events take some unusual time to be received.
The test is supposed to do several mouse movements, which should also update the X11 mouse position using SetCursorPos, triggering some real motion events, and it then expect to receive several WM_INPUT messages at the same time. One is getting processed from the message loop, and the other are expected to be found when calling GetRawInputBuffer.
I've run the tests manually again here, and they don't fail this time:
https://testbot.winehq.org/JobDetails.pl?Key=90266 https://testbot.winehq.org/JobDetails.pl?Key=90267