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.