[PATCH v3] user32: Also scan for mouse devices in GetRawInputDeviceList().

Zebediah Figura z.figura12 at gmail.com
Wed Mar 18 20:09:51 CDT 2020


Halo: Spartan Strike attempts to discover input devices using rawinput. It
expects to be able to open at least one device file with a zero access mask. It
does not perform any other operations on the file.

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 dlls/user32/rawinput.c    | 116 +++++++++++++++++++++++---------------
 dlls/user32/tests/input.c |   5 +-
 2 files changed, 71 insertions(+), 50 deletions(-)

diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c
index 85ff0c5e809..8d1048beb93 100644
--- a/dlls/user32/rawinput.c
+++ b/dlls/user32/rawinput.c
@@ -37,27 +37,30 @@
 
 #include "user_private.h"
 
+#include "initguid.h"
+#include "ntddmou.h"
+
 WINE_DEFAULT_DEBUG_CHANNEL(rawinput);
 
-struct hid_device
+struct device
 {
     WCHAR *path;
     HANDLE file;
-    RID_DEVICE_INFO_HID info;
+    RID_DEVICE_INFO info;
     PHIDP_PREPARSED_DATA data;
 };
 
-static struct hid_device *hid_devices;
-static unsigned int hid_devices_count, hid_devices_max;
+static struct device *rawinput_devices;
+static unsigned int rawinput_devices_count, rawinput_devices_max;
 
-static CRITICAL_SECTION hid_devices_cs;
-static CRITICAL_SECTION_DEBUG hid_devices_cs_debug =
+static CRITICAL_SECTION rawinput_devices_cs;
+static CRITICAL_SECTION_DEBUG rawinput_devices_cs_debug =
 {
-    0, 0, &hid_devices_cs,
-    { &hid_devices_cs_debug.ProcessLocksList, &hid_devices_cs_debug.ProcessLocksList },
-      0, 0, { (DWORD_PTR)(__FILE__ ": hid_devices_cs") }
+    0, 0, &rawinput_devices_cs,
+    { &rawinput_devices_cs_debug.ProcessLocksList, &rawinput_devices_cs_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": rawinput_devices_cs") }
 };
-static CRITICAL_SECTION hid_devices_cs = { &hid_devices_cs_debug, -1, 0, 0, 0, 0 };
+static CRITICAL_SECTION rawinput_devices_cs = { &rawinput_devices_cs_debug, -1, 0, 0, 0, 0 };
 
 static BOOL array_reserve(void **elements, unsigned int *capacity, unsigned int count, unsigned int size)
 {
@@ -86,10 +89,10 @@ static BOOL array_reserve(void **elements, unsigned int *capacity, unsigned int
     return TRUE;
 }
 
-static struct hid_device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface)
+static struct device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface)
 {
     SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail;
-    struct hid_device *device;
+    struct device *device;
     HANDLE file;
     WCHAR *path;
     DWORD size;
@@ -127,7 +130,8 @@ static struct hid_device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *ifa
         return NULL;
     }
 
-    if (!array_reserve((void **)&hid_devices, &hid_devices_max, hid_devices_count + 1, sizeof(*hid_devices)))
+    if (!array_reserve((void **)&rawinput_devices, &rawinput_devices_max,
+            rawinput_devices_count + 1, sizeof(*rawinput_devices)))
     {
         ERR("Failed to allocate memory.\n");
         CloseHandle(file);
@@ -135,19 +139,20 @@ static struct hid_device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *ifa
         return NULL;
     }
 
-    device = &hid_devices[hid_devices_count++];
+    device = &rawinput_devices[rawinput_devices_count++];
     device->path = path;
     device->file = file;
+    device->info.cbSize = sizeof(RID_DEVICE_INFO);
 
     return device;
 }
 
