internal static extern bool DeviceIoControlIde(SafeFileHandle hDevice, WindowsIoctl ioControlCode, ref IdePassThroughDirect inBuffer, uint nInBufferSize, ref IdePassThroughDirect outBuffer, uint nOutBufferSize, ref uint pBytesReturned, IntPtr overlapped);
/// <summary> /// Sends an ATA command in 28-bit LBA mode using undocumented Windows XP ioctl /// </summary> /// <returns>0 if no error occurred, otherwise, errno</returns> /// <param name="fd">File handle</param> /// <param name="buffer">Buffer for SCSI command response</param> /// <param name="timeout">Timeout in seconds</param> /// <param name="duration">Time it took to execute the command in milliseconds</param> /// <param name="sense"><c>True</c> if ATA error returned non-OK status</param> /// <param name="registers">Registers to send to drive</param> /// <param name="errorRegisters">Registers returned by drive</param> /// <param name="protocol">ATA protocol to use</param> internal static int SendIdeCommand(SafeFileHandle fd, AtaRegistersLba28 registers, out AtaErrorRegistersLba28 errorRegisters, AtaProtocol protocol, ref byte[] buffer, uint timeout, out double duration, out bool sense) { duration = 0; sense = false; errorRegisters = new AtaErrorRegistersLba28(); if (buffer == null) { return(-1); } IdePassThroughDirect iptd = new IdePassThroughDirect { CurrentTaskFile = new AtaTaskFile { Command = registers.Command, CylinderHigh = registers.LbaHigh, CylinderLow = registers.LbaMid, DeviceHead = registers.DeviceHead, Features = registers.Feature, SectorCount = registers.SectorCount, SectorNumber = registers.LbaLow }, DataBufferSize = 512, DataBuffer = new byte[512] }; uint k = 0; int error = 0; Array.Copy(buffer, 0, iptd.DataBuffer, 0, buffer.Length); DateTime start = DateTime.Now; sense = !Extern.DeviceIoControlIde(fd, WindowsIoctl.IoctlIdePassThrough, ref iptd, (uint)Marshal.SizeOf(iptd), ref iptd, (uint)Marshal.SizeOf(iptd), ref k, IntPtr.Zero); DateTime end = DateTime.Now; if (sense) { error = Marshal.GetLastWin32Error(); } buffer = new byte[k - 12]; Array.Copy(iptd.DataBuffer, 0, buffer, 0, buffer.Length); duration = (end - start).TotalMilliseconds; errorRegisters.LbaHigh = iptd.CurrentTaskFile.CylinderHigh; errorRegisters.LbaMid = iptd.CurrentTaskFile.CylinderLow; errorRegisters.DeviceHead = iptd.CurrentTaskFile.DeviceHead; errorRegisters.Error = iptd.CurrentTaskFile.Error; errorRegisters.LbaLow = iptd.CurrentTaskFile.SectorNumber; errorRegisters.SectorCount = iptd.CurrentTaskFile.SectorCount; errorRegisters.Status = iptd.CurrentTaskFile.Status; sense = errorRegisters.Error != 0 || (errorRegisters.Status & 0xA5) != 0; return(error); }