First Commit
This commit is contained in:
131
3rdparty/winwil/include/wil/wrl.h
vendored
Normal file
131
3rdparty/winwil/include/wil/wrl.h
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
//! @file
|
||||
//! Windows Runtime Library Helpers: helpers for constructing RuntimeClass based objects and agile WRL Callback objects
|
||||
#ifndef __WIL_WRL_INCLUDED
|
||||
#define __WIL_WRL_INCLUDED
|
||||
|
||||
#include <wrl.h>
|
||||
#include "result.h"
|
||||
#include "common.h" // wistd type_traits helpers
|
||||
#include <libloaderapi.h> // GetModuleHandleW
|
||||
|
||||
/// @cond
|
||||
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
|
||||
/// @endcond
|
||||
|
||||
namespace wil
|
||||
{
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
#pragma region Object construction helpers that throw exceptions
|
||||
|
||||
/** Used to construct a RuntimeClass based object that uses 2 phase construction.
|
||||
Construct a RuntimeClass based object that uses 2 phase construction (by implementing
|
||||
RuntimeClassInitialize() and returning error codes for failures.
|
||||
@code
|
||||
// SomeClass uses 2 phase initialization by implementing RuntimeClassInitialize()
|
||||
auto someClass = MakeAndInitializeOrThrow<SomeClass>(L"input", true);
|
||||
@endcode
|
||||
*/
|
||||
template <typename T, typename... TArgs>
|
||||
Microsoft::WRL::ComPtr<T> MakeAndInitializeOrThrow(TArgs&&... args)
|
||||
{
|
||||
Microsoft::WRL::ComPtr<T> obj;
|
||||
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<T>(&obj, Microsoft::WRL::Details::Forward<TArgs>(args)...));
|
||||
return obj;
|
||||
}
|
||||
|
||||
/** Used to construct an RuntimeClass based object that uses exceptions in its constructor (and does
|
||||
not require 2 phase construction).
|
||||
@code
|
||||
// SomeClass uses exceptions for error handling in its constructor.
|
||||
auto someClass = MakeOrThrow<SomeClass>(L"input", true);
|
||||
@endcode
|
||||
*/
|
||||
template <typename T, typename... TArgs>
|
||||
Microsoft::WRL::ComPtr<T> MakeOrThrow(TArgs&&... args)
|
||||
{
|
||||
// This is how you can detect the presence of RuntimeClassInitialize() and find dangerous use.
|
||||
// Unfortunately this produces false positives as all RuntimeClass derived classes have
|
||||
// a RuntimeClassInitialize() method from their base class.
|
||||
// static_assert(!std::is_member_function_pointer<decltype(&T::RuntimeClassInitialize)>::value,
|
||||
// "class has a RuntimeClassInitialize member, use MakeAndInitializeOrThrow instead");
|
||||
auto obj = Microsoft::WRL::Make<T>(Microsoft::WRL::Details::Forward<TArgs>(args)...);
|
||||
THROW_IF_NULL_ALLOC(obj.Get());
|
||||
return obj;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
/** By default WRL Callback objects are not agile, use this to make an agile one. Replace use of Callback<> with
|
||||
MakeAgileCallback<>. Will return null on failure, translate that into E_OUTOFMEMORY using XXX_IF_NULL_ALLOC() from wil/result.h
|
||||
to test the result. */
|
||||
template <typename TDelegateInterface, typename... Args>
|
||||
::Microsoft::WRL::ComPtr<TDelegateInterface> MakeAgileCallbackNoThrow(Args&&... args) WI_NOEXCEPT
|
||||
{
|
||||
using namespace Microsoft::WRL;
|
||||
return Callback<Implements<RuntimeClassFlags<ClassicCom>, TDelegateInterface, FtmBase>>(wistd::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
template <typename TDelegateInterface, typename... Args>
|
||||
::Microsoft::WRL::ComPtr<TDelegateInterface> MakeAgileCallback(Args&&... args)
|
||||
{
|
||||
auto result = MakeAgileCallbackNoThrow<TDelegateInterface, Args...>(wistd::forward<Args>(args)...);
|
||||
THROW_IF_NULL_ALLOC(result);
|
||||
return result;
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
/** Holds a reference to the host WRL module to prevent it from being unloaded.
|
||||
Normally, the reference is held implicitly because you are a member function
|
||||
of a DLL-hosted COM object, or because you retain a strong reference
|
||||
to some DLL-hosted COM object, but if those do not apply to you, then you
|
||||
will need to hold a reference explicitly. For examples (and for the C++/WinRT
|
||||
equivalent), see winrt_module_reference.
|
||||
*/
|
||||
struct [[nodiscard]] wrl_module_reference
|
||||
{
|
||||
wrl_module_reference()
|
||||
{
|
||||
if (auto modulePtr = ::Microsoft::WRL::GetModuleBase())
|
||||
{
|
||||
modulePtr->IncrementObjectCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef GET_MODULE_HANDLE_EX_FLAG_PIN
|
||||
// If this assertion fails, then you are using wrl_module_reference
|
||||
// from a DLL that does not host WRL objects, and the module reference
|
||||
// has no effect.
|
||||
WI_ASSERT(reinterpret_cast<HMODULE>(&__ImageBase) == GetModuleHandleW(nullptr));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
wrl_module_reference(wrl_module_reference const&) : wrl_module_reference()
|
||||
{
|
||||
}
|
||||
|
||||
~wrl_module_reference()
|
||||
{
|
||||
if (auto modulePtr = ::Microsoft::WRL::GetModuleBase())
|
||||
{
|
||||
modulePtr->DecrementObjectCount();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace wil
|
||||
|
||||
#endif // __WIL_WRL_INCLUDED
|
||||
Reference in New Issue
Block a user