From: "Erich E. Hoover" Subject: [PATCH v3 resend 2/4] mountmgr: Add support for IRP_MJ_QUERY_VOLUME_INFORMATION. Message-Id: Date: Tue, 8 Sep 2020 14:01:48 -0600 This patch allows the mountmgr to handle the volume information request IRP, allowing volume information to be queried from the mountmgr. v3: Use SystemBuffer instead of UserBuffer (see 8e98dcd42e13bfeb5a2397ff9bf1c7f63c224e23) v2: Per Zeb's request, now storing the volume with the disk_device so that the lookup doesn't require a search. Best, Erich From 3ac8c619d6184f514f2ea54742b62f7b5f414c0b Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" 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 --- dlls/mountmgr.sys/device.c | 122 +++++++++++++++++++++++++++++++++++-- 1 file changed, 118 insertions(+), 4 deletions(-) diff --git a/dlls/mountmgr.sys/device.c b/dlls/mountmgr.sys/device.c index ccb0685cedd..1868644437a 100644 --- a/dlls/mountmgr.sys/device.c +++ b/dlls/mountmgr.sys/device.c @@ -90,6 +90,7 @@ struct disk_device char *unix_device; /* unix device path */ char *unix_mount; /* unix mount point path */ char *serial; /* disk serial number */ + struct volume *volume; /* associated volume */ }; struct volume @@ -745,7 +746,7 @@ static DWORD VOLUME_GetAudioCDSerial( const CDROM_TOC *toc ) /* create the disk device for a given volume */ -static NTSTATUS create_disk_device( enum device_type type, struct disk_device **device_ret ) +static NTSTATUS create_disk_device( enum device_type type, struct disk_device **device_ret, struct volume *volume ) { static const WCHAR harddiskvolW[] = {'\\','D','e','v','i','c','e', '\\','H','a','r','d','d','i','s','k','V','o','l','u','m','e','%','u',0}; @@ -807,6 +808,7 @@ static NTSTATUS create_disk_device( enum device_type type, struct disk_device ** device->unix_device = NULL; device->unix_mount = NULL; device->symlink.Buffer = NULL; + device->volume = volume; if (link_format) { @@ -929,7 +931,7 @@ static NTSTATUS create_volume( const char *udi, enum device_type type, struct vo if (!(volume = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*volume) ))) return STATUS_NO_MEMORY; - if (!(status = create_disk_device( type, &volume->device ))) + if (!(status = create_disk_device( type, &volume->device, volume ))) { if (udi) set_volume_udi( volume, udi ); list_add_tail( &volumes_list, &volume->entry ); @@ -1116,7 +1118,7 @@ static NTSTATUS set_volume_info( struct volume *volume, struct dos_drive *drive, if (type != disk_device->type) { - if ((status = create_disk_device( type, &disk_device ))) return status; + if ((status = create_disk_device( type, &disk_device, volume ))) return status; if (volume->mount) { delete_mount_point( volume->mount ); @@ -1817,6 +1819,117 @@ static void query_property( struct disk_device *device, IRP *irp ) } } +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 = dev->volume; + if (!volume) + { + io->u.Status = STATUS_BAD_DEVICE_TYPE; + goto done; + } + + switch(info_class) + { + case FileFsVolumeInformation: + { + + FILE_FS_VOLUME_INFORMATION *info = irp->AssociatedIrp.SystemBuffer; + + 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->AssociatedIrp.SystemBuffer; + 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 ) { @@ -1914,9 +2027,10 @@ 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 ); + create_disk_device( DEVICE_HARDDISK, &device, NULL ); create_drive_devices(); -- 2.17.1