Skip to content
Merged
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
7 changes: 7 additions & 0 deletions crates/cargo-wdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ Driver 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'`

InfVerif Options:
--infverif-args <ARGS> Custom arguments to pass to `infverif` when validating the INF, e.g. `--infverif-args '/rulever 10.0.22621 /info'`

Feature Selection:
--all-features Activate all available features
--no-default-features Do not activate the `default` feature
Expand Down Expand Up @@ -112,6 +115,10 @@ If you have a workspace with a mix of sample and non-sample driver projects, the

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`.

#### Customizing `infverif` arguments

To customize the behaviour of `infverif`, pass `--infverif-args` with arguments to forward to `infverif`. Args `-h`, `-w`, `-u` and paths to `.INF` files are not allowed because they are always supplied by `cargo-wdk` itself.

#### Signing and Verification

The `build` command has a `--sign-mode` flag that controls how driver artifacts are signed. It accepts the following values:
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 infverif_args: Option<Vec<String>>,
pub is_sample_class: bool,
pub locked: bool,
pub target_platform: TargetPlatform,
Expand All @@ -95,6 +96,7 @@ pub struct BuildAction<'a> {
target_arch: Option<CpuArchitecture>,
sign_mode: SignMode,
inf2cat_args: Option<Vec<String>>,
infverif_args: Option<Vec<String>>,
is_sample_class: bool,
locked: bool,
target_platform: TargetPlatform,
Expand Down Expand Up @@ -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(),
infverif_args: params.infverif_args.clone(),
is_sample_class: params.is_sample_class,
locked: params.locked,
target_platform: params.target_platform,
Expand Down Expand Up @@ -453,6 +456,7 @@ impl<'a> BuildAction<'a> {
target_arch: &target_arch,
sign_mode: self.sign_mode.clone(),
inf2cat_args: self.inf2cat_args.clone(),
infverif_args: self.infverif_args.clone(),
sample_class: self.is_sample_class,
driver_model,
target_platform: self.target_platform,
Expand Down
73 changes: 73 additions & 0 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 infverif_args: Option<Vec<String>>,
pub sample_class: bool,
pub driver_model: DriverConfig,
pub target_platform: TargetPlatform,
Expand All @@ -95,6 +96,7 @@ pub struct PackageTask<'a> {
package_name: String,
sign_mode: SignMode,
inf2cat_args: Option<Vec<String>>,
infverif_args: Option<Vec<String>>,
sample_class: bool,

// src paths
Expand Down Expand Up @@ -207,6 +209,7 @@ impl<'a> PackageTask<'a> {
package_name,
sign_mode: params.sign_mode,
inf2cat_args: params.inf2cat_args,
infverif_args: params.infverif_args,
sample_class: params.sample_class,
src_inx_file_path,
src_driver_binary_file_path,
Expand Down Expand Up @@ -642,6 +645,9 @@ impl<'a> PackageTask<'a> {
if self.sample_class {
args.push(additional_args);
}
if let Some(infverif_args) = &self.infverif_args {
args.extend(infverif_args.iter().map(String::as_str));
}
args.push(&inf_path);

if let Err(e) = self.command_exec.run("infverif", &args, None, None) {
Expand Down Expand Up @@ -737,6 +743,7 @@ mod tests {
signtool_args: Vec::new(),
},
inf2cat_args: None,
infverif_args: None,
target_platform: TargetPlatform::Universal,
};
let dest_root = target_dir.join(format!("{package_name}_package"));
Expand Down Expand Up @@ -811,6 +818,7 @@ mod tests {
signtool_args: Vec::new(),
},
inf2cat_args: None,
infverif_args: None,
target_platform: TargetPlatform::Universal,
};

Expand Down Expand Up @@ -842,6 +850,7 @@ mod tests {
signtool_args: Vec::new(),
},
inf2cat_args: None,
infverif_args: None,
target_platform: TargetPlatform::Universal,
};

Expand Down Expand Up @@ -882,6 +891,7 @@ mod tests {
signtool_args: Vec::new(),
},
inf2cat_args: None,
infverif_args: None,
target_platform: TargetPlatform::Universal,
};

Expand Down Expand Up @@ -940,6 +950,7 @@ mod tests {
signtool_args: Vec::new(),
},
inf2cat_args: None,
infverif_args: None,
target_platform: TargetPlatform::Universal,
};

Expand Down Expand Up @@ -985,6 +996,7 @@ mod tests {
signtool_args: Vec::new(),
},
inf2cat_args: Some(Vec::new()),
infverif_args: None,
target_platform: TargetPlatform::Universal,
};

Expand Down Expand Up @@ -1030,6 +1042,7 @@ mod tests {
"/os:10_x64,10_CO_X64".to_string(),
"/verbose".to_string(),
]),
infverif_args: None,
target_platform: TargetPlatform::Universal,
};

Expand Down Expand Up @@ -1088,6 +1101,7 @@ mod tests {
sample_class: false,
sign_mode: SignMode::Off,
inf2cat_args: None,
infverif_args: None,
target_platform: TargetPlatform::Universal,
};
PackageTask::new(params, wdk_build, command_exec, fs)
Expand Down Expand Up @@ -1285,6 +1299,7 @@ mod tests {
],
},
inf2cat_args: None,
infverif_args: None,
target_platform: TargetPlatform::Universal,
};
let task = PackageTask::new(params, &wdk_build, &command_exec, &fs);
Expand Down Expand Up @@ -1312,6 +1327,7 @@ mod tests {
sample_class: false,
sign_mode: SignMode::Off,
inf2cat_args: None,
infverif_args: None,
target_platform,
};

Expand Down Expand Up @@ -1374,6 +1390,63 @@ mod tests {
);
}

#[test]
fn run_infverif_with_custom_args_forwards_them_verbatim() {
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: true,
sign_mode: SignMode::Off,
inf2cat_args: None,
infverif_args: Some(vec![
"/rulever".to_string(),
"10.0.22621".to_string(),
"/info".to_string(),
]),
target_platform: TargetPlatform::Universal,
};

let fs = Fs::default();
let mut wdk_build = WdkBuild::default();
wdk_build
.expect_detect_wdk_build_number()
.once()
.returning(|| Ok(26101));

let expected_args_before_inf = ["/v", "/u", "/samples", "/rulever", "10.0.22621", "/info"];
let expected_inf_path = target_dir
.join("driver_package")
.join("driver.inf")
.to_string_lossy()
.to_string();
let mut command_exec = CommandExec::default();
command_exec
.expect_run()
.withf(move |cmd: &str, args: &[&str], _, _| {
cmd == "infverif"
&& args[..args.len() - 1] == expected_args_before_inf
&& args[args.len() - 1] == expected_inf_path
})
.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());
}

mod named_mutex {
use std::{
ffi::CString,
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 @@ -1754,6 +1754,7 @@ fn initialize_build_action<'a>(
target_arch,
sign_mode,
inf2cat_args: None,
infverif_args: None,
is_sample_class: sample_class,
locked: test_build_action.locked,
target_platform: TargetPlatform::Universal,
Expand Down
109 changes: 109 additions & 0 deletions crates/cargo-wdk/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,18 @@ pub struct BuildArgs {
)]
pub inf2cat_args: Option<PassthroughArgs>,

/// Custom arguments to pass to `infverif` when validating the INF,
/// e.g. `--infverif-args '/rulever 10.0.22621 /info'`.
#[arg(
long,
value_name = "ARGS",
// `infverif` args can be `-` prefixed.
allow_hyphen_values = true,
value_parser = parse_passthrough_args,
help_heading = "InfVerif Options"
Comment thread
gurry marked this conversation as resolved.
)]
pub infverif_args: Option<PassthroughArgs>,

/// Assert that `Cargo.lock` will remain unchanged
#[arg(long)]
pub locked: bool,
Expand Down Expand Up @@ -228,6 +240,37 @@ impl BuildArgs {
}
Ok(Some(args))
}

/// Resolves the arguments to forward to `infverif`. Rejects the arguments
/// cargo-wdk supplies itself: the mode flags derived from the
/// `--target-platform` option and the INF file path.
fn infverif_args(&self) -> Result<Option<Vec<String>>, clap::Error> {
const MODE_FLAGS: [&str; 3] = ["h", "w", "u"];

let Some(args) = self.infverif_args.clone().map(|parsed| parsed.0) else {
return Ok(None);
};
for arg in &args {
let mode_flag = arg.trim_start_matches(['/', '-']).to_ascii_lowercase();
let reason = if MODE_FLAGS.contains(&mode_flag.as_str()) {
format!(
"cargo-wdk derives the mode flag `{arg}` from the `--target-platform` option"
)
} else if Path::new(arg)
.extension()
.is_some_and(|extension| extension.eq_ignore_ascii_case("inf"))
{
"cargo-wdk supplies the INF file path itself".to_string()
} else {
continue;
};
return Err(Cli::command().error(
ErrorKind::ArgumentConflict,
format!("`--infverif-args` must not contain `{arg}`; {reason}"),
));
}
Ok(Some(args))
}
}

/// `value_parser` for passthrough tool arguments: tokenizes the raw string
Expand Down Expand Up @@ -355,13 +398,15 @@ impl Cli {
Subcmd::Build(cli_args) => {
let sign_mode = cli_args.sign_mode()?;
let inf2cat_args = cli_args.inf2cat_args()?;
let infverif_args = cli_args.infverif_args()?;
BuildAction::new(
&BuildActionParams {
working_dir: Path::new("."), // Using current dir as working dir
profile: cli_args.profile.as_ref(),
target_arch: cli_args.target_arch,
sign_mode,
inf2cat_args,
infverif_args,
is_sample_class: cli_args.sample,
locked: cli_args.locked,
target_platform: cli_args.target_platform.into(),
Expand Down Expand Up @@ -556,6 +601,70 @@ mod tests {
Some(vec!["/os:10_x64".to_string(), "/uselocaltime".to_string()])
);
}

fn assert_infverif_args_rejected(value: &str, expected_reason: &str) {
let args = parse_build_args(&["--infverif-args", value]).expect("args should parse");
let err = args
.infverif_args()
.expect_err("reserved argument should be rejected");
assert!(
err.to_string().contains(expected_reason),
"unexpected error for {value:?}: {err}"
);
}

#[test]
fn infverif_args_rejects_mode_flags() {
for (value, mode_flag) in [
("/h", "/h"),
("-w", "-w"),
Comment thread
gurry marked this conversation as resolved.
("/U", "/U"),
("/info -w", "-w"),
("-info /w", "/w"),
("/rulever 10.0.22621 -h /info /w pkg.inf", "-h"),
] {
assert_infverif_args_rejected(
value,
&format!(
"cargo-wdk derives the mode flag `{mode_flag}` from the \
`--target-platform` option"
),
);
}
}

#[test]
fn infverif_args_rejects_inf_paths() {
for value in [
"extra.inf",
"/info C:\\pkg\\other.INF",
"-info C:\\pkg\\other.INF",
] {
assert_infverif_args_rejected(value, "cargo-wdk supplies the INF file path itself");
}
}

#[test]
fn infverif_args_allows_other_args() {
for (value, expected) in [
(
"/rulever 10.0.22621 -info",
["/rulever", "10.0.22621", "-info"],
),
(
"-rulever 10.0.22621 /info",
["-rulever", "10.0.22621", "/info"],
),
] {
let args =
parse_build_args(&["--infverif-args", value]).expect("args should parse");
assert_eq!(
args.infverif_args().expect("should resolve"),
Some(expected.map(str::to_string).to_vec()),
"unexpected args for {value:?}"
);
}
}
}

mod parse_passthrough_args {
Expand Down
Loading
Loading