ACE_NT_Service Class Reference

Provide the base class which defines the interface for controlling an NT service. More...

#include <NT_Service.h>

Inheritance diagram for ACE_NT_Service:

Inheritance graph
[legend]
Collaboration diagram for ACE_NT_Service:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 ACE_NT_Service (DWORD start_timeout=ACE_NT_SERVICE_START_TIMEOUT, DWORD service_type=SERVICE_WIN32_OWN_PROCESS, DWORD controls_mask=SERVICE_ACCEPT_STOP)
 Constructor primarily for use when running the service.

 ACE_NT_Service (const ACE_TCHAR *name, const ACE_TCHAR *desc=0, 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)
virtual int fini (void)
virtual int svc (void)
virtual void handle_control (DWORD control_code)
void svc_handle (const SERVICE_STATUS_HANDLE new_svc_handle)
void name (const ACE_TCHAR *name, const ACE_TCHAR *desc=0)
const ACE_TCHARname (void) const
 Get the service name.

const ACE_TCHARdesc (void) const
 Get the service description.

void host (const ACE_TCHAR *host)
 Sets the host machine.

const ACE_TCHARhost (void) const
 Get the host machine.

int insert (DWORD start_type=SERVICE_DEMAND_START, DWORD error_control=SERVICE_ERROR_IGNORE, const ACE_TCHAR *exe_path=0, const ACE_TCHAR *group_name=0, LPDWORD tag_id=0, const ACE_TCHAR *dependencies=0, const ACE_TCHAR *account_name=0, const ACE_TCHAR *password=0)
int remove (void)
int startup (DWORD startup)
 Sets the startup type for the service. Returns -1 on error, 0 on success.

DWORD startup (void)
 Returns the current startup type.

void capture_log_msg_attributes (void)
void inherit_log_msg_attributes (void)
int start_svc (ACE_Time_Value *wait_time=0, DWORD *svc_state=0, DWORD argc=0, const ACE_TCHAR **argv=0)
int stop_svc (ACE_Time_Value *wait_time=0, DWORD *svc_state=0)
int pause_svc (ACE_Time_Value *wait_time=0, DWORD *svc_state=0)
 Pause the service.

int continue_svc (ACE_Time_Value *wait_time=0, DWORD *svc_state=0)
 Continue the service.

DWORD state (ACE_Time_Value *wait_hint=0)
int state (DWORD *pstate, ACE_Time_Value *wait_hint=0)
int test_access (DWORD desired_access=SERVICE_ALL_ACCESS)

Public Attributes

 ACE_ALLOC_HOOK_DECLARE
 Declare the dynamic allocation hooks.


Protected Member Functions

int report_status (DWORD new_status, DWORD time_hint=0)
SC_HANDLE svc_sc_handle (void)
void wait_for_service_state (DWORD desired_state, ACE_Time_Value *wait_time)
virtual void stop_requested (DWORD control_code)
 Called by when a stop/shutdown was requested.

virtual void pause_requested (DWORD control_code)
 Called by when a pause was requested.

virtual void continue_requested (DWORD control_code)
 Called by when a continue was requested.

virtual void interrogate_requested (DWORD control_code)
 Called by when a interrogate was requested.


Protected Attributes

DWORD start_time_
 Estimate of init time needed.

SERVICE_STATUS_HANDLE svc_handle_
 Service handle - doesn't need close.

SERVICE_STATUS svc_status_
SC_HANDLE svc_sc_handle_
 Service's SCM handle.

ACE_TCHARname_
ACE_TCHARdesc_
ACE_TCHARhost_
ACE_OS_Log_Msg_Attributes log_msg_attributes_
 ACE_Log_Msg attributes to inherit from the starting thread.


Detailed Description

Provide the base class which defines the interface for controlling an NT service.

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:

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.

Definition at line 100 of file NT_Service.h.


Constructor & Destructor Documentation

ACE_BEGIN_VERSIONED_NAMESPACE_DECL ACE_INLINE ACE_NT_Service::ACE_NT_Service DWORD  start_timeout = ACE_NT_SERVICE_START_TIMEOUT,
DWORD  service_type = SERVICE_WIN32_OWN_PROCESS,
DWORD  controls_mask = SERVICE_ACCEPT_STOP
 

Constructor primarily for use when running the service.

Definition at line 8 of file NT_Service.inl.

References svc_status_.

