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

📄 service.c

📁 Apache 2.0.63 is the current stable version of the 2.0 series, and is recommended over any previous
💻 C
📖 第 1 页 / 共 4 页
字号:

        /* 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 + -