#![cfg_attr(not(doc), allow(unused_imports))]
use crate::*;
use winapi::ctypes::c_void;
use winapi::shared::minwindef::FALSE;
use winapi::shared::ntdef::HANDLE;
use winapi::shared::winerror::*;
use winapi::um::handleapi::*;
use winapi::um::winnt::{DUPLICATE_CLOSE_SOURCE, DUPLICATE_SAME_ACCESS};
use core::fmt::{self, Formatter};
use core::ptr::{null_mut, NonNull};
pub type HANDLENN = NonNull<c_void>;
pub fn close_handle(object: impl Into<handle::Owned>) -> Result<(), Error> {
let object = object.into();
let h = object.as_handle();
core::mem::forget(object);
Error::get_last_if(FALSE == unsafe { CloseHandle(h) })
}
#[track_caller] pub(crate) unsafe fn drop_close_handle_nn<T>(this: &mut impl AsLocalHandleNN<T>) {
let handle = this.as_handle_nn().as_ptr().cast();
assert!(0 != unsafe { CloseHandle(handle) }, "CloseHandle(0x{:X}) failed with GetLastError()={:?}", handle as usize, Error::get_last());
}
#[cfg(doc)]
pub unsafe fn close_remote_handle(process: &process::Handle, handle: HANDLE) -> Result<(), Error> {
Error::get_last_if(FALSE == unsafe { DuplicateHandle(process.as_handle(), handle, null_mut(), null_mut(), 0, false as _, DUPLICATE_CLOSE_SOURCE)})
}
#[cfg(doc)] pub fn compare_object_handles(first: &handle::Owned, second: &handle::Owned) -> bool {
FALSE != unsafe { CompareObjectHandles(first.as_handle(), second.as_handle()) }
}
pub(crate) fn debug<T>(fmt: &mut Formatter, module: &str, name: &str, handle: NonNull<T>) -> fmt::Result {
write!(fmt, "{module}::{name}(")?;
match handle.as_ptr() as isize {
-1 => write!(fmt, "-1 aka GetCurrentProcess()"),
-2 => write!(fmt, "-2 aka GetCurrentThread()"),
-3 => write!(fmt, "-3 aka GetCurrentSession()"), -4 => write!(fmt, "-4 aka GetCurrentProcessToken()"),
-5 => write!(fmt, "-5 aka GetCurrentThreadToken()"),
-6 => write!(fmt, "-6 aka GetCurrentThreadEffectiveToken()"),
o => write!(fmt, "0x{:08x}", o as usize),
}?;
write!(fmt, ")")
}
#[test] fn verify_debug_values() {
assert_eq!(-1, get_current_process() .as_handle() as isize);
assert_eq!(-2, get_current_thread() .as_handle() as isize);
assert_eq!(-4, get_current_process_token() .as_handle() as isize);
assert_eq!(-5, get_current_thread_token() .as_handle() as isize);
assert_eq!(-6, get_current_thread_effective_token() .as_handle() as isize);
}
pub fn duplicate_handle_local<'a>(source: impl AsRef<handle::Psuedo<'a>>, access: impl Into<access::Mask>, inherit_handle: bool) -> Result<handle::Owned, Error> { let process = get_current_process();
let source = source.as_ref();
let mut target = null_mut();
Error::get_last_if(FALSE == unsafe { DuplicateHandle(
process.as_handle(),
source.as_handle(),
process.as_handle(),
&mut target,
access.into().into(),
inherit_handle as _,
0
)})?;
unsafe { handle::Owned::from_raw(target) }
}
pub fn duplicate_handle_local_same_access<'a>(source: impl AsRef<handle::Psuedo<'a>>, inherit_handle: bool) -> Result<handle::Owned, Error> { let process = get_current_process();
let source = source.as_ref();
let mut target = null_mut();
Error::get_last_if(FALSE == unsafe { DuplicateHandle(
process.as_handle(),
source.as_handle(),
process.as_handle(),
&mut target,
0,
inherit_handle as _,
DUPLICATE_SAME_ACCESS
)})?;
unsafe { handle::Owned::from_raw(target) }
}
pub fn get_handle_information<'a>(object: impl AsRef<handle::Borrowed<'a>>) -> Result<handle::Flags, Error> {
let mut flags = 0;
Error::get_last_if(FALSE == unsafe { GetHandleInformation(object.as_ref().as_handle(), &mut flags) })?;
Ok(unsafe { handle::Flags::from_unchecked(flags) })
}
pub fn set_handle_information<'a>(object: impl AsRef<handle::Borrowed<'a>>, mask: impl Into<handle::FlagsMask>, flags: impl Into<handle::Flags>) -> Result<(), Error> {
Error::get_last_if(FALSE == unsafe { SetHandleInformation(object.as_ref().as_handle(), mask.into().into(), flags.into().into()) })
}