Beispiel #1
0
        private static byte[] _SendCommand(SafeFileHandle handle, byte[] cmd, byte[] data, int bytesExpected)
        {
            const int IOCTL_SCSI_PASS_THROUGH_DIRECT = 0x4D014;
            const int TIMEOUT_SECS = 30;
            SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER scsi = null;
            IntPtr inBuffer = IntPtr.Zero;

            byte[] ret = null;

            try
            {
                scsi                      = new SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER();
                scsi.sptd.Length          = (short)Marshal.SizeOf(scsi.sptd);
                scsi.sptd.TimeOutValue    = TIMEOUT_SECS;
                scsi.sptd.SenseInfoOffset = (uint)Marshal.OffsetOf(typeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), "sense");
                scsi.sptd.SenseInfoLength = (byte)scsi.sense.Length;
                scsi.sptd.CdbLength       = (byte)cmd.Length;
                Array.Copy(cmd, scsi.sptd.Cdb, cmd.Length);
                scsi.sptd.DataIn             = data != null && data.Length > 0 ? SCSI_IOCTL_DATA_OUT : SCSI_IOCTL_DATA_IN;
                scsi.sptd.DataTransferLength = data != null && data.Length > 0 ? data.Length : bytesExpected;
                scsi.sptd.DataBuffer         = Marshal.AllocHGlobal(scsi.sptd.DataTransferLength);
                if (data != null && data.Length > 0)
                {
                    Marshal.Copy(data, 0, scsi.sptd.DataBuffer, data.Length);
                }

                uint bytesReturned;
                inBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(scsi));
                var size = (uint)Marshal.SizeOf(scsi);
                Marshal.StructureToPtr(scsi, inBuffer, false);
                if (!DeviceIoControl(handle.DangerousGetHandle(), IOCTL_SCSI_PASS_THROUGH_DIRECT,
                                     inBuffer, size, inBuffer, size, out bytesReturned, IntPtr.Zero))
                {
                    //Whoops, do something with the error code
                    int last = Marshal.GetLastWin32Error();
                    throw new InvalidOperationException("DeviceIoControl failed: " + last.ToString("X04"));
                }
                else
                {
                    if (scsi.sptd.ScsiStatus != 0)
                    {
                        //Whoops, do something with the error code
                        throw new InvalidOperationException("SCSI command failed: " + scsi.sptd.ScsiStatus.ToString("X02"));
                    }
                    else
                    {
                        //Success, marshal back any data we received
                        if (scsi.sptd.DataTransferLength > 0)
                        {
                            ret = new byte[scsi.sptd.DataTransferLength];
                            Marshal.Copy(scsi.sptd.DataBuffer, ret, 0, ret.Length);
                        }
                    }
                }
            }
            finally
            {
                /* Free any unmanaged resources */

                if (scsi != null && scsi.sptd.DataBuffer != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(scsi.sptd.DataBuffer);
                }

                if (inBuffer != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(inBuffer);
                }
            }

            return(ret);
        }
Beispiel #2
0
        private static byte[] _SendCommand(SafeFileHandle handle, byte[] cmd, byte[] data, int bytesExpected)
        {
            const int IOCTL_SCSI_PASS_THROUGH_DIRECT = 0x4D014;
            const int TIMEOUT_SECS = 30;
            SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER scsi = null;
            IntPtr inBuffer = IntPtr.Zero;
            byte[] ret = null;

            try
            {
                scsi = new SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER();
                scsi.sptd.Length = (short)Marshal.SizeOf(scsi.sptd);
                scsi.sptd.TimeOutValue = TIMEOUT_SECS;
                scsi.sptd.SenseInfoOffset = (uint)Marshal.OffsetOf(typeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), "sense");
                scsi.sptd.SenseInfoLength = (byte)scsi.sense.Length;
                scsi.sptd.CdbLength = (byte)cmd.Length;
                Array.Copy(cmd, scsi.sptd.Cdb, cmd.Length);
                scsi.sptd.DataIn = data != null && data.Length > 0 ? SCSI_IOCTL_DATA_OUT : SCSI_IOCTL_DATA_IN;
                scsi.sptd.DataTransferLength = data != null && data.Length > 0 ? data.Length : bytesExpected;
                scsi.sptd.DataBuffer = Marshal.AllocHGlobal(scsi.sptd.DataTransferLength);
                if (data != null && data.Length > 0)
                {
                    Marshal.Copy(data, 0, scsi.sptd.DataBuffer, data.Length);
                }

                uint bytesReturned;
                inBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(scsi));
                var size = (uint)Marshal.SizeOf(scsi);
                Marshal.StructureToPtr(scsi, inBuffer, false);
                if (!DeviceIoControl(handle.DangerousGetHandle(), IOCTL_SCSI_PASS_THROUGH_DIRECT,
                    inBuffer, size, inBuffer, size, out bytesReturned, IntPtr.Zero))
                {
                    //Whoops, do something with the error code
                    int last = Marshal.GetLastWin32Error();
                    throw new InvalidOperationException("DeviceIoControl failed: " + last.ToString("X04"));
                }
                else
                {
                    if (scsi.sptd.ScsiStatus != 0)
                    {
                        //Whoops, do something with the error code
                        throw new InvalidOperationException("SCSI command failed: " + scsi.sptd.ScsiStatus.ToString("X02"));
                    }
                    else
                    {
                        //Success, marshal back any data we received
                        if (scsi.sptd.DataTransferLength > 0)
                        {
                            ret = new byte[scsi.sptd.DataTransferLength];
                            Marshal.Copy(scsi.sptd.DataBuffer, ret, 0, ret.Length);
                        }
                    }
                }
            }
            finally
            {
                /* Free any unmanaged resources */

                if (scsi != null && scsi.sptd.DataBuffer != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(scsi.sptd.DataBuffer);
                }

                if (inBuffer != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(inBuffer);
                }
            }

            return ret;
        }