user32: Return HID devices in GetRawInputDeviceList().

Signed-off-by: Zebediah Figura <zfigura@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2018-08-20 15:24:41 -05:00 committed by Alexandre Julliard
parent 9e4e594972
commit 85d5fc23b4
3 changed files with 147 additions and 5 deletions

View File

@ -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 \

View File

@ -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;
}
/***********************************************************************

View File

@ -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 */