/* * 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); } }
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); }
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); }
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; }
/* 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; }
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; }
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); }
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())); }
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"); }
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); }
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; }
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); }
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; }