proclist 0.9.2

Cross-platform library to retrieve OS processes information.
Documentation
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,
    }
}