feat(windows-drivers): vendor wdk 0.5.1 + add ApiSubset::Iddcx (M1 spike)
windows-drivers / probe-and-proto (push) Successful in 24s
apple / swift (push) Successful in 1m8s
windows-drivers / driver-build (push) Failing after 43s
ci / rust (push) Successful in 1m31s
ci / web (push) Successful in 1m5s
ci / docs-site (push) Successful in 52s
apple / screenshots (push) Failing after 2m35s
windows-host / package (push) Successful in 5m23s
ci / bench (push) Successful in 4m48s
android / android (push) Successful in 10m1s
decky / build-publish (push) Successful in 26s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 4s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
deb / build-publish (push) Successful in 3m29s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m21s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 8m23s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 8m18s
docker / deploy-docs (push) Successful in 21s

Vendor the published, self-contained windows-drivers-rs 0.5.1 crates
(wdk-build, wdk-sys) under vendor/ and add a first-class ApiSubset::Iddcx that
bindgens iddcx/1.10/IddCx.h in an extra pass reusing bindgen::Builder::wdk_default
(allowlist_file (?i).*iddcx.* — emits only IddCx items; WDF/DXGI types resolve to
the shared base/wdf bindings, type-identity by construction). Mirrors the existing
gpio/hid/spb subsets exactly: wdk-build gets the enum variant + iddcx_headers()
(UMDF-only), wdk-sys gets generate_iddcx + the iddcx feature + pub mod iddcx.
[patch.crates-io] redirects all wdk-sys/wdk-build (incl. wdk 0.4.1 transitive) to
the patched copies. wdk-probe enables the iddcx feature.

