| Server IP : 209.209.40.120 / Your IP : 216.73.217.112 Web Server : Microsoft-IIS/10.0 System : Windows NT NEWWWW 10.0 build 17763 (Windows Server 2019) i586 User : NEWWWW$ ( 0) PHP Version : 8.3.30 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /Program Files (x86)/Windows Kits/10/Include/10.0.19041.0/winrt/wrl/ |
Upload File : |
//
// Copyright (C) Microsoft Corporation
// All rights reserved.
//
// Code in Details namespace is for internal usage within the library code
//
#ifndef _WRL_IMPLEMENTS_H_
#define _WRL_IMPLEMENTS_H_
#ifdef _MSC_VER
#pragma once
#endif // _MSC_VER
#pragma region includes
#include <inspectable.h>
#include <roapi.h>
#ifdef BUILD_WINDOWS
#include <winrt.h>
#endif
#include <activation.h>
#include <WinString.h>
#include <new.h>
#include <weakreference.h>
#include <objbase.h> // IMarshal
#include <cguid.h> // CLSID_StdGlobalInterfaceTable
#include <intrin.h>
#include <wrl\def.h>
#include <wrl\client.h>
#if (NTDDI_VERSION >= NTDDI_WINBLUE)
#include "roerrorapi.h"
#endif // (NTDDI_VERSION >= NTDDI_WINBLUE)
// Set packing
#include <pshpack8.h>
#pragma endregion
#ifndef __WRL_NO_DEFAULT_LIB__
#pragma comment(lib, "ole32.lib") // For CoTaskMemAlloc
#endif
#pragma region disable warnings
#pragma warning(push)
#pragma warning(disable: 4584) // 'class1' : base-class 'class2' is already a base-class of 'class3'
#pragma warning(disable: 4481) // nonstandard extension used: override specifier 'override'
#pragma endregion // disable warnings
namespace Microsoft {
namespace WRL {
// Indicator for RuntimeClass,Implements and ChainInterfaces that T interface
// will be not accessible on IID list
// Example:
// struct MyRuntimeClass : RuntimeClass<CloakedIid<IMyCloakedInterface>> {}
template<typename T>
struct CloakedIid : T
{
};
enum RuntimeClassType
{
WinRt = 0x0001,
ClassicCom = 0x0002,
WinRtClassicComMix = WinRt | ClassicCom,
InhibitWeakReference = 0x0004,
Delegate = ClassicCom,
InhibitFtmBase = 0x0008,
InhibitRoOriginateError = 0x0010
};
template <unsigned int flags>
struct RuntimeClassFlags
{
static const unsigned int value = flags;
};
namespace Details
{
// Empty struct used for validating template parameter types in Implements
struct ImplementsBase
{
};
} // namespace Details
// MixIn modifier allows to combine QI from
// a class that doesn't have default constructor on it
template<typename Derived, typename MixInType, bool hasImplements = __is_base_of(Details::ImplementsBase, MixInType)>
struct MixIn
{
};
// ComposableBase template to allow deriving from a RuntimeClass
// Optionally allows specifying the base factory and statics interface
template <typename FactoryInterface = IInspectable>
class ComposableBase
{
};
// Back-compat indicator for RuntimeClass to not support IWeakReferenceSource
typedef RuntimeClassFlags<WinRt | InhibitWeakReference> InhibitWeakReferencePolicy;
template<unsigned int RuntimeClassTypeT>
struct ErrorHelper
{
static void OriginateError(HRESULT hr, HSTRING message)
{
#if (NTDDI_VERSION >= NTDDI_WINBLUE)
::RoOriginateError(hr, message);
#else
UNREFERENCED_PARAMETER(hr);
UNREFERENCED_PARAMETER(message);
#endif // (NTDDI_VERSION >= NTDDI_WINBLUE)
}
};
template<>
struct ErrorHelper<InhibitRoOriginateError>
{
static void OriginateError(HRESULT hr, HSTRING message)
{
UNREFERENCED_PARAMETER(hr);
UNREFERENCED_PARAMETER(message);
// No-Op
}
};
namespace Details
{
//Forward declaration
struct CreatorMap;
// Sections automatically generate a list of pointers to CreatorMap through the linker
// Sections a and z are used as a terminators
#pragma section("minATL$__a", read)
// Section f is used to put com objects to creator map
#pragma section("minATL$__f", read)
// Section m divides COM entries from WinRT entries
#pragma section("minATL$__m", read)
// Section r is used to put WinRT objects to creator map
#pragma section("minATL$__r", read)
#pragma section("minATL$__z", read)
extern "C"
{
// Location of the first and last entries for the linker generated list of pointers to CreatorMapEntry
__declspec(selectany) __declspec(allocate("minATL$__a")) const CreatorMap* __pobjectentryfirst = nullptr;
// Section m divides COM objects from WinRT objects
// - sections between a and m we store COM object info
// - sections between m+1 and z we store WinRT object info
__declspec(selectany) __declspec(allocate("minATL$__m")) const CreatorMap* __pobjectentrymid = nullptr;
__declspec(selectany) __declspec(allocate("minATL$__z")) const CreatorMap* __pobjectentrylast = nullptr;
}
// Base class used by all module classes.
class __declspec(novtable) ModuleBase
{
private:
// Lock that synchronize access and termination of factories
static void* moduleLock_;
static_assert(sizeof(moduleLock_) == sizeof(SRWLOCK), "cacheLock must have the same size as SRWLOCK");
protected:
static volatile unsigned long objectCount_;
public:
static ModuleBase *module_;
ModuleBase() throw()
{
#ifdef _DEBUG
// WRLs support for activatable classes requires there is only one instance of Module<>, this assert
// ensures there is only one. Since Module<> is templatized, using different template parameters will
// result in multiple instances, avoid this by making sure all code in a component uses the same parameters.
// Note that the C++ CX runtime creates an instance; Module<InProc, Platform::Details::InProcModule>,
// so mixing it with non CX code can result in this assert.
// WRL supports static and dynamically allocated Module<>, choose dynamic by defining __WRL_DISABLE_STATIC_INITIALIZE__
// and allocate that instance with new but only once, for example in the main() entry point of an application.
__WRL_ASSERT__(::InterlockedCompareExchangePointer(reinterpret_cast<void* volatile*>(&module_), this, nullptr) == nullptr &&
"The module was already instantiated");
SRWLOCK initSRWLOCK = SRWLOCK_INIT;
__WRL_ASSERT__(reinterpret_cast<SRWLOCK*>(&moduleLock_)->Ptr == initSRWLOCK.Ptr && "Different value for moduleLock_ than SRWLOCK_INIT");
(initSRWLOCK);
#else
module_ = this;
#endif
}
ModuleBase(const ModuleBase&) = delete;
ModuleBase& operator=(const ModuleBase&) = delete;
virtual ~ModuleBase() throw()
{
#ifdef _DEBUG
__WRL_ASSERT__(::InterlockedCompareExchangePointer(reinterpret_cast<void* volatile*>(&module_), nullptr, this) == this &&
"The module was already instantiated");
#else
module_ = nullptr;
#endif
}
// Number of active objects in the module
STDMETHOD_(unsigned long, IncrementObjectCount)() = 0;
STDMETHOD_(unsigned long, DecrementObjectCount)() = 0;
STDMETHOD_(unsigned long, GetObjectCount)() const
{
return objectCount_;
}
STDMETHOD_(const CreatorMap**, GetFirstEntryPointer)() const
{
return &__pobjectentryfirst;
}
STDMETHOD_(const CreatorMap**, GetMidEntryPointer)() const
{
return &__pobjectentrymid;
}
STDMETHOD_(const CreatorMap**, GetLastEntryPointer)() const
{
return &__pobjectentrylast;
}
STDMETHOD_(SRWLOCK*, GetLock)() const
{
return reinterpret_cast<SRWLOCK*>(&moduleLock_);
}
STDMETHOD(RegisterWinRTObject)(_In_opt_z_ const wchar_t*, _In_z_ const wchar_t** activatableClassIds, _Inout_ RO_REGISTRATION_COOKIE* cookie, unsigned int) = 0;
STDMETHOD(UnregisterWinRTObject)(_In_opt_z_ const wchar_t*, _In_ RO_REGISTRATION_COOKIE) = 0;
STDMETHOD(RegisterCOMObject)(_In_opt_z_ const wchar_t*, _In_ IID*, _In_ IClassFactory**, _Inout_ DWORD*, unsigned int) = 0;
STDMETHOD(UnregisterCOMObject)(_In_opt_z_ const wchar_t*, _Inout_ DWORD*, unsigned int) = 0;
};
__declspec(selectany) volatile unsigned long ModuleBase::objectCount_ = 0;
// moduleLock_ value must be equal SRWLOCK_INIT which is nullptr
__declspec(selectany) void* ModuleBase::moduleLock_ = nullptr;
__declspec(selectany) ModuleBase *ModuleBase::module_ = nullptr;
#pragma region helper types
// Empty struct used as default template parameter
class Nil
{
};
// Used on RuntimeClass to protect it from being constructed with new
class DontUseNewUseMake
{
private:
void* operator new(size_t) throw()
{
__WRL_ASSERT__(false);
return 0;
}
public:
void* operator new(size_t, _In_ void* placement) throw()
{
return placement;
}
};
// RuntimeClassBase is used for detection of RuntimeClass in Make method
class RuntimeClassBase
{
};
// RuntimeClassBaseT provides helper methods for QI and getting IIDs
template <unsigned int RuntimeClassTypeT>
class RuntimeClassBaseT : private RuntimeClassBase
{
protected:
template<typename T>
static HRESULT AsIID(_In_ T* implements, REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject) throw()
{
*ppvObject = nullptr;
#pragma warning(push)
// Conditional expression is constant
#pragma warning(disable: 4127)
// Potential comparison of a constant with another constant
#pragma warning(disable: 6326)
// Conditional check using template parameter is constant and can be used to optimize the code
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)) || ((RuntimeClassTypeT & WinRt) != 0 && InlineIsEqualGUID(riid, __uuidof(IInspectable))))
#pragma warning(pop)
{
*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();
}
#pragma warning(suppress: 6102) // '*ppvObject' is used but may not be initialized
_Analysis_assume_(SUCCEEDED(hr) || (*ppvObject == nullptr));
return hr;
}
template<typename T>
static HRESULT GetImplementedIIDS(
_In_ T* implements,
_Out_ ULONG *iidCount,
_When_(*iidCount == 0, _At_(*iids, _Post_null_))
_When_(*iidCount > 0, _At_(*iids, _Post_notnull_))
_Result_nullonfailure_ IID **iids) throw()
{
*iids = nullptr;
*iidCount = 0;
unsigned long count = implements->GetIidCount();
// If there is no iids the CoTaskMemAlloc don't have to be called
if (count == 0)
{
return S_OK;
}
IID* iidArray = reinterpret_cast<IID*>(::CoTaskMemAlloc(sizeof(IID) * count));
if (iidArray == nullptr)
{
return E_OUTOFMEMORY;
}
unsigned long index = 0;
// assign the IIDs to the array
implements->FillArrayWithIid(&index, iidArray);
__WRL_ASSERT__(index == count);
// and return it
*iidCount = count;
*iids = iidArray;
return S_OK;
}
public:
HRESULT RuntimeClassInitialize() throw()
{
return S_OK;
}
};
// Base class required to mark FtmBase
class FtmBaseMarker
{
};
// Verifies that I is derived from specified base
template <unsigned int type, typename I, bool doStrictCheck = true, bool isImplementsBased = __is_base_of(ImplementsBase, I)>
struct VerifyInterfaceHelper;
// Specialization for ClassicCom interface
template <typename I, bool doStrictCheck>
struct VerifyInterfaceHelper<ClassicCom, I, doStrictCheck, false>
{
static void Verify() throw()
{
#ifdef __WRL_STRICT__
// Make sure that your interfaces inherit from IUnknown and are not IUnknown and/or IInspectable based
// The IUnknown is allowed only on RuntimeClass as first template parameter
static_assert(__is_base_of(IUnknown, I) && !__is_base_of(IInspectable, I) && !(doStrictCheck && IsSame<IUnknown, I>::value),
"'I' has to derive from 'IUnknown' and not from 'IInspectable'. 'I' must not be IUnknown.");
#else
static_assert(__is_base_of(IUnknown, I), "'I' has to derive from 'IUnknown'.");
#endif
}
};
// Specialization for WinRtClassicComMix interface
template <typename I, bool doStrictCheck>
struct VerifyInterfaceHelper<WinRtClassicComMix, I, doStrictCheck, false>
{
static void Verify() throw()
{
#ifdef __WRL_STRICT__
// Make sure that your interfaces inherit from IUnknown and are not IUnknown and/or IInspectable
// except when IInspectable is the first template parameter
static_assert(__is_base_of(IUnknown, I) &&
(doStrictCheck ? !(IsSame<IInspectable, I>::value || IsSame<IUnknown, I>::value) : __is_base_of(IInspectable, I)),
"'I' has to derive from 'IUnknown' and must not be IUnknown and/or IInspectable.");
#else
static_assert(__is_base_of(IUnknown, I), "'I' has to derive from 'IUnknown'.");
#endif
}
};
// Specialization for WinRt interface
template <typename I, bool doStrictCheck>
struct VerifyInterfaceHelper<WinRt, I, doStrictCheck, false>
{
static void Verify() throw()
{
#ifdef __WRL_STRICT__
// IWeakReferenceSource is exception for WinRt and can be used however it cannot be first templated interface
// Make sure that your interfaces inherit from IInspectable and are not IInspectable
// The IInspectable is allowed only on RuntimeClass as first template parameter
static_assert((__is_base_of(IWeakReferenceSource, I) && doStrictCheck) ||
(__is_base_of(IInspectable, I) && !(doStrictCheck && IsSame<IInspectable, I>::value)),
"'I' has to derive from 'IWeakReferenceSource' or 'IInspectable' and must not be IInspectable");
#else
// IWeakReference and IWeakReferneceSource are exceptions for WinRT
static_assert(__is_base_of(IWeakReference, I) ||
__is_base_of(IWeakReferenceSource, I) ||
__is_base_of(IInspectable, I), "'I' has to derive from 'IWeakReference', 'IWeakReferenceSource' or 'IInspectable'");
#endif
}
};
// Specialization for Implements passed as template parameter
template <unsigned int type, typename I>
struct VerifyInterfaceHelper<type, I, true, true>
{
static void Verify() throw()
{
#ifdef __WRL_STRICT__
// Verifies if Implements has correct RuntimeClassFlags setting
// Allow using FtmBase on classes configured with RuntimeClassFlags<WinRt> (Default configuration)
static_assert(I::ClassFlags::value == type ||
type == WinRtClassicComMix ||
__is_base_of(::Microsoft::WRL::Details::FtmBaseMarker, I),
"Implements class must have the same and/or compatibile flags configuration");
#endif
}
};
// Specialization for Implements passed as first template parameter
template <unsigned int type, typename I>
struct VerifyInterfaceHelper<type, I, false, true>
{
static void Verify() throw()
{
#ifdef __WRL_STRICT__
// Verifies if Implements has correct RuntimeClassFlags setting
static_assert(I::ClassFlags::value == type || type == WinRtClassicComMix,
"Implements class must have the same and/or compatible flags configuration."
"If you use WRL::FtmBase it cannot be specified as first template parameter on RuntimeClass");
// Besides make sure that the first interface on Implements meet flags requirement
VerifyInterfaceHelper<type, I::FirstInterface, false>::Verify();
#endif
}
};
// Interface traits provides casting and filling iids methods helpers
template<typename I0>
struct __declspec(novtable) InterfaceTraits
{
typedef I0 Base;
static const unsigned long IidCount = 1;
template<unsigned int ClassType>
static void Verify() throw()
{
VerifyInterfaceHelper<ClassType & WinRtClassicComMix, Base>::Verify();
}
template<typename T>
static Base* CastToBase(_In_ T* ptr) throw()
{
return static_cast<Base*>(ptr);
}
template<typename T>
static IUnknown* CastToUnknown(_In_ T* ptr) throw()
{
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) throw()
{
// 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;
}
static void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw()
{
*(iids + *index) = __uuidof(Base);
(*index)++;
}
};
// Specialization of traits for cloaked interface
template<typename CloakedType>
struct __declspec(novtable) InterfaceTraits<CloakedIid<CloakedType>>
{
typedef CloakedType Base;
static const unsigned long IidCount = 0;
template<unsigned int ClassType>
static void Verify() throw()
{
VerifyInterfaceHelper<ClassType & WinRtClassicComMix, Base>::Verify();
}
template<typename T>
static Base* CastToBase(_In_ T* ptr) throw()
{
return static_cast<Base*>(ptr);
}
template<typename T>
static IUnknown* CastToUnknown(_In_ T* ptr) throw()
{
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) throw()
{
// 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;
}
// Cloaked specialization makes it always IID list empty
static void FillArrayWithIid(_Inout_ unsigned long*, _Inout_ IID*) throw()
{
}
};
// Specialization for Nil parameter
template<>
struct __declspec(novtable) InterfaceTraits<Nil>
{
typedef Nil Base;
static const unsigned long IidCount = 0;
template<unsigned int ClassType>
static void Verify() throw()
{
}
static void FillArrayWithIid(_Inout_ unsigned long *, _Inout_ IID*) throw()
{
}
template <typename T>
_Success_(return == true)
static bool CanCastTo(_In_ T*, REFIID, _Outptr_ void **) throw()
{
return false;
}
};
// Verify inheritance
template <typename I, typename Base>
struct VerifyInheritanceHelper
{
static void Verify() throw()
{
static_assert(Details::IsBaseOfStrict<typename InterfaceTraits<Base>::Base, typename InterfaceTraits<I>::Base>::value, "'I' needs to inherit from 'Base'.");
}
};
template <typename I>
struct VerifyInheritanceHelper<I, Nil>
{
static void Verify() throw()
{
}
};
#pragma endregion // helper types
} // namespace Details
inline Details::ModuleBase* GetModuleBase() throw()
{
return Details::ModuleBase::module_;
}
// 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 = Details::Nil, typename I3 = Details::Nil,
typename I4 = Details::Nil, typename I5 = Details::Nil, typename I6 = Details::Nil,
typename I7 = Details::Nil, typename I8 = Details::Nil, typename I9 = Details::Nil>
struct ChainInterfaces : I0
{
protected:
template<unsigned int ClassType>
static void Verify() throw()
{
Details::InterfaceTraits<I0>::template Verify<ClassType>();
Details::InterfaceTraits<I1>::template Verify<ClassType>();
Details::InterfaceTraits<I2>::template Verify<ClassType>();
Details::InterfaceTraits<I3>::template Verify<ClassType>();
Details::InterfaceTraits<I4>::template Verify<ClassType>();
Details::InterfaceTraits<I5>::template Verify<ClassType>();
Details::InterfaceTraits<I6>::template Verify<ClassType>();
Details::InterfaceTraits<I7>::template Verify<ClassType>();
Details::InterfaceTraits<I8>::template Verify<ClassType>();
Details::InterfaceTraits<I9>::template Verify<ClassType>();
Details::VerifyInheritanceHelper<I0, I1>::Verify();
Details::VerifyInheritanceHelper<I0, I2>::Verify();
Details::VerifyInheritanceHelper<I0, I3>::Verify();
Details::VerifyInheritanceHelper<I0, I4>::Verify();
Details::VerifyInheritanceHelper<I0, I5>::Verify();
Details::VerifyInheritanceHelper<I0, I6>::Verify();
Details::VerifyInheritanceHelper<I0, I7>::Verify();
Details::VerifyInheritanceHelper<I0, I8>::Verify();
Details::VerifyInheritanceHelper<I0, I9>::Verify();
}
HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv) throw()
{
typename Details::InterfaceTraits<I0>::Base* ptr = Details::InterfaceTraits<I0>::CastToBase(this);
return (Details::InterfaceTraits<I0>::CanCastTo(this, riid, ppv) ||
Details::InterfaceTraits<I1>::CanCastTo(ptr, riid, ppv) ||
Details::InterfaceTraits<I2>::CanCastTo(ptr, riid, ppv) ||
Details::InterfaceTraits<I3>::CanCastTo(ptr, riid, ppv) ||
Details::InterfaceTraits<I4>::CanCastTo(ptr, riid, ppv) ||
Details::InterfaceTraits<I5>::CanCastTo(ptr, riid, ppv) ||
Details::InterfaceTraits<I6>::CanCastTo(ptr, riid, ppv) ||
Details::InterfaceTraits<I7>::CanCastTo(ptr, riid, ppv) ||
Details::InterfaceTraits<I8>::CanCastTo(ptr, riid, ppv) ||
Details::InterfaceTraits<I9>::CanCastTo(ptr, riid, ppv)) ? S_OK : E_NOINTERFACE;
}
IUnknown* CastToUnknown() throw()
{
return Details::InterfaceTraits<I0>::CastToUnknown(this);
}
static const unsigned long IidCount =
Details::InterfaceTraits<I0>::IidCount +
Details::InterfaceTraits<I1>::IidCount +
Details::InterfaceTraits<I2>::IidCount +
Details::InterfaceTraits<I3>::IidCount +
Details::InterfaceTraits<I4>::IidCount +
Details::InterfaceTraits<I5>::IidCount +
Details::InterfaceTraits<I6>::IidCount +
Details::InterfaceTraits<I7>::IidCount +
Details::InterfaceTraits<I8>::IidCount +
Details::InterfaceTraits<I9>::IidCount;
static void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw()
{
Details::InterfaceTraits<I0>::FillArrayWithIid(index, iids);
Details::InterfaceTraits<I1>::FillArrayWithIid(index, iids);
Details::InterfaceTraits<I2>::FillArrayWithIid(index, iids);
Details::InterfaceTraits<I3>::FillArrayWithIid(index, iids);
Details::InterfaceTraits<I4>::FillArrayWithIid(index, iids);
Details::InterfaceTraits<I5>::FillArrayWithIid(index, iids);
Details::InterfaceTraits<I6>::FillArrayWithIid(index, iids);
Details::InterfaceTraits<I7>::FillArrayWithIid(index, iids);
Details::InterfaceTraits<I8>::FillArrayWithIid(index, iids);
Details::InterfaceTraits<I9>::FillArrayWithIid(index, iids);
}
};
template <typename DerivedType, typename BaseType, bool hasImplements, typename I1, typename I2, typename I3,
typename I4, typename I5, typename I6,
typename I7, typename I8, typename I9>
struct ChainInterfaces<MixIn<DerivedType, BaseType, hasImplements>, I1, I2, I3, I4, I5, I6, I7, I8, I9>
{
static_assert(!hasImplements, "Cannot use ChainInterfaces<MixIn<...>> to Mix a class implementing interfaces using \"Implements\"");
protected:
template<unsigned int ClassType>
static void Verify() throw()
{
Details::InterfaceTraits<BaseType>::template Verify<ClassType>();
Details::InterfaceTraits<I1>::template Verify<ClassType>();
Details::InterfaceTraits<I2>::template Verify<ClassType>();
Details::InterfaceTraits<I3>::template Verify<ClassType>();
Details::InterfaceTraits<I4>::template Verify<ClassType>();
Details::InterfaceTraits<I5>::template Verify<ClassType>();
Details::InterfaceTraits<I6>::template Verify<ClassType>();
Details::InterfaceTraits<I7>::template Verify<ClassType>();
Details::InterfaceTraits<I8>::template Verify<ClassType>();
Details::InterfaceTraits<I9>::template Verify<ClassType>();
Details::VerifyInheritanceHelper<BaseType, I1>::Verify();
Details::VerifyInheritanceHelper<BaseType, I2>::Verify();
Details::VerifyInheritanceHelper<BaseType, I3>::Verify();
Details::VerifyInheritanceHelper<BaseType, I4>::Verify();
Details::VerifyInheritanceHelper<BaseType, I5>::Verify();
Details::VerifyInheritanceHelper<BaseType, I6>::Verify();
Details::VerifyInheritanceHelper<BaseType, I7>::Verify();
Details::VerifyInheritanceHelper<BaseType, I8>::Verify();
Details::VerifyInheritanceHelper<BaseType, I9>::Verify();
}
HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv) throw()
{
BaseType* ptr = static_cast<BaseType*>(static_cast<DerivedType*>(this));
return (
Details::InterfaceTraits<I1>::CanCastTo(ptr, riid, ppv) ||
Details::InterfaceTraits<I2>::CanCastTo(ptr, riid, ppv) ||
Details::InterfaceTraits<I3>::CanCastTo(ptr, riid, ppv) ||
Details::InterfaceTraits<I4>::CanCastTo(ptr, riid, ppv) ||
Details::InterfaceTraits<I5>::CanCastTo(ptr, riid, ppv) ||
Details::InterfaceTraits<I6>::CanCastTo(ptr, riid, ppv) ||
Details::InterfaceTraits<I7>::CanCastTo(ptr, riid, ppv) ||
Details::InterfaceTraits<I8>::CanCastTo(ptr, riid, ppv) ||
Details::InterfaceTraits<I9>::CanCastTo(ptr, riid, ppv)) ? S_OK : E_NOINTERFACE;
}
// It's not possible to cast to IUnknown when Base interface inherit more interfaces
// The RuntimeClass is taking always the first interface as IUnknown thus it's required to
// list IInspectable or IUnknown class before MixIn<Derived, MixInType> parameter, such as:
// struct MyRuntimeClass : RuntimeClass<IInspectable, ChainInterfaces<MixIn<MyRuntimeClass,MyIndependentImplementation>, IFoo, IBar>, MyIndependentImplementation {}
IUnknown* CastToUnknown() throw() = delete;
static const unsigned long IidCount =
Details::InterfaceTraits<I1>::IidCount +
Details::InterfaceTraits<I2>::IidCount +
Details::InterfaceTraits<I3>::IidCount +
Details::InterfaceTraits<I4>::IidCount +
Details::InterfaceTraits<I5>::IidCount +
Details::InterfaceTraits<I6>::IidCount +
Details::InterfaceTraits<I7>::IidCount +
Details::InterfaceTraits<I8>::IidCount +
Details::InterfaceTraits<I9>::IidCount;
static void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw()
{
Details::InterfaceTraits<I1>::FillArrayWithIid(index, iids);
Details::InterfaceTraits<I2>::FillArrayWithIid(index, iids);
Details::InterfaceTraits<I3>::FillArrayWithIid(index, iids);
Details::InterfaceTraits<I4>::FillArrayWithIid(index, iids);
Details::InterfaceTraits<I5>::FillArrayWithIid(index, iids);
Details::InterfaceTraits<I6>::FillArrayWithIid(index, iids);
Details::InterfaceTraits<I7>::FillArrayWithIid(index, iids);
Details::InterfaceTraits<I8>::FillArrayWithIid(index, iids);
Details::InterfaceTraits<I9>::FillArrayWithIid(index, iids);
}
};
namespace Details
{
#pragma region Implements helper templates
// Helper template used by Implements. This template traverses a list of interfaces and adds them as base class and information
// to enable QI. doStrictCheck is typically false only for the first interface, allowing IInspectable to be explicitly specified
// only as the first interface.
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces>
struct __declspec(novtable) ImplementsHelper;
template <typename T>
struct __declspec(novtable) ImplementsMarker
{};
template <typename I0, bool isImplements>
struct __declspec(novtable) MarkImplements;
template <typename I0>
struct __declspec(novtable) MarkImplements<I0, false>
{
typedef I0 Type;
};
template <typename I0>
struct __declspec(novtable) MarkImplements<I0, true>
{
typedef ImplementsMarker<I0> Type;
};
template <typename I0>
struct __declspec(novtable) MarkImplements<CloakedIid<I0>, true>
{
// Cloaked Implements type will be handled in the nested processing.
// Applying the ImplementsMarker too early will bypass Cloaked behavior.
typedef CloakedIid<I0> Type;
};
template <typename DerivedType, typename BaseType, bool hasImplements>
struct __declspec(novtable) MarkImplements<MixIn<DerivedType, BaseType, hasImplements>, true>
{
// Implements type in mix-ins will be handled in the nested processing.
typedef MixIn<DerivedType, BaseType, hasImplements> Type;
};
// AdjustImplements pre-processes the type list for more efficient builds.
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...Bases>
struct __declspec(novtable) AdjustImplements;
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename I0, typename ...Bases>
struct __declspec(novtable) AdjustImplements<RuntimeClassFlagsT, doStrictCheck, I0, Bases...>
{
typedef ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, typename MarkImplements<I0, __is_base_of(ImplementsBase, I0)>::Type, Bases...> Type;
};
// Use AdjustImplements to remove instances of "Details::Nil" from the type list.
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...Bases>
struct __declspec(novtable) AdjustImplements<RuntimeClassFlagsT, doStrictCheck, typename Details::Nil, Bases...>
{
typedef typename AdjustImplements<RuntimeClassFlagsT, doStrictCheck, Bases...>::Type Type;
};
template <typename RuntimeClassFlagsT, bool doStrictCheck>
struct __declspec(novtable) AdjustImplements<RuntimeClassFlagsT, doStrictCheck>
{
typedef ImplementsHelper<RuntimeClassFlagsT, doStrictCheck> Type;
};
// Specialization handles unadorned interfaces
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename I0, typename ...TInterfaces>
struct __declspec(novtable) ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, I0, TInterfaces...> :
I0,
AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type
{
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct ImplementsHelper;
template <unsigned int RuntimeClassTypeT> friend class RuntimeClassBaseT;
protected:
HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) throw()
{
VerifyInterfaceHelper<RuntimeClassFlagsT::value & WinRtClassicComMix, I0, doStrictCheck>::Verify();
// 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<RuntimeClassFlagsT, true, TInterfaces...>::Type::CanCastTo(riid, ppv, pRefDelegated);
}
IUnknown* CastToUnknown() throw()
{
return reinterpret_cast<I0*>(reinterpret_cast<void*>(this));
}
unsigned long GetIidCount() throw()
{
return 1 + AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type::GetIidCount();
}
// FillArrayWithIid
void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw()
{
*(iids + *index) = __uuidof(I0);
(*index)++;
AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type::FillArrayWithIid(index, iids);
}
};
// 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 __declspec(novtable) Selector : public base
{
};
// Specialization handles types that derive from ImplementsHelper (e.g. nested Implements).
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename I0, typename ...TInterfaces>
struct __declspec(novtable) ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, ImplementsMarker<I0>, TInterfaces...> :
Selector<I0, ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, ImplementsMarker<I0>, TInterfaces...>>,
Selector<typename AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type, ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, ImplementsMarker<I0>, TInterfaces...>>
{
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct ImplementsHelper;
template <unsigned int RuntimeClassTypeT> friend class RuntimeClassBaseT;
protected:
typedef Selector<I0, ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, ImplementsMarker<I0>, TInterfaces...>> CurrentType;
typedef Selector<typename AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type, ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, ImplementsMarker<I0>, TInterfaces...>> BaseType;
HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) throw()
{
VerifyInterfaceHelper<RuntimeClassFlagsT::value & WinRtClassicComMix, I0, doStrictCheck>::Verify();
HRESULT hr = CurrentType::CanCastTo(riid, ppv);
if (hr == E_NOINTERFACE)
{
hr = BaseType::CanCastTo(riid, ppv, pRefDelegated);
}
return hr;
}
IUnknown* CastToUnknown() throw()
{
// First in list wins.
return CurrentType::CastToUnknown();
}
unsigned long GetIidCount() throw()
{
return CurrentType::GetIidCount() + BaseType::GetIidCount();
}
// FillArrayWithIid
void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw()
{
CurrentType::FillArrayWithIid(index, iids);
BaseType::FillArrayWithIid(index, iids);
}
};
// CloakedIid instance. Since the first "real" interface should be checked against doStrictCheck,
// pass this through unchanged. Two specializations for cloaked prevent the need to use the Selector
// used in the Implements<> case. The same can't be done there because some type ambiguities are unavoidable.
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename I0, typename I1, typename ...TInterfaces>
struct __declspec(novtable) ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, CloakedIid<I0>, I1, TInterfaces...> :
AdjustImplements<RuntimeClassFlagsT, doStrictCheck, I0>::Type,
AdjustImplements<RuntimeClassFlagsT, true, I1, TInterfaces...>::Type
{
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct ImplementsHelper;
template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT;
protected:
typedef typename AdjustImplements<RuntimeClassFlagsT, doStrictCheck, I0>::Type CurrentType;
typedef typename AdjustImplements<RuntimeClassFlagsT, true, I1, TInterfaces...>::Type BaseType;
HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) throw()
{
VerifyInterfaceHelper<RuntimeClassFlagsT::value & WinRtClassicComMix, I0, doStrictCheck>::Verify();
HRESULT hr = CurrentType::CanCastTo(riid, ppv, pRefDelegated);
if (SUCCEEDED(hr))
{
return S_OK;
}
return BaseType::CanCastTo(riid, ppv, pRefDelegated);
}
IUnknown* CastToUnknown() throw()
{
return CurrentType::CastToUnknown();
}
// Don't expose the cloaked IID(s), but continue processing the rest of the interfaces
unsigned long GetIidCount() throw()
{
return BaseType::GetIidCount();
}
void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw()
{
BaseType::FillArrayWithIid(index, iids);
}
};
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename I0>
struct __declspec(novtable) ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, CloakedIid<I0>> :
AdjustImplements<RuntimeClassFlagsT, doStrictCheck, I0>::Type
{
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct ImplementsHelper;
template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT;
protected:
typedef typename AdjustImplements<RuntimeClassFlagsT, doStrictCheck, I0>::Type CurrentType;
HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) throw()
{
VerifyInterfaceHelper<RuntimeClassFlagsT::value & WinRtClassicComMix, I0, doStrictCheck>::Verify();
return CurrentType::CanCastTo(riid, ppv, pRefDelegated);
}
IUnknown* CastToUnknown() throw()
{
return CurrentType::CastToUnknown();
}
// Don't expose the cloaked IID(s), but continue processing the rest of the interfaces
unsigned long GetIidCount() throw()
{
return 0;
}
void FillArrayWithIid(_Inout_ unsigned long * /*index*/, _Inout_ IID* /*iids*/) throw()
{
// no-op
}
};
// terminal case specialization.
template <typename RuntimeClassFlagsT, bool doStrictCheck>
struct __declspec(novtable) ImplementsHelper<RuntimeClassFlagsT, doStrictCheck>
{
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct ImplementsHelper;
template <unsigned int RuntimeClassTypeT> friend class RuntimeClassBaseT;
protected:
template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT;
HRESULT CanCastTo(_In_ REFIID /*riid*/, _Outptr_ void ** /*ppv*/, bool * /*pRefDelegated*/ = nullptr) throw()
{
return E_NOINTERFACE;
}
// IUnknown* CastToUnknown() throw(); // not defined for terminal case.
unsigned long GetIidCount() throw()
{
return 0;
}
void FillArrayWithIid(_Inout_ unsigned long * /*index*/, _Inout_ IID* /*iids*/) throw()
{
}
};
// Specialization handles chaining interfaces
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename C0, typename C1, typename C2, typename C3, typename C4, typename C5, typename C6, typename C7, typename C8, typename C9, typename ...TInterfaces>
struct __declspec(novtable) ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>, TInterfaces...> :
ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>,
AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type
{
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct ImplementsHelper;
template <unsigned int RuntimeClassTypeT> friend class RuntimeClassBaseT;
protected:
template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT;
typedef typename AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type BaseType;
HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) throw()
{
ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>::template Verify<RuntimeClassFlagsT::value>();
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() throw()
{
return ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>::CastToUnknown();
}
unsigned long GetIidCount() throw()
{
return ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>::IidCount + BaseType::GetIidCount();
}
void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw()
{
ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>::FillArrayWithIid(index, iids);
BaseType::FillArrayWithIid(index, iids);
}
};
// Mixin specialization
template <typename RuntimeClassFlagsT, typename DerivedType, typename BaseMixInType, bool hasImplements, typename ...TInterfaces, bool doStrictCheck>
struct __declspec(novtable) ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, MixIn<DerivedType, BaseMixInType, hasImplements>, TInterfaces...> :
AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type
{
static_assert(hasImplements, "Cannot use MixIn to with a class not deriving from \"Implements\"");
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct ImplementsHelper;
template <unsigned int RuntimeClassTypeT> friend class RuntimeClassBaseT;
protected:
template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT;
typedef typename AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type BaseType;
HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) throw()
{
VerifyInterfaceHelper<RuntimeClassFlagsT::value & WinRtClassicComMix, BaseMixInType, doStrictCheck>::Verify();
HRESULT hr = static_cast<BaseMixInType*>(static_cast<DerivedType*>(this))->CanCastTo(riid, ppv);
if (FAILED(hr))
{
hr = BaseType::CanCastTo(riid, ppv, pRefDelegated);
}
return hr;
}
IUnknown* CastToUnknown() throw()
{
return static_cast<BaseMixInType*>(static_cast<DerivedType*>(this))->CastToUnknown();
}
unsigned long GetIidCount() throw()
{
return static_cast<BaseMixInType*>(static_cast<DerivedType*>(this))->GetIidCount() +
BaseType::GetIidCount();
}
void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw()
{
static_cast<BaseMixInType*>(static_cast<DerivedType*>(this))->FillArrayWithIid(index, iids);
BaseType::FillArrayWithIid(index, iids);
}
};
// Specialization handles inheriting COM objects. ComposableBase must be the last non-nil interface in the list.
// Trailing nil's are allowed for compatibility with some tools that pad out the list.
template <typename I0, typename ...>
struct AreAllNil
{
static const bool value = false;
};
template <typename ...TInterfaces>
struct AreAllNil<Microsoft::WRL::Details::Nil, TInterfaces...>
{
static const bool value = AreAllNil<TInterfaces...>::value;
};
template <>
struct AreAllNil<Microsoft::WRL::Details::Nil>
{
static const bool value = true;
};
template <typename RuntimeClassFlagsT, typename FactoryInterface, bool doStrictCheck, typename ...TInterfaces>
struct __declspec(novtable) ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, ComposableBase<FactoryInterface>, TInterfaces...> :
ImplementsHelper<RuntimeClassFlagsT, true, ComposableBase<FactoryInterface>>
{
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct ImplementsHelper;
template <unsigned int RuntimeClassTypeT> friend class RuntimeClassBaseT;
protected:
template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT;
typedef ImplementsHelper<RuntimeClassFlagsT, true, ComposableBase<FactoryInterface>> BaseType;
HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) throw()
{
static_assert(AreAllNil<TInterfaces...>::value, "ComposableBase should be the last template parameter to RuntimeClass");
return BaseType::CanCastTo(riid, ppv, pRefDelegated);
}
IUnknown* CastToUnknown() throw()
{
static_assert(AreAllNil<TInterfaces...>::value, "ComposableBase should be the last template parameter to RuntimeClass");
return BaseType::CastToUnknown();
}
unsigned long GetIidCount() throw()
{
static_assert(AreAllNil<TInterfaces...>::value, "ComposableBase should be the last template parameter to RuntimeClass");
return BaseType::GetIidCount();
}
void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw()
{
static_assert(AreAllNil<TInterfaces...>::value, "ComposableBase should be the last template parameter to RuntimeClass");
BaseType::FillArrayWithIid(index, iids);
}
};
template <typename RuntimeClassFlagsT, typename FactoryInterface, bool doStrictCheck>
struct __declspec(novtable) ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, ComposableBase<FactoryInterface>>
{
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct ImplementsHelper;
template <unsigned int RuntimeClassTypeT> friend class RuntimeClassBaseT;
protected:
template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT;
HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated) throw()
{
*pRefDelegated = true;
return composableBase_.CopyTo(riid, ppv);
}
IUnknown* CastToUnknown() throw()
{
return nullptr;
}
unsigned long GetIidCount() throw()
{
return iidCount_;
}
void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw()
{
for(unsigned long i = 0; i < iidCount_; i++)
{
*(iids + *index) = *(iidsCached_ + i);
(*index)++;
}
}
ImplementsHelper() throw() : iidsCached_(nullptr), iidCount_(0)
{
}
~ImplementsHelper() throw()
{
::CoTaskMemFree(iidsCached_);
iidsCached_ = nullptr;
iidCount_ = 0;
}
public:
HRESULT SetComposableBasePointers(_In_ IInspectable* base, _In_opt_ FactoryInterface* baseFactory = nullptr) throw()
{
if (composableBase_ != nullptr)
{
#if (NTDDI_VERSION >= NTDDI_WINBLUE)
ErrorHelper<RuntimeClassFlagsT::value & InhibitRoOriginateError>::OriginateError(E_UNEXPECTED, nullptr);
#endif // (NTDDI_VERSION >= NTDDI_WINBLUE)
return E_UNEXPECTED;
}
HRESULT hr = base->GetIids(&iidCount_, &iidsCached_);
if (SUCCEEDED(hr))
{
composableBase_ = base;
composableBaseFactory_ = baseFactory;
}
return hr;
}
ComPtr<IInspectable> GetComposableBase() throw()
{
return composableBase_;
}
ComPtr<FactoryInterface> GetComposableBaseFactory() throw()
{
return composableBaseFactory_;
}
private:
ComPtr<IInspectable> composableBase_;
ComPtr<FactoryInterface> composableBaseFactory_;
IID *iidsCached_;
unsigned long iidCount_;
};
#pragma endregion // Implements helper templates
} // namespace Details
// 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 __declspec(novtable) Implements :
Details::AdjustImplements<RuntimeClassFlags<WinRt>, true, I0, TInterfaces...>::Type,
Details::ImplementsBase
{
public:
typedef RuntimeClassFlags<WinRt> ClassFlags;
typedef I0 FirstInterface;
protected:
typedef typename Details::AdjustImplements<RuntimeClassFlags<WinRt>, true, I0, TInterfaces...>::Type BaseType;
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct Details::ImplementsHelper;
template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT;
HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv) throw()
{
return BaseType::CanCastTo(riid, ppv);
}
IUnknown* CastToUnknown() throw()
{
return BaseType::CastToUnknown();
}
unsigned long GetIidCount() throw()
{
return BaseType::GetIidCount();
}
void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw()
{
BaseType::FillArrayWithIid(index, iids);
}
};
template <int flags, typename I0, typename ...TInterfaces>
struct __declspec(novtable) Implements<RuntimeClassFlags<flags>, I0, TInterfaces...> :
Details::AdjustImplements<RuntimeClassFlags<flags>, true, I0, TInterfaces...>::Type,
Details::ImplementsBase
{
public:
typedef RuntimeClassFlags<flags> ClassFlags;
typedef I0 FirstInterface;
protected:
typedef typename Details::AdjustImplements<RuntimeClassFlags<flags>, true, I0, TInterfaces...>::Type BaseType;
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct Details::ImplementsHelper;
template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT;
HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv) throw()
{
return BaseType::CanCastTo(riid, ppv);
}
IUnknown* CastToUnknown() throw()
{
return BaseType::CastToUnknown();
}
unsigned long GetIidCount() throw()
{
return BaseType::GetIidCount();
}
void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw()
{
BaseType::FillArrayWithIid(index, iids);
}
};
class FtmBase :
public Implements<
::Microsoft::WRL::RuntimeClassFlags<WinRtClassicComMix>,
::Microsoft::WRL::CloakedIid< ::IMarshal> >,
// Inheriting from FtmBaseMarker allows using FtmBase on classes configured with RuntimeClassFlags<WinRt> (Default configuration)
private ::Microsoft::WRL::Details::FtmBaseMarker
{
// defining type 'Super' for other compilers since '__super' is a VC++-specific language extension
using Super = Implements<
::Microsoft::WRL::RuntimeClassFlags<WinRtClassicComMix>,
::Microsoft::WRL::CloakedIid< ::IMarshal> >;
protected:
template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct Details::ImplementsHelper;
HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv) throw()
{
// 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(::IAgileObject)))
{
*ppv = Super::CastToUnknown();
return S_OK;
}
return Super::CanCastTo(riid, ppv);
}
public:
FtmBase() throw()
{
ComPtr<IUnknown> unknown;
if (SUCCEEDED(::CoCreateFreeThreadedMarshaler(nullptr, &unknown)))
{
unknown.As(&marshaller_);
}
}
// IMarshal Methods
#pragma warning(suppress: 6101) // PREFast cannot see through the smart-pointer invocation
STDMETHOD(GetUnmarshalClass)(_In_ REFIID riid,
_In_opt_ void *pv,
_In_ DWORD dwDestContext,
_Reserved_ void *pvDestContext,
_In_ DWORD mshlflags,
_Out_ CLSID *pCid) override
{
if (marshaller_)
{
return marshaller_->GetUnmarshalClass(riid, pv, dwDestContext, pvDestContext, mshlflags, pCid);
}
return E_OUTOFMEMORY;
}
#pragma warning(suppress: 6101) // PREFast cannot see through the smart-pointer invocation
STDMETHOD(GetMarshalSizeMax)(_In_ REFIID riid, _In_opt_ void *pv, _In_ DWORD dwDestContext,
_Reserved_ void *pvDestContext, _In_ DWORD mshlflags, _Out_ DWORD *pSize) override
{
if (marshaller_)
{
return marshaller_->GetMarshalSizeMax(riid, pv, dwDestContext, pvDestContext, mshlflags, pSize);
}
return E_OUTOFMEMORY;
}
STDMETHOD(MarshalInterface)(_In_ IStream *pStm, _In_ REFIID riid, _In_opt_ void *pv, _In_ DWORD dwDestContext,
_Reserved_ void *pvDestContext, _In_ DWORD mshlflags) override
{
if (marshaller_)
{
return marshaller_->MarshalInterface(pStm, riid, pv, dwDestContext, pvDestContext, mshlflags);
}
return E_OUTOFMEMORY;
}
#pragma warning(suppress: 6101) // PREFast cannot see through the smart-pointer invocation
STDMETHOD(UnmarshalInterface)(_In_ IStream *pStm, _In_ REFIID riid, _Outptr_ void **ppv) override
{
if (marshaller_)
{
return marshaller_->UnmarshalInterface(pStm, riid, ppv);
}
return E_OUTOFMEMORY;
}
STDMETHOD(ReleaseMarshalData)(_In_ IStream *pStm) override
{
if (marshaller_)
{
return marshaller_->ReleaseMarshalData(pStm);
}
return E_OUTOFMEMORY;
}
STDMETHOD(DisconnectObject)(_In_ DWORD dwReserved) override
{
if (marshaller_)
{
return marshaller_->DisconnectObject(dwReserved);
}
return E_OUTOFMEMORY;
}
static HRESULT CreateGlobalInterfaceTable(_Out_ IGlobalInterfaceTable **git) throw()
{
*git = nullptr;
return ::CoCreateInstance(CLSID_StdGlobalInterfaceTable,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IGlobalInterfaceTable),
reinterpret_cast<void**>(git));
}
::Microsoft::WRL::ComPtr<IMarshal> marshaller_; // Holds a reference to the free threaded marshaler
};
namespace Details
{
#ifdef _PERF_COUNTERS
class __declspec(novtable) PerfCountersBase
{
public:
ULONG GetAddRefCount() throw()
{
return addRefCount_;
}
ULONG GetReleaseCount() throw()
{
return releaseCount_;
}
ULONG GetQueryInterfaceCount() throw()
{
return queryInterfaceCount_;
}
void ResetPerfCounters() throw()
{
addRefCount_ = 0;
releaseCount_ = 0;
queryInterfaceCount_ = 0;
}
protected:
PerfCountersBase() throw() :
addRefCount_(0),
releaseCount_(0),
queryInterfaceCount_(0)
{
}
void IncrementAddRefCount() throw()
{
InterlockedIncrement(&addRefCount_);
}
void IncrementReleaseCount() throw()
{
InterlockedIncrement(&releaseCount_);
}
void IncrementQueryInterfaceCount() throw()
{
InterlockedIncrement(&queryInterfaceCount_);
}
private:
volatile unsigned long addRefCount_;
volatile unsigned long releaseCount_;
volatile unsigned long queryInterfaceCount_;
};
#endif
#if defined(_X86_) || defined(_AMD64_)
#define UnknownIncrementReference InterlockedIncrement
#define UnknownDecrementReference InterlockedDecrement
#define UnknownBarrierAfterInterlock()
#define UnknownInterlockedCompareExchangePointer InterlockedCompareExchangePointer
#define UnknownInterlockedCompareExchangePointerForIncrement InterlockedCompareExchangePointer
#define UnknownInterlockedCompareExchangePointerForRelease InterlockedCompareExchangePointer
#elif defined(_ARM_)
#define UnknownIncrementReference InterlockedIncrementNoFence
#define UnknownDecrementReference InterlockedDecrementRelease
#define UnknownBarrierAfterInterlock() __dmb(_ARM_BARRIER_ISH)
#define UnknownInterlockedCompareExchangePointer InterlockedCompareExchangePointer
#define UnknownInterlockedCompareExchangePointerForIncrement InterlockedCompareExchangePointerNoFence
#define UnknownInterlockedCompareExchangePointerForRelease InterlockedCompareExchangePointerRelease
#elif defined(_ARM64_)
#define UnknownIncrementReference InterlockedIncrementNoFence
#define UnknownDecrementReference InterlockedDecrementRelease
#define UnknownBarrierAfterInterlock() __dmb(_ARM64_BARRIER_ISH)
#define UnknownInterlockedCompareExchangePointer InterlockedCompareExchangePointer
#define UnknownInterlockedCompareExchangePointerForIncrement InterlockedCompareExchangePointerNoFence
#define UnknownInterlockedCompareExchangePointerForRelease InterlockedCompareExchangePointerRelease
#else
#error Unsupported architecture.
#endif
// Since variadic templates can't have a parameter pack after default arguments, provide a convenient helper for defaults.
#define DETAILS_RTCLASS_FLAGS_ARGUMENTS(RuntimeClassFlagsT) \
RuntimeClassFlagsT, \
(RuntimeClassFlagsT::value & InhibitWeakReference) == 0, \
(RuntimeClassFlagsT::value & WinRt) == WinRt, \
__WRL_IMPLEMENTS_FTM_BASE__(RuntimeClassFlagsT::value) \
template <class RuntimeClassFlagsT, bool implementsWeakReferenceSource, bool implementsInspectable, bool implementsFtmBase, typename ...TInterfaces>
class __declspec(novtable) RuntimeClassImpl;
#pragma warning(push)
// PREFast cannot see through template instantiation for AsIID()
#pragma warning(disable: 6388)
template <class RuntimeClassFlagsT, bool implementsWeakReferenceSource, bool implementsFtmBase, typename ...TInterfaces>
class __declspec(novtable) RuntimeClassImpl<RuntimeClassFlagsT, implementsWeakReferenceSource, false, implementsFtmBase, TInterfaces...> :
public Details::AdjustImplements<RuntimeClassFlagsT, false, TInterfaces...>::Type,
public RuntimeClassBaseT<RuntimeClassFlagsT::value>,
protected RuntimeClassFlags<InhibitWeakReference>,
public DontUseNewUseMake
#ifdef _PERF_COUNTERS
, public PerfCountersBase
#endif
{
public:
typedef RuntimeClassFlagsT ClassFlags;
STDMETHOD(QueryInterface)(REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject)
{
#ifdef _PERF_COUNTERS
IncrementQueryInterfaceCount();
#endif
return Super::AsIID(this, riid, ppvObject);
}
STDMETHOD_(ULONG, AddRef)()
{
return InternalAddRef();
}
STDMETHOD_(ULONG, Release)()
{
ULONG ref = InternalRelease();
if (ref == 0)
{
delete this;
auto modulePtr = ::Microsoft::WRL::GetModuleBase();
if (modulePtr != nullptr)
{
modulePtr->DecrementObjectCount();
}
}
return ref;
}
protected:
using Super = RuntimeClassBaseT<RuntimeClassFlagsT::value>;
RuntimeClassImpl() throw() : refcount_(1)
{
}
virtual ~RuntimeClassImpl() throw()
{
// Set refcount_ to -(LONG_MAX/2) to protect destruction and
// also catch mismatched Release in debug builds
refcount_ = -(LONG_MAX/2);
}
unsigned long InternalAddRef() throw()
{
#ifdef _PERF_COUNTERS
IncrementAddRefCount();
#endif
return UnknownIncrementReference(&refcount_);
}
unsigned long InternalRelease() throw()
{
#ifdef _PERF_COUNTERS
IncrementReleaseCount();
#endif
// A release fence is required to ensure all guarded memory accesses are
// complete before any thread can begin destroying the object.
unsigned long newValue = UnknownDecrementReference(&refcount_);
if (newValue == 0)
{
// An acquire fence is required before object destruction to ensure
// that the destructor cannot observe values changing on other threads.
UnknownBarrierAfterInterlock();
}
return newValue;
}
unsigned long GetRefCount() const throw()
{
return refcount_;
}
friend class WeakReferenceImpl;
private:
volatile long refcount_;
};
template<typename I, bool isImplementsBased = __is_base_of(ImplementsBase, I)>
struct HasIInspectable;
template<typename I>
struct HasIInspectable<I, false>
{
static const bool isIInspectable = __is_base_of(IInspectable, I);
};
template<typename I>
struct HasIInspectable<I, true>
{
static const bool isIInspectable = HasIInspectable<typename I::FirstInterface>::isIInspectable;
};
#ifdef __WRL_STRICT__
template<typename I0, bool isIInspectable = true>
#else
template<typename I0, bool isIInspectable = HasIInspectable<I0>::isIInspectable>
#endif
struct IInspectableInjector;
template<typename I0>
struct IInspectableInjector<I0, true>
{
typedef Details::Nil InspectableIfNeeded;
};
template<typename I0>
struct IInspectableInjector<I0, false>
{
typedef IInspectable InspectableIfNeeded;
};
// Implements IInspectable in ILst
template <class RuntimeClassFlagsT, typename I0, typename ...TInterfaces>
class __declspec(novtable) RuntimeClassImpl<RuntimeClassFlagsT, false, true, false, I0, TInterfaces...> :
public Details::AdjustImplements<RuntimeClassFlagsT, false, typename IInspectableInjector<I0>::InspectableIfNeeded, I0, TInterfaces...>::Type,
public RuntimeClassBaseT<RuntimeClassFlagsT::value>,
protected RuntimeClassFlags<InhibitWeakReference>,
public DontUseNewUseMake
#ifdef _PERF_COUNTERS
, public PerfCountersBase
#endif
{
public:
typedef RuntimeClassFlagsT ClassFlags;
STDMETHOD(QueryInterface)(REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject)
{
#ifdef _PERF_COUNTERS
IncrementQueryInterfaceCount();
#endif
return Super::AsIID(this, riid, ppvObject);
}
STDMETHOD_(ULONG, AddRef)()
{
return InternalAddRef();
}
STDMETHOD_(ULONG, Release)()
{
ULONG ref = InternalRelease();
if (ref == 0)
{
delete this;
auto modulePtr = ::Microsoft::WRL::GetModuleBase();
if (modulePtr != nullptr)
{
modulePtr->DecrementObjectCount();
}
}
return ref;
}
// IInspectable methods
STDMETHOD(GetIids)(
_Out_ ULONG *iidCount,
_When_(*iidCount == 0, _At_(*iids, _Post_null_))
_When_(*iidCount > 0, _At_(*iids, _Post_notnull_))
_Result_nullonfailure_ IID **iids)
{
return Super::GetImplementedIIDS(this, iidCount, iids);
}
#if !defined(__WRL_STRICT__) || !defined(__WRL_FORCE_INSPECTABLE_CLASS_MACRO__)
STDMETHOD(GetRuntimeClassName)(_Out_ HSTRING* runtimeClassName)
{
*runtimeClassName = nullptr;
__WRL_ASSERT__(false && "Use InspectableClass macro to set runtime class name and trust level.");
#if (NTDDI_VERSION >= NTDDI_WINBLUE)
ErrorHelper<RuntimeClassFlagsT::value & InhibitRoOriginateError>::OriginateError(E_NOTIMPL, nullptr);
#endif // (NTDDI_VERSION >= NTDDI_WINBLUE)
return E_NOTIMPL;
}
STDMETHOD(GetTrustLevel)(_Out_ ::TrustLevel*)
{
__WRL_ASSERT__(false && "Use InspectableClass macro to set runtime class name and trust level.");
#if (NTDDI_VERSION >= NTDDI_WINBLUE)
ErrorHelper<RuntimeClassFlagsT::value & InhibitRoOriginateError>::OriginateError(E_NOTIMPL, nullptr);
#endif // (NTDDI_VERSION >= NTDDI_WINBLUE)
return E_NOTIMPL;
}
#endif // !defined(__WRL_STRICT__) || !defined(__WRL_FORCE_INSPECTABLE_CLASS_MACRO__)
protected:
using Super = RuntimeClassBaseT<RuntimeClassFlagsT::value>;
RuntimeClassImpl() throw() : refcount_(1)
{
}
virtual ~RuntimeClassImpl() throw()
{
// Set refcount_ to -(LONG_MAX/2) to protect destruction and
// also catch mismatched Release in debug builds
refcount_ = -(LONG_MAX/2);
}
unsigned long InternalAddRef() throw()
{
#ifdef _PERF_COUNTERS
IncrementAddRefCount();
#endif
return UnknownIncrementReference(&refcount_);
}
unsigned long InternalRelease() throw()
{
#ifdef _PERF_COUNTERS
IncrementReleaseCount();
#endif
// A release fence is required to ensure all guarded memory accesses are
// complete before any thread can begin destroying the object.
unsigned long newValue = UnknownDecrementReference(&refcount_);
if (newValue == 0)
{
// An acquire fence is required before object destruction to ensure
// that the destructor cannot observe values changing on other threads.
UnknownBarrierAfterInterlock();
}
return newValue;
}
unsigned long GetRefCount() const throw()
{
return refcount_;
}
private:
volatile long refcount_;
};
class StrongReference
{
public:
StrongReference(long refCount = 1) throw() : strongRefCount_(refCount) {}
~StrongReference() throw()
{
// Set refcount_ to -(LONG_MAX/2) to protect destruction and
// also catch mismatched Release in debug builds
strongRefCount_ = -(LONG_MAX / 2);
}
unsigned long IncrementStrongReference() throw()
{
return UnknownIncrementReference(&strongRefCount_);
}
unsigned long DecrementStrongReference() throw()
{
// A release fence is required to ensure all guarded memory accesses are
// complete before any thread can begin destroying the object.
unsigned long newValue = UnknownDecrementReference(&strongRefCount_);
if (newValue == 0)
{
// An acquire fence is required before object destruction to ensure
// that the destructor cannot observe values changing on other threads.
UnknownBarrierAfterInterlock();
}
return newValue;
}
unsigned long GetStrongReferenceCount() throw()
{
return strongRefCount_;
}
void SetStrongReference(unsigned long value) throw()
{
strongRefCount_ = value;
}
long strongRefCount_;
};
// To support storing, encoding and decoding reference-count/pointers regardless of the target platform.
// In a RuntimeClass, the refCount_ member can mean either
// 1. actual reference count
// 2. pointer to the weak reference object which holds the strong count
// The member
// 1. If it is a count, the most significant bit will be OFF
// 2. If it is an encoded pointer to the weak reference, the most significant bit will be turned ON
// To test which mode it is
// 1. Test for negative
// 2. If it is, it is an encoded pointer to the weak reference
// 3. If it is not, it is the actual reference count
// To yield the encoded pointer
// 1. Test the value for negative
// 2. If it is, shift the value to the left and cast it to a WeakReferenceImpl*
//
const UINT_PTR EncodeWeakReferencePointerFlag = static_cast<UINT_PTR>(1) << ((sizeof(UINT_PTR) * 8) - 1);
union ReferenceCountOrWeakReferencePointer
{
// Represents the count when it is a count (in practice only the least significant 4 bytes)
UINT_PTR refCount;
// Pointer size, *signed* to help with ease of casting and such
INT_PTR rawValue;
// The hint that this could also be a pointer
void* ifHighBitIsSetThenShiftLeftToYieldPointerToWeakReference;
};
// Helper methods to test, decode and decode the different representations of ReferenceCountOrWeakReferencePointer
inline bool IsValueAPointerToWeakReference(INT_PTR value)
{
return value < 0;
}
// Forward declaration
class WeakReferenceImpl;
inline INT_PTR EncodeWeakReferencePointer(Microsoft::WRL::Details::WeakReferenceImpl* value);
inline Microsoft::WRL::Details::WeakReferenceImpl* DecodeWeakReferencePointer(INT_PTR value);
// Helper functions, originally from winnt.h, needed to get the semantics right when fetching values
// in multi-threaded scenarios. This is in order to guarantee the compiler emits exactly one read
// (compiler may decide to re-fetch the value later on, which in some cases can break code)
#if defined(_ARM_)
FORCEINLINE
LONG
ReadULongPtrNoFence (
_In_ _Interlocked_operand_ DWORD const volatile *Source
)
{
LONG Value;
Value = __iso_volatile_load32((int *)Source);
return Value;
}
#elif defined(_ARM64_)
FORCEINLINE
LONG64
ReadULongPtrNoFence (
_In_ _Interlocked_operand_ DWORD64 const volatile *Source
)
{
LONG64 Value;
Value = __iso_volatile_load64((__int64 *)Source);
return Value;
}
#elif defined(_X86_)
FORCEINLINE
LONG
ReadULongPtrNoFence (
_In_ _Interlocked_operand_ DWORD const volatile *Source
)
{
LONG Value;
Value = *Source;
return Value;
}
#elif defined(_AMD64_)
FORCEINLINE
LONG64
ReadULongPtrNoFence (
_In_ _Interlocked_operand_ DWORD64 const volatile *Source
)
{
LONG64 Value;
Value = *Source;
return Value;
}
#else
#error Unsupported architecture.
#endif
template <typename T>
inline T ReadValueFromPointerNoFence(_In_ const volatile T* value)
{
ULONG_PTR currentValue = ReadULongPtrNoFence(reinterpret_cast<const volatile ULONG_PTR *>(value));
const T* currentPointerToValue = reinterpret_cast<T*>(¤tValue);
return *currentPointerToValue;
}
inline WeakReferenceImpl* CreateWeakReference(_In_ IUnknown*);
// Implementation of activatable class that implements IWeakReferenceSource
// and delegates reference counting to WeakReferenceImpl object
template <class RuntimeClassFlagsT, typename I0, typename ...TInterfaces>
class __declspec(novtable) RuntimeClassImpl<RuntimeClassFlagsT, true, true, false, I0, TInterfaces...> :
public Details::AdjustImplements<RuntimeClassFlagsT, false, typename IInspectableInjector<I0>::InspectableIfNeeded, I0, IWeakReferenceSource, TInterfaces...>::Type,
public RuntimeClassBaseT<RuntimeClassFlagsT::value>,
public DontUseNewUseMake
#ifdef _PERF_COUNTERS
, public PerfCountersBase
#endif
{
public:
typedef RuntimeClassFlagsT ClassFlags;
RuntimeClassImpl() throw()
{
refCount_.rawValue = 1;
}
STDMETHOD(QueryInterface)(REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject)
{
#ifdef _PERF_COUNTERS
IncrementQueryInterfaceCount();
#endif
return Super::AsIID(this, riid, ppvObject);
}
STDMETHOD_(ULONG, AddRef)()
{
return InternalAddRef();
}
STDMETHOD_(ULONG, Release)()
{
ULONG ref = InternalRelease();
if (ref == 0)
{
delete this;
auto modulePtr = ::Microsoft::WRL::GetModuleBase();
if (modulePtr != nullptr)
{
modulePtr->DecrementObjectCount();
}
}
return ref;
}
// IInspectable methods
STDMETHOD(GetIids)(
_Out_ ULONG *iidCount,
_When_(*iidCount == 0, _At_(*iids, _Post_null_))
_When_(*iidCount > 0, _At_(*iids, _Post_notnull_))
_Result_nullonfailure_ IID **iids)
{
return Super::GetImplementedIIDS(this, iidCount, iids);
}
#if !defined(__WRL_STRICT__) || !defined(__WRL_FORCE_INSPECTABLE_CLASS_MACRO__)
STDMETHOD(GetRuntimeClassName)(_Out_ HSTRING* runtimeClassName)
{
*runtimeClassName = nullptr;
__WRL_ASSERT__(false && "Use InspectableClass macro to set runtime class name and trust level.");
#if (NTDDI_VERSION >= NTDDI_WINBLUE)
ErrorHelper<RuntimeClassFlagsT::value & InhibitRoOriginateError>::OriginateError(E_NOTIMPL, nullptr);
#endif // (NTDDI_VERSION >= NTDDI_WINBLUE)
return E_NOTIMPL;
}
STDMETHOD(GetTrustLevel)(_Out_ ::TrustLevel*)
{
__WRL_ASSERT__(false && "Use InspectableClass macro to set runtime class name and trust level.");
#if (NTDDI_VERSION >= NTDDI_WINBLUE)
ErrorHelper<RuntimeClassFlagsT::value & InhibitRoOriginateError>::OriginateError(E_NOTIMPL, nullptr);
#endif // (NTDDI_VERSION >= NTDDI_WINBLUE)
return E_NOTIMPL;
}
#endif // !defined(__WRL_STRICT__) || !defined(__WRL_FORCE_INSPECTABLE_CLASS_MACRO__)
STDMETHOD(GetWeakReference)(_Outptr_ IWeakReference **weakReference);
virtual ~RuntimeClassImpl() throw();
protected:
template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT;
using ImplementsHelper = typename Details::AdjustImplements<RuntimeClassFlagsT, false, typename IInspectableInjector<I0>::InspectableIfNeeded, I0, IWeakReferenceSource, TInterfaces...>::Type;
using Super = RuntimeClassBaseT<RuntimeClassFlagsT::value>;
unsigned long InternalAddRef() throw();
unsigned long InternalRelease() throw();
unsigned long GetRefCount() const throw();
friend class WeakReferenceImpl;
#ifdef __WRL_UNITTEST__
protected:
#else
private:
#endif
ReferenceCountOrWeakReferencePointer refCount_;
};
inline INT_PTR EncodeWeakReferencePointer(Microsoft::WRL::Details::WeakReferenceImpl* value)
{
return ((reinterpret_cast<INT_PTR>(value) >> 1) | EncodeWeakReferencePointerFlag);
}
inline Microsoft::WRL::Details::WeakReferenceImpl* DecodeWeakReferencePointer(INT_PTR value)
{
return reinterpret_cast<Microsoft::WRL::Details::WeakReferenceImpl*>(value << 1);
}
#pragma warning(pop) // C6388
template <class RuntimeClassFlagsT, typename I0, typename ...TInterfaces>
class __declspec(novtable) RuntimeClassImpl<RuntimeClassFlagsT, false, true, true, I0, TInterfaces...> :
public RuntimeClassImpl<RuntimeClassFlagsT, false, true, false, I0, TInterfaces...>
{
};
template <class RuntimeClassFlagsT, typename I0, typename ...TInterfaces>
class __declspec(novtable) RuntimeClassImpl<RuntimeClassFlagsT, true, true, true, I0, TInterfaces...> :
public RuntimeClassImpl<RuntimeClassFlagsT, true, true, false, I0, FtmBase, TInterfaces...>
{
};
// To minimize breaks with code written against WRL before variadic support was added, this form is maintained.
template <typename ...TInterfaces>
struct InterfaceListHelper
{
typedef InterfaceListHelper<TInterfaces...> TypeT;
};
template <
typename ILst,
class RuntimeClassFlagsT,
bool implementsWeakReferenceSource = (RuntimeClassFlagsT::value & InhibitWeakReference) == 0,
bool implementsInspectable = (RuntimeClassFlagsT::value & WinRt) == WinRt,
bool implementsFtmBase = __WRL_IMPLEMENTS_FTM_BASE__(RuntimeClassFlagsT::value)
>
class RuntimeClass;
template <
typename RuntimeClassFlagsT,
bool implementsWeakReferenceSource,
bool implementsInspectable,
bool implementsFtmBase,
typename ...TInterfaces
>
class RuntimeClass<InterfaceListHelper<TInterfaces...>, RuntimeClassFlagsT, implementsWeakReferenceSource, implementsInspectable, implementsFtmBase> :
public RuntimeClassImpl<RuntimeClassFlagsT, implementsWeakReferenceSource, implementsInspectable, implementsFtmBase, TInterfaces...>
{
protected:
HRESULT CustomQueryInterface(REFIID /*riid*/, _Outptr_result_nullonfailure_ void** /*ppvObject*/, _Out_ bool *handled)
{
*handled = false;
return S_OK;
}
};
} // namespace Details
// The RuntimeClass IUnknown methods
// It inherits from Details::RuntimeClass that provides helper methods for reference counting and
// collecting IIDs
template <typename ...TInterfaces>
class RuntimeClass :
public Details::RuntimeClassImpl<DETAILS_RTCLASS_FLAGS_ARGUMENTS(RuntimeClassFlags<WinRt>), TInterfaces...>
{
RuntimeClass(const RuntimeClass&);
RuntimeClass& operator=(const RuntimeClass&);
protected:
HRESULT CustomQueryInterface(REFIID /*riid*/, _Outptr_result_nullonfailure_ void** /*ppvObject*/, _Out_ bool *handled)
{
*handled = false;
return S_OK;
}
public:
RuntimeClass() throw()
{
auto modulePtr = ::Microsoft::WRL::GetModuleBase();
if (modulePtr != nullptr)
{
modulePtr->IncrementObjectCount();
}
}
typedef RuntimeClass RuntimeClassT;
};
template <unsigned int classFlags, typename ...TInterfaces>
class RuntimeClass<RuntimeClassFlags<classFlags>, TInterfaces...> :
public Details::RuntimeClassImpl<DETAILS_RTCLASS_FLAGS_ARGUMENTS(RuntimeClassFlags<classFlags>), TInterfaces...>
{
RuntimeClass(const RuntimeClass&);
RuntimeClass& operator=(const RuntimeClass&);
protected:
HRESULT CustomQueryInterface(REFIID /*riid*/, _Outptr_result_nullonfailure_ void** /*ppvObject*/, _Out_ bool *handled)
{
*handled = false;
return S_OK;
}
public:
RuntimeClass() throw()
{
auto modulePtr = ::Microsoft::WRL::GetModuleBase();
if (modulePtr != nullptr)
{
modulePtr->IncrementObjectCount();
}
}
typedef RuntimeClass RuntimeClassT;
};
namespace Details
{
// Weak reference implementation
class WeakReferenceImpl final :
public ::Microsoft::WRL::RuntimeClass<RuntimeClassFlags<ClassicCom>, IWeakReference>,
public StrongReference
{
public:
WeakReferenceImpl(_In_ IUnknown* unk) throw() : StrongReference(LONG_MAX / 2), unknown_(unk)
{
// Set ref count to 2 to avoid unnecessary interlocked increment operation while returning
// WeakReferenceImpl from GetWeakReference method. One reference is hold by the object the second is hold
// by the caller of GetWeakReference method.
refcount_ = 2;
}
virtual ~WeakReferenceImpl() throw()
{
}
STDMETHOD(Resolve)(REFIID riid, _Outptr_result_maybenull_ _Result_nullonfailure_ IInspectable **ppvObject)
{
*ppvObject = nullptr;
for(;;)
{
long ref = this->strongRefCount_;
if (ref == 0)
{
return S_OK;
}
// InterlockedCompareExchange calls _InterlockedCompareExchange intrinsic thus we call directly _InterlockedCompareExchange to save the call
if (::_InterlockedCompareExchange(&this->strongRefCount_, ref + 1, ref) == ref)
{
#ifdef _PERF_COUNTERS
// This artificially manipulates the strong ref count via AddRef to account for the resolve
// interlocked operation above when tallying reference counting operations.
unknown_->AddRef();
::_InterlockedDecrement(&this->strongRefCount_);
#endif
break;
}
}
HRESULT hr = unknown_->QueryInterface(riid, reinterpret_cast<void**>(ppvObject));
unknown_->Release();
return hr;
}
private:
IUnknown *unknown_;
};
template <class RuntimeClassFlagsT, typename I0, typename ...TInterfaces>
RuntimeClassImpl<RuntimeClassFlagsT, true, true, false, I0, TInterfaces...>::~RuntimeClassImpl() throw()
{
if (IsValueAPointerToWeakReference(refCount_.rawValue))
{
WeakReferenceImpl* weakRef = DecodeWeakReferencePointer(refCount_.rawValue);
weakRef->Release();
weakRef = nullptr;
}
}
template <class RuntimeClassFlagsT, typename I0, typename ...TInterfaces>
unsigned long RuntimeClassImpl<RuntimeClassFlagsT, true, true, false, I0, TInterfaces...>::GetRefCount() const throw()
{
ReferenceCountOrWeakReferencePointer currentValue = ReadValueFromPointerNoFence<ReferenceCountOrWeakReferencePointer>(&refCount_);
if (IsValueAPointerToWeakReference(currentValue.rawValue))
{
WeakReferenceImpl* weakRef = DecodeWeakReferencePointer(currentValue.rawValue);
return weakRef->GetStrongReferenceCount();
}
else
{
return static_cast<unsigned long>(currentValue.refCount);
}
}
template <class RuntimeClassFlagsT, typename I0, typename ...TInterfaces>
unsigned long RuntimeClassImpl<RuntimeClassFlagsT, true, true, false, I0, TInterfaces...>::InternalAddRef() throw()
{
#ifdef _PERF_COUNTERS
IncrementAddRefCount();
#endif
ReferenceCountOrWeakReferencePointer currentValue = ReadValueFromPointerNoFence<ReferenceCountOrWeakReferencePointer>(&refCount_);
for (;;)
{
if (!IsValueAPointerToWeakReference(currentValue.rawValue))
{
UINT_PTR updateValue = currentValue.refCount + 1;
#ifdef __WRL_UNITTEST__
OnBeforeInternalAddRefIncrement();
#endif
INT_PTR previousValue = reinterpret_cast<INT_PTR>(UnknownInterlockedCompareExchangePointerForIncrement(reinterpret_cast<PVOID*>(&(refCount_.refCount)), reinterpret_cast<PVOID>(updateValue), reinterpret_cast<PVOID>(currentValue.refCount)));
if (previousValue == currentValue.rawValue)
{
return static_cast<unsigned long>(updateValue);
}
currentValue.rawValue = previousValue;
}
else
{
WeakReferenceImpl* weakRef = DecodeWeakReferencePointer(currentValue.rawValue);
return weakRef->IncrementStrongReference();
}
}
}
template <class RuntimeClassFlagsT, typename I0, typename ...TInterfaces>
unsigned long RuntimeClassImpl<RuntimeClassFlagsT, true, true, false, I0, TInterfaces...>::InternalRelease() throw()
{
#ifdef _PERF_COUNTERS
IncrementReleaseCount();
#endif
ReferenceCountOrWeakReferencePointer currentValue = ReadValueFromPointerNoFence<ReferenceCountOrWeakReferencePointer>(&refCount_);
for (;;)
{
if (!IsValueAPointerToWeakReference(currentValue.rawValue))
{
UINT_PTR updateValue = currentValue.refCount - 1;
#ifdef __WRL_UNITTEST__
OnBeforeInternalReleaseDecrement();
#endif
INT_PTR previousValue = reinterpret_cast<INT_PTR>(UnknownInterlockedCompareExchangePointerForIncrement(reinterpret_cast<PVOID*>(&(refCount_.refCount)), reinterpret_cast<PVOID>(updateValue), reinterpret_cast<PVOID>(currentValue.refCount)));
if (previousValue == currentValue.rawValue)
{
return static_cast<unsigned long>(updateValue);
}
currentValue.rawValue = previousValue;
}
else
{
WeakReferenceImpl* weakRef = DecodeWeakReferencePointer(currentValue.rawValue);
return weakRef->DecrementStrongReference();
}
}
}
template <class RuntimeClassFlagsT, typename I0, typename ...TInterfaces>
HRESULT RuntimeClassImpl<RuntimeClassFlagsT, true, true, false, I0, TInterfaces...>::GetWeakReference(_Outptr_ IWeakReference **weakReference)
{
WeakReferenceImpl* weakRef = nullptr;
INT_PTR encodedWeakRef = 0;
ReferenceCountOrWeakReferencePointer currentValue = ReadValueFromPointerNoFence<ReferenceCountOrWeakReferencePointer>(&refCount_);
*weakReference = nullptr;
if (IsValueAPointerToWeakReference(currentValue.rawValue))
{
weakRef = DecodeWeakReferencePointer(currentValue.rawValue);
weakRef->AddRef();
*weakReference = weakRef;
return S_OK;
}
// WeakReferenceImpl is created with ref count 2 to avoid interlocked increment
weakRef = CreateWeakReference(ImplementsHelper::CastToUnknown());
if (weakRef == nullptr)
{
return E_OUTOFMEMORY;
}
encodedWeakRef = EncodeWeakReferencePointer(weakRef);
for (;;)
{
INT_PTR previousValue = 0;
weakRef->SetStrongReference(static_cast<unsigned long>(currentValue.refCount));
#ifdef __WRL_UNITTEST__
OnBeforeGetWeakReferenceSwap();
#endif
previousValue = reinterpret_cast<INT_PTR>(UnknownInterlockedCompareExchangePointer(reinterpret_cast<PVOID*>(&(this->refCount_.ifHighBitIsSetThenShiftLeftToYieldPointerToWeakReference)), reinterpret_cast<PVOID>(encodedWeakRef), currentValue.ifHighBitIsSetThenShiftLeftToYieldPointerToWeakReference));
if (previousValue == currentValue.rawValue)
{
// No need to call AddRef in this case, WeakReferenceImpl is created with ref count 2 to avoid interlocked increment
*weakReference = weakRef;
return S_OK;
}
else if (IsValueAPointerToWeakReference(previousValue))
{
// Another thread beat this call to create the weak reference.
delete weakRef;
weakRef = DecodeWeakReferencePointer(previousValue);
weakRef->AddRef();
*weakReference = weakRef;
return S_OK;
}
// Another thread won via an AddRef or Release.
// Let's try again
currentValue.rawValue = previousValue;
}
}
// Memory allocation for object that doesn't support weak references
// It only allocates memory
template<typename T>
class MakeAllocator
{
public:
MakeAllocator() throw() : buffer_(nullptr)
{
}
~MakeAllocator() throw()
{
if (buffer_ != nullptr)
{
delete buffer_;
}
}
void* Allocate() throw()
{
__WRL_ASSERT__(buffer_ == nullptr);
// Allocate memory with operator new(size, nothrow) only
// This will allow developer to override one operator only
// to enable different memory allocation model
buffer_ = (char*) (operator new (sizeof(T), std::nothrow));
return buffer_;
}
void Detach() throw()
{
buffer_ = nullptr;
}
private:
char* buffer_;
};
} //Details
#pragma region make overloads
namespace Details {
// Make and MakeAndInitialize functions must not be marked as throw() as the constructor is allowed to throw exceptions.
template <typename T, typename ...TArgs>
ComPtr<T> Make(TArgs&&... args)
{
static_assert(__is_base_of(Details::RuntimeClassBase, T), "Make can only instantiate types that derive from RuntimeClass");
ComPtr<T> object;
Details::MakeAllocator<T> allocator;
void *buffer = allocator.Allocate();
if (buffer != nullptr)
{
auto ptr = new (buffer)T(Details::Forward<TArgs>(args)...);
object.Attach(ptr);
allocator.Detach();
}
return object;
}
#pragma warning(push)
#pragma warning(disable:6387 6388 28196) // PREFast does not understand call to ComPtr<T>::CopyTo() is safe here
template <typename T, typename I, typename ...TArgs>
HRESULT MakeAndInitialize(_Outptr_result_nullonfailure_ I** result, TArgs&&... args)
{
static_assert(__is_base_of(Details::RuntimeClassBase, T), "Make can only instantiate types that derive from RuntimeClass");
static_assert(__is_base_of(I, T), "The 'T' runtime class doesn't implement 'I' interface");
*result = nullptr;
Details::MakeAllocator<T> allocator;
void *buffer = allocator.Allocate();
if (buffer == nullptr) { return E_OUTOFMEMORY; }
auto ptr = new (buffer)T;
ComPtr<T> object;
object.Attach(ptr);
allocator.Detach();
HRESULT hr = object->RuntimeClassInitialize(Details::Forward<TArgs>(args)...);
if (FAILED(hr)) { return hr; }
return object.CopyTo(result);
}
#pragma warning(pop) // C6387 C6388 C28196
template <typename T, typename I, typename ...TArgs>
HRESULT MakeAndInitialize(_Inout_ ComPtrRef<ComPtr<I>> ppvObject, TArgs&&... args)
{
return MakeAndInitialize<T>(ppvObject.ReleaseAndGetAddressOf(), Details::Forward<TArgs>(args)...);
}
} //end of Details
using Details::MakeAndInitialize;
using Details::Make;
#pragma endregion // make overloads
namespace Details
{
inline WeakReferenceImpl* CreateWeakReference(_In_ IUnknown* unk)
{
return Make<WeakReferenceImpl>(unk).Detach();
}
}
#define InspectableClass(runtimeClassName, trustLevel) \
public: \
static _Null_terminated_ const wchar_t* STDMETHODCALLTYPE InternalGetRuntimeClassName() throw() \
{ \
static_assert((RuntimeClassT::ClassFlags::value & ::Microsoft::WRL::WinRtClassicComMix) == ::Microsoft::WRL::WinRt || \
(RuntimeClassT::ClassFlags::value & ::Microsoft::WRL::WinRtClassicComMix) == ::Microsoft::WRL::WinRtClassicComMix, \
"'InspectableClass' macro must not be used with ClassicCom clasess."); \
static_assert(__is_base_of(::Microsoft::WRL::Details::RuntimeClassBase, RuntimeClassT), "'InspectableClass' macro can only be used with ::Windows::WRL::RuntimeClass types"); \
static_assert(!__is_base_of(IActivationFactory, RuntimeClassT), "Incorrect usage of IActivationFactory interface. Make sure that your RuntimeClass doesn't implement IActivationFactory interface use ::Windows::WRL::ActivationFactory instead or 'InspectableClass' macro is not used on ::Windows::WRL::ActivationFactory"); \
return runtimeClassName; \
} \
static ::TrustLevel STDMETHODCALLTYPE InternalGetTrustLevel() throw() \
{ \
return trustLevel; \
} \
STDMETHOD(GetRuntimeClassName)(_Out_ HSTRING* runtimeName) \
{ \
*runtimeName = nullptr; \
HRESULT hr = S_OK; \
auto name = InternalGetRuntimeClassName(); \
if (name != nullptr) \
{ \
hr = ::WindowsCreateString(name, static_cast<UINT32>(::wcslen(name)), runtimeName); \
} \
return hr; \
} \
STDMETHOD(GetTrustLevel)(_Out_ ::TrustLevel* trustLvl) \
{ \
*trustLvl = trustLevel; \
return S_OK; \
} \
STDMETHOD(GetIids)(_Out_ ULONG *iidCount, \
_When_(*iidCount == 0, _At_(*iids, _Post_null_)) \
_When_(*iidCount > 0, _At_(*iids, _Post_notnull_)) \
_Result_nullonfailure_ IID **iids) \
{ \
return RuntimeClassT::GetIids(iidCount, iids); \
} \
STDMETHOD(QueryInterface)(REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject) \
{ \
bool handled = false; \
HRESULT hr = this->CustomQueryInterface(riid, ppvObject, &handled); \
if (FAILED(hr) || handled) return hr; \
return RuntimeClassT::QueryInterface(riid, ppvObject); \
} \
STDMETHOD_(ULONG, Release)() \
{ \
return RuntimeClassT::Release(); \
} \
STDMETHOD_(ULONG, AddRef)() \
{ \
return RuntimeClassT::AddRef(); \
} \
private:
#define MixInHelper() \
public: \
STDMETHOD(QueryInterface)(REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject) \
{ \
static_assert((RuntimeClassT::ClassFlags::value & ::Microsoft::WRL::WinRt) == 0, "'MixInClass' macro must not be used with WinRt clasess."); \
static_assert(__is_base_of(::Microsoft::WRL::Details::RuntimeClassBase, RuntimeClassT), "'MixInHelper' macro can only be used with ::Windows::WRL::RuntimeClass types"); \
static_assert(!__is_base_of(IClassFactory, RuntimeClassT), "Incorrect usage of IClassFactory interface. Make sure that your RuntimeClass doesn't implement IClassFactory interface use ::Windows::WRL::ClassFactory instead or 'MixInHelper' macro is not used on ::Windows::WRL::ClassFactory"); \
return RuntimeClassT::QueryInterface(riid, ppvObject); \
} \
STDMETHOD_(ULONG, Release)() \
{ \
return RuntimeClassT::Release(); \
} \
STDMETHOD_(ULONG, AddRef)() \
{ \
return RuntimeClassT::AddRef(); \
} \
private:
// Please make sure that those macros are in sync with those ones from 'wrl/module.h'
#ifndef WrlCreatorMapIncludePragmaEx
#define WrlCreatorMapIncludePragmaEx(className, group) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'WrlCreatorMapIncludePragmaEx' macro");
#endif
#ifndef WrlCreatorMapIncludePragma
#define WrlCreatorMapIncludePragma(className) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'WrlCreatorMapIncludePragma' macro");
#endif
#ifndef ActivatableClassWithFactoryEx
#define ActivatableClassWithFactoryEx(className, factory, groupId) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'ActivatableClassWithFactoryEx' macro");
#endif
#ifndef ActivatableClassWithFactory
#define ActivatableClassWithFactory(className, factory) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'ActivatableClassWithFactory' macro");
#endif
#ifndef ActivatableClass
#define ActivatableClass(className) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'ActivatableClass' macro");
#endif
#ifndef ActivatableStaticOnlyFactoryEx
#define ActivatableStaticOnlyFactoryEx(factory, serverName) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'ActivatableStaticOnlyFactoryEx' macro");
#endif
#ifndef ActivatableStaticOnlyFactory
#define ActivatableStaticOnlyFactory(factory) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'ActivatableStaticOnlyFactory' macro");
#endif
#ifndef CoCreatableClassWithFactoryEx
#define CoCreatableClassWithFactoryEx(className, factory, groupId) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'CoCreatableClassWithFactory' macro");
#endif
#ifndef CoCreatableClassWithFactory
#define CoCreatableClassWithFactory(className, factory) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'CoCreatableClassWithFactory' macro");
#endif
#ifndef CoCreatableClass
#define CoCreatableClass(className) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'CoCreatableClass' macro");
#endif
#ifndef CoCreatableClassWrlCreatorMapInclude
#define CoCreatableClassWrlCreatorMapInclude(className) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'CoCreatableClassWrlCreatorMapInclude' macro");
#endif
#ifndef CoCreatableClassWrlCreatorMapIncludeEx
#define CoCreatableClassWrlCreatorMapIncludeEx(className, groupId) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'CoCreatableClassWrlCreatorMapInclude' macro");
#endif
#undef UnknownIncrementReference
#undef UnknownDecrementReference
#undef UnknownBarrierAfterInterlock
#undef UnknownInterlockedCompareExchangePointer
#undef UnknownInterlockedCompareExchangePointerForIncrement
#undef UnknownInterlockedCompareExchangePointerForRelease
}} // namespace Microsoft::WRL
#pragma warning(pop)
// Restore packing
#include <poppack.h>
#endif // _WRL_IMPLEMENTS_H_