[Wine-patches] [5/5] Create USBSTOR device interfaces.

Alexander Morozov =?iso-8859-1?q?amorozov_=CE=C1_etersoft=2Eru?=
Ср Ноя 12 12:46:01 MSK 2008


Ветка eterhack, баг 2581
----------- следующая часть -----------
From 57c7b44944913472f1fb5113e65a7ffa7005f95c Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Wed, 12 Nov 2008 11:24:33 +0300
Subject: [PATCH] Create USBSTOR device interfaces.

---
 dlls/mountmgr.sys/device.c |   81 ++++++++++++++++++++++++++++++++++++-------
 include/winioctl.h         |    2 +
 2 files changed, 69 insertions(+), 14 deletions(-)

diff --git a/dlls/mountmgr.sys/device.c b/dlls/mountmgr.sys/device.c
index eb48d3f..c5b04f7 100644
--- a/dlls/mountmgr.sys/device.c
+++ b/dlls/mountmgr.sys/device.c
@@ -77,6 +77,7 @@ struct dos_drive
     char                 *unix_device; /* unix device path */
     char                 *unix_mount;  /* unix mount point path */
     STORAGE_BUS_TYPE      bus_type;    /* bus type */
+    UNICODE_STRING        usbstor;     /* USBSTOR device symlink */
 };
 
 static struct list drives_list = LIST_INIT(drives_list);
