use libmem_sys::{lm_process_t, LM_ADDRESS_BAD, LM_TRUE};
use crate::{Address, Process, Prot};
use std::mem::{self, MaybeUninit};
pub unsafe fn read_memory<T>(source: Address) -> T {
let size = std::mem::size_of::<T>();
let mut value: MaybeUninit<T> = MaybeUninit::uninit();
libmem_sys::LM_ReadMemory(source, value.as_mut_ptr() as *mut u8, size);
value.assume_init()
}
pub fn read_memory_ex<T>(process: &Process, source: Address) -> Option<T> {
let raw_process: lm_process_t = process.to_owned().into();
let size = mem::size_of::<T>();
let mut value: MaybeUninit<T> = MaybeUninit::uninit();
let rdsize = unsafe {
libmem_sys::LM_ReadMemoryEx(
&raw_process as *const lm_process_t,
source,
value.as_mut_ptr() as *mut u8,
size,
)
};
(rdsize == size).then_some(unsafe { value.assume_init() })
}
#[inline(always)]
pub unsafe fn read_memory_buf(source: Address, buffer: &mut [u8]) {
libmem_sys::LM_ReadMemory(source, buffer.as_mut_ptr(), buffer.len());
}
pub fn read_memory_buf_ex(process: &Process, source: Address, buffer: &mut [u8]) -> Option<usize> {
let raw_process: lm_process_t = process.to_owned().into();
let result = unsafe {
libmem_sys::LM_ReadMemoryEx(
&raw_process as *const lm_process_t,
source,
buffer.as_mut_ptr(),
buffer.len(),
)
};
(result == buffer.len()).then_some(result)
}
#[inline(always)]
pub unsafe fn write_memory<T: ?Sized>(dest: Address, value: &T) {
libmem_sys::LM_WriteMemory(
dest,
value as *const T as *const u8,
mem::size_of_val(value),
);
}
pub fn write_memory_ex<T: ?Sized>(process: &Process, dest: Address, value: &T) -> Option<()> {
let raw_process: lm_process_t = process.to_owned().into();
let size = mem::size_of_val(value);
let result = unsafe {
libmem_sys::LM_WriteMemoryEx(
&raw_process as *const lm_process_t,
dest,
value as *const T as *const u8,
size,
)
};
(result == size).then_some(())
}
#[inline(always)]
pub unsafe fn write_memory_buf(dest: Address, buffer: &[u8]) {
libmem_sys::LM_WriteMemory(dest, buffer.as_ptr(), buffer.len());
}
pub fn write_memory_buf_ex(process: &Process, dest: Address, buffer: &[u8]) -> Option<usize> {
let raw_process: lm_process_t = process.to_owned().into();
let result = unsafe {
libmem_sys::LM_WriteMemoryEx(
&raw_process as *const lm_process_t,
dest,
buffer.as_ptr(),
buffer.len(),
)
};
(result == buffer.len()).then_some(result)
}
#[inline(always)]
pub unsafe fn set_memory(dest: Address, byte: u8, size: usize) {
libmem_sys::LM_SetMemory(dest, byte, size);
}
pub fn set_memory_ex(process: &Process, dest: Address, byte: u8, size: usize) -> Option<()> {
let raw_process: lm_process_t = process.to_owned().into();
let result = unsafe {
libmem_sys::LM_SetMemoryEx(&raw_process as *const lm_process_t, dest, byte, size)
};
(result == size).then_some(())
}
pub unsafe fn prot_memory(address: Address, size: usize, prot: Prot) -> Option<Prot> {
let mut oldprot: MaybeUninit<u32> = MaybeUninit::uninit();
let result = libmem_sys::LM_ProtMemory(address, size, prot.bits(), oldprot.as_mut_ptr());
(result == LM_TRUE).then_some(unsafe { oldprot.assume_init() }.into())
}
pub fn prot_memory_ex(
process: &Process,
address: Address,
size: usize,
prot: Prot,
) -> Option<Prot> {
let raw_process: lm_process_t = process.to_owned().into();
let mut oldprot: MaybeUninit<u32> = MaybeUninit::uninit();
let result = unsafe {
libmem_sys::LM_ProtMemoryEx(
&raw_process as *const lm_process_t,
address,
size,
prot.bits(),
oldprot.as_mut_ptr(),
)
};
(result == LM_TRUE).then_some(unsafe { oldprot.assume_init() }.into())
}
pub fn alloc_memory(size: usize, prot: Prot) -> Option<Address> {
let alloc = unsafe { libmem_sys::LM_AllocMemory(size, prot.bits()) };
(alloc != LM_ADDRESS_BAD).then_some(alloc)
}
pub fn alloc_memory_ex(process: &Process, size: usize, prot: Prot) -> Option<Address> {
let raw_process: lm_process_t = process.to_owned().into();
let alloc = unsafe {
libmem_sys::LM_AllocMemoryEx(&raw_process as *const lm_process_t, size, prot.bits())
};
(alloc != LM_ADDRESS_BAD).then_some(alloc)
}
pub unsafe fn free_memory(alloc: Address, size: usize) -> Option<()> {
let result = libmem_sys::LM_FreeMemory(alloc, size);
(result == LM_TRUE).then_some(())
}
pub fn free_memory_ex(process: &Process, alloc: Address, size: usize) -> Option<()> {
let raw_process: lm_process_t = process.to_owned().into();
let result =
unsafe { libmem_sys::LM_FreeMemoryEx(&raw_process as *const lm_process_t, alloc, size) };
(result == LM_TRUE).then_some(())
}
#[inline(always)]
pub unsafe fn deep_pointer<T>(base: Address, offsets: &[Address]) -> *mut T {
libmem_sys::LM_DeepPointer(base, offsets.as_ptr(), offsets.len()) as *mut T
}
pub fn deep_pointer_ex(process: &Process, base: Address, offsets: &[Address]) -> Option<Address> {
let raw_process: lm_process_t = process.to_owned().into();
let result = unsafe {
libmem_sys::LM_DeepPointerEx(
&raw_process as *const lm_process_t,
base,
offsets.as_ptr(),
offsets.len(),
)
};
(result != LM_ADDRESS_BAD).then_some(result)
}