A broad projected Windows API for Rust binary applications.
- 📦 crates.io
- 📖 API reference
- 🚀 Getting started
- 🧩 Samples
- 📁 Source
The windows crate projects Win32, COM, and WinRT metadata into Rust. It keeps the Windows API
shape while adding typed handles, COM reference counting, string and parameter conversions, and
Result-returning wrappers where the metadata describes an HRESULT result.
| Need | Choose | Why |
|---|---|---|
| Focused crate covers the task | That focused crate | Small, stable dependency and safer API |
| Reusable library needs another API | windows-bindgen |
Owned binding set |
| Binary application needs broad rich bindings | windows |
Pre-generated projected API |
| Binary application needs broad raw bindings | windows-sys |
Pre-generated FFI |
Start with the focused crates listed in the crate index. They provide smaller
dependencies and APIs designed around a particular task. If a reusable library needs APIs they do
not expose, generate a private, reviewed binding set with windows-bindgen.
Use windows when a binary application benefits more from a pre-generated broad projection than
from owning generated bindings. Cargo features limit what compiles, but the umbrella crate still
adds dependency weight and version churn. Different libraries can otherwise bring incompatible
versions of the same large crate into one dependency tree.
It is possible to mix windows and windows-sys, but their similarly named types are distinct.
Keep conversions at a small boundary rather than passing values from both crates throughout an
application.
Windows APIs retain their metadata organization:
- WinRT namespaces use Rust modules such as
windows::Data::Xml::Dom. - Win32 header groups are exposed below
windows::Win32, such ashandleapi,synchapi, andwinuser. - Shared runtime types and traits are under
windows::core.
Use this workflow when adding an API:
- Find the Windows API by its native name in the API reference.
- Read the projected Rust signature rather than translating the C signature by hand.
- Enable the feature shown for the item. WinRT features follow namespace names with
_separators, such asData_Xml_Dom. Win32 features usually follow lowercase header groups, such ashandleapi. - Import narrowly while learning the API. A path such as
windows::Win32::CreateEventWmakes missing features and name collisions easier to diagnose than a glob import. - Add supporting features reported by the compiler or reference. Cargo feature dependencies pull in many prerequisite types automatically, but a function and the types in its signature may be gated separately.
Keep the feature list near the code that motivates it. For a workspace, a shared dependency can centralize the version while each package selects only the features it calls. Avoid enabling every feature as a discovery shortcut: it slows builds and hides the intended API boundary.
If a documented item does not appear after enabling its feature, check the target first. The
windows crate is Windows-only, and availability in Windows metadata does not guarantee that an
API exists on every supported Windows version. Runtime version checks and documented fallback
behavior remain the application's responsibility.
The Rust signature is the contract. Projection changes common ABI details in useful ways:
- Nullable pointers may become
Option. - C
BOOLinputs may become Rustbool. - String and interface inputs may accept
Param<T>implementations rather than one exact type. - COM and WinRT out parameters may become return values.
- HRESULT-returning methods may become
windows::core::Result<T>. - Slice-shaped pointer and length pairs may become Rust slices.
These changes do not make every Windows call safe. Generated functions remain unsafe when the
caller must uphold pointer, lifetime, threading, initialization, or API-specific invariants. Keep
the unsafe block small and document the invariant in the safe wrapper around it.
COM and WinRT interface values are owning, reference-counted wrappers. Cloning one calls AddRef,
dropping one calls Release, and Interface::cast performs QueryInterface. Prefer those
operations over manipulating raw interface pointers.
Win32 handle types such as HANDLE and HWND improve type checking but do not imply ownership.
The API documentation determines whether a returned handle is borrowed, owned, or a sentinel and
which function releases it. Pair acquisition and release in one abstraction so early returns do
not leak the resource.
Generated structs follow the Windows ABI. Initialize them with Default when supported, then set
required size, version, discriminant, or pointer fields exactly as the native API requires.
Constants sometimes need a cast because the metadata preserves the native constant type while a
function accepts another integer type.
windows::core::Result<T> and windows::core::Error cover HRESULT-based failures. The ? operator
is the normal path for projected methods that return Result.
Win32 APIs use several other failure conventions. A function may return BOOL, a null handle,
INVALID_HANDLE_VALUE, zero, or another sentinel. Do not apply one check to every function:
- Use
.ok()?when a projectedBOOLorHRESULTis documented as success/failure. - Check handle and integer sentinels exactly as documented.
- Call
Error::from_thread()immediately after an API reports a last-error failure. Another Windows call may overwrite the thread's last-error value. - Do not treat every zero as failure. Some APIs use zero as a valid result or require a separate status query.
The getting-started example demonstrates both patterns: CreateEventW requires a null-handle
check, while SetEvent and CloseHandle return values support .ok()?.
Choose a string representation from the parameter type and ownership contract:
| Form | Use |
|---|---|
w!("text") |
Static null-terminated UTF-16 input (PCWSTR) |
s!("text") |
Static null-terminated narrow input (PCSTR) |
h!("text") |
Static WinRT HSTRING |
HSTRING |
Owned WinRT string, including dynamic text |
BSTR |
Owned Automation string |
PCWSTR / PCSTR |
Borrowed const pointer with externally managed lifetime |
PWSTR / PSTR |
Mutable pointer, commonly for caller-provided output storage |
Prefer the W variant of a Win32 API for new code. The A variant uses an API-specific Windows
code page, not Rust UTF-8. The literal macros include the required trailing null where applicable.
For dynamic pointer strings, keep the backing buffer alive and immovable for the entire call and
add a trailing null yourself. A pointer string has no ownership; never free it unless the API says
the caller owns the allocation.
When a binary application wraps an API from this crate:
- Keep generated types and calls in a Windows-specific module.
- Validate Rust inputs before entering
unsafe. - Convert strings and buffers once, immediately before the call.
- Check the API's documented success convention before making another Windows call.
- Move owned handles or interfaces into a type whose
Dropimplementation uses the matching release function. - Return ordinary Rust values and
Resultfrom the public wrapper.
This boundary makes API version checks, resource cleanup, and platform-specific tests visible. It
also prevents raw pointers and similarly named windows and windows-sys types from spreading
through the rest of the program. A reusable library should apply the same boundary to focused
crates and private windows-bindgen output instead of depending on this umbrella crate.
The remainder of this page is for repository contributors.
The published crate is generated by tool-package, which drives windows-bindgen in --package
mode from crates/tools/package/src/windows.txt. It emits src/Windows/mod.rs and one file per
metadata namespace. src/lib.rs is hand-maintained and supplies the docs.rs stub that redirects to
the external API reference.
The generated Cargo features mirror namespaces and Win32 header groups. Feature dependency edges
are generated from type and namespace dependencies. The crate re-exports windows-core as
windows::core and depends on the focused collections, future, numerics, reference, and time
crates used by the projection.
Do not edit generated source under crates/libs/windows/src/Windows. Change metadata, filters, or
the generator and run the appropriate repository tool.
Run cargo test -p windows; the workspace test crates and Windows samples cover broader API and
projection behavior.