直接访问物理cdrom设备

时间:2012-11-16 18:55:52

标签: c# winapi device

Iam尝试访问物理cdrom设备以检查它是否可引导,因此我需要从中读取字节。我尝试了以下两种方法,但没有运气:

方法A:

FileStream stream = new FileStream(H:, FileMode.Open);

但我在H:上获得了拒绝访问权限。我知道我可以访问。

方法B:     通过Pinvoke

  IntPtr handle = CreateFile(source, FileAccess.Read, FileShare.ReadWrite, 0, FileMode.Open, 0, IntPtr.Zero);
            binReader = new BinaryReader(new FileStream(handle, FileAccess.Read,true));

但我明白了:

FileStream不会打开Win32设备,例如磁盘分区和磁带驱动器。 避免在路径中使用“\。\”。

有没有办法在c#中完成我想要的东西?

非常感谢

1 个答案:

答案 0 :(得分:1)

好吧......问题是DVD和CD之间的区别......显然我们不能这样读DVD ......但是你走了......

using System;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using System.ComponentModel;

namespace cdDvdAccess
{
    public class Program
    {

        //some interesting IOCTLs
        public const uint IOCTL_CDROM_READ_TOC = 0x00024000;
        public const uint IOCTL_CDROM_RAW_READ = 0x0002403E;
        public const uint IOCTL_STORAGE_EJECT_MEDIA = 0x002D4808;
        public const uint IOCTL_STORAGE_LOAD_MEDIA = 0x002D480C;


        // P/Invoke signatures
        [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool DeviceIoControl(
                SafeFileHandle hDevice,
                uint dwIoControlCode,
                IntPtr InBuffer, // arbitrary buffer
                int nInBufferSize,
                IntPtr OutBuffer,
                int nOutBufferSize,
                ref int pBytesReturned,
                IntPtr lpOverlapped);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool DeviceIoControl(
                SafeFileHandle hDevice,
                uint dwIoControlCode,
                ref RAW_READ_INFO InBuffer, // with RAW_READ_INFO
                int nInBufferSize,
                IntPtr OutBuffer,
                int nOutBufferSize,
                ref int pBytesReturned,
                IntPtr lpOverlapped);

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        private static extern SafeFileHandle CreateFile(
           string lpFileName,
           EFileAccess dwDesiredAccess,
           EFileShare dwShareMode,
           IntPtr lpSecurityAttributes,
           ECreationDisposition dwCreationDisposition,
           EFileAttributes dwFlagsAndAttributes,
           IntPtr hTemplateFile);

        [Flags]
        public enum EFileAccess : uint
        {
            //
            // Standart Section
            //

            AccessSystemSecurity = 0x1000000,   // AccessSystemAcl access type
            MaximumAllowed = 0x2000000,     // MaximumAllowed access type

            Delete = 0x10000,
            ReadControl = 0x20000,
            WriteDAC = 0x40000,
            WriteOwner = 0x80000,
            Synchronize = 0x100000,

            StandardRightsRequired = 0xF0000,
            StandardRightsRead = ReadControl,
            StandardRightsWrite = ReadControl,
            StandardRightsExecute = ReadControl,
            StandardRightsAll = 0x1F0000,
            SpecificRightsAll = 0xFFFF,

            FILE_READ_DATA = 0x0001,        // file & pipe
            FILE_LIST_DIRECTORY = 0x0001,       // directory
            FILE_WRITE_DATA = 0x0002,       // file & pipe
            FILE_ADD_FILE = 0x0002,         // directory
            FILE_APPEND_DATA = 0x0004,      // file
            FILE_ADD_SUBDIRECTORY = 0x0004,     // directory
            FILE_CREATE_PIPE_INSTANCE = 0x0004, // named pipe
            FILE_READ_EA = 0x0008,          // file & directory
            FILE_WRITE_EA = 0x0010,         // file & directory
            FILE_EXECUTE = 0x0020,          // file
            FILE_TRAVERSE = 0x0020,         // directory
            FILE_DELETE_CHILD = 0x0040,     // directory
            FILE_READ_ATTRIBUTES = 0x0080,      // all
            FILE_WRITE_ATTRIBUTES = 0x0100,     // all

            //
            // Generic Section
            //

            GenericRead = 0x80000000,
            GenericWrite = 0x40000000,
            GenericExecute = 0x20000000,
            GenericAll = 0x10000000,

            SPECIFIC_RIGHTS_ALL = 0x00FFFF,
            FILE_ALL_ACCESS =
            StandardRightsRequired |
            Synchronize |
            0x1FF,

            FILE_GENERIC_READ =
            StandardRightsRead |
            FILE_READ_DATA |
            FILE_READ_ATTRIBUTES |
            FILE_READ_EA |
            Synchronize,

            FILE_GENERIC_WRITE =
            StandardRightsWrite |
            FILE_WRITE_DATA |
            FILE_WRITE_ATTRIBUTES |
            FILE_WRITE_EA |
            FILE_APPEND_DATA |
            Synchronize,

            FILE_GENERIC_EXECUTE =
            StandardRightsExecute |
              FILE_READ_ATTRIBUTES |
              FILE_EXECUTE |
              Synchronize
        }

        [Flags]
        public enum EFileShare : uint
        {
            /// <summary>
            ///
            /// </summary>
            None = 0x00000000,
            /// <summary>
            /// Enables subsequent open operations on an object to request read access.
            /// Otherwise, other processes cannot open the object if they request read access.
            /// If this flag is not specified, but the object has been opened for read access, the function fails.
            /// </summary>
            Read = 0x00000001,
            /// <summary>
            /// Enables subsequent open operations on an object to request write access.
            /// Otherwise, other processes cannot open the object if they request write access.
            /// If this flag is not specified, but the object has been opened for write access, the function fails.
            /// </summary>
            Write = 0x00000002,
            /// <summary>
            /// Enables subsequent open operations on an object to request delete access.
            /// Otherwise, other processes cannot open the object if they request delete access.
            /// If this flag is not specified, but the object has been opened for delete access, the function fails.
            /// </summary>
            Delete = 0x00000004
        }

        public enum ECreationDisposition : uint
        {
            /// <summary>
            /// Creates a new file. The function fails if a specified file exists.
            /// </summary>
            New = 1,
            /// <summary>
            /// Creates a new file, always.
            /// If a file exists, the function overwrites the file, clears the existing attributes, combines the specified file attributes,
            /// and flags with FILE_ATTRIBUTE_ARCHIVE, but does not set the security descriptor that the SECURITY_ATTRIBUTES structure specifies.
            /// </summary>
            CreateAlways = 2,
            /// <summary>
            /// Opens a file. The function fails if the file does not exist.
            /// </summary>
            OpenExisting = 3,
            /// <summary>
            /// Opens a file, always.
            /// If a file does not exist, the function creates a file as if dwCreationDisposition is CREATE_NEW.
            /// </summary>
            OpenAlways = 4,
            /// <summary>
            /// Opens a file and truncates it so that its size is 0 (zero) bytes. The function fails if the file does not exist.
            /// The calling process must open the file with the GENERIC_WRITE access right.
            /// </summary>
            TruncateExisting = 5
        }

        [Flags]
        public enum EFileAttributes : uint
        {
            Readonly = 0x00000001,
            Hidden = 0x00000002,
            System = 0x00000004,
            Directory = 0x00000010,
            Archive = 0x00000020,
            Device = 0x00000040,
            Normal = 0x00000080,
            Temporary = 0x00000100,
            SparseFile = 0x00000200,
            ReparsePoint = 0x00000400,
            Compressed = 0x00000800,
            Offline = 0x00001000,
            NotContentIndexed = 0x00002000,
            Encrypted = 0x00004000,
            Write_Through = 0x80000000,
            Overlapped = 0x40000000,
            NoBuffering = 0x20000000,
            RandomAccess = 0x10000000,
            SequentialScan = 0x08000000,
            DeleteOnClose = 0x04000000,
            BackupSemantics = 0x02000000,
            PosixSemantics = 0x01000000,
            OpenReparsePoint = 0x00200000,
            OpenNoRecall = 0x00100000,
            FirstPipeInstance = 0x00080000
        }

        public enum TRACK_MODE_TYPE
        {
            YellowMode2 = 0,
            XAForm2 = 1,
            CDDA = 2,
            RawWithC2AndSubCode = 3,
            RawWithC2 = 4,
            RawWithSubCode = 5
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct RAW_READ_INFO
        {
            public long DiskOffset;
            public uint SectorCount;
            public TRACK_MODE_TYPE TrackMode;

        }

        static void Main(string[] args)
        {
            Byte[] data; // a variable to hold our desired data...
            Win32Exception ex, ex2; //see using block below
            int outputBufferSize = 4096000;//just some buffer ... way to big, but hey ...
            var unmanagedOutputBuffer = Marshal.AllocHGlobal(outputBufferSize); // Marshal will give us an unmanaged buffer of desired size ... hopefully
            RAW_READ_INFO ri = new RAW_READ_INFO { DiskOffset = 0, SectorCount = 20, TrackMode = TRACK_MODE_TYPE.YellowMode2 }; // what do we want to read?
            var ri_size = Marshal.SizeOf(ri); // since we are giving ri to an unmanaged function, we need to tell that function the size of ri
            int bytesReturned = 0; // if everything works as expected, we will get something written in our unmanaged buffer ... here we can store how many bytes were written
            using (var hDev = CreateFile(@"\\.\H:", EFileAccess.GenericRead, EFileShare.Read | EFileShare.Write, IntPtr.Zero, ECreationDisposition.OpenExisting, EFileAttributes.Normal, IntPtr.Zero))
            {// since we are working with a handle, we have to make sure we release it after we are done ... "using" does that for us
                ex = new Win32Exception();//will tell you if CreateFile worked 
                var b = DeviceIoControl(hDev, IOCTL_CDROM_RAW_READ, ref ri, ri_size, unmanagedOutputBuffer, outputBufferSize, ref bytesReturned, IntPtr.Zero); // the magic happens here
                ex2 = new Win32Exception();//will tell you if DeviceIoControl worked
            }

            if (bytesReturned > 0)
            {
                data = new byte[bytesReturned]; //this time, a managed buffer to hold our data
                Marshal.Copy(unmanagedOutputBuffer, data, 0, bytesReturned); // copy from unmanaged buffer to managed buffer (from the land of dragons and monsters into the .net world)
            }
            Marshal.FreeHGlobal(unmanagedOutputBuffer);//release the unmanaged buffer

            // if everything worked as expected you should now have the first 20 sectors of a ordinary CD-Rom (Yellow Book - Mode 2) in the data array ...

        }
    }
}