The published Microsoft contract does not clearly establish user-mode support for NtCreateFile with both a file-system RootDirectory and OBJ_DONT_REPARSE, so it should not be treated as a portable, version-stable security guarantee without clarification from Microsoft.
What is documented
Two individually documented behaviors overlap, but their combination is not explicitly documented:
-
OBJECT_ATTRIBUTES.RootDirectorymay be a file-system directory handle, withObjectNameinterpreted relative to that directory.^1^ - The general
OBJECT_ATTRIBUTESdefinition saysOBJ_DONT_REPARSEprevents following reparse points while parsing the associated name and returnsSTATUS_REPARSE_POINT_ENCOUNTEREDif any are encountered.^1^ - The user-mode
NtCreateFilepage documents directory-relative names, but its description ofOBJECT_ATTRIBUTES.Attributessays the value can be zero orOBJ_CASE_INSENSITIVE; it does not listOBJ_DONT_REPARSE.^2^
Consequently, the general structure page describes what OBJ_DONT_REPARSE means when applicable, but the narrower NtCreateFile page does not confirm that the flag is accepted as part of the supported user-mode file-open contract. The documentation also does not state that the narrower list is merely illustrative or obsolete.
A Microsoft Q&A test found that the combination worked on one Windows 11 build and rejected both final and intermediate junctions, but that is implementation evidence for that configuration—not a published cross-version contract.^3^
Traversal scope
If the general OBJ_DONT_REPARSE definition is applied, its stated scope is any reparse encountered while parsing the associated object name, not only the final component. The documented result is STATUS_REPARSE_POINT_ENCOUNTERED.^1^
That wording is tag-neutral, so it is not limited to symbolic-link tags, junction tags, or mount-point tags. However, the documentation does not explicitly guarantee how every file system or third-party filter implementation interacts with this particular user-mode NtCreateFile combination. Reparse processing can be implemented by the file system and by a filter associated with the reparse tag.^4^
Therefore:
- Semantic definition: refuse any reparse encountered during name parsing.
- Supported user-mode
NtCreateFilecombination: not explicitly established. - Universal file-system/filter guarantee: not documented.
- Version provenance/minimum Windows version: not documented in the supplied API references.
Also, STATUS_REPARSE_POINT_ENCOUNTERED is distinct from STATUS_REPARSE. The NtCreateFile statement that it never returns STATUS_REPARSE does not contradict the former status.^2^
FILE_OPEN_REPARSE_POINT is not an equivalent replacement
FILE_OPEN_REPARSE_POINT is explicitly documented for NtCreateFile. When the target file has a reparse point, it bypasses normal processing and attempts to open the reparse-point object itself.^2^
It does not document the same fail-on-any-reparse behavior as OBJ_DONT_REPARSE:
-
OBJ_DONT_REPARSE: fail if a reparse is encountered while parsing. -
FILE_OPEN_REPARSE_POINT: open the reparse-point object rather than its target. - The documented Win32 behavior is focused on an existing target that is itself a symbolic link or other reparse point; it does not promise rejection of reparse points in every intermediate component.^5^
There is an additional directory-option problem: the documented FILE_DIRECTORY_FILE compatibility list does not include FILE_OPEN_REPARSE_POINT.^6^ Accordingly, even if a particular system accepts that combination, the listed options do not establish it as a supported contract for opening each child directory.
Documented alternative and remaining gap
The documented Win32 approach is to open a path with CreateFileW and FILE_FLAG_OPEN_REPARSE_POINT, then inspect the returned object rather than the target.^7^ This can identify or inspect a final reparse point, but the documentation does not establish it as a race-resistant substitute that:
- resolves each child relative to an already-held directory handle,
- refuses all intermediate reparses, and
- atomically guarantees containment beneath that handle.
Checking FILE_ATTRIBUTE_REPARSE_POINT, querying reparse data, comparing final paths, or comparing file IDs after opening can validate what was reached, but those checks do not retroactively prevent traversal or provide an atomic create-under-parent guarantee. File IDs can determine whether two handles identify the same file, but that is identity verification rather than traversal prevention.^8^
Thus, no documented public Win32 alternative in these references provides the complete handle-relative, reject-any-reparse, race-resistant contract requested. For a product security boundary, the unresolved contract should be raised through Microsoft support or documentation feedback, including the exact Windows versions, file systems, create options, and reparse/filter classes that must be supported.
References
- OBJECT_ATTRIBUTES structure (ntdef.h)
- NtCreateFile function (winternl.h)
- Is OBJ_DONT_REPARSE supported by user-mode NtCreateFile with a directory-relative name? - Microsoft Q&A
- File system reparse points
- Reparse Points and File Operations
- NtCreateFile function (ntifs.h)
- CreateFileW function (fileapi.h)
- FILE_ID_INFO structure (winbase.h)