use std::io;
use std::ops::BitOr;
use std::os::windows::io::{AsHandle, AsRawHandle, FromRawHandle, OwnedHandle};
use std::ptr;
use windows_sys::Win32::Foundation::{DUPLICATE_SAME_ACCESS, DuplicateHandle, FALSE, HANDLE, TRUE};
use windows_sys::Win32::System::Threading::{
EVENT_MODIFY_STATE, GetCurrentProcess, SYNCHRONIZATION_SYNCHRONIZE,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Access(u32);
impl Access {
pub const SYNCHRONIZE: Self = Self(SYNCHRONIZATION_SYNCHRONIZE);
pub const EVENT_MODIFY_STATE: Self = Self(EVENT_MODIFY_STATE);
#[must_use]
pub const fn from_bits(bits: u32) -> Self {
Self(bits)
}
#[must_use]
pub const fn bits(self) -> u32 {
self.0
}
}
impl BitOr for Access {
type Output = Self;
fn bitor(self, other: Self) -> Self {
Self(self.0 | other.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DuplicateAccess {
Same,
Chosen(Access),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Inheritance {
NotInheritable,
Inheritable,
}
pub fn duplicate_handle(
handle: impl AsHandle,
access: DuplicateAccess,
inheritance: Inheritance,
) -> io::Result<OwnedHandle> {
let (desired_access, options) = match access {
DuplicateAccess::Same => (0, DUPLICATE_SAME_ACCESS),
DuplicateAccess::Chosen(mask) => (mask.bits(), 0),
};
let inherit = match inheritance {
Inheritance::NotInheritable => FALSE,
Inheritance::Inheritable => TRUE,
};
let mut duplicate: HANDLE = ptr::null_mut();
let ok = unsafe {
DuplicateHandle(
GetCurrentProcess(),
handle.as_handle().as_raw_handle(),
GetCurrentProcess(),
&mut duplicate,
desired_access,
inherit,
options,
)
};
if ok == FALSE {
return Err(io::Error::last_os_error());
}
Ok(unsafe { OwnedHandle::from_raw_handle(duplicate) })
}
pub fn duplicate_handle_with_access(
handle: impl AsHandle,
access: Access,
) -> io::Result<OwnedHandle> {
duplicate_handle(
handle,
DuplicateAccess::Chosen(access),
Inheritance::NotInheritable,
)
}
#[cfg(test)]
mod tests;