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
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: stdclass.hxx
//
// Contents: Helper class for implementing class factories.
//
// Macros: DECLARE_CLASSFACTORY
// IMPLEMENT_CLASSFACTORY
// DECLARE_CF_UNKNOWN_METHODS
//
// Classes: CStdFactory
// CStdClassFactory
//
// Functions: DllAddRef
// DllRelease
//
// History: 25-Mar-93 JohnEls Created.
// 25-Apr-93 DavidBak Added dialog classes, message loop.
// 28-May-93 MikeSe Split out from Pharos project
// 2-Jul-93 ShannonC Split into CStdFactory and CStdClassFactory
//
// Summary of usage:
//
// 1. Declare your factory class as a subclass of CStdClassFactory
// and implement the _CreateInstance method.
//
// If your class factory supports no interfaces other than
// IClassFactory and has no instance data you can use the
// DECLARE_CLASSFACTORY macro to do declare it.
//
// Otherwise you must do the declaration by hand. Then you
// must implement the constructor for your class
// including invoking the CStdClassFactory constructor in the
// exact same way as DECLARE_CLASSFACTORY. In addition (if you
// are supporting additional interfaces ) you must implement
// the _QueryInterface method and also place an invocation
// of DECLARE_CF_UNKNOWN_METHODS in your class definition.
//
// 2. Declare a single static instance of your class, in any
// convenient source module (eg: the one containing the
// implementation of _CreateInstance).
//
// 3. You DO NOT write implementations of DllGetClassObject or
// DllCanUnloadNow; these are supplied automatically. However,
// you must place exports for these functions in your .DEF file.
// You can compose multiple classes into a single DLL simply
// by linking the appropriate modules together. You must link
// with $(COMMON)\SRC\STDCLASS\$(OBJDIR)\STDCLASS.LIB, which
// should be listed in the LIBS line of FILELIST.MK *before*
// $(CAIROLIB) [otherwise you will erroneously pick up
// DllGetClassObject from ole2base.lib].
//
// If you are developing a LOCAL_SERVER rather than an
// INPROC_SERVER you still need to link with the above library,
// but you can safely ignore the Dll functions.
//
//
//--------------------------------------------------------------------------
#ifndef _STDCLASS_HXX_
#define _STDCLASS_HXX_
#include <windows.h>
//+-------------------------------------------------------------------------
//
// Function: DllAddRef, DllRelease
//
// Synopsis: Bumps the DLL reference count
//
// Notes: These functions are used by INPROC_SERVER class implementors
// whose class factories utilise the standard mechanism, and
// hence inherit the standard implementations of DllGetClassObject
// and DllCanUnloadNow.
//
// Call these functions to manipulate the reference count for
// the DLL directly (as opposed to via AddRef/Release on a class
// object).
//
//--------------------------------------------------------------------------
STDAPI_(void) DllAddRef ( void );
STDAPI_(void) DllRelease ( void );
//+-------------------------------------------------------------------------
//
// Class: CStdClassFactory (cf)
//
// Synopsis: Standard implementation of a class factory. Class factory
// implementations should inherit this class and implement the
// method.
//
// Derivation: IClassFactory
//
// Notes: By deriving a class from this base class, you automatically
// acquire implementations of DllGetClassObject and DllCanUnloadNow.
// These can be ignored if implementing an LOCAL_SERVER.
//
//--------------------------------------------------------------------------
class CStdClassFactory: public IClassFactory
{
public:
CStdClassFactory ( REFCLSID rcls );
//
// IUnknown methods
//
STDMETHOD(QueryInterface) ( REFIID iid, void** ppv );
STDMETHOD_(ULONG,AddRef) ( void );
STDMETHOD_(ULONG,Release) ( void );
//
// IClassFactory methods
//
STDMETHOD(CreateInstance) (
IUnknown* punkOuter,
REFIID iidInterface,
void** ppunkObject );
STDMETHOD(LockServer) ( BOOL fLock );
protected:
friend HRESULT DllGetClassObject (
REFCLSID rclsid,
REFIID riid,
LPVOID FAR* ppv );
friend HRESULT DllCanUnloadNow ( void );
friend void DllAddRef ( void );
friend void DllRelease ( void );
// must be provided in subclass. Behaviour is as for CreateInstance.
STDMETHOD(_CreateInstance) (
IUnknown* punkOuter,
REFIID iidInterface,
void** ppunkObject ) PURE;
// overridden by subclass if the class supports interfaces
// other than IClassFactory. Behaviour is as for QueryInterface
// in respect of the additional interfaces. (Do not test for
// IClassFactory or IUnknown).
STDMETHOD(_QueryInterface) ( REFIID riid, void** ppv );
static ULONG _gcDllRefs;
static CStdClassFactory * _gpcfFirst;
REFCLSID _rcls;
CStdClassFactory * _pcfNext;
ULONG _cRefs;
};
//+-------------------------------------------------------------------------
//
// Macro: DECLARE_CLASSFACTORY
//
// Synopsis: Declares a class factory.
//
// Arguments: [cls] -- The class of object that the class factory creates.
//
// Note: Use this macro to declare a subclass of CStdClassFactory
// which does not support any interfaces other than IClassFactory.
// If your class object supports additional interfaces or has
// any member variables you should duplicate the behaviour
// of this macro (in respect of calling the base class
// constructor) and also:
//
// - override the _QueryInterface method
// - use the DECLARE_CF_UNKNOWN_METHODS macro within your
// derived class declaration.
//
//--------------------------------------------------------------------------
#define DECLARE_CLASSFACTORY(cls) \
\
class cls##CF : public CStdClassFactory \
{ \
public: \
cls##CF() : \
CStdClassFactory(CLSID_##cls) {}; \
protected: \
STDMETHOD(_CreateInstance)(IUnknown* pUnkOuter, \
REFIID iidInterface, \
void** ppv); \
};
//+-------------------------------------------------------------------------
//
// Macro: IMPLEMENT_CLASSFACTORY
//
// Synopsis: Implements the _CreateInstance method for a class factory.
//
// Arguments: [cls] -- The class of object that the class factory creates.
// [ctrargs] -- A bracketed list of arguments to be passed
// to the constructor of cls. Typically just ()
//
// Note: Use this macro when implementing a subclass of
// CStdClassFactory that creates objects of a class derived
// from CStdComponentObject.
//
//--------------------------------------------------------------------------
#define IMPLEMENT_CLASSFACTORY(cls,ctrargs) \
\
STDMETHODIMP cls##CF::_CreateInstance( \
IUnknown* punkOuter, \
REFIID riid, \
void** ppv) \
{ \
cls* pInstance; \
HRESULT hr; \
\
pInstance = new cls ctrargs; \
if (pInstance == NULL) \
{ \
hr = ResultFromScode(E_OUTOFMEMORY); \
} \
else \
{ \
__try \
{ \
hr = pInstance->InitInstance ( \
punkOuter, \
riid, \
ppv ); \
if ( FAILED(hr) ) \
{ \
delete pInstance; \
} \
} \
__except(EXCEPTION_EXECUTE_HANDLER) \
{ \
delete pInstance; \
hr = HRESULT_FROM_NT(GetExceptionCode()); \
} \
} \
return hr; \
}
//+-------------------------------------------------------------------------
//
// Macro: DECLARE_CF_UNKNOWN_METHODS
//
// Synopsis: Declares and implements the IUnknown methods in a derived
// class which supports interfaces other than IClassFactory.
//
// Note: Place an invocation of this macro within the declaration
// of the derived class.
//
//--------------------------------------------------------------------------
#define DECLARE_CF_UNKNOWN_METHODS \
STDMETHOD(QueryInterface) ( REFIID riid, void ** ppv) \
{ return CStdClassFactory::QueryInterface(riid,ppv);}; \
STDMETHOD_(ULONG,AddRef) ( void ) \
{ return CStdClassFactory::AddRef();}; \
STDMETHOD_(ULONG,Release) ( void ) \
{ return CStdClassFactory::Release();};
#endif // _STDCLASS_HXX_
|