You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Windows内核中ZwQueryDirectoryFile仅返回'.'目录项的问题求助

问题排查与修复方案

嘿,我一眼就揪出了问题的核心——你调用NtQueryDirectoryFile时设置了**ReturnSingleEntry = TRUE**,这个参数会强制函数只返回单个目录条目(也就是当前目录.),哪怕你的缓冲区足够装下一堆内容!

关键参数错误解析

看你这段NtQueryDirectoryFile的调用代码:

Status = NtQueryDirectoryFile(
    DirectoryHandle,
    0,
    0,
    0,
    &IoStatusBlock,
    DirInformation,
    sizeof(FILE_BOTH_DIR_INFORMATION) * 512,
    FileBothDirectoryInformation,
    TRUE,  // 这里就是罪魁祸首!
    0,
    0);

根据Windows内核文档,当ReturnSingleEntry设为TRUE时,函数读完第一个条目就会立刻返回,不会继续读取目录里的其他文件和子目录。这就是为什么你只拿到了.这一个结果。

其他细节确认

好在其他部分的代码没什么大问题:

  • 你给ZwCreateFile指定的FILE_LIST_DIRECTORY | SYNCHRONIZE权限完全正确,是枚举目录内容的必要权限;
  • 分配的sizeof(FILE_BOTH_DIR_INFORMATION)*512非分页池缓冲区大小足够,\Windows目录的条目数量用这个缓冲区完全能装下;
  • 你通过NextEntryOffset遍历条目的逻辑也是对的,只要修正上面的参数,就能正常遍历所有内容。

修正后的代码

ReturnSingleEntry改成FALSE就行,其他参数保持不变:

Status = NtQueryDirectoryFile(
    DirectoryHandle,
    0,
    0,
    0,
    &IoStatusBlock,
    DirInformation,
    sizeof(FILE_BOTH_DIR_INFORMATION) * 512,
    FileBothDirectoryInformation,
    FALSE,  // 改这里!允许返回多个条目
    0,
    0);

另外别忘了在循环结束后释放你分配的池内存,避免内存泄漏:

ExFreePool(DirInformation);

额外小提示

如果之后遇到STATUS_BUFFER_OVERFLOWSTATUS_BUFFER_TOO_SMALL错误,说明缓冲区不够用了,这时候可以要么增大缓冲区,要么多次调用NtQueryDirectoryFile,通过FileName参数指定上次读到的最后一个文件名来分批读取——不过对于\Windows目录来说,你现在的缓冲区大小应该完全够用了。

内容的提问来源于stack exchange,提问作者SlayerBae

火山引擎 最新活动