[PATCH 2/4] mountmgr: Add support for IRP_MJ_QUERY_VOLUME_INFORMATION.

Erich E. Hoover erich.e.hoover at gmail.com
Wed Jul 15 20:58:02 CDT 2020


On Wed, Jul 15, 2020 at 9:35 AM Zebediah Figura <z.figura12 at gmail.com> wrote:
>. ..
> This seems less than ideal. I guess maybe a better thing to do is have a
> union of "struct disk_device" and "struct volume" in the device extension.
> ...

Thanks Zeb!  At least the way we're currently doing things, it looks
to me like that would be problematic.  Right now we create a
disk_device for every volume (this is fine), but that we can also
change the device type of a volume at any time (this looks
problematic).  That's not unsolvable though, I can see a couple
choices:
1) if we call set_volume_info with (type != disk_device->type) then we
could store the volume info, delete the device (and volume), and then
recreate it again
2) we could add an optional volume entry to disk_device on creation,
making the reverse lookup simple (even if the device type changes)

I've attached an example of the second option, since that seems
simpler, and would appreciate your thoughts.

Best,
Erich


> We could probably do a better job of properly differentiating drives and
> volumes anyway, e.g. I think we currently create a "volume" object for
> all drives, and we create a "disk_device" for drives defined with
> DEFINE_UNIX_DRIVE and DRIVE_REMOVABLE. It's my understanding that only
> "volumes" can be mounted, even for removable drives.
>
> > +
> > +static NTSTATUS WINAPI harddisk_query_volume( DEVICE_OBJECT *device, IRP *irp )
> > +{
> > +    IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
> > +    int info_class = irpsp->Parameters.QueryVolume.FsInformationClass;
> > +    ULONG length = irpsp->Parameters.QueryVolume.Length;
> > +    struct disk_device *dev = device->DeviceExtension;
> > +    PIO_STATUS_BLOCK io = &irp->IoStatus;
> > +    struct volume *volume;
> > +
> > +    TRACE( "volume query %x length %u\n", info_class,
> > +           length );
> > +
> > +    EnterCriticalSection( &device_section );
> > +    volume = find_mount_volume( dev->unix_mount, DEVICE_HARDDISK_VOL );
> > +    if (!volume)
> > +    {
> > +        io->u.Status = STATUS_BAD_DEVICE_TYPE;
> > +        goto done;
> > +    }
> > +
> > +    switch(info_class)
> > +    {
> > +    case FileFsVolumeInformation:
> > +    {
> > +
> > +        FILE_FS_VOLUME_INFORMATION *info = irp->UserBuffer;
> > +
> > +        if (length < sizeof(FILE_FS_VOLUME_INFORMATION))
> > +        {
> > +            io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
> > +            break;
> > +        }
> > +
> > +        info->VolumeCreationTime.QuadPart = 0; /* FIXME */
> > +        info->VolumeSerialNumber = volume->serial;
> > +        info->VolumeLabelLength = min( strlenW(volume->label) * sizeof(WCHAR),
> > +                                       length - offsetof( FILE_FS_VOLUME_INFORMATION, VolumeLabel ) );
> > +        info->SupportsObjects = (get_mountmgr_fs_type(volume->fs_type) == MOUNTMGR_FS_TYPE_NTFS);
> > +        memcpy( info->VolumeLabel, volume->label, info->VolumeLabelLength );
> > +
> > +        io->Information = offsetof( FILE_FS_VOLUME_INFORMATION, VolumeLabel ) + info->VolumeLabelLength;
> > +        io->u.Status = STATUS_SUCCESS;
> > +        break;
> > +    }
> > +    case FileFsAttributeInformation:
> > +    {
> > +        static const WCHAR fatW[] = {'F','A','T'};
> > +        static const WCHAR fat32W[] = {'F','A','T','3','2'};
> > +        static const WCHAR ntfsW[] = {'N','T','F','S'};
> > +        static const WCHAR cdfsW[] = {'C','D','F','S'};
> > +        static const WCHAR udfW[] = {'U','D','F'};
> > +
> > +        FILE_FS_ATTRIBUTE_INFORMATION *info = irp->UserBuffer;
> > +        enum mountmgr_fs_type fs_type = get_mountmgr_fs_type(volume->fs_type);
> > +
> > +        if (length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
> > +        {
> > +            io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
> > +            break;
> > +        }
> > +
> > +        switch (fs_type)
> > +        {
> > +        case MOUNTMGR_FS_TYPE_ISO9660:
> > +            info->FileSystemAttributes = FILE_READ_ONLY_VOLUME;
> > +            info->MaximumComponentNameLength = 221;
> > +            info->FileSystemNameLength = min( sizeof(cdfsW), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) );
> > +            memcpy(info->FileSystemName, cdfsW, info->FileSystemNameLength);
> > +            break;
> > +        case MOUNTMGR_FS_TYPE_UDF:
> > +            info->FileSystemAttributes = FILE_READ_ONLY_VOLUME | FILE_UNICODE_ON_DISK | FILE_CASE_SENSITIVE_SEARCH;
> > +            info->MaximumComponentNameLength = 255;
> > +            info->FileSystemNameLength = min( sizeof(udfW), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) );
> > +            memcpy(info->FileSystemName, udfW, info->FileSystemNameLength);
> > +            break;
> > +        case MOUNTMGR_FS_TYPE_FAT:
> > +            info->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES; /* FIXME */
> > +            info->MaximumComponentNameLength = 255;
> > +            info->FileSystemNameLength = min( sizeof(fatW), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) );
> > +            memcpy(info->FileSystemName, fatW, info->FileSystemNameLength);
> > +            break;
> > +        case MOUNTMGR_FS_TYPE_FAT32:
> > +            info->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES; /* FIXME */
> > +            info->MaximumComponentNameLength = 255;
> > +            info->FileSystemNameLength = min( sizeof(fat32W), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) );
> > +            memcpy(info->FileSystemName, fat32W, info->FileSystemNameLength);
> > +            break;
> > +        default:
> > +            info->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES | FILE_PERSISTENT_ACLS;
> > +            info->MaximumComponentNameLength = 255;
> > +            info->FileSystemNameLength = min( sizeof(ntfsW), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) );
> > +            memcpy(info->FileSystemName, ntfsW, info->FileSystemNameLength);
> > +            break;
> > +        }
> > +
> > +        io->Information = offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) + info->FileSystemNameLength;
> > +        io->u.Status = STATUS_SUCCESS;
> > +        break;
> > +    }
> > +    default:
> > +        FIXME("Unsupported volume query %x\n", irpsp->Parameters.QueryVolume.FsInformationClass);
> > +        io->u.Status = STATUS_NOT_SUPPORTED;
> > +        break;
> > +    }
> > +
> > +done:
> > +    LeaveCriticalSection( &device_section );
> > +    IoCompleteRequest( irp, IO_NO_INCREMENT );
> > +    return STATUS_SUCCESS;
> > +}
> > +
> >  /* handler for ioctls on the harddisk device */
> >  static NTSTATUS WINAPI harddisk_ioctl( DEVICE_OBJECT *device, IRP *irp )
> >  {
> > @@ -1915,6 +2051,7 @@ NTSTATUS WINAPI harddisk_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *pa
> >
> >      harddisk_driver = driver;
> >      driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = harddisk_ioctl;
> > +    driver->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = harddisk_query_volume;
> >
> >      /* create a harddisk0 device that isn't assigned to any drive */
> >      create_disk_device( DEVICE_HARDDISK, &device );
> >
> > --
> > 2.17.1
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0002-mountmgr-Add-support-for-IRP_MJ_QUERY_VOLUME_INFORMA.patch
Type: text/x-patch
Size: 8186 bytes
Desc: not available
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20200715/9e0068ee/attachment-0001.bin>


More information about the wine-devel mailing list