Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
9 changes: 8 additions & 1 deletion crates/cargo-wdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ Driver Signing:
--verify-signature Verify the signatures of the driver binary and catalog file after signing

Inf2Cat Options:
--inf2cat-args <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 <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 <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"'`
Comment thread
gurry marked this conversation as resolved.

InfVerif Options:
--infverif-args <ARGS> Custom arguments to pass to `infverif` when validating the INF, e.g. `--infverif-args '/rulever 10.0.22621 /info'`
Expand Down Expand Up @@ -111,6 +114,10 @@ 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 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`.
Expand Down
4 changes: 4 additions & 0 deletions crates/cargo-wdk/src/actions/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ pub struct BuildActionParams<'a> {
pub target_arch: Option<CpuArchitecture>,
pub sign_mode: SignMode,
pub inf2cat_args: Option<Vec<String>>,
pub stampinf_args: Option<Vec<String>>,
pub infverif_args: Option<Vec<String>>,
pub is_sample_class: bool,
pub locked: bool,
Expand All @@ -96,6 +97,7 @@ pub struct BuildAction<'a> {
target_arch: Option<CpuArchitecture>,
sign_mode: SignMode,
inf2cat_args: Option<Vec<String>>,
stampinf_args: Option<Vec<String>>,
infverif_args: Option<Vec<String>>,
is_sample_class: bool,
locked: bool,
Expand Down Expand Up @@ -146,6 +148,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(),
infverif_args: params.infverif_args.clone(),
is_sample_class: params.is_sample_class,
locked: params.locked,
Expand Down Expand Up @@ -456,6 +459,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(),
infverif_args: self.infverif_args.clone(),
sample_class: self.is_sample_class,
driver_model,
Expand Down
197 changes: 172 additions & 25 deletions crates/cargo-wdk/src/actions/build/package_task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ pub struct PackageTaskParams<'a> {
pub target_arch: &'a CpuArchitecture,
pub sign_mode: SignMode,
pub inf2cat_args: Option<Vec<String>>,
pub stampinf_args: Option<Vec<String>>,
pub infverif_args: Option<Vec<String>>,
pub sample_class: bool,
pub driver_model: DriverConfig,
Expand All @@ -96,6 +97,7 @@ pub struct PackageTask<'a> {
package_name: String,
sign_mode: SignMode,
inf2cat_args: Option<Vec<String>>,
stampinf_args: Option<Vec<String>>,
infverif_args: Option<Vec<String>>,
sample_class: bool,

Expand Down Expand Up @@ -202,6 +204,7 @@ impl<'a> PackageTask<'a> {
package_name,
sign_mode: params.sign_mode,
inf2cat_args: params.inf2cat_args,
stampinf_args: params.stampinf_args,
infverif_args: params.infverif_args,
sample_class: params.sample_class,
src_inx_file_path,
Expand Down Expand Up @@ -377,42 +380,49 @@ 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("d") {
args.extend(["-d", "*"]);
}
args.extend(["-a", &arch, "-c", &cat_file_path]);
if self.stampinf_args_contains("v") {
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());
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));
}
if let Err(e) = self.command_exec.run("stampinf", &args, None, None) {
return Err(PackageTaskError::StampinfCommand(e));
}
Ok(())
}

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(arg_name))
})
}

fn run_inf2cat(&self) -> Result<(), PackageTaskError> {
info!("Running inf2cat");
let driver_arg = format!(
Expand Down Expand Up @@ -733,6 +743,7 @@ mod tests {
signtool_args: Vec::new(),
},
inf2cat_args: None,
stampinf_args: None,
infverif_args: None,
target_platform: TargetPlatform::Universal,
};
Expand Down Expand Up @@ -803,6 +814,7 @@ mod tests {
signtool_args: Vec::new(),
},
inf2cat_args: None,
stampinf_args: None,
infverif_args: None,
target_platform: TargetPlatform::Universal,
};
Expand Down Expand Up @@ -835,6 +847,7 @@ mod tests {
signtool_args: Vec::new(),
},
inf2cat_args: None,
stampinf_args: None,
infverif_args: None,
target_platform: TargetPlatform::Universal,
};
Expand Down Expand Up @@ -876,6 +889,7 @@ mod tests {
signtool_args: Vec::new(),
},
inf2cat_args: None,
stampinf_args: None,
infverif_args: None,
target_platform: TargetPlatform::Universal,
};
Expand Down Expand Up @@ -917,6 +931,132 @@ mod tests {
}
}

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;

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()),
infverif_args: None,
target_platform: TargetPlatform::Universal,
};

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<String> = expected.iter().map(ToString::to_string).collect();
command_exec
.expect_run()
.withf(move |cmd: &str, args: &[&str], _, _| {
cmd == "stampinf"
&& args.len() >= 2
&& args[0] == "-f"
&& args[1] == expected_inf_file_path
&& 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() {
assert_stampinf_args(
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() {
assert_stampinf_args(
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() {
assert_stampinf_args(
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");
Expand All @@ -935,6 +1075,7 @@ mod tests {
signtool_args: Vec::new(),
},
inf2cat_args: None,
stampinf_args: None,
infverif_args: None,
target_platform: TargetPlatform::Universal,
};
Expand Down Expand Up @@ -981,6 +1122,7 @@ mod tests {
signtool_args: Vec::new(),
},
inf2cat_args: Some(Vec::new()),
stampinf_args: None,
infverif_args: None,
target_platform: TargetPlatform::Universal,
};
Expand Down Expand Up @@ -1027,6 +1169,7 @@ mod tests {
"/os:10_x64,10_CO_X64".to_string(),
"/verbose".to_string(),
]),
stampinf_args: None,
infverif_args: None,
target_platform: TargetPlatform::Universal,
};
Expand Down Expand Up @@ -1086,6 +1229,7 @@ mod tests {
sample_class: false,
sign_mode: SignMode::Off,
inf2cat_args: None,
stampinf_args: None,
infverif_args: None,
target_platform: TargetPlatform::Universal,
};
Expand Down Expand Up @@ -1284,6 +1428,7 @@ mod tests {
],
},
inf2cat_args: None,
stampinf_args: None,
infverif_args: None,
target_platform: TargetPlatform::Universal,
};
Expand Down Expand Up @@ -1312,6 +1457,7 @@ mod tests {
sample_class: false,
sign_mode: SignMode::Off,
inf2cat_args: None,
stampinf_args: None,
infverif_args: None,
target_platform,
};
Expand Down Expand Up @@ -1390,6 +1536,7 @@ mod tests {
sample_class: true,
sign_mode: SignMode::Off,
inf2cat_args: None,
stampinf_args: None,
infverif_args: Some(vec![
"/rulever".to_string(),
"10.0.22621".to_string(),
Expand Down
1 change: 1 addition & 0 deletions crates/cargo-wdk/src/actions/build/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1745,6 +1745,7 @@ fn initialize_build_action<'a>(
target_arch,
sign_mode,
inf2cat_args: None,
stampinf_args: None,
infverif_args: None,
is_sample_class: sample_class,
locked: test_build_action.locked,
Expand Down
Loading
Loading