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