📄 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 + -