00010                                                      :
00011                                  start_time_(start_timeout),
00012                                  svc_handle_(0),
00013                                  svc_sc_handle_(0),
00014                                  name_(0),
00015                                  desc_(0),
00016                                  host_(0)
00017 {
00018   svc_status_.dwServiceType = service_type;
00019   svc_status_.dwCurrentState = 0;
00020   svc_status_.dwControlsAccepted = controls_mask;
00021   svc_status_.dwWin32ExitCode = NO_ERROR;
00022   svc_status_.dwServiceSpecificExitCode = 0;
00023   svc_status_.dwCheckPoint = 0;
00024   svc_status_.dwWaitHint = 0;
00025 }

ACE_INLINE ACE_NT_Service::ACE_NT_Service const ACE_TCHAR name,
const ACE_TCHAR desc = 0,
DWORD  start_timeout = ACE_NT_SERVICE_START_TIMEOUT,
DWORD  service_type = SERVICE_WIN32_OWN_PROCESS,
DWORD  controls_mask = SERVICE_ACCEPT_STOP
 

Constructor primarily for use when inserting/removing/controlling the service.

Definition at line 29 of file NT_Service.inl.

References ACE_TCHAR, and svc_status_.

00033                                                      :
00034                                  start_time_(start_timeout),
00035                                  svc_handle_(0),
00036                                  svc_sc_handle_(0),
00037                                  name_(ACE::strnew(name)),
00038                                  desc_(ACE::strnew(desc)),
00039                                  host_(0)
00040 {
00041   svc_status_.dwServiceType = service_type;
00042   svc_status_.dwCurrentState = 0;
00043   svc_status_.dwControlsAccepted = controls_mask;
00044   svc_status_.dwWin32ExitCode = NO_ERROR;
00045   svc_status_.dwServiceSpecificExitCode = 0;
00046   svc_status_.dwCheckPoint = 0;
00047 }

ACE_BEGIN_VERSIONED_NAMESPACE_DECL ACE_NT_Service::~ACE_NT_Service void   )  [virtual]
 

Definition at line 23 of file NT_Service.cpp.

References host_, and svc_sc_handle_.

00024 {
00025   if (this->svc_sc_handle_ != 0)
00026     {
00027       CloseServiceHandle (this->svc_sc_handle_);
00028       this->svc_sc_handle_ = 0;
00029     }
00030   delete [] this->desc_;
00031   delete [] this->name_;
00032   delete [] this->host_;
00033 }


Member Function Documentation

void ACE_NT_Service::capture_log_msg_attributes void   ) 
 

Set the ACE_Log_Msg attributes that the service thread will use to initialize its ACE_Log_Msg instance. This is how the initiating thread's logging ostream, etc. get into the service thread. The logging attributes in effect when this function is called are what the service thread will have at its disposal when it starts; therefore, the main thread should set up logging options for the process, and call this function just before calling the StartServiceCtrlDispatcher function.

Definition at line 310 of file NT_Service.cpp.

References ACE_Log_Msg::init_hook().

00311 {
00312   ACE_Log_Msg::init_hook (this->log_msg_attributes_);
00313 }

void ACE_NT_Service::continue_requested DWORD  control_code  )  [protected, virtual]
 

Called by when a continue was requested.

Definition at line 131 of file NT_Service.cpp.

References report_status(), and ACE_Task_Base::resume().

Referenced by handle_control().

00132 {
00133   this->report_status (SERVICE_CONTINUE_PENDING);
00134   this->resume ();
00135   this->report_status (SERVICE_RUNNING);
00136 }

int ACE_NT_Service::continue_svc ACE_Time_Value wait_time = 0,
DWORD *  svc_state = 0
 

Continue the service.

Definition at line 386 of file NT_Service.cpp.

References svc_sc_handle(), svc_status_, and wait_for_service_state().

00388 {
00389   SC_HANDLE svc = this->svc_sc_handle ();
00390   if (svc == 0)
00391     return -1;
00392 
00393   if (!ControlService (svc,
00394                        SERVICE_CONTROL_CONTINUE,
00395                        &this->svc_status_))
00396     return -1;
00397 
00398   this->wait_for_service_state (SERVICE_RUNNING,
00399                                 wait_time);
00400   if (svc_state != 0)
00401     *svc_state = this->svc_status_.dwCurrentState;
00402 
00403   return 0;
00404 }

ACE_INLINE const ACE_TCHAR * ACE_NT_Service::desc void   )  const
 

