diff options
Diffstat (limited to 'ace/NT_Service.cpp')
-rw-r--r-- | ace/NT_Service.cpp | 610 |
1 files changed, 0 insertions, 610 deletions
diff --git a/ace/NT_Service.cpp b/ace/NT_Service.cpp deleted file mode 100644 index 1562ed4c9f0..00000000000 --- a/ace/NT_Service.cpp +++ /dev/null @@ -1,610 +0,0 @@ -// $Id$ - -// NT_Service.cpp - -#include "ace/config-all.h" -#if defined (ACE_WIN32) && \ - !defined (ACE_HAS_PHARLAP) && !defined (ACE_HAS_WINCE) - -#include "ace/NT_Service.h" -#include "ace/Log_Msg.h" -#include "ace/Service_Object.h" - -#if !defined (__ACE_INLINE__) -#include "ace/NT_Service.i" -#endif /* __ACE_INLINE__ */ - -ACE_ALLOC_HOOK_DEFINE(ACE_NT_Service) - -// ACE_NT_Service destructor. - -ACE_NT_Service::~ACE_NT_Service (void) -{ - if (this->svc_sc_handle_ != 0) - { - CloseServiceHandle (this->svc_sc_handle_); - this->svc_sc_handle_ = 0; - } - delete [] this->desc_; - delete [] this->name_; - delete [] this->host_; -} - -// This default implementation of ACE_NT_Service::open sets the -// service's status to START_PENDING with the estimated time until -// STARTED set to the value given when this object was constructed. -// Then the svc function is called, which implements the guts of the -// service. Note that this function is running in a thread created by -// the OS, not by ACE_Thread_Manager. The thread manager does not -// know anything about this thread. The service can, however, use -// ACE_Thread_Manager to start more threads if desired. When the svc -// function returns, the service status is set to STOPPED, and exit -// codes set based on errno/GetLastError if the svc function returns -// -1. -// -// The svc function is expected to set the service status to SERVICE_RUNNING -// after it initializes. -// -// The handle_control function will be called for each time there is a -// request for the service. It is up to that function and svc to -// cooperate to both respond appropriately to the request (by at least -// updating the service's status) and to fulfill the request. - -int -ACE_NT_Service::open (void *args) -{ - ACE_UNUSED_ARG (args); - this->report_status (SERVICE_START_PENDING, 0); - - int svc_return = this->svc (); - if (svc_return == 0) - { - this->svc_status_.dwWin32ExitCode = NO_ERROR; - this->svc_status_.dwServiceSpecificExitCode = 0; - } - else - { - if (errno == 0) - { - this->svc_status_.dwWin32ExitCode = GetLastError (); - } - else - { - this->svc_status_.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; - this->svc_status_.dwServiceSpecificExitCode = errno; - } - } - - return svc_return; - -} - -int -ACE_NT_Service::fini (void) -{ - return this->report_status (SERVICE_STOPPED, 0); -} - - -void -ACE_NT_Service::handle_control (DWORD control_code) -{ - switch (control_code) - { - case SERVICE_CONTROL_SHUTDOWN: - case SERVICE_CONTROL_STOP: - this->stop_requested (control_code); - break; - - case SERVICE_CONTROL_PAUSE: - this->pause_requested (control_code); - break; - - case SERVICE_CONTROL_CONTINUE: - this->continue_requested (control_code); - break; - - case SERVICE_CONTROL_INTERROGATE: - this->interrogate_requested (control_code); - break; - } -} - -void -ACE_NT_Service::stop_requested (DWORD) -{ - this->report_status (SERVICE_STOP_PENDING); - /* how to cancel? */ -} - -void -ACE_NT_Service::pause_requested (DWORD) -{ - this->report_status (SERVICE_PAUSE_PENDING); - this->suspend (); - this->report_status (SERVICE_PAUSED); -} - -void -ACE_NT_Service::continue_requested (DWORD) -{ - this->report_status (SERVICE_CONTINUE_PENDING); - this->resume (); - this->report_status (SERVICE_RUNNING); -} - -void -ACE_NT_Service::interrogate_requested (DWORD) -{ - this->report_status (0); -} - -void -ACE_NT_Service::name (const ACE_TCHAR *name, const ACE_TCHAR *desc) -{ - delete [] this->desc_; - delete [] this->name_; - - if (desc == 0) - desc = name; - - this->name_ = ACE::strnew (name); - this->desc_ = ACE::strnew (desc); -} - -void -ACE_NT_Service::host (const ACE_TCHAR *host) -{ - delete [] this->host_; - - if (this->svc_sc_handle_ != 0) - { - CloseServiceHandle (this->svc_sc_handle_); - this->svc_sc_handle_ = 0; - } - - if (host == 0) - { - this->host_ = 0; - } - else - { - this->host_ = ACE::strnew (host); - } -} - -int -ACE_NT_Service::insert (DWORD start_type, - DWORD error_control, - const ACE_TCHAR *exe_path, - const ACE_TCHAR *group_name, - LPDWORD tag_id, - const ACE_TCHAR *dependencies, - const ACE_TCHAR *account_name, - const ACE_TCHAR *password) -{ - ACE_TCHAR this_exe[MAXPATHLEN]; - - // Insure ACE_OS::last_error finds GetLastError unless we set errno. - errno = 0; - - if (exe_path == 0) - { - if (ACE_TEXT_GetModuleFileName (0, this_exe, sizeof this_exe) == 0) - return -1; - exe_path = this_exe; - } - - SC_HANDLE sc_mgr = ACE_TEXT_OpenSCManager (this->host (), - 0, - SC_MANAGER_ALL_ACCESS); - if (sc_mgr == 0) - return -1; - - SC_HANDLE sh = ACE_TEXT_CreateService (sc_mgr, - this->name (), - this->desc (), - SERVICE_ALL_ACCESS, - this->svc_status_.dwServiceType, - start_type, - error_control, - exe_path, - group_name, - tag_id, - dependencies, - account_name, - password); - // If there was an error, stash GetLastError before CloseServiceHandle - // smashes it. ACE_OS::last_error will find the saved error value. - if (sh == 0) - ACE_OS::set_errno_to_last_error (); - - CloseServiceHandle (sc_mgr); - - if (sh == 0) - return -1; - - if (this->svc_sc_handle_ != 0) - CloseServiceHandle (this->svc_sc_handle_); - this->svc_sc_handle_ = sh; - - return 0; - -} - -int -ACE_NT_Service::remove (void) -{ - if (this->svc_sc_handle () == 0) - return -1; - - if (DeleteService (this->svc_sc_handle()) == 0 - && GetLastError () != ERROR_SERVICE_MARKED_FOR_DELETE) - return -1; - - return 0; -} - -// Sets the startup type for the service. Returns -1 on error, 0 on -// success. -int -ACE_NT_Service::startup (DWORD startup) -{ - SC_HANDLE svc = this->svc_sc_handle (); - if (svc == 0) - return -1; - - BOOL ok = - ChangeServiceConfig (svc, - (DWORD) SERVICE_NO_CHANGE,// No change to service type - startup, // New startup type - (DWORD) SERVICE_NO_CHANGE,// No change to error ctrl - 0, // No change to pathname - 0, // No change to load group - 0, // No change to tag - 0, // No change to dependencies - 0, 0, // No change to acct/passwd - 0); // No change to name - - return ok ? 0 : -1; -} - -// Returns the current startup type. - -DWORD -ACE_NT_Service::startup (void) -{ - // The query buffer will hold strings as well as the defined struct. - // The string pointers in the struct point to other areas in the - // passed memory area, so it has to be large enough to hold the - // struct plus all the strings. - char cfgbuff[1024]; - LPQUERY_SERVICE_CONFIG cfg; - DWORD cfgsize, needed_size; - - SC_HANDLE svc = this->svc_sc_handle (); - if (svc == 0) - { - // To distinguish this error from the QueryServiceConfig failure - // below, return the DWORD equivalent of -2, rather than -1. - return MAXDWORD - 1; - } - cfgsize = sizeof cfgbuff; - cfg = (LPQUERY_SERVICE_CONFIG) cfgbuff; - BOOL ok = QueryServiceConfig (svc, cfg, cfgsize, &needed_size); - if (ok) - return cfg->dwStartType; - // Zero is a valid return value for QueryServiceConfig, so if - // QueryServiceConfig fails, return the DWORD equivalent of -1. - return MAXDWORD; - -} - - -void -ACE_NT_Service::capture_log_msg_attributes (void) -{ - ACE_Log_Msg::init_hook (this->log_msg_attributes_); -} - -void -ACE_NT_Service::inherit_log_msg_attributes (void) -{ - // There's no thread descriptor involved with a NT-started - // thread, so the first arg is 0. - ACE_Log_Msg::inherit_hook (0, this->log_msg_attributes_); -} - - -int -ACE_NT_Service::start_svc (ACE_Time_Value *wait_time, - DWORD *svc_state, - DWORD argc, const ACE_TCHAR **argv) -{ - SC_HANDLE svc = this->svc_sc_handle (); - if (svc == 0) - return -1; - - if (!ACE_TEXT_StartService (svc, argc, argv)) - return -1; - - this->wait_for_service_state (SERVICE_RUNNING, wait_time); - if (svc_state != 0) - *svc_state = this->svc_status_.dwCurrentState; - - return 0; -} - -int -ACE_NT_Service::stop_svc (ACE_Time_Value *wait_time, - DWORD *svc_state) -{ - SC_HANDLE svc = this->svc_sc_handle (); - if (svc == 0) - return -1; - - if (!ControlService (svc, - SERVICE_CONTROL_STOP, - &this->svc_status_)) - return -1; - - this->wait_for_service_state (SERVICE_STOPPED, - wait_time); - if (svc_state != 0) - *svc_state = this->svc_status_.dwCurrentState; - - return 0; -} - -int -ACE_NT_Service::pause_svc (ACE_Time_Value *wait_time, - DWORD *svc_state) -{ - SC_HANDLE svc = this->svc_sc_handle (); - if (svc == 0) - return -1; - - if (!ControlService (svc, - SERVICE_CONTROL_PAUSE, - &this->svc_status_)) - return -1; - - this->wait_for_service_state (SERVICE_PAUSED, - wait_time); - if (svc_state != 0) - *svc_state = this->svc_status_.dwCurrentState; - - return 0; -} - -int -ACE_NT_Service::continue_svc (ACE_Time_Value *wait_time, - DWORD *svc_state) -{ - SC_HANDLE svc = this->svc_sc_handle (); - if (svc == 0) - return -1; - - if (!ControlService (svc, - SERVICE_CONTROL_CONTINUE, - &this->svc_status_)) - return -1; - - this->wait_for_service_state (SERVICE_RUNNING, - wait_time); - if (svc_state != 0) - *svc_state = this->svc_status_.dwCurrentState; - - return 0; -} - -DWORD -ACE_NT_Service::state (ACE_Time_Value *wait_hint) -{ - DWORD curr_state; - - if (this->state (&curr_state, - wait_hint) == -1) - return 0; - return curr_state; -} - -int -ACE_NT_Service::state (DWORD *pstate, - ACE_Time_Value *wait_hint) -{ - SC_HANDLE svc = this->svc_sc_handle (); - - if (svc == 0) - return -1; - - // Need to create a temporary copy of this variable since the - // QueryServiceStatus call will modify the setting depending on the - // current state of the Service. If the service is currently - // STOPPED, the value will be cleared. - DWORD controls_accepted = this->svc_status_.dwControlsAccepted; - - if (QueryServiceStatus (svc, - &this->svc_status_) == 0) - return -1; - - if (wait_hint != 0) - wait_hint->msec (this->svc_status_.dwWaitHint); - - *pstate = this->svc_status_.dwCurrentState; - this->svc_status_.dwControlsAccepted = controls_accepted; - return 0; -} - -// test_access -// -// Open a new handle, ignoring any handle open in svc_sc_handle_. -// This function's results are returned without leaving the handle -// open. - -int -ACE_NT_Service::test_access (DWORD desired_access) -{ - int status = -1; // Guilty until proven innocent - - SC_HANDLE sc_mgr = ACE_TEXT_OpenSCManager (this->host (), - 0, - GENERIC_READ); - if (sc_mgr != 0) - { - SC_HANDLE handle = ACE_TEXT_OpenService (sc_mgr, - this->name (), - desired_access); - CloseServiceHandle (sc_mgr); - if (handle != 0) - { - status = 0; - CloseServiceHandle (handle); - } - } - - return status; -} - -// report_status -// -// Reports the current status. If new_status is not 0, it sets the -// status to the new value before reporting. NOTE - this assumes that -// no actual service status values have the value 0. This is true in -// WinNT 4. If the status is a 'pending' type, the supplied time hint -// is used unless it's 0, in which case the existing hint is used. -// The dwWaitHint is not updated by this function. The checkpoint is -// incremented by one after a pending report. - -int -ACE_NT_Service::report_status (DWORD new_status, - DWORD time_hint) -{ - int bump_checkpoint = 0; - int retval = 0; - DWORD save_controls = 0; - - if (new_status != 0) - this->svc_status_.dwCurrentState = new_status; - switch (this->svc_status_.dwCurrentState) - { - case SERVICE_START_PENDING: - save_controls = this->svc_status_.dwControlsAccepted; - this->svc_status_.dwControlsAccepted = 0; - /* Fall through */ - case SERVICE_STOP_PENDING: - case SERVICE_CONTINUE_PENDING: - case SERVICE_PAUSE_PENDING: - this->svc_status_.dwWaitHint = time_hint ? time_hint : this->start_time_; - bump_checkpoint = 1; - break; - - default: - this->svc_status_.dwCheckPoint = 0; - } - - retval = SetServiceStatus (this->svc_handle_, - &this->svc_status_) ? 0 : -1; - - if (save_controls != 0) - this->svc_status_.dwControlsAccepted = save_controls; - - if (bump_checkpoint) - ++this->svc_status_.dwCheckPoint; - - return retval; -} - -SC_HANDLE -ACE_NT_Service::svc_sc_handle (void) -{ - if (this->svc_sc_handle_ == 0) - { - SC_HANDLE sc_mgr = ACE_TEXT_OpenSCManager (this->host (), - 0, - SC_MANAGER_ALL_ACCESS); - if (sc_mgr != 0) - { - this->svc_sc_handle_ = ACE_TEXT_OpenService (sc_mgr, - this->name (), - SERVICE_ALL_ACCESS); - if (this->svc_sc_handle_ == 0) - ACE_OS::set_errno_to_last_error (); - CloseServiceHandle (sc_mgr); - } - else - ACE_OS::set_errno_to_last_error (); - } - - return this->svc_sc_handle_; -} - -void -ACE_NT_Service::wait_for_service_state (DWORD desired_state, - ACE_Time_Value *wait_time) -{ - DWORD last_state, last_check_point; - int first_time = 1; - int service_ok; - - ACE_Time_Value time_out = ACE_OS::gettimeofday (); - if (wait_time != 0) - time_out += *wait_time; - - // Poll until the service reaches the desired state. - for (;;) - { - service_ok = 0 != QueryServiceStatus (this->svc_sc_handle_, - &this->svc_status_); - - // If we cannot query the service, we are done. - if (!service_ok) - break; - - // If the service has the desired state, we are done. - if (desired_state == this->svc_status_.dwCurrentState) - break; - - // If we time-out, we are done - if (wait_time != 0 && ACE_OS::gettimeofday () > time_out ) - { - errno = ETIME; - break; - } - - if (first_time) - { - // remember the service state, the first time we wait - last_state = this->svc_status_.dwCurrentState; - last_check_point = this->svc_status_.dwCheckPoint; - first_time = 0; - } - else - { - // update the state change. - if (last_state != this->svc_status_.dwCurrentState) - { - last_state = this->svc_status_.dwCurrentState; - last_check_point = this->svc_status_.dwCheckPoint; - } - else - { - // The check-point should have increased - if (this->svc_status_.dwCheckPoint > last_check_point) - last_check_point = this->svc_status_.dwCheckPoint; - else - { - // Service control failure, we are done. - service_ok = 0; - break; - } - } - } - - ::Sleep (this->svc_status_.dwWaitHint); - } - - return; -} - -#endif /* ACE_WIN32 && !ACE_HAS_PHARLAP */ |