1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
use std::{io, mem, ptr};
use std::ffi::OsStr;
use std::path::Path;
use std::os::windows::ffi::OsStrExt;
use std::os::windows::io::{AsRawHandle, RawHandle};
use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING};
use winapi::um::memoryapi::{CreateFileMappingW, MapViewOfFile, UnmapViewOfFile, VirtualQuery, FILE_MAP_READ, FILE_MAP_COPY};
use winapi::um::handleapi::{CloseHandle, INVALID_HANDLE_VALUE};
use winapi::shared::ntdef::{NULL, HANDLE};
use winapi::shared::minwindef::{LPVOID};
use winapi::um::winnt::{PAGE_READONLY, SEC_IMAGE, GENERIC_READ, FILE_SHARE_READ, FILE_ATTRIBUTE_NORMAL};
pub struct ImageMap {
handle: HANDLE,
bytes: *mut [u8],
}
impl ImageMap {
pub fn open<P: AsRef<Path> + ?Sized>(path: &P) -> io::Result<ImageMap> {
unsafe { Self::_open(path.as_ref()) }
}
unsafe fn _open(path: &Path) -> io::Result<ImageMap> {
let file = {
let path: &OsStr = path.as_ref();
let mut wpath: Vec<u16> = path.encode_wide().collect();
wpath.push(0);
CreateFileW(wpath.as_ptr(), GENERIC_READ, FILE_SHARE_READ, ptr::null_mut(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)
};
if file != INVALID_HANDLE_VALUE {
let map = CreateFileMappingW(file, ptr::null_mut(), PAGE_READONLY | SEC_IMAGE, 0, 0, ptr::null());
CloseHandle(file);
if map != NULL {
let view = MapViewOfFile(map, FILE_MAP_COPY, 0, 0, 0);
if view != ptr::null_mut() {
use crate::image::{IMAGE_DOS_HEADER, IMAGE_NT_HEADERS64};
let dos_header = view as *const IMAGE_DOS_HEADER;
let nt_header = (view as usize + (*dos_header).e_lfanew as usize) as *const IMAGE_NT_HEADERS64;
let size_of = (*nt_header).OptionalHeader.SizeOfImage;
let bytes = ptr::slice_from_raw_parts_mut(view as *mut u8, size_of as usize);
return Ok(ImageMap { handle: map, bytes });
}
let err = io::Error::last_os_error();
CloseHandle(map);
return Err(err);
}
}
Err(io::Error::last_os_error())
}
}
impl AsRawHandle for ImageMap {
fn as_raw_handle(&self) -> RawHandle {
self.handle as RawHandle
}
}
impl AsRef<[u8]> for ImageMap {
fn as_ref(&self) -> &[u8] {
unsafe { &*self.bytes }
}
}
impl Drop for ImageMap {
fn drop(&mut self) {
unsafe {
UnmapViewOfFile((*self.bytes).as_ptr() as LPVOID);
CloseHandle(self.handle);
}
}
}
pub struct FileMap {
handle: HANDLE,
bytes: *mut [u8],
}
impl FileMap {
pub fn open<P: AsRef<Path> + ?Sized>(path: &P) -> io::Result<FileMap> {
unsafe { Self::_open(path.as_ref()) }
}
unsafe fn _open(path: &Path) -> io::Result<FileMap> {
let file = {
let path: &OsStr = path.as_ref();
let mut wpath: Vec<u16> = path.encode_wide().collect();
wpath.push(0);
CreateFileW(wpath.as_ptr(), GENERIC_READ, FILE_SHARE_READ, ptr::null_mut(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)
};
if file == INVALID_HANDLE_VALUE {
return Err(io::Error::last_os_error());
}
let map = CreateFileMappingW(file, ptr::null_mut(), PAGE_READONLY, 0, 0, ptr::null());
CloseHandle(file);
if map == NULL {
return Err(io::Error::last_os_error());
}
let view = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
if view == ptr::null_mut() {
let err = io::Error::last_os_error();
CloseHandle(map);
return Err(err);
}
let mut mem_basic_info = mem::zeroed();
let vq_result = VirtualQuery(view, &mut mem_basic_info, mem::size_of_val(&mem_basic_info));
debug_assert_eq!(vq_result, mem::size_of_val(&mem_basic_info));
let bytes = ptr::slice_from_raw_parts_mut(view as *mut u8, mem_basic_info.RegionSize as usize);
Ok(FileMap { handle: map, bytes })
}
}
impl AsRawHandle for FileMap {
fn as_raw_handle(&self) -> RawHandle {
self.handle as RawHandle
}
}
impl AsRef<[u8]> for FileMap {
fn as_ref(&self) -> &[u8] {
unsafe { &*self.bytes }
}
}
impl Drop for FileMap {
fn drop(&mut self) {
unsafe {
UnmapViewOfFile((*self.bytes).as_ptr() as LPVOID);
CloseHandle(self.handle);
}
}
}