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.
 
 
 
 
 
 

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