Example #1
0
        public static string GetDeviceFromDrive(System.IO.DriveInfo driveInfo)
        {
            IntPtr pStorageDeviceNumber = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (STORAGE_DEVICE_NUMBER)));
            SafeFileHandle hDrive = null;
            try {
                string driveName = "\\\\.\\" + driveInfo.ToString ().Substring (0, 2);
                hDrive = ApiFunctions.CreateFile (driveName, AccessMask.GENERIC_READ,
                    System.IO.FileShare.ReadWrite, 0, System.IO.FileMode.Open, 0, IntPtr.Zero);

                if (hDrive.IsInvalid)
                    throw new FileLoadException ("Drive handle invalid");

                bool status;
                int retByte;
                System.Threading.NativeOverlapped nativeOverlap = new System.Threading.NativeOverlapped ();
                status = ApiFunctions.DeviceIoControl (hDrive, DeviceIOControlCode.StorageGetDeviceNumber, IntPtr.Zero, 0,
                    pStorageDeviceNumber, Marshal.SizeOf (typeof (STORAGE_DEVICE_NUMBER)), out retByte, ref nativeOverlap);

                if (!status)
                    throw new FileLoadException ("DeviceIoControl error");

                STORAGE_DEVICE_NUMBER storDevNum = (STORAGE_DEVICE_NUMBER)Marshal.PtrToStructure (pStorageDeviceNumber, typeof (STORAGE_DEVICE_NUMBER));

                return "\\\\.\\PhysicalDrive" + storDevNum.DeviceNumber;
            }
            finally {
                Marshal.FreeHGlobal (pStorageDeviceNumber);
                if (hDrive != null)
                    hDrive.Close ();
            }
        }
Example #2
0
 static internal extern bool GetOverlappedResult(IntPtr hFile, [In] ref System.Threading.NativeOverlapped lpOverlapped, out uint lpNumberOfBytesTransferred, bool bWait);
Example #3
0
 public static extern Boolean ReadFile(IntPtr hFile,
                                       [Out] Byte[] lpBuffer,
                                       Int32 nNumberOfBytesToRead,
                                       IntPtr lpNumberOfBytesRead,
                                       [In] ref System.Threading.NativeOverlapped lpOverlapped);
Example #4
0
 static extern bool ReadFileEx(IntPtr hFile, [Out] byte[] lpBuffer,
                               uint nNumberOfBytesToRead, [In] ref System.Threading.NativeOverlapped lpOverlapped,
                               ReadFileCompletionDelegate lpCompletionRoutine);
 public static extern bool SFileReadFile(MpqFileSafeHandle hFile, IntPtr lpBuffer, uint dwToRead, out uint pdwRead, ref System.Threading.NativeOverlapped lpOverlapped);
Example #6
0
 static internal extern bool ReadFile(IntPtr hFile, [Out] byte[] lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, [In] ref System.Threading.NativeOverlapped lpOverlapped);
Example #7
0
 internal static extern int WriteFile(
     IntPtr hFile,
     byte[] lpBuffer,
     UInt32 bytesToWrite,
     out UInt32 bytesWritten,
     ref System.Threading.NativeOverlapped lpOverlapped);
Example #8
0
 public static extern Boolean GetOverlappedResult(
     IntPtr hFile,
     [In] ref System.Threading.NativeOverlapped lpOverlapped,
     out Int32 lpNumberOfBytesTransferred,
     Boolean bWait
     );
Example #9
0
 internal static extern bool ReadFileEx(
     IntPtr hFile,
     [Out] byte[] lpBuffer,
     uint nNumberOfBytesToRead,
     [In] ref System.Threading.NativeOverlapped lpOverlapped,
     System.Threading.IOCompletionCallback lpCompletionRoutine);