Get the service description.

Definition at line 66 of file NT_Service.inl.

Referenced by insert().

00067 {
00068   return desc_;
00069 }

int ACE_NT_Service::fini void   )  [virtual]
 

Hook called when terminating the service. Inherited from ACE_Shared_Object. Default implementation sets the service status to SERVICE_STOPPED.

Reimplemented from ACE_Shared_Object.

Definition at line 85 of file NT_Service.cpp.

References report_status().

00086 {
00087   return this->report_status (SERVICE_STOPPED, 0);
00088 }

void ACE_NT_Service::handle_control DWORD  control_code  )  [virtual]
 

This function is called in response to a request from the Service Dispatcher. It must interact with the 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, , set paused SERVICE_CONTROL_CONTINUE: set continue pending, , set running SERVICE_CONTROL_INTERROGATE: reports current status SERVICE_CONTROL_SHUTDOWN: same as SERVICE_CONTROL_STOP.

Definition at line 92 of file NT_Service.cpp.

References continue_requested(), interrogate_requested(), pause_requested(), and stop_requested().

00093 {
00094   switch (control_code)
00095     {
00096     case SERVICE_CONTROL_SHUTDOWN:
00097     case SERVICE_CONTROL_STOP:
00098       this->stop_requested (control_code);
00099       break;
00100 
00101     case SERVICE_CONTROL_PAUSE:
00102       this->pause_requested (control_code);
00103       break;
00104 
00105     case SERVICE_CONTROL_CONTINUE:
00106       this->continue_requested (control_code);
00107       break;
00108 
00109     case SERVICE_CONTROL_INTERROGATE:
00110       this->interrogate_requested (control_code);
00111       break;
00112     }
00113 }

ACE_INLINE const ACE_TCHAR * ACE_NT_Service::host void   )  const
 

Get the host machine.

Definition at line 73 of file NT_Service.inl.

References host_.

00074 {
00075   return host_;
00076 }

void ACE_NT_Service::host const ACE_TCHAR host  ) 
 

Sets the host machine.

Definition at line 158 of file NT_Service.cpp.

References ACE_TCHAR, host_, ACE::strnew(), and svc_sc_handle_.

00159 {
00160   delete [] this->host_;
00161 
00162   if (this->svc_sc_handle_ != 0)
00163     {
00164       CloseServiceHandle (this->svc_sc_handle_);
00165       this->svc_sc_handle_ = 0;
00166     }
00167 
00168   if (host == 0)
00169     {
00170       this->host_ = 0;
00171     }
00172   else
00173     {
00174       this->host_ = ACE::strnew (host);
00175     }
00176 }

void ACE_NT_Service::inherit_log_msg_attributes void   ) 
 

Set the ACE_Log_Msg attributes in the current thread to those saved in the most recent call to capture_log_msg_attributes(). This function should be called from the service's service thread. Ideally, it is the first method called to be sure that any logging done is incorporated correctly into the process's established logging setup.

Definition at line 316 of file NT_Service.cpp.

References ACE_Log_Msg::inherit_hook().

00317 {
00318   // There's no thread descriptor involved with a NT-started
00319   // thread, so the first arg is 0.
00320   ACE_Log_Msg::inherit_hook (0, this->log_msg_attributes_);
00321 }

int ACE_NT_Service::insert DWORD  start_type = SERVICE_DEMAND_START,
DWORD  error_control = SERVICE_ERROR_IGNORE,
const ACE_TCHAR exe_path = 0,
const ACE_TCHAR group_name = 0,
LPDWORD  tag_id = 0,
const ACE_TCHAR dependencies = 0,
const ACE_TCHAR account_name = 0,
const ACE_TCHAR password = 0
 

Insert (create) the service in the NT Service Control Manager, with the given creation values. exe_path defaults to the path name of the program that calls the function. All other 0-defaulted arguments pass 0 into the service creation, taking NT_specified defaults. Returns -1 on error, 0 on success.

Definition at line 179 of file NT_Service.cpp.

References ACE_LIB_TEXT, ACE_TCHAR, desc(), MAXPATHLEN, ACE_OS::set_errno_to_last_error(), ACE_OS::strcat(), svc_sc_handle_, and svc_status_.

