use std::ops::Deref;
use winapi::shared::minwindef::{DWORD, HLOCAL, LPVOID};
use winapi::shared::ntdef::NULL;
use winapi::um::combaseapi::CoTaskMemFree;
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::handleapi::{CloseHandle, INVALID_HANDLE_VALUE};
use winapi::um::winbase::LocalFree;
use winapi::um::winnt::HANDLE;
#[repr(transparent)]
#[derive(Debug)]
pub struct Handle(HANDLE);
impl Handle {
pub unsafe fn wrap_valid(h: HANDLE) -> Result<Handle, DWORD> {
if h == INVALID_HANDLE_VALUE {
Err(GetLastError())
} else {
Ok(Handle(h))
}
}
pub unsafe fn wrap_nonnull(h: HANDLE) -> Result<Handle, DWORD> {
if h == NULL {
Err(GetLastError())
} else {
Ok(Handle(h))
}
}
}
impl Deref for Handle {
type Target = HANDLE;
fn deref(&self) -> &HANDLE {
&self.0
}
}
impl Drop for Handle {
fn drop(&mut self) {
unsafe {
CloseHandle(self.0);
}
}
}
#[macro_export]
macro_rules! call_valid_handle_getter {
($f:ident ( $($arg:expr),* )) => {
{
use $crate::error::{Error, ErrorCode, FileLine};
$crate::handle::Handle::wrap_valid($f($($arg),*))
.map_err(|last_error| Win32Error {
code: last_error,
function: Some(stringify!($f)),
file_line: Some(FileLine(file!(), line!())),
})
}
};
($f:ident ( $($arg:expr),+ , )) => {
$crate::call_valid_handle_getter!($f($($arg),*))
};
}
#[macro_export]
macro_rules! call_nonnull_handle_getter {
($f:ident ( $($arg:expr),* )) => {
{
use $crate::error::{Error, ErrorCode, FileLine};
$crate::handle::Handle::wrap_nonnull($f($($arg),*))
.map_err(|last_error| Win32Error {
code: last_error,
function: Some(stringify!($f)),
file_line: Some(FileLine(file!(), line!())),
})
}
};
($f:ident ( $($arg:expr),+ , )) => {
$crate::call_nonnull_handle_getter!($f($($arg),*))
};
}
#[repr(transparent)]
#[derive(Debug)]
pub struct HLocal(HLOCAL);
impl HLocal {
pub unsafe fn wrap(h: HLOCAL) -> Result<HLocal, DWORD> {
if h == NULL {
Err(GetLastError())
} else {
Ok(HLocal(h))
}
}
}
impl Deref for HLocal {
type Target = HLOCAL;
fn deref(&self) -> &HLOCAL {
&self.0
}
}
impl Drop for HLocal {
fn drop(&mut self) {
unsafe {
LocalFree(self.0);
}
}
}
#[repr(transparent)]
#[derive(Debug)]
pub struct CoTaskMem(LPVOID);
impl CoTaskMem {
pub unsafe fn wrap(p: LPVOID) -> Result<CoTaskMem, ()> {
if p == NULL {
Err(())
} else {
Ok(CoTaskMem(p))
}
}
}
impl Deref for CoTaskMem {
type Target = LPVOID;
fn deref(&self) -> &LPVOID {
&self.0
}
}
impl Drop for CoTaskMem {
fn drop(&mut self) {
unsafe {
CoTaskMemFree(self.0);
}
}
}