/// <summary>Sends a SCSI command</summary> /// <returns>0 if no error occurred, otherwise, errno</returns> /// <param name="fd">File handle</param> /// <param name="cdb">SCSI CDB</param> /// <param name="buffer">Buffer for SCSI command response</param> /// <param name="senseBuffer">Buffer with the SCSI sense</param> /// <param name="timeout">Timeout in seconds</param> /// <param name="direction">SCSI command transfer direction</param> /// <param name="duration">Time it took to execute the command in milliseconds</param> /// <param name="sense"> /// <c>True</c> if SCSI error returned non-OK status and <paramref name="senseBuffer" /> contains SCSI /// sense /// </param> internal static int SendScsiCommand(SafeFileHandle fd, byte[] cdb, ref byte[] buffer, out byte[] senseBuffer, uint timeout, ScsiIoctlDirection direction, out double duration, out bool sense) { senseBuffer = null; duration = 0; sense = false; if (buffer == null) { return(-1); } var sptdSb = new ScsiPassThroughDirectAndSenseBuffer { SenseBuf = new byte[32], sptd = new ScsiPassThroughDirect { Cdb = new byte[16], CdbLength = (byte)cdb.Length, SenseInfoLength = 32, DataIn = direction, DataTransferLength = (uint)buffer.Length, TimeOutValue = timeout, DataBuffer = Marshal.AllocHGlobal(buffer.Length) } }; sptdSb.sptd.Length = (ushort)Marshal.SizeOf(sptdSb.sptd); sptdSb.sptd.SenseInfoOffset = (uint)Marshal.SizeOf(sptdSb.sptd); Array.Copy(cdb, sptdSb.sptd.Cdb, cdb.Length); uint k = 0; int error = 0; Marshal.Copy(buffer, 0, sptdSb.sptd.DataBuffer, buffer.Length); DateTime start = DateTime.Now; bool hasError = !Extern.DeviceIoControlScsi(fd, WindowsIoctl.IoctlScsiPassThroughDirect, ref sptdSb, (uint)Marshal.SizeOf(sptdSb), ref sptdSb, (uint)Marshal.SizeOf(sptdSb), ref k, IntPtr.Zero); DateTime end = DateTime.Now; if (hasError) { error = Marshal.GetLastWin32Error(); } Marshal.Copy(sptdSb.sptd.DataBuffer, buffer, 0, buffer.Length); sense |= sptdSb.sptd.ScsiStatus != 0; senseBuffer = new byte[32]; Array.Copy(sptdSb.SenseBuf, senseBuffer, 32); duration = (end - start).TotalMilliseconds; Marshal.FreeHGlobal(sptdSb.sptd.DataBuffer); return(error); }
internal static extern bool DeviceIoControlScsi(SafeFileHandle hDevice, WindowsIoctl ioControlCode, ref ScsiPassThroughDirectAndSenseBuffer inBuffer, uint nInBufferSize, ref ScsiPassThroughDirectAndSenseBuffer outBuffer, uint nOutBufferSize, ref uint pBytesReturned, IntPtr overlapped);