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 #ifdef __GNUC__ 24 #define ATTRIBUTE_UNUSED __attribute__((unused)) 25 #else 26 #define ATTRIBUTE_UNUSED 27 #endif 28 29 namespace mozilla { 30 namespace a11y { 31 32 class AutoRefCnt 33 { 34 public: AutoRefCnt()35 AutoRefCnt() : mValue(0) {} 36 37 ULONG operator++() { return ++mValue; } 38 ULONG operator--() { return --mValue; } 39 ULONG operator++(int) { return ++mValue; } 40 ULONG operator--(int) { return --mValue; } 41 ULONG()42 operator ULONG() const { return mValue; } 43 44 private: 45 ULONG mValue; 46 }; 47 48 } // namespace a11y 49 } // namespace mozilla 50 51 #define DECL_IUNKNOWN \ 52 public: \ 53 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**); \ 54 virtual ULONG STDMETHODCALLTYPE AddRef() final \ 55 { \ 56 MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \ 57 ++mRefCnt; \ 58 return mRefCnt; \ 59 } \ 60 virtual ULONG STDMETHODCALLTYPE Release() final \ 61 { \ 62 MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \ 63 --mRefCnt; \ 64 if (mRefCnt) \ 65 return mRefCnt; \ 66 \ 67 delete this; \ 68 return 0; \ 69 } \ 70 private: \ 71 mozilla::a11y::AutoRefCnt mRefCnt; \ 72 public: 73 74 #define DECL_IUNKNOWN_INHERITED \ 75 public: \ 76 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**); \ 77 78 #define IMPL_IUNKNOWN_QUERY_HEAD(Class) \ 79 STDMETHODIMP \ 80 Class::QueryInterface(REFIID aIID, void** aInstancePtr) \ 81 { \ 82 A11Y_TRYBLOCK_BEGIN \ 83 if (!aInstancePtr) \ 84 return E_INVALIDARG; \ 85 *aInstancePtr = nullptr; \ 86 \ 87 HRESULT hr ATTRIBUTE_UNUSED = E_NOINTERFACE; 88 89 #define IMPL_IUNKNOWN_QUERY_TAIL \ 90 return hr; \ 91 A11Y_TRYBLOCK_END \ 92 } 93 94 #define IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(Member) \ 95 return Member->QueryInterface(aIID, aInstancePtr); \ 96 A11Y_TRYBLOCK_END \ 97 } 98 99 #define IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(BaseClass) \ 100 return BaseClass::QueryInterface(aIID, aInstancePtr); \ 101 A11Y_TRYBLOCK_END \ 102 } 103 104 #define IMPL_IUNKNOWN_QUERY_IFACE(Iface) \ 105 if (aIID == IID_##Iface) { \ 106 *aInstancePtr = static_cast<Iface*>(this); \ 107 AddRef(); \ 108 return S_OK; \ 109 } 110 111 #define IMPL_IUNKNOWN_QUERY_IFACE_AMBIGIOUS(Iface, aResolveIface) \ 112 if (aIID == IID_##Iface) { \ 113 *aInstancePtr = static_cast<Iface*>(static_cast<aResolveIface*>(this)); \ 114 AddRef(); \ 115 return S_OK; \ 116 } 117 118 #define IMPL_IUNKNOWN_QUERY_CLASS(Class) \ 119 hr = Class::QueryInterface(aIID, aInstancePtr); \ 120 if (SUCCEEDED(hr)) \ 121 return hr; 122 123 #define IMPL_IUNKNOWN_QUERY_CLASS_COND(Class, Cond) \ 124 if (Cond) { \ 125 hr = Class::QueryInterface(aIID, aInstancePtr); \ 126 if (SUCCEEDED(hr)) \ 127 return hr; \ 128 } 129 130 #define IMPL_IUNKNOWN_QUERY_AGGR_COND(Member, Cond) \ 131 if (Cond) { \ 132 hr = Member->QueryInterface(aIID, aInstancePtr); \ 133 if (SUCCEEDED(hr)) \ 134 return hr; \ 135 } 136 137 #define IMPL_IUNKNOWN1(Class, I1) \ 138 IMPL_IUNKNOWN_QUERY_HEAD(Class) \ 139 IMPL_IUNKNOWN_QUERY_IFACE(I1); \ 140 IMPL_IUNKNOWN_QUERY_IFACE(IUnknown); \ 141 IMPL_IUNKNOWN_QUERY_TAIL \ 142 143 #define IMPL_IUNKNOWN2(Class, I1, I2) \ 144 IMPL_IUNKNOWN_QUERY_HEAD(Class) \ 145 IMPL_IUNKNOWN_QUERY_IFACE(I1); \ 146 IMPL_IUNKNOWN_QUERY_IFACE(I2); \ 147 IMPL_IUNKNOWN_QUERY_IFACE_AMBIGIOUS(IUnknown, I1); \ 148 IMPL_IUNKNOWN_QUERY_TAIL \ 149 150 #define IMPL_IUNKNOWN_INHERITED1(Class, Super0, Super1) \ 151 IMPL_IUNKNOWN_QUERY_HEAD(Class) \ 152 IMPL_IUNKNOWN_QUERY_CLASS(Super1); \ 153 IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(Super0) 154 155 #define IMPL_IUNKNOWN_INHERITED2(Class, Super0, Super1, Super2) \ 156 IMPL_IUNKNOWN_QUERY_HEAD(Class) \ 157 IMPL_IUNKNOWN_QUERY_CLASS(Super1); \ 158 IMPL_IUNKNOWN_QUERY_CLASS(Super2); \ 159 IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(Super0) 160 161 162 /** 163 * Wrap every method body by these macroses to pass exception to the crash 164 * reporter. 165 */ 166 #define A11Y_TRYBLOCK_BEGIN \ 167 MOZ_SEH_TRY { 168 169 #define A11Y_TRYBLOCK_END \ 170 } MOZ_SEH_EXCEPT(mozilla::a11y::FilterExceptions(::GetExceptionCode(), \ 171 GetExceptionInformation())) \ 172 { } \ 173 return E_FAIL; 174 175 176 namespace mozilla { 177 namespace a11y { 178 179 /** 180 * Converts nsresult to HRESULT. 181 */ 182 HRESULT GetHRESULT(nsresult aResult); 183 184 /** 185 * Used to pass an exception to the crash reporter. 186 */ 187 int FilterExceptions(unsigned int aCode, EXCEPTION_POINTERS* aExceptionInfo); 188 189 } // namespace a11y; 190 } //namespace mozilla; 191 192 #endif 193