Message ID | 1253459790-17859-2-git-send-email-mgoldish@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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? > > Signed-off-by: Michael Goldish <mgoldish@redhat.com> > --- > 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@test.kernel.org > 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@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
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"); }
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. Signed-off-by: Michael Goldish <mgoldish@redhat.com> --- client/tests/kvm/deps/rss.cpp | 54 +++++++++++++++++----------------------- 1 files changed, 23 insertions(+), 31 deletions(-)