238 lines
8.1 KiB
C++

//----------------------------------------------------------------------------
//
// Copyright (C) Intel Corporation, 2007 - 2008.
//
// File: BaseService.cpp
//
// Contents: Provides a base class for a service that will exist as
// part of a service application. BaseService must be
// derived when creating a new service class.
//
// Notes: To use this class you should derived this class and
// implement the following methods:
// ServiceInitialization - initialization of the service.
// _ServiceCtrlHandler - take care of calling the callback
// function specified for each
// control operations.
// ServiceMainLoop - Service main application
//
//----------------------------------------------------------------------------
#include "BaseService.h"
#include "WindowsEventLog.h"
#include "MPSMessageFile.h"
#include <iostream>
#include <fstream>
// The single, static service instance pointer.
BaseService* BaseService::m_pService = NULL;
//*****************************************************************************
// Name: ServiceBase
// Description: Constructor - initializes a new instance of the
// BaseService class and set the service name.
//*****************************************************************************
BaseService::BaseService(LPCTSTR pszServiceName):
m_ServiceHandle()
{
m_pService = this;
m_ServiceName = pszServiceName;
m_InitFlag = false;
eventLogger = new WindowsEventLog(APPLICATION, m_ServiceName.c_str(), EVENT_LOG_CATEGORY_COUNT);
}
//*****************************************************************************
// Name : InitializeService
// Description: The service initialization function.
// This function does all the initialization code for the service
//*****************************************************************************
int BaseService::InitializeService(DWORD dwServiceType,
DWORD dwControlsAccepted,
DWORD dwWaitHint)
{
_ASSERT(m_ServiceName.empty() == false );
// Set the dispatcher table (pass it to the service ctrl iapatcher function).
m_ServiceDispatcher[0].lpServiceName = const_cast<LPTSTR>(m_ServiceName.c_str());
m_ServiceDispatcher[0].lpServiceProc = ServiceMain;
m_ServiceDispatcher[1].lpServiceName = NULL;
m_ServiceDispatcher[1].lpServiceProc = NULL;
// setting the service current status - before registering the service
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwControlsAccepted = dwControlsAccepted;
m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
m_ServiceStatus.dwServiceSpecificExitCode = 0;
m_ServiceStatus.dwServiceType = dwServiceType;
m_ServiceStatus.dwWaitHint = dwWaitHint;
m_ServiceStatus.dwWin32ExitCode = 0;
m_InitFlag = true;
return 0; // success
}
//*****************************************************************************
// Name : ServiceMain
// Description: this is the actual service main that gets called as soon as the
// service runs.
//*****************************************************************************
void WINAPI BaseService::ServiceMain(DWORD argc,LPTSTR *argv)
{
m_pService->_ServiceMain(argc,argv);
}
//*****************************************************************************
// Name : WriteToErrorLog
// Description: Write an error message to the Windows Event log.
//*****************************************************************************
void BaseService::WriteToErrorLog(const char *message)
{
mutex.acquire();
ACE_TCHAR szBuf[1024];
ACE_OS::sprintf(szBuf, " [%s] %s\n", m_ServiceName.c_str(), message);
const ACE_TCHAR *lpStrings[] = {szBuf};
unsigned int NumOfStrings = 1;
if (eventLogger != NULL) {
eventLogger->LogEvent(SERVICE_GENERAL, SERVICE_ERROR_MESSAGE, EVENTLOG_ERROR_TYPE, lpStrings,NumOfStrings, NULL, 0);
}
mutex.release();
}
//*****************************************************************************
// Name : getFormatMessage
// Description: Gets the windows system error description from a windows system
// error code
//*****************************************************************************
void BaseService::getFormatMessage(DWORD errorCode, string &errorBuf)
{
void *errorMsgBuf = NULL;
DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_FROM_SYSTEM;
FormatMessageA(dwFormatFlags,
NULL,
errorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR) &errorMsgBuf,
0,
NULL);
/* Free error message buf */
errorBuf = (char*) errorMsgBuf;
if (errorMsgBuf != NULL) {
LocalFree(errorMsgBuf);
}
}
//*****************************************************************************
// Name : ServiceMain
// Description: non-static function which does all the job of the service main
//*****************************************************************************
void WINAPI BaseService::_ServiceMain(DWORD argc,LPTSTR *argv)
{
_ASSERT(m_InitFlag == true); // check for call to initialize
DWORD status;
DWORD specificError;
string errorBuf;
// Register the service
m_ServiceHandle = RegisterServiceCtrlHandlerEx( m_ServiceName.c_str(),
BaseService::ServiceCtrlHandler, NULL);
// Check for errors.
if (m_ServiceHandle == (SERVICE_STATUS_HANDLE)0)
{
getFormatMessage(GetLastError(), errorBuf);
WriteToErrorLog(errorBuf.c_str());
return;
}
// Update the service status
BOOL res = UpdateService(SERVICE_START_PENDING);
if (res == FALSE) {
getFormatMessage(GetLastError(), errorBuf);
WriteToErrorLog(errorBuf.c_str());
return;
}
// This is where the service does its work.
status = ServiceInitialization(argc,argv, &specificError);
// Handle error condition
if (status != NO_ERROR) {
m_ServiceStatus.dwWin32ExitCode = status;
m_ServiceStatus.dwServiceSpecificExitCode = specificError;
getFormatMessage(GetLastError(), errorBuf);
WriteToErrorLog(errorBuf.c_str());
UpdateService (SERVICE_STOPPED);
return;
}
// Set the service status.
if( !UpdateService(SERVICE_RUNNING) ) {
getFormatMessage(GetLastError(), errorBuf);
WriteToErrorLog(errorBuf.c_str());
return;
}
// Loop while no error and do your job.
ServiceMainLoop();
if (!UpdateService(SERVICE_STOPPED)) {
getFormatMessage(GetLastError(), errorBuf);
WriteToErrorLog(errorBuf.c_str());
return;
}
return;
}
//*****************************************************************************
// Name : ServiceCtrlHandler
// Description: This is the service control handler which was registered to SCM.
// call the non-static function that implements the code for service
// control handler
//*****************************************************************************
DWORD WINAPI BaseService::ServiceCtrlHandler(
DWORD dwControl,
DWORD dwEventType,
LPVOID lpEventData,
LPVOID lpContext)
{
return m_pService->_ServiceCtrlHandler(dwControl, dwEventType, lpEventData, lpContext);
}
//*****************************************************************************
// Name : StartDispatcher
// Description: Connect to the SCM and start the control dispatcher thread
// The dispatcher thread loops, waiting for incoming control
// requests for the services specified in the dispatch table.
//*****************************************************************************
DWORD BaseService::StartDispatcher()
{
if( !StartServiceCtrlDispatcher(m_ServiceDispatcher) )
{
string errorBuf;
getFormatMessage(GetLastError(), errorBuf);
WriteToErrorLog(errorBuf.c_str());
return -1;
}
return 0;
}
//*****************************************************************************
// Name : UpdateService
// Description: Updates the status of the service using the SetServiceStatus SCM
// function.
//*****************************************************************************
BOOL BaseService::UpdateService(DWORD dwCurrentState)
{
m_ServiceStatus.dwCurrentState = dwCurrentState;
BOOL status = SetServiceStatus(m_ServiceHandle,&m_ServiceStatus);
return status;
}