#![allow(clippy::upper_case_acronyms)]
use super::*;
use std::ffi::c_void;
use std::os::windows::io::AsRawHandle;
use std::os::windows::io::RawHandle;
use std::ptr;
const PAGE_READWRITE: u32 = 0x4;
const STANDARD_RIGHTS_REQUIRED: u32 = 0x000f0000;
const SECTION_QUERY: u32 = 0x0001;
const SECTION_MAP_WRITE: u32 = 0x0002;
const SECTION_MAP_READ: u32 = 0x0004;
const SECTION_MAP_EXECUTE: u32 = 0x0008;
const SECTION_EXTEND_SIZE: u32 = 0x0010;
const SECTION_ALL_ACCESS: u32 = STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_WRITE
| SECTION_MAP_READ
| SECTION_MAP_EXECUTE
| SECTION_EXTEND_SIZE;
const FILE_MAP_ALL_ACCESS: u32 = SECTION_ALL_ACCESS;
#[repr(C)]
struct SECURITY_ATTRIBUTES {
length: u32,
descriptor: *mut c_void,
inherit: u32,
}
extern "system" {
fn CreateFileMappingW(
file: RawHandle,
attributes: *mut SECURITY_ATTRIBUTES,
protect: u32,
max_size_high: u32,
max_size_low: u32,
name: *const u16,
) -> RawHandle;
fn MapViewOfFileEx(
file_mapping: RawHandle,
desired_access: u32,
offset_high: u32,
offset_low: u32,
bytes_to_map: usize,
base_address: *mut u8,
) -> *mut u8;
fn FlushFileBuffers(file: RawHandle) -> u32;
fn FlushViewOfFile(base_address: *const u8, number_of_bytes_to_flush: usize) -> u32;
fn UnmapViewOfFile(base_address: *const u8) -> u32;
fn CloseHandle(handle: RawHandle) -> u32;
}
struct AutoHandle {
inner: RawHandle,
}
impl Drop for AutoHandle {
fn drop(&mut self) {
unsafe {
CloseHandle(self.inner);
}
}
}
pub(super) struct MmapInner {
mmap: *mut u8,
len: usize,
handle: RawHandle,
}
impl MmapInner {
pub(super) fn create_mapping(file: &File, len: u64) -> Result<Self> {
assert!(len > 0);
let mmap = unsafe { Self::map_file(file, len)? };
Ok(Self {
mmap,
len: len.try_into().unwrap(),
handle: file.as_raw_handle(),
})
}
pub(super) fn can_resize(&self, _new_len: u64) -> bool {
false
}
pub(super) fn base_addr(&self) -> *mut u8 {
self.mmap
}
unsafe fn map_file(file: &File, len: u64) -> Result<*mut u8> {
let handle = file.as_raw_handle();
#[allow(clippy::cast_possible_truncation)]
let lo = (len & u32::MAX as u64) as u32;
let hi = (len >> 32) as u32;
let ptr = {
let mapping = AutoHandle {
inner: CreateFileMappingW(
handle,
ptr::null_mut(),
PAGE_READWRITE,
hi,
lo,
ptr::null(),
),
};
if mapping.inner.is_null() {
return Err(Error::Io(io::Error::last_os_error()));
}
MapViewOfFileEx(
mapping.inner,
FILE_MAP_ALL_ACCESS,
0,
0,
len.try_into().unwrap(),
ptr::null_mut(),
)
};
Ok(ptr)
}
pub(super) unsafe fn resize(&self, _len: u64) -> Result<()> {
unimplemented!()
}
pub(super) fn flush(&self) -> Result {
self.eventual_flush()?;
#[cfg(not(fuzzing))]
{
if unsafe { FlushFileBuffers(self.handle) } == 0 {
return Err(Error::Io(io::Error::last_os_error()));
}
}
Ok(())
}
#[inline]
pub(super) fn eventual_flush(&self) -> Result {
#[cfg(not(fuzzing))]
{
let result = unsafe { FlushViewOfFile(self.mmap, self.len) };
if result != 0 {
Ok(())
} else {
Err(Error::Io(io::Error::last_os_error()))
}
}
#[cfg(fuzzing)]
{
Ok(())
}
}
}
impl Drop for MmapInner {
fn drop(&mut self) {
unsafe {
UnmapViewOfFile(self.mmap);
}
}
}