【问题标题】:CreateFile on Directory in NTFS fails on ReadFile在 NTFS 中的目录上的 CreateFile 在 ReadFile 上失败
【发布时间】:2017-07-28 11:47:39
【问题描述】:

据说可以实际打开和读取 NTFS 卷上的目录。但是,我尝试这个的代码不起作用,所以我尝试了谷歌,它找到了我 this

关键的观察似乎是您必须使用 FILE_FLAG_BACKUP_SEMANTICS。所以,减少它,我基本上得到:

HANDLE hFile = CreateFile(L"C:\\temp", GENERIC_READ, FILE_SHARE_READ,
    0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);

DWORD dwFileSize = GetFileSize(hFile, 0);
char* buf = new char[dwFileSize];

DWORD dwBytesRead = 0;
BOOL b = ReadFile(hFile, buf, dwFileSize, &dwBytesRead, 0);

看起来很简单。不幸的是,它不起作用。

CreateFileGetFileSize 都可以工作(句柄不是 INVALID_HANDLE_VALUE,非零且文件大小合理),但 ReadFile 返回 FALSE,dwBytesRead 为零,GetLastError 返回 1(“函数不正确”) .呵呵。

当我输入这个问题时,“类似问题”提示向我显示了this。关于使用AdjustTokenPrivileges 的业务非常有意义。然而,它没有帮助。在该示例中添加 ReadFile(并使用 c:\temp)会产生相同的行为。仔细阅读CreateFile docs 表明,即使没有 SE_BACKUP_NAME 权限,由于管理员权限,我也应该能够打开文件。

我尝试了多种排列方式:

  • 指定目录名称的不同方式(c:\tempc:\temp\\\.\c:\temp\\?\c:\temp\ 等)。
  • 不同的目录
  • 不同的驱动器
  • 不同的共享选项(0、FILE_SHARE_READ、FILE_SHARE_READ | FILE_SHARE_WRITE)
  • 不同的访问权限(GENERIC_READFILE_LIST_DIRECTORYFILE_LIST_DIRECTORY + FILE_READ_EA + FILE_READ_ATTRIBUTESFILE_LIST_DIRECTORY + FILE_READ_EA + FILE_READ_ATTRIBUTES + FILE_TRAVERSE
  • 除了 FILE_FLAG_BACKUP_SEMANTICS(我认为这是必需的)之外,我看不到任何可能适用的标志,但我尝试了 FILE_FLAG_NO_BUFFERING 和 4096 字节对齐的缓冲区。没有。

我(目前)尝试了 152 种排列,但没有一个 ReadFiles 工作。我错过了什么?

我原来的假设不正确吗?真的不可能从目录中“读取”吗?还是只是我仍然缺少一些技巧?

我还应该提到什么?

  • 我以管理员身份运行,可以对卷执行 CreateFile。
  • 我的程序是 64 位,专为 unicode 构建的。
  • Windows 7 x64
  • NTFS 3.1 卷
  • 外面多云(嘿,你永远不知道什么是重要的......)

【问题讨论】:

  • 你可以打开一个目录的句柄来做某些事情,但调用ReadFile不是其中之一。
  • msdn.microsoft.com/en-us/library/windows/desktop/… 有一个函数列表,您可以将目录句柄传递给这些函数。
  • 您希望从目录中读取什么内容?文件列表?
  • 这个问题的目标是能够对目录执行 ReadFile。答案似乎很明确:你不能。如果要读取目录的原始 $INDEX_ALLOCATION 数据,则需要以另一种方式进行(我已经开始编写)。 @JonathanPotter 如果您想发布您的 cmets 作为答案,我会接受。
  • 文件系统驱动程序(也包括 ntfs)总是在 IRP_MJ_READ 请求目录文件时返回错误代码。通常是STATUS_INVALID_DEVICE_REQUESTSTATUS_INVALID_PARAMETER

标签: windows winapi directory ntfs-mft


【解决方案1】:

如果您想打开流,则需要在路径中包含流名称和/或类型:

  • c:\foo:bar A.K.A. c:\foo:bar:$DATA
  • c:\foo::$INDEX_ALLOCATION

如果您不指定流,则使用默认的 $DATA 流。 $DATA 存储文件“普通数据”。

如果您想要目录中的文件列表,则可以使用GetFileInformationByHandleEx(FileIdBothDirectoryInfo)(在旧系统上使用NtQueryDirectoryFile)。

【讨论】:

  • 我假设您的意思是 INDEX_ALLOCATION。但是没关系,因为 ReadFile 对两者都失败了。因此,即使您忽略文档说 so "DirName"、"DirName::$INDEX_ALLOCATION" 和 "DirName:$I30:$INDEX_ALLOCATION" 都是等价的。,我认为这里的答案是乔纳森所说的:ReadFile 只是目录的禁忌
  • dir C:\Windows:$I30:$INDEX_ALLOCATION 对我有用,您可以调试 cmd.exe 并查看它的作用。您当然有可能无法使用 ReadFile,即使可以,二进制格式也可能没有记录。
  • “您可以调试 cmd.exe 并查看它的作用”我不确定这会告诉我什么。是的,这行得通,但它并不像它需要做一个 ReadFile 才能成功。它可能只是执行 Harry 提到的 GetFileInformationByHandleEx。至于文档,MS 可能没有任何内容。但是有一些讨论 herethere 谈论它。
【解决方案2】:

看起来 Jonathan Potter 给出了正确答案。尽管有提示,他还是选择不发布他的 cmets 作为答案。因此,我将根据他的回答创建一个以结束问题。

简而言之:“您可以打开目录句柄来执行某些操作,但在其上调用 ReadFile 不是其中之一。”

什么东西? These things。此列表包括:

  • BackupRead
  • BackupSeek
  • 备份写入
  • GetFileInformationByHandle
  • 获取文件大小
  • 获取文件时间
  • 获取文件类型
  • ReadDirectoryChangesW
  • 设置文件时间

总而言之:虽然您可以“打开”目录并“读取”有关它们的某些信息,但实际上不能使用 ReadFile。如果您想阅读 DirName::$INDEX_ALLOCATION 信息,则必须使用不同的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-19
    • 2017-11-09
    • 2015-04-07
    • 2018-06-15
    • 2012-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多