[Wine-patches] [eterhack 16/23] usbhub.sys: Add registry entries for present USB devices.

Alexander Morozov =?iso-8859-1?q?amorozov_=CE=C1_etersoft=2Eru?=
Пт Июн 5 13:00:16 MSD 2009


---
 dlls/usbhub.sys/usbhub.c |  115 +++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 113 insertions(+), 2 deletions(-)

diff --git a/dlls/usbhub.sys/usbhub.c b/dlls/usbhub.sys/usbhub.c
index b94c1cc..731e12a 100644
--- a/dlls/usbhub.sys/usbhub.c
+++ b/dlls/usbhub.sys/usbhub.c
@@ -1138,7 +1138,11 @@ static BOOL enum_reg_usb_devices(void)
         if (buf == NULL) goto fail;
         ret = SetupDiGetDeviceRegistryPropertyW( set, &devInfo, SPDRP_SERVICE,
                 NULL, (BYTE *)buf, size, NULL );
-        if (!ret) goto fail;
+        if (!ret)
+        {
+            HeapFree( GetProcessHeap(), 0, buf );
+            buf = NULL;
+        }
 
         /* add DeviceInstance structure to Devices list */
         instance = HeapAlloc( GetProcessHeap(), 0, sizeof(*instance) );
@@ -1169,6 +1173,101 @@ fail:
     return FALSE;
 }
 
