diff --git a/include/spdlog/details/os-inl.h b/include/spdlog/details/os-inl.h index 87c8c5a0..2413aec9 100644 --- a/include/spdlog/details/os-inl.h +++ b/include/spdlog/details/os-inl.h @@ -459,6 +459,41 @@ SPDLOG_INLINE void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target) throw_spdlog_ex(fmt::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError())); } + +SPDLOG_INLINE void utf8_to_wstrbuf(string_view_t str, memory_buf_t &target) +{ + if (str.size() > static_cast((std::numeric_limits::max)())) + { + throw_spdlog_ex("UTF-8 string is too big to be converted to UTF-16"); + } + + int str_size = static_cast(str.size()); + if (str_size == 0) + { + target.resize(0); + return; + } + + int result_size = static_cast(target.capacity()); + if ((str_size + 1) * 2 < result_size) + { + result_size = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str.data(), str_size, NULL, 0); + } + + if (result_size > 0) + { + target.resize(result_size); + result_size = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str.data(), str_size, (LPWSTR)target.data(), result_size); + + if (result_size > 0) + { + target.resize(result_size); + return; + } + } + + throw_spdlog_ex(fmt::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError())); +} #endif // (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32) // return true on success diff --git a/include/spdlog/details/os.h b/include/spdlog/details/os.h index 243a4fb8..88f13dbe 100644 --- a/include/spdlog/details/os.h +++ b/include/spdlog/details/os.h @@ -85,6 +85,8 @@ SPDLOG_API bool in_terminal(FILE *file) SPDLOG_NOEXCEPT; #if (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32) SPDLOG_API void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target); + +SPDLOG_INLINE void utf8_to_wstrbuf(string_view_t str, memory_buf_t &target); #endif // Return directory name from given path or empty string diff --git a/include/spdlog/sinks/win_eventlog_sink.h b/include/spdlog/sinks/win_eventlog_sink.h index 5d028744..f154c55a 100644 --- a/include/spdlog/sinks/win_eventlog_sink.h +++ b/include/spdlog/sinks/win_eventlog_sink.h @@ -39,8 +39,6 @@ Windows Registry Editor Version 5.00 #include #include #include -#include -#include namespace spdlog { namespace sinks { @@ -226,22 +224,35 @@ protected: formatted.push_back('\0'); #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT - auto buf = std::wstring_convert>().from_bytes(formatted.data()); - LPCWSTR lp_wstr = reinterpret_cast(buf.c_str()); + try + { + memory_buf_t buf; + details::os::utf8_to_wstrbuf(string_view_t(formatted.data(), formatted.size()), buf); - succeeded = ::ReportEventW(event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), event_id_, + LPCWSTR lp_wstr = reinterpret_cast(buf.data()); + succeeded = ::ReportEventW(event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), event_id_, current_user_sid_.as_sid(), 1, 0, &lp_wstr, nullptr); + + if (!succeeded) + { + SPDLOG_THROW(win32_error("ReportEvent")); + } + } + catch (...) + { + // WCHAR string conversion can fail and if it does, we shouldn't call to report event function. + } #else LPCSTR lp_str = reinterpret_cast(formatted.data()); succeeded = ::ReportEventA(event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), event_id_, current_user_sid_.as_sid(), 1, 0, &lp_str, nullptr); -#endif if (!succeeded) { SPDLOG_THROW(win32_error("ReportEvent")); } +#endif } void flush_() override {}