Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: prevent unused import warning in arguments to call_unsafe_wdf_function_binding #207

Merged
merged 2 commits into from
Sep 6, 2024
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
33 changes: 20 additions & 13 deletions crates/wdk-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub fn call_unsafe_wdf_function_binding(input_tokens: TokenStream) -> TokenStrea
call_unsafe_wdf_function_binding_impl(TokenStream2::from(input_tokens)).into()
}

/// A trait to provide additional functionality to the `String` type
/// A trait to provide additional functionality to the [`String`] type
trait StringExt {
/// Convert a string to `snake_case`
fn to_snake_case(&self) -> String;
Expand All @@ -72,9 +72,9 @@ struct Inputs {
wdf_function_arguments: Punctuated<Expr, Token![,]>,
}

/// Struct storing all the AST fragments derived from `Inputs`. This represents
/// all the derived ASTs depend on `Inputs` that ultimately get used in the
/// final generated code that.
/// Struct storing all the AST fragments derived from [`Inputs`]. This
/// represents all the ASTs derived from [`Inputs`]. These ultimately get used
/// in the final generated code.
#[derive(Debug, PartialEq)]
struct DerivedASTFragments {
function_pointer_type: Ident,
Expand All @@ -87,7 +87,7 @@ struct DerivedASTFragments {
}

/// Struct storing the AST fragments that form distinct sections of the final
/// generated code. These sections are derived from `DerivedASTFragments`.
/// generated code. Each field is derived from [`DerivedASTFragments`].
struct IntermediateOutputASTFragments {
must_use_attribute: Option<Attribute>,
inline_wdf_fn_signature: Signature,
Expand Down Expand Up @@ -281,16 +281,23 @@ impl IntermediateOutputASTFragments {

quote! {
{
use wdk_sys::*;

#conditional_must_use_attribute
#[inline(always)]
#[allow(non_snake_case)]
#inline_wdf_fn_signature {
#(#inline_wdf_fn_body_statments)*
// Use a private module to prevent leaking of glob import into inline_wdf_fn_invocation's parameters
mod private__ {
// Glob import types from wdk_sys. glob importing is done instead of blindly prepending the
// paramters types with wdk_sys:: because bindgen generates some paramters as native rust types
use wdk_sys::*;

// If the function returns a value, add a `#[must_use]` attribute to the function
#conditional_must_use_attribute
// Encapsulate the code in an inline functions to allow for condition must_use attribute.
// core::hint::must_use is not stable yet: https://github.com/rust-lang/rust/issues/94745
#[inline(always)]
pub #inline_wdf_fn_signature {
#(#inline_wdf_fn_body_statments)*
}
}

#inline_wdf_fn_invocation
private__::#inline_wdf_fn_invocation
}
}
}
Expand Down
1 change: 1 addition & 0 deletions examples/sample-kmdf-driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use wdk_sys::{
DRIVER_OBJECT,
NTSTATUS,
PCUNICODE_STRING,
PDRIVER_OBJECT,
ULONG,
UNICODE_STRING,
WCHAR,
Expand Down
1 change: 1 addition & 0 deletions tests/wdk-macros-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ macro_rules! generate_call_unsafe_wdf_binding_tests {
() => {
$crate::generate_macrotest_tests!(
bug_tuple_struct_shadowing,
bug_unused_imports,
wdf_driver_create,
wdf_device_create,
wdf_device_create_device_interface,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (c) Microsoft Corporation
// License: MIT OR Apache-2.0

#![no_main]
#![deny(warnings)]

//! This is a regression test for a bug where the arguments to the
//! [`call_unsafe_wdf_function_binding`] macro would need to be brought into
//! scope, but rust-analyzer would treat them as unused imports. This resulted
//! in the following compilation error:
#[rustfmt::skip]
/// ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
/// error: unused import: `WDF_NO_OBJECT_ATTRIBUTES`
/// --> C:/windows-drivers-rs/tests/wdk-macros-tests/tests/outputs/nightly/macrotest/bug_unused_imports.rs:31:49
/// |
/// 31 | use wdk_sys::{call_unsafe_wdf_function_binding, WDF_NO_OBJECT_ATTRIBUTES, NTSTATUS, PDRIVER_OBJECT, ULONG, PCUNICODE_STRING, WDF_DRIVER_C...
/// | ^^^^^^^^^^^^^^^^^^^^^^^^
/// |
/// note: the lint level is defined here
/// --> C:/windows-drivers-rs/tests/wdk-macros-tests/tests/wdk-macros-tests/tests/outputs/nightly/macrotest/bug_unused_imports.rs:5:9
/// |
/// 5 | #![deny(warnings)]
/// | ^^^^^^^^
/// = note: `#[deny(unused_imports)]` implied by `#[deny(warnings)]`
/// ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈

use wdk_sys::{
call_unsafe_wdf_function_binding,
NTSTATUS,
PCUNICODE_STRING,
PDRIVER_OBJECT,
ULONG,
WDFDRIVER,
WDF_DRIVER_CONFIG,
WDF_NO_HANDLE,
WDF_NO_OBJECT_ATTRIBUTES,
};

#[export_name = "DriverEntry"] // WDF expects a symbol with the name DriverEntry
pub extern "system" fn driver_entry(
driver: PDRIVER_OBJECT,
registry_path: PCUNICODE_STRING,
) -> NTSTATUS {
let mut driver_config = WDF_DRIVER_CONFIG {
Size: core::mem::size_of::<WDF_DRIVER_CONFIG>() as ULONG,
..Default::default()
};
let driver_handle_output = WDF_NO_HANDLE as *mut WDFDRIVER;

unsafe {
call_unsafe_wdf_function_binding!(
WdfDriverCreate,
driver,
registry_path,
WDF_NO_OBJECT_ATTRIBUTES,
&mut driver_config,
driver_handle_output,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,39 +31,40 @@ fn foo(
) {
unsafe {
{
use wdk_sys::*;
#[inline(always)]
#[allow(non_snake_case)]
unsafe fn wdf_device_init_set_pnp_power_event_callbacks_impl(
device_init__: PWDFDEVICE_INIT,
pnp_power_event_callbacks__: PWDF_PNPPOWER_EVENT_CALLBACKS,
) {
let wdf_function: wdk_sys::PFN_WDFDEVICEINITSETPNPPOWEREVENTCALLBACKS = Some(unsafe {
core::mem::transmute(
wdk_sys::WDF_FUNCTION_TABLE[wdk_sys::_WDFFUNCENUM::WdfDeviceInitSetPnpPowerEventCallbacksTableIndex
as usize],
)
});
if let Some(wdf_function) = wdf_function {
unsafe {
(wdf_function)(
wdk_sys::WdfDriverGlobals,
device_init__,
pnp_power_event_callbacks__,
mod private__ {
use wdk_sys::*;
#[inline(always)]
pub unsafe fn wdf_device_init_set_pnp_power_event_callbacks_impl(
device_init__: PWDFDEVICE_INIT,
pnp_power_event_callbacks__: PWDF_PNPPOWER_EVENT_CALLBACKS,
) {
let wdf_function: wdk_sys::PFN_WDFDEVICEINITSETPNPPOWEREVENTCALLBACKS = Some(unsafe {
core::mem::transmute(
wdk_sys::WDF_FUNCTION_TABLE[wdk_sys::_WDFFUNCENUM::WdfDeviceInitSetPnpPowerEventCallbacksTableIndex
as usize],
)
});
if let Some(wdf_function) = wdf_function {
unsafe {
(wdf_function)(
wdk_sys::WdfDriverGlobals,
device_init__,
pnp_power_event_callbacks__,
)
}
} else {
{
::core::panicking::panic_fmt(
format_args!(
"internal error: entered unreachable code: {0}",
format_args!("Option should never be None"),
),
);
};
}
} else {
{
::core::panicking::panic_fmt(
format_args!(
"internal error: entered unreachable code: {0}",
format_args!("Option should never be None"),
),
);
};
}
}
wdf_device_init_set_pnp_power_event_callbacks_impl(
private__::wdf_device_init_set_pnp_power_event_callbacks_impl(
device_init.0,
pnp_power_callbacks,
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#![no_main]
#![deny(warnings)]
//! This is a regression test for a bug where the arguments to the
//! [`call_unsafe_wdf_function_binding`] macro would need to be brought into
//! scope, but rust-analyzer would treat them as unused imports. This resulted
//! in the following compilation error:
#[rustfmt::skip]
/// ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
/// error: unused import: `WDF_NO_OBJECT_ATTRIBUTES`
/// --> C:/windows-drivers-rs/tests/wdk-macros-tests/tests/outputs/nightly/macrotest/bug_unused_imports.rs:31:49
/// |
/// 31 | use wdk_sys::{call_unsafe_wdf_function_binding, WDF_NO_OBJECT_ATTRIBUTES, NTSTATUS, PDRIVER_OBJECT, ULONG, PCUNICODE_STRING, WDF_DRIVER_C...
/// | ^^^^^^^^^^^^^^^^^^^^^^^^
/// |
/// note: the lint level is defined here
/// --> C:/windows-drivers-rs/tests/wdk-macros-tests/tests/wdk-macros-tests/tests/outputs/nightly/macrotest/bug_unused_imports.rs:5:9
/// |
/// 5 | #![deny(warnings)]
/// | ^^^^^^^^
/// = note: `#[deny(unused_imports)]` implied by `#[deny(warnings)]`
/// ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
use wdk_sys::{
call_unsafe_wdf_function_binding, NTSTATUS, PCUNICODE_STRING, PDRIVER_OBJECT, ULONG,
WDFDRIVER, WDF_DRIVER_CONFIG, WDF_NO_HANDLE, WDF_NO_OBJECT_ATTRIBUTES,
};
#[export_name = "DriverEntry"]
pub extern "system" fn driver_entry(
driver: PDRIVER_OBJECT,
registry_path: PCUNICODE_STRING,
) -> NTSTATUS {
let mut driver_config = WDF_DRIVER_CONFIG {
Size: core::mem::size_of::<WDF_DRIVER_CONFIG>() as ULONG,
..Default::default()
};
let driver_handle_output = WDF_NO_HANDLE as *mut WDFDRIVER;
unsafe {
{
mod private__ {
use wdk_sys::*;
#[must_use]
#[inline(always)]
pub unsafe fn wdf_driver_create_impl(
driver_object__: PDRIVER_OBJECT,
registry_path__: PCUNICODE_STRING,
driver_attributes__: PWDF_OBJECT_ATTRIBUTES,
driver_config__: PWDF_DRIVER_CONFIG,
driver__: *mut WDFDRIVER,
) -> NTSTATUS {
let wdf_function: wdk_sys::PFN_WDFDRIVERCREATE = Some(unsafe {
core::mem::transmute(
wdk_sys::WDF_FUNCTION_TABLE[wdk_sys::_WDFFUNCENUM::WdfDriverCreateTableIndex
as usize],
)
});
if let Some(wdf_function) = wdf_function {
unsafe {
(wdf_function)(
wdk_sys::WdfDriverGlobals,
driver_object__,
registry_path__,
driver_attributes__,
driver_config__,
driver__,
)
}
} else {
{
::core::panicking::panic_fmt(
format_args!(
"internal error: entered unreachable code: {0}",
format_args!("Option should never be None"),
),
);
};
}
}
}
private__::wdf_driver_create_impl(
driver,
registry_path,
WDF_NO_OBJECT_ATTRIBUTES,
&mut driver_config,
driver_handle_output,
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,43 @@ extern "C" fn evt_driver_device_add(
let mut device_handle_output: wdk_sys::WDFDEVICE = wdk_sys::WDF_NO_HANDLE.cast();
unsafe {
{
use wdk_sys::*;
#[must_use]
#[inline(always)]
#[allow(non_snake_case)]
unsafe fn wdf_device_create_impl(
device_init__: *mut PWDFDEVICE_INIT,
device_attributes__: PWDF_OBJECT_ATTRIBUTES,
device__: *mut WDFDEVICE,
) -> NTSTATUS {
let wdf_function: wdk_sys::PFN_WDFDEVICECREATE = Some(unsafe {
core::mem::transmute(
wdk_sys::WDF_FUNCTION_TABLE[wdk_sys::_WDFFUNCENUM::WdfDeviceCreateTableIndex
as usize],
)
});
if let Some(wdf_function) = wdf_function {
unsafe {
(wdf_function)(
wdk_sys::WdfDriverGlobals,
device_init__,
device_attributes__,
device__,
mod private__ {
use wdk_sys::*;
#[must_use]
#[inline(always)]
pub unsafe fn wdf_device_create_impl(
device_init__: *mut PWDFDEVICE_INIT,
device_attributes__: PWDF_OBJECT_ATTRIBUTES,
device__: *mut WDFDEVICE,
) -> NTSTATUS {
let wdf_function: wdk_sys::PFN_WDFDEVICECREATE = Some(unsafe {
core::mem::transmute(
wdk_sys::WDF_FUNCTION_TABLE[wdk_sys::_WDFFUNCENUM::WdfDeviceCreateTableIndex
as usize],
)
});
if let Some(wdf_function) = wdf_function {
unsafe {
(wdf_function)(
wdk_sys::WdfDriverGlobals,
device_init__,
device_attributes__,
device__,
)
}
} else {
{
::core::panicking::panic_fmt(
format_args!(
"internal error: entered unreachable code: {0}",
format_args!("Option should never be None"),
),
);
};
}
} else {
{
::core::panicking::panic_fmt(
format_args!(
"internal error: entered unreachable code: {0}",
format_args!("Option should never be None"),
),
);
};
}
}
wdf_device_create_impl(
private__::wdf_device_create_impl(
&mut device_init,
wdk_sys::WDF_NO_OBJECT_ATTRIBUTES,
&mut device_handle_output,
Expand Down
Loading
Loading