WinStd
Additional templates and function helpers for Microsoft Windows using Standard C++ classes
ETW.h
Go to the documentation of this file.
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 1991-2022 Amebis
4 Copyright © 2016 GÉANT
5*/
6
12
13#pragma once
14
15#include "Common.h"
16#include <assert.h>
17#include <evntprov.h>
18#include <evntcons.h>
19#include <stdarg.h>
20#include <tdh.h>
21#include <memory>
22#include <string>
23#include <vector>
24
25#pragma warning(push)
26#pragma warning(disable: 4505) // Don't warn on unused code
27
30
36template<class _Ty, class _Ax>
37static _Success_(return == ERROR_SUCCESS) ULONG TdhGetProperty(_In_ PEVENT_RECORD pEvent, _In_ ULONG TdhContextCount, _In_reads_opt_(TdhContextCount) PTDH_CONTEXT pTdhContext, _In_ ULONG PropertyDataCount, _In_reads_(PropertyDataCount) PPROPERTY_DATA_DESCRIPTOR pPropertyData, _Inout_ std::vector<_Ty, _Ax> &aData)
38{
39 ULONG ulSize, ulResult;
40
41 // Query property size.
42 ulResult = TdhGetPropertySize(pEvent, TdhContextCount, pTdhContext, PropertyDataCount, pPropertyData, &ulSize);
43 if (ulResult == ERROR_SUCCESS) {
44 if (ulSize) {
45 // Query property value.
46 aData.resize((ulSize + sizeof(_Ty) - 1) / sizeof(_Ty));
47 ulResult = TdhGetProperty(pEvent, TdhContextCount, pTdhContext, PropertyDataCount, pPropertyData, ulSize, reinterpret_cast<LPBYTE>(aData.data()));
48 } else {
49 // Property value size is zero.
50 aData.clear();
51 }
52 }
53
54 return ulResult;
55}
56
62static _Success_(return == ERROR_SUCCESS) ULONG TdhGetEventInformation(_In_ PEVENT_RECORD pEvent, _In_ ULONG TdhContextCount, _In_reads_opt_(TdhContextCount) PTDH_CONTEXT pTdhContext, _Out_ std::unique_ptr<TRACE_EVENT_INFO> &info)
63{
64 BYTE szBuffer[WINSTD_STACK_BUFFER_BYTES];
65 ULONG ulSize = sizeof(szBuffer), ulResult;
66
67 // Try with stack buffer first.
68 ulResult = TdhGetEventInformation(pEvent, TdhContextCount, pTdhContext, (PTRACE_EVENT_INFO)szBuffer, &ulSize);
69 if (ulResult == ERROR_SUCCESS) {
70 // Copy from stack.
71 info.reset(reinterpret_cast<PTRACE_EVENT_INFO>(new char[ulSize]));
72 memcpy(info.get(), szBuffer, ulSize);
73 return ERROR_SUCCESS;
74 } else if (ulResult == ERROR_INSUFFICIENT_BUFFER) {
75 // Create buffer on heap and retry.
76 info.reset(reinterpret_cast<PTRACE_EVENT_INFO>(new char[ulSize]));
77 return TdhGetEventInformation(pEvent, TdhContextCount, pTdhContext, info.get(), &ulSize);
78 }
79
80 return ulResult;
81}
82
88static _Success_(return == ERROR_SUCCESS) ULONG TdhGetEventMapInformation(_In_ PEVENT_RECORD pEvent, _In_ LPWSTR pMapName, _Inout_ std::unique_ptr<EVENT_MAP_INFO> &info)
89{
90 BYTE szBuffer[WINSTD_STACK_BUFFER_BYTES];
91 ULONG ulSize = sizeof(szBuffer), ulResult;
92
93 // Try with stack buffer first.
94 ulResult = TdhGetEventMapInformation(pEvent, pMapName, (PEVENT_MAP_INFO)szBuffer, &ulSize);
95 if (ulResult == ERROR_SUCCESS) {
96 // Copy from stack.
97 info.reset(reinterpret_cast<PEVENT_MAP_INFO>(new char[ulSize]));
98 memcpy(info.get(), szBuffer, ulSize);
99 return ERROR_SUCCESS;
100 } else if (ulResult == ERROR_INSUFFICIENT_BUFFER) {
101 // Create buffer on heap and retry.
102 info.reset(reinterpret_cast<PEVENT_MAP_INFO>(new char[ulSize]));
103 return TdhGetEventMapInformation(pEvent, pMapName, info.get(), &ulSize);
104 }
105
106 return ulResult;
107}
108
110
111#pragma warning(pop)
112
113namespace winstd
114{
117
121 class event_data : public EVENT_DATA_DESCRIPTOR
122 {
123 public:
128 {
129 Ptr = 0;
130 Size = 0;
131 Reserved = (ULONG)-1; // Used for varadic argument terminator.
132 }
133
141 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
142 event_data(_In_ const char &data)
143 {
144 EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
145 }
146
154 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
155 event_data(_In_ const unsigned char &data)
156 {
157 EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
158 }
159
167 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
168 event_data(_In_ const int &data)
169 {
170 EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
171 }
172
180 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
181 event_data(_In_ const unsigned int &data)
182 {
183 EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
184 }
185
193 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
194 event_data(_In_ const long &data)
195 {
196 EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
197 }
198
206 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
207 event_data(_In_ const unsigned long &data)
208 {
209 EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
210 }
211
219 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
220 event_data(_In_ const GUID &data)
221 {
222 EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
223 }
224
232 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
233 event_data(_In_opt_z_ const char *data)
234 {
235 if (data)
236 EventDataDescCreate(this, data, (ULONG)((strlen(data) + 1) * sizeof(*data)));
237 else {
238 // Writing NULL pointer with 0B length causes trouble in Event Viewer: message template string is displayed only, parameters are not rendered.
239 static const char null[] = "(null)";
240 EventDataDescCreate(this, null, sizeof(null));
241 }
242 }
243
251 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
252 event_data(_In_opt_z_ const wchar_t *data)
253 {
254 if (data)
255 EventDataDescCreate(this, data, (ULONG)((wcslen(data) + 1) * sizeof(*data)));
256 else {
257 // Writing NULL pointer with 0B length causes trouble in Event Viewer: message template string is displayed only, parameters are not rendered.
258 static const wchar_t null[] = L"(null)";
259 EventDataDescCreate(this, null, sizeof(null));
260 }
261 }
262
270 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
271 template<class _Elem, class _Traits, class _Ax>
272 event_data(_In_ const std::basic_string<_Elem, _Traits, _Ax> &data)
273 {
274 EventDataDescCreate(this, data.c_str(), (ULONG)((data.length() + 1) * sizeof(_Elem)));
275 }
276
285 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
286 event_data(_In_bytecount_(size) const void *data, _In_ ULONG size)
287 {
288 EventDataDescCreate(this, data, size);
289 }
290 };
291
296
300 class event_rec : public EVENT_RECORD
301 {
302 public:
307 {
308 memset((EVENT_RECORD*)this, 0, sizeof(EVENT_RECORD));
309 }
310
316 event_rec(_In_ const event_rec &other) : EVENT_RECORD(other)
317 {
318 set_extended_data_internal(other.ExtendedDataCount, other.ExtendedData);
319 set_user_data_internal(other.UserDataLength, other.UserData);
320 }
321
327 event_rec(_In_ const EVENT_RECORD &other) : EVENT_RECORD(other)
328 {
329 set_extended_data_internal(other.ExtendedDataCount, other.ExtendedData);
330 set_user_data_internal(other.UserDataLength, other.UserData);
331 }
332
338 event_rec(_Inout_ event_rec&& other) noexcept : EVENT_RECORD(other)
339 {
340 memset((EVENT_RECORD*)&other, 0, sizeof(EVENT_RECORD));
341 }
342
347 {
348 if (ExtendedData)
349 delete reinterpret_cast<unsigned char*>(ExtendedData);
350
351 if (UserData)
352 delete reinterpret_cast<unsigned char*>(UserData);
353 }
354
360 event_rec& operator=(_In_ const event_rec &other)
361 {
362 if (this != std::addressof(other)) {
363 (EVENT_RECORD&)*this = other;
364 set_extended_data_internal(other.ExtendedDataCount, other.ExtendedData);
365 set_user_data_internal(other.UserDataLength, other.UserData);
366 }
367
368 return *this;
369 }
370
376 event_rec& operator=(_In_ const EVENT_RECORD &other)
377 {
378 if (this != std::addressof(other)) {
379 (EVENT_RECORD&)*this = other;
380 set_extended_data_internal(other.ExtendedDataCount, other.ExtendedData);
381 set_user_data_internal(other.UserDataLength, other.UserData);
382 }
383
384 return *this;
385 }
386
392 event_rec& operator=(_Inout_ event_rec&& other) noexcept
393 {
394 if (this != std::addressof(other)) {
395 (EVENT_RECORD&)*this = other;
396 memset((EVENT_RECORD*)&other, 0, sizeof(EVENT_RECORD));
397 }
398
399 return *this;
400 }
401
408 void set_extended_data(_In_ USHORT count, _In_count_(count) const EVENT_HEADER_EXTENDED_DATA_ITEM *data)
409 {
410 if (ExtendedData)
411 delete reinterpret_cast<unsigned char*>(ExtendedData);
412
413 set_extended_data_internal(count, data);
414 }
415
422 void set_user_data(_In_ USHORT size, _In_bytecount_(size) LPCVOID data)
423 {
424 if (UserData)
425 delete reinterpret_cast<unsigned char*>(UserData);
426
427 set_user_data_internal(size, data);
428 }
429
430 protected:
437 void set_extended_data_internal(_In_ USHORT count, _In_count_(count) const EVENT_HEADER_EXTENDED_DATA_ITEM *data)
438 {
439 if (count) {
440 assert(data);
441
442 // Count the total required memory.
443 size_t data_size = 0;
444 for (size_t i = 0; i < count; i++)
445 data_size += data[i].DataSize;
446
447 // Allocate memory for extended data.
448 ExtendedData = reinterpret_cast<EVENT_HEADER_EXTENDED_DATA_ITEM*>(new unsigned char[sizeof(EVENT_HEADER_EXTENDED_DATA_ITEM)*count + data_size]);
449
450 // Bulk-copy extended data descriptors.
451 memcpy(ExtendedData, data, sizeof(EVENT_HEADER_EXTENDED_DATA_ITEM) * count);
452
453 // Copy the data.
454 unsigned char *ptr = reinterpret_cast<unsigned char*>(ExtendedData + count);
455 for (size_t i = 0; i < count; i++) {
456 if (data[i].DataSize) {
457 memcpy(ptr, (void*)(data[i].DataPtr), data[i].DataSize);
458 ExtendedData[i].DataPtr = (ULONGLONG)ptr;
459 ptr += data[i].DataSize;
460 } else
461 ExtendedData[i].DataPtr = NULL;
462 }
463 } else
464 ExtendedData = NULL;
465
466 ExtendedDataCount = count;
467 }
468
475 void set_user_data_internal(_In_ USHORT size, _In_bytecount_(size) LPCVOID data)
476 {
477 if (size) {
478 assert(data);
479
480 // Allocate memory for user data.
481 UserData = new unsigned char[size];
482
483 // Copy user data.
484 memcpy(UserData, data, size);
485 } else
486 UserData = NULL;
487
488 UserDataLength = size;
489 }
490 };
491
495 class event_provider : public handle<REGHANDLE, NULL>
496 {
498
499 public:
506 {
507 if (m_h != invalid)
509 }
510
520 ULONG create(_In_ LPCGUID ProviderId)
521 {
522 handle_type h;
523 ULONG ulRes = EventRegister(ProviderId, enable_callback, this, &h);
524 if (ulRes == ERROR_SUCCESS)
525 attach(h);
526 return ulRes;
527 }
528
538 ULONG write(_In_ PCEVENT_DESCRIPTOR EventDescriptor)
539 {
540 assert(m_h != invalid);
541 return EventWrite(m_h, EventDescriptor, 0, NULL);
542 }
543
553 ULONG write(_In_ PCEVENT_DESCRIPTOR EventDescriptor, _In_ ULONG UserDataCount = 0, _In_opt_count_(UserDataCount) PEVENT_DATA_DESCRIPTOR UserData = NULL)
554 {
555 assert(m_h != invalid);
556 return EventWrite(m_h, EventDescriptor, UserDataCount, UserData);
557 }
558
570 ULONG write(_In_ PCEVENT_DESCRIPTOR EventDescriptor, _In_ const EVENT_DATA_DESCRIPTOR param1, ...)
571 {
572 assert(m_h != invalid);
573
574 // The first argument (param1) is outside of varadic argument list.
575 if (param1.Ptr == winstd::blank_event_data.Ptr &&
576 param1.Size == winstd::blank_event_data.Size &&
577 param1.Reserved == winstd::blank_event_data.Reserved)
578 return EventWrite(m_h, EventDescriptor, 0, NULL);
579
580 va_list arg;
581 va_start(arg, param1);
582 va_list arg_start = arg;
583 std::vector<EVENT_DATA_DESCRIPTOR> params;
584 ULONG param_count;
585
586 // Preallocate array.
587 for (param_count = 1; param_count < MAX_EVENT_DATA_DESCRIPTORS; param_count++) {
588 const EVENT_DATA_DESCRIPTOR &p = va_arg(arg, const EVENT_DATA_DESCRIPTOR);
589 if (p.Ptr == winstd::blank_event_data.Ptr &&
590 p.Size == winstd::blank_event_data.Size &&
591 p.Reserved == winstd::blank_event_data.Reserved) break;
592 }
593 params.reserve(param_count);
594
595 // Copy parameters to array.
596 arg = arg_start;
597 params.push_back(param1);
598 for (;;) {
599 const EVENT_DATA_DESCRIPTOR &p = va_arg(arg, const EVENT_DATA_DESCRIPTOR);
600 if (p.Ptr == winstd::blank_event_data.Ptr &&
601 p.Size == winstd::blank_event_data.Size &&
602 p.Reserved == winstd::blank_event_data.Reserved) break;
603 params.push_back(p);
604 }
605
606 va_end(arg);
607#pragma warning(push)
608#pragma warning(disable: 28020)
609 return EventWrite(m_h, EventDescriptor, param_count, params.data());
610#pragma warning(pop)
611 }
612
624 ULONG write(_In_ PCEVENT_DESCRIPTOR EventDescriptor, _In_ va_list arg)
625 {
626 assert(m_h != invalid);
627
628 va_list arg_start = arg;
629 std::vector<EVENT_DATA_DESCRIPTOR> params;
630 ULONG param_count;
631
632 // Preallocate array.
633 for (param_count = 0; param_count < MAX_EVENT_DATA_DESCRIPTORS; param_count++) {
634 const EVENT_DATA_DESCRIPTOR &p = va_arg(arg, const EVENT_DATA_DESCRIPTOR);
635 if (p.Ptr == winstd::blank_event_data.Ptr &&
636 p.Size == winstd::blank_event_data.Size &&
637 p.Reserved == winstd::blank_event_data.Reserved) break;
638 }
639 params.reserve(param_count);
640
641 // Copy parameters to array.
642 arg = arg_start;
643 for (;;) {
644 const EVENT_DATA_DESCRIPTOR &p = va_arg(arg, const EVENT_DATA_DESCRIPTOR);
645 if (p.Ptr == winstd::blank_event_data.Ptr &&
646 p.Size == winstd::blank_event_data.Size &&
647 p.Reserved == winstd::blank_event_data.Reserved) break;
648 params.push_back(p);
649 }
650
651#pragma warning(push)
652#pragma warning(disable: 28020)
653 return EventWrite(m_h, EventDescriptor, param_count, params.data());
654#pragma warning(pop)
655 }
656
666 ULONG write(_In_ UCHAR Level, _In_ ULONGLONG Keyword, _In_z_ _Printf_format_string_ PCWSTR String, ...)
667 {
668 assert(m_h != invalid);
669
670 std::wstring msg;
671 va_list arg;
672
673 // Format message.
674 va_start(arg, String);
675 vsprintf(msg, String, arg);
676 va_end(arg);
677
678 // Write string event.
679 return EventWriteString(m_h, Level, Keyword, msg.c_str());
680 }
681
682 protected:
688 void free_internal() noexcept override
689 {
690 EventUnregister(m_h);
691 }
692
698 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)
699 {
700 UNREFERENCED_PARAMETER(SourceId);
701 UNREFERENCED_PARAMETER(IsEnabled);
702 UNREFERENCED_PARAMETER(Level);
703 UNREFERENCED_PARAMETER(MatchAnyKeyword);
704 UNREFERENCED_PARAMETER(MatchAllKeyword);
705 UNREFERENCED_PARAMETER(FilterData);
706 }
707
713 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)
714 {
715 if (CallbackContext)
716 static_cast<event_provider*>(CallbackContext)->enable_callback(SourceId, IsEnabled, Level, MatchAnyKeyword, MatchAllKeyword, FilterData);
717 else
718 assert(0); // Where did the "this" pointer get lost?
719 }
720 };
721
725 class event_session : public handle<TRACEHANDLE, 0>
726 {
728
729 public:
734 {
735 }
736
743 event_session(_In_opt_ handle_type h, _In_ const EVENT_TRACE_PROPERTIES *prop) :
744 m_prop(reinterpret_cast<EVENT_TRACE_PROPERTIES*>(new char[prop->Wnode.BufferSize])),
745 handle(h)
746 {
747 memcpy(m_prop.get(), prop, prop->Wnode.BufferSize);
748 }
749
755 event_session(_Inout_ event_session &&other) noexcept :
756 m_prop(std::move(other.m_prop)),
757 handle(std::move(other))
758 {
759 }
760
767 {
768 if (m_h != invalid)
770 }
771
777 event_session& operator=(_Inout_ event_session &&other) noexcept
778 {
779 if (this != std::addressof(other)) {
780 (handle<handle_type, 0>&&)*this = std::move(other);
781 m_prop = std::move(other.m_prop);
782 }
783 return *this;
784 }
785
791 operator const EVENT_TRACE_PROPERTIES*() const
792 {
793 return m_prop.get();
794 }
795
801 LPCTSTR name() const
802 {
803 const EVENT_TRACE_PROPERTIES *prop = m_prop.get();
804 return reinterpret_cast<LPCTSTR>(reinterpret_cast<const char*>(prop) + prop->LoggerNameOffset);
805 }
806
815 void attach(_In_opt_ handle_type h, _In_ EVENT_TRACE_PROPERTIES *prop)
816 {
818 m_prop.reset(prop);
819 }
820
830 ULONG create(_In_z_ LPCTSTR SessionName, _In_ const EVENT_TRACE_PROPERTIES *Properties)
831 {
832 handle_type h;
833 std::unique_ptr<EVENT_TRACE_PROPERTIES> prop(reinterpret_cast<EVENT_TRACE_PROPERTIES*>(new char[Properties->Wnode.BufferSize]));
834 memcpy(prop.get(), Properties, Properties->Wnode.BufferSize);
835 ULONG ulRes = StartTrace(&h, SessionName, prop.get());
836 if (ulRes == ERROR_SUCCESS)
837 attach(h, prop.release());
838 return ulRes;
839 }
840
850 ULONG enable_trace(_In_ LPCGUID ProviderId, _In_ UCHAR Level, _In_opt_ ULONGLONG MatchAnyKeyword = 0, _In_opt_ ULONGLONG MatchAllKeyword = 0, _In_opt_ ULONG EnableProperty = 0, _In_opt_ PEVENT_FILTER_DESCRIPTOR EnableFilterDesc = NULL)
851 {
852 assert(m_h != invalid);
853 return EnableTraceEx(
854 ProviderId,
855 &m_prop->Wnode.Guid,
856 m_h,
857 EVENT_CONTROL_CODE_ENABLE_PROVIDER,
858 Level,
859 MatchAnyKeyword,
860 MatchAllKeyword,
861 EnableProperty,
862 EnableFilterDesc);
863 }
864
874 ULONG disable_trace(_In_ LPCGUID ProviderId, _In_ UCHAR Level, _In_opt_ ULONGLONG MatchAnyKeyword = 0, _In_opt_ ULONGLONG MatchAllKeyword = 0, _In_opt_ ULONG EnableProperty = 0, _In_opt_ PEVENT_FILTER_DESCRIPTOR EnableFilterDesc = NULL)
875 {
876 assert(m_h != invalid);
877 return EnableTraceEx(
878 ProviderId,
879 &m_prop->Wnode.Guid,
880 m_h,
881 EVENT_CONTROL_CODE_DISABLE_PROVIDER,
882 Level,
883 MatchAnyKeyword,
884 MatchAllKeyword,
885 EnableProperty,
886 EnableFilterDesc);
887 }
888
889 protected:
895 void free_internal() noexcept override
896 {
897 ControlTrace(m_h, name(), m_prop.get(), EVENT_TRACE_CONTROL_STOP);
898 }
899
900 protected:
901 std::unique_ptr<EVENT_TRACE_PROPERTIES> m_prop;
902 };
903
909 class event_trace : public handle<TRACEHANDLE, INVALID_PROCESSTRACE_HANDLE>
910 {
911 WINSTD_HANDLE_IMPL(event_trace, INVALID_PROCESSTRACE_HANDLE)
912
913 public:
919 virtual ~event_trace()
920 {
921 if (m_h != invalid)
923 }
924
925 protected:
931 void free_internal() noexcept override
932 {
933 CloseTrace(m_h);
934 }
935 };
936
941 {
942 public:
949 _In_opt_ LPCGUID SourceId,
950 _In_ TRACEHANDLE TraceHandle,
951 _In_ LPCGUID ProviderId,
952 _In_ UCHAR Level,
953 _In_opt_ ULONGLONG MatchAnyKeyword = 0,
954 _In_opt_ ULONGLONG MatchAllKeyword = 0,
955 _In_opt_ ULONG EnableProperty = 0,
956 _In_opt_ PEVENT_FILTER_DESCRIPTOR EnableFilterDesc = NULL) :
957 m_provider_id(ProviderId),
958 m_source_id(SourceId),
959 m_trace_handle(TraceHandle),
960 m_level(Level),
961 m_match_any_keyword(MatchAnyKeyword),
962 m_match_all_keyword(MatchAllKeyword),
963 m_enable_property(EnableProperty),
964 m_enable_filter_desc(EnableFilterDesc)
965 {
966 m_status = EnableTraceEx(
970 EVENT_CONTROL_CODE_ENABLE_PROVIDER,
971 m_level,
976 }
977
984 _In_ const event_session &session,
985 _In_ LPCGUID ProviderId,
986 _In_ UCHAR Level,
987 _In_opt_ ULONGLONG MatchAnyKeyword = 0,
988 _In_opt_ ULONGLONG MatchAllKeyword = 0,
989 _In_opt_ ULONG EnableProperty = 0,
990 _In_opt_ PEVENT_FILTER_DESCRIPTOR EnableFilterDesc = NULL) :
991 m_provider_id(ProviderId),
992 m_source_id(&((const EVENT_TRACE_PROPERTIES*)session)->Wnode.Guid),
993 m_trace_handle(session),
994 m_level(Level),
995 m_match_any_keyword(MatchAnyKeyword),
996 m_match_all_keyword(MatchAllKeyword),
997 m_enable_property(EnableProperty),
998 m_enable_filter_desc(EnableFilterDesc)
999 {
1000 m_status = EnableTraceEx(
1004 EVENT_CONTROL_CODE_ENABLE_PROVIDER,
1005 m_level,
1010 }
1011
1017 ULONG status() const
1018 {
1019 return m_status;
1020 }
1021
1028 {
1029 if (m_status == ERROR_SUCCESS)
1030 EnableTraceEx(
1034 EVENT_CONTROL_CODE_DISABLE_PROVIDER,
1035 m_level,
1040 }
1041
1042 protected:
1043 ULONG m_status;
1045 LPCGUID m_source_id;
1046 TRACEHANDLE m_trace_handle;
1047 UCHAR m_level;
1051 PEVENT_FILTER_DESCRIPTOR m_enable_filter_desc;
1052 };
1053
1060 {
1061 public:
1065 event_fn_auto(_In_ event_provider &ep, _In_ const EVENT_DESCRIPTOR *event_cons, _In_ const EVENT_DESCRIPTOR *event_dest, _In_z_ LPCSTR pszFnName) :
1066 m_ep(ep),
1067 m_event_dest(event_dest)
1068 {
1069 EventDataDescCreate(&m_fn_name, pszFnName, (ULONG)(strlen(pszFnName) + 1)*sizeof(*pszFnName));
1070 m_ep.write(event_cons, 1, &m_fn_name);
1071 }
1072
1076 event_fn_auto(_In_ const event_fn_auto &other) :
1077 m_ep(other.m_ep),
1079 m_fn_name(other.m_fn_name)
1080 {
1081 }
1082
1086 event_fn_auto(_Inout_ event_fn_auto &&other) noexcept :
1087 m_ep(other.m_ep),
1088 m_event_dest(other.m_event_dest),
1089 m_fn_name(std::move(other.m_fn_name))
1090 {
1091 other.m_event_dest = NULL;
1092 }
1093
1098 {
1099 if (m_event_dest)
1101 }
1102
1107 {
1108 if (this != &other) {
1109 assert(&m_ep == &other.m_ep);
1110 m_event_dest = other.m_event_dest;
1111 m_fn_name = other.m_fn_name;
1112 }
1113
1114 return *this;
1115 }
1116
1120 event_fn_auto& operator=(_Inout_ event_fn_auto &&other) noexcept
1121 {
1122 if (this != &other) {
1123 assert(&m_ep == &other.m_ep);
1124 m_event_dest = other.m_event_dest;
1125 m_fn_name = std::move(other.m_fn_name);
1126 other.m_event_dest = NULL;
1127 }
1128
1129 return *this;
1130 }
1131
1132 protected:
1134 const EVENT_DESCRIPTOR *m_event_dest;
1135 EVENT_DATA_DESCRIPTOR m_fn_name;
1136 };
1137
1143 template<class T>
1145 {
1146 public:
1150 event_fn_auto_ret(_In_ event_provider &ep, _In_ const EVENT_DESCRIPTOR *event_cons, _In_ const EVENT_DESCRIPTOR *event_dest, _In_z_ LPCSTR pszFnName, T &result) :
1151 m_ep(ep),
1152 m_event_dest(event_dest),
1153 m_result(result)
1154 {
1155 EventDataDescCreate(m_desc + 0, pszFnName, (ULONG)(strlen(pszFnName) + 1)*sizeof(*pszFnName));
1156 m_ep.write(event_cons, 1, m_desc);
1157 }
1158
1163 m_ep(other.m_ep),
1165 m_result(other.m_result)
1166 {
1167 m_desc[0] = other.m_desc[0];
1168 }
1169
1174 m_ep(other.m_ep),
1176 m_result(other.m_result)
1177 {
1178 m_desc[0] = std::move(other.m_desc[0]);
1179 other.m_event_dest = NULL;
1180 }
1181
1186 {
1187 if (m_event_dest) {
1188 EventDataDescCreate(m_desc + 1, &m_result, sizeof(T));
1190 }
1191 }
1192
1197 {
1198 if (this != &other) {
1199 assert(&m_ep == &other.m_ep);
1200 m_event_dest = other.m_event_dest;
1201 m_desc[0] = other.m_desc[0];
1202 assert(&m_result == &other.m_result);
1203 }
1204
1205 return *this;
1206 }
1207
1212 {
1213 if (this != &other) {
1214 assert(&m_ep == &other.m_ep);
1215 m_event_dest = other.m_event_dest;
1216 m_desc[0] = std::move(other.m_desc[0]);
1217 assert(&m_result == &other.m_result);
1218 other.m_event_dest = NULL;
1219 }
1220
1221 return *this;
1222 }
1223
1224 protected:
1226 const EVENT_DESCRIPTOR *m_event_dest;
1227 EVENT_DATA_DESCRIPTOR m_desc[2];
1229 };
1230
1232}
General API.
EVENT_DATA_DESCRIPTOR wrapper.
Definition: ETW.h:122
event_data(const char &data)
Construct class pointing to an char.
Definition: ETW.h:142
event_data(const wchar_t *data)
Construct class pointing to a wide string.
Definition: ETW.h:252
event_data(const int &data)
Construct class pointing to an int.
Definition: ETW.h:168
event_data(const void *data, ULONG size)
Construct class pointing to binary data.
Definition: ETW.h:286
event_data(const GUID &data)
Construct class pointing to a GUID.
Definition: ETW.h:220
event_data(const unsigned int &data)
Construct class pointing to an unsigned int.
Definition: ETW.h:181
event_data(const char *data)
Construct class pointing to a string.
Definition: ETW.h:233
event_data(const unsigned char &data)
Construct class pointing to an unsigned char.
Definition: ETW.h:155
event_data(const std::basic_string< _Elem, _Traits, _Ax > &data)
Template to construct pointing to a std::basic_string<>.
Definition: ETW.h:272
event_data(const unsigned long &data)
Construct class pointing to an unsigned long.
Definition: ETW.h:207
event_data()
Construct empty class.
Definition: ETW.h:127
event_data(const long &data)
Construct class pointing to a long.
Definition: ETW.h:194
Helper template to write an event on entry/exit of scope with one parameter (typically result).
Definition: ETW.h:1145
event_fn_auto_ret(const event_fn_auto_ret< T > &other)
Copies the object.
Definition: ETW.h:1162
~event_fn_auto_ret()
Writes the event_dest event.
Definition: ETW.h:1185
EVENT_DATA_DESCRIPTOR m_desc[2]
Function name and return value.
Definition: ETW.h:1227
event_provider & m_ep
Reference to event provider in use.
Definition: ETW.h:1225
event_fn_auto_ret(event_provider &ep, const EVENT_DESCRIPTOR *event_cons, const EVENT_DESCRIPTOR *event_dest, LPCSTR pszFnName, T &result)
Writes the event_cons event.
Definition: ETW.h:1150
T & m_result
Function result.
Definition: ETW.h:1228
event_fn_auto_ret & operator=(const event_fn_auto_ret< T > &other)
Copies the object.
Definition: ETW.h:1196
const EVENT_DESCRIPTOR * m_event_dest
Event descriptor at destruction.
Definition: ETW.h:1226
event_fn_auto_ret(event_fn_auto_ret< T > &&other)
Moves the object.
Definition: ETW.h:1173
event_fn_auto_ret & operator=(event_fn_auto_ret< T > &&other)
Moves the object.
Definition: ETW.h:1211
Helper class to write an event on entry/exit of scope.
Definition: ETW.h:1060
const EVENT_DESCRIPTOR * m_event_dest
Event descriptor at destruction.
Definition: ETW.h:1134
event_fn_auto(event_fn_auto &&other) noexcept
Moves the object.
Definition: ETW.h:1086
event_fn_auto(event_provider &ep, const EVENT_DESCRIPTOR *event_cons, const EVENT_DESCRIPTOR *event_dest, LPCSTR pszFnName)
Writes the event_cons event.
Definition: ETW.h:1065
~event_fn_auto()
Writes the event_dest event.
Definition: ETW.h:1097
event_fn_auto & operator=(event_fn_auto &&other) noexcept
Moves the object.
Definition: ETW.h:1120
event_fn_auto & operator=(const event_fn_auto &other)
Copies the object.
Definition: ETW.h:1106
event_provider & m_ep
Reference to event provider in use.
Definition: ETW.h:1133
EVENT_DATA_DESCRIPTOR m_fn_name
Function name.
Definition: ETW.h:1135
event_fn_auto(const event_fn_auto &other)
Copies the object.
Definition: ETW.h:1076
ETW event provider.
Definition: ETW.h:496
ULONG write(PCEVENT_DESCRIPTOR EventDescriptor)
Writes an event with no parameters.
Definition: ETW.h:538
ULONG write(PCEVENT_DESCRIPTOR EventDescriptor, ULONG UserDataCount=0, PEVENT_DATA_DESCRIPTOR UserData=NULL)
Writes an event with parameters stored in array.
Definition: ETW.h:553
ULONG write(UCHAR Level, ULONGLONG Keyword, PCWSTR String,...)
Writes a string event.
Definition: ETW.h:666
ULONG write(PCEVENT_DESCRIPTOR EventDescriptor, va_list arg)
Writes an event with variable number of parameters.
Definition: ETW.h:624
virtual ~event_provider()
Closes the event provider.
Definition: ETW.h:505
virtual void enable_callback(LPCGUID SourceId, ULONG IsEnabled, UCHAR Level, ULONGLONG MatchAnyKeyword, ULONGLONG MatchAllKeyword, PEVENT_FILTER_DESCRIPTOR FilterData)
Receive enable or disable notification requests.
Definition: ETW.h:698
void free_internal() noexcept override
Releases the event provider.
Definition: ETW.h:688
ULONG write(PCEVENT_DESCRIPTOR EventDescriptor, const EVENT_DATA_DESCRIPTOR param1,...)
Writes an event with one or more parameter.
Definition: ETW.h:570
static VOID NTAPI enable_callback(LPCGUID SourceId, ULONG IsEnabled, UCHAR Level, ULONGLONG MatchAnyKeyword, ULONGLONG MatchAllKeyword, PEVENT_FILTER_DESCRIPTOR FilterData, PVOID CallbackContext)
Receive enable or disable notification requests.
Definition: ETW.h:713
ULONG create(LPCGUID ProviderId)
Registers the event provider.
Definition: ETW.h:520
EVENT_RECORD wrapper.
Definition: ETW.h:301
void set_extended_data_internal(USHORT count, const EVENT_HEADER_EXTENDED_DATA_ITEM *data)
Sets event record extended data.
Definition: ETW.h:437
void set_user_data(USHORT size, LPCVOID data)
Sets event record user data.
Definition: ETW.h:422
event_rec & operator=(event_rec &&other) noexcept
Moves the event record.
Definition: ETW.h:392
~event_rec()
Destroys event record data and frees the allocated memory.
Definition: ETW.h:346
event_rec & operator=(const EVENT_RECORD &other)
Copies an existing event record.
Definition: ETW.h:376
event_rec(const EVENT_RECORD &other)
Copies an existing event record.
Definition: ETW.h:327
event_rec & operator=(const event_rec &other)
Copies an existing event record.
Definition: ETW.h:360
void set_extended_data(USHORT count, const EVENT_HEADER_EXTENDED_DATA_ITEM *data)
Sets event record extended data.
Definition: ETW.h:408
event_rec(event_rec &&other) noexcept
Moves the event record.
Definition: ETW.h:338
event_rec()
Constructs a blank event record.
Definition: ETW.h:306
void set_user_data_internal(USHORT size, LPCVOID data)
Sets event record user data.
Definition: ETW.h:475
event_rec(const event_rec &other)
Copies an existing event record.
Definition: ETW.h:316
ETW session.
Definition: ETW.h:726
LPCTSTR name() const
Auto-typecasting operator.
Definition: ETW.h:801
event_session(event_session &&other) noexcept
Move constructor.
Definition: ETW.h:755
event_session(handle_type h, const EVENT_TRACE_PROPERTIES *prop)
Initializes a new session with an already available object handle.
Definition: ETW.h:743
event_session()
Initializes a new empty session.
Definition: ETW.h:733
virtual ~event_session()
Closes the session.
Definition: ETW.h:766
void free_internal() noexcept override
Releases the session.
Definition: ETW.h:895
event_session & operator=(event_session &&other) noexcept
Move assignment.
Definition: ETW.h:777
ULONG disable_trace(LPCGUID ProviderId, UCHAR Level, ULONGLONG MatchAnyKeyword=0, ULONGLONG MatchAllKeyword=0, ULONG EnableProperty=0, PEVENT_FILTER_DESCRIPTOR EnableFilterDesc=NULL)
Disables the specified event trace provider.
Definition: ETW.h:874
ULONG enable_trace(LPCGUID ProviderId, UCHAR Level, ULONGLONG MatchAnyKeyword=0, ULONGLONG MatchAllKeyword=0, ULONG EnableProperty=0, PEVENT_FILTER_DESCRIPTOR EnableFilterDesc=NULL)
Enables the specified event trace provider.
Definition: ETW.h:850
std::unique_ptr< EVENT_TRACE_PROPERTIES > m_prop
Session properties.
Definition: ETW.h:901
ULONG create(LPCTSTR SessionName, const EVENT_TRACE_PROPERTIES *Properties)
Registers and starts an event tracing session.
Definition: ETW.h:830
void attach(handle_type h, EVENT_TRACE_PROPERTIES *prop)
Sets a new session handle for the class.
Definition: ETW.h:815
Helper class to enable event provider in constructor and disables it in destructor.
Definition: ETW.h:941
UCHAR m_level
Logging level.
Definition: ETW.h:1047
PEVENT_FILTER_DESCRIPTOR m_enable_filter_desc
Event filter descriptor.
Definition: ETW.h:1051
ULONGLONG m_match_any_keyword
Keyword match mask (any)
Definition: ETW.h:1048
event_trace_enabler(LPCGUID SourceId, TRACEHANDLE TraceHandle, LPCGUID ProviderId, UCHAR Level, ULONGLONG MatchAnyKeyword=0, ULONGLONG MatchAllKeyword=0, ULONG EnableProperty=0, PEVENT_FILTER_DESCRIPTOR EnableFilterDesc=NULL)
Enables event trace.
Definition: ETW.h:948
ULONG m_status
Result of EnableTraceEx call.
Definition: ETW.h:1043
TRACEHANDLE m_trace_handle
Trace handle.
Definition: ETW.h:1046
virtual ~event_trace_enabler()
Disables event trace.
Definition: ETW.h:1027
ULONG status() const
Return result of EnableTraceEx() call.
Definition: ETW.h:1017
event_trace_enabler(const event_session &session, LPCGUID ProviderId, UCHAR Level, ULONGLONG MatchAnyKeyword=0, ULONGLONG MatchAllKeyword=0, ULONG EnableProperty=0, PEVENT_FILTER_DESCRIPTOR EnableFilterDesc=NULL)
Enables event trace.
Definition: ETW.h:983
ULONGLONG m_match_all_keyword
Keyword match mask (all)
Definition: ETW.h:1049
LPCGUID m_provider_id
Provider ID.
Definition: ETW.h:1044
LPCGUID m_source_id
Session ID.
Definition: ETW.h:1045
ULONG m_enable_property
Enable property.
Definition: ETW.h:1050
ETW trace.
Definition: ETW.h:910
virtual ~event_trace()
Closes the trace.
Definition: ETW.h:919
void free_internal() noexcept override
Closes the trace.
Definition: ETW.h:931
Base abstract template class to support generic object handle keeping.
Definition: Common.h:615
handle() noexcept
Initializes a new class instance with the object handle set to INVAL.
Definition: Common.h:630
REGHANDLE handle_type
Datatype of the object handle this template class handles.
Definition: Common.h:620
handle_type m_h
Object handle.
Definition: Common.h:866
void attach(handle_type h) noexcept
Sets a new object handle for the class.
Definition: Common.h:829
static ULONG TdhGetEventInformation(PEVENT_RECORD pEvent, ULONG TdhContextCount, PTDH_CONTEXT pTdhContext, std::unique_ptr< TRACE_EVENT_INFO > &info)
Retrieves metadata about an event.
Definition: ETW.h:62
static ULONG TdhGetProperty(PEVENT_RECORD pEvent, ULONG TdhContextCount, PTDH_CONTEXT pTdhContext, ULONG PropertyDataCount, PPROPERTY_DATA_DESCRIPTOR pPropertyData, std::vector< _Ty, _Ax > &aData)
Retrieves a property value from the event data.
Definition: ETW.h:37
static ULONG TdhGetEventMapInformation(PEVENT_RECORD pEvent, LPWSTR pMapName, std::unique_ptr< EVENT_MAP_INFO > &info)
Retrieves information about the event map contained in the event.
Definition: ETW.h:88
static const event_data blank_event_data
Blank event data used as terminator.
Definition: ETW.h:295
#define WINSTD_NONCOPYABLE(C)
Declares a class as non-copyable.
Definition: Common.h:74
#define WINSTD_STACK_BUFFER_BYTES
Size of the stack buffer in bytes used for initial system function call.
Definition: Common.h:101
static int vsprintf(std::basic_string< _Elem, _Traits, _Ax > &str, const _Elem *format, va_list arg)
Formats string using printf().
Definition: Common.h:259
#define WINSTD_HANDLE_IMPL(C, INVAL)
Implements default constructors and operators to prevent their auto-generation by compiler.
Definition: Common.h:171
static const REGHANDLE invalid
Invalid handle value.
Definition: Common.h:625