aboutsummaryrefslogtreecommitdiff
path: root/contrib/DirectX-Headers/include/wsl/wrladapter.h
blob: 883ecab3be06f73dc72043eb0e5b550bebe745e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#pragma once

#include "winadapter.h"

// defined by winadapter.h and needed by some windows headers, but conflicts
// with some libc++ implementation headers
#ifdef __in
#undef __in
#endif
#ifdef __out
#undef __out
#endif

#include <type_traits>
#include <atomic>
#include <memory>
#include <climits>
#include <cassert>

namespace Microsoft
{
namespace WRL
{
    namespace Details
    {
        struct BoolStruct { int Member; };
        typedef int BoolStruct::* BoolType;

        template <typename T> // T should be the ComPtr<T> or a derived type of it, not just the interface
        class ComPtrRefBase
        {
        public:
            typedef typename T::InterfaceType InterfaceType;

            operator IUnknown**() const throw()
            {
                static_assert(__is_base_of(IUnknown, InterfaceType), "Invalid cast: InterfaceType does not derive from IUnknown");
                return reinterpret_cast<IUnknown**>(ptr_->ReleaseAndGetAddressOf());
            }

        protected:
            T* ptr_;
        };

        template <typename T>
        class ComPtrRef : public Details::ComPtrRefBase<T> // T should be the ComPtr<T> or a derived type of it, not just the interface
        {
            using Super = Details::ComPtrRefBase<T>;
            using InterfaceType = typename Super::InterfaceType;
        public:
            ComPtrRef(_In_opt_ T* ptr) throw()
            {
                this->ptr_ = ptr;
            }

            // Conversion operators
            operator void**() const throw()
            {
                return reinterpret_cast<void**>(this->ptr_->ReleaseAndGetAddressOf());
            }

            // This is our operator ComPtr<U> (or the latest derived class from ComPtr (e.g. WeakRef))
            operator T*() throw()
            {
                *this->ptr_ = nullptr;
                return this->ptr_;
            }

            // We define operator InterfaceType**() here instead of on ComPtrRefBase<T>, since
            // if InterfaceType is IUnknown or IInspectable, having it on the base will collide.
            operator InterfaceType**() throw()
            {
                return this->ptr_->ReleaseAndGetAddressOf();
            }

            // This is used for IID_PPV_ARGS in order to do __uuidof(**(ppType)).
            // It does not need to clear  ptr_ at this point, it is done at IID_PPV_ARGS_Helper(ComPtrRef&) later in this file.
            InterfaceType* operator *() throw()
            {
                return this->ptr_->Get();
            }

            // Explicit functions
            InterfaceType* const * GetAddressOf() const throw()
            {
                return this->ptr_->GetAddressOf();
            }

            InterfaceType** ReleaseAndGetAddressOf() throw()
            {
                return this->ptr_->ReleaseAndGetAddressOf();
            }
        };
    }

    template <typename T>
    class ComPtr
    {
    public:
        typedef T InterfaceType;

    protected:
        InterfaceType *ptr_;
        template<class U> friend class ComPtr;

        void InternalAddRef() const throw()
        {
            if (ptr_ != nullptr)
            {
                ptr_->AddRef();
            }
        }

        unsigned long InternalRelease() throw()
        {
            unsigned long ref = 0;
            T* temp = ptr_;

            if (temp != nullptr)
            {
                ptr_ = nullptr;
                ref = temp->Release();
            }

            return ref;
        }

    public:
        ComPtr() throw() : ptr_(nullptr)
        {
        }

        ComPtr(decltype(nullptr)) throw() : ptr_(nullptr)
        {
        }

        template<class U>
        ComPtr(_In_opt_ U *other) throw() : ptr_(other)
        {
            InternalAddRef();
        }

        ComPtr(const ComPtr& other) throw() : ptr_(other.ptr_)
        {
            InternalAddRef();
        }

