#![cfg(windows)]
use std::io;
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::System::Console::{COORD, HPCON, PSEUDOCONSOLE_INHERIT_CURSOR};
use super::conpty_api::{self, ConPtyApi};
use super::PSEUDOCONSOLE_PASSTHROUGH_MODE;
const PSEUDOCONSOLE_RESIZE_QUIRK: u32 = 0x2;
const PSEUDOCONSOLE_WIN32_INPUT_MODE: u32 = 0x4;
pub(super) struct PseudoConsole {
handle: HPCON,
api: &'static ConPtyApi,
}
unsafe impl Send for PseudoConsole {}
unsafe impl Sync for PseudoConsole {}
impl PseudoConsole {
pub(super) fn new(size: COORD, input: HANDLE, output: HANDLE) -> io::Result<Self> {
let (api, _source) = conpty_api::get();
let mut hpc: HPCON = 0;
let flags = PSEUDOCONSOLE_INHERIT_CURSOR
| PSEUDOCONSOLE_RESIZE_QUIRK
| PSEUDOCONSOLE_WIN32_INPUT_MODE
| PSEUDOCONSOLE_PASSTHROUGH_MODE;
let hr = unsafe { (api.create)(size, input, output, flags, &mut hpc) };
if hr != 0 {
return Err(io::Error::other(format!(
"CreatePseudoConsole failed: HRESULT 0x{:08x}",
hr as u32
)));
}
if hpc == 0 {
return Err(io::Error::other(
"CreatePseudoConsole returned S_OK but null HPCON",
));
}
Ok(Self { handle: hpc, api })
}
pub(super) fn as_handle(&self) -> HPCON {
self.handle
}
pub(super) fn resize(&self, size: COORD) -> io::Result<()> {
let hr = unsafe { (self.api.resize)(self.handle, size) };
if hr != 0 {
return Err(io::Error::other(format!(
"ResizePseudoConsole failed: HRESULT 0x{:08x}",
hr as u32
)));
}
Ok(())
}
}
impl Drop for PseudoConsole {
fn drop(&mut self) {
if self.handle != 0 {
unsafe { (self.api.close)(self.handle) };
self.handle = 0;
}
}
}