use crate::module;
use crate::module::error::Error;
use crate::module::library::symbol::Symbol;
use std::ffi::CString;
use std::fmt::Debug;
use std::os::windows::ffi::OsStrExt;
use std::path::Path;
use windows_sys::Win32::Foundation::{FreeLibrary, HMODULE};
use windows_sys::Win32::System::LibraryLoader::{GetModuleHandleW, GetProcAddress, LoadLibraryW};
pub const EXT: &str = "dll";
#[derive(Debug)]
pub struct Library(HMODULE);
unsafe impl Send for Library {}
impl Library {
pub fn open_self() -> module::Result<Self> {
let handle = unsafe { GetModuleHandleW(std::ptr::null()) };
if handle.is_null() {
return Err(Error::Io(std::io::Error::last_os_error()));
}
Ok(Library(handle))
}
pub unsafe fn load(path: impl AsRef<Path>) -> module::Result<Self> {
let mut path = path.as_ref().as_os_str().encode_wide().collect::<Vec<_>>();
if path.iter().any(|v| *v == 0x0) {
return Err(Error::Null);
}
path.push(0);
let handle = LoadLibraryW(path.as_ptr());
if handle.is_null() {
return Err(Error::Io(std::io::Error::last_os_error()));
}
Ok(Library(handle))
}
}
impl super::Library for Library {
unsafe fn load_symbol<T>(
&self,
name: impl AsRef<str>,
) -> module::Result<Option<Symbol<'_, T>>> {
let name = CString::new(name.as_ref().as_bytes()).map_err(|_| Error::Null)?;
let sym = GetProcAddress(self.0, name.as_ptr() as _);
if sym.is_none() {
Ok(None)
} else {
Ok(Some(Symbol::from_raw(std::mem::transmute(sym))))
}
}
}
impl Drop for Library {
fn drop(&mut self) {
unsafe { FreeLibrary(self.0) };
}
}