NtCreateFile: supported type-neutral metadata-only open with no-follow and no-recall flags?

Doug Oweczkin 0 Reputation points
2026-09-13T09:25:01.0733333+00:00

Could Microsoft clarify the supported contract and acquisition-time guarantees for this exact user-mode NtCreateFile call?

Parameters:

  • DesiredAccess = 0x00100080: FILE_READ_ATTRIBUTES | SYNCHRONIZE

CreateOptions = 0x00600020: FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT | FILE_OPEN_NO_RECALL. Neither FILE_DIRECTORY_FILE nor FILE_NON_DIRECTORY_FILE is set.

ObjectAttributes.Attributes = 0x1040: OBJ_CASE_INSENSITIVE | OBJ_DONT_REPARSE

RootDirectory: a retained filesystem-directory handle

ObjectName: one relative child-name component

CreateDisposition = FILE_OPEN

ShareAccess = FILE_SHARE_READ

AllocationSize, EaBuffer, SecurityDescriptor and SecurityQualityOfService pointers: null

FileAttributes = 0; EaLength = 0

The caller requests no data-read, directory-listing or write access. It would check the returned object's type and identity through the same handle before using it as a parent, retaining that handle without reopening by path.

This is a contract-clarification question, not a claim that the candidate combination has been validated.

Documentation ambiguity:

The user-mode NtCreateFile documentation lists compatible options for FILE_DIRECTORY_FILE without including FILE_OPEN_REPARSE_POINT or FILE_OPEN_NO_RECALL. The proposed candidate therefore omits directory-type enforcement at open time.

The same page describes ObjectAttributes.Attributes more narrowly than the general OBJECT_ATTRIBUTES documentation, which explicitly documents OBJ_DONT_REPARSE.

The NtCreateFile driver reference documents FILE_OPEN_NO_RECALL as instructing offline-storage or virtualisation filters not to recall file contents because of the open.

Questions:

Is this exact user-mode combination supported for directories and ordinary files? Please clarify the documentation differences and any Windows-version or filesystem limitations.

Does it prevent reparse-target traversal and content recall during acquisition, including when the child is an unexpected type or offline/cloud placeholder? Is checking directory type through the returned handle sufficient for these guarantees, or is acquisition-time type enforcement required?

Does FILE_OPEN_NO_RECALL prevent only content recall, or also provider callbacks, network activity or metadata hydration caused by the open?

Please provide an authoritative reference or supported alternative preserving the requested access restriction, existing-only opening, acquisition-time no-follow/no-recall protection and retained parent-relative resolution. We do not want to infer these guarantees from a successful trial or remove protective flags by assumption.

Official references:

NtCreateFile — user-mode reference: https://learn.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntcreatefile

OBJECT_ATTRIBUTES: https://learn.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-_object_attributes

NtCreateFile — driver reference: https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntcreatefile

Windows development | Windows API - Win32
0 comments No comments

1 answer

Sort by: Most helpful
  1. Taki Ly (WICLOUD CORPORATION) 4,450 Reputation points Microsoft External Staff Moderator
    2026-09-14T03:04:01.4233333+00:00

    Hello @Doug Oweczkin ,

    The relevant references for this call are the ntifs NtCreateFile page, the ntdef OBJECT_ATTRIBUTES page, and the "Symbolic Link Behavior" section of CreateFile. The user‑mode winternl page is an abridged version of the same code path, which accounts for the wording gaps you noted.

    1. Whether this works for both files and directories. It does. FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN_REPARSE_POINT, and FILE_OPEN_NO_RECALL are ordinary CreateOptions and are not tied to one type. Leaving out FILE_DIRECTORY_FILE and FILE_NON_DIRECTORY_FILE means either type is accepted; FILE_DIRECTORY_FILE is the flag that enforces a directory at open time. The winternl table lists which options are compatible with FILE_DIRECTORY_FILE; it does not make the other flags invalid when that flag is absent. CreateFile also states that FILE_FLAG_OPEN_REPARSE_POINT is "ignored" when the target is not a reparse point, so the same call opens both. Your DesiredAccess 0x00100080 includes SYNCHRONIZE, which FILE_SYNCHRONOUS_IO_NONALERT requires.

    2. Whether it stops reparse follow at open time, and whether checking the type afterward is sufficient. Stopping the follow at the final name is documented. The ntifs page states that with FILE_OPEN_REPARSE_POINT, "normal reparse processing does not occur… never returns STATUS_REPARSE." CreateFile states that with the flag you receive a handle to the link itself, and without it a handle to the target. OBJ_DONT_REPARSE only fails on a reparse point encountered while walking the path, so it protects the intermediate components of a path. Since you open a single child name from a handle you already hold, there is no intermediate component for it to protect, so the leaf no‑follow comes from FILE_OPEN_REPARSE_POINT, not OBJ_DONT_REPARSE.

    This flag set does not enforce the type at open time. It returns a handle to whatever the child is. Checking FILE_ATTRIBUTE_REPARSE_POINT and the reparse tag through the handle is therefore required, not only sufficient. If you want the open itself to fail on the wrong type, add FILE_DIRECTORY_FILE or FILE_NON_DIRECTORY_FILE. Your protection against swaps comes from opening relative to the handle you already hold, which you are doing.

    3. Whether FILE_OPEN_NO_RECALL stops only content recall, or also callbacks, network, and metadata. The documented scope is the content part only, and only for legacy remote‑storage/HSM. The ntifs page states it instructs those filters "not to recall the contents of the file," and CreateFile states it is "for use by remote storage systems." There is no documented statement about provider callbacks, network activity, or metadata being pulled in. Modern cloud files are a separate system. Per Build a Cloud Sync Engine, placeholders are reparse points, but the cloud filter hides them from ordinary apps unless you opt in with RtlSetProcessPlaceholderCompatibilityMode. Hydration is decided at open time, and FILE_ATTRIBUTE_RECALL_ON_OPEN items can be fetched on open. Opening a cloud placeholder can therefore pull data even with FILE_OPEN_NO_RECALL set.

    4. References and a pattern that keeps your constraints. See the pages linked above: NtCreateFile (ntifs.h), OBJECT_ATTRIBUTES (ntdef.h), CreateFile (fileapi.h), File Attribute Constants and Reparse Point Tags (WinNT.h), and Build a Cloud Sync Engine (cfapi). Keep the call as it stands: the held parent handle plus one child name, minimal access, FILE_OPEN, and FILE_OPEN_REPARSE_POINT for leaf no‑follow. Verify the reparse tag and type through the handle before using it as a parent. If avoiding hydration on cloud placeholders is a requirement, handle it through the cloud files (cfapi) path rather than through FILE_OPEN_NO_RECALL.

    On the parts the documentation does not state, namely the whole flag combination as a contract, the exact OBJ_DONT_REPARSE and FILE_OPEN_REPARSE_POINT behavior at the final name, and how this open behaves against modern cfapi placeholders: this is a community forum and I do not have access to the product source or internal specifications, so I cannot commit to a supported‑contract answer on those, and a passing test should not be treated as proof. For a binding answer, please open an official Azure/Windows developer support request, since that team can confirm it directly. Include this exact NtCreateFile call with all parameters, your target Windows build, and the file system or provider you are testing on.

    I hope this information helps clarify the behavior. If you found my response helpful or informative, I would greatly appreciate it if you could follow this guide for your confirmation.

    Thank you.

    Was this answer helpful?

    1 person found this answer helpful.

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.