private static extern bool DeviceIoControl( SafeFileHandle hDevice, uint dwIoControlCode, ref AtaIdentifyDeviceQuery lpInBuffer, uint nInBufferSize, ref AtaIdentifyDeviceQuery lpOutBuffer, uint nOutBufferSize, out uint lpBytesReturned, IntPtr lpOverlapped);
/// <summary> /// Check if the drive has a nominal media rotation rate. /// </summary> /// <param name="physicalDriveName">A valid physicalDriveName.</param> /// <returns><c> true </c> if the drive has a media rotation rate otherwise, <c> false </c></returns> /// <remarks>Administrative privilege is required!</remarks> /// <exception cref="DetectionFailedException"></exception> private static bool HasDriveNominalMediaRotationRate(string physicalDriveName) { var hDrive = CreateFileW( physicalDriveName, GenericRead | GenericWrite, // Administrative privilege is required FileShareRead | FileShareWrite, IntPtr.Zero, OpenExisting, FileAttributeNormal, IntPtr.Zero); if (hDrive == null || hDrive.IsInvalid) { throw new DetectionFailedException(string.Format("Could not detect NominalMediaRotationRate of {0}", physicalDriveName)); } var ioctlAtaPassThrough = CTL_CODE( IoctlScsiBase, 0x040b, MethodBuffered, FileReadAccess | FileWriteAccess); // From ntddscsi.h var idQuery = new AtaIdentifyDeviceQuery {data = new ushort[256]}; idQuery.header.Length = (ushort) Marshal.SizeOf(idQuery.header); idQuery.header.AtaFlags = (ushort) AtaFlagsDataIn; idQuery.header.DataTransferLength = (uint) (idQuery.data.Length*2); // Size of "data" in bytes idQuery.header.TimeOutValue = 3; // Sec idQuery.header.DataBufferOffset = Marshal.OffsetOf( typeof (AtaIdentifyDeviceQuery), "data"); idQuery.header.PreviousTaskFile = new byte[8]; idQuery.header.CurrentTaskFile = new byte[8]; idQuery.header.CurrentTaskFile[6] = 0xec; // ATA IDENTIFY DEVICE uint retvalSize; var result = DeviceIoControl( hDrive, ioctlAtaPassThrough, ref idQuery, (uint) Marshal.SizeOf(idQuery), ref idQuery, (uint) Marshal.SizeOf(idQuery), out retvalSize, IntPtr.Zero); hDrive.Close(); if (result == false) { throw new DetectionFailedException(string.Format("Could not detect NominalMediaRotationRate of {0}", physicalDriveName)); } // Word index of nominal media rotation rate // (1 means non-rotate device) const int kNominalMediaRotRateWordIndex = 217; if (idQuery.data[kNominalMediaRotRateWordIndex] == 1) { return false; } return true; }
/// <summary> /// Check if the drive has a nominal media rotation rate. /// </summary> /// <param name="physicalDriveName">A valid physicalDriveName.</param> /// <returns><c> true </c> if the drive has a media rotation rate otherwise, <c> false </c></returns> /// <remarks>Administrative privilege is required!</remarks> /// <exception cref="DetectionFailedException"></exception> private static bool HasDriveNominalMediaRotationRate(string physicalDriveName) { var hDrive = CreateFileW( physicalDriveName, GenericRead | GenericWrite, // Administrative privilege is required FileShareRead | FileShareWrite, IntPtr.Zero, OpenExisting, FileAttributeNormal, IntPtr.Zero); if (hDrive == null || hDrive.IsInvalid) { throw new DetectionFailedException(string.Format("Could not detect NominalMediaRotationRate of {0}", physicalDriveName)); } var ioctlAtaPassThrough = CTL_CODE( IoctlScsiBase, 0x040b, MethodBuffered, FileReadAccess | FileWriteAccess); // From ntddscsi.h var idQuery = new AtaIdentifyDeviceQuery { data = new ushort[256] }; idQuery.header.Length = (ushort)Marshal.SizeOf(idQuery.header); idQuery.header.AtaFlags = (ushort)AtaFlagsDataIn; idQuery.header.DataTransferLength = (uint)(idQuery.data.Length * 2); // Size of "data" in bytes idQuery.header.TimeOutValue = 3; // Sec idQuery.header.DataBufferOffset = Marshal.OffsetOf( typeof(AtaIdentifyDeviceQuery), "data"); idQuery.header.PreviousTaskFile = new byte[8]; idQuery.header.CurrentTaskFile = new byte[8]; idQuery.header.CurrentTaskFile[6] = 0xec; // ATA IDENTIFY DEVICE uint retvalSize; var result = DeviceIoControl( hDrive, ioctlAtaPassThrough, ref idQuery, (uint)Marshal.SizeOf(idQuery), ref idQuery, (uint)Marshal.SizeOf(idQuery), out retvalSize, IntPtr.Zero); hDrive.Close(); if (result == false) { throw new DetectionFailedException(string.Format("Could not detect NominalMediaRotationRate of {0}", physicalDriveName)); } // Word index of nominal media rotation rate // (1 means non-rotate device) const int kNominalMediaRotRateWordIndex = 217; if (idQuery.data[kNominalMediaRotRateWordIndex] == 1) { return(false); } return(true); }