#![allow(clippy::uninit_vec)]
use super::psuedocon::HPCON;
use anyhow::Error;
use anyhow::ensure;
use std::ffi::c_void;
use std::io::Error as IoError;
use std::mem;
use std::ptr;
use winapi::shared::minwindef::DWORD;
use winapi::um::processthreadsapi::*;
use winapi::um::winnt::HANDLE;
const PROC_THREAD_ATTRIBUTE_JOB_LIST: usize = 0x0002000D;
const PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE: usize = 0x00020016;
pub struct ProcThreadAttributeList {
data: Vec<u8>,
job_list: Vec<HANDLE>,
}
impl ProcThreadAttributeList {
pub fn with_capacity(num_attributes: DWORD) -> Result<Self, Error> {
let mut bytes_required: usize = 0;
unsafe {
InitializeProcThreadAttributeList(
ptr::null_mut(),
num_attributes,
0,
&mut bytes_required,
)
};
let mut data = Vec::with_capacity(bytes_required);
unsafe { data.set_len(bytes_required) };
let attr_ptr = data.as_mut_slice().as_mut_ptr() as *mut _;
let res = unsafe {
InitializeProcThreadAttributeList(attr_ptr, num_attributes, 0, &mut bytes_required)
};
ensure!(
res != 0,
"InitializeProcThreadAttributeList failed: {}",
IoError::last_os_error()
);
Ok(Self {
data,
job_list: Vec::new(),
})
}
pub fn as_mut_ptr(&mut self) -> LPPROC_THREAD_ATTRIBUTE_LIST {
self.data.as_mut_slice().as_mut_ptr() as *mut _
}
pub fn set_pty(&mut self, con: HPCON) -> Result<(), Error> {
unsafe {
self.update(
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
con,
mem::size_of::<HPCON>(),
)
}
}
pub fn set_job(&mut self, job: HANDLE) -> Result<(), Error> {
self.job_list = vec![job];
let value = self.job_list.as_mut_ptr().cast();
let size = std::mem::size_of_val(self.job_list.as_slice());
unsafe { self.update(PROC_THREAD_ATTRIBUTE_JOB_LIST, value, size) }
}
unsafe fn update(
&mut self,
attribute: usize,
value: *mut c_void,
size: usize,
) -> Result<(), Error> {
let res = unsafe {
UpdateProcThreadAttribute(
self.as_mut_ptr(),
0,
attribute,
value,
size,
ptr::null_mut(),
ptr::null_mut(),
)
};
ensure!(
res != 0,
"UpdateProcThreadAttribute failed: {}",
IoError::last_os_error()
);
Ok(())
}
}
impl Drop for ProcThreadAttributeList {
fn drop(&mut self) {
unsafe { DeleteProcThreadAttributeList(self.as_mut_ptr()) };
}
}