From: "Rémi Bernon" Subject: [PATCH 6/7] user32: Implement WM_INPUT/RIM_TYPEHID message handling. Message-Id: <20190919120721.31604-7-rbernon@codeweavers.com> Date: Thu, 19 Sep 2019 14:07:20 +0200 In-Reply-To: <20190919120721.31604-1-rbernon@codeweavers.com> References: <20190919120721.31604-1-rbernon@codeweavers.com> Signed-off-by: Rémi Bernon --- dlls/user32/message.c | 19 ++++++++++++++++++- dlls/user32/rawinput.c | 37 +++++++++++++++++++++++++++++++++++++ dlls/user32/user_private.h | 2 ++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/dlls/user32/message.c b/dlls/user32/message.c index 43ce77c2dd6..ca2e01f45e5 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -2285,10 +2285,17 @@ static BOOL process_rawinput_message( MSG *msg, const struct hardware_msg_data * { struct user_thread_info *thread_info = get_user_thread_info(); RAWINPUT *rawinput = thread_info->rawinput; + SIZE_T data_len = 0; + + if (msg_data->rawinput.type == RIM_TYPEHID) + { + data_len = msg_data->rawinput.hid.length; + rawinput = thread_info->rawinput = HeapReAlloc( GetProcessHeap(), 0, rawinput, sizeof(*rawinput) + data_len ); + } if (!rawinput) { - thread_info->rawinput = HeapAlloc( GetProcessHeap(), 0, sizeof(*rawinput) ); + thread_info->rawinput = HeapAlloc( GetProcessHeap(), 0, sizeof(*rawinput) + data_len ); if (!(rawinput = thread_info->rawinput)) return FALSE; } @@ -2383,6 +2390,16 @@ static BOOL process_rawinput_message( MSG *msg, const struct hardware_msg_data * rawinput->data.keyboard.Message = msg_data->rawinput.kbd.message; rawinput->data.keyboard.ExtraInformation = msg_data->info; } + else if (msg_data->rawinput.type == RIM_TYPEHID) + { + rawinput->header.dwSize = FIELD_OFFSET(RAWINPUT, data.hid.bRawData) + data_len; + rawinput->header.hDevice = rawinput_handle_from_device_handle(wine_server_ptr_handle(msg_data->rawinput.hid.device)); + rawinput->header.wParam = 0; + + rawinput->data.hid.dwSizeHid = data_len; + rawinput->data.hid.dwCount = 1; + memcpy(rawinput->data.hid.bRawData, msg_data + 1, data_len); + } else { FIXME("Unhandled rawinput type %#x.\n", msg_data->rawinput.type); diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index 94cf7a9a5d2..511f8ce1755 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -42,6 +42,7 @@ struct hid_device { WCHAR *path; HANDLE file; + HANDLE handle; RID_DEVICE_INFO_HID info; PHIDP_PREPARSED_DATA data; }; @@ -58,6 +59,8 @@ static CRITICAL_SECTION_DEBUG hid_devices_cs_debug = }; static CRITICAL_SECTION hid_devices_cs = { &hid_devices_cs_debug, -1, 0, 0, 0, 0 }; +extern DWORD WINAPI GetFinalPathNameByHandleW(HANDLE file, LPWSTR path, DWORD charcount, DWORD flags); + static BOOL array_reserve(void **elements, unsigned int *capacity, unsigned int count, unsigned int size) { unsigned int new_capacity, max_capacity; @@ -137,10 +140,43 @@ static struct hid_device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *ifa device = &hid_devices[hid_devices_count++]; device->path = path; device->file = file; + device->handle = INVALID_HANDLE_VALUE; return device; } +HANDLE rawinput_handle_from_device_handle(HANDLE device) +{ + WCHAR buffer[sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH + 1]; + OBJECT_NAME_INFORMATION *info = (OBJECT_NAME_INFORMATION*)&buffer; + ULONG dummy; + unsigned int i; + + for (i = 0; i < hid_devices_count; ++i) + { + if (hid_devices[i].handle == device) + return &hid_devices[i]; + } + + if (NtQueryObject( device, ObjectNameInformation, &buffer, sizeof(buffer) - sizeof(WCHAR), &dummy ) || !info->Name.Buffer) + return NULL; + + /* replace \??\ with \\?\ to match hid_devices paths */ + if (info->Name.Length > 1 && info->Name.Buffer[0] == '\\' && info->Name.Buffer[1] == '?') + info->Name.Buffer[1] = '\\'; + + for (i = 0; i < hid_devices_count; ++i) + { + if (strcmpW(hid_devices[i].path, info->Name.Buffer) == 0) + { + hid_devices[i].handle = device; + return &hid_devices[i]; + } + } + + return NULL; +} + static void find_hid_devices(void) { static ULONGLONG last_check; @@ -413,6 +449,7 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE device, UINT command, void *data, UINT device, command, data, data_size); if (!data_size) return ~0U; + if (!device) return ~0U; switch (command) { diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index c11aae707c9..60ceedf3a6a 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -371,4 +371,6 @@ static inline WCHAR *heap_strdupW(const WCHAR *src) return dst; } +extern HANDLE rawinput_handle_from_device_handle(HANDLE device); + #endif /* __WINE_USER_PRIVATE_H */ -- 2.23.0