On 7/15/20 10:08 AM, Erich E. Hoover wrote:
From 2dd03df6e1fc2944d7590cc400059b05a8edbaa1 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" <erich.e.hoover(a)gmail.com> Date: Fri, 12 Jun 2020 14:48:25 -0600 Subject: mountmgr: Add support for IRP_MJ_QUERY_VOLUME_INFORMATION.
Signed-off-by: Erich E. Hoover <erich.e.hoover(a)gmail.com> --- dlls/mountmgr.sys/device.c | 137 +++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+)
diff --git a/dlls/mountmgr.sys/device.c b/dlls/mountmgr.sys/device.c index f7a1f1e9b55..439dbc0c7d3 100644 --- a/dlls/mountmgr.sys/device.c +++ b/dlls/mountmgr.sys/device.c @@ -1818,6 +1818,142 @@ static void query_property( struct disk_device *device, IRP *irp ) } }
+/* find a volume that matches the given mount point */ +static struct volume *find_mount_volume( const char *mount_point, enum device_type type ) +{ + struct volume *volume; + struct disk_device *disk_device; + + LIST_FOR_EACH_ENTRY( volume, &volumes_list, struct volume, entry ) + { + int match = 0; + + disk_device = volume->device; + if (disk_device->type != type) continue; + if (mount_point && disk_device->unix_mount) + { + if (strcmp( mount_point, disk_device->unix_mount )) continue; + match++; + } + if (!match) continue; + TRACE( "found matching volume %s for mount %s type %u\n", + debugstr_guid(&volume->guid), debugstr_a(mount_point), type ); + return grab_volume( volume ); + } + return NULL; +}
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. 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