////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1999-2002 Microsoft Corporation // // Module Name: // ServiceMgr.cpp // // Description: // Service Manager implementation. // // Documentation: // Yes. // // Maintained By: // Galen Barbee (GalenB) 22-NOV-1999 // ////////////////////////////////////////////////////////////////////////////// #include "Pch.h" // #include "ServiceMgr.h" - already included in DLL.H DEFINE_THISCLASS("CServiceManager") #define CServiceManager CServiceManager #define LPTHISCLASS CServiceManager * //**************************************************************************** // // Protected Global // //**************************************************************************** IServiceProvider * g_pspServiceManager = NULL; //**************************************************************************** // // Class Static Variables // //**************************************************************************** CRITICAL_SECTION CServiceManager::sm_cs; //**************************************************************************** // // Constructor / Destructor // //**************************************************************************** ////////////////////////////////////////////////////////////////////////////// // // HRESULT // CServiceManager::S_HrCreateInstance( // IUnknown ** ppunkOut // ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CServiceManager::S_HrCreateInstance( IUnknown ** ppunkOut ) { TraceFunc( "" ); HRESULT hr = S_OK; LPTHISCLASS pthis = NULL; EnterCriticalSection( &sm_cs ); Assert( ppunkOut != NULL ); if ( ppunkOut == NULL ) { hr = THR( E_POINTER ); goto Cleanup; } // if: if ( g_pspServiceManager != NULL ) { hr = THR( g_pspServiceManager->TypeSafeQI( IUnknown, ppunkOut ) ); goto Cleanup; } // if: assign new service manager pthis = new CServiceManager(); if ( pthis == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } // if: // // Can't hold CS in Init. // LeaveCriticalSection( &sm_cs ); hr = THR( pthis->HrInit() ); EnterCriticalSection( &sm_cs ); if ( FAILED( hr ) ) { goto Cleanup; } // if: Assert( g_pspServiceManager == NULL ); // No REF - or we'll never die! g_pspServiceManager = static_cast< IServiceProvider * >( pthis ); TraceMoveToMemoryList( g_pspServiceManager, g_GlobalMemoryList ); hr = THR( g_pspServiceManager->TypeSafeQI( IUnknown, ppunkOut ) ); if ( FAILED( hr ) ) { goto Cleanup; } Cleanup: if ( pthis != NULL ) { pthis->Release(); } // if: LeaveCriticalSection( &sm_cs ); HRETURN( hr ); } //*** CServiceManager::S_HrCreateInstance ////////////////////////////////////////////////////////////////////////////// //++ // // HRESULT // CServiceManager::S_HrGetManagerPointer( IServiceProvider ** ppspOut ) // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT CServiceManager::S_HrGetManagerPointer( IServiceProvider ** ppspOut ) { TraceFunc( "ppspOut" ); HRESULT hr = HRESULT_FROM_WIN32( ERROR_PROCESS_ABORTED ); EnterCriticalSection( &sm_cs ); if ( g_pspServiceManager != NULL ) { g_pspServiceManager->AddRef(); *ppspOut = g_pspServiceManager; hr = S_OK; } // if: valid service manager else { // // KB 18-JUN-2001 DavidP // Don't wrap this with THR because it is expected to return // E_POINTER on the very first call. // hr = E_POINTER; } // else: no pointer LeaveCriticalSection( &sm_cs ); HRETURN ( hr ); } //*** CServiceManager::S_HrGetManagerPointer ////////////////////////////////////////////////////////////////////////////// //++ // // CServiceManager::S_HrProcessInitialize // // Description: // Do process initialization by intializing the critical section. // // Return Value: // S_OK // // Remarks: // This function is called from DllMain() when DLL_PROCESS_ATTACH // is sent. This function is needed because we need a known point // to create a critical section that synchronizes the creation and // deletion of this object. Given this object's life cycle and // static creator function it is possible to have a race when this // object is destrying itself with the static creator function. // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT CServiceManager::S_HrProcessInitialize( void ) { TraceFunc( "" ); HRESULT hr = S_OK; if ( InitializeCriticalSectionAndSpinCount( &sm_cs, RECOMMENDED_SPIN_COUNT ) == 0 ) { DWORD scLastError = TW32( GetLastError() ); hr = HRESULT_FROM_WIN32( scLastError ); } HRETURN( hr ); } //*** CServiceManager::S_HrProcessInitialize ////////////////////////////////////////////////////////////////////////////// //++ // // CServiceManager::S_HrProcessUninitialize // // Description: // Do process uninitialization by deleting the critical section. // // Return Value: // S_OK // // Remarks: // Delete the critical section that sychronizes the creation and // deletion code. // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT CServiceManager::S_HrProcessUninitialize( void ) { TraceFunc( "" ); HRESULT hr = S_OK; DeleteCriticalSection( &sm_cs ); HRETURN( hr ); } //*** CServiceManager::S_HrProcessUninitialize ////////////////////////////////////////////////////////////////////////////// // // CServiceManager::CServiceManager // ////////////////////////////////////////////////////////////////////////////// CServiceManager::CServiceManager( void ) : m_cRef( 1 ) { TraceFunc( "" ); InterlockedIncrement( &g_cObjects ); TraceFuncExit(); } //*** CServiceManager::CServiceManager ////////////////////////////////////////////////////////////////////////////// // // HRESULT // CServiceManager::HrInit // ////////////////////////////////////////////////////////////////////////////// HRESULT CServiceManager::HrInit( void ) { TraceFunc( "" ); HRESULT hr; ITaskManager * ptm = NULL; IDoTask * pdt = NULL; IObjectManager * pom = NULL; INotificationManager * pnm = NULL; IConnectionManager * pcm = NULL; ILogManager * plm = NULL; // IUnknown Assert( m_cRef == 1 ); // IServiceProvider Assert( m_dwLogManagerCookie == 0 ); Assert( m_dwConnectionManagerCookie == 0 ); Assert( m_dwNotificationManagerCookie == 0 ); Assert( m_dwObjectManagerCookie == 0 ); Assert( m_dwTaskManagerCookie == 0 ); Assert( m_pgit == NULL ); // IServiceProvider stuff hr = THR( HrCoCreateInternalInstance( CLSID_ObjectManager, NULL, CLSCTX_INPROC_SERVER, TypeSafeParams( IObjectManager, &pom ) ) ); if ( FAILED( hr ) ) { goto Cleanup; } hr = THR( HrCoCreateInternalInstance( CLSID_TaskManager, NULL, CLSCTX_INPROC_SERVER, TypeSafeParams( ITaskManager, &ptm ) ) ); if ( FAILED( hr ) ) { goto Cleanup; } hr = THR( HrCoCreateInternalInstance( CLSID_NotificationManager, NULL, CLSCTX_INPROC_SERVER, TypeSafeParams( INotificationManager, &pnm ) ) ); if ( FAILED( hr ) ) { goto Cleanup; } hr = THR( HrCoCreateInternalInstance( CLSID_ClusterConnectionManager, NULL, CLSCTX_INPROC_SERVER, TypeSafeParams( IConnectionManager, &pcm ) ) ); if ( FAILED( hr ) ) { goto Cleanup; } hr = THR( HrCoCreateInternalInstance( CLSID_LogManager, NULL, CLSCTX_INPROC_SERVER, TypeSafeParams( ILogManager, &plm ) ) ); if ( FAILED( hr ) ) { goto Cleanup; } // // Store the interfaces in the GIT. // hr = THR( CoCreateInstance( CLSID_StdGlobalInterfaceTable , NULL , CLSCTX_INPROC_SERVER , IID_IGlobalInterfaceTable , reinterpret_cast< void ** >( &m_pgit ) ) ); if ( FAILED( hr ) ) { goto Cleanup; } hr = THR( m_pgit->RegisterInterfaceInGlobal( pom, IID_IObjectManager, &m_dwObjectManagerCookie ) ); if ( FAILED( hr ) ) { goto Cleanup; } hr = THR( m_pgit->RegisterInterfaceInGlobal( ptm, IID_ITaskManager, &m_dwTaskManagerCookie ) ); if ( FAILED( hr ) ) { goto Cleanup; } hr = THR( m_pgit->RegisterInterfaceInGlobal( pnm, IID_INotificationManager, &m_dwNotificationManagerCookie ) ); if ( FAILED( hr ) ) { goto Cleanup; } hr = THR( m_pgit->RegisterInterfaceInGlobal( pcm, IID_IConnectionManager, &m_dwConnectionManagerCookie ) ); if ( FAILED( hr ) ) { goto Cleanup; } hr = THR( m_pgit->RegisterInterfaceInGlobal( plm, IID_ILogManager, &m_dwLogManagerCookie ) ); if ( FAILED( hr ) ) { goto Cleanup; } Cleanup: if ( pom != NULL ) { pom->Release(); } // if: if ( pnm != NULL ) { pnm->Release(); } // if: if ( pcm != NULL ) { pcm->Release(); } // if: if ( plm != NULL ) { plm->Release(); } // if: if ( ptm != NULL ) { ptm->Release(); } // if: if ( pdt != NULL ) { pdt->Release(); } // if: HRETURN( hr ); } //*** CServiceManager::HrInit ////////////////////////////////////////////////////////////////////////////// // // CServiceManager::~CServiceManager // ////////////////////////////////////////////////////////////////////////////// CServiceManager::~CServiceManager( void ) { TraceFunc( "" ); EnterCriticalSection( &sm_cs ); if ( g_pspServiceManager == static_cast< IServiceProvider * >( this ) ) { TraceMoveFromMemoryList( g_pspServiceManager, g_GlobalMemoryList ); g_pspServiceManager = NULL; } // if: its our pointer if ( m_pgit != NULL ) { if ( m_dwLogManagerCookie != 0 ) { THR( m_pgit->RevokeInterfaceFromGlobal( m_dwLogManagerCookie ) ); } // if: if ( m_dwConnectionManagerCookie != 0 ) { THR( m_pgit->RevokeInterfaceFromGlobal( m_dwConnectionManagerCookie ) ); } // if: if ( m_dwNotificationManagerCookie != 0 ) { THR( m_pgit->RevokeInterfaceFromGlobal( m_dwNotificationManagerCookie ) ); } // if: if ( m_dwObjectManagerCookie != 0 ) { THR( m_pgit->RevokeInterfaceFromGlobal( m_dwObjectManagerCookie ) ); } // if: if ( m_dwTaskManagerCookie != 0 ) { THR( m_pgit->RevokeInterfaceFromGlobal( m_dwTaskManagerCookie ) ); } // if: m_pgit->Release(); } // if: InterlockedDecrement( &g_cObjects ); LeaveCriticalSection( &sm_cs ); TraceFuncExit(); } //*** CServiceManager::~CServiceManager //**************************************************************************** // // IUnknown // //**************************************************************************** ////////////////////////////////////////////////////////////////////////////// //++ // // CServiceManager::QueryInterface // // Description: // Query this object for the passed in interface. // // Arguments: // riidIn // Id of interface requested. // // ppvOut // Pointer to the requested interface. // // Return Value: // S_OK // If the interface is available on this object. // // E_NOINTERFACE // If the interface is not available. // // E_POINTER // ppvOut was NULL. // // Remarks: // None. // //-- ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CServiceManager::QueryInterface( REFIID riidIn , LPVOID * ppvOut ) { TraceQIFunc( riidIn, ppvOut ); HRESULT hr = S_OK; // // Validate arguments. // Assert( ppvOut != NULL ); if ( ppvOut == NULL ) { hr = THR( E_POINTER ); goto Cleanup; } // // Handle known interfaces. // if ( IsEqualIID( riidIn, IID_IUnknown ) ) { *ppvOut = static_cast< LPUNKNOWN >( this ); } // if: IUnknown else if ( IsEqualIID( riidIn, IID_IServiceProvider ) ) { *ppvOut = TraceInterface( __THISCLASS__, IServiceProvider, this, 0 ); } // else if: IQueryService else { *ppvOut = NULL; hr = E_NOINTERFACE; } // // Add a reference to the interface if successful. // if ( SUCCEEDED( hr ) ) { ((IUnknown *) *ppvOut)->AddRef(); } // if: success Cleanup: QIRETURN_IGNORESTDMARSHALLING( hr, riidIn ); } //*** CServiceManager::QueryInterface ////////////////////////////////////////////////////////////////////////////// // // STDMETHODIMP_( ULONG ) // CServiceManager::AddRef // ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP_( ULONG ) CServiceManager::AddRef( void ) { TraceFunc( "[IUnknown]" ); InterlockedIncrement( &m_cRef ); CRETURN( m_cRef ); } //*** CServiceManager::AddRef ////////////////////////////////////////////////////////////////////////////// //++ // // STDMETHODIMP_( ULONG ) // CServiceManager::Release // //-- ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP_( ULONG ) CServiceManager::Release( void ) { TraceFunc( "[IUnknown]" ); LONG cRef; cRef = InterlockedDecrement( &m_cRef ); if ( cRef == 0 ) { TraceDo( delete this ); } CRETURN( cRef ); } //*** CServiceManager::Release //**************************************************************************** // // IServiceProvider // //**************************************************************************** ////////////////////////////////////////////////////////////////////////////// //++ // // STDMETHODIMP // CServiceManager::QueryService( // REFCLSID rclsidIn // , REFIID riidInIn // , void ** ppvOutOut // ) // //-- ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CServiceManager::QueryService( REFCLSID rclsidIn , REFIID riidIn , void ** ppvOut ) { TraceFunc( "[IServiceProvider]" ); HRESULT hr = CLASS_E_CLASSNOTAVAILABLE; if ( m_pgit != NULL ) { if ( IsEqualIID( rclsidIn, CLSID_ObjectManager ) ) { IObjectManager * pom; hr = THR( m_pgit->GetInterfaceFromGlobal( m_dwObjectManagerCookie, TypeSafeParams( IObjectManager, &pom ) ) ); if ( FAILED( hr ) ) goto Cleanup; hr = THR( pom->QueryInterface( riidIn, ppvOut ) ); pom->Release(); // fall thru } else if ( IsEqualIID( rclsidIn, CLSID_TaskManager ) ) { ITaskManager * ptm; hr = THR( m_pgit->GetInterfaceFromGlobal( m_dwTaskManagerCookie, TypeSafeParams( ITaskManager, &ptm ) ) ); if ( FAILED( hr ) ) goto Cleanup; hr = THR( ptm->QueryInterface( riidIn, ppvOut ) ); ptm->Release(); // fall thru } else if ( IsEqualIID( rclsidIn, CLSID_NotificationManager ) ) { INotificationManager * pnm; hr = THR( m_pgit->GetInterfaceFromGlobal( m_dwNotificationManagerCookie, TypeSafeParams( INotificationManager, &pnm ) ) ); if ( FAILED( hr ) ) goto Cleanup; hr = THR( pnm->QueryInterface( riidIn, ppvOut ) ); pnm->Release(); // fall thru } else if ( IsEqualIID( rclsidIn, CLSID_ClusterConnectionManager ) ) { IConnectionManager * pcm; hr = THR( m_pgit->GetInterfaceFromGlobal( m_dwConnectionManagerCookie, TypeSafeParams( IConnectionManager, &pcm ) ) ); if ( FAILED( hr ) ) goto Cleanup; hr = THR( pcm->QueryInterface( riidIn, ppvOut ) ); pcm->Release(); // fall thru } else if ( IsEqualIID( rclsidIn, CLSID_LogManager ) ) { ILogManager * plm; hr = THR( m_pgit->GetInterfaceFromGlobal( m_dwLogManagerCookie, TypeSafeParams( ILogManager, &plm ) ) ); if ( FAILED( hr ) ) goto Cleanup; hr = THR( plm->QueryInterface( riidIn, ppvOut ) ); plm->Release(); // fall thru } } // if: GIT pointer not NULL Cleanup: HRETURN( hr ); } //*** CServiceManager::QueryService //**************************************************************************** // // Private Methods // //****************************************************************************