/////////////////////////////////////////////////////////////////////////// // // Copyright(C) 1997-1998 Microsoft Corporation all rights reserved. // // Module: sdocoremgr.cpp // // Project: Everest // // Description: IAS - Server Core Manager Implementation // // Log: // // When Who What // ---- --- ---- // 6/08/98 TLP Initial Version // /////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "sdocoremgr.h" #include "sdohelperfuncs.h" #include "sdocomponentfactory.h" #include "sdo.h" #include "sdoserviceias.h" ///////////////////////// // Core manager retrieval CCoreMgr& GetCoreManager(void) { ////////////////////////////////////////////////////////////////////////// static CCoreMgr theCoreManager; // The one and only core manager ////////////////////////////////////////////////////////////////////////// return theCoreManager; } ////////////////////////////////////////////////////////////////////////////// // IAS CORE MANAGER CLASS IMPLEMENTATION // // This class is responsible for managing the lifetimes of the components // that do "real" work. It also provides services to the class that // implements the ISdoService interface. ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // Constructor ////////////////////////////////////////////////////////////////////////////// CCoreMgr::CCoreMgr() : m_eCoreState(CORE_STATE_SHUTDOWN) { } ////////////////////////////////////////////////////////////////////////////// // // Function: CCoreMgr::StartService() // // Visibility: Public // // Inputs: eType: type of service to stop // // Outputs: S_OK - function succeeded - service started. // E_FAIL - function failed - service not started. // // Description: Starts a specified IAS service. // ////////////////////////////////////////////////////////////////////////////// HRESULT CCoreMgr::StartService(SERVICE_TYPE eType) { HRESULT hr = S_OK; LONG lProtocolId; bool fUpdateConfiguration = true; do { // Initialize the core if we've not already done so... // if ( CORE_STATE_SHUTDOWN == m_eCoreState ) { hr = InitializeComponents(); if ( FAILED(hr) ) break; // No need to update configuration (InitializeComponents() just did) // fUpdateConfiguration = false; } // Start the requested service if it ain't already started // if ( ! m_ServiceStatus.IsServiceStarted(eType) ) { switch ( eType ) { case SERVICE_TYPE_IAS: lProtocolId = IAS_PROTOCOL_MICROSOFT_RADIUS; break; case SERVICE_TYPE_RAS: lProtocolId = IAS_PROTOCOL_MICROSOFT_SURROGATE; break; default: // BAD! - tar and feather the caller // _ASSERT(FALSE); break; }; hr = E_FAIL; // Brackets provide scope that ensures the protocol // handle is released before invoking ShutdownComponents(). // This allows all protocols to be released in the // context of the ShutdownProtocols() function. { ComponentMapIterator iter = m_Protocols.find(lProtocolId); _ASSERT( iter != m_Protocols.end() ); if ( iter != m_Protocols.end() ) { // Update the service configuration if we're already // initialized and we're just resuming a protocol. We need // to do this because the service may be started in an // instance of svchost running another of our services. // // For example, RRAS is running automatically and then the // user configures IAS via the IAS UI and then starts the // IAS service. If the service starts in the instance of // svchost running RRAS then we need to update its // configuration. hr = S_OK; if ( fUpdateConfiguration ) { hr = UpdateConfiguration(); if ( FAILED(hr) ) IASTracePrintf("IAS Core Manager was unable to configure service: %d...", eType); } if ( SUCCEEDED(hr) ) { ComponentPtr pProtocol = (*iter).second; hr = pProtocol->Resume(); } } } if ( SUCCEEDED(hr) ) { m_ServiceStatus.SetServiceStatus(eType, IAS_SERVICE_STATUS_STARTED); // TODO: Log Service Started Event (IAS Only) IASTracePrintf("IAS Core Manager successfully started service %d...", eType); } else { // TODO: Log Service Failed Event (IAS Only) // This function did not succeed so shutdown the core if no // other services are started. // if ( ! m_ServiceStatus.IsAnyServiceStarted() ) ShutdownComponents(); } } } while ( FALSE ); return hr; } ////////////////////////////////////////////////////////////////////////////// // // Function: CCoreMgr::StopService() // // Visibility: Public // // Inputs: eType: type of service to stop // // Outputs: S_OK - function succeeded - service started. // E_FAIL - function failed - service not started. // // Description: Stops a specified IAS service. // ////////////////////////////////////////////////////////////////////////////// HRESULT CCoreMgr::StopService(SERVICE_TYPE eType) { HRESULT hr = E_FAIL; LONG lProtocolId; do { switch ( eType ) { case SERVICE_TYPE_IAS: lProtocolId = IAS_PROTOCOL_MICROSOFT_RADIUS; break; case SERVICE_TYPE_RAS: lProtocolId = IAS_PROTOCOL_MICROSOFT_SURROGATE; break; default: // BAD! - tar and feather the caller // _ASSERT(FALSE); break; }; // Brackets provide scope that ensures the protocol // handle is released before invoking ShutdownComponents(). // This allows all protocols to be released in the // context of the ShutdownProtocols() function. { ComponentMapIterator iter = m_Protocols.find(lProtocolId); if ( iter == m_Protocols.end() ) break; ComponentPtr pProtocol = (*iter).second; hr = pProtocol->Suspend(); if ( SUCCEEDED(hr) ) IASTracePrintf("IAS Core Manager stopped service %d...", eType); } m_ServiceStatus.SetServiceStatus(eType, IAS_SERVICE_STATUS_STOPPED); // Shutdown the core if this was the last active service // if ( ! m_ServiceStatus.IsAnyServiceStarted() ) ShutdownComponents(); } while ( FALSE ); return hr; } ////////////////////////////////////////////////////////////////////////////// // // Function: CCoreMgr::UpdateConfiguration() // // Visibility: Public // // Inputs: None // // Outputs: S_OK - function succeeded - service started. // E_FAIL - function failed - service not started. // // Description: Used to update the configuration information used // by the core components. // ////////////////////////////////////////////////////////////////////////////// HRESULT CCoreMgr::UpdateConfiguration() { HRESULT hr = E_FAIL; _ASSERT ( CORE_STATE_INITIALIZED == m_eCoreState ); IASTracePrintf("IAS Core Manager is updating component configuration..."); do { CComPtr pSdoMachine; hr = CoCreateInstance( CLSID_SdoMachine, NULL, CLSCTX_INPROC_SERVER, IID_ISdoMachine, (void**)&pSdoMachine ); if ( FAILED(hr) ) break; IASTracePrintf("IAS Core Manager is attaching to the local machine..."); hr = pSdoMachine->Attach(NULL); if ( FAILED(hr) ) break; // Get the service SDO // CComPtr pUnknown; hr = pSdoMachine->GetServiceSDO(GetDataStore(), IASServiceName, &pUnknown); if ( FAILED(hr) ) break; CComPtr pSdoService; hr = pUnknown->QueryInterface(__uuidof(SdoService), (void**)&pSdoService); if ( FAILED(hr) ) { IASTracePrintf("Error in Core Manager - InitializeComponents() - QueryInterface(ISdo) failed..."); break; } hr = ConfigureAuditors(pSdoService); if ( FAILED(hr) ) break; CComPtr dstore; pSdoService->getDataStoreObject(&dstore); hr = LinkHandlerProperties(pSdoService, dstore); if ( FAILED(hr) ) break; hr = m_PipelineMgr.Configure(pSdoService); if ( FAILED(hr) ) break; hr = ConfigureProtocols(pSdoService); if ( FAILED(hr) ) break; } while ( FALSE ); return hr; } ////////////////////////////////////////////////////////////////////////////// // Core Manager Private Member Functions ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// HRESULT CCoreMgr::InitializeComponents(void) { HRESULT hr; _ASSERT ( CORE_STATE_SHUTDOWN == m_eCoreState ); do { IASTraceInitialize(); IASTraceString("IAS Core Manager is initializing the IAS components..."); IASInitialize(); CComPtr pSdoMachine; hr = CoCreateInstance( CLSID_SdoMachine, NULL, CLSCTX_INPROC_SERVER, IID_ISdoMachine, (void**)&pSdoMachine ); if ( FAILED(hr) ) break; IASTracePrintf("IAS Core Manager is attaching to the local machine..."); hr = pSdoMachine->Attach(NULL); if ( FAILED(hr) ) break; CComPtr pUnknown; hr = pSdoMachine->GetServiceSDO(GetDataStore(), IASServiceName, &pUnknown); if ( FAILED(hr) ) break; CComPtr pSdoService; hr = pUnknown->QueryInterface(__uuidof(SdoService), (void**)&pSdoService); if ( FAILED(hr) ) { IASTracePrintf("Error in Core Manager - InitializeComponents() - QueryInterface(ISdo - Service) failed..."); break; } hr = InitializeAuditors(pSdoService); if ( FAILED(hr) ) break; CComPtr dstore; pSdoService->getDataStoreObject(&dstore); hr = LinkHandlerProperties(pSdoService, dstore); if ( FAILED(hr) ) { ShutdownAuditors(); break; } hr = m_PipelineMgr.Initialize(pSdoService); if ( FAILED(hr) ) { ShutdownAuditors(); break; } hr = InitializeProtocols(pSdoService); if ( FAILED(hr) ) { m_PipelineMgr.Shutdown(); ShutdownAuditors(); break; } m_eCoreState = CORE_STATE_INITIALIZED; } while (FALSE); if ( FAILED(hr) ) { IASUninitialize(); IASTraceUninitialize(); } return hr; } ////////////////////////////////////////////////////////////////////////////// void CCoreMgr::ShutdownComponents(void) { _ASSERT ( CORE_STATE_INITIALIZED == m_eCoreState ); IASTracePrintf("IAS Core Manager is shutting down the IAS components..."); ShutdownProtocols(); m_PipelineMgr.Shutdown(); ShutdownAuditors(); IASUninitialize(); IASTraceUninitialize(); m_eCoreState = CORE_STATE_SHUTDOWN; } ////////////////////////////////////////////////////////////////////////////// IASDATASTORE CCoreMgr::GetDataStore() { CRegKey IASKey; LONG lResult = IASKey.Open( HKEY_LOCAL_MACHINE, IAS_POLICY_REG_KEY, KEY_READ ); if ( lResult == ERROR_SUCCESS ) { DWORD dwValue; lResult = IASKey.QueryValue( dwValue, (LPCTSTR)IAS_DATASTORE_TYPE ); if ( lResult == ERROR_SUCCESS ) return (IASDATASTORE)dwValue; } return DATA_STORE_LOCAL; } ////////////////////////////////////////////////////////////////////////////// HRESULT CCoreMgr::InitializeAuditors(ISdo* pSdoService) { HRESULT hr; LONG lComponentId; CComPtr pEnumAuditors; CComPtr pSdoAuditor; // Note about state: When this function completes, either all of the // auditors are initialized or none of the auditors are initialized IASTracePrintf("IAS Core Manager is initializing the auditors..."); try { do { hr = ::SDOGetCollectionEnumerator(pSdoService, PROPERTY_IAS_AUDITORS_COLLECTION, &pEnumAuditors); if ( FAILED(hr) ) break; hr = ::SDONextObjectFromCollection(pEnumAuditors, &pSdoAuditor); while ( S_OK == hr ) { hr = ::SDOGetComponentIdFromObject(pSdoAuditor, &lComponentId); if ( FAILED(hr) ) break; { ComponentPtr pAuditor = ::MakeComponent(COMPONENT_TYPE_AUDITOR, lComponentId); if ( ! pAuditor.IsValid() ) { hr = E_FAIL; break; } hr = pAuditor->Initialize(pSdoAuditor); if ( FAILED(hr) ) break; if ( ! AddComponent(lComponentId, pAuditor, m_Auditors) ) { hr = E_FAIL; break; } } pSdoAuditor.Release(); hr = ::SDONextObjectFromCollection(pEnumAuditors, &pSdoAuditor); } if ( S_FALSE == hr ) hr = S_OK; } while ( FALSE ); } catch(...) { IASTracePrintf("Error in IAS Core Manager - InitializeAuditors() - Caught unknown exception..."); hr = E_FAIL; } if ( FAILED(hr) ) { IASTracePrintf("Error in IAS Core Manager - InitializeAuditors() - Could not initialize the auditors..."); ShutdownAuditors(); } return hr; } ////////////////////////////////////////////////////////////////////////////// HRESULT CCoreMgr::ConfigureAuditors(ISdo* pSdoService) { HRESULT hr = S_OK; IASTracePrintf("IAS Core Manager is configuring the auditors..."); try { // Try to update the configuration settings for each request handler. We // assume that auditors are autonomous with respect to configuration // and if one fails to configure we'll continue to try to configure the others // ComponentMapIterator iter = m_Auditors.begin(); while ( iter != m_Auditors.end() ) { CComPtr pSdoComponent; ComponentPtr pAuditor = (*iter).second; // get the component from the collection hr = ::SDOGetComponentFromCollection (pSdoService, PROPERTY_IAS_AUDITORS_COLLECTION, pAuditor->GetId (), &pSdoComponent); if (SUCCEEDED (hr)) { hr = pAuditor->Configure(pSdoComponent); if ( FAILED(hr) ) { IASTracePrintf("IAS Core Manager - ConfigureAuditors() - Auditor %d could not be configured...", pAuditor->GetId()); hr = S_OK; } } else { IASTracePrintf("IAS Core Manager - ConfigureAuditors() - unable to get component from collection in auditor %d...", pAuditor->GetId()); hr = S_OK; } iter++; } } catch(...) { IASTracePrintf("Error in IAS Core Manager - ConfigureAuditors() - Caught unknown exception..."); hr = E_FAIL; } return hr; } ////////////////////////////////////////////////////////////////////////////// void CCoreMgr::ShutdownAuditors(void) { IASTracePrintf("IAS Core Manager is shutting down the auditors..."); try { ComponentMapIterator iter = m_Auditors.begin(); while ( iter != m_Auditors.end() ) { ComponentPtr pAuditor = (*iter).second; pAuditor->Suspend(); pAuditor->Shutdown(); iter = m_Auditors.erase(iter); } } catch(...) { IASTracePrintf("Error in IAS Core Manager - ShutdownAuditors() - Caught unknown exception..."); } } ////////////////////////////////////////////////////////////////////////////// HRESULT CCoreMgr::InitializeProtocols(ISdo* pSdoService) { HRESULT hr = E_FAIL; IASTracePrintf("IAS Core Manager is initializing the protocols..."); // Note about state: When this function completes, either all of the // protocols are initialized or none of the protocols are initialized try { do { CComPtr pRequestHandler; m_PipelineMgr.GetPipeline(&pRequestHandler); CComPtr pEnumProtocols; hr = ::SDOGetCollectionEnumerator(pSdoService, PROPERTY_IAS_PROTOCOLS_COLLECTION, &pEnumProtocols); if ( FAILED(hr) ) break; LONG lComponentId; CComPtr pSdoProtocol; hr = ::SDONextObjectFromCollection(pEnumProtocols, &pSdoProtocol); while ( S_OK == hr ) { hr = ::SDOGetComponentIdFromObject(pSdoProtocol, &lComponentId); if ( FAILED(hr) ) break; { ComponentPtr pProtocol = ::MakeComponent(COMPONENT_TYPE_PROTOCOL, lComponentId); if ( ! pProtocol.IsValid() ) { hr = E_FAIL; break; } // Don't treat protocol initialization as a critical failure // hr = pProtocol->Initialize(pSdoProtocol); if ( SUCCEEDED(hr) ) { hr = pProtocol->PutObject(pRequestHandler, IID_IRequestHandler); if ( FAILED(hr) ) break; hr = pProtocol->Suspend(); if ( FAILED(hr) ) break; if ( ! AddComponent(lComponentId, pProtocol, m_Protocols) ) { hr = E_FAIL; break; } } pSdoProtocol.Release(); } hr = ::SDONextObjectFromCollection(pEnumProtocols, &pSdoProtocol); } if ( S_FALSE == hr ) hr = S_OK; } while ( FALSE ); } catch(...) { IASTracePrintf("Error in IAS Core Manager - InitializeProtocols() - Caught unknown exception..."); hr = E_FAIL; } if ( FAILED(hr) ) { IASTracePrintf("Error in IAS Core Manager - InitializeProtocols() - Could not initialize the protocols..."); ShutdownProtocols(); } return hr; } ////////////////////////////////////////////////////////////////////////////// HRESULT CCoreMgr::ConfigureProtocols(ISdo* pSdoService) { HRESULT hr = S_OK; IASTracePrintf("IAS Core Manager is configuring the protocols..."); // Try to update the configuration settings for each protocol // Note we assume the request handler used by a protocol is not // dynamically configurable! // try { ComponentMapIterator iter = m_Protocols.begin(); while ( iter != m_Protocols.end() ) { CComPtr pSdoComponent; ComponentPtr pProtocol = (*iter).second; // get the protocol collection hr = ::SDOGetComponentFromCollection (pSdoService, PROPERTY_IAS_PROTOCOLS_COLLECTION, pProtocol->GetId (), &pSdoComponent); if (SUCCEEDED (hr)) { hr = pProtocol->Configure(pSdoComponent); if ( FAILED(hr) ) { IASTracePrintf("IAS Core Manager - ConfigureProtocols() - Protocol %d could not be configured...", pProtocol->GetId()); hr = S_OK; } } else { IASTracePrintf("IAS Core Manager - ConfigureProtocols() - unnable to get component from collection for protocol %d...", pProtocol->GetId()); hr = S_OK; } iter++; } } catch(...) { IASTracePrintf("Error in IAS Core Manager - ConfigureProtocols() - Caught unknown exception..."); hr = E_FAIL; } return hr; } ////////////////////////////////////////////////////////////////////////////// void CCoreMgr::ShutdownProtocols(void) { IASTracePrintf("IAS Core Manager is shutting down the protocols..."); try { ComponentMapIterator iter = m_Protocols.begin(); while ( iter != m_Protocols.end() ) { ComponentPtr pProtocol = (*iter).second; // We only initialize a protocol when its associated // service (IAS or RAS currently) is started. if ( COMPONENT_STATE_INITIALIZED == pProtocol->GetState() ) pProtocol->Suspend(); pProtocol->Shutdown(); iter = m_Protocols.erase(iter); } } catch(...) { IASTracePrintf("Error in IAS Core Manager - ShutdownProtocols() - Caught unknown exception..."); } }