// // FUNCTION: service_ctrl // // PURPOSE: This function is called by the SCM whenever // ControlService() is called on this service. // // PARAMETERS: // dwCtrlCode - type of control requested // // RETURN VALUE: // none // // COMMENTS: See the user-defined Handler() entry in the PSDK // VOID WINAPI service_ctrl(DWORD dwCtrlCode) { switch(dwCtrlCode) { // Stop the service. // case SERVICE_CONTROL_SHUTDOWN: case SERVICE_CONTROL_STOP: ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL, "Service Stop/Shutdown signaled, shutting down server."); ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 15000); ap_start_shutdown(); break; case SERVICE_APACHE_RESTART: ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL, "Service Restart signaled, shutting down server."); ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 15000); ap_start_restart(1); break; // Update the service status. // case SERVICE_CONTROL_INTERROGATE: ReportStatusToSCMgr(globdat.ssStatus.dwCurrentState, NO_ERROR, 0); break; // invalid control code, ignored // default: break; } }
int send_signal_to_service(char *display_name, char *sig, int argc, char **argv) { DWORD service_pid; HANDLE hwnd; SC_HANDLE schService; SC_HANDLE schSCManager; char *service_name; int success = FALSE; enum { start, restart, stop, unknown } action; static char *param[] = { "start", "restart", "shutdown" }; static char *participle[] = { "starting", "restarting", "stopping" }; static char *past[] = { "started", "restarted", "stopped" }; for (action = start; action < unknown; action++) if (!strcasecmp(sig, param[action])) break; if (action == unknown) { printf("signal must be start, restart, or shutdown\n"); return FALSE; } service_name = get_service_name(display_name); if (isWindowsNT()) { schSCManager = OpenSCManager( NULL, // machine (NULL == local) NULL, // database (NULL == default) SC_MANAGER_ALL_ACCESS // access required ); if (!schSCManager) { ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, "OpenSCManager failed"); return FALSE; } schService = OpenService(schSCManager, service_name, SERVICE_ALL_ACCESS); if (schService == NULL) { /* Could not open the service */ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, "OpenService failed"); CloseServiceHandle(schSCManager); return FALSE; } if (!QueryServiceStatus(schService, &globdat.ssStatus)) { ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, "QueryService failed"); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); } } else /* !isWindowsNT() */ { /* Locate the window named service_name of class ApacheWin95ServiceMonitor * from the active top level windows */ hwnd = FindWindow("ApacheWin95ServiceMonitor", service_name); if (hwnd && GetWindowThreadProcessId(hwnd, &service_pid)) globdat.ssStatus.dwCurrentState = SERVICE_RUNNING; else globdat.ssStatus.dwCurrentState = SERVICE_STOPPED; } if (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED && action == stop) { printf("The %s service is not started.\n", display_name); return FALSE; } else if (globdat.ssStatus.dwCurrentState == SERVICE_RUNNING && action == start) { printf("The %s service has already been started.\n", display_name); strcpy(sig, ""); return FALSE; } else { printf("The %s service is %s.\n", display_name, participle[action]); if (isWindowsNT()) { if (action == stop) success = ap_stop_service(schService); else if ((action == start) || ((action == restart) && (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED))) { /* start NT service needs service args */ char **args = malloc(argc * sizeof(char*)); int i, j; for (i = 1, j = 0; i < argc; i++) { if ((argv[i][0] == '-') && ((argv[i][1] == 'k') || (argv[i][1] == 'n'))) ++i; else args[j++] = argv[i]; } success = ap_start_service(schService, j, args); } else if (action == restart) success = ap_restart_service(schService); } else /* !isWindowsNT()) */ { char prefix[20]; ap_snprintf(prefix, sizeof(prefix), "ap%ld", (long)service_pid); setup_signal_names(prefix); if (action == stop) { int ticks = 60; ap_start_shutdown(); while (--ticks) { if (!IsWindow(hwnd)) { success = TRUE; break; } Sleep(1000); } } else if (action == restart) { /* This gets a bit tricky... start and restart (of stopped service) * will simply fall through and *THIS* process will fade into an * invisible 'service' process, detaching from the user's console. * We need to change the restart signal to "start", however, * if the service was not -yet- running, and we do return FALSE * to assure main() that we haven't done anything yet. */ if (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED) { printf("The %s service has %s.\n", display_name, past[action]); strcpy(sig, "start"); return FALSE; } ap_start_restart(1); success = TRUE; } else /* action == start */ { printf("The %s service is %s.\n", display_name, past[action]); return FALSE; } } if( success ) printf("The %s service has %s.\n", display_name, past[action]); else printf("Failed to %s the %s service.\n", sig, display_name); } if (isWindowsNT()) { CloseServiceHandle(schService); CloseServiceHandle(schSCManager); } return success; }
static void restart(int sig) { ap_start_restart(sig == AP_SIG_GRACEFUL); }