-
Notifications
You must be signed in to change notification settings - Fork 5
/
dispimpl2.h
267 lines (245 loc) · 8.94 KB
/
dispimpl2.h
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
// dispimpl2.h: Alternative implementations of IDispatch
/////////////////////////////////////////////////////////////////////////////
// Copyright (c) 1998-2003 Chris Sells
// All rights reserved.
/////////////////////////////////////////////////////////////////////////////
// History:
// 6/11/03:
// -Ehab Kashkash ([email protected]): Added "typename" keyword
// when initializing static variables of user-defined types (_tihclass)
// in order to be able to compile with VS.NET.
//
// 3/3/00:
// -Added some description of using IDelegatingDispImpl with controls to
// satisfied picky control contains (like VB). Thanks to Greg Kedge
// [[email protected]] for providing the initial draft.
//
// 7/22/99 (later again...):
// -Simon Fell ([email protected]) pointed out a bug where
// I don't actually derived from D in IDelegatingDispImpl. Doh!
//
// 7/22/99 (sometime later):
// -Put optional D back in as a base, but default to IDispatch,
// allowing you to use IDelegatingDispImpl like so:
//
// class CFoo :
// public IDelegatingDispImpl<IFoo, &IID_IFoo, DFoo>...
//
// 7/22/99:
// -Simplified usage of IDelegatingDispImpl. You will
// have to change your usage from:
//
// class CFoo :
// public IDelegatingDispImpl<DFoo, IFoo>...
//
// to:
//
// class CFoo :
// public IDelegatingDispImpl<IFoo>...
//
// 10/25/98:
// -Initial release.
//
// NO WARRANTIES ARE EXTENDED. USE AT YOUR OWN RISK.
//
// Contact the author with suggestions or comments at [email protected].
//
/////////////////////////////////////////////////////////////////////////////
//
// This header defines three C++ classes for use in implementing
// dispatch-based interfaces:
//
// -IDualDispImpl for implementing dual interfaces.
//
// -IDelegatingDispImpl for implementing IDispatch by delegation
// to another interface (typically a custom interface).
//
// -IRawDispImpl for implementing raw dispinterfaces.
//
// These classes are useful because ATL's IDispatchImpl can
// only implement duals.
//
/////////////////////////////////////////////////////////////////////////////
//
// IDualDispImpl: For use with dispatch-based interfaces declared like so:
//
// [dual]
// interface IFoo : IDispatch
// {
// ...
// }
//
// IDualDispImpl implements all four IDispatch methods.
// IDualDispImpl gets the IDispatch vtbl entries by deriving from
// the IDispatch that servers as the base class for the dual interface.
// IDualDispImpl is just like ATL's IDispatchImpl (in fact, it
// derives from IDispatchImpl), but it uses __uuidof to make the usage
// simplier.
//
// Usage:
// class CFoo : ..., public IDualDispImpl<IFoo>
//
/////////////////////////////////////////////////////////////////////////////
//
// IDelegatingDispImpl: For implementing IDispatch in terms of another
// (typically custom) interface, e.g.:
//
// [oleautomation]
// interface IFoo : IUnknown
// {
// ...
// }
//
// IDelegatingDispImpl implements all four IDispatch methods.
// IDelegatingDispImpl gets the IDispatch vtbl entries by deriving from
// IDispatch in addition to the implementation interface.
//
// Usage:
// class CFoo : ..., public IDelegatingDispImpl<IFoo>
//
// In the case where the coclass is intended to represent a control,
// there is a need for the coclass to have a [default] dispinterface.
// Otherwise, some control containers (notably VB) throw arcane error when
// the control is loaded. For a control that you intend to provide the
// custom interface and delegating dispatch mechanism, you will have to
// provide a dispinterface defined in terms of a custom interface like
// so:
//
// dispinterface DFoo
// {
// interface IFoo;
// }
//
// coclass Foo
// {
// [default] interface DFoo;
// interface IFoo;
// };
//
// For every other situation, declaring a dispinterface in terms of a
// custom interface is not necessary to use IDelegatingDispatchImpl.
// However, if you'd like DFoo to be in the base class list (as needed
// for the caveat control), you may use DFoo as the base class instead
// of the default template argument IDispatch like so:
//
// Usage:
// class CFoo : ..., public IDelegatingDispImpl<IFoo, &IID_IFoo, DFoo>
//
/////////////////////////////////////////////////////////////////////////////
//
// IRawDispImpl: For use with dispatch-based interfaces declared like so:
//
// dispinterface DFoo
// {
// properties:
// ...
// methods:
// ...
// }
//
// IRawDispImpl implements three of the IDispatch methods.
// Invoke is left to the implementor.
//
// Usage:
// class CFoo : ..., public IRawDispImpl<DFoo>
// {
// ...
// STDMETHODIMP Invoke(...); // Implemented by hand.
// };
//
/////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef INC_DISPIMPL2
#define INC_DISPIMPL2
/////////////////////////////////////////////////////////////////////////////
// IDualDispImpl
template <class T, const IID* piid = &__uuidof(T), const GUID* plibid = &CComModule::m_libid, WORD wMajor = 1,
WORD wMinor = 0, class tihclass = CComTypeInfoHolder>
class ATL_NO_VTABLE IDualDispImpl : public IDispatchImpl<T, piid, plibid, wMajor, wMinor, tihclass> {};
/////////////////////////////////////////////////////////////////////////////
// IDelegatingDispImpl
template <class T, const IID* piid = &__uuidof(T), class D = IDispatch,
const GUID* plibid = &CComModule::m_libid, WORD wMajor = 1,
WORD wMinor = 0, class tihclass = CComTypeInfoHolder>
class ATL_NO_VTABLE IDelegatingDispImpl : public T, public D
{
public:
typedef tihclass _tihclass;
// IDispatch
STDMETHOD(GetTypeInfoCount)(UINT* pctinfo)
{
*pctinfo = 1;
return S_OK;
}
STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
{
return _tih.GetTypeInfo(itinfo, lcid, pptinfo);
}
STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
LCID lcid, DISPID* rgdispid)
{
return _tih.GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
}
STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid,
LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
// NOTE: reinterpret_cast because CComTypeInfoHolder makes the mistaken
// assumption that the typeinfo can only Invoke using an IDispatch*.
// Since the implementation only passes the itf onto
// ITypeInfo::Invoke (which takes a void*), this is a safe cast
// until the ATL team fixes CComTypeInfoHolder.
return _tih.Invoke(reinterpret_cast<IDispatch*>(static_cast<T*>(this)),
dispidMember, riid, lcid, wFlags, pdispparams,
pvarResult, pexcepinfo, puArgErr);
}
protected:
static _tihclass _tih;
static HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo)
{
return _tih.GetTI(lcid, ppInfo);
}
};
template <class T, const IID* piid, class D, const GUID* plibid, WORD wMajor, WORD wMinor, class tihclass>
typename IDelegatingDispImpl<T, piid, D, plibid, wMajor, wMinor, tihclass>::_tihclass
IDelegatingDispImpl<T, piid, D, plibid, wMajor, wMinor, tihclass>::_tih =
{ piid, plibid, wMajor, wMinor, NULL, 0, NULL, 0 };
/////////////////////////////////////////////////////////////////////////////
// IRawDispImpl
template <class T, const IID* piid = &__uuidof(T), const GUID* plibid = &CComModule::m_libid, WORD wMajor = 1,
WORD wMinor = 0, class tihclass = CComTypeInfoHolder>
class ATL_NO_VTABLE IRawDispImpl : public T
{
public:
typedef tihclass _tihclass;
// IDispatch
STDMETHOD(GetTypeInfoCount)(UINT* pctinfo)
{
*pctinfo = 1;
return S_OK;
}
STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
{
return _tih.GetTypeInfo(itinfo, lcid, pptinfo);
}
STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
LCID lcid, DISPID* rgdispid)
{
return _tih.GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
}
// You have to implement Invoke by hand.
// However, the same techniques used for IDispEventImpl
// could be used to implement this as well.
STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr) = 0;
protected:
static _tihclass _tih;
static HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo)
{
return _tih.GetTI(lcid, ppInfo);
}
};
template <class T, const IID* piid, const GUID* plibid, WORD wMajor, WORD wMinor, class tihclass>
typename IRawDispImpl<T, piid, plibid, wMajor, wMinor, tihclass>::_tihclass
IRawDispImpl<T, piid, plibid, wMajor, wMinor, tihclass>::_tih =
{piid, plibid, wMajor, wMinor, NULL, 0, NULL, 0};
#endif // INC_DISPIMPL2