mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-01 12:23:39 +00:00
mountmgr.sys: Implemented FileFsSizeInformation and FileFsFullSizeInformation volume queries.
This patch fixes GetDiskFreeSpaceA/W when an NT-style GUID volume path is provided e.g. "\\?\Volume{00000000-0000-0000-0000-000000000043}\" as might be retrieved by FindFirstVolumeA/W and FindNextVolumeA/W. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53547 Signed-off-by: Joel Holdsworth <joel@airwebreathe.org.uk>
This commit is contained in:
parent
6af3590799
commit
7546b4a63d
|
@ -164,7 +164,6 @@ static void test_GetDiskFreeSpaceA(void)
|
|||
ok(ret, "GetVolumeNameForVolumeMountPointA error %ld\n", GetLastError());
|
||||
|
||||
ret = GetDiskFreeSpaceA(volume_guid_path, §ors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
|
||||
todo_wine
|
||||
ok(ret, "GetDiskFreeSpaceA error %ld\n", GetLastError());
|
||||
|
||||
logical_drives = GetLogicalDrives();
|
||||
|
@ -257,7 +256,6 @@ static void test_GetDiskFreeSpaceW(void)
|
|||
ok(ret, "GetVolumeNameForVolumeMountPointW error %ld\n", GetLastError());
|
||||
|
||||
ret = GetDiskFreeSpaceW(volume_guid_path, §ors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
|
||||
todo_wine
|
||||
ok(ret, "GetDiskFreeSpaceW error %ld\n", GetLastError());
|
||||
|
||||
logical_drives = GetLogicalDrives();
|
||||
|
|
|
@ -1656,6 +1656,30 @@ static NTSTATUS WINAPI harddisk_query_volume( DEVICE_OBJECT *device, IRP *irp )
|
|||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
case FileFsSizeInformation:
|
||||
{
|
||||
FILE_FS_SIZE_INFORMATION *info = irp->AssociatedIrp.SystemBuffer;
|
||||
struct size_info size_info = { 0, 0, 0, 0, 0 };
|
||||
struct get_volume_size_info_params params = { dev->unix_mount, &size_info };
|
||||
|
||||
if (length < sizeof(FILE_FS_SIZE_INFORMATION))
|
||||
{
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = MOUNTMGR_CALL( get_volume_size_info, ¶ms )) == STATUS_SUCCESS)
|
||||
{
|
||||
info->TotalAllocationUnits.QuadPart = size_info.total_allocation_units;
|
||||
info->AvailableAllocationUnits.QuadPart = size_info.caller_available_allocation_units;
|
||||
info->SectorsPerAllocationUnit = size_info.sectors_per_allocation_unit;
|
||||
info->BytesPerSector = size_info.bytes_per_sector;
|
||||
io->Information = sizeof(*info);
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case FileFsAttributeInformation:
|
||||
{
|
||||
FILE_FS_ATTRIBUTE_INFORMATION *info = irp->AssociatedIrp.SystemBuffer;
|
||||
|
@ -1702,6 +1726,32 @@ static NTSTATUS WINAPI harddisk_query_volume( DEVICE_OBJECT *device, IRP *irp )
|
|||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
case FileFsFullSizeInformation:
|
||||
{
|
||||
FILE_FS_FULL_SIZE_INFORMATION *info = irp->AssociatedIrp.SystemBuffer;
|
||||
struct size_info size_info = { 0, 0, 0, 0, 0 };
|
||||
struct get_volume_size_info_params params = { dev->unix_mount, &size_info };
|
||||
|
||||
if (length < sizeof(FILE_FS_FULL_SIZE_INFORMATION))
|
||||
{
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = MOUNTMGR_CALL( get_volume_size_info, ¶ms )) == STATUS_SUCCESS)
|
||||
{
|
||||
info->TotalAllocationUnits.QuadPart = size_info.total_allocation_units;
|
||||
info->CallerAvailableAllocationUnits.QuadPart = size_info.caller_available_allocation_units;
|
||||
info->ActualAvailableAllocationUnits.QuadPart = size_info.actual_available_allocation_units;
|
||||
info->SectorsPerAllocationUnit = size_info.sectors_per_allocation_unit;
|
||||
info->BytesPerSector = size_info.bytes_per_sector;
|
||||
io->Information = sizeof(*info);
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
FIXME("Unsupported volume query %x\n", irpsp->Parameters.QueryVolume.FsInformationClass);
|
||||
status = STATUS_NOT_SUPPORTED;
|
||||
|
|
|
@ -30,12 +30,63 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_SYS_STATFS_H
|
||||
#include <sys/statfs.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STATVFS_H
|
||||
# include <sys/statvfs.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
#include "unixlib.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(mountmgr);
|
||||
|
||||
static struct run_loop_params run_loop_params;
|
||||
|
||||
static NTSTATUS errno_to_status( int err )
|
||||
{
|
||||
TRACE( "errno = %d\n", err );
|
||||
switch (err)
|
||||
{
|
||||
case EAGAIN: return STATUS_SHARING_VIOLATION;
|
||||
case EBADF: return STATUS_INVALID_HANDLE;
|
||||
case EBUSY: return STATUS_DEVICE_BUSY;
|
||||
case ENOSPC: return STATUS_DISK_FULL;
|
||||
case EPERM:
|
||||
case EROFS:
|
||||
case EACCES: return STATUS_ACCESS_DENIED;
|
||||
case ENOTDIR: return STATUS_OBJECT_PATH_NOT_FOUND;
|
||||
case ENOENT: return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
case EISDIR: return STATUS_INVALID_DEVICE_REQUEST;
|
||||
case EMFILE:
|
||||
case ENFILE: return STATUS_TOO_MANY_OPENED_FILES;
|
||||
case EINVAL: return STATUS_INVALID_PARAMETER;
|
||||
case ENOTEMPTY: return STATUS_DIRECTORY_NOT_EMPTY;
|
||||
case EPIPE: return STATUS_PIPE_DISCONNECTED;
|
||||
case EIO: return STATUS_DEVICE_NOT_READY;
|
||||
#ifdef ENOMEDIUM
|
||||
case ENOMEDIUM: return STATUS_NO_MEDIA_IN_DEVICE;
|
||||
#endif
|
||||
case ENXIO: return STATUS_NO_SUCH_DEVICE;
|
||||
case ENOTTY:
|
||||
case EOPNOTSUPP:return STATUS_NOT_SUPPORTED;
|
||||
case ECONNRESET:return STATUS_PIPE_DISCONNECTED;
|
||||
case EFAULT: return STATUS_ACCESS_VIOLATION;
|
||||
case ESPIPE: return STATUS_ILLEGAL_FUNCTION;
|
||||
case ELOOP: return STATUS_REPARSE_POINT_NOT_RESOLVED;
|
||||
#ifdef ETIME /* Missing on FreeBSD */
|
||||
case ETIME: return STATUS_IO_TIMEOUT;
|
||||
#endif
|
||||
case ENOEXEC: /* ?? */
|
||||
case EEXIST: /* ?? */
|
||||
default:
|
||||
FIXME( "Converting errno %d to STATUS_UNSUCCESSFUL\n", err );
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
|
||||
static char *get_dosdevices_path( const char *dev )
|
||||
{
|
||||
const char *home = getenv( "HOME" );
|
||||
|
@ -266,6 +317,85 @@ static NTSTATUS set_dosdev_symlink( void *args )
|
|||
return status;
|
||||
}
|
||||
|
||||
static NTSTATUS get_volume_size_info( void *args )
|
||||
{
|
||||
const struct get_volume_size_info_params *params = args;
|
||||
const char *unix_mount = params->unix_mount;
|
||||
struct size_info *info = params->info;
|
||||
|
||||
struct stat st;
|
||||
ULONGLONG bsize;
|
||||
NTSTATUS status;
|
||||
int fd = -1;
|
||||
|
||||
#if !defined(linux) || !defined(HAVE_FSTATFS)
|
||||
struct statvfs stfs;
|
||||
#else
|
||||
struct statfs stfs;
|
||||
#endif
|
||||
|
||||
if (!unix_mount) return STATUS_NO_SUCH_DEVICE;
|
||||
|
||||
if (unix_mount[0] != '/')
|
||||
{
|
||||
char *path = get_dosdevices_path( unix_mount );
|
||||
if (path) fd = open( path, O_RDONLY );
|
||||
free( path );
|
||||
}
|
||||
else fd = open( unix_mount, O_RDONLY );
|
||||
|
||||
if (fstat( fd, &st ) < 0)
|
||||
{
|
||||
status = errno_to_status( errno );
|
||||
goto done;
|
||||
}
|
||||
if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
|
||||
{
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Linux's fstatvfs is buggy */
|
||||
#if !defined(linux) || !defined(HAVE_FSTATFS)
|
||||
if (fstatvfs( fd, &stfs ) < 0)
|
||||
{
|
||||
status = errno_to_status( errno );
|
||||
goto done;
|
||||
}
|
||||
bsize = stfs.f_frsize;
|
||||
#else
|
||||
if (fstatfs( fd, &stfs ) < 0)
|
||||
{
|
||||
status = errno_to_status( errno );
|
||||
goto done;
|
||||
}
|
||||
bsize = stfs.f_bsize;
|
||||
#endif
|
||||
if (bsize == 2048) /* assume CD-ROM */
|
||||
{
|
||||
info->bytes_per_sector = 2048;
|
||||
info->sectors_per_allocation_unit = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
info->bytes_per_sector = 512;
|
||||
info->sectors_per_allocation_unit = 8;
|
||||
}
|
||||
|
||||
info->total_allocation_units =
|
||||
bsize * stfs.f_blocks / (info->bytes_per_sector * info->sectors_per_allocation_unit);
|
||||
info->caller_available_allocation_units =
|
||||
bsize * stfs.f_bavail / (info->bytes_per_sector * info->sectors_per_allocation_unit);
|
||||
info->actual_available_allocation_units =
|
||||
bsize * stfs.f_bfree / (info->bytes_per_sector * info->sectors_per_allocation_unit);
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
done:
|
||||
close( fd );
|
||||
return status;
|
||||
}
|
||||
|
||||
static NTSTATUS get_volume_dos_devices( void *args )
|
||||
{
|
||||
const struct get_volume_dos_devices_params *params = args;
|
||||
|
@ -440,6 +570,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
|
|||
add_drive,
|
||||
get_dosdev_symlink,
|
||||
set_dosdev_symlink,
|
||||
get_volume_size_info,
|
||||
get_volume_dos_devices,
|
||||
read_volume_file,
|
||||
match_unixdev,
|
||||
|
|
|
@ -64,6 +64,21 @@ struct add_drive_params
|
|||
int *letter;
|
||||
};
|
||||
|
||||
struct size_info
|
||||
{
|
||||
LONGLONG total_allocation_units;
|
||||
LONGLONG caller_available_allocation_units;
|
||||
LONGLONG actual_available_allocation_units;
|
||||
ULONG sectors_per_allocation_unit;
|
||||
ULONG bytes_per_sector;
|
||||
};
|
||||
|
||||
struct get_volume_size_info_params
|
||||
{
|
||||
const char *unix_mount;
|
||||
struct size_info *info;
|
||||
};
|
||||
|
||||
struct get_dosdev_symlink_params
|
||||
{
|
||||
const char *dev;
|
||||
|
@ -142,6 +157,7 @@ enum mountmgr_funcs
|
|||
unix_add_drive,
|
||||
unix_get_dosdev_symlink,
|
||||
unix_set_dosdev_symlink,
|
||||
unix_get_volume_size_info,
|
||||
unix_get_volume_dos_devices,
|
||||
unix_read_volume_file,
|
||||
unix_match_unixdev,
|
||||
|
|
Loading…
Reference in a new issue