#![cfg(windows)]
use std::ffi::c_void;
use std::io;
use std::ptr;
use windows_sys::Win32::System::Console::HPCON;
use windows_sys::Win32::System::Threading::{
DeleteProcThreadAttributeList, InitializeProcThreadAttributeList, UpdateProcThreadAttribute,
LPPROC_THREAD_ATTRIBUTE_LIST,
};
const PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE: usize = 0x00020016;
pub(super) struct ProcThreadAttributeList {
buffer: Vec<u8>,
}
impl ProcThreadAttributeList {
pub(super) fn with_pseudoconsole(hpc: HPCON) -> io::Result<Self> {
let mut size: usize = 0;
unsafe {
let _ = InitializeProcThreadAttributeList(ptr::null_mut(), 1, 0, &mut size);
}
if size == 0 {
return Err(io::Error::other(
"InitializeProcThreadAttributeList size probe returned 0",
));
}
let mut buffer = vec![0u8; size];
let list_ptr = buffer.as_mut_ptr() as LPPROC_THREAD_ATTRIBUTE_LIST;
let ok = unsafe { InitializeProcThreadAttributeList(list_ptr, 1, 0, &mut size) };
if ok == 0 {
return Err(io::Error::last_os_error());
}
let ok = unsafe {
UpdateProcThreadAttribute(
list_ptr,
0,
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
hpc as *const c_void,
std::mem::size_of::<HPCON>(),
ptr::null_mut(),
ptr::null(),
)
};
if ok == 0 {
let err = io::Error::last_os_error();
unsafe { DeleteProcThreadAttributeList(list_ptr) };
return Err(err);
}
Ok(Self { buffer })
}
pub(super) fn as_mut_ptr(&mut self) -> LPPROC_THREAD_ATTRIBUTE_LIST {
self.buffer.as_mut_ptr() as LPPROC_THREAD_ATTRIBUTE_LIST
}
}
impl Drop for ProcThreadAttributeList {
fn drop(&mut self) {
unsafe {
DeleteProcThreadAttributeList(self.buffer.as_mut_ptr() as LPPROC_THREAD_ATTRIBUTE_LIST)
};
}
}