// Scintilla source code edit control /** @file WinTypes.h ** Implement safe release of COM objects and access to functions in DLLs. ** Header contains all implementation - there is no .cxx file. **/ // Copyright 2020-2021 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #ifndef WINTYPES_H #define WINTYPES_H namespace Scintilla::Internal { // Release an IUnknown* and set to nullptr. // While IUnknown::Release must be noexcept, it isn't marked as such so produces // warnings which are avoided by the catch. template inline void ReleaseUnknown(T *&ppUnknown) noexcept { if (ppUnknown) { try { ppUnknown->Release(); } catch (...) { // Never occurs } ppUnknown = nullptr; } } struct UnknownReleaser { // Called by unique_ptr to destroy/free the resource template void operator()(T *pUnknown) noexcept { try { pUnknown->Release(); } catch (...) { // IUnknown::Release must not throw, ignore if it does. } } }; // Wrap COM IUnknown::QueryInterface to produce std::unique_ptr objects to help // ensure safe reference counting. template inline HRESULT UniquePtrFromQI(IUnknown *source, REFIID riid, std::unique_ptr &destination) noexcept { T *ptr{}; HRESULT hr = E_FAIL; try { hr = source->QueryInterface(riid, reinterpret_cast(&ptr)); } catch (...) { // Shouldn't have exceptions from QueryInterface but not marked noexcept } if (SUCCEEDED(hr)) { destination.reset(ptr); } else { destination.reset(); } return hr; } /// Find a function in a DLL and convert to a function pointer. /// This avoids undefined and conditionally defined behaviour. template inline T DLLFunction(HMODULE hModule, LPCSTR lpProcName) noexcept { if (!hModule) { return nullptr; } FARPROC function = ::GetProcAddress(hModule, lpProcName); static_assert(sizeof(T) == sizeof(function)); T fp {}; memcpy(&fp, &function, sizeof(T)); return fp; } } #endif