|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "service.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tlog.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tconvert.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tfilepath.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
9f5a1b |
#ifdef _WIN32
|
|
Toshihiro Shimizu |
890ddd |
#pragma warning(disable : 4996)
|
|
Toshihiro Shimizu |
890ddd |
#include <windows.h></windows.h>
|
|
Toshihiro Shimizu |
890ddd |
#include <stdio.h></stdio.h>
|
|
Toshihiro Shimizu |
890ddd |
#include <stdlib.h></stdlib.h>
|
|
Toshihiro Shimizu |
890ddd |
#include <process.h></process.h>
|
|
Toshihiro Shimizu |
890ddd |
#include <tchar.h></tchar.h>
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Toshihiro Shimizu |
890ddd |
#include <string.h></string.h>
|
|
Toshihiro Shimizu |
890ddd |
#include <errno.h></errno.h>
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define SZDEPENDENCIES ""
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
9f5a1b |
#ifdef _WIN32
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
LPTSTR GetLastErrorText(LPTSTR lpszBuf, DWORD dwSize) {
|
|
Shinya Kitaoka |
120a6e |
DWORD dwRet;
|
|
Shinya Kitaoka |
120a6e |
LPTSTR lpszTemp = NULL;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
dwRet = FormatMessage(
|
|
Shinya Kitaoka |
120a6e |
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
|
Shinya Kitaoka |
120a6e |
FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
Shinya Kitaoka |
120a6e |
NULL, GetLastError(), LANG_NEUTRAL, (LPTSTR)&lpszTemp, 0, NULL);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// supplied buffer is not long enough
|
|
Shinya Kitaoka |
120a6e |
if (!dwRet || ((long)dwSize < (long)dwRet + 14))
|
|
Shinya Kitaoka |
120a6e |
lpszBuf[0] = TEXT('\0');
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
lpszTemp[lstrlen(lpszTemp) - 2] =
|
|
Shinya Kitaoka |
120a6e |
TEXT('\0'); // remove cr and newline character
|
|
Shinya Kitaoka |
120a6e |
_stprintf(lpszBuf, TEXT("%s (0x%x)"), lpszTemp, GetLastError());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (lpszTemp) LocalFree((HLOCAL)lpszTemp);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return lpszBuf;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
#endif // _WIN32
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::string getLastErrorText() {
|
|
Shinya Kitaoka |
120a6e |
std::string errText;
|
|
Shinya Kitaoka |
9f5a1b |
#ifdef _WIN32
|
|
Shinya Kitaoka |
120a6e |
char errBuff[256];
|
|
Shinya Kitaoka |
120a6e |
errText = GetLastErrorText(errBuff, sizeof(errBuff));
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Shinya Kitaoka |
120a6e |
errText = strerror(errno);
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return errText;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//==============================================================================
|
|
Toshihiro Shimizu |
890ddd |
//==============================================================================
|
|
Toshihiro Shimizu |
890ddd |
//==============================================================================
|
|
Toshihiro Shimizu |
890ddd |
//==============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class TService::Imp {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
Imp() {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
9f5a1b |
#ifdef _WIN32
|
|
Shinya Kitaoka |
120a6e |
static void WINAPI serviceMain(DWORD dwArgc, LPTSTR *lpszArgv);
|
|
Shinya Kitaoka |
120a6e |
static void WINAPI serviceCtrl(DWORD dwCtrlCode);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static BOOL WINAPI controlHandler(DWORD dwCtrlType);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static bool reportStatusToSCMgr(long currentState, long win32ExitCode,
|
|
Shinya Kitaoka |
120a6e |
long waitHint);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::string m_name;
|
|
Shinya Kitaoka |
120a6e |
std::string m_displayName;
|
|
Shinya Kitaoka |
120a6e |
static bool m_console;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
9f5a1b |
#ifdef _WIN32
|
|
Shinya Kitaoka |
120a6e |
static SERVICE_STATUS_HANDLE m_hService;
|
|
Shinya Kitaoka |
120a6e |
static SERVICE_STATUS m_ssStatus; // current status of the service
|
|
Shinya Kitaoka |
120a6e |
static DWORD m_dwErr;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
9f5a1b |
#ifdef _WIN32
|
|
Toshihiro Shimizu |
890ddd |
SERVICE_STATUS_HANDLE TService::Imp::m_hService = 0;
|
|
Toshihiro Shimizu |
890ddd |
SERVICE_STATUS TService::Imp::m_ssStatus;
|
|
Toshihiro Shimizu |
890ddd |
DWORD TService::Imp::m_dwErr = 0;
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool TService::Imp::m_console = false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
2148c8 |
TService::TService(const std::string &name, const std::string &displayName)
|
|
Shinya Kitaoka |
120a6e |
: m_imp(new Imp) {
|
|
Shinya Kitaoka |
120a6e |
m_imp->m_name = name;
|
|
Shinya Kitaoka |
120a6e |
m_imp->m_displayName = displayName;
|
|
Shinya Kitaoka |
120a6e |
m_instance = this;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TService::~TService() {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TService *TService::instance() { return m_instance; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TService *TService::m_instance = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TService::setStatus(Status status, long exitCode, long waitHint) {
|
|
Shinya Kitaoka |
9f5a1b |
#ifdef _WIN32
|
|
Shinya Kitaoka |
120a6e |
if (!isRunningAsConsoleApp())
|
|
Shinya Kitaoka |
120a6e |
TService::Imp::reportStatusToSCMgr(status, exitCode, waitHint);
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
if (status == Stopped) exit(1);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Shinya Kitaoka |
120a6e |
if (status == Stopped) exit(1);
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::string TService::getName() const { return m_imp->m_name; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::string TService::getDisplayName() const { return m_imp->m_displayName; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
9f5a1b |
#ifdef _WIN32
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void WINAPI TService::Imp::serviceCtrl(DWORD dwCtrlCode) {
|
|
Shinya Kitaoka |
120a6e |
// Handle the requested control code.
|
|
Shinya Kitaoka |
120a6e |
//
|
|
Shinya Kitaoka |
120a6e |
switch (dwCtrlCode) {
|
|
Shinya Kitaoka |
120a6e |
// Stop the service.
|
|
Shinya Kitaoka |
120a6e |
//
|
|
Shinya Kitaoka |
120a6e |
// SERVICE_STOP_PENDING should be reported before
|
|
Shinya Kitaoka |
120a6e |
// setting the Stop Event - hServerStopEvent - in
|
|
Shinya Kitaoka |
120a6e |
// ServiceStop(). This avoids a race condition
|
|
Shinya Kitaoka |
120a6e |
// which may result in a 1053 - The Service did not respond...
|
|
Shinya Kitaoka |
120a6e |
// error.
|
|
Shinya Kitaoka |
120a6e |
case SERVICE_CONTROL_STOP:
|
|
Shinya Kitaoka |
120a6e |
case SERVICE_CONTROL_SHUTDOWN: {
|
|
Shinya Kitaoka |
120a6e |
TService::Imp::reportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR,
|
|
Shinya Kitaoka |
120a6e |
3000 /*1*/ /*0*/);
|
|
Shinya Kitaoka |
120a6e |
TService::instance()->onStop();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TService::Imp::reportStatusToSCMgr(SERVICE_STOPPED, NO_ERROR, 3000);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Update the service status.
|
|
Shinya Kitaoka |
120a6e |
//
|
|
Shinya Kitaoka |
120a6e |
case SERVICE_CONTROL_INTERROGATE:
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// invalid control code
|
|
Shinya Kitaoka |
120a6e |
//
|
|
Shinya Kitaoka |
120a6e |
default:
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
reportStatusToSCMgr(m_ssStatus.dwCurrentState, NO_ERROR, 0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void WINAPI TService::Imp::serviceMain(DWORD dwArgc, LPTSTR *lpszArgv) {
|
|
Shinya Kitaoka |
120a6e |
// register our service control handler:
|
|
Shinya Kitaoka |
120a6e |
//
|
|
Shinya Kitaoka |
120a6e |
m_hService = RegisterServiceCtrlHandler(
|
|
Shinya Kitaoka |
120a6e |
TService::instance()->getName().c_str(), TService::Imp::serviceCtrl);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (m_hService == 0) goto cleanup;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// SERVICE_STATUS members that don't change in example
|
|
Shinya Kitaoka |
120a6e |
//
|
|
Shinya Kitaoka |
120a6e |
m_ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
|
Shinya Kitaoka |
120a6e |
m_ssStatus.dwServiceSpecificExitCode = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// report the status to the service control manager.
|
|
Shinya Kitaoka |
120a6e |
//
|
|
Shinya Kitaoka |
120a6e |
if (!reportStatusToSCMgr(SERVICE_START_PENDING, // service state
|
|
Shinya Kitaoka |
120a6e |
NO_ERROR, // exit code
|
|
Shinya Kitaoka |
120a6e |
3000)) // wait hint
|
|
Shinya Kitaoka |
120a6e |
goto cleanup;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// AGGIUNGERE INIZIALIZZAZIONE QUI
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (!reportStatusToSCMgr(SERVICE_RUNNING, // service state
|
|
Shinya Kitaoka |
120a6e |
NO_ERROR, // exit code
|
|
Shinya Kitaoka |
120a6e |
0)) // wait hint
|
|
Shinya Kitaoka |
120a6e |
goto cleanup;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TService::instance()->onStart(dwArgc, lpszArgv);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
cleanup:
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// try to report the stopped status to the service control manager.
|
|
Shinya Kitaoka |
120a6e |
//
|
|
Shinya Kitaoka |
120a6e |
if (m_hService) reportStatusToSCMgr(SERVICE_STOPPED, m_dwErr, 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// TService::Imp::controlHandler( DWORD dwCtrlType )
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// PURPOSE: Handled console control events
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// PARAMETERS:
|
|
Toshihiro Shimizu |
890ddd |
// dwCtrlType - type of control event
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// RETURN VALUE:
|
|
Toshihiro Shimizu |
890ddd |
// True - handled
|
|
Toshihiro Shimizu |
890ddd |
// False - unhandled
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// COMMENTS:
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
BOOL WINAPI TService::Imp::controlHandler(DWORD dwCtrlType) {
|
|
Shinya Kitaoka |
120a6e |
switch (dwCtrlType) {
|
|
Shinya Kitaoka |
120a6e |
case CTRL_CLOSE_EVENT:
|
|
Shinya Kitaoka |
120a6e |
case CTRL_LOGOFF_EVENT:
|
|
Shinya Kitaoka |
120a6e |
case CTRL_SHUTDOWN_EVENT:
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate
|
|
Shinya Kitaoka |
120a6e |
case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in debug mode
|
|
Shinya Kitaoka |
120a6e |
_tprintf(TEXT("Stopping %s.\n"),
|
|
Shinya Kitaoka |
120a6e |
TService::instance()->getDisplayName().c_str());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TService::instance()->onStop();
|
|
Shinya Kitaoka |
120a6e |
return TRUE;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return FALSE;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// FUNCTION: ReportStatusToSCMgr()
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// PURPOSE: Sets the current status of the service and
|
|
Toshihiro Shimizu |
890ddd |
// reports it to the Service Control Manager
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// PARAMETERS:
|
|
Toshihiro Shimizu |
890ddd |
// dwCurrentState - the state of the service
|
|
Toshihiro Shimizu |
890ddd |
// dwWin32ExitCode - error code to report
|
|
Toshihiro Shimizu |
890ddd |
// dwWaitHint - worst case estimate to next checkpoint
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// RETURN VALUE:
|
|
Toshihiro Shimizu |
890ddd |
// TRUE - success
|
|
Toshihiro Shimizu |
890ddd |
// FALSE - failure
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// COMMENTS:
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool TService::Imp::reportStatusToSCMgr(long currentState, long win32ExitCode,
|
|
Shinya Kitaoka |
120a6e |
long waitHint) {
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
SERVICE_STATUS srvStatus; // Declare a SERVICE_STATUS structure,
|
|
Shinya Kitaoka |
120a6e |
and fill it in
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
srvStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; // We're a service
|
|
Shinya Kitaoka |
120a6e |
running in our own process
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Set the state of the service from the argument, and save it away
|
|
Shinya Kitaoka |
120a6e |
// for future use
|
|
Shinya Kitaoka |
120a6e |
_dwPrevState=_dwCurrState;
|
|
Shinya Kitaoka |
120a6e |
srvStatus.dwCurrentState = _dwCurrState = dwState;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Which commands will we accept from the SCM? All the common ones...
|
|
Shinya Kitaoka |
120a6e |
srvStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
|
|
Shinya Kitaoka |
120a6e |
SERVICE_ACCEPT_PAUSE_CONTINUE |
|
|
Shinya Kitaoka |
120a6e |
SERVICE_ACCEPT_SHUTDOWN;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
srvStatus.dwWin32ExitCode = dwExitCode; // Set the Win32 exit code for
|
|
Shinya Kitaoka |
120a6e |
the service
|
|
Shinya Kitaoka |
120a6e |
srvStatus.dwServiceSpecificExitCode = 0; // Set the service-specific exit
|
|
Shinya Kitaoka |
120a6e |
code
|
|
Shinya Kitaoka |
120a6e |
srvStatus.dwCheckPoint = dwProgress; // Set the checkpoint value
|
|
Shinya Kitaoka |
120a6e |
srvStatus.dwWaitHint = __WAIT_TIME_FOR_SERVICE; // 3 second timeout for
|
|
Shinya Kitaoka |
120a6e |
waits
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return SetServiceStatus( _hService, &srvStatus); // pass the structure to the
|
|
Shinya Kitaoka |
120a6e |
SCM
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static DWORD dwCheckPoint = 1;
|
|
Shinya Kitaoka |
120a6e |
BOOL fResult = true;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!m_console) // when running as a console application we don't report to
|
|
Shinya Kitaoka |
120a6e |
// the SCM
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
if (currentState == SERVICE_START_PENDING)
|
|
Shinya Kitaoka |
120a6e |
m_ssStatus.dwControlsAccepted = 0;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
m_ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
|
|
Shinya Kitaoka |
120a6e |
SERVICE_ACCEPT_PAUSE_CONTINUE |
|
|
Shinya Kitaoka |
120a6e |
SERVICE_ACCEPT_SHUTDOWN;
|
|
Shinya Kitaoka |
120a6e |
;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_ssStatus.dwCurrentState = currentState;
|
|
Shinya Kitaoka |
120a6e |
m_ssStatus.dwWin32ExitCode = win32ExitCode;
|
|
Shinya Kitaoka |
120a6e |
m_ssStatus.dwWaitHint = waitHint;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if ((currentState == SERVICE_RUNNING) || (currentState == SERVICE_STOPPED))
|
|
Shinya Kitaoka |
120a6e |
m_ssStatus.dwCheckPoint = 0;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
m_ssStatus.dwCheckPoint = dwCheckPoint++;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Report the status of the service to the service control manager.
|
|
Shinya Kitaoka |
120a6e |
//
|
|
Shinya Kitaoka |
120a6e |
if (!(fResult = SetServiceStatus(m_hService, &m_ssStatus))) {
|
|
Shinya Kitaoka |
120a6e |
TService::addToMessageLog(QString("Failed to set the service status"));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return !!fResult;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TService::run(int argc, char *argv[], bool console) {
|
|
Shinya Kitaoka |
120a6e |
m_imp->m_console = console;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
#ifdef _DEBUG
|
|
Toshihiro Shimizu |
890ddd |
DebugBreak();
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
9f5a1b |
#ifdef _WIN32
|
|
Shinya Kitaoka |
120a6e |
if (console) {
|
|
Shinya Kitaoka |
120a6e |
_tprintf(TEXT("Starting %s.\n"),
|
|
Shinya Kitaoka |
120a6e |
TService::instance()->getDisplayName().c_str());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
SetConsoleCtrlHandler(TService::Imp::controlHandler, TRUE);
|
|
Shinya Kitaoka |
120a6e |
TService::instance()->onStart(argc, argv);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
SERVICE_TABLE_ENTRY dispatchTable[2];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::string name = TService::instance()->getName().c_str();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
dispatchTable[0].lpServiceName = (char *)name.c_str();
|
|
Shinya Kitaoka |
120a6e |
dispatchTable[0].lpServiceProc =
|
|
Shinya Kitaoka |
120a6e |
(LPSERVICE_MAIN_FUNCTION)TService::Imp::serviceMain;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
dispatchTable[1].lpServiceName = NULL;
|
|
Shinya Kitaoka |
120a6e |
dispatchTable[1].lpServiceProc = NULL;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (!StartServiceCtrlDispatcher(dispatchTable))
|
|
Shinya Kitaoka |
120a6e |
TService::addToMessageLog(QString(TEXT("Service start failed.")));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Shinya Kitaoka |
120a6e |
TService::instance()->onStart(argc, argv);
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TService::start(const std::string &name) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TService::stop(const std::string &name) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool TService::isRunningAsConsoleApp() const { return m_imp->m_console; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TService::install(const std::string &name, const std::string &displayName,
|
|
Shinya Kitaoka |
120a6e |
const TFilePath &appPath) {
|
|
Shinya Kitaoka |
9f5a1b |
#ifdef _WIN32
|
|
Shinya Kitaoka |
120a6e |
SC_HANDLE schService;
|
|
Shinya Kitaoka |
120a6e |
SC_HANDLE schSCManager;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
schSCManager = OpenSCManager(NULL, // machine (NULL == local)
|
|
Shinya Kitaoka |
120a6e |
NULL, // database (NULL == default)
|
|
Shinya Kitaoka |
120a6e |
SC_MANAGER_ALL_ACCESS); // access required
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (schSCManager) {
|
|
Shinya Kitaoka |
120a6e |
schService = CreateService(
|
|
Shinya Kitaoka |
120a6e |
schSCManager, // SCManager database
|
|
Shinya Kitaoka |
120a6e |
name.c_str(), // name of service
|
|
Shinya Kitaoka |
120a6e |
displayName.c_str(), // name to display
|
|
Shinya Kitaoka |
120a6e |
SERVICE_ALL_ACCESS, // desired access
|
|
Shinya Kitaoka |
120a6e |
SERVICE_WIN32_OWN_PROCESS, // service type
|
|
Shinya Kitaoka |
120a6e |
SERVICE_DEMAND_START, // start type
|
|
Shinya Kitaoka |
120a6e |
SERVICE_ERROR_NORMAL, // error control type
|
|
Shinya Kitaoka |
120a6e |
::to_string(appPath.getWideString()).c_str(), // service's binary
|
|
Shinya Kitaoka |
120a6e |
NULL, // no load ordering group
|
|
Shinya Kitaoka |
120a6e |
NULL, // no tag identifier
|
|
Shinya Kitaoka |
120a6e |
TEXT(SZDEPENDENCIES), // dependencies
|
|
Shinya Kitaoka |
120a6e |
NULL, // LocalSystem account
|
|
Shinya Kitaoka |
120a6e |
NULL); // no password
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (schService) {
|
|
Shinya Kitaoka |
120a6e |
_tprintf(TEXT("%s installed.\n"), displayName.c_str());
|
|
Shinya Kitaoka |
120a6e |
CloseServiceHandle(schService);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
_tprintf(TEXT("CreateService failed - %s\n"), getLastErrorText().c_str());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
CloseServiceHandle(schSCManager);
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
_tprintf(TEXT("OpenSCManager failed - %s\n"), getLastErrorText().c_str());
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TService::remove(const std::string &name) {
|
|
Shinya Kitaoka |
9f5a1b |
#ifdef _WIN32
|
|
Shinya Kitaoka |
120a6e |
std::string displayName = name;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
SC_HANDLE schService;
|
|
Shinya Kitaoka |
120a6e |
SC_HANDLE schSCManager;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
schSCManager = OpenSCManager(NULL, // machine (NULL == local)
|
|
Shinya Kitaoka |
120a6e |
NULL, // database (NULL == default)
|
|
Shinya Kitaoka |
120a6e |
SC_MANAGER_ALL_ACCESS); // access required
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (schSCManager) {
|
|
Shinya Kitaoka |
120a6e |
schService = OpenService(schSCManager, name.c_str(), SERVICE_ALL_ACCESS);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (schService) {
|
|
Shinya Kitaoka |
120a6e |
SERVICE_STATUS ssStatus; // current status of the service
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// try to stop the service
|
|
Shinya Kitaoka |
120a6e |
if (ControlService(schService, SERVICE_CONTROL_STOP, &ssStatus)) {
|
|
Shinya Kitaoka |
120a6e |
_tprintf(TEXT("Stopping %s."), displayName.c_str());
|
|
Shinya Kitaoka |
120a6e |
Sleep(1000);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
while (QueryServiceStatus(schService, &ssStatus)) {
|
|
Shinya Kitaoka |
120a6e |
if (ssStatus.dwCurrentState == SERVICE_STOP_PENDING) {
|
|
Shinya Kitaoka |
120a6e |
_tprintf(TEXT("."));
|
|
Shinya Kitaoka |
120a6e |
Sleep(1000);
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (ssStatus.dwCurrentState == SERVICE_STOPPED)
|
|
Shinya Kitaoka |
120a6e |
_tprintf(TEXT("\n%s stopped.\n"), displayName.c_str());
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
_tprintf(TEXT("\n%s failed to stop.\n"), displayName.c_str());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// now remove the service
|
|
Shinya Kitaoka |
120a6e |
if (DeleteService(schService))
|
|
Shinya Kitaoka |
120a6e |
_tprintf(TEXT("%s removed.\n"), displayName.c_str());
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
_tprintf(TEXT("DeleteService failed - %s\n"),
|
|
Shinya Kitaoka |
120a6e |
getLastErrorText().c_str());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
CloseServiceHandle(schService);
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
_tprintf(TEXT("OpenService failed - %s\n"), getLastErrorText().c_str());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
CloseServiceHandle(schSCManager);
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
_tprintf(TEXT("OpenSCManager failed - %s\n"), getLastErrorText().c_str());
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TService::addToMessageLog(const QString &msg) {
|
|
Shinya Kitaoka |
120a6e |
addToMessageLog(msg.toStdString());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TService::addToMessageLog(const std::string &msg) {
|
|
Shinya Kitaoka |
9f5a1b |
#ifdef _WIN32
|
|
Shinya Kitaoka |
120a6e |
TCHAR szMsg[256];
|
|
Shinya Kitaoka |
120a6e |
HANDLE hEventSource;
|
|
Shinya Kitaoka |
120a6e |
LPCTSTR lpszStrings[2];
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!TService::Imp::m_console) {
|
|
Shinya Kitaoka |
120a6e |
TService::Imp::m_dwErr = GetLastError();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Use event logging to log the error.
|
|
Shinya Kitaoka |
120a6e |
//
|
|
Shinya Kitaoka |
120a6e |
hEventSource =
|
|
Shinya Kitaoka |
120a6e |
RegisterEventSource(NULL, TService::instance()->getName().c_str());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
_stprintf(szMsg, TEXT("%s error: %d"),
|
|
Shinya Kitaoka |
120a6e |
TService::instance()->getName().c_str(), TService::Imp::m_dwErr);
|
|
Shinya Kitaoka |
120a6e |
lpszStrings[0] = szMsg;
|
|
Shinya Kitaoka |
120a6e |
lpszStrings[1] = msg.c_str();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (hEventSource != NULL) {
|
|
Shinya Kitaoka |
120a6e |
ReportEvent(hEventSource, // handle of event source
|
|
Shinya Kitaoka |
120a6e |
EVENTLOG_ERROR_TYPE, // event type
|
|
Shinya Kitaoka |
120a6e |
0, // event category
|
|
Shinya Kitaoka |
120a6e |
0, // event ID
|
|
Shinya Kitaoka |
120a6e |
NULL, // current user's SID
|
|
Shinya Kitaoka |
120a6e |
2, // strings in lpszStrings
|
|
Shinya Kitaoka |
120a6e |
0, // no bytes of raw data
|
|
Shinya Kitaoka |
120a6e |
lpszStrings, // array of error strings
|
|
Shinya Kitaoka |
120a6e |
NULL); // no raw data
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
(VOID) DeregisterEventSource(hEventSource);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
std::cout << msg.c_str();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Shinya Kitaoka |
120a6e |
if (!TService::Imp::m_console) {
|
|
Shinya Kitaoka |
120a6e |
QString str(msg.c_str());
|
|
Shinya Kitaoka |
120a6e |
TSysLog::error(str);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
std::cout << msg.c_str();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
}
|