memory_rs/internal/
macros.rs

1/// Macro that creates the MainDLL function.
2/// This function has a special signature that needed by WinAPI to
3/// create a DLL.
4#[macro_export]
5macro_rules! main_dll {
6    ($func:expr) => {
7        #[no_mangle]
8        #[allow(non_snake_case)]
9        pub extern "system" fn DllMain(
10            lib: windows_sys::Win32::Foundation::HINSTANCE,
11            reason: u32,
12            _: usize,
13        ) -> u32 {
14            unsafe {
15                match reason {
16                    windows_sys::Win32::System::SystemServices::DLL_PROCESS_ATTACH => {
17                        windows_sys::Win32::System::Threading::CreateThread(
18                            std::ptr::null_mut(),
19                            0,
20                            Some($func),
21                            lib as *const std::ffi::c_void,
22                            0,
23                            std::ptr::null_mut(),
24                        );
25                    }
26                    _ => (),
27                };
28            }
29
30            return true as u32;
31        }
32    };
33}
34
35/// Macro created by t0mstone
36/// You can check the original source at
37/// https://github.com/T0mstone/tlibs/blob/master/some_macros/src/lib.rs#L23-L29
38#[macro_export]
39macro_rules! count_args {
40    (@one $($t:tt)*) => { 1 };
41    ($(($($x:tt)*)),*$(,)?) => {
42        0 $(+ $crate::count_args!(@one $($x)*))*
43    };
44}
45
46/// Map winapi error to lib error.
47#[macro_export]
48macro_rules! try_winapi {
49    ($call:expr) => {{
50        let res = $call;
51        if res == 0 {
52            let msg = format!(
53                "{} failed with error code {}",
54                std::stringify!($call),
55                std::io::Error::last_os_error()
56            );
57            return Err($crate::error::Error::new($crate::error::ErrorType::WinAPI, msg).into());
58        }
59    }};
60}
61
62/// Wrap a function to a lambda which returns a Result<_, Error>
63/// depending of the condition.
64/// You should use it like
65/// wrap_winapi!(MyFunction(), MyCondition) where
66/// MyCondition **must** start with an x and the comparison.
67/// For example
68/// ```
69/// # use memory_rs::wrap_winapi;
70/// // This should fail since we are saying that
71/// // when the return value equals to 0 it's an error.
72/// assert!(wrap_winapi!((|| 0)(), x == 0).is_err());
73/// ```
74#[macro_export]
75macro_rules! wrap_winapi {
76    ($call:expr, x $($tt:tt)*) => {
77        (|| -> Result<_, $crate::error::Error> {
78            let res = $call;
79            let x = res as usize;
80            if x $($tt)* {
81                let msg = format!(
82                    "{} failed with error `{}`",
83                    std::stringify!($call),
84                    std::io::Error::last_os_error()
85                );
86                return Err($crate::error::Error::new(
87                    $crate::error::ErrorType::WinAPI,
88                    msg,
89                )
90                .into());
91            }
92            Ok(res)
93        })()
94    };
95}
96
97/// Scoped no mangle to avoid repetition
98#[macro_export]
99macro_rules! scoped_no_mangle {
100    ($($name:ident: $v:ty = $val:expr;)*) => {
101        $(#[no_mangle] pub static mut $name: $v = $val;)*
102    }
103}
104
105/// Returns a MemoryPattern struct
106#[macro_export]
107macro_rules! generate_aob_pattern {
108    [$($val:tt),* ] => {
109        $crate::internal::memory::MemoryPattern::new(
110            $crate::count_args!($(($val)),*),
111        |slice: &[u8]| -> bool {
112            matches!(slice, [$($val),*])
113        }
114        )
115    }
116}