1 // 2 // Copyright (C) Microsoft Corporation 3 // All rights reserved. 4 // 5 // Code in Details namespace is for internal usage within the library code 6 // 7 8 #ifndef _WRL_IMPLEMENTS_H_ 9 #define _WRL_IMPLEMENTS_H_ 10 11 #ifdef _MSC_VER 12 #pragma once 13 #endif // _MSC_VER 14 15 #ifdef __clang__ 16 #pragma clang diagnostic push 17 #pragma clang diagnostic ignored "-Wpragma-pack" 18 #pragma clang diagnostic ignored "-Wunused-value" 19 #pragma clang diagnostic ignored "-Wmicrosoft-sealed" 20 #pragma clang diagnostic ignored "-Winaccessible-base" 21 #endif 22 23 #pragma region includes 24 25 #include <inspectable.h> 26 #include <roapi.h> 27 #ifdef BUILD_WINDOWS 28 #include <winrt.h> 29 #endif 30 #include <activation.h> 31 #include <WinString.h> 32 33 #include <new.h> 34 #include <weakreference.h> 35 #include <objbase.h> // IMarshal 36 #include <cguid.h> // CLSID_StdGlobalInterfaceTable 37 #include <intrin.h> 38 39 #include <wrl\def.h> 40 #include <wrl\client.h> 41 42 #if (NTDDI_VERSION >= NTDDI_WINBLUE) 43 #include "roerrorapi.h" 44 #endif // (NTDDI_VERSION >= NTDDI_WINBLUE) 45 46 // Set packing 47 #include <pshpack8.h> 48 49 #pragma endregion 50 51 #ifndef __WRL_NO_DEFAULT_LIB__ 52 #pragma comment(lib, "ole32.lib") // For CoTaskMemAlloc 53 #endif 54 55 #pragma region disable warnings 56 57 #pragma warning(push) 58 #pragma warning(disable: 4584) // 'class1' : base-class 'class2' is already a base-class of 'class3' 59 #pragma warning(disable: 4481) // nonstandard extension used: override specifier 'override' 60 61 #pragma endregion // disable warnings 62 63 namespace Microsoft { 64 namespace WRL { 65 66 // Indicator for RuntimeClass,Implements and ChainInterfaces that T interface 67 // will be not accessible on IID list 68 // Example: 69 // struct MyRuntimeClass : RuntimeClass<CloakedIid<IMyCloakedInterface>> {} 70 template<typename T> 71 struct CloakedIid : T 72 { 73 }; 74 75 enum RuntimeClassType 76 { 77 WinRt = 0x0001, 78 ClassicCom = 0x0002, 79 WinRtClassicComMix = WinRt | ClassicCom, 80 InhibitWeakReference = 0x0004, 81 Delegate = ClassicCom, 82 InhibitFtmBase = 0x0008, 83 InhibitRoOriginateError = 0x0010 84 }; 85 86 template <unsigned int flags> 87 struct RuntimeClassFlags 88 { 89 static const unsigned int value = flags; 90 }; 91 92 namespace Details 93 { 94 // Empty struct used for validating template parameter types in Implements 95 struct ImplementsBase 96 { 97 }; 98 99 } // namespace Details 100 101 // MixIn modifier allows to combine QI from 102 // a class that doesn't have default constructor on it 103 template<typename Derived, typename MixInType, bool hasImplements = __is_base_of(Details::ImplementsBase, MixInType)> 104 struct MixIn 105 { 106 }; 107 108 // ComposableBase template to allow deriving from a RuntimeClass 109 // Optionally allows specifying the base factory and statics interface 110 template <typename FactoryInterface = IInspectable> 111 class ComposableBase 112 { 113 }; 114 // Back-compat indicator for RuntimeClass to not support IWeakReferenceSource 115 typedef RuntimeClassFlags<WinRt | InhibitWeakReference> InhibitWeakReferencePolicy; 116 117 template<unsigned int RuntimeClassTypeT> 118 struct ErrorHelper 119 { OriginateErrorErrorHelper120 static void OriginateError(HRESULT hr, HSTRING message) 121 { 122 #if (NTDDI_VERSION >= NTDDI_WINBLUE) 123 ::RoOriginateError(hr, message); 124 #else 125 UNREFERENCED_PARAMETER(hr); 126 UNREFERENCED_PARAMETER(message); 127 #endif // (NTDDI_VERSION >= NTDDI_WINBLUE) 128 } 129 }; 130 131 template<> 132 struct ErrorHelper<InhibitRoOriginateError> 133 { 134 static void OriginateError(HRESULT hr, HSTRING message) 135 { 136 UNREFERENCED_PARAMETER(hr); 137 UNREFERENCED_PARAMETER(message); 138 // No-Op 139 } 140 }; 141 142 namespace Details 143 { 144 145 //Forward declaration 146 struct CreatorMap; 147 148 // Sections automatically generate a list of pointers to CreatorMap through the linker 149 // Sections a and z are used as a terminators 150 #pragma section("minATL$__a", read) 151 // Section f is used to put com objects to creator map 152 #pragma section("minATL$__f", read) 153 // Section m divides COM entries from WinRT entries 154 #pragma section("minATL$__m", read) 155 // Section r is used to put WinRT objects to creator map 156 #pragma section("minATL$__r", read) 157 #pragma section("minATL$__z", read) 158 159 extern "C" 160 { 161 // Location of the first and last entries for the linker generated list of pointers to CreatorMapEntry 162 __declspec(selectany) __declspec(allocate("minATL$__a")) const CreatorMap* __pobjectentryfirst = nullptr; 163 // Section m divides COM objects from WinRT objects 164 // - sections between a and m we store COM object info 165 // - sections between m+1 and z we store WinRT object info 166 __declspec(selectany) __declspec(allocate("minATL$__m")) const CreatorMap* __pobjectentrymid = nullptr; 167 __declspec(selectany) __declspec(allocate("minATL$__z")) const CreatorMap* __pobjectentrylast = nullptr; 168 } 169 170 // Base class used by all module classes. 171 class __declspec(novtable) ModuleBase 172 { 173 private: 174 // Lock that synchronize access and termination of factories 175 static void* moduleLock_; 176 177 static_assert(sizeof(moduleLock_) == sizeof(SRWLOCK), "cacheLock must have the same size as SRWLOCK"); 178 protected: 179 static volatile unsigned long objectCount_; 180 public: 181 static ModuleBase *module_; 182 183 ModuleBase() throw() 184 { 185 #ifdef _DEBUG 186 // WRLs support for activatable classes requires there is only one instance of Module<>, this assert 187 // ensures there is only one. Since Module<> is templatized, using different template parameters will 188 // result in multiple instances, avoid this by making sure all code in a component uses the same parameters. 189 // Note that the C++ CX runtime creates an instance; Module<InProc, Platform::Details::InProcModule>, 190 // so mixing it with non CX code can result in this assert. 191 // WRL supports static and dynamically allocated Module<>, choose dynamic by defining __WRL_DISABLE_STATIC_INITIALIZE__ 192 // and allocate that instance with new but only once, for example in the main() entry point of an application. 193 __WRL_ASSERT__(::InterlockedCompareExchangePointer(reinterpret_cast<void* volatile*>(&module_), this, nullptr) == nullptr && 194 "The module was already instantiated"); 195 196 SRWLOCK initSRWLOCK = SRWLOCK_INIT; 197 __WRL_ASSERT__(reinterpret_cast<SRWLOCK*>(&moduleLock_)->Ptr == initSRWLOCK.Ptr && "Different value for moduleLock_ than SRWLOCK_INIT"); 198 (initSRWLOCK); 199 #else 200 module_ = this; 201 #endif 202 } 203 204 ModuleBase(const ModuleBase&) = delete; 205 ModuleBase& operator=(const ModuleBase&) = delete; 206 207 virtual ~ModuleBase() throw() 208 { 209 #ifdef _DEBUG 210 __WRL_ASSERT__(::InterlockedCompareExchangePointer(reinterpret_cast<void* volatile*>(&module_), nullptr, this) == this && 211 "The module was already instantiated"); 212 #else 213 module_ = nullptr; 214 #endif 215 } 216 217 // Number of active objects in the module 218 STDMETHOD_(unsigned long, IncrementObjectCount)() = 0; 219 STDMETHOD_(unsigned long, DecrementObjectCount)() = 0; 220 221 STDMETHOD_(unsigned long, GetObjectCount)() const 222 { 223 return objectCount_; 224 } 225 226 STDMETHOD_(const CreatorMap**, GetFirstEntryPointer)() const 227 { 228 return &__pobjectentryfirst; 229 } 230 231 STDMETHOD_(const CreatorMap**, GetMidEntryPointer)() const 232 { 233 return &__pobjectentrymid; 234 } 235 236 STDMETHOD_(const CreatorMap**, GetLastEntryPointer)() const 237 { 238 return &__pobjectentrylast; 239 } 240 241 STDMETHOD_(SRWLOCK*, GetLock)() const 242 { 243 return reinterpret_cast<SRWLOCK*>(&moduleLock_); 244 } 245 246 STDMETHOD(RegisterWinRTObject)(_In_opt_z_ const wchar_t*, _In_z_ const wchar_t** activatableClassIds, _Inout_ RO_REGISTRATION_COOKIE* cookie, unsigned int) = 0; 247 STDMETHOD(UnregisterWinRTObject)(_In_opt_z_ const wchar_t*, _In_ RO_REGISTRATION_COOKIE) = 0; 248 STDMETHOD(RegisterCOMObject)(_In_opt_z_ const wchar_t*, _In_ IID*, _In_ IClassFactory**, _Inout_ DWORD*, unsigned int) = 0; 249 STDMETHOD(UnregisterCOMObject)(_In_opt_z_ const wchar_t*, _Inout_ DWORD*, unsigned int) = 0; 250 }; 251 252 __declspec(selectany) volatile unsigned long ModuleBase::objectCount_ = 0; 253 // moduleLock_ value must be equal SRWLOCK_INIT which is nullptr 254 __declspec(selectany) void* ModuleBase::moduleLock_ = nullptr; 255 __declspec(selectany) ModuleBase *ModuleBase::module_ = nullptr; 256 257 #pragma region helper types 258 // Empty struct used as default template parameter 259 class Nil 260 { 261 }; 262 263 // Used on RuntimeClass to protect it from being constructed with new 264 class DontUseNewUseMake 265 { 266 private: 267 void* operator new(size_t) throw() 268 { 269 __WRL_ASSERT__(false); 270 return 0; 271 } 272 273 public: 274 void* operator new(size_t, _In_ void* placement) throw() 275 { 276 return placement; 277 } 278 }; 279 280 // RuntimeClassBase is used for detection of RuntimeClass in Make method 281 class RuntimeClassBase 282 { 283 }; 284 285 // RuntimeClassBaseT provides helper methods for QI and getting IIDs 286 template <unsigned int RuntimeClassTypeT> 287 class RuntimeClassBaseT : private RuntimeClassBase 288 { 289 protected: 290 template<typename T> 291 static HRESULT AsIID(_In_ T* implements, REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject) throw() 292 { 293 *ppvObject = nullptr; 294 #pragma warning(push) 295 // Conditional expression is constant 296 #pragma warning(disable: 4127) 297 // Potential comparison of a constant with another constant 298 #pragma warning(disable: 6326) 299 // Conditional check using template parameter is constant and can be used to optimize the code 300 bool isRefDelegated = false; 301 // Prefer InlineIsEqualGUID over other forms since it's better perf on 4-byte aligned data, which is almost always the case. 302 if (InlineIsEqualGUID(riid, __uuidof(IUnknown)) || ((RuntimeClassTypeT & WinRt) != 0 && InlineIsEqualGUID(riid, __uuidof(IInspectable)))) 303 #pragma warning(pop) 304 { 305 *ppvObject = implements->CastToUnknown(); 306 static_cast<IUnknown*>(*ppvObject)->AddRef(); 307 return S_OK; 308 } 309 310 HRESULT hr = implements->CanCastTo(riid, ppvObject, &isRefDelegated); 311 if (SUCCEEDED(hr) && !isRefDelegated) 312 { 313 static_cast<IUnknown*>(*ppvObject)->AddRef(); 314 } 315 316 #pragma warning(suppress: 6102) // '*ppvObject' is used but may not be initialized 317 _Analysis_assume_(SUCCEEDED(hr) || (*ppvObject == nullptr)); 318 319 return hr; 320 } 321 template<typename T> 322 static HRESULT GetImplementedIIDS( 323 _In_ T* implements, 324 _Out_ ULONG *iidCount, 325 _When_(*iidCount == 0, _At_(*iids, _Post_null_)) 326 _When_(*iidCount > 0, _At_(*iids, _Post_notnull_)) 327 _Result_nullonfailure_ IID **iids) throw() 328 { 329 *iids = nullptr; 330 *iidCount = 0; 331 unsigned long count = implements->GetIidCount(); 332 333 // If there is no iids the CoTaskMemAlloc don't have to be called 334 if (count == 0) 335 { 336 return S_OK; 337 } 338 339 IID* iidArray = reinterpret_cast<IID*>(::CoTaskMemAlloc(sizeof(IID) * count)); 340 if (iidArray == nullptr) 341 { 342 return E_OUTOFMEMORY; 343 } 344 345 unsigned long index = 0; 346 347 // assign the IIDs to the array 348 implements->FillArrayWithIid(&index, iidArray); 349 __WRL_ASSERT__(index == count); 350 351 // and return it 352 *iidCount = count; 353 *iids = iidArray; 354 return S_OK; 355 } 356 357 public: 358 HRESULT RuntimeClassInitialize() throw() 359 { 360 return S_OK; 361 } 362 }; 363 364 // Base class required to mark FtmBase 365 class FtmBaseMarker 366 { 367 }; 368 369 // Verifies that I is derived from specified base 370 template <unsigned int type, typename I, bool doStrictCheck = true, bool isImplementsBased = __is_base_of(ImplementsBase, I)> 371 struct VerifyInterfaceHelper; 372 373 // Specialization for ClassicCom interface 374 template <typename I, bool doStrictCheck> 375 struct VerifyInterfaceHelper<ClassicCom, I, doStrictCheck, false> 376 { 377 static void Verify() throw() 378 { 379 #ifdef __WRL_STRICT__ 380 // Make sure that your interfaces inherit from IUnknown and are not IUnknown and/or IInspectable based 381 // The IUnknown is allowed only on RuntimeClass as first template parameter 382 static_assert(__is_base_of(IUnknown, I) && !__is_base_of(IInspectable, I) && !(doStrictCheck && IsSame<IUnknown, I>::value), 383 "'I' has to derive from 'IUnknown' and not from 'IInspectable'. 'I' must not be IUnknown."); 384 #else 385 static_assert(__is_base_of(IUnknown, I), "'I' has to derive from 'IUnknown'."); 386 #endif 387 } 388 }; 389 390 // Specialization for WinRtClassicComMix interface 391 template <typename I, bool doStrictCheck> 392 struct VerifyInterfaceHelper<WinRtClassicComMix, I, doStrictCheck, false> 393 { 394 static void Verify() throw() 395 { 396 #ifdef __WRL_STRICT__ 397 // Make sure that your interfaces inherit from IUnknown and are not IUnknown and/or IInspectable 398 // except when IInspectable is the first template parameter 399 static_assert(__is_base_of(IUnknown, I) && 400 (doStrictCheck ? !(IsSame<IInspectable, I>::value || IsSame<IUnknown, I>::value) : __is_base_of(IInspectable, I)), 401 "'I' has to derive from 'IUnknown' and must not be IUnknown and/or IInspectable."); 402 #else 403 static_assert(__is_base_of(IUnknown, I), "'I' has to derive from 'IUnknown'."); 404 #endif 405 } 406 }; 407 408 // Specialization for WinRt interface 409 template <typename I, bool doStrictCheck> 410 struct VerifyInterfaceHelper<WinRt, I, doStrictCheck, false> 411 { 412 static void Verify() throw() 413 { 414 #ifdef __WRL_STRICT__ 415 // IWeakReferenceSource is exception for WinRt and can be used however it cannot be first templated interface 416 // Make sure that your interfaces inherit from IInspectable and are not IInspectable 417 // The IInspectable is allowed only on RuntimeClass as first template parameter 418 static_assert((__is_base_of(IWeakReferenceSource, I) && doStrictCheck) || 419 (__is_base_of(IInspectable, I) && !(doStrictCheck && IsSame<IInspectable, I>::value)), 420 "'I' has to derive from 'IWeakReferenceSource' or 'IInspectable' and must not be IInspectable"); 421 #else 422 // IWeakReference and IWeakReferneceSource are exceptions for WinRT 423 static_assert(__is_base_of(IWeakReference, I) || 424 __is_base_of(IWeakReferenceSource, I) || 425 __is_base_of(IInspectable, I), "'I' has to derive from 'IWeakReference', 'IWeakReferenceSource' or 'IInspectable'"); 426 #endif 427 } 428 }; 429 430 // Specialization for Implements passed as template parameter 431 template <unsigned int type, typename I> 432 struct VerifyInterfaceHelper<type, I, true, true> 433 { 434 static void Verify() throw() 435 { 436 #ifdef __WRL_STRICT__ 437 // Verifies if Implements has correct RuntimeClassFlags setting 438 // Allow using FtmBase on classes configured with RuntimeClassFlags<WinRt> (Default configuration) 439 static_assert(I::ClassFlags::value == type || 440 type == WinRtClassicComMix || 441 __is_base_of(::Microsoft::WRL::Details::FtmBaseMarker, I), 442 "Implements class must have the same and/or compatibile flags configuration"); 443 #endif 444 } 445 }; 446 447 // Specialization for Implements passed as first template parameter 448 template <unsigned int type, typename I> 449 struct VerifyInterfaceHelper<type, I, false, true> 450 { 451 static void Verify() throw() 452 { 453 #ifdef __WRL_STRICT__ 454 // Verifies if Implements has correct RuntimeClassFlags setting 455 static_assert(I::ClassFlags::value == type || type == WinRtClassicComMix, 456 "Implements class must have the same and/or compatible flags configuration." 457 "If you use WRL::FtmBase it cannot be specified as first template parameter on RuntimeClass"); 458 459 // Besides make sure that the first interface on Implements meet flags requirement 460 VerifyInterfaceHelper<type, I::FirstInterface, false>::Verify(); 461 #endif 462 } 463 }; 464 465 // Interface traits provides casting and filling iids methods helpers 466 template<typename I0> 467 struct __declspec(novtable) InterfaceTraits 468 { 469 typedef I0 Base; 470 static const unsigned long IidCount = 1; 471 472 template<unsigned int ClassType> 473 static void Verify() throw() 474 { 475 VerifyInterfaceHelper<ClassType & WinRtClassicComMix, Base>::Verify(); 476 } 477 478 template<typename T> 479 static Base* CastToBase(_In_ T* ptr) throw() 480 { 481 return static_cast<Base*>(ptr); 482 } 483 484 template<typename T> 485 static IUnknown* CastToUnknown(_In_ T* ptr) throw() 486 { 487 return static_cast<IUnknown*>(static_cast<Base*>(ptr)); 488 } 489 490 template <typename T> 491 _Success_(return == true) 492 static bool CanCastTo(_In_ T* ptr, REFIID riid, _Outptr_ void **ppv) throw() 493 { 494 // Prefer InlineIsEqualGUID over other forms since it's better perf on 4-byte aligned data, which is almost always the case. 495 if (InlineIsEqualGUID(riid, __uuidof(Base))) 496 { 497 *ppv = static_cast<Base*>(ptr); 498 return true; 499 } 500 501 return false; 502 } 503 504 static void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw() 505 { 506 *(iids + *index) = __uuidof(Base); 507 (*index)++; 508 } 509 }; 510 511 // Specialization of traits for cloaked interface 512 template<typename CloakedType> 513 struct __declspec(novtable) InterfaceTraits<CloakedIid<CloakedType>> 514 { 515 typedef CloakedType Base; 516 static const unsigned long IidCount = 0; 517 518 template<unsigned int ClassType> 519 static void Verify() throw() 520 { 521 VerifyInterfaceHelper<ClassType & WinRtClassicComMix, Base>::Verify(); 522 } 523 524 template<typename T> 525 static Base* CastToBase(_In_ T* ptr) throw() 526 { 527 return static_cast<Base*>(ptr); 528 } 529 530 template<typename T> 531 static IUnknown* CastToUnknown(_In_ T* ptr) throw() 532 { 533 return static_cast<IUnknown*>(static_cast<Base*>(ptr)); 534 } 535 536 template <typename T> 537 _Success_(return == true) 538 static bool CanCastTo(_In_ T* ptr, REFIID riid, _Outptr_ void **ppv) throw() 539 { 540 // Prefer InlineIsEqualGUID over other forms since it's better perf on 4-byte aligned data, which is almost always the case. 541 if (InlineIsEqualGUID(riid, __uuidof(Base))) 542 { 543 *ppv = static_cast<Base*>(ptr); 544 return true; 545 } 546 547 return false; 548 } 549 550 // Cloaked specialization makes it always IID list empty 551 static void FillArrayWithIid(_Inout_ unsigned long*, _Inout_ IID*) throw() 552 { 553 } 554 }; 555 556 // Specialization for Nil parameter 557 template<> 558 struct __declspec(novtable) InterfaceTraits<Nil> 559 { 560 typedef Nil Base; 561 static const unsigned long IidCount = 0; 562 563 template<unsigned int ClassType> 564 static void Verify() throw() 565 { 566 } 567 568 static void FillArrayWithIid(_Inout_ unsigned long *, _Inout_ IID*) throw() 569 { 570 } 571 572 template <typename T> 573 _Success_(return == true) 574 static bool CanCastTo(_In_ T*, REFIID, _Outptr_ void **) throw() 575 { 576 return false; 577 } 578 }; 579 580 // Verify inheritance 581 template <typename I, typename Base> 582 struct VerifyInheritanceHelper 583 { 584 static void Verify() throw() 585 { 586 static_assert(Details::IsBaseOfStrict<typename InterfaceTraits<Base>::Base, typename InterfaceTraits<I>::Base>::value, "'I' needs to inherit from 'Base'."); 587 } 588 }; 589 590 template <typename I> 591 struct VerifyInheritanceHelper<I, Nil> 592 { 593 static void Verify() throw() 594 { 595 } 596 }; 597 598 #pragma endregion // helper types 599 600 } // namespace Details 601 602 inline Details::ModuleBase* GetModuleBase() throw() 603 { 604 return Details::ModuleBase::module_; 605 } 606 607 // ChainInterfaces - template allows specifying a derived COM interface along with its class hierarchy to allow QI for the base interfaces 608 template <typename I0, typename I1, typename I2 = Details::Nil, typename I3 = Details::Nil, 609 typename I4 = Details::Nil, typename I5 = Details::Nil, typename I6 = Details::Nil, 610 typename I7 = Details::Nil, typename I8 = Details::Nil, typename I9 = Details::Nil> 611 struct ChainInterfaces : I0 612 { 613 protected: 614 template<unsigned int ClassType> 615 static void Verify() throw() 616 { 617 Details::InterfaceTraits<I0>::template Verify<ClassType>(); 618 Details::InterfaceTraits<I1>::template Verify<ClassType>(); 619 Details::InterfaceTraits<I2>::template Verify<ClassType>(); 620 Details::InterfaceTraits<I3>::template Verify<ClassType>(); 621 Details::InterfaceTraits<I4>::template Verify<ClassType>(); 622 Details::InterfaceTraits<I5>::template Verify<ClassType>(); 623 Details::InterfaceTraits<I6>::template Verify<ClassType>(); 624 Details::InterfaceTraits<I7>::template Verify<ClassType>(); 625 Details::InterfaceTraits<I8>::template Verify<ClassType>(); 626 Details::InterfaceTraits<I9>::template Verify<ClassType>(); 627 628 Details::VerifyInheritanceHelper<I0, I1>::Verify(); 629 Details::VerifyInheritanceHelper<I0, I2>::Verify(); 630 Details::VerifyInheritanceHelper<I0, I3>::Verify(); 631 Details::VerifyInheritanceHelper<I0, I4>::Verify(); 632 Details::VerifyInheritanceHelper<I0, I5>::Verify(); 633 Details::VerifyInheritanceHelper<I0, I6>::Verify(); 634 Details::VerifyInheritanceHelper<I0, I7>::Verify(); 635 Details::VerifyInheritanceHelper<I0, I8>::Verify(); 636 Details::VerifyInheritanceHelper<I0, I9>::Verify(); 637 } 638 639 HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv) throw() 640 { 641 typename Details::InterfaceTraits<I0>::Base* ptr = Details::InterfaceTraits<I0>::CastToBase(this); 642 643 return (Details::InterfaceTraits<I0>::CanCastTo(this, riid, ppv) || 644 Details::InterfaceTraits<I1>::CanCastTo(ptr, riid, ppv) || 645 Details::InterfaceTraits<I2>::CanCastTo(ptr, riid, ppv) || 646 Details::InterfaceTraits<I3>::CanCastTo(ptr, riid, ppv) || 647 Details::InterfaceTraits<I4>::CanCastTo(ptr, riid, ppv) || 648 Details::InterfaceTraits<I5>::CanCastTo(ptr, riid, ppv) || 649 Details::InterfaceTraits<I6>::CanCastTo(ptr, riid, ppv) || 650 Details::InterfaceTraits<I7>::CanCastTo(ptr, riid, ppv) || 651 Details::InterfaceTraits<I8>::CanCastTo(ptr, riid, ppv) || 652 Details::InterfaceTraits<I9>::CanCastTo(ptr, riid, ppv)) ? S_OK : E_NOINTERFACE; 653 } 654 655 IUnknown* CastToUnknown() throw() 656 { 657 return Details::InterfaceTraits<I0>::CastToUnknown(this); 658 } 659 660 static const unsigned long IidCount = 661 Details::InterfaceTraits<I0>::IidCount + 662 Details::InterfaceTraits<I1>::IidCount + 663 Details::InterfaceTraits<I2>::IidCount + 664 Details::InterfaceTraits<I3>::IidCount + 665 Details::InterfaceTraits<I4>::IidCount + 666 Details::InterfaceTraits<I5>::IidCount + 667 Details::InterfaceTraits<I6>::IidCount + 668 Details::InterfaceTraits<I7>::IidCount + 669 Details::InterfaceTraits<I8>::IidCount + 670 Details::InterfaceTraits<I9>::IidCount; 671 672 static void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw() 673 { 674 Details::InterfaceTraits<I0>::FillArrayWithIid(index, iids); 675 Details::InterfaceTraits<I1>::FillArrayWithIid(index, iids); 676 Details::InterfaceTraits<I2>::FillArrayWithIid(index, iids); 677 Details::InterfaceTraits<I3>::FillArrayWithIid(index, iids); 678 Details::InterfaceTraits<I4>::FillArrayWithIid(index, iids); 679 Details::InterfaceTraits<I5>::FillArrayWithIid(index, iids); 680 Details::InterfaceTraits<I6>::FillArrayWithIid(index, iids); 681 Details::InterfaceTraits<I7>::FillArrayWithIid(index, iids); 682 Details::InterfaceTraits<I8>::FillArrayWithIid(index, iids); 683 Details::InterfaceTraits<I9>::FillArrayWithIid(index, iids); 684 } 685 }; 686 687 template <typename DerivedType, typename BaseType, bool hasImplements, typename I1, typename I2, typename I3, 688 typename I4, typename I5, typename I6, 689 typename I7, typename I8, typename I9> 690 struct ChainInterfaces<MixIn<DerivedType, BaseType, hasImplements>, I1, I2, I3, I4, I5, I6, I7, I8, I9> 691 { 692 static_assert(!hasImplements, "Cannot use ChainInterfaces<MixIn<...>> to Mix a class implementing interfaces using \"Implements\""); 693 694 protected: 695 template<unsigned int ClassType> 696 static void Verify() throw() 697 { 698 Details::InterfaceTraits<BaseType>::template Verify<ClassType>(); 699 Details::InterfaceTraits<I1>::template Verify<ClassType>(); 700 Details::InterfaceTraits<I2>::template Verify<ClassType>(); 701 Details::InterfaceTraits<I3>::template Verify<ClassType>(); 702 Details::InterfaceTraits<I4>::template Verify<ClassType>(); 703 Details::InterfaceTraits<I5>::template Verify<ClassType>(); 704 Details::InterfaceTraits<I6>::template Verify<ClassType>(); 705 Details::InterfaceTraits<I7>::template Verify<ClassType>(); 706 Details::InterfaceTraits<I8>::template Verify<ClassType>(); 707 Details::InterfaceTraits<I9>::template Verify<ClassType>(); 708 709 Details::VerifyInheritanceHelper<BaseType, I1>::Verify(); 710 Details::VerifyInheritanceHelper<BaseType, I2>::Verify(); 711 Details::VerifyInheritanceHelper<BaseType, I3>::Verify(); 712 Details::VerifyInheritanceHelper<BaseType, I4>::Verify(); 713 Details::VerifyInheritanceHelper<BaseType, I5>::Verify(); 714 Details::VerifyInheritanceHelper<BaseType, I6>::Verify(); 715 Details::VerifyInheritanceHelper<BaseType, I7>::Verify(); 716 Details::VerifyInheritanceHelper<BaseType, I8>::Verify(); 717 Details::VerifyInheritanceHelper<BaseType, I9>::Verify(); 718 } 719 720 HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv) throw() 721 { 722 BaseType* ptr = static_cast<BaseType*>(static_cast<DerivedType*>(this)); 723 724 return ( 725 Details::InterfaceTraits<I1>::CanCastTo(ptr, riid, ppv) || 726 Details::InterfaceTraits<I2>::CanCastTo(ptr, riid, ppv) || 727 Details::InterfaceTraits<I3>::CanCastTo(ptr, riid, ppv) || 728 Details::InterfaceTraits<I4>::CanCastTo(ptr, riid, ppv) || 729 Details::InterfaceTraits<I5>::CanCastTo(ptr, riid, ppv) || 730 Details::InterfaceTraits<I6>::CanCastTo(ptr, riid, ppv) || 731 Details::InterfaceTraits<I7>::CanCastTo(ptr, riid, ppv) || 732 Details::InterfaceTraits<I8>::CanCastTo(ptr, riid, ppv) || 733 Details::InterfaceTraits<I9>::CanCastTo(ptr, riid, ppv)) ? S_OK : E_NOINTERFACE; 734 } 735 736 // It's not possible to cast to IUnknown when Base interface inherit more interfaces 737 // The RuntimeClass is taking always the first interface as IUnknown thus it's required to 738 // list IInspectable or IUnknown class before MixIn<Derived, MixInType> parameter, such as: 739 // struct MyRuntimeClass : RuntimeClass<IInspectable, ChainInterfaces<MixIn<MyRuntimeClass,MyIndependentImplementation>, IFoo, IBar>, MyIndependentImplementation {} 740 IUnknown* CastToUnknown() throw() = delete; 741 742 static const unsigned long IidCount = 743 Details::InterfaceTraits<I1>::IidCount + 744 Details::InterfaceTraits<I2>::IidCount + 745 Details::InterfaceTraits<I3>::IidCount + 746 Details::InterfaceTraits<I4>::IidCount + 747 Details::InterfaceTraits<I5>::IidCount + 748 Details::InterfaceTraits<I6>::IidCount + 749 Details::InterfaceTraits<I7>::IidCount + 750 Details::InterfaceTraits<I8>::IidCount + 751 Details::InterfaceTraits<I9>::IidCount; 752 753 static void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw() 754 { 755 Details::InterfaceTraits<I1>::FillArrayWithIid(index, iids); 756 Details::InterfaceTraits<I2>::FillArrayWithIid(index, iids); 757 Details::InterfaceTraits<I3>::FillArrayWithIid(index, iids); 758 Details::InterfaceTraits<I4>::FillArrayWithIid(index, iids); 759 Details::InterfaceTraits<I5>::FillArrayWithIid(index, iids); 760 Details::InterfaceTraits<I6>::FillArrayWithIid(index, iids); 761 Details::InterfaceTraits<I7>::FillArrayWithIid(index, iids); 762 Details::InterfaceTraits<I8>::FillArrayWithIid(index, iids); 763 Details::InterfaceTraits<I9>::FillArrayWithIid(index, iids); 764 } 765 }; 766 767 namespace Details 768 { 769 770 #pragma region Implements helper templates 771 772 // Helper template used by Implements. This template traverses a list of interfaces and adds them as base class and information 773 // to enable QI. doStrictCheck is typically false only for the first interface, allowing IInspectable to be explicitly specified 774 // only as the first interface. 775 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> 776 struct __declspec(novtable) ImplementsHelper; 777 778 template <typename T> 779 struct __declspec(novtable) ImplementsMarker 780 {}; 781 782 template <typename I0, bool isImplements> 783 struct __declspec(novtable) MarkImplements; 784 785 template <typename I0> 786 struct __declspec(novtable) MarkImplements<I0, false> 787 { 788 typedef I0 Type; 789 }; 790 791 template <typename I0> 792 struct __declspec(novtable) MarkImplements<I0, true> 793 { 794 typedef ImplementsMarker<I0> Type; 795 }; 796 797 template <typename I0> 798 struct __declspec(novtable) MarkImplements<CloakedIid<I0>, true> 799 { 800 // Cloaked Implements type will be handled in the nested processing. 801 // Applying the ImplementsMarker too early will bypass Cloaked behavior. 802 typedef CloakedIid<I0> Type; 803 }; 804 805 template <typename DerivedType, typename BaseType, bool hasImplements> 806 struct __declspec(novtable) MarkImplements<MixIn<DerivedType, BaseType, hasImplements>, true> 807 { 808 // Implements type in mix-ins will be handled in the nested processing. 809 typedef MixIn<DerivedType, BaseType, hasImplements> Type; 810 }; 811 812 // AdjustImplements pre-processes the type list for more efficient builds. 813 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...Bases> 814 struct __declspec(novtable) AdjustImplements; 815 816 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename I0, typename ...Bases> 817 struct __declspec(novtable) AdjustImplements<RuntimeClassFlagsT, doStrictCheck, I0, Bases...> 818 { 819 typedef ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, typename MarkImplements<I0, __is_base_of(ImplementsBase, I0)>::Type, Bases...> Type; 820 }; 821 822 // Use AdjustImplements to remove instances of "Details::Nil" from the type list. 823 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...Bases> 824 struct __declspec(novtable) AdjustImplements<RuntimeClassFlagsT, doStrictCheck, typename Details::Nil, Bases...> 825 { 826 typedef typename AdjustImplements<RuntimeClassFlagsT, doStrictCheck, Bases...>::Type Type; 827 }; 828 829 830 template <typename RuntimeClassFlagsT, bool doStrictCheck> 831 struct __declspec(novtable) AdjustImplements<RuntimeClassFlagsT, doStrictCheck> 832 { 833 typedef ImplementsHelper<RuntimeClassFlagsT, doStrictCheck> Type; 834 }; 835 836 837 // Specialization handles unadorned interfaces 838 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename I0, typename ...TInterfaces> 839 struct __declspec(novtable) ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, I0, TInterfaces...> : 840 I0, 841 AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type 842 { 843 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct ImplementsHelper; 844 template <unsigned int RuntimeClassTypeT> friend class RuntimeClassBaseT; 845 846 protected: 847 848 HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) throw() 849 { 850 VerifyInterfaceHelper<RuntimeClassFlagsT::value & WinRtClassicComMix, I0, doStrictCheck>::Verify(); 851 // Prefer InlineIsEqualGUID over other forms since it's better perf on 4-byte aligned data, which is almost always the case. 852 if (InlineIsEqualGUID(riid, __uuidof(I0))) 853 { 854 *ppv = reinterpret_cast<I0*>(reinterpret_cast<void*>(this)); 855 return S_OK; 856 } 857 return AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type::CanCastTo(riid, ppv, pRefDelegated); 858 } 859 860 IUnknown* CastToUnknown() throw() 861 { 862 return reinterpret_cast<I0*>(reinterpret_cast<void*>(this)); 863 } 864 865 unsigned long GetIidCount() throw() 866 { 867 return 1 + AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type::GetIidCount(); 868 } 869 870 // FillArrayWithIid 871 void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw() 872 { 873 *(iids + *index) = __uuidof(I0); 874 (*index)++; 875 AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type::FillArrayWithIid(index, iids); 876 } 877 }; 878 879 880 // Selector is used to "tag" base interfaces to be used in casting, since a runtime class may indirectly derive from 881 // the same interface or Implements<> template multiple times 882 template <typename base, typename disciminator> 883 struct __declspec(novtable) Selector : public base 884 { 885 }; 886 887 // Specialization handles types that derive from ImplementsHelper (e.g. nested Implements). 888 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename I0, typename ...TInterfaces> 889 struct __declspec(novtable) ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, ImplementsMarker<I0>, TInterfaces...> : 890 Selector<I0, ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, ImplementsMarker<I0>, TInterfaces...>>, 891 Selector<typename AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type, ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, ImplementsMarker<I0>, TInterfaces...>> 892 { 893 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct ImplementsHelper; 894 template <unsigned int RuntimeClassTypeT> friend class RuntimeClassBaseT; 895 896 protected: 897 typedef Selector<I0, ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, ImplementsMarker<I0>, TInterfaces...>> CurrentType; 898 typedef Selector<typename AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type, ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, ImplementsMarker<I0>, TInterfaces...>> BaseType; 899 900 HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) throw() 901 { 902 VerifyInterfaceHelper<RuntimeClassFlagsT::value & WinRtClassicComMix, I0, doStrictCheck>::Verify(); 903 HRESULT hr = CurrentType::CanCastTo(riid, ppv); 904 if (hr == E_NOINTERFACE) 905 { 906 hr = BaseType::CanCastTo(riid, ppv, pRefDelegated); 907 } 908 return hr; 909 } 910 911 IUnknown* CastToUnknown() throw() 912 { 913 // First in list wins. 914 return CurrentType::CastToUnknown(); 915 } 916 917 unsigned long GetIidCount() throw() 918 { 919 return CurrentType::GetIidCount() + BaseType::GetIidCount(); 920 } 921 922 // FillArrayWithIid 923 void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw() 924 { 925 CurrentType::FillArrayWithIid(index, iids); 926 BaseType::FillArrayWithIid(index, iids); 927 } 928 }; 929 930 // CloakedIid instance. Since the first "real" interface should be checked against doStrictCheck, 931 // pass this through unchanged. Two specializations for cloaked prevent the need to use the Selector 932 // used in the Implements<> case. The same can't be done there because some type ambiguities are unavoidable. 933 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename I0, typename I1, typename ...TInterfaces> 934 struct __declspec(novtable) ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, CloakedIid<I0>, I1, TInterfaces...> : 935 AdjustImplements<RuntimeClassFlagsT, doStrictCheck, I0>::Type, 936 AdjustImplements<RuntimeClassFlagsT, true, I1, TInterfaces...>::Type 937 { 938 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct ImplementsHelper; 939 template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT; 940 941 protected: 942 943 typedef typename AdjustImplements<RuntimeClassFlagsT, doStrictCheck, I0>::Type CurrentType; 944 typedef typename AdjustImplements<RuntimeClassFlagsT, true, I1, TInterfaces...>::Type BaseType; 945 946 HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) throw() 947 { 948 VerifyInterfaceHelper<RuntimeClassFlagsT::value & WinRtClassicComMix, I0, doStrictCheck>::Verify(); 949 950 HRESULT hr = CurrentType::CanCastTo(riid, ppv, pRefDelegated); 951 if (SUCCEEDED(hr)) 952 { 953 return S_OK; 954 } 955 return BaseType::CanCastTo(riid, ppv, pRefDelegated); 956 } 957 958 IUnknown* CastToUnknown() throw() 959 { 960 return CurrentType::CastToUnknown(); 961 } 962 963 // Don't expose the cloaked IID(s), but continue processing the rest of the interfaces 964 unsigned long GetIidCount() throw() 965 { 966 return BaseType::GetIidCount(); 967 } 968 969 void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw() 970 { 971 BaseType::FillArrayWithIid(index, iids); 972 } 973 }; 974 975 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename I0> 976 struct __declspec(novtable) ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, CloakedIid<I0>> : 977 AdjustImplements<RuntimeClassFlagsT, doStrictCheck, I0>::Type 978 { 979 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct ImplementsHelper; 980 template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT; 981 982 protected: 983 984 typedef typename AdjustImplements<RuntimeClassFlagsT, doStrictCheck, I0>::Type CurrentType; 985 986 HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) throw() 987 { 988 VerifyInterfaceHelper<RuntimeClassFlagsT::value & WinRtClassicComMix, I0, doStrictCheck>::Verify(); 989 990 return CurrentType::CanCastTo(riid, ppv, pRefDelegated); 991 } 992 993 IUnknown* CastToUnknown() throw() 994 { 995 return CurrentType::CastToUnknown(); 996 } 997 998 // Don't expose the cloaked IID(s), but continue processing the rest of the interfaces 999 unsigned long GetIidCount() throw() 1000 { 1001 return 0; 1002 } 1003 1004 void FillArrayWithIid(_Inout_ unsigned long * /*index*/, _Inout_ IID* /*iids*/) throw() 1005 { 1006 // no-op 1007 } 1008 }; 1009 1010 1011 // terminal case specialization. 1012 template <typename RuntimeClassFlagsT, bool doStrictCheck> 1013 struct __declspec(novtable) ImplementsHelper<RuntimeClassFlagsT, doStrictCheck> 1014 { 1015 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct ImplementsHelper; 1016 template <unsigned int RuntimeClassTypeT> friend class RuntimeClassBaseT; 1017 1018 protected: 1019 template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT; 1020 1021 HRESULT CanCastTo(_In_ REFIID /*riid*/, _Outptr_ void ** /*ppv*/, bool * /*pRefDelegated*/ = nullptr) throw() 1022 { 1023 return E_NOINTERFACE; 1024 } 1025 1026 // IUnknown* CastToUnknown() throw(); // not defined for terminal case. 1027 1028 unsigned long GetIidCount() throw() 1029 { 1030 return 0; 1031 } 1032 1033 void FillArrayWithIid(_Inout_ unsigned long * /*index*/, _Inout_ IID* /*iids*/) throw() 1034 { 1035 } 1036 }; 1037 1038 // Specialization handles chaining interfaces 1039 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> 1040 struct __declspec(novtable) ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>, TInterfaces...> : 1041 ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>, 1042 AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type 1043 { 1044 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct ImplementsHelper; 1045 template <unsigned int RuntimeClassTypeT> friend class RuntimeClassBaseT; 1046 1047 protected: 1048 template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT; 1049 typedef typename AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type BaseType; 1050 1051 HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) throw() 1052 { 1053 ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>::template Verify<RuntimeClassFlagsT::value>(); 1054 1055 HRESULT hr = ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>::CanCastTo(riid, ppv); 1056 if (FAILED(hr)) 1057 { 1058 hr = BaseType::CanCastTo(riid, ppv, pRefDelegated); 1059 } 1060 1061 return hr; 1062 } 1063 1064 IUnknown* CastToUnknown() throw() 1065 { 1066 return ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>::CastToUnknown(); 1067 } 1068 1069 unsigned long GetIidCount() throw() 1070 { 1071 return ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>::IidCount + BaseType::GetIidCount(); 1072 } 1073 1074 void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw() 1075 { 1076 ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>::FillArrayWithIid(index, iids); 1077 BaseType::FillArrayWithIid(index, iids); 1078 } 1079 }; 1080 1081 1082 // Mixin specialization 1083 template <typename RuntimeClassFlagsT, typename DerivedType, typename BaseMixInType, bool hasImplements, typename ...TInterfaces, bool doStrictCheck> 1084 struct __declspec(novtable) ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, MixIn<DerivedType, BaseMixInType, hasImplements>, TInterfaces...> : 1085 AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type 1086 { 1087 static_assert(hasImplements, "Cannot use MixIn to with a class not deriving from \"Implements\""); 1088 1089 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct ImplementsHelper; 1090 template <unsigned int RuntimeClassTypeT> friend class RuntimeClassBaseT; 1091 1092 protected: 1093 template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT; 1094 typedef typename AdjustImplements<RuntimeClassFlagsT, true, TInterfaces...>::Type BaseType; 1095 1096 HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) throw() 1097 { 1098 VerifyInterfaceHelper<RuntimeClassFlagsT::value & WinRtClassicComMix, BaseMixInType, doStrictCheck>::Verify(); 1099 1100 HRESULT hr = static_cast<BaseMixInType*>(static_cast<DerivedType*>(this))->CanCastTo(riid, ppv); 1101 if (FAILED(hr)) 1102 { 1103 hr = BaseType::CanCastTo(riid, ppv, pRefDelegated); 1104 } 1105 1106 return hr; 1107 } 1108 1109 IUnknown* CastToUnknown() throw() 1110 { 1111 return static_cast<BaseMixInType*>(static_cast<DerivedType*>(this))->CastToUnknown(); 1112 } 1113 1114 unsigned long GetIidCount() throw() 1115 { 1116 return static_cast<BaseMixInType*>(static_cast<DerivedType*>(this))->GetIidCount() + 1117 BaseType::GetIidCount(); 1118 } 1119 1120 void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw() 1121 { 1122 static_cast<BaseMixInType*>(static_cast<DerivedType*>(this))->FillArrayWithIid(index, iids); 1123 BaseType::FillArrayWithIid(index, iids); 1124 } 1125 }; 1126 1127 // Specialization handles inheriting COM objects. ComposableBase must be the last non-nil interface in the list. 1128 // Trailing nil's are allowed for compatibility with some tools that pad out the list. 1129 template <typename I0, typename ...> 1130 struct AreAllNil 1131 { 1132 static const bool value = false; 1133 }; 1134 1135 template <typename ...TInterfaces> 1136 struct AreAllNil<Microsoft::WRL::Details::Nil, TInterfaces...> 1137 { 1138 static const bool value = AreAllNil<TInterfaces...>::value; 1139 }; 1140 1141 template <> 1142 struct AreAllNil<Microsoft::WRL::Details::Nil> 1143 { 1144 static const bool value = true; 1145 }; 1146 1147 template <typename RuntimeClassFlagsT, typename FactoryInterface, bool doStrictCheck, typename ...TInterfaces> 1148 struct __declspec(novtable) ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, ComposableBase<FactoryInterface>, TInterfaces...> : 1149 ImplementsHelper<RuntimeClassFlagsT, true, ComposableBase<FactoryInterface>> 1150 { 1151 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct ImplementsHelper; 1152 template <unsigned int RuntimeClassTypeT> friend class RuntimeClassBaseT; 1153 1154 protected: 1155 template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT; 1156 1157 typedef ImplementsHelper<RuntimeClassFlagsT, true, ComposableBase<FactoryInterface>> BaseType; 1158 1159 HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) throw() 1160 { 1161 static_assert(AreAllNil<TInterfaces...>::value, "ComposableBase should be the last template parameter to RuntimeClass"); 1162 return BaseType::CanCastTo(riid, ppv, pRefDelegated); 1163 } 1164 1165 IUnknown* CastToUnknown() throw() 1166 { 1167 static_assert(AreAllNil<TInterfaces...>::value, "ComposableBase should be the last template parameter to RuntimeClass"); 1168 return BaseType::CastToUnknown(); 1169 } 1170 1171 unsigned long GetIidCount() throw() 1172 { 1173 static_assert(AreAllNil<TInterfaces...>::value, "ComposableBase should be the last template parameter to RuntimeClass"); 1174 return BaseType::GetIidCount(); 1175 } 1176 1177 void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw() 1178 { 1179 static_assert(AreAllNil<TInterfaces...>::value, "ComposableBase should be the last template parameter to RuntimeClass"); 1180 BaseType::FillArrayWithIid(index, iids); 1181 } 1182 }; 1183 1184 template <typename RuntimeClassFlagsT, typename FactoryInterface, bool doStrictCheck> 1185 struct __declspec(novtable) ImplementsHelper<RuntimeClassFlagsT, doStrictCheck, ComposableBase<FactoryInterface>> 1186 { 1187 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct ImplementsHelper; 1188 template <unsigned int RuntimeClassTypeT> friend class RuntimeClassBaseT; 1189 1190 protected: 1191 template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT; 1192 1193 HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated) throw() 1194 { 1195 *pRefDelegated = true; 1196 return composableBase_.CopyTo(riid, ppv); 1197 } 1198 1199 IUnknown* CastToUnknown() throw() 1200 { 1201 return nullptr; 1202 } 1203 1204 unsigned long GetIidCount() throw() 1205 { 1206 return iidCount_; 1207 } 1208 1209 void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw() 1210 { 1211 for(unsigned long i = 0; i < iidCount_; i++) 1212 { 1213 *(iids + *index) = *(iidsCached_ + i); 1214 (*index)++; 1215 } 1216 } 1217 1218 ImplementsHelper() throw() : iidsCached_(nullptr), iidCount_(0) 1219 { 1220 } 1221 1222 ~ImplementsHelper() throw() 1223 { 1224 ::CoTaskMemFree(iidsCached_); 1225 iidsCached_ = nullptr; 1226 iidCount_ = 0; 1227 } 1228 1229 public: 1230 HRESULT SetComposableBasePointers(_In_ IInspectable* base, _In_opt_ FactoryInterface* baseFactory = nullptr) throw() 1231 { 1232 if (composableBase_ != nullptr) 1233 { 1234 #if (NTDDI_VERSION >= NTDDI_WINBLUE) 1235 ErrorHelper<RuntimeClassFlagsT::value & InhibitRoOriginateError>::OriginateError(E_UNEXPECTED, nullptr); 1236 #endif // (NTDDI_VERSION >= NTDDI_WINBLUE) 1237 return E_UNEXPECTED; 1238 } 1239 1240 HRESULT hr = base->GetIids(&iidCount_, &iidsCached_); 1241 if (SUCCEEDED(hr)) 1242 { 1243 composableBase_ = base; 1244 composableBaseFactory_ = baseFactory; 1245 } 1246 return hr; 1247 } 1248 1249 ComPtr<IInspectable> GetComposableBase() throw() 1250 { 1251 return composableBase_; 1252 } 1253 1254 ComPtr<FactoryInterface> GetComposableBaseFactory() throw() 1255 { 1256 return composableBaseFactory_; 1257 } 1258 1259 private: 1260 ComPtr<IInspectable> composableBase_; 1261 ComPtr<FactoryInterface> composableBaseFactory_; 1262 IID *iidsCached_; 1263 unsigned long iidCount_; 1264 }; 1265 1266 #pragma endregion // Implements helper templates 1267 1268 } // namespace Details 1269 1270 // Implements - template implementing QI using the information provided through its template parameters 1271 // Each template parameter has to be one of the following: 1272 // * COM Interface 1273 // * A class that implements one or more COM interfaces 1274 // * ChainInterfaces template 1275 template <typename I0, typename ...TInterfaces> 1276 struct __declspec(novtable) Implements : 1277 Details::AdjustImplements<RuntimeClassFlags<WinRt>, true, I0, TInterfaces...>::Type, 1278 Details::ImplementsBase 1279 { 1280 public: 1281 typedef RuntimeClassFlags<WinRt> ClassFlags; 1282 typedef I0 FirstInterface; 1283 protected: 1284 typedef typename Details::AdjustImplements<RuntimeClassFlags<WinRt>, true, I0, TInterfaces...>::Type BaseType; 1285 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct Details::ImplementsHelper; 1286 template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT; 1287 1288 HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv) throw() 1289 { 1290 return BaseType::CanCastTo(riid, ppv); 1291 } 1292 1293 IUnknown* CastToUnknown() throw() 1294 { 1295 return BaseType::CastToUnknown(); 1296 } 1297 1298 unsigned long GetIidCount() throw() 1299 { 1300 return BaseType::GetIidCount(); 1301 } 1302 1303 void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw() 1304 { 1305 BaseType::FillArrayWithIid(index, iids); 1306 } 1307 }; 1308 1309 template <int flags, typename I0, typename ...TInterfaces> 1310 struct __declspec(novtable) Implements<RuntimeClassFlags<flags>, I0, TInterfaces...> : 1311 Details::AdjustImplements<RuntimeClassFlags<flags>, true, I0, TInterfaces...>::Type, 1312 Details::ImplementsBase 1313 { 1314 public: 1315 typedef RuntimeClassFlags<flags> ClassFlags; 1316 typedef I0 FirstInterface; 1317 protected: 1318 1319 typedef typename Details::AdjustImplements<RuntimeClassFlags<flags>, true, I0, TInterfaces...>::Type BaseType; 1320 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct Details::ImplementsHelper; 1321 template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT; 1322 1323 HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv) throw() 1324 { 1325 return BaseType::CanCastTo(riid, ppv); 1326 } 1327 1328 IUnknown* CastToUnknown() throw() 1329 { 1330 return BaseType::CastToUnknown(); 1331 } 1332 1333 unsigned long GetIidCount() throw() 1334 { 1335 return BaseType::GetIidCount(); 1336 } 1337 1338 void FillArrayWithIid(_Inout_ unsigned long *index, _Inout_ IID* iids) throw() 1339 { 1340 BaseType::FillArrayWithIid(index, iids); 1341 } 1342 }; 1343 1344 class FtmBase : 1345 public Implements< 1346 ::Microsoft::WRL::RuntimeClassFlags<WinRtClassicComMix>, 1347 ::Microsoft::WRL::CloakedIid< ::IMarshal> >, 1348 // Inheriting from FtmBaseMarker allows using FtmBase on classes configured with RuntimeClassFlags<WinRt> (Default configuration) 1349 private ::Microsoft::WRL::Details::FtmBaseMarker 1350 { 1351 // defining type 'Super' for other compilers since '__super' is a VC++-specific language extension 1352 using Super = Implements< 1353 ::Microsoft::WRL::RuntimeClassFlags<WinRtClassicComMix>, 1354 ::Microsoft::WRL::CloakedIid< ::IMarshal> >; 1355 protected: 1356 template <typename RuntimeClassFlagsT, bool doStrictCheck, typename ...TInterfaces> friend struct Details::ImplementsHelper; 1357 1358 HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv) throw() 1359 { 1360 // Prefer InlineIsEqualGUID over other forms since it's better perf on 4-byte aligned data, which is almost always the case. 1361 if (InlineIsEqualGUID(riid, __uuidof(::IAgileObject))) 1362 { 1363 1364 *ppv = Super::CastToUnknown(); 1365 return S_OK; 1366 } 1367 1368 return Super::CanCastTo(riid, ppv); 1369 } 1370 1371 public: 1372 FtmBase() throw() 1373 { 1374 ComPtr<IUnknown> unknown; 1375 if (SUCCEEDED(::CoCreateFreeThreadedMarshaler(nullptr, &unknown))) 1376 { 1377 unknown.As(&marshaller_); 1378 } 1379 } 1380 1381 // IMarshal Methods 1382 #pragma warning(suppress: 6101) // PREFast cannot see through the smart-pointer invocation 1383 STDMETHOD(GetUnmarshalClass)(_In_ REFIID riid, 1384 _In_opt_ void *pv, 1385 _In_ DWORD dwDestContext, 1386 _Reserved_ void *pvDestContext, 1387 _In_ DWORD mshlflags, 1388 _Out_ CLSID *pCid) override 1389 { 1390 if (marshaller_) 1391 { 1392 return marshaller_->GetUnmarshalClass(riid, pv, dwDestContext, pvDestContext, mshlflags, pCid); 1393 } 1394 return E_OUTOFMEMORY; 1395 } 1396 1397 #pragma warning(suppress: 6101) // PREFast cannot see through the smart-pointer invocation 1398 STDMETHOD(GetMarshalSizeMax)(_In_ REFIID riid, _In_opt_ void *pv, _In_ DWORD dwDestContext, 1399 _Reserved_ void *pvDestContext, _In_ DWORD mshlflags, _Out_ DWORD *pSize) override 1400 { 1401 if (marshaller_) 1402 { 1403 return marshaller_->GetMarshalSizeMax(riid, pv, dwDestContext, pvDestContext, mshlflags, pSize); 1404 } 1405 return E_OUTOFMEMORY; 1406 } 1407 1408 STDMETHOD(MarshalInterface)(_In_ IStream *pStm, _In_ REFIID riid, _In_opt_ void *pv, _In_ DWORD dwDestContext, 1409 _Reserved_ void *pvDestContext, _In_ DWORD mshlflags) override 1410 { 1411 if (marshaller_) 1412 { 1413 return marshaller_->MarshalInterface(pStm, riid, pv, dwDestContext, pvDestContext, mshlflags); 1414 } 1415 return E_OUTOFMEMORY; 1416 } 1417 1418 #pragma warning(suppress: 6101) // PREFast cannot see through the smart-pointer invocation 1419 STDMETHOD(UnmarshalInterface)(_In_ IStream *pStm, _In_ REFIID riid, _Outptr_ void **ppv) override 1420 { 1421 if (marshaller_) 1422 { 1423 return marshaller_->UnmarshalInterface(pStm, riid, ppv); 1424 } 1425 return E_OUTOFMEMORY; 1426 } 1427 1428 STDMETHOD(ReleaseMarshalData)(_In_ IStream *pStm) override 1429 { 1430 if (marshaller_) 1431 { 1432 return marshaller_->ReleaseMarshalData(pStm); 1433 } 1434 return E_OUTOFMEMORY; 1435 } 1436 1437 STDMETHOD(DisconnectObject)(_In_ DWORD dwReserved) override 1438 { 1439 if (marshaller_) 1440 { 1441 return marshaller_->DisconnectObject(dwReserved); 1442 } 1443 return E_OUTOFMEMORY; 1444 } 1445 1446 static HRESULT CreateGlobalInterfaceTable(_Out_ IGlobalInterfaceTable **git) throw() 1447 { 1448 *git = nullptr; 1449 return ::CoCreateInstance(CLSID_StdGlobalInterfaceTable, 1450 nullptr, 1451 CLSCTX_INPROC_SERVER, 1452 __uuidof(IGlobalInterfaceTable), 1453 reinterpret_cast<void**>(git)); 1454 } 1455 1456 ::Microsoft::WRL::ComPtr<IMarshal> marshaller_; // Holds a reference to the free threaded marshaler 1457 }; 1458 1459 namespace Details 1460 { 1461 1462 #ifdef _PERF_COUNTERS 1463 class __declspec(novtable) PerfCountersBase 1464 { 1465 public: 1466 ULONG GetAddRefCount() throw() 1467 { 1468 return addRefCount_; 1469 } 1470 1471 ULONG GetReleaseCount() throw() 1472 { 1473 return releaseCount_; 1474 } 1475 1476 ULONG GetQueryInterfaceCount() throw() 1477 { 1478 return queryInterfaceCount_; 1479 } 1480 1481 void ResetPerfCounters() throw() 1482 { 1483 addRefCount_ = 0; 1484 releaseCount_ = 0; 1485 queryInterfaceCount_ = 0; 1486 } 1487 1488 protected: 1489 PerfCountersBase() throw() : 1490 addRefCount_(0), 1491 releaseCount_(0), 1492 queryInterfaceCount_(0) 1493 { 1494 } 1495 1496 void IncrementAddRefCount() throw() 1497 { 1498 InterlockedIncrement(&addRefCount_); 1499 } 1500 1501 void IncrementReleaseCount() throw() 1502 { 1503 InterlockedIncrement(&releaseCount_); 1504 } 1505 1506 void IncrementQueryInterfaceCount() throw() 1507 { 1508 InterlockedIncrement(&queryInterfaceCount_); 1509 } 1510 1511 private: 1512 volatile unsigned long addRefCount_; 1513 volatile unsigned long releaseCount_; 1514 volatile unsigned long queryInterfaceCount_; 1515 }; 1516 #endif 1517 1518 #if defined(_X86_) || defined(_AMD64_) 1519 1520 #define UnknownIncrementReference InterlockedIncrement 1521 #define UnknownDecrementReference InterlockedDecrement 1522 #define UnknownBarrierAfterInterlock() 1523 #define UnknownInterlockedCompareExchangePointer InterlockedCompareExchangePointer 1524 #define UnknownInterlockedCompareExchangePointerForIncrement InterlockedCompareExchangePointer 1525 #define UnknownInterlockedCompareExchangePointerForRelease InterlockedCompareExchangePointer 1526 1527 #elif defined(_ARM_) 1528 1529 #define UnknownIncrementReference InterlockedIncrementNoFence 1530 #define UnknownDecrementReference InterlockedDecrementRelease 1531 #define UnknownBarrierAfterInterlock() __dmb(_ARM_BARRIER_ISH) 1532 #define UnknownInterlockedCompareExchangePointer InterlockedCompareExchangePointer 1533 #define UnknownInterlockedCompareExchangePointerForIncrement InterlockedCompareExchangePointerNoFence 1534 #define UnknownInterlockedCompareExchangePointerForRelease InterlockedCompareExchangePointerRelease 1535 1536 #elif defined(_ARM64_) 1537 1538 #define UnknownIncrementReference InterlockedIncrementNoFence 1539 #define UnknownDecrementReference InterlockedDecrementRelease 1540 #define UnknownBarrierAfterInterlock() __dmb(_ARM64_BARRIER_ISH) 1541 #define UnknownInterlockedCompareExchangePointer InterlockedCompareExchangePointer 1542 #define UnknownInterlockedCompareExchangePointerForIncrement InterlockedCompareExchangePointerNoFence 1543 #define UnknownInterlockedCompareExchangePointerForRelease InterlockedCompareExchangePointerRelease 1544 1545 #else 1546 1547 #error Unsupported architecture. 1548 1549 #endif 1550 1551 // Since variadic templates can't have a parameter pack after default arguments, provide a convenient helper for defaults. 1552 #define DETAILS_RTCLASS_FLAGS_ARGUMENTS(RuntimeClassFlagsT) \ 1553 RuntimeClassFlagsT, \ 1554 (RuntimeClassFlagsT::value & InhibitWeakReference) == 0, \ 1555 (RuntimeClassFlagsT::value & WinRt) == WinRt, \ 1556 __WRL_IMPLEMENTS_FTM_BASE__(RuntimeClassFlagsT::value) \ 1557 1558 template <class RuntimeClassFlagsT, bool implementsWeakReferenceSource, bool implementsInspectable, bool implementsFtmBase, typename ...TInterfaces> 1559 class __declspec(novtable) RuntimeClassImpl; 1560 1561 #pragma warning(push) 1562 // PREFast cannot see through template instantiation for AsIID() 1563 #pragma warning(disable: 6388) 1564 1565 template <class RuntimeClassFlagsT, bool implementsWeakReferenceSource, bool implementsFtmBase, typename ...TInterfaces> 1566 class __declspec(novtable) RuntimeClassImpl<RuntimeClassFlagsT, implementsWeakReferenceSource, false, implementsFtmBase, TInterfaces...> : 1567 public Details::AdjustImplements<RuntimeClassFlagsT, false, TInterfaces...>::Type, 1568 public RuntimeClassBaseT<RuntimeClassFlagsT::value>, 1569 protected RuntimeClassFlags<InhibitWeakReference>, 1570 public DontUseNewUseMake 1571 #ifdef _PERF_COUNTERS 1572 , public PerfCountersBase 1573 #endif 1574 { 1575 public: 1576 typedef RuntimeClassFlagsT ClassFlags; 1577 1578 STDMETHOD(QueryInterface)(REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject) 1579 { 1580 #ifdef _PERF_COUNTERS 1581 IncrementQueryInterfaceCount(); 1582 #endif 1583 return Super::AsIID(this, riid, ppvObject); 1584 } 1585 1586 STDMETHOD_(ULONG, AddRef)() 1587 { 1588 return InternalAddRef(); 1589 } 1590 1591 STDMETHOD_(ULONG, Release)() 1592 { 1593 ULONG ref = InternalRelease(); 1594 if (ref == 0) 1595 { 1596 delete this; 1597 1598 auto modulePtr = ::Microsoft::WRL::GetModuleBase(); 1599 if (modulePtr != nullptr) 1600 { 1601 modulePtr->DecrementObjectCount(); 1602 } 1603 } 1604 1605 return ref; 1606 } 1607 1608 protected: 1609 using Super = RuntimeClassBaseT<RuntimeClassFlagsT::value>; 1610 1611 RuntimeClassImpl() throw() : refcount_(1) 1612 { 1613 } 1614 1615 virtual ~RuntimeClassImpl() throw() 1616 { 1617 // Set refcount_ to -(LONG_MAX/2) to protect destruction and 1618 // also catch mismatched Release in debug builds 1619 refcount_ = -(LONG_MAX/2); 1620 } 1621 1622 unsigned long InternalAddRef() throw() 1623 { 1624 #ifdef _PERF_COUNTERS 1625 IncrementAddRefCount(); 1626 #endif 1627 return UnknownIncrementReference(&refcount_); 1628 } 1629 1630 unsigned long InternalRelease() throw() 1631 { 1632 #ifdef _PERF_COUNTERS 1633 IncrementReleaseCount(); 1634 #endif 1635 // A release fence is required to ensure all guarded memory accesses are 1636 // complete before any thread can begin destroying the object. 1637 unsigned long newValue = UnknownDecrementReference(&refcount_); 1638 if (newValue == 0) 1639 { 1640 // An acquire fence is required before object destruction to ensure 1641 // that the destructor cannot observe values changing on other threads. 1642 UnknownBarrierAfterInterlock(); 1643 } 1644 return newValue; 1645 } 1646 1647 unsigned long GetRefCount() const throw() 1648 { 1649 return refcount_; 1650 } 1651 1652 friend class WeakReferenceImpl; 1653 1654 private: 1655 volatile long refcount_; 1656 }; 1657 1658 template<typename I, bool isImplementsBased = __is_base_of(ImplementsBase, I)> 1659 struct HasIInspectable; 1660 1661 template<typename I> 1662 struct HasIInspectable<I, false> 1663 { 1664 static const bool isIInspectable = __is_base_of(IInspectable, I); 1665 }; 1666 1667 template<typename I> 1668 struct HasIInspectable<I, true> 1669 { 1670 static const bool isIInspectable = HasIInspectable<typename I::FirstInterface>::isIInspectable; 1671 }; 1672 1673 #ifdef __WRL_STRICT__ 1674 template<typename I0, bool isIInspectable = true> 1675 #else 1676 template<typename I0, bool isIInspectable = HasIInspectable<I0>::isIInspectable> 1677 #endif 1678 struct IInspectableInjector; 1679 1680 template<typename I0> 1681 struct IInspectableInjector<I0, true> 1682 { 1683 typedef Details::Nil InspectableIfNeeded; 1684 }; 1685 1686 template<typename I0> 1687 struct IInspectableInjector<I0, false> 1688 { 1689 typedef IInspectable InspectableIfNeeded; 1690 }; 1691 1692 // Implements IInspectable in ILst 1693 template <class RuntimeClassFlagsT, typename I0, typename ...TInterfaces> 1694 class __declspec(novtable) RuntimeClassImpl<RuntimeClassFlagsT, false, true, false, I0, TInterfaces...> : 1695 public Details::AdjustImplements<RuntimeClassFlagsT, false, typename IInspectableInjector<I0>::InspectableIfNeeded, I0, TInterfaces...>::Type, 1696 public RuntimeClassBaseT<RuntimeClassFlagsT::value>, 1697 protected RuntimeClassFlags<InhibitWeakReference>, 1698 public DontUseNewUseMake 1699 #ifdef _PERF_COUNTERS 1700 , public PerfCountersBase 1701 #endif 1702 { 1703 public: 1704 typedef RuntimeClassFlagsT ClassFlags; 1705 1706 STDMETHOD(QueryInterface)(REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject) 1707 { 1708 #ifdef _PERF_COUNTERS 1709 IncrementQueryInterfaceCount(); 1710 #endif 1711 return Super::AsIID(this, riid, ppvObject); 1712 } 1713 1714 STDMETHOD_(ULONG, AddRef)() 1715 { 1716 return InternalAddRef(); 1717 } 1718 1719 STDMETHOD_(ULONG, Release)() 1720 { 1721 ULONG ref = InternalRelease(); 1722 if (ref == 0) 1723 { 1724 delete this; 1725 1726 auto modulePtr = ::Microsoft::WRL::GetModuleBase(); 1727 if (modulePtr != nullptr) 1728 { 1729 modulePtr->DecrementObjectCount(); 1730 } 1731 } 1732 1733 return ref; 1734 } 1735 1736 // IInspectable methods 1737 STDMETHOD(GetIids)( 1738 _Out_ ULONG *iidCount, 1739 _When_(*iidCount == 0, _At_(*iids, _Post_null_)) 1740 _When_(*iidCount > 0, _At_(*iids, _Post_notnull_)) 1741 _Result_nullonfailure_ IID **iids) 1742 { 1743 return Super::GetImplementedIIDS(this, iidCount, iids); 1744 } 1745 1746 #if !defined(__WRL_STRICT__) || !defined(__WRL_FORCE_INSPECTABLE_CLASS_MACRO__) 1747 STDMETHOD(GetRuntimeClassName)(_Out_ HSTRING* runtimeClassName) 1748 { 1749 *runtimeClassName = nullptr; 1750 1751 __WRL_ASSERT__(false && "Use InspectableClass macro to set runtime class name and trust level."); 1752 1753 #if (NTDDI_VERSION >= NTDDI_WINBLUE) 1754 ErrorHelper<RuntimeClassFlagsT::value & InhibitRoOriginateError>::OriginateError(E_NOTIMPL, nullptr); 1755 #endif // (NTDDI_VERSION >= NTDDI_WINBLUE) 1756 return E_NOTIMPL; 1757 } 1758 1759 STDMETHOD(GetTrustLevel)(_Out_ ::TrustLevel*) 1760 { 1761 __WRL_ASSERT__(false && "Use InspectableClass macro to set runtime class name and trust level."); 1762 1763 #if (NTDDI_VERSION >= NTDDI_WINBLUE) 1764 ErrorHelper<RuntimeClassFlagsT::value & InhibitRoOriginateError>::OriginateError(E_NOTIMPL, nullptr); 1765 #endif // (NTDDI_VERSION >= NTDDI_WINBLUE) 1766 return E_NOTIMPL; 1767 } 1768 #endif // !defined(__WRL_STRICT__) || !defined(__WRL_FORCE_INSPECTABLE_CLASS_MACRO__) 1769 1770 protected: 1771 using Super = RuntimeClassBaseT<RuntimeClassFlagsT::value>; 1772 1773 RuntimeClassImpl() throw() : refcount_(1) 1774 { 1775 } 1776 1777 virtual ~RuntimeClassImpl() throw() 1778 { 1779 // Set refcount_ to -(LONG_MAX/2) to protect destruction and 1780 // also catch mismatched Release in debug builds 1781 refcount_ = -(LONG_MAX/2); 1782 } 1783 1784 unsigned long InternalAddRef() throw() 1785 { 1786 #ifdef _PERF_COUNTERS 1787 IncrementAddRefCount(); 1788 #endif 1789 return UnknownIncrementReference(&refcount_); 1790 } 1791 1792 unsigned long InternalRelease() throw() 1793 { 1794 #ifdef _PERF_COUNTERS 1795 IncrementReleaseCount(); 1796 #endif 1797 // A release fence is required to ensure all guarded memory accesses are 1798 // complete before any thread can begin destroying the object. 1799 unsigned long newValue = UnknownDecrementReference(&refcount_); 1800 if (newValue == 0) 1801 { 1802 // An acquire fence is required before object destruction to ensure 1803 // that the destructor cannot observe values changing on other threads. 1804 UnknownBarrierAfterInterlock(); 1805 } 1806 return newValue; 1807 } 1808 1809 unsigned long GetRefCount() const throw() 1810 { 1811 return refcount_; 1812 } 1813 private: 1814 volatile long refcount_; 1815 }; 1816 1817 class StrongReference 1818 { 1819 public: 1820 StrongReference(long refCount = 1) throw() : strongRefCount_(refCount) {} 1821 1822 ~StrongReference() throw() 1823 { 1824 // Set refcount_ to -(LONG_MAX/2) to protect destruction and 1825 // also catch mismatched Release in debug builds 1826 strongRefCount_ = -(LONG_MAX / 2); 1827 } 1828 1829 unsigned long IncrementStrongReference() throw() 1830 { 1831 return UnknownIncrementReference(&strongRefCount_); 1832 } 1833 1834 unsigned long DecrementStrongReference() throw() 1835 { 1836 // A release fence is required to ensure all guarded memory accesses are 1837 // complete before any thread can begin destroying the object. 1838 unsigned long newValue = UnknownDecrementReference(&strongRefCount_); 1839 if (newValue == 0) 1840 { 1841 // An acquire fence is required before object destruction to ensure 1842 // that the destructor cannot observe values changing on other threads. 1843 UnknownBarrierAfterInterlock(); 1844 } 1845 return newValue; 1846 } 1847 1848 unsigned long GetStrongReferenceCount() throw() 1849 { 1850 return strongRefCount_; 1851 } 1852 1853 void SetStrongReference(unsigned long value) throw() 1854 { 1855 strongRefCount_ = value; 1856 } 1857 1858 long strongRefCount_; 1859 }; 1860 1861 // To support storing, encoding and decoding reference-count/pointers regardless of the target platform. 1862 // In a RuntimeClass, the refCount_ member can mean either 1863 // 1. actual reference count 1864 // 2. pointer to the weak reference object which holds the strong count 1865 // The member 1866 // 1. If it is a count, the most significant bit will be OFF 1867 // 2. If it is an encoded pointer to the weak reference, the most significant bit will be turned ON 1868 // To test which mode it is 1869 // 1. Test for negative 1870 // 2. If it is, it is an encoded pointer to the weak reference 1871 // 3. If it is not, it is the actual reference count 1872 // To yield the encoded pointer 1873 // 1. Test the value for negative 1874 // 2. If it is, shift the value to the left and cast it to a WeakReferenceImpl* 1875 // 1876 const UINT_PTR EncodeWeakReferencePointerFlag = static_cast<UINT_PTR>(1) << ((sizeof(UINT_PTR) * 8) - 1); 1877 1878 union ReferenceCountOrWeakReferencePointer 1879 { 1880 // Represents the count when it is a count (in practice only the least significant 4 bytes) 1881 UINT_PTR refCount; 1882 // Pointer size, *signed* to help with ease of casting and such 1883 INT_PTR rawValue; 1884 // The hint that this could also be a pointer 1885 void* ifHighBitIsSetThenShiftLeftToYieldPointerToWeakReference; 1886 }; 1887 1888 // Helper methods to test, decode and decode the different representations of ReferenceCountOrWeakReferencePointer 1889 inline bool IsValueAPointerToWeakReference(INT_PTR value) 1890 { 1891 return value < 0; 1892 } 1893 1894 // Forward declaration 1895 class WeakReferenceImpl; 1896 inline INT_PTR EncodeWeakReferencePointer(Microsoft::WRL::Details::WeakReferenceImpl* value); 1897 inline Microsoft::WRL::Details::WeakReferenceImpl* DecodeWeakReferencePointer(INT_PTR value); 1898 1899 // Helper functions, originally from winnt.h, needed to get the semantics right when fetching values 1900 // in multi-threaded scenarios. This is in order to guarantee the compiler emits exactly one read 1901 // (compiler may decide to re-fetch the value later on, which in some cases can break code) 1902 #if defined(_ARM_) 1903 1904 FORCEINLINE 1905 LONG 1906 ReadULongPtrNoFence ( 1907 _In_ _Interlocked_operand_ DWORD const volatile *Source 1908 ) 1909 1910 { 1911 LONG Value; 1912 1913 Value = __iso_volatile_load32((int *)Source); 1914 return Value; 1915 } 1916 1917 #elif defined(_ARM64_) 1918 1919 FORCEINLINE 1920 LONG64 1921 ReadULongPtrNoFence ( 1922 _In_ _Interlocked_operand_ DWORD64 const volatile *Source 1923 ) 1924 1925 { 1926 LONG64 Value; 1927 1928 Value = __iso_volatile_load64((__int64 *)Source); 1929 return Value; 1930 } 1931 1932 #elif defined(_X86_) 1933 1934 FORCEINLINE 1935 LONG 1936 ReadULongPtrNoFence ( 1937 _In_ _Interlocked_operand_ DWORD const volatile *Source 1938 ) 1939 1940 { 1941 LONG Value; 1942 1943 Value = *Source; 1944 return Value; 1945 } 1946 1947 #elif defined(_AMD64_) 1948 1949 FORCEINLINE 1950 LONG64 1951 ReadULongPtrNoFence ( 1952 _In_ _Interlocked_operand_ DWORD64 const volatile *Source 1953 ) 1954 1955 { 1956 LONG64 Value; 1957 1958 Value = *Source; 1959 return Value; 1960 } 1961 1962 #else 1963 1964 #error Unsupported architecture. 1965 1966 #endif 1967 1968 template <typename T> 1969 inline T ReadValueFromPointerNoFence(_In_ const volatile T* value) 1970 { 1971 ULONG_PTR currentValue = ReadULongPtrNoFence(reinterpret_cast<const volatile ULONG_PTR *>(value)); 1972 const T* currentPointerToValue = reinterpret_cast<T*>(¤tValue); 1973 return *currentPointerToValue; 1974 } 1975 1976 inline WeakReferenceImpl* CreateWeakReference(_In_ IUnknown*); 1977 1978 // Implementation of activatable class that implements IWeakReferenceSource 1979 // and delegates reference counting to WeakReferenceImpl object 1980 template <class RuntimeClassFlagsT, typename I0, typename ...TInterfaces> 1981 class __declspec(novtable) RuntimeClassImpl<RuntimeClassFlagsT, true, true, false, I0, TInterfaces...> : 1982 public Details::AdjustImplements<RuntimeClassFlagsT, false, typename IInspectableInjector<I0>::InspectableIfNeeded, I0, IWeakReferenceSource, TInterfaces...>::Type, 1983 public RuntimeClassBaseT<RuntimeClassFlagsT::value>, 1984 public DontUseNewUseMake 1985 #ifdef _PERF_COUNTERS 1986 , public PerfCountersBase 1987 #endif 1988 { 1989 public: 1990 typedef RuntimeClassFlagsT ClassFlags; 1991 1992 RuntimeClassImpl() throw() 1993 { 1994 refCount_.rawValue = 1; 1995 } 1996 1997 STDMETHOD(QueryInterface)(REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject) 1998 { 1999 #ifdef _PERF_COUNTERS 2000 IncrementQueryInterfaceCount(); 2001 #endif 2002 return Super::AsIID(this, riid, ppvObject); 2003 } 2004 2005 STDMETHOD_(ULONG, AddRef)() 2006 { 2007 return InternalAddRef(); 2008 } 2009 2010 STDMETHOD_(ULONG, Release)() 2011 { 2012 ULONG ref = InternalRelease(); 2013 if (ref == 0) 2014 { 2015 delete this; 2016 2017 auto modulePtr = ::Microsoft::WRL::GetModuleBase(); 2018 if (modulePtr != nullptr) 2019 { 2020 modulePtr->DecrementObjectCount(); 2021 } 2022 } 2023 2024 return ref; 2025 } 2026 2027 // IInspectable methods 2028 STDMETHOD(GetIids)( 2029 _Out_ ULONG *iidCount, 2030 _When_(*iidCount == 0, _At_(*iids, _Post_null_)) 2031 _When_(*iidCount > 0, _At_(*iids, _Post_notnull_)) 2032 _Result_nullonfailure_ IID **iids) 2033 { 2034 return Super::GetImplementedIIDS(this, iidCount, iids); 2035 } 2036 2037 #if !defined(__WRL_STRICT__) || !defined(__WRL_FORCE_INSPECTABLE_CLASS_MACRO__) 2038 STDMETHOD(GetRuntimeClassName)(_Out_ HSTRING* runtimeClassName) 2039 { 2040 *runtimeClassName = nullptr; 2041 2042 __WRL_ASSERT__(false && "Use InspectableClass macro to set runtime class name and trust level."); 2043 2044 #if (NTDDI_VERSION >= NTDDI_WINBLUE) 2045 ErrorHelper<RuntimeClassFlagsT::value & InhibitRoOriginateError>::OriginateError(E_NOTIMPL, nullptr); 2046 #endif // (NTDDI_VERSION >= NTDDI_WINBLUE) 2047 return E_NOTIMPL; 2048 } 2049 2050 STDMETHOD(GetTrustLevel)(_Out_ ::TrustLevel*) 2051 { 2052 __WRL_ASSERT__(false && "Use InspectableClass macro to set runtime class name and trust level."); 2053 #if (NTDDI_VERSION >= NTDDI_WINBLUE) 2054 ErrorHelper<RuntimeClassFlagsT::value & InhibitRoOriginateError>::OriginateError(E_NOTIMPL, nullptr); 2055 #endif // (NTDDI_VERSION >= NTDDI_WINBLUE) 2056 return E_NOTIMPL; 2057 } 2058 #endif // !defined(__WRL_STRICT__) || !defined(__WRL_FORCE_INSPECTABLE_CLASS_MACRO__) 2059 2060 STDMETHOD(GetWeakReference)(_Outptr_ IWeakReference **weakReference); 2061 2062 virtual ~RuntimeClassImpl() throw(); 2063 2064 protected: 2065 template <unsigned int RuntimeClassTypeT> friend class Details::RuntimeClassBaseT; 2066 using ImplementsHelper = typename Details::AdjustImplements<RuntimeClassFlagsT, false, typename IInspectableInjector<I0>::InspectableIfNeeded, I0, IWeakReferenceSource, TInterfaces...>::Type; 2067 using Super = RuntimeClassBaseT<RuntimeClassFlagsT::value>; 2068 2069 unsigned long InternalAddRef() throw(); 2070 2071 unsigned long InternalRelease() throw(); 2072 2073 unsigned long GetRefCount() const throw(); 2074 2075 friend class WeakReferenceImpl; 2076 2077 #ifdef __WRL_UNITTEST__ 2078 protected: 2079 #else 2080 private: 2081 #endif 2082 ReferenceCountOrWeakReferencePointer refCount_; 2083 }; 2084 2085 inline INT_PTR EncodeWeakReferencePointer(Microsoft::WRL::Details::WeakReferenceImpl* value) 2086 { 2087 return ((reinterpret_cast<INT_PTR>(value) >> 1) | EncodeWeakReferencePointerFlag); 2088 } 2089 2090 inline Microsoft::WRL::Details::WeakReferenceImpl* DecodeWeakReferencePointer(INT_PTR value) 2091 { 2092 return reinterpret_cast<Microsoft::WRL::Details::WeakReferenceImpl*>(value << 1); 2093 } 2094 2095 #pragma warning(pop) // C6388 2096 2097 template <class RuntimeClassFlagsT, typename I0, typename ...TInterfaces> 2098 class __declspec(novtable) RuntimeClassImpl<RuntimeClassFlagsT, false, true, true, I0, TInterfaces...> : 2099 public RuntimeClassImpl<RuntimeClassFlagsT, false, true, false, I0, TInterfaces...> 2100 { 2101 }; 2102 2103 template <class RuntimeClassFlagsT, typename I0, typename ...TInterfaces> 2104 class __declspec(novtable) RuntimeClassImpl<RuntimeClassFlagsT, true, true, true, I0, TInterfaces...> : 2105 public RuntimeClassImpl<RuntimeClassFlagsT, true, true, false, I0, FtmBase, TInterfaces...> 2106 { 2107 }; 2108 2109 // To minimize breaks with code written against WRL before variadic support was added, this form is maintained. 2110 template <typename ...TInterfaces> 2111 struct InterfaceListHelper 2112 { 2113 typedef InterfaceListHelper<TInterfaces...> TypeT; 2114 }; 2115 2116 template < 2117 typename ILst, 2118 class RuntimeClassFlagsT, 2119 bool implementsWeakReferenceSource = (RuntimeClassFlagsT::value & InhibitWeakReference) == 0, 2120 bool implementsInspectable = (RuntimeClassFlagsT::value & WinRt) == WinRt, 2121 bool implementsFtmBase = __WRL_IMPLEMENTS_FTM_BASE__(RuntimeClassFlagsT::value) 2122 > 2123 class RuntimeClass; 2124 2125 2126 template < 2127 typename RuntimeClassFlagsT, 2128 bool implementsWeakReferenceSource, 2129 bool implementsInspectable, 2130 bool implementsFtmBase, 2131 typename ...TInterfaces 2132 > 2133 class RuntimeClass<InterfaceListHelper<TInterfaces...>, RuntimeClassFlagsT, implementsWeakReferenceSource, implementsInspectable, implementsFtmBase> : 2134 public RuntimeClassImpl<RuntimeClassFlagsT, implementsWeakReferenceSource, implementsInspectable, implementsFtmBase, TInterfaces...> 2135 { 2136 protected: 2137 HRESULT CustomQueryInterface(REFIID /*riid*/, _Outptr_result_nullonfailure_ void** /*ppvObject*/, _Out_ bool *handled) 2138 { 2139 *handled = false; 2140 return S_OK; 2141 } 2142 }; 2143 2144 } // namespace Details 2145 2146 // The RuntimeClass IUnknown methods 2147 // It inherits from Details::RuntimeClass that provides helper methods for reference counting and 2148 // collecting IIDs 2149 template <typename ...TInterfaces> 2150 class RuntimeClass : 2151 public Details::RuntimeClassImpl<DETAILS_RTCLASS_FLAGS_ARGUMENTS(RuntimeClassFlags<WinRt>), TInterfaces...> 2152 { 2153 RuntimeClass(const RuntimeClass&); 2154 RuntimeClass& operator=(const RuntimeClass&); 2155 protected: 2156 HRESULT CustomQueryInterface(REFIID /*riid*/, _Outptr_result_nullonfailure_ void** /*ppvObject*/, _Out_ bool *handled) 2157 { 2158 *handled = false; 2159 return S_OK; 2160 } 2161 public: 2162 RuntimeClass() throw() 2163 { 2164 auto modulePtr = ::Microsoft::WRL::GetModuleBase(); 2165 if (modulePtr != nullptr) 2166 { 2167 modulePtr->IncrementObjectCount(); 2168 } 2169 } 2170 typedef RuntimeClass RuntimeClassT; 2171 }; 2172 2173 template <unsigned int classFlags, typename ...TInterfaces> 2174 class RuntimeClass<RuntimeClassFlags<classFlags>, TInterfaces...> : 2175 public Details::RuntimeClassImpl<DETAILS_RTCLASS_FLAGS_ARGUMENTS(RuntimeClassFlags<classFlags>), TInterfaces...> 2176 { 2177 RuntimeClass(const RuntimeClass&); 2178 RuntimeClass& operator=(const RuntimeClass&); 2179 protected: 2180 HRESULT CustomQueryInterface(REFIID /*riid*/, _Outptr_result_nullonfailure_ void** /*ppvObject*/, _Out_ bool *handled) 2181 { 2182 *handled = false; 2183 return S_OK; 2184 } 2185 public: 2186 RuntimeClass() throw() 2187 { 2188 auto modulePtr = ::Microsoft::WRL::GetModuleBase(); 2189 if (modulePtr != nullptr) 2190 { 2191 modulePtr->IncrementObjectCount(); 2192 } 2193 } 2194 typedef RuntimeClass RuntimeClassT; 2195 }; 2196 2197 namespace Details 2198 { 2199 //Weak reference implementation 2200 class WeakReferenceImpl sealed: 2201 public ::Microsoft::WRL::RuntimeClass<RuntimeClassFlags<ClassicCom>, IWeakReference>, 2202 public StrongReference 2203 { 2204 public: 2205 WeakReferenceImpl(_In_ IUnknown* unk) throw() : StrongReference(LONG_MAX / 2), unknown_(unk) 2206 { 2207 // Set ref count to 2 to avoid unnecessary interlocked increment operation while returning 2208 // WeakReferenceImpl from GetWeakReference method. One reference is hold by the object the second is hold 2209 // by the caller of GetWeakReference method. 2210 refcount_ = 2; 2211 } 2212 2213 virtual ~WeakReferenceImpl() throw() 2214 { 2215 } 2216 2217 STDMETHOD(Resolve)(REFIID riid, _Outptr_result_maybenull_ _Result_nullonfailure_ IInspectable **ppvObject) 2218 { 2219 *ppvObject = nullptr; 2220 2221 for(;;) 2222 { 2223 long ref = this->strongRefCount_; 2224 if (ref == 0) 2225 { 2226 return S_OK; 2227 } 2228 2229 // InterlockedCompareExchange calls _InterlockedCompareExchange intrinsic thus we call directly _InterlockedCompareExchange to save the call 2230 if (::_InterlockedCompareExchange(&this->strongRefCount_, ref + 1, ref) == ref) 2231 { 2232 #ifdef _PERF_COUNTERS 2233 // This artificially manipulates the strong ref count via AddRef to account for the resolve 2234 // interlocked operation above when tallying reference counting operations. 2235 unknown_->AddRef(); 2236 ::_InterlockedDecrement(&this->strongRefCount_); 2237 #endif 2238 break; 2239 } 2240 } 2241 2242 HRESULT hr = unknown_->QueryInterface(riid, reinterpret_cast<void**>(ppvObject)); 2243 unknown_->Release(); 2244 return hr; 2245 } 2246 2247 2248 private: 2249 IUnknown *unknown_; 2250 }; 2251 2252 template <class RuntimeClassFlagsT, typename I0, typename ...TInterfaces> 2253 RuntimeClassImpl<RuntimeClassFlagsT, true, true, false, I0, TInterfaces...>::~RuntimeClassImpl() throw() 2254 { 2255 if (IsValueAPointerToWeakReference(refCount_.rawValue)) 2256 { 2257 WeakReferenceImpl* weakRef = DecodeWeakReferencePointer(refCount_.rawValue); 2258 weakRef->Release(); 2259 weakRef = nullptr; 2260 } 2261 } 2262 2263 template <class RuntimeClassFlagsT, typename I0, typename ...TInterfaces> 2264 unsigned long RuntimeClassImpl<RuntimeClassFlagsT, true, true, false, I0, TInterfaces...>::GetRefCount() const throw() 2265 { 2266 ReferenceCountOrWeakReferencePointer currentValue = ReadValueFromPointerNoFence<ReferenceCountOrWeakReferencePointer>(&refCount_); 2267 2268 if (IsValueAPointerToWeakReference(currentValue.rawValue)) 2269 { 2270 WeakReferenceImpl* weakRef = DecodeWeakReferencePointer(currentValue.rawValue); 2271 return weakRef->GetStrongReferenceCount(); 2272 } 2273 else 2274 { 2275 return static_cast<unsigned long>(currentValue.refCount); 2276 } 2277 } 2278 2279 template <class RuntimeClassFlagsT, typename I0, typename ...TInterfaces> 2280 unsigned long RuntimeClassImpl<RuntimeClassFlagsT, true, true, false, I0, TInterfaces...>::InternalAddRef() throw() 2281 { 2282 #ifdef _PERF_COUNTERS 2283 IncrementAddRefCount(); 2284 #endif 2285 2286 ReferenceCountOrWeakReferencePointer currentValue = ReadValueFromPointerNoFence<ReferenceCountOrWeakReferencePointer>(&refCount_); 2287 2288 for (;;) 2289 { 2290 if (!IsValueAPointerToWeakReference(currentValue.rawValue)) 2291 { 2292 UINT_PTR updateValue = currentValue.refCount + 1; 2293 2294 #ifdef __WRL_UNITTEST__ 2295 OnBeforeInternalAddRefIncrement(); 2296 #endif 2297 2298 INT_PTR previousValue = reinterpret_cast<INT_PTR>(UnknownInterlockedCompareExchangePointerForIncrement(reinterpret_cast<PVOID*>(&(refCount_.refCount)), reinterpret_cast<PVOID>(updateValue), reinterpret_cast<PVOID>(currentValue.refCount))); 2299 if (previousValue == currentValue.rawValue) 2300 { 2301 return static_cast<unsigned long>(updateValue); 2302 } 2303 2304 currentValue.rawValue = previousValue; 2305 } 2306 else 2307 { 2308 WeakReferenceImpl* weakRef = DecodeWeakReferencePointer(currentValue.rawValue); 2309 return weakRef->IncrementStrongReference(); 2310 } 2311 } 2312 } 2313 2314 template <class RuntimeClassFlagsT, typename I0, typename ...TInterfaces> 2315 unsigned long RuntimeClassImpl<RuntimeClassFlagsT, true, true, false, I0, TInterfaces...>::InternalRelease() throw() 2316 { 2317 #ifdef _PERF_COUNTERS 2318 IncrementReleaseCount(); 2319 #endif 2320 2321 ReferenceCountOrWeakReferencePointer currentValue = ReadValueFromPointerNoFence<ReferenceCountOrWeakReferencePointer>(&refCount_); 2322 2323 for (;;) 2324 { 2325 if (!IsValueAPointerToWeakReference(currentValue.rawValue)) 2326 { 2327 UINT_PTR updateValue = currentValue.refCount - 1; 2328 2329 #ifdef __WRL_UNITTEST__ 2330 OnBeforeInternalReleaseDecrement(); 2331 #endif 2332 2333 INT_PTR previousValue = reinterpret_cast<INT_PTR>(UnknownInterlockedCompareExchangePointerForIncrement(reinterpret_cast<PVOID*>(&(refCount_.refCount)), reinterpret_cast<PVOID>(updateValue), reinterpret_cast<PVOID>(currentValue.refCount))); 2334 if (previousValue == currentValue.rawValue) 2335 { 2336 return static_cast<unsigned long>(updateValue); 2337 } 2338 2339 currentValue.rawValue = previousValue; 2340 } 2341 else 2342 { 2343 WeakReferenceImpl* weakRef = DecodeWeakReferencePointer(currentValue.rawValue); 2344 return weakRef->DecrementStrongReference(); 2345 } 2346 } 2347 } 2348 2349 template <class RuntimeClassFlagsT, typename I0, typename ...TInterfaces> 2350 COM_DECLSPEC_NOTHROW HRESULT RuntimeClassImpl<RuntimeClassFlagsT, true, true, false, I0, TInterfaces...>::GetWeakReference(_Outptr_ IWeakReference **weakReference) 2351 { 2352 WeakReferenceImpl* weakRef = nullptr; 2353 INT_PTR encodedWeakRef = 0; 2354 ReferenceCountOrWeakReferencePointer currentValue = ReadValueFromPointerNoFence<ReferenceCountOrWeakReferencePointer>(&refCount_); 2355 2356 *weakReference = nullptr; 2357 2358 if (IsValueAPointerToWeakReference(currentValue.rawValue)) 2359 { 2360 weakRef = DecodeWeakReferencePointer(currentValue.rawValue); 2361 2362 weakRef->AddRef(); 2363 *weakReference = weakRef; 2364 return S_OK; 2365 } 2366 2367 // WeakReferenceImpl is created with ref count 2 to avoid interlocked increment 2368 weakRef = CreateWeakReference(ImplementsHelper::CastToUnknown()); 2369 if (weakRef == nullptr) 2370 { 2371 return E_OUTOFMEMORY; 2372 } 2373 2374 encodedWeakRef = EncodeWeakReferencePointer(weakRef); 2375 2376 for (;;) 2377 { 2378 INT_PTR previousValue = 0; 2379 2380 weakRef->SetStrongReference(static_cast<unsigned long>(currentValue.refCount)); 2381 2382 #ifdef __WRL_UNITTEST__ 2383 OnBeforeGetWeakReferenceSwap(); 2384 #endif 2385 2386 previousValue = reinterpret_cast<INT_PTR>(UnknownInterlockedCompareExchangePointer(reinterpret_cast<PVOID*>(&(this->refCount_.ifHighBitIsSetThenShiftLeftToYieldPointerToWeakReference)), reinterpret_cast<PVOID>(encodedWeakRef), currentValue.ifHighBitIsSetThenShiftLeftToYieldPointerToWeakReference)); 2387 if (previousValue == currentValue.rawValue) 2388 { 2389 // No need to call AddRef in this case, WeakReferenceImpl is created with ref count 2 to avoid interlocked increment 2390 *weakReference = weakRef; 2391 return S_OK; 2392 } 2393 else if (IsValueAPointerToWeakReference(previousValue)) 2394 { 2395 // Another thread beat this call to create the weak reference. 2396 2397 delete weakRef; 2398 2399 weakRef = DecodeWeakReferencePointer(previousValue); 2400 weakRef->AddRef(); 2401 *weakReference = weakRef; 2402 return S_OK; 2403 } 2404 2405 // Another thread won via an AddRef or Release. 2406 // Let's try again 2407 currentValue.rawValue = previousValue; 2408 } 2409 } 2410 2411 // Memory allocation for object that doesn't support weak references 2412 // It only allocates memory 2413 template<typename T> 2414 class MakeAllocator 2415 { 2416 public: 2417 MakeAllocator() throw() : buffer_(nullptr) 2418 { 2419 } 2420 2421 ~MakeAllocator() throw() 2422 { 2423 if (buffer_ != nullptr) 2424 { 2425 delete buffer_; 2426 } 2427 } 2428 2429 void* Allocate() throw() 2430 { 2431 __WRL_ASSERT__(buffer_ == nullptr); 2432 // Allocate memory with operator new(size, nothrow) only 2433 // This will allow developer to override one operator only 2434 // to enable different memory allocation model 2435 buffer_ = (char*) (operator new (sizeof(T), std::nothrow)); 2436 return buffer_; 2437 } 2438 2439 void Detach() throw() 2440 { 2441 buffer_ = nullptr; 2442 } 2443 private: 2444 char* buffer_; 2445 }; 2446 2447 } //Details 2448 2449 #pragma region make overloads 2450 2451 namespace Details { 2452 2453 // Make and MakeAndInitialize functions must not be marked as throw() as the constructor is allowed to throw exceptions. 2454 template <typename T, typename ...TArgs> 2455 ComPtr<T> Make(TArgs&&... args) 2456 { 2457 static_assert(__is_base_of(Details::RuntimeClassBase, T), "Make can only instantiate types that derive from RuntimeClass"); 2458 ComPtr<T> object; 2459 Details::MakeAllocator<T> allocator; 2460 void *buffer = allocator.Allocate(); 2461 if (buffer != nullptr) 2462 { 2463 auto ptr = new (buffer)T(Details::Forward<TArgs>(args)...); 2464 object.Attach(ptr); 2465 allocator.Detach(); 2466 } 2467 return object; 2468 } 2469 2470 #pragma warning(push) 2471 #pragma warning(disable:6387 6388 28196) // PREFast does not understand call to ComPtr<T>::CopyTo() is safe here 2472 2473 template <typename T, typename I, typename ...TArgs> 2474 HRESULT MakeAndInitialize(_Outptr_result_nullonfailure_ I** result, TArgs&&... args) 2475 { 2476 static_assert(__is_base_of(Details::RuntimeClassBase, T), "Make can only instantiate types that derive from RuntimeClass"); 2477 static_assert(__is_base_of(I, T), "The 'T' runtime class doesn't implement 'I' interface"); 2478 *result = nullptr; 2479 Details::MakeAllocator<T> allocator; 2480 void *buffer = allocator.Allocate(); 2481 if (buffer == nullptr) { return E_OUTOFMEMORY; } 2482 auto ptr = new (buffer)T; 2483 ComPtr<T> object; 2484 object.Attach(ptr); 2485 allocator.Detach(); 2486 HRESULT hr = object->RuntimeClassInitialize(Details::Forward<TArgs>(args)...); 2487 if (FAILED(hr)) { return hr; } 2488 return object.CopyTo(result); 2489 } 2490 2491 #pragma warning(pop) // C6387 C6388 C28196 2492 2493 template <typename T, typename I, typename ...TArgs> 2494 HRESULT MakeAndInitialize(_Inout_ ComPtrRef<ComPtr<I>> ppvObject, TArgs&&... args) 2495 { 2496 return MakeAndInitialize<T>(ppvObject.ReleaseAndGetAddressOf(), Details::Forward<TArgs>(args)...); 2497 } 2498 2499 } //end of Details 2500 2501 using Details::MakeAndInitialize; 2502 using Details::Make; 2503 2504 #pragma endregion // make overloads 2505 2506 namespace Details 2507 { 2508 inline WeakReferenceImpl* CreateWeakReference(_In_ IUnknown* unk) 2509 { 2510 return Make<WeakReferenceImpl>(unk).Detach(); 2511 } 2512 } 2513 2514 #define InspectableClass(runtimeClassName, trustLevel) \ 2515 public: \ 2516 static _Null_terminated_ const wchar_t* STDMETHODCALLTYPE InternalGetRuntimeClassName() throw() \ 2517 { \ 2518 static_assert((RuntimeClassT::ClassFlags::value & ::Microsoft::WRL::WinRtClassicComMix) == ::Microsoft::WRL::WinRt || \ 2519 (RuntimeClassT::ClassFlags::value & ::Microsoft::WRL::WinRtClassicComMix) == ::Microsoft::WRL::WinRtClassicComMix, \ 2520 "'InspectableClass' macro must not be used with ClassicCom clasess."); \ 2521 static_assert(__is_base_of(::Microsoft::WRL::Details::RuntimeClassBase, RuntimeClassT), "'InspectableClass' macro can only be used with ::Windows::WRL::RuntimeClass types"); \ 2522 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"); \ 2523 return runtimeClassName; \ 2524 } \ 2525 static ::TrustLevel STDMETHODCALLTYPE InternalGetTrustLevel() throw() \ 2526 { \ 2527 return trustLevel; \ 2528 } \ 2529 STDMETHOD(GetRuntimeClassName)(_Out_ HSTRING* runtimeName) \ 2530 { \ 2531 *runtimeName = nullptr; \ 2532 HRESULT hr = S_OK; \ 2533 auto name = InternalGetRuntimeClassName(); \ 2534 if (name != nullptr) \ 2535 { \ 2536 hr = ::WindowsCreateString(name, static_cast<UINT32>(::wcslen(name)), runtimeName); \ 2537 } \ 2538 return hr; \ 2539 } \ 2540 STDMETHOD(GetTrustLevel)(_Out_ ::TrustLevel* trustLvl) \ 2541 { \ 2542 *trustLvl = trustLevel; \ 2543 return S_OK; \ 2544 } \ 2545 STDMETHOD(GetIids)(_Out_ ULONG *iidCount, \ 2546 _When_(*iidCount == 0, _At_(*iids, _Post_null_)) \ 2547 _When_(*iidCount > 0, _At_(*iids, _Post_notnull_)) \ 2548 _Result_nullonfailure_ IID **iids) \ 2549 { \ 2550 return RuntimeClassT::GetIids(iidCount, iids); \ 2551 } \ 2552 STDMETHOD(QueryInterface)(REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject) \ 2553 { \ 2554 bool handled = false; \ 2555 HRESULT hr = this->CustomQueryInterface(riid, ppvObject, &handled); \ 2556 if (FAILED(hr) || handled) return hr; \ 2557 return RuntimeClassT::QueryInterface(riid, ppvObject); \ 2558 } \ 2559 STDMETHOD_(ULONG, Release)() \ 2560 { \ 2561 return RuntimeClassT::Release(); \ 2562 } \ 2563 STDMETHOD_(ULONG, AddRef)() \ 2564 { \ 2565 return RuntimeClassT::AddRef(); \ 2566 } \ 2567 private: 2568 2569 #define MixInHelper() \ 2570 public: \ 2571 STDMETHOD(QueryInterface)(REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject) \ 2572 { \ 2573 static_assert((RuntimeClassT::ClassFlags::value & ::Microsoft::WRL::WinRt) == 0, "'MixInClass' macro must not be used with WinRt clasess."); \ 2574 static_assert(__is_base_of(::Microsoft::WRL::Details::RuntimeClassBase, RuntimeClassT), "'MixInHelper' macro can only be used with ::Windows::WRL::RuntimeClass types"); \ 2575 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"); \ 2576 return RuntimeClassT::QueryInterface(riid, ppvObject); \ 2577 } \ 2578 STDMETHOD_(ULONG, Release)() \ 2579 { \ 2580 return RuntimeClassT::Release(); \ 2581 } \ 2582 STDMETHOD_(ULONG, AddRef)() \ 2583 { \ 2584 return RuntimeClassT::AddRef(); \ 2585 } \ 2586 private: 2587 2588 // Please make sure that those macros are in sync with those ones from 'wrl/module.h' 2589 #ifndef WrlCreatorMapIncludePragmaEx 2590 #define WrlCreatorMapIncludePragmaEx(className, group) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'WrlCreatorMapIncludePragmaEx' macro"); 2591 #endif 2592 2593 #ifndef WrlCreatorMapIncludePragma 2594 #define WrlCreatorMapIncludePragma(className) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'WrlCreatorMapIncludePragma' macro"); 2595 #endif 2596 2597 #ifndef ActivatableClassWithFactoryEx 2598 #define ActivatableClassWithFactoryEx(className, factory, groupId) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'ActivatableClassWithFactoryEx' macro"); 2599 #endif 2600 2601 #ifndef ActivatableClassWithFactory 2602 #define ActivatableClassWithFactory(className, factory) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'ActivatableClassWithFactory' macro"); 2603 #endif 2604 2605 #ifndef ActivatableClass 2606 #define ActivatableClass(className) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'ActivatableClass' macro"); 2607 #endif 2608 2609 #ifndef ActivatableStaticOnlyFactoryEx 2610 #define ActivatableStaticOnlyFactoryEx(factory, serverName) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'ActivatableStaticOnlyFactoryEx' macro"); 2611 #endif 2612 2613 #ifndef ActivatableStaticOnlyFactory 2614 #define ActivatableStaticOnlyFactory(factory) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'ActivatableStaticOnlyFactory' macro"); 2615 #endif 2616 2617 #ifndef CoCreatableClassWithFactoryEx 2618 #define CoCreatableClassWithFactoryEx(className, factory, groupId) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'CoCreatableClassWithFactory' macro"); 2619 #endif 2620 2621 #ifndef CoCreatableClassWithFactory 2622 #define CoCreatableClassWithFactory(className, factory) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'CoCreatableClassWithFactory' macro"); 2623 #endif 2624 2625 #ifndef CoCreatableClass 2626 #define CoCreatableClass(className) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'CoCreatableClass' macro"); 2627 #endif 2628 2629 #ifndef CoCreatableClassWrlCreatorMapInclude 2630 #define CoCreatableClassWrlCreatorMapInclude(className) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'CoCreatableClassWrlCreatorMapInclude' macro"); 2631 #endif 2632 2633 #ifndef CoCreatableClassWrlCreatorMapIncludeEx 2634 #define CoCreatableClassWrlCreatorMapIncludeEx(className, groupId) static_assert(false, "It's required to include 'wrl/module.h' to be able to use 'CoCreatableClassWrlCreatorMapInclude' macro"); 2635 #endif 2636 2637 #undef UnknownIncrementReference 2638 #undef UnknownDecrementReference 2639 #undef UnknownBarrierAfterInterlock 2640 #undef UnknownInterlockedCompareExchangePointer 2641 #undef UnknownInterlockedCompareExchangePointerForIncrement 2642 #undef UnknownInterlockedCompareExchangePointerForRelease 2643 2644 }} // namespace Microsoft::WRL 2645 2646 #pragma warning(pop) 2647 2648 // Restore packing 2649 #include <poppack.h> 2650 2651 #ifdef __clang__ 2652 #pragma clang diagnostic pop 2653 #endif 2654 2655 #endif // _WRL_IMPLEMENTS_H_ 2656