use windows::Win32::Foundation::HANDLE;
use crate::memory::{MemoryError, read_memory_bytes};
use crate::memory_hook::BytesSwitch;
use crate::memory_resolver::{AddressSource, ParseError};
use super::super::register::ModifierHandler;
#[derive(Clone, Debug)]
pub struct BytesSwitchConfig {
pub name: String,
pub byte_count: usize,
pub patch_bytes: Vec<u8>,
}
pub struct BytesSwitchHandler {
config: BytesSwitchConfig,
address_source: AddressSource,
instance: Option<BytesSwitch>,
last_handle: Option<HANDLE>,
last_pid: Option<u32>,
}
impl BytesSwitchHandler {
fn new(config: BytesSwitchConfig, address_source: AddressSource) -> Self {
Self {
config,
address_source,
instance: None,
last_handle: None,
last_pid: None,
}
}
pub fn new_with_address(
name: impl Into<String>,
address_source: AddressSource,
byte_count: usize,
patch_bytes: Vec<u8>,
) -> Box<dyn ModifierHandler> {
let config = BytesSwitchConfig {
name: name.into(),
byte_count,
patch_bytes,
};
Box::new(Self::new(config, address_source))
}
pub fn new_nop_with_address(
name: impl Into<String>,
address_source: AddressSource,
byte_count: usize,
) -> Box<dyn ModifierHandler> {
Self::new_with_address(name, address_source, byte_count, vec![0x90; byte_count])
}
pub fn new_bytes_switch_pattern(
name: impl Into<String>,
pattern: &str,
byte_count: usize,
patch_bytes: Vec<u8>,
) -> Result<Box<dyn ModifierHandler>, ParseError> {
let addr = AddressSource::from_pattern(pattern)?;
Ok(Self::new_with_address(name, addr, byte_count, patch_bytes))
}
pub fn new_nop_switch_pattern(
name: impl Into<String>,
pattern: &str,
byte_count: usize,
) -> Result<Box<dyn ModifierHandler>, ParseError> {
let addr = AddressSource::from_pattern(pattern)?;
Ok(Self::new_nop_with_address(name, addr, byte_count))
}
pub fn new_bytes_switch_x86(
name: impl Into<String>,
pattern: &str,
byte_count: usize,
patch_bytes: Vec<u8>,
) -> Result<Box<dyn ModifierHandler>, ParseError> {
let addr = AddressSource::from_pattern_x86(pattern)?;
Ok(Self::new_with_address(name, addr, byte_count, patch_bytes))
}
pub fn new_nop_switch_x86(
name: impl Into<String>,
pattern: &str,
byte_count: usize,
) -> Result<Box<dyn ModifierHandler>, ParseError> {
let addr = AddressSource::from_pattern_x86(pattern)?;
Ok(Self::new_nop_with_address(name, addr, byte_count))
}
pub fn new_bytes_switch_x64(
name: impl Into<String>,
pattern: &str,
byte_count: usize,
patch_bytes: Vec<u8>,
) -> Result<Box<dyn ModifierHandler>, ParseError> {
let addr = AddressSource::from_pattern_x64(pattern)?;
Ok(Self::new_with_address(name, addr, byte_count, patch_bytes))
}
pub fn new_nop_switch_x64(
name: impl Into<String>,
pattern: &str,
byte_count: usize,
) -> Result<Box<dyn ModifierHandler>, ParseError> {
let addr = AddressSource::from_pattern_x64(pattern)?;
Ok(Self::new_nop_with_address(name, addr, byte_count))
}
pub fn new_bytes_switch_aob(
name: impl Into<String>,
pattern: &str,
byte_count: usize,
patch_bytes: Vec<u8>,
) -> Result<Box<dyn ModifierHandler>, String> {
let addr = AddressSource::from_aob(pattern)?;
Ok(Self::new_with_address(name, addr, byte_count, patch_bytes))
}
pub fn new_nop_switch_aob(
name: impl Into<String>,
pattern: &str,
byte_count: usize,
) -> Result<Box<dyn ModifierHandler>, String> {
let addr = AddressSource::from_aob(pattern)?;
Ok(Self::new_nop_with_address(name, addr, byte_count))
}
}
impl ModifierHandler for BytesSwitchHandler {
fn name(&self) -> &str { &self.config.name }
fn activate(&mut self, handle: HANDLE, pid: u32) -> Result<(), MemoryError> {
let context_changed = self.last_handle != Some(handle) || self.last_pid != Some(pid);
if self.instance.is_some() && !context_changed {
return Ok(());
}
if self.instance.is_some() {
self.deactivate()?;
}
let target_address = self.address_source.resolve(handle, pid)
.map_err(|e| MemoryError::InvalidAddress(format!("Failed to resolve address: {}", e)))?;
let original_bytes = read_memory_bytes(handle, target_address, self.config.byte_count)?;
let mut switch = BytesSwitch::new(
handle,
target_address,
original_bytes,
self.config.patch_bytes.clone(),
);
switch.enable()?;
self.instance = Some(switch);
self.last_handle = Some(handle);
self.last_pid = Some(pid);
Ok(())
}
fn deactivate(&mut self) -> Result<(), MemoryError> {
if let Some(_switch) = self.instance.take() {
}
self.last_handle = None;
self.last_pid = None;
Ok(())
}
fn is_active(&self) -> bool {
self.instance.is_some()
}
}
unsafe impl Send for BytesSwitchHandler {}