You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

读取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;
}

问题原因分析

  1. 未验证读取字节数:ReadFile返回成功仅表示读取操作完成,但不保证读取了请求的512字节。如果实际读取的bytesRead小于512,sector数组中未被填充的部分会保留随机垃圾数据,两次读取的垃圾数据不同,导致BPB解析结果不一致。
  2. 文件指针操作未做错误检查:SetFilePointer可能执行失败(比如偏移量无效),但代码未检查其返回值,会导致后续读取位置错误,读取到错误的数据。
  3. 偏移量类型限制: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 00:05:25