#![cfg(windows)]
use std::io;
use std::os::windows::io::{FromRawHandle, OwnedHandle, RawHandle};
use std::ptr;
use windows_sys::Win32::Foundation::{HANDLE, INVALID_HANDLE_VALUE};
use windows_sys::Win32::Security::SECURITY_ATTRIBUTES;
use windows_sys::Win32::System::Pipes::CreatePipe;
pub(super) struct PipePair {
pub(super) host: OwnedHandle,
pub(super) child: OwnedHandle,
}
#[derive(Copy, Clone)]
pub(super) enum PipeDirection {
HostWriteChildRead,
HostReadChildWrite,
}
pub(super) fn create_pipe(direction: PipeDirection) -> io::Result<PipePair> {
let mut sa: SECURITY_ATTRIBUTES = unsafe { std::mem::zeroed() };
sa.nLength = std::mem::size_of::<SECURITY_ATTRIBUTES>() as u32;
sa.bInheritHandle = 0;
sa.lpSecurityDescriptor = ptr::null_mut();
let mut read_handle: HANDLE = INVALID_HANDLE_VALUE;
let mut write_handle: HANDLE = INVALID_HANDLE_VALUE;
let ok = unsafe { CreatePipe(&mut read_handle, &mut write_handle, &sa, 0) };
if ok == 0 {
return Err(io::Error::last_os_error());
}
let read_owned = unsafe { OwnedHandle::from_raw_handle(read_handle as RawHandle) };
let write_owned = unsafe { OwnedHandle::from_raw_handle(write_handle as RawHandle) };
let (host_owned, child_owned) = match direction {
PipeDirection::HostWriteChildRead => (write_owned, read_owned),
PipeDirection::HostReadChildWrite => (read_owned, write_owned),
};
Ok(PipePair {
host: host_owned,
child: child_owned,
})
}