Module: wine Branch: master Commit: 3e6b15c7b5234002b0af2720df58cdf084cba40c URL: https://source.winehq.org/git/wine.git/?a=commit;h=3e6b15c7b5234002b0af2720d...
Author: Alexandre Julliard julliard@winehq.org Date: Thu Feb 20 13:05:55 2020 +0100
ntdll: Implement RtlIsNormalizedString().
Signed-off-by: Alexandre Julliard julliard@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; }