Optimize win_eventlog to avoid string allocation

This commit is contained in:
gabime 2020-02-10 00:37:45 +02:00
parent fccee959b1
commit 640921cd3f

View File

@ -37,6 +37,7 @@ Windows Registry Editor Version 5.00
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <vector>
namespace spdlog { namespace spdlog {
namespace sinks { namespace sinks {
@ -55,7 +56,7 @@ struct win32_error : public spdlog_ex
std::string system_message; std::string system_message;
LPSTR format_message_result {}; LPSTR format_message_result {};
auto format_message_succeeded = FormatMessage( auto format_message_succeeded = ::FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, 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); error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &format_message_result, 0, nullptr);
@ -65,7 +66,9 @@ struct win32_error : public spdlog_ex
} }
if (format_message_result) if (format_message_result)
{
LocalFree((HLOCAL)format_message_result); LocalFree((HLOCAL)format_message_result);
}
return fmt::format("{}: {}{}", user_message, error_code, system_message); return fmt::format("{}: {}{}", user_message, error_code, system_message);
} }
@ -87,15 +90,19 @@ public:
/** creates a wrapped SID copy */ /** creates a wrapped SID copy */
static sid_t duplicate_sid(PSID psid) static sid_t duplicate_sid(PSID psid)
{ {
if (!IsValidSid(psid)) if (!::IsValidSid(psid))
{
SPDLOG_THROW(spdlog_ex("sid_t::sid_t(): invalid SID received")); SPDLOG_THROW(spdlog_ex("sid_t::sid_t(): invalid SID received"));
}
auto const sid_length {::GetLengthSid(psid)}; auto const sid_length {::GetLengthSid(psid)};
sid_t result; sid_t result;
result.buffer_.resize(sid_length); result.buffer_.resize(sid_length);
if (!CopySid(sid_length, (PSID) result.as_sid(), psid)) if (!::CopySid(sid_length, (PSID)result.as_sid(), psid))
{
SPDLOG_THROW(win32_error("CopySid")); SPDLOG_THROW(win32_error("CopySid"));
}
return result; return result;
} }
@ -112,34 +119,36 @@ public:
/* create and init RAII holder for process token */ /* create and init RAII holder for process token */
struct process_token_t struct process_token_t
{ {
HANDLE hToken_; HANDLE token_handle_= INVALID_HANDLE_VALUE;
bool hasToken_; explicit process_token_t(HANDLE process)
{
process_token_t(HANDLE process) if (!::OpenProcessToken(process, TOKEN_QUERY, &token_handle_))
: hToken_(0)
, hasToken_(OpenProcessToken(process, TOKEN_QUERY, &hToken_))
{ {
if (!hasToken_)
SPDLOG_THROW(win32_error("OpenProcessToken")); SPDLOG_THROW(win32_error("OpenProcessToken"));
} }
}
~process_token_t() ~process_token_t()
{ {
if (hasToken_) ::CloseHandle(token_handle_);
CloseHandle(hToken_);
} }
} current_process_token(GetCurrentProcess()); // GetCurrentProcess returns pseudohandle, no leak here!
} current_process_token(::GetCurrentProcess()); // GetCurrentProcess returns pseudohandle, no leak here!
// Get the required size, this is expected to fail with ERROR_INSUFFICIENT_BUFFER and return the token size // Get the required size, this is expected to fail with ERROR_INSUFFICIENT_BUFFER and return the token size
DWORD tusize = 0; DWORD tusize = 0;
GetTokenInformation(current_process_token.hToken_, TokenUser, NULL, 0, &tusize); ::GetTokenInformation(current_process_token.token_handle_, TokenUser, NULL, 0, &tusize);
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
SPDLOG_THROW(win32_error("GetTokenInformation")); SPDLOG_THROW(win32_error("GetTokenInformation"));
}
// get user token // get user token
std::vector<unsigned char> buffer(tusize); std::vector<unsigned char> buffer(static_cast<size_t>(tusize));
if (!GetTokenInformation(current_process_token.hToken_, TokenUser, (LPVOID) buffer.data(), tusize, &tusize)) if (!GetTokenInformation(current_process_token.token_handle_, TokenUser, (LPVOID)buffer.data(), tusize, &tusize))
{
SPDLOG_THROW(win32_error("GetTokenInformation")); SPDLOG_THROW(win32_error("GetTokenInformation"));
}
// create a wrapper of the SID data as stored in the user token // create a wrapper of the SID data as stored in the user token
return sid_t::duplicate_sid(((TOKEN_USER*) buffer.data())->User.Sid); return sid_t::duplicate_sid(((TOKEN_USER*) buffer.data())->User.Sid);
@ -213,9 +222,8 @@ protected:
memory_buf_t formatted; memory_buf_t formatted;
formatter_->format(msg, formatted); formatter_->format(msg, formatted);
formatted.push_back('\0');
auto formatted_string = fmt::to_string(formatted); LPCSTR lp_str = static_cast<LPCSTR>(formatted.data());
auto formatted_string_lpsz = formatted_string.c_str();
bool succeeded = ReportEvent( bool succeeded = ReportEvent(
event_log_handle(), event_log_handle(),
@ -225,7 +233,7 @@ protected:
current_user_sid_.as_sid(), current_user_sid_.as_sid(),
1, 1,
0, 0,
&formatted_string_lpsz, &lp_str,
nullptr); nullptr);
if (!succeeded) if (!succeeded)