diff options
| author | Stefan Boberg <[email protected]> | 2023-05-15 17:58:46 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-05-15 17:58:46 +0200 |
| commit | 121d3fb3d9835ec78a1de7f268e79bf79cbf5865 (patch) | |
| tree | 2f9c9f5c6a1d3ed41a9f3009104002bc5dd94bb8 /src/zencore/include | |
| parent | all threads should be named (#304) (diff) | |
| download | zen-121d3fb3d9835ec78a1de7f268e79bf79cbf5865.tar.xz zen-121d3fb3d9835ec78a1de7f268e79bf79cbf5865.zip | |
Remove ATL header usage (#306)
ATL has been used here and there as a convenience. Given that this is a legacy component and not always something which gets installed along with the compiler we hereby remove the dependency altogether in favour of our own simple wrappers
Diffstat (limited to 'src/zencore/include')
| -rw-r--r-- | src/zencore/include/zencore/except.h | 1 | ||||
| -rw-r--r-- | src/zencore/include/zencore/windows.h | 417 |
2 files changed, 404 insertions, 14 deletions
diff --git a/src/zencore/include/zencore/except.h b/src/zencore/include/zencore/except.h index d3269f33a..114f98d77 100644 --- a/src/zencore/include/zencore/except.h +++ b/src/zencore/include/zencore/except.h @@ -3,6 +3,7 @@ #pragma once #include <zencore/string.h> +#include <zencore/zencore.h> #if ZEN_PLATFORM_WINDOWS # include <zencore/windows.h> #else diff --git a/src/zencore/include/zencore/windows.h b/src/zencore/include/zencore/windows.h index 91828f0ec..333188cb3 100644 --- a/src/zencore/include/zencore/windows.h +++ b/src/zencore/include/zencore/windows.h @@ -4,22 +4,411 @@ #include <zencore/zencore.h> +#if ZEN_PLATFORM_WINDOWS + ZEN_THIRD_PARTY_INCLUDES_START struct IUnknown; // Workaround for "combaseapi.h(229): error C2187: syntax error: 'identifier' was unexpected here" when using /permissive- -#ifndef NOMINMAX -# define NOMINMAX // We don't want your min/max macros -#endif -#ifndef NOGDI -# define NOGDI // We don't want your GetObject define -#endif -#ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -#endif -#ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0A00 -#endif -#include <windows.h> -#undef GetObject +# ifndef NOMINMAX +# define NOMINMAX // We don't want your min/max macros +# endif +# ifndef NOGDI +# define NOGDI // We don't want your GetObject define +# endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0A00 +# endif +# include <windows.h> +# undef GetObject ZEN_THIRD_PARTY_INCLUDES_END + +////////////////////////////////////////////////////////////////////////// + +namespace zen::windows { + +class Handle +{ +public: + Handle() noexcept = default; + inline Handle(Handle& h) noexcept { Attach(h.Detach()); } + explicit Handle(HANDLE h) noexcept : m_Handle(h) {} + inline ~Handle() noexcept + { + if (m_Handle) + { + Close(); + } + } + + Handle& operator=(Handle& InHandle) noexcept + { + if (this != &InHandle) + { + if (m_Handle != NULL) + { + Close(); + } + Attach(InHandle.Detach()); + } + + return *this; + } + + inline operator HANDLE() const noexcept { return m_Handle; } + inline void Attach(HANDLE h) noexcept + { + ZEN_ASSERT(m_Handle == NULL); + m_Handle = h; + } + inline HANDLE Detach() noexcept + { + HANDLE h; + + h = m_Handle; + m_Handle = NULL; + + return h; + } + void Close() noexcept + { + if (m_Handle != NULL) + { + ::CloseHandle(m_Handle); + m_Handle = NULL; + } + } + +public: + HANDLE m_Handle{0}; +}; + +///////////////////////////////////////////////////////////////////////////// +// Error to HRESULT helpers + +inline HRESULT +MapHresultFromLastError() noexcept +{ + DWORD ErrorCode = ::GetLastError(); + return HRESULT_FROM_WIN32(ErrorCode); +} + +inline HRESULT +MapHresultFromWin32(DWORD ErrorCode) noexcept +{ + return HRESULT_FROM_WIN32(ErrorCode); +} + +////////////////////////////////////////////////////////////////////////// + +class FileHandle : public Handle +{ +public: + FileHandle() noexcept = default; + FileHandle(FileHandle& InFile) noexcept : Handle(InFile) {} + explicit FileHandle(HANDLE InFileHandle) noexcept : Handle(InFileHandle) {} + + HRESULT Create(LPCTSTR szFilename, + DWORD dwDesiredAccess, + DWORD dwShareMode, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL) + { + ZEN_ASSERT(m_Handle == NULL); + + HANDLE hFile = ::CreateFile(szFilename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); + + if (hFile == INVALID_HANDLE_VALUE) + return MapHresultFromLastError(); + + Attach(hFile); + + return S_OK; + } + + HRESULT Read(LPVOID pBuffer, DWORD nBufSize) + { + ZEN_ASSERT(m_Handle != NULL); + + DWORD nBytesRead = 0; + BOOL Success = ::ReadFile(m_Handle, pBuffer, nBufSize, &nBytesRead, NULL); + + if (!Success) + return MapHresultFromLastError(); + + if (nBytesRead != nBufSize) + return HRESULT_FROM_WIN32(ERROR_HANDLE_EOF); + + return S_OK; + } + + HRESULT Read(LPVOID pBuffer, DWORD nBufSize, LPOVERLAPPED pOverlapped) + { + ZEN_ASSERT(m_Handle != NULL); + + BOOL Success = ::ReadFile(m_Handle, pBuffer, nBufSize, NULL, pOverlapped); + if (!Success) + return MapHresultFromLastError(); + + return S_OK; + } + + HRESULT Write(LPCVOID pBuffer, DWORD nBufSize, DWORD* pnBytesWritten = NULL) + { + ZEN_ASSERT(m_Handle != NULL); + + DWORD nBytesWritten; + if (pnBytesWritten == NULL) + pnBytesWritten = &nBytesWritten; + + BOOL Success = ::WriteFile(m_Handle, pBuffer, nBufSize, pnBytesWritten, NULL); + if (!Success) + return MapHresultFromLastError(); + + return S_OK; + } + + HRESULT Write(LPCVOID pBuffer, DWORD nBufSize, LPOVERLAPPED pOverlapped) + { + ZEN_ASSERT(m_Handle != NULL); + + BOOL Success = ::WriteFile(m_Handle, pBuffer, nBufSize, NULL, pOverlapped); + if (!Success) + return MapHresultFromLastError(); + + return S_OK; + } + + HRESULT Seek(LONGLONG nOffset, DWORD dwFrom = FILE_CURRENT) + { + ZEN_ASSERT(m_Handle != NULL); + ZEN_ASSERT(dwFrom == FILE_BEGIN || dwFrom == FILE_END || dwFrom == FILE_CURRENT); + + LARGE_INTEGER liOffset; + liOffset.QuadPart = nOffset; + DWORD nNewPos = ::SetFilePointer(m_Handle, liOffset.LowPart, &liOffset.HighPart, dwFrom); + + if (nNewPos == INVALID_SET_FILE_POINTER) + { + HRESULT hr = MapHresultFromLastError(); + + if (FAILED(hr)) + return hr; + } + + return S_OK; + } + + HRESULT GetPosition(ULONGLONG& OutPos) const + { + ZEN_ASSERT(m_Handle != NULL); + + LARGE_INTEGER liOffset; + liOffset.QuadPart = 0; + liOffset.LowPart = ::SetFilePointer(m_Handle, 0, &liOffset.HighPart, FILE_CURRENT); + if (liOffset.LowPart == INVALID_SET_FILE_POINTER) + { + HRESULT hr = MapHresultFromLastError(); + + if (FAILED(hr)) + return hr; + } + OutPos = liOffset.QuadPart; + + return S_OK; + } + + HRESULT GetSize(ULONGLONG& OutLen) const + { + ZEN_ASSERT(m_Handle != NULL); + + ULARGE_INTEGER liFileSize; + liFileSize.LowPart = ::GetFileSize(m_Handle, &liFileSize.HighPart); + + if (liFileSize.LowPart == INVALID_FILE_SIZE) + { + HRESULT hr = MapHresultFromLastError(); + if (FAILED(hr)) + return hr; + } + + OutLen = liFileSize.QuadPart; + + return S_OK; + } +}; + +////////////////////////////////////////////////////////////////////////// + +class FileMapping +{ +public: + FileMapping() throw() + { + m_pData = NULL; + m_hMapping = NULL; + } + + ~FileMapping() throw() { Unmap(); } + + HRESULT MapFile(_In_ HANDLE hFile, + _In_ SIZE_T nMappingSize = 0, + _In_ ULONGLONG nOffset = 0, + _In_ DWORD dwMappingProtection = PAGE_READONLY, + _In_ DWORD dwViewDesiredAccess = FILE_MAP_READ) throw() + { + ZEN_ASSERT(m_pData == NULL); + ZEN_ASSERT(m_hMapping == NULL); + ZEN_ASSERT(hFile != INVALID_HANDLE_VALUE && hFile != NULL); + + ULARGE_INTEGER liFileSize; + liFileSize.LowPart = ::GetFileSize(hFile, &liFileSize.HighPart); + if (liFileSize.QuadPart < nMappingSize) + liFileSize.QuadPart = nMappingSize; + + m_hMapping = ::CreateFileMapping(hFile, NULL, dwMappingProtection, liFileSize.HighPart, liFileSize.LowPart, 0); + if (m_hMapping == NULL) + return MapHresultFromLastError(); + + if (nMappingSize == 0) + m_nMappingSize = (SIZE_T)(liFileSize.QuadPart - nOffset); + else + m_nMappingSize = nMappingSize; + + m_dwViewDesiredAccess = dwViewDesiredAccess; + m_nOffset.QuadPart = nOffset; + + m_pData = ::MapViewOfFileEx(m_hMapping, m_dwViewDesiredAccess, m_nOffset.HighPart, m_nOffset.LowPart, m_nMappingSize, NULL); + if (m_pData == NULL) + { + HRESULT hr; + + hr = MapHresultFromLastError(); + ::CloseHandle(m_hMapping); + m_hMapping = NULL; + return hr; + } + + return S_OK; + } + + HRESULT MapSharedMem(_In_ SIZE_T nMappingSize, + _In_z_ LPCTSTR szName, + _Out_opt_ BOOL* pbAlreadyExisted = NULL, + _In_opt_ LPSECURITY_ATTRIBUTES lpsa = NULL, + _In_ DWORD dwMappingProtection = PAGE_READWRITE, + _In_ DWORD dwViewDesiredAccess = FILE_MAP_ALL_ACCESS) throw() + { + ZEN_ASSERT(m_pData == NULL); + ZEN_ASSERT(m_hMapping == NULL); + ZEN_ASSERT(nMappingSize > 0); + ZEN_ASSERT(szName != NULL); // if you just want a regular chunk of memory, use a heap allocator + + m_nMappingSize = nMappingSize; + + ULARGE_INTEGER nSize; + nSize.QuadPart = nMappingSize; + m_hMapping = ::CreateFileMapping(INVALID_HANDLE_VALUE, lpsa, dwMappingProtection, nSize.HighPart, nSize.LowPart, szName); + if (m_hMapping == NULL) + { + HRESULT hr = MapHresultFromLastError(); + _Analysis_assume_(FAILED(hr)); + return hr; + } + + if (pbAlreadyExisted != NULL) + *pbAlreadyExisted = (GetLastError() == ERROR_ALREADY_EXISTS); + + m_dwViewDesiredAccess = dwViewDesiredAccess; + m_nOffset.QuadPart = 0; + + m_pData = ::MapViewOfFileEx(m_hMapping, m_dwViewDesiredAccess, m_nOffset.HighPart, m_nOffset.LowPart, m_nMappingSize, NULL); + if (m_pData == NULL) + { + HRESULT hr; + + hr = MapHresultFromLastError(); + ::CloseHandle(m_hMapping); + m_hMapping = NULL; + return hr; + } + + return S_OK; + } + + HRESULT OpenMapping(_In_z_ LPCTSTR szName, + _In_ SIZE_T nMappingSize, + _In_ ULONGLONG nOffset = 0, + _In_ DWORD dwViewDesiredAccess = FILE_MAP_ALL_ACCESS) throw() + { + ZEN_ASSERT(m_pData == NULL); + ZEN_ASSERT(m_hMapping == NULL); + ZEN_ASSERT(szName != NULL); // if you just want a regular chunk of memory, use a heap allocator + + m_nMappingSize = nMappingSize; + m_dwViewDesiredAccess = dwViewDesiredAccess; + + m_hMapping = ::OpenFileMapping(m_dwViewDesiredAccess, FALSE, szName); + if (m_hMapping == NULL) + return MapHresultFromLastError(); + + m_dwViewDesiredAccess = dwViewDesiredAccess; + m_nOffset.QuadPart = nOffset; + + m_pData = ::MapViewOfFileEx(m_hMapping, m_dwViewDesiredAccess, m_nOffset.HighPart, m_nOffset.LowPart, m_nMappingSize, NULL); + if (m_pData == NULL) + { + HRESULT hr; + + hr = MapHresultFromLastError(); + ::CloseHandle(m_hMapping); + m_hMapping = NULL; + return hr; + } + + return S_OK; + } + + HRESULT Unmap() throw() + { + HRESULT hr = S_OK; + + if (m_pData != NULL) + { + if (!::UnmapViewOfFile(m_pData)) + hr = MapHresultFromLastError(); + m_pData = NULL; + } + if (m_hMapping != NULL) + { + if (!::CloseHandle(m_hMapping) && SUCCEEDED(hr)) + hr = MapHresultFromLastError(); + m_hMapping = NULL; + } + return hr; + } + + void* GetData() const throw() { return m_pData; } + + HANDLE GetHandle() const throw() { return m_hMapping; } + + SIZE_T GetMappingSize() throw() { return m_nMappingSize; } + + HRESULT CopyFrom(_In_ FileMapping& orig) throw(); + + FileMapping(_In_ FileMapping& orig); + FileMapping& operator=(_In_ FileMapping& orig); + +private: + void* m_pData; + SIZE_T m_nMappingSize; + HANDLE m_hMapping; + ULARGE_INTEGER m_nOffset; + DWORD m_dwViewDesiredAccess; +}; + +} // namespace zen::windows +#endif |