From 5e33a7e58b8d30287b111ee74eccb894498639ac Mon Sep 17 00:00:00 2001 From: Amir Alperin Date: Sun, 13 Dec 2020 10:11:00 +0200 Subject: [PATCH 1/5] fix compilation errors --- include/spdlog/sinks/win_eventlog_sink.h | 51 +++++++++++++++++------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/include/spdlog/sinks/win_eventlog_sink.h b/include/spdlog/sinks/win_eventlog_sink.h index 384fa9eb6..7b50b7b5c 100644 --- a/include/spdlog/sinks/win_eventlog_sink.h +++ b/include/spdlog/sinks/win_eventlog_sink.h @@ -55,20 +55,34 @@ struct win32_error : public spdlog_ex { std::string system_message; + auto fFormatResult = [&system_message](bool format_message_succeeded, void* format_message_result) + { + if (format_message_succeeded && format_message_result) + { + system_message = fmt::format(" ({})", format_message_result); + } + + if (format_message_result) + { + LocalFree((HLOCAL)format_message_result); + } + }; + +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT + LPWSTR format_message_result{}; + auto format_message_succeeded = + ::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, + error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&format_message_result, 0, nullptr); + + fFormatResult(format_message_succeeded, format_message_result); +#else LPSTR format_message_result{}; auto format_message_succeeded = - ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, + ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&format_message_result, 0, nullptr); - if (format_message_succeeded && format_message_result) - { - system_message = fmt::format(" ({})", format_message_result); - } - - if (format_message_result) - { - LocalFree((HLOCAL)format_message_result); - } + fFormatResult(format_message_succeeded, format_message_result); +#endif return fmt::format("{}: {}{}", user_message, error_code, system_message); } @@ -203,7 +217,7 @@ class win_eventlog_sink : public base_sink { if (!hEventLog_) { - hEventLog_ = ::RegisterEventSource(nullptr, source_.c_str()); + hEventLog_ = ::RegisterEventSourceA(nullptr, source_.c_str()); if (!hEventLog_ || hEventLog_ == (HANDLE)ERROR_ACCESS_DENIED) { SPDLOG_THROW(internal::win32_error("RegisterEventSource")); @@ -218,13 +232,22 @@ class win_eventlog_sink : public base_sink { using namespace internal; + bool succeeded; memory_buf_t formatted; base_sink::formatter_->format(msg, formatted); formatted.push_back('\0'); - LPCSTR lp_str = static_cast(formatted.data()); - auto succeeded = ::ReportEvent(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); +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT + LPCWSTR lp_str = reinterpret_cast(formatted.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_str, nullptr); +#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) { From 211478e13ea27588b6d8c88e6b70216f7bd4e7f2 Mon Sep 17 00:00:00 2001 From: Amir Alperin Date: Sun, 13 Dec 2020 10:45:55 +0200 Subject: [PATCH 2/5] convert message back to wchar --- include/spdlog/sinks/win_eventlog_sink.h | 38 ++++++++---------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/include/spdlog/sinks/win_eventlog_sink.h b/include/spdlog/sinks/win_eventlog_sink.h index 7b50b7b5c..ef4de59ea 100644 --- a/include/spdlog/sinks/win_eventlog_sink.h +++ b/include/spdlog/sinks/win_eventlog_sink.h @@ -39,6 +39,8 @@ Windows Registry Editor Version 5.00 #include #include #include +#include +#include namespace spdlog { namespace sinks { @@ -55,34 +57,20 @@ struct win32_error : public spdlog_ex { std::string system_message; - auto fFormatResult = [&system_message](bool format_message_succeeded, void* format_message_result) - { - if (format_message_succeeded && format_message_result) - { - system_message = fmt::format(" ({})", format_message_result); - } - - if (format_message_result) - { - LocalFree((HLOCAL)format_message_result); - } - }; - -#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT - LPWSTR format_message_result{}; - auto format_message_succeeded = - ::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, - error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&format_message_result, 0, nullptr); - - fFormatResult(format_message_succeeded, format_message_result); -#else LPSTR format_message_result{}; auto format_message_succeeded = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&format_message_result, 0, nullptr); - fFormatResult(format_message_succeeded, format_message_result); -#endif + if (format_message_succeeded && format_message_result) + { + system_message = fmt::format(" ({})", format_message_result); + } + + if (format_message_result) + { + LocalFree((HLOCAL)format_message_result); + } return fmt::format("{}: {}{}", user_message, error_code, system_message); } @@ -238,10 +226,10 @@ class win_eventlog_sink : public base_sink formatted.push_back('\0'); #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT - LPCWSTR lp_str = reinterpret_cast(formatted.data()); + auto buf = std::wstring_convert>().from_bytes(formatted.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_str, nullptr); + current_user_sid_.as_sid(), 1, 0, (LPCWSTR*)buf.c_str(), nullptr); #else LPCSTR lp_str = reinterpret_cast(formatted.data()); From 22f514aabfadacace2ed0f611d78f1a905689bbd Mon Sep 17 00:00:00 2001 From: Amir Alperin Date: Sun, 13 Dec 2020 23:11:25 +0200 Subject: [PATCH 3/5] restore ident format --- include/spdlog/sinks/win_eventlog_sink.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/include/spdlog/sinks/win_eventlog_sink.h b/include/spdlog/sinks/win_eventlog_sink.h index ef4de59ea..5d0287446 100644 --- a/include/spdlog/sinks/win_eventlog_sink.h +++ b/include/spdlog/sinks/win_eventlog_sink.h @@ -226,14 +226,15 @@ class win_eventlog_sink : public base_sink formatted.push_back('\0'); #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT - auto buf = std::wstring_convert>().from_bytes(formatted.data()); + auto buf = std::wstring_convert>().from_bytes(formatted.data()); + LPCWSTR lp_wstr = reinterpret_cast(buf.c_str()); - succeeded = ::ReportEventW(event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), event_id_, - current_user_sid_.as_sid(), 1, 0, (LPCWSTR*)buf.c_str(), nullptr); + 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); #else - LPCSTR lp_str = reinterpret_cast(formatted.data()); + LPCSTR lp_str = reinterpret_cast(formatted.data()); - succeeded = ::ReportEventA(event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), event_id_, + 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 From c67974e4c843a334080f989231ffe763d501fa0c Mon Sep 17 00:00:00 2001 From: Amir Alperin Date: Wed, 16 Dec 2020 01:14:55 +0200 Subject: [PATCH 4/5] replace deprected wchar string conversion --- include/spdlog/details/os-inl.h | 35 ++++++++++++++++++++++++ include/spdlog/details/os.h | 2 ++ include/spdlog/sinks/win_eventlog_sink.h | 23 ++++++++++++---- 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/include/spdlog/details/os-inl.h b/include/spdlog/details/os-inl.h index 87c8c5a08..2413aec9f 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 243a4fb85..88f13dbe0 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 5d0287446..f154c55a3 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 @@ class win_eventlog_sink : public base_sink 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 {} From 7fff900a1a3d65b8d3dff8bca7e927df80edf8af Mon Sep 17 00:00:00 2001 From: Amir Alperin Date: Wed, 16 Dec 2020 06:57:24 +0200 Subject: [PATCH 5/5] Fix error message in exception --- include/spdlog/details/os-inl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/spdlog/details/os-inl.h b/include/spdlog/details/os-inl.h index 2413aec9f..c9d0642f7 100644 --- a/include/spdlog/details/os-inl.h +++ b/include/spdlog/details/os-inl.h @@ -492,7 +492,7 @@ SPDLOG_INLINE void utf8_to_wstrbuf(string_view_t str, memory_buf_t &target) } } - throw_spdlog_ex(fmt::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError())); + throw_spdlog_ex(fmt::format("MultiByteToWideChar failed. Last error: {}", ::GetLastError())); } #endif // (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32)