summaryrefslogtreecommitdiffstats
path: root/accessible/windows/msaa/IUnknownImpl.h
blob: dbf6c1374ffa4ba76b6f3319df45d04c125db710 (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
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. *
 */

#ifndef mozilla_a11y_IUnknownImpl_h_
#define mozilla_a11y_IUnknownImpl_h_

#include <windows.h>
#undef CreateEvent // thank you windows you're such a helper
#include "nsError.h"

// Avoid warning C4509 like "nonstandard extension used:
// 'AccessibleWrap::[acc_getName]' uses SEH and 'name' has destructor.
// At this point we're catching a crash which is of much greater
// importance than the missing dereference for the nsCOMPtr<>
#ifdef _MSC_VER
#pragma warning( disable : 4509 )
#endif

#ifdef __GNUC__
#define ATTRIBUTE_UNUSED __attribute__((unused))
#else
#define ATTRIBUTE_UNUSED
#endif

namespace mozilla {
namespace a11y {

class AutoRefCnt
{
public:
  AutoRefCnt() : mValue(0) {}

  ULONG operator++() { return ++mValue; }
  ULONG operator--() { return --mValue; }
  ULONG operator++(int) { return ++mValue; }
  ULONG operator--(int) { return --mValue; }

  operator ULONG() const { return mValue; }

private:
  ULONG mValue;
};

} // namespace a11y
} // namespace mozilla

#define DECL_IUNKNOWN                                                          \
public:                                                                        \
  virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**);            \
  virtual ULONG STDMETHODCALLTYPE AddRef() final                               \
  {                                                                            \
    MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");                       \
    ++mRefCnt;                                                                 \
    return mRefCnt;                                                            \
  }                                                                            \
  virtual ULONG STDMETHODCALLTYPE Release() final                              \
  {                                                                            \
     MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                          \
     --mRefCnt;                                                                \
     if (mRefCnt)                                                              \
       return mRefCnt;                                                         \
                                                                               \
     delete this;                                                              \
     return 0;                                                                 \
  }                                                                            \
private:                                                                       \
  mozilla::a11y::AutoRefCnt mRefCnt;                                           \
public:

#define DECL_IUNKNOWN_INHERITED                                                \
public:                                                                        \
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**);              \

#define IMPL_IUNKNOWN_QUERY_HEAD(Class)                                        \
STDMETHODIMP                                                                   \
Class::QueryInterface(REFIID aIID, void** aInstancePtr)                        \
{                                                                              \
  A11Y_TRYBLOCK_BEGIN                                                          \
  if (!aInstancePtr)                                                           \
    return E_INVALIDARG;                                                       \
  *aInstancePtr = nullptr;                                                     \
                                                                               \
  HRESULT hr ATTRIBUTE_UNUSED = E_NOINTERFACE;

#define IMPL_IUNKNOWN_QUERY_TAIL                                               \
  return hr;                                                                   \
  A11Y_TRYBLOCK_END                                                            \
}

#define IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(Member)                            \
  return Member->QueryInterface(aIID, aInstancePtr);                           \
  A11Y_TRYBLOCK_END                                                            \
}

#define IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(BaseClass)                          \
  return BaseClass::QueryInterface(aIID, aInstancePtr);                        \
  A11Y_TRYBLOCK_END                                                            \
}

#define IMPL_IUNKNOWN_QUERY_IFACE(Iface)                                       \
  if (aIID == IID_##Iface) {                                                   \
    *aInstancePtr = static_cast<Iface*>(this);                                 \
    AddRef();                                                                  \
    return S_OK;                                                               \
  }

#define IMPL_IUNKNOWN_QUERY_IFACE_AMBIGIOUS(Iface, aResolveIface)              \
  if (aIID == IID_##Iface) {                                                   \
    *aInstancePtr = static_cast<Iface*>(static_cast<aResolveIface*>(this));    \
    AddRef();                                                                  \
    return S_OK;                                                               \
  }

#define IMPL_IUNKNOWN_QUERY_CLASS(Class)                                       \
  hr = Class::QueryInterface(aIID, aInstancePtr);                              \
  if (SUCCEEDED(hr))                                                           \
    return hr;

#define IMPL_IUNKNOWN_QUERY_CLASS_COND(Class, Cond)                            \
  if (Cond) {                                                                  \
    hr = Class::QueryInterface(aIID, aInstancePtr);                            \
    if (SUCCEEDED(hr))                                                         \
      return hr;                                                               \
  }

#define IMPL_IUNKNOWN_QUERY_AGGR_COND(Member, Cond)                            \
  if (Cond) {                                                                  \
    hr = Member->QueryInterface(aIID, aInstancePtr);                           \
    if (SUCCEEDED(hr))                                                         \
      return hr;                                                               \
  }

#define IMPL_IUNKNOWN1(Class, I1)                                              \
  IMPL_IUNKNOWN_QUERY_HEAD(Class)                                              \
  IMPL_IUNKNOWN_QUERY_IFACE(I1);                                               \
  IMPL_IUNKNOWN_QUERY_IFACE(IUnknown);                                         \
  IMPL_IUNKNOWN_QUERY_TAIL                                                     \

#define IMPL_IUNKNOWN2(Class, I1, I2)                                          \
  IMPL_IUNKNOWN_QUERY_HEAD(Class)                                              \
  IMPL_IUNKNOWN_QUERY_IFACE(I1);                                               \
  IMPL_IUNKNOWN_QUERY_IFACE(I2);                                               \
  IMPL_IUNKNOWN_QUERY_IFACE_AMBIGIOUS(IUnknown, I1);                           \
  IMPL_IUNKNOWN_QUERY_TAIL                                                     \

#define IMPL_IUNKNOWN_INHERITED1(Class, Super0, Super1)                        \
  IMPL_IUNKNOWN_QUERY_HEAD(Class)                                              \
  IMPL_IUNKNOWN_QUERY_CLASS(Super1);                                           \
  IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(Super0)

#define IMPL_IUNKNOWN_INHERITED2(Class, Super0, Super1, Super2)                \
  IMPL_IUNKNOWN_QUERY_HEAD(Class)                                              \
  IMPL_IUNKNOWN_QUERY_CLASS(Super1);                                           \
  IMPL_IUNKNOWN_QUERY_CLASS(Super2);                                           \
  IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(Super0)


/**
 * Wrap every method body by these macroses to pass exception to the crash
 * reporter.
 */
#define A11Y_TRYBLOCK_BEGIN                                                    \
  MOZ_SEH_TRY {

#define A11Y_TRYBLOCK_END                                                      \
  } MOZ_SEH_EXCEPT(mozilla::a11y::FilterExceptions(::GetExceptionCode(),       \
                                                   GetExceptionInformation())) \
  { }                                                                          \
  return E_FAIL;


namespace mozilla {
namespace a11y {

/**
 * Converts nsresult to HRESULT.
 */
HRESULT GetHRESULT(nsresult aResult);

/**
 * Used to pass an exception to the crash reporter.
 */
int FilterExceptions(unsigned int aCode, EXCEPTION_POINTERS* aExceptionInfo);

} // namespace a11y;
} //namespace mozilla;

#endif