The published Windows contracts do not provide a supported non-administrative recipe for opening an NTFS directory and flushing it with NtFlushBuffersFile[Ex]; use a documented file flush followed by MoveFileExW(..., MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH) for the replacement, but do not claim that this proves complete parent/ancestor namespace durability after power loss.
Why the native directory-flush sequence is not documented as supported
NtFlushBuffersFileEx with Flags == 0 is documented to write cached file data and metadata and synchronize underlying storage. The documentation recognizes directory handles indirectly by stating that FLUSH_FLAGS_FILE_DATA_SYNC_ONLY is invalid for directory handles. It also says user-mode callers should use the NtFlushBuffersFileEx name rather than ZwFlushBuffersFileEx.^1^
However, there is no documented access mask that satisfies both sides of the operation:
- The flush API documents
STATUS_ACCESS_DENIEDwhen the handle has neither write nor append access.^2^ -
NtCreateFileexplicitly says not to specifyFILE_WRITE_DATAorFILE_APPEND_DATAfor a directory. It also says generic rights cannot be used for a directory.^3^ - The Win32 alternative,
FlushFileBuffers, requires a handle opened withGENERIC_WRITE; that does not resolve the directory-access conflict.^4^
Consequently, the documentation supplies no exact supported directory combination of:
-
DesiredAccess; -
CreateOptions; -
ShareAccess; and - flush API.
FILE_DIRECTORY_FILE is the appropriate directory type option and can be combined with synchronous I/O and FILE_WRITE_THROUGH; if synchronous I/O is selected, SYNCHRONIZE is required. Those rules describe opening a directory but do not confer the write/append access required by the documented flush contract.^3^
A standard user can obtain a directory handle with CreateFileW and FILE_FLAG_BACKUP_SEMANTICS; the flag does not require backup privilege merely to open a directory, although privilege is needed to override normal security checks.^5^ The documented list of operations accepting directory handles does not include FlushFileBuffers.^6^
Observed success with another access mask or with FILE_WRITE_ATTRIBUTES would therefore be implementation behavior, not the requested published contract.
What MS-FSA establishes—and what it does not
MS-FSA defines an abstract flush operation over a DataFile or DirectoryFile. For a directory stream, it flushes metadata associated with that directory, ensures the directory structure is persisted, and flushes underlying physical storage.^7^
That specification does not define:
- how an ordinary user-mode application obtains a qualifying Windows handle;
- an
NtCreateFileaccess mask that overcomes the documented restriction; - that flushing directory D includes changes owned by its parent;
- the required parent/ancestor sequence for an NTFS rename or creation.
A child’s newly published name is an entry in its parent’s directory table.^8^ Therefore, flushing only the child cannot be treated as a documented guarantee that its parent-held name binding is durable. The available contracts also do not establish that flushing the parent is sufficient, or that an additional ancestor flush is required. There is no supported user-mode directory-flush sequence with which to implement either proposition.
Likewise, a successful directory flush cannot be cited as a documented guarantee for a preceding replacement when the prerequisite user-mode directory open itself has no documented compatible access contract.
Supported application-level replacement
For an existing JSON file:
- Create the temporary file on the destination volume.
- Write all content.
- Call
FlushFileBufferson the temporary-file handle and require success. - Close handles as required by the replacement operation.
- Call:
BOOL ok = MoveFileExW(
tempPath,
finalPath,
MOVEFILE_REPLACE_EXISTING |
MOVEFILE_WRITE_THROUGH);
if (!ok) {
DWORD error = GetLastError();
// Do not acknowledge publication.
}
MOVEFILE_REPLACE_EXISTING replaces the destination, subject to ACL requirements. MOVEFILE_WRITE_THROUGH says the function does not return until the move is performed on disk, although its explicit flush guarantee is phrased for a move implemented as copy-and-delete.^9^ This is the documented non-administrative publication mechanism, but its contract does not explicitly promise the complete parent/ancestor crash-durability model posed in the question.
There is no equivalent documented flag that turns CreateDirectory plus parent/ancestor publication into that complete model.
Storage and power-loss boundary
Even a successful normal flush depends on the complete storage stack correctly honoring cache synchronization. Devices may use volatile write-back caches, may lack cache-flush or write-through support, or may instead have power-protected cache.^10^
STORAGE_WRITE_CACHE_PROPERTY exposes, among other fields:
-
WriteCacheEnabled; -
WriteThroughSupported; -
FlushCacheSupported; -
NVCacheEnabled.^11^
That query mechanism is documented as unsupported for RAID and flash devices, so it cannot establish a universal end-to-end power-loss guarantee on common configurations.^10^
Accordingly:
- API success: available for file flushing and write-through replacement.
- Filesystem crash consistency: NTFS supplies its recovery behavior, but the cited public contracts do not define the requested full namespace publication sequence.
- Physical power-loss durability: requires compliant filesystem, filter, storage, controller, firmware, and cache behavior; API success alone cannot prove those properties.
If a formal guarantee for a particular Windows build, NTFS version, filter stack, and storage configuration is required, it must be obtained through Microsoft Developer Support or replaced by an application design that can recover and validate publication after restart.
References
- ZwFlushBuffersFileEx function (ntifs.h)
- NtFlushBuffersFileEx function (ntifs.h)
- NtCreateFile function (ntifs.h)
- FlushFileBuffers function (fileapi.h)
- CreateFileW function (fileapi.h)
- Directory Handles
- [IP Address] Server Requests Flushing Cached Data
- About Directory Management
- MoveFileExW function (winbase.h)
- Querying for the Write Cache Property
- STORAGE_WRITE_CACHE_PROPERTY structure (ntddstor.h)