///////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1996-2002 Microsoft Corporation // // Module Name: // CASvc.cpp // // Description: // Implementation of helper functions for accessing and controlling // services. // // Maintained By: // David Potter (davidp) December 23, 1996 // // Revision History: // // Notes: // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include #include "resource.h" #define _RESOURCE_H_ #include "CASvc.h" #include "ConstDef.h" #include "ExcOper.h" #include "TraceTag.h" #include "CluAdmin.h" #include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // Global Variables ///////////////////////////////////////////////////////////////////////////// #ifdef _DEBUG CTraceTag g_tagService( _T("Service"), _T("SERVICE"), 0 ); #endif ///////////////////////////////////////////////////////////////////////////// //++ // // HOpenCluster // // Description: // Open a cluster. If it fails, ask if the cluster service should be // started. // // Arguments: // pszClusterIn -- Name of cluster. // // Return Values: // hCluster -- Cluster handle or NULL. // //-- ///////////////////////////////////////////////////////////////////////////// HCLUSTER HOpenCluster( IN LPCTSTR pszClusterIn ) { HCLUSTER hCluster = NULL; HRESULT hr; DWORD dwStatus; DWORD dwClusterState; LPTSTR pszRealCluster; TCHAR szRealClusterName[ MAX_PATH ]; CString strMsg; CFrameWnd * pframeMain; ASSERT( pszClusterIn != NULL ); pframeMain = PframeMain(); ASSERT( pframeMain != NULL ); if ( _tcscmp( pszClusterIn, _T(".") ) == 0 ) { DWORD nSize = sizeof( szRealClusterName ) / sizeof( TCHAR ); pszRealCluster = NULL; GetComputerName( szRealClusterName, &nSize ); } // if: connecting to the local machine else { pszRealCluster = (LPTSTR) pszClusterIn; hr = StringCchCopy( szRealClusterName, RTL_NUMBER_OF( szRealClusterName ), pszClusterIn ); if ( FAILED( hr ) ) { CNTException nte( hr, 0, NULL, NULL, FALSE /*bAutoDelete*/ ); nte.ReportError(); goto Cleanup; } } // else: not connecting to the local machine // Display a message on the status bar. { CString strStatusBarText; strStatusBarText.FormatMessage( IDS_SB_OPENING_CONNECTION, szRealClusterName ); pframeMain->SetMessageText( strStatusBarText ); pframeMain->UpdateWindow(); } // Display a message on the status bar // Encapsulate wait cursor class. { CWaitCursor wc; Trace( g_tagService, _T("HOpenCluster() - Getting node cluster state on '%s'"), szRealClusterName ); // Get the cluster state of the node. dwStatus = GetNodeClusterState( pszRealCluster, &dwClusterState ); if ( dwStatus != ERROR_SUCCESS ) { CNTException nte( dwStatus, IDS_CANNOT_START_CLUSTER_SERVICE, szRealClusterName, NULL, FALSE /*bAutoDelete*/ ); nte.ReportError( MB_OK | MB_ICONSTOP ); goto Cleanup; } Trace( g_tagService, _T("HOpenCluster() - Node cluster state on '%s' is 0x%08.8x"), szRealClusterName, dwClusterState ); } // Encapsulate wait cursor class // Check to see make sure that clustering is installed and configured // on the specified node. if ( ( dwClusterState == ClusterStateNotInstalled ) || ( dwClusterState == ClusterStateNotConfigured ) ) { strMsg.FormatMessage( IDS_CLUSTER_NOT_INSTALLED_OR_CONFIGURED, szRealClusterName ); AfxMessageBox( strMsg, MB_OK | MB_ICONSTOP ); goto Cleanup; } // if: clustering not installed or configured // If the cluster service is not running, ask if it should be started. if ( dwClusterState == ClusterStateNotRunning ) { ID id; // Ask the user if the cluster service should be started. strMsg.FormatMessage( IDS_START_CLUSTER_SERVICE, szRealClusterName ); id = AfxMessageBox( strMsg, MB_YESNO | MB_ICONEXCLAMATION ); if ( id == IDYES ) { // Display a message on the status bar. { CString strStatusBarText; strStatusBarText.FormatMessage( IDS_SB_STARTING_CLUSTER_SERVICE, szRealClusterName ); pframeMain->SetMessageText( strStatusBarText ); pframeMain->UpdateWindow(); } // Display a message on the status bar // Encapsulate wait cursor class. { CWaitCursor wc; // Start the service. hr = HrStartService( CLUSTER_SERVICE_NAME, szRealClusterName ); if ( ! FAILED( hr ) && ( hr != S_FALSE ) ) { if ( hr == S_OK ) { // Wait a second. This is required to make sure that the // cluster service is running and ready to receive RPC // connections. Sleep( 1000 ); } // if: user didn't cancel the start operation } // if: service started successfully else { CNTException nte( hr, IDS_CANNOT_START_CLUSTER_SERVICE, szRealClusterName, NULL, FALSE /*bAutoDelete*/ ); nte.ReportError(); goto Cleanup; } // else: failed to start the service } // Encapsulate wait cursor class } // if: user approved starting the service } // if: cluster service not running // Encapsulate wait cursor class. { CWaitCursor wc; // Display a message on the status bar. { CString strStatusBarText; strStatusBarText.FormatMessage( IDS_SB_OPENING_CONNECTION, szRealClusterName ); pframeMain->SetMessageText( strStatusBarText ); pframeMain->UpdateWindow(); } // Display a message on the status bar Trace( g_tagService, _T("HOpenCluster() - Opening the cluster on '%s'"), szRealClusterName ); // Open the cluster. hCluster = OpenCluster( pszRealCluster ); if ( hCluster == NULL ) { CNTException nte( GetLastError(), IDS_OPEN_NODE_ERROR, szRealClusterName, NULL, FALSE /*bAutoDelete*/ ); dwStatus = nte.Sc(); nte.ReportError(); goto Cleanup; } // if: error opening the cluster } // Encapsulate wait cursor class Cleanup: // Reset the message on the status bar. pframeMain->SetMessageText( AFX_IDS_IDLEMESSAGE ); pframeMain->UpdateWindow(); if ( dwStatus != ERROR_SUCCESS ) { SetLastError( dwStatus ); } // if: error occurred return hCluster; } //*** HOpenCluster() ///////////////////////////////////////////////////////////////////////////// //++ // // BCanServiceBeStarted // // Description: // Find out if a service can be started on a specified node or not. // // Arguments: // pszServiceNameIn -- Name of service. // pszNodeIn -- Name of node. // // Return Values: // TRUE -- Service can be started on the specified node. // FALSE -- Service can not be started on the specified node. // //-- ///////////////////////////////////////////////////////////////////////////// BOOL BCanServiceBeStarted( LPCTSTR pszServiceNameIn, LPCTSTR pszNodeIn ) { BOOL bCanBeStarted = FALSE; DWORD dwStatus = ERROR_SUCCESS; SC_HANDLE hSCManager = NULL; SC_HANDLE hService = NULL; SERVICE_STATUS ssServiceStatus; // Open the Service Control Manager. hSCManager = OpenSCManager( pszNodeIn, NULL /*lpDatabaseName*/, GENERIC_READ ); if ( hSCManager == NULL ) { dwStatus = GetLastError(); Trace( g_tagService, _T("BCanServiceBeStarted() - Cannot access service control manager on node '%s'! Error: %u."), pszNodeIn, dwStatus ); goto Cleanup; } // if: error opening the Service Control Manager // Open the service. hService = OpenService( hSCManager, pszServiceNameIn, SERVICE_ALL_ACCESS ); if ( hService == NULL ) { dwStatus = GetLastError(); Trace( g_tagService, _T("BCanServiceBeStarted() - Cannot open service %s. Error: %u."), pszServiceNameIn, dwStatus ); if ( dwStatus != ERROR_SERVICE_DOES_NOT_EXIST ) { bCanBeStarted = TRUE; } // if: error not Service Does Not Exist goto Cleanup; } // if: error opening the service // Query the service status. if ( QueryServiceStatus( hService, &ssServiceStatus ) ) { if ( ssServiceStatus.dwCurrentState == SERVICE_STOPPED ) { bCanBeStarted = TRUE; } // if: service is stopped } // if: service status queried successfully else { dwStatus = GetLastError(); } // if: error querying service status Cleanup: if ( hService != NULL ) { CloseServiceHandle( hService ); } if ( hSCManager != NULL ) { CloseServiceHandle( hSCManager ); } SetLastError( dwStatus ); return bCanBeStarted; } //*** BCanServiceBeStarted() ///////////////////////////////////////////////////////////////////////////// //++ // // BIsServiceInstalled // // Routine Description: // Find out if a service is installed on a specified node or not. // // Arguments: // pszServiceNameIn -- Name of service. // pszNodeIn -- Name of node. // // Return Value: // TRUE -- Service is running on the specified node. // FALSE -- Service is not running on the specified node. // //-- ///////////////////////////////////////////////////////////////////////////// BOOL BIsServiceInstalled( LPCTSTR pszServiceNameIn, LPCTSTR pszNodeIn ) { BOOL bInstalled = FALSE; DWORD dwStatus = ERROR_SUCCESS; SC_HANDLE hSCManager = NULL; SC_HANDLE hService = NULL; // Open the Service Control Manager. hSCManager = OpenSCManager( pszNodeIn, NULL /*lpDatabaseName*/, GENERIC_READ ); if ( hSCManager == NULL ) { dwStatus = GetLastError(); Trace( g_tagService, _T("BIsServiceInstalled() - Cannot access service control manager on node '%s'! Error: %u."), pszNodeIn, dwStatus ); goto Cleanup; } // if: error opening the Service Control Manager // Open the service. hService = OpenService( hSCManager, pszServiceNameIn, SERVICE_ALL_ACCESS ); if ( hService == NULL ) { dwStatus = GetLastError(); Trace( g_tagService, _T("BIsServiceInstalled() - Cannot open service %s. Error: %u."), pszServiceNameIn, dwStatus ); if ( dwStatus != ERROR_SERVICE_DOES_NOT_EXIST ) { bInstalled = TRUE; } // if: error not Service Does Not Exist } // if: error opening the service else { bInstalled = TRUE; } // else: service opened successfully Cleanup: if ( hService != NULL ) { CloseServiceHandle( hService ); } if ( hSCManager != NULL ) { CloseServiceHandle( hSCManager ); } SetLastError( dwStatus ); return bInstalled; } //*** BIsServiceInstalled() ///////////////////////////////////////////////////////////////////////////// //++ // // BIsServiceRunning // // Description: // Find out if a service is running on a specified node or not. // // Arguments: // pszServiceNameIn -- Name of service. // pszNodeIn -- Name of node. // // Return Values: // TRUE -- Service is running on the specified node. // FALSE -- Service is not running on the specified node. // //-- ///////////////////////////////////////////////////////////////////////////// BOOL BIsServiceRunning( LPCTSTR pszServiceNameIn, LPCTSTR pszNodeIn ) { BOOL bRunning = FALSE; DWORD dwStatus = ERROR_SUCCESS; SC_HANDLE hSCManager = NULL; SC_HANDLE hService = NULL; SERVICE_STATUS ssServiceStatus; // Open the Service Control Manager. hSCManager = OpenSCManager( pszNodeIn, NULL /*lpDatabaseName*/, GENERIC_READ ); if ( hSCManager == NULL ) { dwStatus = GetLastError(); Trace( g_tagService, _T("BIsServiceRunning() - Cannot access service control manager on node '%s'! Error: %u."), pszNodeIn, dwStatus ); goto Cleanup; } // if: error opening the Service Control Manager // Open the service. hService = OpenService( hSCManager, pszServiceNameIn, SERVICE_ALL_ACCESS ); if ( hService == NULL ) { dwStatus = GetLastError(); Trace( g_tagService, _T("BIsServiceRunning() - Cannot open service %s. Error: %u."), pszServiceNameIn, dwStatus ); goto Cleanup; } // if: error opening the service // Query the service status. if ( QueryServiceStatus( hService, &ssServiceStatus ) ) { if ( ssServiceStatus.dwCurrentState == SERVICE_RUNNING ) { bRunning = TRUE; } // if: service is running } // if: service status queried successfully Cleanup: if ( hService != NULL ) { CloseServiceHandle( hService ); } if ( hSCManager != NULL ) { CloseServiceHandle( hSCManager ); } SetLastError( dwStatus ); return bRunning; } //*** BIsServiceRunning() ///////////////////////////////////////////////////////////////////////////// //++ // // HrStartService // // Description: // Start a service on a specified node. // // Arguments: // pszServiceNameIn -- Name of service. // pszNodeIn -- Name of node. // // Return Values: // S_OK -- Service started successfully. // Any errors returned by SVCMGMT_IStartStopHelper::StartServiceHelper(). // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT HrStartService( LPCTSTR pszServiceNameIn, LPCTSTR pszNodeIn ) { HRESULT hr = S_OK; ISvcMgmtStartStopHelper * psmssh = NULL; BSTR bstrNode = NULL; BSTR bstrServiceName = NULL; CFrameWnd * pframeMain; pframeMain = PframeMain(); ASSERT( pframeMain != NULL ); // Display a message on the status bar. { CString strStatusBarText; strStatusBarText.FormatMessage( IDS_SB_STARTING_SERVICE, pszServiceNameIn, pszNodeIn ); Trace( g_tagService, _T("HrStartService() - Starting the '%s' service on node '%s'."), pszServiceNameIn, pszNodeIn ); pframeMain->SetMessageText( strStatusBarText ); pframeMain->UpdateWindow(); } // Display a message on the status bar // Make BSTRs for the arguments. bstrNode = SysAllocString( pszNodeIn ); if ( bstrNode == NULL ) { hr = E_OUTOFMEMORY; goto Cleanup; } bstrServiceName = SysAllocString( pszServiceNameIn ); if ( bstrServiceName == NULL ) { hr = E_OUTOFMEMORY; goto Cleanup; } // Create the service management object. hr = CoCreateInstance( CLSID_SvcMgmt, NULL, CLSCTX_INPROC_SERVER, __uuidof( ISvcMgmtStartStopHelper ), reinterpret_cast< void ** >( &psmssh ) ); if ( FAILED( hr ) ) { Trace( g_tagService, _T("HrStartService() - Error creating IStartStopHelper interface. Error: %u."), hr ); goto Cleanup; } // Start the service. hr = psmssh->StartServiceHelper( AfxGetMainWnd()->m_hWnd, bstrNode, bstrServiceName, 0, NULL ); if ( FAILED( hr ) ) { Trace( g_tagService, _T("HrStartService() - Error from IStartStopHelper::StartServiceHelper() to start the '%s' service on node '%s'. Error: %u."), pszServiceNameIn, pszNodeIn, hr ); goto Cleanup; } Cleanup: if ( bstrNode != NULL ) { SysFreeString( bstrNode ); } if ( bstrServiceName != NULL ) { SysFreeString( bstrServiceName ); } if ( psmssh != NULL ) { psmssh->Release(); } // Reset the message on the status bar. pframeMain->SetMessageText( AFX_IDS_IDLEMESSAGE ); pframeMain->UpdateWindow(); return hr; } //*** HrStartService() ///////////////////////////////////////////////////////////////////////////// //++ // // HrStopService // // Description: // Stop a service on a specified node. // // Arguments: // pszServiceNameIn -- Name of service. // pszNodeIn -- Name of node. // // Return Values: // S_OK -- Service stopped successfully. // Any errors returned by SVCMGMT_IStartStopHelper::ControlServiceHelper(). // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT HrStopService( LPCTSTR pszServiceNameIn, LPCTSTR pszNodeIn ) { HRESULT hr = S_OK; ISvcMgmtStartStopHelper * psmssh = NULL; BSTR bstrNode = NULL; BSTR bstrServiceName = NULL; CFrameWnd * pframeMain; pframeMain = PframeMain(); ASSERT( pframeMain != NULL ); // Display a message on the status bar. { CString strStatusBarText; strStatusBarText.FormatMessage( IDS_SB_STOPPING_SERVICE, pszServiceNameIn, pszNodeIn ); Trace( g_tagService, _T("HrStopService() - Stopping the '%s' service on node '%s'."), pszServiceNameIn, pszNodeIn ); pframeMain->SetMessageText( strStatusBarText ); pframeMain->UpdateWindow(); } // Display a message on the status bar // Make BSTRs for the arguments. bstrNode = SysAllocString( pszNodeIn ); if ( bstrNode == NULL ) { hr = E_OUTOFMEMORY; goto Cleanup; } bstrServiceName = SysAllocString( pszServiceNameIn ); if ( bstrServiceName == NULL ) { hr = E_OUTOFMEMORY; goto Cleanup; } // Create the service management object. hr = CoCreateInstance( CLSID_SvcMgmt, NULL, CLSCTX_INPROC_SERVER, __uuidof( ISvcMgmtStartStopHelper ), reinterpret_cast< void ** >( &psmssh ) ); if ( FAILED( hr ) ) { Trace( g_tagService, _T("HrStopService() - Error creating IStartStopHelper interface. Error: %u."), hr ); goto Cleanup; } // Start the service. hr = psmssh->ControlServiceHelper( AfxGetMainWnd()->m_hWnd, bstrNode, bstrServiceName, SERVICE_CONTROL_STOP ); if ( FAILED( hr ) ) { Trace( g_tagService, _T("HrStopService() - Error from IStartStopHelper::ControlServiceHelper() to stop the '%s' service on node '%s'. Error: %u."), pszServiceNameIn, pszNodeIn, hr ); goto Cleanup; } Cleanup: if ( bstrNode != NULL ) { SysFreeString( bstrNode ); } if ( bstrServiceName != NULL ) { SysFreeString( bstrServiceName ); } if ( psmssh != NULL ) { psmssh->Release(); } // Reset the message on the status bar. pframeMain->SetMessageText( AFX_IDS_IDLEMESSAGE ); pframeMain->UpdateWindow(); return hr; } //*** HrStopService()