184 lines
8.0 KiB
C++
184 lines
8.0 KiB
C++
/************************************************************************************************
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
Module Name: Service.h
|
|
Abstract: Defines the CService class and related macros. See description below.
|
|
Notes:
|
|
History: 01/25/2001 - created, Luciano Passuello (lucianop).
|
|
************************************************************************************************/
|
|
|
|
#pragma once
|
|
|
|
// global constants
|
|
const int nMaxServiceLen = 256;
|
|
const int nMaxServiceDescLen = 1024;
|
|
|
|
/************************************************************************************************
|
|
Class: CService
|
|
Purpose: Abstract class that implements the service-related code, such as
|
|
threads creating, SCM registering, status retrieval, etc..
|
|
Notes: (1) Class design based on the CService class described in the book:
|
|
Professional NT Services, by Kevin Miller.
|
|
(2) Each derived class must be instantiated one and only time.
|
|
History: 01/25/2001 - created, Luciano Passuello (lucianop)
|
|
************************************************************************************************/
|
|
class CService
|
|
{
|
|
protected:
|
|
// actions that services respond to
|
|
const static DWORD dwStateNoChange;
|
|
|
|
enum SERVICE_NUMBER_EVENTS { nNumServiceEvents = 4 };
|
|
enum SERVICE_EVENTS {STOP, PAUSE, CONTINUE, SHUTDOWN};
|
|
|
|
DWORD m_dwDefaultEventID;
|
|
WORD m_wDefaultCategory;
|
|
|
|
public:
|
|
CService(LPCTSTR szName, LPCTSTR szDisplay, DWORD dwType);
|
|
virtual ~CService();
|
|
|
|
DWORD GetStatus() { return m_dwState; }
|
|
DWORD GetControls() { return m_dwControlsAccepted; }
|
|
LPCTSTR GetName() { return m_szName; }
|
|
LPCTSTR GetDisplayName() { return m_szDisplay; }
|
|
protected:
|
|
void ServiceMainMember(DWORD argc, LPTSTR* argv, LPHANDLER_FUNCTION pf, LPTHREAD_START_ROUTINE pfnWTP);
|
|
void HandlerMember(DWORD dwControl);
|
|
virtual void LaunchWatcherThread(LPTHREAD_START_ROUTINE pfnWTP);
|
|
virtual DWORD WatcherThreadMemberProc();
|
|
|
|
bool SetupHandlerInside(LPHANDLER_FUNCTION lpHandlerProc);
|
|
|
|
void SetStatus(DWORD dwNewState, DWORD dwNewCheckpoint = dwStateNoChange, DWORD dwNewHint = dwStateNoChange,
|
|
DWORD dwNewControls = dwStateNoChange, DWORD dwExitCode = NO_ERROR, DWORD dwSpecificExit = 0);
|
|
|
|
void AbortService(DWORD dwErrorNum = GetLastError());
|
|
// Overrideables
|
|
protected:
|
|
virtual void PreInit(); // if you override, call the base class version
|
|
virtual void Init();
|
|
virtual void DeInit(); // If you override, call the base class version
|
|
virtual void ParseArgs(DWORD argc, LPTSTR* argv);
|
|
virtual void OnPause();
|
|
virtual void OnContinue();
|
|
virtual void OnShutdown();
|
|
virtual void HandleUserDefined(DWORD dwControl);
|
|
|
|
// service events handling
|
|
virtual void OnStopRequest();
|
|
virtual void OnPauseRequest();
|
|
virtual void OnContinueRequest();
|
|
virtual void OnShutdownRequest();
|
|
|
|
virtual void OnBeforeStart();
|
|
virtual void OnAfterStart();
|
|
|
|
virtual void Run() = 0;
|
|
virtual void OnStop(DWORD dwErrorCode) = 0;
|
|
|
|
// Attributes
|
|
protected:
|
|
CRITICAL_SECTION m_cs;
|
|
|
|
// Status info
|
|
SERVICE_STATUS_HANDLE m_hServiceStatus;
|
|
DWORD m_dwState;
|
|
DWORD m_dwControlsAccepted;
|
|
DWORD m_dwCheckpoint;
|
|
DWORD m_dwWaitHint;
|
|
|
|
// Tracks state currently being worked on in Handler
|
|
DWORD m_dwRequestedControl;
|
|
|
|
// Control Events
|
|
HANDLE m_hServiceEvent[nNumServiceEvents];
|
|
HANDLE m_hWatcherThread;
|
|
|
|
TCHAR m_szName[nMaxServiceLen + 1];
|
|
TCHAR m_szDisplay[nMaxServiceLen + 1];
|
|
DWORD m_dwType;
|
|
};
|
|
|
|
|
|
/************************************************************************************************
|
|
Macro: DECLARE_SERVICE
|
|
Synopsis: declares the static functions that will be used as thread-entry points.
|
|
Effects: These functions need to be static because they will be used as thread
|
|
entry-points. Since static functions don't have access to the this pointer, it
|
|
have to be explicitly passed to them (m_pThis). That's why this code need to be
|
|
put in derived classes, otherwise we could have just one CService around at a
|
|
time. We can only have one specific CService-derived class at a time.
|
|
Arguments: [class_name] - the name of the CService-derived class.
|
|
[service_name] - the SCM short service name.
|
|
Notes: to be used in CService-derived class declaration.
|
|
History: 01/25/2001 - created, Luciano Passuello (lucianop).
|
|
************************************************************************************************/
|
|
#define DECLARE_SERVICE(class_name, service_name) \
|
|
public: \
|
|
static class_name##* m_pThis; \
|
|
static void WINAPI service_name##Main(DWORD argc, LPTSTR* argv); \
|
|
static void WINAPI service_name##Handler(DWORD dwControl); \
|
|
static DWORD WINAPI service_name##WatcherThreadProc(LPVOID lpParameter);
|
|
|
|
|
|
/************************************************************************************************
|
|
Macro: IMPLEMENT_SERVICE
|
|
Synopsis: implements the static functions that will be used as thread-entry points.
|
|
Effects: Using the explicit "this" pointer, it just delegates the work to the member
|
|
functions.
|
|
Arguments: [class_name] - the name of the CService-derived class.
|
|
[service_name] - the SCM short service name.
|
|
Notes: to be used in CService-derived class implementation.
|
|
History: 01/25/2001 - created, Luciano Passuello (lucianop).
|
|
************************************************************************************************/
|
|
#define IMPLEMENT_SERVICE(class_name, service_name) \
|
|
class_name##* class_name::m_pThis = NULL; \
|
|
void WINAPI class_name::service_name##Main(DWORD argc, LPTSTR* argv) \
|
|
{ \
|
|
m_pThis->ServiceMainMember(argc, argv, (LPHANDLER_FUNCTION)service_name##Handler, \
|
|
(LPTHREAD_START_ROUTINE)service_name##WatcherThreadProc); \
|
|
} \
|
|
void WINAPI class_name::service_name##Handler(DWORD dwControl) \
|
|
{ \
|
|
m_pThis->HandlerMember(dwControl); \
|
|
} \
|
|
DWORD WINAPI class_name::service_name##WatcherThreadProc(LPVOID /*lpParameter*/) \
|
|
{ \
|
|
return m_pThis->WatcherThreadMemberProc(); \
|
|
}
|
|
|
|
|
|
/************************************************************************************************
|
|
Macro: BEGIN_SERVICE_MAP, SERVICE_MAP_ENTRY, END_SERVICE_MAP
|
|
Synopsis: creates the service map and registers it with the SCM.
|
|
Effects: Using the explicit "this" pointer, it just delegates the work to the member
|
|
functions.
|
|
Arguments: [class_name] - the name of the CService-derived class.
|
|
[service_name] - the SCM short service name.
|
|
Notes: to be used in the entry-point where the CService-derived class is used.
|
|
History: 01/25/2001 - created, Luciano Passuello (lucianop).
|
|
************************************************************************************************/
|
|
#define BEGIN_SERVICE_MAP \
|
|
SERVICE_TABLE_ENTRY svcTable[] = {
|
|
|
|
#define SERVICE_MAP_ENTRY(class_name, service_name) \
|
|
{_T(#service_name), (LPSERVICE_MAIN_FUNCTION)class_name::service_name##Main},
|
|
|
|
#define END_SERVICE_MAP \
|
|
{NULL, NULL}}; \
|
|
StartServiceCtrlDispatcher(svcTable);
|
|
|
|
|
|
/************************************************************************************************
|
|
Macro: IMPLEMENT_STATIC_REFERENCE()
|
|
Synopsis: assigns the "this" pointer to an explicit m_pThis member.
|
|
Effects: makes the static member functions know explicitly about the data in the class,
|
|
since static functions don't have access to the "this" pointer.
|
|
Notes: to be used in CService-derived constructors.
|
|
History: 01/25/2001 - created, Luciano Passuello (lucianop).
|
|
************************************************************************************************/
|
|
#define IMPLEMENT_STATIC_REFERENCE() m_pThis = this
|
|
|
|
|
|
// End of file Service.h.
|