Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix windows event sink log compilation error with UNICODE preprocessor #1760

Merged
merged 5 commits into from
Dec 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions include/spdlog/details/os-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<size_t>((std::numeric_limits<int>::max)()))
{
throw_spdlog_ex("UTF-8 string is too big to be converted to UTF-16");
}

int str_size = static_cast<int>(str.size());
if (str_size == 0)
{
target.resize(0);
return;
}

int result_size = static_cast<int>(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("MultiByteToWideChar failed. Last error: {}", ::GetLastError()));
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong error message in exception. should be “ MultiByteToWideChar”

#endif // (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32)

// return true on success
Expand Down
2 changes: 2 additions & 0 deletions include/spdlog/details/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
33 changes: 28 additions & 5 deletions include/spdlog/sinks/win_eventlog_sink.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ struct win32_error : public spdlog_ex

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)
Expand Down Expand Up @@ -203,7 +203,7 @@ class win_eventlog_sink : public base_sink<Mutex>
{
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"));
Expand All @@ -218,18 +218,41 @@ class win_eventlog_sink : public base_sink<Mutex>
{
using namespace internal;

bool succeeded;
memory_buf_t formatted;
base_sink<Mutex>::formatter_->format(msg, formatted);
formatted.push_back('\0');
LPCSTR lp_str = static_cast<LPCSTR>(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
try
{
memory_buf_t buf;
details::os::utf8_to_wstrbuf(string_view_t(formatted.data(), formatted.size()), buf);

LPCWSTR lp_wstr = reinterpret_cast<LPCWSTR>(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<LPCSTR>(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);

if (!succeeded)
{
SPDLOG_THROW(win32_error("ReportEvent"));
}
#endif
}

void flush_() override {}
Expand Down