Regardless of how long the driver packet is.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/tests/hid.c | 48 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+)
diff --git a/dlls/dinput/tests/hid.c b/dlls/dinput/tests/hid.c index f8e8a275b09..d6232d578ca 100644 --- a/dlls/dinput/tests/hid.c +++ b/dlls/dinput/tests/hid.c @@ -2110,6 +2110,16 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle .ret_status = STATUS_SUCCESS, }, }; + struct hid_expect expect_small[] = + { + { + .code = IOCTL_HID_READ_REPORT, + .report_len = report_id ? 2 : caps.InputReportByteLength - 1, + .report_buf = {report_id ? report_id + 1 : 0x5a,0x5a,0x5a}, + .ret_length = report_id ? 2 : caps.InputReportByteLength - 1, + .ret_status = STATUS_SUCCESS, + }, + };
send_hid_input( file, expect, sizeof(expect) );
@@ -2190,6 +2200,21 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle value, (report_id ? 3 : 4) ); ok( !memcmp( report, buffer, caps.InputReportByteLength ), "expected identical reports\n" );
+ send_hid_input( file, expect_small, sizeof(expect_small) ); + + Sleep( 600 ); + + SetLastError( 0xdeadbeef ); + memset( report, 0, sizeof(report) ); + ret = ReadFile( async_file, report, caps.InputReportByteLength, NULL, &overlapped ); + ok( !ret, "ReadFile succeeded\n" ); + ok( GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError() ); + + ret = GetOverlappedResult( async_file, &overlapped, &value, TRUE ); + ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() ); + ok( value == report_id ? 2 : caps.InputReportByteLength - 1, + "got length %u, expected %u\n", value, report_id ? 2 : caps.InputReportByteLength - 1 ); + CloseHandle( overlapped.hEvent ); CloseHandle( overlapped2.hEvent ); } @@ -2212,6 +2237,16 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle .ret_status = STATUS_SUCCESS, }, }; + struct hid_expect expect_small[] = + { + { + .code = IOCTL_HID_READ_REPORT, + .report_len = report_id ? 2 : caps.InputReportByteLength - 1, + .report_buf = {report_id ? report_id + 1 : 0x5a,0x5a,0x5a}, + .ret_length = report_id ? 2 : caps.InputReportByteLength - 1, + .ret_status = STATUS_SUCCESS, + }, + };
overlapped.hEvent = CreateEventW( NULL, FALSE, FALSE, NULL ); overlapped2.hEvent = CreateEventW( NULL, FALSE, FALSE, NULL ); @@ -2269,6 +2304,19 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle ok( !memcmp( buffer + off, buffer + caps.InputReportByteLength, caps.InputReportByteLength - off ), "expected identical reports\n" );
+ SetLastError( 0xdeadbeef ); + memset( report, 0, sizeof(report) ); + ret = ReadFile( async_file, report, caps.InputReportByteLength, NULL, &overlapped ); + ok( !ret, "ReadFile succeeded\n" ); + ok( GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError() ); + + send_hid_input( file, expect_small, sizeof(expect_small) ); + + ret = GetOverlappedResult( async_file, &overlapped, &value, TRUE ); + ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() ); + todo_wine_if( report_id ) + ok( value == caps.InputReportByteLength, "got length %u, expected %u\n", value, caps.InputReportByteLength ); + CloseHandle( overlapped.hEvent ); CloseHandle( overlapped2.hEvent ); }
The DS4 controllers are sending 563 bytes HID reports by default, this translates to WM_INPUT messages larger than the default message size.
We would otherwise need an additional server roundtrip on each message, and these devices are also known to be very verbose and continuously send HID reports, so we really don't want it.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/message.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/user32/message.c b/dlls/user32/message.c index d7dbc64d796..44b08da79dd 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -2665,7 +2665,7 @@ static int peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags, struct received_message_info info, *old_info; unsigned int hw_id = 0; /* id of previous hardware message */ void *buffer; - size_t buffer_size = 256; + size_t buffer_size = 1024;
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, buffer_size ))) return -1;
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=105190
Your paranoid android.
=== debian11 (64 bit WoW report) ===
user32: menu.c:2337: Test failed: test 25
So that the client allocates a larger receive buffer when needed and not trigger the assert below when setting the reply message data.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- server/queue.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/server/queue.c b/server/queue.c index f7bc28f39e9..4f69a082b74 100644 --- a/server/queue.c +++ b/server/queue.c @@ -2145,6 +2145,14 @@ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user clear_bits &= ~get_hardware_msg_bit( msg ); continue; } + + reply->total = msg->data_size; + if (msg->data_size > get_reply_max_size()) + { + set_error( STATUS_BUFFER_OVERFLOW ); + return 1; + } + /* now we can return it */ if (!msg->unique_id) msg->unique_id = get_unique_id(); reply->type = MSG_HARDWARE;
This fixes several games (e.g. ICEY) not working well with DS4 gamepad over bluetooth, as we fixup the input report sizes, and the game expects them to be longer.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
v2: Fix length in the hid_report allocation.
dlls/dinput/tests/hid.c | 1 - dlls/hidclass.sys/device.c | 19 +++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/dlls/dinput/tests/hid.c b/dlls/dinput/tests/hid.c index d6232d578ca..a0fd2f6c660 100644 --- a/dlls/dinput/tests/hid.c +++ b/dlls/dinput/tests/hid.c @@ -2314,7 +2314,6 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle
ret = GetOverlappedResult( async_file, &overlapped, &value, TRUE ); ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() ); - todo_wine_if( report_id ) ok( value == caps.InputReportByteLength, "got length %u, expected %u\n", value, caps.InputReportByteLength );
CloseHandle( overlapped.hEvent ); diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index dd288a82b67..0744865f8f7 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -53,15 +53,16 @@ static void WINAPI read_cancel_routine(DEVICE_OBJECT *device, IRP *irp) IoCompleteRequest(irp, IO_NO_INCREMENT); }
-static struct hid_report *hid_report_create( HID_XFER_PACKET *packet ) +static struct hid_report *hid_report_create( HID_XFER_PACKET *packet, ULONG length ) { struct hid_report *report;
- if (!(report = malloc( offsetof( struct hid_report, buffer[packet->reportBufferLen] ) ))) + if (!(report = malloc( offsetof( struct hid_report, buffer[length] ) ))) return NULL; report->ref = 1; - report->length = packet->reportBufferLen; - memcpy( report->buffer, packet->reportBuffer, report->length ); + report->length = length; + memcpy( report->buffer, packet->reportBuffer, packet->reportBufferLen ); + memset( report->buffer + packet->reportBufferLen, 0, length - packet->reportBufferLen );
return report; } @@ -218,18 +219,19 @@ static struct hid_report *hid_queue_pop_report( struct hid_queue *queue ) static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *packet ) { BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; + HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc; const BOOL polled = ext->u.pdo.information.Polled; + ULONG size, report_len = polled ? packet->reportBufferLen : desc->InputLength; struct hid_report *last_report, *report; struct hid_queue *queue; LIST_ENTRY completed, *entry; RAWINPUT *rawinput; - ULONG size; KIRQL irql; IRP *irp;
if (IsEqualGUID( ext->class_guid, &GUID_DEVINTERFACE_HID )) { - size = offsetof( RAWINPUT, data.hid.bRawData[packet->reportBufferLen] ); + size = offsetof( RAWINPUT, data.hid.bRawData[report_len] ); if (!(rawinput = malloc( size ))) ERR( "Failed to allocate rawinput data!\n" ); else { @@ -240,8 +242,9 @@ static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *pack rawinput->header.hDevice = ULongToHandle( ext->u.pdo.rawinput_handle ); rawinput->header.wParam = RIM_INPUT; rawinput->data.hid.dwCount = 1; - rawinput->data.hid.dwSizeHid = packet->reportBufferLen; + rawinput->data.hid.dwSizeHid = report_len; memcpy( rawinput->data.hid.bRawData, packet->reportBuffer, packet->reportBufferLen ); + memset( rawinput->data.hid.bRawData + packet->reportBufferLen, 0, report_len - packet->reportBufferLen );
input.type = INPUT_HARDWARE; input.hi.uMsg = WM_INPUT; @@ -253,7 +256,7 @@ static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *pack } }
- if (!(last_report = hid_report_create( packet ))) + if (!(last_report = hid_report_create( packet, report_len ))) { ERR( "Failed to allocate hid_report!\n" ); return;