From c2aeb0e8156e8a50a2689cf5182eedb747b2137d Mon Sep 17 00:00:00 2001 From: Shravan Vasista Date: Tue, 1 Sep 2026 17:03:46 +0530 Subject: [PATCH 01/10] feat(cargo-wdk): add `--stampinf-args` passthrough to customize `stampinf` options --- crates/cargo-wdk/README.md | 3 + crates/cargo-wdk/src/actions/build/mod.rs | 4 + .../src/actions/build/package_task.rs | 193 +++++++++++++++--- crates/cargo-wdk/src/actions/build/tests.rs | 1 + crates/cargo-wdk/src/cli.rs | 90 ++++++++ crates/cargo-wdk/tests/build_command_test.rs | 56 +++++ 6 files changed, 324 insertions(+), 23 deletions(-) diff --git a/crates/cargo-wdk/README.md b/crates/cargo-wdk/README.md index 277a62507..baaddafa8 100644 --- a/crates/cargo-wdk/README.md +++ b/crates/cargo-wdk/README.md @@ -84,6 +84,9 @@ Driver Signing: Inf2Cat Options: --inf2cat-args Custom arguments to pass to `inf2cat` when generating the catalog file, e.g. `--inf2cat-args '/os:10_x64,10_GE_X64 /uselocaltime'` +Stampinf Options: + --stampinf-args Custom arguments to pass to `stampinf` when generating the INF file, e.g. `--stampinf-args '-d 01/01/2026 -v 1.2.3.4 -p "Contoso Ltd"'` + Feature Selection: --all-features Activate all available features --no-default-features Do not activate the `default` feature diff --git a/crates/cargo-wdk/src/actions/build/mod.rs b/crates/cargo-wdk/src/actions/build/mod.rs index 709cd38d0..3043d9293 100644 --- a/crates/cargo-wdk/src/actions/build/mod.rs +++ b/crates/cargo-wdk/src/actions/build/mod.rs @@ -80,6 +80,7 @@ pub struct BuildActionParams<'a> { pub target_arch: Option, pub sign_mode: SignMode, pub inf2cat_args: Option>, + pub stampinf_args: Option>, pub is_sample_class: bool, pub locked: bool, pub target_platform: TargetPlatform, @@ -95,6 +96,7 @@ pub struct BuildAction<'a> { target_arch: Option, sign_mode: SignMode, inf2cat_args: Option>, + stampinf_args: Option>, is_sample_class: bool, locked: bool, target_platform: TargetPlatform, @@ -144,6 +146,7 @@ impl<'a> BuildAction<'a> { target_arch: params.target_arch, sign_mode: params.sign_mode.clone(), inf2cat_args: params.inf2cat_args.clone(), + stampinf_args: params.stampinf_args.clone(), is_sample_class: params.is_sample_class, locked: params.locked, target_platform: params.target_platform, @@ -453,6 +456,7 @@ impl<'a> BuildAction<'a> { target_arch: &target_arch, sign_mode: self.sign_mode.clone(), inf2cat_args: self.inf2cat_args.clone(), + stampinf_args: self.stampinf_args.clone(), sample_class: self.is_sample_class, driver_model, target_platform: self.target_platform, diff --git a/crates/cargo-wdk/src/actions/build/package_task.rs b/crates/cargo-wdk/src/actions/build/package_task.rs index b479a9b32..90c76a633 100644 --- a/crates/cargo-wdk/src/actions/build/package_task.rs +++ b/crates/cargo-wdk/src/actions/build/package_task.rs @@ -85,6 +85,7 @@ pub struct PackageTaskParams<'a> { pub target_arch: &'a CpuArchitecture, pub sign_mode: SignMode, pub inf2cat_args: Option>, + pub stampinf_args: Option>, pub sample_class: bool, pub driver_model: DriverConfig, pub target_platform: TargetPlatform, @@ -95,6 +96,7 @@ pub struct PackageTask<'a> { package_name: String, sign_mode: SignMode, inf2cat_args: Option>, + stampinf_args: Option>, sample_class: bool, // src paths @@ -207,6 +209,7 @@ impl<'a> PackageTask<'a> { package_name, sign_mode: params.sign_mode, inf2cat_args: params.inf2cat_args, + stampinf_args: params.stampinf_args, sample_class: params.sample_class, src_inx_file_path, src_driver_binary_file_path, @@ -359,6 +362,9 @@ impl<'a> PackageTask<'a> { } fn run_stampinf(&self) -> Result<(), PackageTaskError> { + const STAMPINF_DATE_SWITCH: &str = "d"; + const STAMPINF_VERSION_SWITCH: &str = "v"; + info!("Running stampinf"); let wdf_version_flags = match self.driver_model { DriverConfig::Kmdf(kmdf_config) => { @@ -384,42 +390,51 @@ impl<'a> PackageTask<'a> { let cat_file_path = format!("{}.cat", self.package_name); let dest_inf_file_path = self.dest_inf_file_path.to_string_lossy(); let arch = self.arch.to_string(); - let mut args: Vec<&str> = vec![ - "-f", - &dest_inf_file_path, - "-d", - "*", - "-a", - &arch, - "-c", - &cat_file_path, - ]; + let mut args: Vec<&str> = vec!["-f", &dest_inf_file_path]; - match std::env::var(STAMPINF_VERSION_ENV_VAR) { - Ok(version) if !version.trim().is_empty() => { - // When STAMPINF_VERSION is set to a non-empty, non-whitespace - // value, we intentionally omit -v so stampinf - // reads it and populates DriverVer. - // (Whitespace-only values are ignored.) - debug!( - DriverVer = version, - "Using {STAMPINF_VERSION_ENV_VAR} env var to set DriverVer" - ); - } - _ => { - args.extend(["-v", "*"]); + if !self.stampinf_args_contains(STAMPINF_DATE_SWITCH) { + args.extend(["-d", "*"]); + } + args.extend(["-a", &arch, "-c", &cat_file_path]); + if self.stampinf_args_contains(STAMPINF_VERSION_SWITCH) { + debug!("Using -v from --stampinf-args to set DriverVer"); + } else { + match std::env::var(STAMPINF_VERSION_ENV_VAR) { + Ok(version) if !version.trim().is_empty() => { + // When STAMPINF_VERSION is set to a non-empty, + // non-whitespace value, we intentionally omit -v so + // stampinf reads it and populates DriverVer. + // (Whitespace-only values are ignored.) + debug!( + DriverVer = version, + "Using {STAMPINF_VERSION_ENV_VAR} env var to set DriverVer" + ); + } + _ => { + args.extend(["-v", "*"]); + } } } if !wdf_version_flags.is_empty() { args.append(&mut wdf_version_flags.iter().map(String::as_str).collect()); } + if let Some(stampinf_args) = &self.stampinf_args { + args.extend(stampinf_args.iter().map(String::as_str)); + } if let Err(e) = self.command_exec.run("stampinf", &args, None, None) { return Err(PackageTaskError::StampinfCommand(e)); } Ok(()) } + fn stampinf_args_contains(&self, switch: &str) -> bool { + self.stampinf_args.iter().flatten().any(|arg| { + arg.strip_prefix(['-', '/']) + .is_some_and(|arg| arg.eq_ignore_ascii_case(switch)) + }) + } + fn run_inf2cat(&self) -> Result<(), PackageTaskError> { info!("Running inf2cat"); let driver_arg = format!( @@ -737,6 +752,7 @@ mod tests { signtool_args: Vec::new(), }, inf2cat_args: None, + stampinf_args: None, target_platform: TargetPlatform::Universal, }; let dest_root = target_dir.join(format!("{package_name}_package")); @@ -811,6 +827,7 @@ mod tests { signtool_args: Vec::new(), }, inf2cat_args: None, + stampinf_args: None, target_platform: TargetPlatform::Universal, }; @@ -842,6 +859,7 @@ mod tests { signtool_args: Vec::new(), }, inf2cat_args: None, + stampinf_args: None, target_platform: TargetPlatform::Universal, }; @@ -882,6 +900,7 @@ mod tests { signtool_args: Vec::new(), }, inf2cat_args: None, + stampinf_args: None, target_platform: TargetPlatform::Universal, }; @@ -922,6 +941,128 @@ mod tests { } } + fn stampinf_args_works_with_defaults( + env_version: Option<&str>, + stampinf_args: &[&str], + expected: &[&str], + ) { + 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: "driver", + working_dir: &working_dir, + target_dir: &target_dir, + target_arch: &arch, + driver_model: DriverConfig::Kmdf(KmdfConfig::default()), + sample_class: false, + sign_mode: SignMode::Off, + inf2cat_args: None, + stampinf_args: Some(stampinf_args.iter().map(ToString::to_string).collect()), + target_platform: TargetPlatform::Universal, + }; + + let wdk_build = WdkBuild::default(); + let fs = Fs::default(); + let mut command_exec = CommandExec::default(); + let expected: Vec = expected.iter().map(ToString::to_string).collect(); + command_exec + .expect_run() + .withf(move |cmd: &str, args: &[&str], _, _| { + // Skip the `-f ` prefix, whose path is environment + // specific. + cmd == "stampinf" && args[2..] == expected[..] + }) + .once() + .return_once(|_, _, _, _| { + Ok(Output { + status: ExitStatus::default(), + stdout: vec![], + stderr: vec![], + }) + }); + + let result = + crate::test_utils::with_env(&[(STAMPINF_VERSION_ENV_VAR, env_version)], || { + let task = PackageTask::new(params, &wdk_build, &command_exec, &fs); + task.run_stampinf() + }); + assert!(result.is_ok()); + } + + /// The `-k` value cargo-wdk derives from the default KMDF metadata. + fn default_kmdf_version() -> String { + let kmdf = KmdfConfig::default(); + format!( + "{}.{}", + kmdf.kmdf_version_major, kmdf.target_kmdf_version_minor + ) + } + + #[test] + fn run_stampinf_appends_custom_args_after_the_defaults() { + stampinf_args_works_with_defaults( + None, + &["-p", "Contoso Ltd", "-n"], + &[ + "-d", + "*", + "-a", + "amd64", + "-c", + "driver.cat", + "-v", + "*", + "-k", + &default_kmdf_version(), + "-p", + "Contoso Ltd", + "-n", + ], + ); + } + + #[test] + fn run_stampinf_drops_default_date_and_version_when_caller_supplies_them() { + stampinf_args_works_with_defaults( + None, + &["-d", "01/01/2026", "/V", "1.2.3.4"], + &[ + "-a", + "amd64", + "-c", + "driver.cat", + "-k", + &default_kmdf_version(), + "-d", + "01/01/2026", + "/V", + "1.2.3.4", + ], + ); + } + + #[test] + fn run_stampinf_caller_version_wins_over_env_var() { + stampinf_args_works_with_defaults( + Some("9.9.9.9"), + &["-v", "1.2.3.4"], + &[ + "-d", + "*", + "-a", + "amd64", + "-c", + "driver.cat", + "-k", + &default_kmdf_version(), + "-v", + "1.2.3.4", + ], + ); + } + #[test] fn run_inf2cat_with_no_args_uses_arch_os_and_uselocaltime() { let working_dir = PathBuf::from("C:/abs/driver"); @@ -940,6 +1081,7 @@ mod tests { signtool_args: Vec::new(), }, inf2cat_args: None, + stampinf_args: None, target_platform: TargetPlatform::Universal, }; @@ -985,6 +1127,7 @@ mod tests { signtool_args: Vec::new(), }, inf2cat_args: Some(Vec::new()), + stampinf_args: None, target_platform: TargetPlatform::Universal, }; @@ -1030,6 +1173,7 @@ mod tests { "/os:10_x64,10_CO_X64".to_string(), "/verbose".to_string(), ]), + stampinf_args: None, target_platform: TargetPlatform::Universal, }; @@ -1088,6 +1232,7 @@ mod tests { sample_class: false, sign_mode: SignMode::Off, inf2cat_args: None, + stampinf_args: None, target_platform: TargetPlatform::Universal, }; PackageTask::new(params, wdk_build, command_exec, fs) @@ -1285,6 +1430,7 @@ mod tests { ], }, inf2cat_args: None, + stampinf_args: None, target_platform: TargetPlatform::Universal, }; let task = PackageTask::new(params, &wdk_build, &command_exec, &fs); @@ -1312,6 +1458,7 @@ mod tests { sample_class: false, sign_mode: SignMode::Off, inf2cat_args: None, + stampinf_args: None, target_platform, }; diff --git a/crates/cargo-wdk/src/actions/build/tests.rs b/crates/cargo-wdk/src/actions/build/tests.rs index 75ab50984..6e432e5f3 100644 --- a/crates/cargo-wdk/src/actions/build/tests.rs +++ b/crates/cargo-wdk/src/actions/build/tests.rs @@ -1754,6 +1754,7 @@ fn initialize_build_action<'a>( target_arch, sign_mode, inf2cat_args: None, + stampinf_args: None, is_sample_class: sample_class, locked: test_build_action.locked, target_platform: TargetPlatform::Universal, diff --git a/crates/cargo-wdk/src/cli.rs b/crates/cargo-wdk/src/cli.rs index a0d581e78..4d3cc98ff 100644 --- a/crates/cargo-wdk/src/cli.rs +++ b/crates/cargo-wdk/src/cli.rs @@ -164,6 +164,18 @@ pub struct BuildArgs { )] pub inf2cat_args: Option, + /// Custom arguments to pass to `stampinf` when generating the INF file, + /// e.g. `--stampinf-args '-d 01/01/2026 -v 1.2.3.4 -p "Contoso Ltd"'`. + #[arg( + long, + value_name = "ARGS", + // `stampinf` switches are `-` prefixed. + allow_hyphen_values = true, + value_parser = parse_passthrough_args, + help_heading = "Stampinf Options" + )] + pub stampinf_args: Option, + /// Assert that `Cargo.lock` will remain unchanged #[arg(long)] pub locked: bool, @@ -228,6 +240,37 @@ impl BuildArgs { } Ok(Some(args)) } + + /// Resolves the arguments to forward to `stampinf`. Rejects + /// the switches cargo-wdk derives from the build itself: `-f`, `-a`, `-c`, + /// `-k` and `-u`. + /// Returns a `clap::Error` if the caller-supplied arguments are invalid. + fn stampinf_args(&self) -> Result>, clap::Error> { + const STAMPINF_RESERVED_SWITCHES: [&str; 5] = ["f", "a", "c", "k", "u"]; + let Some(args) = self.stampinf_args.clone().map(|parsed| parsed.0) else { + return Ok(None); + }; + for arg in &args { + // `stampinf` accepts both `-x` and `/x`, case-insensitively. + let Some(switch) = arg.strip_prefix(['-', '/']) else { + continue; + }; + if STAMPINF_RESERVED_SWITCHES + .iter() + .any(|reserved| switch.eq_ignore_ascii_case(reserved)) + { + return Err(Cli::command().error( + ErrorKind::ArgumentConflict, + format!( + "`--stampinf-args` must not contain `{arg}`; cargo-wdk supplies the `-{}` \ + switches itself", + STAMPINF_RESERVED_SWITCHES.join("`, `-") + ), + )); + } + } + Ok(Some(args)) + } } /// `value_parser` for passthrough tool arguments: tokenizes the raw string @@ -355,6 +398,7 @@ impl Cli { Subcmd::Build(cli_args) => { let sign_mode = cli_args.sign_mode()?; let inf2cat_args = cli_args.inf2cat_args()?; + let stampinf_args = cli_args.stampinf_args()?; BuildAction::new( &BuildActionParams { working_dir: Path::new("."), // Using current dir as working dir @@ -362,6 +406,7 @@ impl Cli { target_arch: cli_args.target_arch, sign_mode, inf2cat_args, + stampinf_args, is_sample_class: cli_args.sample, locked: cli_args.locked, target_platform: cli_args.target_platform.into(), @@ -556,6 +601,51 @@ mod tests { Some(vec!["/os:10_x64".to_string(), "/uselocaltime".to_string()]) ); } + + #[test] + fn stampinf_args_rejects_switches_reserved_by_cargo_wdk() { + for value in [ + "-f other.inf", + "-a arm64", + "-c other.cat", + "-k 1.15", + "-u 2.33.0", + "/c other.cat", + "-C other.cat", + "-d 01/01/2026 -A arm64", + ] { + let args = + parse_build_args(&["--stampinf-args", value]).expect("args should parse"); + let err = args + .stampinf_args() + .expect_err("reserved switch should be rejected"); + assert!( + err.to_string() + .contains("cargo-wdk supplies the `-f`, `-a`, `-c`, `-k`, `-u` switches"), + "unexpected error for {value:?}: {err}" + ); + } + } + + #[test] + fn stampinf_args_allows_other_switches() { + let args = parse_build_args(&[ + "--stampinf-args", + "-d 01/01/2026 -v 1.2.3.4 -p \"Contoso Ltd\"", + ]) + .expect("args should parse"); + assert_eq!( + args.stampinf_args().expect("should resolve"), + Some(vec![ + "-d".to_string(), + "01/01/2026".to_string(), + "-v".to_string(), + "1.2.3.4".to_string(), + "-p".to_string(), + "Contoso Ltd".to_string(), + ]) + ); + } } mod parse_passthrough_args { diff --git a/crates/cargo-wdk/tests/build_command_test.rs b/crates/cargo-wdk/tests/build_command_test.rs index 020950750..43891d17f 100644 --- a/crates/cargo-wdk/tests/build_command_test.rs +++ b/crates/cargo-wdk/tests/build_command_test.rs @@ -745,6 +745,62 @@ fn kmdf_driver_with_custom_inf2cat_args_builds_successfully() { ); } +/// Functional tests for the `--stampinf-args` passthrough. +mod stampinf_args { + use super::*; + + #[test] + fn kmdf_driver_with_custom_date_and_version_builds_successfully() { + let driver = "kmdf-driver"; + clean_build_and_verify_project( + "kmdf", + driver, + None, + Some("4.3.2.1"), + None, + None, + None, + None, + Some(&["--stampinf-args", "-d 01/01/2026 -v 4.3.2.1"]), + ); + } + + #[test] + fn custom_version_wins_over_stampinf_version_env_var() { + let driver = "kmdf-driver"; + let env = [(STAMPINF_VERSION_ENV_VAR, Some("9.9.9.9".to_string()))]; + clean_build_and_verify_project( + "kmdf", + driver, + None, + Some("4.3.2.1"), + None, + None, + Some(&env), + None, + Some(&["--stampinf-args", "-v 4.3.2.1"]), + ); + } + + #[test] + fn switches_owned_by_cargo_wdk_are_rejected() { + let driver = "kmdf-driver"; + let project_path = format!("tests/{driver}"); + let mut cmd = create_cargo_wdk_cmd( + "build", + Some(&["--stampinf-args", "-c other.cat"]), + None, + Some(&project_path), + ); + let assertion = cmd.assert().failure(); + let stderr = String::from_utf8_lossy(&assertion.get_output().stderr).to_string(); + assert!( + stderr.contains("`--stampinf-args` must not contain `-c`"), + "expected validation error naming the reserved switch, got: {stderr}" + ); + } +} + #[allow(clippy::too_many_arguments)] fn clean_build_and_verify_project( driver_type: &str, From 9073b1876fb13301898053c86be4bdd238efb1b9 Mon Sep 17 00:00:00 2001 From: Shravan Vasista Date: Fri, 4 Sep 2026 14:25:59 +0530 Subject: [PATCH 02/10] refactor(cargo-wdk): address review feedback - rename `switches` to `args` - drop the functional test for reserved args - fix README --- crates/cargo-wdk/README.md | 2 +- .../src/actions/build/package_task.rs | 12 +++++----- crates/cargo-wdk/src/cli.rs | 24 +++++++++---------- crates/cargo-wdk/tests/build_command_test.rs | 18 -------------- 4 files changed, 19 insertions(+), 37 deletions(-) diff --git a/crates/cargo-wdk/README.md b/crates/cargo-wdk/README.md index baaddafa8..a405b180e 100644 --- a/crates/cargo-wdk/README.md +++ b/crates/cargo-wdk/README.md @@ -82,7 +82,7 @@ Driver Signing: --verify-signature Verify the signatures of the driver binary and catalog file after signing Inf2Cat Options: - --inf2cat-args Custom arguments to pass to `inf2cat` when generating the catalog file, e.g. `--inf2cat-args '/os:10_x64,10_GE_X64 /uselocaltime'` + --inf2cat-args Custom arguments to pass to `inf2cat` when generating the catalog file, e.g. `--inf2cat-args '/os:10_x64,10_GE_X64 /uselocaltime'` Stampinf Options: --stampinf-args Custom arguments to pass to `stampinf` when generating the INF file, e.g. `--stampinf-args '-d 01/01/2026 -v 1.2.3.4 -p "Contoso Ltd"'` diff --git a/crates/cargo-wdk/src/actions/build/package_task.rs b/crates/cargo-wdk/src/actions/build/package_task.rs index 90c76a633..1695d35f3 100644 --- a/crates/cargo-wdk/src/actions/build/package_task.rs +++ b/crates/cargo-wdk/src/actions/build/package_task.rs @@ -362,8 +362,8 @@ impl<'a> PackageTask<'a> { } fn run_stampinf(&self) -> Result<(), PackageTaskError> { - const STAMPINF_DATE_SWITCH: &str = "d"; - const STAMPINF_VERSION_SWITCH: &str = "v"; + const STAMPINF_DATE_ARG: &str = "d"; + const STAMPINF_VERSION_ARG: &str = "v"; info!("Running stampinf"); let wdf_version_flags = match self.driver_model { @@ -392,11 +392,11 @@ impl<'a> PackageTask<'a> { let arch = self.arch.to_string(); let mut args: Vec<&str> = vec!["-f", &dest_inf_file_path]; - if !self.stampinf_args_contains(STAMPINF_DATE_SWITCH) { + if !self.stampinf_args_contains(STAMPINF_DATE_ARG) { args.extend(["-d", "*"]); } args.extend(["-a", &arch, "-c", &cat_file_path]); - if self.stampinf_args_contains(STAMPINF_VERSION_SWITCH) { + if self.stampinf_args_contains(STAMPINF_VERSION_ARG) { debug!("Using -v from --stampinf-args to set DriverVer"); } else { match std::env::var(STAMPINF_VERSION_ENV_VAR) { @@ -428,10 +428,10 @@ impl<'a> PackageTask<'a> { Ok(()) } - fn stampinf_args_contains(&self, switch: &str) -> bool { + fn stampinf_args_contains(&self, arg_name: &str) -> bool { self.stampinf_args.iter().flatten().any(|arg| { arg.strip_prefix(['-', '/']) - .is_some_and(|arg| arg.eq_ignore_ascii_case(switch)) + .is_some_and(|arg| arg.eq_ignore_ascii_case(arg_name)) }) } diff --git a/crates/cargo-wdk/src/cli.rs b/crates/cargo-wdk/src/cli.rs index 4d3cc98ff..90b37e01e 100644 --- a/crates/cargo-wdk/src/cli.rs +++ b/crates/cargo-wdk/src/cli.rs @@ -169,7 +169,7 @@ pub struct BuildArgs { #[arg( long, value_name = "ARGS", - // `stampinf` switches are `-` prefixed. + // `stampinf` args are `-` prefixed. allow_hyphen_values = true, value_parser = parse_passthrough_args, help_heading = "Stampinf Options" @@ -242,29 +242,29 @@ impl BuildArgs { } /// Resolves the arguments to forward to `stampinf`. Rejects - /// the switches cargo-wdk derives from the build itself: `-f`, `-a`, `-c`, + /// the args cargo-wdk derives from the build itself: `-f`, `-a`, `-c`, /// `-k` and `-u`. /// Returns a `clap::Error` if the caller-supplied arguments are invalid. fn stampinf_args(&self) -> Result>, clap::Error> { - const STAMPINF_RESERVED_SWITCHES: [&str; 5] = ["f", "a", "c", "k", "u"]; + const STAMPINF_RESERVED_ARGS: [&str; 5] = ["f", "a", "c", "k", "u"]; let Some(args) = self.stampinf_args.clone().map(|parsed| parsed.0) else { return Ok(None); }; for arg in &args { // `stampinf` accepts both `-x` and `/x`, case-insensitively. - let Some(switch) = arg.strip_prefix(['-', '/']) else { + let Some(arg_name) = arg.strip_prefix(['-', '/']) else { continue; }; - if STAMPINF_RESERVED_SWITCHES + if STAMPINF_RESERVED_ARGS .iter() - .any(|reserved| switch.eq_ignore_ascii_case(reserved)) + .any(|reserved| arg_name.eq_ignore_ascii_case(reserved)) { return Err(Cli::command().error( ErrorKind::ArgumentConflict, format!( "`--stampinf-args` must not contain `{arg}`; cargo-wdk supplies the `-{}` \ - switches itself", - STAMPINF_RESERVED_SWITCHES.join("`, `-") + args itself", + STAMPINF_RESERVED_ARGS.join("`, `-") ), )); } @@ -603,7 +603,7 @@ mod tests { } #[test] - fn stampinf_args_rejects_switches_reserved_by_cargo_wdk() { + fn stampinf_args_rejects_args_reserved_by_cargo_wdk() { for value in [ "-f other.inf", "-a arm64", @@ -618,17 +618,17 @@ mod tests { parse_build_args(&["--stampinf-args", value]).expect("args should parse"); let err = args .stampinf_args() - .expect_err("reserved switch should be rejected"); + .expect_err("reserved arg should be rejected"); assert!( err.to_string() - .contains("cargo-wdk supplies the `-f`, `-a`, `-c`, `-k`, `-u` switches"), + .contains("cargo-wdk supplies the `-f`, `-a`, `-c`, `-k`, `-u` args"), "unexpected error for {value:?}: {err}" ); } } #[test] - fn stampinf_args_allows_other_switches() { + fn stampinf_args_allows_other_args() { let args = parse_build_args(&[ "--stampinf-args", "-d 01/01/2026 -v 1.2.3.4 -p \"Contoso Ltd\"", diff --git a/crates/cargo-wdk/tests/build_command_test.rs b/crates/cargo-wdk/tests/build_command_test.rs index 43891d17f..59f181117 100644 --- a/crates/cargo-wdk/tests/build_command_test.rs +++ b/crates/cargo-wdk/tests/build_command_test.rs @@ -781,24 +781,6 @@ mod stampinf_args { Some(&["--stampinf-args", "-v 4.3.2.1"]), ); } - - #[test] - fn switches_owned_by_cargo_wdk_are_rejected() { - let driver = "kmdf-driver"; - let project_path = format!("tests/{driver}"); - let mut cmd = create_cargo_wdk_cmd( - "build", - Some(&["--stampinf-args", "-c other.cat"]), - None, - Some(&project_path), - ); - let assertion = cmd.assert().failure(); - let stderr = String::from_utf8_lossy(&assertion.get_output().stderr).to_string(); - assert!( - stderr.contains("`--stampinf-args` must not contain `-c`"), - "expected validation error naming the reserved switch, got: {stderr}" - ); - } } #[allow(clippy::too_many_arguments)] From 0d43add65e7675a8c46ae2da1a76b85fc25f6952 Mon Sep 17 00:00:00 2001 From: Shravan Vasista Date: Tue, 8 Sep 2026 14:27:25 +0530 Subject: [PATCH 03/10] docs(cargo-wdk): add a `--stampinf-args` section and clarify arg naming --- crates/cargo-wdk/README.md | 10 ++++++++++ crates/cargo-wdk/src/cli.rs | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/crates/cargo-wdk/README.md b/crates/cargo-wdk/README.md index a405b180e..85cba9e54 100644 --- a/crates/cargo-wdk/README.md +++ b/crates/cargo-wdk/README.md @@ -111,6 +111,16 @@ Building a sample driver requires the `--sample` flag. If it is not specified, t If you have a workspace with a mix of sample and non-sample driver projects, the build will fail as that scenario is not supported yet. In the future `build` will be able to automatically detect sample projects. That will remove the need for the `--sample` flag and enable support for this scenario. +#### Customizing `stampinf` arguments + +To stamp a fixed `DriverVer`, `Provider`, or customize the generated INF file, pass `--stampinf-args` with a string of the arguments to forward to `stampinf`. + +**Note:** + +- `cargo-wdk` derives `-f`, `-a`, `-c`, `-k` and `-u` from the build, so passing any of them is an error. +- `cargo-wdk` passes `-d *` and `-v *` by default. You can supply your own `-d ` or `-v ` to override them. +- If `-v ` is present it sets the `DriverVer` version to the value passed, else the `STAMPINF_VERSION` environment variable is used. If neither is available, `cargo-wdk` uses the default, `-v *`. + #### Customizing `inf2cat` arguments To target a specific set of Windows versions or to customize the behaviour of `inf2cat` in any other way, pass `--inf2cat-args` with a string of the arguments to forward to `inf2cat`. `cargo-wdk` itself provides the `/driver` argument so do not include it or its alias `/drv`. diff --git a/crates/cargo-wdk/src/cli.rs b/crates/cargo-wdk/src/cli.rs index 90b37e01e..d8f52637c 100644 --- a/crates/cargo-wdk/src/cli.rs +++ b/crates/cargo-wdk/src/cli.rs @@ -169,7 +169,7 @@ pub struct BuildArgs { #[arg( long, value_name = "ARGS", - // `stampinf` args are `-` prefixed. + // `stampinf` args can be `-` prefixed. allow_hyphen_values = true, value_parser = parse_passthrough_args, help_heading = "Stampinf Options" @@ -628,7 +628,7 @@ mod tests { } #[test] - fn stampinf_args_allows_other_args() { + fn stampinf_args_allows_args_not_reserved_by_cargo_wdk() { let args = parse_build_args(&[ "--stampinf-args", "-d 01/01/2026 -v 1.2.3.4 -p \"Contoso Ltd\"", From 44904cc6492e521f0a28f48dce354203f9f041b4 Mon Sep 17 00:00:00 2001 From: Shravan Vasista Date: Wed, 9 Sep 2026 15:14:28 +0530 Subject: [PATCH 04/10] Update crates/cargo-wdk/README.md Co-authored-by: Gurinder Singh Signed-off-by: Shravan Vasista --- crates/cargo-wdk/README.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/crates/cargo-wdk/README.md b/crates/cargo-wdk/README.md index 85cba9e54..f2748e021 100644 --- a/crates/cargo-wdk/README.md +++ b/crates/cargo-wdk/README.md @@ -113,14 +113,7 @@ If you have a workspace with a mix of sample and non-sample driver projects, the #### Customizing `stampinf` arguments -To stamp a fixed `DriverVer`, `Provider`, or customize the generated INF file, pass `--stampinf-args` with a string of the arguments to forward to `stampinf`. - -**Note:** - -- `cargo-wdk` derives `-f`, `-a`, `-c`, `-k` and `-u` from the build, so passing any of them is an error. -- `cargo-wdk` passes `-d *` and `-v *` by default. You can supply your own `-d ` or `-v ` to override them. -- If `-v ` is present it sets the `DriverVer` version to the value passed, else the `STAMPINF_VERSION` environment variable is used. If neither is available, `cargo-wdk` uses the default, `-v *`. - +To customize the behaviour of `stampinf`, pass `--stampinf-args` with arguments to forward to `stampinf`. Args `-f`, `-a`, `-c`, `-k` and `-u` are not allowed because they are always supplied by `cargo-wdk` itself. #### Customizing `inf2cat` arguments To target a specific set of Windows versions or to customize the behaviour of `inf2cat` in any other way, pass `--inf2cat-args` with a string of the arguments to forward to `inf2cat`. `cargo-wdk` itself provides the `/driver` argument so do not include it or its alias `/drv`. From 40194dc9236c4f1e52d24971a21b55b4f7e555a2 Mon Sep 17 00:00:00 2001 From: Shravan Vasista Date: Wed, 9 Sep 2026 22:12:51 +0530 Subject: [PATCH 05/10] Update crates/cargo-wdk/src/cli.rs Co-authored-by: Gurinder Singh Signed-off-by: Shravan Vasista --- crates/cargo-wdk/src/cli.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/crates/cargo-wdk/src/cli.rs b/crates/cargo-wdk/src/cli.rs index d8f52637c..53d8cbfbd 100644 --- a/crates/cargo-wdk/src/cli.rs +++ b/crates/cargo-wdk/src/cli.rs @@ -259,13 +259,14 @@ impl BuildArgs { .iter() .any(|reserved| arg_name.eq_ignore_ascii_case(reserved)) { - return Err(Cli::command().error( - ErrorKind::ArgumentConflict, - format!( - "`--stampinf-args` must not contain `{arg}`; cargo-wdk supplies the `-{}` \ - args itself", - STAMPINF_RESERVED_ARGS.join("`, `-") - ), + let reserved_args = STAMPINF_RESERVED_ARGS + .iter() + .map(|arg| format!("`-{arg}`")) + .collect::>() + .join(", "); + return Err(Cli::command().error( + ErrorKind::ArgumentConflict, + format!("`--stampinf-args` must not contain `{arg}`; cargo-wdk supplies the {reserved_args} args itself"))); )); } } From cb525e965f7b967d190987ad78bd330aa2037e4b Mon Sep 17 00:00:00 2001 From: Shravan Vasista Date: Wed, 9 Sep 2026 22:38:06 +0530 Subject: [PATCH 06/10] fix: pair the delimiters correctly in `stampinf_args` function --- crates/cargo-wdk/src/cli.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/crates/cargo-wdk/src/cli.rs b/crates/cargo-wdk/src/cli.rs index 53d8cbfbd..20515d1ce 100644 --- a/crates/cargo-wdk/src/cli.rs +++ b/crates/cargo-wdk/src/cli.rs @@ -259,14 +259,17 @@ impl BuildArgs { .iter() .any(|reserved| arg_name.eq_ignore_ascii_case(reserved)) { - let reserved_args = STAMPINF_RESERVED_ARGS + let reserved_args = STAMPINF_RESERVED_ARGS .iter() .map(|arg| format!("`-{arg}`")) .collect::>() .join(", "); - return Err(Cli::command().error( - ErrorKind::ArgumentConflict, - format!("`--stampinf-args` must not contain `{arg}`; cargo-wdk supplies the {reserved_args} args itself"))); + return Err(Cli::command().error( + ErrorKind::ArgumentConflict, + format!( + "`--stampinf-args` must not contain `{arg}`; cargo-wdk supplies the \ + {reserved_args} args itself" + ), )); } } From eb2f4147d4912f40ba641a532a449c9ea625fda5 Mon Sep 17 00:00:00 2001 From: Shravan Vasista Date: Thu, 10 Sep 2026 13:02:06 +0530 Subject: [PATCH 07/10] test(cargo-wdk): use mixed switch prefixes in `--stampinf-args` tests --- crates/cargo-wdk/src/actions/build/package_task.rs | 12 +++++------- crates/cargo-wdk/src/cli.rs | 6 +++--- crates/cargo-wdk/tests/build_command_test.rs | 4 ++-- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/crates/cargo-wdk/src/actions/build/package_task.rs b/crates/cargo-wdk/src/actions/build/package_task.rs index 1695d35f3..77394ec86 100644 --- a/crates/cargo-wdk/src/actions/build/package_task.rs +++ b/crates/cargo-wdk/src/actions/build/package_task.rs @@ -416,9 +416,7 @@ impl<'a> PackageTask<'a> { } } - if !wdf_version_flags.is_empty() { - args.append(&mut wdf_version_flags.iter().map(String::as_str).collect()); - } + args.extend(wdf_version_flags.iter().map(String::as_str)); if let Some(stampinf_args) = &self.stampinf_args { args.extend(stampinf_args.iter().map(String::as_str)); } @@ -1004,7 +1002,7 @@ mod tests { fn run_stampinf_appends_custom_args_after_the_defaults() { stampinf_args_works_with_defaults( None, - &["-p", "Contoso Ltd", "-n"], + &["/p", "Contoso Ltd", "-n"], &[ "-d", "*", @@ -1016,7 +1014,7 @@ mod tests { "*", "-k", &default_kmdf_version(), - "-p", + "/p", "Contoso Ltd", "-n", ], @@ -1047,7 +1045,7 @@ mod tests { fn run_stampinf_caller_version_wins_over_env_var() { stampinf_args_works_with_defaults( Some("9.9.9.9"), - &["-v", "1.2.3.4"], + &["/v", "1.2.3.4"], &[ "-d", "*", @@ -1057,7 +1055,7 @@ mod tests { "driver.cat", "-k", &default_kmdf_version(), - "-v", + "/v", "1.2.3.4", ], ); diff --git a/crates/cargo-wdk/src/cli.rs b/crates/cargo-wdk/src/cli.rs index 20515d1ce..c7c727381 100644 --- a/crates/cargo-wdk/src/cli.rs +++ b/crates/cargo-wdk/src/cli.rs @@ -616,7 +616,7 @@ mod tests { "-u 2.33.0", "/c other.cat", "-C other.cat", - "-d 01/01/2026 -A arm64", + "-d 01/01/2026 /A arm64", ] { let args = parse_build_args(&["--stampinf-args", value]).expect("args should parse"); @@ -635,7 +635,7 @@ mod tests { fn stampinf_args_allows_args_not_reserved_by_cargo_wdk() { let args = parse_build_args(&[ "--stampinf-args", - "-d 01/01/2026 -v 1.2.3.4 -p \"Contoso Ltd\"", + "-d 01/01/2026 /v 1.2.3.4 -p \"Contoso Ltd\"", ]) .expect("args should parse"); assert_eq!( @@ -643,7 +643,7 @@ mod tests { Some(vec![ "-d".to_string(), "01/01/2026".to_string(), - "-v".to_string(), + "/v".to_string(), "1.2.3.4".to_string(), "-p".to_string(), "Contoso Ltd".to_string(), diff --git a/crates/cargo-wdk/tests/build_command_test.rs b/crates/cargo-wdk/tests/build_command_test.rs index 59f181117..d7572e6c9 100644 --- a/crates/cargo-wdk/tests/build_command_test.rs +++ b/crates/cargo-wdk/tests/build_command_test.rs @@ -761,7 +761,7 @@ mod stampinf_args { None, None, None, - Some(&["--stampinf-args", "-d 01/01/2026 -v 4.3.2.1"]), + Some(&["--stampinf-args", "-d 01/01/2026 /v 4.3.2.1"]), ); } @@ -778,7 +778,7 @@ mod stampinf_args { None, Some(&env), None, - Some(&["--stampinf-args", "-v 4.3.2.1"]), + Some(&["--stampinf-args", "/v 4.3.2.1"]), ); } } From bc3d720ce2e66b10fa0a30fb4d9dd4532b7651df Mon Sep 17 00:00:00 2001 From: Shravan Vasista Date: Thu, 10 Sep 2026 17:29:19 +0530 Subject: [PATCH 08/10] docs(cargo-wdk): separate the stampinf section from the next heading --- crates/cargo-wdk/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/cargo-wdk/README.md b/crates/cargo-wdk/README.md index f2748e021..d635939bb 100644 --- a/crates/cargo-wdk/README.md +++ b/crates/cargo-wdk/README.md @@ -113,7 +113,8 @@ If you have a workspace with a mix of sample and non-sample driver projects, the #### Customizing `stampinf` arguments -To customize the behaviour of `stampinf`, pass `--stampinf-args` with arguments to forward to `stampinf`. Args `-f`, `-a`, `-c`, `-k` and `-u` are not allowed because they are always supplied by `cargo-wdk` itself. +To customize the behaviour of `stampinf`, pass `--stampinf-args` with arguments to forward to `stampinf`. Args `-f`, `-a`, `-c`, `-k` and `-u` are not allowed because they are always supplied by `cargo-wdk` itself. + #### Customizing `inf2cat` arguments To target a specific set of Windows versions or to customize the behaviour of `inf2cat` in any other way, pass `--inf2cat-args` with a string of the arguments to forward to `inf2cat`. `cargo-wdk` itself provides the `/driver` argument so do not include it or its alias `/drv`. From bdfda190ffb962afec833ada1789bb325c66f549 Mon Sep 17 00:00:00 2001 From: Shravan Vasista Date: Tue, 15 Sep 2026 10:19:37 +0530 Subject: [PATCH 09/10] refactor(cargo-wdk): address review comments on stampinf passthrough - Inline single-use date and version arg constants in `run_stampinf` - Assert `-f` and generated INF file path in `assert_stampinf_args` unit test - Rename test helper `stampinf_args_works_with_defaults` to `assert_stampinf_args` - Shorten `STAMPINF_RESERVED_ARGS` to `RESERVED_ARGS` in `stampinf_args` --- .../src/actions/build/package_task.rs | 32 +++++++++---------- crates/cargo-wdk/src/cli.rs | 6 ++-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/crates/cargo-wdk/src/actions/build/package_task.rs b/crates/cargo-wdk/src/actions/build/package_task.rs index 77394ec86..45882a297 100644 --- a/crates/cargo-wdk/src/actions/build/package_task.rs +++ b/crates/cargo-wdk/src/actions/build/package_task.rs @@ -362,9 +362,6 @@ impl<'a> PackageTask<'a> { } fn run_stampinf(&self) -> Result<(), PackageTaskError> { - const STAMPINF_DATE_ARG: &str = "d"; - const STAMPINF_VERSION_ARG: &str = "v"; - info!("Running stampinf"); let wdf_version_flags = match self.driver_model { DriverConfig::Kmdf(kmdf_config) => { @@ -392,11 +389,11 @@ impl<'a> PackageTask<'a> { let arch = self.arch.to_string(); let mut args: Vec<&str> = vec!["-f", &dest_inf_file_path]; - if !self.stampinf_args_contains(STAMPINF_DATE_ARG) { + if !self.stampinf_args_contains("d") { args.extend(["-d", "*"]); } args.extend(["-a", &arch, "-c", &cat_file_path]); - if self.stampinf_args_contains(STAMPINF_VERSION_ARG) { + if self.stampinf_args_contains("v") { debug!("Using -v from --stampinf-args to set DriverVer"); } else { match std::env::var(STAMPINF_VERSION_ENV_VAR) { @@ -939,11 +936,7 @@ mod tests { } } - fn stampinf_args_works_with_defaults( - env_version: Option<&str>, - stampinf_args: &[&str], - expected: &[&str], - ) { + fn assert_stampinf_args(env_version: Option<&str>, stampinf_args: &[&str], expected: &[&str]) { let working_dir = PathBuf::from("C:/abs/driver"); let target_dir = PathBuf::from("C:/abs/driver/target/debug"); let arch = CpuArchitecture::Amd64; @@ -964,13 +957,20 @@ mod tests { let wdk_build = WdkBuild::default(); let fs = Fs::default(); let mut command_exec = CommandExec::default(); + let expected_inf_file_path = target_dir + .join("driver_package") + .join("driver.inf") + .to_string_lossy() + .into_owned(); let expected: Vec = expected.iter().map(ToString::to_string).collect(); command_exec .expect_run() .withf(move |cmd: &str, args: &[&str], _, _| { - // Skip the `-f ` prefix, whose path is environment - // specific. - cmd == "stampinf" && args[2..] == expected[..] + cmd == "stampinf" + && args.len() >= 2 + && args[0] == "-f" + && args[1] == expected_inf_file_path + && args[2..] == expected[..] }) .once() .return_once(|_, _, _, _| { @@ -1000,7 +1000,7 @@ mod tests { #[test] fn run_stampinf_appends_custom_args_after_the_defaults() { - stampinf_args_works_with_defaults( + assert_stampinf_args( None, &["/p", "Contoso Ltd", "-n"], &[ @@ -1023,7 +1023,7 @@ mod tests { #[test] fn run_stampinf_drops_default_date_and_version_when_caller_supplies_them() { - stampinf_args_works_with_defaults( + assert_stampinf_args( None, &["-d", "01/01/2026", "/V", "1.2.3.4"], &[ @@ -1043,7 +1043,7 @@ mod tests { #[test] fn run_stampinf_caller_version_wins_over_env_var() { - stampinf_args_works_with_defaults( + assert_stampinf_args( Some("9.9.9.9"), &["/v", "1.2.3.4"], &[ diff --git a/crates/cargo-wdk/src/cli.rs b/crates/cargo-wdk/src/cli.rs index c7c727381..3753538ab 100644 --- a/crates/cargo-wdk/src/cli.rs +++ b/crates/cargo-wdk/src/cli.rs @@ -246,7 +246,7 @@ impl BuildArgs { /// `-k` and `-u`. /// Returns a `clap::Error` if the caller-supplied arguments are invalid. fn stampinf_args(&self) -> Result>, clap::Error> { - const STAMPINF_RESERVED_ARGS: [&str; 5] = ["f", "a", "c", "k", "u"]; + const RESERVED_ARGS: [&str; 5] = ["f", "a", "c", "k", "u"]; let Some(args) = self.stampinf_args.clone().map(|parsed| parsed.0) else { return Ok(None); }; @@ -255,11 +255,11 @@ impl BuildArgs { let Some(arg_name) = arg.strip_prefix(['-', '/']) else { continue; }; - if STAMPINF_RESERVED_ARGS + if RESERVED_ARGS .iter() .any(|reserved| arg_name.eq_ignore_ascii_case(reserved)) { - let reserved_args = STAMPINF_RESERVED_ARGS + let reserved_args = RESERVED_ARGS .iter() .map(|arg| format!("`-{arg}`")) .collect::>() From c12f199cc4106c9abcfb77ca8a8811214a1d2958 Mon Sep 17 00:00:00 2001 From: Shravan Vasista Date: Thu, 17 Sep 2026 09:14:35 +0530 Subject: [PATCH 10/10] test(cargo-wdk): verify exact DriverVer date in stampinf test --- crates/cargo-wdk/tests/build_command_test.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/crates/cargo-wdk/tests/build_command_test.rs b/crates/cargo-wdk/tests/build_command_test.rs index cd681c9d5..ff2a157d8 100644 --- a/crates/cargo-wdk/tests/build_command_test.rs +++ b/crates/cargo-wdk/tests/build_command_test.rs @@ -756,7 +756,7 @@ mod stampinf_args { "kmdf", driver, None, - Some("4.3.2.1"), + Some("01/01/2026,4.3.2.1"), None, None, None, @@ -1013,10 +1013,21 @@ fn assert_driver_ver(package_path: &str, driver_name: &str, driver_version: Opti }; // Example: DriverVer = 09/13/2023,1.0.0.0 + let (driver_date, driver_version) = match driver_version { + Some(val) if val.contains(',') => { + let (d, v) = val.split_once(',').unwrap(); + let d = (!d.is_empty()).then_some(d); + let v = (!v.is_empty()).then_some(v); + (d, v) + } + _ => (None, driver_version), + }; + + let driver_date_regex = driver_date.map_or_else(|| r"\d+/\d+/\d+".to_string(), regex::escape); let driver_version_regex = driver_version.map_or_else(|| r"\d+\.\d+\.\d+\.\d+".to_string(), regex::escape); let re = regex::Regex::new(&format!( - r"^DriverVer\s+=\s+\d+/\d+/\d+,{driver_version_regex}$" + r"^DriverVer\s+=\s+{driver_date_regex},{driver_version_regex}$" )) .unwrap();