Zebediah Figura : user32: Use registry APIs to enumerate raw input devices.

Alexandre Julliard julliard at winehq.org
Fri Jun 10 16:28:26 CDT 2022


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

Author: Zebediah Figura <zfigura at codeweavers.com>
Date:   Sun May 15 12:31:09 2022 -0500

user32: Use registry APIs to enumerate raw input devices.

---

 dlls/user32/rawinput.c | 119 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 84 insertions(+), 35 deletions(-)

diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c
index 3750332c0cf..ab542956f11 100644
--- a/dlls/user32/rawinput.c
+++ b/dlls/user32/rawinput.c
@@ -30,18 +30,13 @@
 #include "winnls.h"
 #include "winreg.h"
 #include "winuser.h"
-#include "setupapi.h"
+#include "ddk/hidclass.h"
 #include "wine/debug.h"
 #include "wine/server.h"
 #include "wine/hid.h"
 
 #include "user_private.h"
 
-#include "initguid.h"
-#include "ddk/hidclass.h"
-#include "ntddmou.h"
-#include "ntddkbd.h"
-
 WINE_DEFAULT_DEBUG_CHANNEL(rawinput);
 
 struct device
@@ -92,40 +87,47 @@ 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, DWORD type )
+static ULONG query_reg_value( HKEY hkey, const WCHAR *name,
+                              KEY_VALUE_PARTIAL_INFORMATION *info, ULONG size )
 {
+    unsigned int name_size = name ? lstrlenW( name ) * sizeof(WCHAR) : 0;
+    UNICODE_STRING nameW = { name_size, name_size, (WCHAR *)name };
+
+    if (NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
+                         info, size, &size ))
+        return 0;
+
+    return size - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
+}
+
+static struct device *add_device( HKEY key, DWORD type )
+{
+    static const WCHAR symbolic_linkW[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
+    char value_buffer[4096];
+    KEY_VALUE_PARTIAL_INFORMATION *value = (KEY_VALUE_PARTIAL_INFORMATION *)value_buffer;
     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)};
     struct hid_preparsed_data *preparsed = NULL;
-    SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail;
     HID_COLLECTION_INFORMATION hid_info;
     struct device *device = NULL;
     RID_DEVICE_INFO info;
     IO_STATUS_BLOCK io;
     WCHAR *path, *pos;
     NTSTATUS status;
+    unsigned int i;
     UINT32 handle;
-    DWORD i, size;
     HANDLE file;
 
-    SetupDiGetDeviceInterfaceDetailW(set, iface, NULL, 0, &size, &device_data);
-    if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+    if (!query_reg_value( key, symbolic_linkW, value, sizeof(value_buffer) ))
     {
-        ERR("Failed to get device path, error %#lx.\n", GetLastError());
-        return FALSE;
+        ERR( "failed to get symbolic link value\n" );
+        return NULL;
     }
 
-    if (!(detail = malloc(size)))
-    {
-        ERR("Failed to allocate memory.\n");
-        return FALSE;
-    }
-    detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
-    SetupDiGetDeviceInterfaceDetailW(set, iface, detail, size, NULL, NULL);
-    path = wcsdup( detail->DevicePath );
-    free( detail );
-    if (!path) return NULL;
+    if (!(path = malloc( value->DataLength + sizeof(WCHAR) )))
+        return NULL;
+    memcpy( path, value->Data, value->DataLength );
+    path[value->DataLength / sizeof(WCHAR)] = 0;
 
     /* upper case everything but the GUID */
     for (pos = path; *pos && *pos != '{'; pos++) *pos = towupper(*pos);
@@ -234,18 +236,65 @@ fail:
     return NULL;
 }
 
-static void enumerate_devices( DWORD type, const GUID *guid )
+static HKEY reg_open_key( HKEY root, const WCHAR *name, ULONG name_len )
 {
-    SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)};
-    HDEVINFO set;
-    DWORD idx;
+    UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name };
+    OBJECT_ATTRIBUTES attr;
+    HANDLE ret;
+
+    attr.Length = sizeof(attr);
+    attr.RootDirectory = root;
+    attr.ObjectName = &nameW;
+    attr.Attributes = 0;
+    attr.SecurityDescriptor = NULL;
+    attr.SecurityQualityOfService = NULL;
+
+    if (NtOpenKeyEx( &ret, MAXIMUM_ALLOWED, &attr, 0 )) return 0;
+    return ret;
+}
 
-    set = SetupDiGetClassDevsW( guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT );
+static const WCHAR device_classesW[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceClasses\\";
+static const WCHAR guid_devinterface_hidW[] = L"{4d1e55b2-f16f-11cf-88cb-001111000030}";
+static const WCHAR guid_devinterface_keyboardW[] = L"{884b96c3-56ef-11d1-bc8c-00a0c91405dd}";
+static const WCHAR guid_devinterface_mouseW[] = L"{378de44c-56ef-11d1-bc8c-00a0c91405dd}";
 
-    for (idx = 0; SetupDiEnumDeviceInterfaces( set, NULL, &GUID_DEVINTERFACE_HID, idx, &iface); ++idx )
-        add_device( set, &iface, type );
+static void enumerate_devices( DWORD type, const WCHAR *class )
+{
+    WCHAR buffer[1024];
+    KEY_NODE_INFORMATION *subkey_info = (void *)buffer;
+    HKEY class_key, device_key, iface_key;
+    unsigned int i, j;
+    DWORD size;
+
+    wcscpy( buffer, device_classesW );
+    wcscat( buffer, class );
+    if (!(class_key = reg_open_key( NULL, buffer, wcslen( buffer ) * sizeof(WCHAR) )))
+        return;
+
+    for (i = 0; !NtEnumerateKey( class_key, i, KeyNodeInformation, buffer, sizeof(buffer), &size ); ++i)
+    {
+        if (!(device_key = reg_open_key( class_key, subkey_info->Name, subkey_info->NameLength )))
+        {
+            ERR( "failed to open %s\n", debugstr_wn(subkey_info->Name, subkey_info->NameLength / sizeof(WCHAR)) );
+            continue;
+        }
+
+        for (j = 0; !NtEnumerateKey( device_key, j, KeyNodeInformation, buffer, sizeof(buffer), &size ); ++j)
+        {
+            if (!(iface_key = reg_open_key( device_key, subkey_info->Name, subkey_info->NameLength )))
+            {
+                ERR( "failed to open %s\n", debugstr_wn(subkey_info->Name, subkey_info->NameLength / sizeof(WCHAR)) );
+                continue;
+            }
+
+            add_device( iface_key, type );
+            NtClose( iface_key );
+        }
+
+        NtClose( device_key );
+    }
 
-    SetupDiDestroyDeviceInfoList( set );
+    NtClose( class_key );
 }
 
 void rawinput_update_device_list(void)
@@ -265,9 +314,9 @@ void rawinput_update_device_list(void)
     }
     rawinput_devices_count = 0;
 
-    enumerate_devices( RIM_TYPEHID, &GUID_DEVINTERFACE_HID );
-    enumerate_devices( RIM_TYPEMOUSE, &GUID_DEVINTERFACE_MOUSE );
-    enumerate_devices( RIM_TYPEKEYBOARD, &GUID_DEVINTERFACE_KEYBOARD );
+    enumerate_devices( RIM_TYPEHID, guid_devinterface_hidW );
+    enumerate_devices( RIM_TYPEMOUSE, guid_devinterface_mouseW );
+    enumerate_devices( RIM_TYPEKEYBOARD, guid_devinterface_keyboardW );
 
     LeaveCriticalSection(&rawinput_devices_cs);
 }




More information about the wine-cvs mailing list