From fd588a22b74b092e3f629b90a09685024d64322d Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 21 Nov 2019 10:43:46 +0100 Subject: [PATCH] kernel32: Move string normalization functions to ntdll. Signed-off-by: Alexandre Julliard --- dlls/kernel32/kernel32.spec | 4 +- dlls/kernel32/locale.c | 66 ------------------------------- dlls/kernel32/tests/locale.c | 29 ++++++++++++-- dlls/kernelbase/kernelbase.spec | 4 +- dlls/kernelbase/locale.c | 22 +++++++++++ dlls/ntdll/locale.c | 70 +++++++++++++++++++++++++++++++++ dlls/ntdll/ntdll.spec | 2 + include/winternl.h | 2 + 8 files changed, 126 insertions(+), 73 deletions(-) diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 5d543f1eb51..b4ff7a79582 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -980,7 +980,7 @@ @ stdcall -import IsDebuggerPresent() @ stub -i386 IsLSCallback # @ stub IsNLSDefinedString -@ stdcall IsNormalizedString(long wstr long) +@ stdcall -import IsNormalizedString(long wstr long) @ stdcall -import IsProcessInJob(long long ptr) @ stdcall -import IsProcessorFeaturePresent(long) @ stub -i386 IsSLCallback @@ -1105,7 +1105,7 @@ # @ stub NlsUpdateLocale # @ stub NlsUpdateSystemLocale # @ stub NlsWriteEtwEvent -@ stdcall NormalizeString(long wstr long ptr long) +@ stdcall -import NormalizeString(long wstr long ptr long) # @ stub NotifyMountMgr @ stub NotifyNLSUserCache # @ stub NotifyUILanguageChange diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c index 791234cb129..1d8371fe0ff 100644 --- a/dlls/kernel32/locale.c +++ b/dlls/kernel32/locale.c @@ -3535,72 +3535,6 @@ BOOL WINAPI EnumSystemGeoID(GEOCLASS geoclass, GEOID parent, GEO_ENUMPROC enumpr return TRUE; } -/****************************************************************************** - * NormalizeString (KERNEL32.@) - */ -INT WINAPI NormalizeString(NORM_FORM form, const WCHAR *src, INT src_len, WCHAR *dst, INT dst_len) -{ - int flags = 0, compose = 0; - unsigned int res, buf_len; - WCHAR *buf = NULL; - - TRACE("%x %s %d %p %d\n", form, debugstr_wn(src, src_len), src_len, dst, dst_len); - - if (src_len == -1) src_len = strlenW(src) + 1; - - if (form == NormalizationKC || form == NormalizationKD) flags |= WINE_DECOMPOSE_COMPAT; - if (form == NormalizationC || form == NormalizationKC) compose = 1; - if (compose || dst_len) flags |= WINE_DECOMPOSE_REORDER; - - if (!compose && dst_len) - { - res = wine_decompose_string( flags, src, src_len, dst, dst_len ); - if (!res) - { - SetLastError( ERROR_INSUFFICIENT_BUFFER ); - goto done; - } - buf = dst; - } - else - { - buf_len = src_len * 4; - do - { - WCHAR *old_buf = buf; - - buf = heap_realloc( buf, buf_len ); - if (!buf) - { - heap_free( old_buf ); - SetLastError( ERROR_OUTOFMEMORY ); - return 0; - } - res = wine_decompose_string( flags, src, src_len, buf, buf_len ); - buf_len *= 2; - } while (!res); - } - - if (compose) - { - res = wine_compose_string( buf, res ); - if (dst_len >= res) memcpy( dst, buf, res * sizeof(WCHAR) ); - } - -done: - if (buf != dst) heap_free( buf ); - return res; -} - -/****************************************************************************** - * IsNormalizedString (KERNEL32.@) - */ -BOOL WINAPI IsNormalizedString(NORM_FORM NormForm, LPCWSTR lpString, INT cwLength) -{ - FIXME("%x %p %d\n", NormForm, lpString, cwLength); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} enum { BASE = 36, diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c index 45cb11d2548..0e2c3496a96 100644 --- a/dlls/kernel32/tests/locale.c +++ b/dlls/kernel32/tests/locale.c @@ -85,6 +85,8 @@ static LANGID (WINAPI *pSetThreadUILanguage)(LANGID); static LANGID (WINAPI *pGetThreadUILanguage)(VOID); static INT (WINAPI *pNormalizeString)(NORM_FORM, LPCWSTR, INT, LPWSTR, INT); static INT (WINAPI *pFindStringOrdinal)(DWORD, LPCWSTR lpStringSource, INT, LPCWSTR, INT, BOOL); +static NTSTATUS (WINAPI *pRtlNormalizeString)(ULONG, LPCWSTR, INT, LPWSTR, INT*); +static NTSTATUS (WINAPI *pRtlIsNormalizedString)(ULONG, LPCWSTR, INT, BOOLEAN*); static void InitFunctionPointers(void) { @@ -126,6 +128,8 @@ static void InitFunctionPointers(void) mod = GetModuleHandleA("ntdll"); X(RtlUpcaseUnicodeChar); X(RtlLocaleNameToLcid); + X(RtlNormalizeString); + X(RtlIsNormalizedString); #undef X } @@ -5838,7 +5842,6 @@ static void test_NormalizeString(void) struct test_data_normal { const WCHAR *str; const WCHAR *expected[4]; - BOOL todo[4]; }; static const struct test_data_normal test_arr[] = { @@ -5869,6 +5872,7 @@ static void test_NormalizeString(void) const struct test_data_normal *ptest = test_arr; const int norm_forms[] = { NormalizationC, NormalizationD, NormalizationKC, NormalizationKD }; WCHAR dst[80]; + NTSTATUS status; int dstlen; if (!pNormalizeString) @@ -5876,6 +5880,7 @@ static void test_NormalizeString(void) win_skip("NormalizeString is not available.\n"); return; } + if (!pRtlNormalizeString) win_skip("RtlNormalizeString is not available.\n"); dstlen = pNormalizeString( NormalizationD, ptest->str, -1, dst, 1 ); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Should have failed with ERROR_INSUFFICIENT_BUFFER\n"); @@ -5899,7 +5904,6 @@ static void test_NormalizeString(void) ok(dstlen == lstrlenW( dst )+1, "%s:%d: Copied length differed: was %d, should be %d\n", wine_dbgstr_w(ptest->str), i, dstlen, lstrlenW( dst )+1); str_cmp = wcsncmp( ptest->expected[i], dst, dstlen+1 ); -todo_wine_if(ptest->todo[i]) ok( str_cmp == 0, "%s:%d: string incorrect got %s expect %s\n", wine_dbgstr_w(ptest->str), i, wine_dbgstr_w(dst), wine_dbgstr_w(ptest->expected[i]) ); } @@ -5912,10 +5916,29 @@ todo_wine_if(ptest->todo[i]) ok(dstlen == lstrlenW( dst ), "%s:%d: Copied length differed: was %d, should be %d\n", wine_dbgstr_w(ptest->str), i, dstlen, lstrlenW( dst )); str_cmp = wcsncmp( ptest->expected[i], dst, dstlen ); -todo_wine_if(ptest->todo[i]) ok( str_cmp == 0, "%s:%d: string incorrect got %s expect %s\n", wine_dbgstr_w(ptest->str), i, wine_dbgstr_w(dst), wine_dbgstr_w(ptest->expected[i]) ); } + + if (pRtlNormalizeString) + { + BOOLEAN ret = FALSE; + + dstlen = 0; + status = pRtlNormalizeString( norm_forms[i], ptest->str, lstrlenW(ptest->str), NULL, &dstlen ); + ok( !status, "%s:%d: failed %x\n", wine_dbgstr_w(ptest->str), i, status ); + memset(dst, 0, sizeof(dst)); + status = pRtlNormalizeString( norm_forms[i], ptest->str, lstrlenW(ptest->str), dst, &dstlen ); + ok( !status, "%s:%d: failed %x\n", wine_dbgstr_w(ptest->str), i, status ); + ok(dstlen == lstrlenW( dst ), "%s:%d: Copied length differed: was %d, should be %d\n", + wine_dbgstr_w(ptest->str), i, dstlen, lstrlenW( dst )); + str_cmp = wcsncmp( ptest->expected[i], dst, dstlen ); + ok( str_cmp == 0, "%s:%d: string incorrect got %s expect %s\n", wine_dbgstr_w(ptest->str), i, + wine_dbgstr_w(dst), wine_dbgstr_w(ptest->expected[i]) ); + 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 ); + } } ptest++; } diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index ab0bc557000..639f4e10b22 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -862,7 +862,7 @@ # @ stub IsGlobalizationUserSettingsKeyRedirected @ stdcall IsInternetESCEnabled() @ stub IsNLSDefinedString -@ stdcall IsNormalizedString(long wstr long) kernel32.IsNormalizedString +@ stdcall IsNormalizedString(long wstr long) # @ stub IsProcessCritical @ stdcall IsProcessInJob(long long ptr) @ stdcall IsProcessorFeaturePresent(long) @@ -972,7 +972,7 @@ @ stub NlsUpdateSystemLocale @ stub NlsValidateLocale @ stub NlsWriteEtwEvent -@ stdcall NormalizeString(long wstr long ptr long) kernel32.NormalizeString +@ stdcall NormalizeString(long wstr long ptr long) @ stub NotifyMountMgr @ stub NotifyRedirectedStringChange @ stdcall ObjectCloseAuditAlarmW(wstr ptr long) diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c index 073d7599367..6a83ee965ad 100644 --- a/dlls/kernelbase/locale.c +++ b/dlls/kernelbase/locale.c @@ -1083,6 +1083,28 @@ LANGID WINAPI DECLSPEC_HOTPATCH GetUserDefaultUILanguage(void) } +/****************************************************************************** + * IsNormalizedString (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH IsNormalizedString( NORM_FORM form, const WCHAR *str, INT len ) +{ + BOOLEAN res; + if (!set_ntstatus( RtlIsNormalizedString( form, str, len, &res ))) res = FALSE; + return res; +} + + +/****************************************************************************** + * NormalizeString (kernelbase.@) + */ +INT WINAPI DECLSPEC_HOTPATCH NormalizeString(NORM_FORM form, const WCHAR *src, INT src_len, + WCHAR *dst, INT dst_len) +{ + set_ntstatus( RtlNormalizeString( form, src, src_len, dst, &dst_len )); + return dst_len; +} + + /****************************************************************************** * ResolveLocaleName (kernelbase.@) */ diff --git a/dlls/ntdll/locale.c b/dlls/ntdll/locale.c index 27e38d6e409..94a945c17c6 100644 --- a/dlls/ntdll/locale.c +++ b/dlls/ntdll/locale.c @@ -538,3 +538,73 @@ found: TRACE( "%s -> %04x\n", debugstr_w(name), *lcid ); return STATUS_SUCCESS; } + + +/****************************************************************************** + * RtlIsNormalizedString (NTDLL.@) + */ +NTSTATUS WINAPI RtlIsNormalizedString( ULONG form, const WCHAR *str, INT len, BOOLEAN *res ) +{ + FIXME( "%x %p %d\n", form, str, len ); + return STATUS_NOT_IMPLEMENTED; +} + + +/****************************************************************************** + * RtlNormalizeString (NTDLL.@) + */ +NTSTATUS WINAPI RtlNormalizeString( ULONG form, const WCHAR *src, INT src_len, WCHAR *dst, INT *dst_len ) +{ + int flags = 0, compose = 0; + unsigned int res, buf_len; + WCHAR *buf = NULL; + NTSTATUS status = STATUS_SUCCESS; + + TRACE( "%x %s %d %p %d\n", form, debugstr_wn(src, src_len), src_len, dst, *dst_len ); + + if (src_len == -1) src_len = strlenW(src) + 1; + + if (form == NormalizationKC || form == NormalizationKD) flags |= WINE_DECOMPOSE_COMPAT; + if (form == NormalizationC || form == NormalizationKC) compose = 1; + if (compose || *dst_len) flags |= WINE_DECOMPOSE_REORDER; + + if (!compose && *dst_len) + { + res = wine_decompose_string( flags, src, src_len, dst, *dst_len ); + if (!res) + { + status = STATUS_BUFFER_TOO_SMALL; + goto done; + } + buf = dst; + } + else + { + buf_len = src_len * 4; + do + { + WCHAR *old_buf = buf; + + if (!buf) buf = RtlAllocateHeap( GetProcessHeap(), 0, buf_len ); + else buf = RtlReAllocateHeap( GetProcessHeap(), 0, buf, buf_len ); + if (!buf) + { + RtlFreeHeap( GetProcessHeap(), 0, old_buf ); + return STATUS_NO_MEMORY; + } + res = wine_decompose_string( flags, src, src_len, buf, buf_len ); + buf_len *= 2; + } while (!res); + } + + if (compose) + { + res = wine_compose_string( buf, res ); + if (*dst_len >= res) memcpy( dst, buf, res * sizeof(WCHAR) ); + } + +done: + if (buf != dst) RtlFreeHeap( GetProcessHeap(), 0, buf ); + *dst_len = res; + return status; +} diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 1cef46953ed..fa2c7a32cd3 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -788,6 +788,7 @@ @ stub RtlIsGenericTableEmpty # @ stub RtlIsGenericTableEmptyAvl @ stdcall RtlIsNameLegalDOS8Dot3(ptr ptr ptr) +@ stdcall RtlIsNormalizedString(long wstr long ptr) @ stdcall RtlIsProcessorFeaturePresent(long) # @ stub RtlIsRangeAvailable @ stdcall RtlIsTextUnicode(ptr long ptr) @@ -830,6 +831,7 @@ # @ stub RtlNewSecurityObjectEx # @ stub RtlNewSecurityObjectWithMultipleInheritance @ stdcall RtlNormalizeProcessParams(ptr) +@ stdcall RtlNormalizeString(long wstr long ptr ptr) # @ stub RtlNtPathNameToDosPathName @ stdcall RtlNtStatusToDosError(long) @ stdcall RtlNtStatusToDosErrorNoTeb(long) diff --git a/include/winternl.h b/include/winternl.h index ba0de0e6dee..8b895a93928 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2769,6 +2769,7 @@ NTSYSAPI BOOL WINAPI RtlIsCriticalSectionLocked(RTL_CRITICAL_SECTION *); NTSYSAPI BOOL WINAPI RtlIsCriticalSectionLockedByThread(RTL_CRITICAL_SECTION *); NTSYSAPI ULONG WINAPI RtlIsDosDeviceName_U(PCWSTR); NTSYSAPI BOOLEAN WINAPI RtlIsNameLegalDOS8Dot3(const UNICODE_STRING*,POEM_STRING,PBOOLEAN); +NTSYSAPI NTSTATUS WINAPI RtlIsNormalizedString(ULONG,const WCHAR*,INT,BOOLEAN*); NTSYSAPI BOOLEAN WINAPI RtlIsProcessorFeaturePresent(UINT); NTSYSAPI BOOLEAN WINAPI RtlIsTextUnicode(LPCVOID,INT,INT *); NTSYSAPI BOOLEAN WINAPI RtlIsValidHandle(const RTL_HANDLE_TABLE *, const RTL_HANDLE *); @@ -2787,6 +2788,7 @@ NTSYSAPI NTSTATUS WINAPI RtlMultiByteToUnicodeN(LPWSTR,DWORD,LPDWORD,LPCSTR,DWO NTSYSAPI NTSTATUS WINAPI RtlMultiByteToUnicodeSize(DWORD*,LPCSTR,UINT); NTSYSAPI NTSTATUS WINAPI RtlNewSecurityObject(PSECURITY_DESCRIPTOR,PSECURITY_DESCRIPTOR,PSECURITY_DESCRIPTOR*,BOOLEAN,HANDLE,PGENERIC_MAPPING); NTSYSAPI PRTL_USER_PROCESS_PARAMETERS WINAPI RtlNormalizeProcessParams(RTL_USER_PROCESS_PARAMETERS*); +NTSYSAPI NTSTATUS WINAPI RtlNormalizeString(ULONG,const WCHAR*,INT,WCHAR*,INT*); NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS); NTSYSAPI ULONG WINAPI RtlNtStatusToDosErrorNoTeb(NTSTATUS); NTSYSAPI ULONG WINAPI RtlNumberOfSetBits(PCRTL_BITMAP);