pub const EXIT_SHARED_CONSOLE: i32 = 3;
#[derive(Debug, PartialEq, Eq)]
pub enum Interrupted {
Sent,
SharedWithSupervisor,
}
pub fn interrupt_console_of(pid: u32, supervisor_pid: u32) -> std::io::Result<Interrupted> {
use windows_sys::Win32::System::Console::{
AttachConsole, CTRL_C_EVENT, FreeConsole, GenerateConsoleCtrlEvent, SetConsoleCtrlHandler,
};
if unsafe { SetConsoleCtrlHandler(None, 1) } == 0 {
return Err(std::io::Error::last_os_error());
}
unsafe { FreeConsole() };
if unsafe { AttachConsole(pid) } == 0 {
return Err(std::io::Error::last_os_error());
}
let result = console_process_list().and_then(|attached| {
if attached.contains(&supervisor_pid) {
return Ok(Interrupted::SharedWithSupervisor);
}
if unsafe { GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0) } == 0 {
return Err(std::io::Error::last_os_error());
}
Ok(Interrupted::Sent)
});
unsafe { FreeConsole() };
result
}
fn console_process_list() -> std::io::Result<Vec<u32>> {
use windows_sys::Win32::System::Console::GetConsoleProcessList;
let mut pids = vec![0u32; 64];
for _ in 0..4 {
let count = unsafe { GetConsoleProcessList(pids.as_mut_ptr(), pids.len() as u32) };
if count == 0 {
return Err(std::io::Error::last_os_error());
}
if count as usize <= pids.len() {
pids.truncate(count as usize);
return Ok(pids);
}
pids.resize(count as usize * 2, 0);
}
Err(std::io::Error::other(
"the console's process list kept outgrowing the buffer",
))
}