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