00187 {
00188   ACE_TCHAR this_exe[MAXPATHLEN + 2];
00189 
00190   // Insure ACE_OS::last_error finds GetLastError unless we set errno.
00191   errno = 0;
00192 
00193   if (exe_path == 0)
00194     {
00195       if (ACE_TEXT_GetModuleFileName (0, this_exe + 1, MAXPATHLEN) == 0)
00196         return -1;
00197       // Make sure that this_exe is quoted
00198       this_exe[0] = ACE_LIB_TEXT ('\"');
00199       ACE_OS::strcat (this_exe, ACE_LIB_TEXT ("\""));
00200       exe_path = this_exe;
00201     }
00202 
00203   SC_HANDLE sc_mgr = ACE_TEXT_OpenSCManager (this->host (),
00204                                              0,
00205                                              SC_MANAGER_ALL_ACCESS);
00206   if (sc_mgr == 0)
00207     return -1;
00208 
00209   SC_HANDLE sh = ACE_TEXT_CreateService (sc_mgr,
00210                                          this->name (),
00211                                          this->desc (),
00212                                          SERVICE_ALL_ACCESS,
00213                                          this->svc_status_.dwServiceType,
00214                                          start_type,
00215                                          error_control,
00216                                          exe_path,
00217                                          group_name,
00218                                          tag_id,
00219                                          dependencies,
00220                                          account_name,
00221                                          password);
00222   // If there was an error, stash GetLastError before CloseServiceHandle
00223   // smashes it. ACE_OS::last_error will find the saved error value.
00224   if (sh == 0)
00225     ACE_OS::set_errno_to_last_error ();
00226 
00227   CloseServiceHandle (sc_mgr);
00228 
00229   if (sh == 0)
00230     return -1;
00231 
00232   if (this->svc_sc_handle_ != 0)
00233     CloseServiceHandle (this->svc_sc_handle_);
00234   this->svc_sc_handle_ = sh;
00235 
00236   return 0;
00237 
00238 }

void ACE_NT_Service::interrogate_requested DWORD  control_code  )  [protected, virtual]
 

Called by when a interrogate was requested.

Definition at line 139 of file NT_Service.cpp.

References report_status().

Referenced by handle_control().

00140 {
00141   this->report_status (0);
00142 }

ACE_INLINE const ACE_TCHAR * ACE_NT_Service::name void   )  const
 

Get the service name.

Reimplemented from ACE_Task< ACE_MT_SYNCH >.

Definition at line 59 of file NT_Service.inl.

00060 {
00061   return name_;
00062 }

void ACE_NT_Service::name const ACE_TCHAR name,
const ACE_TCHAR desc = 0
 

Sets the name and description for the service. If desc is 0, it takes the same value as name.

Definition at line 145 of file NT_Service.cpp.

References ACE_TCHAR, and ACE::strnew().

00146 {
00147   delete [] this->desc_;
00148   delete [] this->name_;
00149 
00150   if (desc == 0)
00151     desc = name;
00152 
00153   this->name_ = ACE::strnew (name);
00154   this->desc_ = ACE::strnew (desc);
00155 }

int ACE_NT_Service::open void *  args = 0  )  [virtual]
 

Hook called to open the service. By default, sets the service status to SERVICE_START_PENDING, calls the svc() method, interprets and sets the service status, and returns.

Reimplemented from ACE_Task_Base.

Definition at line 56 of file NT_Service.cpp.

References report_status(), svc(), and svc_status_.

00057 {
00058   ACE_UNUSED_ARG (args);
00059   this->report_status (SERVICE_START_PENDING, 0);
00060 
00061   int svc_return = this->svc ();
00062   if (svc_return == 0)
00063     {
00064       this->svc_status_.dwWin32ExitCode = NO_ERROR;
00065       this->svc_status_.dwServiceSpecificExitCode = 0;
00066     }
00067   else
00068     {
00069       if (errno == 0)
00070         {
00071           this->svc_status_.dwWin32ExitCode = GetLastError ();
00072         }
00073       else
00074         {
00075           this->svc_status_.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
00076           this->svc_status_.dwServiceSpecificExitCode = errno;
00077         }
00078     }
00079 
00080   return svc_return;
00081 
00082 }

void ACE_NT_Service::pause_requested DWORD  control_code  )  [protected, virtual]
 

Called by when a pause was requested.

Definition at line 123 of file NT_Service.cpp.

References report_status(), and ACE_Task_Base::suspend().

Referenced by handle_control().

00124 {
00125   this->report_status (SERVICE_PAUSE_PENDING);
00126   this->suspend ();
00127   this->report_status (SERVICE_PAUSED);
00128 }

