fenestroj 0.0.11

Easier wrappers for Win32 API stuff, safe when possible
Documentation
#![cfg(feature = "libloaderapi")]

//! Things to dynamically load code objects.

use super::*;

use winapi::um::libloaderapi::{
  FreeLibrary, GetModuleHandleW, GetProcAddress, LoadLibraryW,
};

/// See [`GetModuleHandleW`](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlew)
#[inline]
pub unsafe fn get_module_handle(
  opt_name: Option<&str>,
) -> Result<HMODULE, ErrorCode> {
  let module = match opt_name {
    Some(name) => {
      let name_wide = wide_null(name);
      GetModuleHandleW(name_wide.as_ptr())
    }
    None => GetModuleHandleW(null()),
  };
  if module.is_null() {
    Err(get_last_error())
  } else {
    Ok(module)
  }
}

/// See [`LoadLibraryW`](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryw)
#[inline]
pub fn load_library(lib_file_name: &str) -> Result<HMODULE, ErrorCode> {
  let name_null = wide_null(lib_file_name);
  let h = unsafe { LoadLibraryW(name_null.as_ptr()) };
  if h.is_null() {
    Err(get_last_error())
  } else {
    Ok(h)
  }
}

/// See [`FreeLibrary`](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-freelibrary)
#[inline]
pub unsafe fn free_library(handle: HMODULE) -> Result<(), ErrorCode> {
  if FreeLibrary(handle) != 0 {
    Ok(())
  } else {
    Err(get_last_error())
  }
}

/// See [`GetProcAddress`](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress)
#[inline]
pub unsafe fn get_proc_address(
  module: HMODULE,
  proc: &str,
) -> Result<NonNull<c_void>, ErrorCode> {
  let v: Vec<u8> = proc.bytes().chain(Some(0)).collect();
  NonNull::new(GetProcAddress(module, v.as_ptr().cast()).cast())
    .ok_or_else(|| get_last_error())
}