        // copy constructor that allows to instantiate class when U* is convertible to T*
        template<class U>
        ComPtr(const ComPtr<U> &other, typename std::enable_if<std::is_convertible<U*, T*>::value, void *>::type * = 0) throw() :
            ptr_(other.ptr_)
        {
            InternalAddRef();
        }

        ComPtr(_Inout_ ComPtr &&other) throw() : ptr_(nullptr)
        {
            if (this != reinterpret_cast<ComPtr*>(&reinterpret_cast<unsigned char&>(other)))
            {
                Swap(other);
            }
        }

        // Move constructor that allows instantiation of a class when U* is convertible to T*
        template<class U>
        ComPtr(_Inout_ ComPtr<U>&& other, typename std::enable_if<std::is_convertible<U*, T*>::value, void *>::type * = 0) throw() :
            ptr_(other.ptr_)
        {
            other.ptr_ = nullptr;
        }

        ~ComPtr() throw()
        {
            InternalRelease();
        }

        ComPtr& operator=(decltype(nullptr)) throw()
        {
            InternalRelease();
            return *this;
        }

        ComPtr& operator=(_In_opt_ T *other) throw()
        {
            if (ptr_ != other)
            {
                ComPtr(other).Swap(*this);
            }
            return *this;
        }

        template <typename U>
        ComPtr& operator=(_In_opt_ U *other) throw()
        {
            ComPtr(other).Swap(*this);
            return *this;
        }

        ComPtr& operator=(const ComPtr &other) throw()
        {
            if (ptr_ != other.ptr_)
            {
                ComPtr(other).Swap(*this);
            }
            return *this;
        }

        template<class U>
        ComPtr& operator=(const ComPtr<U>& other) throw()
        {
            ComPtr(other).Swap(*this);
            return *this;
        }

        ComPtr& operator=(_Inout_ ComPtr &&other) throw()
        {
            ComPtr(static_cast<ComPtr&&>(other)).Swap(*this);
            return *this;
        }

        template<class U>
        ComPtr& operator=(_Inout_ ComPtr<U>&& other) throw()
        {
            ComPtr(static_cast<ComPtr<U>&&>(other)).Swap(*this);
            return *this;
        }

        void Swap(_Inout_ ComPtr&& r) throw()
        {
            T* tmp = ptr_;
            ptr_ = r.ptr_;
            r.ptr_ = tmp;
        }

        void Swap(_Inout_ ComPtr& r) throw()
        {
            T* tmp = ptr_;
            ptr_ = r.ptr_;
            r.ptr_ = tmp;
        }

        operator Details::BoolType() const throw()
        {
            return Get() != nullptr ? &Details::BoolStruct::Member : nullptr;
        }

        T* Get() const throw()
        {
            return ptr_;
        }

        InterfaceType* operator->() const throw()
        {
            return ptr_;
        }

        Details::ComPtrRef<ComPtr<T>> operator&() throw()
        {
            return Details::ComPtrRef<ComPtr<T>>(this);
        }

        const Details::ComPtrRef<const ComPtr<T>> operator&() const throw()
        {
            return Details::ComPtrRef<const ComPtr<T>>(this);
        }

        T* const* GetAddressOf() const throw()
        {
            return &ptr_;
        }

        T** GetAddressOf() throw()
        {
            return &ptr_;
        }

        T** ReleaseAndGetAddressOf() throw()
        {
            InternalRelease();
            return &ptr_;
        }

        T* Detach() throw()
        {
            T* ptr = ptr_;
            ptr_ = nullptr;
            return ptr;
        }

        void Attach(_In_opt_ InterfaceType* other) throw()
        {
            if (ptr_ != nullptr)
            {
                auto ref = ptr_->Release();
                // DBG_UNREFERENCED_LOCAL_VARIABLE(ref);
                // Attaching to the same object only works if duplicate references are being coalesced. Otherwise
                // re-attaching will cause the pointer to be released and may cause a crash on a subsequent dereference.
                assert(ref != 0 || ptr_ != other);
            }

            ptr_ = other;
        }