Example #10
0
        private byte[] GetWin32XML(IDevice Ipod)
        {
            IntPtr pSptwb = IntPtr.Zero;
            SafeFileHandle driveHandle = null;

            try {
                ScsiPassThroughWithBuffers sptwb;
                int returned, length;
                string device = GetDeviceFromDrive (((Win32.Device)Ipod).Drive);
                bool status;

                byte [] buffer = new byte [102400];
                int bufferIdx = 0;

                byte page_code, page_start, page_end = 0;

                driveHandle = ApiFunctions.CreateFile (device, AccessMask.GENERIC_ALL,
                    System.IO.FileShare.ReadWrite, 0, System.IO.FileMode.Open, 0, IntPtr.Zero);

                if (driveHandle.IsInvalid)
                    throw new FileLoadException ("Device invalid");

                sptwb = new ScsiPassThroughWithBuffers ();
                sptwb.spt.Length = (ushort)Marshal.SizeOf (typeof (SCSI_PASS_THROUGH));
                sptwb.spt.PathId = 0;
                sptwb.spt.TargetId = 1;
                sptwb.spt.Lun = 0;
                sptwb.spt.CdbLength = 6;
                sptwb.spt.SenseInfoLength = 32;
                sptwb.spt.DataIn = 1; //SCSI_IOCTL_DATA_IN
                sptwb.spt.DataTransferLength = 255;
                sptwb.spt.TimeOutValue = 2;
                sptwb.spt.DataBufferOffset = Marshal.OffsetOf (typeof (ScsiPassThroughWithBuffers), "ucDataBuf");
                sptwb.spt.SenseInfoOffset = Marshal.OffsetOf (typeof (ScsiPassThroughWithBuffers), "ucSenseBuf");
                sptwb.spt.Cdb = new byte [16];
                sptwb.spt.Cdb [0] = 0x12; //SCSI_INQUIRY
                sptwb.spt.Cdb [1] |= 1;
                sptwb.spt.Cdb [2] = 0xC0;
                sptwb.spt.Cdb [4] = 255;

                length = Marshal.OffsetOf (typeof (ScsiPassThroughWithBuffers), "ucDataBuf").ToInt32 ()
                    + (int)sptwb.spt.DataTransferLength;

                pSptwb = Marshal.AllocHGlobal (Marshal.SizeOf (sptwb));
                Marshal.StructureToPtr (sptwb, pSptwb, true);

                System.Threading.NativeOverlapped nativeOverlapped = new System.Threading.NativeOverlapped ();
                status = ApiFunctions.DeviceIoControl (driveHandle, DeviceIOControlCode.ScsiPassThrough,
                    pSptwb, Marshal.SizeOf (typeof (SCSI_PASS_THROUGH)), pSptwb, length, out returned, ref nativeOverlapped);

                if (!status)
                    throw new FileLoadException("DeviceIoControl Error", Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()));

                sptwb = (ScsiPassThroughWithBuffers)Marshal.PtrToStructure (pSptwb, typeof (ScsiPassThroughWithBuffers));

                page_start = sptwb.ucDataBuf [4];
                page_end = sptwb.ucDataBuf [3 + sptwb.ucDataBuf [3]];

                for (page_code = page_start; page_code <= page_end; page_code++) {
                    sptwb.spt.Length = (ushort)Marshal.SizeOf (typeof (SCSI_PASS_THROUGH));
                    sptwb.spt.PathId = 0;
                    sptwb.spt.TargetId = 1;
                    sptwb.spt.Lun = 0;
                    sptwb.spt.CdbLength = 6;
                    sptwb.spt.SenseInfoLength = 32;
                    sptwb.spt.DataIn = 1; //SCSI_IOCTL_DATA_IN
                    sptwb.spt.DataTransferLength = 255;
                    sptwb.spt.TimeOutValue = 2;
                    sptwb.spt.DataBufferOffset = Marshal.OffsetOf (typeof (ScsiPassThroughWithBuffers), "ucDataBuf");
                    sptwb.spt.SenseInfoOffset = Marshal.OffsetOf (typeof (ScsiPassThroughWithBuffers), "ucSenseBuf");
                    sptwb.spt.Cdb = new byte [16];
                    sptwb.spt.Cdb [0] = 0x12; //SCSI_INQUIRY
                    sptwb.spt.Cdb [1] |= 1;
                    sptwb.spt.Cdb [2] = page_code;
                    sptwb.spt.Cdb [4] = 255;

                    length = Marshal.OffsetOf (typeof (ScsiPassThroughWithBuffers), "ucDataBuf").ToInt32 ()
                        + (int)sptwb.spt.DataTransferLength;
                    returned = 0;
                    Marshal.StructureToPtr (sptwb, pSptwb, true);
                    status = ApiFunctions.DeviceIoControl (driveHandle, DeviceIOControlCode.ScsiPassThrough,
                        pSptwb, Marshal.SizeOf (typeof (SCSI_PASS_THROUGH)), pSptwb, length, out returned, ref nativeOverlapped);

                    if (!status)
                        throw new FileLoadException ("DeviceIoControl Error", Marshal.GetExceptionForHR(Marshal.GetLastWin32Error()));

                    sptwb = (ScsiPassThroughWithBuffers)Marshal.PtrToStructure (pSptwb, typeof (ScsiPassThroughWithBuffers));

                    while (bufferIdx + sptwb.ucDataBuf [3] > buffer.Length)
                        Array.Resize<byte> (ref buffer, buffer.Length * 2);

                    Array.Copy (sptwb.ucDataBuf, 4, buffer, bufferIdx, sptwb.ucDataBuf [3]);
                    bufferIdx += sptwb.ucDataBuf [3];
                }

                if (bufferIdx == 0)
                    return null;

                buffer [bufferIdx] = 0;

                Array.Resize<byte> (ref buffer, bufferIdx + 1);

                return buffer;
            }
            finally {
                if (pSptwb != IntPtr.Zero)
                    Marshal.FreeHGlobal (pSptwb);

                if (driveHandle != null)
                    driveHandle.Close ();
            }
        }
