kernel32: Fix writing to a pipe in WriteConsoleW().

Francois Gouget fgouget at free.fr
Wed Aug 3 11:07:09 CDT 2011


WriteFile() checks if the handle corresponds to the console and if it 
does invokes WriteConsoleA(). This barely escaped an infinite loop but 
messed up the string encoding as CP_UNIXCP is usually different from 
CP_ACP.
---

I noticed this issue while testing the net.exe tool. After making it 
use WineConsole() I was getting the following outputs:

$ wine net stop
Spécifie le service à arrêter.
$ ./wine net stop | cat
Sp├®cifie le service ├á arr├¬ter.

It turns out that it's because we only get through the WineConsoleW() -> 
WriteFile() -> WriteConsoleA() loop in the second case.

Now both cases work.


 dlls/kernel32/console.c |   26 ++++++++++++++++++++------
 1 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/dlls/kernel32/console.c b/dlls/kernel32/console.c
index d28c153..bab2322 100644
--- a/dlls/kernel32/console.c
+++ b/dlls/kernel32/console.c
@@ -45,6 +45,7 @@
 # include <sys/poll.h>
 #endif
 
+#define NONAMELESSUNION
 #include "ntstatus.h"
 #define WIN32_NO_STATUS
 #include "windef.h"
@@ -2361,7 +2362,9 @@ BOOL WINAPI WriteConsoleW(HANDLE hConsoleOutput, LPCVOID lpBuffer, DWORD nNumber
     {
         char*           ptr;
         unsigned        len;
-        BOOL            ret;
+        HANDLE          hFile;
+        NTSTATUS        status;
+        IO_STATUS_BLOCK iosb;
 
         close(fd);
         /* FIXME: mode ENABLED_OUTPUT is not processed (or actually we rely on underlying Unix/TTY fd
@@ -2372,17 +2375,28 @@ BOOL WINAPI WriteConsoleW(HANDLE hConsoleOutput, LPCVOID lpBuffer, DWORD nNumber
             return FALSE;
 
         WideCharToMultiByte(CP_UNIXCP, 0, lpBuffer, nNumberOfCharsToWrite, ptr, len, NULL, NULL);
-        ret = WriteFile(wine_server_ptr_handle(console_handle_unmap(hConsoleOutput)),
-                        ptr, len, lpNumberOfCharsWritten, NULL);
-        if (ret && lpNumberOfCharsWritten)
+        hFile = wine_server_ptr_handle(console_handle_unmap(hConsoleOutput));
+        status = NtWriteFile(hFile, NULL, NULL, NULL, &iosb, ptr, len, 0, NULL);
+        if (status == STATUS_PENDING)
         {
-            if (*lpNumberOfCharsWritten == len)
+            WaitForSingleObject(hFile, INFINITE);
+            status = iosb.u.Status;
+        }
+
+        if (status != STATUS_PENDING && lpNumberOfCharsWritten)
+        {
+            if (iosb.Information == len)
                 *lpNumberOfCharsWritten = nNumberOfCharsToWrite;
             else
                 FIXME("Conversion not supported yet\n");
         }
         HeapFree(GetProcessHeap(), 0, ptr);
-        return ret;
+        if (status != STATUS_SUCCESS)
+        {
+            SetLastError(RtlNtStatusToDosError(status));
+            return FALSE;
+        }
+        return TRUE;
     }
 
     if (!GetConsoleMode(hConsoleOutput, &mode) || !GetConsoleScreenBufferInfo(hConsoleOutput, &csbi))
-- 
1.7.5.4


More information about the wine-patches mailing list