You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by wr...@apache.org on 2002/03/01 07:44:54 UTC
cvs commit: httpd-2.0/support/win32 wintty.c
wrowe 02/02/28 22:44:54
Modified: support/win32 wintty.c
Log:
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.
Revision Changes Path
1.7 +114 -72 httpd-2.0/support/win32/wintty.c
Index: wintty.c
===================================================================
RCS file: /home/cvs/httpd-2.0/support/win32/wintty.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- wintty.c 27 Feb 2002 19:38:09 -0000 1.6
+++ wintty.c 1 Mar 2002 06:44:54 -0000 1.7
@@ -86,22 +86,20 @@
"\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 @@
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 @@
}
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 @@
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 @@
WaitForSingleObject(thread, INFINITE);
FreeConsole();
- CloseHandle(herrout);
if (isservice) {
if (!SetProcessWindowStation(hsavewinsta)) {
len = GetLastError();