From: Tim Clem tclem@codeweavers.com
--- dlls/user32/tests/input.c | 1 - dlls/win32u/rawinput.c | 172 ++++++++++++++++++++++++-------------- 2 files changed, 111 insertions(+), 62 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index c2b2e4ded80..95abdbb601b 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -2454,7 +2454,6 @@ static void test_GetRawInputBuffer(void) ok(size == sizeof(buffer), "GetRawInputBuffer returned unexpected size: %u\n", size);
ok(HEADER_FIELD(dwType) == RIM_TYPEKEYBOARD, "Unexpected rawinput dwType: %ld\n", HEADER_FIELD(dwType)); - todo_wine_if(is_wow64) ok(HEADER_FIELD(wParam) == 0 || HEADER_FIELD(wParam) == 1, "Expected wparam 0 or 1, got %Iu\n", (WPARAM)HEADER_FIELD(wParam)); scan_code = is_wow64 ? ((RAWINPUT64 *)buffer)->data.keyboard.MakeCode : ((RAWINPUT *)buffer)->data.keyboard.MakeCode; ok(scan_code == 0x2d, "Unexpected rawinput keyboard scan code: %x\n", scan_code); diff --git a/dlls/win32u/rawinput.c b/dlls/win32u/rawinput.c index ab1252ccea6..f4b5d65b335 100644 --- a/dlls/win32u/rawinput.c +++ b/dlls/win32u/rawinput.c @@ -40,6 +40,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(rawinput); #define WINE_MOUSE_HANDLE ((HANDLE)1) #define WINE_KEYBOARD_HANDLE ((HANDLE)2)
+union rawinput_data +{ + RAWMOUSE mouse; + RAWKEYBOARD keyboard; + RAWHID hid; +}; + #ifdef _WIN64 typedef RAWINPUTHEADER RAWINPUTHEADER64; typedef RAWINPUT RAWINPUT64; @@ -55,12 +62,7 @@ typedef struct typedef struct { RAWINPUTHEADER64 header; - union - { - RAWMOUSE mouse; - RAWKEYBOARD keyboard; - RAWHID hid; - } data; + union rawinput_data data; } RAWINPUT64; #endif
@@ -73,11 +75,57 @@ 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 void set_rawinput_header( void *rawinput_buffer, bool force_64_bit, DWORD type, DWORD size, HANDLE device, WPARAM wParam ) { - SIZE_T size; + if (force_64_bit) + { + RAWINPUTHEADER64 *header = (RAWINPUTHEADER64 *)rawinput_buffer; + header->dwType = type; + header->dwSize = size; + +#ifdef _WIN64 + header->hDevice = device; + header->wParam = wParam; +#else + header->hDevice = HandleToULong(device); + header->wParam = (ULONGLONG)wParam; +#endif + } + else + { + RAWINPUTHEADER *header = (RAWINPUTHEADER *)rawinput_buffer; + header->dwType = type; + header->dwSize = size; + header->hDevice = device; + header->wParam = wParam; + } +} + +static bool rawinput_from_hardware_message( void *rawinput_buffer, const struct hardware_msg_data *msg_data, bool force_64_bit ) +{ + /* Under WoW64, GetRawInputBuffer always gives 64-bit RAWINPUT structs. + * GetRawInputData, however, gives the 32-bit version. If force_64_bit + * is true, this function will treat rawinput_buffer as a RAWINPUT64. + * Otherwise, it's treated as a (platform-correct) RAWINPUT. */ + + union rawinput_data *data; + SIZE_T rawinput_size, incoming_size; + +#define RAWINPUT_FIELD_OFFSET(field) (force_64_bit ? FIELD_OFFSET(RAWINPUT64, field) : FIELD_OFFSET(RAWINPUT, field)) + + if (force_64_bit) + { + rawinput_size = sizeof(RAWINPUT64); + incoming_size = ((RAWINPUT64 *)rawinput_buffer)->header.dwSize; + data = (union rawinput_data *)&((RAWINPUT64 *)rawinput_buffer)->data; + } + else + { + rawinput_size = sizeof(RAWINPUT); + incoming_size = ((RAWINPUT *)rawinput_buffer)->header.dwSize; + data = (union rawinput_data *)&((RAWINPUT *)rawinput_buffer)->data; + }
- rawinput->header.dwType = msg_data->rawinput.type; if (msg_data->rawinput.type == RIM_TYPEMOUSE) { static const unsigned int button_flags[] = @@ -92,98 +140,104 @@ static bool rawinput_from_hardware_message( RAWINPUT *rawinput, const struct har }; unsigned int i;
- rawinput->header.dwSize = FIELD_OFFSET(RAWINPUT, data) + sizeof(RAWMOUSE); - rawinput->header.hDevice = WINE_MOUSE_HANDLE; - rawinput->header.wParam = 0; + set_rawinput_header( rawinput_buffer, force_64_bit, + RIM_TYPEMOUSE, + RAWINPUT_FIELD_OFFSET(data) + sizeof(RAWMOUSE), + WINE_MOUSE_HANDLE, + 0 );
- rawinput->data.mouse.usFlags = MOUSE_MOVE_RELATIVE; - rawinput->data.mouse.usButtonFlags = 0; - rawinput->data.mouse.usButtonData = 0; + data->mouse.usFlags = MOUSE_MOVE_RELATIVE; + data->mouse.usButtonFlags = 0; + 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]; + 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; + data->mouse.usButtonFlags |= RI_MOUSE_WHEEL; + 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; + data->mouse.usButtonFlags |= RI_MOUSE_HORIZONTAL_WHEEL; + 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; + 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; + 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; + 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; + 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; + data->mouse.ulRawButtons = 0; + data->mouse.lLastX = msg_data->rawinput.mouse.x; + data->mouse.lLastY = msg_data->rawinput.mouse.y; + data->mouse.ulExtraInformation = msg_data->info; } 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; + set_rawinput_header( rawinput_buffer, force_64_bit, + RIM_TYPEKEYBOARD, + RAWINPUT_FIELD_OFFSET(data) + sizeof(RAWKEYBOARD), + WINE_KEYBOARD_HANDLE, + 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; + data->keyboard.MakeCode = msg_data->rawinput.kbd.scan; + 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; + data->keyboard.Flags |= RI_KEY_E0; + 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; + data->keyboard.VKey = VK_SHIFT; + data->keyboard.Flags &= ~RI_KEY_E0; break;
case VK_LCONTROL: case VK_RCONTROL: - rawinput->data.keyboard.VKey = VK_CONTROL; + data->keyboard.VKey = VK_CONTROL; break;
case VK_LMENU: case VK_RMENU: - rawinput->data.keyboard.VKey = VK_MENU; + data->keyboard.VKey = VK_MENU; break;
default: - rawinput->data.keyboard.VKey = msg_data->rawinput.kbd.vkey; + 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; + data->keyboard.Message = msg_data->rawinput.kbd.message; + data->keyboard.ExtraInformation = msg_data->info; } else if (msg_data->rawinput.type == RIM_TYPEHID) { - size = msg_data->size - sizeof(*msg_data); - if (size > rawinput->header.dwSize - sizeof(*rawinput)) return false; + SIZE_T data_size = msg_data->size - sizeof(*msg_data); + if (data_size > incoming_size - rawinput_size) 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; + set_rawinput_header( rawinput_buffer, force_64_bit, + RIM_TYPEHID, + RAWINPUT_FIELD_OFFSET(data.hid.bRawData) + data_size, + ULongToHandle( msg_data->rawinput.hid.device ), + 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 ); + data->hid.dwCount = msg_data->rawinput.hid.count; + data->hid.dwSizeHid = msg_data->rawinput.hid.length; + memcpy( data->hid.bRawData, msg_data + 1, data_size ); } else { @@ -192,6 +246,8 @@ static bool rawinput_from_hardware_message( RAWINPUT *rawinput, const struct har }
return true; + +#undef RAWINPUT_FIELD_OFFSET }
struct device @@ -609,17 +665,17 @@ 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; + unsigned int count = 0, remaining, rawinput_size, next_size; struct rawinput_thread_data *thread_data; struct hardware_msg_data *msg_data; RAWINPUT *rawinput; int i; + BOOL is_wow = NtCurrentTeb()->WowTebOffset != 0;
- if (NtCurrentTeb()->WowTebOffset) + if (is_wow) rawinput_size = sizeof(RAWINPUT64); else rawinput_size = sizeof(RAWINPUT); - overhead = rawinput_size - sizeof(RAWINPUT);
if (header_size != sizeof(RAWINPUTHEADER)) { @@ -668,13 +724,7 @@ UINT WINAPI NtUserGetRawInputBuffer( RAWINPUT *data, UINT *data_size, UINT heade for (i = 0; i < count; ++i) { data->header.dwSize = remaining; - if (!rawinput_from_hardware_message( data, msg_data )) break; - if (overhead) - { - memmove( (char *)&data->data + overhead, &data->data, - data->header.dwSize - sizeof(RAWINPUTHEADER) ); - } - data->header.dwSize += overhead; + if (!rawinput_from_hardware_message( data, msg_data, is_wow )) break; remaining -= data->header.dwSize; data = NEXTRAWINPUTBLOCK(data); msg_data = (struct hardware_msg_data *)((char *)msg_data + msg_data->size); @@ -776,7 +826,7 @@ 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; + if (!rawinput_from_hardware_message( thread_data->buffer, msg_data, FALSE )) return FALSE; thread_data->hw_id = hw_id; msg->lParam = (LPARAM)hw_id; }