无法使用ReadFile函数读取物理磁盘

3

我可以使用ReadFile读取简单的文本文件,但是无法正确地使用它来读取物理驱动器。从GetLastError返回错误信息“参数不正确”。以下是我的代码以及提供的更多信息:

using System;
using System.Runtime.InteropServices;

namespace ReadFileTest
{
class Program
{
    [DllImport("kernel32.dll")]
    static extern unsafe uint GetLastError();

    [DllImport("kernel32", SetLastError = true)]
    static extern unsafe System.IntPtr CreateFile
    (
        string FileName,          // file name
        uint DesiredAccess,       // access mode
        uint ShareMode,           // share mode
        uint SecurityAttributes,  // Security Attributes
        uint CreationDisposition, // how to create
        uint FlagsAndAttributes,  // file attributes
        int hTemplateFile         // handle to template file
    );

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern unsafe bool ReadFile
    (
        IntPtr hFile, 
        [Out] byte[] lpBuffer,
        uint nNumberOfBytesToRead, 
        out uint lpNumberOfBytesRead, 
        IntPtr lpOverlapped
    );

    const uint GENERIC_READ = 0x80000000;
    const uint GENERIC_WRITE = 0x050000000;
    const uint GENERIC_ALL = 0x10000000;
    const uint FILE_SHARE_READ = 1;
    const uint FILE_SHARE_WRITE = 2;

    const uint OPEN_EXISTING = 3;
    const int INVALID_HANDLE_VALUE = -1;

    static void Main(string[] args)
    {
        unsafe 
        {
            // Reading a simple text file works perfectly:
            //IntPtr handle = CreateFile("D:\\Test.txt", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);

            // CreateFile of a physical drive gives me a valid handle.
            // But when attempting to read the drive, (all of my drives give the same result), I get the error "The parameter is incorrect."
            IntPtr handle = CreateFile(@"\\.\PHYSICALDRIVE2", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);

            // GetLastError returns this:
            // ERROR_INVALID_PARAMETER87 (0x57)
            // The parameter is incorrect.

            byte[] b = { 1, 2, 3, 4, 5 };
            uint n = 1;

            while (n != 0)
            {
                bool ret = ReadFile(handle, b, (uint)5, out n, (IntPtr)0);
                uint e = GetLastError();
            }

        }
    }
}
}

// I have unmounted the physical drive and run the test with the same results.
// I tried using pointers for the parameters, same result.
// I tried different variations of options for CreateFile.
// Don't know which parameter is giving the error.

你是否正在以管理员权限运行?(我记得普通用户无法直接读取设备。) - Richard
顺便提一下:您应该使用GetLastWin32Error而不是直接使用PInvoke的GetLastError?(不确定为什么您要显示调用GetLastError,因为它会使示例变得更长)。 - Alexei Levenkov
1
此外,您没有检查ReadFile的结果:成功的API调用并不总是清除错误值。 - Richard
1个回答

3
我相信在从原始设备读取时,5 是无效的读取大小 - 应该对齐到某个块大小。例如 0x1000 更有可能成功。
请仔细阅读 ReadFile 文档。如果你真的要深入探索低级API,请考虑阅读《Windows Internals》系列之一。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接