Windows2003-3790/inetsrv/pop3/inc/servutil.h
2020-09-30 16:53:55 +02:00

474 lines
18 KiB
C

#ifndef _SERVUTIL_H_
#define _SERVUTIL_H_
// forward reference
HRESULT _StopService (LPTSTR szServiceName, BOOL bIncludeDependentServices = FALSE, LPTSTR szMachineName = NULL );
inline HRESULT _ChangeServiceStartType (LPTSTR szServiceName, DWORD dwServiceStartType)
{
HRESULT hr = S_OK;
SC_HANDLE hManager = OpenSCManager(NULL, NULL, STANDARD_RIGHTS_REQUIRED);
if (hManager == NULL)
hr = GetLastError();
else {
// stop service if it's running
SC_HANDLE hService = OpenService (hManager, szServiceName, SERVICE_ALL_ACCESS);
if (!hService)
hr = GetLastError();
else {
if (!ChangeServiceConfig (hService,
SERVICE_NO_CHANGE, // service type
dwServiceStartType, // start type
SERVICE_NO_CHANGE, // error control
NULL, NULL, NULL, NULL, NULL, NULL, NULL))
hr = GetLastError();
CloseServiceHandle (hService);
}
CloseServiceHandle (hManager);
}
return HRESULT_FROM_WIN32(hr);
}
inline DWORD _GetServiceStatus (LPTSTR szServiceName, LPTSTR szMachineName = NULL)
{
DWORD dwStatus = 0;
SC_HANDLE hSCManager = OpenSCManager (szMachineName,
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (hSCManager != NULL) {
SC_HANDLE hService = OpenService (hSCManager,
szServiceName,
SERVICE_QUERY_STATUS);
if (hService) {
SERVICE_STATUS ss = {0};
if (QueryServiceStatus (hService, &ss))
dwStatus = ss.dwCurrentState;
CloseServiceHandle (hService);
}
CloseServiceHandle (hSCManager);
}
return dwStatus;
}
inline BOOL _IsServiceStartType (LPTSTR szServiceName, DWORD dwServiceStartType)
{
BOOL b = FALSE;
SC_HANDLE hSCManager = OpenSCManager (NULL, // local machine
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (hSCManager != NULL) {
SC_HANDLE hService = OpenService (hSCManager,
szServiceName,
SERVICE_ALL_ACCESS);
if (hService) {
DWORD dwSize = 0;
if (0 == QueryServiceConfig (hService, NULL, dwSize, &dwSize))
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
QUERY_SERVICE_CONFIG* pQSC = (QUERY_SERVICE_CONFIG*)malloc (dwSize);
if (pQSC) {
if (QueryServiceConfig (hService, pQSC, dwSize, &dwSize)) {
if (pQSC->dwStartType == dwServiceStartType)
b = TRUE;
}
free (pQSC);
}
}
CloseServiceHandle (hService);
}
CloseServiceHandle (hSCManager);
}
return b;
}
inline BOOL _IsServiceStatus (LPTSTR szServiceName, DWORD dwServiceStatus)
{
BOOL b = FALSE;
SC_HANDLE hSCManager = OpenSCManager (NULL, // local machine
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (hSCManager != NULL) {
SC_HANDLE hService = OpenService (hSCManager,
szServiceName,
SERVICE_QUERY_STATUS);
if (hService) {
SERVICE_STATUS ss = {0};
if (QueryServiceStatus (hService, &ss))
if (ss.dwCurrentState == dwServiceStatus)
b = TRUE;
CloseServiceHandle (hService);
}
CloseServiceHandle (hSCManager);
}
return b;
}
inline BOOL _IsServiceRunning (LPTSTR szServiceName)
{
return _IsServiceStatus (szServiceName, SERVICE_RUNNING);
}
inline BOOL _IsServiceInstalled (LPTSTR szServiceName)
{
BOOL b = FALSE;
SC_HANDLE hSCManager = OpenSCManager (NULL, // local machine
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (hSCManager != NULL) {
SC_HANDLE hService = OpenService (hSCManager,
szServiceName,
SERVICE_QUERY_STATUS);
if (hService) {
b = TRUE;
CloseServiceHandle (hService);
}
CloseServiceHandle (hSCManager);
}
return b;
}
// private inline
inline long __WaitForServiceStatus (SC_HANDLE hService, DWORD dwStatus)
{
SetLastError (0);
int iIOPendingErrors = 0;
SERVICE_STATUS ssStatus;
if (!QueryServiceStatus (hService, &ssStatus))
return GetLastError();
if (dwStatus == SERVICE_STOPPED) {
if (!(ssStatus.dwControlsAccepted & SERVICE_ACCEPT_STOP)) {
// service doesn't accept stop!
// return appropriate error
if (ssStatus.dwCurrentState == dwStatus)
return S_OK;
if (ssStatus.dwWin32ExitCode == ERROR_SERVICE_SPECIFIC_ERROR) {
if (ssStatus.dwServiceSpecificExitCode == 0)
return ERROR_INVALID_SERVICE_CONTROL;
return ssStatus.dwServiceSpecificExitCode;
}
if (ssStatus.dwWin32ExitCode != 0)
return ssStatus.dwWin32ExitCode;
return ERROR_INVALID_SERVICE_CONTROL;
}
}
DWORD dwOldCheckPoint, dwOldCurrentState;
while (ssStatus.dwCurrentState != dwStatus) {
// Save the current checkpoint.
dwOldCheckPoint = ssStatus.dwCheckPoint;
dwOldCurrentState = ssStatus.dwCurrentState;
// Wait for the specified interval.
int iSleep = ssStatus.dwWaitHint;
if (iSleep > 2500)
iSleep = 2500;
if (iSleep == 0)
iSleep = 100;
Sleep (iSleep);
// Check the status again.
SetLastError (0);
if (!QueryServiceStatus (hService, &ssStatus))
return GetLastError();
// Break if the checkpoint has not been incremented.
if (dwOldCheckPoint == ssStatus.dwCheckPoint)
if (dwOldCurrentState == ssStatus.dwCurrentState) {
// ok: at this point, we're supposed to be done, or there's an error
if (ssStatus.dwCurrentState == dwStatus)
break;
if (ssStatus.dwWin32ExitCode != 0)
break;
// some kinda screw up: we're not done and no error!
// so, give 'em one last chance....
Sleep (1000);
SetLastError (0);
if (!QueryServiceStatus (hService, &ssStatus))
return GetLastError();
if (dwOldCheckPoint == ssStatus.dwCheckPoint)
if (dwOldCurrentState == ssStatus.dwCurrentState) {
// empirical: I keep getting this when actually everything is ok
if (GetLastError() == ERROR_IO_PENDING)
if (iIOPendingErrors++ < 60)
continue;
break;
}
// if we get here, either the checkpoint or status changed, and we can keep going
}
}
if (ssStatus.dwCurrentState == dwStatus)
return S_OK;
if (ssStatus.dwWin32ExitCode == ERROR_SERVICE_SPECIFIC_ERROR) {
if (ssStatus.dwServiceSpecificExitCode == 0)
return E_FAIL;
return ssStatus.dwServiceSpecificExitCode;
}
if (ssStatus.dwWin32ExitCode != 0)
return ssStatus.dwWin32ExitCode;
// we should never get here
HRESULT hr = GetLastError();
return ERROR_SERVICE_REQUEST_TIMEOUT;
#ifdef BONE_HEADED_WAY
SERVICE_STATUS ssStatus;
// wait for at most 3 minutes
for (int i=0; i<180; i++) {
if (!QueryServiceStatus (hService, &ssStatus))
return HR (GetLastError()); // bad service handle?
if (ssStatus.dwCurrentState == dwStatus)
return S_OK; // all is well
Sleep(1000); // wait a second
}
return HRESULT_FROM_WIN32(ERROR_SERVICE_REQUEST_TIMEOUT);
#endif
}
inline HRESULT _RecursiveStop (SC_HANDLE hService)
{
HRESULT hr = S_OK;
DWORD dwBufSize = 1, dwNumServices = 0;
if (!EnumDependentServices (hService,
SERVICE_ACTIVE,
(LPENUM_SERVICE_STATUS)&dwBufSize,
dwBufSize,
&dwBufSize,
&dwNumServices)) {
// this should fail with ERROR_MORE_DATA, unless there are no dependent services
hr = GetLastError ();
if (hr == ERROR_MORE_DATA) {
hr = S_OK;
ENUM_SERVICE_STATUS * pBuffer = (ENUM_SERVICE_STATUS *)malloc (dwBufSize);
if (!pBuffer)
hr = E_OUTOFMEMORY;
else {
if (!EnumDependentServices (hService,
SERVICE_ACTIVE,
pBuffer,
dwBufSize,
&dwBufSize,
&dwNumServices))
hr = GetLastError(); // shouldn't happen!!!
else {
_ASSERT (dwNumServices > 0);
for (DWORD i=0; i<dwNumServices && S_OK == hr; i++) {
hr = _StopService (pBuffer[i].lpServiceName, FALSE);
}
}
free (pBuffer);
}
}
}
return HRESULT_FROM_WIN32(hr);
}
inline HRESULT _ControlService (LPTSTR szServiceName, DWORD dwControl, LPTSTR szMachineName = NULL )
{
if ( NULL == szServiceName ) return E_INVALIDARG;
if (( SERVICE_CONTROL_PAUSE != dwControl ) && ( SERVICE_CONTROL_CONTINUE != dwControl )) return E_INVALIDARG;
HRESULT hr = S_OK;
SC_HANDLE hManager;
LPTSTR psMachineName = szMachineName;
SERVICE_STATUS ss;
if ( NULL != psMachineName )
{
psMachineName = new TCHAR[ _tcslen( szMachineName ) + 3];
if ( NULL == psMachineName )
return E_OUTOFMEMORY;
_tcscpy( psMachineName, _T( "\\\\" ));
_tcscat( psMachineName, szMachineName );
}
hManager = OpenSCManager(psMachineName, NULL, STANDARD_RIGHTS_REQUIRED);
if ( NULL != psMachineName )
delete [] psMachineName;
if (hManager == NULL)
hr = GetLastError();
else {
SC_HANDLE hService = OpenService (hManager, szServiceName, SERVICE_ALL_ACCESS);
if (hService == NULL)
hr = GetLastError();
else {
if (!ControlService( hService, dwControl, &ss ))
hr = GetLastError();
else
{
if ( SERVICE_CONTROL_PAUSE == dwControl )
hr = __WaitForServiceStatus(hService, SERVICE_PAUSED);
if ( SERVICE_CONTROL_CONTINUE == dwControl )
hr = __WaitForServiceStatus(hService, SERVICE_RUNNING);
}
CloseServiceHandle (hService);
}
CloseServiceHandle (hManager);
}
return HRESULT_FROM_WIN32(hr);
}
inline HRESULT _StopService (LPTSTR szServiceName, BOOL bIncludeDependentServices, LPTSTR szMachineName /*= NULL*/ )
{
HRESULT hr = S_OK;
SC_HANDLE hManager;
LPTSTR psMachineName = szMachineName;
if ( NULL != psMachineName )
{
psMachineName = new TCHAR[ _tcslen( szMachineName ) + 3];
if ( NULL == psMachineName )
return E_OUTOFMEMORY;
_tcscpy( psMachineName, _T( "\\\\" ));
_tcscat( psMachineName, szMachineName );
}
hManager = OpenSCManager(psMachineName, NULL, STANDARD_RIGHTS_REQUIRED);
if ( NULL != psMachineName )
delete [] psMachineName;
if (hManager == NULL)
hr = GetLastError();
else {
// stop service if it's running
SC_HANDLE hService = OpenService (hManager, szServiceName, SERVICE_ALL_ACCESS);
if (!hService)
hr = GetLastError();
else {
LETS_TRY_AGAIN:
SERVICE_STATUS st;
if (!ControlService (hService, SERVICE_CONTROL_STOP, &st)) {
hr = GetLastError(); // for instance, not running
if (hr == ERROR_DEPENDENT_SERVICES_RUNNING) {
if (bIncludeDependentServices == TRUE) {
hr = _RecursiveStop (hService);
if (hr == S_OK)
goto LETS_TRY_AGAIN; // need to stop this service yet
}
}
} else
hr = __WaitForServiceStatus (hService, SERVICE_STOPPED);
CloseServiceHandle (hService);
}
CloseServiceHandle (hManager);
}
return HRESULT_FROM_WIN32(hr);
}
inline HRESULT _StartService (LPTSTR szServiceName, LPTSTR szMachineName = NULL )
{
HRESULT hr = S_OK;
SC_HANDLE hManager;
LPTSTR psMachineName = szMachineName;
if ( NULL != psMachineName )
{
psMachineName = new TCHAR[ _tcslen( szMachineName ) + 3];
if ( NULL == psMachineName )
return E_OUTOFMEMORY;
_tcscpy( psMachineName, _T( "\\\\" ));
_tcscat( psMachineName, szMachineName );
}
hManager = OpenSCManager(psMachineName, NULL, STANDARD_RIGHTS_REQUIRED);
if ( NULL != psMachineName )
delete [] psMachineName;
if (hManager == NULL)
hr = GetLastError();
else {
SC_HANDLE hService = OpenService (hManager, szServiceName, SERVICE_ALL_ACCESS);
if (hService == NULL)
hr = GetLastError();
else {
if (!StartService(hService, 0, NULL))
hr = GetLastError();
else
hr = __WaitForServiceStatus(hService, SERVICE_RUNNING);
CloseServiceHandle (hService);
}
CloseServiceHandle (hManager);
}
return HRESULT_FROM_WIN32(hr);
}
inline HRESULT _RestartService (LPTSTR szServiceName, BOOL bIncludeDependentServices = FALSE)
{
// easy on first
if (bIncludeDependentServices == FALSE) {
_StopService (szServiceName, FALSE);
return _StartService (szServiceName);
}
// get array of dependent services;
DWORD dwNumServices = 0;
ENUM_SERVICE_STATUS * pBuffer = NULL;
HRESULT hr = S_OK, hr1 = S_OK;
SC_HANDLE hManager = OpenSCManager(NULL, NULL, STANDARD_RIGHTS_REQUIRED);
if (hManager == NULL)
hr = GetLastError();
else {
// stop service if it's running
SC_HANDLE hService = OpenService (hManager, szServiceName, SERVICE_ALL_ACCESS);
if (!hService)
hr = GetLastError();
else {
DWORD dwBufSize = 1;
// this should fail with ERROR_MORE_DATA, unless there are no dependent services
if (!EnumDependentServices (hService,
SERVICE_ACTIVE,
(LPENUM_SERVICE_STATUS)&dwBufSize,
dwBufSize,
&dwBufSize,
&dwNumServices)) {
hr = GetLastError ();
if (hr == ERROR_MORE_DATA) {
hr = S_OK;
pBuffer = (ENUM_SERVICE_STATUS *)malloc (dwBufSize);
if (!pBuffer)
hr = E_OUTOFMEMORY;
else {
if (!EnumDependentServices (hService,
SERVICE_ACTIVE,
pBuffer,
dwBufSize,
&dwBufSize,
&dwNumServices))
hr = GetLastError(); // shouldn't happen!!!
}
}
}
CloseServiceHandle (hService);
}
CloseServiceHandle (hManager);
}
if (hr == S_OK) {
// stop dependent services
if (pBuffer && dwNumServices) {
for (DWORD i=0; i<dwNumServices && S_OK == hr; i++) {
hr = _StopService (pBuffer[i].lpServiceName, FALSE);
}
}
if (hr == S_OK) {
// stop this service
hr1 = _RestartService (szServiceName, FALSE);
// always start dependent services
if (pBuffer && dwNumServices) {
for (int i=(int)dwNumServices-1; i>=0 && S_OK == hr; i--) {
hr = _StartService (pBuffer[i].lpServiceName);
}
}
}
}
if (pBuffer != NULL)
free (pBuffer);
if FAILED(hr1)
hr = hr1;
return HRESULT_FROM_WIN32(hr);
}
#endif