Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

329 lines
9.2 KiB

///////////////////////////////////////////////////////////
//
// CFactory
// - Base class for reusing a single class factory for
// all components in a DLL
//
#include <objbase.h>
#include <fusenetincludes.h>
#include "CFactory.h"
LONG CFactory::s_cServerLocks = 0 ; // Count of locks
HMODULE CFactory::s_hModule = NULL ; // DLL module handle
#ifdef _OUTPROC_SERVER_
DWORD CFactory::s_dwThreadID = 0 ;
#endif
// ---------------------------------------------------------------------------
// ctor
// ---------------------------------------------------------------------------
CFactory::CFactory(const CFactoryData* pFactoryData)
: m_cRef(1)
{
m_pFactoryData = pFactoryData ;
}
// ---------------------------------------------------------------------------
// dtor
// ---------------------------------------------------------------------------
CFactory::~CFactory()
{}
// IUnknown implementation
// ---------------------------------------------------------------------------
// QueryInterface
// ---------------------------------------------------------------------------
STDMETHODIMP CFactory::QueryInterface(REFIID iid, void** ppv)
{
IUnknown* pI ;
if ((iid == IID_IUnknown) || (iid == IID_IClassFactory))
{
pI = this ;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
pI->AddRef() ;
*ppv = pI ;
return S_OK;
}
// ---------------------------------------------------------------------------
// AddRef
// ---------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CFactory::AddRef()
{
return ::InterlockedIncrement((LONG*) &m_cRef) ;
}
// ---------------------------------------------------------------------------
// Release
// ---------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CFactory::Release()
{
if (::InterlockedDecrement((LONG*) &m_cRef) == 0)
{
delete this;
return 0 ;
}
return m_cRef;
}
// ---------------------------------------------------------------------------
// IClassFactory implementation
// ---------------------------------------------------------------------------
STDMETHODIMP CFactory::CreateInstance(IUnknown* pUnknownOuter,
const IID& iid, void** ppv)
{
HRESULT hr = S_OK;
MAKE_ERROR_MACROS_STATIC(hr);
CUnknown* pNewComponent = NULL;
// Aggregate only if the requested IID is IID_IUnknown.
if ((pUnknownOuter != NULL) && (iid != IID_IUnknown))
{
hr = CLASS_E_NOAGGREGATION ;
goto exit;
}
// Create the component.
IF_FAILED_EXIT(m_pFactoryData->CreateInstance(pUnknownOuter, &pNewComponent));
// Initialize the component.
IF_FAILED_EXIT(pNewComponent->Init());
// Get the requested interface.
IF_FAILED_EXIT(pNewComponent->QueryInterface(iid, ppv));
exit:
// Release the reference held by the class factory.
SAFERELEASE(pNewComponent);
return hr ;
}
// ---------------------------------------------------------------------------
// LockServer
// ---------------------------------------------------------------------------
STDMETHODIMP CFactory::LockServer(BOOL bLock)
{
if (bLock)
{
::InterlockedIncrement(&s_cServerLocks) ;
}
else
{
::InterlockedDecrement(&s_cServerLocks) ;
}
// If this is an out-of-proc server, check to see
// whether we should shut down.
CloseExe() ; //@local
return S_OK ;
}
// -------------------Support Common to Inproc/OutProc--------------------------
// ---------------------------------------------------------------------------
// Determine if the component can be unloaded.
// ---------------------------------------------------------------------------
HRESULT CFactory::CanUnloadNow()
{
if (CUnknown::ActiveComponents() || IsLocked())
{
return S_FALSE ;
}
else
{
return S_OK ;
}
}
// --------------------------InProc Server support-------------------------------
#ifndef _OUTPROC_SERVER_
// ---------------------------------------------------------------------------
// GetClassObject
// ---------------------------------------------------------------------------
HRESULT CFactory::GetClassObject(const CLSID& clsid,
const IID& iid,
void** ppv)
{
HRESULT hr = S_OK;
MAKE_ERROR_MACROS_STATIC(hr);
BOOL fFound = FALSE;
IF_FALSE_EXIT(((iid == IID_IUnknown) || (iid == IID_IClassFactory)), E_NOINTERFACE);
// Traverse the array of data looking for this class ID.
for (int i = 0; i < g_cFactoryDataEntries; i++)
{
const CFactoryData* pData = &g_FactoryDataArray[i] ;
if (pData->IsClassID(clsid))
{
// Found the ClassID in the array of components we can
// create. So create a class factory for this component.
// Pass the CFactoryData structure to the class factory
// so that it knows what kind of components to create.
*ppv = (IUnknown*) new CFactory(pData) ;
IF_ALLOC_FAILED_EXIT(*ppv);
fFound = TRUE;
}
}
hr = fFound ? NOERROR : CLASS_E_CLASSNOTAVAILABLE;
exit:
return hr;
}
// ---------------------------------------------------------------------------
// DllCanUnloadNow
// ---------------------------------------------------------------------------
STDAPI DllCanUnloadNow()
{
return CFactory::CanUnloadNow() ;
}
// ---------------------------------------------------------------------------
// DllGetClassObject
// ---------------------------------------------------------------------------
STDAPI DllGetClassObject(const CLSID& clsid,
const IID& iid,
void** ppv)
{
return CFactory::GetClassObject(clsid, iid, ppv) ;
}
// ---------------------------------------------------------------------------
// DllRegisterServer
// ---------------------------------------------------------------------------
STDAPI DllRegisterServer()
{
return CFactory::RegisterAll() ;
}
// ---------------------------------------------------------------------------
// DllUnregisterServer
// ---------------------------------------------------------------------------
STDAPI DllUnregisterServer()
{
return CFactory::UnregisterAll() ;
}
// ---------------------------------------------------------------------------
// DllMain
// ---------------------------------------------------------------------------
BOOL APIENTRY DllMain(HANDLE hModule,
DWORD dwReason, void* lpReserved )
{
if (dwReason == DLL_PROCESS_ATTACH)
{
CFactory::s_hModule = (HMODULE) hModule ;
}
return TRUE ;
}
// -------------------------OutProc server support-----------------------------
#else
// ---------------------------------------------------------------------------
// Start factories
// ---------------------------------------------------------------------------
HRESULT CFactory::StartFactories()
{
HRESULT hr = S_OK;
MAKE_ERROR_MACROS_STATIC(hr);
CFactoryData* pStart = &g_FactoryDataArray[0] ;
const CFactoryData* pEnd =
&g_FactoryDataArray[g_cFactoryDataEntries - 1] ;
IClassFactory* pIFactory = NULL;
for(CFactoryData* pData = pStart ; pData <= pEnd ; pData++)
{
// Initialize the class factory pointer and cookie.
pData->m_pIClassFactory = NULL ;
pData->m_dwRegister = NULL ;
// Create the class factory for this component.
pIFactory = new CFactory(pData) ;
IF_ALLOC_FAILED_EXIT(pIFactory);
// Register the class factory.
DWORD dwRegister ;
hr = ::CoRegisterClassObject(
*pData->m_pCLSID,
static_cast<IUnknown*>(pIFactory),
CLSCTX_LOCAL_SERVER,
REGCLS_MULTIPLEUSE,
// REGCLS_MULTI_SEPARATE, //@Multi
&dwRegister) ;
IF_FAILED_EXIT(hr);
// Set the data.
pData->m_pIClassFactory = pIFactory ;
pData->m_dwRegister = dwRegister ;
}
exit:
if (FAILED(hr))
SAFERELEASE(pIFactory);
return hr;
}
// ---------------------------------------------------------------------------
// Stop factories
// ---------------------------------------------------------------------------
void CFactory::StopFactories()
{
CFactoryData* pStart = &g_FactoryDataArray[0] ;
const CFactoryData* pEnd =
&g_FactoryDataArray[g_cFactoryDataEntries - 1] ;
for (CFactoryData* pData = pStart ; pData <= pEnd ; pData++)
{
// Get the magic cookie and stop the factory from running.
DWORD dwRegister = pData->m_dwRegister ;
if (dwRegister != 0)
{
::CoRevokeClassObject(dwRegister) ;
}
// Release the class factory.
IClassFactory* pIFactory = pData->m_pIClassFactory ;
SAFERELEASE(pIFactory);
}
}
#endif //_OUTPROC_SERVER_