Implements StorageDeviceSeekPenaltyProperty for query_propery()
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51065 Signed-off-by: David Koolhoven david@koolhoven-home.net --- dlls/mountmgr.sys/device.c | 120 ++++++++++++++++++++++++++++++++++++- include/ntddstor.h | 9 ++- 2 files changed, 126 insertions(+), 3 deletions(-)
diff --git a/dlls/mountmgr.sys/device.c b/dlls/mountmgr.sys/device.c index 04e8fe3c0f5..d031080c459 100644 --- a/dlls/mountmgr.sys/device.c +++ b/dlls/mountmgr.sys/device.c @@ -28,6 +28,10 @@ #include <fcntl.h> #include <unistd.h> #include <sys/time.h> +#ifdef linux +#include <sys/stat.h> +#include <sys/sysmacros.h> +#endif #ifdef HAVE_SYS_IOCTL_H # include <sys/ioctl.h> #endif @@ -1867,8 +1871,6 @@ static NTSTATUS query_property( struct disk_device *device, IRP *irp ) } else { - FIXME( "Faking StorageDeviceProperty data\n" ); - memset( irp->AssociatedIrp.SystemBuffer, 0, irpsp->Parameters.DeviceIoControl.OutputBufferLength ); descriptor = irp->AssociatedIrp.SystemBuffer; descriptor->Version = sizeof(STORAGE_DEVICE_DESCRIPTOR); @@ -1894,6 +1896,120 @@ static NTSTATUS query_property( struct disk_device *device, IRP *irp )
break; } + case StorageDeviceSeekPenaltyProperty: + { +#ifdef linux + FILE *fp; + char isrotapathstr[260]; + char evpath[260]; + char ueventbufstr[260]; + char isrotastrbuf[2]; + char *fgetsret = NULL; + int ret = 0; + char *rptr = NULL; + char *sptr = NULL; + char *devstr_edited = NULL; + char *mountstr = NULL; + char mountpath[260]; + char *part_dev = NULL; + char *path, *p = NULL; + int c = 0; + struct stat statbuf; + DEVICE_SEEK_PENALTY_DESCRIPTOR *descriptor; + + memset( irp->AssociatedIrp.SystemBuffer, 0, irpsp->Parameters.DeviceIoControl.OutputBufferLength ); + descriptor = irp->AssociatedIrp.SystemBuffer; + descriptor->Version = sizeof(DEVICE_SEEK_PENALTY_DESCRIPTOR); + descriptor->Size = sizeof(DEVICE_SEEK_PENALTY_DESCRIPTOR); + + if (!device->unix_mount) { + status = STATUS_DATA_ERROR; + break; + } + + if (!(path = get_dosdevices_path( &p ))) { + status = STATUS_DATA_ERROR; + break; + } + + /* Crop any drive letters off the end of the string */ + if (!strncmp(&path[strlen(path) - 2], "::", 2)) { + path[strlen(path) - 3] = '\0'; + } + + snprintf (mountpath, 260, "%s%s", path, device->unix_mount); + ret = stat (mountpath, &statbuf); + if (ret == -1) { + status = STATUS_DATA_ERROR; + break; + } + HeapFree( GetProcessHeap(), 0, path ); + sprintf (evpath, "/sys/dev/block/%d:%d/uevent", major(statbuf.st_dev), minor(statbuf.st_dev)); + fp = fopen(evpath, "r"); + if (!fp) { + status = STATUS_DATA_ERROR; + break; + } + while ((rptr = fgets (ueventbufstr, 260, fp))) { + sptr = strstr (rptr, "DEVNAME="); + if (sptr) { + sptr += strlen ("DEVNAME="); + break; + } + } + fclose (fp); + devstr_edited = sptr; + if (!devstr_edited) { + status = STATUS_DATA_ERROR; + break; + } + /* Find first character after forwardslash '/' */ + part_dev = strrchr (devstr_edited, '/'); + if (!part_dev || (part_dev == devstr_edited)) part_dev = devstr_edited; + else part_dev++; + /* Trim off trailing digits and whitespace */ + c = strlen (devstr_edited); + c--; + while ((devstr_edited[c] >= '0' && devstr_edited[c] <= '9') + || (devstr_edited[c] == '\n' || devstr_edited[c] == '\r')) + devstr_edited[c--] = '\0'; + + ret = snprintf (isrotapathstr, 260, "/sys/block/%s/queue/rotational", part_dev); + if (ret < 1 || ret == 260) { + status = STATUS_DATA_ERROR; + break; + } + + fp = fopen(isrotapathstr, "r"); + if (!fp) { + status = STATUS_DATA_ERROR; + break; + } + + fgetsret = fgets(isrotastrbuf, 2, fp); + if (!fgetsret) { + status = STATUS_DATA_ERROR; + break; + } + + fclose (fp); + + if (isrotastrbuf[0] == '1') { + descriptor->IncursSeekPenalty = TRUE; + } else if (isrotastrbuf[0] == '0') { + descriptor->IncursSeekPenalty = FALSE; + } else { + status = STATUS_DATA_ERROR; + break; + } + + status = STATUS_SUCCESS; +#else + FIXME( "Unsupported property StorageDeviceSeekPenalty\n" ); + status = STATUS_NOT_SUPPORTED; +#endif + break; + } default: FIXME( "Unsupported property %#x\n", query->PropertyId ); status = STATUS_NOT_SUPPORTED; diff --git a/include/ntddstor.h b/include/ntddstor.h index b8c4bb73b0d..836def413fe 100644 --- a/include/ntddstor.h +++ b/include/ntddstor.h @@ -214,7 +214,8 @@ typedef enum _STORAGE_QUERY_TYPE {
typedef enum _STORAGE_PROPERTY_ID { StorageDeviceProperty = 0, - StorageAdapterProperty + StorageAdapterProperty = 1, + StorageDeviceSeekPenaltyProperty = 7, } STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID;
typedef struct _STORAGE_PROPERTY_QUERY { @@ -272,6 +273,12 @@ typedef struct _STORAGE_ADAPTER_DESCRIPTOR { USHORT BusMinorVersion; } STORAGE_ADAPTER_DESCRIPTOR, *PSTORAGE_ADAPTER_DESCRIPTOR;
+typedef struct _DEVICE_SEEK_PENALTY_DESCRIPTOR { + ULONG Version; + ULONG Size; + BOOLEAN IncursSeekPenalty; +} DEVICE_SEEK_PENALTY_DESCRIPTOR, *PDEVICE_SEEK_PENALTY_DESCRIPTOR; + #ifdef __cplusplus } #endif