windows-nt/Source/XPSP1/NT/base/cluster/admin/cluadmin/casvc.cpp
2020-09-26 16:20:57 +08:00

644 lines
19 KiB
C++

/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1996-2001 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 <winsvc.h>
#include "resource.h"
#define _RESOURCE_H_
#include "CASvc.h"
#include "ConstDef.h"
#include "ExcOper.h"
#include "TraceTag.h"
#include "CluAdmin.h"
#include <FileMgmt.h>
#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;
_tcscpy( szRealClusterName, pszClusterIn );
} // 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_CANNOT_START_CLUSTER_SERVICE, 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()