📄 service.c
字号:
NULL, // use SYSTEM account NULL); // no password if (!schService) { rv = apr_get_os_error(); ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL, "Failed to create WinNT Service Profile"); CloseServiceHandle(schSCManager); return (rv); } CloseServiceHandle(schService); CloseServiceHandle(schSCManager); } else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */ { /* Store the launch command in the registry */ launch_cmd = apr_psprintf(ptemp, "\"%s\" -n %s -k runservice", exe_path, service_name); rv = ap_registry_store_value(SERVICECONFIG9X, service_name, launch_cmd); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL, "%s: Failed to add the RunServices registry entry.", display_name); return (rv); } apr_snprintf(key_name, sizeof(key_name), SERVICECONFIG, service_name); rv = ap_registry_store_value(key_name, "DisplayName", display_name); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL, "%s: Failed to store DisplayName in the registry.", display_name); return (rv); } } /* For both WinNT & Win9x store the service ConfigArgs in the registry... */ apr_snprintf(key_name, sizeof(key_name), SERVICEPARAMS, service_name); rv = ap_registry_store_array(ptemp, key_name, "ConfigArgs", argc, argv); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL, "%s: Failed to store the ConfigArgs in the registry.", display_name); return (rv); } printf("The %s service is successfully installed.\n", display_name);}apr_status_t mpm_service_uninstall(void){ char key_name[MAX_PATH]; apr_status_t rv; if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) { SC_HANDLE schService; SC_HANDLE schSCManager; printf("Removing the %s service\n", display_name); // TODO: Determine the minimum permissions required for security schSCManager = OpenSCManager(NULL, NULL, /* local, default database */ SC_MANAGER_ALL_ACCESS); 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); } schService = OpenService(schSCManager, service_name, SERVICE_ALL_ACCESS); if (!schService) { rv = apr_get_os_error(); ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL, "%s: OpenService failed", display_name); return (rv); } /* assure the service is stopped before continuing * * This may be out of order... we might not be able to be * granted all access if the service is running anyway. * * And do we want to make it *this easy* for them * to uninstall their service unintentionally? */ // ap_stop_service(schService); if (DeleteService(schService) == 0) { rv = apr_get_os_error(); ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL, "%s: Failed to delete the service.", display_name); return (rv); } CloseServiceHandle(schService); CloseServiceHandle(schSCManager); } else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */ { printf("Removing the %s service\n", display_name); /* TODO: assure the service is stopped before continuing */ if (ap_registry_delete_value(SERVICECONFIG9X, service_name)) { rv = apr_get_os_error(); ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL, "%s: Failed to remove the RunServices registry " "entry.", display_name); return (rv); } /* we blast Services/us, not just the Services/us/Parameters branch */ apr_snprintf(key_name, sizeof(key_name), SERVICECONFIG, service_name); if (ap_registry_delete_key(key_name)) { rv = apr_get_os_error(); ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL, "%s: Failed to remove the service config from the " "registry.", display_name); return (rv); } } printf("The %s service has been removed successfully.\n", display_name); return APR_SUCCESS;}/* signal_service_transition is a simple thunk to signal the service * and monitor it's 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; printf("Starting the %s service\n", display_name); if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) { char **start_argv; SC_HANDLE schService; SC_HANDLE schSCManager; // TODO: Determine the minimum permissions required for security schSCManager = OpenSCManager(NULL, NULL, /* local, default database */ SC_MANAGER_ALL_ACCESS); 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); } schService = OpenService(schSCManager, 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.", 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!", display_name); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return 0; } argc += 1; start_argv = apr_palloc(ptemp, argc * sizeof(const char **)); start_argv[0] = service_name; if (argc > 1) memcpy(start_argv + 1, argv, (argc - 1) * sizeof(const char **)); rv = APR_EINIT; 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 *pCommand; int i; /* Locate the active top level window named service_name * provided the class is ApacheWin95ServiceMonitor */ if (FindWindow("ApacheWin95ServiceMonitor", service_name)) { ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, 0, NULL, "Service %s is already started!", 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; } pCommand = apr_psprintf(ptemp, "\"%s\" -n %s -k runservice", exe_path, service_name); for (i = 0; i < argc; ++i) { pCommand = apr_pstrcat(ptemp, pCommand, " \"", argv[i], "\"", NULL); } 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, pCommand, NULL, NULL, FALSE, DETACHED_PROCESS, /* Creation flags */ NULL, NULL, &si, &pi)) { DWORD code; while (GetExitCodeProcess(pi.hProcess, &code) == STILL_ACTIVE) { if (FindWindow("ApacheWin95ServiceMonitor", 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) printf("The %s service is running.\n", display_name); else ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, "%s: Failed to start the service process.", 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_ALL_ACCESS); if (!schSCManager) { ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(), NULL, "Failed to open the NT Service Manager"); 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_STARTUP, apr_get_os_error(), NULL, "Failed to open the %s Service", 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", display_name); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return; } if (!signal && (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED)) { printf("The %s service is not started.\n", display_name); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return; } printf("The %s service is %s.\n", 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", service_name); if (hwnd && GetWindowThreadProcessId(hwnd, &service_pid)) globdat.ssStatus.dwCurrentState = SERVICE_RUNNING; else { globdat.ssStatus.dwCurrentState = SERVICE_STOPPED; if (!signal) { printf("The %s service is not started.\n", display_name); return; } } printf("The %s service is %s.\n", 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_start_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_start_restart(1); } } } if (success) printf("The %s service has %s.\n", display_name, signal ? "restarted" : "stopped"); else printf("Failed to %s the %s service.\n", signal ? "restart" : "stop", display_name);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -