Efficient Windows error handling and propagation for Win32, COM, and WinRT.
windows-result is the error layer shared by the windows-* crates. Its building blocks are
HRESULT (a Windows status code, with .ok() to convert into a Result), Error (a rich error
carrying an HRESULT and a message), and Result<T>. It also wraps the other Windows status
representations - BOOL, WIN32_ERROR, and NTSTATUS - so they convert cleanly into an Error.
The remainder of this page covers how the crate is built and maintained. It is for contributors and
is not needed to use windows-result.
src/bindings.rs is generated by tool_bindings from crates/tools/bindings/src/result.txt. The
com, bstr, and strings modules add COM error-info support and are gated on windows (and
disabled under the windows_slim_errors cfg).
Run cargo test -p windows-result; see also the workspace test crates.
windows-result currently exports five status types: HRESULT, BOOL, WIN32_ERROR, NTSTATUS,
and RPC_STATUS. The last three were promoted here in
#3783 ("Promote remaining error types to
windows-result"). It's worth re-examining whether all of them earn a place in a focused error
crate, or whether some should revert to being generated per-namespace by windows-bindgen. As of
this writing the promoted types are committed but have not shipped - the last published version
is 0.4.1 (2025-10-06), and #3783 landed 2025-10-09 without a version bump.
A survey of the source metadata (the RDL files under metadata/, which are the authoritative API
surface - the "everything" windows/windows-sys crates are a poor gauge) shows how often each
type is actually returned by an API:
| Type | Fn returns | Files | Notes |
|---|---|---|---|
HRESULT |
26,841 | 374 | Foundational - Error/Result are built on it. Non-negotiable. |
BOOL |
4,277 | 569 | Ubiquitous ABI primitive, but not an error type. |
NTSTATUS |
1,319 | 18 | Driver/native APIs; strongest of the promoted status types. |
RPC_STATUS |
289 | 7 | RPC only; no hand-written consumer in the repo. |
WIN32_ERROR |
0 | 0 | Does not exist in the metadata at all. |
Findings that motivate the re-examination:
WIN32_ERRORis entirely synthetic. It appears zero times in the source metadata. Win32 error constants are typedu32(const ERROR_ACCESS_DENIED: u32 = 5), and classic Win32-error-returning functions useLSTATUS(=i32, e.g.RegCloseKey -> LSTATUS). Its only real consumer in the repo is a single internal helper inwindows-registry(win32_error()inregistry/src/lib.rs) that computesWIN32_ERROR(x).to_hresult()- theHRESULT_FROM_WIN32conversion. That conversion is genuinely useful, but it does not require a public exported newtype; the API surface never hands you aWIN32_ERROR.- The repo already leaves a long tail of equally-legitimate status types generated
per-namespace:
JET_ERR(232 returns),CONFIGRET(224),SQLRETURN(182),MMRESULT(161),SECURITY_STATUS(161),LSTATUS(129),PDH_STATUS(98). PromotingRPC_STATUS(289) andWIN32_ERROR(0) while leaving these generated is a somewhat arbitrary line. NTSTATUSandRPC_STATUShave no hand-written consumer - outside the generatedwindows/windows-syscrates, their only references are the bindgen remap machinery and their own definitions.NTSTATUSat least has a large, meaningful API footprint;RPC_STATUSis niche.
Directions to weigh:
- Keep as-is - one canonical definition shared across namespaces avoids the per-namespace
duplication and feature-gated conversions that made up the bulk of the #3783 diff (the ~12K-line
Win32/Foundationchange). - Trim to a focused error crate - keep
HRESULT(and arguablyNTSTATUS, the strongest of the rest); revertWIN32_ERROR/RPC_STATUSto generated types, and express the Win32 to HRESULT conversionwindows-registryneeds as a helper rather than a promoted newtype. NoteBOOLis an ABI primitive rather than an error type, so it fits an error crate least on thematic grounds even though it predates #3783.
Before acting, also confirm what de-promotion would require in the generated windows crate (how
those namespaces would reference the types once no longer sourced from windows-result).