From: Paul Gofman pgofman@codeweavers.com
--- dlls/kernel32/tests/volume.c | 35 ++++++++++++++++++++++++++++ dlls/mountmgr.sys/device.c | 28 ++++++++++++++++++++++ include/ntddstor.h | 45 +++++++++++++++++++++++++++++++++++- 3 files changed, 107 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/volume.c b/dlls/kernel32/tests/volume.c index baf055c08b0..24a9a2e7124 100644 --- a/dlls/kernel32/tests/volume.c +++ b/dlls/kernel32/tests/volume.c @@ -620,6 +620,7 @@ static void test_disk_query_property(void) STORAGE_PROPERTY_QUERY query = {0}; STORAGE_DESCRIPTOR_HEADER header = {0}; STORAGE_DEVICE_DESCRIPTOR descriptor = {0}; + DEVICE_SEEK_PENALTY_DESCRIPTOR seek_pen = {0}; HANDLE handle; DWORD error; DWORD size; @@ -656,6 +657,40 @@ static void test_disk_query_property(void) ok(descriptor.Version == sizeof(descriptor), "got descriptor.Version %ld\n", descriptor.Version); ok(descriptor.Size >= sizeof(descriptor), "got descriptor.Size %ld\n", descriptor.Size);
+ + query.PropertyId = StorageDeviceSeekPenaltyProperty; + query.QueryType = PropertyStandardQuery; + SetLastError(0xdeadbeef); + ret = DeviceIoControl(handle, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query), &header, sizeof(header), &size, + NULL); + error = GetLastError(); + if (!ret && error == ERROR_INVALID_FUNCTION) + { + win_skip( "StorageDeviceSeekPenaltyProperty is not supported.\n" ); /* Win7 */ + } + else + { + ok(ret, "expect ret %#x, got %#x\n", TRUE, ret); + ok(error == 0xdeadbeef, "expect err %#x, got err %#lx\n", 0xdeadbeef, error); + ok(size == sizeof(header), "got size %ld\n", size); + ok(header.Version == sizeof(seek_pen), "got header.Version %ld\n", header.Version); + ok(header.Size == sizeof(seek_pen), "got header.Size %ld\n", header.Size); + + memset(&seek_pen, 0xcc, sizeof(seek_pen)); + ret = DeviceIoControl(handle, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query), &seek_pen, sizeof(seek_pen), + &size, NULL); + error = GetLastError(); + ok(ret || (error == ERROR_INVALID_FUNCTION /* Win8 VMs */ || (error == ERROR_GEN_FAILURE /* VMs */)), + "got ret %d, error %#lx\n", ret, error); + if (ret) + { + ok(size == sizeof(seek_pen), "got size %ld\n", size); + ok(seek_pen.Version == sizeof(seek_pen), "got %ld\n", seek_pen.Version); + ok(seek_pen.Size == sizeof(seek_pen), "got %ld\n", seek_pen.Size); + ok(seek_pen.IncursSeekPenalty == TRUE || seek_pen.IncursSeekPenalty == FALSE, "got %d.\n", seek_pen.IncursSeekPenalty); + } + } + CloseHandle(handle); }
diff --git a/dlls/mountmgr.sys/device.c b/dlls/mountmgr.sys/device.c index 2aef41dad0f..271f2c86d77 100644 --- a/dlls/mountmgr.sys/device.c +++ b/dlls/mountmgr.sys/device.c @@ -1594,6 +1594,34 @@ static NTSTATUS query_property( struct disk_device *device, IRP *irp )
break; } + case StorageDeviceSeekPenaltyProperty: + { + DEVICE_SEEK_PENALTY_DESCRIPTOR *d = irp->AssociatedIrp.SystemBuffer; + + if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_DESCRIPTOR_HEADER)) + { + status = STATUS_INVALID_PARAMETER; + } + else + { + if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(*d)) + { + d->Version = d->Size = sizeof(*d); + irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER); + } + else + { + FIXME( "Faking StorageDeviceSeekPenaltyProperty data.\n" ); + + memset( d, 0, sizeof(*d) ); + d->Version = d->Size = sizeof(*d); + irp->IoStatus.Information = sizeof(*d); + } + status = STATUS_SUCCESS; + } + break; + } + default: FIXME( "Unsupported property %#x\n", query->PropertyId ); status = STATUS_NOT_SUPPORTED; diff --git a/include/ntddstor.h b/include/ntddstor.h index 4d715efd1ef..0cb6d01f9b9 100644 --- a/include/ntddstor.h +++ b/include/ntddstor.h @@ -214,7 +214,44 @@ typedef enum _STORAGE_QUERY_TYPE {
typedef enum _STORAGE_PROPERTY_ID { StorageDeviceProperty = 0, - StorageAdapterProperty + StorageAdapterProperty, + StorageDeviceIdProperty, + StorageDeviceUniqueIdProperty, + StorageDeviceWriteCacheProperty, + StorageMiniportProperty, + StorageAccessAlignmentProperty, + StorageDeviceSeekPenaltyProperty, + StorageDeviceTrimProperty, + StorageDeviceWriteAggregationProperty, + StorageDeviceDeviceTelemetryProperty, + StorageDeviceLBProvisioningProperty, + StorageDevicePowerProperty, + StorageDeviceCopyOffloadProperty, + StorageDeviceResiliencyProperty, + StorageDeviceMediumProductType, + StorageAdapterRpmbProperty, + StorageAdapterCryptoProperty, + StorageDeviceIoCapabilityProperty = 48, + StorageAdapterProtocolSpecificProperty, + StorageDeviceProtocolSpecificProperty, + StorageAdapterTemperatureProperty, + StorageDeviceTemperatureProperty, + StorageAdapterPhysicalTopologyProperty, + StorageDevicePhysicalTopologyProperty, + StorageDeviceAttributesProperty, + StorageDeviceManagementStatus, + StorageAdapterSerialNumberProperty, + StorageDeviceLocationProperty, + StorageDeviceNumaProperty, + StorageDeviceZonedDeviceProperty, + StorageDeviceUnsafeShutdownCount, + StorageDeviceEnduranceProperty, + StorageDeviceLedStateProperty, + StorageDeviceSelfEncryptionProperty = 64, + StorageFruIdProperty, + StorageStackProperty, + StorageAdapterProtocolSpecificPropertyEx, + StorageDeviceProtocolSpecificPropertyEx, } STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID;
typedef struct _STORAGE_PROPERTY_QUERY { @@ -223,6 +260,12 @@ typedef struct _STORAGE_PROPERTY_QUERY { UCHAR AdditionalParameters[1]; } STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY;
+typedef struct _DEVICE_SEEK_PENALTY_DESCRIPTOR { + DWORD Version; + DWORD Size; + BOOLEAN IncursSeekPenalty; +} DEVICE_SEEK_PENALTY_DESCRIPTOR, *PDEVICE_SEEK_PENALTY_DESCRIPTOR; + typedef struct _STORAGE_DESCRIPTOR_HEADER { ULONG Version; ULONG Size;