wrl.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. //*********************************************************
  2. //
  3. // Copyright (c) Microsoft. All rights reserved.
  4. // This code is licensed under the MIT License.
  5. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
  6. // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  7. // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  8. // PARTICULAR PURPOSE AND NONINFRINGEMENT.
  9. //
  10. //*********************************************************
  11. #ifndef __WIL_WRL_INCLUDED
  12. #define __WIL_WRL_INCLUDED
  13. #include <wrl.h>
  14. #include "result.h"
  15. #include "common.h" // wistd type_traits helpers
  16. #include <libloaderapi.h> // GetModuleHandleW
  17. /// @cond
  18. EXTERN_C IMAGE_DOS_HEADER __ImageBase;
  19. /// @endcond
  20. namespace wil
  21. {
  22. #ifdef WIL_ENABLE_EXCEPTIONS
  23. #pragma region Object construction helpers that throw exceptions
  24. /** Used to construct a RuntimeClass based object that uses 2 phase construction.
  25. Construct a RuntimeClass based object that uses 2 phase construction (by implementing
  26. RuntimeClassInitialize() and returning error codes for failures.
  27. ~~~~
  28. // SomeClass uses 2 phase initialization by implementing RuntimeClassInitialize()
  29. auto someClass = MakeAndInitializeOrThrow<SomeClass>(L"input", true);
  30. ~~~~ */
  31. template <typename T, typename... TArgs>
  32. Microsoft::WRL::ComPtr<T> MakeAndInitializeOrThrow(TArgs&&... args)
  33. {
  34. Microsoft::WRL::ComPtr<T> obj;
  35. THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<T>(&obj, Microsoft::WRL::Details::Forward<TArgs>(args)...));
  36. return obj;
  37. }
  38. /** Used to construct an RuntimeClass based object that uses exceptions in its constructor (and does
  39. not require 2 phase construction).
  40. ~~~~
  41. // SomeClass uses exceptions for error handling in its constructor.
  42. auto someClass = MakeOrThrow<SomeClass>(L"input", true);
  43. ~~~~ */
  44. template <typename T, typename... TArgs>
  45. Microsoft::WRL::ComPtr<T> MakeOrThrow(TArgs&&... args)
  46. {
  47. // This is how you can detect the presence of RuntimeClassInitialize() and find dangerous use.
  48. // Unfortunately this produces false positives as all RuntimeClass derived classes have
  49. // a RuntimeClassInitialize() method from their base class.
  50. // static_assert(!std::is_member_function_pointer<decltype(&T::RuntimeClassInitialize)>::value,
  51. // "class has a RuntimeClassInitialize member, use MakeAndInitializeOrThrow instead");
  52. auto obj = Microsoft::WRL::Make<T>(Microsoft::WRL::Details::Forward<TArgs>(args)...);
  53. THROW_IF_NULL_ALLOC(obj.Get());
  54. return obj;
  55. }
  56. #pragma endregion
  57. #endif // WIL_ENABLE_EXCEPTIONS
  58. /** By default WRL Callback objects are not agile, use this to make an agile one. Replace use of Callback<> with MakeAgileCallback<>.
  59. Will return null on failure, translate that into E_OUTOFMEMORY using XXX_IF_NULL_ALLOC()
  60. from wil\result.h to test the result. */
  61. template<typename TDelegateInterface, typename ...Args>
  62. ::Microsoft::WRL::ComPtr<TDelegateInterface> MakeAgileCallbackNoThrow(Args&&... args) WI_NOEXCEPT
  63. {
  64. using namespace Microsoft::WRL;
  65. return Callback<Implements<RuntimeClassFlags<ClassicCom>, TDelegateInterface, FtmBase>>(wistd::forward<Args>(args)...);
  66. }
  67. #ifdef WIL_ENABLE_EXCEPTIONS
  68. template<typename TDelegateInterface, typename ...Args>
  69. ::Microsoft::WRL::ComPtr<TDelegateInterface> MakeAgileCallback(Args&&... args)
  70. {
  71. auto result = MakeAgileCallbackNoThrow<TDelegateInterface, Args...>(wistd::forward<Args>(args)...);
  72. THROW_IF_NULL_ALLOC(result);
  73. return result;
  74. }
  75. #endif // WIL_ENABLE_EXCEPTIONS
  76. /** Holds a reference to the host WRL module to prevent it from being unloaded.
  77. Normally, the reference is held implicitly because you are a member function
  78. of a DLL-hosted COM object, or because you retain a strong reference
  79. to some DLL-hosted COM object, but if those do not apply to you, then you
  80. will need to hold a reference explicitly. For examples (and for the C++/WinRT
  81. equivalent), see winrt_module_reference.
  82. */
  83. struct [[nodiscard]] wrl_module_reference
  84. {
  85. wrl_module_reference()
  86. {
  87. if (auto modulePtr = ::Microsoft::WRL::GetModuleBase())
  88. {
  89. modulePtr->IncrementObjectCount();
  90. }
  91. else
  92. {
  93. #ifdef GET_MODULE_HANDLE_EX_FLAG_PIN
  94. // If this assertion fails, then you are using wrl_module_reference
  95. // from a DLL that does not host WRL objects, and the module reference
  96. // has no effect.
  97. WI_ASSERT(reinterpret_cast<HMODULE>(&__ImageBase) == GetModuleHandleW(nullptr));
  98. #endif
  99. }
  100. }
  101. wrl_module_reference(wrl_module_reference const&) : wrl_module_reference() {}
  102. ~wrl_module_reference()
  103. {
  104. if (auto modulePtr = ::Microsoft::WRL::GetModuleBase())
  105. {
  106. modulePtr->DecrementObjectCount();
  107. }
  108. }
  109. };
  110. } // namespace wil
  111. #endif // __WIL_WRL_INCLUDED