int ACE_NT_Service::pause_svc ACE_Time_Value wait_time = 0,
DWORD *  svc_state = 0
 

Pause the service.

Definition at line 365 of file NT_Service.cpp.

References svc_sc_handle(), svc_status_, and wait_for_service_state().

00367 {
00368   SC_HANDLE svc = this->svc_sc_handle ();
00369   if (svc == 0)
00370     return -1;
00371 
00372   if (!ControlService (svc,
00373                        SERVICE_CONTROL_PAUSE,
00374                        &this->svc_status_))
00375     return -1;
00376 
00377   this->wait_for_service_state (SERVICE_PAUSED,
00378                                 wait_time);
00379   if (svc_state != 0)
00380     *svc_state = this->svc_status_.dwCurrentState;
00381 
00382   return 0;
00383 }

int ACE_NT_Service::remove void   ) 
 

Remove the service from the NT Service Control Manager. Returns -1 on error, 0 on success. This just affects the SCM and registry - the can and will keep running fine if it is already running.

Definition at line 241 of file NT_Service.cpp.

References svc_sc_handle().

00242 {
00243   if (this->svc_sc_handle () == 0)
00244     return -1;
00245 
00246   if (DeleteService (this->svc_sc_handle()) == 0
00247       && GetLastError () != ERROR_SERVICE_MARKED_FOR_DELETE)
00248     return -1;
00249 
00250   return 0;
00251 }

int ACE_NT_Service::report_status DWORD  new_status,
DWORD  time_hint = 0
[protected]
 

Definition at line 485 of file NT_Service.cpp.

References svc_status_.

Referenced by continue_requested(), fini(), interrogate_requested(), open(), pause_requested(), and stop_requested().

00487 {
00488   int bump_checkpoint = 0;
00489   int retval = 0;
00490   DWORD save_controls = 0;
00491 
00492   if (new_status != 0)
00493     this->svc_status_.dwCurrentState = new_status;
00494   switch (this->svc_status_.dwCurrentState)
00495     {
00496   case SERVICE_START_PENDING:
00497     save_controls = this->svc_status_.dwControlsAccepted;
00498     this->svc_status_.dwControlsAccepted = 0;
00499     /* Fall through */
00500   case SERVICE_STOP_PENDING:
00501   case SERVICE_CONTINUE_PENDING:
00502   case SERVICE_PAUSE_PENDING:
00503     this->svc_status_.dwWaitHint = time_hint ? time_hint : this->start_time_;
00504     bump_checkpoint = 1;
00505     break;
00506 
00507   default:
00508     this->svc_status_.dwCheckPoint = 0;
00509   }
00510 
00511   retval = SetServiceStatus (this->svc_handle_,
00512                              &this->svc_status_) ? 0 : -1;
00513 
00514   if (save_controls != 0)
00515     this->svc_status_.dwControlsAccepted = save_controls;
00516 
00517   if (bump_checkpoint)
00518     ++this->svc_status_.dwCheckPoint;
00519 
00520   return retval;
00521 }

int ACE_NT_Service::start_svc ACE_Time_Value wait_time = 0,
DWORD *  svc_state = 0,
DWORD  argc = 0,
const ACE_TCHAR **  argv = 0
 

Start the service (must have been inserted before). wait_time is the time to wait for the service to reach a steady state before returning. If it is 0, the function waits as long as it takes for the service to reach the 'running' state, or gets stuck in some other state, or exits. If is supplied, it is updated on return to hold the service's last reported wait hint. svc_state can be used to receive the state which the service settled in. If the value is 0, the service never ran. argc/argv are passed to the service's ServiceMain function when it starts. Returns 0 for success, -1 for error.

Definition at line 325 of file NT_Service.cpp.

References ACE_TCHAR, svc_sc_handle(), svc_status_, and wait_for_service_state().

00328 {
00329   SC_HANDLE svc = this->svc_sc_handle ();
00330   if (svc == 0)
00331     return -1;
00332 
00333   if (!ACE_TEXT_StartService (svc, argc, argv))
00334     return -1;
00335 
00336   this->wait_for_service_state (SERVICE_RUNNING, wait_time);
00337   if (svc_state != 0)
00338     *svc_state = this->svc_status_.dwCurrentState;
00339 
00340   return 0;
00341 }

DWORD ACE_NT_Service::startup void   ) 
 

