>From d6068e075eb2df21a633e9decad090d382c031a0 Mon Sep 17 00:00:00 2001
From: Jason Edmeades <us@edmeades.me.uk>
Date: Mon, 16 Apr 2007 21:02:10 +0100
Subject: [PATCH] MSVCRT: (f)printfw should output Multibyte not unicode to text streams

---
 dlls/msvcrt/file.c       |   49 ++++++++++++++++++++++++++++++++++++---------
 dlls/msvcrt/msvcrt.h     |    2 +
 dlls/msvcrt/tests/file.c |   25 +++++++++++++++++++++++
 dlls/msvcrt/wcs.c        |   15 ++++++++++++++
 4 files changed, 81 insertions(+), 10 deletions(-)

diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c
index fa93204..17fc0b5 100644
--- a/dlls/msvcrt/file.c
+++ b/dlls/msvcrt/file.c
@@ -3022,21 +3022,50 @@ int CDECL MSVCRT_vfprintf(MSVCRT_FILE* file, const char *format, va_list valist)
  */
 int CDECL MSVCRT_vfwprintf(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, va_list valist)
 {
-  MSVCRT_wchar_t buf[2048], *mem = buf;
-  int written, resize = sizeof(buf) / sizeof(MSVCRT_wchar_t), retval;
+  int retval;
+
   /* See vfprintf comments */
-  while ((written = MSVCRT_vsnwprintf(mem, resize, format, valist)) == -1 ||
-          written > resize)
+
+  /* Output to text files is in multibyte characters, output to binary
+     is in unicode characters                                         */
+  if (MSVCRT_fdesc[file->_file].wxflag & WX_TEXT)
   {
-    resize = (written == -1 ? resize * 2 : written + sizeof(MSVCRT_wchar_t));
+
+    char buf[2048], *mem = buf;
+    int written, resize = sizeof(buf);
+    
+    while ((written = MSVCRT_vsnwprintf_internal(mem, resize, format, valist)) == -1 ||
+            written > resize)
+    {
+      resize = (written == -1 ? resize * 2 : written + 1);
+      if (mem != buf)
+        MSVCRT_free (mem);
+      if (!(mem = (char *)MSVCRT_malloc(resize)))
+        return MSVCRT_EOF;
+    }
+    retval = MSVCRT_fwrite(mem, sizeof(*mem), written, file);
+    if (mem != buf)
+      MSVCRT_free (mem);
+
+  } else {
+
+    MSVCRT_wchar_t buf[2048], *mem = buf;
+    int written, resize = sizeof(buf) / sizeof(MSVCRT_wchar_t);
+    
+    while ((written = MSVCRT_vsnwprintf(mem, resize, format, valist)) == -1 ||
+            written > resize)
+    {
+      resize = (written == -1 ? resize * 2 : written + sizeof(MSVCRT_wchar_t));
+      if (mem != buf)
+        MSVCRT_free (mem);
+      if (!(mem = (MSVCRT_wchar_t *)MSVCRT_malloc(resize*sizeof(*mem))))
+        return MSVCRT_EOF;
+    }
+  
+    retval = MSVCRT_fwrite(mem, sizeof(*mem), written, file);
     if (mem != buf)
       MSVCRT_free (mem);
-    if (!(mem = (MSVCRT_wchar_t *)MSVCRT_malloc(resize*sizeof(*mem))))
-      return MSVCRT_EOF;
   }
-  retval = MSVCRT_fwrite(mem, sizeof(*mem), written, file);
-  if (mem != buf)
-    MSVCRT_free (mem);
   return retval;
 }
 
diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h
index c0bebba..8215bbb 100644
--- a/dlls/msvcrt/msvcrt.h
+++ b/dlls/msvcrt/msvcrt.h
@@ -626,6 +626,8 @@ MSVCRT_FILE*   MSVCRT__fdopen(int, const char *);
 int            MSVCRT_vsnprintf(char *str, unsigned int len, const char *format, va_list valist);
 int            MSVCRT_vsnwprintf(MSVCRT_wchar_t *str, unsigned int len,
                                  const MSVCRT_wchar_t *format, va_list valist );
+int            MSVCRT_vsnwprintf_internal( char *str, unsigned int len,
+                                 const MSVCRT_wchar_t *format, va_list valist );
 int            MSVCRT_raise(int sig);
 
 #ifndef __WINE_MSVCRT_TEST
diff --git a/dlls/msvcrt/tests/file.c b/dlls/msvcrt/tests/file.c
index d7d7676..6126b8f 100644
--- a/dlls/msvcrt/tests/file.c
+++ b/dlls/msvcrt/tests/file.c
@@ -57,6 +57,7 @@ static void test_fdopen( void )
 static void test_fileops( void )
 {
     static const char outbuffer[] = "0,1,2,3,4,5,6,7,8,9";
+    static const WCHAR outbufferW[] = {'A','B','C', '\0' };
     char buffer[256];
     WCHAR wbuffer[256];
     int fd;
@@ -130,6 +131,30 @@ static void test_fileops( void )
     ok(feof(file), "feof after fread failed\n");
     fclose (file);
 
+    /* Write Unicode to binary file - comes out as unicode */
+    file = fopen("fdopen.tst", "wb");
+    ok( file != NULL, "fopen failed\n");
+    fwprintf(file, outbufferW);
+    fclose (file);
+    file = fopen("fdopen.tst", "rb");
+    ok( file != NULL, "fopen failed\n");
+    memset(wbuffer, 0x00, sizeof(wbuffer));
+    ok (i = (fread (wbuffer, 1, sizeof (wbuffer), file) == 3 * sizeof(WCHAR)), "read wrong byte count got %i\n", c);
+    ok(lstrcmpW(wbuffer,outbufferW)==0, "Bytes read do not match bytes written (read should be Unicode)");
+    fclose (file);
+
+    /* Write Unicode to text file - comes out as ansi (Multibyte) */
+    file = fopen("fdopen.tst", "wt");
+    ok( file != NULL, "fopen failed\n");
+    fwprintf(file, outbufferW);
+    fclose (file);
+    file = fopen("fdopen.tst", "rb");
+    ok( file != NULL, "fopen failed\n");
+    memset(buffer, 0x00, sizeof(buffer));
+    ok (i = (fread (buffer, 1, sizeof (buffer), file) == 3), "read wrong byte count got %i\n", c);
+    ok(lstrcmp(buffer,"ABC")==0, "Bytes read do not match bytes written (Read should be ansi)\n");
+    fclose (file);
+
     unlink ("fdopen.tst");
 }
 
diff --git a/dlls/msvcrt/wcs.c b/dlls/msvcrt/wcs.c
index 32668a3..41c0683 100644
--- a/dlls/msvcrt/wcs.c
+++ b/dlls/msvcrt/wcs.c
@@ -800,6 +800,21 @@ int CDECL MSVCRT_vsnwprintf( MSVCRT_wchar_t *str, unsigned int len,
     return pf_vsnprintf( &out, format, valist );
 }
 
+/* Internal function, equivalent to MSVCRT_vsnwprintf but multibyte
+   rather than unicode output                                      */
+int CDECL MSVCRT_vsnwprintf_internal( char *str, unsigned int len,
+                             const MSVCRT_wchar_t *format, va_list valist )
+{
+    pf_output out;
+
+    out.unicode = FALSE;
+    out.buf.A = str;
+    out.used = 0;
+    out.len = len;
+
+    return pf_vsnprintf( &out, format, valist );
+}
+
 /*********************************************************************
  *		_snwprintf (MSVCRT.@)
  */
-- 
1.5.0

