direct_storage/
runtime_loaded.rs

1//! Functions in this module are loaded dynamically at runtime, instead of linked dynamically
2//! against `dstorage.lib` at compile-time.
3
4use std::{ffi::c_void, sync::OnceLock};
5
6use libloading::Library;
7use windows_core::{Interface, Result, Type, GUID, HRESULT};
8
9use crate::{DSTORAGE_COMPRESSION_FORMAT, DSTORAGE_CONFIGURATION};
10
11static DIRECT_STORAGE_LIB: OnceLock<Libraries> = OnceLock::new();
12
13struct Libraries {
14    ds: Library,
15    _core: Library,
16}
17
18/// Runtime-loaded variant of [`crate::DStorageCreateCompressionCodec()`] from `dstorage.dll`
19///
20/// # Safety
21/// Loads a raw pointer from `dstorage.dll` and casts it to a function to call.
22pub unsafe fn DStorageCreateCompressionCodec<T: Interface>(
23    format: DSTORAGE_COMPRESSION_FORMAT,
24    numThreads: u32,
25) -> Result<T> {
26    let f = DIRECT_STORAGE_LIB
27        .get_or_init(|| unsafe { load_libraries() })
28        .ds
29        .get::<unsafe extern "system" fn(
30            format: DSTORAGE_COMPRESSION_FORMAT,
31            numThreads: u32,
32            riid: *const GUID,
33            ppv: *mut *mut c_void,
34        ) -> HRESULT>(b"DStorageCreateCompressionCodec\0")
35        .expect("Can't load function`DStorageCreateCompressionCodec`");
36
37    let mut result__ = ::std::ptr::null_mut();
38    f(format, numThreads, &T::IID, &mut result__).and_then(|| Type::from_abi(result__))
39}
40
41/// Runtime-loaded variant of [`crate::DStorageSetConfiguration()`] from `dstorage.dll`
42///
43/// # Safety
44/// Loads a raw pointer from `dstorage.dll` and casts it to a function to call.
45pub unsafe fn DStorageSetConfiguration(configuration: &DSTORAGE_CONFIGURATION) -> Result<()> {
46    let f = DIRECT_STORAGE_LIB
47        .get_or_init(|| unsafe { load_libraries() })
48        .ds
49        .get::<unsafe extern "system" fn(configuration: *const DSTORAGE_CONFIGURATION) -> HRESULT>(
50            b"DStorageSetConfiguration\0",
51        )
52        .expect("Can't load function`DStorageSetConfiguration`");
53
54    f(configuration as *const DSTORAGE_CONFIGURATION).ok()
55}
56
57/// Runtime-loaded variant of [`crate::DStorageGetFactory()`] from `dstorage.dll`
58///
59/// # Safety
60/// Loads a raw pointer from `dstorage.dll` and casts it to a function to call.
61pub unsafe fn DStorageGetFactory<T: Interface>() -> Result<T> {
62    let f = DIRECT_STORAGE_LIB
63        .get_or_init(|| unsafe { load_libraries() })
64        .ds
65        .get::<unsafe extern "system" fn(riid: *const GUID, ppv: *mut *mut c_void) -> HRESULT>(
66            b"DStorageGetFactory\0",
67        )
68        .expect("Can't load function`DStorageGetFactory`");
69
70    let mut result__ = ::std::ptr::null_mut();
71    f(&T::IID, &mut result__).and_then(|| Type::from_abi(result__))
72}
73
74unsafe fn load_libraries() -> Libraries {
75    let ds = Library::new("dstorage.dll").expect("Can't load `dstorage.dll`");
76    let core = Library::new("dstoragecore.dll").expect("Can't load `dstoragecore.dll`");
77    Libraries { ds, _core: core }
78}