Example #11
0
 public static extern bool WriteFile(
     IntPtr hFile,
     System.Text.StringBuilder lpBuffer,
     uint nNumberOfBytesToWrite,
     out uint lpNumberOfBytesWritten,
     [In] ref System.Threading.NativeOverlapped lpOverlapped);
Example #12
0
 public static extern bool UnlockFileEx(SafeFileHandle handle, uint reserved, uint countLow, uint countHigh, ref System.Threading.NativeOverlapped overlapped);
Example #13
0
 public static extern Boolean WriteFile(IntPtr hFile,
                                        Byte[] lpBuffer,
                                        Int32 nNumberOfBytesToWrite,
                                        IntPtr lpNumberOfBytesWritten,
                                        [In] ref System.Threading.NativeOverlapped lpOverlapped);
Example #14
0
 static extern bool ConnectNamedPipe(IntPtr hNamedPipe,
                                     [In] ref System.Threading.NativeOverlapped lpOverlapped);
 public static extern bool WriteFile(SafeFileHandle hFile,                                     // Handle to file
                                     byte[] lpBuffer,                                          // Data buffer
                                     uint nNumberOfBytesToWrite,                               // Number of bytes to write
                                     out uint lpNumberOfBytesWritten,                          // Number of bytes written
                                     [In] ref System.Threading.NativeOverlapped lpOverlapped); // Overlapped buffer
Example #16
0
 public static bool _ConnectNamedPipe(IntPtr hNamedPipe,
                                      [In] ref System.Threading.NativeOverlapped lpOverlapped)
 {
     return(ConnectNamedPipe(hNamedPipe, ref lpOverlapped));
 }
 public static extern bool ReadFile(SafeFileHandle hFile, [Out] IntPtr lpBuffer, uint nNumberOfBytesToRead,
                                    out uint lpNumberOfBytesRead, [In] ref System.Threading.NativeOverlapped lpOverlapped);
Example #18
0
        /// <summary>
        /// 驱动通信的IO控制器方法
        /// </summary>
        /// <param name="hDriver">驱动句柄</param>
        /// <param name="nIoCode">IO控制码</param>
        /// <param name="InBuffer">传入缓冲区</param>
        /// <param name="nInBufferSize">传入缓冲区大小</param>
        /// <param name="OutBuffer">输出缓冲区</param>
        /// <param name="nOutBufferSize">输出缓冲区大小</param>
        /// <param name="pBytesReturned">返回字节数</param>
        /// <param name="Overlapped">输入输出的信息的结构体</param>
        /// <returns>bool</returns>
        public static bool IoControl(SafeFileHandle hDriver, uint nIoCode, object InBuffer, uint nInBufferSize, object OutBuffer, uint nOutBufferSize, ref uint pBytesReturned, ref System.Threading.NativeOverlapped Overlapped)
        {
            const uint FILE_ANY_ACCESS = 0;
            const uint METHOD_BUFFERED = 0;
            bool       bRet;

            nIoCode = ((int)NativeApiEx.DEVICE_TYPE.FILE_DEVICE_UNKNOWN * 65536) | (FILE_ANY_ACCESS * 16384) | (nIoCode * 4) | METHOD_BUFFERED;
            bRet    = NativeApi.DeviceIoControl(hDriver, nIoCode, InBuffer, nInBufferSize, OutBuffer, nOutBufferSize, ref pBytesReturned, ref Overlapped);
            return(bRet);
        }
 public static extern bool GetOverlappedResult(SafeFileHandle hFile,
                                               [In] ref System.Threading.NativeOverlapped lpOverlapped,
                                               out uint lpNumberOfBytesTransferred,
                                               [MarshalAs(UnmanagedType.Bool)] bool bWait);
