读取NTFS分区同一扇区两次结果不同,原因何在?
读取NTFS分区同一扇区两次结果不一致的问题
我尝试读取NTFS分区的第0扇区,编写了如下代码,但两次读取同一扇区后打印的BPB结果却不同。我猜测这与WinAPI的CreateFile、ReadFile有关,但无法理解具体原因。结果截图显示两次输出的BPB参数存在明显差异。
主函数
int main(int argc, char** argv) { BYTE sector[512]; ReadSector(L"\\\\.\\E:", 0, sector); PrintBPB(ReadBPB(sector)); BYTE sector2[512]; ReadSector(L"\\\\.\\E:", 0, sector2); PrintBPB(ReadBPB(sector2)); return 0; }
ReadSector函数
#define Sector_Size 512 int ReadSector(LPCWSTR drive, long readPoint, BYTE sector[Sector_Size]) { int retCode = 0; DWORD bytesRead; HANDLE device = NULL; device = CreateFile(drive, // 要打开的驱动器 GENERIC_READ, // 访问模式 FILE_SHARE_READ | FILE_SHARE_WRITE, // 共享模式 NULL, // 安全描述符 OPEN_EXISTING, // 创建方式 0, // 文件属性 NULL); // 模板文件句柄 if (device == INVALID_HANDLE_VALUE) // 打开失败 { printf("CreateFile: %u\n", GetLastError()); return 1; } SetFilePointer(device, readPoint, NULL, FILE_BEGIN);// 设置读取位置 if (!ReadFile(device, sector, 512, &bytesRead, NULL)) { printf("ReadFile: %u\n", GetLastError()); } else { printf("Success!\n"); } CloseHandle(device); return retCode; }
问题原因分析
- 未验证读取字节数:
ReadFile返回成功仅表示读取操作完成,但不保证读取了请求的512字节。如果实际读取的bytesRead小于512,sector数组中未被填充的部分会保留随机垃圾数据,两次读取的垃圾数据不同,导致BPB解析结果不一致。 - 文件指针操作未做错误检查:
SetFilePointer可能执行失败(比如偏移量无效),但代码未检查其返回值,会导致后续读取位置错误,读取到错误的数据。 - 偏移量类型限制:
readPoint使用long类型(32位),对于超过2GB的磁盘,偏移量会溢出,虽读取第0扇区暂时不会触发,但属于潜在问题。
修复方案
修改ReadSector函数,补充错误检查和完整字节数验证:
#define Sector_Size 512 int ReadSector(LPCWSTR drive, LONGLONG readPoint, BYTE sector[Sector_Size]) { DWORD bytesRead; HANDLE device = NULL; // 打开设备时添加FILE_FLAG_NO_BUFFERING避免缓存干扰,需确保缓冲区对齐(这里sector是512字节符合要求) device = CreateFile(drive, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_RANDOM_ACCESS, NULL); if (device == INVALID_HANDLE_VALUE) { printf("CreateFile: %u\n", GetLastError()); return 1; } // 使用SetFilePointerEx支持64位偏移量,并检查返回值 LARGE_INTEGER offset; offset.QuadPart = readPoint; if (!SetFilePointerEx(device, offset, NULL, FILE_BEGIN)) { printf("SetFilePointerEx: %u\n", GetLastError()); CloseHandle(device); return 1; } if (!ReadFile(device, sector, Sector_Size, &bytesRead, NULL)) { printf("ReadFile: %u\n", GetLastError()); CloseHandle(device); return 1; } // 验证是否读取了完整的扇区 if (bytesRead != Sector_Size) { printf("Read incomplete: only %u bytes read\n", bytesRead); CloseHandle(device); return 1; } printf("Success!\n"); CloseHandle(device); return 0; }
同时,主函数中调用时的偏移量要改成(LONGLONG)0:
ReadSector(L"\\\\.\\E:", (LONGLONG)0, sector);
内容的提问来源于stack exchange,提问作者Gula
相关产品推荐
相关产品推荐

