wine-staging/patches/user32-rawinput-hid/0019-user32-Use-device-handles-assigned-by-hidclass.sys.patch
2021-04-24 10:22:14 +10:00

155 lines
4.9 KiB
Diff

From 29aca5031e4237e55b1c3cfe591cd7f4af31fa9c Mon Sep 17 00:00:00 2001
From: Arkadiusz Hiler <ahiler@codeweavers.com>
Date: Mon, 22 Feb 2021 15:41:46 +0200
Subject: [PATCH] user32: Use device handles assigned by hidclass.sys.
This allows us to avoid racy handle mapping for messages from the WM_INPUT
family.
---
dlls/user32/rawinput.c | 61 +++++++++++++++++++++++++++++++++++-------
1 file changed, 51 insertions(+), 10 deletions(-)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c
index 566a5844ad5..d42c2017e78 100644
--- a/dlls/user32/rawinput.c
+++ b/dlls/user32/rawinput.c
@@ -38,15 +38,19 @@
#include "user_private.h"
#include "initguid.h"
+#include "devpkey.h"
#include "ntddmou.h"
#include "ntddkbd.h"
WINE_DEFAULT_DEBUG_CHANNEL(rawinput);
+DEFINE_DEVPROPKEY(DEVPROPKEY_HID_HANDLE, 0xbc62e415, 0xf4fe, 0x405c, 0x8e, 0xda, 0x63, 0x6f, 0xb5, 0x9f, 0x08, 0x98, 2);
+
struct device
{
SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail;
HANDLE file;
+ HANDLE handle;
RID_DEVICE_INFO info;
PHIDP_PREPARSED_DATA data;
};
@@ -92,10 +96,12 @@ static BOOL array_reserve(void **elements, unsigned int *capacity, unsigned int
static struct device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface)
{
+ SP_DEVINFO_DATA device_data = {sizeof(device_data)};
SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail;
+ UINT32 handle;
struct device *device;
HANDLE file;
- DWORD size;
+ DWORD idx, size, type;
SetupDiGetDeviceInterfaceDetailW(set, iface, NULL, 0, &size, NULL);
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
@@ -109,7 +115,27 @@ static struct device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface)
return FALSE;
}
detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
- SetupDiGetDeviceInterfaceDetailW(set, iface, detail, size, NULL, NULL);
+ SetupDiGetDeviceInterfaceDetailW(set, iface, detail, size, NULL, &device_data);
+
+ if (!SetupDiGetDevicePropertyW(set, &device_data, &DEVPROPKEY_HID_HANDLE, &type, (BYTE *)&handle, sizeof(handle), NULL, 0))
+ {
+ ERR("Failed to get handle for %s, skipping HID device.\n", debugstr_w(detail->DevicePath));
+ heap_free(detail);
+ return NULL;
+ }
+
+ if (type != DEVPROP_TYPE_UINT32)
+ ERR("Wrong prop type for HANDLE.\n");
+
+ for (idx = 0; idx < rawinput_devices_count; ++idx)
+ {
+ if (rawinput_devices[idx].handle == ULongToHandle(handle))
+ {
+ TRACE("Discarding %s as it's a duplicate of %s.\n", debugstr_w(detail->DevicePath), debugstr_w(rawinput_devices[idx].detail->DevicePath));
+ heap_free(detail);
+ return NULL;
+ }
+ }
TRACE("Found HID device %s.\n", debugstr_w(detail->DevicePath));
@@ -135,6 +161,7 @@ static struct device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface)
device->detail = detail;
device->file = file;
device->info.cbSize = sizeof(RID_DEVICE_INFO);
+ device->handle = ULongToHandle(handle);
device->data = NULL;
return device;
@@ -142,8 +169,6 @@ static struct device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface)
static void find_devices(void)
{
- static ULONGLONG last_check;
-
SP_DEVICE_INTERFACE_DATA iface = { sizeof(iface) };
struct device *device;
HIDD_ATTRIBUTES attr;
@@ -152,10 +177,6 @@ static void find_devices(void)
HDEVINFO set;
DWORD idx;
- if (GetTickCount64() - last_check < 2000)
- return;
- last_check = GetTickCount64();
-
HidD_GetHidGuid(&hid_guid);
EnterCriticalSection(&rawinput_devices_cs);
@@ -247,6 +268,26 @@ static void find_devices(void)
}
+static struct device *rawinput_device_from_handle(HANDLE handle)
+{
+ unsigned int i;
+
+ if (!handle) return NULL;
+
+ for (i = 0; i < rawinput_devices_count; ++i)
+ if (rawinput_devices[i].handle == handle)
+ return &rawinput_devices[i];
+
+ find_devices();
+
+ for (i = 0; i < rawinput_devices_count; ++i)
+ if (rawinput_devices[i].handle == handle)
+ return &rawinput_devices[i];
+
+ return NULL;
+}
+
+
struct rawinput_thread_data *rawinput_thread_data(void)
{
struct user_thread_info *thread_info = get_user_thread_info();
@@ -420,7 +461,7 @@ UINT WINAPI GetRawInputDeviceList(RAWINPUTDEVICELIST *devices, UINT *device_coun
for (i = 0; i < rawinput_devices_count; ++i)
{
- devices[2 + i].hDevice = &rawinput_devices[i];
+ devices[2 + i].hDevice = rawinput_devices[i].handle;
devices[2 + i].dwType = rawinput_devices[i].info.dwType;
}
@@ -692,7 +733,7 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE handle, UINT command, void *data, UINT
static const RID_DEVICE_INFO_MOUSE mouse_info = {1, 5, 0, FALSE};
RID_DEVICE_INFO info;
- struct device *device = handle;
+ struct device *device = rawinput_device_from_handle(handle);
const void *to_copy;
UINT to_copy_bytes, avail_bytes;
--
2.30.2