|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: stdclass.cxx
//
// Contents: Implementation for standard base class for factory objects
//
// Classes: CStdClassFactory
//
// Functions: DllGetClassObject
// DllCanUnloadNow
//
// History: 28-May-93 MikeSe Created
// 2-Jul-93 ShannonC Split into CStdFactory and CStdClassFactory
//
//--------------------------------------------------------------------------
#include <stdclass.hxx>
//+-------------------------------------------------------------------------
//
// Global data
//
//--------------------------------------------------------------------------
CStdClassFactory * CStdClassFactory::_gpcfFirst = NULL; ULONG CStdClassFactory::_gcDllRefs = 0;
//+-------------------------------------------------------------------------
//
// Function: DllGetClassObject
//
// Synopsis: Standard implementation of entrypoint required by binder.
//
// Arguments: [rclsid] -- class id to find
// [riid] -- interface to return
// [ppv] -- output pointer
//
// Returns: E_UNEXPECTED if class not found
// Otherwise, whatever is returned by the class's QI
//
// Algorithm: Searches the linked list for the required class.
//
// Notes:
//
//--------------------------------------------------------------------------
STDAPI DllGetClassObject ( REFCLSID rclsid, REFIID riid, LPVOID FAR* ppv ) { HRESULT hr;
// Note: this doesn't need to be reentrancy protected either
// as the linked list is fixed post-init.
CStdClassFactory * pcfTry = CStdClassFactory::_gpcfFirst;
while ( pcfTry != NULL && !IsEqualCLSID ( rclsid, pcfTry->_rcls ) ) { pcfTry = pcfTry->_pcfNext; }
if ( pcfTry != NULL ) { // Note: QueryInterface is supposed (required) to do an AddRef
// so we don't need to directly.
hr = pcfTry->QueryInterface ( riid, ppv ); } else { hr = E_UNEXPECTED; *ppv = NULL; }
return hr; }
//+-------------------------------------------------------------------------
//
// Function: DllCanUnloadNow
//
// Synopsis: Standard entrypoint required by binder
//
// Returns: S_OK if DLL reference count is zero
// S_FALSE otherwise
//
// Notes:
//
//--------------------------------------------------------------------------
STDAPI DllCanUnloadNow () { return (CStdClassFactory::_gcDllRefs==0)? S_OK: S_FALSE; }
//+-------------------------------------------------------------------------
//
// Function: DllAddRef
//
// Synopsis: Allows incrementing the DLL reference count without
// AddRef'ing a specific class object.
//
// Notes:
//
//--------------------------------------------------------------------------
STDAPI_(void) DllAddRef () { InterlockedIncrement ( (LONG*)&CStdClassFactory::_gcDllRefs ); }
//+-------------------------------------------------------------------------
//
// Function: DllRelease
//
// Synopsis: Allows decrementing the DLL reference count without
// Release'ing a specific class object.
//
// Notes:
//
//--------------------------------------------------------------------------
STDAPI_(void) DllRelease () { InterlockedDecrement ( (LONG*)&CStdClassFactory::_gcDllRefs ); }
//+-------------------------------------------------------------------------
//
// Member: CStdClassFactory::CStdClassFactory
//
// Synopsis: Constructor
//
// Effects: Initialises member variables
// Adds object to global linked list.
//
// Arguments: [rcls] -- class id of derived class
// [punk] -- controlling IUnknown of derived class
//
// Notes: Do not make this function inline, even though it appears
// trivial, since it is necessary to force the static library
// to be pulled in.
//
//--------------------------------------------------------------------------
CStdClassFactory::CStdClassFactory ( REFCLSID rcls ) :_rcls(rcls), _cRefs(1) // DaveStr - 11/3/94 - Ole32 requires (_cRefs >= 1)
{ // Note: the following is not protected against reentrancy, since it
// is assumed to take place prior to LibMain/main/WinMain.
_pcfNext = _gpcfFirst; _gpcfFirst = this; }
//+-------------------------------------------------------------------------
//
// Method: CStdClassFactory::LockServer
//
// Synopsis: ???
//
// Derivation: IClassFactory
//
//--------------------------------------------------------------------------
STDMETHODIMP CStdClassFactory::LockServer ( BOOL fLock ) { return S_OK; }
//+-------------------------------------------------------------------------
//
// Method: CStdClassFactory::CreateInstance, public
//
// Synopsis: Creates a new instance and returns the requested interface.
// The returned object has a reference count of 1.
//
// Derivation: IClassFactory
//
// Note: Calls the pure virtual method _CreateInstance, which must
// be implemented by subclasses.
//
//--------------------------------------------------------------------------
STDMETHODIMP CStdClassFactory::CreateInstance ( IUnknown* punkOuter, REFIID iidInterface, void** ppv ) { return _CreateInstance ( punkOuter, iidInterface, ppv ); }
//+-------------------------------------------------------------------------
//
// Method: CStdClassFactory::QueryInterface, public
//
// Synopsis: Query for an interface on the class factory.
//
// Derivation: IUnknown
//
//--------------------------------------------------------------------------
STDMETHODIMP CStdClassFactory::QueryInterface ( REFIID iid, void * * ppv ) { HRESULT hr;
if ((IsEqualIID(iid, IID_IUnknown)) || (IsEqualIID(iid, IID_IClassFactory))) { *ppv = (IClassFactory*)this; AddRef(); hr = S_OK; } else { // Make sure we null the return value in case of error
*ppv = NULL; hr = _QueryInterface ( iid, ppv ); }
return hr; }
//+-------------------------------------------------------------------------
//
// Method: CStdClassFactory::_QueryInterface, protected
//
// Synopsis: Default private QI, normally overridden in subclass
//
// Derivation: IUnknown
//
//--------------------------------------------------------------------------
STDMETHODIMP CStdClassFactory::_QueryInterface ( REFIID iid, void * * ppv ) { return E_NOINTERFACE; }
//+-------------------------------------------------------------------------
//
// Method: CStdClassFactory::AddRef, public
//
// Synopsis: Increment DLL and object reference counts
//
// Derivation: IUnknown
//
//--------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CStdClassFactory::AddRef () { InterlockedIncrement ( (LONG*)&_gcDllRefs ); return (ULONG)InterlockedIncrement ( (LONG*)&_cRefs ); }
//+-------------------------------------------------------------------------
//
// Method: CStdClassFactory::Release, public
//
// Synopsis: Decrement DLL and object reference counts
//
// Derivation: IUnknown
//
//--------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CStdClassFactory::Release () { InterlockedDecrement ( (LONG*)&_gcDllRefs ); return (ULONG)InterlockedDecrement ( (LONG*)&_cRefs ); }
|