Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d3e2bdb
driver file versioning via .rc file initial commit
May 20, 2026
d25204c
redesign so PE resource versioning is automatic
May 21, 2026
9fbd5f6
update resolve_version functionality to treat empty string in the env…
May 22, 2026
c797b5c
formatting
May 22, 2026
bc1ccae
fixes method for finding header paths for rc.exe calls and adds robus…
May 27, 2026
7bb3252
change parse_version error information to include more info
Alan632 May 27, 2026
a8742eb
Merge branch 'main' into driver_file_versioning
Alan632 May 27, 2026
34613d4
remove resource_compile from wdk-build's public API
Alan632 May 27, 2026
5ae23ca
modifies RC Error variant CompilerFailed, add short word exception to…
May 27, 2026
6dc80b5
fix public api surface (ResourceCompileError should be public, all el…
May 27, 2026
4fdf830
further minimize API surface to only what's necessary, remove unecess…
May 28, 2026
6ed4a9d
add validation of resource metadata values along with unit tests
May 28, 2026
6790cde
add stripping build info from version and new unit tests, improve Res…
May 28, 2026
5e937a8
Merge branch 'main' into driver_file_versioning
Alan632 Jun 3, 2026
d5dfb2d
Merge branch 'main' into driver_file_versioning
Alan632 Jun 8, 2026
4d31935
Merge branch 'main' into driver_file_versioning
Alan632 Jun 9, 2026
cfe4d0b
add linker arg to prevent .rsrc from being discarded
Jun 11, 2026
797093c
Merge branch 'main' into driver_file_versioning
Alan632 Jun 15, 2026
f85e4b2
Merge branch 'main' into driver_file_versioning
Alan632 Jun 22, 2026
badcee0
- constrain code page to UTF-8 (inputs into rc.exe)
Jun 23, 2026
21202ee
fixing comment
Alan632 Jun 23, 2026
2833f39
- refactor to utilize deserialization to build VersionResourceOverrides
Jun 24, 2026
d3157e7
- update include syntax for common.ver in resource compilation
Jun 29, 2026
2523a29
Merge branch 'main' into driver_file_versioning
Alan632 Jun 30, 2026
9d1fc94
Merge branch 'main' into driver_file_versioning
Alan632 Jul 6, 2026
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
5 changes: 5 additions & 0 deletions .typos.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
[files]
extend-exclude = ["**/Cargo.lock", "**/target/**"]

# Allowlist short words that collide with the typos dictionary but are

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: scope this down as much as possible since this could be a common typo. Something like this could work:

[type.resource_compile]
extend-glob = ["resource_compile.rs"]
extend-words = {
	# rc.exe /fo (output file) switch
	fo = "fo"
}

# legitimate in WDK/rc.exe contexts.
[default.extend-words]
fo = "fo" # rc.exe /fo (output file) switch
Comment thread
Alan632 marked this conversation as resolved.

# Allow specific identifiers in code derived from WDK
[default.extend-identifiers]
STATUS_FVE_MOR_FAILED = "STATUS_FVE_MOR_FAILED"
Expand Down
8 changes: 8 additions & 0 deletions crates/wdk-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ use std::{

pub use bindgen::BuilderExt;
use metadata::TryFromCargoMetadataError;
pub use resource_compile::ResourceCompileError;
use tracing::debug;

pub mod cargo_make;
pub mod metadata;

mod resource_compile;
mod utils;

Comment thread
Alan632 marked this conversation as resolved.
mod bindgen;
Expand Down Expand Up @@ -313,6 +315,10 @@ rustflags = [\"-C\", \"target-feature=+crt-static\"]
/// [`metadata::Wdk`]
#[error(transparent)]
SerdeError(#[from] metadata::Error),

/// Error returned when version resource compilation fails
#[error(transparent)]
ResourceCompileError(#[from] resource_compile::ResourceCompileError),
Comment thread
Alan632 marked this conversation as resolved.
}

/// Subset of APIs in the Windows Driver Kit
Expand Down Expand Up @@ -1224,6 +1230,8 @@ impl Config {
println!("cargo::rustc-cdylib-link-arg=/MANIFEST:NO");
}

resource_compile::compile_version_resource(self)?;

self.emit_cfg_settings()
}

Expand Down
142 changes: 118 additions & 24 deletions crates/wdk-build/src/metadata/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,22 +120,19 @@ fn parse_packages_wdk_metadata(
) -> std::result::Result<HashSet<Wdk>, TryFromCargoMetadataError> {
let wdk_metadata_configurations = packages
.iter()
.filter_map(|package| match &package.metadata["wdk"] {
serde_json::Value::Null => None,
// When wdk section is empty, treat it as if it wasn't there. This is to allow for using
// empty wdk metadata sections to mark the package as a driver (ex. for detection in
// `package_driver_flow_condition_script`)
serde_json::Value::Object(map) if map.is_empty() => None,
wdk_metadata => Some(Wdk::deserialize(wdk_metadata).map_err(|err| {
TryFromCargoMetadataError::WdkMetadataDeserialization {
metadata_source: format!(
"{} for {} package",
stringify!(package.metadata["wdk"]),
package.name
),
error_source: err,
}
})),
.filter_map(|package| {
wdk_driver_model_metadata(&package.metadata["wdk"]).map(|wdk_metadata| {
Wdk::deserialize(wdk_metadata).map_err(|err| {
TryFromCargoMetadataError::WdkMetadataDeserialization {
metadata_source: format!(
"{} for {} package",
stringify!(package.metadata["wdk"]),
package.name
),
error_source: err,
}
})
})
})
.collect::<std::result::Result<HashSet<_>, _>>()?;
Ok(wdk_metadata_configurations)
Expand All @@ -144,15 +141,36 @@ fn parse_packages_wdk_metadata(
fn parse_workspace_wdk_metadata(
workspace_metadata: &serde_json::Value,
) -> std::result::Result<Option<Wdk>, TryFromCargoMetadataError> {
Ok(match &workspace_metadata["wdk"] {
Ok(
match wdk_driver_model_metadata(&workspace_metadata["wdk"]) {
None => None,
Some(wdk_metadata) => Some(Wdk::deserialize(wdk_metadata).map_err(|err| {
TryFromCargoMetadataError::WdkMetadataDeserialization {
metadata_source: stringify!(workspace_metadata["wdk"]).to_string(),
error_source: err,
}
})?),
},
)
}

fn wdk_driver_model_metadata(wdk_metadata: &serde_json::Value) -> Option<serde_json::Value> {
match wdk_metadata {
serde_json::Value::Null => None,
wdk_metadata => Some(Wdk::deserialize(wdk_metadata).map_err(|err| {
TryFromCargoMetadataError::WdkMetadataDeserialization {
metadata_source: stringify!(workspace_metadata["wdk"]).to_string(),
error_source: err,
}
})?),
})
// When wdk section is empty, treat it as if it wasn't there. This is to allow for using
// empty wdk metadata sections to mark the package as a driver (ex. for detection in
// `package_driver_flow_condition_script`)
serde_json::Value::Object(map) if map.is_empty() => None,
// Only `metadata.wdk.driver-model` is part of the WDK driver configuration.
// Other `metadata.wdk.*` sections are allowed to coexist and are parsed by
// their owning features.
serde_json::Value::Object(map) => map.get("driver-model").map(|driver_model| {
let mut driver_model_metadata = serde_json::Map::new();
driver_model_metadata.insert("driver-model".to_string(), driver_model.clone());
serde_json::Value::Object(driver_model_metadata)
}),
wdk_metadata => Some(wdk_metadata.clone()),
}
}

pub(crate) fn iter_manifest_paths(metadata: Metadata) -> impl IntoIterator<Item = Utf8PathBuf> {
Expand Down Expand Up @@ -198,6 +216,82 @@ mod tests {
});
}

#[test]
fn version_resource_metadata_is_not_part_of_wdk_configuration() {
let cwd = PathBuf::from(TEST_ROOT_DIR);
let package_metadata = TestWdkMetadata(
r#"
{
"wdk": {
"driver-model": {
"driver-type": "KMDF",
"kmdf-version-major": 1,
"target-kmdf-version-minor": 33
},
"version-resource": {
"company-name": "Microsoft Corporation",
"copyright": "Copyright",
"product-name": "Surface"
}
}
}
"#
.to_string(),
);
let (member_id, package) =
create_cargo_metadata_package(&cwd, "sample-kmdf", "0.0.1", Some(package_metadata));

set_up_and_assert(&cwd, &[package], &[member_id], None, |wdk| {
assert!(matches!(
wdk.unwrap().driver_model,
DriverConfig::Kmdf(KmdfConfig {
kmdf_version_major: 1,
target_kmdf_version_minor: 33,
minimum_kmdf_version_minor: None
})
));
});
}

#[test]
fn package_version_resource_metadata_can_use_workspace_wdk_configuration() {
let cwd = PathBuf::from(TEST_ROOT_DIR);
let package_metadata = TestWdkMetadata(
r#"
{
"wdk": {
"version-resource": {
"company-name": "Microsoft Corporation",
"copyright": "Copyright",
"product-name": "Surface"
}
}
}
"#
.to_string(),
);
let (member_id, package) =
create_cargo_metadata_package(&cwd, "sample-kmdf", "0.0.1", Some(package_metadata));
let workspace_metadata = create_cargo_metadata_wdk_metadata("KMDF", 1, 33);

set_up_and_assert(
&cwd,
&[package],
&[member_id],
Some(workspace_metadata),
|wdk| {
assert!(matches!(
wdk.unwrap().driver_model,
DriverConfig::Kmdf(KmdfConfig {
kmdf_version_major: 1,
target_kmdf_version_minor: 33,
minimum_kmdf_version_minor: None
})
));
},
);
}

#[test]
fn multiple_members_with_distinct_wdk_configurations() {
let (member_id1, package1, _cwd) = init_kmdf_package_metadata(1, 33);
Expand Down
Loading
Loading