Skip to content

Commit 8696928

Browse files
authored
feat: add support for Storage API subset in wdk-sys (#287)
1 parent e321c95 commit 8696928

8 files changed

Lines changed: 127 additions & 1 deletion

File tree

crates/wdk-build/src/lib.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ pub enum ApiSubset {
201201
Hid,
202202
/// API subset for SPB (Serial Peripheral Bus) drivers: <https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/_spb/>
203203
Spb,
204+
/// API subset for Storage drivers: <https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/_storage/>
205+
Storage,
204206
}
205207

206208
impl Default for Config {
@@ -684,6 +686,37 @@ impl Config {
684686

685687
spb_headers
686688
}
689+
ApiSubset::Storage => {
690+
let mut storage_headers = vec![
691+
"ehstorioctl.h",
692+
"ntddcdrm.h",
693+
"ntddcdvd.h",
694+
"ntdddisk.h",
695+
"ntddmmc.h",
696+
"ntddscsi.h",
697+
"ntddstor.h",
698+
"ntddtape.h",
699+
"ntddvol.h",
700+
"ufs.h",
701+
];
702+
703+
if let DriverConfig::Wdm | DriverConfig::Kmdf(_) = self.driver_config {
704+
storage_headers.extend([
705+
"mountdev.h",
706+
"mountmgr.h",
707+
"ntddchgr.h",
708+
"ntdddump.h",
709+
"storduid.h",
710+
"storport.h",
711+
]);
712+
}
713+
714+
if let DriverConfig::Kmdf(_) = self.driver_config {
715+
storage_headers.extend(["ehstorbandmgmt.h"]);
716+
}
717+
718+
storage_headers
719+
}
687720
}
688721
.into_iter()
689722
.map(std::string::ToString::to_string)

crates/wdk-sys/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ default = []
3737

3838
hid = []
3939
spb = []
40+
storage = []
4041

4142
nightly = ["wdk-macros/nightly"]
4243
test-stubs = []

crates/wdk-sys/build.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ const BINDGEN_FILE_GENERATORS_TUPLES: &[(&str, GenerateFn)] = &[
133133
("wdf.rs", generate_wdf),
134134
("hid.rs", generate_hid),
135135
("spb.rs", generate_spb),
136+
("storage.rs", generate_storage),
136137
];
137138

138139
fn initialize_tracing() -> Result<(), ParseError> {
@@ -199,6 +200,8 @@ fn generate_constants(out_path: &Path, config: &Config) -> Result<(), ConfigErro
199200
ApiSubset::Hid,
200201
#[cfg(feature = "spb")]
201202
ApiSubset::Spb,
203+
#[cfg(feature = "storage")]
204+
ApiSubset::Storage,
202205
]);
203206
trace!(header_contents = ?header_contents);
204207

@@ -223,6 +226,8 @@ fn generate_types(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
223226
ApiSubset::Hid,
224227
#[cfg(feature = "spb")]
225228
ApiSubset::Spb,
229+
#[cfg(feature = "storage")]
230+
ApiSubset::Storage,
226231
]);
227232
trace!(header_contents = ?header_contents);
228233

@@ -358,6 +363,45 @@ fn generate_spb(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
358363
}
359364
}
360365

366+
fn generate_storage(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
367+
cfg_if::cfg_if! {
368+
if #[cfg(feature = "storage")] {
369+
info!("Generating bindings to WDK: storage.rs");
370+
371+
let header_contents = config.bindgen_header_contents([
372+
ApiSubset::Base,
373+
ApiSubset::Wdf,
374+
ApiSubset::Storage,
375+
]);
376+
trace!(header_contents = ?header_contents);
377+
378+
let bindgen_builder = {
379+
let mut builder = bindgen::Builder::wdk_default(config)?
380+
.with_codegen_config((CodegenConfig::TYPES | CodegenConfig::VARS).complement())
381+
.header_contents("storage-input.h", &header_contents);
382+
383+
// Only allowlist files in the storage-specific files to avoid
384+
// duplicate definitions
385+
for header_file in config.headers(ApiSubset::Storage) {
386+
builder = builder.allowlist_file(format!("(?i).*{header_file}.*"));
387+
}
388+
builder
389+
};
390+
trace!(bindgen_builder = ?bindgen_builder);
391+
392+
Ok(bindgen_builder
393+
.generate()
394+
.expect("Bindings should succeed to generate")
395+
.write_to_file(out_path.join("storage.rs"))?)
396+
} else {
397+
let _ = (out_path, config); // Silence unused variable warnings when storage feature is not enabled
398+
399+
info!("Skipping storage.rs generation since storage feature is not enabled");
400+
Ok(())
401+
}
402+
}
403+
}
404+
361405
/// Generates a `wdf_function_count.rs` file in `OUT_DIR` which contains the
362406
/// definition of the function `get_wdf_function_count()`. This is required to
363407
/// be generated here since the size of the table is derived from either a

crates/wdk-sys/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ pub mod hid;
4949
))]
5050
pub mod spb;
5151

52+
#[cfg(all(
53+
any(
54+
driver_model__driver_type = "WDM",
55+
driver_model__driver_type = "KMDF",
56+
driver_model__driver_type = "UMDF"
57+
),
58+
feature = "storage"
59+
))]
60+
pub mod storage;
61+
5262
#[cfg(feature = "test-stubs")]
5363
pub mod test_stubs;
5464

crates/wdk-sys/src/storage.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright (c) Microsoft Corporation
2+
// License: MIT OR Apache-2.0
3+
4+
//! Direct FFI bindings to Storage APIs from the Windows Driver Kit (WDK)
5+
//!
6+
//! This module contains all bindings to functions, constants, methods,
7+
//! constructors and destructors for Storage headers. Types are not included in
8+
//! this module, but are available in the top-level `wdk_sys` module.
9+
10+
#[allow(
11+
missing_docs,
12+
reason = "most items in the WDK headers have no inline documentation, so bindgen is unable to \
13+
generate documentation for their bindings"
14+
)]
15+
mod bindings {
16+
#[allow(
17+
clippy::wildcard_imports,
18+
reason = "the underlying c code relies on all type definitions being in scope, which \
19+
results in the bindgen generated code relying on the generated types being in \
20+
scope as well"
21+
)]
22+
#[allow(
23+
unused_imports,
24+
reason = "in certain configurations of the WDK (ex. UMDF), there are no functions related \
25+
to Storage that can be generated by bindgen, so these types are unused"
26+
)]
27+
use crate::types::*;
28+
29+
include!(concat!(env!("OUT_DIR"), "/storage.rs"));
30+
}
31+
#[allow(
32+
unused_imports,
33+
reason = "in certain configurations of the WDK (ex. UMDF), there are no functions related to \
34+
Storage that can be generated by bindgen, so the `bindings` module is empty"
35+
)]
36+
pub use bindings::*;

examples/sample-kmdf-driver/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ default = []
3434

3535
hid = ["wdk-sys/hid"]
3636
spb = ["wdk-sys/spb"]
37+
storage = ["wdk-sys/storage"]
3738

3839
nightly = ["wdk/nightly", "wdk-sys/nightly"]
3940

examples/sample-umdf-driver/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ default = []
3232

3333
hid = ["wdk-sys/hid"]
3434
spb = ["wdk-sys/spb"]
35+
storage = ["wdk-sys/storage"]
3536

3637
nightly = ["wdk/nightly", "wdk-sys/nightly"]
3738

examples/sample-wdm-driver/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ wdk = { path = "../../crates/wdk", version = "0.3.0" }
2727
wdk-panic = { path = "../../crates/wdk-panic", version = "0.3.0" }
2828
wdk-sys = { path = "../../crates/wdk-sys", version = "0.3.0" }
2929

30-
3130
[features]
3231
default = []
3332

3433
hid = ["wdk-sys/hid"]
3534
spb = ["wdk-sys/spb"]
35+
storage = ["wdk-sys/storage"]
3636

3737
nightly = ["wdk/nightly", "wdk-sys/nightly"]
3838

0 commit comments

Comments
 (0)