/* * Creates a worker thread. */ static void create_worker(void (*func)(void *), void *arg, cb_thread_t *id) { int ret; if ((ret = cb_create_thread(id, func, arg, 0)) != 0) { log_system_error(EXTENSION_LOG_WARNING, NULL, "Can't create thread: %s"); exit(1); } }
static VOID WINAPI service_main (DWORD argc, LPWSTR * argv) { (void) argc; (void) argv; status_handle = RegisterServiceCtrlHandlerExW (service_name, &handle_service_ctrl, NULL); if (status_handle == NULL) { log_system_error (TR_LOG_ERROR, GetLastError (), "RegisterServiceCtrlHandlerEx() failed"); return; } update_service_status (SERVICE_START_PENDING, NO_ERROR, 0, 1, 1000); service_thread = (HANDLE) _beginthreadex (NULL, 0, &service_thread_main, NULL, 0, NULL); if (service_thread == NULL) { log_system_error (TR_LOG_ERROR, GetLastError (), "_beginthreadex() failed"); return; } update_service_status (SERVICE_RUNNING, NO_ERROR, 0, 0, 0); if (WaitForSingleObject (service_thread, INFINITE) != WAIT_OBJECT_0) log_system_error (TR_LOG_ERROR, GetLastError (), "WaitForSingleObject() failed"); if (service_stop_thread != NULL) { WaitForSingleObject (service_stop_thread, INFINITE); CloseHandle (service_stop_thread); } DWORD exit_code; if (!GetExitCodeThread (service_thread, &exit_code)) exit_code = 1; CloseHandle (service_thread); update_service_status (SERVICE_STOPPED, NO_ERROR, exit_code, 0, 0); }
static void stop_service (void) { if (service_stop_thread != NULL) { return; } const DWORD wait_time = 30 * 1000; update_service_status (SERVICE_STOP_PENDING, NO_ERROR, 0, 1, wait_time); service_stop_thread = (HANDLE) _beginthreadex (NULL, 0, &service_stop_thread_main, (LPVOID) (UINT_PTR) wait_time, 0, NULL); if (service_stop_thread == NULL) { log_system_error (TR_LOG_DEBUG, GetLastError (), "_beginthreadex() failed, trying to stop synchronously"); service_stop_thread_main ((LPVOID) (UINT_PTR) wait_time); } }
static void update_service_status (DWORD new_state, DWORD win32_exit_code, DWORD service_specific_exit_code, DWORD check_point, DWORD wait_hint) { SERVICE_STATUS status; status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; status.dwCurrentState = new_state; status.dwControlsAccepted = new_state != SERVICE_RUNNING ? 0 : SERVICE_ACCEPT_PRESHUTDOWN | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PARAMCHANGE; status.dwWin32ExitCode = service_specific_exit_code == 0 ? win32_exit_code : ERROR_SERVICE_SPECIFIC_ERROR; status.dwServiceSpecificExitCode = service_specific_exit_code; status.dwCheckPoint = check_point; status.dwWaitHint = wait_hint; if (SetServiceStatus (status_handle, &status)) current_state = new_state; else log_system_error (TR_LOG_DEBUG, GetLastError (), "SetServiceStatus() failed"); }