From 96197da77ee13b2af683caf2c84176f7bf7c3d41 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Thu, 25 Mar 2021 10:33:24 +0100 Subject: [PATCH] Introduce NormalizeString<>() Signed-off-by: Simon Rozman --- include/WinStd/Win.h | 94 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/include/WinStd/Win.h b/include/WinStd/Win.h index 59dc8daa..5d8a4ed5 100644 --- a/include/WinStd/Win.h +++ b/include/WinStd/Win.h @@ -292,6 +292,22 @@ template inline _Success_(return != 0) int SecureMultiByteToWideChar( /// template inline _Success_(return != 0) int SecureMultiByteToWideChar(_In_ UINT CodePage, _In_ DWORD dwFlags, _In_ const std::basic_string &sMultiByteStr, _Out_ std::basic_string &sWideCharStr) noexcept; +/// +/// Normalizes characters of a text string according to Unicode 4.0 TR#15. +/// +/// \sa [NormalizeString function](https://docs.microsoft.com/en-us/windows/win32/api/winnls/nf-winnls-normalizestring) +/// +template +inline _Success_(return > 0) int NormalizeString(_In_ NORM_FORM NormForm, _In_ LPCWSTR lpSrcString, _In_ int cwSrcLength, _Out_ std::basic_string &sDstString) noexcept; + +/// +/// Normalizes characters of a text string according to Unicode 4.0 TR#15. +/// +/// \sa [NormalizeString function](https://docs.microsoft.com/en-us/windows/win32/api/winnls/nf-winnls-normalizestring) +/// +template +inline _Success_(return > 0) int NormalizeString(_In_ NORM_FORM NormForm, _In_ const std::basic_string &sSrcString, _Out_ std::basic_string &sDstString) noexcept; + /// @copydoc LoadStringW template inline _Success_(return != 0) int WINAPI LoadStringA(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_ std::basic_string &sBuffer) noexcept; @@ -1827,6 +1843,84 @@ inline _Success_(return != 0) int SecureMultiByteToWideChar(_In_ UINT CodePage, } +template +inline _Success_(return > 0) int NormalizeString(_In_ NORM_FORM NormForm, _In_ LPCWSTR lpSrcString, _In_ int cwSrcLength, _Out_ std::basic_string &sDstString) noexcept +{ + WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)]; + + // Try to convert to stack buffer first. + int cch = ::NormalizeString(NormForm, lpSrcString, cwSrcLength, szStackBuffer, _countof(szStackBuffer)); + if (cch > 0) { + // Copy from stack. + sDstString.assign(szStackBuffer, cwSrcLength != -1 ? wcsnlen(szStackBuffer, cch) : (size_t)cch - 1); + } else { + switch (::GetLastError()) { + case ERROR_INSUFFICIENT_BUFFER: + for (int i = 10; i--;) { + // Allocate buffer. Then convert again. + cch = -cch; + std::unique_ptr szBuffer(new WCHAR[cch]); + cch = ::NormalizeString(NormForm, lpSrcString, cwSrcLength, szBuffer.get(), cch); + if (cch > 0) { + sDstString.assign(szBuffer.get(), cwSrcLength != -1 ? wcsnlen(szStackBuffer, cch) : (size_t)cch - 1); + break; + } + if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + sDstString.clear(); + break; + } + } + break; + + case ERROR_SUCCESS: + sDstString.clear(); + break; + } + } + + return cch; +} + + +template +inline _Success_(return > 0) int NormalizeString(_In_ NORM_FORM NormForm, _In_ const std::basic_string &sSrcString, _Out_ std::basic_string &sDstString) noexcept +{ + WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)]; + + // Try to convert to stack buffer first. + int cch = ::NormalizeString(NormForm, sSrcString.c_str(), (int)sSrcString.length(), szStackBuffer, _countof(szStackBuffer)); + if (cch > 0) { + // Copy from stack. + sDstString.assign(szStackBuffer, cch); + } else { + switch (::GetLastError()) { + case ERROR_INSUFFICIENT_BUFFER: + for (int i = 10; i--;) { + // Allocate buffer. Then convert again. + cch = -cch; + std::unique_ptr szBuffer(new WCHAR[cch]); + cch = ::NormalizeString(NormForm, sSrcString.c_str(), (int)sSrcString.length(), szBuffer.get(), cch); + if (cch > 0) { + sDstString.assign(szBuffer.get(), cch); + break; + } + if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + sDstString.clear(); + break; + } + } + break; + + case ERROR_SUCCESS: + sDstString.clear(); + break; + } + } + + return cch; +} + + template inline _Success_(return != 0) int WINAPI LoadStringA(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_ std::basic_string &sBuffer) noexcept {