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();