Peter Beutner : msvcrt: Fix handling of 'h' prefix in swprintf.

Alexandre Julliard julliard at wine.codeweavers.com
Tue May 16 13:54:23 CDT 2006


Module: wine
Branch: refs/heads/master
Commit: bc83ae9fda6bf4a381e881523c3be3dfb3a688b2
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=bc83ae9fda6bf4a381e881523c3be3dfb3a688b2

Author: Peter Beutner <p.beutner at gmx.net>
Date:   Tue May 16 18:18:51 2006 +0200

msvcrt: Fix handling of 'h' prefix in swprintf.

- '%hs' in widechar string functions is wrongly recognized as
  a widechar string. Fix this by always checking the prefix first.
- add testcase
- remove code duplication in %c/%s handling by moving code into a function.

---

 dlls/msvcrt/tests/printf.c |    7 ++++
 dlls/msvcrt/wcs.c          |   69 ++++++++++++++++++--------------------------
 2 files changed, 34 insertions(+), 42 deletions(-)

diff --git a/dlls/msvcrt/tests/printf.c b/dlls/msvcrt/tests/printf.c
index 64b5d5a..ff0058d 100644
--- a/dlls/msvcrt/tests/printf.c
+++ b/dlls/msvcrt/tests/printf.c
@@ -469,8 +469,11 @@ static void test_swprintf( void )
     double pnumber=789456123;
     const wchar_t TwentyThreePoint15e[]= {'%','+','#','2','3','.','1','5','e',0};
     const wchar_t e008[] = {'e','+','0','0','8',0};
-    const char string[]={'s','t','r','i','n','g',0};
+    const wchar_t string_w[] = {'s','t','r','i','n','g',0};
+    const char string[] = "string";
     const wchar_t S[]={'%','S',0};
+    const wchar_t hs[] = {'%', 'h', 's', 0};
+
     swprintf(buffer,TwentyThreePoint15e,pnumber);
     todo_wine
       {
@@ -480,6 +483,8 @@ static void test_swprintf( void )
       ok(wcslen(buffer) == 11,"Problem with long long\n");
     swprintf(buffer,S,string);
       ok(wcslen(buffer) == 6,"Problem with \"%%S\" interpretation\n");
+   swprintf(buffer, hs, string);
+   ok( wcscmp(string_w,buffer) == 0, "swprintf failed with %%hs\n");
 }
 
 static void test_fwprintf( void )
diff --git a/dlls/msvcrt/wcs.c b/dlls/msvcrt/wcs.c
index 9c35c46..095bef7 100644
--- a/dlls/msvcrt/wcs.c
+++ b/dlls/msvcrt/wcs.c
@@ -357,6 +357,26 @@ static inline int pf_output_format_A( pf
     return r;
 }
 
+static int pf_handle_string_format( pf_output *out, const void* str, int len,
+                             pf_flags *flags, BOOL capital_letter)
+{
+     if(str == NULL)  /* catch NULL pointer */
+        return pf_output_format_A( out, "(null)", -1, flags);
+
+     /* prefixes take priority over %c,%s vs. %C,%S, so we handle them first */
+    if(flags->WideString || flags->IntegerLength == 'l')
+        return pf_output_format_W( out, str, len, flags);
+    if(flags->IntegerLength == 'h')
+        return pf_output_format_A( out, str, len, flags);
+
+    /* %s,%c ->  chars in ansi functions & wchars in unicode
+     * %S,%C -> wchars in ansi functions &  chars in unicode */
+    if( capital_letter == out->unicode) /* either both TRUE or both FALSE */
+        return pf_output_format_A( out, str, len, flags);
+    else
+        return pf_output_format_W( out, str, len, flags);
+}
+
 static inline BOOL pf_is_integer_format( char fmt )
 {
     static const char float_fmts[] = "diouxX";
@@ -602,50 +622,17 @@ static int pf_vsnprintf( pf_output *out,
         flags.Format = *p;
         r = 0;
 
-        /* output a unicode string */
-        if( ( flags.Format == 's' && (flags.WideString || flags.IntegerLength == 'l' )) ||
-            ( !out->unicode && flags.Format == 'S' ) ||
-            ( out->unicode && flags.Format == 's' ) )
-        {
-            LPCWSTR str = va_arg( valist, const WCHAR * );
-
-            if( str )
-                r = pf_output_format_W( out, str, -1, &flags );
-            else
-                r = pf_output_format_A( out, "(null)", -1, &flags );
-        }
-
-        /* output a ASCII string */
-        else if( ( flags.Format == 's' && flags.IntegerLength == 'h' ) ||
-            ( out->unicode && flags.Format == 'S' ) ||
-            ( !out->unicode && flags.Format == 's' ) )
-        {
-            LPCSTR str = va_arg( valist, const CHAR * );
-
-            if( str )
-                r = pf_output_format_A( out, str, -1, &flags );
-            else
-                r = pf_output_format_A( out, "(null)", -1, &flags );
-        }
-
-        /* output a single wide character */
-        else if( ( flags.Format == 'c' && flags.IntegerLength == 'w' ) ||
-            ( out->unicode && flags.Format == 'c' ) ||
-            ( !out->unicode && flags.Format == 'C' ) )
-        {
-            WCHAR ch = va_arg( valist, int );
-
-            r = pf_output_format_W( out, &ch, 1, &flags );
-        }
+        /* output a string */
+        if(  flags.Format == 's' || flags.Format == 'S' )
+            r = pf_handle_string_format( out, va_arg(valist, const void*), -1,
+                                         &flags, (flags.Format == 'S') );
 
-        /* output a single ascii character */
-        else if( ( flags.Format == 'c' && flags.IntegerLength == 'h' ) ||
-            ( out->unicode && flags.Format == 'C' ) ||
-            ( !out->unicode && flags.Format == 'c' ) )
+        /* output a single character */
+        else if( flags.Format == 'c' || flags.Format == 'C' )
         {
-            CHAR ch = va_arg( valist, int );
+            INT ch = va_arg( valist, int );
 
-            r = pf_output_format_A( out, &ch, 1, &flags );
+            r = pf_handle_string_format( out, &ch, 1, &flags, (flags.Format == 'C') );
         }
 
         /* output a pointer */




More information about the wine-cvs mailing list