        unsigned long Reset()
        {
            return InternalRelease();
        }

        // Previously, unsafe behavior could be triggered when 'this' is ComPtr<IInspectable> or ComPtr<IUnknown> and CopyTo is used to copy to another type U. 
        // The user will use operator& to convert the destination into a ComPtrRef, which can then implicit cast to IInspectable** and IUnknown**. 
        // If this overload of CopyTo is not present, it will implicitly cast to IInspectable or IUnknown and match CopyTo(InterfaceType**) instead.
        // A valid polymoprhic downcast requires run-time type checking via QueryInterface, so CopyTo(InterfaceType**) will break type safety.
        // This overload matches ComPtrRef before the implicit cast takes place, preventing the unsafe downcast.
        template <typename U>
        HRESULT CopyTo(Details::ComPtrRef<ComPtr<U>> ptr, typename std::enable_if<
            (std::is_same<T, IUnknown>::value)
            && !std::is_same<U*, T*>::value, void *>::type * = 0) const throw()
        {
            return ptr_->QueryInterface(uuidof<U>(), ptr);
        }

        HRESULT CopyTo(_Outptr_result_maybenull_ InterfaceType** ptr) const throw()
        {
            InternalAddRef();
            *ptr = ptr_;
            return S_OK;
        }

        HRESULT CopyTo(REFIID riid, _Outptr_result_nullonfailure_ void** ptr) const throw()
        {
            return ptr_->QueryInterface(riid, ptr);
        }

        template<typename U>
        HRESULT CopyTo(_Outptr_result_nullonfailure_ U** ptr) const throw()
        {
            return ptr_->QueryInterface(uuidof<U>(), reinterpret_cast<void**>(ptr));
        }

        // query for U interface
        template<typename U>
        HRESULT As(_Inout_ Details::ComPtrRef<ComPtr<U>> p) const throw()
        {
            return ptr_->QueryInterface(uuidof<U>(), p);
        }

        // query for U interface
        template<typename U>
        HRESULT As(_Out_ ComPtr<U>* p) const throw()
        {
            return ptr_->QueryInterface(uuidof<U>(), reinterpret_cast<void**>(p->ReleaseAndGetAddressOf()));
        }

        // query for riid interface and return as IUnknown
        HRESULT AsIID(REFIID riid, _Out_ ComPtr<IUnknown>* p) const throw()
        {
            return ptr_->QueryInterface(riid, reinterpret_cast<void**>(p->ReleaseAndGetAddressOf()));
        }

    };    // ComPtr


    namespace Details
    {
        // Empty struct used as default template parameter
        class Nil
        {
        };

        // Empty struct used for validating template parameter types in Implements
        struct ImplementsBase
        {
        };

        class RuntimeClassBase
        {
        protected:
            template<typename T>
            static HRESULT AsIID(_In_ T* implements, REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject) noexcept
            {
                *ppvObject = nullptr;
                bool isRefDelegated = false;
                // Prefer InlineIsEqualGUID over other forms since it's better perf on 4-byte aligned data, which is almost always the case.
                if (InlineIsEqualGUID(riid, uuidof<IUnknown>()))
                {
                    *ppvObject = implements->CastToUnknown();
                    static_cast<IUnknown*>(*ppvObject)->AddRef();
                    return S_OK;
                }

                HRESULT hr = implements->CanCastTo(riid, ppvObject, &isRefDelegated);
                if (SUCCEEDED(hr) && !isRefDelegated)
                {
                    static_cast<IUnknown*>(*ppvObject)->AddRef();
                }

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 6102) // '*ppvObject' is used but may not be initialized
#endif
                _Analysis_assume_(SUCCEEDED(hr) || (*ppvObject == nullptr));
#ifdef _MSC_VER
#pragma warning(pop)
#endif
                return hr;
            }

        public:
            HRESULT RuntimeClassInitialize() noexcept
            {
                return S_OK;
            }
        };

