use std;
use types::*;
use winapi::shared::minwindef::*;
use winapi::um::handleapi::*;
use winapi::um::tlhelp32::*;
use winapi::um::winnt::*;
pub struct ProcessInfoIterator {
snapshot_handle: HANDLE,
is_first_iteration: bool,
process_entry: PROCESSENTRY32,
}
impl ProcessInfoIterator {
#[inline]
pub fn new() -> Self {
unsafe {
let mut pe32 = std::mem::zeroed::<PROCESSENTRY32>();
pe32.dwSize = std::mem::size_of::<PROCESSENTRY32>() as DWORD;
ProcessInfoIterator {
snapshot_handle: CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0),
is_first_iteration: true,
process_entry: pe32,
}
}
}
}
impl std::iter::Iterator for ProcessInfoIterator {
type Item = Result<ProcessInfo, Error>;
#[inline]
fn next(&mut self) -> Option<Result<ProcessInfo, Error>> {
unsafe {
let ret_code = if self.is_first_iteration {
self.is_first_iteration = false;
if self.snapshot_handle == INVALID_HANDLE_VALUE {
let err = Error::foreign_with_errno("CreateToolhelp32Snapshot");
return Option::Some(Result::Err(err));
}
if Process32First(self.snapshot_handle, &mut self.process_entry) == 0 {
let err = Error::foreign_with_errno("Process32First");
return Option::Some(Result::Err(err));
} else {
1
}
} else {
Process32Next(self.snapshot_handle, &mut self.process_entry)
};
match ret_code {
0 => Option::None,
_ => Option::Some(Result::Ok(gather_process_info(&self.process_entry))),
}
}
}
}
impl Drop for ProcessInfoIterator {
#[inline]
fn drop(&mut self) {
unsafe {
CloseHandle(self.snapshot_handle);
}
}
}
#[inline]
unsafe fn gather_process_info(process_entry: &PROCESSENTRY32) -> ProcessInfo {
ProcessInfo {
name: std::ffi::CStr::from_ptr(&process_entry.szExeFile[0])
.to_string_lossy()
.into_owned(),
pid: process_entry.th32ProcessID,
parent_pid: process_entry.th32ParentProcessID,
threads_count: process_entry.cntThreads,
}
}