// // 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; } }
// // 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: // VOID WINAPI service_ctrl(DWORD dwCtrlCode) { int state; state = globdat.ssStatus.dwCurrentState; switch(dwCtrlCode) { // Stop the service. // case SERVICE_CONTROL_STOP: state = SERVICE_STOP_PENDING; ap_start_shutdown(); break; // Update the service status. // case SERVICE_CONTROL_INTERROGATE: break; // invalid control code // default: break; } ReportStatusToSCMgr(state, NO_ERROR, 0); }
/* Console Control handler for processing Ctrl-C/Ctrl-Break and * on Windows NT also user logoff and system shutdown, * this also used for the Win9x hidden service and child process */ static BOOL CALLBACK ap_control_handler(DWORD ctrl_type) { switch (ctrl_type) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL, "Ctrl+C/Break initiated, shutting down server."); real_exit_code = 0; /* for Interrupt signals, shut down the server. * Tell the system we have dealt with the signal * without waiting for Apache to terminate. */ ap_start_shutdown(); return TRUE; case CTRL_LOGOFF_EVENT: if (!die_on_logoff) return TRUE; /* or fall through... */ case CTRL_CLOSE_EVENT: case CTRL_SHUTDOWN_EVENT: ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL, "Close/Logoff/Shutdown initiated, shutting down server."); /* for Terminate signals, shut down the server. * Wait for Apache to terminate, but respond * after a reasonable time to tell the system * that we have already tried to shut down. */ real_exit_code = 0; fprintf(stderr, "Apache server shutdown initiated...\n"); ap_start_shutdown(); Sleep(30000); return TRUE; } /* We should never get here, but this is (mostly) harmless */ return FALSE; }
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; }
void RemoveService(char *display_name) { char *service_name; BOOL success = FALSE; printf("Removing the %s service\n", display_name); /* Remove spaces from display name to create service name */ service_name = get_service_name(display_name); if (isWindowsNT()) { SC_HANDLE schService; SC_HANDLE schSCManager; 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; } 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"); } else { /* try to stop the service */ ap_stop_service(schService); // now remove the service if (DeleteService(schService) == 0) ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, "DeleteService failed"); else success = TRUE; CloseServiceHandle(schService); } /* SCM removes registry parameters */ CloseServiceHandle(schSCManager); } else /* !isWindowsNT() */ { HKEY hkey; DWORD service_pid; DWORD rv; HWND hwnd; /* Locate the named window of class ApacheWin95ServiceMonitor * from the active top level windows */ hwnd = FindWindow("ApacheWin95ServiceMonitor", service_name); if (hwnd && GetWindowThreadProcessId(hwnd, &service_pid)) { int ticks = 120; char prefix[20]; ap_snprintf(prefix, sizeof(prefix), "ap%ld", (long)service_pid); setup_signal_names(prefix); ap_start_shutdown(); while (--ticks) { if (!IsWindow(hwnd)) break; Sleep(1000); } } /* Open the RunServices key */ rv = RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\RunServices", &hkey); if (rv != ERROR_SUCCESS) { SetLastError(rv); ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, "Could not open the RunServices registry key."); } else { /* Delete the registry value for this service */ rv = RegDeleteValue(hkey, service_name); if (rv != ERROR_SUCCESS) { SetLastError(rv); ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, "Unable to remove service: " "Could not delete the RunServices entry."); } else success = TRUE; } RegCloseKey(hkey); /* Open the Services key */ rv = RegOpenKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services", &hkey); if (rv != ERROR_SUCCESS) { rv = RegDeleteValue(hkey, service_name); ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, "Could not open the Services registry key."); success = FALSE; } else { /* Delete the registry key for this service */ rv = RegDeleteKey(hkey, service_name); if (rv != ERROR_SUCCESS) { SetLastError(rv); ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, "Unable to remove service: " "Could not delete the Services registry key."); success = FALSE; } } RegCloseKey(hkey); } if (success) printf("The %s service has been removed successfully.\n", display_name); }
static void sig_term(int sig) { ap_start_shutdown(); }