#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=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