diff --git a/crates/wdk-build/rust-driver-makefile.toml b/crates/wdk-build/rust-driver-makefile.toml index 903af8109..e681d4412 100644 --- a/crates/wdk-build/rust-driver-makefile.toml +++ b/crates/wdk-build/rust-driver-makefile.toml @@ -406,17 +406,23 @@ args = [ [tasks.generate-certificate] private = true +condition_script_runner_args = [ + "--base-path", + "${CARGO_MAKE_CURRENT_TASK_INITIAL_MAKEFILE_DIRECTORY}", +] condition_script = ''' -#!@duckscript +#!@rust -out = exec certmgr.exe -put -s WDRTestCertStore -c -n WDRLocalTestCert ${WDK_BUILD_OUTPUT_DIRECTORY}/WDRLocalTestCert.cer -if eq ${out.code} 0 - echo WDRLocalTestCert found in WDRTestCertStore. Skipping certificate generation. - exit 1 -else - echo WDRLocalTestCert not found in WDRTestCertStore. Generating new certificate. - exit 0 -end +//! ```cargo +//! [dependencies] +//! wdk-build = { path = ".", version = "0.3.0" } +//! anyhow = "1" +//! ``` +#![allow(unused_doc_comments)] + +fn main() -> anyhow::Result<()> { + wdk_build::cargo_make::generate_certificate_condition_script() +} ''' command = "makecert" args = [ diff --git a/crates/wdk-build/src/cargo_make.rs b/crates/wdk-build/src/cargo_make.rs index a900bf354..7b967a5c6 100644 --- a/crates/wdk-build/src/cargo_make.rs +++ b/crates/wdk-build/src/cargo_make.rs @@ -16,6 +16,7 @@ use std::{ env, panic::UnwindSafe, path::{Path, PathBuf}, + process::Command, }; use anyhow::Context; @@ -1007,6 +1008,67 @@ pub fn package_driver_flow_condition_script() -> anyhow::Result<()> { }) } +/// `cargo-make` condition script for `generate-certificate` task in +/// [`rust-driver-makefile.toml`](../rust-driver-makefile.toml) +/// +/// # Errors +/// +/// This functions returns an error whenever it determines that the +/// `generate-certificate` `cargo-make` task should be skipped. This only +/// occurs when `WdrLocalTestCert` already exists in `WDRTestCertStore`. +/// +/// # Panics +/// +/// Panics if `CARGO_MAKE_CURRENT_TASK_NAME` is not set in the environment. +pub fn generate_certificate_condition_script() -> anyhow::Result<()> { + condition_script(|| { + let mut command = Command::new("certmgr"); + + command.args([ + "-put".as_ref(), + "-s".as_ref(), + "WDRTestCertStore".as_ref(), + "-c".as_ref(), + "-n".as_ref(), + "WdrLocalTestCert".as_ref(), + get_wdk_build_output_directory() + .join("WDRLocalTestCert.cer") + .as_os_str(), + ]); + + let output = command.output().unwrap_or_else(|err| { + panic!( + "Failed to run certmgr.exe {} due to error: {}", + command + .get_args() + .map(|arg| arg.to_string_lossy()) + .collect::>() + .join(" "), + err + ) + }); + + match output.status.code() { + Some(0) => Err(anyhow::anyhow!( + "WDRLocalTestCert found in WDRTestCertStore. Skipping certificate generation." + )), + Some(1) => { + eprintln!( + "WDRLocalTestCert not found in WDRTestCertStore. Generating new certificate." + ); + Ok(()) + } + Some(_) => { + eprintln!("Unknown status code found from certmgr. Generating new certificate."); + Ok(()) + } + None => { + unreachable!("Unreachable, no status code found from certmgr."); + } + } + }) +} + fn configure_wdf_build_output_dir(target_arg: Option<&String>, cargo_make_cargo_profile: &str) { let cargo_make_crate_custom_triple_target_directory = env::var(CARGO_MAKE_CRATE_CUSTOM_TRIPLE_TARGET_DIRECTORY_ENV_VAR).unwrap_or_else(|_| {