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