use windows::Win32::{
Foundation::{CloseHandle, HANDLE},
System::Diagnostics::ToolHelp::{
CreateToolhelp32Snapshot, PROCESSENTRY32W, Process32FirstW, Process32NextW,
TH32CS_SNAPPROCESS,
},
};
use super::win32;
use crate::error::ElevateError;
pub struct ProcessSnapshot {
handle: HANDLE,
entry: PROCESSENTRY32W,
started: bool,
}
impl Drop for ProcessSnapshot {
fn drop(&mut self) {
if !self.handle.is_invalid() {
unsafe {
let _ = CloseHandle(self.handle);
}
}
}
}
impl ProcessSnapshot {
pub fn new() -> Result<Self, ElevateError> {
let handle = win32!(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0))?;
let entry = PROCESSENTRY32W {
dwSize: std::mem::size_of::<PROCESSENTRY32W>() as u32,
..Default::default()
};
Ok(Self {
handle,
entry,
started: false,
})
}
}
impl Iterator for ProcessSnapshot {
type Item = (u32, String);
fn next(&mut self) -> Option<Self::Item> {
let ok = if self.started {
unsafe { Process32NextW(self.handle, &raw mut self.entry).is_ok() }
} else {
self.started = true;
unsafe { Process32FirstW(self.handle, &raw mut self.entry).is_ok() }
};
if !ok {
return None;
}
let len = self
.entry
.szExeFile
.iter()
.position(|&c| c == 0)
.unwrap_or(self.entry.szExeFile.len());
let name = String::from_utf16_lossy(&self.entry.szExeFile[..len]);
Some((self.entry.th32ProcessID, name))
}
}