Re: [Autotest] [KVM-AUTOTEST PATCH 2/4] KVM test: rss.cpp: send characters to the console window rather than directly to STDIN

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Sep 21, 2009 at 08:30:26AM -0400, Michael Goldish wrote:
> 
> ----- "Yolkfull Chow" <yzhou@xxxxxxxxxx> wrote:
> 
> > On Sun, Sep 20, 2009 at 06:16:28PM +0300, Michael Goldish wrote:
> > > Some Windows programs behave badly when their STDIN is redirected to
> > a pipe
> > > (most notably wmic).  Therefore, keep STDIN unredirected, and send
> > input to the
> > > console window as a series of WM_CHAR messages.
> > 
> > Hi Michael, I just tried this patch. After re-compiling and
> > installing RSS, seems never a command could be executed successfully
> > or
> > returned with results. I tested this on Win2008-32. Any clue for 
> > fixing up it?
> 
> Did you also apply the other patch --
> "allow setting shell line separator string in the config file"?

I did forget apply the second patch of that set. It now works and 'wmic'
works fine as well. Thank you very much for working this out.:-)

Cheers,

> 
> By default, when using nc, autotest ends commands with "\n".
> The modified rss.exe seems to require lines to end with "\r\n" (it's a
> common line separator in Windows).
> The patch I mentioned adds a "shell_linesep" parameter that controls
> the line separator and changes the line separator on Windows to "\r\n".
> 
> If you can't apply the patch (conflicts or whatever), go to kvm_utils.py,
> find the "netcat" function, and change this line:
> return remote_login(command, password, prompt, "\n", timeout)
> to this:
> return remote_login(command, password, prompt, "\r\n", timeout)
> 
> If it still doesn't work then we have a real problem and I'll have to
> start debugging stuff.
> 
> (Note: if you want to manually test rss.exe, use telnet instead of nc
> (e.g. telnet localhost 5000) because telnet ends lines with "\r\n".)
> 
> > > 
> > > Signed-off-by: Michael Goldish <mgoldish@xxxxxxxxxx>
> > > ---
> > >  client/tests/kvm/deps/rss.cpp |   54
> > +++++++++++++++++-----------------------
> > >  1 files changed, 23 insertions(+), 31 deletions(-)
> > > 
> > > diff --git a/client/tests/kvm/deps/rss.cpp
> > b/client/tests/kvm/deps/rss.cpp
> > > index 73a849a..66d9a5b 100644
> > > --- a/client/tests/kvm/deps/rss.cpp
> > > +++ b/client/tests/kvm/deps/rss.cpp
> > > @@ -22,9 +22,9 @@ struct client_info {
> > >      SOCKET socket;
> > >      sockaddr_in addr;
> > >      int pid;
> > > +    HWND hwnd;
> > >      HANDLE hJob;
> > >      HANDLE hChildOutputRead;
> > > -    HANDLE hChildInputWrite;
> > >      HANDLE hThreadChildToSocket;
> > >  };
> > >  
> > > @@ -161,15 +161,10 @@ DWORD WINAPI SocketToChild(LPVOID
> > client_info_ptr)
> > >          sprintf(message, "Client (%s) entered text: \"%s\"\r\n",
> > >                  client_info_str, formatted_buffer);
> > >          AppendMessage(message);
> > > -        // Write the data to the child's STDIN
> > > -        WriteFile(ci.hChildInputWrite, buffer, bytes_received,
> > > -                  &bytes_written, NULL);
> > > -        // Make sure all the data was written
> > > -        if (bytes_written != bytes_received) {
> > > -            sprintf(message,
> > > -                    "SocketToChild: bytes received (%d) != bytes
> > written (%d)",
> > > -                    bytes_received, bytes_written);
> > > -            ExitOnError(message, 1);
> > > +        // Send the data as a series of WM_CHAR messages to the
> > console window
> > > +        for (int i=0; i<bytes_received; i++) {
> > > +            SendMessage(ci.hwnd, WM_CHAR, (WPARAM)buffer[i], 0);
> > > +            SendMessage(ci.hwnd, WM_SETFOCUS, 0, 0);
> > >          }
> > >      }
> > >  
> > > @@ -194,7 +189,6 @@ DWORD WINAPI SocketToChild(LPVOID
> > client_info_ptr)
> > >      CloseHandle(ci.hJob);
> > >      CloseHandle(ci.hThreadChildToSocket);
> > >      CloseHandle(ci.hChildOutputRead);
> > > -    CloseHandle(ci.hChildInputWrite);
> > >  
> > >      AppendMessage("SocketToChild thread exited\r\n");
> > >  
> > > @@ -203,18 +197,25 @@ DWORD WINAPI SocketToChild(LPVOID
> > client_info_ptr)
> > >  
> > >  void PrepAndLaunchRedirectedChild(client_info *ci,
> > >                                    HANDLE hChildStdOut,
> > > -                                  HANDLE hChildStdIn,
> > >                                    HANDLE hChildStdErr)
> > >  {
> > >      PROCESS_INFORMATION pi;
> > >      STARTUPINFO si;
> > >  
> > > +    // Allocate a new console for the child
> > > +    HWND hwnd = GetForegroundWindow();
> > > +    FreeConsole();
> > > +    AllocConsole();
> > > +    ShowWindow(GetConsoleWindow(), SW_HIDE);
> > > +    if (hwnd)
> > > +        SetForegroundWindow(hwnd);
> > > +
> > >      // Set up the start up info struct.
> > >      ZeroMemory(&si, sizeof(STARTUPINFO));
> > >      si.cb = sizeof(STARTUPINFO);
> > >      si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
> > >      si.hStdOutput = hChildStdOut;
> > > -    si.hStdInput  = hChildStdIn;
> > > +    si.hStdInput  = GetStdHandle(STD_INPUT_HANDLE);
> > >      si.hStdError  = hChildStdErr;
> > >      // Use this if you want to hide the child:
> > >      si.wShowWindow = SW_HIDE;
> > > @@ -223,7 +224,7 @@ void PrepAndLaunchRedirectedChild(client_info
> > *ci,
> > >  
> > >      // Launch the process that you want to redirect.
> > >      if (!CreateProcess(NULL, "cmd.exe", NULL, NULL, TRUE,
> > > -                       CREATE_NEW_CONSOLE, NULL, "C:\\", &si,
> > &pi))
> > > +                       0, NULL, "C:\\", &si, &pi))
> > >          ExitOnError("CreateProcess failed");
> > >  
> > >      // Close any unnecessary handles.
> > > @@ -235,12 +236,16 @@ void PrepAndLaunchRedirectedChild(client_info
> > *ci,
> > >      // Assign the process to a newly created JobObject
> > >      ci->hJob = CreateJobObject(NULL, NULL);
> > >      AssignProcessToJobObject(ci->hJob, pi.hProcess);
> > > +    // Keep the console window's handle
> > > +    ci->hwnd = GetConsoleWindow();
> > > +
> > > +    // Detach from the child's console
> > > +    FreeConsole();
> > >  }
> > >  
> > >  void SpawnSession(client_info *ci)
> > >  {
> > >      HANDLE hOutputReadTmp, hOutputRead, hOutputWrite;
> > > -    HANDLE hInputWriteTmp, hInputRead, hInputWrite;
> > >      HANDLE hErrorWrite;
> > >      SECURITY_ATTRIBUTES sa;
> > >  
> > > @@ -261,10 +266,6 @@ void SpawnSession(client_info *ci)
> > >                           TRUE, DUPLICATE_SAME_ACCESS))
> > >          ExitOnError("DuplicateHandle failed");
> > >  
> > > -    // Create the child input pipe.
> > > -    if (!CreatePipe(&hInputRead, &hInputWriteTmp, &sa, 0))
> > > -        ExitOnError("CreatePipe failed");
> > > -
> > >      // Create new output read handle and the input write handles.
> > Set
> > >      // the Properties to FALSE. Otherwise, the child inherits the
> > >      // properties and, as a result, non-closeable handles to the
> > pipes
> > > @@ -276,29 +277,20 @@ void SpawnSession(client_info *ci)
> > >                           DUPLICATE_SAME_ACCESS))
> > >          ExitOnError("DuplicateHandle failed");
> > >  
> > > -    if (!DuplicateHandle(GetCurrentProcess(), hInputWriteTmp,
> > > -                         GetCurrentProcess(),
> > > -                         &hInputWrite, // Address of new handle.
> > > -                         0, FALSE, // Make it uninheritable.
> > > -                         DUPLICATE_SAME_ACCESS))
> > > -        ExitOnError("DuplicateHandle failed");
> > > -
> > >      // Close inheritable copies of the handles you do not want to
> > be
> > >      // inherited.
> > > -    if (!CloseHandle(hOutputReadTmp)) ExitOnError("CloseHandle
> > failed");
> > > -    if (!CloseHandle(hInputWriteTmp)) ExitOnError("CloseHandle
> > failed");
> > > +    if (!CloseHandle(hOutputReadTmp))
> > > +        ExitOnError("CloseHandle failed");
> > >  
> > > -    PrepAndLaunchRedirectedChild(ci, hOutputWrite, hInputRead,
> > hErrorWrite);
> > > +    PrepAndLaunchRedirectedChild(ci, hOutputWrite, hErrorWrite);
> > >  
> > >      ci->hChildOutputRead = hOutputRead;
> > > -    ci->hChildInputWrite = hInputWrite;
> > >  
> > >      // Close pipe handles (do not continue to modify the parent).
> > >      // You need to make sure that no handles to the write end of
> > the
> > >      // output pipe are maintained in this process or else the pipe
> > will
> > >      // not close when the child process exits and the ReadFile will
> > hang.
> > >      if (!CloseHandle(hOutputWrite)) ExitOnError("CloseHandle
> > failed");
> > > -    if (!CloseHandle(hInputRead )) ExitOnError("CloseHandle
> > failed");
> > >      if (!CloseHandle(hErrorWrite)) ExitOnError("CloseHandle
> > failed");
> > >  }
> > >  
> > > -- 
> > > 1.5.4.1
> > > 
> > > _______________________________________________
> > > Autotest mailing list
> > > Autotest@xxxxxxxxxxxxxxx
> > > http://test.kernel.org/cgi-bin/mailman/listinfo/autotest
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux