Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion crates/cargo-wdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,11 @@ Usage: cargo wdk build [OPTIONS]
Options:
--profile <PROFILE> Build artifacts with the specified profile
--target-arch <TARGET_ARCH> Build for the target architecture
--target-platform <TARGET_PLATFORM>
Driver target platform [possible values: desktop, universal, windows-driver]
--sample Build sample class driver project
Comment thread
svasista-ms marked this conversation as resolved.
--sign-mode <SIGN_MODE> Driver signing mode [default: test] [possible values: off, test]
--verify-signature Verify the signature
--sample Build sample class driver project
--locked Assert that `Cargo.lock` will remain unchanged
-h, --help Print help

Expand Down
6 changes: 5 additions & 1 deletion crates/cargo-wdk/src/actions/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ use build_task::BuildTask;
use cargo_metadata::{CrateType, Message, Metadata as CargoMetadata, Package, TargetKind};
use error::BuildActionError;
use mockall_double::double;
pub use package_task::SignMode;
use package_task::{PackageTask, PackageTaskParams};
pub use package_task::{SignMode, TargetPlatform};
use tracing::{debug, error as err, info, trace, warn};
use wdk_build::{
CpuArchitecture,
Expand All @@ -41,6 +41,7 @@ pub struct BuildActionParams<'a> {
pub sign_mode: SignMode,
pub is_sample_class: bool,
pub locked: bool,
pub target_platform: Option<TargetPlatform>,
Comment thread
gurry marked this conversation as resolved.
Outdated
pub verbosity_level: clap_verbosity_flag::Verbosity,
}

Expand All @@ -53,6 +54,7 @@ pub struct BuildAction<'a> {
sign_mode: SignMode,
is_sample_class: bool,
locked: bool,
target_platform: Option<TargetPlatform>,
verbosity_level: clap_verbosity_flag::Verbosity,

// Injected deps
Expand Down Expand Up @@ -99,6 +101,7 @@ impl<'a> BuildAction<'a> {
sign_mode: params.sign_mode,
is_sample_class: params.is_sample_class,
locked: params.locked,
target_platform: params.target_platform,
verbosity_level: params.verbosity_level,
wdk_build,
command_exec,
Expand Down Expand Up @@ -398,6 +401,7 @@ impl<'a> BuildAction<'a> {
sign_mode: self.sign_mode,
sample_class: self.is_sample_class,
driver_model,
target_platform: self.target_platform,
},
self.wdk_build,
self.command_exec,
Expand Down
209 changes: 193 additions & 16 deletions crates/cargo-wdk/src/actions/build/package_task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ use windows::{
use crate::providers::{exec::CommandExec, fs::Fs, wdk_build::WdkBuild};
use crate::{actions::build::error::PackageTaskError, providers::error::FileError};

// FIXME: This range is inclusive of 25798. Update with range end after /sample
// flag is added to InfVerif CLI
Comment thread
svasista-ms marked this conversation as resolved.
Outdated
Comment thread
svasista-ms marked this conversation as resolved.
Outdated
const MISSING_SAMPLE_FLAG_WDK_BUILD_NUMBER_RANGE: RangeFrom<u32> = 25798..;
Comment thread
svasista-ms marked this conversation as resolved.
const WDR_TEST_CERT_STORE: &str = "WDRTestCertStore";
const WDR_LOCAL_TEST_CERT: &str = "WDRLocalTestCert";
const STAMPINF_VERSION_ENV_VAR: &str = "STAMPINF_VERSION";

/// Signing mode.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SignMode {
Expand All @@ -43,12 +50,31 @@ pub enum SignMode {
},
}

// FIXME: This range is inclusive of 25798. Update with range end after /sample
// flag is added to InfVerif CLI
const MISSING_SAMPLE_FLAG_WDK_BUILD_NUMBER_RANGE: RangeFrom<u32> = 25798..;
const WDR_TEST_CERT_STORE: &str = "WDRTestCertStore";
const WDR_LOCAL_TEST_CERT: &str = "WDRLocalTestCert";
const STAMPINF_VERSION_ENV_VAR: &str = "STAMPINF_VERSION";
/// Driver target platform as per <https://learn.microsoft.com/en-us/windows-hardware/drivers/develop/target-platforms>
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TargetPlatform {
/// Universal target (default). Validates that the INF meets Universal
/// driver requirements (`infverif /u`) — portable everywhere.
Comment thread
gurry marked this conversation as resolved.
Outdated
Universal,
/// Desktop target. Validates that the INF meets WHQL signature
/// requirements (`infverif /h`).
Desktop,
/// Windows Driver target. Validates that the INF meets Windows Driver
/// requirements (`infverif /w`) — declarative (DCH) + driver package
/// isolation.
WindowsDriver,
}

impl TargetPlatform {
/// Returns the `InfVerif` mode flag for this target platform.
const fn infverif_flag(self) -> &'static str {
Comment thread
gurry marked this conversation as resolved.
Outdated
match self {
Self::Universal => "/u",
Self::Desktop => "/h",
Self::WindowsDriver => "/w",
}
}
}

