Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
This is likely to be the cause of some of the spurious failures.
v2: (PATCH 3) Check hid.length vs request data size and prefer request data size.
dlls/user32/tests/input.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 3d4f0d03d0d..d7e7c09650f 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -2138,7 +2138,7 @@ static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wpara { RAWINPUT ri; char buffer[16 * sizeof(RAWINPUT64)]; - UINT size, count, rawinput_size, iteration = rawinputbuffer_wndproc_count++; + UINT size, count, rawinput_size, iteration; MSG message;
if (is_wow64) rawinput_size = sizeof(RAWINPUT64); @@ -2146,6 +2146,8 @@ static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wpara
if (msg == WM_INPUT) { + iteration = rawinputbuffer_wndproc_count++; + count = GetRawInputBuffer(NULL, NULL, sizeof(RAWINPUTHEADER)); ok(count == ~0U, "GetRawInputBuffer succeeded\n");
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 | 19 ++++++++++++------- server/trace.c | 38 ++++++++++++++++++++------------------ tools/make_requests | 2 +- 6 files changed, 42 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 6d8208b128b..ba2abc6813e 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..034c056bf1c 100644 --- a/server/queue.c +++ b/server/queue.c @@ -2004,8 +2004,12 @@ 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(); + + if (input->hw.rawinput.type == RIM_TYPEHID && + input->hw.rawinput.hid.length != raw_msg.extra_len) + return;
msg_data = &raw_msg.data; msg_data->info = 0; @@ -3308,16 +3312,17 @@ 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 : msg->data_size - sizeof(*data);
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 + msg->data_size > buf + get_reply_max_size()) break; + if (cur + msg->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 +3332,7 @@ DECL_HANDLER(get_rawinput_buffer) buf = tmp; }
- memcpy(cur, data, sizeof(*data)); + memcpy( cur, data, msg->data_size ); list_remove( &msg->entry ); free_message( msg );
diff --git a/server/trace.c b/server/trace.c index ad7236dd393..9970d37be8b 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=", cur_size ); + 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=90445
Your paranoid android.
=== debiant2 (32 bit Chinese:China report) ===
user32: input.c:2162: Test failed: GetRawInputBuffer returned 4 input.c:2157: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2162: Test failed: GetRawInputBuffer returned 0 input.c:2163: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2164: Test failed: Unexpected rawinput data: 0 input.c:2165: Test failed: Unexpected rawinput data: 0 input.c:2166: Test failed: Unexpected rawinput data: 0 input.c:2224: Test failed: GetRawInputData succeeded input.c:2225: Test failed: GetRawInputData returned deadbeef input.c:2338: Test failed: Spurious WM_INPUT messages input.c:2789: Test failed: 15: expected WM_INPUT message input.c:2792: Test failed: 15: expected RIM_INPUT message
=== debiant2 (64 bit WoW report) ===
user32: input.c:2162: Test failed: GetRawInputBuffer returned 4 input.c:2157: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2162: Test failed: GetRawInputBuffer returned 0 input.c:2163: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2164: Test failed: Unexpected rawinput data: 0 input.c:2165: Test failed: Unexpected rawinput data: 0 input.c:2166: Test failed: Unexpected rawinput data: 0 input.c:2224: Test failed: GetRawInputData succeeded input.c:2225: Test failed: GetRawInputData returned deadbeef input.c:2338: Test failed: Spurious WM_INPUT messages win.c:10155: Test failed: Expected foreground window 0, got 0000000000F60050 win.c:10161: Test failed: Expected foreground window 00000000000E0120, got 0000000000F60050 win.c:10178: Test failed: Expected foreground window 00000000000E0120, got 0000000000F60050 win.c:10180: Test failed: GetActiveWindow() = 0000000000000000 win.c:10180: Test failed: GetFocus() = 0000000000000000 win.c:10182: Test failed: Received WM_ACTIVATEAPP(0), did not expect it. win.c:10190: Test failed: Expected foreground window 00000000000E0120, got 0000000000000000 win.c:10192: Test failed: GetActiveWindow() = 0000000000000000 win.c:10192: Test failed: GetFocus() = 0000000000000000 win.c:10200: Test failed: Received WM_ACTIVATEAPP(1), did not expect it.
On 5/14/21 9:45 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=90445
Your paranoid android.
=== debiant2 (32 bit Chinese:China report) ===
user32: input.c:2162: Test failed: GetRawInputBuffer returned 4 input.c:2157: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2162: Test failed: GetRawInputBuffer returned 0 input.c:2163: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2164: Test failed: Unexpected rawinput data: 0 input.c:2165: Test failed: Unexpected rawinput data: 0 input.c:2166: Test failed: Unexpected rawinput data: 0 input.c:2224: Test failed: GetRawInputData succeeded input.c:2225: Test failed: GetRawInputData returned deadbeef input.c:2338: Test failed: Spurious WM_INPUT messages input.c:2789: Test failed: 15: expected WM_INPUT message input.c:2792: Test failed: 15: expected RIM_INPUT message
=== debiant2 (64 bit WoW report) ===
user32: input.c:2162: Test failed: GetRawInputBuffer returned 4 input.c:2157: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2162: Test failed: GetRawInputBuffer returned 0 input.c:2163: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2164: Test failed: Unexpected rawinput data: 0 input.c:2165: Test failed: Unexpected rawinput data: 0 input.c:2166: Test failed: Unexpected rawinput data: 0 input.c:2224: Test failed: GetRawInputData succeeded input.c:2225: Test failed: GetRawInputData returned deadbeef
Aaaand it didn't solve them...
Rémi Bernon rbernon@codeweavers.com writes:
@@ -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 */
That's not true in server requests, I don't think we should pretend that it is. The report data should be declared as a separate VARARG field in the request, and use a separate pointer where necessary. The length can probably be stored separately as well.
On 5/14/21 9:38 PM, Alexandre Julliard wrote:
Rémi Bernon rbernon@codeweavers.com writes:
@@ -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 */
That's not true in server requests, I don't think we should pretend that it is. The report data should be declared as a separate VARARG field in the request, and use a separate pointer where necessary. The length can probably be stored separately as well.
Yes, I think I had it like that at some point, it probably got lost somewhere.
I understand that this is only for the send_hardware_message request? I don't see how to do that for get_message request or get_rawinput_buffer, where the replied message data (or message buffer) is already a VARARG, and for which we reply a struct hardware_msg_data, followed by extra bytes for the hid report?
Rémi Bernon rbernon@codeweavers.com writes:
On 5/14/21 9:38 PM, Alexandre Julliard wrote:
Rémi Bernon rbernon@codeweavers.com writes:
@@ -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 */
That's not true in server requests, I don't think we should pretend that it is. The report data should be declared as a separate VARARG field in the request, and use a separate pointer where necessary. The length can probably be stored separately as well.
Yes, I think I had it like that at some point, it probably got lost somewhere.
I understand that this is only for the send_hardware_message request? I don't see how to do that for get_message request or get_rawinput_buffer, where the replied message data (or message buffer) is already a VARARG, and for which we reply a struct hardware_msg_data, followed by extra bytes for the hid report?
Yes, in the message data it would need to be packed in with the rest. But even there it would follow the hardware_msg_data struct, not the rawinput.hid field (right now it's the same, but that could change if other fields are added).
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 034c056bf1c..14cc63649b1 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 9970d37be8b..81a67860cca 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=90446
Your paranoid android.
=== debiant2 (32 bit Chinese:China report) ===
user32: input.c:2157: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2162: Test failed: GetRawInputBuffer returned 0 input.c:2163: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2164: Test failed: Unexpected rawinput data: 0 input.c:2165: Test failed: Unexpected rawinput data: 0 input.c:2166: Test failed: Unexpected rawinput data: 0 input.c:2224: Test failed: GetRawInputData succeeded input.c:2225: Test failed: GetRawInputData returned deadbeef input.c:2338: Test failed: Spurious WM_INPUT messages
=== debiant2 (64 bit WoW report) ===
user32: input.c:2162: Test failed: GetRawInputBuffer returned 4 input.c:2157: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2162: Test failed: GetRawInputBuffer returned 0 input.c:2163: Test failed: GetRawInputBuffer returned unexpected size: 0 input.c:2164: Test failed: Unexpected rawinput data: 0 input.c:2165: Test failed: Unexpected rawinput data: 0 input.c:2166: Test failed: Unexpected rawinput data: 0 input.c:2224: Test failed: GetRawInputData succeeded input.c:2225: Test failed: GetRawInputData returned deadbeef input.c:2338: Test failed: Spurious WM_INPUT messages menu.c:2337: Test failed: test 25
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=90443
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
user32: input.c:757: Test failed: 0 (a4/0): 00 from 00 -> 80 unexpected input.c:757: Test failed: 0 (a4/0): 41 from 01 -> 00 unexpected
=== wvistau64 (64 bit report) ===
user32: input.c:757: Test failed: 0 (a4/0): 01 from 01 -> 00 unexpected input.c:757: Test failed: 0 (a4/0): 11 from 01 -> 00 unexpected input.c:757: Test failed: 0 (a4/0): a2 from 01 -> 00 unexpected
On 5/14/21 9:15 AM, Rémi Bernon wrote:
Signed-off-by: Rémi Bernon rbernon@codeweavers.com
This is likely to be the cause of some of the spurious failures.
v2: (PATCH 3) Check hid.length vs request data size and prefer request data size.
dlls/user32/tests/input.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 3d4f0d03d0d..d7e7c09650f 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -2138,7 +2138,7 @@ static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wpara { RAWINPUT ri; char buffer[16 * sizeof(RAWINPUT64)];
- UINT size, count, rawinput_size, iteration = rawinputbuffer_wndproc_count++;
UINT size, count, rawinput_size, iteration; MSG message;
if (is_wow64) rawinput_size = sizeof(RAWINPUT64);
@@ -2146,6 +2146,8 @@ static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wpara
if (msg == WM_INPUT) {
iteration = rawinputbuffer_wndproc_count++;
count = GetRawInputBuffer(NULL, NULL, sizeof(RAWINPUTHEADER)); ok(count == ~0U, "GetRawInputBuffer succeeded\n");
This first patch can simply be ignored, I've sent some updated version to try to fix the failures (although it's hard to reproduce).
I think the other three patches are pretty much unrelated to the issue.