From 06919a60ae61d6d88546b23b52092f742599a8ae Mon Sep 17 00:00:00 2001 From: Lev Stipakov Date: Wed, 17 Sep 2025 11:05:48 +0200 Subject: [PATCH] openvpnserv: Fix writing messages to the event log MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit There are two problems with the current implementation: - due to the code bug, we never display actual error message corresponding to the Windows error code. We use FORMAT_MESSAGE_ALLOCATE_BUFFER, in which case we must pass a pointer to the LPTSTR, not the LPTSTR itself. - The error is not displayed in the "General" tab, which is very confusing. One needs to go to the "Details" tab to see what is wrong. This commit solves both problems. We now display a proper error message in addition to the text provided by the service ("what went wrong"). While on it, remove trailing symbols ín a safer way. To display the message in "General" tab, we create a registered message file (openvpnservmsg.dll), which contains message template. Note that this requires changes to the installer - we need to install the new DLL and add a registry entry. GitHub: https://github.com/OpenVPN/openvpn/issues/842 Change-Id: I423c9880def0eb479abb72bef2e8034a73cf5905 Signed-off-by: Lev Stipakov Acked-by: Selva Nair Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1188 Message-Id: <20250917090557.25414-1-gert@greenie.muc.de> URL: https://sourceforge.net/p/openvpn/mailman/message/59234559/ Signed-off-by: Gert Doering --- src/openvpnserv/CMakeLists.txt | 34 +++++++++++++++++++++++++++++ src/openvpnserv/common.c | 39 ++++++++++++++++++++++------------ src/openvpnserv/eventmsg.mc | 23 ++++++++++++++++++++ 3 files changed, 82 insertions(+), 14 deletions(-) create mode 100644 src/openvpnserv/eventmsg.mc diff --git a/src/openvpnserv/CMakeLists.txt b/src/openvpnserv/CMakeLists.txt index 7e3efb264..82099f16f 100644 --- a/src/openvpnserv/CMakeLists.txt +++ b/src/openvpnserv/CMakeLists.txt @@ -6,11 +6,14 @@ project(openvpnserv) add_executable(openvpnserv) +set(MC_GEN_DIR ${CMAKE_CURRENT_BINARY_DIR}/mc) + target_include_directories(openvpnserv PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/../../ ../../include/ ../openvpn/ ../compat/ + ${MC_GEN_DIR} ) target_sources(openvpnserv PRIVATE common.c @@ -33,3 +36,34 @@ if (MINGW) target_compile_options(openvpnserv PRIVATE -municode) target_link_options(openvpnserv PRIVATE -municode) endif () + +# below we generate a DLL which contains an event source for event log messages from eventmsg.mc template +file(MAKE_DIRECTORY ${MC_GEN_DIR}) +set(MC_FILE ${CMAKE_CURRENT_SOURCE_DIR}/eventmsg.mc) + +find_program(MC_COMPILER NAMES mc mc.exe x86_64-w64-mingw32-windmc i686-w64-mingw32-windmc windmc) + +if (NOT MC_COMPILER) + message(FATAL_ERROR "No message compiler found.") +endif() + +add_custom_command( + OUTPUT ${MC_GEN_DIR}/eventmsg.rc ${MC_GEN_DIR}/eventmsg.h + COMMAND ${MC_COMPILER} -U -h ${MC_GEN_DIR} -r ${MC_GEN_DIR} ${MC_FILE} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/eventmsg.mc + VERBATIM + ) + +# generate rc file for DLL and header for the service binary +add_custom_target(msg_mc_gen ALL DEPENDS ${MC_GEN_DIR}/eventmsg.rc ${MC_GEN_DIR}/eventmsg.h) + +add_library(openvpnservmsg SHARED ${MC_GEN_DIR}/eventmsg.rc) + +if (MSVC) + set_target_properties(openvpnservmsg PROPERTIES LINK_FLAGS "/NOENTRY") +else() + target_link_options(openvpnservmsg PRIVATE "-Wl,--no-entry") +endif() + +add_dependencies(openvpnservmsg msg_mc_gen) +add_dependencies(openvpnserv msg_mc_gen) diff --git a/src/openvpnserv/common.c b/src/openvpnserv/common.c index a42c65d29..e975cc758 100644 --- a/src/openvpnserv/common.c +++ b/src/openvpnserv/common.c @@ -22,6 +22,7 @@ #include "service.h" #include "validate.h" +#include "eventmsg.h" LPCWSTR service_instance = L""; static wchar_t win_sys_path[MAX_PATH]; @@ -203,25 +204,29 @@ GetLastErrorText(void) LPWSTR tmp = NULL; error = GetLastError(); - len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_ARGUMENT_ARRAY, - NULL, error, LANG_NEUTRAL, tmp, 0, NULL); + len = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&tmp, 0, NULL); - if (len == 0 || (long)_countof(buf) < (long)len + 14) + if (!len || !tmp) { - buf[0] = L'\0'; - } - else - { - tmp[wcslen(tmp) - 2] = L'\0'; /* remove CR/LF characters */ - swprintf(buf, _countof(buf), L"%ls (0x%x)", tmp, error); + swprintf(buf, _countof(buf), L"Unknown error (0x%lx)", error); + if (tmp) + { + LocalFree(tmp); + } + return buf; } - if (tmp) + /* trim trailing CR / LF / spaces safely */ + while (len && (tmp[len - 1] == L'\r' || tmp[len - 1] == L'\n' || tmp[len - 1] == L' ')) { - LocalFree(tmp); + tmp[--len] = L'\0'; } + swprintf(buf, _countof(buf), L"%ls (0x%lx)", tmp, error); + + LocalFree(tmp); return buf; } @@ -253,8 +258,14 @@ MsgToEventLog(DWORD flags, LPCWSTR format, ...) const WCHAR *mesg[] = { msg[0], msg[1] }; ReportEvent(hEventSource, - flags & MSG_FLAGS_ERROR ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE, 0, 0, - NULL, 2, 0, mesg, NULL); + flags & MSG_FLAGS_ERROR ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE, + 0, + EVT_TEXT_2, + NULL, + 2, + 0, + mesg, + NULL); DeregisterEventSource(hEventSource); } diff --git a/src/openvpnserv/eventmsg.mc b/src/openvpnserv/eventmsg.mc new file mode 100644 index 000000000..722a30e4d --- /dev/null +++ b/src/openvpnserv/eventmsg.mc @@ -0,0 +1,23 @@ +MessageIdTypedef=DWORD + +SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS + Informational=0x1:STATUS_SEVERITY_INFORMATIONAL + Warning=0x2:STATUS_SEVERITY_WARNING + Error=0x3:STATUS_SEVERITY_ERROR + ) + +FacilityNames=(System=0x0:FACILITY_SYSTEM + Runtime=0x2:FACILITY_RUNTIME + Stubs=0x3:FACILITY_STUBS + Io=0x4:FACILITY_IO_ERROR_CODE +) + +LanguageNames=(English=0x409:MSG00409) + +MessageId=0x1 +Severity=Error +Facility=Runtime +SymbolicName=EVT_TEXT_2 +Language=English +%1%n%2 +. -- 2.47.3