예제 #1
0
파일: service.c 프로젝트: AzerTyQsdF/osx
/*
 * The Win32 Apache child cannot loose its console since 16bit cgi 
 * processes will hang (9x) or fail (NT) if they are not launched 
 * from a 32bit console app into that app's console window.  
 * Mark the 9x child as a service process and let the parent process 
 * clean it up as necessary.
 */
void ap_start_child_console(int is_child_of_service)
{
    int maxwait = 100;

    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL,
                 "Hooking up the child process monitor to watch for shutdown.");

    /* The child is never exactly a service */
    is_service = 0;
    
    /* Prevent holding open the (hidden) console */
    real_exit_code = 0;

    /* We only die on logoff if we not a service's child */
    die_on_logoff = !is_child_of_service;

    if (isWindowsNT()) {
        if (!is_child_of_service) {
            /*
             * Console mode Apache/WinNT needs to detach from the parent
             * console and create and hide it's own console window.
             * Not only is logout and shutdown more stable under W2K,
             * but this eliminates the mystery 'flicker' that users see
             * when invoking CGI apps (e.g. the titlebar or icon of the
             * console window changing to the cgi process's identifiers.)
             */
            FreeConsole();
            AllocConsole();
            EnumWindows(EnumttyWindow, (long)(&console_wnd));
            if (console_wnd)
                ShowWindow(console_wnd, SW_HIDE);
        }
        /*
         * Apache/WinNT installs no child console handler, otherwise
         * logoffs interfere with the service's child process!
         * The child process must have a later shutdown priority
         * than the parent, or the parent cannot shut down the
         * child process properly.  (The parent's default is 0x280.)
         */
        SetProcessShutdownParameters(0x200, 0);
        return;
    }

    if (!is_child_of_service) {
        FreeConsole();
        AllocConsole();
    }
    while (!console_wnd && maxwait-- > 0) { 
        EnumWindows(EnumttyWindow, (long)(&console_wnd));
        Sleep(100);
    }
    if (console_wnd) {
        FixConsoleCtrlHandler(ap_control_handler, die_on_logoff ? 1 : 2);
        ShowWindow(console_wnd, SW_HIDE);
        atexit(stop_child_monitor);
    }
}
예제 #2
0
파일: service.c 프로젝트: AzerTyQsdF/osx
void ap_start_console_monitor(void)
{
    HANDLE console_input;

    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL,
                 "Hooking up the console monitor to watch for shutdown.");

    die_on_logoff = TRUE;

    is_service = 0;

    console_input = GetStdHandle(STD_INPUT_HANDLE);
    /* Assure we properly accept Ctrl+C as an interrupt...
     * Win/2000 definately makes some odd assumptions about 
     * ctrl+c and the reserved console mode bits!
     */
    if (console_input != INVALID_HANDLE_VALUE)
    {
        /* The SetConsoleCtrlHandler(NULL... would fault under Win9x 
         * WinNT also includes an undocumented 0x80 bit for console mode
         * that preserves the console window behavior, and prevents the
         * bogus 'selection' mode from being accedently triggered.
         */
        if (isWindowsNT()) {
	    SetConsoleCtrlHandler(NULL, FALSE);
            SetConsoleMode(console_input, ENABLE_LINE_INPUT 
                                        | ENABLE_ECHO_INPUT 
                                        | ENABLE_PROCESSED_INPUT
                                        | 0x80);
        }
	else {
            SetConsoleMode(console_input, ENABLE_LINE_INPUT 
                                        | ENABLE_ECHO_INPUT 
                                        | ENABLE_PROCESSED_INPUT);
        }
    }
    
    if (!isWindowsNT())
        FixConsoleCtrlHandler(ap_control_handler, die_on_logoff ? 1 : 2);

    SetConsoleCtrlHandler(ap_control_handler, TRUE);

    atexit(stop_console_monitor);
}
예제 #3
0
파일: service.c 프로젝트: AzerTyQsdF/osx
void stop_console_monitor(void)
{
    /* Remove the control handler at the end of the day. */
    SetConsoleCtrlHandler(ap_control_handler, FALSE);

    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL,
                 "Unhooking the console monitor for shutdown.");

    if (!isWindowsNT())
        FixConsoleCtrlHandler(ap_control_handler, 0);
}
예제 #4
0
파일: service.c 프로젝트: AzerTyQsdF/osx
BOOL isProcessService() 
{
    if (is_service != -1)
        return is_service;
    if (!isWindowsNT() || !AllocConsole()) {
        /* Don't assume anything, just yet */
        return FALSE;
    }
    FreeConsole();
    is_service = 1;
    return TRUE;
}
예제 #5
0
파일: service.c 프로젝트: AzerTyQsdF/osx
/* Once we are running a child process in our tty, it can no longer 
 * determine which console window is our own, since the window
 * reports that it is owned by the child process.
 */
