-- v3: user32: Factor out raw input device enumeration. user32: Use HID ioctls directly. user32: Use GUID_DEVINTERFACE_HID directly. user32: Retrieve the usage page and usage directly from the hid_preparsed_data structure. user32: Handle failure from HID APIs. user32: Populate the RID_DEVICE_INFO structure in add_device().
From: Zebediah Figura zfigura@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/user32/rawinput.c | 84 +++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 37 deletions(-)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index d706e19d64f..1867e213223 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -94,15 +94,21 @@ static BOOL array_reserve(void **elements, unsigned int *capacity, unsigned int return TRUE; }
-static struct device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface) +static struct device *add_device( HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface, DWORD type ) { + 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}; SP_DEVINFO_DATA device_data = {sizeof(device_data)}; + PHIDP_PREPARSED_DATA preparsed_data = NULL; SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail; struct device *device = NULL; + RID_DEVICE_INFO info; + HIDD_ATTRIBUTES attr; + HIDP_CAPS caps; UINT32 handle; + DWORD i, size; HANDLE file; WCHAR *pos; - DWORD i, size, type;
SetupDiGetDeviceInterfaceDetailW(set, iface, NULL, 0, &size, &device_data); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) @@ -138,6 +144,40 @@ static struct device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface) return NULL; }
+ memset( &info, 0, sizeof(info) ); + info.cbSize = sizeof(info); + info.dwType = type; + + switch (type) + { + case RIM_TYPEHID: + attr.Size = sizeof(HIDD_ATTRIBUTES); + if (!HidD_GetAttributes( device->file, &attr )) + WARN("Failed to get attributes.\n"); + + info.hid.dwVendorId = attr.VendorID; + info.hid.dwProductId = attr.ProductID; + info.hid.dwVersionNumber = attr.VersionNumber; + + if (!HidD_GetPreparsedData( file, &preparsed_data )) + WARN("Failed to get preparsed data.\n"); + + if (!HidP_GetCaps( preparsed_data, &caps )) + WARN("Failed to get caps.\n"); + + info.hid.usUsagePage = caps.UsagePage; + info.hid.usUsage = caps.Usage; + break; + + case RIM_TYPEMOUSE: + info.mouse = mouse_info; + break; + + case RIM_TYPEKEYBOARD: + info.keyboard = keyboard_info; + break; + } + for (i = 0; i < rawinput_devices_count && !device; ++i) if (rawinput_devices[i].handle == UlongToHandle(handle)) device = rawinput_devices + i; @@ -166,8 +206,8 @@ static struct device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface) device->detail = detail; device->file = file; device->handle = ULongToHandle(handle); - device->info.cbSize = sizeof(RID_DEVICE_INFO); - device->data = NULL; + device->info = info; + device->data = preparsed_data;
return device; } @@ -176,8 +216,6 @@ void rawinput_update_device_list(void) { SP_DEVICE_INTERFACE_DATA iface = { sizeof(iface) }; struct device *device; - HIDD_ATTRIBUTES attr; - HIDP_CAPS caps; GUID hid_guid; HDEVINFO set; DWORD idx; @@ -201,26 +239,8 @@ void rawinput_update_device_list(void)
for (idx = 0; SetupDiEnumDeviceInterfaces(set, NULL, &hid_guid, idx, &iface); ++idx) { - if (!(device = add_device(set, &iface))) + if (!(device = add_device( set, &iface, RIM_TYPEHID ))) continue; - - attr.Size = sizeof(HIDD_ATTRIBUTES); - if (!HidD_GetAttributes(device->file, &attr)) - WARN("Failed to get attributes.\n"); - - device->info.dwType = RIM_TYPEHID; - device->info.hid.dwVendorId = attr.VendorID; - device->info.hid.dwProductId = attr.ProductID; - device->info.hid.dwVersionNumber = attr.VersionNumber; - - if (!HidD_GetPreparsedData(device->file, &device->data)) - WARN("Failed to get preparsed data.\n"); - - if (!HidP_GetCaps(device->data, &caps)) - WARN("Failed to get caps.\n"); - - device->info.hid.usUsagePage = caps.UsagePage; - device->info.hid.usUsage = caps.Usage; }
SetupDiDestroyDeviceInfoList(set); @@ -229,13 +249,8 @@ void rawinput_update_device_list(void)
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))) + if (!(device = add_device( set, &iface, RIM_TYPEMOUSE ))) continue; - - device->info.dwType = RIM_TYPEMOUSE; - device->info.mouse = mouse_info; }
SetupDiDestroyDeviceInfoList(set); @@ -244,13 +259,8 @@ void rawinput_update_device_list(void)
for (idx = 0; SetupDiEnumDeviceInterfaces(set, NULL, &GUID_DEVINTERFACE_KEYBOARD, idx, &iface); ++idx) { - static const RID_DEVICE_INFO_KEYBOARD keyboard_info = {0, 0, 1, 12, 3, 101}; - - if (!(device = add_device(set, &iface))) + if (!(device = add_device( set, &iface, RIM_TYPEHID ))) continue; - - device->info.dwType = RIM_TYPEKEYBOARD; - device->info.keyboard = keyboard_info; }
SetupDiDestroyDeviceInfoList(set);
From: Zebediah Figura zfigura@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/user32/rawinput.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index 1867e213223..a103751a109 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -153,17 +153,26 @@ static struct device *add_device( HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface, case RIM_TYPEHID: attr.Size = sizeof(HIDD_ATTRIBUTES); if (!HidD_GetAttributes( device->file, &attr )) - WARN("Failed to get attributes.\n"); + { + ERR( "Failed to get attributes.\n" ); + goto fail; + }
info.hid.dwVendorId = attr.VendorID; info.hid.dwProductId = attr.ProductID; info.hid.dwVersionNumber = attr.VersionNumber;
if (!HidD_GetPreparsedData( file, &preparsed_data )) - WARN("Failed to get preparsed data.\n"); + { + ERR( "Failed to get preparsed data.\n" ); + goto fail; + }
if (!HidP_GetCaps( preparsed_data, &caps )) - WARN("Failed to get caps.\n"); + { + ERR( "Failed to get caps.\n" ); + goto fail; + }
info.hid.usUsagePage = caps.UsagePage; info.hid.usUsage = caps.Usage; @@ -198,9 +207,7 @@ static struct device *add_device( HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface, else { ERR("Failed to allocate memory.\n"); - CloseHandle(file); - free(detail); - return NULL; + goto fail; }
device->detail = detail; @@ -210,6 +217,12 @@ static struct device *add_device( HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface, device->data = preparsed_data;
return device; + +fail: + free( preparsed_data ); + CloseHandle( file ); + free( detail ); + return NULL; }
void rawinput_update_device_list(void)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=115965
Your paranoid android.
=== debian11 (32 bit WoW report) ===
user32: win.c:10976: Test failed: Expected foreground window 0, got 011400CE win.c:10982: Test failed: Expected foreground window 001A0124, got 011400CE
From: Zebediah Figura zfigura@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/user32/rawinput.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index a103751a109..e9ac5e9aff2 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -101,10 +101,10 @@ static struct device *add_device( HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface, SP_DEVINFO_DATA device_data = {sizeof(device_data)}; PHIDP_PREPARSED_DATA preparsed_data = NULL; SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail; + struct hid_preparsed_data *preparsed; struct device *device = NULL; RID_DEVICE_INFO info; HIDD_ATTRIBUTES attr; - HIDP_CAPS caps; UINT32 handle; DWORD i, size; HANDLE file; @@ -167,15 +167,10 @@ static struct device *add_device( HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface, ERR( "Failed to get preparsed data.\n" ); goto fail; } + preparsed = (struct hid_preparsed_data *)preparsed_data;
- if (!HidP_GetCaps( preparsed_data, &caps )) - { - ERR( "Failed to get caps.\n" ); - goto fail; - } - - info.hid.usUsagePage = caps.UsagePage; - info.hid.usUsage = caps.Usage; + info.hid.usUsagePage = preparsed->usage_page; + info.hid.usUsage = preparsed->usage; break;
case RIM_TYPEMOUSE:
From: Zebediah Figura zfigura@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/user32/rawinput.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index e9ac5e9aff2..c9afc18ea53 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -38,6 +38,7 @@ #include "user_private.h"
#include "initguid.h" +#include "ddk/hidclass.h" #include "devpkey.h" #include "ntddmou.h" #include "ntddkbd.h" @@ -224,14 +225,11 @@ void rawinput_update_device_list(void) { SP_DEVICE_INTERFACE_DATA iface = { sizeof(iface) }; struct device *device; - GUID hid_guid; HDEVINFO set; DWORD idx;
TRACE("\n");
- HidD_GetHidGuid(&hid_guid); - EnterCriticalSection(&rawinput_devices_cs);
/* destroy previous list */ @@ -243,9 +241,9 @@ void rawinput_update_device_list(void) } rawinput_devices_count = 0;
- set = SetupDiGetClassDevsW(&hid_guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); + set = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_HID, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
- for (idx = 0; SetupDiEnumDeviceInterfaces(set, NULL, &hid_guid, idx, &iface); ++idx) + for (idx = 0; SetupDiEnumDeviceInterfaces(set, NULL, &GUID_DEVINTERFACE_HID, idx, &iface); ++idx) { if (!(device = add_device( set, &iface, RIM_TYPEHID ))) continue;
From: Zebediah Figura zfigura@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/user32/Makefile.in | 2 +- dlls/user32/rawinput.c | 53 +++++++++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 22 deletions(-)
diff --git a/dlls/user32/Makefile.in b/dlls/user32/Makefile.in index 3f4115c5679..79821929390 100644 --- a/dlls/user32/Makefile.in +++ b/dlls/user32/Makefile.in @@ -3,7 +3,7 @@ MODULE = user32.dll IMPORTLIB = user32 IMPORTS = $(PNG_PE_LIBS) gdi32 version sechost advapi32 kernelbase win32u EXTRAINCL = $(PNG_PE_CFLAGS) -DELAYIMPORTS = hid setupapi imm32 +DELAYIMPORTS = setupapi imm32
C_SRCS = \ button.c \ diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index c9afc18ea53..5f5c898be0e 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -26,11 +26,11 @@ #include "windef.h" #include "winbase.h" #include "wingdi.h" +#include "winioctl.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" #include "wine/hid.h" @@ -53,7 +53,7 @@ struct device HANDLE file; HANDLE handle; RID_DEVICE_INFO info; - PHIDP_PREPARSED_DATA data; + struct hid_preparsed_data *data; };
static struct device *rawinput_devices; @@ -100,12 +100,13 @@ static struct device *add_device( HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface, 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}; SP_DEVINFO_DATA device_data = {sizeof(device_data)}; - PHIDP_PREPARSED_DATA preparsed_data = NULL; + struct hid_preparsed_data *preparsed = NULL; SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail; - struct hid_preparsed_data *preparsed; + HID_COLLECTION_INFORMATION hid_info; struct device *device = NULL; RID_DEVICE_INFO info; - HIDD_ATTRIBUTES attr; + IO_STATUS_BLOCK io; + NTSTATUS status; UINT32 handle; DWORD i, size; HANDLE file; @@ -152,23 +153,33 @@ static struct device *add_device( HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface, switch (type) { case RIM_TYPEHID: - attr.Size = sizeof(HIDD_ATTRIBUTES); - if (!HidD_GetAttributes( device->file, &attr )) + status = NtDeviceIoControlFile( device->file, NULL, NULL, NULL, &io, + IOCTL_HID_GET_COLLECTION_INFORMATION, + NULL, 0, &hid_info, sizeof(hid_info) ); + if (status) { - ERR( "Failed to get attributes.\n" ); + ERR( "Failed to get collection information, status %#lx.\n", status ); goto fail; }
- info.hid.dwVendorId = attr.VendorID; - info.hid.dwProductId = attr.ProductID; - info.hid.dwVersionNumber = attr.VersionNumber; + info.hid.dwVendorId = hid_info.VendorID; + info.hid.dwProductId = hid_info.ProductID; + info.hid.dwVersionNumber = hid_info.VersionNumber; + + if (!(preparsed = malloc( hid_info.DescriptorSize ))) + { + ERR( "Failed to allocate memory.\n" ); + goto fail; + }
- if (!HidD_GetPreparsedData( file, &preparsed_data )) + status = NtDeviceIoControlFile( device->file, NULL, NULL, NULL, &io, + IOCTL_HID_GET_COLLECTION_DESCRIPTOR, + NULL, 0, preparsed, hid_info.DescriptorSize ); + if (status) { - ERR( "Failed to get preparsed data.\n" ); + ERR( "Failed to get collection descriptor, status %#lx.\n", status ); goto fail; } - preparsed = (struct hid_preparsed_data *)preparsed_data;
info.hid.usUsagePage = preparsed->usage_page; info.hid.usUsage = preparsed->usage; @@ -190,7 +201,7 @@ static struct device *add_device( HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface, if (device) { TRACE("Updating device %x / %s.\n", handle, debugstr_w(detail->DevicePath)); - HidD_FreePreparsedData(device->data); + free(device->data); CloseHandle(device->file); free(device->detail); } @@ -210,12 +221,12 @@ static struct device *add_device( HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface, device->file = file; device->handle = ULongToHandle(handle); device->info = info; - device->data = preparsed_data; + device->data = preparsed;
return device;
fail: - free( preparsed_data ); + free( preparsed ); CloseHandle( file ); free( detail ); return NULL; @@ -235,7 +246,7 @@ void rawinput_update_device_list(void) /* destroy previous list */ for (idx = 0; idx < rawinput_devices_count; ++idx) { - HidD_FreePreparsedData(rawinput_devices[idx].data); + free(rawinput_devices[idx].data); CloseHandle(rawinput_devices[idx].file); free(rawinput_devices[idx].detail); } @@ -779,12 +790,12 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE handle, UINT command, void *data, UINT break;
case RIDI_PREPARSEDDATA: - if (!(preparsed = (struct hid_preparsed_data *)device->data)) len = 0; + if (!(preparsed = device->data)) len = 0; else len = preparsed->caps_size + FIELD_OFFSET(struct hid_preparsed_data, value_caps[0]) + preparsed->number_link_collection_nodes * sizeof(struct hid_collection_node);
- if (device->data && len <= data_len && data) - memcpy(data, device->data, len); + if (preparsed && len <= data_len && data) + memcpy(data, preparsed, len); *data_size = len; break;
From: Zebediah Figura zfigura@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/user32/rawinput.c | 49 +++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 32 deletions(-)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index 5f5c898be0e..90ca074f2a4 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -232,13 +232,24 @@ fail: return NULL; }
-void rawinput_update_device_list(void) +static void enumerate_devices( DWORD type, const GUID *guid ) { - SP_DEVICE_INTERFACE_DATA iface = { sizeof(iface) }; - struct device *device; + SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}; HDEVINFO set; DWORD idx;
+ set = SetupDiGetClassDevsW( guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT ); + + for (idx = 0; SetupDiEnumDeviceInterfaces( set, NULL, &GUID_DEVINTERFACE_HID, idx, &iface); ++idx ) + add_device( set, &iface, type ); + + SetupDiDestroyDeviceInfoList( set ); +} + +void rawinput_update_device_list(void) +{ + DWORD idx; + TRACE("\n");
EnterCriticalSection(&rawinput_devices_cs); @@ -252,35 +263,9 @@ void rawinput_update_device_list(void) } rawinput_devices_count = 0;
- set = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_HID, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); - - for (idx = 0; SetupDiEnumDeviceInterfaces(set, NULL, &GUID_DEVINTERFACE_HID, idx, &iface); ++idx) - { - if (!(device = add_device( set, &iface, RIM_TYPEHID ))) - continue; - } - - 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) - { - if (!(device = add_device( set, &iface, RIM_TYPEMOUSE ))) - continue; - } - - SetupDiDestroyDeviceInfoList(set); - - set = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_KEYBOARD, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); - - for (idx = 0; SetupDiEnumDeviceInterfaces(set, NULL, &GUID_DEVINTERFACE_KEYBOARD, idx, &iface); ++idx) - { - if (!(device = add_device( set, &iface, RIM_TYPEHID ))) - continue; - } - - SetupDiDestroyDeviceInfoList(set); + enumerate_devices( RIM_TYPEHID, &GUID_DEVINTERFACE_HID ); + enumerate_devices( RIM_TYPEMOUSE, &GUID_DEVINTERFACE_MOUSE ); + enumerate_devices( RIM_TYPEKEYBOARD, &GUID_DEVINTERFACE_KEYBOARD );
LeaveCriticalSection(&rawinput_devices_cs); }
This merge request was approved by Rémi Bernon.