我正在玩MFT,首先使用P / Invoke调用读取我的C:驱动器的根目录。使用下面的代码,如果缓冲区大小是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;
}
}
答案 0 :(得分:4)
对于直接卷访问,您必须以扇区长度的倍数读取和写入,并从对齐的偏移量开始。也就是说,该位置必须是扇区长度的倍数。
您需要查询卷以查找扇区长度。为此,请使用GetDiskFreeSpace
或IOCTL_DISK_GET_DRIVE_GEOMETRY_EX
。
我看到您正在请求写入权限并在本地C盘上运行。你确定这是明智的吗?一个滑动,你已经冲洗了你的系统。也许在虚拟机或卷中工作,您会乐于失去。