Listing 2: Implementation file for NTService class
#include <windows.h> #include "ntservice.h" NTService::NTService( const char *name, LPSERVICE_MAIN_FUNCTION funp_srvmain, LPHANDLER_FUNCTION funp_ctrl) { //== first initialize data members from the args //== set function pointers for later use mfpSrvMain = funp_srvmain; mfpSrvControl = funp_ctrl; //== copy the service name - if needed add UNICODE support here memset( m_name, 0, sizeof(m_name) ); strncpy( m_name, name, sizeof(m_name)-1); //== clear the status flags m_isStarted = false; m_isPaused = false; //== clear the dispatch table memset( &mDispatchTable[0], 0, sizeof( mDispatchTable ) ); //== clear the SERVICE_STATUS data structure memset( &mStat, 0, sizeof( SERVICE_STATUS )); mh_Stat = 0; //== Now initialize SERVICE_STATUS here so we can //== call SetAcceptedControls() before Startup() or //== override in constructor of child class. mStat.dwServiceType = SERVICE_WIN32; mStat.dwCurrentState = SERVICE_START_PENDING; mStat.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN; } NTService::~NTService( void ) { } DWORD NTService::Startup( void ) { //== initialize the dispatch table mDispatchTable[0].lpServiceName = m_name; //== Note: these mDispatchTable[0].lpServiceProc = mfpSrvMain; // are pointers //== starts the service if( !StartServiceCtrlDispatcher( mDispatchTable )){ m_err = ::GetLastError(); return m_err; } return NO_ERROR; } int NTService::Service( DWORD argc, LPTSTR* argv ) { mh_Stat = RegisterServiceCtrlHandler( TEXT( m_name ), mfpSrvControl ); if( (SERVICE_STATUS_HANDLE)0 == mh_Stat ) { m_err = ::GetLastError(); return m_err; } if( Init( argc, argv ) != NO_ERROR ) { ChangeStatus( SERVICE_STOPPED ); return m_err; } ChangeStatus( SERVICE_RUNNING ); return Run(); } void NTService::Control( DWORD opcode ) { switch( opcode ) { case SERVICE_CONTROL_PAUSE: ChangeStatus( SERVICE_PAUSE_PENDING ); if( OnPause() == NO_ERROR ) { m_isPaused = true; ChangeStatus( SERVICE_PAUSED ); } break; case SERVICE_CONTROL_CONTINUE: ChangeStatus( SERVICE_CONTINUE_PENDING ); if( OnContinue() == NO_ERROR ) { m_isPaused = false; ChangeStatus( SERVICE_RUNNING ); } break; case SERVICE_CONTROL_STOP: ChangeStatus( SERVICE_STOP_PENDING ); OnStop(); ChangeStatus( SERVICE_STOPPED ); break; case SERVICE_CONTROL_SHUTDOWN: ChangeStatus( SERVICE_STOP_PENDING ); OnShutdown(); ChangeStatus( SERVICE_STOPPED ); break; case SERVICE_CONTROL_INTERROGATE: OnInquire(); SetServiceStatus( mh_Stat, &mStat ); break; default: OnUserControl( opcode ); SetServiceStatus( mh_Stat, &mStat ); break; }; return; } bool NTService::Install( void ) { //== check to see if we are already installled if( IsInstalled() ) return true; //== get the service manager handle SC_HANDLE schSCMgr = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if( schSCMgr == NULL ) { m_err = ::GetLastError(); return false; } //== get the full path of the executable char szFilePath[_MAX_PATH]; ::GetModuleFileName(NULL, szFilePath, sizeof(szFilePath)); //== install the service SC_HANDLE schSrv = CreateService( schSCMgr, m_name, m_name, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, szFilePath, NULL, NULL, NULL, NULL, NULL ); bool bRetval = true; if( schSrv == NULL ) { m_err = ::GetLastError(); bRetval = false; } else InstallAid(); //== overload to add registry entries // if needed //== All done, so pick up our toys and go home! CloseServiceHandle( schSrv ); CloseServiceHandle( schSCMgr ); return bRetval; } bool NTService::UnInstall( void ) { if( !IsInstalled() ) return true; //== get the service manager handle SC_HANDLE schSCMgr = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if( schSCMgr == NULL ) { m_err = ::GetLastError(); return false; } //== Get the service handle SC_HANDLE schSrv = OpenService( schSCMgr, m_name, DELETE ); if( schSrv == NULL ) { m_err = ::GetLastError(); CloseServiceHandle( schSCMgr ); return false; } //== Now delete the service bool bRetval = true; if( !DeleteService( schSrv ) ) { bRetval = false; m_err = ::GetLastError(); } //== do any application specific cleanup UnInstallAid(); //== Put away toys and go home! CloseServiceHandle( schSrv ); CloseServiceHandle( schSCMgr ); return bRetval; } DWORD NTService::GetLastError( void ) { return m_err; } /*================================================================= bool NTService::IsInstalled() Purpose: Returns true if the service has already been installed. =================================================================*/ bool NTService::IsInstalled( void ) { bool bResult = false; // Open the Service Control Manager SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (hSCM) { // Try to open the service SC_HANDLE hService = ::OpenService(hSCM, m_name, SERVICE_QUERY_CONFIG); if (hService) { bResult = true; ::CloseServiceHandle(hService); } ::CloseServiceHandle(hSCM); } return bResult; } void NTService::SetAcceptedControls( DWORD controls ) { mStat.dwControlsAccepted = controls; } void NTService::ChangeStatus( DWORD state, DWORD checkpoint, DWORD waithint ) { mStat.dwCurrentState = state; mStat.dwCheckPoint = checkpoint; mStat.dwWaitHint = waithint; SetServiceStatus( mh_Stat, &mStat ); } /*================================================================= Stubs =================================================================*/ DWORD NTService::Init( DWORD argc, LPTSTR* argv ) { return NO_ERROR; } void NTService::InstallAid( void ) {} void NTService::UnInstallAid( void ) {} DWORD NTService::OnPause( void ) { return NO_ERROR; } DWORD NTService::OnContinue( void ) { return NO_ERROR; } void NTService::OnStop( void ) {} void NTService::OnShutdown( void ) { OnStop(); } void NTService::OnInquire( void ) {} void NTService::OnUserControl( DWORD ) {} //End of File