Alexandre Julliard : kernelbase: Use RtlNormalizeString() directly in FoldStringW().

Alexandre Julliard julliard at winehq.org
Mon Feb 3 15:06:05 CST 2020


Module: wine
Branch: master
Commit: f0a82c3a2aa324d410d0d706aad80da430a0cb21
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=f0a82c3a2aa324d410d0d706aad80da430a0cb21

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Feb  3 16:31:08 2020 +0100

kernelbase: Use RtlNormalizeString() directly in FoldStringW().

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernelbase/locale.c | 163 +++++++++++++++++++++++++++++------------------
 1 file changed, 102 insertions(+), 61 deletions(-)

diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c
index 9953bf7e1a..c697da16eb 100644
--- a/dlls/kernelbase/locale.c
+++ b/dlls/kernelbase/locale.c
@@ -836,9 +836,10 @@ static const WCHAR *get_ligature( WCHAR wc )
 }
 
 
-static int expand_ligatures( const WCHAR *src, int srclen, WCHAR *dst, int dstlen )
+static NTSTATUS expand_ligatures( const WCHAR *src, int srclen, WCHAR *dst, int *dstlen )
 {
     int i, len, pos = 0;
+    NTSTATUS ret = STATUS_SUCCESS;
     const WCHAR *expand;
 
     for (i = 0; i < srclen; i++)
@@ -850,30 +851,93 @@ static int expand_ligatures( const WCHAR *src, int srclen, WCHAR *dst, int dstle
         }
         else len = lstrlenW( expand );
 
-        if (dstlen)
+        if (*dstlen && ret == STATUS_SUCCESS)
         {
-            if (pos + len > dstlen) break;
-            memcpy( dst + pos, expand, len * sizeof(WCHAR) );
+            if (pos + len <= *dstlen) memcpy( dst + pos, expand, len * sizeof(WCHAR) );
+            else ret = STATUS_BUFFER_TOO_SMALL;
         }
         pos += len;
     }
-    return pos;
+    *dstlen = pos;
+    return ret;
 }
 
 
-static int fold_digits( const WCHAR *src, int srclen, WCHAR *dst, int dstlen )
+static NTSTATUS fold_digits( const WCHAR *src, int srclen, WCHAR *dst, int *dstlen )
 {
     extern const WCHAR wine_digitmap[] DECLSPEC_HIDDEN;
-    int i;
+    int i, len = *dstlen;
 
-    if (!dstlen) return srclen;
-    if (srclen > dstlen) return 0;
+    *dstlen = srclen;
+    if (!len) return STATUS_SUCCESS;
+    if (srclen > len) return STATUS_BUFFER_TOO_SMALL;
     for (i = 0; i < srclen; i++)
     {
         WCHAR digit = get_table_entry( wine_digitmap, src[i] );
         dst[i] = digit ? digit : src[i];
     }
-    return srclen;
+    return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS fold_string( DWORD flags, const WCHAR *src, int srclen, WCHAR *dst, int *dstlen )
+{
+    NTSTATUS ret;
+    WCHAR *tmp;
+
+    switch (flags)
+    {
+    case MAP_PRECOMPOSED:
+        return RtlNormalizeString( NormalizationC, src, srclen, dst, dstlen );
+    case MAP_FOLDCZONE:
+    case MAP_PRECOMPOSED | MAP_FOLDCZONE:
+        return RtlNormalizeString( NormalizationKC, src, srclen, dst, dstlen );
+    case MAP_COMPOSITE:
+        return RtlNormalizeString( NormalizationD, src, srclen, dst, dstlen );
+    case MAP_COMPOSITE | MAP_FOLDCZONE:
+        return RtlNormalizeString( NormalizationKD, src, srclen, dst, dstlen );
+    case MAP_FOLDDIGITS:
+        return fold_digits( src, srclen, dst, dstlen );
+    case MAP_EXPAND_LIGATURES:
+    case MAP_EXPAND_LIGATURES | MAP_FOLDCZONE:
+        return expand_ligatures( src, srclen, dst, dstlen );
+    case MAP_FOLDDIGITS | MAP_PRECOMPOSED:
+        if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0, srclen * sizeof(WCHAR) )))
+            return STATUS_NO_MEMORY;
+        fold_digits( src, srclen, tmp, &srclen );
+        ret = RtlNormalizeString( NormalizationC, tmp, srclen, dst, dstlen );
+        break;
+    case MAP_FOLDDIGITS | MAP_FOLDCZONE:
+    case MAP_FOLDDIGITS | MAP_PRECOMPOSED | MAP_FOLDCZONE:
+        if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0, srclen * sizeof(WCHAR) )))
+            return STATUS_NO_MEMORY;
+        fold_digits( src, srclen, tmp, &srclen );
+        ret = RtlNormalizeString( NormalizationKC, tmp, srclen, dst, dstlen );
+        break;
+    case MAP_FOLDDIGITS | MAP_COMPOSITE:
+        if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0, srclen * sizeof(WCHAR) )))
+            return STATUS_NO_MEMORY;
+        fold_digits( src, srclen, tmp, &srclen );
+        ret = RtlNormalizeString( NormalizationD, tmp, srclen, dst, dstlen );
+        break;
+    case MAP_FOLDDIGITS | MAP_COMPOSITE | MAP_FOLDCZONE:
+        if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0, srclen * sizeof(WCHAR) )))
+            return STATUS_NO_MEMORY;
+        fold_digits( src, srclen, tmp, &srclen );
+        ret = RtlNormalizeString( NormalizationKD, tmp, srclen, dst, dstlen );
+        break;
+    case MAP_EXPAND_LIGATURES | MAP_FOLDDIGITS:
+    case MAP_EXPAND_LIGATURES | MAP_FOLDDIGITS | MAP_FOLDCZONE:
+        if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0, srclen * sizeof(WCHAR) )))
+            return STATUS_NO_MEMORY;
+        fold_digits( src, srclen, tmp, &srclen );
+        ret = expand_ligatures( tmp, srclen, dst, dstlen );
+        break;
+    default:
+        return STATUS_INVALID_PARAMETER_1;
+    }
+    RtlFreeHeap( GetProcessHeap(), 0, tmp );
+    return ret;
 }
 
 
