use crate::memory::MemoryError;
use crate::memory_hook::Architecture;
use crate::utils::detect_process_architecture;
use std::collections::HashMap;
use windows::Win32::Foundation::HANDLE;
use super::register::ModifierHandler;
#[derive(Clone, Debug)]
pub struct ProcessContext {
pub handle: HANDLE,
pub pid: u32,
pub architecture: Architecture,
}
pub struct ModifierManager {
context: Option<ProcessContext>,
handlers: HashMap<String, Box<dyn ModifierHandler>>,
}
impl ModifierManager {
pub fn new() -> Self {
Self {
context: None,
handlers: HashMap::new(),
}
}
pub fn set_context(&mut self, handle: HANDLE, pid: u32) {
let _ = self.deactivate_all();
if let Some(old_ctx) = &self.context {
crate::memory_aobscan::clear_region_cache(old_ctx.handle);
}
let architecture = detect_process_architecture(pid);
self.context = Some(ProcessContext {
handle,
pid,
architecture,
});
}
pub fn register(&mut self, name: impl Into<String>, handler: Box<dyn ModifierHandler>) {
let name = name.into();
if let Some(mut old_handler) = self.handlers.remove(&name) {
let _ = old_handler.deactivate();
}
self.handlers.insert(name, handler);
}
pub fn unregister(&mut self, name: &str) -> Result<(), MemoryError> {
if let Some(mut handler) = self.handlers.remove(name) {
handler.deactivate()?;
}
Ok(())
}
pub fn clear(&mut self) -> Result<(), MemoryError> {
for (_, mut handler) in self.handlers.drain() {
let _ = handler.deactivate();
}
if let Some(ctx) = &self.context {
crate::memory_aobscan::clear_region_cache(ctx.handle);
}
self.context = None;
Ok(())
}
pub fn activate(&mut self, name: &str) -> Result<(), MemoryError> {
let ctx = self
.context
.as_ref()
.ok_or_else(|| MemoryError::ReadFailed("No process context bound".to_string()))?;
let handler = self
.handlers
.get_mut(name)
.ok_or_else(|| MemoryError::ReadFailed(format!("Handler '{}' not found", name)))?;
handler.activate(ctx)?;
Ok(())
}
pub fn deactivate(&mut self, name: &str) -> Result<(), MemoryError> {
if let Some(handler) = self.handlers.get_mut(name) {
handler.deactivate()?;
}
Ok(())
}
pub fn activate_all(&mut self) -> Result<(), MemoryError> {
let names: Vec<String> = self.handlers.keys().cloned().collect();
for name in names {
self.activate(&name)?;
}
Ok(())
}
pub fn deactivate_all(&mut self) -> Result<(), MemoryError> {
let names: Vec<String> = self.handlers.keys().cloned().collect();
for name in names {
self.deactivate(&name)?;
}
Ok(())
}
pub fn is_active(&self, name: &str) -> bool {
self.handlers.get(name).map_or(false, |h| h.is_active())
}
pub fn list_handlers(&self) -> Vec<&String> {
self.handlers.keys().collect()
}
pub fn get_context(&self) -> Option<&ProcessContext> {
self.context.as_ref()
}
}
impl Drop for ModifierManager {
fn drop(&mut self) {
if let Some(ctx) = &self.context {
crate::memory_aobscan::clear_region_cache(ctx.handle);
}
for (_, mut handler) in self.handlers.drain() {
let _ = handler.deactivate();
}
}
}