diff --git a/crates/wdk-build/src/bindgen.rs b/crates/wdk-build/src/bindgen.rs
index f815cd5c6..983d26ab4 100644
--- a/crates/wdk-build/src/bindgen.rs
+++ b/crates/wdk-build/src/bindgen.rs
@@ -131,6 +131,9 @@ impl BuilderExt for Builder {
.blocklist_item(".*USBDEVICE_ABORTIO")
.blocklist_item(".*USBDEVICE_STARTIO")
.blocklist_item(".*USBDEVICE_TREE_PURGEIO")
+ // FIXME: bindgen unable to generate nameless fields
+ .blocklist_item(".*NET_BUFFER_HEADER")
+ .blocklist_item(".*NDIS_OPEN_BLOCK")
// FIXME: arrays with more than 32 entries currently fail to generate a `Default`` impl: https://github.com/rust-lang/rust-bindgen/issues/2803
.no_default(".*tagMONITORINFOEXA")
.must_use_type("NTSTATUS")
@@ -142,7 +145,8 @@ impl BuilderExt for Builder {
.parse_callbacks(Box::new(WdkCallbacks::new(config)))
.formatter(bindgen::Formatter::Prettyplease)
.rust_target(get_rust_target()?)
- .rust_edition(get_rust_edition()?);
+ .rust_edition(get_rust_edition()?)
+ .wrap_unsafe_ops(true);
// The `_USBPM_CLIENT_CONFIG_EXTRA_INFO` struct only has members when
// _KERNEL_MODE flag is defined. We need to mark this type as opaque to avoid
diff --git a/crates/wdk-build/src/lib.rs b/crates/wdk-build/src/lib.rs
index dd33189b8..9b89c4375 100644
--- a/crates/wdk-build/src/lib.rs
+++ b/crates/wdk-build/src/lib.rs
@@ -335,6 +335,8 @@ pub enum ApiSubset {
Storage,
/// API subset for USB (Universal Serial Bus) drivers:
Usb,
+ /// API subset for network drivers:
+ Network,
}
#[derive(Debug, Error, PartialEq, Eq)]
@@ -687,21 +689,25 @@ impl Config {
// ]
// .into_iter()
// .map(|(key, value)| (key.to_string(), value.map(|v| v.to_string())))
+ let mut defs = vec![("NDIS_SUPPORT_NDIS6", None)];
+
match self.cpu_architecture {
// Definitions sourced from `Program Files\Windows
// Kits\10\build\10.0.22621.0\WindowsDriver.x64.props`
CpuArchitecture::Amd64 => {
- vec![("_WIN64", None), ("_AMD64_", None), ("AMD64", None)]
+ defs.extend([("_WIN64", None), ("_AMD64_", None), ("AMD64", None)]);
+ defs
}
// Definitions sourced from `Program Files\Windows
// Kits\10\build\10.0.22621.0\WindowsDriver.arm64.props`
CpuArchitecture::Arm64 => {
- vec![
+ defs.extend([
("_ARM64_", None),
("ARM64", None),
("_USE_DECLSPECS_FOR_SAL", Some(1)),
("STD_CALL", None),
- ]
+ ]);
+ defs
}
}
.into_iter()
@@ -816,6 +822,7 @@ impl Config {
ApiSubset::Wdf => self.wdf_headers(),
ApiSubset::Gpio => self.gpio_headers(),
ApiSubset::Hid => self.hid_headers(),
+ ApiSubset::Network => self.network_headers(),
ApiSubset::ParallelPorts => self.parallel_ports_headers(),
ApiSubset::Spb => self.spb_headers(),
ApiSubset::Storage => self.storage_headers(),
@@ -994,6 +1001,11 @@ impl Config {
Ok(headers)
}
+ #[tracing::instrument(level = "trace")]
+ fn network_headers(&self) -> Vec<&'static str> {
+ vec!["ndis.h", "fwpmk.h", "fwpsk.h"]
+ }
+
/// Determines whether to include the ufxclient.h header based on the Clang
/// version used by bindgen.
///
@@ -1167,6 +1179,8 @@ impl Config {
println!("cargo::rustc-link-lib=static=wmilib");
println!("cargo::rustc-link-lib=static=WdfLdr");
println!("cargo::rustc-link-lib=static=WdfDriverEntry");
+ println!("cargo::rustc-link-lib=static=Fwpkclnt");
+ println!("cargo::rustc-link-lib=static=netio");
// Emit ARM64-specific libraries to link to derived from
// WindowsDriver.arm64.props
diff --git a/crates/wdk-sys/Cargo.toml b/crates/wdk-sys/Cargo.toml
index a1428cc09..70dc23253 100644
--- a/crates/wdk-sys/Cargo.toml
+++ b/crates/wdk-sys/Cargo.toml
@@ -25,6 +25,7 @@ parallel-ports = ["gpio"]
spb = []
storage = []
usb = []
+network = []
nightly = ["wdk-macros/nightly", "wdk-build/nightly"]
test-stubs = []
diff --git a/crates/wdk-sys/build.rs b/crates/wdk-sys/build.rs
index 2a7308487..aa588035d 100644
--- a/crates/wdk-sys/build.rs
+++ b/crates/wdk-sys/build.rs
@@ -145,6 +145,8 @@ const ENABLED_API_SUBSETS: &[ApiSubset] = &[
ApiSubset::Storage,
#[cfg(feature = "usb")]
ApiSubset::Usb,
+ #[cfg(feature = "network")]
+ ApiSubset::Network,
];
type GenerateFn = fn(&Path, &Config) -> Result<(), ConfigError>;
@@ -165,6 +167,8 @@ const BINDGEN_FILE_GENERATORS_TUPLES: &[(&str, GenerateFn)] = &[
("storage.rs", generate_storage),
#[cfg(feature = "usb")]
("usb.rs", generate_usb),
+ #[cfg(feature = "network")]
+ ("network.rs", generate_network),
];
fn initialize_tracing() -> Result<(), ParseError> {
@@ -495,6 +499,36 @@ fn generate_usb(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
.map_err(|source| IoError::with_path(output_file_path, source))?)
}
+#[cfg(feature = "network")]
+fn generate_network(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
+ info!("Generating bindings to WDK: network.rs");
+
+ let header_contents =
+ config.bindgen_header_contents([ApiSubset::Base, ApiSubset::Wdf, ApiSubset::Network])?;
+ 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("network.h", &header_contents);
+
+ // Only allowlist files in the network-specific files to avoid
+ // duplicate definitions
+ for header_file in config.headers(ApiSubset::Network)? {
+ builder = builder.allowlist_file(format!("(?i).*{header_file}.*"));
+ }
+ builder
+ };
+ trace!(bindgen_builder = ?bindgen_builder);
+
+ let output_file_path = out_path.join("network.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
diff --git a/crates/wdk-sys/src/lib.rs b/crates/wdk-sys/src/lib.rs
index 39a88977c..4a575f0ff 100644
--- a/crates/wdk-sys/src/lib.rs
+++ b/crates/wdk-sys/src/lib.rs
@@ -89,6 +89,16 @@ pub mod storage;
))]
pub mod usb;
+#[cfg(all(
+ any(
+ driver_model__driver_type = "WDM",
+ driver_model__driver_type = "KMDF",
+ driver_model__driver_type = "UMDF"
+ ),
+ feature = "network"
+))]
+pub mod network;
+
#[cfg(feature = "test-stubs")]
pub mod test_stubs;
diff --git a/crates/wdk-sys/src/network.rs b/crates/wdk-sys/src/network.rs
new file mode 100644
index 000000000..0bd7ccb7b
--- /dev/null
+++ b/crates/wdk-sys/src/network.rs
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft Corporation
+// License: MIT OR Apache-2.0
+
+//! Direct FFI bindings to network APIs from the Windows Driver Kit (WDK)
+//!
+//! This module contains all bindings for network 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"
+)]
+#[allow(clippy::derive_partial_eq_without_eq)]
+#[allow(non_camel_case_types)]
+#[allow(non_snake_case)]
+#[allow(non_upper_case_globals)]
+#[allow(unnecessary_transmutes)]
+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"), "/network.rs"));
+}
+
+pub use bindings::*;
diff --git a/crates/wdk-sys/src/types.rs b/crates/wdk-sys/src/types.rs
index 76e8ae9f4..cd3f7e2a8 100644
--- a/crates/wdk-sys/src/types.rs
+++ b/crates/wdk-sys/src/types.rs
@@ -69,5 +69,17 @@ pub use bindings::*;
#[allow(clippy::useless_transmute)]
#[allow(clippy::use_self)]
mod bindings {
+ // TODO: These types are blocklisted in bindgen because it cannot handle structs
+ // with fields that are unnamed.
+ #[cfg(feature = "network")]
+ #[repr(C)]
+ #[derive(Copy, Clone)]
+ pub union _NET_BUFFER_HEADER {
+ pub NetBufferData: NET_BUFFER_DATA,
+ pub Link: SLIST_HEADER,
+ }
+ #[cfg(feature = "network")]
+ pub type NET_BUFFER_HEADER = _NET_BUFFER_HEADER;
+
include!(concat!(env!("OUT_DIR"), "/types.rs"));
}