From 8e7042f4ca2872c187c7dd1ffa679453ec86e610 Mon Sep 17 00:00:00 2001 From: Alin Gabriel Serdean Date: Tue, 17 Nov 2020 00:36:36 +0200 Subject: [PATCH] common: Add Windows ETW support This patch adds generic ETW logging on top of syslog calls. The events are described in the message compiler file `event_logging.mc`. Using the cross platform utility `windmc`, we will generate the header file, `event_logging.h`, needed by the ETW implementation, and the resource file `event_logging.rc`. Over the generated resource file we will run another utility called `windres`. this tool is used to compile the binary objects needed by the OS utilities (i.e. `Event Viewer`) to view the logged events. On usage, a registry key needs to be added/removed on the target computer. The registry looks like the following: [HKLM\SYSTEM\CurrentControlSet\Services\EventLog\Application\] "EventMessageFile"="\\event_logging.dll" I.E.: [HKLM\SYSTEM\CurrentControlSet\Services\EventLog\Application\rbd-wnbd] "EventMessageFile"="C:\\Program Files\\Ceph\\bin\\event_logging.dll" Signed-off-by: Alin Gabriel Serdean Signed-off-by: Lucian Petrut Co-authored-by: Lucian Petrut --- src/common/CMakeLists.txt | 23 ++++++++- src/common/win32/event_logging.mc | 35 ++++++++++++++ src/common/win32/syslog.cc | 77 +++++++++++++++++++++++++++++++ src/include/win32/syslog.h | 12 +++-- 4 files changed, 141 insertions(+), 6 deletions(-) create mode 100644 src/common/win32/event_logging.mc create mode 100644 src/common/win32/syslog.cc diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index e9a732ba9161f..6f29dfef35080 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -104,13 +104,34 @@ set(common_srcs version.cc) if(WIN32) + if(MINGW) + set(CMAKE_MC_COMPILER x86_64-w64-mingw32-windmc) + set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) + endif() + + add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/src/common/event_logging.h + COMMAND ${CMAKE_MC_COMPILER} -b -e h -h ${CMAKE_BINARY_DIR}/src/common/ + -r ${CMAKE_BINARY_DIR}/src/common ${CMAKE_SOURCE_DIR}/src/common/win32/event_logging.mc + COMMAND ${CMAKE_RC_COMPILER} ${CMAKE_BINARY_DIR}/src/common/event_logging.rc + -o ${CMAKE_BINARY_DIR}/src/common/event_logging.o + COMMAND ${CMAKE_CXX_COMPILER} -o ${CMAKE_BINARY_DIR}/bin/event_logging.dll -shared + ${CMAKE_BINARY_DIR}/src/common/event_logging.o + DEPENDS ${CMAKE_SOURCE_DIR}/src/common/win32/event_logging.mc) + + set_source_files_properties(${CMAKE_SOURCE_DIR}/src/common/win32/syslog.cc + APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_BINARY_DIR}/src/common/event_logging.h) + + include_directories(SYSTEM "${CMAKE_BINARY_DIR}/src/common/") + list(APPEND common_srcs win32/blkdev.cc win32/dns_resolve.cc win32/ifaddrs.cc win32/registry.cc win32/service.cc - win32/SubProcess.cc) + win32/SubProcess.cc + win32/syslog.cc) else() list(APPEND common_srcs blkdev.cc diff --git a/src/common/win32/event_logging.mc b/src/common/win32/event_logging.mc new file mode 100644 index 0000000000000..3d08889aa1e4f --- /dev/null +++ b/src/common/win32/event_logging.mc @@ -0,0 +1,35 @@ +SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS + Informational=0x1:STATUS_SEVERITY_INFORMATIONAL + Warning=0x2:STATUS_SEVERITY_WARNING + Error=0x3:STATUS_SEVERITY_ERROR + ) + + +MessageId=0x0001 +Severity=Success +SymbolicName=SUCCESS_EVENTMSG +Language=English +%1 +. + +MessageId=0x0002 +Severity=Informational +SymbolicName=INFO_EVENTMSG +Language=English +%1 +. + +MessageId=0x0003 +Severity=Warning +SymbolicName=WARN_EVENTMSG +Language=English +%1 +. + +MessageId=0x0004 +Severity=Error +SymbolicName=ERROR_EVENTMSG +Language=English +%1 +. + diff --git a/src/common/win32/syslog.cc b/src/common/win32/syslog.cc new file mode 100644 index 0000000000000..7a1a90c9b1104 --- /dev/null +++ b/src/common/win32/syslog.cc @@ -0,0 +1,77 @@ +#include +#include +#include "event_logging.h" +#include "common/code_environment.h" + +static HANDLE g_event_source = NULL; + +bool get_event_source() +{ + if (!g_event_source) { + HANDLE temp = RegisterEventSourceA(NULL, get_process_name_cpp().c_str()); + if (!temp) + return false; + + if (InterlockedCompareExchangePointer(&g_event_source, temp, NULL)) { + // There already was an event source, let's cleanup the one that we've + // just created. + DeregisterEventSource(temp); + } + } + + return true; +} + +void write_event_log_entry(int level, const char* msg) +{ + if (!get_event_source()) { + return; + } + + WORD type; + DWORD event_id; + switch (level) { + case LOG_DEBUG: + event_id = SUCCESS_EVENTMSG; + type = EVENTLOG_SUCCESS; + break; + + case LOG_INFO: + case LOG_NOTICE: + event_id = INFO_EVENTMSG; + type = EVENTLOG_INFORMATION_TYPE; + break; + + case LOG_WARNING: + event_id = WARN_EVENTMSG; + type = EVENTLOG_WARNING_TYPE; + break; + + default: + event_id = ERROR_EVENTMSG; + type = EVENTLOG_ERROR_TYPE; + } + + ReportEventA(g_event_source, type, + 0, event_id, NULL, 1, 0, &msg, NULL); +} + +void syslog(int priority, const char* format, ...) +{ + va_list args; + va_start(args, format); + + size_t length = (size_t)_vscprintf(format, args) + 1; + + char* buffer = (char*) malloc(length); + if (NULL == buffer) { + va_end(args); + return; + } + + vsnprintf_s(buffer, length, length - 1, format, args); + va_end(args); + + write_event_log_entry(LOG_PRI(priority), buffer); + free(buffer); +} diff --git a/src/include/win32/syslog.h b/src/include/win32/syslog.h index d59cd3d0c7cb7..28389e0b999cd 100644 --- a/src/include/win32/syslog.h +++ b/src/include/win32/syslog.h @@ -25,7 +25,6 @@ #define LOG_NOTICE 5 /* normal but significant condition */ #define LOG_INFO 6 /* informational */ #define LOG_DEBUG 7 /* debug-level messages */ -#define LOG_NDELAY 8 /* don't delay open */ #define LOG_KERN (0<<3) /* kernel messages */ #define LOG_USER (1<<3) /* user-level messages */ @@ -49,14 +48,17 @@ #define LOG_LOCAL6 (22<<3) /* reserved for local use */ #define LOG_LOCAL7 (23<<3) /* reserved for local use */ +#define LOG_PRIMASK 0x07 /* mask to extract priority part (internal) */ + /* extract priority */ +#define LOG_PRI(p) ((p) & LOG_PRIMASK) + + static inline void openlog(const char *ident, int option, int facility) { } -static inline void -syslog(int priority, const char *format, ...) -{ -} +void +syslog(int priority, const char *format, ...); #endif /* syslog.h */ -- 2.39.5