windows-nt/Source/XPSP1/NT/com/published/inc/stdclass.wxx
2020-09-26 16:20:57 +08:00

268 lines
10 KiB
Plaintext

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// 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_