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_OVERFLOW或STATUS_BUFFER_TOO_SMALL错误,说明缓冲区不够用了,这时候可以要么增大缓冲区,要么多次调用NtQueryDirectoryFile,通过FileName参数指定上次读到的最后一个文件名来分批读取——不过对于\Windows目录来说,你现在的缓冲区大小应该完全够用了。
内容的提问来源于stack exchange,提问作者SlayerBae