Returns the current startup type.

Definition at line 280 of file NT_Service.cpp.

References svc_sc_handle().

00281 {
00282   // The query buffer will hold strings as well as the defined struct.
00283   // The string pointers in the struct point to other areas in the
00284   // passed memory area, so it has to be large enough to hold the
00285   // struct plus all the strings.
00286   char cfgbuff[1024];
00287   LPQUERY_SERVICE_CONFIG cfg;
00288   DWORD cfgsize, needed_size;
00289 
00290   SC_HANDLE svc = this->svc_sc_handle ();
00291   if (svc == 0)
00292   {
00293     // To distinguish this error from the QueryServiceConfig failure
00294     // below, return the DWORD equivalent of -2, rather than -1.
00295     return MAXDWORD - 1;
00296   }
00297   cfgsize = sizeof cfgbuff;
00298   cfg = (LPQUERY_SERVICE_CONFIG) cfgbuff;
00299   BOOL ok = QueryServiceConfig (svc, cfg, cfgsize, &needed_size);
00300   if (ok)
00301     return cfg->dwStartType;
00302   // Zero is a valid return value for QueryServiceConfig, so if
00303   // QueryServiceConfig fails, return the DWORD equivalent of -1.
00304   return MAXDWORD;
00305 
00306 }

int ACE_NT_Service::startup DWORD  startup  ) 
 

Sets the startup type for the service. Returns -1 on error, 0 on success.

Definition at line 256 of file NT_Service.cpp.

References svc_sc_handle().

00257 {
00258   SC_HANDLE svc = this->svc_sc_handle ();
00259   if (svc == 0)
00260     return -1;
00261 
00262   BOOL ok =
00263     ChangeServiceConfig (svc,
00264                          (DWORD) SERVICE_NO_CHANGE,// No change to service type
00265                          startup,                  // New startup type
00266                          (DWORD) SERVICE_NO_CHANGE,// No change to error ctrl
00267                          0,                        // No change to pathname
00268                          0,                        // No change to load group
00269                          0,                        // No change to tag
00270                          0,                        // No change to dependencies
00271                          0, 0,                     // No change to acct/passwd
00272                          0);                       // No change to name
00273 
00274   return ok ? 0 : -1;
00275 }

int ACE_NT_Service::state DWORD *  pstate,
ACE_Time_Value wait_hint = 0
 

A version of that returns -1 for failure, 0 for success. The DWORD pointed to by pstate receives the state value.

Definition at line 418 of file NT_Service.cpp.

References ACE_Time_Value::msec(), svc_sc_handle(), and svc_status_.

00420 {
00421   SC_HANDLE svc = this->svc_sc_handle ();
00422 
00423   if (svc == 0)
00424     return -1;
00425 
00426   // Need to create a temporary copy of this variable since the
00427   // QueryServiceStatus call will modify the setting depending on the
00428   // current state of the Service.  If the service is currently
00429   // STOPPED, the value will be cleared.
00430   DWORD controls_accepted = this->svc_status_.dwControlsAccepted;
00431 
00432   if (QueryServiceStatus (svc,
00433                           &this->svc_status_) == 0)
00434     return -1;
00435 
00436   if (wait_hint != 0)
00437     wait_hint->msec (this->svc_status_.dwWaitHint);
00438 
00439   *pstate = this->svc_status_.dwCurrentState;
00440   this->svc_status_.dwControlsAccepted = controls_accepted;
00441   return 0;
00442 }

DWORD ACE_NT_Service::state ACE_Time_Value wait_hint = 0  ) 
 

Get the current state for the service. If is not 0, it receives the service's reported wait hint. Note that this function returns 0 on failure (not -1 as is usual in ACE). A zero return would (probably) only be returned if there is either no service with the given name in the SCM database, or the caller does not have sufficient rights to access the service state. The set of valid service state values are all greater than 0.

Definition at line 407 of file NT_Service.cpp.

00408 {
00409   DWORD curr_state;
00410 
00411   if (this->state (&curr_state,
00412                    wait_hint) == -1)
00413     return 0;
00414   return curr_state;
00415 }

void ACE_NT_Service::stop_requested DWORD  control_code  )  [protected, virtual]
 

Called by when a stop/shutdown was requested.

Definition at line 116 of file NT_Service.cpp.

References report_status().

Referenced by handle_control().

