Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

210 lines
5.7 KiB

// Copyright (c) 2000-2001 Microsoft Corporation, All Rights Reserved
// Factory.cpp
#include "precomp.h"
#include <iostream.h>
#include <objbase.h>
#include "CUnknown.h"
#include "factory.h"
#include "Registry.h"
// Set static members
LONG CFactory::s_cServerLocks = 0L ; // Count of locks
HMODULE CFactory::s_hModule = NULL ; // DLL module handle
extern CFactoryData g_FactoryDataArray[];
/*****************************************************************************/
// Class factory constructor
/*****************************************************************************/
CFactory::CFactory(const CFactoryData* pFactoryData)
: m_cRef(1)
{
m_pFactoryData = pFactoryData ;
LockServer(TRUE);
}
/*****************************************************************************/
// Class factory IUnknown implementation
/*****************************************************************************/
STDMETHODIMP CFactory::QueryInterface(const IID& iid, void** ppv)
{
if ((iid == IID_IUnknown) || (iid == IID_IClassFactory))
{
*ppv = static_cast<IClassFactory*>(this) ;
}
else
{
*ppv = NULL ;
return E_NOINTERFACE ;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef() ;
return S_OK ;
}
STDMETHODIMP_(ULONG) CFactory::AddRef()
{
return InterlockedIncrement(&m_cRef) ;
}
STDMETHODIMP_(ULONG) CFactory::Release()
{
if (InterlockedDecrement(&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;
// Cannot aggregate.
if (pUnknownOuter != NULL)
{
hr = CLASS_E_NOAGGREGATION;
}
if(SUCCEEDED(hr))
{
// Create component using the specific component's version of CreateInstance.
CUnknown* pNewComponent ;
hr = m_pFactoryData->CreateInstance(&pNewComponent) ;
if(SUCCEEDED(hr))
{
// Initialize the component
hr = pNewComponent->Init();
if(SUCCEEDED(hr))
{
// Get the requested interface.
hr = pNewComponent->QueryInterface(iid, ppv);
}
// Release the IUnknown pointer (the new AND the QI incremented the refcount on SUC.
// (If QueryInterface failed, component will delete itself.)
pNewComponent->Release();
}
}
return hr ;
}
/*****************************************************************************/
// Lock server
/*****************************************************************************/
STDMETHODIMP CFactory::LockServer(BOOL bLock)
{
if (bLock)
{
InterlockedIncrement(&s_cServerLocks) ;
}
else
{
InterlockedDecrement(&s_cServerLocks) ;
}
return S_OK ;
}
/*****************************************************************************/
// GetClassObject - Create a class factory based on a CLSID.
/*****************************************************************************/
HRESULT CFactory::GetClassObject(const CLSID& clsid,
const IID& iid,
void** ppv)
{
HRESULT hr = S_OK;
if ((iid != IID_IUnknown) && (iid != IID_IClassFactory))
{
hr = E_NOINTERFACE ;
}
if(SUCCEEDED(hr))
{
// Traverse the array of data looking for this class ID.
for (int i = 0; i < g_cFactoryDataEntries; i++)
{
if(g_FactoryDataArray[i].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.
const CFactoryData* pData = &g_FactoryDataArray[i] ;
CFactory* pFactory = new CFactory(pData);
if (pFactory == NULL)
{
hr = E_OUTOFMEMORY ;
}
else
{
// Get requested interface.
HRESULT hr = pFactory->QueryInterface(iid, ppv);
pFactory->Release();
}
break;
}
}
if(i == g_cFactoryDataEntries)
{
hr = CLASS_E_CLASSNOTAVAILABLE;
}
}
return hr;
}
/*****************************************************************************/
// Register all components.
/*****************************************************************************/
HRESULT CFactory::RegisterAll()
{
for(int i = 0 ; i < g_cFactoryDataEntries ; i++)
{
RegisterServer(s_hModule,
*(g_FactoryDataArray[i].m_pCLSID),
g_FactoryDataArray[i].m_RegistryName,
g_FactoryDataArray[i].m_szVerIndProgID,
g_FactoryDataArray[i].m_szProgID) ;
}
return S_OK ;
}
/*****************************************************************************/
// Un-register all components
/*****************************************************************************/
HRESULT CFactory::UnregisterAll()
{
for(int i = 0 ; i < g_cFactoryDataEntries ; i++)
{
UnregisterServer(*(g_FactoryDataArray[i].m_pCLSID),
g_FactoryDataArray[i].m_szVerIndProgID,
g_FactoryDataArray[i].m_szProgID) ;
}
return S_OK ;
}
/*****************************************************************************/
// Determine if the component can be unloaded.
/*****************************************************************************/
HRESULT CFactory::CanUnloadNow()
{
if (CUnknown::ActiveComponents() || IsLocked())
{
return S_FALSE ;
}
else
{
return S_OK ;
}
}