use crate::win32_error_with_context;
use std::io::{Error as IoError, Result as IoResult};
use winapi::shared::minwindef::DWORD;
use winapi::um::handleapi::{CloseHandle, INVALID_HANDLE_VALUE};
use winapi::um::processthreadsapi::{GetExitCodeProcess, OpenProcess};
use winapi::um::synchapi::WaitForSingleObject;
use winapi::um::winbase::{INFINITE, WAIT_FAILED};
use winapi::um::winnt::HANDLE;
pub struct Process(HANDLE);
unsafe impl Send for Process {}
impl Drop for Process {
fn drop(&mut self) {
unsafe {
CloseHandle(self.0);
}
}
}
impl Process {
pub fn with_process_id(
desired_access: DWORD,
inherit_handles: bool,
pid: DWORD,
) -> IoResult<Self> {
let proc = unsafe { OpenProcess(desired_access, inherit_handles as _, pid) };
if proc == INVALID_HANDLE_VALUE {
Err(win32_error_with_context(
"OpenProcess",
IoError::last_os_error(),
))
} else {
Ok(Self(proc))
}
}
pub fn as_handle(&self) -> HANDLE {
self.0
}
pub fn with_handle(proc: HANDLE) -> Self {
Self(proc)
}
pub fn wait_for(&self, duration: Option<DWORD>) -> IoResult<DWORD> {
let res = unsafe { WaitForSingleObject(self.0, duration.unwrap_or(INFINITE)) };
if res == WAIT_FAILED {
Err(win32_error_with_context(
"WaitForSingleObject(process)",
IoError::last_os_error(),
))
} else {
Ok(res)
}
}
pub fn exit_code(&self) -> IoResult<DWORD> {
let mut exit_code = 0;
if unsafe { GetExitCodeProcess(self.0, &mut exit_code) } != 0 {
Ok(exit_code)
} else {
Err(win32_error_with_context(
"GetExitCodeProcess",
IoError::last_os_error(),
))
}
}
}