use std::io;
use std::ops::BitOr;
use std::os::windows::io::{AsHandle, AsRawHandle, FromRawHandle, OwnedHandle};
use std::ptr;
use windows_sys::Win32::Foundation::{DuplicateHandle, FALSE, HANDLE};
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)
}
}
pub fn duplicate_handle_with_access(
handle: impl AsHandle,
access: Access,
) -> io::Result<OwnedHandle> {
let mut duplicate: HANDLE = ptr::null_mut();
let ok = unsafe {
DuplicateHandle(
GetCurrentProcess(),
handle.as_handle().as_raw_handle(),
GetCurrentProcess(),
&mut duplicate,
access.bits(),
FALSE,
0,
)
};
if ok == FALSE {
return Err(io::Error::last_os_error());
}
Ok(unsafe { OwnedHandle::from_raw_handle(duplicate) })
}
#[cfg(test)]
mod tests;