Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I have this code which runs fine if path points to a regular directory:

#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];
        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;
            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);

But if the directory points to a junction point, it returns (ERROR_INVALID_PARAMETER invalid parameter)

FileIdInfo error: 0x00000057
FileIdExtdDirectoryInfo error: 0x00000057

So, I've tried this for CreateFile

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

and now, I have no error, but it only shows "." and ".." entries, not all the files in the directory which I can read using cmd.exe

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
                this must not be. code must work and for reparse points too. try RtlGetLastNtStatus() instead GetLastError() - may be this give more info. use FILE_FLAG_OPEN_REPARSE_POINT is wrong - in this case will be opened reparse point itself instead folder to which it point
– RbMm
                Oct 10, 2021 at 16:02
                Ok, since you say it should work (which is in itself an interesting info, also RtlGetLastNtStatus gives back STATUS_INVALID_PARAMETER), I've tested with other junction points (like "C:\Documents and Settings" with MAXIMUM_ALLOWED instead of FILE_LIST_DIRECTORY) and the code works fine. But the cmd.exe command still succeeds where this code fails, so there should be a way to make it work? I want to use GetFileInformationByHandleEx to be able to get FILE_ID_EXTD_DIR_INFO.
– Jean-René Friton
                Oct 10, 2021 at 16:22
                cmd.exe used FindFirstFileEx or NtQueryDirectoryFile with FileDirectoryInformation - you can try this too on your junction and look for result. on all junctions which i test - GetFileInformationByHandleEx work ok
– RbMm
                Oct 10, 2021 at 16:41
                @RbMm - I need the Id so I don't think I can use FindFirstFile(Ex), but it seems to work ok with NtQueryDirectoryFile (FileIdFullDirectoryInformation) ... strange...
– Jean-René Friton
                Oct 10, 2021 at 17:53
                @RbMm - More info, NtQueryDirectoryFile  with FileIdExtdDirectoryInformation (not FileIdFullDirectoryInformation) fails with the same STATUS_INVALID_PARAMETER result. So the issue is really about 128-bit object id (which I think is why it works with cmd.exe / FindFirstFileEx, because they don't read that). And in fact the mount point target is a volume that doesn't have the FILE_SUPPORTS_OBJECT_IDS flag, so I guess it all makes sense now.
– Jean-René Friton
                Oct 10, 2021 at 21:07

It turns out my code in itself is correct, but it can fail if the file system below doesn't support NTFS object ID, since this is what it's trying to read (using FILE_INFO_BY_HANDLE_CLASS::FileIdInfo and FILE_INFO_BY_HANDLE_CLASS::FileIdExtdDirectoryInfo).

This happens for example if the directory is an NTFS mount point with a substitute name that points to a volume that doesn't have the FILE_SUPPORTS_OBJECT_IDS flag set (seen in virtual drive scenarios).

The error here (ERROR_INVALID_PARAMETER) is kind of misleading as there's no problem with any parameter (except maybe the FileInformationClass one), I would have expected some "unsupported" error instead.

As for cmd.exe, well, it just doesn't read/need that information so it works fine.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.