Skip to main content

windows_dll/platform/
winapi_crate.rs

1use core::{
2    mem::transmute,
3    ptr,
4    sync::atomic::{AtomicPtr, Ordering},
5};
6
7pub(crate) use winapi::shared::{
8    basetsd::ULONG_PTR,
9    minwindef::{DWORD, HMODULE, WORD},
10};
11pub use winapi::um::winnt::{LPCSTR, LPCWSTR};
12use winapi::{
13    shared::minwindef::{__some_function, FARPROC, HINSTANCE__, TRUE},
14    um::libloaderapi::{FreeLibrary, GetProcAddress, LoadLibraryExW},
15};
16
17pub mod flags {
18    pub const NO_FLAGS: LOAD_LIBRARY_FLAGS = 0;
19
20    #[allow(non_camel_case_types)]
21    pub type LOAD_LIBRARY_FLAGS = super::DWORD;
22
23    pub use winapi::um::libloaderapi::{
24        DONT_RESOLVE_DLL_REFERENCES, LOAD_IGNORE_CODE_AUTHZ_LEVEL, LOAD_LIBRARY_AS_DATAFILE,
25        LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE, LOAD_LIBRARY_AS_IMAGE_RESOURCE,
26        LOAD_LIBRARY_REQUIRE_SIGNED_TARGET, LOAD_LIBRARY_SAFE_CURRENT_DIRS,
27        LOAD_LIBRARY_SEARCH_APPLICATION_DIR, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS,
28        LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR, LOAD_LIBRARY_SEARCH_SYSTEM32,
29        LOAD_LIBRARY_SEARCH_USER_DIRS, LOAD_WITH_ALTERED_SEARCH_PATH,
30    };
31}
32
33#[repr(transparent)]
34pub(crate) struct AtomicDllHandle(AtomicPtr<HINSTANCE__>);
35impl AtomicDllHandle {
36    pub(crate) const fn empty() -> Self {
37        Self(AtomicPtr::new(ptr::null_mut()))
38    }
39    pub(crate) fn load(&self) -> DllHandle {
40        DllHandle(self.0.load(Ordering::SeqCst))
41    }
42    pub(crate) fn store(&self, handle: DllHandle) {
43        self.0.store(handle.0, Ordering::SeqCst);
44    }
45    pub(crate) fn clear(&self) {
46        self.0.store(ptr::null_mut(), Ordering::SeqCst);
47    }
48}
49
50#[derive(Clone, Copy)]
51#[repr(transparent)]
52pub(crate) struct DllHandle(HMODULE);
53impl DllHandle {
54    pub(crate) unsafe fn load(lib_file_name: LPCWSTR, flags: flags::LOAD_LIBRARY_FLAGS) -> Self {
55        Self(LoadLibraryExW(lib_file_name, ptr::null_mut(), flags))
56    }
57    pub(crate) fn is_invalid(&self) -> bool {
58        self.0.is_null()
59    }
60    pub(crate) unsafe fn free(self) -> bool {
61        let succeeded = FreeLibrary(self.0);
62
63        succeeded == TRUE
64    }
65    pub(crate) unsafe fn get_proc(&self, name: LPCSTR) -> Option<DllProcPtr> {
66        DllProcPtr::new(GetProcAddress(self.0, name))
67    }
68}
69
70#[repr(transparent)]
71pub(crate) struct AtomicDllProcPtr(AtomicPtr<__some_function>);
72impl AtomicDllProcPtr {
73    pub(crate) const fn empty() -> Self {
74        Self(AtomicPtr::new(ptr::null_mut()))
75    }
76    pub(crate) fn load(&self) -> Option<DllProcPtr> {
77        DllProcPtr::new(self.0.load(Ordering::SeqCst))
78    }
79    pub(crate) fn store(&self, handle: Option<DllProcPtr>) {
80        self.0.store(
81            handle
82                .map(|proc| proc.0.as_ptr())
83                .unwrap_or(ptr::null_mut()),
84            Ordering::SeqCst,
85        );
86    }
87}
88
89#[repr(transparent)]
90pub(crate) struct DllProcPtr(ptr::NonNull<__some_function>);
91impl DllProcPtr {
92    fn new(proc: FARPROC) -> Option<Self> {
93        ptr::NonNull::new(proc).map(DllProcPtr)
94    }
95    pub(crate) unsafe fn transmute<T: Copy>(self) -> T {
96        *transmute::<_, &T>(&self.0)
97    }
98}