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.
985 lines
31 KiB
985 lines
31 KiB
/**********************************************************************/
|
|
/** Microsoft Windows/NT **/
|
|
/** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
service.cpp
|
|
Calls to start and stop services.
|
|
|
|
FILE HISTORY:
|
|
|
|
*/
|
|
#include "stdafx.h"
|
|
#include "DynamLnk.h"
|
|
#include "cluster.h"
|
|
|
|
DynamicDLL g_NetApiDLL( _T("NETAPI32.DLL"), g_apchNetApiFunctionNames );
|
|
|
|
/*---------------------------------------------------------------------------
|
|
IsComputerNT
|
|
Checks to see if the given computer is running NT
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
TFSCORE_API(DWORD)
|
|
TFSIsComputerNT
|
|
(
|
|
LPCTSTR pszComputer,
|
|
BOOL * bIsNT
|
|
)
|
|
{
|
|
DWORD err = 0;
|
|
BYTE * pbBuffer;
|
|
|
|
*bIsNT = FALSE;
|
|
|
|
if ( !g_NetApiDLL.LoadFunctionPointers() )
|
|
return err;
|
|
|
|
err = ((NETSERVERGETINFO) g_NetApiDLL[NET_API_NET_SERVER_GET_INFO])
|
|
( (LPTSTR) pszComputer,
|
|
101,
|
|
&pbBuffer );
|
|
|
|
if (err == NERR_Success)
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_INVALID_LEVEL
|
|
// ERROR_INVALID_PARAMETER
|
|
// ERROR_NOT_ENOUGH_MEMORY
|
|
//
|
|
SERVER_INFO_101 * pServerInfo = (SERVER_INFO_101 *) pbBuffer;
|
|
|
|
if ( (pServerInfo->sv101_type & SV_TYPE_NT) )
|
|
{
|
|
*bIsNT = TRUE;
|
|
}
|
|
|
|
err = ERROR_SUCCESS; //Translate the NERR code to a winerror code
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
IsNTServer
|
|
Checks to see if the given computer is running NTS
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
TFSCORE_API(DWORD)
|
|
TFSIsNTServer
|
|
(
|
|
LPCTSTR pszComputer,
|
|
BOOL * bIsNTS
|
|
)
|
|
{
|
|
DWORD err = 0;
|
|
BYTE * pbBuffer;
|
|
|
|
*bIsNTS = FALSE;
|
|
|
|
if ( !g_NetApiDLL.LoadFunctionPointers() )
|
|
return err;
|
|
|
|
err = ((NETSERVERGETINFO) g_NetApiDLL[NET_API_NET_SERVER_GET_INFO])
|
|
( (LPTSTR) pszComputer,
|
|
101,
|
|
&pbBuffer );
|
|
|
|
if (err == NERR_Success)
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_INVALID_LEVEL
|
|
// ERROR_INVALID_PARAMETER
|
|
// ERROR_NOT_ENOUGH_MEMORY
|
|
//
|
|
SERVER_INFO_101 * pServerInfo = (SERVER_INFO_101 *) pbBuffer;
|
|
|
|
if ( (pServerInfo->sv101_type & SV_TYPE_SERVER_NT) ||
|
|
(pServerInfo->sv101_type & SV_TYPE_DOMAIN_CTRL) ||
|
|
(pServerInfo->sv101_type & SV_TYPE_DOMAIN_BAKCTRL) )
|
|
{
|
|
*bIsNTS = TRUE;
|
|
}
|
|
|
|
err = ERROR_SUCCESS; //Translate the NERR code to a winerror code
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
TFSIsServiceRunning
|
|
Checks to see if the given service is running on a machine
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
TFSCORE_API(DWORD)
|
|
TFSIsServiceRunning
|
|
(
|
|
LPCTSTR pszComputer,
|
|
LPCTSTR pszServiceName,
|
|
BOOL * fIsRunning
|
|
)
|
|
{
|
|
DWORD err = 0;
|
|
DWORD dwStatus;
|
|
|
|
*fIsRunning = FALSE;
|
|
|
|
err = TFSGetServiceStatus(pszComputer, pszServiceName, &dwStatus, NULL);
|
|
|
|
if (err == 0)
|
|
*fIsRunning = (BOOL)(dwStatus & SERVICE_RUNNING);
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
TFSGetServiceStatus
|
|
Returns ERROR_SUCCESS on API success.
|
|
Returns an error code otherwise.
|
|
|
|
pszComputer - name of the computer to attach to.
|
|
pszServiceName - name of the service to check.
|
|
pdwServiceStatus - returns the status of the service.
|
|
pdwErrorCode - returns the error code returned from the service
|
|
(this is NOT the error code from the API itself).
|
|
This may be NULL.
|
|
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
TFSCORE_API(DWORD)
|
|
TFSGetServiceStatus
|
|
(
|
|
LPCWSTR pszComputer,
|
|
LPCWSTR pszServiceName,
|
|
DWORD * pdwServiceStatus,
|
|
OPTIONAL DWORD * pdwErrorCode
|
|
)
|
|
{
|
|
DWORD err = 0;
|
|
SC_HANDLE hScManager;
|
|
|
|
Assert(pdwServiceStatus);
|
|
|
|
*pdwServiceStatus = 0;
|
|
|
|
if (pdwErrorCode)
|
|
*pdwErrorCode = 0;
|
|
|
|
//
|
|
// Find out if the service is running on the given machine
|
|
//
|
|
hScManager = ::OpenSCManager(pszComputer, NULL, GENERIC_READ);
|
|
if (hScManager == NULL)
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_DATABASE_DOES_NOT_EXIST
|
|
// ERROR_INVALID_PARAMETER
|
|
//
|
|
return GetLastError();
|
|
}
|
|
|
|
SC_HANDLE hService = ::OpenService(hScManager, pszServiceName, SERVICE_QUERY_STATUS);
|
|
if (hService == NULL)
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_INVALID_HANDLE
|
|
// ERROR_INVALID_NAME
|
|
// ERROR_SERVICE_DOES_NOT_EXIST
|
|
//
|
|
err = GetLastError();
|
|
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
|
|
SERVICE_STATUS serviceStatus;
|
|
if (!::QueryServiceStatus(hService, &serviceStatus))
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_INVALID_HANDLE
|
|
//
|
|
err = GetLastError();
|
|
|
|
::CloseServiceHandle(hService);
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
|
|
*pdwServiceStatus = serviceStatus.dwCurrentState;
|
|
|
|
// Also return the error code
|
|
if (pdwErrorCode)
|
|
{
|
|
if (serviceStatus.dwWin32ExitCode == ERROR_SERVICE_SPECIFIC_ERROR)
|
|
*pdwErrorCode = serviceStatus.dwServiceSpecificExitCode;
|
|
else
|
|
*pdwErrorCode = serviceStatus.dwWin32ExitCode;
|
|
}
|
|
|
|
::CloseServiceHandle(hService);
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
StartService
|
|
Starts the given service on a machine
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
TFSCORE_API(DWORD)
|
|
TFSStartService
|
|
(
|
|
LPCTSTR pszComputer,
|
|
LPCTSTR pszServiceName,
|
|
LPCTSTR pszServiceDesc
|
|
)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
DWORD err = 0;
|
|
|
|
err = StartSCMService(pszComputer, pszServiceName, pszServiceDesc);
|
|
|
|
return err;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
StartServiceEx
|
|
Starts the given service on a machine, cluster aware
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
TFSCORE_API(DWORD)
|
|
TFSStartServiceEx
|
|
(
|
|
LPCTSTR pszComputer,
|
|
LPCTSTR pszServiceName,
|
|
LPCTSTR pszClusterResourceType,
|
|
LPCTSTR pszServiceDesc
|
|
)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
DWORD err = 0;
|
|
|
|
if (FIsComputerInRunningCluster(pszComputer))
|
|
{
|
|
err = ControlClusterService(pszComputer, pszClusterResourceType, pszServiceDesc, TRUE);
|
|
}
|
|
else
|
|
{
|
|
err = StartSCMService(pszComputer, pszServiceName, pszServiceDesc);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
StopService
|
|
Stops the given service on a machine
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
TFSCORE_API(DWORD)
|
|
TFSStopService
|
|
(
|
|
LPCTSTR pszComputer,
|
|
LPCTSTR pszServiceName,
|
|
LPCTSTR pszServiceDesc
|
|
)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
DWORD err = 0;
|
|
|
|
err = StopSCMService(pszComputer, pszServiceName, pszServiceDesc);
|
|
|
|
return err;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
StopServiceEx
|
|
Stops the given service on a machine, cluster aware
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
TFSCORE_API(DWORD)
|
|
TFSStopServiceEx
|
|
(
|
|
LPCTSTR pszComputer,
|
|
LPCTSTR pszServiceName,
|
|
LPCTSTR pszClusterResourceType,
|
|
LPCTSTR pszServiceDesc
|
|
)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
DWORD err = 0;
|
|
|
|
if (FIsComputerInRunningCluster(pszComputer))
|
|
{
|
|
err = ControlClusterService(pszComputer, pszClusterResourceType, pszServiceDesc, FALSE);
|
|
}
|
|
else
|
|
{
|
|
err = StopSCMService(pszComputer, pszServiceName, pszServiceDesc);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
TFSCORE_API(DWORD) TFSGetServiceStartType(LPCWSTR pszComputer, LPCWSTR pszServiceName, DWORD *pdwStartType)
|
|
{
|
|
DWORD err = 0;
|
|
SC_HANDLE hScManager = 0;
|
|
SC_HANDLE hService = 0;
|
|
HRESULT hr = hrOK;
|
|
BOOL fReturn = FALSE;
|
|
LPQUERY_SERVICE_CONFIG pqsConfig = NULL;
|
|
DWORD cbNeeded = sizeof( QUERY_SERVICE_CONFIG );
|
|
DWORD cbSize;
|
|
|
|
//
|
|
// Find out if the service is running on the given machine
|
|
//
|
|
hScManager = ::OpenSCManager(pszComputer, NULL, GENERIC_READ);
|
|
if (hScManager == NULL)
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_DATABASE_DOES_NOT_EXIST
|
|
// ERROR_INVALID_PARAMETER
|
|
//
|
|
err = GetLastError();
|
|
goto Exit;
|
|
}
|
|
|
|
hService = ::OpenService(hScManager, pszServiceName, SERVICE_QUERY_CONFIG);
|
|
if (hService == NULL)
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_INVALID_HANDLE
|
|
// ERROR_INVALID_NAME
|
|
// ERROR_SERVICE_DOES_NOT_EXIST
|
|
//
|
|
err = GetLastError();
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
|
|
*pdwStartType = 0;
|
|
|
|
// loop, allocating the needed size
|
|
do
|
|
{
|
|
delete [] (PBYTE)pqsConfig;
|
|
|
|
pqsConfig = (LPQUERY_SERVICE_CONFIG) new BYTE[cbNeeded];
|
|
cbSize = cbNeeded;
|
|
|
|
fReturn = ::QueryServiceConfig( hService,
|
|
pqsConfig,
|
|
cbSize,
|
|
&cbNeeded );
|
|
*pdwStartType = pqsConfig->dwStartType;
|
|
delete [] (PBYTE)pqsConfig;
|
|
pqsConfig = NULL;
|
|
|
|
if (!fReturn && (cbNeeded == cbSize))
|
|
{
|
|
// error
|
|
*pdwStartType = 0;
|
|
err = GetLastError();
|
|
goto Error;
|
|
}
|
|
|
|
} while (!fReturn && (cbNeeded != cbSize));
|
|
|
|
|
|
COM_PROTECT_ERROR_LABEL;
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
|
|
if (!FHrSucceeded(hr))
|
|
{
|
|
// The only time we should get here (with an hr is for outofmemory)
|
|
err = ERROR_OUTOFMEMORY;
|
|
}
|
|
|
|
Exit:
|
|
if (err != 0)
|
|
{
|
|
*pdwStartType = 0;
|
|
}
|
|
::CloseServiceHandle(hService);
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
|
|
TFSCORE_API(DWORD) TFSSetServiceStartType(LPCWSTR pszComputer, LPCWSTR pszServiceName, DWORD dwStartType)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
DWORD err = 0;
|
|
SC_HANDLE hScManager;
|
|
|
|
//
|
|
// Open the SCManager so that we can try to stop the service
|
|
//
|
|
hScManager = ::OpenSCManager(pszComputer, NULL, SC_MANAGER_ALL_ACCESS);
|
|
if (hScManager == NULL)
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_DATABASE_DOES_NOT_EXIST
|
|
// ERROR_INVALID_PARAMETER
|
|
//
|
|
return GetLastError();
|
|
}
|
|
|
|
SC_HANDLE hService = ::OpenService(hScManager, pszServiceName, SERVICE_STOP | SERVICE_ALL_ACCESS);
|
|
if (hService == NULL)
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_INVALID_HANDLE
|
|
// ERROR_INVALID_NAME
|
|
// ERROR_SERVICE_DOES_NOT_EXIST
|
|
//
|
|
err = GetLastError();
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
|
|
if (!::ChangeServiceConfig( hService,
|
|
SERVICE_NO_CHANGE,
|
|
dwStartType,
|
|
SERVICE_NO_CHANGE,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL))
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_CIRCULAR_DEPENDENCY
|
|
// ERROR_DUP_NAME
|
|
// ERROR_INVALID_HANDLE
|
|
// ERROR_INVALID_PARAMETER
|
|
// ERROR_INVALID_SERVICE_ACCOUNT
|
|
// ERROR_SERVICE_MARKED_FOR_DELETE
|
|
//
|
|
err = ::GetLastError();
|
|
::CloseServiceHandle(hService);
|
|
::CloseServiceHandle(hScManager);
|
|
return err;
|
|
}
|
|
|
|
::CloseServiceHandle(hService);
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
|
|
DWORD
|
|
StartSCMService
|
|
(
|
|
LPCTSTR pszComputer,
|
|
LPCTSTR pszServiceName,
|
|
LPCTSTR pszServiceDesc
|
|
)
|
|
{
|
|
DWORD err = 0;
|
|
SC_HANDLE hScManager;
|
|
|
|
//
|
|
// Open the SCManager so that we can try to start the service
|
|
//
|
|
hScManager = ::OpenSCManager(pszComputer, NULL, SC_MANAGER_CONNECT );
|
|
if (hScManager == NULL)
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_DATABASE_DOES_NOT_EXIST
|
|
// ERROR_INVALID_PARAMETER
|
|
//
|
|
return GetLastError();
|
|
}
|
|
|
|
SC_HANDLE hService = ::OpenService(hScManager, pszServiceName, SERVICE_START | SERVICE_QUERY_STATUS);
|
|
if (hService == NULL)
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_INVALID_HANDLE
|
|
// ERROR_INVALID_NAME
|
|
// ERROR_SERVICE_DOES_NOT_EXIST
|
|
//
|
|
err = GetLastError();
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
|
|
SERVICE_STATUS serviceStatus;
|
|
if (!::QueryServiceStatus(hService, &serviceStatus))
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_INVALID_HANDLE
|
|
//
|
|
err = GetLastError();
|
|
::CloseServiceHandle(hService);
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
|
|
// If the service is in a start pending, do not do anything
|
|
if (serviceStatus.dwCurrentState == SERVICE_START_PENDING)
|
|
{
|
|
::CloseServiceHandle(hService);
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
err = ERROR_SERVICE_ALREADY_RUNNING;
|
|
|
|
return err;
|
|
}
|
|
|
|
if (!::StartService(hService, NULL, NULL))
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_INVALID_HANDLE
|
|
// ERROR_PATH_NOT_FOUND
|
|
// ERROR_SERVICE_ALREADY_RUNNING
|
|
// ERROR_SERVICE_DATABASE_LOCKED
|
|
// ERROR_SERVICE_DEPENDENCY_DELETED
|
|
// ERROR_SERVICE_DEPENDENCY_FAIL
|
|
// ERROR_SERVICE_DISABLED
|
|
// ERROR_SERVICE_LOGON_FAILED
|
|
// ERROR_SERVICE_MARKED_FOR_DELETE
|
|
// ERROR_SERVICE_NO_THREAD
|
|
// ERROR_SERVICE_REQUEST_TIMEOUT
|
|
//
|
|
err = GetLastError();
|
|
::CloseServiceHandle(hService);
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
|
|
//
|
|
// Put up the dialog with the funky spinning thing to
|
|
// let the user know that something is happening
|
|
//
|
|
CServiceCtrlDlg dlgServiceCtrl(hService, pszComputer, pszServiceDesc, TRUE);
|
|
|
|
dlgServiceCtrl.DoModal();
|
|
err = dlgServiceCtrl.m_dwErr;
|
|
|
|
//
|
|
// Everything started ok, close up and get going
|
|
//
|
|
::CloseServiceHandle(hService);
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
DWORD
|
|
StopSCMService
|
|
(
|
|
LPCTSTR pszComputer,
|
|
LPCTSTR pszServiceName,
|
|
LPCTSTR pszServiceDesc
|
|
)
|
|
{
|
|
DWORD err = 0;
|
|
SC_HANDLE hScManager;
|
|
LPENUM_SERVICE_STATUS lpScStatus = NULL;
|
|
DWORD dwNumService = 0, dwSize = 0, dwSizeReqd = 0, i = 0;
|
|
BOOL bRet;
|
|
|
|
|
|
//
|
|
// Open the SCManager so that we can try to stop the service
|
|
//
|
|
hScManager = ::OpenSCManager(pszComputer, NULL, SC_MANAGER_CONNECT );
|
|
if (hScManager == NULL)
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_DATABASE_DOES_NOT_EXIST
|
|
// ERROR_INVALID_PARAMETER
|
|
//
|
|
return GetLastError();
|
|
}
|
|
|
|
SC_HANDLE hService = ::OpenService(
|
|
hScManager, pszServiceName,
|
|
SERVICE_STOP | SERVICE_QUERY_STATUS |
|
|
SERVICE_ENUMERATE_DEPENDENTS
|
|
);
|
|
if (hService == NULL)
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_INVALID_HANDLE
|
|
// ERROR_INVALID_NAME
|
|
// ERROR_SERVICE_DOES_NOT_EXIST
|
|
//
|
|
err = GetLastError();
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
|
|
//
|
|
// Stop all dependent services that are currently active.
|
|
// Since the number of services is unknown (up front),
|
|
// EnumDependentServices is called atleast twice (first
|
|
// to get the size of buffer, and second to get the
|
|
// list of services). If the number of services changes
|
|
// between the calls, then EnumDependentServices is called
|
|
// one more time (as per the logic, i < 3).
|
|
//
|
|
|
|
do
|
|
{
|
|
//
|
|
// Enumerate all dependent services
|
|
//
|
|
|
|
bRet = ::EnumDependentServices(
|
|
hService, SERVICE_ACTIVE, lpScStatus, dwSize,
|
|
&dwSizeReqd, &dwNumService
|
|
);
|
|
|
|
if (!bRet && (GetLastError() == ERROR_MORE_DATA))
|
|
{
|
|
//
|
|
// Not enough buffer to hold the dependent service list,
|
|
// delete previous allocation (if any) and allocate new
|
|
// buffer of requiste size.
|
|
//
|
|
|
|
if (lpScStatus) { delete lpScStatus; lpScStatus = NULL; }
|
|
|
|
lpScStatus = reinterpret_cast<LPENUM_SERVICE_STATUS>
|
|
(new BYTE[2 * dwSizeReqd]);
|
|
if (lpScStatus == NULL)
|
|
{
|
|
//
|
|
// allocation failed, forget about stopping dependent
|
|
// services
|
|
//
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Increment attempt count. At most 3 attempts will be made
|
|
// to get the list of dependent services
|
|
//
|
|
|
|
dwSize = 2 * dwSizeReqd;
|
|
dwSizeReqd = 0;
|
|
i++;
|
|
}
|
|
|
|
else
|
|
{
|
|
//
|
|
// Success or failure for other than insufficent buffer reason
|
|
//
|
|
|
|
break;
|
|
}
|
|
|
|
} while( i < 3 );
|
|
|
|
//
|
|
// if dependent service were successfully enumerated
|
|
// stop them all
|
|
//
|
|
|
|
if (bRet)
|
|
{
|
|
for (i = 0; i < dwNumService; i++)
|
|
{
|
|
StopSCMService(
|
|
pszComputer,
|
|
lpScStatus[i].lpServiceName,
|
|
lpScStatus[i].lpDisplayName
|
|
);
|
|
}
|
|
}
|
|
|
|
if (lpScStatus) { delete lpScStatus; lpScStatus = NULL; }
|
|
|
|
//
|
|
// Stop the service, now that all dependents have been stopped
|
|
//
|
|
|
|
SERVICE_STATUS serviceStatus;
|
|
if (!::ControlService(hService, SERVICE_CONTROL_STOP, &serviceStatus))
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_DEPENDENT_SERVICES_RUNNING
|
|
// ERROR_INVALID_SERVICE_CONTROL
|
|
// ERROR_SERVICE_CANNOT_ACCEPT_CTRL
|
|
// ERROR_SERVICE_NOT_ACTIVE
|
|
// ERROR_SERVICE_REQUEST_TIMEOUT
|
|
//
|
|
err = GetLastError();
|
|
::CloseServiceHandle(hService);
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
|
|
if ( serviceStatus.dwCurrentState != SERVICE_STOPPED )
|
|
{
|
|
//
|
|
// Put up the dialog with the funky spinning thing to
|
|
// let the user know that something is happening
|
|
//
|
|
CServiceCtrlDlg dlgServiceCtrl(hService, pszComputer, pszServiceDesc, FALSE);
|
|
|
|
dlgServiceCtrl.DoModal();
|
|
err = dlgServiceCtrl.m_dwErr;
|
|
}
|
|
|
|
//
|
|
// Everything stopped ok, close up and get going
|
|
//
|
|
::CloseServiceHandle(hService);
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
TFSCORE_API(DWORD) TFSPauseService(LPCTSTR pszComputer, LPCTSTR pszServiceName, LPCTSTR pszServiceDesc)
|
|
{
|
|
return PauseSCMService(pszComputer, pszServiceName, pszServiceDesc);
|
|
}
|
|
|
|
|
|
|
|
TFSCORE_API(DWORD) TFSResumeService(LPCTSTR pszComputer, LPCTSTR pszServiceName, LPCTSTR pszServiceDesc)
|
|
{
|
|
return ResumeSCMService(pszComputer, pszServiceName, pszServiceDesc);
|
|
}
|
|
|
|
|
|
DWORD
|
|
PauseSCMService
|
|
(
|
|
LPCTSTR pszComputer,
|
|
LPCTSTR pszServiceName,
|
|
LPCTSTR pszServiceDesc
|
|
)
|
|
{
|
|
DWORD err = 0;
|
|
SC_HANDLE hScManager;
|
|
|
|
//
|
|
// Open the SCManager so that we can try to stop the service
|
|
//
|
|
hScManager = ::OpenSCManager(pszComputer, NULL, SC_MANAGER_CONNECT );
|
|
if (hScManager == NULL)
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_DATABASE_DOES_NOT_EXIST
|
|
// ERROR_INVALID_PARAMETER
|
|
//
|
|
return GetLastError();
|
|
}
|
|
|
|
SC_HANDLE hService = ::OpenService(hScManager, pszServiceName, SERVICE_PAUSE_CONTINUE | SERVICE_QUERY_STATUS);
|
|
if (hService == NULL)
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_INVALID_HANDLE
|
|
// ERROR_INVALID_NAME
|
|
// ERROR_SERVICE_DOES_NOT_EXIST
|
|
//
|
|
err = GetLastError();
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
|
|
SERVICE_STATUS serviceStatus;
|
|
if (!::ControlService(hService, SERVICE_CONTROL_PAUSE, &serviceStatus))
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_DEPENDENT_SERVICES_RUNNING
|
|
// ERROR_INVALID_SERVICE_CONTROL
|
|
// ERROR_SERVICE_CANNOT_ACCEPT_CTRL
|
|
// ERROR_SERVICE_NOT_ACTIVE
|
|
// ERROR_SERVICE_REQUEST_TIMEOUT
|
|
//
|
|
err = GetLastError();
|
|
::CloseServiceHandle(hService);
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
|
|
#if 0
|
|
if ( serviceStatus.dwCurrentState != SERVICE_STOPPED )
|
|
{
|
|
//
|
|
// Put up the dialog with the funky spinning thing to
|
|
// let the user know that something is happening
|
|
//
|
|
CServiceCtrlDlg dlgServiceCtrl(hService, pszComputer, pszServiceDesc, FALSE);
|
|
|
|
dlgServiceCtrl.DoModal();
|
|
err = dlgServiceCtrl.m_dwErr;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Everything stopped ok, close up and get going
|
|
//
|
|
::CloseServiceHandle(hService);
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
|
|
DWORD
|
|
ResumeSCMService
|
|
(
|
|
LPCTSTR pszComputer,
|
|
LPCTSTR pszServiceName,
|
|
LPCTSTR pszServiceDesc
|
|
)
|
|
{
|
|
DWORD err = 0;
|
|
SC_HANDLE hScManager;
|
|
|
|
//
|
|
// Open the SCManager so that we can try to stop the service
|
|
//
|
|
hScManager = ::OpenSCManager(pszComputer, NULL, SC_MANAGER_CONNECT );
|
|
if (hScManager == NULL)
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_DATABASE_DOES_NOT_EXIST
|
|
// ERROR_INVALID_PARAMETER
|
|
//
|
|
return GetLastError();
|
|
}
|
|
|
|
SC_HANDLE hService = ::OpenService(hScManager, pszServiceName, SERVICE_PAUSE_CONTINUE | SERVICE_QUERY_STATUS);
|
|
if (hService == NULL)
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_INVALID_HANDLE
|
|
// ERROR_INVALID_NAME
|
|
// ERROR_SERVICE_DOES_NOT_EXIST
|
|
//
|
|
err = GetLastError();
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
|
|
SERVICE_STATUS serviceStatus;
|
|
if (!::ControlService(hService, SERVICE_CONTROL_CONTINUE, &serviceStatus))
|
|
{
|
|
//
|
|
// Possible Errors:
|
|
// ERROR_ACCESS_DENIED
|
|
// ERROR_DEPENDENT_SERVICES_RUNNING
|
|
// ERROR_INVALID_SERVICE_CONTROL
|
|
// ERROR_SERVICE_CANNOT_ACCEPT_CTRL
|
|
// ERROR_SERVICE_NOT_ACTIVE
|
|
// ERROR_SERVICE_REQUEST_TIMEOUT
|
|
//
|
|
err = GetLastError();
|
|
::CloseServiceHandle(hService);
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
#if 0
|
|
if ( serviceStatus.dwCurrentState != SERVICE_STOPPED )
|
|
{
|
|
//
|
|
// Put up the dialog with the funky spinning thing to
|
|
// let the user know that something is happening
|
|
//
|
|
CServiceCtrlDlg dlgServiceCtrl(hService, pszComputer, pszServiceDesc, FALSE);
|
|
|
|
dlgServiceCtrl.DoModal();
|
|
err = dlgServiceCtrl.m_dwErr;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Everything stopped ok, close up and get going
|
|
//
|
|
::CloseServiceHandle(hService);
|
|
::CloseServiceHandle(hScManager);
|
|
|
|
return err;
|
|
}
|
|
|