        // Interface traits provides casting and filling iids methods helpers
        template<typename I0>
        struct InterfaceTraits
        {
            typedef I0 Base;

            template<typename T>
            static Base* CastToBase(_In_ T* ptr) noexcept
            {
                return static_cast<Base*>(ptr);
            }

            template<typename T>
            static IUnknown* CastToUnknown(_In_ T* ptr) noexcept
            {
                return static_cast<IUnknown*>(static_cast<Base*>(ptr));
            }

            template <typename T>
            _Success_(return == true)
                static bool CanCastTo(_In_ T* ptr, REFIID riid, _Outptr_ void **ppv) noexcept
            {
                // Prefer InlineIsEqualGUID over other forms since it's better perf on 4-byte aligned data, which is almost always the case.
                if (InlineIsEqualGUID(riid, uuidof<Base>()))
                {
                    *ppv = static_cast<Base*>(ptr);
                    return true;
                }

                return false;
            }
        };

        // Specialization for Nil parameter
        template<>
        struct InterfaceTraits<Nil>
        {
            typedef Nil Base;

            template <typename T>
            _Success_(return == true)
                static bool CanCastTo(_In_ T*, REFIID, _Outptr_ void **) noexcept
            {
                return false;
            }
        };

        // ChainInterfaces - template allows specifying a derived COM interface along with its class hierarchy to allow QI for the base interfaces
        template <typename I0, typename I1, typename I2 = Nil, typename I3 = Nil,
            typename I4 = Nil, typename I5 = Nil, typename I6 = Nil,
            typename I7 = Nil, typename I8 = Nil, typename I9 = Nil>
            struct ChainInterfaces : I0
        {
        protected:
            HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv) throw()
            {
                typename InterfaceTraits<I0>::Base* ptr = InterfaceTraits<I0>::CastToBase(this);

                return (InterfaceTraits<I0>::CanCastTo(this, riid, ppv) ||
                    InterfaceTraits<I1>::CanCastTo(ptr, riid, ppv) ||
                    InterfaceTraits<I2>::CanCastTo(ptr, riid, ppv) ||
                    InterfaceTraits<I3>::CanCastTo(ptr, riid, ppv) ||
                    InterfaceTraits<I4>::CanCastTo(ptr, riid, ppv) ||
                    InterfaceTraits<I5>::CanCastTo(ptr, riid, ppv) ||
                    InterfaceTraits<I6>::CanCastTo(ptr, riid, ppv) ||
                    InterfaceTraits<I7>::CanCastTo(ptr, riid, ppv) ||
                    InterfaceTraits<I8>::CanCastTo(ptr, riid, ppv) ||
                    InterfaceTraits<I9>::CanCastTo(ptr, riid, ppv)) ? S_OK : E_NOINTERFACE;
            }

            IUnknown* CastToUnknown() throw()
            {
                return InterfaceTraits<I0>::CastToUnknown(this);
            }
        };

        // Helper template used by Implements. This template traverses a list of interfaces and adds them as base class and information
        // to enable QI.
        template <typename ...TInterfaces>
        struct ImplementsHelper;

        template <typename T>
        struct ImplementsMarker
        {};

        template <typename I0, bool isImplements>
        struct MarkImplements;

        template <typename I0>
        struct MarkImplements<I0, false>
        {
            typedef I0 Type;
        };

        template <typename I0>
        struct MarkImplements<I0, true>
        {
            typedef ImplementsMarker<I0> Type;
        };

        // AdjustImplements pre-processes the type list for more efficient builds.
        template <typename ...Bases>
        struct AdjustImplements;

        template <typename I0, typename ...Bases>
        struct AdjustImplements<I0, Bases...>
        {
            typedef ImplementsHelper<typename MarkImplements<I0, std::is_base_of<ImplementsBase, I0>::value>::Type, Bases...> Type;
        };

        // Use AdjustImplements to remove instances of "Nil" from the type list.
        template <typename ...Bases>
        struct AdjustImplements<Nil, Bases...>
        {
            typedef typename AdjustImplements<Bases...>::Type Type;
        };

