K
und noch die Service Klasse:
// cService.h: interface for the cService class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_CSERVICE_H__FD1A6E41_AAFB_11D7_A8B4_000AE637F271__INCLUDED_)
#define AFX_CSERVICE_H__FD1A6E41_AAFB_11D7_A8B4_000AE637F271__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "winsvc.h"
class cService
{
public:
cService();
virtual ~cService();
DWORD Start();
DWORD Stop();
DWORD Create();
DWORD Delete();
void Dispatch();
void MainStart (DWORD argc, LPTSTR *argv);
void ControlHandler (DWORD Opcode);
Set Settings;
List JobList;
AppPathStr AppPathSt;
bool Running;
private:
SERVICE_STATUS_HANDLE hdlStat;
};
#endif // !defined(AFX_CSERVICE_H__FD1A6E41_AAFB_11D7_A8B4_000AE637F271__INCLUDED_)
// cService.cpp: implementation of the cService class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Service.h"
#include "cService.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
extern Set Settings;
// global instance of Service
cService g_Service;
cService::cService()
{
Running = false;
}
cService::~cService()
{
}
// return Errorcode or 0
// Install the service when user clicks the Create button
DWORD cService::Create()
{
SC_HANDLE hdlSCM = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
CString Calling = ::GetCommandLine();
Calling += " /Service";
if (hdlSCM == 0) return ::GetLastError();
SC_HANDLE hdlServ = CreateService(
hdlSCM, // SCManager database
ServiceName, // name of service
ServiceDisplayName, // service name to display
STANDARD_RIGHTS_REQUIRED, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_DEMAND_START, // start type
SERVICE_ERROR_NORMAL, // error control type
Calling, // service's binary Path name
0, // no load ordering group
0, // no tag identifier
0, // no dependencies
0, // LocalSystem account
0); // no password
DWORD Ret = 0;
if (!hdlServ) Ret = ::GetLastError();
CloseServiceHandle(hdlServ);
return Ret;
}
// return Errorcode or 0
// Uninstall the service when user clicks the Delete button
DWORD cService::Delete()
{
SC_HANDLE hdlSCM = OpenSCManager(0, 0, STANDARD_RIGHTS_REQUIRED);
if (!hdlSCM) return ::GetLastError();
SC_HANDLE hdlServ = OpenService(hdlSCM, ServiceName, DELETE);
DWORD Ret = 0;
if (!DeleteService(hdlServ)) Ret = ::GetLastError();
CloseServiceHandle(hdlServ);
return Ret;
}
// return Errorcode or 0
// Start the service when user clicks the Start button
DWORD cService::Start()
{
SC_HANDLE hdlSCM = OpenSCManager(0, 0, STANDARD_RIGHTS_REQUIRED);
if (!hdlSCM) return ::GetLastError();
SC_HANDLE hdlServ = OpenService(hdlSCM, ServiceName, SERVICE_START);
DWORD Ret = 0;
if (!StartService(hdlServ, 0, 0)) Ret = ::GetLastError();
CloseServiceHandle(hdlServ);
Running = true;
return Ret;
}
// return Errorcode or 0
// Stop the service when user clicks the Stop button
DWORD cService::Stop()
{
SC_HANDLE hdlSCM = OpenSCManager(0, 0, STANDARD_RIGHTS_REQUIRED);
if (!hdlSCM) return ::GetLastError();
SC_HANDLE hdlServ = OpenService(hdlSCM, ServiceName, SERVICE_STOP);
SERVICE_STATUS ServStat;
DWORD Ret = 0;
if (!ControlService(hdlServ, SERVICE_CONTROL_STOP, &ServStat)) Ret = ::GetLastError();
CloseServiceHandle(hdlServ);
Running = false;
return Ret;
}
// this function must be in global namespace (Windows API callback)
void ApiServiceMainStarter(DWORD argc, LPTSTR *argv);
void ApiServiceMainStarter(DWORD argc, LPTSTR *argv)
{
g_Service.MainStart(argc, argv);
}
// this function must be in global namespace (Windows API callback)
void ApiServiceControlHandler(DWORD Opcode);
void ApiServiceControlHandler(DWORD Opcode)
{
g_Service.ControlHandler(Opcode);
}
// Service Main Function called by Windows
void cService::MainStart(DWORD argc, LPTSTR *argv)
{
CString Out = *argv;
//Output("Service Main -- Start with Arguments: \"" + Out + "\"");
if(!AfxSocketInit())
{
AfxMessageBox("Could not initialize Windows Sockets!");
return ;
}
hdlStat = ::RegisterServiceCtrlHandler(ServiceName, (LPHANDLER_FUNCTION) ApiServiceControlHandler);
if (!hdlStat)
{
int Err = ::GetLastError();
Out.Format("Service Main -- RegisterServiceHandler Error : %d\n", Err);
//Output(Out);
return;
}
//else Output("Service Main -- RegisterServiceHandler");
ControlHandler (0); // Set status Running
LoadAppPath(&AppPathSt);
LoadSettings(&Settings);
LoadJobs(&JobList);
EndlessLoop(); // Do the service work (write to logfile every 5 seconds)
JobList.DelAll();
}
// Start the service (in the Exe which is running as Service!!)
void cService::Dispatch()
{
SERVICE_TABLE_ENTRY DispTbl[] =
{
{ ServiceName, (LPSERVICE_MAIN_FUNCTION) ApiServiceMainStarter},
{ 0 , 0}
};
//Output("Dispatch -- Before calling StartServiceCtrlDispatcher\n");
if (!::StartServiceCtrlDispatcher(DispTbl)) // does not return until service stopped
{
int Err = ::GetLastError();
CString Out;
Out.Format("Dispatch -- StartServiceCtrlDispatcher Error : %d\n", Err);
//Output(Out);
}
//else Output("Dispatch -- Returning from StartServiceCtrlDispatcher\n");
}
// Control Handler handles Start / Stop events
void cService::ControlHandler(DWORD Opcode)
{
SERVICE_STATUS strctStat;
strctStat.dwServiceType = SERVICE_WIN32;
strctStat.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
strctStat.dwWin32ExitCode = NO_ERROR;
strctStat.dwServiceSpecificExitCode = 0; // returned Status code
strctStat.dwCheckPoint = 0; // returned Error code
strctStat.dwWaitHint = 0;
CString Command, Status;
if (Opcode == SERVICE_CONTROL_STOP)
{
Command = "CONTROL_STOP";
strctStat.dwCurrentState = SERVICE_STOPPED;
Status = "SERVICE_STOPPED";
}
else if (Opcode == SERVICE_CONTROL_SHUTDOWN)
{
Command = "CONTROL_SHUTDOWN";
strctStat.dwCurrentState = SERVICE_STOPPED;
Status = "SERVICE_STOPPED";
}
else if (Opcode == SERVICE_CONTROL_INTERROGATE)
{
Command = "CONTROL_INTERROGATE";
strctStat.dwCurrentState = SERVICE_RUNNING;
Status = "SERVICE_RUNNING";
}
else
{
Command.Format("Command Opcode Nr. %d ", Opcode);
strctStat.dwCurrentState = SERVICE_RUNNING;
Status = "SERVICE_RUNNING";
}
//if (Opcode != 0) Output("Control Handler -- received Command "+Command);
if (!SetServiceStatus (hdlStat, &strctStat))
{
int Err = ::GetLastError();
CString Out;
Out.Format("Control Handler -- Set Status Error : %d", Err);
// Output(Out);
return;
}
//else Output("Control Handler -- SetStatus "+Status);
}