#[derive(Debug)]
pub struct PackageTaskParams<'a> {
Expand All @@ -59,6 +85,7 @@ pub struct PackageTaskParams<'a> {
pub sign_mode: SignMode,
pub sample_class: bool,
pub driver_model: DriverConfig,
pub target_platform: Option<TargetPlatform>,
}

/// Supports low level driver packaging operations
Expand Down Expand Up @@ -87,6 +114,7 @@ pub struct PackageTask<'a> {
arch: &'a CpuArchitecture,
os_mapping: &'a str,
driver_model: DriverConfig,
target_platform: Option<TargetPlatform>,

// Injected deps
wdk_build: &'a WdkBuild,
Expand Down Expand Up @@ -192,6 +220,7 @@ impl<'a> PackageTask<'a> {
arch: params.target_arch,
os_mapping,
driver_model: params.driver_model,
target_platform: params.target_platform,
wdk_build,
command_exec,
fs,
Expand Down Expand Up @@ -558,15 +587,13 @@ impl<'a> PackageTask<'a> {
};

info!("Running infverif");
let mut args = vec![
"/v",
match self.driver_model {
DriverConfig::Kmdf(_) | DriverConfig::Wdm => "/w",
// TODO: This should be /u if WDK <= GE && DRIVER_MODEL == UMDF, otherwise it should
// be /w
DriverConfig::Umdf(_) => "/u",
},
];

let mode_flag = self.target_platform.map_or_else(
|| TargetPlatform::Universal.infverif_flag(),
TargetPlatform::infverif_flag,
);

let mut args = vec!["/v", mode_flag];
Comment thread
svasista-ms marked this conversation as resolved.
Outdated
Comment thread
svasista-ms marked this conversation as resolved.
let inf_path = self.dest_inf_file_path.to_string_lossy();

if self.sample_class {
Expand Down Expand Up @@ -644,7 +671,7 @@ mod tests {
process::{ExitStatus, Output},
};

use wdk_build::{CpuArchitecture, KmdfConfig};
use wdk_build::{CpuArchitecture, KmdfConfig, UmdfConfig};

use super::*;

Expand All @@ -665,6 +692,7 @@ mod tests {
sign_mode: SignMode::Test {
verify_signature: false,
},
target_platform: None,
};
let dest_root = target_dir.join(format!("{package_name}_package"));

Expand Down Expand Up @@ -735,6 +763,7 @@ mod tests {
sign_mode: SignMode::Test {
verify_signature: false,
},
target_platform: None,
};

let command_exec = CommandExec::default();
Expand Down Expand Up @@ -763,6 +792,7 @@ mod tests {
sign_mode: SignMode::Test {
verify_signature: false,
},
target_platform: None,
};

let command_exec = CommandExec::default();
Expand Down Expand Up @@ -800,6 +830,7 @@ mod tests {
sign_mode: SignMode::Test {
verify_signature: false,
},
target_platform: None,
};

let wdk_build = WdkBuild::default();
Expand Down Expand Up @@ -839,6 +870,152 @@ mod tests {
}
}

fn assert_default_infverif_mode_flag(

@gurry gurry Jul 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like an almost complete duplicate of assert_target_platform_infverif_mode_flag. Instead of these two methods, we can have a single method which takes, driver_model, target_platform and expected_mode_flag e.g.:

fn assert_infverif_mode_flag(
    driver_model: DriverConfig,
    target_platform: TargetPlatform,
    expected_mode_flag: &'static str,
)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done ✅

driver_model: DriverConfig,
expected_mode_flag: &'static str,
) {
let package_name = "driver";
let working_dir = PathBuf::from("C:/abs/driver");
let target_dir = PathBuf::from("C:/abs/driver/target/debug");
let arch = CpuArchitecture::Amd64;

let params = PackageTaskParams {
package_name,
working_dir: &working_dir,
target_dir: &target_dir,
target_arch: &arch,
driver_model,
sample_class: false,
sign_mode: SignMode::Off,
target_platform: None,
};

let fs = Fs::default();
let wdk_build = WdkBuild::default();

let mut command_exec = CommandExec::default();
command_exec
.expect_run()
.withf(move |cmd: &str, args: &[&str], _, _| {
cmd == "infverif"
&& args.len() >= 2
&& args[0] == "/v"
&& args[1] == expected_mode_flag
})
.once()
.returning(|_, _, _, _| {
Ok(Output {
status: ExitStatus::default(),
stdout: vec![],
stderr: vec![],
})
});

let task = PackageTask::new(params, &wdk_build, &command_exec, &fs);
assert!(task.run_infverif().is_ok());
}

#[test]
fn run_infverif_defaults_to_universal_for_all_driver_models() {
assert_default_infverif_mode_flag(DriverConfig::Kmdf(KmdfConfig::default()), "/u");
assert_default_infverif_mode_flag(DriverConfig::Wdm, "/u");
assert_default_infverif_mode_flag(
DriverConfig::Umdf(UmdfConfig {
umdf_version_major: 2,
target_umdf_version_minor: 33,
minimum_umdf_version_minor: None,
}),
"/u",
);
}

#[test]
fn run_infverif_uses_target_platform_mode_flag() {
assert_target_platform_infverif_mode_flag(TargetPlatform::Universal, "/u");
assert_target_platform_infverif_mode_flag(TargetPlatform::Desktop, "/h");
assert_target_platform_infverif_mode_flag(TargetPlatform::WindowsDriver, "/w");
}

fn assert_target_platform_infverif_mode_flag(
target_platform: TargetPlatform,
expected_mode_flag: &'static str,
) {
let package_name = "kmdf_driver";
let working_dir = PathBuf::from("C:/abs/kmdf_driver");
let target_dir = PathBuf::from("C:/abs/kmdf_driver/target/debug");
let arch = CpuArchitecture::Amd64;

let params = PackageTaskParams {
package_name,
working_dir: &working_dir,
target_dir: &target_dir,
target_arch: &arch,
driver_model: DriverConfig::Kmdf(KmdfConfig::default()),
sample_class: false,
sign_mode: SignMode::Off,
target_platform: Some(target_platform),
};

let fs = Fs::default();
let wdk_build = WdkBuild::default();

let mut command_exec = CommandExec::default();
command_exec
.expect_run()
.withf(move |cmd: &str, args: &[&str], _, _| {
cmd == "infverif"
&& args.len() >= 2
&& args[0] == "/v"
&& args[1] == expected_mode_flag
})
.once()
.returning(|_, _, _, _| {
Ok(Output {
status: ExitStatus::default(),
stdout: vec![],
stderr: vec![],
})
});

let task = PackageTask::new(params, &wdk_build, &command_exec, &fs);
assert!(task.run_infverif().is_ok());
}

#[test]
fn run_infverif_skips_sample_class_when_samples_flag_missing() {
let package_name = "kmdf_driver";
let working_dir = PathBuf::from("C:/abs/kmdf_driver");
let target_dir = PathBuf::from("C:/abs/kmdf_driver/target/debug");
let arch = CpuArchitecture::Amd64;

let params = PackageTaskParams {
package_name,
working_dir: &working_dir,
target_dir: &target_dir,
target_arch: &arch,
driver_model: DriverConfig::Kmdf(KmdfConfig::default()),
sample_class: true,
sign_mode: SignMode::Off,
target_platform: Some(TargetPlatform::WindowsDriver),
};

let fs = Fs::default();
let mut wdk_build = WdkBuild::default();
// A WDK build number in the missing-`/samples`-flag range, so InfVerif
// is skipped for the sample class.
Comment thread
svasista-ms marked this conversation as resolved.
wdk_build
.expect_detect_wdk_build_number()
.once()
.returning(|| Ok(28000u32));

let mut command_exec = CommandExec::default();
// `infverif` must not be invoked when the sample class is skipped.
command_exec.expect_run().never();

let task = PackageTask::new(params, &wdk_build, &command_exec, &fs);
assert!(task.run_infverif().is_ok());
}

mod named_mutex {
use std::{
ffi::CString,
Expand Down
12 changes: 5 additions & 7 deletions crates/cargo-wdk/src/actions/build/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1677,6 +1677,7 @@ fn initialize_build_action<'a>(
sign_mode,
is_sample_class: sample_class,
locked: test_build_action.locked,
target_platform: None,
verbosity_level: clap_verbosity_flag::Verbosity::new(1, 0),
},
test_build_action.mock_wdk_build_provider(),
Expand Down Expand Up @@ -2922,15 +2923,12 @@ impl TestBuildAction {
mut self,
driver_name: &str,
driver_dir: &Path,
driver_type: &str,
_driver_type: &str,
override_output: Option<Output>,
) -> Self {
let mut expected_infverif_args = vec!["/v".to_string()];
if driver_type.eq_ignore_ascii_case("KMDF") || driver_type.eq_ignore_ascii_case("WDM") {
expected_infverif_args.push("/w".to_string());
} else {
expected_infverif_args.push("/u".to_string());
}
// cargo-wdk emits its derived mode flag. With no `--target-platform`,
// cargo-wdk defaults to `Universal` (`/u`) for every driver model.
Comment thread
svasista-ms marked this conversation as resolved.
Outdated
let mut expected_infverif_args = vec!["/v".to_string(), "/u".to_string()];
if self.sample_class {
expected_infverif_args.push("/msft".to_string());
}
Expand Down
Loading
Loading