Считывание корневого тома NTFS не выполняется, если размер буфера не кратен 512

Я играю с MFT, начиная с чтения корня диска C: с помощью вызовов P/Invoke. Используя приведенный ниже код, я получаю ожидаемые результаты, если размер буфера кратен 512, но в противном случае чтение завершается ошибкой с ERROR_INVALID_PARAMETER. Это связано с размером кластера? Это кажется маловероятным, так как у меня размер кластера 4 Кбайт. Очевидно, я мог бы просто использовать кратное 512, но мне кажется, что это может быть не переносимым, и, конечно, я хотел бы понять, почему это так.

    public void Test()
    {
        string driveRoot = @"\\.\" + "C:";

        IntPtr hRoot = MFT.CreateFile(
            driveRoot,
            MFT.GENERIC_READ | MFT.GENERIC_WRITE,
            MFT.FILE_SHARE_READ | MFT.FILE_SHARE_WRITE,
            IntPtr.Zero,
            MFT.OPEN_EXISTING,
            MFT.FILE_ATTRIBUTE_NORMAL,
            IntPtr.Zero);

        if (hRoot.ToInt32() == MFT.INVALID_HANDLE_VALUE)
            throw new IOException(string.Format("CreateFile() returned invalid handle [Win32 error {0}]", Marshal.GetLastWin32Error()));

        // TODO why does this fail unless buffer size is a multiple of 512? Is it to do with cluster size?
        UInt32 numBytesToRead = 512;
        byte[] buffer = new byte[numBytesToRead];
        if (ReadFileFromHandleSync(hRoot, buffer, numBytesToRead))
            Debug.WriteLine("OK " + i);
    }


    public bool ReadFileFromHandleSync(IntPtr handle, byte[] buffer, UInt32 numBytesToRead)
    {
        UInt32 numBytesRead;

        NativeOverlapped overlapped = new NativeOverlapped();

        bool readOK = ReadFile(handle, buffer, numBytesToRead, out numBytesRead, ref overlapped);

        return readOK;
    }
}

1 ответ

Решение

Для прямого доступа к объему вы должны читать и писать кратно длине сектора и начиная с выровненных смещений. То есть позиция должна быть кратна длине сектора.

Вы хотите запросить объем, чтобы узнать длину сектора. использование GetDiskFreeSpace или же IOCTL_DISK_GET_DRIVE_GEOMETRY_EX за это.

Я вижу, что вы запрашиваете доступ для записи и работаете на локальном диске C. Вы уверены, что это разумно? Один промах, и вы подключили свою систему. Возможно, работа в виртуальной машине или томе, который вы бы с удовольствием потеряли.

Другие вопросы по тегам