xref: /reactos/sdk/lib/atl/atlfile.h (revision d955b932)
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:
CAtlFileMappingBase()37     CAtlFileMappingBase() noexcept
38         :m_pData(NULL)
39         ,m_nMappingSize(0)
40         ,m_hMapping(NULL)
41         ,m_dwViewDesiredAccess(0)
42     {
43         m_nOffset.QuadPart = 0;
44     }
45 
~CAtlFileMappingBase()46     ~CAtlFileMappingBase() noexcept
47     {
48         Unmap();
49     }
50 
CAtlFileMappingBase(CAtlFileMappingBase & orig)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 
CopyFrom(CAtlFileMappingBase & orig)77     HRESULT CopyFrom(CAtlFileMappingBase& orig) noexcept
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, 0, 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) noexcept
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) noexcept
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) noexcept
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 
Unmap()228     HRESULT Unmap() noexcept
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 
GetData()251     void* GetData() const noexcept
252     {
253         return m_pData;
254     }
255 
GetHandle()256     HANDLE GetHandle() throw ()
257     {
258         return m_hMapping;
259     }
260 
GetMappingSize()261     SIZE_T GetMappingSize() noexcept
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 noexcept
275     {
276         return reinterpret_cast<T*>(GetData());
277     }
278 };
279 
280 
281 }
282