commonlibsse_ng\rex/
win32.rs

1use std::path::PathBuf;
2
3/// # Errors
4/// Returns an error if the known dir could not be obtained
5pub fn known_folder(folder_id: windows::core::GUID) -> windows::core::Result<PathBuf> {
6    use windows::Win32::UI::Shell::KNOWN_FOLDER_FLAG;
7    unsafe {
8        let path = windows::Win32::UI::Shell::SHGetKnownFolderPath(
9            &folder_id,
10            KNOWN_FOLDER_FLAG(0),
11            None,
12        )?;
13        Ok(PathBuf::from(path.to_hstring().to_os_string()))
14    }
15}
16
17/// Get the document dir.
18/// # Errors
19/// Returns an error if the document dir could not be obtained
20#[inline]
21pub fn document_dir() -> windows::core::Result<PathBuf> {
22    known_folder(windows::Win32::UI::Shell::FOLDERID_Documents)
23}
24
25/// Show message(For critical error)
26pub fn message_box(title: &str, message: &str) {
27    use windows::Win32::UI::WindowsAndMessaging::{MB_OK, MessageBoxW};
28    use windows::core::HSTRING;
29
30    let title = HSTRING::from(title.to_string());
31    let message = HSTRING::from(message.to_string());
32    let _result = unsafe { MessageBoxW(None, &message, &title, MB_OK) };
33}
34
35/// Check memory page access permissions
36pub fn is_valid_range(ptr: *const u8, len: usize) -> bool {
37    use windows::Win32::System::Memory::{MEMORY_BASIC_INFORMATION, PAGE_NOACCESS, VirtualQuery};
38
39    unsafe {
40        let mut mbi = MEMORY_BASIC_INFORMATION::default();
41        let mut check_ptr = ptr;
42
43        while (check_ptr as usize) < (ptr as usize + len) {
44            let is_invalid = VirtualQuery(
45                Some(check_ptr.cast()),
46                &mut mbi,
47                std::mem::size_of::<MEMORY_BASIC_INFORMATION>(),
48            ) == 0;
49
50            if is_invalid {
51                return false;
52            }
53
54            if mbi.Protect == PAGE_NOACCESS {
55                return false;
56            }
57
58            check_ptr = check_ptr.add(mbi.RegionSize);
59        }
60        true
61    }
62}
63
64/// Is this an accessible struct?
65///
66/// Returns `false` if
67/// - The address pointed to by `T` is null
68/// - When the address pointed to by `T` is not located at a memory address that is a multiple of `T` (unaligned)
69/// - There is no permission to access an address of size `T`.
70pub fn is_accessible_struct<T>(target: *const T) -> bool {
71    if target.is_null() || !target.is_aligned() {
72        return false;
73    }
74
75    is_valid_range(target.cast(), core::mem::size_of::<T>())
76}
77
78/// Gets the module size.
79///
80/// # Errors
81/// Returns an error when module information cannot be obtained.
82pub fn get_module_size(handle: windows::Win32::Foundation::HMODULE) -> windows::core::Result<u32> {
83    use windows::Win32::System::ProcessStatus::GetModuleInformation;
84    use windows::Win32::System::ProcessStatus::MODULEINFO;
85    use windows::Win32::System::Threading::GetCurrentProcess;
86
87    const MODULEINFO_SIZE: u32 = core::mem::size_of::<MODULEINFO>() as u32;
88
89    let mut module_info = MODULEINFO::default();
90    unsafe {
91        GetModuleInformation(GetCurrentProcess(), handle, &mut module_info, MODULEINFO_SIZE)?;
92    }
93
94    Ok(module_info.SizeOfImage)
95}
96
97#[cfg(test)]
98mod tests {
99    use super::*;
100
101    #[test]
102    fn test_messaging_interface() {
103        if let Ok(dirs) = document_dir() {
104            println!("{}", dirs.display());
105        };
106    }
107
108    #[test]
109    fn test_is_valid_range() {
110        let valid_data = [42_u8; 16];
111        let valid_ptr = valid_data.as_ptr();
112        assert!(is_valid_range(valid_ptr, 16));
113
114        let invalid_ptr: *const u8 = core::ptr::null();
115        assert!(!is_valid_range(invalid_ptr, 16));
116    }
117}