285 lines
7.4 KiB
C++
285 lines
7.4 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// 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 );
|
||
|
}
|
||
|
|
||
|
|