From 212e30e919dcc77286cc149b963cabf6d719ef21 Mon Sep 17 00:00:00 2001 From: Axel Holzinger Date: Wed, 15 May 2024 10:22:47 +0200 Subject: [PATCH] Do support non-latin character sets with windows error text and do not limit in size. --- src/flexasio/FlexASIOUtil/windows_error.cpp | 34 ++++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/flexasio/FlexASIOUtil/windows_error.cpp b/src/flexasio/FlexASIOUtil/windows_error.cpp index b551734c..3ab36fe1 100644 --- a/src/flexasio/FlexASIOUtil/windows_error.cpp +++ b/src/flexasio/FlexASIOUtil/windows_error.cpp @@ -1,21 +1,39 @@ #include "windows_error.h" -#include +#include +#include + +static void rtrim(std::string& s) +{ + size_t end = s.find_last_of(" \n\r\t\f\v"); + if (end != std::string::npos && end > 0) + s.resize(end - 1U); +} namespace flexasio { std::string GetWindowsErrorString(DWORD error) { - std::string message(4096, 0); - auto messageSize = ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, 0, message.data(), DWORD(message.size()), NULL); - if (messageSize <= 0 || messageSize >= message.size()) { - message = "failed to format error message - result " + std::to_string(messageSize) + ", error " + std::to_string(GetLastError()) + ")"; + LPWSTR buffer = nullptr; + std::string message; + const auto dwSize = ::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, error, 0, (LPWSTR) &buffer, 0, nullptr); + if (dwSize == 0) { + message = "failed to format error message - result, error " + std::to_string(GetLastError()); } else { - for (; messageSize > 0 && isspace(static_cast(message[messageSize - 1])); --messageSize); - message.resize(messageSize); + // FormatMessage results in a max of 128K buffer + const auto iSize = ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, buffer, int(dwSize), nullptr, 0, nullptr, nullptr); + if (iSize <= 0) + message = "failed to convert error message to determine size - result, error " + std::to_string(GetLastError()); + else { + message.resize(size_t(iSize + 1), '\0'); // add space for the trailing 0 + if (::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, buffer, iSize, message.data(), int(message.size()), nullptr, nullptr) != iSize) + message = "failed to convert error message - result, error " + std::to_string(GetLastError()); + else + ::rtrim(message); + } + ::LocalFree(buffer); } return "Windows error code " + std::to_string(error) + " \"" + message + "\""; } - } \ No newline at end of file