[PATCH 1/3] mountmgr: Return the disk serial from IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE.

Hans Leidekker hans at codeweavers.com
Mon May 18 02:49:39 CDT 2020


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/mountmgr.sys/dbus.c     | 13 +++++----
 dlls/mountmgr.sys/device.c   | 55 ++++++++++++++++++++++++++++++------
 dlls/mountmgr.sys/mountmgr.c | 17 +++++++++--
 dlls/mountmgr.sys/mountmgr.h |  6 ++--
 include/ddk/mountmgr.h       |  1 +
 5 files changed, 73 insertions(+), 19 deletions(-)

diff --git a/dlls/mountmgr.sys/dbus.c b/dlls/mountmgr.sys/dbus.c
index 27b35acd9ca..98b2a47ba6d 100644
--- a/dlls/mountmgr.sys/dbus.c
+++ b/dlls/mountmgr.sys/dbus.c
@@ -317,7 +317,7 @@ static void udisks_new_device( const char *udi )
     if (device)
     {
         if (removable) add_dos_device( -1, udi, device, mount_point, drive_type, guid_ptr, NULL );
-        else if (guid_ptr) add_volume( udi, device, mount_point, DEVICE_HARDDISK_VOL, guid_ptr );
+        else if (guid_ptr) add_volume( udi, device, mount_point, DEVICE_HARDDISK_VOL, guid_ptr, NULL );
     }
 
     p_dbus_message_unref( reply );
@@ -385,7 +385,7 @@ static const char *udisks2_string_from_array( DBusMessageIter *iter )
 
 /* find the drive entry in the dictionary and get its parameters */
 static void udisks2_get_drive_info( const char *drive_name, DBusMessageIter *dict,
-                                    enum device_type *drive_type, int *removable )
+                                    enum device_type *drive_type, int *removable, const char **serial )
 {
     DBusMessageIter iter, drive, variant;
     const char *name;
@@ -403,6 +403,8 @@ static void udisks2_get_drive_info( const char *drive_name, DBusMessageIter *dic
                     p_dbus_message_iter_get_basic( &variant, removable );
                 else if (!strcmp( name, "MediaCompatibility" ))
                     *drive_type = udisks_parse_media_compatibility( &variant );
+                else if (!strcmp( name, "Id" ))
+                    p_dbus_message_iter_get_basic( &variant, serial );
             }
         }
     }
@@ -415,6 +417,7 @@ static void udisks2_add_device( const char *udi, DBusMessageIter *dict, DBusMess
     const char *mount_point = NULL;
     const char *type = NULL;
     const char *drive = NULL;
+    const char *id = NULL;
     GUID guid, *guid_ptr = NULL;
     const char *iface, *name;
     int removable = FALSE;
@@ -448,7 +451,7 @@ static void udisks2_add_device( const char *udi, DBusMessageIter *dict, DBusMess
                 else if (!strcmp( name, "Drive" ))
                 {
                     p_dbus_message_iter_get_basic( &variant, &drive );
-                    udisks2_get_drive_info( drive, dict, &drive_type, &removable );
+                    udisks2_get_drive_info( drive, dict, &drive_type, &removable, &id );
                 }
                 else if (!strcmp( name, "IdUUID" ))
                 {
@@ -483,7 +486,7 @@ static void udisks2_add_device( const char *udi, DBusMessageIter *dict, DBusMess
     if (device)
     {
         if (removable) add_dos_device( -1, udi, device, mount_point, drive_type, guid_ptr, NULL );
-        else if (guid_ptr) add_volume( udi, device, mount_point, DEVICE_HARDDISK_VOL, guid_ptr );
+        else if (guid_ptr) add_volume( udi, device, mount_point, DEVICE_HARDDISK_VOL, guid_ptr, id );
     }
 }
 
@@ -799,7 +802,7 @@ static void hal_new_device( LibHalContext *ctx, const char *udi )
         /* add property watch for mount point */
         p_libhal_device_add_property_watch( ctx, udi, &error );
     }
-    else if (guid_ptr) add_volume( udi, device, mount_point, DEVICE_HARDDISK_VOL, guid_ptr );
+    else if (guid_ptr) add_volume( udi, device, mount_point, DEVICE_HARDDISK_VOL, guid_ptr, NULL );
 
 done:
     if (type) p_libhal_free_string( type );
diff --git a/dlls/mountmgr.sys/device.c b/dlls/mountmgr.sys/device.c
index a6794fa6ac4..babdaa3e884 100644
--- a/dlls/mountmgr.sys/device.c
+++ b/dlls/mountmgr.sys/device.c
@@ -89,6 +89,7 @@ struct disk_device
     STORAGE_DEVICE_NUMBER devnum;      /* device number info */
     char                 *unix_device; /* unix device path */
     char                 *unix_mount;  /* unix mount point path */
+    char                 *serial;      /* disk serial number */
 };
 
 struct volume
@@ -873,6 +874,7 @@ static void delete_disk_device( struct disk_device *device )
     }
     RtlFreeHeap( GetProcessHeap(), 0, device->unix_device );
     RtlFreeHeap( GetProcessHeap(), 0, device->unix_mount );
