如何使用GetFileInformationByHandleEx读取junction point目录中的文件
问题原因与解决方案
核心问题根源
- 你添加
FILE_FLAG_OPEN_REPARSE_POINT标志的操作不符合需求:该标志的作用是让CreateFile直接打开重解析点(junction point)本身,而不会跟随重解析指向它映射的目标目录。此时你拿到的句柄对应的是存储重解析配置数据的特殊对象,不是实际的文件目录,自然只能读取到.和..两个默认条目,无法获取目标目录下的真实文件列表。 - 最初未加该标志时返回
ERROR_INVALID_PARAMETER(错误码0x57),是因为FileIdInfo、FileIdExtdDirectoryInfo这两类信息查询,对跨卷重解析得到的目录句柄兼容性较差,部分Windows版本下直接对重解析后的目录句柄调用会参数校验失败。
修复方案
步骤1:还原CreateFile调用
去掉FILE_FLAG_OPEN_REPARSE_POINT标志,保证CreateFile自动跟随重解析打开实际的目标目录:
auto h = CreateFile(path, FILE_LIST_DIRECTORY, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
步骤2:调整查询逻辑
两种可选方案,根据你的需求选择:
- 如果仅需要遍历目录内容,优先使用兼容性更好的
FileDirectoryInfo代替FileIdExtdDirectoryInfo,不需要额外修改其他逻辑即可正常遍历junction映射的目录内容。 - 如果必须获取文件ID信息,先通过
GetFinalPathNameByHandleW获取重解析指向的实际目录路径,再重新打开该实际路径得到新句柄,用新句柄调用GetFileInformationByHandleEx查询FileId相关信息即可避免参数错误。
修复后参考代码
#include <windows.h> #include <stdio.h> int main() { wchar_t path[1024] = L"C:\\MyPath\\MyDir"; auto h = CreateFile(path, FILE_LIST_DIRECTORY, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (h == INVALID_HANDLE_VALUE) { printf("CreateFile error: 0x%08X\n", GetLastError()); return 0; } // 先拿实际目标路径,如果需要查询FileId就用这个路径重新打开 wchar_t targetPath[1024] = {0}; GetFinalPathNameByHandleW(h, targetPath, ARRAYSIZE(targetPath), FILE_NAME_NORMALIZED); wprintf(L"实际指向路径:%s\n", targetPath); unsigned char buffer[4096]; do { // 改用FileDirectoryInfo保证兼容性 if (!GetFileInformationByHandleEx(h, FILE_INFO_BY_HANDLE_CLASS::FileDirectoryInfo, buffer, ARRAYSIZE(buffer))) { auto gle = GetLastError(); if (gle == ERROR_NO_MORE_FILES) break; printf("FileDirectoryInfo error: 0x%08X\n", gle); break; } auto current = buffer; do { auto info = (FILE_DIRECTORY_INFO*)current; wprintf(L"name: %.*s\n", info->FileNameLength / 2, info->FileName); if (!info->NextEntryOffset) break; current += info->NextEntryOffset; } while (true); } while (true); CloseHandle(h); }
内容的提问来源于stack exchange,提问作者Alfonso-Rachid Huilda
相关产品推荐
相关产品推荐

