如何使用 GetFileInformationByHandleEx 读取连接点目录中的文件?

How to read files in a junction point directory, using GetFileInformationByHandleEx?

如果 path 指向常规目录,我的代码运行良好:

#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;
    }

    FILE_ID_INFO id = {};
    if (!GetFileInformationByHandleEx(h, FILE_INFO_BY_HANDLE_CLASS::FileIdInfo, &id, sizeof(id)))
    {
        printf("FileIdInfo error: 0x%08X\n", GetLastError());
    }

    unsigned char buffer[4096];
    do
    {
        if (!GetFileInformationByHandleEx(h, FILE_INFO_BY_HANDLE_CLASS::FileIdExtdDirectoryInfo, buffer, ARRAYSIZE(buffer)))
        {
            auto gle = GetLastError();
            if (gle == ERROR_NO_MORE_FILES)
                break;

            printf("FileIdExtdDirectoryInfo error: 0x%08X\n", gle);
            break;
        }

        auto current = buffer;
        do
        {
            auto info = (FILE_ID_EXTD_DIR_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);
}

但是如果目录指向一个连接点,它returns(ERROR_INVALID_PARAMETER无效参数)

FileIdInfo error: 0x00000057
FileIdExtdDirectoryInfo error: 0x00000057

所以,我已经为 CreateFile

试过了
auto h = CreateFile(path, FILE_LIST_DIRECTORY, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);

现在,我没有错误,但它只显示 "."".." 条目,而不是我可以使用 cmd.exe[=19 读取的目录中的所有文件=]

C:\MyPath\MyDir>dir
 Volume in drive C has no label.
 Volume Serial Number is AEA6-688A

 Directory of C:\MyPath\MyDir

20/10/2017  14:08             (157) My Icon.ico
11/04/2018  09:08               321 My File.cpp
30/04/2018  15:14    <DIR>          My dossier
19/09/2019  10:40          (41 650) New Rich Text Document.rtf
10/10/2021  11:06                 0 New Text Document.txt
               4 File(s)         46 224 bytes
               1 Dir(s)  544 625 274 880 bytes free

事实证明我的代码本身是正确的,但如果下面的文件系统不支持 NTFS object ID,它可能会失败,因为这是它试图读取的内容(使用 FILE_INFO_BY_HANDLE_CLASS::FileIdInfo 和FILE_INFO_BY_HANDLE_CLASS::FileIdExtdDirectoryInfo).

例如,如果目录是 NTFS mount point with a substitute name that points to a volume that doesn't have the FILE_SUPPORTS_OBJECT_IDS 标志集(在虚拟驱动器场景中看到),就会发生这种情况。

这里的错误 (ERROR_INVALID_PARAMETER) 有点误导,因为任何参数都没有问题(可能 FileInformationClass 一个除外),我本以为会出现一些“不受支持”的错误。

至于 cmd.exe,嗯,它只是没有 read/need 那个信息,所以它工作正常。