//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1997 - 1998 // // File: C S E R V I C E . H // // Contents: This file contains CService and CServiceManager, wrapper // classes to the Win32 Service APIs. // // Notes: Note that not all functionallity is currently extended through // these classes. // Note that most functionality is inline in this file. What is // not inline is in cservice.cpp // // Author: mikemi 6 Mar 1997 // //---------------------------------------------------------------------------- #ifndef _CSERVICE_H_ #define _CSERVICE_H_ //#include "debugx.h" //#include "ncbase.h" //------------------------------------------------------------------- // // //------------------------------------------------------------------- size_t CchMsz(const TCHAR * msz); class CService { friend class CServiceManager; public: CService() { _schandle = NULL; }; ~CService() { Close(); }; VOID Close() { BOOL frt; if (_schandle) { frt = ::CloseServiceHandle( _schandle ); AssertSz(frt, "CloseServiceHandle failed!"); _schandle = NULL; } } HRESULT HrDelete() { Assert(_schandle != NULL ); if (::DeleteService( _schandle )) return S_OK; else return HRESULT_FROM_WIN32(GetLastError()); } HRESULT HrStart( DWORD cNumServiceArgs = 0, LPCTSTR* papServiceArgs = NULL) { Assert(_schandle != NULL ); if (::StartService( _schandle, cNumServiceArgs, papServiceArgs )) return S_OK; else return HRESULT_FROM_WIN32(GetLastError()); } HRESULT HrControl( DWORD dwControl ) { SERVICE_STATUS sStatus; Assert(_schandle != NULL ); AssertSz((dwControl != SERVICE_CONTROL_INTERROGATE), "CService::HrControl does not support the SERVICE_CONTROL_INTERROGATE flag"); if ( ::ControlService( _schandle, dwControl, &sStatus )) return S_OK; else return HRESULT_FROM_WIN32(GetLastError()); } HRESULT HrMoveOutOfState( DWORD dwState ); HRESULT HrQueryState( DWORD* pdwState ); HRESULT HrQueryStartType( DWORD* pdwStartType ); HRESULT HrSetStartType( DWORD dwStartType ) { Assert(_schandle != NULL ); if (::ChangeServiceConfig( _schandle, SERVICE_NO_CHANGE, dwStartType, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) return S_OK; else return HRESULT_FROM_WIN32(GetLastError()); } HRESULT HrQueryDependencies(OUT LPTSTR * pmszDependencyList); HRESULT HrSetDependencies(IN LPCTSTR mszDependencyList) { Assert(_schandle != NULL ); if (::ChangeServiceConfig( _schandle, SERVICE_NO_CHANGE, // ServiceType SERVICE_NO_CHANGE, // StartType SERVICE_NO_CHANGE, // ErrorControl NULL, // BinaryPathName NULL, // LoadOredrGroup NULL, // TagId mszDependencyList, // Dependencies NULL, // ServiceStartName NULL, // Password NULL)) // DisplayName return S_OK; else return HRESULT_FROM_WIN32(GetLastError()); } HRESULT HrSetDisplayName(IN LPCTSTR mszDisplayName) { Assert(_schandle != NULL ); if (::ChangeServiceConfig( _schandle, SERVICE_NO_CHANGE, // ServiceType SERVICE_NO_CHANGE, // StartType SERVICE_NO_CHANGE, // ErrorControl NULL, // BinaryPathName NULL, // LoadOredrGroup NULL, // TagId NULL, // Dependencies NULL, // ServiceStartName NULL, // Password mszDisplayName)) // DisplayName { return S_OK; } else { return HRESULT_FROM_WIN32(GetLastError()); } } HRESULT HrSetServiceObjectSecurity( SECURITY_INFORMATION dwSecurityInformation, PSECURITY_DESCRIPTOR lpSecurityDescriptor) { Assert(_schandle != NULL ); if (::SetServiceObjectSecurity( _schandle, dwSecurityInformation, lpSecurityDescriptor)) { return S_OK; } else { return HRESULT_FROM_WIN32(GetLastError()); } } private: SC_HANDLE _schandle; }; //------------------------------------------------------------------- // // //------------------------------------------------------------------- class CServiceManager { public: CServiceManager() { _schandle = NULL; _sclock = NULL; }; ~CServiceManager() { if (_sclock) { Unlock(); } if (_schandle) { Close(); } }; HRESULT HrOpen( DWORD dwDesiredAccess = SC_MANAGER_ALL_ACCESS, LPCTSTR pszMachineName = NULL, LPCTSTR pszDatabaseName = NULL ) { if (_schandle != NULL) { Close(); } _schandle = ::OpenSCManager( pszMachineName, pszDatabaseName, dwDesiredAccess ); if ( _schandle != NULL ) return S_OK; else return HRESULT_FROM_WIN32(GetLastError()); } VOID Close() { BOOL frt; Assert(_schandle != NULL ); frt = ::CloseServiceHandle( _schandle ); _schandle = NULL; AssertSz(frt, "CloseServiceHandle failed!"); } HRESULT HrLock() { INT cRetries = 3; static const INT c_secWait = 30; static const INT c_msecWait = (c_secWait / (cRetries - 1)) * 1000; Assert(_schandle != NULL ); Assert(_sclock == NULL ); while (cRetries--) { _sclock = ::LockServiceDatabase( _schandle ); if (_sclock != NULL) return S_OK; else { if (GetLastError() != ERROR_SERVICE_DATABASE_LOCKED || !cRetries) { return HRESULT_FROM_WIN32(GetLastError()); } Trace1("SCM is locked, waiting for %d seconds before retrying...", c_msecWait / 1000); // wait for a bit to see if the database unlocks in that Sleep(c_msecWait); } } AssertSz(FALSE, "HrLock error"); return S_OK; } VOID Unlock() { BOOL frt; Assert(_schandle != NULL ); Assert(_sclock != NULL ); frt = ::UnlockServiceDatabase( _sclock ); _sclock = NULL; AssertSz(frt, "UnlockServiceDatabase failed!"); } HRESULT HrQueryLocked(BOOL *pfLocked); HRESULT HrOpenService( CService* pcsService, LPCTSTR pszServiceName, DWORD dwDesiredAccess = SERVICE_ALL_ACCESS ) { // make sure the service is not in use if (pcsService->_schandle != NULL) { pcsService->Close(); } pcsService->_schandle = ::OpenService( _schandle, pszServiceName, dwDesiredAccess ); if ( pcsService->_schandle != NULL ) return S_OK; else { DWORD dw=GetLastError(); return HRESULT_FROM_WIN32(dw); } } HRESULT HrCreateService( CService* pcsService, LPCTSTR pszServiceName, LPCTSTR pszDisplayName, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCTSTR pszBinaryPathName, LPCTSTR pslzDependencies = NULL, LPCTSTR pszLoadOrderGroup = NULL, PDWORD pdwTagId = NULL, DWORD dwDesiredAccess = SERVICE_ALL_ACCESS, LPCTSTR pszServiceStartName = NULL, LPCTSTR pszPassword = NULL ) { // make sure the service is not in use if (pcsService->_schandle != NULL) { pcsService->Close(); } pcsService->_schandle = ::CreateService( _schandle, pszServiceName, pszDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, pszBinaryPathName, pszLoadOrderGroup, pdwTagId, pslzDependencies, pszServiceStartName, pszPassword ); if ( pcsService->_schandle != NULL ) return S_OK; else return HRESULT_FROM_WIN32(GetLastError()); } enum SERVICE_START_CRITERIA { SERVICE_NO_CRITERIA, // Start the service regardless SERVICE_ONLY_AUTO_START // Only start the service if it is of type // Auto-Start }; HRESULT HrStartService(LPCTSTR szService) { return (HrStartServiceHelper(szService, SERVICE_NO_CRITERIA)); } HRESULT HrStartAutoStartService(LPCTSTR szService) { return (HrStartServiceHelper(szService, SERVICE_ONLY_AUTO_START)); } HRESULT HrStartServiceHelper(LPCTSTR szService, SERVICE_START_CRITERIA eCriteria); HRESULT HrStopService(LPCTSTR szService); enum DEPENDENCY_ADDREMOVE { DEPENDENCY_ADD, DEPENDENCY_REMOVE }; HRESULT HrAddServiceDependency(LPCTSTR szServiceName, LPCTSTR szDependency) { return HrAddRemoveServiceDependency(szServiceName, szDependency, DEPENDENCY_ADD); } HRESULT HrRemoveServiceDependency(LPCTSTR szServiceName, LPCTSTR szDependency) { return HrAddRemoveServiceDependency(szServiceName, szDependency, DEPENDENCY_REMOVE); } HRESULT HrAddRemoveServiceDependency(LPCTSTR szServiceName, LPCTSTR szDependency, DEPENDENCY_ADDREMOVE enumFlag); private: SC_HANDLE _schandle; SC_LOCK _sclock; }; #endif // _CSERVICE_H_