windows_win/raw/
memory.rs

1//! Provides functions to interact with memory.
2
3use core::{fmt, ptr, mem};
4
5use crate::sys::*;
6use crate::utils::{self, Result};
7
8///Convenient wrapper over [MEMORY_BASIC_INFORMATION](https://msdn.microsoft.com/en-us/library/windows/desktop/aa366775(v=vs.85).aspx)
9pub struct Info(pub MEMORY_BASIC_INFORMATION);
10
11impl Info {
12    #[inline]
13    ///Returns region's base address
14    ///
15    ///Memory can be read from this address up to `<base> + <region size>`
16    ///
17    ///You can get this pointer by accessing inner structure `self.0.BaseAddress`
18    pub fn base_addr(&self) -> usize {
19        self.0.BaseAddress as usize
20    }
21
22    #[inline]
23    ///Returns Allocation base.
24    ///
25    ///You can get this pointer by accessing inner structure `self.0.AllocationBase`
26    pub fn alloc_base(&self) -> usize {
27        self.0.AllocationBase as usize
28    }
29
30    #[inline]
31    ///Returns memory size.
32    pub fn size(&self) -> SIZE_T {
33        self.0.RegionSize
34    }
35
36    #[inline]
37    ///Returns whether memory is committed or not.
38    ///
39    ///Basically it is in use currently
40    pub fn is_commit(&self) -> bool {
41        self.0.State == MEM_COMMIT
42    }
43
44    #[inline]
45    ///Returns whether memory is free or not.
46    pub fn is_free(&self) -> bool {
47        self.0.State == MEM_FREE
48    }
49
50    #[inline]
51    ///Returns whether memory is reserved or not.
52    ///
53    ///This space is not backed by actual physical storage.
54    pub fn is_reserved(&self) -> bool {
55        self.0.State == MEM_RESERVE
56    }
57}
58
59impl fmt::Debug for Info {
60    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61        write!(f, "Info {{ BaseAddress={:p}, AllocationBase={:p}, AllocationProtect={}, RegionSize={}, State={}, Protect={}, Type={} }}",
62                   self.0.BaseAddress, self.0.AllocationBase, self.0.AllocationProtect, self.0.RegionSize, self.0.State, self.0.Protect, self.0.Type)
63    }
64}
65
66///Iterator over memory regions
67///
68///Returns memory addresses
69pub struct Virtual {
70    handle: HANDLE,
71    addr: *const u8
72}
73
74impl Virtual {
75    ///Creates new instance to retrieve memory regions of provided process.
76    ///
77    ///It is assumed that handle is valid, if it is not then nothing can be retrieved.
78    pub fn new(handle: HANDLE) -> Self {
79        Virtual {
80            handle,
81            addr: ptr::null()
82        }
83    }
84}
85
86impl Iterator for Virtual {
87    type Item = Info;
88
89    fn next(&mut self) -> Option<Self::Item> {
90        virtual_query_ex(self.handle, self.addr as *const c_void).ok().map(|info| {
91            self.addr = unsafe { self.addr.add(info.size()) };
92            info
93        })
94    }
95}
96
97///Retrieves information about virtual memory of specified process.
98///
99///Wrapper over `VirtualQueryEx`
100///
101///In case no information is available i.e. `VirtualQueryEx` returns 0
102///function returns None.
103///
104///# Note:
105///
106///When using this function on process of different bitness it might not work correctly.
107pub fn virtual_query_ex(handle: HANDLE, base: *const c_void) -> Result<Info> {
108    let mut info: MEMORY_BASIC_INFORMATION = unsafe { mem::zeroed() };
109
110    if unsafe { VirtualQueryEx(handle, base, &mut info as *mut _, mem::size_of_val(&info) as SIZE_T) } != 0 {
111        Ok(Info(info))
112    }
113    else {
114        Err(utils::get_last_error())
115    }
116}