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
use crate::aliases::WinResult;
use crate::co;
use crate::handles::{HFILE, HFILEMAP, HFILEMAPVIEW};
pub enum MappedFileAccess {
Read,
ReadWrite,
}
pub struct MappedFile {
access: MappedFileAccess,
hfile: HFILE,
hmap: HFILEMAP,
hview: HFILEMAPVIEW,
size: usize,
}
impl Drop for MappedFile {
fn drop(&mut self) {
if !self.hview.is_null() { let _ = self.hview.UnmapViewOfFile(); }
if !self.hmap.is_null() { let _ = self.hmap.CloseHandle(); }
if !self.hfile.is_null() { let _ = self.hfile.CloseHandle(); }
}
}
impl MappedFile {
pub fn open(
file_path: &str, access: MappedFileAccess) -> WinResult<MappedFile>
{
let (hfile, _) = HFILE::CreateFile(
file_path,
match access {
MappedFileAccess::Read => co::GENERIC::READ,
MappedFileAccess::ReadWrite => co::GENERIC::READ | co::GENERIC::WRITE,
},
match access {
MappedFileAccess::Read => co::FILE_SHARE::READ,
MappedFileAccess::ReadWrite => co::FILE_SHARE::NoValue,
},
None,
match access {
MappedFileAccess::Read => co::DISPOSITION::OPEN_EXISTING,
MappedFileAccess::ReadWrite => co::DISPOSITION::OPEN_ALWAYS
},
co::FILE_ATTRIBUTE::NORMAL,
None,
)?;
let mut new_self = Self {
access,
hfile,
hmap: HFILEMAP::NULL,
hview: HFILEMAPVIEW::NULL,
size: 0,
};
new_self.map_in_memory()?;
Ok(new_self)
}
fn map_in_memory(&mut self) -> WinResult<()> {
self.hmap = self.hfile.CreateFileMapping(
None,
match self.access {
MappedFileAccess::Read => co::PAGE::READONLY,
MappedFileAccess::ReadWrite => co::PAGE::READWRITE,
},
None,
None,
)?;
self.hview = self.hmap.MapViewOfFile(
match self.access {
MappedFileAccess::Read => co::FILE_MAP::READ,
MappedFileAccess::ReadWrite => co::FILE_MAP::READ | co::FILE_MAP::WRITE,
},
0,
None,
)?;
self.size = self.hfile.GetFileSizeEx()?;
Ok(())
}
pub fn size(&self) -> usize {
self.size
}
pub fn as_slice(&self) -> &[u8] {
self.hview.as_slice(self.size)
}
pub fn as_mut_slice(&mut self) -> &mut [u8] {
self.hview.as_mut_slice(self.size)
}
pub fn resize(&mut self, num_bytes: usize) -> WinResult<()> {
self.hview.UnmapViewOfFile()?;
self.hmap.CloseHandle()?;
self.hfile.SetFilePointerEx(num_bytes as _, co::FILE_STARTING_POINT::BEGIN)?;
self.hfile.SetEndOfFile()?;
self.hfile.SetFilePointerEx(0, co::FILE_STARTING_POINT::BEGIN)?;
self.map_in_memory()?;
Ok(())
}
}