        template <>
        struct AdjustImplements<>
        {
            typedef ImplementsHelper<> Type;
        };

        // Specialization handles unadorned interfaces
        template <typename I0, typename ...TInterfaces>
        struct ImplementsHelper<I0, TInterfaces...> :
            I0,
            AdjustImplements<TInterfaces...>::Type
        {
            template <typename ...> friend struct ImplementsHelper;
            friend class RuntimeClassBase;

        protected:

            HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) noexcept
            {
                // Prefer InlineIsEqualGUID over other forms since it's better perf on 4-byte aligned data, which is almost always the case.
                if (InlineIsEqualGUID(riid, uuidof<I0>()))
                {
                    *ppv = reinterpret_cast<I0*>(reinterpret_cast<void*>(this));
                    return S_OK;
                }
                return AdjustImplements<TInterfaces...>::Type::CanCastTo(riid, ppv, pRefDelegated);
            }

            IUnknown* CastToUnknown() noexcept
            {
                return reinterpret_cast<I0*>(reinterpret_cast<void*>(this));
            }
        };


        // Selector is used to "tag" base interfaces to be used in casting, since a runtime class may indirectly derive from 
        // the same interface or Implements<> template multiple times
        template <typename base, typename disciminator>
        struct  Selector : public base
        {
        };

        // Specialization handles types that derive from ImplementsHelper (e.g. nested Implements).
        template <typename I0, typename ...TInterfaces>
        struct ImplementsHelper<ImplementsMarker<I0>, TInterfaces...> :
            Selector<I0, ImplementsHelper<ImplementsMarker<I0>, TInterfaces...>>,
            Selector<typename AdjustImplements<TInterfaces...>::Type, ImplementsHelper<ImplementsMarker<I0>, TInterfaces...>>
        {
            template <typename ...> friend struct ImplementsHelper;
            friend class RuntimeClassBase;

        protected:
            typedef Selector<I0, ImplementsHelper<ImplementsMarker<I0>, TInterfaces...>> CurrentType;
            typedef Selector<typename AdjustImplements<TInterfaces...>::Type, ImplementsHelper<ImplementsMarker<I0>, TInterfaces...>> BaseType;

            HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) noexcept
            {
                HRESULT hr = CurrentType::CanCastTo(riid, ppv);
                if (hr == E_NOINTERFACE)
                {
                    hr = BaseType::CanCastTo(riid, ppv, pRefDelegated);
                }
                return hr;
            }

            IUnknown* CastToUnknown() noexcept
            {
                // First in list wins.
                return CurrentType::CastToUnknown();
            }
        };

        // terminal case specialization.
        template <>
        struct ImplementsHelper<>
        {
            template <typename ...> friend struct ImplementsHelper;
            friend class RuntimeClassBase;

        protected:
            HRESULT CanCastTo(_In_ REFIID /*riid*/, _Outptr_ void ** /*ppv*/, bool * /*pRefDelegated*/ = nullptr) noexcept
            {
                return E_NOINTERFACE;
            }

            // IUnknown* CastToUnknown() noexcept; // not defined for terminal case.
        };

        // Specialization handles chaining interfaces
        template <typename C0, typename C1, typename C2, typename C3, typename C4, typename C5, typename C6, typename C7, typename C8, typename C9, typename ...TInterfaces>
        struct ImplementsHelper<ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>, TInterfaces...> :
            ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>,
            AdjustImplements<TInterfaces...>::Type
        {
            template <typename ...> friend struct ImplementsHelper;
            friend class RuntimeClassBase;

        protected:
            typedef typename AdjustImplements<TInterfaces...>::Type BaseType;

            HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) noexcept
            {
                HRESULT hr = ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>::CanCastTo(riid, ppv);
                if (FAILED(hr))
                {
                    hr = BaseType::CanCastTo(riid, ppv, pRefDelegated);
                }

                return hr;
            }

            IUnknown* CastToUnknown() noexcept
            {
                return ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>::CastToUnknown();
            }
        };

        // Implements - template implementing QI using the information provided through its template parameters
        // Each template parameter has to be one of the following:
        // * COM Interface
        // * A class that implements one or more COM interfaces
        // * ChainInterfaces template
        template <typename I0, typename ...TInterfaces>
        struct Implements :
            AdjustImplements<I0, TInterfaces...>::Type,
            ImplementsBase
        {
        public:
            typedef I0 FirstInterface;
        protected:
            typedef typename AdjustImplements<I0, TInterfaces...>::Type BaseType;
            template <typename ...> friend struct ImplementsHelper;
            friend class RuntimeClassBase;

            HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv) noexcept
            {
                return BaseType::CanCastTo(riid, ppv);
            }

            IUnknown* CastToUnknown() noexcept
            {
                return BaseType::CastToUnknown();
            }
        };

        // Used on RuntimeClass to protect it from being constructed with new
        class DontUseNewUseMake
        {
        private:
            void* operator new(size_t) noexcept
            {
                assert(false);
                return 0;
            }

        public:
            void* operator new(size_t, _In_ void* placement) noexcept
            {
                return placement;
            }
        };

        template <typename ...TInterfaces>
        class RuntimeClassImpl :
            public AdjustImplements<TInterfaces...>::Type,
            public RuntimeClassBase,
            public DontUseNewUseMake
        {
        public:
            STDMETHOD(QueryInterface)(REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject)
            {
                return Super::AsIID(this, riid, ppvObject);
            }

            STDMETHOD_(ULONG, AddRef)()
            {
                return InternalAddRef();
            }

            STDMETHOD_(ULONG, Release)()
            {
                ULONG ref = InternalRelease();
                if (ref == 0)
                {
                    delete this;
                }

                return ref;
            }

        protected:
            using Super = RuntimeClassBase;
            static const LONG c_lProtectDestruction = -(LONG_MAX / 2);

            RuntimeClassImpl() noexcept = default;

            virtual ~RuntimeClassImpl() noexcept
            {
                // Set refcount_ to -(LONG_MAX/2) to protect destruction and
                // also catch mismatched Release in debug builds
                refcount_ = static_cast<ULONG>(c_lProtectDestruction);
            }

            ULONG InternalAddRef() noexcept
            {
                return ++refcount_;
            }

            ULONG InternalRelease() noexcept
            {
                return --refcount_;
            }

            unsigned long GetRefCount() const noexcept
            {
                return refcount_;
            }

            std::atomic<ULONG> refcount_{1};
        };
    }

    template <typename ...TInterfaces>
    class Base : public Details::RuntimeClassImpl<TInterfaces...>
    {
        Base(const Base&) = delete;
        Base& operator=(const Base&) = delete;

    protected:
        HRESULT CustomQueryInterface(REFIID /*riid*/, _Outptr_result_nullonfailure_ void** /*ppvObject*/, _Out_ bool *handled)
        {
            *handled = false;
            return S_OK;
        }

    public:
        Base() throw() = default;
        typedef Base RuntimeClassT;
    };

    // Creates a Nano-COM object wrapped in a smart pointer.
    template <typename T, typename ...TArgs>
    ComPtr<T> Make(TArgs&&... args)
    {
        ComPtr<T> object;

        std::unique_ptr<unsigned char[]> buffer(new unsigned char[sizeof(T)]);
        if (buffer)
        {
            T* ptr = new (buffer.get())T(std::forward<TArgs>(args)...);
            object.Attach(ptr);
            buffer.release();
        }

        return object;
    }

    using Details::ChainInterfaces;
}
}

// Overloaded global function to provide to IID_PPV_ARGS that support Details::ComPtrRef
template<typename T>
void** IID_PPV_ARGS_Helper(Microsoft::WRL::Details::ComPtrRef<T> pp) throw()
{
    return pp;
}