⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winservice.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
  winservice_status_handle =    RegisterServiceCtrlHandler(WINSERVICE_SERVICE_NAME, winservice_handler);  if (winservice_status_handle == NULL)    {      /* Ok, that's not fair.  We received a request to start a service,         and now we cannot bind to the SCM in order to update status?         Bring down the app. */      error = GetLastError();      dbg_print("RegisterServiceCtrlHandler FAILED\r\n");      /* Put the error code somewhere where winservice_start can find it. */      winservice_status.dwWin32ExitCode = error;      SetEvent(winservice_start_event);      return;    }  winservice_status.dwCurrentState = SERVICE_START_PENDING;  winservice_status.dwWin32ExitCode = ERROR_SUCCESS;  winservice_update_state();  dbg_print("winservice_service_main: service is starting\r\n");  SetEvent(winservice_start_event);}static const SERVICE_TABLE_ENTRY winservice_service_table[] =  {    { WINSERVICE_SERVICE_NAME, winservice_service_main },    { NULL, NULL }  };/* This is the thread routine for the "dispatcher" thread.  The   purpose of this thread is to connect this process with the Service   Control Manager, which allows this process to receive control   requests from the SCM, and allows this process to update the SCM   with status information.   The StartServiceCtrlDispatcher connects this process to the SCM.   If it succeeds, then it will not return until all of the services   running in this process have stopped.  (In our case, there is only   one service per process.) */static DWORD WINAPIwinservice_dispatcher_thread_routine(PVOID arg){  dbg_print("winservice_dispatcher_thread_routine: starting\r\n");  if (!StartServiceCtrlDispatcher(winservice_service_table))    {      /* This is a common error.  Usually, it means the user has         invoked the service with the --service flag directly.  This         is incorrect.  The only time the --service flag is passed is         when the process is being started by the SCM. */      DWORD error = GetLastError();      dbg_print("dispatcher: FAILED to connect to SCM\r\n");      return error;    }  dbg_print("dispatcher: SCM is done using this process -- exiting\r\n");  return ERROR_SUCCESS;}/* If svnserve needs to run as a Win32 service, then we need to   coordinate with the Service Control Manager (SCM) before   continuing.  This function call registers the svnserve.exe process   with the SCM, waits for the "start" command from the SCM (which   will come very quickly), and confirms that those steps succeeded.   After this call succeeds, the service should perform whatever work   it needs to start the service, and then the service should call   winservice_running() (if no errors occurred) or winservice_stop()   (if something failed during startup). */svn_error_t *winservice_start(void){  HANDLE handles[2];  DWORD thread_id;  DWORD error_code;  apr_status_t apr_status;  DWORD wait_status;  dbg_print("winservice_start: starting svnserve as a service...\r\n");  ZeroMemory(&winservice_status, sizeof(winservice_status));  winservice_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;  winservice_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;  winservice_status.dwCurrentState = SERVICE_STOPPED;  /* Create the event that will wake up this thread when the SCM     creates the ServiceMain thread. */  winservice_start_event = CreateEvent(NULL, FALSE, FALSE, NULL);  if (winservice_start_event == NULL)    {      apr_status = apr_get_os_error();      return svn_error_wrap_apr(apr_status,                                _("Failed to create winservice_start_event"));    }  winservice_dispatcher_thread =    (HANDLE)_beginthreadex(NULL, 0, winservice_dispatcher_thread_routine,                           NULL, 0, &thread_id);  if (winservice_dispatcher_thread == NULL)    {      apr_status = apr_get_os_error();      winservice_cleanup();      return svn_error_wrap_apr(apr_status,                                _("The service failed to start"));    }  /* Next, we wait for the "start" event to fire (meaning the service     logic has successfully started), or for the dispatch thread to     exit (meaning the service logic could not start). */  handles[0] = winservice_start_event;  handles[1] = winservice_dispatcher_thread;  wait_status = WaitForMultipleObjects(2, handles, FALSE, INFINITE);  switch (wait_status)    {    case WAIT_OBJECT_0:      dbg_print("winservice_start: service is now starting\r\n");      /* We no longer need the start event. */      CloseHandle(winservice_start_event);      winservice_start_event = NULL;      /* Register our cleanup logic. */      atexit(winservice_atexit);      return SVN_NO_ERROR;    case WAIT_OBJECT_0+1:      /* The dispatcher thread exited without starting the service.         This happens when the dispatcher fails to connect to the SCM. */      dbg_print("winservice_start: dispatcher thread has failed\r\n");      if (GetExitCodeThread(winservice_dispatcher_thread, &error_code))        {          dbg_print("winservice_start: dispatcher thread failed\r\n");          if (error_code == ERROR_SUCCESS)            error_code = ERROR_INTERNAL_ERROR;        }      else        {          error_code = ERROR_INTERNAL_ERROR;        }      CloseHandle(winservice_dispatcher_thread);      winservice_dispatcher_thread = NULL;      winservice_cleanup();      return svn_error_wrap_apr        (APR_FROM_OS_ERROR(error_code),         _("Failed to connect to Service Control Manager"));    default:      /* This should never happen! This indicates that our handles are         broken, or some other highly unusual error.  There is nothing         rational that we can do to recover. */      apr_status = apr_get_os_error();      dbg_print("winservice_start: WaitForMultipleObjects failed!\r\n");      winservice_cleanup();      return svn_error_wrap_apr        (apr_status, _("The service failed to start; an internal error"                       " occurred while starting the service"));    }}/* main() calls this function in order to inform the SCM that the   service has successfully started.  This is required; otherwise, the   SCM will believe that the service is stuck in the "starting" state,   and management tools will also believe that the service is stuck. */voidwinservice_running(void){  winservice_status.dwCurrentState = SERVICE_RUNNING;  winservice_update_state();  dbg_print("winservice_notify_running: service is now running\r\n");}/* main() calls this function in order to notify the SCM that the   service has stopped.  This function also handles cleaning up the   dispatcher thread (the one that we created above in   winservice_start. */static voidwinservice_stop(DWORD exit_code){  dbg_print("winservice_stop - notifying SCM that service has stopped\r\n");  winservice_status.dwCurrentState = SERVICE_STOPPED;  winservice_status.dwWin32ExitCode = exit_code;  winservice_update_state();  if (winservice_dispatcher_thread != NULL)    {      dbg_print("waiting for dispatcher thread to exit...\r\n");      WaitForSingleObject(winservice_dispatcher_thread, INFINITE);      dbg_print("dispatcher thread has exited.\r\n");      CloseHandle(winservice_dispatcher_thread);      winservice_dispatcher_thread = NULL;    }  else    {      /* There was no dispatcher thread.  So we never started in          the first place. */      exit_code = winservice_status.dwWin32ExitCode;      dbg_print("dispatcher thread was not running\r\n");    }  if (winservice_start_event != NULL)    {      CloseHandle(winservice_start_event);      winservice_start_event = NULL;    }  dbg_print("winservice_stop - service has stopped\r\n");}/* This function is installed as an atexit-handler.  This is done so  that we don't need to alter every exit() call in main(). */static voidwinservice_atexit(void){  dbg_print("winservice_atexit - stopping\r\n");  winservice_stop(ERROR_SUCCESS);}svn_boolean_twinservice_is_stopping(void){  return (winservice_status.dwCurrentState == SERVICE_STOP_PENDING);}#endif /* WIN32 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -