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#中完成我想要的东西?
非常感谢
答案 0 :(得分:1)
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 ...
}
}
}