diff options
author | Steve Huston <shuston@riverace.com> | 1998-10-06 20:21:36 +0000 |
---|---|---|
committer | Steve Huston <shuston@riverace.com> | 1998-10-06 20:21:36 +0000 |
commit | 6f4be9ceac3b0595721a50462112d1d871953b39 (patch) | |
tree | e0583e7df0b626ce702258f77b0456564b93014a /ace/NT_Service.h | |
parent | 6c9f26c72230fb1cc0d355c588f4cff16d9249f4 (diff) | |
download | ATCD-6f4be9ceac3b0595721a50462112d1d871953b39.tar.gz |
New for NT only - adapt an NT Service to an ACE_Task.
Diffstat (limited to 'ace/NT_Service.h')
-rw-r--r-- | ace/NT_Service.h | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/ace/NT_Service.h b/ace/NT_Service.h new file mode 100644 index 00000000000..ef1e1562b77 --- /dev/null +++ b/ace/NT_Service.h @@ -0,0 +1,179 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// NT_Service.h +// +// = AUTHOR +// Steve Huston +// +// ============================================================================ + +#if !defined (ACE_NT_SERVICE_H) +#define ACE_NT_SERVICE_H + +#include "ace/inc_user_config.h" + +#if defined (ACE_HAS_WINNT4) && ACE_HAS_WINNT4 != 0 + +#include "ace/Service_Object.h" +#include "ace/Synch.h" +#include "ace/Task.h" + +// NT Services can be implemented using the framework defined by the +// ACE_NT_Service class, and the macros defined in this file. Some quick +// refresher notes on NT Services: +// - The main program defines an array of entries describing the services +// offered. The ACE_NT_SERVICE_ENTRY macro can help with this. +// - For each service, a separate ServiceMain and Handler function need to +// be defined. These are taken care of by the ACE_NT_SERVICE_DEFINE +// macro. +// - When the main program/thread calls StartServiceCtrlDispatcher, NT +// creates a thread for each service, and runs the ServiceMain function +// for the service in that new thread. When that thread exits, the service +// is gone. +// +// To use this facility, you could derive a class from ACE_Service_Object (if +// you want to start via ACE's service configurator), or use any other class +// to run when the image starts (assuming that NT runs the image). You must +// set up an NT SERVICE_TABLE_ENTRY array to define your service(s). You +// can use the ACE_NT_SERVICE_... macros defined below for this. +// A SERVICE_TABLE might look like this: +// ACE_NT_SERVICE_REFERENCE(Svc1); // If service is in another file +// SERVICE_TABLE_ENTRY myServices[] = { +// ACE_NT_SERVICE_ENTRY ("MyNeatService", Svc1), +// { 0, 0 } }; +// +// In the file where your service(s) are implemented, use the +// ACE_NT_SERVICE_DEFINE macro to set up the following: +// 1. A pointer to the service's implementation object (must be derived +// from ACE_NT_Service). +// 2. The service's Handler function (forwards all requests to the +// ACE_NT_Service-derived object's handle_control function). +// 3. The service's ServiceMain function. Creates a new instance of the +// ACE_NT_Service-derived class SVCCLASS, unless one has been created +// already. +// +// If you are using all the default constructor values, you +// can let the generated ServiceMain function create the object, else +// you need to create it by hand before calling StartServiceCtrlDispatcher. +// Set the pointer so ServiceMain won't create another one. +// Another reason you may want to do the object creation yourself is if you +// want to also implement suspend and resume functions (the ones inherited +// from ACE_Service_Object) to do something intelligent to the services which +// are running, like call their handle_control functions to request suspend +// and resume actions, similar to what NT would do if a Services control panel +// applet would do if the user clicks on Suspend. + + +// ACE_NT_SERVICE_START_TIMEOUT is an estimate of the number of milliseconds +// your service will take to start. Default is 5 seconds; you can pass +// a different value (or set one) when you create the ACE_NT_Service object +// for your service. +#if !defined ACE_NT_SERVICE_START_TIMEOUT +#define ACE_NT_SERVICE_START_TIMEOUT 5000 +#endif /* ACE_NT_SERVICE_TIMEOUT */ + +class ACE_Export ACE_NT_Service : public ACE_Task<ACE_MT_SYNCH> +{ + // = TITLE + // Provide the base class which defines the interface for controlling + // an NT service. + // + // = DESCRIPTION +public: + // = Initialization and termination methods. + ACE_NT_Service (DWORD start_timeout = ACE_NT_SERVICE_START_TIMEOUT, + DWORD service_type = SERVICE_WIN32_OWN_PROCESS, + DWORD controls_mask = SERVICE_ACCEPT_STOP); + + virtual ~ACE_NT_Service (void); + + virtual int open (void *args = 0); + // Hook called to open the service. By default, will set the status to + // START_PENDING, svc(), wait(), then set the status to STOPPED. + + virtual int svc (void) = 0; + // The actual service implementation. This function must be implemented + // by subclasses. It is expected that this function will set the status + // to RUNNING. + + virtual void handle_control (DWORD control_code); + // This function is called in response to a request from the Service + // Dispatcher. It must interact with the svc() function to effect the + // requested control operation. The default implementation handles + // all requests as follows: + // SERVICE_CONTROL_STOP: set stop pending, set cancel flag + // SERVICE_CONTROL_PAUSE: set pause pending, suspend(), set paused + // SERVICE_CONTROL_CONTINUE: set continue pending, resume(), set running + // SERVICE_CONTROL_INTERROGATE: reports current status + // SERVICE_CONTROL_SHUTDOWN: same as SERVICE_CONTROL_STOP. + + void svc_handle (const SERVICE_STATUS_HANDLE new_svc_handle); + // Set the svc_handle_ member. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + int report_status (DWORD new_status, DWORD time_hint = 0); + +protected: + DWORD start_time_; // Estimate of init time needed + SERVICE_STATUS_HANDLE svc_handle_; // Service handle - doesn't need close. + SERVICE_STATUS svc_status_; +}; + + +// These macros help to get things set up correctly at compile time and +// to take most of the grudge work out of creating the proper functions +// and doing the registrations. +// +// ACE_NT_SERVICE_DEFINE - defines the 'ServiceMain' function which NT will +// call in its own thread when the service control +// dispatcher starts. + +#define ACE_NT_SERVICE_DEFINE(SVCNAME, SVCCLASS, SVCDESC) \ + ACE_NT_Service * _ace_nt_svc_obj_##SVCNAME = 0; \ + VOID WINAPI ace_nt_svc_handler_##SVCNAME (DWORD fdwControl) { \ + _ace_nt_svc_obj_##SVCNAME->handle_control(fdwControl); \ + } \ + VOID WINAPI ace_nt_svc_main_##SVCNAME (DWORD dwArgc, LPTSTR *lpszArgv) { \ + int delete_svc_obj = 0; \ + if (_ace_nt_svc_obj_##SVCNAME == 0) { \ + ACE_NEW (_ace_nt_svc_obj_##SVCNAME, SVCCLASS); \ + if (_ace_nt_svc_obj_##SVCNAME == 0) \ + return; \ + delete_svc_obj = 1; \ + } \ + _ace_nt_svc_obj_##SVCNAME->init(dwArgc, lpszArgv); \ + _ace_nt_svc_obj_##SVCNAME->svc_handle( \ + RegisterServiceCtrlHandler(SVCDESC, \ + &ace_nt_svc_handler_##SVCNAME)); \ + _ace_nt_svc_obj_##SVCNAME->open(); \ + _ace_nt_svc_obj_##SVCNAME->wait(); \ + _ace_nt_svc_obj_##SVCNAME->fini(); \ + if (delete_svc_obj) { \ + delete _ace_nt_svc_obj_##SVCNAME; \ + _ace_nt_svc_obj_##SVCNAME = 0; \ + } \ + return; \ + } + +#define ACE_NT_SERVICE_REFERENCE(SVCNAME) \ +extern VOID WINAPI ace_nt_svc_main_##SVCNAME (DWORD dwArgc, LPTSTR *lpszArgv); + +#define ACE_NT_SERVICE_ENTRY(SVCDESC, SVCNAME) \ + { SVCDESC, &ace_nt_svc_main_##SVCNAME } + +#if defined (__ACE_INLINE__) +#include "ace/NT_Service.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_HAS_WINNT4 */ +#endif /* ACE_SERVICE_OBJECT_H */ |