📄 service.c
字号:
* The system will also signal the parent process, * which will terminate Apache, so we need to wait. */ Sleep(30000); return TRUE; } /* We should never get here, but this is (mostly) harmless */ return FALSE;}static void stop_child_console_handler(void){ SetConsoleCtrlHandler(child_control_handler, FALSE);}void mpm_start_child_console_handler(void){ if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) { FreeConsole(); } else { SetConsoleCtrlHandler(child_control_handler, TRUE); atexit(stop_child_console_handler); }}/********************************** WinNT service control management **********************************/static int ReportStatusToSCMgr(int currentState, int exitCode, int waitHint){ static int checkPoint = 1; int rv = APR_SUCCESS; if (globdat.hServiceStatus) { if (currentState == SERVICE_RUNNING) { globdat.ssStatus.dwWaitHint = 0; globdat.ssStatus.dwCheckPoint = 0; globdat.ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; } else if (currentState == SERVICE_STOPPED) { globdat.ssStatus.dwWaitHint = 0; globdat.ssStatus.dwCheckPoint = 0; if (!exitCode && globdat.ssStatus.dwCurrentState != SERVICE_STOP_PENDING) { /* An unexpected exit? Better to error! */ exitCode = 1; } if (exitCode) { globdat.ssStatus.dwWin32ExitCode =ERROR_SERVICE_SPECIFIC_ERROR; globdat.ssStatus.dwServiceSpecificExitCode = exitCode; } } else { globdat.ssStatus.dwCheckPoint = ++checkPoint; globdat.ssStatus.dwControlsAccepted = 0; if(waitHint) globdat.ssStatus.dwWaitHint = waitHint; } globdat.ssStatus.dwCurrentState = currentState; rv = SetServiceStatus(globdat.hServiceStatus, &globdat.ssStatus); } return(rv);}/* Set the service description regardless of platform. * We revert to set_service_description on NT/9x, the * very long way so any Apache management program can grab the * description. This would be bad on Win2000, since it wouldn't * notify the service control manager of the name change. *//* borrowed from mpm_winnt.c */extern apr_pool_t *pconf;/* Windows 2000 alone supports ChangeServiceConfig2 in order to * register our server_version string... so we need some fixups * to avoid binding to that function if we are on WinNT/9x. */static void set_service_description(void){ const char *full_description; SC_HANDLE schSCManager; BOOL ret = 0; /* Nothing to do if we are a console */ if (!mpm_service_name) return; /* Time to fix up the description, upon each successful restart */ full_description = ap_get_server_version(); if ((osver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osver.dwMajorVersion > 4) && (ChangeServiceConfig2) && (schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT))) { SC_HANDLE schService = OpenService(schSCManager, mpm_service_name, SERVICE_CHANGE_CONFIG); if (schService) { /* Cast is necessary, ChangeServiceConfig2 handles multiple * object types, some volatile, some not. */ /* ###: utf-ize */ if (ChangeServiceConfig2(schService, 1 /* SERVICE_CONFIG_DESCRIPTION */, (LPVOID) &full_description)) { full_description = NULL; } CloseServiceHandle(schService); } CloseServiceHandle(schSCManager); } if (full_description) { char szPath[MAX_PATH]; ap_regkey_t *svckey; apr_status_t rv; /* Find the Service key that Monitor Applications iterate */ apr_snprintf(szPath, sizeof(szPath), "SYSTEM\\CurrentControlSet\\Services\\%s", mpm_service_name); rv = ap_regkey_open(&svckey, AP_REGKEY_LOCAL_MACHINE, szPath, APR_READ | APR_WRITE, pconf); if (rv != APR_SUCCESS) { return; } /* Attempt to set the Description value for our service */ ap_regkey_value_set(svckey, "Description", full_description, 0, pconf); ap_regkey_close(svckey); }}/* handle the SCM's ControlService() callbacks to our service */static VOID WINAPI service_nt_ctrl(DWORD dwCtrlCode){ if (dwCtrlCode == SERVICE_CONTROL_STOP) { ap_signal_parent(SIGNAL_PARENT_SHUTDOWN); ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 30000); return; } if (dwCtrlCode == SERVICE_APACHE_RESTART) { ap_signal_parent(SIGNAL_PARENT_RESTART); ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 30000); return; } ReportStatusToSCMgr(globdat.ssStatus.dwCurrentState, NO_ERROR, 0); }/* service_nt_main_fn is outside of the call stack and outside of the * primary server thread... so now we _really_ need a placeholder! * The winnt_rewrite_args has created and shared mpm_new_argv with us. */extern apr_array_header_t *mpm_new_argv;/* ###: utf-ize */static void __stdcall service_nt_main_fn(DWORD argc, LPTSTR *argv){ const char *ignored; /* args and service names live in the same pool */ mpm_service_set_name(mpm_new_argv->pool, &ignored, argv[0]); memset(&globdat.ssStatus, 0, sizeof(globdat.ssStatus)); globdat.ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; globdat.ssStatus.dwCurrentState = SERVICE_START_PENDING; globdat.ssStatus.dwCheckPoint = 1; /* ###: utf-ize */ if (!(globdat.hServiceStatus = RegisterServiceCtrlHandler(argv[0], service_nt_ctrl))) { ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, apr_get_os_error(), NULL, "Failure registering service handler"); return; } /* Report status, no errors, and buy 3 more seconds */ ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 30000); /* We need to append all the command arguments passed via StartService() * to our running service... which just got here via the SCM... * but we hvae no interest in argv[0] for the mpm_new_argv list. */ if (argc > 1) { char **cmb_data; mpm_new_argv->nalloc = mpm_new_argv->nelts + argc - 1; cmb_data = malloc(mpm_new_argv->nalloc * sizeof(const char *)); /* mpm_new_argv remains first (of lower significance) */ memcpy (cmb_data, mpm_new_argv->elts, mpm_new_argv->elt_size * mpm_new_argv->nelts); /* Service args follow from StartService() invocation */ memcpy (cmb_data + mpm_new_argv->nelts, argv + 1, mpm_new_argv->elt_size * (argc - 1)); /* The replacement arg list is complete */ mpm_new_argv->elts = (char *)cmb_data; mpm_new_argv->nelts = mpm_new_argv->nalloc; } /* Let the main thread continue now... but hang on to the * signal_monitor event so we can take further action */ SetEvent(globdat.service_init); WaitForSingleObject(globdat.service_term, INFINITE);}DWORD WINAPI service_nt_dispatch_thread(LPVOID nada){ apr_status_t rv = APR_SUCCESS; SERVICE_TABLE_ENTRY dispatchTable[] = { { "", service_nt_main_fn }, { NULL, NULL } }; /* ###: utf-ize */ if (!StartServiceCtrlDispatcher(dispatchTable)) { /* This is a genuine failure of the SCM. */ rv = apr_get_os_error(); ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL, "Error starting service control dispatcher"); } return (rv);}apr_status_t mpm_service_set_name(apr_pool_t *p, const char **display_name, const char *set_name){ char key_name[MAX_PATH]; ap_regkey_t *key; apr_status_t rv; /* ### Needs improvement, on Win2K the user can _easily_ * change the display name to a string that doesn't reflect * the internal service name + whitespace! */ mpm_service_name = apr_palloc(p, strlen(set_name) + 1); apr_collapse_spaces((char*) mpm_service_name, set_name); apr_snprintf(key_name, sizeof(key_name), SERVICECONFIG, mpm_service_name); rv = ap_regkey_open(&key, AP_REGKEY_LOCAL_MACHINE, key_name, APR_READ, pconf); if (rv == APR_SUCCESS) { rv = ap_regkey_value_get(&mpm_display_name, key, "DisplayName", pconf); ap_regkey_close(key); } if (rv != APR_SUCCESS) { /* Take the given literal name if there is no service entry */ mpm_display_name = apr_pstrdup(p, set_name); } *display_name = mpm_display_name; return rv;}apr_status_t mpm_merge_service_args(apr_pool_t *p, apr_array_header_t *args, int fixed_args){ apr_array_header_t *svc_args = NULL; char conf_key[MAX_PATH]; char **cmb_data; apr_status_t rv; ap_regkey_t *key; apr_snprintf(conf_key, sizeof(conf_key), SERVICEPARAMS, mpm_service_name); rv = ap_regkey_open(&key, AP_REGKEY_LOCAL_MACHINE, conf_key, APR_READ, p); if (rv == APR_SUCCESS) { rv = ap_regkey_value_array_get(&svc_args, key, "ConfigArgs", p); ap_regkey_close(key); } if (rv != APR_SUCCESS) { if (rv == ERROR_FILE_NOT_FOUND) { ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, "No ConfigArgs registered for %s, perhaps " "this service is not installed?", mpm_service_name); return APR_SUCCESS; } else return (rv); } if (!svc_args || svc_args->nelts == 0) { return (APR_SUCCESS); } /* Now we have the mpm_service_name arg, and the mpm_runservice_nt() * call appended the arguments passed by StartService(), so it's * time to _prepend_ the default arguments for the server from * the service's default arguments (all others override them)... */ args->nalloc = args->nelts + svc_args->nelts; cmb_data = malloc(args->nalloc * sizeof(const char *)); /* First three args (argv[0], -f, path) remain first */ memcpy(cmb_data, args->elts, args->elt_size * fixed_args); /* Service args follow from service registry array */ memcpy(cmb_data + fixed_args, svc_args->elts, svc_args->elt_size * svc_args->nelts); /* Remaining new args follow */ memcpy(cmb_data + fixed_args + svc_args->nelts, (const char **)args->elts + fixed_args, args->elt_size * (args->nelts - fixed_args)); args->elts = (char *)cmb_data; args->nelts = args->nalloc; return APR_SUCCESS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -