Add minimalistic protected-headers support
[gpgol.git] / src / eventsink.h
1 /* eventsink.h - Macros to implement an OLE event sink
2  * Copyright (C) 2009 g10 Code GmbH
3  * Copyright (C) 2015 by Bundesamt für Sicherheit in der Informationstechnik
4  * Software engineering by Intevation GmbH
5  *
6  * This file is part of GpgOL.
7  *
8  * GpgOL is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * GpgOL is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 /* This is our lame implementation of event sinks.  It is sufficient
23    for our purpose but far from optimal; e.g. we should not simply
24    provide stubs but do real sub-classing by modifying the vtables.  */
25
26 /* See eventsinks.cpp for example usage */
27
28 #ifndef EVENTSINK_H
29 #define EVENTSINK_H
30
31
32 #define BEGIN_EVENT_SINK(subcls,parentcls)                               \
33 class subcls : public parentcls                                          \
34 {                                                                        \
35  public:                                                                 \
36   subcls (void);                                                         \
37   virtual ~subcls (void);                                                \
38   LPDISPATCH m_object;                                                   \
39   LPCONNECTIONPOINT m_pCP;                                               \
40   DWORD m_cookie;                                                        \
41  private:                                                                \
42   ULONG     m_ref;                                                       \
43  public:                                                                 \
44   STDMETHODIMP QueryInterface (REFIID riid, LPVOID FAR *ppvObj);         \
45   inline STDMETHODIMP_(ULONG) AddRef (void)                              \
46     {                                                                    \
47       ++m_ref;                                                           \
48       if ((opt.enable_debug & DBG_OOM))                                               \
49         log_debug ("%s:" #subcls ":%s: m_ref now %lu",                   \
50                    SRCNAME,__func__, m_ref);                             \
51       return m_ref;                                                      \
52     }                                                                    \
53   inline STDMETHODIMP_(ULONG) Release (void)                             \
54     {                                                                    \
55       ULONG count = --m_ref;                                             \
56       if ((opt.enable_debug & DBG_OOM))                                               \
57         log_debug ("%s:" #subcls ":%s: mref now %lu",                    \
58                    SRCNAME,__func__,count);                              \
59       if (!count)                                                        \
60         delete this;                                                     \
61       return count;                                                      \
62     }                                                                    \
63   STDMETHODIMP GetTypeInfoCount (UINT*);                                 \
64   STDMETHODIMP GetTypeInfo (UINT, LCID, LPTYPEINFO*);                    \
65   STDMETHODIMP GetIDsOfNames (REFIID, LPOLESTR*, UINT, LCID, DISPID*);   \
66   STDMETHODIMP Invoke (DISPID, REFIID, LCID, WORD,                       \
67                        DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*);        \
68 /* End of macro BEGIN_EVENT_SINK.  */
69
70 #define EVENT_SINK_CTOR(subcls)                                          \
71 };                                                                       \
72 subcls::subcls ()                                                        \
73 {                                                                        \
74   m_ref = 1;                                                             \
75 /* End of macro EVENT_SINK_CTOR.  */
76
77 #define EVENT_SINK_DTOR(subcls)                                          \
78 }                                                                        \
79 subcls::~subcls ()                                                       \
80 /* End of macro EVENT_SINK_DTOR.  */
81
82 #define EVENT_SINK_INVOKE(subcls)                                        \
83 STDMETHODIMP subcls::Invoke (DISPID dispid, REFIID riid, LCID lcid,      \
84                 WORD flags, DISPPARAMS *parms, VARIANT *result,          \
85                 EXCEPINFO *exepinfo, UINT *argerr)                       \
86 /* End of macro EVENT_SINK_INVOKE.  */
87
88 #define USE_INVOKE_ARGS                                                  \
89   (void)riid; (void)lcid; (void)flags; (void)parms; (void)result;       \
90   (void)exepinfo; (void)argerr; (void)dispid;
91 /* End of macro USE_INVOKE_ARGS. */
92
93 #define EVENT_SINK_DEFAULT_DTOR_CODE(subcls)                             \
94 {                                                                        \
95   if ((opt.enable_debug & DBG_OOM))                                                         \
96     log_debug ("%s:" #subcls ":%s: dtor", SRCNAME, __func__);            \
97   if (m_pCP)                                                             \
98     m_pCP->Unadvise(m_cookie);                                           \
99   if (m_object)                                                          \
100     gpgol_release (m_object);                                                 \
101 }                                                                        \
102 /* End of macro EVENT_SINK_DTOR_DEFAULT_CODE.  */
103
104
105 #define EVENT_SINK_DEFAULT_CTOR(subcls)                                  \
106   EVENT_SINK_CTOR(subcls)                                                \
107 /* End of macro EVENT_SINK_STD_DTOR.  */
108
109 #define EVENT_SINK_DEFAULT_DTOR(subcls)                                  \
110   EVENT_SINK_DTOR(subcls)                                                \
111   EVENT_SINK_DEFAULT_DTOR_CODE(subcls)                                   \
112 /* End of macro EVENT_SINK_STD_DTOR.  */
113
114
115 #define END_EVENT_SINK(subcls,iidcls)                                    \
116 STDMETHODIMP subcls::QueryInterface (REFIID riid, LPVOID FAR *ppvObj)    \
117 {                                                                        \
118   /*log_debug ("%s:%s:%s: called riid=%08lx-%04hx-%04hx"                 \
119              "-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",                 \
120              SRCNAME, #subcls, __func__,                                 \
121              riid.Data1, riid.Data2, riid.Data3,                         \
122              riid.Data4[0], riid.Data4[1], riid.Data4[2],                \
123              riid.Data4[3], riid.Data4[4], riid.Data4[5],                \
124              riid.Data4[6], riid.Data4[7] );*/                           \
125   if (riid == IID_IUnknown || riid == iidcls || riid == IID_IDispatch)   \
126     {                                                                    \
127       *ppvObj = (LPUNKNOWN) this;                                        \
128       ((LPUNKNOWN)*ppvObj)->AddRef();                                    \
129       return S_OK;                                                       \
130     }                                                                    \
131   *ppvObj = NULL;                                                        \
132   return E_NOINTERFACE;                                                  \
133 }                                                                        \
134 STDMETHODIMP subcls::GetTypeInfoCount (UINT *r_count)                    \
135 {                                                                        \
136   *r_count = 0;                                                          \
137   return S_OK;                                                           \
138 }                                                                        \
139 STDMETHODIMP subcls::GetTypeInfo (UINT iTypeInfo, LCID lcid,             \
140                                   LPTYPEINFO *r_typeinfo)                \
141 {                                                                        \
142   (void)iTypeInfo;                                                       \
143   (void)lcid;                                                            \
144   (void)r_typeinfo;                                                      \
145   return E_NOINTERFACE;                                                  \
146 }                                                                        \
147 STDMETHODIMP subcls::GetIDsOfNames (REFIID riid, LPOLESTR *rgszNames,    \
148                                     UINT cNames, LCID lcid,              \
149                                     DISPID *rgDispId)                    \
150 {                                                                        \
151   (void)riid;                                                            \
152   (void)rgszNames;                                                       \
153   (void)cNames;                                                          \
154   (void)lcid;                                                            \
155   (void)rgDispId;                                                        \
156   return E_NOINTERFACE;                                                  \
157 }                                                                        \
158 LPDISPATCH install_ ## subcls ## _sink (LPDISPATCH object)               \
159 {                                                                        \
160   HRESULT hr;                                                            \
161   LPDISPATCH disp;                                                       \
162   LPCONNECTIONPOINTCONTAINER pCPC;                                       \
163   LPCONNECTIONPOINT pCP;                                                 \
164   subcls *sink;                                                          \
165   DWORD cookie;                                                          \
166                                                                          \
167   disp = NULL;                                                           \
168   hr = gpgol_queryInterface (object, IID_IConnectionPointContainer,      \
169                              (LPVOID*)&disp);                            \
170   if (hr != S_OK || !disp)                                               \
171     {                                                                    \
172       log_error ("%s:%s:%s: IConnectionPoint not supported: hr=%#lx",    \
173                  SRCNAME, #subcls, __func__, hr);                        \
174       return NULL;                                                       \
175     }                                                                    \
176   pCPC = (LPCONNECTIONPOINTCONTAINER)disp;                               \
177   pCP = NULL;                                                            \
178   hr = pCPC->FindConnectionPoint (iidcls, &pCP);                         \
179   memdbg_addRef (pCP);                                                   \
180   if (hr != S_OK || !pCP)                                                \
181     {                                                                    \
182       log_error ("%s:%s:%s: ConnectionPoint not found: hr=%#lx",         \
183                  SRCNAME,#subcls,  __func__, hr);                        \
184       gpgol_release (pCPC);                                                  \
185       return NULL;                                                       \
186     }                                                                    \
187   sink = new subcls; /* Note: Advise does another AddRef.  */            \
188   hr = pCP->Advise ((LPUNKNOWN)sink, &cookie);                           \
189   memdbg_addRef (sink);                                                  \
190   gpgol_release (pCPC);                                                      \
191   if (hr != S_OK)                                                        \
192     {                                                                    \
193       log_error ("%s:%s:%s: Advice failed: hr=%#lx",                     \
194                  SRCNAME, #subcls, __func__, hr);                        \
195       gpgol_release (pCP);                                                   \
196       gpgol_release (sink);                                                  \
197       return NULL;                                                       \
198     }                                                                    \
199   if ((opt.enable_debug & DBG_OOM))                                                         \
200     log_debug ("%s:%s:%s: Advice succeeded", SRCNAME, #subcls, __func__);\
201   sink->m_cookie = cookie;                                               \
202   sink->m_pCP = pCP;                                                     \
203   object->AddRef ();                                                     \
204   memdbg_addRef (object);                                                \
205   sink->m_object = object;                                               \
206   return (LPDISPATCH)sink;                                               \
207 }                                                                        \
208 void detach_ ## subcls ## _sink (LPDISPATCH obj)                         \
209 {                                                                        \
210   HRESULT hr;                                                            \
211   subcls *sink;                                                          \
212                                                                          \
213   if ((opt.enable_debug & DBG_OOM))                                                   \
214     log_debug ("%s:%s:%s: Called", SRCNAME, #subcls, __func__);          \
215   hr = gpgol_queryInterface (obj, iidcls, (void**)&sink);                \
216   if (hr != S_OK || !sink)                                               \
217     {                                                                    \
218       log_error ("%s:%s:%s: invalid object passed: hr=%#lx",             \
219                  SRCNAME, #subcls, __func__, hr);                        \
220       return;                                                            \
221     }                                                                    \
222   if (sink->m_pCP)                                                       \
223     {                                                                    \
224       if ((opt.enable_debug & DBG_OOM))                                               \
225         log_debug ("%s:%s:%s: Unadvising", SRCNAME, #subcls, __func__);  \
226       hr = sink->m_pCP->Unadvise (sink->m_cookie);                       \
227       if (hr != S_OK)                                                    \
228         log_error ("%s:%s:%s: Unadvice failed: hr=%#lx",                 \
229                    SRCNAME, #subcls, __func__, hr);                      \
230       if ((opt.enable_debug & DBG_OOM))                                               \
231         log_debug ("%s:%s:%s: Releasing connt point",                    \
232                    SRCNAME, #subcls, __func__);                          \
233       gpgol_release (sink->m_pCP);                                           \
234       sink->m_pCP = NULL;                                                \
235     }                                                                    \
236   if (sink->m_object)                                                    \
237     {                                                                    \
238       if ((opt.enable_debug & DBG_OOM))                                               \
239         log_debug ("%s:%s:%s: Releasing actual object",                  \
240                    SRCNAME, #subcls, __func__);                          \
241       gpgol_release (sink->m_object);                                        \
242       sink->m_object = NULL;                                             \
243     }                                                                    \
244   gpgol_release (sink);                                                      \
245 }                                                                        \
246 /* End of macro END_EVENT_SINK.  */
247
248
249 #endif /*EVENTSINK_H*/