#![cfg(windows)]
use std::cmp::Ordering;
use std::ffi::{CStr, CString};
use std::mem::{size_of, zeroed};
use winapi::shared::minwindef::{DWORD, FALSE, TRUE};
use winapi::um::processthreadsapi::OpenProcess;
use winapi::um::tlhelp32::{
CreateToolhelp32Snapshot, Process32First, Process32Next, PROCESSENTRY32, TH32CS_SNAPPROCESS,
};
use winapi::um::winnt::{HANDLE, PROCESS_ALL_ACCESS};
#[derive(Clone)]
pub struct WindowsProcess {
handle: HANDLE,
}
impl WindowsProcess {
fn new(handle: HANDLE) -> WindowsProcess {
WindowsProcess { handle: handle }
}
pub fn find_by_name(name: &str) -> Option<WindowsProcess> {
let processes = WindowsProcess::find_all_by_name(name);
match processes.len() {
0 => None,
_ => Some(processes[0].clone()),
}
}
pub fn find_all_by_name(name: &str) -> Vec<WindowsProcess> {
let snapshot = unsafe { CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) };
let dest_path = CString::new(name).unwrap();
let mut vec = Vec::<WindowsProcess>::new();
let mut entry = unsafe { zeroed::<PROCESSENTRY32>() };
entry.dwSize = size_of::<PROCESSENTRY32>() as DWORD;
let loop_func = |entry: PROCESSENTRY32, vec: &mut Vec<WindowsProcess>| {
let path = unsafe { CString::from(CStr::from_ptr(entry.szExeFile.as_ptr())) };
if path.cmp(&dest_path) == Ordering::Equal {
let handle = unsafe { OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID) };
vec.push(WindowsProcess::new(handle));
}
};
if unsafe { Process32First(snapshot, &mut entry) == TRUE } {
while {
loop_func(entry.clone(), &mut vec);
unsafe { Process32Next(snapshot, &mut entry) == TRUE }
} {}
}
vec
}
}