Hi @Bulqe ,
Thanks for the detailed write-up.
Most pieces of your sequence are documented individually, but I couldn't find a published statement that guarantees the full no-reparse-traversal property for this exact combination. That's especially true for how the initial handle is obtained and what happens under concurrent changes.
For the flag combination
-
OBJ_DONT_REPARSE: OBJECT_ATTRIBUTES defines it: no reparse points are followed during name parsing, and the call fails withSTATUS_REPARSE_POINT_ENCOUNTEREDif one is hit. The same page allows a file system directory handle asRootDirectory. However, the user-mode NtCreateFile page only lists zero orOBJ_CASE_INSENSITIVEforAttributes, and nothing published reconciles the two. A related thread reports the flag working on a specific Windows 11 build, but that's observed behavior, not a cross-version guarantee. - With
FILE_OPEN_REPARSE_POINT: that flag opens the reparse point itself, whileOBJ_DONT_REPARSEasks the call to fail. Their interaction isn't documented, so don't assume the combination rejects a final reparse point. Checking each returned handle is the right safeguard. - No directory/non-directory flag: this is consistent with the docs, since
FILE_OPEN_REPARSE_POINTisn't on the list of options compatible withFILE_DIRECTORY_FILE. It does mean the call won't enforce the object type for you. - Access and options:
FILE_READ_ATTRIBUTES | SYNCHRONIZEwithFILE_SYNCHRONOUS_IO_NONALERTis consistent with the docs.FILE_OPEN_NO_RECALLis a hint to offline-storage filters and isn't tied to any reparse guarantee. You're also right not to rely on sharing restrictions: this thread shows a directory being converted to a junction with onlyFILE_WRITE_ATTRIBUTESaccess.
No documented method guarantees getting the first handle without following a reparse:
-
\??\C:\...passes through Object Manager symbolic links before NTFS sees the name, and the docs don't say whetherOBJ_DONT_REPARSEtreats those as reparse points. -
CreateFileWwithFILE_FLAG_OPEN_REPARSE_POINTonly covers the last path component. - CreateFile3 with
FILE_FLAG_DISALLOW_PATH_REDIRECTS(Windows 11 24H2 / Windows Server 2025) adds redirect protection, but it still starts from a path.
Either way, verify the starting directory on its handle rather than trusting the path.
Before using a handle as the next RootDirectory, query GetFileInformationByHandleEx with FileAttributeTagInfo I suggest reject the handle if FILE_ATTRIBUTE_REPARSE_POINT is set and require FILE_ATTRIBUTE_DIRECTORY for intermediate components and a non-directory for the final one.
FILE_ID_INFO helps compare identity across handles. These checks confirm what a handle refers to, not how it was reached. Behavior can also vary with filesystem filters (Reparse Points and File Operations).
And an ordinary rename won't redirect a held RootDirectory handle. But if the held directory is turned into a junction during the call, the docs don't define the outcome. This thread covers that gap in more detail.
So if this is a security boundary, I'd use OBJ_DONT_REPARSE as defense in depth, accept each component only after checking its handle, and fail closed whenever a check can't be completed.
A definitive support statement for this flag combination, including how the initial handle is obtained and what's guaranteed under concurrent changes, isn't something I can independently provide or validate through this forum. If you need an authoritative answer, you can open a case with Microsoft Support through Support for Business. That route lets the question be reviewed by the appropriate Windows engineering channels.
If you found my support helpful, I'd really appreciate it if you could follow this guide so others with a similar issue can benefit as well.
Thank you