| /** |
| * This file has no copyright assigned and is placed in the Public Domain. |
| * This file is part of the mingw-w64 runtime package. |
| * No warranty is given; refer to the file DISCLAIMER.PD within this package. |
| */ |
| |
| #ifndef _WRL_CLIENT_H_ |
| #define _WRL_CLIENT_H_ |
| |
| #include <stddef.h> |
| #include <unknwn.h> |
| /* #include <weakreference.h> */ |
| #include <roapi.h> |
| |
| /* #include <wrl/def.h> */ |
| #include <wrl/internal.h> |
| |
| namespace Microsoft { |
| namespace WRL { |
| namespace Details { |
| template <typename T> class ComPtrRefBase { |
| protected: |
| T* ptr_; |
| |
| public: |
| typedef typename T::InterfaceType InterfaceType; |
| |
| #ifndef __WRL_CLASSIC_COM__ |
| operator IInspectable**() const throw() { |
| static_assert(__is_base_of(IInspectable, InterfaceType), "Invalid cast"); |
| return reinterpret_cast<IInspectable**>(ptr_->ReleaseAndGetAddressOf()); |
| } |
| #endif |
| |
| operator IUnknown**() const throw() { |
| static_assert(__is_base_of(IUnknown, InterfaceType), "Invalid cast"); |
| return reinterpret_cast<IUnknown**>(ptr_->ReleaseAndGetAddressOf()); |
| } |
| }; |
| |
| template <typename T> class ComPtrRef : public Details::ComPtrRefBase<T> { |
| public: |
| ComPtrRef(T *ptr) throw() { |
| ComPtrRefBase<T>::ptr_ = ptr; |
| } |
| |
| operator void**() const throw() { |
| return reinterpret_cast<void**>(ComPtrRefBase<T>::ptr_->ReleaseAndGetAddressOf()); |
| } |
| |
| operator T*() throw() { |
| *ComPtrRefBase<T>::ptr_ = nullptr; |
| return ComPtrRefBase<T>::ptr_; |
| } |
| |
| operator typename ComPtrRefBase<T>::InterfaceType**() throw() { |
| return ComPtrRefBase<T>::ptr_->ReleaseAndGetAddressOf(); |
| } |
| |
| typename ComPtrRefBase<T>::InterfaceType *operator*() throw() { |
| return ComPtrRefBase<T>::ptr_->Get(); |
| } |
| |
| typename ComPtrRefBase<T>::InterfaceType *const *GetAddressOf() const throw() { |
| return ComPtrRefBase<T>::ptr_->GetAddressOf(); |
| } |
| |
| typename ComPtrRefBase<T>::InterfaceType **ReleaseAndGetAddressOf() throw() { |
| return ComPtrRefBase<T>::ptr_->ReleaseAndGetAddressOf(); |
| } |
| }; |
| |
| } |
| |
| template<typename T> class ComPtr { |
| public: |
| typedef T InterfaceType; |
| |
| ComPtr() throw() : ptr_(nullptr) {} |
| ComPtr(decltype(nullptr)) throw() : ptr_(nullptr) {} |
| |
| template<class U> ComPtr(U *other) throw() : ptr_(other) { |
| InternalAddRef(); |
| } |
| |
| ComPtr(const ComPtr &other) throw() : ptr_(other.ptr_) { |
| InternalAddRef(); |
| } |
| |
| template<class U> |
| ComPtr(const ComPtr<U> &other) throw() : ptr_(other.Get()) { |
| InternalAddRef(); |
| } |
| |
| ComPtr(ComPtr &&other) throw() : ptr_(nullptr) { |
| if(this != reinterpret_cast<ComPtr*>(&reinterpret_cast<unsigned char&>(other))) |
| Swap(other); |
| } |
| |
| template<class U> |
| ComPtr(ComPtr<U>&& other) throw() : ptr_(other.Detach()) {} |
| |
| ~ComPtr() throw() { |
| InternalRelease(); |
| } |
| |
| ComPtr &operator=(decltype(nullptr)) throw() { |
| InternalRelease(); |
| return *this; |
| } |
| |
| ComPtr &operator=(InterfaceType *other) throw() { |
| if (ptr_ != other) { |
| InternalRelease(); |
| ptr_ = other; |
| InternalAddRef(); |
| } |
| return *this; |
| } |
| |
| template<typename U> |
| ComPtr &operator=(U *other) throw() { |
| if (ptr_ != other) { |
| InternalRelease(); |
| ptr_ = other; |
| InternalAddRef(); |
| } |
| 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=(ComPtr &&other) throw() { |
| ComPtr(other).Swap(*this); |
| return *this; |
| } |
| |
| template<class U> |
| ComPtr& operator=(ComPtr<U> &&other) throw() { |
| ComPtr(other).Swap(*this); |
| return *this; |
| } |
| |
| void Swap(ComPtr &&r) throw() { |
| InterfaceType *tmp = ptr_; |
| ptr_ = r.ptr_; |
| r.ptr_ = tmp; |
| } |
| |
| void Swap(ComPtr &r) throw() { |
| InterfaceType *tmp = ptr_; |
| ptr_ = r.ptr_; |
| r.ptr_ = tmp; |
| } |
| |
| operator Details::BoolType() const throw() { |
| return Get() != nullptr ? &Details::BoolStruct::Member : nullptr; |
| } |
| |
| InterfaceType *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); |
| } |
| |
| InterfaceType *const *GetAddressOf() const throw() { |
| return &ptr_; |
| } |
| |
| InterfaceType **GetAddressOf() throw() { |
| return &ptr_; |
| } |
| |
| InterfaceType **ReleaseAndGetAddressOf() throw() { |
| InternalRelease(); |
| return &ptr_; |
| } |
| |
| InterfaceType *Detach() throw() { |
| T* ptr = ptr_; |
| ptr_ = nullptr; |
| return ptr; |
| } |
| |
| void Attach(InterfaceType *other) throw() { |
| if (ptr_ != other) { |
| InternalRelease(); |
| ptr_ = other; |
| InternalAddRef(); |
| } |
| } |
| |
| unsigned long Reset() { |
| return InternalRelease(); |
| } |
| |
| HRESULT CopyTo(InterfaceType **ptr) const throw() { |
| InternalAddRef(); |
| *ptr = ptr_; |
| return S_OK; |
| } |
| |
| HRESULT CopyTo(REFIID riid, void **ptr) const throw() { |
| return ptr_->QueryInterface(riid, ptr); |
| } |
| |
| template<typename U> |
| HRESULT CopyTo(U **ptr) const throw() { |
| return ptr_->QueryInterface(__uuidof(U), reinterpret_cast<void**>(ptr)); |
| } |
| |
| template<typename U> |
| HRESULT As(Details::ComPtrRef<ComPtr<U>> p) const throw() { |
| return ptr_->QueryInterface(__uuidof(U), p); |
| } |
| |
| template<typename U> |
| HRESULT As(ComPtr<U> *p) const throw() { |
| return ptr_->QueryInterface(__uuidof(U), reinterpret_cast<void**>(p->ReleaseAndGetAddressOf())); |
| } |
| |
| HRESULT AsIID(REFIID riid, ComPtr<IUnknown> *p) const throw() { |
| return ptr_->QueryInterface(riid, reinterpret_cast<void**>(p->ReleaseAndGetAddressOf())); |
| } |
| |
| /* |
| HRESULT AsWeak(WeakRef *pWeakRef) const throw() { |
| return ::Microsoft::WRL::AsWeak(ptr_, pWeakRef); |
| } |
| */ |
| protected: |
| InterfaceType *ptr_; |
| |
| void InternalAddRef() const throw() { |
| if(ptr_) |
| ptr_->AddRef(); |
| } |
| |
| unsigned long InternalRelease() throw() { |
| InterfaceType *tmp = ptr_; |
| if(!tmp) |
| return 0; |
| ptr_ = nullptr; |
| return tmp->Release(); |
| } |
| }; |
| } |
| } |
| |
| template<typename T> |
| void **IID_PPV_ARGS_Helper(::Microsoft::WRL::Details::ComPtrRef<T> pp) throw() { |
| static_assert(__is_base_of(IUnknown, typename T::InterfaceType), "Expected COM interface"); |
| return pp; |
| } |
| |
| namespace Windows { |
| namespace Foundation { |
| template<typename T> |
| inline HRESULT ActivateInstance(HSTRING classid, ::Microsoft::WRL::Details::ComPtrRef<T> instance) throw() { |
| return ActivateInstance(classid, instance.ReleaseAndGetAddressOf()); |
| } |
| |
| template<typename T> |
| inline HRESULT GetActivationFactory(HSTRING classid, ::Microsoft::WRL::Details::ComPtrRef<T> factory) throw() { |
| return RoGetActivationFactory(classid, IID_INS_ARGS(factory.ReleaseAndGetAddressOf())); |
| } |
| } |
| } |
| |
| namespace ABI { |
| namespace Windows { |
| namespace Foundation { |
| template<typename T> |
| inline HRESULT ActivateInstance(HSTRING classid, ::Microsoft::WRL::Details::ComPtrRef<T> instance) throw() { |
| return ActivateInstance(classid, instance.ReleaseAndGetAddressOf()); |
| } |
| |
| template<typename T> |
| inline HRESULT GetActivationFactory(HSTRING classid, ::Microsoft::WRL::Details::ComPtrRef<T> factory) throw() { |
| return RoGetActivationFactory(classid, IID_INS_ARGS(factory.ReleaseAndGetAddressOf())); |
| } |
| } |
| } |
| } |
| |
| #endif |