| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803 |
- // Copyright (c) Microsoft Corporation.
- // Licensed under the MIT License.
- #pragma once
- #include "winadapter.h"
- // defined by winadapter.h and needed by some windows headers, but conflicts
- // with some libc++ implementation headers
- #ifdef __in
- #undef __in
- #endif
- #ifdef __out
- #undef __out
- #endif
- #include <type_traits>
- #include <atomic>
- #include <memory>
- #include <new>
- #include <climits>
- #include <cassert>
- namespace Microsoft
- {
- namespace WRL
- {
- namespace Details
- {
- struct BoolStruct { int Member; };
- typedef int BoolStruct::* BoolType;
- template <typename T> // T should be the ComPtr<T> or a derived type of it, not just the interface
- class ComPtrRefBase
- {
- public:
- typedef typename T::InterfaceType InterfaceType;
- operator IUnknown**() const throw()
- {
- static_assert(__is_base_of(IUnknown, InterfaceType), "Invalid cast: InterfaceType does not derive from IUnknown");
- return reinterpret_cast<IUnknown**>(ptr_->ReleaseAndGetAddressOf());
- }
- protected:
- T* ptr_;
- };
- template <typename T>
- class ComPtrRef : public Details::ComPtrRefBase<T> // T should be the ComPtr<T> or a derived type of it, not just the interface
- {
- using Super = Details::ComPtrRefBase<T>;
- using InterfaceType = typename Super::InterfaceType;
- public:
- ComPtrRef(_In_opt_ T* ptr) throw()
- {
- this->ptr_ = ptr;
- }
- // Conversion operators
- operator void**() const throw()
- {
- return reinterpret_cast<void**>(this->ptr_->ReleaseAndGetAddressOf());
- }
- // This is our operator ComPtr<U> (or the latest derived class from ComPtr (e.g. WeakRef))
- operator T*() throw()
- {
- *this->ptr_ = nullptr;
- return this->ptr_;
- }
- // We define operator InterfaceType**() here instead of on ComPtrRefBase<T>, since
- // if InterfaceType is IUnknown or IInspectable, having it on the base will collide.
- operator InterfaceType**() throw()
- {
- return this->ptr_->ReleaseAndGetAddressOf();
- }
- // This is used for IID_PPV_ARGS in order to do __uuidof(**(ppType)).
- // It does not need to clear ptr_ at this point, it is done at IID_PPV_ARGS_Helper(ComPtrRef&) later in this file.
- InterfaceType* operator *() throw()
- {
- return this->ptr_->Get();
- }
- // Explicit functions
- InterfaceType* const * GetAddressOf() const throw()
- {
- return this->ptr_->GetAddressOf();
- }
- InterfaceType** ReleaseAndGetAddressOf() throw()
- {
- return this->ptr_->ReleaseAndGetAddressOf();
- }
- };
- }
- template <typename T>
- class ComPtr
- {
- public:
- typedef T InterfaceType;
- protected:
- InterfaceType *ptr_;
- template<class U> friend class ComPtr;
- void InternalAddRef() const throw()
- {
- if (ptr_ != nullptr)
- {
- ptr_->AddRef();
- }
- }
- unsigned long InternalRelease() throw()
- {
- unsigned long ref = 0;
- T* temp = ptr_;
- if (temp != nullptr)
- {
- ptr_ = nullptr;
- ref = temp->Release();
- }
- return ref;
- }
- public:
- ComPtr() throw() : ptr_(nullptr)
- {
- }
- ComPtr(decltype(nullptr)) throw() : ptr_(nullptr)
- {
- }
- template<class U>
- ComPtr(_In_opt_ U *other) throw() : ptr_(other)
- {
- InternalAddRef();
- }
- ComPtr(const ComPtr& other) throw() : ptr_(other.ptr_)
- {
- InternalAddRef();
- }
- // copy constructor that allows to instantiate class when U* is convertible to T*
- template<class U>
- ComPtr(const ComPtr<U> &other, typename std::enable_if<std::is_convertible<U*, T*>::value, void *>::type * = 0) throw() :
- ptr_(other.ptr_)
- {
- InternalAddRef();
- }
- ComPtr(_Inout_ ComPtr &&other) throw() : ptr_(nullptr)
- {
- if (this != reinterpret_cast<ComPtr*>(&reinterpret_cast<unsigned char&>(other)))
- {
- Swap(other);
- }
- }
- // Move constructor that allows instantiation of a class when U* is convertible to T*
- template<class U>
- ComPtr(_Inout_ ComPtr<U>&& other, typename std::enable_if<std::is_convertible<U*, T*>::value, void *>::type * = 0) throw() :
- ptr_(other.ptr_)
- {
- other.ptr_ = nullptr;
- }
- ~ComPtr() throw()
- {
- InternalRelease();
- }
- ComPtr& operator=(decltype(nullptr)) throw()
- {
- InternalRelease();
- return *this;
- }
- ComPtr& operator=(_In_opt_ T *other) throw()
- {
- if (ptr_ != other)
- {
- ComPtr(other).Swap(*this);
- }
- return *this;
- }
- template <typename U>
- ComPtr& operator=(_In_opt_ U *other) throw()
- {
- ComPtr(other).Swap(*this);
- return *this;
- }
- ComPtr& operator=(const ComPtr &other) throw()
- {
- if (ptr_ != other.ptr_)
- {
- ComPtr(other).Swap(*this);
- }
- return *this;
- }
- template<class U>
- ComPtr& operator=(const ComPtr<U>& other) throw()
- {
- ComPtr(other).Swap(*this);
- return *this;
- }
- ComPtr& operator=(_Inout_ ComPtr &&other) throw()
- {
- ComPtr(static_cast<ComPtr&&>(other)).Swap(*this);
- return *this;
- }
- template<class U>
- ComPtr& operator=(_Inout_ ComPtr<U>&& other) throw()
- {
- ComPtr(static_cast<ComPtr<U>&&>(other)).Swap(*this);
- return *this;
- }
- void Swap(_Inout_ ComPtr&& r) throw()
- {
- T* tmp = ptr_;
- ptr_ = r.ptr_;
- r.ptr_ = tmp;
- }
- void Swap(_Inout_ ComPtr& r) throw()
- {
- T* tmp = ptr_;
- ptr_ = r.ptr_;
- r.ptr_ = tmp;
- }
- operator Details::BoolType() const throw()
- {
- return Get() != nullptr ? &Details::BoolStruct::Member : nullptr;
- }
- T* Get() const throw()
- {
- return ptr_;
- }
- InterfaceType* operator->() const throw()
- {
- return ptr_;
- }
- Details::ComPtrRef<ComPtr<T>> operator&() throw()
- {
- return Details::ComPtrRef<ComPtr<T>>(this);
- }
- const Details::ComPtrRef<const ComPtr<T>> operator&() const throw()
- {
- return Details::ComPtrRef<const ComPtr<T>>(this);
- }
- T* const* GetAddressOf() const throw()
- {
- return &ptr_;
- }
- T** GetAddressOf() throw()
- {
- return &ptr_;
- }
- T** ReleaseAndGetAddressOf() throw()
- {
- InternalRelease();
- return &ptr_;
- }
- T* Detach() throw()
- {
- T* ptr = ptr_;
- ptr_ = nullptr;
- return ptr;
- }
- void Attach(_In_opt_ InterfaceType* other) throw()
- {
- if (ptr_ != nullptr)
- {
- auto ref = ptr_->Release();
- // DBG_UNREFERENCED_LOCAL_VARIABLE(ref);
- // Attaching to the same object only works if duplicate references are being coalesced. Otherwise
- // re-attaching will cause the pointer to be released and may cause a crash on a subsequent dereference.
- assert(ref != 0 || ptr_ != other);
- }
- ptr_ = other;
- }
- unsigned long Reset()
- {
- return InternalRelease();
- }
- // Previously, unsafe behavior could be triggered when 'this' is ComPtr<IInspectable> or ComPtr<IUnknown> and CopyTo is used to copy to another type U.
- // The user will use operator& to convert the destination into a ComPtrRef, which can then implicit cast to IInspectable** and IUnknown**.
- // If this overload of CopyTo is not present, it will implicitly cast to IInspectable or IUnknown and match CopyTo(InterfaceType**) instead.
- // A valid polymoprhic downcast requires run-time type checking via QueryInterface, so CopyTo(InterfaceType**) will break type safety.
- // This overload matches ComPtrRef before the implicit cast takes place, preventing the unsafe downcast.
- template <typename U>
- HRESULT CopyTo(Details::ComPtrRef<ComPtr<U>> ptr, typename std::enable_if<
- (std::is_same<T, IUnknown>::value)
- && !std::is_same<U*, T*>::value, void *>::type * = 0) const throw()
- {
- return ptr_->QueryInterface(__uuidof(U), ptr);
- }
- HRESULT CopyTo(_Outptr_result_maybenull_ InterfaceType** ptr) const throw()
- {
- InternalAddRef();
- *ptr = ptr_;
- return S_OK;
- }
- HRESULT CopyTo(REFIID riid, _Outptr_result_nullonfailure_ void** ptr) const throw()
- {
- return ptr_->QueryInterface(riid, ptr);
- }
- template<typename U>
- HRESULT CopyTo(_Outptr_result_nullonfailure_ U** ptr) const throw()
- {
- return ptr_->QueryInterface(__uuidof(U), reinterpret_cast<void**>(ptr));
- }
- // query for U interface
- template<typename U>
- HRESULT As(_Inout_ Details::ComPtrRef<ComPtr<U>> p) const throw()
- {
- return ptr_->QueryInterface(__uuidof(U), p);
- }
- // query for U interface
- template<typename U>
- HRESULT As(_Out_ ComPtr<U>* p) const throw()
- {
- return ptr_->QueryInterface(__uuidof(U), reinterpret_cast<void**>(p->ReleaseAndGetAddressOf()));
- }
- // query for riid interface and return as IUnknown
- HRESULT AsIID(REFIID riid, _Out_ ComPtr<IUnknown>* p) const throw()
- {
- return ptr_->QueryInterface(riid, reinterpret_cast<void**>(p->ReleaseAndGetAddressOf()));
- }
- }; // ComPtr
- namespace Details
- {
- // Empty struct used as default template parameter
- class Nil
- {
- };
- // Empty struct used for validating template parameter types in Implements
- struct ImplementsBase
- {
- };
- class RuntimeClassBase
- {
- protected:
- template<typename T>
- static HRESULT AsIID(_In_ T* implements, REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject) noexcept
- {
- *ppvObject = nullptr;
- bool isRefDelegated = false;
- // Prefer InlineIsEqualGUID over other forms since it's better perf on 4-byte aligned data, which is almost always the case.
- if (InlineIsEqualGUID(riid, __uuidof(IUnknown)))
- {
- *ppvObject = implements->CastToUnknown();
- static_cast<IUnknown*>(*ppvObject)->AddRef();
- return S_OK;
- }
- HRESULT hr = implements->CanCastTo(riid, ppvObject, &isRefDelegated);
- if (SUCCEEDED(hr) && !isRefDelegated)
- {
- static_cast<IUnknown*>(*ppvObject)->AddRef();
- }
- #ifdef _MSC_VER
- #pragma warning(push)
- #pragma warning(disable: 6102) // '*ppvObject' is used but may not be initialized
- #endif
- _Analysis_assume_(SUCCEEDED(hr) || (*ppvObject == nullptr));
- #ifdef _MSC_VER
- #pragma warning(pop)
- #endif
- return hr;
- }
- public:
- HRESULT RuntimeClassInitialize() noexcept
- {
- return S_OK;
- }
- };
- // Interface traits provides casting and filling iids methods helpers
- template<typename I0>
- struct InterfaceTraits
- {
- typedef I0 Base;
- template<typename T>
- static Base* CastToBase(_In_ T* ptr) noexcept
- {
- return static_cast<Base*>(ptr);
- }
- template<typename T>
- static IUnknown* CastToUnknown(_In_ T* ptr) noexcept
- {
- return static_cast<IUnknown*>(static_cast<Base*>(ptr));
- }
- template <typename T>
- _Success_(return == true)
- static bool CanCastTo(_In_ T* ptr, REFIID riid, _Outptr_ void **ppv) noexcept
- {
- // Prefer InlineIsEqualGUID over other forms since it's better perf on 4-byte aligned data, which is almost always the case.
- if (InlineIsEqualGUID(riid, __uuidof(Base)))
- {
- *ppv = static_cast<Base*>(ptr);
- return true;
- }
- return false;
- }
- };
- // Specialization for Nil parameter
- template<>
- struct InterfaceTraits<Nil>
- {
- typedef Nil Base;
- template <typename T>
- _Success_(return == true)
- static bool CanCastTo(_In_ T*, REFIID, _Outptr_ void **) noexcept
- {
- return false;
- }
- };
- // ChainInterfaces - template allows specifying a derived COM interface along with its class hierarchy to allow QI for the base interfaces
- template <typename I0, typename I1, typename I2 = Nil, typename I3 = Nil,
- typename I4 = Nil, typename I5 = Nil, typename I6 = Nil,
- typename I7 = Nil, typename I8 = Nil, typename I9 = Nil>
- struct ChainInterfaces : I0
- {
- protected:
- HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv) throw()
- {
- typename InterfaceTraits<I0>::Base* ptr = InterfaceTraits<I0>::CastToBase(this);
- return (InterfaceTraits<I0>::CanCastTo(this, riid, ppv) ||
- InterfaceTraits<I1>::CanCastTo(ptr, riid, ppv) ||
- InterfaceTraits<I2>::CanCastTo(ptr, riid, ppv) ||
- InterfaceTraits<I3>::CanCastTo(ptr, riid, ppv) ||
- InterfaceTraits<I4>::CanCastTo(ptr, riid, ppv) ||
- InterfaceTraits<I5>::CanCastTo(ptr, riid, ppv) ||
- InterfaceTraits<I6>::CanCastTo(ptr, riid, ppv) ||
- InterfaceTraits<I7>::CanCastTo(ptr, riid, ppv) ||
- InterfaceTraits<I8>::CanCastTo(ptr, riid, ppv) ||
- InterfaceTraits<I9>::CanCastTo(ptr, riid, ppv)) ? S_OK : E_NOINTERFACE;
- }
- IUnknown* CastToUnknown() throw()
- {
- return InterfaceTraits<I0>::CastToUnknown(this);
- }
- };
- // Helper template used by Implements. This template traverses a list of interfaces and adds them as base class and information
- // to enable QI.
- template <typename ...TInterfaces>
- struct ImplementsHelper;
- template <typename T>
- struct ImplementsMarker
- {};
- template <typename I0, bool isImplements>
- struct MarkImplements;
- template <typename I0>
- struct MarkImplements<I0, false>
- {
- typedef I0 Type;
- };
- template <typename I0>
- struct MarkImplements<I0, true>
- {
- typedef ImplementsMarker<I0> Type;
- };
- // AdjustImplements pre-processes the type list for more efficient builds.
- template <typename ...Bases>
- struct AdjustImplements;
- template <typename I0, typename ...Bases>
- struct AdjustImplements<I0, Bases...>
- {
- typedef ImplementsHelper<typename MarkImplements<I0, std::is_base_of<ImplementsBase, I0>::value>::Type, Bases...> Type;
- };
- // Use AdjustImplements to remove instances of "Nil" from the type list.
- template <typename ...Bases>
- struct AdjustImplements<Nil, Bases...>
- {
- typedef typename AdjustImplements<Bases...>::Type Type;
- };
- template <>
- struct AdjustImplements<>
- {
- typedef ImplementsHelper<> Type;
- };
- // Specialization handles unadorned interfaces
- template <typename I0, typename ...TInterfaces>
- struct ImplementsHelper<I0, TInterfaces...> :
- I0,
- AdjustImplements<TInterfaces...>::Type
- {
- template <typename ...> friend struct ImplementsHelper;
- friend class RuntimeClassBase;
- protected:
- HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) noexcept
- {
- // Prefer InlineIsEqualGUID over other forms since it's better perf on 4-byte aligned data, which is almost always the case.
- if (InlineIsEqualGUID(riid, __uuidof(I0)))
- {
- *ppv = reinterpret_cast<I0*>(reinterpret_cast<void*>(this));
- return S_OK;
- }
- return AdjustImplements<TInterfaces...>::Type::CanCastTo(riid, ppv, pRefDelegated);
- }
- IUnknown* CastToUnknown() noexcept
- {
- return reinterpret_cast<I0*>(reinterpret_cast<void*>(this));
- }
- };
- // Selector is used to "tag" base interfaces to be used in casting, since a runtime class may indirectly derive from
- // the same interface or Implements<> template multiple times
- template <typename base, typename disciminator>
- struct Selector : public base
- {
- };
- // Specialization handles types that derive from ImplementsHelper (e.g. nested Implements).
- template <typename I0, typename ...TInterfaces>
- struct ImplementsHelper<ImplementsMarker<I0>, TInterfaces...> :
- Selector<I0, ImplementsHelper<ImplementsMarker<I0>, TInterfaces...>>,
- Selector<typename AdjustImplements<TInterfaces...>::Type, ImplementsHelper<ImplementsMarker<I0>, TInterfaces...>>
- {
- template <typename ...> friend struct ImplementsHelper;
- friend class RuntimeClassBase;
- protected:
- typedef Selector<I0, ImplementsHelper<ImplementsMarker<I0>, TInterfaces...>> CurrentType;
- typedef Selector<typename AdjustImplements<TInterfaces...>::Type, ImplementsHelper<ImplementsMarker<I0>, TInterfaces...>> BaseType;
- HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) noexcept
- {
- HRESULT hr = CurrentType::CanCastTo(riid, ppv);
- if (hr == E_NOINTERFACE)
- {
- hr = BaseType::CanCastTo(riid, ppv, pRefDelegated);
- }
- return hr;
- }
- IUnknown* CastToUnknown() noexcept
- {
- // First in list wins.
- return CurrentType::CastToUnknown();
- }
- };
- // terminal case specialization.
- template <>
- struct ImplementsHelper<>
- {
- template <typename ...> friend struct ImplementsHelper;
- friend class RuntimeClassBase;
- protected:
- HRESULT CanCastTo(_In_ REFIID /*riid*/, _Outptr_ void ** /*ppv*/, bool * /*pRefDelegated*/ = nullptr) noexcept
- {
- return E_NOINTERFACE;
- }
- // IUnknown* CastToUnknown() noexcept; // not defined for terminal case.
- };
- // Specialization handles chaining interfaces
- template <typename C0, typename C1, typename C2, typename C3, typename C4, typename C5, typename C6, typename C7, typename C8, typename C9, typename ...TInterfaces>
- struct ImplementsHelper<ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>, TInterfaces...> :
- ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>,
- AdjustImplements<TInterfaces...>::Type
- {
- template <typename ...> friend struct ImplementsHelper;
- friend class RuntimeClassBase;
- protected:
- typedef typename AdjustImplements<TInterfaces...>::Type BaseType;
- HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) noexcept
- {
- HRESULT hr = ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>::CanCastTo(riid, ppv);
- if (FAILED(hr))
- {
- hr = BaseType::CanCastTo(riid, ppv, pRefDelegated);
- }
- return hr;
- }
- IUnknown* CastToUnknown() noexcept
- {
- return ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>::CastToUnknown();
- }
- };
- // Implements - template implementing QI using the information provided through its template parameters
- // Each template parameter has to be one of the following:
- // * COM Interface
- // * A class that implements one or more COM interfaces
- // * ChainInterfaces template
- template <typename I0, typename ...TInterfaces>
- struct Implements :
- AdjustImplements<I0, TInterfaces...>::Type,
- ImplementsBase
- {
- public:
- typedef I0 FirstInterface;
- protected:
- typedef typename AdjustImplements<I0, TInterfaces...>::Type BaseType;
- template <typename ...> friend struct ImplementsHelper;
- friend class RuntimeClassBase;
- HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv) noexcept
- {
- return BaseType::CanCastTo(riid, ppv);
- }
- IUnknown* CastToUnknown() noexcept
- {
- return BaseType::CastToUnknown();
- }
- };
- // Used on RuntimeClass to protect it from being constructed with new
- class DontUseNewUseMake
- {
- private:
- void* operator new(size_t) noexcept
- {
- assert(false);
- return 0;
- }
- public:
- void* operator new(size_t, _In_ void* placement) noexcept
- {
- return placement;
- }
- };
- template <typename ...TInterfaces>
- class RuntimeClassImpl :
- public AdjustImplements<TInterfaces...>::Type,
- public RuntimeClassBase,
- public DontUseNewUseMake
- {
- public:
- STDMETHOD(QueryInterface)(REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject)
- {
- return Super::AsIID(this, riid, ppvObject);
- }
- STDMETHOD_(ULONG, AddRef)()
- {
- return InternalAddRef();
- }
- STDMETHOD_(ULONG, Release)()
- {
- ULONG ref = InternalRelease();
- if (ref == 0)
- {
- this->~RuntimeClassImpl();
- delete[] reinterpret_cast<char*>(this);
- }
- return ref;
- }
- protected:
- using Super = RuntimeClassBase;
- static const LONG c_lProtectDestruction = -(LONG_MAX / 2);
- RuntimeClassImpl() noexcept = default;
- virtual ~RuntimeClassImpl() noexcept
- {
- // Set refcount_ to -(LONG_MAX/2) to protect destruction and
- // also catch mismatched Release in debug builds
- refcount_ = static_cast<ULONG>(c_lProtectDestruction);
- }
- ULONG InternalAddRef() noexcept
- {
- return ++refcount_;
- }
- ULONG InternalRelease() noexcept
- {
- return --refcount_;
- }
- unsigned long GetRefCount() const noexcept
- {
- return refcount_;
- }
- std::atomic<ULONG> refcount_{1};
- };
- }
- template <typename ...TInterfaces>
- class Base : public Details::RuntimeClassImpl<TInterfaces...>
- {
- Base(const Base&) = delete;
- Base& operator=(const Base&) = delete;
- protected:
- HRESULT CustomQueryInterface(REFIID /*riid*/, _Outptr_result_nullonfailure_ void** /*ppvObject*/, _Out_ bool *handled)
- {
- *handled = false;
- return S_OK;
- }
- public:
- Base() throw() = default;
- typedef Base RuntimeClassT;
- };
- // Creates a Nano-COM object wrapped in a smart pointer.
- template <typename T, typename ...TArgs>
- ComPtr<T> Make(TArgs&&... args)
- {
- std::unique_ptr<char[]> buffer(new(std::nothrow) char[sizeof(T)]);
- ComPtr<T> object;
- if (buffer)
- {
- T* ptr = new (buffer.get())T(std::forward<TArgs>(args)...);
- object.Attach(ptr);
- buffer.release();
- }
- return object;
- }
- using Details::ChainInterfaces;
- }
- }
- // Overloaded global function to provide to IID_PPV_ARGS that support Details::ComPtrRef
- template<typename T>
- void** IID_PPV_ARGS_Helper(Microsoft::WRL::Details::ComPtrRef<T> pp) throw()
- {
- return pp;
- }
|