#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