Zebediah Figura : user32: Return HID devices in GetRawInputDeviceList().

Alexandre Julliard julliard at winehq.org
Tue Aug 21 16:49:01 CDT 2018


Module: wine
Branch: master
Commit: 85d5fc23b4cf6d369115802725e211d0c1195ccf
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=85d5fc23b4cf6d369115802725e211d0c1195ccf

Author: Zebediah Figura <zfigura at codeweavers.com>
Date:   Mon Aug 20 15:24:41 2018 -0500

user32: Return HID devices in GetRawInputDeviceList().

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/user32/Makefile.in    |   2 +-
 dlls/user32/rawinput.c     | 138 +++++++++++++++++++++++++++++++++++++++++++--
 dlls/user32/user_private.h |  12 ++++
 3 files changed, 147 insertions(+), 5 deletions(-)

diff --git a/dlls/user32/Makefile.in b/dlls/user32/Makefile.in
index 81cde06..d420dcb 100644
--- a/dlls/user32/Makefile.in
+++ b/dlls/user32/Makefile.in
@@ -3,7 +3,7 @@ MODULE    = user32.dll
 IMPORTLIB = user32
 IMPORTS   = gdi32 version advapi32
 EXTRAINCL = $(PNG_CFLAGS)
-DELAYIMPORTS = imm32 usp10
+DELAYIMPORTS = hid imm32 setupapi usp10
 
 C_SRCS = \
 	button.c \
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c
index bd5fbf4..91dcff4 100644
--- a/dlls/user32/rawinput.c
+++ b/dlls/user32/rawinput.c
@@ -27,7 +27,10 @@
 #include "winbase.h"
 #include "wingdi.h"
 #include "winnls.h"
+#include "winreg.h"
 #include "winuser.h"
+#include "setupapi.h"
+#include "ddk/hidsdi.h"
 #include "wine/debug.h"
 #include "wine/server.h"
 
@@ -35,11 +38,130 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(rawinput);
 
