|
|
/************************************************************************************************
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.
|