Example #20
0
 internal static extern int ReadFile(
     IntPtr hFile,
     byte[] lpBuffer,
     UInt32 bytesToRead,
     out UInt32 bytesRead,
     ref System.Threading.NativeOverlapped lpOverlapped);
 public static extern bool WaitCommEvent(SafeFileHandle hFile,
                                         [MarshalAs(UnmanagedType.U4)] out NativeMethods.SerialEventMask lpEvtMask,
                                         ref System.Threading.NativeOverlapped lpOverlapped);
Example #22
0
 internal static extern bool WriteFile(
     SafeFileHandle hFile, byte[] lpBuffer,
     uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten,
     [In] ref System.Threading.NativeOverlapped lpOverlapped);
Example #23
0
 public static extern bool GetOverlappedResult(IntPtr hFile,
                                               ref System.Threading.NativeOverlapped lpOverlapped,
                                               ref uint lpNumberOfBytesTransferred, bool bWait);
Example #24
0
 static internal extern bool WriteFile(IntPtr hFile, IntPtr lpBuffer, uint nNumberOfBytesToWrite,
                                       out uint lpNumberOfBytesWritten, [In] ref System.Threading.NativeOverlapped lpOverlapped);
Example #25
0
 public static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode,
                                           [In] byte[] lpInBuffer, uint nInBufferSize,
                                           byte[] lpOutBuffer, uint nOutBufferSize,
                                           ref uint lpBytesReturned, ref System.Threading.NativeOverlapped lpOverlapped);
