use std::{
error::Error,
ffi::{CStr, CString},
};
use winapi::{
ctypes::c_void,
um::{
errhandlingapi::GetLastError,
handleapi::{CloseHandle, INVALID_HANDLE_VALUE},
memoryapi::{MapViewOfFileEx, UnmapViewOfFile, FILE_MAP_ALL_ACCESS},
winbase::{
CreateFileMappingA, FormatMessageA, LocalFree, FORMAT_MESSAGE_ALLOCATE_BUFFER,
FORMAT_MESSAGE_FROM_SYSTEM, FORMAT_MESSAGE_IGNORE_INSERTS,
},
winnt::PAGE_READWRITE,
},
};
pub unsafe fn open_memory(
name: &str,
size: usize,
base_address: *mut c_void,
) -> Result<(*mut c_void, *mut c_void), Box<dyn Error>> {
let high_size: u32 = ((size as u64 & 0xFFFF_FFFF_0000_0000_u64) >> 32) as u32;
let low_size: u32 = (size as u64 & 0xFFFF_FFFF_u64) as u32;
let name = CString::new(name)?;
let file = CreateFileMappingA(
INVALID_HANDLE_VALUE, std::ptr::null_mut(), PAGE_READWRITE, high_size, low_size, name.as_ptr(),
);
if file.is_null() {
let error = get_last_error_as_string();
return Err(format!("Could not create file mapping object: {}", error).into());
}
let buffer = MapViewOfFileEx(
file, FILE_MAP_ALL_ACCESS, 0,
0,
size,
base_address,
);
if buffer.is_null() {
CloseHandle(file);
let error = get_last_error_as_string();
return Err(format!("Could not map view of file: {:?}", error).into());
}
Ok((file, buffer))
}
pub unsafe fn release_memory(file: *mut c_void, buffer: *mut c_void) {
UnmapViewOfFile(buffer as *mut _);
CloseHandle(file);
}
unsafe fn get_last_error_as_string() -> String {
let error_message_id = GetLastError();
if error_message_id == 0 {
return String::new();
}
let mut message_buffer: usize = 0;
let size = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
std::ptr::null_mut(),
error_message_id,
0,
(&mut message_buffer) as *mut usize as *mut i8,
5000,
std::ptr::null_mut(),
);
if size == 0 {
return String::new();
}
let message = match CStr::from_ptr(message_buffer as *mut i8).to_str() {
Ok(message) => message.to_owned(),
Err(_) => String::new(),
};
LocalFree(message_buffer as *mut _);
message
}