ntdll: Implement RtlIsNormalizedString().

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-02-20 13:05:55 +01:00
parent 55dc4fce99
commit 3e6b15c7b5
2 changed files with 65 additions and 6 deletions

View File

@ -6105,16 +6105,15 @@ static void test_NormalizeString(void)
wine_dbgstr_w(dst), wine_dbgstr_w(ptest->expected[i]) ); wine_dbgstr_w(dst), wine_dbgstr_w(ptest->expected[i]) );
ret = FALSE; ret = FALSE;
status = pRtlIsNormalizedString( norm_forms[i], ptest->str, -1, &ret ); 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 )) if (!wcscmp( ptest->str, dst ))
todo_wine
ok( ret, "%s:%d: not normalized\n", wine_dbgstr_w(ptest->str), i ); ok( ret, "%s:%d: not normalized\n", wine_dbgstr_w(ptest->str), i );
else else
ok( !ret, "%s:%d: normalized (dst %s)\n", wine_dbgstr_w(ptest->str), i, wine_dbgstr_w(dst) ); ok( !ret, "%s:%d: normalized (dst %s)\n", wine_dbgstr_w(ptest->str), i, wine_dbgstr_w(dst) );
ret = FALSE; ret = FALSE;
status = pRtlIsNormalizedString( norm_forms[i], dst, dstlen, &ret ); status = pRtlIsNormalizedString( norm_forms[i], dst, dstlen, &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 );
todo_wine ok( ret, "%s:%d: not normalized\n", wine_dbgstr_w(ptest->str), i ); ok( ret, "%s:%d: not normalized\n", wine_dbgstr_w(ptest->str), i );
} }
} }
ptest++; ptest++;

View File

@ -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 ) NTSTATUS WINAPI RtlIsNormalizedString( ULONG form, const WCHAR *str, INT len, BOOLEAN *res )
{ {
FIXME( "%x %p %d\n", form, str, len ); const struct norm_table *info;
return STATUS_NOT_IMPLEMENTED; 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;
} }