@@ -3280,8 +3344,9 @@ INT WINAPI DECLSPEC_HOTPATCH FindStringOrdinal( DWORD flag, const WCHAR *src, IN
  */
 INT WINAPI DECLSPEC_HOTPATCH FoldStringW( DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen )
 {
-    WCHAR *tmp;
-    int ret;
+    NTSTATUS status;
+    WCHAR *buf = dst;
+    int len = dstlen;
 
     if (!src || !srclen || dstlen < 0 || (dstlen && !dst) || src == dst)
     {
@@ -3290,60 +3355,36 @@ INT WINAPI DECLSPEC_HOTPATCH FoldStringW( DWORD flags, LPCWSTR src, INT srclen,
     }
     if (srclen == -1) srclen = lstrlenW(src) + 1;
 
-    switch (flags)
+    if (!dstlen && (flags & (MAP_PRECOMPOSED | MAP_FOLDCZONE | MAP_COMPOSITE)))
     {
-    case MAP_PRECOMPOSED:
-        return NormalizeString( NormalizationC, src, srclen, dst, dstlen );
-    case MAP_FOLDCZONE:
-    case MAP_PRECOMPOSED | MAP_FOLDCZONE:
-        return NormalizeString( NormalizationKC, src, srclen, dst, dstlen );
-    case MAP_COMPOSITE:
-        return NormalizeString( NormalizationD, src, srclen, dst, dstlen );
-    case MAP_COMPOSITE | MAP_FOLDCZONE:
-        return NormalizeString( NormalizationKD, src, srclen, dst, dstlen );
-    case MAP_FOLDDIGITS:
-        return fold_digits( src, srclen, dst, dstlen );
-    case MAP_EXPAND_LIGATURES:
-    case MAP_EXPAND_LIGATURES | MAP_FOLDCZONE:
-        return expand_ligatures( src, srclen, dst, dstlen );
-    case MAP_FOLDDIGITS | MAP_PRECOMPOSED:
-        if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0, srclen * sizeof(WCHAR) ))) break;
-        if (!(ret = fold_digits( src, srclen, tmp, srclen ))) break;
-        ret = NormalizeString( NormalizationC, tmp, srclen, dst, dstlen );
-        break;
-    case MAP_FOLDDIGITS | MAP_FOLDCZONE:
-    case MAP_FOLDDIGITS | MAP_PRECOMPOSED | MAP_FOLDCZONE:
-        if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0, srclen * sizeof(WCHAR) ))) break;
-        if (!(ret = fold_digits( src, srclen, tmp, srclen ))) break;
-        ret = NormalizeString( NormalizationKC, tmp, srclen, dst, dstlen );
-        break;
-    case MAP_FOLDDIGITS | MAP_COMPOSITE:
-        if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0, srclen * sizeof(WCHAR) ))) break;
-        if (!(ret = fold_digits( src, srclen, tmp, srclen ))) break;
-        ret = NormalizeString( NormalizationD, tmp, srclen, dst, dstlen );
-        break;
-    case MAP_FOLDDIGITS | MAP_COMPOSITE | MAP_FOLDCZONE:
-        if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0, srclen * sizeof(WCHAR) ))) break;
-        if (!(ret = fold_digits( src, srclen, tmp, srclen ))) break;
-        ret = NormalizeString( NormalizationKD, tmp, srclen, dst, dstlen );
-        break;
-    case MAP_EXPAND_LIGATURES | MAP_FOLDDIGITS:
-    case MAP_EXPAND_LIGATURES | MAP_FOLDDIGITS | MAP_FOLDCZONE:
-        if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0, srclen * sizeof(WCHAR) ))) break;
-        if (!(ret = fold_digits( src, srclen, tmp, srclen ))) break;
-        ret = expand_ligatures( tmp, srclen, dst, dstlen );
-        break;
-    default:
-        SetLastError( ERROR_INVALID_FLAGS );
-        return 0;
+        len = srclen * 4;
+        if (!(buf = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
+        {
+            SetLastError( ERROR_OUTOFMEMORY );
+            return 0;
+        }
     }
-    if (!tmp)
+
+    for (;;)
     {
-        SetLastError( ERROR_OUTOFMEMORY );
+        status = fold_string( flags, src, srclen, buf, &len );
+        if (buf != dst) RtlFreeHeap( GetProcessHeap(), 0, buf );
+        if (status != STATUS_BUFFER_TOO_SMALL) break;
+        if (!(buf = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
+        {
+            SetLastError( ERROR_OUTOFMEMORY );
+            return 0;
+        }
+    }
+    if (status == STATUS_INVALID_PARAMETER_1)
+    {
+        SetLastError( ERROR_INVALID_FLAGS );
         return 0;
     }
-    RtlFreeHeap( GetProcessHeap(), 0, tmp );
-    return ret;
+    if (!set_ntstatus( status )) return 0;
+
+    if (dstlen && dstlen < len) SetLastError( ERROR_INSUFFICIENT_BUFFER );
+    return len;
 }
 
 




More information about the wine-cvs mailing list