use super::{open_process_by_id, ProcessIterator, ThreadIterator};
use crate::{types::ModuleInfoWithName, MfError};
use core::mem::{size_of, zeroed};
use windows::Win32::{
Foundation::HANDLE,
System::{
Diagnostics::ToolHelp::{
CreateToolhelp32Snapshot, Module32FirstW, Module32NextW, MODULEENTRY32W,
TH32CS_SNAPMODULE, TH32CS_SNAPMODULE32,
},
Threading::PROCESS_QUERY_INFORMATION,
},
};
pub struct ModuleIterator {
h: HANDLE,
entry: MODULEENTRY32W,
stop: bool,
}
impl ModuleIterator {
pub fn new(process_id: u32) -> crate::Result<Self> {
unsafe {
if let Ok(h) =
CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, process_id)
{
let mut this = Self {
h,
entry: zeroed(),
stop: false,
};
this.entry.dwSize = size_of::<MODULEENTRY32W>() as _;
if !Module32FirstW(this.h, &mut this.entry).as_bool() {
return MfError::last();
}
Ok(this)
} else {
MfError::last()
}
}
}
}
impl Iterator for ModuleIterator {
type Item = ModuleInfoWithName;
fn next(&mut self) -> Option<Self::Item> {
if self.stop {
return None;
}
let current = ModuleInfoWithName::from(&self.entry);
unsafe {
self.stop = !Module32NextW(self.h, &mut self.entry).as_bool();
}
Some(current)
}
}
pub fn processes() -> ProcessIterator {
ProcessIterator::new().unwrap()
}
pub fn modules(process_id: u32) -> impl Iterator<Item = ModuleInfoWithName> {
open_process_by_id(process_id, false, PROCESS_QUERY_INFORMATION)
.expect("Faild to open the process")
.modules()
.expect("Faild to create an iterator over process's modules")
}
pub fn threads(process_id: u32) -> ThreadIterator {
open_process_by_id(process_id, false, PROCESS_QUERY_INFORMATION)
.expect("Faild to open the process")
.threads()
.expect("Faild to create an iterator over process's modules")
}