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