diff --git a/src/error.rs b/src/error.rs index fb1a96e..28f31ef 100644 --- a/src/error.rs +++ b/src/error.rs @@ -2,11 +2,11 @@ use thiserror::Error; #[derive(Debug, Error)] pub enum Error { - #[error("couldn't get handle to process")] + #[error("failed to obtain handle")] HandleError(String), - #[error("couldn't create instance of process")] + #[error("failed to create instance")] ProcessError(String), - #[error("couldn't create snapshot")] + #[error("failed to create snapshot")] SnapshotError(String), #[error("failed to convert integer")] IntegerConversionError(#[from] std::num::TryFromIntError), diff --git a/src/process/handle.rs b/src/process/handle.rs index 9ad23b4..d210f58 100644 --- a/src/process/handle.rs +++ b/src/process/handle.rs @@ -21,7 +21,7 @@ impl Drop for Handle { if self.0 != INVALID_HANDLE_VALUE { unsafe { if let Err(why) = CloseHandle(**self) { - eprintln!("couldn't close handle: {why}"); + eprintln!("failed to close handle: {why}"); }; } } @@ -35,13 +35,13 @@ impl Handle { .or_else(|_| OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE, false, pid)) .map_err(|why| { crate::Error::HandleError(format!( - "couldn't open process with needed access: {why}", + "failed to open process with needed access: {why}", )) })? }; if handle == INVALID_HANDLE_VALUE { return Err(crate::Error::HandleError( - "couldn't get a valid handle".to_string(), + "failed to get a valid handle".to_string(), )); } Ok(Self(handle)) diff --git a/src/process/process.rs b/src/process/process.rs index 4092548..d72f0d9 100644 --- a/src/process/process.rs +++ b/src/process/process.rs @@ -2,6 +2,7 @@ use super::{handle::Handle, snapshot}; use derive_more::derive::Display; +#[allow(dead_code)] #[derive(Debug, Default)] pub struct Process { name: String, @@ -28,7 +29,7 @@ impl Process { }; let Some(snapshot) = snapshot else { return Err(crate::Error::ProcessError(format!( - "couldn't find a process with identifier `{identifier}`", + "failed to find a process with identifier `{identifier}`", ))); }; let process = Self { @@ -47,4 +48,17 @@ impl Process { pub fn with_name(name: &str) -> Result { Self::from(&Identifier::Name(name.to_string())) } + + pub fn module(&self, name: &str) -> Result { + dbg!(snapshot::Module::get_modules(self.id)?); + let Some(module) = snapshot::Module::get_modules(self.id)? + .into_iter() + .find(|snapshot| snapshot.name == name) + else { + return Err(crate::Error::ProcessError(format!( + "failed to find a module with identifier `{name}`", + ))); + }; + Ok(module) + } } diff --git a/src/process/snapshot.rs b/src/process/snapshot.rs index 7e499ab..81188d7 100644 --- a/src/process/snapshot.rs +++ b/src/process/snapshot.rs @@ -1,8 +1,9 @@ use windows::Win32::System::Diagnostics::ToolHelp::{ - CreateToolhelp32Snapshot, Process32FirstW, Process32NextW, PROCESSENTRY32W, TH32CS_SNAPPROCESS, + CreateToolhelp32Snapshot, Module32FirstW, Module32NextW, Process32FirstW, Process32NextW, + MODULEENTRY32W, PROCESSENTRY32W, TH32CS_SNAPMODULE, TH32CS_SNAPMODULE32, TH32CS_SNAPPROCESS, }; -#[derive(Debug, Default)] +#[derive(Debug)] pub struct Process { pub id: u32, pub name: String, @@ -15,7 +16,7 @@ impl Process { Ok(snapshot) => snapshot, Err(why) => { return Err(crate::Error::SnapshotError(format!( - "couldn't create snapshot: {why}" + "failed to create process snapshot: {why}" ))) } } @@ -29,7 +30,7 @@ impl Process { Ok(()) => {} Err(why) => { return Err(crate::Error::SnapshotError(format!( - "couldn't get first process from snapshot: {why}" + "failed to get first process from snapshot: {why}" ))) } }; @@ -53,3 +54,64 @@ impl Process { Ok(processes) } } + +#[derive(Debug)] +pub struct Module { + pub process_id: u32, + pub name: String, + pub path: String, + pub base_address: usize, + pub base_size: usize, +} + +impl Module { + pub fn get_modules(pid: u32) -> Result, crate::Error> { + let snapshot = unsafe { + match CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid) { + Ok(snapshot) => snapshot, + Err(why) => { + return Err(crate::Error::SnapshotError(format!( + "failed to create module snapshot: {why}" + ))) + } + } + }; + let mut module_entry_32_w = MODULEENTRY32W { + dwSize: u32::try_from(size_of::())?, + ..Default::default() + }; + unsafe { + match Module32FirstW(snapshot, &mut module_entry_32_w) { + Ok(()) => {} + Err(why) => { + return Err(crate::Error::SnapshotError(format!( + "failed to get first module from snapshot: {why}" + ))) + } + } + } + let mut modules = Vec::new(); + loop { + let name = String::from_utf16_lossy(&module_entry_32_w.szModule) + .trim_end_matches('\0') + .to_string(); + let path = String::from_utf16_lossy(&module_entry_32_w.szExePath) + .trim_end_matches('\0') + .to_string(); + let module = Module { + process_id: pid, + name, + path, + base_address: module_entry_32_w.modBaseAddr as usize, + base_size: module_entry_32_w.modBaseSize as usize, + }; + modules.push(module); + unsafe { + if Module32NextW(snapshot, &mut module_entry_32_w).is_err() { + break; + } + } + } + Ok(modules) + } +}