+struct hid_device
+{
+    WCHAR *path;
+    HANDLE file;
+};
+
+static struct hid_device *hid_devices;
+static unsigned int hid_devices_count, hid_devices_max;
+
+static CRITICAL_SECTION hid_devices_cs;
+static CRITICAL_SECTION_DEBUG hid_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") }
+};
+static CRITICAL_SECTION hid_devices_cs = { &hid_devices_cs_debug, -1, 0, 0, 0, 0 };
+
+static void find_hid_devices(void)
+{
+    static ULONGLONG last_check;
+
+    SP_DEVICE_INTERFACE_DATA iface = { sizeof(iface) };
+    SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail;
+    DWORD detail_size, needed;
+    DWORD idx, didx;
+    GUID hid_guid;
+    HDEVINFO set;
+    HANDLE file;
+    WCHAR *path;
+
+    if (GetTickCount64() - last_check < 2000)
+        return;
+    last_check = GetTickCount64();
+
+    HidD_GetHidGuid(&hid_guid);
+
+    set = SetupDiGetClassDevsW(&hid_guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
+
+    detail_size = sizeof(*detail) + (MAX_PATH * sizeof(WCHAR));
+    if (!(detail = heap_alloc(detail_size)))
+        return;
+    detail->cbSize = sizeof(*detail);
+
+    EnterCriticalSection(&hid_devices_cs);
+
+    /* destroy previous list */
+    for (didx = 0; didx < hid_devices_count; ++didx)
+    {
+        CloseHandle(hid_devices[didx].file);
+        heap_free(hid_devices[didx].path);
+    }
+
+    didx = 0;
+    for (idx = 0; SetupDiEnumDeviceInterfaces(set, NULL, &hid_guid, idx, &iface); ++idx)
+    {
+        if (!SetupDiGetDeviceInterfaceDetailW(set, &iface, detail, detail_size, &needed, NULL))
+        {
+            if (!(detail = heap_realloc(detail, needed)))
+            {
+                ERR("Failed to allocate memory.\n");
+                goto done;
+            }
+            detail_size = needed;
+
+            SetupDiGetDeviceInterfaceDetailW(set, &iface, detail, detail_size, NULL, NULL);
+        }
+
+        if (!(path = heap_strdupW(detail->DevicePath)))
+        {
+            ERR("Failed to allocate memory.\n");
+            goto done;
+        }
+
+        file = CreateFileW(path, GENERIC_READ | GENERIC_WRITE,
+                FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
+        if (file == INVALID_HANDLE_VALUE)
+        {
+            ERR("Failed to open device file %s, error %u.\n", debugstr_w(path), GetLastError());
+            heap_free(path);
+            continue;
+        }
+
+        if (didx >= hid_devices_max)
+        {
+            if (hid_devices)
+            {
+                hid_devices_max *= 2;
+                hid_devices = heap_realloc(hid_devices,
+                    hid_devices_max * sizeof(hid_devices[0]));
+            }
+            else
+            {
+                hid_devices_max = 8;
+                hid_devices = heap_alloc(hid_devices_max * sizeof(hid_devices[0]));
+            }
+            if (!hid_devices)
+            {
+                ERR("Failed to allocate memory.\n");
+                goto done;
+            }
+        }
+
+        TRACE("Found HID device %s.\n", debugstr_w(path));
+
+        hid_devices[didx].path = path;
+        hid_devices[didx].file = file;
+
+        didx++;
+    }
+    hid_devices_count = didx;
+
+done:
+    LeaveCriticalSection(&hid_devices_cs);
+    heap_free(detail);
+}
+
 /***********************************************************************
  *              GetRawInputDeviceList   (USER32.@)
  */
 UINT WINAPI GetRawInputDeviceList(RAWINPUTDEVICELIST *devices, UINT *device_count, UINT size)
 {
+    UINT i;
+
     TRACE("devices %p, device_count %p, size %u.\n", devices, device_count, size);
 
     if (size != sizeof(*devices))
@@ -54,16 +176,18 @@ UINT WINAPI GetRawInputDeviceList(RAWINPUTDEVICELIST *devices, UINT *device_coun
         return ~0U;
     }
 
+    find_hid_devices();
+
     if (!devices)
     {
-        *device_count = 2;
+        *device_count = 2 + hid_devices_count;
         return 0;
     }
 
-    if (*device_count < 2)
+    if (*device_count < 2 + hid_devices_count)
     {
         SetLastError(ERROR_INSUFFICIENT_BUFFER);
-        *device_count = 2;
+        *device_count = 2 + hid_devices_count;
         return ~0U;
     }
 
@@ -72,7 +196,13 @@ UINT WINAPI GetRawInputDeviceList(RAWINPUTDEVICELIST *devices, UINT *device_coun
     devices[1].hDevice = WINE_KEYBOARD_HANDLE;
     devices[1].dwType = RIM_TYPEKEYBOARD;
 
-    return 2;
+    for (i = 0; i < hid_devices_count; ++i)
+    {
+        devices[2 + i].hDevice = &hid_devices[i];
+        devices[2 + i].dwType = RIM_TYPEHID;
+    }
+
+    return 2 + hid_devices_count;
 }
 
 /***********************************************************************
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
index 7a70ae9..73a2bad 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -28,6 +28,8 @@
 #include "winuser.h"
 #include "winreg.h"
 #include "winternl.h"
+#include "wine/heap.h"
+#include "wine/unicode.h"
 
 #define GET_WORD(ptr)  (*(const WORD *)(ptr))
 #define GET_DWORD(ptr) (*(const DWORD *)(ptr))
@@ -354,4 +356,14 @@ extern BOOL get_icon_size( HICON handle, SIZE *size ) DECLSPEC_HIDDEN;
 #define assert(expr) ((void)0)
 #endif
 
+static inline WCHAR *heap_strdupW(const WCHAR *src)
+{
+    WCHAR *dst;
+    unsigned len;
+    if (!src) return NULL;
+    len = (strlenW(src) + 1) * sizeof(WCHAR);
+    if ((dst = heap_alloc(len))) memcpy(dst, src, len);
+    return dst;
+}
+
 #endif /* __WINE_USER_PRIVATE_H */




More information about the wine-cvs mailing list