P/Invoke 呼び出しを使用して C: ドライブのルートを読み取ることから始めて、MFT をいじっています。以下のコードを使用すると、バッファー サイズが 512 の倍数の場合は期待どおりの結果が得られますが、それ以外の場合は読み取りが ERROR_INVALID_PARAMETER で失敗します。これはクラスターサイズと関係がありますか? クラスタ サイズが 4k バイトであるため、これはありそうにありません。明らかに、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;
}
}