From b701355a766dea7af040344c6221dda56be4726e Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Wed, 18 May 2016 13:44:28 +0200 Subject: [PATCH] Event Tracing for Windows support added --- build/WinStd.vcxproj | 1 + build/WinStd.vcxproj.filters | 3 + include/WinStd/ETW.h | 223 +++++++++++++++++++++++++++++++++++ src/StdAfx.h | 3 + 4 files changed, 230 insertions(+) create mode 100644 include/WinStd/ETW.h diff --git a/build/WinStd.vcxproj b/build/WinStd.vcxproj index 0127bf12..4715d91c 100644 --- a/build/WinStd.vcxproj +++ b/build/WinStd.vcxproj @@ -87,6 +87,7 @@ + diff --git a/build/WinStd.vcxproj.filters b/build/WinStd.vcxproj.filters index 5f9e0822..93845d37 100644 --- a/build/WinStd.vcxproj.filters +++ b/build/WinStd.vcxproj.filters @@ -55,5 +55,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/include/WinStd/ETW.h b/include/WinStd/ETW.h new file mode 100644 index 00000000..496fc145 --- /dev/null +++ b/include/WinStd/ETW.h @@ -0,0 +1,223 @@ +/* + Copyright 1991-2016 Amebis + Copyright 2016 GÉANT + + This file is part of WinStd. + + Setup is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Setup is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Setup. If not, see . +*/ + +#include "Common.h" + +#include +#include +#include + +#include + +namespace winstd +{ + class event_provider; + class event_auto; + template class event_auto_res; +} + +#define WINSTD_ETW_ERROR(ep, key, f, ...) (ep).write ( TRACE_LEVEL_ERROR , key, _T(" ") _T(__FUNCTION__) _T(" ") f, ##__VA_ARGS__) +#define WINSTD_ETW_WARNING(ep, key, f, ...) (ep).write ( TRACE_LEVEL_WARNING , key, _T(" ") _T(__FUNCTION__) _T(" ") f, ##__VA_ARGS__) +#define WINSTD_ETW_INFO(ep, key, f, ...) (ep).write ( TRACE_LEVEL_INFORMATION, key, _T(" ") _T(__FUNCTION__) _T(" ") f, ##__VA_ARGS__) +#define WINSTD_ETW_DEBUG(ep, key, f, ...) (ep).write ( TRACE_LEVEL_VERBOSE , key, _T(" ") _T(__FUNCTION__) _T(" ") f, ##__VA_ARGS__) +#define WINSTD_ETW_FN_VOID_WARNING(ep, key) winstd::event_auto _event_auto(ep, TRACE_LEVEL_WARNING , key, _T("->") _T(__FUNCTION__), _T("<-") _T(__FUNCTION__)) +#define WINSTD_ETW_FN_VOID_INFO(ep, key) winstd::event_auto _event_auto(ep, TRACE_LEVEL_INFORMATION, key, _T("->") _T(__FUNCTION__), _T("<-") _T(__FUNCTION__)) +#define WINSTD_ETW_FN_VOID_DEBUG(ep, key) winstd::event_auto _event_auto(ep, TRACE_LEVEL_VERBOSE , key, _T("->") _T(__FUNCTION__), _T("<-") _T(__FUNCTION__)) +#define WINSTD_ETW_FN_WARNING(ep, key, res) winstd::event_auto_res _event_auto(ep, TRACE_LEVEL_WARNING , key, _T("->") _T(__FUNCTION__), _T("<-") _T(__FUNCTION__) _T(" (%ld)"), res) +#define WINSTD_ETW_FN_INFO(ep, key, res) winstd::event_auto_res _event_auto(ep, TRACE_LEVEL_INFORMATION, key, _T("->") _T(__FUNCTION__), _T("<-") _T(__FUNCTION__) _T(" (%ld)"), res) +#define WINSTD_ETW_FN_DEBUG(ep, key, res) winstd::event_auto_res _event_auto(ep, TRACE_LEVEL_VERBOSE , key, _T("->") _T(__FUNCTION__), _T("<-") _T(__FUNCTION__) _T(" (%ld)"), res) + +#pragma once + + +namespace winstd +{ + /// + /// \defgroup WinStdETWAPI Event Tracing for Windows API + /// Integrates WinStd classes with Event Tracing for Windows API + /// + /// @{ + + + /// + /// ETW event provider + /// + class event_provider : public handle + { + public: + /// + /// Closes the event provider. + /// + /// \sa [EventUnregister function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363749.aspx) + /// + virtual ~event_provider() + { + if (m_h) + EventUnregister(m_h); + } + + + /// + /// Registers the event provider. + /// + /// \return + /// - `ERROR_SUCCESS` when creation succeeds; + /// - error code otherwise. + /// + /// \sa [CertOpenStore function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376559.aspx) + /// + inline ULONG create(_In_ LPCGUID ProviderId) + { + handle_type h; + ULONG ulRes = EventRegister(ProviderId, enable_callback, this, &h); + if (ulRes == ERROR_SUCCESS) + attach(h); + return ulRes; + } + + + /// + /// Writes a string event. + /// + /// \return + /// - `ERROR_SUCCESS` when creation succeeds; + /// - error code otherwise. + /// + /// \sa [EventWriteString function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363750v=vs.85.aspx) + /// + inline ULONG write(_In_ UCHAR Level, _In_ ULONGLONG Keyword, _In_ PCWSTR String, ...) + { + if (!m_h) + return ERROR_NOT_SUPPORTED; + + std::wstring msg; + va_list arg; + + // Format message. + va_start(arg, String); + vsprintf(msg, String, arg); + va_end(arg); + + // Write string event. + return EventWriteString(m_h, Level, Keyword, msg.c_str()); + } + + protected: + /// + /// Releases the event provider. + /// + /// \sa [EventUnregister function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363749.aspx) + /// + virtual void free_internal() + { + EventUnregister(m_h); + } + + + /// + /// Receive enable or disable notification requests + /// + /// \sa [EnableCallback callback function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363707.aspx) + /// + virtual void enable_callback(_In_ LPCGUID SourceId, _In_ ULONG IsEnabled, _In_ UCHAR Level, _In_ ULONGLONG MatchAnyKeyword, _In_ ULONGLONG MatchAllKeyword, _In_opt_ PEVENT_FILTER_DESCRIPTOR FilterData) + { + UNREFERENCED_PARAMETER(SourceId); + UNREFERENCED_PARAMETER(IsEnabled); + UNREFERENCED_PARAMETER(Level); + UNREFERENCED_PARAMETER(MatchAnyKeyword); + UNREFERENCED_PARAMETER(MatchAllKeyword); + UNREFERENCED_PARAMETER(FilterData); + } + + + /// + /// Receive enable or disable notification requests + /// + /// \sa [EnableCallback callback function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363707.aspx) + /// + static VOID NTAPI enable_callback(_In_ LPCGUID SourceId, _In_ ULONG IsEnabled, _In_ UCHAR Level, _In_ ULONGLONG MatchAnyKeyword, _In_ ULONGLONG MatchAllKeyword, _In_opt_ PEVENT_FILTER_DESCRIPTOR FilterData, _Inout_opt_ PVOID CallbackContext) + { + if (CallbackContext) + static_cast(CallbackContext)->enable_callback(SourceId, IsEnabled, Level, MatchAnyKeyword, MatchAllKeyword, FilterData); + else + assert(0); // Where did the "this" pointer get lost? + } + }; + + // winstd::event_auto actually and winstd::event_auto_res<> do not need an assignment operator actually, so the C4512 warning is safely ignored. + #pragma warning(push) + #pragma warning(disable: 4512) + + /// + /// Helper class to write a string event on entry/exit of scope. + /// + /// It writes one string event at creation and another at destruction. + /// + class event_auto { + public: + inline event_auto(_In_ event_provider &ep, _In_ UCHAR Level, _In_ ULONGLONG Keyword, _In_z_ PCWSTR pszFormatEntry, _In_z_ PCWSTR pszFormatExit) : + m_ep(ep), + m_level(Level), + m_keyword(Keyword), + m_pszFormatExit(pszFormatExit) + { + m_ep.write(m_level, m_keyword, pszFormatEntry); + } + + inline ~event_auto() + { + m_ep.write(m_level, m_keyword, m_pszFormatExit); + } + + protected: + event_provider &m_ep; // Reference to event provider in use + UCHAR m_level; // Event level + ULONGLONG m_keyword; // Event keyword mask + PCWSTR m_pszFormatExit; // Pointer to string for string event at destruction + }; + + + /// + /// Helper template to write a string event on entry/exit of scope with one parameter (typically result). + /// + /// It writes one string event at creation and another at destruction, with allowing one sprintf type parameter for string event at destruction. + /// + template + class event_auto_res : public event_auto { + public: + inline event_auto_res(_In_ event_provider &ep, _In_ UCHAR Level, _In_ ULONGLONG Keyword, _In_z_ PCWSTR pszFormatEntry, _In_z_ PCWSTR pszFormatExit, _In_ T &tResult) : + m_tResult(tResult), + event_auto(ep, Level, Keyword, pszFormatEntry, pszFormatExit) + { + } + + inline ~event_auto_res() + { + m_ep.write(m_level, m_keyword, m_pszFormatExit, m_tResult); + } + + protected: + T &m_tResult; // Parameter for string event at destruction. + }; + + #pragma warning(pop) + + /// @} +} diff --git a/src/StdAfx.h b/src/StdAfx.h index c61ec832..8a27808c 100644 --- a/src/StdAfx.h +++ b/src/StdAfx.h @@ -25,6 +25,9 @@ #include "../include/WinStd/Cred.h" #include "../include/WinStd/Crypt.h" #include "../include/WinStd/EAP.h" +#if _WIN32_WINNT >= _WIN32_WINNT_VISTA +#include "../include/WinStd/ETW.h" +#endif #include "../include/WinStd/Common.h" #include "../include/WinStd/MSI.h" #if defined(SECURITY_WIN32) || defined(SECURITY_KERNEL) || defined(SECURITY_MAC)