use std::fs::OpenOptions;
use std::io;
use std::os::windows::fs::OpenOptionsExt;
use std::os::windows::io::{AsHandle, BorrowedHandle, OwnedHandle};
use std::path::Path;
const FILE_FLAG_OVERLAPPED: u32 = 0x4000_0000;
pub(crate) mod notification_flags {
pub(crate) const SKIP_COMPLETION_PORT_ON_SUCCESS: u8 = 0x1;
pub(crate) const SKIP_SET_EVENT_ON_HANDLE: u8 = 0x2;
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct NotificationModes {
pub skip_completion_port_on_success: bool,
pub skip_set_event_on_handle: bool,
}
#[derive(Debug)]
pub struct UnassociatedEndpoint {
handle: OwnedHandle,
modes: NotificationModes,
}
impl UnassociatedEndpoint {
pub fn open(
path: impl AsRef<Path>,
read: bool,
write: bool,
extra_flags: u32,
) -> io::Result<Self> {
let file = OpenOptions::new()
.read(read)
.write(write)
.custom_flags(FILE_FLAG_OVERLAPPED | extra_flags)
.open(path)?;
Ok(unsafe { Self::assume_overlapped(OwnedHandle::from(file)) })
}
#[must_use]
pub unsafe fn assume_overlapped(handle: OwnedHandle) -> Self {
Self {
handle,
modes: NotificationModes::default(),
}
}
#[must_use]
pub fn handle(&self) -> BorrowedHandle<'_> {
self.handle.as_handle()
}
#[must_use]
pub fn notification_modes(&self) -> NotificationModes {
self.modes
}
#[must_use]
pub fn into_handle(self) -> OwnedHandle {
self.handle
}
pub fn set_notification_modes(&mut self, modes: NotificationModes) -> io::Result<()> {
use std::os::windows::io::AsRawHandle;
let mut flags = 0_u8;
if modes.skip_completion_port_on_success {
flags |= notification_flags::SKIP_COMPLETION_PORT_ON_SUCCESS;
}
if modes.skip_set_event_on_handle {
flags |= notification_flags::SKIP_SET_EVENT_ON_HANDLE;
}
let ok = unsafe {
windows_sys::Win32::Storage::FileSystem::SetFileCompletionNotificationModes(
self.handle.as_raw_handle(),
flags,
)
};
if ok == 0 {
return Err(io::Error::last_os_error());
}
self.modes.skip_completion_port_on_success |= modes.skip_completion_port_on_success;
self.modes.skip_set_event_on_handle |= modes.skip_set_event_on_handle;
Ok(())
}
}
#[cfg(test)]
mod tests;