📄 service.c
字号:
/* TODO: assure the service is stopped before continuing */ rv = ap_regkey_open(&key, AP_REGKEY_LOCAL_MACHINE, SERVICECONFIG9X, APR_READ | APR_WRITE | APR_CREATE, pconf); if (rv == APR_SUCCESS) { rv = ap_regkey_value_remove(key, mpm_service_name, pconf); ap_regkey_close(key); } if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL, "%s: Failed to remove the RunServices registry " "entry.", mpm_display_name); } /* we blast Services/us, not just the Services/us/Parameters branch */ apr_snprintf(key_name, sizeof(key_name), SERVICEPARAMS, mpm_service_name); rv2 = ap_regkey_remove(AP_REGKEY_LOCAL_MACHINE, key_name, pconf); apr_snprintf(key_name, sizeof(key_name), SERVICECONFIG, mpm_service_name); rv3 = ap_regkey_remove(AP_REGKEY_LOCAL_MACHINE, key_name, pconf); rv2 = (rv2 != APR_SUCCESS) ? rv2 : rv3; if (rv2 != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv2, NULL, "%s: Failed to remove the service config from the " "registry.", mpm_display_name); } rv = (rv != APR_SUCCESS) ? rv : rv2; if (rv != APR_SUCCESS) return rv; } fprintf(stderr,"The %s service has been removed successfully.\n", mpm_display_name); return APR_SUCCESS;}/* signal_service_transition is a simple thunk to signal the service * and monitor its successful transition. If the signal passed is 0, * then the caller is assumed to already have performed some service * operation to be monitored (such as StartService), and no actual * ControlService signal is sent. */static int signal_service_transition(SC_HANDLE schService, DWORD signal, DWORD pending, DWORD complete){ if (signal && !ControlService(schService, signal, &globdat.ssStatus)) return FALSE; do { Sleep(1000); if (!QueryServiceStatus(schService, &globdat.ssStatus)) return FALSE; } while (globdat.ssStatus.dwCurrentState == pending); return (globdat.ssStatus.dwCurrentState == complete);}apr_status_t mpm_service_start(apr_pool_t *ptemp, int argc, const char * const * argv){ apr_status_t rv; fprintf(stderr,"Starting the %s service\n", mpm_display_name); if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) { char **start_argv; SC_HANDLE schService; SC_HANDLE schSCManager; schSCManager = OpenSCManager(NULL, NULL, /* local, default database */ SC_MANAGER_CONNECT); if (!schSCManager) { rv = apr_get_os_error(); ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL, "Failed to open the WinNT service manager"); return (rv); } /* ###: utf-ize */ schService = OpenService(schSCManager, mpm_service_name, SERVICE_START | SERVICE_QUERY_STATUS); if (!schService) { rv = apr_get_os_error(); ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL, "%s: Failed to open the service.", mpm_display_name); CloseServiceHandle(schSCManager); return (rv); } if (QueryServiceStatus(schService, &globdat.ssStatus) && (globdat.ssStatus.dwCurrentState == SERVICE_RUNNING)) { ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, 0, NULL, "Service %s is already started!", mpm_display_name); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return 0; } start_argv = malloc((argc + 1) * sizeof(const char **)); memcpy(start_argv, argv, argc * sizeof(const char **)); start_argv[argc] = NULL; rv = APR_EINIT; /* ###: utf-ize */ if (StartService(schService, argc, start_argv) && signal_service_transition(schService, 0, /* test only */ SERVICE_START_PENDING, SERVICE_RUNNING)) rv = APR_SUCCESS; if (rv != APR_SUCCESS) rv = apr_get_os_error(); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); } else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */ { STARTUPINFO si; /* Filled in prior to call to CreateProcess */ PROCESS_INFORMATION pi; /* filled in on call to CreateProcess */ char exe_path[MAX_PATH]; char exe_cmd[MAX_PATH * 4]; char *next_arg; int i; /* Locate the active top level window named service_name * provided the class is ApacheWin95ServiceMonitor */ if (FindWindow("ApacheWin95ServiceMonitor", mpm_service_name)) { ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, 0, NULL, "Service %s is already started!", mpm_display_name); return 0; } /* This may not appear intuitive, but Win9x will not allow a process * to detach from the console without releasing the entire console. * Ergo, we must spawn a new process for the service to get back our * console window. * The config is pre-flighted, so there should be no danger of failure. */ if (GetModuleFileName(NULL, exe_path, sizeof(exe_path)) == 0) { apr_status_t rv = apr_get_os_error(); ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL, "GetModuleFileName failed"); return rv; } apr_snprintf(exe_cmd, sizeof(exe_cmd), "\"%s\" -n %s -k runservice", exe_path, mpm_service_name); next_arg = strchr(exe_cmd, '\0'); for (i = 0; i < argc; ++i) { apr_snprintf(next_arg, sizeof(exe_cmd) - (next_arg - exe_cmd), " \"%s\"", argv[i]); next_arg = strchr(exe_cmd, '\0'); } memset(&si, 0, sizeof(si)); memset(&pi, 0, sizeof(pi)); si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; /* This might be redundant */ rv = APR_EINIT; if (CreateProcess(NULL, exe_cmd, NULL, NULL, FALSE, DETACHED_PROCESS, /* Creation flags */ NULL, NULL, &si, &pi)) { DWORD code; while (GetExitCodeProcess(pi.hProcess, &code) == STILL_ACTIVE) { if (FindWindow("ApacheWin95ServiceMonitor", mpm_service_name)) { rv = APR_SUCCESS; break; } Sleep (1000); } } if (rv != APR_SUCCESS) rv = apr_get_os_error(); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } if (rv == APR_SUCCESS) fprintf(stderr,"The %s service is running.\n", mpm_display_name); else ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, "%s: Failed to start the service process.", mpm_display_name); return rv;}/* signal is zero to stop, non-zero for restart */void mpm_signal_service(apr_pool_t *ptemp, int signal){ int success = FALSE; if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) { SC_HANDLE schService; SC_HANDLE schSCManager; schSCManager = OpenSCManager(NULL, NULL, // default machine & database SC_MANAGER_CONNECT); if (!schSCManager) { ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(), NULL, "Failed to open the NT Service Manager"); return; } /* ###: utf-ize */ schService = OpenService(schSCManager, mpm_service_name, SERVICE_INTERROGATE | SERVICE_QUERY_STATUS | SERVICE_USER_DEFINED_CONTROL | SERVICE_START | SERVICE_STOP); if (schService == NULL) { /* Could not open the service */ ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(), NULL, "Failed to open the %s Service", mpm_display_name); CloseServiceHandle(schSCManager); return; } if (!QueryServiceStatus(schService, &globdat.ssStatus)) { ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(), NULL, "Query of Service %s failed", mpm_display_name); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return; } if (!signal && (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED)) { fprintf(stderr,"The %s service is not started.\n", mpm_display_name); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return; } fprintf(stderr,"The %s service is %s.\n", mpm_display_name, signal ? "restarting" : "stopping"); if (!signal) success = signal_service_transition(schService, SERVICE_CONTROL_STOP, SERVICE_STOP_PENDING, SERVICE_STOPPED); else if (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED) { mpm_service_start(ptemp, 0, NULL); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return; } else success = signal_service_transition(schService, SERVICE_APACHE_RESTART, SERVICE_START_PENDING, SERVICE_RUNNING); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); } else /* !isWindowsNT() */ { DWORD service_pid; HANDLE hwnd; char prefix[20]; /* Locate the active top level window named service_name * provided the class is ApacheWin95ServiceMonitor */ hwnd = FindWindow("ApacheWin95ServiceMonitor", mpm_service_name); if (hwnd && GetWindowThreadProcessId(hwnd, &service_pid)) globdat.ssStatus.dwCurrentState = SERVICE_RUNNING; else { globdat.ssStatus.dwCurrentState = SERVICE_STOPPED; if (!signal) { fprintf(stderr,"The %s service is not started.\n", mpm_display_name); return; } } fprintf(stderr,"The %s service is %s.\n", mpm_display_name, signal ? "restarting" : "stopping"); apr_snprintf(prefix, sizeof(prefix), "ap%ld", (long)service_pid); setup_signal_names(prefix); if (!signal) { int ticks = 60; ap_signal_parent(SIGNAL_PARENT_SHUTDOWN); while (--ticks) { if (!IsWindow(hwnd)) { success = TRUE; break; } Sleep(1000); } } else /* !stop */ { /* TODO: Aught to add a little test to the restart logic, and * store the restart counter in the window's user dword. * Then we can hang on and report a successful restart. But * that's a project for another day. */ if (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED) { mpm_service_start(ptemp, 0, NULL); return; } else { success = TRUE; ap_signal_parent(SIGNAL_PARENT_RESTART); } } } if (success) fprintf(stderr,"The %s service has %s.\n", mpm_display_name, signal ? "restarted" : "stopped"); else fprintf(stderr,"Failed to %s the %s service.\n", signal ? "restart" : "stop", mpm_display_name);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -