Skip to main content

windows_dll/
lib.rs

1mod cache;
2#[doc(hidden)]
3pub mod macro_internal;
4mod platform;
5
6#[doc = include_str!("../macro.md")]
7pub use windows_dll_codegen::dll;
8
9pub use platform::flags;
10
11use cache::DllCache;
12use platform::{LPCSTR, LPCWSTR};
13use core::marker::PhantomData;
14
15pub trait WindowsDll: Sized + 'static {
16    const LEN: usize;
17    const LIB: &'static str;
18    const LIB_LPCWSTR: LPCWSTR;
19    const FLAGS: flags::LOAD_LIBRARY_FLAGS;
20
21    unsafe fn cache() -> &'static DllCache<Self>;
22    unsafe fn exists() -> bool {
23        Self::cache().lib_exists()
24    }
25    unsafe fn free() -> bool {
26        let library = Self::cache();
27        library.free_lib()
28    }
29}
30
31pub trait WindowsDllProc: Sized {
32    type Dll: WindowsDll;
33    type Sig: Copy;
34    const CACHE_INDEX: usize;
35    const PROC: Proc;
36    const PROC_LPCSTR: LPCSTR;
37
38    unsafe fn proc() -> Result<Self::Sig, Error<Self>>;
39    unsafe fn exists() -> bool {
40        Self::proc().is_ok()
41    }
42}
43
44#[derive(Debug, Clone)]
45pub enum Proc {
46    Name(&'static str),
47    Ordinal(u16),
48}
49
50impl core::fmt::Display for Proc {
51    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
52        match self {
53            Self::Name(name) => name.fmt(f),
54            Self::Ordinal(ordinal) => ordinal.fmt(f),
55        }
56    }
57}
58
59#[derive(Debug, Copy, Clone)]
60#[repr(u8)]
61pub enum ErrorKind {
62    Lib,
63    Proc,
64}
65
66pub struct Error<D> {
67    pub kind: ErrorKind,
68    _dll: PhantomData<D>,
69}
70impl<D> Error<D> {
71    pub fn lib() -> Self {
72        Self {
73            kind: ErrorKind::Lib,
74            _dll: PhantomData,
75        }
76    }
77    pub fn proc() -> Self {
78        Self {
79            kind: ErrorKind::Proc,
80            _dll: PhantomData,
81        }
82    }
83}
84
85impl<D> Copy for Error<D> {}
86impl<D> Clone for Error<D> {
87    fn clone(&self) -> Self {
88        *self
89    }
90}
91
92impl<D> From<ErrorKind> for Error<D> {
93    fn from(kind: ErrorKind) -> Self {
94        Self {
95            kind,
96            _dll: PhantomData,
97        }
98    }
99}
100
101impl<D: WindowsDllProc> std::error::Error for Error<D> {}
102
103impl<D: WindowsDllProc> core::fmt::Display for Error<D> {
104    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
105        match &self.kind {
106            ErrorKind::Lib => write!(f, "Could not load {}", D::Dll::LIB),
107            ErrorKind::Proc => write!(f, "Could not load {}#{}", D::Dll::LIB, D::PROC),
108        }
109    }
110}
111impl<D: WindowsDllProc> core::fmt::Debug for Error<D> {
112    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
113        f.debug_struct("Error")
114            .field("kind", &self.kind)
115            .field("lib", &D::Dll::LIB)
116            .field("proc", &D::PROC)
117            .finish()
118    }
119}