Alexandre Julliard : ntdll: Implement RtlIsNormalizedString().

Alexandre Julliard julliard at winehq.org
Fri Feb 21 15:27:05 CST 2020


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Feb 20 13:05:55 2020 +0100

ntdll: Implement RtlIsNormalizedString().

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

---

 dlls/kernel32/tests/locale.c |  7 +++--
 dlls/ntdll/locale.c          | 64 ++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 65 insertions(+), 6 deletions(-)

diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c
index 7684002992..4d16600251 100644
--- a/dlls/kernel32/tests/locale.c
+++ b/dlls/kernel32/tests/locale.c
@@ -6105,16 +6105,15 @@ static void test_NormalizeString(void)
                     wine_dbgstr_w(dst), wine_dbgstr_w(ptest->expected[i]) );
                 ret = FALSE;
                 status = pRtlIsNormalizedString( norm_forms[i], ptest->str, -1, &ret );
-                todo_wine ok( !status, "%s:%d: failed %x\n", wine_dbgstr_w(ptest->str), i, status );
+                ok( !status, "%s:%d: failed %x\n", wine_dbgstr_w(ptest->str), i, status );
                 if (!wcscmp( ptest->str, dst ))
-                    todo_wine
                     ok( ret, "%s:%d: not normalized\n", wine_dbgstr_w(ptest->str), i );
                 else
                     ok( !ret, "%s:%d: normalized (dst %s)\n", wine_dbgstr_w(ptest->str), i, wine_dbgstr_w(dst) );
                 ret = FALSE;
                 status = pRtlIsNormalizedString( norm_forms[i], dst, dstlen, &ret );
-                todo_wine ok( !status, "%s:%d: failed %x\n", wine_dbgstr_w(ptest->str), i, status );
-                todo_wine ok( ret, "%s:%d: not normalized\n", wine_dbgstr_w(ptest->str), i );
+                ok( !status, "%s:%d: failed %x\n", wine_dbgstr_w(ptest->str), i, status );
+                ok( ret, "%s:%d: not normalized\n", wine_dbgstr_w(ptest->str), i );
             }
         }
         ptest++;
diff --git a/dlls/ntdll/locale.c b/dlls/ntdll/locale.c
index 5d53d91ddd..7ec8a16074 100644
--- a/dlls/ntdll/locale.c
+++ b/dlls/ntdll/locale.c
@@ -1896,8 +1896,68 @@ NTSTATUS WINAPI RtlUnicodeToUTF8N( char *dst, DWORD dstlen, DWORD *reslen, const
  */
 NTSTATUS WINAPI RtlIsNormalizedString( ULONG form, const WCHAR *str, INT len, BOOLEAN *res )
 {
-    FIXME( "%x %p %d\n", form, str, len );
-    return STATUS_NOT_IMPLEMENTED;
+    const struct norm_table *info;
+    NTSTATUS status;
+    BYTE props, class, last_class = 0;
+    unsigned int ch;
+    int i, r, result = 1;
+
+    if ((status = load_norm_table( form, &info ))) return status;
+
+    if (len == -1) len = strlenW( str );
+
+    for (i = 0; i < len && result; i += r)
+    {
+        if (!(r = get_utf16( str + i, len - i, &ch ))) return STATUS_NO_UNICODE_TRANSLATION;
+        if (info->comp_size)
+        {
+            if ((ch >= HANGUL_VBASE && ch < HANGUL_VBASE + HANGUL_VCOUNT) ||
+                (ch >= HANGUL_TBASE && ch < HANGUL_TBASE + HANGUL_TCOUNT))
+            {
+                result = -1;  /* QC=Maybe */
+                continue;
+            }
+        }
+        else if (ch >= HANGUL_SBASE && ch < HANGUL_SBASE + HANGUL_SCOUNT)
+        {
+            result = 0;  /* QC=No */
+            break;
+        }
+        props = get_char_props( info, ch );
+        class = props & 0x3f;
+        if (class == 0x3f)
+        {
+            last_class = 0;
+            if (props == 0xbf) result = 0;  /* QC=No */
+            else if (props == 0xff)
+            {
+                /* ignore other chars in Hangul range */
+                if (ch >= HANGUL_LBASE && ch < HANGUL_LBASE + 0x100) continue;
+                if (ch >= HANGUL_SBASE && ch < HANGUL_SBASE + 0x2c00) continue;
+                return STATUS_NO_UNICODE_TRANSLATION;
+            }
+        }
+        else if (props & 0x80)
+        {
+            if ((props & 0xc0) == 0xc0) result = -1;  /* QC=Maybe */
+            if (class && class < last_class) result = 0;  /* QC=No */
+            last_class = class;
+        }
+        else last_class = 0;
+    }
+
+    if (result == -1)
+    {
+        int dstlen = len * 4;
+        NTSTATUS status;
+        WCHAR *buffer = RtlAllocateHeap( GetProcessHeap(), 0, dstlen * sizeof(WCHAR) );
+        if (!buffer) return STATUS_NO_MEMORY;
+        status = RtlNormalizeString( form, str, len, buffer, &dstlen );
+        result = !status && (dstlen == len) && !strncmpW( buffer, str, len );
+        RtlFreeHeap( GetProcessHeap(), 0, buffer );
+    }
+    *res = result;
+    return STATUS_SUCCESS;
 }
 
 




More information about the wine-cvs mailing list