use core::{fmt, ptr, mem};
use crate::sys::*;
use crate::utils::{self, Result};
pub struct Info(pub MEMORY_BASIC_INFORMATION);
impl Info {
#[inline]
pub fn base_addr(&self) -> usize {
self.0.BaseAddress as usize
}
#[inline]
pub fn alloc_base(&self) -> usize {
self.0.AllocationBase as usize
}
#[inline]
pub fn size(&self) -> SIZE_T {
self.0.RegionSize
}
#[inline]
pub fn is_commit(&self) -> bool {
self.0.State == MEM_COMMIT
}
#[inline]
pub fn is_free(&self) -> bool {
self.0.State == MEM_FREE
}
#[inline]
pub fn is_reserved(&self) -> bool {
self.0.State == MEM_RESERVE
}
}
impl fmt::Debug for Info {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Info {{ BaseAddress={:p}, AllocationBase={:p}, AllocationProtect={}, RegionSize={}, State={}, Protect={}, Type={} }}",
self.0.BaseAddress, self.0.AllocationBase, self.0.AllocationProtect, self.0.RegionSize, self.0.State, self.0.Protect, self.0.Type)
}
}
pub struct Virtual {
handle: HANDLE,
addr: *const u8
}
impl Virtual {
pub fn new(handle: HANDLE) -> Self {
Virtual {
handle,
addr: ptr::null()
}
}
}
impl Iterator for Virtual {
type Item = Info;
fn next(&mut self) -> Option<Self::Item> {
virtual_query_ex(self.handle, self.addr as *const c_void).ok().map(|info| {
self.addr = unsafe { self.addr.add(info.size()) };
info
})
}
}
pub fn virtual_query_ex(handle: HANDLE, base: *const c_void) -> Result<Info> {
let mut info: MEMORY_BASIC_INFORMATION = unsafe { mem::zeroed() };
if unsafe { VirtualQueryEx(handle, base, &mut info as *mut _, mem::size_of_val(&info) as SIZE_T) } != 0 {
Ok(Info(info))
}
else {
Err(utils::get_last_error())
}
}