MAKE-OR-BREAK: does IddCx.h bindgen in wdk-sys config without a header conflict
(issue #515) + does the generated module compile (type-identity)? CI answers it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-24 14:12:43 +00:00
parent 6975691f7d
commit 9fd19b90a9
38 changed files with 13208 additions and 5 deletions
+106
View File
@@ -0,0 +1,106 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.5.1](https://github.com/microsoft/windows-drivers-rs/compare/wdk-sys-v0.5.0...wdk-sys-v0.5.1) - 2025-11-13
### Other
- fix wdk-build version in readme ([#568](https://github.com/microsoft/windows-drivers-rs/pull/568))
## [0.5.0](https://github.com/microsoft/windows-drivers-rs/compare/wdk-sys-v0.4.0...wdk-sys-v0.5.0) - 2025-11-06
### Added
- enhance error handling with IoError and IoErrorMetadata for improved std::io::Error diagnostics for fs errors ([#480](https://github.com/microsoft/windows-drivers-rs/pull/480))
### Fixed
- use latest version of ucx in the WDKContent as default ([#411](https://github.com/microsoft/windows-drivers-rs/pull/411))
- allow unnecessary_transmutes lint for bindgen-generated types.rs ([#350](https://github.com/microsoft/windows-drivers-rs/pull/350))
### Other
- [**breaking**] bump to Rust 2024 Edition ([#430](https://github.com/microsoft/windows-drivers-rs/pull/430))
- improve logging for build action ([#495](https://github.com/microsoft/windows-drivers-rs/pull/495))
- enforce typo checking ([#452](https://github.com/microsoft/windows-drivers-rs/pull/452))
- Add stubs for __CxxFrameHandler4 and __GSHandlerCheck_EH4 ([#438](https://github.com/microsoft/windows-drivers-rs/pull/438))
## [0.4.0](https://github.com/microsoft/windows-drivers-rs/compare/wdk-sys-v0.3.0...wdk-sys-v0.4.0) - 2025-04-18
### Added
- extend coverage in `wdk-sys` to include usb-related headers ([#296](https://github.com/microsoft/windows-drivers-rs/pull/296))
- expand wdk-sys coverage to include gpio and parallel ports related headers ([#278](https://github.com/microsoft/windows-drivers-rs/pull/278))
- add support for Storage API subset in `wdk-sys` ([#287](https://github.com/microsoft/windows-drivers-rs/pull/287))
- expand `wdk-sys` coverage to include spb-related headers ([#263](https://github.com/microsoft/windows-drivers-rs/pull/263))
- [**breaking**] expand `wdk-sys` coverage to include hid-related headers ([#260](https://github.com/microsoft/windows-drivers-rs/pull/260))
- Use stack-based formatter for debug-printing. ([#233](https://github.com/microsoft/windows-drivers-rs/pull/233))
### Fixed
- passing cache tests when WDK config is enabled ([#332](https://github.com/microsoft/windows-drivers-rs/pull/332))
- [**breaking**] specify rust version & edition to wdk-default bindgen::builder ([#314](https://github.com/microsoft/windows-drivers-rs/pull/314))
- use absolute paths for items used in PAGED_CODE macro ([#297](https://github.com/microsoft/windows-drivers-rs/pull/297))
### Other
- update README to clarify community engagement and contact methods ([#312](https://github.com/microsoft/windows-drivers-rs/pull/312))
- [**breaking**] Remove lazy static instances ([#250](https://github.com/microsoft/windows-drivers-rs/pull/250))
- use `is_none_or` for `clippy::nonminimal_bool` and resolve `clippy::needless_raw_string_hashes` ([#231](https://github.com/microsoft/windows-drivers-rs/pull/231))
## [0.3.0](https://github.com/microsoft/windows-drivers-rs/compare/wdk-sys-v0.2.0...wdk-sys-v0.3.0) - 2024-09-27
### Added
- add more precise NTSTATUS const fns ([#183](https://github.com/microsoft/windows-drivers-rs/pull/183))
- configure WDK configuration via parsing Cargo manifest metadata ([#186](https://github.com/microsoft/windows-drivers-rs/pull/186))
### Fixed
- typos in Getting Started section of README.md ([#213](https://github.com/microsoft/windows-drivers-rs/pull/213))
- [**breaking**] prevent linking of wdk libraries in tests that depend on `wdk-sys` ([#118](https://github.com/microsoft/windows-drivers-rs/pull/118))
### Other
- Improve doc comments to comply with `too_long_first_doc_paragraph` clippy lint ([#202](https://github.com/microsoft/windows-drivers-rs/pull/202))
- Update README.md ([#180](https://github.com/microsoft/windows-drivers-rs/pull/180))
- update readme to call out bugged LLVM 18 versions ([#169](https://github.com/microsoft/windows-drivers-rs/pull/169))
- Build perf: Make calls to bindgen run in parallel ([#159](https://github.com/microsoft/windows-drivers-rs/pull/159))
- Bump rustversion from 1.0.14 to 1.0.15 ([#145](https://github.com/microsoft/windows-drivers-rs/pull/145))
- use a standardized workspace lint table ([#134](https://github.com/microsoft/windows-drivers-rs/pull/134))
- Bump anyhow from 1.0.79 to 1.0.82 ([#140](https://github.com/microsoft/windows-drivers-rs/pull/140))
- Bump thiserror from 1.0.56 to 1.0.59 ([#142](https://github.com/microsoft/windows-drivers-rs/pull/142))
- change version bounds for `manual_c_str_literals` and `ref_as_ptr` clippy lints ([#127](https://github.com/microsoft/windows-drivers-rs/pull/127))
- fix `winget` llvm install command option ([#115](https://github.com/microsoft/windows-drivers-rs/pull/115))
- fix various pipeline breakages (nightly rustfmt bug, new nightly clippy lints, upstream winget dependency issue) ([#117](https://github.com/microsoft/windows-drivers-rs/pull/117))
- add lint exceptions for clippy::manual_c_str_literals and clippy::ref_as_ptr ([#108](https://github.com/microsoft/windows-drivers-rs/pull/108))
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.2.0](https://github/microsoft/windows-drivers-rs/compare/wdk-sys-v0.1.0...wdk-sys-v0.2.0) - 2024-02-08
### Added
- generate CStr for c string constants instead of &[u8] ([#72](https://github/microsoft/windows-drivers-rs/pull/72))
### Fixed
- resolve warnings in rust-script blocks and only fail warnings in CI ([#87](https://github/microsoft/windows-drivers-rs/pull/87))
### Other
- update dependencies
- allow multiple_crate_versions in wdk-build (build dependency) ([#98](https://github/microsoft/windows-drivers-rs/pull/98))
- allow exception for clippy::pub_underscore_fields in generated code ([#77](https://github/microsoft/windows-drivers-rs/pull/77))
- Bump thiserror from 1.0.48 to 1.0.55 ([#59](https://github/microsoft/windows-drivers-rs/pull/59))
- reduce noise from bindgen warnings
- fix clippy errors missed due to buggy ci stage
- restrict to one unsafe operation per block ([#24](https://github/microsoft/windows-drivers-rs/pull/24))
- [**breaking**] enable rustdoc lints and resolve errors
- remove extra keywords in cargo manifests
- initial open-source check in
+859
View File
@@ -0,0 +1,859 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "anstream"
version = "0.6.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys",
]
[[package]]
name = "anyhow"
version = "1.0.97"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
[[package]]
name = "bindgen"
version = "0.71.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3"
dependencies = [
"bitflags",
"cexpr",
"clang-sys",
"itertools",
"log",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn",
]
[[package]]
name = "bitflags"
version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
[[package]]
name = "camino"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3"
dependencies = [
"serde",
]
[[package]]
name = "cargo-platform"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc"
dependencies = [
"serde",
]
[[package]]
name = "cargo_metadata"
version = "0.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba"
dependencies = [
"camino",
"cargo-platform",
"semver",
"serde",
"serde_json",
"thiserror",
]
[[package]]
name = "cc"
version = "1.2.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1d05d92f4b1fd76aad469d46cdd858ca761576082cd37df81416691e50199fb"
dependencies = [
"find-msvc-tools",
"shlex",
]
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
[[package]]
name = "clang-sys"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "clap"
version = "4.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap-cargo"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d546f0e84ff2bfa4da1ce9b54be42285767ba39c688572ca32412a09a73851e5"
dependencies = [
"anstyle",
"clap",
]
[[package]]
name = "clap_builder"
version = "4.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]]
name = "colorchoice"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "errno"
version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "find-msvc-tools"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0399f9d26e5191ce32c498bebd31e7a3ceabc2745f0ac54af3f335126c3f24b3"
[[package]]
name = "fs4"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8640e34b88f7652208ce9e88b1a37a2ae95227d84abec377ccd3c5cfeb141ed4"
dependencies = [
"rustix",
"windows-sys",
]
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "is_terminal_polyfill"
version = "1.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.172"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
[[package]]
name = "libloading"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d"
dependencies = [
"cfg-if",
"windows-targets",
]
[[package]]
name = "linux-raw-sys"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
[[package]]
name = "log"
version = "0.4.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
[[package]]
name = "matchers"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
dependencies = [
"regex-automata",
]
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "nu-ansi-term"
version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
dependencies = [
"windows-sys",
]
[[package]]
name = "once_cell"
version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "once_cell_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "prettyplease"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e"
dependencies = [
"proc-macro2",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
[[package]]
name = "rustc-hash"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
[[package]]
name = "rustix"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "rustversion"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "scratch"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f6280af86e5f559536da57a45ebc84948833b3bee313a7dd25232e09c878a52"
[[package]]
name = "semver"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
dependencies = [
"serde",
]
[[package]]
name = "serde"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "thread_local"
version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
dependencies = [
"cfg-if",
"once_cell",
]
[[package]]
name = "tracing"
version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
dependencies = [
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
dependencies = [
"once_cell",
"valuable",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5"
dependencies = [
"matchers",
"nu-ansi-term",
"once_cell",
"regex-automata",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "wdk-build"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c150122a579af759770b354064cd2994d29e97525d904f65ff1412ad5122766"
dependencies = [
"anyhow",
"bindgen",
"camino",
"cargo_metadata",
"cfg-if",
"clap",
"clap-cargo",
"paste",
"regex",
"rustversion",
"semver",
"serde",
"serde_json",
"thiserror",
"tracing",
"windows",
]
[[package]]
name = "wdk-macros"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b288d5ef6b276345d197fe0b82ef274dcb5a1f658a2294c67ff85b775f63ee26"
dependencies = [
"cfg-if",
"fs4",
"itertools",
"proc-macro2",
"quote",
"scratch",
"serde",
"serde_json",
"syn",
]
[[package]]
name = "wdk-sys"
version = "0.5.1"
dependencies = [
"anyhow",
"bindgen",
"cargo_metadata",
"cc",
"cfg-if",
"rustversion",
"serde_json",
"thiserror",
"tracing",
"tracing-subscriber",
"wdk-build",
"wdk-macros",
]
[[package]]
name = "windows"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
dependencies = [
"windows-core",
"windows-targets",
]
[[package]]
name = "windows-core"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
dependencies = [
"windows-implement",
"windows-interface",
"windows-result",
"windows-strings",
"windows-targets",
]
[[package]]
name = "windows-implement"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-interface"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-result"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-strings"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
dependencies = [
"windows-result",
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+119
View File
@@ -0,0 +1,119 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2024"
name = "wdk-sys"
version = "0.5.1"
build = "build.rs"
links = "wdk"
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "Direct bindings to APIs available in the Windows Development Kit (WDK)"
readme = "README.md"
keywords = [
"wdk",
"windows",
"wdf",
"wdm",
"ffi",
]
categories = [
"external-ffi-bindings",
"development-tools::ffi",
"os::windows-apis",
"os",
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/microsoft/windows-drivers-rs"
[features]
default = []
gpio = []
hid = []
nightly = [
"wdk-macros/nightly",
"wdk-build/nightly",
]
parallel-ports = ["gpio"]
spb = []
storage = []
test-stubs = []
usb = []
iddcx = []
[lib]
name = "wdk_sys"
path = "src/lib.rs"
[dependencies.rustversion]
version = "1.0.20"
[dependencies.wdk-macros]
version = "=0.5.1"
[build-dependencies.anyhow]
version = "1.0.97"
[build-dependencies.bindgen]
version = "0.71.0"
[build-dependencies.cargo_metadata]
version = "0.19.2"
[build-dependencies.cc]
version = "1.2.39"
[build-dependencies.cfg-if]
version = "1.0.3"
[build-dependencies.serde_json]
version = "1.0"
[build-dependencies.thiserror]
version = "2.0.12"
[build-dependencies.tracing]
version = "0.1.40"
[build-dependencies.tracing-subscriber]
version = "0.3.20"
features = ["env-filter"]
[build-dependencies.wdk-build]
version = "0.5.1"
[lints.clippy]
all = "deny"
cargo = "warn"
multiple_unsafe_ops_per_block = "deny"
nursery = "warn"
pedantic = "warn"
undocumented_unsafe_blocks = "deny"
unnecessary_safety_doc = "forbid"
[lints.rust]
missing_docs = "warn"
unsafe_op_in_unsafe_fn = "deny"
[lints.rustdoc]
bare_urls = "warn"
broken_intra_doc_links = "warn"
invalid_codeblock_attributes = "warn"
invalid_html_tags = "warn"
invalid_rust_codeblocks = "warn"
missing_crate_level_docs = "warn"
private_intra_doc_links = "warn"
redundant_explicit_links = "warn"
unescaped_backticks = "warn"
+237
View File
@@ -0,0 +1,237 @@
# windows-drivers-rs
This repo is a collection of Rust crates that enable developers to develop Windows Drivers in Rust. It is the intention to support both WDM and WDF driver development models. This repo contains the following crates:
* [wdk-build](./crates/wdk-build): A library to configure a Cargo build script for binding generation and downstream linking of the WDK (Windows Driver Kit). While this crate is written to be flexible with different WDK releases and different WDF version, it is currently only tested for NI eWDK, KMDF 1.33, UMDF 2.33, and WDM Drivers. There may be missing linker options for older DDKs.
* [wdk-sys](./crates/wdk-sys): Direct FFI bindings to APIs available in the Windows Development Kit (WDK). This includes both autogenerated ffi bindings from `bindgen`, and also manual re-implementations of macros that bindgen fails to generate.
* [wdk](./crates/wdk): Safe idiomatic bindings to APIs available in the Windows Development Kit (WDK)
* [wdk-panic](./crates/wdk-panic/): Default panic handler implementations for programs built with WDK
* [wdk-alloc](./crates/wdk-alloc): alloc support for binaries compiled with the Windows Development Kit (WDK)
* [wdk-macros](./crates/wdk-macros): A collection of macros that help make it easier to interact with wdk-sys's direct bindings. This crate is re-exported via `wdk-sys` and crates should typically never need to directly depend on `wdk-macros`
To see an example of this repo used to create drivers, see [Windows-rust-driver-samples](https://github.com/microsoft/Windows-rust-driver-samples).
Note: This project is still in early stages of development and is not yet recommended for production use. We encourage community experimentation and collaboration through our [GitHub Discussions forum](https://github.com/microsoft/windows-drivers-rs/discussions)!
## <a name="supported-configs">Supported Configurations
This project was built with support of WDM, KMDF, and UMDF drivers in mind, as well as Win32 Services. This includes support for all versions of WDF included in WDK 22H2 and newer. Currently, the crates available on [`crates.io`](https://crates.io) only support KMDF v1.33, but bindings can be generated for everything else by cloning `windows-drivers-rs` and modifying the config specified in [`build.rs` of `wdk-sys`](./crates/wdk-sys/build.rs). Crates.io support for other WDK configurations is planned in the near future.
## Repo Layout
* [crates](./crates): Contains all the main crates that are a part of the Cargo workspace.
* [examples](./examples): Contains workspace-level examples. These examples consist of different types of minimal Windows drivers (ie. WDM, KMDF, UMDF).
* [tests](./tests): Contains workspace-level tests, including tests for metadata-based wdk configuration in packages and workspaces.
**Note:**: Since the workspace level examples and tests use different WDK configurations, and WDR only supports one WDK configuration per workspace, the workspace-level examples and tests folder are excluded from the [repository root's Cargo manifest](./Cargo.toml).
## Getting Started
### Build Requirements
* Binding generation via `bindgen` requires `libclang`. The easiest way to acquire this is via `winget`
* `winget install -i LLVM.LLVM --version 17.0.6 --force`
* Ensure you select the GUI option to add LLVM to the PATH
* LLVM 18 has a bug that causes bindings to fail to generate for ARM64. Continue using LLVM 17 until LLVM 19 comes out with [the fix](https://github.com/llvm/llvm-project/pull/93235). See [this](https://github.com/rust-lang/rust-bindgen/issues/2842) for more details.
* To execute post-build tasks (ie. `inf2cat`, `infverif`, etc.), `cargo make` is used
* `cargo install --locked cargo-make --no-default-features --features tls-native`
* Building programs with the WDK also requires being in a valid WDK environment. The recommended way to do this is to [enter an eWDK developer prompt](https://learn.microsoft.com/en-us/windows-hardware/drivers/develop/using-the-enterprise-wdk#getting-started)
### Adding windows-drivers-rs to Your Driver Package
The crates in this repository are available from [`crates.io`](https://crates.io), but take into account the current limitations outlined in [Supported Configurations](#supported-configs). If you need to support a different config, try cloning this repo and using [path dependencies](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-path-dependencies)
1. Create a new Cargo package with a lib crate:
```pwsh
cargo new <driver_name> --lib
```
1. Add dependencies on `windows-drivers-rs` crates:
```pwsh
cd <driver_name>
cargo add --build wdk-build
cargo add wdk wdk-sys wdk-alloc wdk-panic
```
1. Set the crate type to `cdylib` by adding the following snippet to `Cargo.toml`:
```toml
[lib]
crate-type = ["cdylib"]
```
1. Add a wdk metadata section and configure the wdk for your use case. This also lets the cargo-make tasks know that the package is a driver and that the driver packaging steps need to run.
UMDF Example:
```toml
[package.metadata.wdk.driver-model]
driver-type = "UMDF"
umdf-version-major = 1
target-umdf-version-minor = 33
```
1. **For Kernel Mode crates** (ex. `KMDF` drivers, `WDM` drivers): Set crate panic strategy to `abort` in `Cargo.toml`:
```toml
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
```
1. Create a `build.rs` and add the following snippet:
```rust
fn main() -> Result<(), wdk_build::ConfigError> {
wdk_build::configure_wdk_binary_build()
}
```
1. **For Kernel Mode crates** (ex. `KMDF` drivers, `WDM` drivers): Mark your driver crate as `no_std` in `lib.rs`:
```rust
#![no_std]
```
1. **For Kernel Mode crates** (ex. `KMDF` drivers, `WDM` drivers): Add a panic handler in `lib.rs`:
```rust
#[cfg(not(test))]
extern crate wdk_panic;
```
1. **For Kernel Mode crates** (ex. `KMDF` drivers, `WDM` drivers): Add an optional global allocator in `lib.rs`:
```rust
#[cfg(not(test))]
use wdk_alloc::WdkAllocator;
#[cfg(not(test))]
#[global_allocator]
static GLOBAL_ALLOCATOR: WdkAllocator = WdkAllocator;
```
This is only required if you want to be able to use the [`alloc` modules](https://doc.rust-lang.org/alloc/) in the rust standard library.
1. Add a DriverEntry in `lib.rs`:
```rust
use wdk_sys::{
PDRIVER_OBJECT,
NTSTATUS,
PCUNICODE_STRING,
};
// SAFETY: "DriverEntry" is the required symbol name for Windows driver entry points.
// No other function in this compilation unit exports this name, preventing symbol conflicts.
#[unsafe(export_name = "DriverEntry")] // WDF expects a symbol with the name DriverEntry
pub unsafe extern "system" fn driver_entry(
driver: PDRIVER_OBJECT,
registry_path: PCUNICODE_STRING,
) -> NTSTATUS {
0
}
```
Note: In Kernel Mode crates, you can use `driver: &mut DRIVER_OBJECT` instead of `driver: PDRIVER_OBJECT`.
1. Add a `Makefile.toml`:
```toml
extend = "target/rust-driver-makefile.toml"
[config]
load_script = '''
#!@rust
//! ```cargo
//! [dependencies]
//! wdk-build = "0.5.1"
//! ```
#![allow(unused_doc_comments)]
wdk_build::cargo_make::load_rust_driver_makefile()?
'''
```
1. Add an inx file that matches the name of your `cdylib` crate.
1. Enable static crt linkage. One approach is to add this to your `.cargo/config.toml`:
```toml
[build]
rustflags = ["-C", "target-feature=+crt-static"]
```
1. Build the driver:
```pwsh
cargo make
```
A signed driver package, including a `WDRLocalTestCert.cer` file, will be generated at `target/<Cargo profile>/package`. If a specific target architecture was specified, the driver package will be generated at `target/<target architecture>/<Cargo profile>/package`
Minimal examples of `WDM`, `KMDF`, and `UMDF` drivers can be found in the [examples directory](./examples).
## Cargo Make
[`cargo-make`](https://github.com/sagiegurari/cargo-make) is used to facilitate builds using `windows-drivers-rs`, including for executing post-build driver packaging steps.
To execute the default action (build and package driver):
`cargo make default`
When executing the default task, just `cargo make` make also works since the `default` task is implied.
### Argument Forwarding
`windows-drivers-rs` extends `cargo make` to forward specific arguments to the underlying `cargo` commands. In order to specify arguments to forward, they must be provided **after explicitly specifying the `cargo-make` task name** (ie. omitting the name for the `default` task is not supported).
#### Examples
For a specific target:
`cargo make default --target <TARGET TRIPLE>`
For release builds:
`cargo make default --release` or `cargo make default --profile release`
To specify specific features:
`cargo make default --features <FEATURES>`
To specify a specific rust toolchain:
`cargo make default +<TOOLCHAIN>`
To display help and see the full list of supported CLI args to forward to Cargo:
`cargo make help`
### Driver Package Signature Verification
The `WDK_BUILD_ENABLE_SIGNTOOL_VERIFY` [cargo-make environment variable](https://github.com/sagiegurari/cargo-make?tab=readme-ov-file#environment-variables) can be set to `true` to enable tasks that handle signature verification of the generated `.sys` and `.cat` files. `signtool verify` requires the certificate to be installed as in the `Trusted Root Certification Authorities` for this verification to function. These tasks are not enabled by default as the default behavior of `WDR` is to sign with a generated test certificate. These test certificates are typically only installed into `Trusted Root Certification Authorities` on computers dedicated to testing drivers, and not personal development machines, given the security implications of installing your own root certificates.
If you understand these implications, and have installed the test certificate, then you may validate the signatures as follows:
```
cargo make --env WDK_BUILD_ENABLE_SIGNTOOL_VERIFY=true
```
## Contact
* For bug reports, feature requests, and other actionable items, please use [GitHub Issues](https://github.com/microsoft/windows-drivers-rs/issues)
* For broader questions, architectural discussions, and community engagement, please use [GitHub Discussions](https://github.com/microsoft/windows-drivers-rs/discussions)
* For inquiries not suitable for public forums, email us at <RustWindowsDrivers@microsoft.com>
## Crates.io Release Policy
Releases to crates.io are not made after every change merged to main. Releases will only be made when requested by the community, or when the `windows-drivers-rs` team believes there is sufficient value in pushing a release.
## Trademark Notice
Trademarks This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsofts Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-partys policies.
+799
View File
@@ -0,0 +1,799 @@
// Copyright (c) Microsoft Corporation
// License: MIT OR Apache-2.0
//! Build script for the `wdk-sys` crate.
//!
//! This parses the WDK configuration from metadata provided in the build tree,
//! and generates the relevant bindings to WDK APIs.
use std::{
env,
fs::File,
io::Write,
panic,
path::{Path, PathBuf},
sync::LazyLock,
thread,
};
use anyhow::Context;
use bindgen::CodegenConfig;
use tracing::{Span, info, info_span, trace};
use tracing_subscriber::{
EnvFilter,
filter::{LevelFilter, ParseError},
};
use wdk_build::{
ApiSubset,
BuilderExt,
Config,
ConfigError,
DriverConfig,
IoError,
KmdfConfig,
UmdfConfig,
configure_wdk_library_build_and_then,
};
const OUT_DIR_PLACEHOLDER: &str =
"<PLACEHOLDER FOR LITERAL VALUE CONTAINING OUT_DIR OF wdk-sys CRATE>";
const WDFFUNCTIONS_SYMBOL_NAME_PLACEHOLDER: &str =
"<PLACEHOLDER FOR LITERAL VALUE CONTAINING WDFFUNCTIONS SYMBOL NAME>";
const WDF_FUNCTION_COUNT_PLACEHOLDER: &str =
"<PLACEHOLDER FOR EXPRESSION FOR NUMBER OF WDF FUNCTIONS IN `wdk_sys::WdfFunctions`";
const WDF_FUNCTION_COUNT_DECLARATION_EXTERNAL_SYMBOL: &str =
"// SAFETY: `crate::WdfFunctionCount` is generated as a mutable static, but is not supposed \
to be ever mutated by WDF.
(unsafe { crate::WdfFunctionCount }) as usize";
const WDF_FUNCTION_COUNT_DECLARATION_TABLE_INDEX: &str =
"crate::_WDFFUNCENUM::WdfFunctionTableNumEntries as usize";
static WDF_FUNCTION_COUNT_FUNCTION_TEMPLATE: LazyLock<String> = LazyLock::new(|| {
format!(
r"#[allow(clippy::must_use_candidate)]
/// Returns the number of functions available in the WDF function table.
/// Should not be used in public API.
pub fn get_wdf_function_count() -> usize {{
{WDF_FUNCTION_COUNT_PLACEHOLDER}
}}"
)
});
static CALL_UNSAFE_WDF_BINDING_TEMPLATE: LazyLock<String> = LazyLock::new(|| {
format!(
r#"
/// A procedural macro that allows WDF functions to be called by name.
///
/// This function parses the name of the WDF function, finds it function
/// pointer from the WDF function table, and then calls it with the
/// arguments passed to it
///
/// # Safety
/// Function arguments must abide by any rules outlined in the WDF
/// documentation. This macro does not perform any validation of the
/// arguments passed to it., beyond type validation.
///
/// # Examples
///
/// ```rust, no_run
/// use wdk_sys::*;
///
/// pub unsafe extern "system" fn driver_entry(
/// driver: &mut DRIVER_OBJECT,
/// registry_path: PCUNICODE_STRING,
/// ) -> NTSTATUS {{
///
/// let mut driver_config = WDF_DRIVER_CONFIG {{
/// Size: core::mem::size_of::<WDF_DRIVER_CONFIG>() as ULONG,
/// ..WDF_DRIVER_CONFIG::default()
/// }};
/// let driver_handle_output = WDF_NO_HANDLE as *mut WDFDRIVER;
///
/// unsafe {{
/// call_unsafe_wdf_function_binding!(
/// WdfDriverCreate,
/// driver as PDRIVER_OBJECT,
/// registry_path,
/// WDF_NO_OBJECT_ATTRIBUTES,
/// &mut driver_config,
/// driver_handle_output,
/// )
/// }}
/// }}
/// ```
#[macro_export]
macro_rules! call_unsafe_wdf_function_binding {{
( $($tt:tt)* ) => {{
$crate::__proc_macros::call_unsafe_wdf_function_binding! (
r"{OUT_DIR_PLACEHOLDER}",
$($tt)*
)
}}
}}"#
)
});
static TEST_STUBS_TEMPLATE: LazyLock<String> = LazyLock::new(|| {
format!(
r"
use crate::WDFFUNC;
/// Stubbed version of the symbol that `WdfFunctions` links to so that test targets will compile
// SAFETY: Generated WDF symbol name is required for test compilation and is unique per build.
// No other symbols in this crate export this name, preventing linker conflicts.
#[unsafe(no_mangle)]
pub static mut {WDFFUNCTIONS_SYMBOL_NAME_PLACEHOLDER}: *const WDFFUNC = core::ptr::null();
",
)
});
/// Enabled API subsets based off of cargo-features
const ENABLED_API_SUBSETS: &[ApiSubset] = &[
ApiSubset::Base,
ApiSubset::Wdf,
#[cfg(feature = "gpio")]
ApiSubset::Gpio,
#[cfg(feature = "hid")]
ApiSubset::Hid,
#[cfg(feature = "parallel-ports")]
ApiSubset::ParallelPorts,
#[cfg(feature = "spb")]
ApiSubset::Spb,
#[cfg(feature = "storage")]
ApiSubset::Storage,
#[cfg(feature = "usb")]
ApiSubset::Usb,
#[cfg(feature = "iddcx")]
ApiSubset::Iddcx,
];
type GenerateFn = fn(&Path, &Config) -> Result<(), ConfigError>;
const BINDGEN_FILE_GENERATORS_TUPLES: &[(&str, GenerateFn)] = &[
("constants.rs", generate_constants),
("types.rs", generate_types),
("base.rs", generate_base),
("wdf.rs", generate_wdf),
#[cfg(feature = "gpio")]
("gpio.rs", generate_gpio),
#[cfg(feature = "hid")]
("hid.rs", generate_hid),
#[cfg(feature = "parallel-ports")]
("parallel_ports.rs", generate_parallel_ports),
#[cfg(feature = "spb")]
("spb.rs", generate_spb),
#[cfg(feature = "storage")]
("storage.rs", generate_storage),
#[cfg(feature = "usb")]
("usb.rs", generate_usb),
#[cfg(feature = "iddcx")]
("iddcx.rs", generate_iddcx),
];
fn initialize_tracing() -> Result<(), ParseError> {
let tracing_filter = EnvFilter::default()
// Show up to INFO level by default
.add_directive(LevelFilter::INFO.into())
// Silence various warnings originating from bindgen that are not currently actionable
// FIXME: this currently sets the minimum log level to error for the listed modules. It
// should actually be turning off logging (level=off) for specific warnings in these
// modules, but a bug in the tracing crate's filtering is preventing this from working as expected. See https://github.com/tokio-rs/tracing/issues/2843.
.add_directive("bindgen::codegen::helpers[{message}]=error".parse()?)
.add_directive("bindgen::codegen::struct_layout[{message}]=error".parse()?)
.add_directive("bindgen::ir::comp[{message}]=error".parse()?)
.add_directive("bindgen::ir::context[{message}]=error".parse()?)
.add_directive("bindgen::ir::ty[{message}]=error".parse()?)
.add_directive("bindgen::ir::var[{message}]=error".parse()?);
// Allow overriding tracing behaviour via `EnvFilter::DEFAULT_ENV` env var
let tracing_filter =
if let Ok(filter_directives_from_env_var) = env::var(EnvFilter::DEFAULT_ENV) {
// Append each directive from the env var to the filter
filter_directives_from_env_var.split(',').fold(
tracing_filter,
|tracing_filter, filter_directive| {
match filter_directive.parse() {
Ok(parsed_filter_directive) => {
tracing_filter.add_directive(parsed_filter_directive)
}
Err(parsing_error) => {
// Must use eprintln!() here as tracing is not yet initialized
eprintln!(
"Skipping filter directive, {}, which failed to be parsed from {} \
obtained from {} with the following error: {}",
filter_directive,
filter_directives_from_env_var,
EnvFilter::DEFAULT_ENV,
parsing_error
);
tracing_filter
}
}
},
)
} else {
tracing_filter
};
tracing_subscriber::fmt()
.pretty()
.with_env_filter(tracing_filter)
.with_span_events(tracing_subscriber::fmt::format::FmtSpan::CLOSE)
.init();
Ok(())
}
fn generate_constants(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
info!("Generating bindings to WDK: constants.rs");
let header_contents = config.bindgen_header_contents(ENABLED_API_SUBSETS.iter().copied())?;
trace!(header_contents = ?header_contents);
let bindgen_builder = bindgen::Builder::wdk_default(config)?
.with_codegen_config(CodegenConfig::VARS)
.header_contents("constants-input.h", &header_contents);
trace!(bindgen_builder = ?bindgen_builder);
let output_file_path = out_path.join("constants.rs");
Ok(bindgen_builder
.generate()
.expect("Bindings should succeed to generate")
.write_to_file(&output_file_path)
.map_err(|source| IoError::with_path(output_file_path, source))?)
}
fn generate_types(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
info!("Generating bindings to WDK: types.rs");
let header_contents = config.bindgen_header_contents(ENABLED_API_SUBSETS.iter().copied())?;
trace!(header_contents = ?header_contents);
let bindgen_builder = bindgen::Builder::wdk_default(config)?
.with_codegen_config(CodegenConfig::TYPES)
.header_contents("types-input.h", &header_contents);
trace!(bindgen_builder = ?bindgen_builder);
let output_file_path = out_path.join("types.rs");
Ok(bindgen_builder
.generate()
.expect("Bindings should succeed to generate")
.write_to_file(&output_file_path)
.map_err(|source| IoError::with_path(output_file_path, source))?)
}
fn generate_base(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
let outfile_name = match &config.driver_config {
DriverConfig::Wdm | DriverConfig::Kmdf(_) => "ntddk",
DriverConfig::Umdf(_) => "windows",
};
info!("Generating bindings to WDK: {outfile_name}.rs");
let header_contents = config.bindgen_header_contents([ApiSubset::Base])?;
trace!(header_contents = ?header_contents);
let bindgen_builder = bindgen::Builder::wdk_default(config)?
.with_codegen_config((CodegenConfig::TYPES | CodegenConfig::VARS).complement())
.header_contents(&format!("{outfile_name}-input.h"), &header_contents);
trace!(bindgen_builder = ?bindgen_builder);
let output_file_path = out_path.join(format!("{outfile_name}.rs"));
Ok(bindgen_builder
.generate()
.expect("Bindings should succeed to generate")
.write_to_file(&output_file_path)
.map_err(|source| IoError::with_path(output_file_path, source))?)
}
fn generate_wdf(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
if let DriverConfig::Kmdf(_) | DriverConfig::Umdf(_) = config.driver_config {
info!("Generating bindings to WDK: wdf.rs");
let header_contents = config.bindgen_header_contents([ApiSubset::Base, ApiSubset::Wdf])?;
trace!(header_contents = ?header_contents);
let bindgen_builder = bindgen::Builder::wdk_default(config)?
.with_codegen_config((CodegenConfig::TYPES | CodegenConfig::VARS).complement())
.header_contents("wdf-input.h", &header_contents)
// Only generate for files that are prefixed with (case-insensitive) wdf (ie.
// /some/path/WdfSomeHeader.h), to prevent duplication of code in ntddk.rs
.allowlist_file("(?i).*wdf.*");
trace!(bindgen_builder = ?bindgen_builder);
let output_file_path = out_path.join("wdf.rs");
Ok(bindgen_builder
.generate()
.expect("Bindings should succeed to generate")
.write_to_file(&output_file_path)
.map_err(|source| IoError::with_path(output_file_path, source))?)
} else {
info!(
"Skipping wdf.rs generation since driver_config is {:#?}",
config.driver_config
);
Ok(())
}
}
#[cfg(feature = "gpio")]
fn generate_gpio(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
info!("Generating bindings to WDK: gpio.rs");
let header_contents =
config.bindgen_header_contents([ApiSubset::Base, ApiSubset::Wdf, ApiSubset::Gpio])?;
trace!(header_contents = ?header_contents);
let bindgen_builder = {
let mut builder = bindgen::Builder::wdk_default(config)?
.with_codegen_config((CodegenConfig::TYPES | CodegenConfig::VARS).complement())
.header_contents("gpio-input.h", &header_contents);
// Only allowlist files in the gpio-specific files to avoid
// duplicate definitions
for header_file in config.headers(ApiSubset::Gpio)? {
builder = builder.allowlist_file(format!("(?i).*{header_file}.*"));
}
builder
};
trace!(bindgen_builder = ?bindgen_builder);
let output_file_path = out_path.join("gpio.rs");
Ok(bindgen_builder
.generate()
.expect("Bindings should succeed to generate")
.write_to_file(&output_file_path)
.map_err(|source| IoError::with_path(output_file_path, source))?)
}
#[cfg(feature = "iddcx")]
fn generate_iddcx(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
info!("Generating bindings to WDK: iddcx.rs");
let header_contents =
config.bindgen_header_contents([ApiSubset::Base, ApiSubset::Wdf, ApiSubset::Iddcx])?;
trace!(header_contents = ?header_contents);
let bindgen_builder = {
bindgen::Builder::wdk_default(config)?
.with_codegen_config((CodegenConfig::TYPES | CodegenConfig::VARS).complement())
.header_contents("iddcx-input.h", &header_contents)
// Allowlist by the "iddcx" path component (separator-agnostic) so ONLY IddCx items are
// emitted; the WDF/Win/DXGI types they reference RESOLVE to the shared base/wdf bindings
// instead of being redefined.
.allowlist_file("(?i).*iddcx.*")
};
trace!(bindgen_builder = ?bindgen_builder);
let output_file_path = out_path.join("iddcx.rs");
Ok(bindgen_builder
.generate()
.expect("Bindings should succeed to generate")
.write_to_file(&output_file_path)
.map_err(|source| IoError::with_path(output_file_path, source))?)
}
#[cfg(feature = "hid")]
fn generate_hid(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
info!("Generating bindings to WDK: hid.rs");
let header_contents =
config.bindgen_header_contents([ApiSubset::Base, ApiSubset::Wdf, ApiSubset::Hid])?;
trace!(header_contents = ?header_contents);
let bindgen_builder = {
let mut builder = bindgen::Builder::wdk_default(config)?
.with_codegen_config((CodegenConfig::TYPES | CodegenConfig::VARS).complement())
.header_contents("hid-input.h", &header_contents);
// Only allowlist files in the hid-specific files to avoid
// duplicate definitions
for header_file in config.headers(ApiSubset::Hid)? {
builder = builder.allowlist_file(format!("(?i).*{header_file}.*"));
}
builder
};
trace!(bindgen_builder = ?bindgen_builder);
let output_file_path = out_path.join("hid.rs");
Ok(bindgen_builder
.generate()
.expect("Bindings should succeed to generate")
.write_to_file(&output_file_path)
.map_err(|source| IoError::with_path(output_file_path, source))?)
}
#[cfg(feature = "parallel-ports")]
fn generate_parallel_ports(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
info!("Generating bindings to WDK: parallel_ports.rs");
let header_contents = config.bindgen_header_contents([
ApiSubset::Base,
ApiSubset::Wdf,
ApiSubset::ParallelPorts,
])?;
trace!(header_contents = ?header_contents);
let bindgen_builder = {
let mut builder = bindgen::Builder::wdk_default(config)?
.with_codegen_config((CodegenConfig::TYPES | CodegenConfig::VARS).complement())
.header_contents("parallel-ports-input.h", &header_contents);
// Only allowlist files in the parallel-ports-specific files to
// avoid duplicate definitions
for header_file in config.headers(ApiSubset::ParallelPorts)? {
builder = builder.allowlist_file(format!("(?i).*{header_file}.*"));
}
builder
};
trace!(bindgen_builder = ?bindgen_builder);
let output_file_path = out_path.join("parallel_ports.rs");
Ok(bindgen_builder
.generate()
.expect("Bindings should succeed to generate")
.write_to_file(&output_file_path)
.map_err(|source| IoError::with_path(output_file_path, source))?)
}
#[cfg(feature = "spb")]
fn generate_spb(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
info!("Generating bindings to WDK: spb.rs");
let header_contents =
config.bindgen_header_contents([ApiSubset::Base, ApiSubset::Wdf, ApiSubset::Spb])?;
trace!(header_contents = ?header_contents);
let bindgen_builder = {
let mut builder = bindgen::Builder::wdk_default(config)?
.with_codegen_config((CodegenConfig::TYPES | CodegenConfig::VARS).complement())
.header_contents("spb-input.h", &header_contents);
// Only allowlist files in the spb-specific files to avoid
// duplicate definitions
for header_file in config.headers(ApiSubset::Spb)? {
builder = builder.allowlist_file(format!("(?i).*{header_file}.*"));
}
builder
};
trace!(bindgen_builder = ?bindgen_builder);
let output_file_path = out_path.join("spb.rs");
Ok(bindgen_builder
.generate()
.expect("Bindings should succeed to generate")
.write_to_file(&output_file_path)
.map_err(|source| IoError::with_path(output_file_path, source))?)
}
#[cfg(feature = "storage")]
fn generate_storage(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
info!("Generating bindings to WDK: storage.rs");
let header_contents =
config.bindgen_header_contents([ApiSubset::Base, ApiSubset::Wdf, ApiSubset::Storage])?;
trace!(header_contents = ?header_contents);
let bindgen_builder = {
let mut builder = bindgen::Builder::wdk_default(config)?
.with_codegen_config((CodegenConfig::TYPES | CodegenConfig::VARS).complement())
.header_contents("storage-input.h", &header_contents);
// Only allowlist files in the storage-specific files to avoid
// duplicate definitions
for header_file in config.headers(ApiSubset::Storage)? {
builder = builder.allowlist_file(format!("(?i).*{header_file}.*"));
}
builder
};
trace!(bindgen_builder = ?bindgen_builder);
let output_file_path = out_path.join("storage.rs");
Ok(bindgen_builder
.generate()
.expect("Bindings should succeed to generate")
.write_to_file(&output_file_path)
.map_err(|source| IoError::with_path(output_file_path, source))?)
}
#[cfg(feature = "usb")]
fn generate_usb(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
info!("Generating bindings to WDK: usb.rs");
let header_contents =
config.bindgen_header_contents([ApiSubset::Base, ApiSubset::Wdf, ApiSubset::Usb])?;
trace!(header_contents = ?header_contents);
let bindgen_builder = {
let mut builder = bindgen::Builder::wdk_default(config)?
.with_codegen_config((CodegenConfig::TYPES | CodegenConfig::VARS).complement())
.header_contents("usb-input.h", &header_contents);
// Only allowlist files in the usb-specific files to avoid
// duplicate definitions
for header_file in config.headers(ApiSubset::Usb)? {
builder = builder.allowlist_file(format!("(?i).*{header_file}.*"));
}
builder
};
trace!(bindgen_builder = ?bindgen_builder);
let output_file_path = out_path.join("usb.rs");
Ok(bindgen_builder
.generate()
.expect("Bindings should succeed to generate")
.write_to_file(&output_file_path)
.map_err(|source| IoError::with_path(output_file_path, source))?)
}
/// Generates a `wdf_function_count.rs` file in `OUT_DIR` which contains the
/// definition of the function `get_wdf_function_count()`. This is required to
/// be generated here since the size of the table is derived from either a
/// global symbol that newer WDF versions expose, or an enum that older versions
/// use.
fn generate_wdf_function_count(out_path: &Path, config: &Config) -> Result<(), IoError> {
const MINIMUM_MINOR_VERSION_TO_GENERATE_WDF_FUNCTION_COUNT: u8 = 25;
let generated_file_path = out_path.join("wdf_function_count.rs");
let mut generated_file = File::create(&generated_file_path)
.map_err(|source| IoError::with_path(&generated_file_path, source))?;
let is_wdf_function_count_generated = match *config {
Config {
driver_config:
DriverConfig::Kmdf(KmdfConfig {
kmdf_version_major,
target_kmdf_version_minor,
..
}),
..
} => {
kmdf_version_major >= 1
&& target_kmdf_version_minor >= MINIMUM_MINOR_VERSION_TO_GENERATE_WDF_FUNCTION_COUNT
}
Config {
driver_config:
DriverConfig::Umdf(UmdfConfig {
umdf_version_major,
target_umdf_version_minor,
..
}),
..
} => {
umdf_version_major >= 2
&& target_umdf_version_minor >= MINIMUM_MINOR_VERSION_TO_GENERATE_WDF_FUNCTION_COUNT
}
_ => {
unreachable!(
"generate_wdf_function_table is only called with WDF driver configurations"
)
}
};
let wdf_function_table_count_snippet = WDF_FUNCTION_COUNT_FUNCTION_TEMPLATE.replace(
WDF_FUNCTION_COUNT_PLACEHOLDER,
if is_wdf_function_count_generated {
WDF_FUNCTION_COUNT_DECLARATION_EXTERNAL_SYMBOL
} else {
WDF_FUNCTION_COUNT_DECLARATION_TABLE_INDEX
},
);
generated_file
.write_all(wdf_function_table_count_snippet.as_bytes())
.map_err(|source| IoError::with_path(generated_file_path, source))?;
Ok(())
}
/// Generates a `macros.rs` file in `OUT_DIR` which contains a
/// `call_unsafe_wdf_function_binding!` macro that redirects to the
/// `wdk_macros::call_unsafe_wdf_function_binding` `proc_macro` . This is
/// required in order to add an additional argument with the path to the file
/// containing generated types. There is currently no other way to pass
/// `OUT_DIR` of `wdk-sys` to the `proc_macro`.
fn generate_call_unsafe_wdf_function_binding_macro(out_path: &Path) -> Result<(), IoError> {
let generated_file_path = out_path.join("call_unsafe_wdf_function_binding.rs");
let mut generated_file = File::create(&generated_file_path)
.map_err(|source| IoError::with_path(&generated_file_path, source))?;
generated_file
.write_all(
CALL_UNSAFE_WDF_BINDING_TEMPLATE
.replace(
OUT_DIR_PLACEHOLDER,
out_path.join("types.rs").to_str().expect(
"path to file with generated type information should successfully convert \
to a str",
),
)
.as_bytes(),
)
.map_err(|source| IoError::with_path(generated_file_path, source))?;
Ok(())
}
/// Generates a `test_stubs.rs` file in `OUT_DIR` which contains stubs required
/// for tests to compile. This should only generate the stubs whose names are
/// dependent on the WDK configuration, and would otherwise be impossible to
/// just include in `src/test_stubs.rs` directly.
fn generate_test_stubs(out_path: &Path, config: &Config) -> Result<(), IoError> {
let stubs_file_path = out_path.join("test_stubs.rs");
let mut stubs_file = File::create(&stubs_file_path)
.map_err(|source| IoError::with_path(&stubs_file_path, source))?;
stubs_file
.write_all(
TEST_STUBS_TEMPLATE
.replace(
WDFFUNCTIONS_SYMBOL_NAME_PLACEHOLDER,
&config.compute_wdffunctions_symbol_name().expect(
"KMDF and UMDF configs should always have a computable WdfFunctions \
symbol name",
),
)
.as_bytes(),
)
.map_err(|source| IoError::with_path(stubs_file_path, source))?;
Ok(())
}
/// Starts parallel bindgen tasks for generating binding files.
fn start_bindgen_tasks<'scope>(
thread_scope: &'scope thread::Scope<'scope, '_>,
out_path: &'scope Path,
config: &'scope Config,
thread_join_handles: &mut Vec<thread::ScopedJoinHandle<'scope, Result<(), ConfigError>>>,
) {
info_span!("bindgen generation").in_scope(|| {
for (file_name, generate_function) in BINDGEN_FILE_GENERATORS_TUPLES {
let current_span = Span::current();
thread_join_handles.push(
thread::Builder::new()
.name(format!("bindgen {file_name} generator"))
.spawn_scoped(thread_scope, move || {
// Parent span must be manually set since spans do not persist across thread boundaries: https://github.com/tokio-rs/tracing/issues/1391
info_span!(parent: &current_span, "worker thread", generated_file_name = file_name).in_scope(|| generate_function(out_path, config))
})
.expect("Scoped Thread should spawn successfully"),
);
}
});
}
/// Starts a task that compiles a C shim to expose WDF symbols hidden by
/// `__declspec(selectany)`.
fn start_wdf_symbol_export_tasks<'scope>(
thread_scope: &'scope thread::Scope<'scope, '_>,
out_path: &'scope Path,
config: &'scope Config,
thread_join_handles: &mut Vec<thread::ScopedJoinHandle<'scope, Result<(), ConfigError>>>,
) {
let current_span = Span::current();
// Compile a c library to expose symbols that are not exposed because of
// __declspec(selectany)
thread_join_handles.push(
thread::Builder::new()
.name("wdf.c cc compilation".to_string())
.spawn_scoped(thread_scope, move || {
// Parent span must be manually set since spans do not persist across thread boundaries: https://github.com/tokio-rs/tracing/issues/1391
info_span!(parent: current_span, "cc").in_scope(|| {
info!("Compiling wdf.c");
// Write all included headers into wdf.c (existing file, if present
// (i.e. incremental rebuild), is truncated)
let wdf_c_file_path = out_path.join("wdf.c");
{
let mut wdf_c_file = File::create(&wdf_c_file_path)
.map_err(|source| IoError::with_path(&wdf_c_file_path, source))?;
wdf_c_file
.write_all(
config
// This should include the entirety of the `ENABLED_API_SUBSETS`, but this is currently blocked by issues with mutually exclusive headers: https://github.com/microsoft/windows-drivers-rs/issues/515
.bindgen_header_contents([
ApiSubset::Base,
ApiSubset::Wdf,
#[cfg(feature = "hid")]
ApiSubset::Hid,
#[cfg(feature = "spb")]
ApiSubset::Spb,
])?
.as_bytes(),
)
.map_err(|source| IoError::with_path(&wdf_c_file_path, source))?;
// Explicitly sync_all to surface any IO errors (File::drop
// silently ignores close errors)
wdf_c_file
.sync_all()
.map_err(|source| IoError::with_path(&wdf_c_file_path, source))?;
}
let mut cc_builder = cc::Build::new();
for (key, value) in config.preprocessor_definitions() {
cc_builder.define(&key, value.as_deref());
}
cc_builder
.includes(config.include_paths()?)
.file(wdf_c_file_path)
.compile("wdf");
Ok::<(), ConfigError>(())
})
})
.expect("Scoped Thread should spawn successfully"),
);
}
/// Starts generation/compilation tasks for WDF-specific artifacts for driver
/// configurations.
///
/// Uses the `start_*_tasks` naming convention: dispatches work to scoped
/// threads and returns after scheduling.
fn start_wdf_artifact_tasks<'scope>(
thread_scope: &'scope thread::Scope<'scope, '_>,
out_path: &'scope Path,
config: &'scope Config,
thread_join_handles: &mut Vec<thread::ScopedJoinHandle<'scope, Result<(), ConfigError>>>,
) -> anyhow::Result<()> {
if let DriverConfig::Kmdf(_) | DriverConfig::Umdf(_) = config.driver_config {
start_wdf_symbol_export_tasks(thread_scope, out_path, config, thread_join_handles);
info_span!("wdf_function_count.rs generation")
.in_scope(|| generate_wdf_function_count(out_path, config))?;
info_span!("call_unsafe_wdf_function_binding.rs generation")
.in_scope(|| generate_call_unsafe_wdf_function_binding_macro(out_path))?;
info_span!("test_stubs.rs generation")
.in_scope(|| generate_test_stubs(out_path, config))?;
}
Ok(())
}
/// Joins all worker threads and collects their results
fn join_worker_threads(
thread_join_handles: Vec<thread::ScopedJoinHandle<'_, Result<(), ConfigError>>>,
) -> anyhow::Result<()> {
for join_handle in thread_join_handles {
let thread_name = join_handle.thread().name().unwrap_or("UNNAMED").to_string();
match join_handle.join() {
// Forward panics to the main thread
Err(panic_payload) => {
panic::resume_unwind(panic_payload);
}
Ok(thread_result) => {
thread_result.with_context(|| {
format!(r#""{thread_name}" thread failed to exit successfully"#)
})?;
}
}
}
Ok(())
}
fn main() -> anyhow::Result<()> {
initialize_tracing()?;
configure_wdk_library_build_and_then(|config| {
let out_path = PathBuf::from(
env::var("OUT_DIR").expect("OUT_DIR should be exist in Cargo build environment"),
);
thread::scope(|thread_scope| {
let mut thread_join_handles = Vec::new();
start_bindgen_tasks(thread_scope, &out_path, &config, &mut thread_join_handles);
start_wdf_artifact_tasks(thread_scope, &out_path, &config, &mut thread_join_handles)?;
join_worker_threads(thread_join_handles)
})?;
Ok::<(), anyhow::Error>(())
})?;
Ok(())
}
File diff suppressed because it is too large Load Diff
+37
View File
@@ -0,0 +1,37 @@
// Copyright (c) Microsoft Corporation
// License: MIT OR Apache-2.0
//! Direct FFI bindings to GPIO APIs from the Windows Driver Kit (WDK)
//!
//! This module contains all bindings to functions, constants, methods,
//! constructors and destructors in the following headers: `gpio.h`,
//! `gpioclx.h`. Types are not included in this module, but are available in the
//! top-level `wdk_sys` module.
#[allow(
missing_docs,
reason = "most items in the WDK headers have no inline documentation, so bindgen is unable to \
generate documentation for their bindings"
)]
mod bindings {
#[allow(
clippy::wildcard_imports,
reason = "the underlying c code relies on all type definitions being in scope, which \
results in the bindgen generated code relying on the generated types being in \
scope as well"
)]
#[allow(
unused_imports,
reason = "in certain versions of the WDK, there are no functions related to GPIO that can \
be generated by bindgen, so these types are unused"
)]
use crate::types::*;
include!(concat!(env!("OUT_DIR"), "/gpio.rs"));
}
#[allow(
unused_imports,
reason = "in certain versions of the WDK, there are no functions related to GPIO that can be \
generated by bindgen, so the `bindings` module is empty"
)]
pub use bindings::*;
+28
View File
@@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation
// License: MIT OR Apache-2.0
//! Direct FFI bindings to HID APIs from the Windows Driver Kit (WDK)
//!
//! This module contains all bindings to functions, constants, methods,
//! constructors and destructors in the following headers: `hidpddi.h`,
//! `hidport.h`, `HidSpiCx/1.0/hidspicx.h`, `kbdmou.h`, `ntdd8042.h`,
//! `hidclass.h`, `hidsdi.h`, `hidpi.h`, `vhf.h`. Types are not included in this
//! module, but are available in the top-level `wdk_sys` module.
#[allow(
missing_docs,
reason = "most items in the WDK headers have no inline documentation, so bindgen is unable to \
generate documentation for their bindings"
)]
mod bindings {
#[allow(
clippy::wildcard_imports,
reason = "the underlying c code relies on all type definitions being in scope, which \
results in the bindgen generated code relying on the generated types being in \
scope as well"
)]
use crate::types::*;
include!(concat!(env!("OUT_DIR"), "/hid.rs"));
}
pub use bindings::*;
+36
View File
@@ -0,0 +1,36 @@
// Copyright (c) Microsoft Corporation
// License: MIT OR Apache-2.0
//! Direct FFI bindings to IddCx APIs from the Windows Driver Kit (WDK)
//!
//! This module contains all bindings to functions, constants, methods,
//! constructors and destructors in the following headers: `iddcx/1.10/IddCx.h`. Types are not included in this module, but are available in the
//! top-level `wdk_sys` module.
#[allow(
missing_docs,
reason = "most items in the WDK headers have no inline documentation, so bindgen is unable to \
generate documentation for their bindings"
)]
mod bindings {
#[allow(
clippy::wildcard_imports,
reason = "the underlying c code relies on all type definitions being in scope, which \
results in the bindgen generated code relying on the generated types being in \
scope as well"
)]
#[allow(
unused_imports,
reason = "in certain versions of the WDK, there are no functions related to IddCx that can \
be generated by bindgen, so these types are unused"
)]
use crate::types::*;
include!(concat!(env!("OUT_DIR"), "/iddcx.rs"));
}
#[allow(
unused_imports,
reason = "in certain versions of the WDK, there are no functions related to IddCx that can be \
generated by bindgen, so the `bindings` module is empty"
)]
pub use bindings::*;
+242
View File
@@ -0,0 +1,242 @@
// Copyright (c) Microsoft Corporation
// License: MIT OR Apache-2.0
//! Direct bindings to APIs available in the Windows Development Kit (WDK)
#![no_std]
#[cfg(any(
driver_model__driver_type = "WDM",
driver_model__driver_type = "KMDF",
driver_model__driver_type = "UMDF"
))]
#[doc(hidden)]
pub use wdk_macros as __proc_macros;
#[cfg(any(
driver_model__driver_type = "WDM",
driver_model__driver_type = "KMDF",
driver_model__driver_type = "UMDF"
))]
pub use crate::{constants::*, types::*};
#[cfg(any(driver_model__driver_type = "WDM", driver_model__driver_type = "KMDF"))]
pub mod ntddk;
#[cfg(driver_model__driver_type = "UMDF")]
pub mod windows;
#[cfg(any(driver_model__driver_type = "KMDF", driver_model__driver_type = "UMDF"))]
pub mod wdf;
#[cfg(all(
any(
driver_model__driver_type = "WDM",
driver_model__driver_type = "KMDF",
driver_model__driver_type = "UMDF"
),
feature = "gpio"
))]
pub mod gpio;
#[cfg(all(
any(
driver_model__driver_type = "WDM",
driver_model__driver_type = "KMDF",
driver_model__driver_type = "UMDF"
),
feature = "hid"
))]
pub mod hid;
#[cfg(all(
any(
driver_model__driver_type = "WDM",
driver_model__driver_type = "KMDF",
driver_model__driver_type = "UMDF"
),
feature = "parallel-ports"
))]
pub mod parallel_ports;
#[cfg(all(
any(
driver_model__driver_type = "WDM",
driver_model__driver_type = "KMDF",
driver_model__driver_type = "UMDF"
),
feature = "spb"
))]
pub mod spb;
#[cfg(all(
any(
driver_model__driver_type = "WDM",
driver_model__driver_type = "KMDF",
driver_model__driver_type = "UMDF"
),
feature = "storage"
))]
pub mod storage;
#[cfg(all(
any(
driver_model__driver_type = "WDM",
driver_model__driver_type = "KMDF",
driver_model__driver_type = "UMDF"
),
feature = "usb"
))]
pub mod usb;
#[cfg(all(driver_model__driver_type = "UMDF", feature = "iddcx"))]
pub mod iddcx;
#[cfg(feature = "test-stubs")]
pub mod test_stubs;
#[cfg(any(
driver_model__driver_type = "WDM",
driver_model__driver_type = "KMDF",
driver_model__driver_type = "UMDF"
))]
mod constants;
#[cfg(any(
driver_model__driver_type = "WDM",
driver_model__driver_type = "KMDF",
driver_model__driver_type = "UMDF"
))]
mod types;
#[cfg(any(
driver_model__driver_type = "WDM",
driver_model__driver_type = "KMDF",
driver_model__driver_type = "UMDF"
))]
mod macros;
// This is fine because we don't actually have any floating point instruction in
// our binary, thanks to our target defining soft-floats. fltused symbol is
// necessary due to LLVM being too eager to set it: it checks the LLVM IR for
// floating point instructions - even if soft-float is enabled!
#[allow(missing_docs)]
// SAFETY: _fltused is a required Windows linker symbol for floating point support.
// No other symbols in this crate export this name, preventing linker conflicts.
#[unsafe(no_mangle)]
pub static _fltused: () = ();
// FIXME: Is there any way to avoid these stubs? See https://github.com/rust-lang/rust/issues/101134
#[cfg(panic = "abort")]
#[allow(missing_docs)]
// SAFETY: __CxxFrameHandler3 is a required Windows C++ exception handler symbol.
// No other symbols in this crate export this name, preventing linker conflicts.
#[unsafe(no_mangle)]
pub const extern "system" fn __CxxFrameHandler3() -> i32 {
0
}
#[cfg(panic = "abort")]
#[allow(missing_docs)]
// SAFETY: __CxxFrameHandler4 is a required Windows C++ exception handler symbol.
// No other symbols in this crate export this name, preventing linker conflicts.
#[unsafe(no_mangle)]
pub const extern "system" fn __CxxFrameHandler4() -> i32 {
// This is a stub for the C++ exception handling frame handler. It's never
// called but it needs to be distinct from __CxxFrameHandler3 to not confuse
// binary analysis tools. We return a different value to prevent folding.
1
}
#[cfg(panic = "abort")]
#[allow(missing_docs)]
// SAFETY: __GSHandlerCheck_EH4 is a required Windows C++ exception handler symbol.
// No other symbols in this crate export this name, preventing linker conflicts.
#[unsafe(no_mangle)]
pub const extern "system" fn __GSHandlerCheck_EH4() -> i32 {
// This is a stub for the C++ exception handling frame handler. It's never
// called but it needs to be distinct from __CxxFrameHandler3 and
// __CxxFrameHandler4 to not confuse binary analysis tools. We return a
// different value to prevent folding.
2
}
#[cfg(any(
driver_model__driver_type = "WDM",
driver_model__driver_type = "KMDF",
driver_model__driver_type = "UMDF"
))]
#[must_use]
#[allow(non_snake_case)]
/// Evaluates to TRUE if the return value specified by `nt_status` is a success
/// type (0 0x3FFFFFFF) or an informational type (0x40000000 0x7FFFFFFF).
/// This function is taken from ntdef.h in the WDK.
///
/// See the [NTSTATUS reference](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/87fba13e-bf06-450e-83b1-9241dc81e781) and
/// [Using NTSTATUS values](https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values) for details.
pub const fn NT_SUCCESS(nt_status: NTSTATUS) -> bool {
nt_status >= 0
}
#[cfg(any(
driver_model__driver_type = "WDM",
driver_model__driver_type = "KMDF",
driver_model__driver_type = "UMDF"
))]
#[must_use]
#[allow(non_snake_case)]
#[allow(clippy::cast_sign_loss)]
/// Evaluates to TRUE if the return value specified by `nt_status` is an
/// informational type (0x40000000 0x7FFFFFFF). This function is taken from
/// ntdef.h in the WDK.
///
/// See the [NTSTATUS reference](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/87fba13e-bf06-450e-83b1-9241dc81e781) and
/// [Using NTSTATUS values](https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values) for details.
pub const fn NT_INFORMATION(nt_status: NTSTATUS) -> bool {
(nt_status as u32 >> 30) == 1
}
#[cfg(any(
driver_model__driver_type = "WDM",
driver_model__driver_type = "KMDF",
driver_model__driver_type = "UMDF"
))]
#[must_use]
#[allow(non_snake_case)]
#[allow(clippy::cast_sign_loss)]
/// Evaluates to TRUE if the return value specified by `nt_status` is a warning
/// type (0x80000000 0xBFFFFFFF). This function is taken from ntdef.h in the
/// WDK.
///
/// See the [NTSTATUS reference](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/87fba13e-bf06-450e-83b1-9241dc81e781) and
/// [Using NTSTATUS values](https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values) for details.
pub const fn NT_WARNING(nt_status: NTSTATUS) -> bool {
(nt_status as u32 >> 30) == 2
}
#[cfg(any(
driver_model__driver_type = "WDM",
driver_model__driver_type = "KMDF",
driver_model__driver_type = "UMDF"
))]
#[must_use]
#[allow(non_snake_case)]
#[allow(clippy::cast_sign_loss)]
/// Evaluates to TRUE if the return value specified by `nt_status` is an error
/// type (0xC0000000 - 0xFFFFFFFF). This function is taken from ntdef.h in the
/// WDK.
///
/// See the [NTSTATUS reference](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/87fba13e-bf06-450e-83b1-9241dc81e781) and
/// [Using NTSTATUS values](https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values) for details.
pub const fn NT_ERROR(nt_status: NTSTATUS) -> bool {
(nt_status as u32 >> 30) == 3
}
#[cfg(any(driver_model__driver_type = "WDM", driver_model__driver_type = "KMDF"))]
#[allow(missing_docs)]
#[macro_export]
#[allow(non_snake_case)]
macro_rules! PAGED_CODE {
() => {
debug_assert!(unsafe { $crate::ntddk::KeGetCurrentIrql() <= $crate::APC_LEVEL as u8 });
};
}
+14
View File
@@ -0,0 +1,14 @@
// Copyright (c) Microsoft Corporation
// License: MIT OR Apache-2.0
//! Macros for use in the `wdk-sys` crate. This is especially useful for
//! interacting with WDK apis which are inlined, and so are impossible to
//! generate with [bindgen](https://docs.rs/bindgen/latest/bindgen/).
#[cfg(any(driver_model__driver_type = "KMDF", driver_model__driver_type = "UMDF"))]
mod wdf {
include!(concat!(
env!("OUT_DIR"),
"/call_unsafe_wdf_function_binding.rs"
));
}
+24
View File
@@ -0,0 +1,24 @@
// Copyright (c) Microsoft Corporation
// License: MIT OR Apache-2.0
//! Direct FFI bindings to NTDDK APIs from the Windows Driver Kit (WDK)
//!
//! This module contains all bindings to functions, constants, methods,
//! constructors and destructors in `ntddk.h`. Types are not included in this
//! module, but are available in the top-level `wdk_sys` module.
pub use bindings::*;
#[allow(missing_docs)]
#[allow(clippy::derive_partial_eq_without_eq)]
mod bindings {
#[allow(
clippy::wildcard_imports,
reason = "the underlying c code relies on all type definitions being in scope, which \
results in the bindgen generated code relying on the generated types being in \
scope as well"
)]
use crate::types::*;
include!(concat!(env!("OUT_DIR"), "/ntddk.rs"));
}
@@ -0,0 +1,37 @@
// Copyright (c) Microsoft Corporation
// License: MIT OR Apache-2.0
//! Direct FFI bindings to Parallel Ports APIs from the Windows Driver Kit (WDK)
//!
//! This module contains all bindings to functions, constants, methods,
//! constructors and destructors in the following headers: `ntddpar.h`,
//! `ntddser.h`, `parallel.h`. Types are not included in this module, but are
//! available in the top-level `wdk_sys` module.
#[allow(
missing_docs,
reason = "most items in the WDK headers have no inline documentation, so bindgen is unable to \
generate documentation for their bindings"
)]
mod bindings {
#[allow(
clippy::wildcard_imports,
reason = "the underlying c code relies on all type definitions being in scope, which \
results in the bindgen generated code relying on the generated types being in \
scope as well"
)]
#[allow(
unused_imports,
reason = "in certain versions of the WDK, there are no functions related to SPB that can \
be generated by bindgen, so these types are unused"
)]
use crate::types::*;
include!(concat!(env!("OUT_DIR"), "/parallel_ports.rs"));
}
#[allow(
unused_imports,
reason = "in certain versions of the WDK, there are no functions related to SPB that can be \
generated by bindgen, so the `bindings` module is empty"
)]
pub use bindings::*;
+37
View File
@@ -0,0 +1,37 @@
// Copyright (c) Microsoft Corporation
// License: MIT OR Apache-2.0
//! Direct FFI bindings to SPB APIs from the Windows Driver Kit (WDK)
//!
//! This module contains all bindings to functions, constants, methods,
//! constructors and destructors in the following headers: `spb.h`, `spbcx.h`,
//! `reshub.h`, `pwmutil.h`. Types are not included in this module, but are
//! available in the top-level `wdk_sys` module.
#[allow(
missing_docs,
reason = "most items in the WDK headers have no inline documentation, so bindgen is unable to \
generate documentation for their bindings"
)]
mod bindings {
#[allow(
clippy::wildcard_imports,
reason = "the underlying c code relies on all type definitions being in scope, which \
results in the bindgen generated code relying on the generated types being in \
scope as well"
)]
#[allow(
unused_imports,
reason = "in certain versions of the WDK, there are no functions related to SPB that can \
be generated by bindgen, so these types are unused"
)]
use crate::types::*;
include!(concat!(env!("OUT_DIR"), "/spb.rs"));
}
#[allow(
unused_imports,
reason = "in certain versions of the WDK, there are no functions related to SPB that can be \
generated by bindgen, so the `bindings` module is empty"
)]
pub use bindings::*;
+36
View File
@@ -0,0 +1,36 @@
// Copyright (c) Microsoft Corporation
// License: MIT OR Apache-2.0
//! Direct FFI bindings to Storage APIs from the Windows Driver Kit (WDK)
//!
//! This module contains all bindings to functions, constants, methods,
//! constructors and destructors for Storage headers. Types are not included in
//! this module, but are available in the top-level `wdk_sys` module.
#[allow(
missing_docs,
reason = "most items in the WDK headers have no inline documentation, so bindgen is unable to \
generate documentation for their bindings"
)]
mod bindings {
#[allow(
clippy::wildcard_imports,
reason = "the underlying c code relies on all type definitions being in scope, which \
results in the bindgen generated code relying on the generated types being in \
scope as well"
)]
#[allow(
unused_imports,
reason = "in certain configurations of the WDK (ex. UMDF), there are no functions related \
to Storage that can be generated by bindgen, so these types are unused"
)]
use crate::types::*;
include!(concat!(env!("OUT_DIR"), "/storage.rs"));
}
#[allow(
unused_imports,
reason = "in certain configurations of the WDK (ex. UMDF), there are no functions related to \
Storage that can be generated by bindgen, so the `bindings` module is empty"
)]
pub use bindings::*;
@@ -0,0 +1,52 @@
// Copyright (c) Microsoft Corporation
// License: MIT OR Apache-2.0
//! Any library dependency that depends on `wdk-sys` requires these stubs to
//! provide symbols to successfully compile and run tests.
//!
//! These stubs can be brought into scope by introducing `wdk-sys` with the
//! `test-stubs` feature in the `dev-dependencies` of the crate's `Cargo.toml`
#[cfg(any(driver_model__driver_type = "KMDF", driver_model__driver_type = "UMDF"))]
pub use wdf::*;
#[cfg(any(
driver_model__driver_type = "WDM",
driver_model__driver_type = "KMDF",
driver_model__driver_type = "UMDF"
))]
use crate::{DRIVER_OBJECT, NTSTATUS, PCUNICODE_STRING};
/// Stubbed version of `DriverEntry` Symbol so that test targets will compile
///
/// # Safety
///
/// This function should never be called, so its safety is irrelevant
#[cfg(any(
driver_model__driver_type = "WDM",
driver_model__driver_type = "KMDF",
driver_model__driver_type = "UMDF"
))]
// SAFETY: "DriverEntry" is the required symbol name for Windows driver entry points.
// No other function in this compilation unit exports this name, preventing symbol conflicts.
#[unsafe(export_name = "DriverEntry")] // WDF expects a symbol with the name DriverEntry
pub const unsafe extern "system" fn driver_entry_stub(
_driver: &mut DRIVER_OBJECT,
_registry_path: PCUNICODE_STRING,
) -> NTSTATUS {
0
}
#[cfg(any(driver_model__driver_type = "KMDF", driver_model__driver_type = "UMDF"))]
mod wdf {
use crate::ULONG;
/// Stubbed version of `WdfFunctionCount` Symbol so that test targets will
/// compile
// SAFETY: WdfFunctionCount is a required WDF symbol for test compilation.
// No other symbols in this crate export this name, preventing linker conflicts.
#[unsafe(no_mangle)]
pub static mut WdfFunctionCount: ULONG = 0;
include!(concat!(env!("OUT_DIR"), "/test_stubs.rs"));
}
+73
View File
@@ -0,0 +1,73 @@
// Copyright (c) Microsoft Corporation
// License: MIT OR Apache-2.0
pub use bindings::*;
#[allow(missing_docs)]
#[allow(non_upper_case_globals)]
#[allow(non_camel_case_types)]
#[allow(non_snake_case)]
#[rustversion::attr(
any(
all(not(nightly), since(1.88)),
all(nightly, since(2025-04-25)),
),
allow(unnecessary_transmutes)
)]
#[allow(unsafe_op_in_unsafe_fn)]
#[allow(clippy::cast_lossless)]
#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_possible_wrap)]
#[allow(clippy::cognitive_complexity)]
#[allow(clippy::doc_markdown)]
#[allow(clippy::default_trait_access)]
#[allow(clippy::derive_partial_eq_without_eq)]
#[rustversion::attr(
any(
all(not(nightly), before(1.74)),
all(nightly, before(2023-09-13)),
),
allow(clippy::incorrect_clone_impl_on_copy_type)
)]
#[rustversion::attr(
any(
all(not(nightly), since(1.74)),
all(nightly, since(2023-09-13)),
),
allow(clippy::non_canonical_clone_impl)
)]
#[allow(clippy::missing_const_for_fn)]
#[allow(clippy::missing_safety_doc)]
#[allow(clippy::module_name_repetitions)]
#[allow(clippy::multiple_unsafe_ops_per_block)]
#[allow(clippy::must_use_candidate)]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[allow(clippy::ptr_as_ptr)]
#[allow(clippy::ptr_offset_with_cast)]
#[rustversion::attr(
any(
all(not(nightly), since(1.77)),
all(nightly, since(2024-01-11)),
),
allow(clippy::pub_underscore_fields)
)]
#[rustversion::attr(
any(
all(not(nightly), since(1.78)),
all(nightly, since(2024-02-09)),
),
allow(clippy::ref_as_ptr)
)]
#[allow(clippy::semicolon_if_nothing_returned)]
#[allow(clippy::too_many_arguments)]
#[allow(clippy::too_many_lines)]
#[allow(clippy::transmute_ptr_to_ptr)]
#[allow(clippy::undocumented_unsafe_blocks)]
#[allow(clippy::unnecessary_cast)]
#[allow(clippy::unreadable_literal)]
#[allow(clippy::used_underscore_binding)]
#[allow(clippy::useless_transmute)]
#[allow(clippy::use_self)]
mod bindings {
include!(concat!(env!("OUT_DIR"), "/types.rs"));
}
+26
View File
@@ -0,0 +1,26 @@
// Copyright (c) Microsoft Corporation
// License: MIT OR Apache-2.0
//! Direct FFI bindings to USB APIs from the Windows Driver Kit (WDK)
//!
//! This module contains all bindings to functions, constants, methods,
//! constructors and destructors for USB headers. Types are not included in this
//! module, but are available in the top-level `wdk_sys` module.
#[allow(
missing_docs,
reason = "most items in the WDK headers have no inline documentation, so bindgen is unable to \
generate documentation for their bindings"
)]
mod bindings {
#[allow(
clippy::wildcard_imports,
reason = "the underlying c code relies on all type definitions being in scope, which \
results in the bindgen generated code relying on the generated types being in \
scope as well"
)]
use crate::types::*;
include!(concat!(env!("OUT_DIR"), "/usb.rs"));
}
pub use bindings::*;
+35
View File
@@ -0,0 +1,35 @@
// Copyright (c) Microsoft Corporation
// License: MIT OR Apache-2.0
//! Direct FFI bindings to WDF APIs from the Windows Driver Kit (WDK)
//!
//! This module contains all bindings to functions, constants, methods,
//! constructors and destructors in `wdf.h`. Types are not included in this
//! module, but are available in the top-level `wdk_sys` module.
pub use bindings::*;
#[allow(missing_docs)]
#[allow(clippy::unreadable_literal)]
mod bindings {
#[allow(
clippy::wildcard_imports,
reason = "the underlying c code relies on all type definitions being in scope, which \
results in the bindgen generated code relying on the generated types being in \
scope as well"
)]
use crate::types::*;
include!(concat!(env!("OUT_DIR"), "/wdf.rs"));
}
// This is a workaround to expose the generated function count to the
// `call_unsafe_wdf_function_binding` proc-macro, so that the macro-generated
// code can determine the slice size at runtime. When we are able to
// conditionally compile based off a cfg range for WDF version, this module
// can be removed and the runtime check can be replaced with a conditional
// compilation: https://github.com/microsoft/windows-drivers-rs/issues/276
#[doc(hidden)]
pub mod __private {
include!(concat!(env!("OUT_DIR"), "/wdf_function_count.rs"));
}
+23
View File
@@ -0,0 +1,23 @@
// Copyright (c) Microsoft Corporation
// License: MIT OR Apache-2.0
//! Direct FFI bindings to WIN32 APIs from the Windows Driver Kit (WDK)
//!
//! This module contains all bindings to functions, constants, methods,
//! constructors and destructors in `windows.h`. Types are not included in this
//! module, but are available in the top-level `wdk_sys` module.
pub use bindings::*;
#[allow(missing_docs)]
mod bindings {
#[allow(
clippy::wildcard_imports,
reason = "the underlying c code relies on all type definitions being in scope, which \
results in the bindgen generated code relying on the generated types being in \
scope as well"
)]
use crate::types::*;
include!(concat!(env!("OUT_DIR"), "/windows.rs"));
}