Skip to content

Commit

Permalink
addressed PR comments, removed function table static
Browse files Browse the repository at this point in the history
  • Loading branch information
Leon Durrenberger committed Dec 11, 2024
1 parent ea050a6 commit b49a18f
Show file tree
Hide file tree
Showing 27 changed files with 465 additions and 115 deletions.
16 changes: 15 additions & 1 deletion crates/wdk-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,23 @@ impl DerivedASTFragments {
// arguments for the WDF function is safe befause WDF maintains the strict mapping between the
// function table index and the correct function pointer type.
unsafe {
let wdf_function_table = wdk_sys::WdfFunctions;

// SAFETY: This is safe because:
// 1. `WdfFunctions` is valid for reads for `{NUM_WDF_FUNCTIONS_PLACEHOLDER}` * `core::mem::size_of::<WDFFUNC>()`
// bytes, and is guaranteed to be aligned and it must be properly aligned.
// 2. `WdfFunctions` points to `{NUM_WDF_FUNCTIONS_PLACEHOLDER}` consecutive properly initialized values of
// type `WDFFUNC`.
// 3. WDF does not mutate the memory referenced by the returned slice for for its entire `'static' lifetime.
// 4. The total size, `{NUM_WDF_FUNCTIONS_PLACEHOLDER}` * `core::mem::size_of::<WDFFUNC>()`, of the slice must be no
// larger than `isize::MAX`. This is proven by the below `const_assert!`.

debug_assert!(isize::try_from(wdk_sys::wdf::WDF_FUNCTION_COUNT * core::mem::size_of::<wdk_sys::WDFFUNC>()).is_ok());
let wdf_function_table = core::slice::from_raw_parts(wdf_function_table, wdk_sys::wdf::WDF_FUNCTION_COUNT);

core::mem::transmute(
// FIXME: investigate why _WDFFUNCENUM does not have a generated type alias without the underscore prefix
wdk_sys::WDF_FUNCTION_TABLE[wdk_sys::_WDFFUNCENUM::#function_table_index as usize],
wdf_function_table[wdk_sys::_WDFFUNCENUM::#function_table_index as usize],
)
}
);
Expand Down
103 changes: 16 additions & 87 deletions crates/wdk-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,77 +31,20 @@ use wdk_build::{
UmdfConfig,
};

const NUM_WDF_FUNCTIONS_PLACEHOLDER: &str =
"<PLACEHOLDER FOR IDENTIFIER FOR VARIABLE CORRESPONDING TO NUMBER OF WDF FUNCTIONS>";
const WDF_FUNCTION_COUNT_DECLARATION_PLACEHOLDER: &str =
"<PLACEHOLDER FOR DECLARATION OF wdf_function_count VARIABLE>";
const OUT_DIR_PLACEHOLDER: &str =
"<PLACEHOLDER FOR LITERAL VALUE CONTAINING OUT_DIR OF wdk-sys CRATE>";
const WDFFUNCTIONS_SYMBOL_NAME_PLACEHOLDER: &str =
"<PLACEHOLDER FOR LITERAL VALUE CONTAINING WDFFUNCTIONS SYMBOL NAME>";

const WDF_FUNCTION_COUNT_DECLARATION_EXTERNAL_SYMBOL: &str = "
// SAFETY: `crate::WdfFunctionCount` is generated as a mutable static, but is not supposed \
to be ever mutated by WDF.
let wdf_function_count = unsafe { crate::WdfFunctionCount } as usize;";
const WDF_FUNCTION_COUNT_DECLARATION_TABLE_INDEX: &str = "
let wdf_function_count = crate::_WDFFUNCENUM::WdfFunctionTableNumEntries as usize;";

static WDF_FUNCTION_TABLE_TEMPLATE: LazyLock<String> = LazyLock::new(|| {
format!(
r"
extern crate alloc;
/// Struct to encapsulate a function table.
/// Lazily initializes on access via index operation.
pub struct FunctionTable {{
inner: once_cell::race::OnceBox<alloc::boxed::Box<[crate::WDFFUNC]>>
}}
impl core::ops::Index<usize> for FunctionTable {{
type Output = crate::WDFFUNC;
fn index(&self, index: usize) -> &Self::Output {{
&(**(self.get_function_table()))[index]
}}
}}
impl FunctionTable {{
/// Initializes new FunctionTable.
/// Will not contain data until accessed via index operator.
pub const fn new() -> FunctionTable {{
FunctionTable {{
inner: once_cell::race::OnceBox::new()
}}
}}
fn get_function_table(&self) -> &alloc::boxed::Box<[crate::WDFFUNC]> {{
self.inner.get_or_init(|| {{
// SAFETY: `WdfFunctions` is generated as a mutable static, but is not supposed to be ever mutated by WDF.
let wdf_function_table = unsafe {{ crate::WdfFunctions }};
{WDF_FUNCTION_COUNT_DECLARATION_PLACEHOLDER}
// SAFETY: This is safe because:
// 1. `WdfFunctions` is valid for reads for `{NUM_WDF_FUNCTIONS_PLACEHOLDER}` * `core::mem::size_of::<WDFFUNC>()`
// bytes, and is guaranteed to be aligned and it must be properly aligned.
// 2. `WdfFunctions` points to `{NUM_WDF_FUNCTIONS_PLACEHOLDER}` consecutive properly initialized values of
// type `WDFFUNC`.
// 3. WDF does not mutate the memory referenced by the returned slice for for its entire `'static' lifetime.
// 4. The total size, `{NUM_WDF_FUNCTIONS_PLACEHOLDER}` * `core::mem::size_of::<WDFFUNC>()`, of the slice must be no
// larger than `isize::MAX`. This is proven by the below `debug_assert!`.
unsafe {{
debug_assert!(isize::try_from(wdf_function_count * core::mem::size_of::<crate::WDFFUNC>()).is_ok());
alloc::boxed::Box::new(core::slice::from_raw_parts(wdf_function_table, wdf_function_count).into())
}}
}})
}}
}}
// SAFETY: `crate::WdfFunctionCount` is generated as a mutable static, but is not supposed \
to be ever mutated by WDF.
/// Number of functions in the WDF function table
pub static WDF_FUNCTION_COUNT: usize = unsafe { crate::WdfFunctionCount } as usize;";

/// Static instance of the function table to be used throughout generated code.
pub static WDF_FUNCTION_TABLE: FunctionTable = FunctionTable::new();
"
)
});
const WDF_FUNCTION_COUNT_DECLARATION_TABLE_INDEX: &str = "
/// Number of functions in the WDF function table
pub static WDF_FUNCTION_COUNT: usize = crate::_WDFFUNCENUM::WdfFunctionTableNumEntries as usize;";

static CALL_UNSAFE_WDF_BINDING_TEMPLATE: LazyLock<String> = LazyLock::new(|| {
format!(
Expand Down Expand Up @@ -290,15 +233,14 @@ fn generate_wdf(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
}
}

/// Generates a `wdf_function_table.rs` file in `OUT_DIR` which contains the
/// definition of `WDF_FUNCTION_TABLE`. This is required to be generated here
/// Generates a `wdf_function_count.rs` file in `OUT_DIR` which contains the
/// definition of `WDF_FUNCTION_COUNT`. This is required to be generated here
/// since the size of the table is derived from either a global symbol
/// (`WDF_FUNCTION_COUNT`) that newer WDF versions expose, or an enum that older
/// versions use.
/// that newer WDF versions expose, or an enum that older versions use.
fn generate_wdf_function_table(out_path: &Path, config: &Config) -> std::io::Result<()> {
const MINIMUM_MINOR_VERSION_TO_GENERATE_WDF_FUNCTION_COUNT: u8 = 25;

let generated_file_path = out_path.join("wdf_function_table.rs");
let generated_file_path = out_path.join("wdf_function_count.rs");
let mut generated_file = std::fs::File::create(generated_file_path)?;

let is_wdf_function_count_generated = match *config {
Expand Down Expand Up @@ -335,26 +277,13 @@ fn generate_wdf_function_table(out_path: &Path, config: &Config) -> std::io::Res
}
};

let wdf_function_table_code_snippet = if is_wdf_function_count_generated {
WDF_FUNCTION_TABLE_TEMPLATE
.replace(NUM_WDF_FUNCTIONS_PLACEHOLDER, "crate::WdfFunctionCount")
.replace(
WDF_FUNCTION_COUNT_DECLARATION_PLACEHOLDER,
WDF_FUNCTION_COUNT_DECLARATION_EXTERNAL_SYMBOL,
)
let wdf_function_table_count_snippet = if is_wdf_function_count_generated {
WDF_FUNCTION_COUNT_DECLARATION_EXTERNAL_SYMBOL
} else {
WDF_FUNCTION_TABLE_TEMPLATE
.replace(
NUM_WDF_FUNCTIONS_PLACEHOLDER,
"crate::_WDFFUNCENUM::WdfFunctionTableNumEntries",
)
.replace(
WDF_FUNCTION_COUNT_DECLARATION_PLACEHOLDER,
WDF_FUNCTION_COUNT_DECLARATION_TABLE_INDEX,
)
WDF_FUNCTION_COUNT_DECLARATION_TABLE_INDEX
};

generated_file.write_all(wdf_function_table_code_snippet.as_bytes())?;
generated_file.write_all(wdf_function_table_count_snippet.as_bytes())?;
Ok(())
}

Expand Down Expand Up @@ -458,7 +387,7 @@ fn main() -> anyhow::Result<()> {
.expect("Scoped Thread should spawn successfully"),
);

info_span!("wdf_function_table.rs generation").in_scope(|| {
info_span!("wdf_function_count.rs generation").in_scope(|| {
generate_wdf_function_table(&out_path, &config)?;
Ok::<(), std::io::Error>(())
})?;
Expand Down
3 changes: 1 addition & 2 deletions crates/wdk-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
#![no_std]

#[cfg(any(driver_model__driver_type = "KMDF", driver_model__driver_type = "UMDF"))]
pub use wdf::WDF_FUNCTION_TABLE;

#[cfg(any(
driver_model__driver_type = "WDM",
driver_model__driver_type = "KMDF",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,25 @@ fn foo(
pnp_power_event_callbacks__: PWDF_PNPPOWER_EVENT_CALLBACKS,
) {
let wdf_function: wdk_sys::PFN_WDFDEVICEINITSETPNPPOWEREVENTCALLBACKS = Some(unsafe {
let wdf_function_table = wdk_sys::WdfFunctions;
if true {
if !isize::try_from(
wdk_sys::wdf::WDF_FUNCTION_COUNT
* core::mem::size_of::<wdk_sys::WDFFUNC>(),
)
.is_ok()
{
::core::panicking::panic(
"assertion failed: isize::try_from(wdk_sys::wdf::WDF_FUNCTION_COUNT *\n core::mem::size_of::<wdk_sys::WDFFUNC>()).is_ok()",
)
}
}
let wdf_function_table = core::slice::from_raw_parts(
wdf_function_table,
wdk_sys::wdf::WDF_FUNCTION_COUNT,
);
core::mem::transmute(
wdk_sys::WDF_FUNCTION_TABLE[wdk_sys::_WDFFUNCENUM::WdfDeviceInitSetPnpPowerEventCallbacksTableIndex
wdf_function_table[wdk_sys::_WDFFUNCENUM::WdfDeviceInitSetPnpPowerEventCallbacksTableIndex
as usize],
)
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,25 @@ pub extern "system" fn driver_entry(
driver__: *mut WDFDRIVER,
) -> NTSTATUS {
let wdf_function: wdk_sys::PFN_WDFDRIVERCREATE = Some(unsafe {
let wdf_function_table = wdk_sys::WdfFunctions;
if true {
if !isize::try_from(
wdk_sys::wdf::WDF_FUNCTION_COUNT
* core::mem::size_of::<wdk_sys::WDFFUNC>(),
)
.is_ok()
{
::core::panicking::panic(
"assertion failed: isize::try_from(wdk_sys::wdf::WDF_FUNCTION_COUNT *\n core::mem::size_of::<wdk_sys::WDFFUNC>()).is_ok()",
)
}
}
let wdf_function_table = core::slice::from_raw_parts(
wdf_function_table,
wdk_sys::wdf::WDF_FUNCTION_COUNT,
);
core::mem::transmute(
wdk_sys::WDF_FUNCTION_TABLE[wdk_sys::_WDFFUNCENUM::WdfDriverCreateTableIndex
wdf_function_table[wdk_sys::_WDFFUNCENUM::WdfDriverCreateTableIndex
as usize],
)
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,25 @@ extern "C" fn evt_driver_device_add(
device__: *mut WDFDEVICE,
) -> NTSTATUS {
let wdf_function: wdk_sys::PFN_WDFDEVICECREATE = Some(unsafe {
let wdf_function_table = wdk_sys::WdfFunctions;
if true {
if !isize::try_from(
wdk_sys::wdf::WDF_FUNCTION_COUNT
* core::mem::size_of::<wdk_sys::WDFFUNC>(),
)
.is_ok()
{
::core::panicking::panic(
"assertion failed: isize::try_from(wdk_sys::wdf::WDF_FUNCTION_COUNT *\n core::mem::size_of::<wdk_sys::WDFFUNC>()).is_ok()",
)
}
}
let wdf_function_table = core::slice::from_raw_parts(
wdf_function_table,
wdk_sys::wdf::WDF_FUNCTION_COUNT,
);
core::mem::transmute(
wdk_sys::WDF_FUNCTION_TABLE[wdk_sys::_WDFFUNCENUM::WdfDeviceCreateTableIndex
wdf_function_table[wdk_sys::_WDFFUNCENUM::WdfDeviceCreateTableIndex
as usize],
)
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,25 @@ fn create_device_interface(wdf_device: wdk_sys::WDFDEVICE) -> wdk_sys::NTSTATUS
reference_string__: PCUNICODE_STRING,
) -> NTSTATUS {
let wdf_function: wdk_sys::PFN_WDFDEVICECREATEDEVICEINTERFACE = Some(unsafe {
let wdf_function_table = wdk_sys::WdfFunctions;
if true {
if !isize::try_from(
wdk_sys::wdf::WDF_FUNCTION_COUNT
* core::mem::size_of::<wdk_sys::WDFFUNC>(),
)
.is_ok()
{
::core::panicking::panic(
"assertion failed: isize::try_from(wdk_sys::wdf::WDF_FUNCTION_COUNT *\n core::mem::size_of::<wdk_sys::WDFFUNC>()).is_ok()",
)
}
}
let wdf_function_table = core::slice::from_raw_parts(
wdf_function_table,
wdk_sys::wdf::WDF_FUNCTION_COUNT,
);
core::mem::transmute(
wdk_sys::WDF_FUNCTION_TABLE[wdk_sys::_WDFFUNCENUM::WdfDeviceCreateDeviceInterfaceTableIndex
wdf_function_table[wdk_sys::_WDFFUNCENUM::WdfDeviceCreateDeviceInterfaceTableIndex
as usize],
)
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,25 @@ pub extern "system" fn driver_entry(
driver__: *mut WDFDRIVER,
) -> NTSTATUS {
let wdf_function: wdk_sys::PFN_WDFDRIVERCREATE = Some(unsafe {
let wdf_function_table = wdk_sys::WdfFunctions;
if true {
if !isize::try_from(
wdk_sys::wdf::WDF_FUNCTION_COUNT
* core::mem::size_of::<wdk_sys::WDFFUNC>(),
)
.is_ok()
{
::core::panicking::panic(
"assertion failed: isize::try_from(wdk_sys::wdf::WDF_FUNCTION_COUNT *\n core::mem::size_of::<wdk_sys::WDFFUNC>()).is_ok()",
)
}
}
let wdf_function_table = core::slice::from_raw_parts(
wdf_function_table,
wdk_sys::wdf::WDF_FUNCTION_COUNT,
);
core::mem::transmute(
wdk_sys::WDF_FUNCTION_TABLE[wdk_sys::_WDFFUNCENUM::WdfDriverCreateTableIndex
wdf_function_table[wdk_sys::_WDFFUNCENUM::WdfDriverCreateTableIndex
as usize],
)
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,25 @@ fn process_wdf_request(request: wdk_sys::WDFREQUEST) {
length__: *mut usize,
) -> NTSTATUS {
let wdf_function: wdk_sys::PFN_WDFREQUESTRETRIEVEOUTPUTBUFFER = Some(unsafe {
let wdf_function_table = wdk_sys::WdfFunctions;
if true {
if !isize::try_from(
wdk_sys::wdf::WDF_FUNCTION_COUNT
* core::mem::size_of::<wdk_sys::WDFFUNC>(),
)
.is_ok()
{
::core::panicking::panic(
"assertion failed: isize::try_from(wdk_sys::wdf::WDF_FUNCTION_COUNT *\n core::mem::size_of::<wdk_sys::WDFFUNC>()).is_ok()",
)
}
}
let wdf_function_table = core::slice::from_raw_parts(
wdf_function_table,
wdk_sys::wdf::WDF_FUNCTION_COUNT,
);
core::mem::transmute(
wdk_sys::WDF_FUNCTION_TABLE[wdk_sys::_WDFFUNCENUM::WdfRequestRetrieveOutputBufferTableIndex
wdf_function_table[wdk_sys::_WDFFUNCENUM::WdfRequestRetrieveOutputBufferTableIndex
as usize],
)
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,25 @@ fn acquire_lock(wdf_spin_lock: wdk_sys::WDFSPINLOCK) {
#[inline(always)]
pub unsafe fn wdf_spin_lock_acquire_impl(spin_lock__: WDFSPINLOCK) {
let wdf_function: wdk_sys::PFN_WDFSPINLOCKACQUIRE = Some(unsafe {
let wdf_function_table = wdk_sys::WdfFunctions;
if true {
if !isize::try_from(
wdk_sys::wdf::WDF_FUNCTION_COUNT
* core::mem::size_of::<wdk_sys::WDFFUNC>(),
)
.is_ok()
{
::core::panicking::panic(
"assertion failed: isize::try_from(wdk_sys::wdf::WDF_FUNCTION_COUNT *\n core::mem::size_of::<wdk_sys::WDFFUNC>()).is_ok()",
)
}
}
let wdf_function_table = core::slice::from_raw_parts(
wdf_function_table,
wdk_sys::wdf::WDF_FUNCTION_COUNT,
);
core::mem::transmute(
wdk_sys::WDF_FUNCTION_TABLE[wdk_sys::_WDFFUNCENUM::WdfSpinLockAcquireTableIndex
wdf_function_table[wdk_sys::_WDFFUNCENUM::WdfSpinLockAcquireTableIndex
as usize],
)
});
Expand Down
Loading

0 comments on commit b49a18f

Please sign in to comment.