/////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // 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 ; }