00117 {
00118   this->report_status (SERVICE_STOP_PENDING);
00119   /* how to cancel? */
00120 }

int ACE_NT_Service::stop_svc ACE_Time_Value wait_time = 0,
DWORD *  svc_state = 0
 

Requests the service to stop. Will wait up to for the service to actually stop. If not specified, the function waits until the service either stops or gets stuck in some other state before it stops. If is specified, it receives the last reported state of the service. Returns 0 if the request was made successfully, -1 if not.

Definition at line 344 of file NT_Service.cpp.

References svc_sc_handle(), svc_status_, and wait_for_service_state().

00346 {
00347   SC_HANDLE svc = this->svc_sc_handle ();
00348   if (svc == 0)
00349     return -1;
00350 
00351   if (!ControlService (svc,
00352                        SERVICE_CONTROL_STOP,
00353                        &this->svc_status_))
00354     return -1;
00355 
00356   this->wait_for_service_state (SERVICE_STOPPED,
00357                                 wait_time);
00358   if (svc_state != 0)
00359     *svc_state = this->svc_status_.dwCurrentState;
00360 
00361   return 0;
00362 }

ACE_INLINE int ACE_NT_Service::svc void   )  [virtual]
 

The actual service implementation. This function need not be overridden by applications that are just using SCM capabilities, but must be by subclasses when actually running the service. It is expected that this function will set the status to RUNNING.

Reimplemented from ACE_Task_Base.

Definition at line 51 of file NT_Service.inl.

Referenced by open().

00052 {
00053   return -1;
00054 }

ACE_INLINE void ACE_NT_Service::svc_handle const SERVICE_STATUS_HANDLE  new_svc_handle  ) 
 

Set the svc_handle_ member. This is only a public function because the macro-generated service function calls it.

Definition at line 79 of file NT_Service.inl.

References svc_handle_.

00080 {
00081   this->svc_handle_ = new_svc_handle;
00082   return;
00083 }

SC_HANDLE ACE_NT_Service::svc_sc_handle void   )  [protected]
 

Return the svc_sc_handle_ member. If the member is null, it retrieves the handle from the Service Control Manager and caches it.

Definition at line 524 of file NT_Service.cpp.

References ACE_OS::set_errno_to_last_error(), and svc_sc_handle_.

Referenced by continue_svc(), pause_svc(), remove(), start_svc(), startup(), state(), and stop_svc().

00525 {
00526   if (this->svc_sc_handle_ == 0)
00527     {
00528       SC_HANDLE sc_mgr = ACE_TEXT_OpenSCManager (this->host (),
00529                                                  0,
00530                                                  SC_MANAGER_ALL_ACCESS);
00531       if (sc_mgr != 0)
00532         {
00533           this->svc_sc_handle_ = ACE_TEXT_OpenService (sc_mgr,
00534                                                        this->name (),
00535                                                        SERVICE_ALL_ACCESS);
00536           if (this->svc_sc_handle_ == 0)
00537             ACE_OS::set_errno_to_last_error ();
00538           CloseServiceHandle (sc_mgr);
00539         }
00540       else
00541         ACE_OS::set_errno_to_last_error ();
00542     }
00543 
00544   return this->svc_sc_handle_;
00545 }

int ACE_NT_Service::test_access DWORD  desired_access = SERVICE_ALL_ACCESS  ) 
 

Test access to the object's service in the SCM. The service must already have been inserted in the SCM database. This function has no affect on the service itself. Returns 0 if the specified access is allowed, -1 otherwise (either the access is denied, or there is a problem with the service's definition - check ACE_OS::last_error to get the specific error indication.

Definition at line 451 of file NT_Service.cpp.

00452 {
00453   int status = -1;     // Guilty until proven innocent
00454 
00455   SC_HANDLE sc_mgr = ACE_TEXT_OpenSCManager (this->host (),
00456                                              0,
00457                                              GENERIC_READ);
00458   if (sc_mgr != 0)
00459     {
00460       SC_HANDLE handle = ACE_TEXT_OpenService (sc_mgr,
00461                                                this->name (),
00462                                                desired_access);
00463       CloseServiceHandle (sc_mgr);
00464       if (handle != 0)
00465         {
00466           status = 0;
00467           CloseServiceHandle (handle);
00468         }
00469     }
00470 
00471   return status;
00472 }

void ACE_NT_Service::wait_for_service_state DWORD  desired_state,
ACE_Time_Value wait_time
[protected]
 

