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

📄 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 页
字号:
}


void service_stopped(void)
{
    /* Still have a thread & window to clean up, so signal now */
    if (globdat.service_thread)
    {
        if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
        {
            /* Stop logging to the event log */
            mpm_nt_eventlog_stderr_flush();

            /* Cause the service_nt_main_fn to complete */
            ReleaseMutex(globdat.service_term);

            ReportStatusToSCMgr(SERVICE_STOPPED, // service state
                                NO_ERROR,        // exit code
                                0);              // wait hint
        }
        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(const char **display_name, apr_pool_t *p)
{
    HANDLE hProc = GetCurrentProcess();
    HANDLE hThread = GetCurrentThread();
    HANDLE waitfor[2];

    /* Prevent holding open the (hidden) console */
    real_exit_code = 0;

     /* GetCurrentThread returns a psuedo-handle, we need
      * a real handle for another thread to wait upon.
      */
    if (!DuplicateHandle(hProc, hThread, hProc, &(globdat.mpm_thread),
                         0, FALSE, DUPLICATE_SAME_ACCESS)) {
        return APR_ENOTHREAD;
    }
    
    if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
    {
        globdat.service_init = CreateEvent(NULL, FALSE, FALSE, NULL);
        globdat.service_term = CreateMutex(NULL, TRUE, NULL);
        if (!globdat.service_init || !globdat.service_term) {
             return APR_EGENERAL;
        }

        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.service_init = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (!globdat.service_init) {
            return APR_EGENERAL;
        }

        globdat.service_thread = CreateThread(NULL, 0, monitor_service_9x_thread, 
                                              (LPVOID) mpm_service_name, 0,
                                              &globdat.service_thread_id);
    }

    if (!globdat.service_thread) {
        return APR_ENOTHREAD;
    }

    waitfor[0] = globdat.service_init;
    waitfor[1] = globdat.service_thread;

    /* Wait for controlling thread init or termination */
    if (WaitForMultipleObjects(2, waitfor, FALSE, 10000) != WAIT_OBJECT_0) {
        return APR_ENOTHREAD;
    }

    atexit(service_stopped);
    *display_name = mpm_display_name; 
    return APR_SUCCESS;
}


apr_status_t mpm_service_started(void)
{
    set_service_description();
    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
                            30000);               // wait hint
}


apr_status_t mpm_service_install(apr_pool_t *ptemp, int argc, 
                                 const char * const * argv, int reconfig)
{
    char key_name[MAX_PATH];
    char exe_path[MAX_PATH];
    char *launch_cmd;
    ap_regkey_t *key;
    apr_status_t rv;
    
    fprintf(stderr,reconfig ? "Reconfiguring the %s service\n"
		   : "Installing the %s service\n", mpm_display_name);

    /* ###: utf-ize */
    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;

        schSCManager = OpenSCManager(NULL, NULL, /* local, default database */
                                     SC_MANAGER_CREATE_SERVICE);
        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);

        if (reconfig) {
            /* ###: utf-ize */
            schService = OpenService(schSCManager, mpm_service_name, 
                                     SERVICE_CHANGE_CONFIG);
            if (!schService) {
                ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_ERR, 
                             apr_get_os_error(), NULL,
                             "OpenService failed");
            }
            /* ###: utf-ize */
            else if (!ChangeServiceConfig(schService, 
                                          SERVICE_WIN32_OWN_PROCESS,
                                          SERVICE_AUTO_START,
                                          SERVICE_ERROR_NORMAL,
                                          launch_cmd, NULL, NULL, 
                                          "Tcpip\0Afd\0", NULL, NULL,
                                          mpm_display_name)) {
                ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_ERR, 
                             apr_get_os_error(), NULL,
                             "ChangeServiceConfig failed");
	        /* !schService aborts configuration below */
	        CloseServiceHandle(schService);
	        schService = NULL;
	    }
        }
        else {
            /* 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.
             */
            /* ###: utf-ize */
            schService = CreateService(schSCManager,         // SCManager database
                                   mpm_service_name,     // name of service
                                   mpm_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
                                   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, mpm_service_name);
        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_set(key, mpm_service_name, 
                                     launch_cmd, 0, pconf);
            ap_regkey_close(key);
        }
        if (rv != APR_SUCCESS) {
            ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL, 
                         "%s: Failed to add the RunServices registry entry.", 
                         mpm_display_name);
            return (rv);
        }

        apr_snprintf(key_name, sizeof(key_name), SERVICECONFIG, mpm_service_name);
        rv = ap_regkey_open(&key, AP_REGKEY_LOCAL_MACHINE, key_name, 
                            APR_READ | APR_WRITE | APR_CREATE, pconf);
        if (rv != APR_SUCCESS) {
            ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL, 
                         "%s: Failed to create the registry service key.", 
                         mpm_display_name);
            return (rv);
        }
        rv = ap_regkey_value_set(key, "ImagePath", launch_cmd, 0, pconf);
        if (rv != APR_SUCCESS) {
            ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL, 
                         "%s: Failed to store ImagePath in the registry.", 
                         mpm_display_name);
            ap_regkey_close(key);
            return (rv);
        }
        rv = ap_regkey_value_set(key, "DisplayName", 
                                 mpm_display_name, 0, pconf);
        ap_regkey_close(key);
        if (rv != APR_SUCCESS) {
            ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL, 
                         "%s: Failed to store DisplayName in the registry.", 
                         mpm_display_name);
            return (rv);
        }
    }

    set_service_description();

    /* For both WinNT & Win9x store the service ConfigArgs in the registry...
     */
    apr_snprintf(key_name, sizeof(key_name), SERVICEPARAMS, mpm_service_name);
    rv = ap_regkey_open(&key, AP_REGKEY_LOCAL_MACHINE, key_name, 
                        APR_READ | APR_WRITE | APR_CREATE, pconf);
    if (rv == APR_SUCCESS) {
        rv = ap_regkey_value_array_set(key, "ConfigArgs", argc, argv, pconf);
        ap_regkey_close(key);
    }
    if (rv != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL, 
                     "%s: Failed to store the ConfigArgs in the registry.", 
                     mpm_display_name);
        return (rv);
    }
    fprintf(stderr,"The %s service is successfully installed.\n", mpm_display_name);
    return APR_SUCCESS;
}


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;

        fprintf(stderr,"Removing the %s service\n", mpm_display_name);

        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, DELETE);

        if (!schService) {
           rv = apr_get_os_error();
           ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, rv, NULL,
			"%s: OpenService failed", mpm_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.", mpm_display_name);
            return (rv);
        }
        
        CloseServiceHandle(schService);        
        CloseServiceHandle(schSCManager);
    }
    else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */
    {
        apr_status_t rv2, rv3;
        ap_regkey_t *key;
        fprintf(stderr,"Removing the %s service\n", mpm_display_name);

⌨️ 快捷键说明

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