From: William A. Rowe Jr Date: Fri, 1 Mar 2002 06:44:54 +0000 (+0000) Subject: Significant cleanup and enable wintty to -always- escape from the service X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3fa0666aa074d37df110d8676bcbcd7abc961ecc;p=apache Significant cleanup and enable wintty to -always- escape from the service context when the run-as-user is LocalSystem or has access to the windows station and desktop. The original method did not give us a visible tty unless the 'Allow Service to Interact with Desktop' toggle was set. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@93655 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/support/win32/wintty.c b/support/win32/wintty.c index 26a827b2d5..733f595e81 100644 --- a/support/win32/wintty.c +++ b/support/win32/wintty.c @@ -86,22 +86,20 @@ const char *options = "\t-v{erbose} error reporting (for debugging)\n" "\t-? for this message\n\n"; -HANDLE herrout = NULL; BOOL verbose = FALSE; void printerr(char *fmt, ...) { char str[1024]; va_list args; - DWORD len; - if (!verbose || !herrout) + if (!verbose) return; va_start(args, fmt); wvsprintf(str, fmt, args); - WriteFile(herrout, str, len = strlen(str), &len, NULL); + OutputDebugString(str); } -DWORD WINAPI feedback(LPVOID pipeout); +DWORD WINAPI feedback(LPVOID args); typedef struct feedback_args_t { HANDLE in; @@ -115,8 +113,7 @@ int main(int argc, char** argv) HANDLE hwinsta, hsavewinsta; HANDLE hdesk, hsavedesk; HANDLE conin, conout; - HANDLE pipein, pipeout; - HANDLE hstdin, hstdout, hstderr; + HANDLE hstdin, hstdout, hstderr, hdup; feedback_args_t feed; DWORD conmode; DWORD newinmode = 0, notinmode = 0; @@ -172,89 +169,134 @@ int main(int argc, char** argv) } hproc = GetCurrentProcess(); - herrout = hstderr = GetStdHandle(STD_ERROR_HANDLE); - if (!hstderr || hstderr == INVALID_HANDLE_VALUE) { - printerr("GetStdHandle(STD_ERROR_HANDLE) failed (%d)\n", GetLastError()); - herrout = NULL; + hsavewinsta = GetProcessWindowStation(); + if (!hsavewinsta || hsavewinsta == INVALID_HANDLE_VALUE) { + printerr("GetProcessWindowStation() failed (%d)\n", GetLastError()); } - else if (!DuplicateHandle(hproc, hstderr, - hproc, &herrout, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - printerr("DupHandle(stderr) failed (%d)\n", GetLastError()); + else if (!GetUserObjectInformation(hsavewinsta, UOI_NAME, str, sizeof(str), &len)) { + printerr("GetUserObjectInfoformation(hWinSta) failed (%d)\n", GetLastError()); } + else if (strnicmp(str, "Service-", 8) == 0) { + printerr("WindowStation Name %s is a service\n", str); + isservice = TRUE; + } + SetLastError(0); hstdin = GetStdHandle(STD_INPUT_HANDLE); if (!hstdin || hstdin == INVALID_HANDLE_VALUE) { - printerr("GetStdHandle(STD_INPUT_HANDLE) failed (%d)\n", GetLastError()); + printerr("GetStdHandle(STD_INPUT_HANDLE) failed (%d)\n", + GetLastError()); } - else if (!DuplicateHandle(hproc, hstdin, - hproc, &pipein, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - printerr("DupHandle(stdin) failed (%d)\n", GetLastError()); + else if (DuplicateHandle(hproc, hstdin, hproc, &hdup, 0, + isservice, DUPLICATE_SAME_ACCESS)) { + CloseHandle(hstdin); + hstdin = hdup; + } + else { + printerr("DupHandle(stdin [%x]) failed (%d)\n", + hstdin, GetLastError()); } hstdout = GetStdHandle(STD_OUTPUT_HANDLE); if (!hstdout || hstdout == INVALID_HANDLE_VALUE) { - printerr("GetStdHandle(STD_OUTPUT_HANDLE) failed (%d)\n", GetLastError()); + printerr("GetStdHandle(STD_OUTPUT_HANDLE) failed (%d)\n", + GetLastError()); } - else if (!DuplicateHandle(hproc, hstdout, - hproc, &pipeout, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - printerr("DupHandle(stdout) failed (%d)\n", GetLastError()); + else if (DuplicateHandle(hproc, hstdout, hproc, &hdup, 0, + isservice, DUPLICATE_SAME_ACCESS)) { + CloseHandle(hstdout); + hstdout = hdup; + } + else { + printerr("DupHandle(stdout [%x]) failed (%d)\n", + hstdout, GetLastError()); } - hsavewinsta = GetProcessWindowStation(); - if (!hsavewinsta || hsavewinsta == INVALID_HANDLE_VALUE) { - printerr("GetProcWinSta() failed (%d)\n", GetLastError()); + hstderr = GetStdHandle(STD_ERROR_HANDLE); + if (!hstderr || hstderr == INVALID_HANDLE_VALUE) { + printerr("GetStdHandle(STD_ERROR_HANDLE) failed (%d)\n", + GetLastError()); } - else if (!GetUserObjectInformation(hsavewinsta, UOI_NAME, str, sizeof(str), &len)) { - printerr("GetUserObjectInfo(GetProcWinSta) failed (%d)\n", GetLastError()); - CloseHandle(hsavewinsta); + else if (DuplicateHandle(hproc, hstderr, hproc, &hdup, 0, + isservice, DUPLICATE_SAME_ACCESS)) { + CloseHandle(hstderr); + hstderr = hdup; } - else if (strnicmp(str, "Service-", 8) == 0) { - isservice = TRUE; + else { + printerr("DupHandle(stderr [%x]) failed (%d)\n", + hstderr, GetLastError()); } - else - CloseHandle(hsavewinsta); - SetLastError(0); + /* You can't close the console till all the handles above were + * rescued by DuplicateHandle() + */ if (!FreeConsole()) - printerr("DupHandle(stdout) failed (%d)\n", GetLastError()); - + printerr("FreeConsole() failed (%d)\n", GetLastError()); + if (isservice) { - hwinsta = OpenWindowStation("WinSta0", TRUE, - WINSTA_ACCESSCLIPBOARD - | WINSTA_ACCESSGLOBALATOMS - | WINSTA_ENUMDESKTOPS - | WINSTA_ENUMERATE - | WINSTA_READATTRIBUTES - | WINSTA_READSCREEN - | WINSTA_WRITEATTRIBUTES); +#ifdef WE_EVER_FIGURE_OUT_WHY_THIS_DOESNT_WORK + hsavedesk = GetThreadDesktop(GetCurrentThreadId()); + if (!hsavedesk || hsavedesk == INVALID_HANDLE_VALUE) { + printerr("GetThreadDesktop(GetTID()) failed (%d)\n", GetLastError()); + } + CloseWindowStation(hwinsta); + hwinsta = OpenWindowStation("WinSta0", TRUE, MAXIMUM_ALLOWED); if (!hwinsta || hwinsta == INVALID_HANDLE_VALUE) { printerr("OpenWinSta(WinSta0) failed (%d)\n", GetLastError()); } else if (!SetProcessWindowStation(hwinsta)) { printerr("SetProcWinSta(WinSta0) failed (%d)\n", GetLastError()); } - hsavedesk = GetThreadDesktop(GetCurrentThreadId()); - if (!hsavedesk || hsavedesk == INVALID_HANDLE_VALUE) { - printerr("GetThreadDesktop(GetTID()) failed (%d)\n", GetLastError()); - } - hdesk = OpenDesktop("Default", 0, TRUE, - DESKTOP_READOBJECTS - | DESKTOP_CREATEWINDOW - | DESKTOP_CREATEMENU - | DESKTOP_HOOKCONTROL - | DESKTOP_JOURNALRECORD - | DESKTOP_JOURNALPLAYBACK - | DESKTOP_ENUMERATE - | DESKTOP_WRITEOBJECTS); + hdesk = OpenDesktop("Default", 0, TRUE, MAXIMUM_ALLOWED); if (!hdesk || hdesk == INVALID_HANDLE_VALUE) { printerr("OpenDesktop(Default) failed (%d)\n", GetLastError()); } else if (!SetThreadDesktop(hdesk)) { printerr("SetThreadDesktop(Default) failed (%d)\n", GetLastError()); } +#else + PROCESS_INFORMATION pi; + STARTUPINFO si; + DWORD exitcode = 1; + char appbuff[MAX_PATH]; + char *appname = NULL; + char *cmdline = GetCommandLine(); + + if (!GetModuleFileName(NULL, appbuff, sizeof(appbuff))) { + appname = appbuff; + } + + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + si.dwFlags = STARTF_USESHOWWINDOW + | STARTF_USESTDHANDLES; + si.lpDesktop = "WinSta0\\Default"; + si.wShowWindow = 1; /* SW_SHOWNORMAL */ + si.hStdInput = hstdin; + si.hStdOutput = hstdout; + si.hStdError = hstderr; + + /* Instantly, upon creating the new process, we will close our + * copies of the handles so our parent isn't confused when the + * child closes their copy of the handle. Without this action, + * we would hold a copy of the handle, and the parent would not + * receive their EOF notification. + */ + if (CreateProcess(appname, cmdline, NULL, NULL, TRUE, + CREATE_SUSPENDED | CREATE_NEW_CONSOLE, + NULL, NULL, &si, &pi)) { + CloseHandle(si.hStdInput); + CloseHandle(si.hStdOutput); + CloseHandle(si.hStdError); + ResumeThread(pi.hThread); + CloseHandle(pi.hThread); + WaitForSingleObject(pi.hProcess, INFINITE); + GetExitCodeProcess(pi.hProcess, &exitcode); + CloseHandle(pi.hProcess); + return exitcode; + } + return 1; +#endif } if (!AllocConsole()) { @@ -269,42 +311,43 @@ int main(int argc, char** argv) FILE_SHARE_READ | FILE_SHARE_WRITE, FALSE, OPEN_EXISTING, 0, NULL); if (!conout || conout == INVALID_HANDLE_VALUE) { - printerr("GetStdHandle(STD_OUTPUT_HANDLE) failed (%d)\n", GetLastError()); - } - else if (!herrout) { - herrout = conout; + printerr("CreateFile(CONOUT$) failed (%d)\n", GetLastError()); } else if (!GetConsoleMode(conout, &conmode)) { printerr("GetConsoleMode(CONOUT) failed (%d)\n", GetLastError()); } - else if (!SetConsoleMode(conout, conmode = ((conmode | newoutmode) & ~notoutmode))) { - printerr("SetConsoleMode(CONOUT, 0x%x) failed (%d)\n", conmode, GetLastError()); + else if (!SetConsoleMode(conout, conmode = ((conmode | newoutmode) + & ~notoutmode))) { + printerr("SetConsoleMode(CONOUT, 0x%x) failed (%d)\n", + conmode, GetLastError()); } conin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, FALSE, OPEN_EXISTING, 0, NULL); if (!conin || conin == INVALID_HANDLE_VALUE) { - printerr("GetStdHandle(STD_INPUT_HANDLE) failed (%d)\n", GetLastError()); + printerr("CreateFile(CONIN$) failed (%d)\n", GetLastError()); } else if (!GetConsoleMode(conin, &conmode)) { printerr("GetConsoleMode(CONIN) failed (%d)\n", GetLastError()); } - else if (!SetConsoleMode(conin, conmode = ((conmode | newinmode) & ~notinmode))) { - printerr("SetConsoleMode(CONIN, 0x%x) failed (%d)\n", conmode, GetLastError()); + else if (!SetConsoleMode(conin, conmode = ((conmode | newinmode) + & ~notinmode))) { + printerr("SetConsoleMode(CONIN, 0x%x) failed (%d)\n", + conmode, GetLastError()); } feed.in = conin; - feed.out = pipeout; + feed.out = hstdout; thread = CreateThread(NULL, 0, feedback, (LPVOID)&feed, 0, &tid); - while (ReadFile(pipein, str, sizeof(str), &len, NULL)) + while (ReadFile(hstdin, str, sizeof(str), &len, NULL)) if (!len || !WriteFile(conout, str, len, &len, NULL)) break; printerr("[EOF] from stdin (%d)\n", GetLastError()); - CloseHandle(pipeout); + CloseHandle(stdout); if (!GetConsoleTitle(str, sizeof(str))) { printerr("SetConsoleTitle() failed (%d)\n", GetLastError()); } @@ -317,7 +360,6 @@ int main(int argc, char** argv) WaitForSingleObject(thread, INFINITE); FreeConsole(); - CloseHandle(herrout); if (isservice) { if (!SetProcessWindowStation(hsavewinsta)) { len = GetLastError();