Waits for the service to reach or get (apparently) stuck before it reaches that state. Will wait at most to get to the desired state. If is 0, then the function keeps waiting until the desired state is reached or the service doesn't update its state any further. The svc_status_ class member is updated upon return.

Definition at line 548 of file NT_Service.cpp.

References ETIME, ACE_OS::gettimeofday(), and svc_status_.

Referenced by continue_svc(), pause_svc(), start_svc(), and stop_svc().

00550 {
00551   DWORD last_state = 0;
00552   DWORD last_check_point = 0;
00553   int first_time = 1;
00554   int service_ok;
00555 
00556   ACE_Time_Value time_out = ACE_OS::gettimeofday ();
00557   if (wait_time != 0)
00558     time_out += *wait_time;
00559 
00560   // Poll until the service reaches the desired state.
00561   for (;;)
00562     {
00563       service_ok = 0 != QueryServiceStatus (this->svc_sc_handle_,
00564                                             &this->svc_status_);
00565 
00566       // If we cannot query the service, we are done.
00567       if (!service_ok)
00568         break;
00569 
00570       // If the service has the desired state, we are done.
00571       if (desired_state == this->svc_status_.dwCurrentState)
00572         break;
00573 
00574       // If we time-out, we are done
00575       if (wait_time != 0 && ACE_OS::gettimeofday () > time_out )
00576         {
00577           errno = ETIME;
00578           break;
00579         }
00580 
00581       if (first_time)
00582         {
00583           // remember the service state, the first time we wait
00584           last_state       = this->svc_status_.dwCurrentState;
00585           last_check_point = this->svc_status_.dwCheckPoint;
00586           first_time = 0;
00587         }
00588       else
00589         {
00590           // update the state change.
00591           if (last_state != this->svc_status_.dwCurrentState)
00592             {
00593               last_state       = this->svc_status_.dwCurrentState;
00594               last_check_point = this->svc_status_.dwCheckPoint;
00595             }
00596           else
00597             {
00598               // The check-point should have increased
00599               if (this->svc_status_.dwCheckPoint > last_check_point)
00600                 last_check_point = this->svc_status_.dwCheckPoint;
00601               else
00602                 {
00603                   // Service control failure, we are done.
00604                   service_ok = 0;
00605                   break;
00606                 }
00607             }
00608         }
00609 
00610       ::Sleep (this->svc_status_.dwWaitHint);
00611     }
00612 
00613   return;
00614 }


Member Data Documentation

ACE_NT_Service::ACE_ALLOC_HOOK_DECLARE
 

Declare the dynamic allocation hooks.

Reimplemented from ACE_Task< ACE_MT_SYNCH >.

Definition at line 320 of file NT_Service.h.

ACE_TCHAR* ACE_NT_Service::desc_ [protected]
 

Definition at line 365 of file NT_Service.h.

ACE_TCHAR* ACE_NT_Service::host_ [protected]
 

Definition at line 366 of file NT_Service.h.

Referenced by host(), and ~ACE_NT_Service().

ACE_OS_Log_Msg_Attributes ACE_NT_Service::log_msg_attributes_ [protected]
 

ACE_Log_Msg attributes to inherit from the starting thread.

Definition at line 369 of file NT_Service.h.

ACE_TCHAR* ACE_NT_Service::name_ [protected]
 

Definition at line 364 of file NT_Service.h.

DWORD ACE_NT_Service::start_time_ [protected]
 

Estimate of init time needed.

Definition at line 357 of file NT_Service.h.

SERVICE_STATUS_HANDLE ACE_NT_Service::svc_handle_ [protected]
 

Service handle - doesn't need close.

Definition at line 359 of file NT_Service.h.

Referenced by svc_handle().

SC_HANDLE ACE_NT_Service::svc_sc_handle_ [protected]
 

Service's SCM handle.

Definition at line 363 of file NT_Service.h.

Referenced by host(), insert(), svc_sc_handle(), and ~ACE_NT_Service().

SERVICE_STATUS ACE_NT_Service::svc_status_ [protected]
 

Definition at line 360 of file NT_Service.h.

Referenced by ACE_NT_Service(), continue_svc(), insert(), open(), pause_svc(), report_status(), start_svc(), state(), stop_svc(), and wait_for_service_state().


The documentation for this class was generated from the following files:
Generated on Thu Nov 9 11:25:56 2006 for ACE by doxygen 1.3.6