-- v8: 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.
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 350baff600d..657730fa099 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 */ @@ -2013,7 +2011,6 @@ static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wpara SetLastError( 0xdeadbeef ); size = sizeof(rawinput); 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 ); @@ -2027,7 +2024,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() ); @@ -2184,7 +2180,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); @@ -2226,9 +2221,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; @@ -2244,9 +2237,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 e896f6cb72a..a88e1534d24 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 657730fa099..be95bd150b4 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 a88e1534d24..8b51618ebe0 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=142954
Your paranoid android.
=== w11pro64 (32 bit report) ===
user32: input.c:3975: Test failed: layered 5: button_up_hwnd_todo 0: got MSG_TEST_WIN hwnd 001000F0, msg WM_LBUTTONUP, wparam 0, lparam 0x320032 input.c:3975: Test failed: layered 5: button_up_hwnd_todo 1 (missing): MSG_TEST_WIN hwnd 001000F0, WM_LBUTTONUP, wparam 0, lparam 0x320032 input.c:3975: Test failed: layered 6: button_up_hwnd_todo 0: got MSG_TEST_WIN hwnd 001100F0, msg WM_LBUTTONUP, wparam 0, lparam 0x320032 input.c:3975: Test failed: layered 6: button_up_hwnd_todo 1 (missing): MSG_TEST_WIN hwnd 001100F0, WM_LBUTTONUP, wparam 0, lparam 0x320032
=== w1064v1809 (64 bit report) ===
user32: input.c:3868: Test failed: button_up_hwnd 1 (missing): MSG_TEST_WIN hwnd 0000000000040280, WM_LBUTTONUP, wparam 0, lparam 0x320032
Rebased and updated with the remaining changes.
Test failures aren't related. Usual user32:sysparams failures on Windows, adsldp:ldap timeout on Linux.