blob: 83b4cb327003037df829767d266fcc2f65d72dd9 [file] [log] [blame]
/**
* 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.ptr_) {
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.ptr_) {
other.ptr_ = nullptr;
}
~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