由Pinvoke在c#中读取DVD的特定扇区

本文关键字:扇区 DVD 读取 Pinvoke | 更新日期: 2023-09-27 18:13:08

我使用c#直接从磁盘读取并调用kernel32 ReadFile方法。我只是想读一个特定的扇区,以节省时间,但ReadFile从第一个读取到N扇区。怎么能用我的选择只读自己的扇区?

    [StructLayout(LayoutKind.Sequential)]
    public struct OVERLAPPED
    {
        public uint Internal;
        public uint InternalHigh;
        public uint Offset;
        public uint OffsetHigh;
        public int hEvent;
    }
    [DllImport("kernel32", SetLastError = true)]
    static extern int CreateFile(string filename, uint desiredAccess, uint shareMode, IntPtr attributes, uint creationDisposition, uint flagsAndAttributes, IntPtr templateFile);
    [DllImport("kernel32", SetLastError = true)]
    public static extern Boolean CloseHandle(int handle);
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern Boolean ReadFile(IntPtr hFile, Byte[] buffer, UInt32 BytesToRead, ref UInt32 BytedRead, OVERLAPPED OverLapped);
    static int EIGHT_K = 8192;
    static int FIVE_TWELVE_BYTES = 512;
    static uint GENERIC_READ = 0x80000000;
    static uint OPEN_EXISTING = 3;
    static uint FILE_SHARE_READ = 1;
    static uint FILE_SHARE_WRITE = 2;
    [STAThread]
    private void button1_Click(object sender, EventArgs e)
    {
        int fileHandle = 0;
        bool returnVal = true;
        try
        {
            // Open the device specified (Using the boot partition)
            string deviceName = @"''.'f:";
            fileHandle = CreateFile(deviceName, GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE, (IntPtr)0, OPEN_EXISTING, 0,(IntPtr)0);
            if (fileHandle != -1)
            {
                Byte[] sector = new Byte[EIGHT_K];
                UInt32 bytesRead = (uint)EIGHT_K;
                OVERLAPPED ol = new OVERLAPPED();
                // Can't get a FileStream ctor to work so I am using Win32 API ReadFile
                bool worked = ReadFile((IntPtr)fileHandle, sector, (uint)EIGHT_K, ref bytesRead, ol);
                return;
            }
        }
        catch (Exception ex)
        {
            return;
        }
        finally
        {
            CloseHandle(fileHandle);
        }
        return;
    }

我想把DVD标记为需要原始DVD才能运行程序。

由Pinvoke在c#中读取DVD的特定扇区

您的OVERLAPPED结构声明不佳,并且在64位进程中不正确。但无论如何你都不需要它。您没有执行重叠的I/O。这也无妨,因为ReadFile的申报是不正确的。该函数需要一个指向OVERLAPPED结构体的指针。按值传递

在任何情况下,您都不需要考虑重叠的I/O。因此,通过从代码中删除OVERLAPPED结构声明来修复此问题。然后像这样声明ReadFile:
[DllImport("kernel32.dll", SetLastError = true)]
public static extern Boolean ReadFile(IntPtr hFile, Byte[] buffer, 
    UInt32 BytesToRead, out UInt32 BytedRead, IntPtr Overlapped);

IntPtr.Zero作为Overlapped参数。并且一定要检查ReadFile的返回值是否有错误。

下一步是查找文件中的一个位置。使用SetFilePointerEx

DllImport("kernel32.dll")]
static extern bool SetFilePointerEx(IntPtr hFile, long liDistanceToMove,
   out long lpNewFilePointer, uint dwMoveMethod);

查阅SetFilePointerEx的文档,了解如何调用这个函数。

由于您使用的是直接磁盘访问,您当然需要将读取与扇区边界对齐。