use std::result;
use heim_common::prelude::*;
use winapi::shared::winerror;
use winapi::um::minwinbase;
use super::bindings;
use crate::{Pid, ProcessError};
pub fn pids() -> impl Stream<Item = result::Result<Pid, ProcessError>> {
future::lazy(|_| {
let pids = bindings::pids()?;
Ok(stream::iter(pids).map(Ok))
})
.try_flatten_stream()
.map_ok(Pid::from)
}
pub fn pid_exists(pid: Pid) -> impl Future<Output = result::Result<bool, ProcessError>> {
future::lazy(move |_| {
if pid == 0 {
return Ok(true);
}
let process = match bindings::ProcessHandle::query_limited_info(pid) {
Ok(process) => process,
Err(ref e) if e.raw_os_error() == Some(winerror::ERROR_INVALID_PARAMETER as i32) => {
return Ok(false)
}
Err(ref e) if e.raw_os_error() == Some(winerror::ERROR_ACCESS_DENIED as i32) => {
return Ok(true)
}
Err(e) => return Err(ProcessError::from(Error::from(e))),
};
match process.exit_code() {
Ok(code) if code == minwinbase::STILL_ACTIVE => Ok(true),
Err(ref e) if e.raw_os_error() == Some(winerror::ERROR_ACCESS_DENIED as i32) => {
Ok(true)
}
Err(e) => Err(e.into()),
Ok(..) => {
let pids = bindings::pids().map_err(Error::from)?;
Ok(pids.contains(&pid))
}
}
})
}