-static void find_hid_devices(void)
+static void find_devices(void)
 {
     static ULONGLONG last_check;
 
     SP_DEVICE_INTERFACE_DATA iface = { sizeof(iface) };
-    struct hid_device *device;
+    struct device *device;
     HIDD_ATTRIBUTES attr;
     HIDP_CAPS caps;
     GUID hid_guid;
@@ -160,18 +165,18 @@ static void find_hid_devices(void)
 
     HidD_GetHidGuid(&hid_guid);
 
-    set = SetupDiGetClassDevsW(&hid_guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
-
-    EnterCriticalSection(&hid_devices_cs);
+    EnterCriticalSection(&rawinput_devices_cs);
 
     /* destroy previous list */
-    for (idx = 0; idx < hid_devices_count; ++idx)
+    for (idx = 0; idx < rawinput_devices_count; ++idx)
     {
-        CloseHandle(hid_devices[idx].file);
-        heap_free(hid_devices[idx].path);
+        CloseHandle(rawinput_devices[idx].file);
+        heap_free(rawinput_devices[idx].path);
     }
+    rawinput_devices_count = 0;
+
+    set = SetupDiGetClassDevsW(&hid_guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
 
-    hid_devices_count = 0;
     for (idx = 0; SetupDiEnumDeviceInterfaces(set, NULL, &hid_guid, idx, &iface); ++idx)
     {
         if (!(device = add_device(set, &iface)))
@@ -180,9 +185,11 @@ static void find_hid_devices(void)
         attr.Size = sizeof(HIDD_ATTRIBUTES);
         if (!HidD_GetAttributes(device->file, &attr))
             WARN("Failed to get attributes.\n");
-        device->info.dwVendorId = attr.VendorID;
-        device->info.dwProductId = attr.ProductID;
-        device->info.dwVersionNumber = attr.VersionNumber;
+
+        device->info.dwType = RIM_TYPEHID;
+        device->info.u.hid.dwVendorId = attr.VendorID;
+        device->info.u.hid.dwProductId = attr.ProductID;
+        device->info.u.hid.dwVersionNumber = attr.VersionNumber;
 
         if (!HidD_GetPreparsedData(device->file, &device->data))
             WARN("Failed to get preparsed data.\n");
@@ -190,12 +197,28 @@ static void find_hid_devices(void)
         if (!HidP_GetCaps(device->data, &caps))
             WARN("Failed to get caps.\n");
 
-        device->info.usUsagePage = caps.UsagePage;
-        device->info.usUsage = caps.Usage;
+        device->info.u.hid.usUsagePage = caps.UsagePage;
+        device->info.u.hid.usUsage = caps.Usage;
+    }
+
+    SetupDiDestroyDeviceInfoList(set);
+
+    set = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_MOUSE, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
+
+    for (idx = 0; SetupDiEnumDeviceInterfaces(set, NULL, &GUID_DEVINTERFACE_MOUSE, idx, &iface); ++idx)
+    {
+        static const RID_DEVICE_INFO_MOUSE mouse_info = {1, 5, 0, FALSE};
+
+        if (!(device = add_device(set, &iface)))
+            continue;
+
+        device->info.dwType = RIM_TYPEMOUSE;
+        device->info.u.mouse = mouse_info;
     }
 
-    LeaveCriticalSection(&hid_devices_cs);
     SetupDiDestroyDeviceInfoList(set);
+
+    LeaveCriticalSection(&rawinput_devices_cs);
 }
 
 /***********************************************************************
@@ -219,18 +242,18 @@ UINT WINAPI GetRawInputDeviceList(RAWINPUTDEVICELIST *devices, UINT *device_coun
         return ~0U;
     }
 
-    find_hid_devices();
+    find_devices();
 
     if (!devices)
     {
-        *device_count = 2 + hid_devices_count;
+        *device_count = 2 + rawinput_devices_count;
         return 0;
     }
 
-    if (*device_count < 2 + hid_devices_count)
+    if (*device_count < 2 + rawinput_devices_count)
     {
         SetLastError(ERROR_INSUFFICIENT_BUFFER);
-        *device_count = 2 + hid_devices_count;
+        *device_count = 2 + rawinput_devices_count;
         return ~0U;
     }
 
@@ -239,13 +262,13 @@ UINT WINAPI GetRawInputDeviceList(RAWINPUTDEVICELIST *devices, UINT *device_coun
     devices[1].hDevice = WINE_KEYBOARD_HANDLE;
     devices[1].dwType = RIM_TYPEKEYBOARD;
 
-    for (i = 0; i < hid_devices_count; ++i)
+    for (i = 0; i < rawinput_devices_count; ++i)
     {
-        devices[2 + i].hDevice = &hid_devices[i];
-        devices[2 + i].dwType = RIM_TYPEHID;
+        devices[2 + i].hDevice = &rawinput_devices[i];
+        devices[2 + i].dwType = rawinput_devices[i].info.dwType;
     }
 
-    return 2 + hid_devices_count;
+    return 2 + rawinput_devices_count;
 }
 
 /***********************************************************************
@@ -398,7 +421,7 @@ UINT WINAPI GetRawInputDeviceInfoA(HANDLE device, UINT command, void *data, UINT
 /***********************************************************************
  *              GetRawInputDeviceInfoW   (USER32.@)
  */
-UINT WINAPI GetRawInputDeviceInfoW(HANDLE device, UINT command, void *data, UINT *data_size)
+UINT WINAPI GetRawInputDeviceInfoW(HANDLE handle, UINT command, void *data, UINT *data_size)
 {
     /* FIXME: Most of this is made up. */
     static const WCHAR keyboard_name[] = {'\\','\\','?','\\','W','I','N','E','_','K','E','Y','B','O','A','R','D',0};
@@ -406,8 +429,8 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE device, UINT command, void *data, UINT
     static const RID_DEVICE_INFO_KEYBOARD keyboard_info = {0, 0, 1, 12, 3, 101};
     static const RID_DEVICE_INFO_MOUSE mouse_info = {1, 5, 0, FALSE};
 
+    struct device *device = handle;
     RID_DEVICE_INFO info;
-    struct hid_device *hid_device = device;
     const void *to_copy;
     UINT to_copy_bytes, avail_bytes;
 
@@ -427,20 +450,20 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE device, UINT command, void *data, UINT
     case RIDI_DEVICENAME:
         /* for RIDI_DEVICENAME, data_size is in characters, not bytes */
         avail_bytes = *data_size * sizeof(WCHAR);
-        if (device == WINE_MOUSE_HANDLE)
+        if (handle == WINE_MOUSE_HANDLE)
         {
             *data_size = ARRAY_SIZE(mouse_name);
             to_copy = mouse_name;
         }
-        else if (device == WINE_KEYBOARD_HANDLE)
+        else if (handle == WINE_KEYBOARD_HANDLE)
         {
             *data_size = ARRAY_SIZE(keyboard_name);
             to_copy = keyboard_name;
         }
         else
         {
-            *data_size = strlenW(hid_device->path) + 1;
-            to_copy = hid_device->path;
+            *data_size = strlenW(device->path) + 1;
+            to_copy = device->path;
         }
         to_copy_bytes = *data_size * sizeof(WCHAR);
         break;
@@ -460,8 +483,7 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE device, UINT command, void *data, UINT
         }
         else
         {
-            info.dwType = RIM_TYPEHID;
-            info.u.hid = hid_device->info;
+            info = device->info;
         }
         to_copy_bytes = sizeof(info);
         *data_size = to_copy_bytes;
@@ -479,9 +501,9 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE device, UINT command, void *data, UINT
         }
         else
         {
-            to_copy_bytes = ((WINE_HIDP_PREPARSED_DATA*)hid_device->data)->dwSize;
+            to_copy_bytes = ((WINE_HIDP_PREPARSED_DATA *)device->data)->dwSize;
             *data_size = to_copy_bytes;
-            to_copy = hid_device->data;
+            to_copy = device->data;
         }
         break;
 
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
index ddaf7541e48..2b6a4974f17 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -1689,7 +1689,7 @@ static void test_GetRawInputDeviceList(void)
          * understand that; so use the \\?\ prefix instead */
         name[1] = '\\';
         file = CreateFileW(name, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
-        todo_wine_if(info.dwType != RIM_TYPEHID)
+        todo_wine_if(i == 0 || i == 1)
             ok(file != INVALID_HANDLE_VALUE, "Failed to open %s, error %u\n", wine_dbgstr_w(name), GetLastError());
 
         sz = 0;
@@ -1719,8 +1719,7 @@ static void test_GetRawInputDeviceList(void)
             {
                 /* succeeds on hardware, fails in some VMs */
                 br = HidD_GetPreparsedData(file, &preparsed);
-                todo_wine
-                    ok(br == TRUE || broken(br == FALSE), "HidD_GetPreparsedData failed\n");
+                ok(br == TRUE || broken(br == FALSE), "HidD_GetPreparsedData failed\n");
             }
 
             if (br)
-- 
2.25.1




More information about the wine-devel mailing list