summaryrefslogtreecommitdiffstats
path: root/accessible/windows/msaa/IUnknownImpl.h
blob: 7935ebedda24d75d3b7d0591b96af1b3ecb5b325 (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
/* -*- 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

#if defined(__GNUC__) || defined(__clang__)
#  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**); \
  ULONG STDMETHODCALLTYPE AddRef() override {                       \
    MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");            \
    ++mRefCnt;                                                      \
    return mRefCnt;                                                 \
  }                                                                 \
  ULONG STDMETHODCALLTYPE Release() override {                      \
    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) { \
    if (!aInstancePtr) return E_INVALIDARG;                 \
    *aInstancePtr = nullptr;                                \
                                                            \
    HRESULT hr ATTRIBUTE_UNUSED = E_NOINTERFACE;

#define IMPL_IUNKNOWN_QUERY_TAIL \
  return hr;                     \
  }

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

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

#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)

/**
 * Overrides AddRef and Release to call a specific base class.
 * If you are inheriting a single class (e.g. to override some methods), you
 * shouldn't need to use this. However, if you are inheriting from a COM
 * implementation and also inheriting additional COM interfaces, you will need
 * to use this to specify which base implements reference counting.
 */
#define IMPL_IUNKNOWN_REFCOUNTING_INHERITED(BaseClass)                      \
 public:                                                                    \
  ULONG STDMETHODCALLTYPE AddRef() override { return BaseClass::AddRef(); } \
  ULONG STDMETHODCALLTYPE Release() override { return BaseClass::Release(); }

namespace mozilla {
namespace a11y {

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

}  // namespace a11y
}  // namespace mozilla

#endif