+    RtlFreeHeap( GetProcessHeap(), 0, device->serial );
     RtlFreeUnicodeString( &device->name );
     IoDeleteDevice( device->dev_obj );
 }
@@ -1078,9 +1080,40 @@ static BOOL get_volume_device_info( struct volume *volume )
     return TRUE;
 }
 
+/* set disk serial for dos devices that reside on a given Unix device */
+static void set_dos_devices_disk_serial( struct disk_device *device )
+{
+    struct dos_drive *drive;
+    struct stat dev_st, drive_st;
+    char *path, *p;
+
+    if (!device->unix_mount || stat( device->unix_mount, &dev_st ) == -1) return;
+
+    if (!(path = get_dosdevices_path( &p ))) return;
+    p[2] = 0;
+
+    LIST_FOR_EACH_ENTRY( drive, &drives_list, struct dos_drive, entry )
+    {
+        /* drives mapped to Unix devices already have serial set, if available */
+        if (drive->volume->device->unix_device) continue;
+
+        p[0] = 'a' + drive->drive;
+
+        /* copy serial if drive resides on this Unix device */
+        if (stat( path, &drive_st ) != -1 && drive_st.st_rdev == dev_st.st_rdev)
+        {
+            HeapFree( GetProcessHeap(), 0, drive->volume->device->serial );
+            drive->volume->device->serial = strdupA( device->serial );
+        }
+    }
+
+    HeapFree( GetProcessHeap(), 0, path );
+}
+
 /* change the information for an existing volume */
 static NTSTATUS set_volume_info( struct volume *volume, struct dos_drive *drive, const char *device,
-                                 const char *mount_point, enum device_type type, const GUID *guid )
+                                 const char *mount_point, enum device_type type, const GUID *guid,
+                                 const char *disk_serial )
 {
     void *id = NULL;
     unsigned int id_len = 0;
@@ -1107,9 +1140,12 @@ static NTSTATUS set_volume_info( struct volume *volume, struct dos_drive *drive,
     {
         RtlFreeHeap( GetProcessHeap(), 0, disk_device->unix_device );
         RtlFreeHeap( GetProcessHeap(), 0, disk_device->unix_mount );
+        RtlFreeHeap( GetProcessHeap(), 0, disk_device->serial );
     }
     disk_device->unix_device = strdupA( device );
     disk_device->unix_mount = strdupA( mount_point );
+    disk_device->serial = strdupA( disk_serial );
+    if (disk_device->serial) set_dos_devices_disk_serial( disk_device );
 
     if (!get_volume_device_info( volume ))
     {
@@ -1306,7 +1342,7 @@ static void create_drive_devices(void)
         {
             /* don't reset uuid if we used an existing volume */
             const GUID *guid = volume ? NULL : get_default_uuid(i);
-            set_volume_info( drive->volume, drive, device, link, drive_type, guid );
+            set_volume_info( drive->volume, drive, device, link, drive_type, guid, NULL );
         }
         else
         {
@@ -1459,7 +1495,7 @@ void set_scsi_device_name( SCSI_ADDRESS *scsi_addr, const UNICODE_STRING *dev )
 
 /* create a new disk volume */
 NTSTATUS add_volume( const char *udi, const char *device, const char *mount_point,
-                     enum device_type type, const GUID *guid )
+                     enum device_type type, const GUID *guid, const char *disk_serial )
 {
     struct volume *volume;
     NTSTATUS status = STATUS_SUCCESS;
@@ -1480,13 +1516,13 @@ NTSTATUS add_volume( const char *udi, const char *device, const char *mount_poin
     else status = create_volume( udi, type, &volume );
 
 found:
-    if (!status) status = set_volume_info( volume, NULL, device, mount_point, type, guid );
+    if (!status) status = set_volume_info( volume, NULL, device, mount_point, type, guid, disk_serial );
     if (volume) release_volume( volume );
     LeaveCriticalSection( &device_section );
     return status;
 }
 
-/* create a new disk volume */
+/* remove a disk volume */
 NTSTATUS remove_volume( const char *udi )
 {
     NTSTATUS status = STATUS_NO_SUCH_DEVICE;
@@ -1560,7 +1596,7 @@ found:
     p[0] = 'a' + drive->drive;
     p[2] = 0;
     update_symlink( path, mount_point, volume->device->unix_mount );
-    set_volume_info( volume, drive, device, mount_point, type, guid );
+    set_volume_info( volume, drive, device, mount_point, type, guid, NULL );
 
     TRACE( "added device %c: udi %s for %s on %s type %u\n",
            'a' + drive->drive, wine_dbgstr_a(udi), wine_dbgstr_a(device),
@@ -1656,7 +1692,8 @@ enum mountmgr_fs_type get_mountmgr_fs_type(enum fs_type fs_type)
 
 /* query information about an existing dos drive, by letter or udi */
 NTSTATUS query_dos_device( int letter, enum device_type *type, enum mountmgr_fs_type *fs_type,
-                           DWORD *serial, char **device, char **mount_point, WCHAR **label )
+                           DWORD *serial, char **device, char **mount_point, WCHAR **label,
+                           char **disk_serial )
 {
     NTSTATUS status = STATUS_NO_SUCH_DEVICE;
     struct dos_drive *drive;
@@ -1673,6 +1710,7 @@ NTSTATUS query_dos_device( int letter, enum device_type *type, enum mountmgr_fs_
         if (device) *device = strdupA( disk_device->unix_device );
         if (mount_point) *mount_point = strdupA( disk_device->unix_mount );
         if (label) *label = strdupW( drive->volume->label );
+        if (disk_serial) *disk_serial = strdupA( disk_device->serial );
         status = STATUS_SUCCESS;
         break;
     }
@@ -1683,7 +1721,7 @@ NTSTATUS query_dos_device( int letter, enum device_type *type, enum mountmgr_fs_
 /* query information about an existing unix device, by dev_t */
 NTSTATUS query_unix_device( ULONGLONG unix_dev, enum device_type *type,
                             enum mountmgr_fs_type *fs_type, DWORD *serial, char **device,
-                            char **mount_point, WCHAR **label )
+                            char **mount_point, WCHAR **label, char **disk_serial )
 {
     NTSTATUS status = STATUS_NO_SUCH_DEVICE;
     struct volume *volume;
@@ -1706,6 +1744,7 @@ NTSTATUS query_unix_device( ULONGLONG unix_dev, enum device_type *type,
         if (device) *device = strdupA( disk_device->unix_device );
         if (mount_point) *mount_point = strdupA( disk_device->unix_mount );
         if (label) *label = strdupW( volume->label );
+        if (disk_serial) *disk_serial = strdupA( disk_device->serial );
         status = STATUS_SUCCESS;
         break;
     }
diff --git a/dlls/mountmgr.sys/mountmgr.c b/dlls/mountmgr.sys/mountmgr.c
index cf12f03a73b..bd967793057 100644
--- a/dlls/mountmgr.sys/mountmgr.c
+++ b/dlls/mountmgr.sys/mountmgr.c
@@ -291,7 +291,7 @@ static NTSTATUS query_unix_drive( void *buff, SIZE_T insize,
 {
     const struct mountmgr_unix_drive *input = buff;
     struct mountmgr_unix_drive *output = NULL;
-    char *device, *mount_point;
+    char *device, *mount_point, *disk_serial;
     int letter = tolowerW( input->letter );
     NTSTATUS status;
     DWORD size, type = DEVICE_UNKNOWN, serial;
@@ -303,7 +303,7 @@ static NTSTATUS query_unix_drive( void *buff, SIZE_T insize,
     if (!letter)
     {
         if ((status = query_unix_device( input->unix_dev, &device_type, &fs_type,
-                                         &serial, &device, &mount_point, &label )))
+                                         &serial, &device, &mount_point, &label, &disk_serial )))
             return status;
     }
     else
@@ -311,7 +311,7 @@ static NTSTATUS query_unix_drive( void *buff, SIZE_T insize,
         if (letter < 'a' || letter > 'z') return STATUS_INVALID_PARAMETER;
 
         if ((status = query_dos_device( letter - 'a', &device_type, &fs_type, &serial, &device,
-                                        &mount_point, &label )))
+                                        &mount_point, &label, &disk_serial )))
             return status;
     }
 
@@ -330,6 +330,7 @@ static NTSTATUS query_unix_drive( void *buff, SIZE_T insize,
     size = sizeof(*output);
     if (device) size += strlen(device) + 1;
     if (mount_point) size += strlen(mount_point) + 1;
+    if (disk_serial) size += strlen(disk_serial) + 1;
 
     input = NULL;
     output = buff;
@@ -341,6 +342,7 @@ static NTSTATUS query_unix_drive( void *buff, SIZE_T insize,
     output->mount_point_offset = 0;
     output->device_offset = 0;
     output->label_offset = 0;
+    output->disk_serial_offset = 0;
 
     if (size > outsize)
     {
@@ -385,6 +387,14 @@ static NTSTATUS query_unix_drive( void *buff, SIZE_T insize,
     }
     else output->label_offset = 0;
 
+    if (disk_serial)
+    {
+        output->disk_serial_offset = ptr - (char *)output;
+        strcpy( ptr, disk_serial );
+        ptr += strlen(disk_serial) + 1;
+    }
+    else output->disk_serial_offset = 0;
+
     TRACE( "returning %c: dev %s mount %s type %u\n",
            letter, debugstr_a(device), debugstr_a(mount_point), type );
 
@@ -393,6 +403,7 @@ done:
     RtlFreeHeap( GetProcessHeap(), 0, device );
     RtlFreeHeap( GetProcessHeap(), 0, mount_point );
     RtlFreeHeap( GetProcessHeap(), 0, label );
+    RtlFreeHeap( GetProcessHeap(), 0, disk_serial );
     return status;
 }
 
diff --git a/dlls/mountmgr.sys/mountmgr.h b/dlls/mountmgr.sys/mountmgr.h
index 82d783a7a04..6462d8719c6 100644
--- a/dlls/mountmgr.sys/mountmgr.h
+++ b/dlls/mountmgr.sys/mountmgr.h
@@ -51,17 +51,17 @@ enum device_type
 };
 
 extern NTSTATUS add_volume( const char *udi, const char *device, const char *mount_point,
-                            enum device_type type, const GUID *guid ) DECLSPEC_HIDDEN;
+                            enum device_type type, const GUID *guid, const char *disk_serial ) DECLSPEC_HIDDEN;
 extern NTSTATUS remove_volume( const char *udi ) DECLSPEC_HIDDEN;
 extern NTSTATUS add_dos_device( int letter, const char *udi, const char *device,
                                 const char *mount_point, enum device_type type, const GUID *guid,
                                 UNICODE_STRING *devname ) DECLSPEC_HIDDEN;
 extern NTSTATUS remove_dos_device( int letter, const char *udi ) DECLSPEC_HIDDEN;
 extern NTSTATUS query_dos_device( int letter, enum device_type *type, enum mountmgr_fs_type *fs_type, DWORD *serial,
-                                  char **device, char **mount_point, WCHAR **label ) DECLSPEC_HIDDEN;
+                                  char **device, char **mount_point, WCHAR **label, char **disk_serial ) DECLSPEC_HIDDEN;
 extern NTSTATUS query_unix_device( ULONGLONG unix_dev, enum device_type *type,
                                    DWORD *serial, enum mountmgr_fs_type *fs_type, char **device,
-                                   char **mount_point, WCHAR **label ) DECLSPEC_HIDDEN;
+                                   char **mount_point, WCHAR **label, char **disk_serial ) DECLSPEC_HIDDEN;
 extern NTSTATUS WINAPI harddisk_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) DECLSPEC_HIDDEN;
 extern NTSTATUS WINAPI serial_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) DECLSPEC_HIDDEN;
 extern NTSTATUS WINAPI parallel_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) DECLSPEC_HIDDEN;
diff --git a/include/ddk/mountmgr.h b/include/ddk/mountmgr.h
index 13829a53954..aa1e7eaee80 100644
--- a/include/ddk/mountmgr.h
+++ b/include/ddk/mountmgr.h
@@ -72,6 +72,7 @@ struct mountmgr_unix_drive
     USHORT    mount_point_offset;
     USHORT    device_offset;
     USHORT    label_offset;
+    USHORT    disk_serial_offset;
 };
 
 #define IOCTL_MOUNTMGR_QUERY_DHCP_REQUEST_PARAMS CTL_CODE(MOUNTMGRCONTROLTYPE, 64, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
-- 
2.20.1




More information about the wine-devel mailing list