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}