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.
379 lines
13 KiB
379 lines
13 KiB
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// FactoryRouter.cpp -- Generic Com Class factory class
|
|
//
|
|
// Copyright (c) 2000-2001 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#include "precomp.h"
|
|
#include "dllmain.h"
|
|
#include "cautolock.h"
|
|
|
|
using namespace std;
|
|
#include "FactoryRouter.h"
|
|
#define DUPLICATE_RELEASE FALSE
|
|
|
|
extern CFactoryRouterData g_FactoryRouterData;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//*************************************************************************************************************
|
|
// Utility functions
|
|
//*************************************************************************************************************
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void ClsToString( CHString &a_chsClsId, REFGUID a_rClsId )
|
|
{
|
|
WCHAR wcID[128] ;
|
|
StringFromGUID2( a_rClsId, wcID, 128 ) ;
|
|
|
|
a_chsClsId = wcID ;
|
|
|
|
a_chsClsId.MakeUpper() ;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//*************************************************************************************************************
|
|
// The CFactoryRouter Class
|
|
//*************************************************************************************************************
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
CFactoryRouter::CFactoryRouter(REFGUID a_rClsId, LPCWSTR a_pClassName):m_Register( 0 )
|
|
{
|
|
m_ClsId = a_rClsId ;
|
|
m_sDescription = a_pClassName ;
|
|
g_FactoryRouterData.AddToMap( a_rClsId,this ) ;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
CFactoryRouter::~CFactoryRouter()
|
|
{
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_( ULONG ) CFactoryRouter::AddRef()
|
|
{
|
|
return g_FactoryRouterData.AddRef();
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_(ULONG) CFactoryRouter::Release()
|
|
{
|
|
ULONG nRet = g_FactoryRouterData.Release();
|
|
if ( nRet == 0 )
|
|
{
|
|
try
|
|
{
|
|
LogMessage(L"CFactoryRouter Ref Count = 0");
|
|
}
|
|
catch ( ... )
|
|
{
|
|
}
|
|
// delete this; Can't delete this, because these hang around the whole time the dll is loaded
|
|
// the ptr to this factory is deleted upon dll being detached
|
|
}
|
|
else if (nRet > 0x80000000)
|
|
{
|
|
ASSERT_BREAK(DUPLICATE_RELEASE);
|
|
LogErrorMessage(L"Duplicate CFactoryRouter Release()");
|
|
}
|
|
return nRet;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CFactoryRouter::QueryInterface( REFIID a_riid, PPVOID a_ppv )
|
|
{
|
|
*a_ppv = NULL ;
|
|
|
|
if ( IID_IUnknown == a_riid || IID_IClassFactory == a_riid )
|
|
{
|
|
*a_ppv = this ;
|
|
}
|
|
|
|
if ( NULL != *a_ppv )
|
|
{
|
|
AddRef() ;
|
|
return NOERROR ;
|
|
}
|
|
return ResultFromScode( E_NOINTERFACE ) ;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CFactoryRouter::LockServer
|
|
//
|
|
// Purpose:
|
|
// Increments or decrements the lock count of the DLL. If the
|
|
// lock count goes to zero and there are no objects, the DLL
|
|
// is allowed to unload. See DllCanUnloadNow.
|
|
//
|
|
// Parameters:
|
|
// fLock BOOL specifying whether to increment or
|
|
// decrement the lock count.
|
|
//
|
|
// Return Value:
|
|
// HRESULT NOERROR always.
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CFactoryRouter::LockServer( BOOL a_fLock )
|
|
{
|
|
if ( a_fLock )
|
|
{
|
|
g_FactoryRouterData.AddLock();
|
|
}
|
|
else
|
|
{
|
|
g_FactoryRouterData.ReleaseLock();
|
|
}
|
|
return S_OK ;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CFactoryRouter::CreateInstance
|
|
//
|
|
// Purpose: Instantiates a Event Provider object returning an interface pointer.
|
|
//
|
|
// Parameters:
|
|
// pUnkOuter LPUNKNOWN to the controlling IUnknown if we are
|
|
// being used in an aggregation.
|
|
// riid REFIID identifying the interface the caller
|
|
// desires to have for the new object.
|
|
// ppvObj PPVOID in which to store the desired
|
|
// interface pointer for the new object.
|
|
//
|
|
// Return Value:
|
|
// HRESULT NOERROR if successful, otherwise E_NOINTERFACE
|
|
// if we cannot support the requested interface.
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CFactoryRouter::CreateInstance (LPUNKNOWN a_pUnkOuter ,REFIID a_riid ,LPVOID FAR *a_ppvObject)
|
|
{
|
|
HRESULT t_status = S_OK ;
|
|
if ( a_pUnkOuter )
|
|
{
|
|
t_status = CLASS_E_NOAGGREGATION ;
|
|
}
|
|
else
|
|
{
|
|
// resolve request to whomever derived from us
|
|
IUnknown *t_lpunk = (IUnknown *) CreateInstance( a_riid, a_ppvObject ) ;
|
|
|
|
if ( t_lpunk == NULL )
|
|
{
|
|
t_status = E_OUTOFMEMORY ;
|
|
}
|
|
else
|
|
{
|
|
// declare interface support
|
|
t_status = t_lpunk->QueryInterface ( a_riid , a_ppvObject ) ;
|
|
if ( FAILED ( t_status ) )
|
|
{
|
|
delete t_lpunk ;
|
|
}
|
|
}
|
|
}
|
|
return t_status ;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
REFGUID CFactoryRouter::GetClsId()
|
|
{
|
|
return m_ClsId;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
LPCWSTR CFactoryRouter::GetClassDescription()
|
|
{
|
|
return (LPCWSTR)m_sDescription;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
DWORD CFactoryRouter::GetRegister()
|
|
{
|
|
return m_Register;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CFactoryRouter::SetRegister( DWORD a_dwRegister )
|
|
{
|
|
m_Register = a_dwRegister;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//*************************************************************************************************************
|
|
//
|
|
//*************************************************************************************************************
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
CFactoryRouterData::CFactoryRouterData()
|
|
{
|
|
s_LocksInProgress = s_ObjectsInProgress = m_ReferenceCount = 0;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
CFactoryRouterData::~CFactoryRouterData()
|
|
{
|
|
CAutoLock cal( m_cs);
|
|
LogMessage(L"************ Clearing the FactoryRouterMap");
|
|
|
|
mg_oFactoryMap.clear() ;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CFactoryRouterData::AddToMap( REFGUID a_rClsId, CFactoryRouter * pFactory )
|
|
{
|
|
CHString t_chsClsId ;
|
|
ClsToString( t_chsClsId, a_rClsId ) ;
|
|
CAutoLock cal( m_cs);
|
|
|
|
LogMessage2(L"************ Adding to map %s", (WCHAR*)(const WCHAR*) t_chsClsId);
|
|
// map class and instance
|
|
mg_oFactoryMap[ t_chsClsId ] = pFactory ;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/*void CFactoryRouterData::RemoveFromMap( REFGUID a_rClsId )
|
|
{
|
|
CHString t_chsClsId ;
|
|
ClsToString( t_chsClsId, a_rClsId ) ;
|
|
CAutoLock cal( m_cs);
|
|
mg_oFactoryMap.erase( t_chsClsId ) ;
|
|
}*/
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
BOOL CFactoryRouterData::DllCanUnloadNow()
|
|
{
|
|
return !(s_ObjectsInProgress || s_LocksInProgress) ;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CFactoryRouterData::AddLock()
|
|
{
|
|
InterlockedIncrement ( &s_LocksInProgress ) ;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CFactoryRouterData::ReleaseLock()
|
|
{
|
|
InterlockedDecrement ( &s_LocksInProgress ) ;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_( ULONG ) CFactoryRouterData::AddRef()
|
|
{
|
|
InterlockedIncrement ( &s_ObjectsInProgress ) ;
|
|
return InterlockedIncrement ( &m_ReferenceCount ) ;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_(ULONG) CFactoryRouterData::Release()
|
|
{
|
|
InterlockedDecrement ( &s_ObjectsInProgress ) ;
|
|
return InterlockedDecrement( &m_ReferenceCount ) ;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CFactoryRouterData::DllGetClassObject( REFCLSID a_rclsid, REFIID a_riid, PPVOID a_ppv )
|
|
{
|
|
HRESULT t_hResult = E_FAIL ;
|
|
CHString t_chsClsId ;
|
|
Factory_Map::iterator t_FactoryIter;
|
|
|
|
ClsToString( t_chsClsId, a_rclsid ) ;
|
|
CAutoLock cal(m_cs);
|
|
|
|
LogMessage2(L"************ Looking for %s in DllGetClassObject", (WCHAR*)(const WCHAR*) t_chsClsId);
|
|
|
|
t_FactoryIter = mg_oFactoryMap.find( t_chsClsId ) ;
|
|
if( t_FactoryIter != mg_oFactoryMap.end() )
|
|
{
|
|
t_hResult = t_FactoryIter->second->QueryInterface( a_riid, a_ppv ) ;
|
|
}
|
|
LogMessage2(L"************ DllGetClassObject QueryInterface returned %x",t_hResult);
|
|
|
|
return t_hResult ;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CFactoryRouterData::DllRegisterServer()
|
|
{
|
|
HRESULT t_hResult = NOERROR;
|
|
CAutoLock cal(m_cs);
|
|
|
|
Factory_Map::iterator t_FactoryIter ;
|
|
t_FactoryIter = mg_oFactoryMap.begin() ;
|
|
|
|
while( t_FactoryIter != mg_oFactoryMap.end() )
|
|
{
|
|
bstr_t t_bstrPreface( "WMI instrumentation: " ) ;
|
|
bstr_t t_bstrClassDescription( t_FactoryIter->second->GetClassDescription() ) ;
|
|
|
|
t_bstrPreface += t_bstrClassDescription ;
|
|
t_hResult = ::RegisterServer( t_bstrPreface, t_FactoryIter->second->GetClsId() ) ;
|
|
|
|
if( NOERROR != t_hResult )
|
|
{
|
|
break ;
|
|
}
|
|
|
|
++t_FactoryIter ;
|
|
}
|
|
return t_hResult ;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CFactoryRouterData::DllUnregisterServer()
|
|
{
|
|
HRESULT t_hResult = NOERROR ;
|
|
CAutoLock cal(m_cs);
|
|
|
|
Factory_Map::iterator t_FactoryIter ;
|
|
|
|
t_FactoryIter = mg_oFactoryMap.begin() ;
|
|
|
|
while( t_FactoryIter != mg_oFactoryMap.end() )
|
|
{
|
|
t_hResult = ::UnregisterServer( t_FactoryIter->second->GetClsId() ) ;
|
|
|
|
if( NOERROR != t_hResult )
|
|
{
|
|
break ;
|
|
}
|
|
|
|
++t_FactoryIter ;
|
|
}
|
|
return t_hResult ;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CFactoryRouterData::InitComServer()
|
|
{
|
|
HRESULT t_hResult = S_OK ;
|
|
CAutoLock cal(m_cs);
|
|
|
|
Factory_Map::iterator t_FactoryIter ;
|
|
|
|
t_FactoryIter = mg_oFactoryMap.begin() ;
|
|
|
|
while( t_FactoryIter != mg_oFactoryMap.end() )
|
|
{
|
|
DWORD t_ClassContext = CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER ;
|
|
DWORD t_Flags = REGCLS_MULTIPLEUSE ;
|
|
DWORD t_dwRegister = 0 ;
|
|
|
|
t_hResult = CoRegisterClassObject(t_FactoryIter->second->GetClsId(),t_FactoryIter->second,t_ClassContext,t_Flags,&t_dwRegister);
|
|
if( NOERROR != t_hResult )
|
|
{
|
|
break ;
|
|
}
|
|
|
|
t_FactoryIter->second->SetRegister( t_dwRegister ) ;
|
|
++t_FactoryIter ;
|
|
}
|
|
return t_hResult ;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CFactoryRouterData::UninitComServer()
|
|
{
|
|
HRESULT t_hResult = S_OK ;
|
|
CAutoLock cal( m_cs);
|
|
|
|
Factory_Map::iterator t_FactoryIter ;
|
|
t_FactoryIter = mg_oFactoryMap.begin() ;
|
|
|
|
while( t_FactoryIter != mg_oFactoryMap.end() )
|
|
{
|
|
DWORD t_ClassContext = CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER ;
|
|
DWORD t_Flags = REGCLS_MULTIPLEUSE ;
|
|
DWORD t_dwRegister = t_FactoryIter->second->GetRegister() ;
|
|
|
|
if( t_dwRegister )
|
|
{
|
|
t_hResult = CoRevokeClassObject ( t_dwRegister ) ;
|
|
t_FactoryIter->second->SetRegister( 0 ) ;
|
|
}
|
|
|
|
if( NOERROR != t_hResult )
|
|
{
|
|
break ;
|
|
}
|
|
|
|
++t_FactoryIter ;
|
|
}
|
|
|
|
return t_hResult ;
|
|
}
|