IUnknownImpl.h (6784B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. * 6 */ 7 8 #ifndef mozilla_a11y_IUnknownImpl_h_ 9 #define mozilla_a11y_IUnknownImpl_h_ 10 11 #include <windows.h> 12 #undef CreateEvent // thank you windows you're such a helper 13 #include "nsError.h" 14 15 // Avoid warning C4509 like "nonstandard extension used: 16 // 'AccessibleWrap::[acc_getName]' uses SEH and 'name' has destructor. 17 // At this point we're catching a crash which is of much greater 18 // importance than the missing dereference for the nsCOMPtr<> 19 #ifdef _MSC_VER 20 # pragma warning(disable : 4509) 21 #endif 22 23 namespace mozilla { 24 namespace a11y { 25 26 class AutoRefCnt { 27 public: 28 AutoRefCnt() : mValue(0) {} 29 30 ULONG operator++() { return ++mValue; } 31 ULONG operator--() { return --mValue; } 32 ULONG operator++(int) { return ++mValue; } 33 ULONG operator--(int) { return --mValue; } 34 35 operator ULONG() const { return mValue; } 36 37 private: 38 ULONG mValue; 39 }; 40 41 } // namespace a11y 42 } // namespace mozilla 43 44 #define DECL_IUNKNOWN \ 45 public: \ 46 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**) override; \ 47 ULONG STDMETHODCALLTYPE AddRef() override { \ 48 MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \ 49 ++mRefCnt; \ 50 return mRefCnt; \ 51 } \ 52 ULONG STDMETHODCALLTYPE Release() override { \ 53 MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \ 54 --mRefCnt; \ 55 if (mRefCnt) return mRefCnt; \ 56 \ 57 delete this; \ 58 return 0; \ 59 } \ 60 \ 61 private: \ 62 mozilla::a11y::AutoRefCnt mRefCnt; \ 63 \ 64 public: 65 66 #define DECL_IUNKNOWN_INHERITED \ 67 public: \ 68 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**) override; 69 70 #define IMPL_IUNKNOWN_QUERY_HEAD(Class) \ 71 STDMETHODIMP \ 72 Class::QueryInterface(REFIID aIID, void** aInstancePtr) { \ 73 if (!aInstancePtr) return E_INVALIDARG; \ 74 *aInstancePtr = nullptr; \ 75 \ 76 [[maybe_unused]] HRESULT hr = E_NOINTERFACE; 77 78 #define IMPL_IUNKNOWN_QUERY_TAIL \ 79 return hr; \ 80 } 81 82 #define IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(Member) \ 83 return Member->QueryInterface(aIID, aInstancePtr); \ 84 } 85 86 #define IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(BaseClass) \ 87 return BaseClass::QueryInterface(aIID, aInstancePtr); \ 88 } 89 90 #define IMPL_IUNKNOWN_QUERY_IFACE(Iface) \ 91 if (aIID == IID_##Iface) { \ 92 *aInstancePtr = static_cast<Iface*>(this); \ 93 AddRef(); \ 94 return S_OK; \ 95 } 96 97 #define IMPL_IUNKNOWN_QUERY_IFACE_AMBIGIOUS(Iface, aResolveIface) \ 98 if (aIID == IID_##Iface) { \ 99 *aInstancePtr = static_cast<Iface*>(static_cast<aResolveIface*>(this)); \ 100 AddRef(); \ 101 return S_OK; \ 102 } 103 104 #define IMPL_IUNKNOWN_QUERY_CLASS(Class) \ 105 hr = Class::QueryInterface(aIID, aInstancePtr); \ 106 if (SUCCEEDED(hr)) return hr; 107 108 #define IMPL_IUNKNOWN_QUERY_CLASS_COND(Class, Cond) \ 109 if (Cond) { \ 110 hr = Class::QueryInterface(aIID, aInstancePtr); \ 111 if (SUCCEEDED(hr)) return hr; \ 112 } 113 114 #define IMPL_IUNKNOWN_QUERY_AGGR_COND(Member, Cond) \ 115 if (Cond) { \ 116 hr = Member->QueryInterface(aIID, aInstancePtr); \ 117 if (SUCCEEDED(hr)) return hr; \ 118 } 119 120 #define IMPL_IUNKNOWN1(Class, I1) \ 121 IMPL_IUNKNOWN_QUERY_HEAD(Class) \ 122 IMPL_IUNKNOWN_QUERY_IFACE(I1); \ 123 IMPL_IUNKNOWN_QUERY_IFACE(IUnknown); \ 124 IMPL_IUNKNOWN_QUERY_TAIL 125 126 #define IMPL_IUNKNOWN2(Class, I1, I2) \ 127 IMPL_IUNKNOWN_QUERY_HEAD(Class) \ 128 IMPL_IUNKNOWN_QUERY_IFACE(I1); \ 129 IMPL_IUNKNOWN_QUERY_IFACE(I2); \ 130 IMPL_IUNKNOWN_QUERY_IFACE_AMBIGIOUS(IUnknown, I1); \ 131 IMPL_IUNKNOWN_QUERY_TAIL 132 133 #define IMPL_IUNKNOWN_INHERITED1(Class, Super0, Super1) \ 134 IMPL_IUNKNOWN_QUERY_HEAD(Class) \ 135 IMPL_IUNKNOWN_QUERY_CLASS(Super1); \ 136 IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(Super0) 137 138 #define IMPL_IUNKNOWN_INHERITED2(Class, Super0, Super1, Super2) \ 139 IMPL_IUNKNOWN_QUERY_HEAD(Class) \ 140 IMPL_IUNKNOWN_QUERY_CLASS(Super1); \ 141 IMPL_IUNKNOWN_QUERY_CLASS(Super2); \ 142 IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(Super0) 143 144 /** 145 * Overrides AddRef and Release to call a specific base class. 146 * If you are inheriting a single class (e.g. to override some methods), you 147 * shouldn't need to use this. However, if you are inheriting from a COM 148 * implementation and also inheriting additional COM interfaces, you will need 149 * to use this to specify which base implements reference counting. 150 */ 151 #define IMPL_IUNKNOWN_REFCOUNTING_INHERITED(BaseClass) \ 152 public: \ 153 ULONG STDMETHODCALLTYPE AddRef() override { return BaseClass::AddRef(); } \ 154 ULONG STDMETHODCALLTYPE Release() override { return BaseClass::Release(); } 155 156 namespace mozilla { 157 namespace a11y { 158 159 /** 160 * Converts nsresult to HRESULT. 161 */ 162 HRESULT GetHRESULT(nsresult aResult); 163 164 } // namespace a11y 165 } // namespace mozilla 166 167 #endif