From a43be63b337172575b5b7406aa308b8be939a76b Mon Sep 17 00:00:00 2001 From: Alexander Morozov Date: Fri, 5 Jun 2009 13:00:16 +0400 Subject: [PATCH] usbhub.sys: Add registry entries for present USB devices. --- dlls/usbhub.sys/usbhub.c | 115 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 2 deletions(-) diff --git a/dlls/usbhub.sys/usbhub.c b/dlls/usbhub.sys/usbhub.c index b94c1ccdef..731e12a360 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: -- 2.33.8