[PATCH 2/2] mountmgr.sys: Implement StorageDeviceSeekPenaltyProperty

David Koolhoven david at koolhoven-home.net
Mon Apr 26 14:57:55 CDT 2021


Implements StorageDeviceSeekPenaltyProperty for
query_propery()

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51065
Signed-off-by: David Koolhoven <david at 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
-- 
2.19.1




More information about the wine-devel mailing list