#[cfg(feature = "memory")]
use win_auto_utils::memory::read_memory_bytes;
#[cfg(all(feature = "memory", feature = "handle"))]
use win_auto_utils::handle::open_process_handle;
#[cfg(feature = "snapshot")]
use win_auto_utils::snapshot::get_process_pid;
#[cfg(all(feature = "memory", feature = "handle"))]
fn main() {
println!("🔧 Memory Operations Example\n");
let pid = if cfg!(feature = "snapshot") {
#[cfg(feature = "snapshot")]
{
println!("📋 Looking for notepad.exe...");
match get_process_pid("notepad.exe") {
Some(pid) => {
println!("✅ Found notepad.exe with PID: {}", pid);
pid
}
None => {
eprintln!("❌ notepad.exe not found!");
eprintln!("💡 Please start notepad.exe and try again");
return;
}
}
}
#[cfg(not(feature = "snapshot"))]
{
unreachable!()
}
} else {
println!("⚠️ Using default PID 12345 (replace with actual PID)");
12345
};
println!("\n🔓 Opening process with memory access rights via handle module...");
use windows::Win32::System::Threading::{PROCESS_VM_READ, PROCESS_VM_WRITE, PROCESS_VM_OPERATION};
let desired_access = PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION;
let handle = match open_process_handle(pid, desired_access) {
Some(h) => {
println!("✅ Successfully opened process");
h
}
None => {
eprintln!("❌ Failed to open process");
eprintln!("💡 Try running as Administrator");
return;
}
};
defer_close_handle(handle);
println!("\n📖 Reading bytes from memory...");
let example_address = 0x7FF600000000usize;
match read_memory_bytes(handle, example_address, 16) {
Ok(bytes) => {
println!("✅ Read {} bytes from 0x{:X}", bytes.len(), example_address);
println!(" Data: {:02X?}", bytes);
}
Err(e) => {
println!("⚠️ Read failed (expected for invalid address): {}", e);
println!("💡 In real usage, use valid addresses from process memory");
}
}
println!("\n📊 Type-specific operations:");
println!(" Available functions:");
println!(" - read_memory_i8/i16/i32/i64");
println!(" - read_memory_u8/u16/u32/u64");
println!(" - read_memory_f32/f64");
println!(" - write_memory_i8/i16/i32/i64");
println!(" - write_memory_u8/u16/u32/u64");
println!(" - write_memory_f32/f64");
println!(" - read_memory_bytes / write_memory_bytes (for byte arrays)");
println!(" - read_memory_t / write_memory_t (generic for any Copy type)");
println!("\n🎯 Generic API example:");
println!(" use win_auto_utils::memory::{{read_memory_t, write_memory_t}};");
println!(" ");
println!(" // Read any Copy type");
println!(" let value: i32 = read_memory_t(handle, address)?;");
println!(" ");
println!(" // Write any Copy type");
println!(" write_memory_t(handle, address, 999i32)?;");
println!("\n✨ Memory operations module ready for use!");
println!("\n📝 Common use cases:");
println!(" - Game hacking: Read/write player stats, positions, etc.");
println!(" - Process debugging: Inspect memory contents");
println!(" - Memory patching: Modify code or data at runtime");
println!(" - Data extraction: Read structured data from processes");
}
#[cfg(not(all(feature = "memory", feature = "handle")))]
fn main() {
eprintln!("❌ This example requires both 'memory' and 'handle' features");
eprintln!("💡 Run with: cargo run --example memory_operations --features \"memory handle\"");
}
#[cfg(all(feature = "memory", feature = "handle"))]
fn defer_close_handle(handle: windows::Win32::Foundation::HANDLE) {
struct HandleGuard(windows::Win32::Foundation::HANDLE);
impl Drop for HandleGuard {
fn drop(&mut self) {
unsafe {
let _ = windows::Win32::Foundation::CloseHandle(self.0);
}
}
}
let _guard = HandleGuard(handle);
}