The current CreateDirectory2W reference is internally inconsistent and is not sufficient by itself to establish the exact ABI and security contract; use the five-parameter SDK declaration, defensively reject both NULL and INVALID_HANDLE_VALUE, and do not assume stronger intermediate-component or concurrency guarantees than Microsoft explicitly documents.
Return value and example defects
The Unicode page says failure returns zero, but its example checks INVALID_HANDLE_VALUE and passes six arguments to a documented five-parameter function.^1^
The ANSI counterpart has the same five parameters but explicitly says failure returns INVALID_HANDLE_VALUE; it also lists ERROR_PATH_REDIRECTED as a possible error.^2^
These pages therefore do not provide one consistent normative failure value. For code targeting the currently supported releases, treat either sentinel as failure and capture GetLastError() immediately:
HANDLE h = CreateDirectory2W(
path,
FILE_LIST_DIRECTORY | SYNCHRONIZE,
FILE_SHARE_READ,
DIRECTORY_FLAGS_DISALLOW_PATH_REDIRECTS,
securityAttributes);
if (h == nullptr || h == INVALID_HANDLE_VALUE) {
const DWORD error = GetLastError();
// Report or map error here.
return error;
}
// Use h; close it exactly once.
CloseHandle(h);
This is a defensive workaround for the published discrepancy, not confirmation that both values are emitted by the implementation.
The example’s sixth NULL argument does not match either documented declaration and should not be copied.
Declaration and calling convention
The public syntax currently shown is:
HANDLE CreateDirectory2W(
LPCWSTR lpPathName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
DIRECTORY_FLAGS DirectoryFlags,
LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
The documented requirements are Windows 11 24H2 or Windows Server 2025, fileapi.h through Windows.h, Kernel32.lib, and Kernel32.dll.^1^ The header index also identifies CreateDirectory2W as the Unicode entry point.^3^
However, the rendered declaration omits any import/export and calling-convention macros. The supplied public references do not establish the expanded calling convention. For ABI-sensitive use, the authoritative declaration for a particular build is the unmodified fileapi.h shipped with the exact Windows SDK used to compile it; do not create a handwritten declaration or infer the convention from the simplified Learn syntax. Microsoft needs to publish the complete header declaration if a source-level ABI specification is required.
Also call CreateDirectory2W explicitly rather than the encoding-neutral CreateDirectory2 alias when the path is UTF-16. The alias selects ANSI or Unicode according to UNICODE.^1^
Returned-handle semantics
The API accepts desired access and sharing parameters described as applying to “the returned handle,” strongly indicating that successful creation returns an open directory handle.^1^ The example likewise retains that handle to prevent deletion and closes it after using the directory.
Nevertheless, the current text does not explicitly specify:
- an object-identity guarantee tying the handle to the directory inserted by that same operation;
- behavior under concurrent rename or reparse-point conversion;
- an atomic “create in the intended directory or create nothing” boundary.
For a security proof that depends on those properties, the present public documentation is insufficient.
DIRECTORY_FLAGS_DISALLOW_PATH_REDIRECTS
The published flag definition says it prevents the specified path from being redirected by reparse points or symbolic links.^4^ The ANSI page associates a detected redirect with ERROR_PATH_REDIRECTED.^2^
It does not precisely define for CreateDirectory2W:
- whether every intermediate component is checked;
- which reparse tags are covered beyond the stated reparse points and symbolic links;
- behavior when a component changes concurrently during resolution;
- filesystem, SMB, or filter-driver qualifications;
- whether detecting a redirect guarantees that no directory was created elsewhere.
RemoveDirectory2W is more explicit for its own operation: it says the call fails if any part of the path is redirected.^5^ That wording should not be promoted into a contractual guarantee for CreateDirectory2W.
Consequently, CreateDirectory2W may be useful as a mitigation on its supported systems, but the current references do not establish the full intermediate-component and race-resistant contract needed for a security-sensitive provisioning primitive. A corrected reference should specify the failure sentinel, exact exported declaration, handle/object identity, component coverage, race semantics, and no-side-effect behavior on ERROR_PATH_REDIRECTED.
References