[ATL][ATL_APITEST] Add test + implementation for CAtlFileMapping
[reactos.git] / sdk / lib / atl / atlfile.h
1 /*
2 * PROJECT: ReactOS ATL
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: ATL File implementation
5 * COPYRIGHT: Copyright 2019 Mark Jansen (mark.jansen@reactos.org)
6 */
7
8 #pragma once
9
10 #include <atlbase.h>
11
12 namespace ATL
13 {
14
15 //class CAtlFile: TODO
16 // public CHandle
17 //{
18 //};
19
20
21 //class CAtlTemporaryFile TODO
22 //{
23 //};
24
25
26
27 class CAtlFileMappingBase
28 {
29 private:
30 void* m_pData;
31 SIZE_T m_nMappingSize;
32 HANDLE m_hMapping;
33 ULARGE_INTEGER m_nOffset;
34 DWORD m_dwViewDesiredAccess;
35
36 public:
37 CAtlFileMappingBase() throw()
38 :m_pData(NULL)
39 ,m_nMappingSize(0)
40 ,m_hMapping(NULL)
41 ,m_dwViewDesiredAccess(0)
42 {
43 m_nOffset.QuadPart = 0;
44 }
45
46 ~CAtlFileMappingBase() throw()
47 {
48 Unmap();
49 }
50
51 CAtlFileMappingBase(CAtlFileMappingBase& orig)
52 {
53 HRESULT hr;
54
55 m_pData = NULL;
56 m_nMappingSize = 0;
57 m_hMapping = NULL;
58 m_dwViewDesiredAccess = 0;
59 m_nOffset.QuadPart = 0;
60
61 hr = CopyFrom(orig);
62 if (FAILED(hr))
63 AtlThrow(hr);
64 }
65
66 CAtlFileMappingBase& operator=(CAtlFileMappingBase& orig)
67 {
68 HRESULT hr;
69
70 hr = CopyFrom(orig);
71 if (FAILED(hr))
72 AtlThrow(hr);
73
74 return *this;
75 }
76
77 HRESULT CopyFrom(CAtlFileMappingBase& orig) throw()
78 {
79 HRESULT hr = S_OK;
80
81 if (&orig == this)
82 return S_OK;
83
84 ATLASSERT(m_pData == NULL);
85 ATLASSERT(m_hMapping == NULL);
86 ATLASSERT(orig.m_pData != NULL);
87
88 m_nMappingSize = orig.m_nMappingSize;
89 m_nOffset.QuadPart = orig.m_nOffset.QuadPart;
90 m_dwViewDesiredAccess = orig.m_dwViewDesiredAccess;
91
92 if (::DuplicateHandle(GetCurrentProcess(), orig.m_hMapping, GetCurrentProcess(), &m_hMapping, NULL, TRUE, DUPLICATE_SAME_ACCESS))
93 {
94 m_pData = ::MapViewOfFile(m_hMapping, m_dwViewDesiredAccess, m_nOffset.HighPart, m_nOffset.LowPart, m_nMappingSize);
95 if (!m_pData)
96 {
97 hr = AtlHresultFromLastError();
98 ::CloseHandle(m_hMapping);
99 m_hMapping = NULL;
100 }
101 }
102 else
103 {
104 hr = AtlHresultFromLastError();
105 }
106
107 return hr;
108 }
109
110 HRESULT MapFile(
111 HANDLE hFile,
112 SIZE_T nMappingSize = 0,
113 ULONGLONG nOffset = 0,
114 DWORD dwMappingProtection = PAGE_READONLY,
115 DWORD dwViewDesiredAccess = FILE_MAP_READ) throw()
116 {
117 HRESULT hr = S_OK;
118 ULARGE_INTEGER FileSize;
119
120 ATLASSERT(hFile != INVALID_HANDLE_VALUE);
121 ATLASSERT(m_pData == NULL);
122 ATLASSERT(m_hMapping == NULL);
123
124 FileSize.LowPart = ::GetFileSize(hFile, &FileSize.HighPart);
125 FileSize.QuadPart = nMappingSize > FileSize.QuadPart ? nMappingSize : FileSize.QuadPart;
126
127 m_hMapping = ::CreateFileMapping(hFile, NULL, dwMappingProtection, FileSize.HighPart, FileSize.LowPart, 0);
128 if (m_hMapping)
129 {
130 m_nMappingSize = nMappingSize == 0 ? (SIZE_T)(FileSize.QuadPart - nOffset) : nMappingSize;
131 m_nOffset.QuadPart = nOffset;
132 m_dwViewDesiredAccess = dwViewDesiredAccess;
133
134 m_pData = ::MapViewOfFile(m_hMapping, m_dwViewDesiredAccess, m_nOffset.HighPart, m_nOffset.LowPart, m_nMappingSize);
135 if (!m_pData)
136 {
137 hr = AtlHresultFromLastError();
138 ::CloseHandle(m_hMapping);
139 m_hMapping = NULL;
140 }
141 }
142 else
143 {
144 hr = AtlHresultFromLastError();
145 }
146
147 return hr;
148 }
149
150 HRESULT MapSharedMem(
151 SIZE_T nMappingSize,
152 LPCTSTR szName,
153 BOOL* pbAlreadyExisted = NULL,
154 LPSECURITY_ATTRIBUTES lpsa = NULL,
155 DWORD dwMappingProtection = PAGE_READWRITE,
156 DWORD dwViewDesiredAccess = FILE_MAP_ALL_ACCESS) throw()
157 {
158 HRESULT hr = S_OK;
159 ULARGE_INTEGER Size;
160
161 ATLASSERT(nMappingSize > 0);
162 ATLASSERT(szName != NULL);
163 ATLASSERT(m_pData == NULL);
164 ATLASSERT(m_hMapping == NULL);
165
166 m_nMappingSize = nMappingSize;
167 m_dwViewDesiredAccess = dwViewDesiredAccess;
168 m_nOffset.QuadPart = 0;
169 Size.QuadPart = nMappingSize;
170
171 m_hMapping = ::CreateFileMapping(NULL, lpsa, dwMappingProtection, Size.HighPart, Size.LowPart, szName);
172 if (m_hMapping != NULL)
173 {
174 if (pbAlreadyExisted)
175 *pbAlreadyExisted = GetLastError() == ERROR_ALREADY_EXISTS;
176
177 m_pData = ::MapViewOfFile(m_hMapping, dwViewDesiredAccess, m_nOffset.HighPart, m_nOffset.LowPart, m_nMappingSize);
178 if (!m_pData)
179 {
180 hr = AtlHresultFromLastError();
181 ::CloseHandle(m_hMapping);
182 m_hMapping = NULL;
183 }
184 }
185 else
186 {
187 hr = AtlHresultFromLastError();
188 }
189
190 return hr;
191 }
192
193 HRESULT OpenMapping(
194 LPCTSTR szName,
195 SIZE_T nMappingSize,
196 ULONGLONG nOffset = 0,
197 DWORD dwViewDesiredAccess = FILE_MAP_ALL_ACCESS) throw()
198 {
199 HRESULT hr = S_OK;
200
201 ATLASSERT(szName != NULL);
202 ATLASSERT(m_pData == NULL);
203 ATLASSERT(m_hMapping == NULL);
204
205 m_nMappingSize = nMappingSize;
206 m_dwViewDesiredAccess = dwViewDesiredAccess;
207 m_nOffset.QuadPart = nOffset;
208
209 m_hMapping = ::OpenFileMapping(m_dwViewDesiredAccess, FALSE, szName);
210 if (m_hMapping)
211 {
212 m_pData = ::MapViewOfFile(m_hMapping, dwViewDesiredAccess, m_nOffset.HighPart, m_nOffset.LowPart, m_nMappingSize);
213 if (!m_pData)
214 {
215 hr = AtlHresultFromLastError();
216 ::CloseHandle(m_hMapping);
217 m_hMapping = NULL;
218 }
219 }
220 else
221 {
222 hr = AtlHresultFromLastError();
223 }
224
225 return hr;
226 }
227
228 HRESULT Unmap() throw()
229 {
230 HRESULT hr = S_OK;
231
232 if (m_pData)
233 {
234 if (!::UnmapViewOfFile(m_pData))
235 hr = AtlHresultFromLastError();
236
237 m_pData = NULL;
238 }
239 if (m_hMapping)
240 {
241 // If we already had an error, do not overwrite it
242 if (!::CloseHandle(m_hMapping) && SUCCEEDED(hr))
243 hr = AtlHresultFromLastError();
244
245 m_hMapping = NULL;
246 }
247
248 return hr;
249 }
250
251 void* GetData() const throw()
252 {
253 return m_pData;
254 }
255
256 HANDLE GetHandle() throw ()
257 {
258 return m_hMapping;
259 }
260
261 SIZE_T GetMappingSize() throw()
262 {
263 return m_nMappingSize;
264 }
265
266 };
267
268
269 template <typename T = char>
270 class CAtlFileMapping:
271 public CAtlFileMappingBase
272 {
273 public:
274 operator T*() const throw()
275 {
276 return reinterpret_cast<T*>(GetData());
277 }
278 };
279
280
281 }