static BOOL CALLBACK EnumttyWindow(HWND wnd, LPARAM retwnd)
{
    char tmp[20], *tty;
    if (isWindowsNT())
        tty = "ConsoleWindowClass";
    else
        tty = "tty";
    if (GetClassName(wnd, tmp, sizeof(tmp)) && !strcmp(tmp, tty)) 
    {
        DWORD wndproc, thisproc = GetCurrentProcessId();
        GetWindowThreadProcessId(wnd, &wndproc);
        if (wndproc == thisproc) {
            *((HWND*)retwnd) = wnd;
            return FALSE;
        }
    }
    return TRUE;
}
예제 #6
0
파일: service.c 프로젝트: AzerTyQsdF/osx
char *get_display_name(char *service_name)
{
    /* Get the service's display name from the SCM on NT/2000, since it
     * can be changed by the user on 2000, especially, from the
     * service control panel.  We can't trust the service name as
     * provided by the user.
     */
    if (isWindowsNT())
    {
        char display_name[MAX_PATH];
        SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
        DWORD namelen = sizeof(display_name);
        if (scm) {
            BOOL ok = GetServiceDisplayName(scm, service_name, display_name,
                                            &namelen);
            CloseServiceHandle(scm);
            if (ok)
                return strdup(display_name);
        }
    }
    return service_name;
}
예제 #7
0
파일: service.c 프로젝트: AzerTyQsdF/osx
char *get_service_name(char *display_name)
{
    /* Get the service's true name from the SCM on NT/2000, since it
     * can be changed by the user on 2000, especially, from the
     * service control panel.  We can't trust the service name to 
     * match a space-collapsed display name.
     */
    char service_name[MAX_PATH];
    if (isWindowsNT())
    {
        SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
        DWORD namelen = sizeof(service_name);
        if (scm) {
            BOOL ok = GetServiceKeyName(scm, display_name, service_name, 
                                        &namelen);
            CloseServiceHandle(scm);
            if (ok)
                return strdup(service_name);
        }
    }
    ap_remove_spaces(service_name, display_name);
    return strdup(service_name);
}
예제 #8
0
void ExecThread::run()
{
    HANDLE inPipe[2] = { NULL, NULL };
    HANDLE outPipe[2] = { NULL, NULL };
    HANDLE errPipe[2] = { NULL, NULL };

    SECURITY_ATTRIBUTES sa;
    SECURITY_DESCRIPTOR sd;
    ZeroMemory(&sa, sizeof(sa));
    sa.nLength = sizeof(sa);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;
    if(isWindowsNT()){
        InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
        SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
        sa.lpSecurityDescriptor = &sd;
    }

    if (!CreatePipe(&inPipe[0], &inPipe[1],&sa, PIPE_SIZE) ||
            !CreatePipe(&outPipe[0],&outPipe[1],&sa,PIPE_SIZE) ||
            !CreatePipe(&errPipe[0],&errPipe[1],&sa,PIPE_SIZE)){
        if (inPipe[READ]) CloseHandle(inPipe[READ]);
        if (inPipe[WRITE]) CloseHandle(inPipe[WRITE]);
        if (outPipe[READ]) CloseHandle(outPipe[READ]);
        if (outPipe[WRITE]) CloseHandle(outPipe[WRITE]);
        if (errPipe[READ]) CloseHandle(errPipe[READ]);
        if (errPipe[WRITE]) CloseHandle(errPipe[WRITE]);
        QTimer::singleShot(0, exec, SLOT(finished()));
        return;
    }

    _STARTUPINFOA si;
    memset(&si, 0, sizeof(si));
    si.cb = sizeof(si);
    si.dwX = (unsigned)CW_USEDEFAULT;
    si.dwY = (unsigned)CW_USEDEFAULT;
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;

    si.hStdInput  = inPipe[READ];
    si.hStdOutput = outPipe[WRITE];
    si.hStdError  = errPipe[WRITE];

    const char *shell = NULL;
    string prg;
    string args;
    bool bScript = true;
    if (exec->prog[0] == '\"'){
        const char *prog = exec->prog.c_str();
        const char *p = strchr(prog + 1, '\"');
        if (p){
            prg = exec->prog.substr(1, p - prog - 1);
            args = p + 1;
        }else{
            prg = "";
            args = exec->prog;
        }
    }else{
        const char *prog = exec->prog.c_str();
        const char *p = strchr(prog, ' ');
        if (p){
            prg = exec->prog.substr(0, p - prog);
            args = p + 1;
        }else{
            prg = exec->prog;
        }
    }
    if (prg.length()){
        char *ext = strrchr(prg.c_str(), '.');
        if (ext && (!strcmp(ext, ".exe") || !strcmp(ext, ".com")))
            bScript = false;
    }
    if (bScript){
        shell = getenv("COMSPEC");
        if (shell == NULL) shell = "command.com";
        args = "/c \"";
        args += exec->prog;
        args += "\"";
    }else{
        shell = prg.c_str();
    }

    PROCESS_INFORMATION pi;
    if (!CreateProcessA(shell, (char*)(args.c_str()), NULL, NULL, TRUE,
                        CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)){
        log(L_WARN, "Can't create process %s (%X)", exec->prog.c_str(), GetLastError());
        CloseHandle(inPipe[READ]);
        CloseHandle(inPipe[WRITE]);
        CloseHandle(outPipe[READ]);
        CloseHandle(outPipe[WRITE]);
        CloseHandle(errPipe[READ]);
        CloseHandle(errPipe[WRITE]);
        QTimer::singleShot(0, exec, SLOT(finished()));
        return;
    }
    CloseHandle(outPipe[WRITE]);
    CloseHandle(errPipe[WRITE]);
    CloseHandle(inPipe[READ]);

    ReadPipeThread pOut;
    pOut.pipe    = outPipe[READ];
    pOut.b       = &exec->bOut;

    ReadPipeThread pErr;
    pErr.pipe	 = errPipe[READ];
    pErr.b		 = &exec->bErr;

    pOut.start();
    pErr.start();

    DWORD exitCode = 0;
    unsigned long wrtn;
    BOOL success = FALSE;
    for (; exec->bIn.readPos() < exec->bIn.size();){
        success = GetExitCodeProcess(pi.hProcess, &exitCode);
        if (success && (exitCode != STILL_ACTIVE))
            break;
        unsigned tail = exec->bIn.size() - exec->bIn.readPos();
        if (tail > PIPE_SIZE) tail = PIPE_SIZE;
        if (WriteFile(inPipe[WRITE],
                      exec->bIn.data(exec->bIn.readPos()), tail, &wrtn, NULL) == 0) break;
        exec->bIn.incReadPos(tail);
    }
    if (!success)
        success = GetExitCodeProcess(pi.hProcess, &exitCode);
    if (!success || (exitCode == STILL_ACTIVE))
        WriteFile(inPipe[WRITE], "", 0, &wrtn, NULL);

    WaitForSingleObject(pi.hProcess, INFINITE);
    if (!success)
        GetExitCodeProcess(pi.hProcess, &exitCode);

    CloseHandle(inPipe[WRITE]);
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);

    pOut.wait();
    pErr.wait();

    exec->result = exitCode;
    QTimer::singleShot(0, exec, SLOT(finished()));
}
예제 #9
0
파일: service.c 프로젝트: AzerTyQsdF/osx
void InstallService(pool *p, char *display_name, int argc, char **argv, int reconfig)
{
    TCHAR szPath[MAX_PATH];
    TCHAR szQuotedPath[512];
    char *service_name;
    int regargc = 0;
    char default_depends[] = "Tcpip\0Afd\0";
    char *depends = default_depends;
    size_t depends_len = sizeof(default_depends);
    char **regargv = malloc((argc + 4) * sizeof(char*));
    char **newelem = regargv;

    regargc += 4;
    *(newelem++) = "-d";
    *(newelem++) = ap_server_root;
    *(newelem++) = "-f";
    *(newelem++) = ap_server_confname;

    while (++argv, --argc) {
        if ((**argv == '-') && strchr("kndf", argv[0][1]))
            --argc, ++argv; /* Skip already handled -k -n -d -f options */
        else if ((**argv == '-') && (argv[0][1] == 'W')) 
        {
            /* Catch this service -W dependency 
             * the depends list is null seperated, double-null terminated
             */
            char *service = get_service_name(*(argv + 1));
            size_t add_len = strlen(service) + 1;
            char *more_depends = malloc(depends_len + add_len);
            memcpy (more_depends, depends, depends_len - 1);
            memcpy (more_depends + depends_len - 1, service, add_len);
            depends_len += add_len;
            depends = more_depends;
            depends[depends_len - 1] = '\0';
            ++argv, --argc;
        }
        else if ((**argv != '-') || !strchr("iuw", argv[0][1]))
            *(newelem++) = *argv, ++regargc;  /* Ignoring -i -u -w options */
    }

    /* Remove spaces from display name to create service name */
    service_name = get_service_name(display_name);
    
    printf(reconfig ? "Reconfiguring the %s service\n"
                    : "Installing the %s service\n", 
           display_name);

    if (GetModuleFileName( NULL, szPath, 512 ) == 0)
    {
        ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
        "GetModuleFileName failed");
        return;
    }

    if (isWindowsNT())
    {
        SC_HANDLE schService;
        SC_HANDLE schSCManager;

        ap_snprintf(szQuotedPath, sizeof(szQuotedPath), "\"%s\" --ntservice", szPath);

        schSCManager = OpenSCManager(
                            NULL,                 // machine (local)
                            NULL,                 // database (default)
                            SC_MANAGER_ALL_ACCESS // access required
                            );
        if (!schSCManager) {
            ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
                         "OpenSCManager failed");
            return;
        }
        
        /* Added dependencies for the following: TCPIP, AFD
         * AFD is the winsock handler, TCPIP is self evident
         *
         * RPCSS is the Remote Procedure Call (RPC) Locator
         * required for DCOM communication.  I am far from
         * convinced we should toggle this, but be warned that
         * future apache modules or ISAPI dll's may depend on it.
         * Also UNC share users may need the networking service 
         * started (usually "LanmanWorkstation").  "ProtectedStorage" 
         * may be needed depending on how files and registry keys are 
         * stored.  And W3SVC may be needed to wait until IIS has
         * glommed and released 0.0.0.0:80 if the admin allocates 
         * two different IP's to Apache and IIS on the same port.
         */
        if (reconfig) 
        {
            schService = OpenService(schSCManager, service_name, 
                                     SERVICE_ALL_ACCESS);
            if (!schService)
                ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, 
                             "OpenService failed");
            else if (!ChangeServiceConfig(
                        schService,                 // Service handle
                        SERVICE_WIN32_OWN_PROCESS,  // service type
                        SERVICE_AUTO_START,         // start type
                        SERVICE_ERROR_NORMAL,       // error control type
                        szQuotedPath,               // service's binary
                        NULL,                       // no load ordering group
                        NULL,                       // no tag identifier
                        depends,                    // dependencies
                        NULL,                       // user account
                        NULL,                       // account password
                        display_name)) {            // service display name
                ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, 
		             "ChangeServiceConfig failed");
                /* !schService aborts configuration below */
                CloseServiceHandle(schService);
                schService = NULL;
            }
        }
        else /* !reconfig */
        {
            schService = CreateService(
                        schSCManager,               // SCManager database
                        service_name,               // name of service
                        display_name,               // name to display
                        SERVICE_ALL_ACCESS,         // desired access
                        SERVICE_WIN32_OWN_PROCESS,  // service type
                        SERVICE_AUTO_START,         // start type
                        SERVICE_ERROR_NORMAL,       // error control type
                        szQuotedPath,               // service's binary
                        NULL,                       // no load ordering group
                        NULL,                       // no tag identifier
                        depends,                    // dependencies
                        NULL,                       // user account
                        NULL);                      // account password
            if (!schService)
                ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, 
                             "CreateService failed");
        }
        if (schService)
            CloseServiceHandle(schService);
        
        CloseServiceHandle(schSCManager);
        
        if (!schService)
            return;
    }
    else /* !isWindowsNT() */
    {
        HKEY hkey;
        DWORD rv;

        ap_snprintf(szQuotedPath, sizeof(szQuotedPath),
                    "\"%s\" -k start -n %s", 
                    szPath, service_name);
        /* Create/Find the RunServices key */
        rv = RegCreateKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows"
                          "\\CurrentVersion\\RunServices", &hkey);
        if (rv != ERROR_SUCCESS) {
            SetLastError(rv);
            ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
                         "Could not create/open the RunServices registry key");
            return;
        }

        /* Attempt to add the value for our service */
        rv = RegSetValueEx(hkey, service_name, 0, REG_SZ, 
                           (unsigned char *)szQuotedPath, 
                           strlen(szQuotedPath) + 1);
        if (rv != ERROR_SUCCESS) {
            SetLastError(rv);
            ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
                         "Unable to install service: "
                         "Could not add to RunServices Registry Key");
            RegCloseKey(hkey);
            return;
        }

        RegCloseKey(hkey);

        /* Create/Find the Service key for Monitor Applications to iterate */
        ap_snprintf(szPath, sizeof(szPath), 
                    "SYSTEM\\CurrentControlSet\\Services\\%s", service_name);
        rv = RegCreateKey(HKEY_LOCAL_MACHINE, szPath, &hkey);
        if (rv != ERROR_SUCCESS) {
            SetLastError(rv);
            ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
                         "Could not create/open the %s registry key", szPath);
            return;
        }

        /* Attempt to add the ImagePath value to identify it as Apache */
        rv = RegSetValueEx(hkey, "ImagePath", 0, REG_SZ, 
                           (unsigned char *)szQuotedPath, 
                           strlen(szQuotedPath) + 1);
        if (rv != ERROR_SUCCESS) {
            SetLastError(rv);
            ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
                         "Unable to install service: "
                         "Could not add ImagePath to %s Registry Key", 
                         service_name);
            RegCloseKey(hkey);
            return;
        }

        /* Attempt to add the DisplayName value for our service */
        rv = RegSetValueEx(hkey, "DisplayName", 0, REG_SZ, 
                           (unsigned char *)display_name, 
                           strlen(display_name) + 1);
        if (rv != ERROR_SUCCESS) {
            SetLastError(rv);
            ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
                         "Unable to install service: "
                         "Could not add DisplayName to %s Registry Key", 
                         service_name);
            RegCloseKey(hkey);
            return;
        }

        RegCloseKey(hkey);
    }

    /* Both Platforms: Now store the args in the registry */
    if (ap_registry_set_service_args(p, regargc, regargv, service_name)) {
        return;
    }

    printf("The %s service has been %s successfully.\n", 
           display_name, reconfig ? "reconfigured" : "installed");
}
예제 #10
0
파일: service.c 프로젝트: AzerTyQsdF/osx
void hold_console_open_on_error(void)
{
    HANDLE hConIn;
    HANDLE hConErr;
    DWORD result;
    DWORD mode;
    time_t start;
    time_t remains;
    char *msg = "Note the errors or messages above, "
                "and press the <ESC> key to exit.  ";
    CONSOLE_SCREEN_BUFFER_INFO coninfo;
    INPUT_RECORD in;
    char count[16];

#ifdef WIN32
    /* The service parent cannot just 'pop' out of the main thread,
     * as it is about to try to do...
     * We must end this thread properly so the service control
     * thread exits gracefully.  atexit()s registered in the running
     * apache_main thread _should_ have already been handled, so now
     * we can exit this thread and allow the service thread to exit.
     */
    if (isWindowsNT() && isProcessService() && globdat.connected) {
        service_set_status(SERVICE_STOPPED);
        ExitThread(0);
    }
#endif

    if (!real_exit_code)
        return;
    hConIn = GetStdHandle(STD_INPUT_HANDLE);
    hConErr = GetStdHandle(STD_ERROR_HANDLE);
    if ((hConIn == INVALID_HANDLE_VALUE) || (hConErr == INVALID_HANDLE_VALUE))
        return;
    if (!WriteConsole(hConErr, msg, strlen(msg), &result, NULL) || !result)
        return;
    if (!GetConsoleScreenBufferInfo(hConErr, &coninfo))
        return;
    if (isWindowsNT())
        mode = ENABLE_MOUSE_INPUT | 0x80;
    else
        mode = ENABLE_MOUSE_INPUT;
    if (!SetConsoleMode(hConIn, mode))
        return;
        
    start = time(NULL);
    do
    {
        while (PeekConsoleInput(hConIn, &in, 1, &result) && result)
        {
            if (!ReadConsoleInput(hConIn, &in, 1, &result) || !result)
                return;
            if ((in.EventType == KEY_EVENT) && in.Event.KeyEvent.bKeyDown 
                    && (in.Event.KeyEvent.uChar.AsciiChar == 27))
                return;
            if (in.EventType == MOUSE_EVENT 
                    && (in.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK))
                return;
        }
        remains = ((start + 30) - time(NULL)); 
        sprintf (count, "%d...", remains);
        if (!SetConsoleCursorPosition(hConErr, coninfo.dwCursorPosition))
            return;
        if (!WriteConsole(hConErr, count, strlen(count), &result, NULL) 
                || !result)
            return;
    }
    while ((remains > 0) && WaitForSingleObject(hConIn, 1000) != WAIT_FAILED);
}
예제 #11
0
파일: service.c 프로젝트: AzerTyQsdF/osx
int send_signal_to_service(char *display_name, char *sig, 
                           int argc, char **argv)
{
    DWORD       service_pid;
    HANDLE      hwnd;
    SC_HANDLE   schService;
    SC_HANDLE   schSCManager;
    char       *service_name;
    int success = FALSE;

    enum                        { start,      restart,      stop, unknown } action;
    static char *param[] =      { "start",    "restart",    "shutdown" };
    static char *participle[] = { "starting", "restarting", "stopping" };
    static char *past[]       = { "started",  "restarted",  "stopped"  };

    for (action = start; action < unknown; action++)
        if (!strcasecmp(sig, param[action]))
            break;

    if (action == unknown) {
        printf("signal must be start, restart, or shutdown\n");
        return FALSE;
    }

    service_name = get_service_name(display_name);

    if (isWindowsNT()) 
    {
        schSCManager = OpenSCManager(
                            NULL,                   // machine (NULL == local)
                            NULL,                   // database (NULL == default)
                            SC_MANAGER_ALL_ACCESS   // access required
                            );
        if (!schSCManager) {
            ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
                         "OpenSCManager failed");
            return FALSE;
        }
        
        schService = OpenService(schSCManager, service_name, SERVICE_ALL_ACCESS);

        if (schService == NULL) {
            /* Could not open the service */
            ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
                         "OpenService failed");
            CloseServiceHandle(schSCManager);
            return FALSE;
        }
        
        if (!QueryServiceStatus(schService, &globdat.ssStatus)) {
            ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
                         "QueryService failed");
            CloseServiceHandle(schService);
            CloseServiceHandle(schSCManager);
        }
    }
    else /* !isWindowsNT() */
    {
        /* Locate the window named service_name of class ApacheWin95ServiceMonitor
         * from the active top level windows
         */
        hwnd = FindWindow("ApacheWin95ServiceMonitor", service_name);
        if (hwnd && GetWindowThreadProcessId(hwnd, &service_pid))
            globdat.ssStatus.dwCurrentState = SERVICE_RUNNING;
        else
            globdat.ssStatus.dwCurrentState = SERVICE_STOPPED;
    }

    if (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED 
            && action == stop) {
        printf("The %s service is not started.\n", display_name);
        return FALSE;
    }
    else if (globdat.ssStatus.dwCurrentState == SERVICE_RUNNING 
                 && action == start) {
        printf("The %s service has already been started.\n", display_name);
        strcpy(sig, "");
        return FALSE;
    }
    else
    {
        printf("The %s service is %s.\n", display_name, participle[action]);

        if (isWindowsNT()) 
        {
            if (action == stop)
                success = ap_stop_service(schService);
            else if ((action == start) 
                     || ((action == restart) 
                            && (globdat.ssStatus.dwCurrentState 
                                    == SERVICE_STOPPED)))
            {
                /* start NT service needs service args */
                char **args = malloc(argc * sizeof(char*));
                int i, j;
                for (i = 1, j = 0; i < argc; i++) {
                    if ((argv[i][0] == '-') && ((argv[i][1] == 'k') 
                                             || (argv[i][1] == 'n')))
                        ++i;
                    else
                        args[j++] = argv[i];
                }
                success = ap_start_service(schService, j, args);
            }
            else if (action == restart)
                success = ap_restart_service(schService);
        }
        else /* !isWindowsNT()) */
        {
            char prefix[20];
            ap_snprintf(prefix, sizeof(prefix), "ap%ld", (long)service_pid);
            setup_signal_names(prefix);

            if (action == stop) {
                int ticks = 60;
                ap_start_shutdown();
                while (--ticks)
                {
                    if (!IsWindow(hwnd)) {
                        success = TRUE;
                        break;
                    }
                    Sleep(1000);
                }
            }
            else if (action == restart) 
            {   
                /* This gets a bit tricky... start and restart (of stopped service)
                 * will simply fall through and *THIS* process will fade into an
                 * invisible 'service' process, detaching from the user's console.
                 * We need to change the restart signal to "start", however,
                 * if the service was not -yet- running, and we do return FALSE
                 * to assure main() that we haven't done anything yet.
                 */
                if (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED) 
                {
                    printf("The %s service has %s.\n", display_name, 
                           past[action]);
                    strcpy(sig, "start");
                    return FALSE;
                }
                
                ap_start_restart(1);
                success = TRUE;
            }
            else /* action == start */
            {
                printf("The %s service is %s.\n", display_name, 
                       past[action]);
                return FALSE;
            }
        }

        if( success )
            printf("The %s service has %s.\n", display_name, past[action]);
        else
            printf("Failed to %s the %s service.\n", sig, display_name);
    }

    if (isWindowsNT()) {
        CloseServiceHandle(schService);
        CloseServiceHandle(schSCManager);
    }
    return success;
}
예제 #12
0
파일: service.c 프로젝트: AzerTyQsdF/osx
void RemoveService(char *display_name)
{
    char *service_name;
    BOOL success = FALSE;

    printf("Removing the %s service\n", display_name);

    /* Remove spaces from display name to create service name */
    service_name = get_service_name(display_name);
    
    if (isWindowsNT())
    {
        SC_HANDLE   schService;
        SC_HANDLE   schSCManager;
    
        schSCManager = OpenSCManager(
                            NULL,                   // machine (NULL == local)
                            NULL,                   // database (NULL == default)
                            SC_MANAGER_ALL_ACCESS   // access required
                            );
        if (!schSCManager) {
            ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
                         "OpenSCManager failed");
            return;
        }

        schService = OpenService(schSCManager, service_name, SERVICE_ALL_ACCESS);

        if (schService == NULL) {
            /* Could not open the service */
            ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
                         "OpenService failed");
        }
        else {
            /* try to stop the service */
            ap_stop_service(schService);

            // now remove the service
            if (DeleteService(schService) == 0)
                ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
                             "DeleteService failed");
            else
                success = TRUE;
            CloseServiceHandle(schService);
        }
        /* SCM removes registry parameters  */
        CloseServiceHandle(schSCManager);
    }
    else /* !isWindowsNT() */
    {
        HKEY hkey;
        DWORD service_pid;
        DWORD rv;
        HWND hwnd;

        /* Locate the named window of class ApacheWin95ServiceMonitor
         * from the active top level windows
         */
        hwnd = FindWindow("ApacheWin95ServiceMonitor", service_name);
        if (hwnd && GetWindowThreadProcessId(hwnd, &service_pid))
        {
            int ticks = 120;
            char prefix[20];
            ap_snprintf(prefix, sizeof(prefix), "ap%ld", (long)service_pid);
            setup_signal_names(prefix);
            ap_start_shutdown();
            while (--ticks) {
                if (!IsWindow(hwnd))
                    break;
                Sleep(1000);
            }
        }

        /* Open the RunServices key */
        rv = RegOpenKey(HKEY_LOCAL_MACHINE, 
                "Software\\Microsoft\\Windows\\CurrentVersion\\RunServices",
                    &hkey);
        if (rv != ERROR_SUCCESS) {
            SetLastError(rv);
            ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
                         "Could not open the RunServices registry key.");
        } 
        else {
            /* Delete the registry value for this service */
            rv = RegDeleteValue(hkey, service_name);
            if (rv != ERROR_SUCCESS) {
                SetLastError(rv);
                ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
                             "Unable to remove service: "
                             "Could not delete the RunServices entry.");
            }
            else
                success = TRUE;
        }
        RegCloseKey(hkey);

        /* Open the Services key */
        rv = RegOpenKey(HKEY_LOCAL_MACHINE, 
                        "SYSTEM\\CurrentControlSet\\Services", &hkey);
        if (rv != ERROR_SUCCESS) {
            rv = RegDeleteValue(hkey, service_name);
            ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
                         "Could not open the Services registry key.");
            success = FALSE;
        } 
        else {
            /* Delete the registry key for this service */
            rv = RegDeleteKey(hkey, service_name);
            if (rv != ERROR_SUCCESS) {
                SetLastError(rv);
                ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
                             "Unable to remove service: "
                             "Could not delete the Services registry key.");
                success = FALSE;
            }
        }
        RegCloseKey(hkey);
    }
    if (success)
        printf("The %s service has been removed successfully.\n", 
               display_name);
}
예제 #13
0
pxResult pxExecute(char *acommandline, char *ainput, char **aoutput, LPDWORD aexitcode)
{
  BOOL success;
  STARTUPINFO startupinfo;
  SECURITY_ATTRIBUTES securityattributes;
  SECURITY_DESCRIPTOR securitydescriptor;
  PROCESS_INFORMATION processinformation;
  HANDLE  newstdin, newstdout, readstdout, writestdin;
  char *inputpos;
  DWORD transfered;
  int size;

  LogMessage("commandline:\n", acommandline, "\n");

  ZeroMemory(&securityattributes, sizeof(securityattributes));
  securityattributes.nLength=sizeof(SECURITY_ATTRIBUTES);
  securityattributes.bInheritHandle=TRUE;

  if(isWindowsNT())
  {
    InitializeSecurityDescriptor(&securitydescriptor, SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl(&securitydescriptor, TRUE, NULL, FALSE);
    securityattributes.lpSecurityDescriptor=&securitydescriptor;
  }
  else securityattributes.lpSecurityDescriptor=NULL;

  success=CreatePipe(&newstdin, &writestdin ,&securityattributes ,0);
  if(! success)
  {
    LogMessage("--- ", "create pipe failed", "\n");
    return pxCreatePipeFailed;
  }

  success=CreatePipe(&readstdout, &newstdout, &securityattributes, 0);
  if(! success)
  {
    LogMessage("--- ", "create pipe failed", "\n");
    CloseHandle(newstdin);
    CloseHandle(writestdin);
    return pxCreatePipeFailed;
  }

  GetStartupInfo(&startupinfo);
  startupinfo.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
  startupinfo.wShowWindow=SW_HIDE;
  startupinfo.hStdOutput=newstdout;
  startupinfo.hStdError=newstdout;
  startupinfo.hStdInput=newstdin;

  success=CreateProcess(NULL, acommandline, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &startupinfo, &processinformation);

  if(! success)
  {
    LogMessage("--- ", "create process failed", "\n");
    CloseHandle(newstdin);
    CloseHandle(writestdin);
    CloseHandle(newstdout);
    CloseHandle(readstdout);
    return pxCreateProcessFailed;
  }

  inputpos=ainput;

  while(TRUE)
  {
    success=GetExitCodeProcess(processinformation.hProcess, aexitcode);
    if((success)&&(*aexitcode!=STILL_ACTIVE)) break;

    storeOutput(readstdout, aoutput);

    if(*inputpos!='\0') size=1;
    else size=0;

    success=WriteFile(writestdin, inputpos, size, &transfered, NULL);

    inputpos+=transfered;
  }

  storeOutput(readstdout, aoutput);
  WaitForSingleObject(processinformation.hProcess, INFINITE);

  LogMessage("output:\n", *aoutput, "");

  CloseHandle(processinformation.hThread);
  CloseHandle(processinformation.hProcess);
  CloseHandle(newstdin);
  CloseHandle(newstdout);
  CloseHandle(readstdout);
  CloseHandle(writestdin);

  return pxSuccess;
}