Example #26
0
        static void Main(string[] args)
        {
            ManagementScope scope = new ManagementScope(@"\\.\root\CIMv2");
            SelectQuery query = new SelectQuery("SELECT * FROM Win32_DiskDrive");
            List<WritablePhysicalDevice> allDevices = new List<WritablePhysicalDevice>();
            WritablePhysicalDevice myDevice = null;
            bool force = false;
            bool listOnly = false;
            int devNum = -1;
            byte[] imageBytes = null;
            string imageFile = string.Empty;
            UInt64 startingsector = UInt64.MaxValue;
            uint bytesWritten = 0;
            string helpText = HelpText.Print();

            if (helpText.Length < 1)
            {
                Environment.ExitCode = (int)WinErrorCodes.ERROR_RESOURCE_NOT_PRESENT;
                return;
            }

            if (args.Length < 1)
            {
                Console.WriteLine(helpText);
                Environment.ExitCode = (int)WinErrorCodes.ERROR_BAD_ARGUMENTS;
                return;
            }
            foreach (string arg in args)
            {
                string formattedArg = arg.ToLower().Trim();
                if (formattedArg == "force")
                {
                    force = true;
                    continue;
                }
                if (formattedArg == "list")
                {
                    listOnly = true;
                    break;
                }
                if (!formattedArg.Contains("=") || formattedArg.Split('=').Length != 2)
                {
                    Console.WriteLine(helpText);
                    Environment.ExitCode = (int)WinErrorCodes.ERROR_BAD_ARGUMENTS;
                    return;
                }
                if (formattedArg.Split('=')[0] == "image")
                {
                    imageFile = formattedArg.Split('=')[1];
                    if (!File.Exists(imageFile))
                    {
                        Environment.ExitCode = (int)WinErrorCodes.ERROR_INVALID_NAME;
                        Console.WriteLine("Error: The supplied image path does not exist.");
                        return;
                    }
                }
                else if (formattedArg.Split('=')[0] == "device")
                {
                    if (!int.TryParse(formattedArg.Split('=')[1], out devNum))
                    {
                        Environment.ExitCode = (int)WinErrorCodes.ERROR_BAD_ARGUMENTS;
                        Console.WriteLine("Error: Could not validate device number argument.");
                        return;
                    }
                }
                else if (formattedArg.Split('=')[0] == "startingsector")
                {
                    if (!UInt64.TryParse(formattedArg.Split('=')[1], out startingsector))
                    {
                        Environment.ExitCode = (int)WinErrorCodes.ERROR_BAD_ARGUMENTS;
                        Console.WriteLine("Error: Could not validate startingsector argument.");
                        return;
                    }
                }
                else
                {
                    Console.WriteLine(helpText);
                    Environment.ExitCode = (int)WinErrorCodes.ERROR_BAD_ARGUMENTS;
                    Console.WriteLine("Error: Invalid argument.");
                    return;
                }
            }
            if ((devNum < 0 || imageFile.Length < 1) & !listOnly)
            {
                Console.WriteLine(helpText);
                Environment.ExitCode = (int)WinErrorCodes.ERROR_BAD_ARGUMENTS;
                return;
            }

            try
            {
                scope.Connect();
            }
            catch (Exception ex)
            {
                Environment.ExitCode = (int)WinErrorCodes.ERROR_WMI_DP_FAILED;
                Console.WriteLine("Error: " + ex.Message);
                return;
            }

            try
            {
                using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query))
                using (ManagementObjectCollection queryCollection = searcher.Get())
                {
                    foreach (ManagementObject mObject in queryCollection)
                    {
                        // 4 = Supports Writing - Win32_DiskDrive: msdn.microsoft.com/en-us/library/aa394132(v=vs.85).aspx
                        UInt16[] capabilities = (UInt16[])mObject["Capabilities"];
                        if (capabilities.Contains((UInt16)4) & mObject["DeviceID"].ToString().Contains("PHYSICALDRIVE"))
                            allDevices.Add(new WritablePhysicalDevice((string)mObject["DeviceID"], (UInt32)mObject["BytesPerSector"], (UInt64)mObject["TotalSectors"], (UInt64)mObject["Size"]));
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error: " + ex.Message);
                Environment.ExitCode = (int)WinErrorCodes.ERROR_WMI_DP_FAILED;
                return;
            }

            if (listOnly)
            {
                foreach (WritablePhysicalDevice dev in allDevices)
                {
                    Console.WriteLine("\n     DeviceID: " + dev.deviceID);
                    Console.WriteLine(" Bytes/Sector: " + dev.bytesPerSector);
                    Console.WriteLine("Total Sectors: " + dev.totalSectors);
                    Console.WriteLine("   Total Size: " + dev.size);
                }
                return;
            }

            foreach (WritablePhysicalDevice dev in allDevices)
                if (dev.deviceNum == devNum)
                    myDevice = dev;

            if (myDevice == null)
            {
                Environment.ExitCode = (int)WinErrorCodes.ERROR_DEV_NOT_EXIST;
                Console.WriteLine("Error: Device number " + devNum + " does not exist!");
                return;
            }

            if (startingsector > myDevice.totalSectors)
            {
                Environment.ExitCode = (int)WinErrorCodes.ERROR_INVALID_BLOCK;
                Console.WriteLine("Error: Starting sector was greater than drive's total sectors!");
                return;
            }

            if (!force)
            {
                Console.WriteLine("\nPress Y if you are sure you want to write the data in");
                Console.WriteLine(imageFile);
                Console.Write("to " + myDevice.deviceID + " starting at sector " + startingsector + ": ");
                if (Console.ReadKey().Key != ConsoleKey.Y)
                    return;

                Console.WriteLine();
            }

            try
            {
                imageBytes = File.ReadAllBytes(imageFile);
                Console.WriteLine("Read " + imageBytes.Length + " bytes from source image.");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error reading source file: " + ex.Message);
                Environment.ExitCode = (int)WinErrorCodes.ERROR_READ_FAULT;
                return;
            }

            if (imageBytes.Length % myDevice.bytesPerSector != 0)
            {
                Console.WriteLine("The image provided is not a multiple of " + myDevice.bytesPerSector + " bytes.");
                Console.WriteLine("Data will be padded with zeroes to the nearest sector...");
                do
                {
                    byte[] newArray = new byte[imageBytes.Length + 1];
                    imageBytes.CopyTo(newArray, 0);
                    newArray[newArray.Length - 1] = 0;
                    imageBytes = newArray;
                }
                while (imageBytes.Length % myDevice.bytesPerSector != 0);
                Console.WriteLine("Adjusted image size is " + imageBytes.Length + " bytes.");
            }

            if ((ulong)imageBytes.Length > (myDevice.size - (startingsector * myDevice.bytesPerSector)))
            {
                Console.WriteLine("Error: Image is larger than the space available on the drive!");
                Environment.ExitCode = (int)WinErrorCodes.ERROR_FILE_TOO_LARGE;
                return;
            }

            Console.WriteLine("Opening handle to " + myDevice.deviceID + "...");
            try
            {
                using (SafeFileHandle safeHandle = NativeMethods.CreateFile(myDevice.deviceID, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero))
                {
                    if (safeHandle.IsClosed || safeHandle.IsInvalid)
                        throw new Exception("Device handle could not be opened! (Check Administrator privileges.)");

                    Console.WriteLine("Seeking to sector " + startingsector + " (byte " + startingsector * myDevice.bytesPerSector + ")...");
                    unsafe
                    {
                        UInt64 n = 0;
                        IntPtr ptr = new IntPtr(&n);
                        int ret = 0;

                        NativeMethods.SetFilePointerEx(safeHandle, (long)(startingsector * myDevice.bytesPerSector), ptr, NativeMethods.EMoveMethod.Begin);
                        ret = Marshal.GetLastWin32Error();
                        if (ret != 0)
                            throw new Exception("Error during file seek! Win32 code: " + ret);

                        var nativeOverlap = new System.Threading.NativeOverlapped();
                        NativeMethods.WriteFile(safeHandle, imageBytes, (uint)imageBytes.Length, out bytesWritten, ref nativeOverlap);
                        ret = Marshal.GetLastWin32Error();
                        if (ret != 0)
                            throw new Exception("Error during file write! Win32 code: " + ret);

                        Console.WriteLine(bytesWritten + " bytes were written to " + myDevice.deviceID + ".");
                    }
                }
            }
            catch (Exception ex)
            {
                Environment.ExitCode = (int)WinErrorCodes.ERROR_WRITE_FAULT;
                Console.WriteLine("Error: " + ex.Message);
            }
        }
Example #27
0
        private byte [] GetWin32XML(IDevice Ipod)
        {
            IntPtr         pSptwb      = IntPtr.Zero;
            SafeFileHandle driveHandle = null;

            try {
                ScsiPassThroughWithBuffers sptwb;
                int    returned, length;
                string device = GetDeviceFromDrive(((Win32.Device)Ipod).Drive);
                bool   status;

                byte [] buffer    = new byte [102400];
                int     bufferIdx = 0;

                byte page_code, page_start, page_end = 0;

                driveHandle = ApiFunctions.CreateFile(device, AccessMask.GENERIC_ALL,
                                                      System.IO.FileShare.ReadWrite, 0, System.IO.FileMode.Open, 0, IntPtr.Zero);

                if (driveHandle.IsInvalid)
                {
                    throw new FileLoadException("Device invalid");
                }

                sptwb                        = new ScsiPassThroughWithBuffers();
                sptwb.spt.Length             = (ushort)Marshal.SizeOf(typeof(SCSI_PASS_THROUGH));
                sptwb.spt.PathId             = 0;
                sptwb.spt.TargetId           = 1;
                sptwb.spt.Lun                = 0;
                sptwb.spt.CdbLength          = 6;
                sptwb.spt.SenseInfoLength    = 32;
                sptwb.spt.DataIn             = 1; //SCSI_IOCTL_DATA_IN
                sptwb.spt.DataTransferLength = 255;
                sptwb.spt.TimeOutValue       = 2;
                sptwb.spt.DataBufferOffset   = Marshal.OffsetOf(typeof(ScsiPassThroughWithBuffers), "ucDataBuf");
                sptwb.spt.SenseInfoOffset    = Marshal.OffsetOf(typeof(ScsiPassThroughWithBuffers), "ucSenseBuf");
                sptwb.spt.Cdb                = new byte [16];
                sptwb.spt.Cdb [0]            = 0x12; //SCSI_INQUIRY
                sptwb.spt.Cdb [1]           |= 1;
                sptwb.spt.Cdb [2]            = 0xC0;
                sptwb.spt.Cdb [4]            = 255;

                length = Marshal.OffsetOf(typeof(ScsiPassThroughWithBuffers), "ucDataBuf").ToInt32()
                         + (int)sptwb.spt.DataTransferLength;

                pSptwb = Marshal.AllocHGlobal(Marshal.SizeOf(sptwb));
                Marshal.StructureToPtr(sptwb, pSptwb, true);

                System.Threading.NativeOverlapped nativeOverlapped = new System.Threading.NativeOverlapped();
                status = ApiFunctions.DeviceIoControl(driveHandle, DeviceIOControlCode.ScsiPassThrough,
                                                      pSptwb, Marshal.SizeOf(typeof(SCSI_PASS_THROUGH)), pSptwb, length, out returned, ref nativeOverlapped);

                if (!status)
                {
                    throw new FileLoadException("DeviceIoControl Error", Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()));
                }

                sptwb = (ScsiPassThroughWithBuffers)Marshal.PtrToStructure(pSptwb, typeof(ScsiPassThroughWithBuffers));

                page_start = sptwb.ucDataBuf [4];
                page_end   = sptwb.ucDataBuf [3 + sptwb.ucDataBuf [3]];

                for (page_code = page_start; page_code <= page_end; page_code++)
                {
                    sptwb.spt.Length             = (ushort)Marshal.SizeOf(typeof(SCSI_PASS_THROUGH));
                    sptwb.spt.PathId             = 0;
                    sptwb.spt.TargetId           = 1;
                    sptwb.spt.Lun                = 0;
                    sptwb.spt.CdbLength          = 6;
                    sptwb.spt.SenseInfoLength    = 32;
                    sptwb.spt.DataIn             = 1; //SCSI_IOCTL_DATA_IN
                    sptwb.spt.DataTransferLength = 255;
                    sptwb.spt.TimeOutValue       = 2;
                    sptwb.spt.DataBufferOffset   = Marshal.OffsetOf(typeof(ScsiPassThroughWithBuffers), "ucDataBuf");
                    sptwb.spt.SenseInfoOffset    = Marshal.OffsetOf(typeof(ScsiPassThroughWithBuffers), "ucSenseBuf");
                    sptwb.spt.Cdb                = new byte [16];
                    sptwb.spt.Cdb [0]            = 0x12; //SCSI_INQUIRY
                    sptwb.spt.Cdb [1]           |= 1;
                    sptwb.spt.Cdb [2]            = page_code;
                    sptwb.spt.Cdb [4]            = 255;

                    length = Marshal.OffsetOf(typeof(ScsiPassThroughWithBuffers), "ucDataBuf").ToInt32()
                             + (int)sptwb.spt.DataTransferLength;
                    returned = 0;
                    Marshal.StructureToPtr(sptwb, pSptwb, true);
                    status = ApiFunctions.DeviceIoControl(driveHandle, DeviceIOControlCode.ScsiPassThrough,
                                                          pSptwb, Marshal.SizeOf(typeof(SCSI_PASS_THROUGH)), pSptwb, length, out returned, ref nativeOverlapped);

                    if (!status)
                    {
                        throw new FileLoadException("DeviceIoControl Error", Marshal.GetExceptionForHR(Marshal.GetLastWin32Error()));
                    }

                    sptwb = (ScsiPassThroughWithBuffers)Marshal.PtrToStructure(pSptwb, typeof(ScsiPassThroughWithBuffers));

                    while (bufferIdx + sptwb.ucDataBuf [3] > buffer.Length)
                    {
                        Array.Resize <byte> (ref buffer, buffer.Length * 2);
                    }

                    Array.Copy(sptwb.ucDataBuf, 4, buffer, bufferIdx, sptwb.ucDataBuf [3]);
                    bufferIdx += sptwb.ucDataBuf [3];
                }

                if (bufferIdx == 0)
                {
                    return(null);
                }

                buffer [bufferIdx] = 0;

                Array.Resize <byte> (ref buffer, bufferIdx + 1);

                return(buffer);
            }
            finally {
                if (pSptwb != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pSptwb);
                }

                if (driveHandle != null)
                {
                    driveHandle.Close();
                }
            }
        }