use crate::memory::MemoryError;
use crate::memory_hook::Architecture;
use windows::Win32::Foundation::HANDLE;
use windows::Win32::System::Memory::{
VirtualAllocEx, MEM_COMMIT, MEM_RESERVE, PAGE_EXECUTE_READWRITE,
};
pub(super) fn allocate_detour_memory(
handle: HANDLE,
target_address: usize,
size: usize,
architecture: Architecture,
) -> Result<usize, MemoryError> {
match architecture {
Architecture::X86 => {
let allocated = unsafe {
VirtualAllocEx(
handle,
None,
size,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE,
)
};
if allocated.is_null() {
return Err(MemoryError::WriteFailed(
"Failed to allocate detour memory (x86)".to_string(),
));
}
Ok(allocated as usize)
}
Architecture::X64 => {
let hint_distance = 0x1000_0000; let hint_address = target_address.wrapping_sub(hint_distance);
let allocated = unsafe {
VirtualAllocEx(
handle,
Some(hint_address as *mut _),
size,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE,
)
};
if !allocated.is_null() {
return Ok(allocated as usize);
}
let allocated = unsafe {
VirtualAllocEx(
handle,
None,
size,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE,
)
};
if allocated.is_null() {
return Err(MemoryError::WriteFailed(
"Failed to allocate detour memory (x64)".to_string(),
));
}
Ok(allocated as usize)
}
}
}
pub(super) fn allocate_trampoline_nearby(
handle: HANDLE,
target_address: usize,
size: usize,
architecture: Architecture,
) -> Result<usize, MemoryError> {
if architecture == Architecture::X86 {
return allocate_memory_direct(handle, size);
}
allocate_trampoline_x64(handle, target_address, size)
}
fn allocate_memory_direct(handle: HANDLE, size: usize) -> Result<usize, MemoryError> {
let allocated = unsafe {
VirtualAllocEx(
handle,
None, size,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE,
)
};
if allocated.is_null() {
return Err(MemoryError::WriteFailed(
"Failed to allocate trampoline memory".to_string(),
));
}
Ok(allocated as usize)
}
fn allocate_trampoline_x64(
handle: HANDLE,
target_address: usize,
size: usize,
) -> Result<usize, MemoryError> {
let hint_distance = 0x1000_0000; let hint_address = target_address.wrapping_sub(hint_distance);
let allocated = unsafe {
VirtualAllocEx(
handle,
Some(hint_address as *mut _),
size,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE,
)
};
if !allocated.is_null() {
return Ok(allocated as usize);
}
let allocated = unsafe {
VirtualAllocEx(
handle,
None,
size,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE,
)
};
if allocated.is_null() {
return Err(MemoryError::WriteFailed(
"Failed to allocate trampoline memory".to_string(),
));
}
Ok(allocated as usize)
}