Supported user-mode NtCreateFile sequence for handle-relative opens without reparse traversal

Bulqe 0 Reputation points
2026-11-08T04:41:16.22+00:00

Hello,

We are designing a read-only diagnostic reader for one existing file on local NTFS. Before allowing real-file access, we need to establish a supported opening sequence that cannot silently follow a filesystem reparse point.

Our proposed approach retains a directory handle and opens exactly one relative path component at a time. Each returned handle is inspected before proceeding.

Proposed metadata-open parameters:

RootDirectory: retained directory handle
ObjectName: one relative component, no separators or stream syntax
DesiredAccess: FILE_READ_ATTRIBUTES | SYNCHRONIZE
ShareAccess: FILE_SHARE_READ
CreateDisposition: FILE_OPEN
CreateOptions:
    FILE_SYNCHRONOUS_IO_NONALERT
    FILE_OPEN_REPARSE_POINT
    FILE_OPEN_NO_RECALL
ObjectAttributes.Attributes:
    OBJ_CASE_INSENSITIVE
    OBJ_DONT_REPARSE

Neither FILE_DIRECTORY_FILE nor FILE_NON_DIRECTORY_FILE is set during this metadata-admission step.

What supported user-mode opening sequence establishes this no-reparse-traversal property, including acquisition of the initial directory handle? Please confirm whether the exact combination above is supported and identify any required corrections or Windows-version restrictions.

The threat model includes concurrent renaming or reparse-point changes by another ordinary process. It excludes a compromised kernel, malicious filesystem driver or administrator overriding protections. We are not assuming that sharing restrictions prevent changes to file attributes.

We consulted:

Please distinguish documented guarantees from observed behavior. If Windows does not expose a supported sequence meeting this requirement, an explicit statement would help us choose a narrower design.

Windows development | Windows API - Win32
0 comments No comments

1 answer

Sort by: Oldest
  1. Percy Nguyen (WICLOUD CORPORATION) 240 Reputation points Microsoft External Staff Moderator
    2026-11-09T02:13:39.4533333+00:00

    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 with STATUS_REPARSE_POINT_ENCOUNTERED if one is hit. The same page allows a file system directory handle as RootDirectory. However, the user-mode NtCreateFile page only lists zero or OBJ_CASE_INSENSITIVE for Attributes, 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, while OBJ_DONT_REPARSE asks 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_POINT isn't on the list of options compatible with FILE_DIRECTORY_FILE. It does mean the call won't enforce the object type for you.
    • Access and options: FILE_READ_ATTRIBUTES | SYNCHRONIZE with FILE_SYNCHRONOUS_IO_NONALERT is consistent with the docs. FILE_OPEN_NO_RECALL is 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 only FILE_WRITE_ATTRIBUTES access.

    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 whether OBJ_DONT_REPARSE treats those as reparse points.
    • CreateFileW with FILE_FLAG_OPEN_REPARSE_POINT only 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

    Was this answer helpful?

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.