+static char *new_instance_id( USHORT vid, USHORT pid )
+{
+    struct DeviceInstance *instance;
+    char *p, *prefix = NULL;
+    unsigned int id = 0, n, prefix_len = 0;
+    char *ret;
+
+    LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
+    {
+        if (vid == instance->vid && pid == instance->pid)
+        {
+            if (prefix == NULL)
+            {
+                prefix = instance->instance_id;
+                p = strrchr( instance->instance_id, '&' );
+                if (p == NULL) prefix_len = 0;
+                else prefix_len = p + 1 - prefix;
+                id = strtoul( prefix + prefix_len, NULL, 10 ) + 1;
+            }
+            else
+            {
+                p = strrchr( instance->instance_id, '&' );
+                if (prefix_len)
+                {
+                    if (p == NULL || p + 1 - instance->instance_id != prefix_len ||
+                        strncmp( instance->instance_id, prefix, prefix_len ))
+                        continue;
+                }
+                else if (p != NULL) continue;
+                n = strtoul( instance->instance_id + prefix_len, NULL, 10 ) + 1;
+                if (n > id) id = n;
+            }
+        }
+    }
+    ret = HeapAlloc( GetProcessHeap(), 0, prefix_len + 16 );
+    if (ret == NULL) return NULL;
+    memcpy( ret, prefix, prefix_len );
+    snprintf( ret + prefix_len, prefix_len + 16, "%d", id );
+    return ret;
+}
+
+static void register_usb_device( USHORT vid, USHORT pid, void *dev )
+{
+    static const WCHAR id_fmtW[] = {'U','S','B',
+                                    '\\','V','i','d','_','%','0','4','x',
+                                    '&','P','i','d','_','%','0','4','x',
+                                    '\\','%','s',0};
+
+    struct DeviceInstance *instance;
+    HDEVINFO set = INVALID_HANDLE_VALUE;
+    SP_DEVINFO_DATA devInfo;
+    WCHAR *devnameW = NULL, *instance_idW = NULL;
+    char *instance_id;
+    ULONG size;
+
+    instance_id = new_instance_id( vid, pid );
+    if (instance_id == NULL) return;
+
+    instance = HeapAlloc( GetProcessHeap(), 0, sizeof(*instance) );
+    if (instance == NULL)
+    {
+        HeapFree( GetProcessHeap(), 0, instance_id );
+        goto done;
+    }
+    instance->vid = vid;
+    instance->pid = pid;
+    instance->instance_id = instance_id;
+    instance->service = NULL;
+    instance->dev = dev;
+    list_add_tail( &Devices, &instance->entry );
+
+    size = (strlen(instance_id) + 1) * sizeof(WCHAR);
+    instance_idW = HeapAlloc( GetProcessHeap(), 0, size );
+    if (instance_idW == NULL) goto done;
+    RtlMultiByteToUnicodeN( instance_idW, size, NULL,
+            instance_id, strlen(instance_id) + 1 );
+
+    size = sizeof(id_fmtW) + (strlenW(instance_idW) - 2) * sizeof(WCHAR);
+    devnameW = HeapAlloc( GetProcessHeap(), 0, size );
+    if (devnameW == NULL) goto done;
+    snprintfW( devnameW, size / sizeof(WCHAR), id_fmtW, vid, pid, instance_idW );
+
+    set = SetupDiGetClassDevsW( NULL, usbW, 0, DIGCF_ALLCLASSES );
+    if (set == INVALID_HANDLE_VALUE) goto done;
+    devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
+    if (SetupDiCreateDeviceInfoW( set, devnameW, &GUID_DEVCLASS_USB,
+            NULL, NULL, 0, &devInfo ))
+        SetupDiRegisterDeviceInfo( set, &devInfo, 0, NULL, NULL, NULL );
+done:
+    if (set != INVALID_HANDLE_VALUE)
+        SetupDiDestroyDeviceInfoList( set );
+    if (devnameW) HeapFree( GetProcessHeap(), 0, devnameW );
+    if (instance_idW) HeapFree( GetProcessHeap(), 0, instance_idW );
+}
+
 static void start_device_drivers( DRIVER_OBJECT *hubdrv )
 {
     static const WCHAR grdkeyW[] = {'G','r','d','K','e','y',0};
@@ -1180,7 +1279,7 @@ static void start_device_drivers( DRIVER_OBJECT *hubdrv )
 
     LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
     {
-        if (instance->dev == NULL) continue;
+        if (instance->service == NULL || instance->dev == NULL) continue;
         /* HACK for grdkey.sys */
         if (instance->vid == 0xa89 && start_service( grdkeyW ))
         {
@@ -1225,6 +1324,7 @@ static DWORD CALLBACK enum_usb_devices( void *usbhubdrv )
 #endif
     struct DeviceInstance *instance;
     HANDLE event;
+    BOOL new_device;
 
     if (!enum_reg_usb_devices())
     {
@@ -1256,15 +1356,19 @@ static DWORD CALLBACK enum_usb_devices( void *usbhubdrv )
             create_root_hub_device( desc.idVendor, desc.idProduct, dev, usbhubdrv );
             continue;
         }
+        new_device = TRUE;
         LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
         {
             if (instance->dev == NULL && desc.idVendor == instance->vid &&
                 desc.idProduct == instance->pid)
             {
                 instance->dev = dev;
+                new_device = FALSE;
                 break;
             }
         }
+        if (new_device)
+            register_usb_device( desc.idVendor, desc.idProduct, dev );
     }
     libusb_free_device_list( devs, 1 );
 #else
@@ -1280,6 +1384,8 @@ static DWORD CALLBACK enum_usb_devices( void *usbhubdrv )
     }
     for (bus = usb_busses; bus; bus = bus->next)
         for (dev = bus->devices->next; dev; dev = dev->next)
+        {
+            new_device = TRUE;
             LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
             {
                 if (instance->dev == NULL &&
@@ -1287,9 +1393,14 @@ static DWORD CALLBACK enum_usb_devices( void *usbhubdrv )
                     dev->descriptor.idProduct == instance->pid)
                 {
                     instance->dev = dev;
+                    new_device = FALSE;
                     break;
                 }
             }
+            if (new_device)
+                register_usb_device( dev->descriptor.idVendor,
+                        dev->descriptor.idProduct, dev );
+        }
 #endif
     start_device_drivers( usbhubdrv );
 end:
-- 
1.6.3.1



Подробная информация о списке рассылки Wine-patches