@@ -208,6 +209,7 @@ static NTSTATUS create_disk_device( const char *udi, DWORD type, struct dos_driv
         drive->unix_mount  = NULL;
         drive->symlink.Buffer = NULL;
         drive->bus_type = BusTypeUnknown;
+        drive->usbstor.Buffer = NULL;
         if (udi)
         {
             if (!(drive->udi = HeapAlloc( GetProcessHeap(), 0, strlen(udi)+1 )))
@@ -273,6 +275,11 @@ static void delete_disk_device( struct dos_drive *drive )
     list_remove( &drive->entry );
     if (drive->dosdev) delete_mount_point( drive->dosdev );
     if (drive->volume) delete_mount_point( drive->volume );
+    if (drive->usbstor.Buffer)
+    {
+        IoDeleteSymbolicLink( &drive->usbstor );
+        RtlFreeUnicodeString( &drive->usbstor );
+    }
     if (drive->symlink.Buffer)
     {
         IoDeleteSymbolicLink( &drive->symlink );
@@ -479,17 +486,27 @@ static void create_drive_devices(void)
     RtlFreeHeap( GetProcessHeap(), 0, path );
 }
 
-/* write information about USBSTOR device to registry */
-static void register_usbstor_device( const char *vendor, const char *product,
-                                     const char *revision, const char *serial )
+/* write information about USBSTOR device to registry and create symbolic link */
+static void register_usbstor_device( struct dos_drive *drive, const char *vendor,
+                                     const char *product, const char *revision,
+                                     const char *serial )
 {
     static const WCHAR usbstorW[] = {'U','S','B','S','T','O','R',0};
     static const WCHAR disk_idW[] = {'%','s','\\','D','i','s','k','&','V','e','n','_',
                                      '%','s','&','P','r','o','d','_','%','s','&',
                                      'R','e','v','_','%','s','\\','%','s','&','0',0};
-    LPWSTR devnameW, vendorW, productW, revisionW, serialW;
-    size_t size;
+    static const WCHAR dos_devicesW[] = {'\\','D','o','s','D','e','v','i','c','e','s',0};
+    WCHAR diskW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',
+                     'A' + drive->drive,':',0};
+    LPWSTR devnameW, vendorW, productW, revisionW, serialW, linkW, device_idW = NULL;
+    SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail = NULL;
+    SP_DEVICE_INTERFACE_DATA interfaceData;
+    SP_DEVINFO_DATA devInfo;
     HDEVINFO set;
+    UNICODE_STRING target;
+    DWORD size, i = 0;
+    int found = 0;
+    BOOL ret;
 
     size = sizeof(disk_idW) - 22 + sizeof(usbstorW) + (strlen(vendor)
             + strlen(product) + strlen(revision) + strlen(serial)) * sizeof(WCHAR);
@@ -517,17 +534,53 @@ static void register_usbstor_device( const char *vendor, const char *product,
     sprintfW( devnameW, disk_idW, usbstorW, vendorW, productW, revisionW, serialW );
 
     set = SetupDiGetClassDevsW( NULL, usbstorW, 0, DIGCF_ALLCLASSES );
-    if (set != INVALID_HANDLE_VALUE)
+    if (set == INVALID_HANDLE_VALUE)
     {
-        SP_DEVINFO_DATA devInfo;
-
-        devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
-        if (SetupDiCreateDeviceInfoW( set, devnameW, &GUID_DEVCLASS_DISKDRIVE,
-                                      NULL, NULL, 0, &devInfo ))
-            SetupDiRegisterDeviceInfo( set, &devInfo, 0, NULL, NULL, NULL );
-        SetupDiDestroyDeviceInfoList( set );
+        RtlFreeHeap( GetProcessHeap(), 0, devnameW );
+        return;
     }
 
+    devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
+    while (!found && SetupDiEnumDeviceInfo( set, i++, &devInfo ))
+    {
+        size = (strlenW(devnameW) + 1) * sizeof(WCHAR);
+        device_idW = RtlAllocateHeap( GetProcessHeap(), 0, size );
+        if (!device_idW) goto done;
+        ret = SetupDiGetDeviceInstanceIdW( set, &devInfo, device_idW, size, NULL );
+        if (ret)
+            if (!lstrcmpiW( devnameW, device_idW )) found = 1;
+        RtlFreeHeap( GetProcessHeap(), 0, device_idW );
+    }
+    if (!found)
+    {
+        ret = SetupDiCreateDeviceInfoW( set, devnameW, &GUID_DEVCLASS_DISKDRIVE,
+                                        NULL, NULL, 0, &devInfo );
+        if (!ret) goto done;
+        ret = SetupDiRegisterDeviceInfo( set, &devInfo, 0, NULL, NULL, NULL );
+        if (!ret) goto done;
+    }
+    interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+    ret = SetupDiCreateDeviceInterfaceW( set, &devInfo, &GUID_DEVINTERFACE_DISK,
+                                        NULL, 0, &interfaceData );
+    if (!ret) goto done;
+    SetupDiGetDeviceInterfaceDetailW( set, &interfaceData, NULL, 0, &size, NULL );
+    detail = RtlAllocateHeap( GetProcessHeap(), 0, size );
+    if (!detail) goto done;
+    detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
+    ret = SetupDiGetDeviceInterfaceDetailW( set, &interfaceData, detail,
+                                            size, NULL, NULL );
+    if (!ret) goto done;
+    linkW = RtlAllocateHeap( GetProcessHeap(), 0, (strlenW(dos_devicesW)
+                             + strlenW(detail->DevicePath) - 2) * sizeof(WCHAR) );
+    if (!linkW) goto done;
+    strcpyW( linkW, dos_devicesW );
+    strcatW( linkW, detail->DevicePath + 3 );
+    RtlInitUnicodeString( &drive->usbstor, linkW );
+    RtlInitUnicodeString( &target, diskW );
+    IoCreateSymbolicLink( &drive->usbstor, &target );
+done:
+    if (detail) RtlFreeHeap( GetProcessHeap(), 0, detail );
+    SetupDiDestroyDeviceInfoList( set );
     RtlFreeHeap( GetProcessHeap(), 0, devnameW );
 }
 
@@ -598,7 +651,7 @@ found:
         }
 
         if (bus == BusTypeUsb && vendor && product && revision && serial)
-            register_usbstor_device( vendor, product, revision, serial );
+            register_usbstor_device( drive, vendor, product, revision, serial );
 
         if (udi) send_notify( drive->drive, DBT_DEVICEARRIVAL );
     }
diff --git a/include/winioctl.h b/include/winioctl.h
index 8b99f10..9cb554b 100644
--- a/include/winioctl.h
+++ b/include/winioctl.h
@@ -477,6 +477,8 @@ typedef struct _FILE_PIPE_PEEK_BUFFER {
 /* Device GUIDs */
 #ifdef DEFINE_GUID
 
+DEFINE_GUID(GUID_DEVINTERFACE_DISK, 0x53F56307L, 0xB6BF,
+ 0x11D0, 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B);
 DEFINE_GUID(GUID_DEVINTERFACE_COMPORT, 0x86E0D1E0L, 0x8089,
  0x11D0, 0x9C, 0xE4, 0x08, 0x00, 0x3E, 0x30, 0x1F, 0x73);
 DEFINE_GUID(GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, 0x4D36E978L, 0xE325,
-- 
1.5.6.5.GIT



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