[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