⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 service.c

📁 Apache V2.0.15 Alpha For Linuxhttpd-2_0_15-alpha.tar.Z
💻 C
📖 第 1 页 / 共 3 页
字号:
        ReportStatusToSCMgr(globdat.ssStatus.dwCurrentState, NO_ERROR, 0);            }long __stdcall service_stderr_thread(LPVOID hPipe){    HANDLE hPipeRead = (HANDLE) hPipe;    HANDLE hEventSource;    char errbuf[256];    char *errmsg = errbuf;    const char *errarg[9];    DWORD errlen = 0;    DWORD errres;    HKEY hk;        errarg[0] = "The Apache service named";    errarg[1] = display_name;    errarg[2] = "reported the following error:\r\n>>>";    errarg[3] = errmsg;    errarg[4] = "<<<\r\n before the error.log file could be opened.\r\n";    errarg[5] = "More information may be available in the error.log file.";    errarg[6] = NULL;    errarg[7] = NULL;    errarg[8] = NULL;        /* What are we going to do in here, bail on the user?  not. */    if (!RegCreateKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services"                      "\\EventLog\\Application\\Apache Service", &hk))     {        /* The stock message file */        char *netmsgkey = "%SystemRoot%\\System32\\netmsg.dll";        DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |                        EVENTLOG_INFORMATION_TYPE;          RegSetValueEx(hk, "EventMessageFile", 0, REG_EXPAND_SZ,                          (LPBYTE) netmsgkey, strlen(netmsgkey) + 1);                RegSetValueEx(hk, "TypesSupported", 0, REG_DWORD,                          (LPBYTE) &dwData, sizeof(dwData));        RegCloseKey(hk);    }    hEventSource = RegisterEventSource(NULL, "Apache Service");    while (ReadFile(hPipeRead, errmsg, 1, &errres, NULL) && (errres == 1))    {        if ((errmsg > errbuf) || !isspace(*errmsg))        {            ++errlen;            ++errmsg;            if ((*(errmsg - 1) == '\n') || (errlen == sizeof(errbuf) - 1))            {                while (errlen && isspace(errbuf[errlen - 1]))                    --errlen;                errbuf[errlen] = '\0';                /* Generic message: '%1 %2 %3 %4 %5 %6 %7 %8 %9'                 * The event code in netmsg.dll is 3299                 */                ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0,                             3299, NULL, 9, 0, errarg, NULL);                errmsg = errbuf;                errlen = 0;            }        }    }    CloseHandle(hPipeRead);    return 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;static void __stdcall service_nt_main_fn(DWORD argc, LPTSTR *argv){    HANDLE waitfor[2];    HANDLE hCurrentProcess;    HANDLE hPipeRead = NULL;    HANDLE hPipeWrite = NULL;    HANDLE hPipeReadDup;    HANDLE thread;    DWORD  threadid;    SECURITY_ATTRIBUTES sa = {0};          /* args and service names live in the same pool */    mpm_service_set_name(mpm_new_argv->cont, argv[0]);    globdat.ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;    globdat.ssStatus.dwCurrentState = SERVICE_START_PENDING;    globdat.ssStatus.dwServiceSpecificExitCode = 0;    globdat.ssStatus.dwCheckPoint = 1;    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");        PulseEvent(globdat.signal_monitor);        return;    }    ReportStatusToSCMgr(globdat.ssStatus.dwCurrentState, // service state                        NO_ERROR,              // exit code                        3000);                 // wait hint, 3 seconds more        /* Create a pipe to send stderr messages to the system error log */    hCurrentProcess = GetCurrentProcess();    if (CreatePipe(&hPipeRead, &hPipeWrite, &sa, 0))     {        if (DuplicateHandle(hCurrentProcess, hPipeRead, hCurrentProcess,                            &hPipeReadDup, 0, FALSE, DUPLICATE_SAME_ACCESS))        {            CloseHandle(hPipeRead);            hPipeRead = hPipeReadDup;            thread = CreateThread(NULL, 0, service_stderr_thread,                                   (LPVOID) hPipeRead, 0, &threadid);            if (thread)            {                int fh;                FILE *fl;                CloseHandle(thread);            	fflush(stderr);		SetStdHandle(STD_ERROR_HANDLE, hPipeWrite);				                fh = _open_osfhandle((long) STD_ERROR_HANDLE,                                      _O_WRONLY | _O_BINARY);                dup2(fh, STDERR_FILENO);                fl = _fdopen(STDERR_FILENO, "wcb");                memcpy(stderr, fl, sizeof(FILE));            }            else            {                CloseHandle(hPipeRead);                CloseHandle(hPipeWrite);                hPipeWrite = NULL;            }                    }        else        {            CloseHandle(hPipeRead);            CloseHandle(hPipeWrite);            hPipeWrite = NULL;        }                }    /* 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 = apr_palloc(mpm_new_argv->cont,                              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.signal_monitor);    waitfor[0] = globdat.signal_monitor;    waitfor[1] = globdat.mpm_thread;    WaitForMultipleObjects(2, waitfor, FALSE, INFINITE);    /* The process is ready to terminate, or already has */    CloseHandle(hPipeWrite);}DWORD WINAPI service_nt_dispatch_thread(LPVOID nada){    apr_status_t rv = APR_SUCCESS;    SERVICE_TABLE_ENTRY dispatchTable[] =    {        { "", service_nt_main_fn },        { NULL, NULL }    };    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");    }    globdat.service_thread_id = 0;    return (rv);}apr_status_t mpm_service_set_name(apr_pool_t *p, const char *name){    char *key_name;        service_name = apr_palloc(p, strlen(name) + 1);    apr_collapse_spaces((char*) service_name, name);    key_name = apr_psprintf(p, SERVICECONFIG, service_name);    if (ap_registry_get_value(p, key_name, "DisplayName", (char**)&display_name) == APR_SUCCESS)        return APR_SUCCESS;    /* Take the given literal name if there is no service entry */    display_name = apr_pstrdup(p, name);    return APR_ENOFILE;}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;    apr_snprintf(conf_key, sizeof(conf_key), SERVICEPARAMS, service_name);    rv = ap_registry_get_array(p, conf_key, "ConfigArgs", &svc_args);    if (rv != APR_SUCCESS) {        if (rv == ERROR_FILE_NOT_FOUND) {            ap_log_error(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, NULL,                         "No ConfigArgs registered for %s, perhaps "                         "this service is not installed?",                          service_name);            return APR_SUCCESS;        }        else            return (rv);            }    if (!svc_args || svc_args->nelts == 0) {        return (APR_SUCCESS);    }    /* Now we have the 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 = apr_palloc(p, 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;}void service_stopped(void){    /* Still have a thread & window to clean up, so signal now */    if (globdat.service_thread_id)    {        if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)        {            ReportStatusToSCMgr(SERVICE_STOPPED,    // service state                                NO_ERROR,           // exit code                                0);                 // wait hint            /* Cause the service_nt_main_fn to complete */            SetEvent(globdat.signal_monitor);        }        else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */        {            RegisterServiceProcess(0, 0);            PostThreadMessage(globdat.service_thread_id, WM_CLOSE, 0, 0);        }        WaitForSingleObject(globdat.service_thread, 5000);        CloseHandle(globdat.service_thread);    }}apr_status_t mpm_service_to_start(void){    HANDLE waitfor[2];    globdat.mpm_thread = GetCurrentThread();        if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)    {        globdat.signal_monitor = CreateEvent(NULL, FALSE, FALSE, NULL);        if (globdat.signal_monitor)            globdat.service_thread = CreateThread(NULL, 0,                                                   service_nt_dispatch_thread,                                                   NULL, 0,                                                   &globdat.service_thread_id);    }    else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */    {        if (!RegisterServiceProcess(0, 1))             return GetLastError();        globdat.signal_monitor = CreateEvent(NULL, FALSE, FALSE, NULL);        if (globdat.signal_monitor)            globdat.service_thread = CreateThread(NULL, 0,                                                  monitor_service_9x_thread,                                                   (LPVOID) service_name, 0,                                                   &globdat.service_thread_id);    }    if (globdat.signal_monitor && globdat.service_thread)     {        waitfor[0] = globdat.signal_monitor;        waitfor[1] = globdat.service_thread;            /* SetEvent(globdat.signal_monitor) to clean up the SCM thread */        if (WaitForMultipleObjects(2, waitfor, FALSE, 10000) != WAIT_OBJECT_0) {            CloseHandle(globdat.service_thread);            return APR_ENOTHREAD;        }    }    if (globdat.service_thread_id)        atexit(service_stopped);    else if (globdat.service_thread)        CloseHandle(globdat.service_thread);    return APR_SUCCESS;}apr_status_t mpm_service_started(void){    if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)    {        ReportStatusToSCMgr(SERVICE_RUNNING,    // service state                            NO_ERROR,           // exit code                            0);                 // wait hint    }    return APR_SUCCESS;}void mpm_service_stopping(void){    if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)        ReportStatusToSCMgr(SERVICE_STOP_PENDING, // service state                            NO_ERROR,             // exit code                            3000);                // wait hint}apr_status_t mpm_service_install(apr_pool_t *ptemp, int argc,                                  const char * const * argv){    char key_name[MAX_PATH];    char exe_path[MAX_PATH];    char *launch_cmd;    apr_status_t(rv);        printf("Installing the %s service\n", display_name);    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;    }    if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)    {        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);        }        launch_cmd = apr_psprintf(ptemp, "\"%s\" -k runservice", exe_path);        /* RPCSS is the Remote Procedure Call (RPC) Locator required for DCOM          * communication pipes.  I am far from convinced we should add this to         * the default service dependencies, but be warned that future apache          * modules or ISAPI dll's may depend on it.         */        schService = CreateService(schSCManager,         // SCManager database                                   service_name,         // name of service                                   display_name,         // name to display                                   SERVICE_ALL_ACCESS,   // access required                                   SERVICE_WIN32_OWN_PROCESS,  // service type                                   SERVICE_AUTO_START,   // start type                                   SERVICE_ERROR_NORMAL, // error control type                                   launch_cmd,           // service's binary                                   NULL,                 // no load svc group                                   NULL,                 // no tag identifier                                   "Tcpip\0Afd\0",       // dependencies

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -