michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. * michael@0: */ michael@0: michael@0: #ifndef mozilla_a11y_IUnknownImpl_h_ michael@0: #define mozilla_a11y_IUnknownImpl_h_ michael@0: michael@0: #include michael@0: #undef CreateEvent // thank you windows you're such a helper michael@0: #include "nsError.h" michael@0: michael@0: // Avoid warning C4509 like "nonstandard extension used: michael@0: // 'AccessibleWrap::[acc_getName]' uses SEH and 'name' has destructor. michael@0: // At this point we're catching a crash which is of much greater michael@0: // importance than the missing dereference for the nsCOMPtr<> michael@0: #ifdef _MSC_VER michael@0: #pragma warning( disable : 4509 ) michael@0: #endif michael@0: michael@0: namespace mozilla { michael@0: namespace a11y { michael@0: michael@0: class AutoRefCnt michael@0: { michael@0: public: michael@0: AutoRefCnt() : mValue(0) {} michael@0: michael@0: ULONG operator++() { return ++mValue; } michael@0: ULONG operator--() { return --mValue; } michael@0: ULONG operator++(int) { return ++mValue; } michael@0: ULONG operator--(int) { return --mValue; } michael@0: michael@0: operator ULONG() const { return mValue; } michael@0: michael@0: private: michael@0: ULONG mValue; michael@0: }; michael@0: michael@0: } // namespace a11y michael@0: } // namespace mozilla michael@0: michael@0: #define DECL_IUNKNOWN \ michael@0: public: \ michael@0: virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**); \ michael@0: virtual ULONG STDMETHODCALLTYPE AddRef() MOZ_FINAL \ michael@0: { \ michael@0: MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \ michael@0: ++mRefCnt; \ michael@0: return mRefCnt; \ michael@0: } \ michael@0: virtual ULONG STDMETHODCALLTYPE Release() MOZ_FINAL \ michael@0: { \ michael@0: MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \ michael@0: --mRefCnt; \ michael@0: if (mRefCnt) \ michael@0: return mRefCnt; \ michael@0: \ michael@0: delete this; \ michael@0: return 0; \ michael@0: } \ michael@0: private: \ michael@0: mozilla::a11y::AutoRefCnt mRefCnt; \ michael@0: public: michael@0: michael@0: #define DECL_IUNKNOWN_INHERITED \ michael@0: public: \ michael@0: virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**); \ michael@0: michael@0: #define IMPL_IUNKNOWN_QUERY_HEAD(Class) \ michael@0: STDMETHODIMP \ michael@0: Class::QueryInterface(REFIID aIID, void** aInstancePtr) \ michael@0: { \ michael@0: A11Y_TRYBLOCK_BEGIN \ michael@0: if (!aInstancePtr) \ michael@0: return E_INVALIDARG; \ michael@0: *aInstancePtr = nullptr; \ michael@0: \ michael@0: HRESULT hr = E_NOINTERFACE; michael@0: michael@0: #define IMPL_IUNKNOWN_QUERY_TAIL \ michael@0: return hr; \ michael@0: A11Y_TRYBLOCK_END \ michael@0: } michael@0: michael@0: #define IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(Member) \ michael@0: return Member->QueryInterface(aIID, aInstancePtr); \ michael@0: A11Y_TRYBLOCK_END \ michael@0: } michael@0: michael@0: #define IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(BaseClass) \ michael@0: return BaseClass::QueryInterface(aIID, aInstancePtr); \ michael@0: A11Y_TRYBLOCK_END \ michael@0: } michael@0: michael@0: #define IMPL_IUNKNOWN_QUERY_IFACE(Iface) \ michael@0: if (aIID == IID_##Iface) { \ michael@0: *aInstancePtr = static_cast(this); \ michael@0: AddRef(); \ michael@0: return S_OK; \ michael@0: } michael@0: michael@0: #define IMPL_IUNKNOWN_QUERY_IFACE_AMBIGIOUS(Iface, aResolveIface) \ michael@0: if (aIID == IID_##Iface) { \ michael@0: *aInstancePtr = static_cast(static_cast(this)); \ michael@0: AddRef(); \ michael@0: return S_OK; \ michael@0: } michael@0: michael@0: #define IMPL_IUNKNOWN_QUERY_CLASS(Class) \ michael@0: hr = Class::QueryInterface(aIID, aInstancePtr); \ michael@0: if (SUCCEEDED(hr)) \ michael@0: return hr; michael@0: michael@0: #define IMPL_IUNKNOWN_QUERY_CLASS_COND(Class, Cond) \ michael@0: if (Cond) { \ michael@0: hr = Class::QueryInterface(aIID, aInstancePtr); \ michael@0: if (SUCCEEDED(hr)) \ michael@0: return hr; \ michael@0: } michael@0: michael@0: #define IMPL_IUNKNOWN_QUERY_AGGR_COND(Member, Cond) \ michael@0: if (Cond) { \ michael@0: hr = Member->QueryInterface(aIID, aInstancePtr); \ michael@0: if (SUCCEEDED(hr)) \ michael@0: return hr; \ michael@0: } michael@0: michael@0: #define IMPL_IUNKNOWN1(Class, I1) \ michael@0: IMPL_IUNKNOWN_QUERY_HEAD(Class) \ michael@0: IMPL_IUNKNOWN_QUERY_IFACE(I1); \ michael@0: IMPL_IUNKNOWN_QUERY_IFACE(IUnknown); \ michael@0: IMPL_IUNKNOWN_QUERY_TAIL \ michael@0: michael@0: #define IMPL_IUNKNOWN2(Class, I1, I2) \ michael@0: IMPL_IUNKNOWN_QUERY_HEAD(Class) \ michael@0: IMPL_IUNKNOWN_QUERY_IFACE(I1); \ michael@0: IMPL_IUNKNOWN_QUERY_IFACE(I2); \ michael@0: IMPL_IUNKNOWN_QUERY_IFACE_AMBIGIOUS(IUnknown, I1); \ michael@0: IMPL_IUNKNOWN_QUERY_TAIL \ michael@0: michael@0: #define IMPL_IUNKNOWN_INHERITED1(Class, Super0, Super1) \ michael@0: IMPL_IUNKNOWN_QUERY_HEAD(Class) \ michael@0: IMPL_IUNKNOWN_QUERY_CLASS(Super1); \ michael@0: IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(Super0) michael@0: michael@0: #define IMPL_IUNKNOWN_INHERITED2(Class, Super0, Super1, Super2) \ michael@0: IMPL_IUNKNOWN_QUERY_HEAD(Class) \ michael@0: IMPL_IUNKNOWN_QUERY_CLASS(Super1); \ michael@0: IMPL_IUNKNOWN_QUERY_CLASS(Super2); \ michael@0: IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(Super0) michael@0: michael@0: michael@0: /** michael@0: * Wrap every method body by these macroses to pass exception to the crash michael@0: * reporter. michael@0: */ michael@0: #define A11Y_TRYBLOCK_BEGIN \ michael@0: MOZ_SEH_TRY { michael@0: michael@0: #define A11Y_TRYBLOCK_END \ michael@0: } MOZ_SEH_EXCEPT(mozilla::a11y::FilterExceptions(::GetExceptionCode(), \ michael@0: GetExceptionInformation())) \ michael@0: { } \ michael@0: return E_FAIL; michael@0: michael@0: michael@0: namespace mozilla { michael@0: namespace a11y { michael@0: michael@0: /** michael@0: * Converts nsresult to HRESULT. michael@0: */ michael@0: HRESULT GetHRESULT(nsresult aResult); michael@0: michael@0: /** michael@0: * Used to pass an exception to the crash reporter. michael@0: */ michael@0: int FilterExceptions(unsigned int aCode, EXCEPTION_POINTERS* aExceptionInfo); michael@0: michael@0: } // namespace a11y; michael@0: } //namespace mozilla; michael@0: michael@0: #endif