WinStd
Windows Win32 API using Standard C++
Loading...
Searching...
No Matches
ETW.h
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 1991-2022 Amebis
4 Copyright © 2016 GÉANT
5*/
6
8
9#pragma once
10
11#include "Common.h"
12#include <assert.h>
13#include <evntprov.h>
14#include <evntcons.h>
15#include <stdarg.h>
16#include <tdh.h>
17#include <memory>
18#include <string>
19#include <vector>
20
21#pragma warning(push)
22#pragma warning(disable: 4505) // Don't warn on unused code
23
26
32template<class _Ty, class _Ax>
33static _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)
34{
35 ULONG ulSize, ulResult;
36
37 // Query property size.
38 ulResult = TdhGetPropertySize(pEvent, TdhContextCount, pTdhContext, PropertyDataCount, pPropertyData, &ulSize);
39 if (ulResult == ERROR_SUCCESS) {
40 if (ulSize) {
41 // Query property value.
42 aData.resize((ulSize + sizeof(_Ty) - 1) / sizeof(_Ty));
43 ulResult = TdhGetProperty(pEvent, TdhContextCount, pTdhContext, PropertyDataCount, pPropertyData, ulSize, reinterpret_cast<PBYTE>(aData.data()));
44 } else {
45 // Property value size is zero.
46 aData.clear();
47 }
48 }
49
50 return ulResult;
51}
52
58static _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)
59{
60 BYTE szBuffer[WINSTD_STACK_BUFFER_BYTES];
61 ULONG ulSize = sizeof(szBuffer), ulResult;
62
63 // Try with stack buffer first.
64 ulResult = TdhGetEventInformation(pEvent, TdhContextCount, pTdhContext, (PTRACE_EVENT_INFO)szBuffer, &ulSize);
65 if (ulResult == ERROR_SUCCESS) {
66 // Copy from stack.
67 info.reset(reinterpret_cast<PTRACE_EVENT_INFO>(new char[ulSize]));
68 memcpy(info.get(), szBuffer, ulSize);
69 return ERROR_SUCCESS;
70 } else if (ulResult == ERROR_INSUFFICIENT_BUFFER) {
71 // Create buffer on heap and retry.
72 info.reset(reinterpret_cast<PTRACE_EVENT_INFO>(new char[ulSize]));
73 return TdhGetEventInformation(pEvent, TdhContextCount, pTdhContext, info.get(), &ulSize);
74 }
75
76 return ulResult;
77}
78
84static _Success_(return == ERROR_SUCCESS) ULONG TdhGetEventMapInformation(_In_ PEVENT_RECORD pEvent, _In_ LPWSTR pMapName, _Inout_ std::unique_ptr<EVENT_MAP_INFO> &info)
85{
86 BYTE szBuffer[WINSTD_STACK_BUFFER_BYTES];
87 ULONG ulSize = sizeof(szBuffer), ulResult;
88
89 // Try with stack buffer first.
90 ulResult = TdhGetEventMapInformation(pEvent, pMapName, (PEVENT_MAP_INFO)szBuffer, &ulSize);
91 if (ulResult == ERROR_SUCCESS) {
92 // Copy from stack.
93 info.reset(reinterpret_cast<PEVENT_MAP_INFO>(new char[ulSize]));
94 memcpy(info.get(), szBuffer, ulSize);
95 return ERROR_SUCCESS;
96 } else if (ulResult == ERROR_INSUFFICIENT_BUFFER) {
97 // Create buffer on heap and retry.
98 info.reset(reinterpret_cast<PEVENT_MAP_INFO>(new char[ulSize]));
99 return TdhGetEventMapInformation(pEvent, pMapName, info.get(), &ulSize);
100 }
101
102 return ulResult;
103}
104
106
107#pragma warning(pop)
108
109namespace winstd
110{
113
117 class event_data : public EVENT_DATA_DESCRIPTOR
118 {
119 public:
124 {
125 Ptr = 0;
126 Size = 0;
127 Reserved = (ULONG)-1; // Used for varadic argument terminator.
128 }
129
137 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
138 event_data(_In_ const char &data)
139 {
140 EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
141 }
142
150 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
151 event_data(_In_ const unsigned char &data)
152 {
153 EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
154 }
155
163 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
164 event_data(_In_ const int &data)
165 {
166 EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
167 }
168
176 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
177 event_data(_In_ const unsigned int &data)
178 {
179 EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
180 }
181
189 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
190 event_data(_In_ const long &data)
191 {
192 EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
193 }
194
202 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
203 event_data(_In_ const unsigned long &data)
204 {
205 EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
206 }
207
215 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
216 event_data(_In_ const GUID &data)
217 {
218 EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
219 }
220
228 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
229 event_data(_In_opt_z_ const char *data)
230 {
231 if (data)
232 EventDataDescCreate(this, data, (ULONG)((strlen(data) + 1) * sizeof(*data)));
233 else {
234 // Writing NULL pointer with 0B length causes trouble in Event Viewer: message template string is displayed only, parameters are not rendered.
235 static const char null[] = "(null)";
236 EventDataDescCreate(this, null, sizeof(null));
237 }
238 }
239
247 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
248 event_data(_In_opt_z_ const wchar_t *data)
249 {
250 if (data)
251 EventDataDescCreate(this, data, (ULONG)((wcslen(data) + 1) * sizeof(*data)));
252 else {
253 // Writing NULL pointer with 0B length causes trouble in Event Viewer: message template string is displayed only, parameters are not rendered.
254 static const wchar_t null[] = L"(null)";
255 EventDataDescCreate(this, null, sizeof(null));
256 }
257 }
258
266 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
267 template<class _Elem, class _Traits, class _Ax>
268 event_data(_In_ const std::basic_string<_Elem, _Traits, _Ax> &data)
269 {
270 EventDataDescCreate(this, data.c_str(), (ULONG)((data.length() + 1) * sizeof(_Elem)));
271 }
272
281 #pragma warning(suppress: 26495) // EventDataDescCreate() initializes all members of EVENT_DATA_DESCRIPTOR
282 event_data(_In_bytecount_(size) const void *data, _In_ ULONG size)
283 {
284 EventDataDescCreate(this, data, size);
285 }
286 };
287
292
296 class event_rec : public EVENT_RECORD
297 {
298 public:
303 {
304 memset((EVENT_RECORD*)this, 0, sizeof(EVENT_RECORD));
305 }
306
312 event_rec(_In_ const event_rec &other) : EVENT_RECORD(other)
313 {
314 set_extended_data_internal(other.ExtendedDataCount, other.ExtendedData);
315 set_user_data_internal(other.UserDataLength, other.UserData);
316 }
317
323 event_rec(_In_ const EVENT_RECORD &other) : EVENT_RECORD(other)
324 {
325 set_extended_data_internal(other.ExtendedDataCount, other.ExtendedData);
326 set_user_data_internal(other.UserDataLength, other.UserData);
327 }
328
334 event_rec(_Inout_ event_rec&& other) noexcept : EVENT_RECORD(other)
335 {
336 memset((EVENT_RECORD*)&other, 0, sizeof(EVENT_RECORD));
337 }
338
343 {
344 if (ExtendedData)
345 delete reinterpret_cast<unsigned char*>(ExtendedData);
346
347 if (UserData)
348 delete reinterpret_cast<unsigned char*>(UserData);
349 }
350
356 event_rec& operator=(_In_ const event_rec &other)
357 {
358 if (this != std::addressof(other)) {
359 (EVENT_RECORD&)*this = other;
360 set_extended_data_internal(other.ExtendedDataCount, other.ExtendedData);
361 set_user_data_internal(other.UserDataLength, other.UserData);
362 }
363
364 return *this;
365 }
366
372 event_rec& operator=(_In_ const EVENT_RECORD &other)
373 {
374 if (this != std::addressof(other)) {
375 (EVENT_RECORD&)*this = other;
376 set_extended_data_internal(other.ExtendedDataCount, other.ExtendedData);
377 set_user_data_internal(other.UserDataLength, other.UserData);
378 }
379
380 return *this;
381 }
382
388 event_rec& operator=(_Inout_ event_rec&& other) noexcept
389 {
390 if (this != std::addressof(other)) {
391 (EVENT_RECORD&)*this = other;
392 memset((EVENT_RECORD*)&other, 0, sizeof(EVENT_RECORD));
393 }
394
395 return *this;
396 }
397
404 void set_extended_data(_In_ USHORT count, _In_count_(count) const EVENT_HEADER_EXTENDED_DATA_ITEM *data)
405 {
406 if (ExtendedData)
407 delete reinterpret_cast<unsigned char*>(ExtendedData);
408
409 set_extended_data_internal(count, data);
410 }
411
418 void set_user_data(_In_ USHORT size, _In_bytecount_(size) LPCVOID data)
419 {
420 if (UserData)
421 delete reinterpret_cast<unsigned char*>(UserData);
422
423 set_user_data_internal(size, data);
424 }
425
426 protected:
433 void set_extended_data_internal(_In_ USHORT count, _In_count_(count) const EVENT_HEADER_EXTENDED_DATA_ITEM *data)
434 {
435 if (count) {
436 assert(data);
437
438 // Count the total required memory.
439 size_t data_size = 0;
440 for (size_t i = 0; i < count; i++)
441 data_size += data[i].DataSize;
442
443 // Allocate memory for extended data.
444 ExtendedData = reinterpret_cast<EVENT_HEADER_EXTENDED_DATA_ITEM*>(new unsigned char[sizeof(EVENT_HEADER_EXTENDED_DATA_ITEM)*count + data_size]);
445
446 // Bulk-copy extended data descriptors.
447 memcpy(ExtendedData, data, sizeof(EVENT_HEADER_EXTENDED_DATA_ITEM) * count);
448
449 // Copy the data.
450 unsigned char *ptr = reinterpret_cast<unsigned char*>(ExtendedData + count);
451 for (size_t i = 0; i < count; i++) {
452 if (data[i].DataSize) {
453 memcpy(ptr, (void*)(data[i].DataPtr), data[i].DataSize);
454 ExtendedData[i].DataPtr = (ULONGLONG)ptr;
455 ptr += data[i].DataSize;
456 } else
457 ExtendedData[i].DataPtr = NULL;
458 }
459 } else
460 ExtendedData = NULL;
461
462 ExtendedDataCount = count;
463 }
464
471 void set_user_data_internal(_In_ USHORT size, _In_bytecount_(size) LPCVOID data)
472 {
473 if (size) {
474 assert(data);
475
476 // Allocate memory for user data.
477 UserData = new unsigned char[size];
478
479 // Copy user data.
480 memcpy(UserData, data, size);
481 } else
482 UserData = NULL;
483
484 UserDataLength = size;
485 }
486 };
487
491 class event_provider : public handle<REGHANDLE, NULL>
492 {
494
495 public:
502 {
503 if (m_h != invalid)
505 }
506
516 ULONG create(_In_ LPCGUID ProviderId)
517 {
518 handle_type h;
519 ULONG ulRes = EventRegister(ProviderId, enable_callback, this, &h);
520 if (ulRes == ERROR_SUCCESS)
521 attach(h);
522 return ulRes;
523 }
524
534 ULONG write(_In_ PCEVENT_DESCRIPTOR EventDescriptor)
535 {
536 assert(m_h != invalid);
537 return EventWrite(m_h, EventDescriptor, 0, NULL);
538 }
539
549 ULONG write(_In_ PCEVENT_DESCRIPTOR EventDescriptor, _In_ ULONG UserDataCount = 0, _In_opt_count_(UserDataCount) PEVENT_DATA_DESCRIPTOR UserData = NULL)
550 {
551 assert(m_h != invalid);
552 return EventWrite(m_h, EventDescriptor, UserDataCount, UserData);
553 }
554
566 ULONG write(_In_ PCEVENT_DESCRIPTOR EventDescriptor, _In_ const EVENT_DATA_DESCRIPTOR param1, ...)
567 {
568 assert(m_h != invalid);
569
570 // The first argument (param1) is outside of varadic argument list.
571 if (param1.Ptr == winstd::blank_event_data.Ptr &&
572 param1.Size == winstd::blank_event_data.Size &&
573 param1.Reserved == winstd::blank_event_data.Reserved)
574 return EventWrite(m_h, EventDescriptor, 0, NULL);
575
576 va_list arg;
577 va_start(arg, param1);
578 va_list arg_start = arg;
579 std::vector<EVENT_DATA_DESCRIPTOR> params;
580 ULONG param_count;
581
582 // Preallocate array.
583 for (param_count = 1; param_count < MAX_EVENT_DATA_DESCRIPTORS; param_count++) {
584 const EVENT_DATA_DESCRIPTOR &p = va_arg(arg, const EVENT_DATA_DESCRIPTOR);
585 if (p.Ptr == winstd::blank_event_data.Ptr &&
586 p.Size == winstd::blank_event_data.Size &&
587 p.Reserved == winstd::blank_event_data.Reserved) break;
588 }
589 params.reserve(param_count);
590
591 // Copy parameters to array.
592 arg = arg_start;
593 params.push_back(param1);
594 for (;;) {
595 const EVENT_DATA_DESCRIPTOR &p = va_arg(arg, const EVENT_DATA_DESCRIPTOR);
596 if (p.Ptr == winstd::blank_event_data.Ptr &&
597 p.Size == winstd::blank_event_data.Size &&
598 p.Reserved == winstd::blank_event_data.Reserved) break;
599 params.push_back(p);
600 }
601
602 va_end(arg);
603#pragma warning(push)
604#pragma warning(disable: 28020)
605 return EventWrite(m_h, EventDescriptor, param_count, params.data());
606#pragma warning(pop)
607 }
608
620 ULONG write(_In_ PCEVENT_DESCRIPTOR EventDescriptor, _In_ va_list arg)
621 {
622 assert(m_h != invalid);
623
624 va_list arg_start = arg;
625 std::vector<EVENT_DATA_DESCRIPTOR> params;
626 ULONG param_count;
627
628 // Preallocate array.
629 for (param_count = 0; param_count < MAX_EVENT_DATA_DESCRIPTORS; param_count++) {
630 const EVENT_DATA_DESCRIPTOR &p = va_arg(arg, const EVENT_DATA_DESCRIPTOR);
631 if (p.Ptr == winstd::blank_event_data.Ptr &&
632 p.Size == winstd::blank_event_data.Size &&
633 p.Reserved == winstd::blank_event_data.Reserved) break;
634 }
635 params.reserve(param_count);
636
637 // Copy parameters to array.
638 arg = arg_start;
639 for (;;) {
640 const EVENT_DATA_DESCRIPTOR &p = va_arg(arg, const EVENT_DATA_DESCRIPTOR);
641 if (p.Ptr == winstd::blank_event_data.Ptr &&
642 p.Size == winstd::blank_event_data.Size &&
643 p.Reserved == winstd::blank_event_data.Reserved) break;
644 params.push_back(p);
645 }
646
647#pragma warning(push)
648#pragma warning(disable: 28020)
649 return EventWrite(m_h, EventDescriptor, param_count, params.data());
650#pragma warning(pop)
651 }
652
662 ULONG write(_In_ UCHAR Level, _In_ ULONGLONG Keyword, _In_z_ _Printf_format_string_ PCWSTR String, ...)
663 {
664 assert(m_h != invalid);
665
666 std::wstring msg;
667 va_list arg;
668
669 // Format message.
670 va_start(arg, String);
671 vsprintf(msg, String, arg);
672 va_end(arg);
673
674 // Write string event.
675 return EventWriteString(m_h, Level, Keyword, msg.c_str());
676 }
677
678 protected:
684 void free_internal() noexcept override
685 {
686 EventUnregister(m_h);
687 }
688
694 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)
695 {
696 UNREFERENCED_PARAMETER(SourceId);
697 UNREFERENCED_PARAMETER(IsEnabled);
698 UNREFERENCED_PARAMETER(Level);
699 UNREFERENCED_PARAMETER(MatchAnyKeyword);
700 UNREFERENCED_PARAMETER(MatchAllKeyword);
701 UNREFERENCED_PARAMETER(FilterData);
702 }
703
709 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)
710 {
711 if (CallbackContext)
712 static_cast<event_provider*>(CallbackContext)->enable_callback(SourceId, IsEnabled, Level, MatchAnyKeyword, MatchAllKeyword, FilterData);
713 else
714 assert(0); // Where did the "this" pointer get lost?
715 }
716 };
717
721 class event_session : public handle<TRACEHANDLE, 0>
722 {
724
725 public:
730 {
731 }
732
739 event_session(_In_opt_ handle_type h, _In_ const EVENT_TRACE_PROPERTIES *prop) :
740 m_prop(reinterpret_cast<EVENT_TRACE_PROPERTIES*>(new char[prop->Wnode.BufferSize])),
741 handle(h)
742 {
743 memcpy(m_prop.get(), prop, prop->Wnode.BufferSize);
744 }
745
751 event_session(_Inout_ event_session &&other) noexcept :
752 m_prop(std::move(other.m_prop)),
753 handle(std::move(other))
754 {
755 }
756
763 {
764 if (m_h != invalid)
766 }
767
773 event_session& operator=(_Inout_ event_session &&other) noexcept
774 {
775 if (this != std::addressof(other)) {
776 (handle<handle_type, 0>&&)*this = std::move(other);
777 m_prop = std::move(other.m_prop);
778 }
779 return *this;
780 }
781
787 operator const EVENT_TRACE_PROPERTIES*() const
788 {
789 return m_prop.get();
790 }
791
797 LPCTSTR name() const
798 {
799 const EVENT_TRACE_PROPERTIES *prop = m_prop.get();
800 return reinterpret_cast<LPCTSTR>(reinterpret_cast<LPCBYTE>(prop) + prop->LoggerNameOffset);
801 }
802
811 void attach(_In_opt_ handle_type h, _In_ EVENT_TRACE_PROPERTIES *prop)
812 {
814 m_prop.reset(prop);
815 }
816
826 ULONG create(_In_z_ LPCTSTR SessionName, _In_ const EVENT_TRACE_PROPERTIES *Properties)
827 {
828 handle_type h;
829 std::unique_ptr<EVENT_TRACE_PROPERTIES> prop(reinterpret_cast<EVENT_TRACE_PROPERTIES*>(new char[Properties->Wnode.BufferSize]));
830 memcpy(prop.get(), Properties, Properties->Wnode.BufferSize);
831 ULONG ulRes = StartTrace(&h, SessionName, prop.get());
832 if (ulRes == ERROR_SUCCESS)
833 attach(h, prop.release());
834 return ulRes;
835 }
836
846 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)
847 {
848 assert(m_h != invalid);
849 return EnableTraceEx(
850 ProviderId,
851 &m_prop->Wnode.Guid,
852 m_h,
853 EVENT_CONTROL_CODE_ENABLE_PROVIDER,
854 Level,
855 MatchAnyKeyword,
856 MatchAllKeyword,
857 EnableProperty,
858 EnableFilterDesc);
859 }
860
870 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)
871 {
872 assert(m_h != invalid);
873 return EnableTraceEx(
874 ProviderId,
875 &m_prop->Wnode.Guid,
876 m_h,
877 EVENT_CONTROL_CODE_DISABLE_PROVIDER,
878 Level,
879 MatchAnyKeyword,
880 MatchAllKeyword,
881 EnableProperty,
882 EnableFilterDesc);
883 }
884
885 protected:
891 void free_internal() noexcept override
892 {
893 ControlTrace(m_h, name(), m_prop.get(), EVENT_TRACE_CONTROL_STOP);
894 }
895
896 protected:
897 std::unique_ptr<EVENT_TRACE_PROPERTIES> m_prop;
898 };
899
905 class event_trace : public handle<TRACEHANDLE, INVALID_PROCESSTRACE_HANDLE>
906 {
907 WINSTD_HANDLE_IMPL(event_trace, INVALID_PROCESSTRACE_HANDLE)
908
909 public:
915 virtual ~event_trace()
916 {
917 if (m_h != invalid)
919 }
920
921 protected:
927 void free_internal() noexcept override
928 {
929 CloseTrace(m_h);
930 }
931 };
932
937 {
938 public:
945 _In_opt_ LPCGUID SourceId,
946 _In_ TRACEHANDLE TraceHandle,
947 _In_ LPCGUID ProviderId,
948 _In_ UCHAR Level,
949 _In_opt_ ULONGLONG MatchAnyKeyword = 0,
950 _In_opt_ ULONGLONG MatchAllKeyword = 0,
951 _In_opt_ ULONG EnableProperty = 0,
952 _In_opt_ PEVENT_FILTER_DESCRIPTOR EnableFilterDesc = NULL) :
953 m_provider_id(ProviderId),
954 m_source_id(SourceId),
955 m_trace_handle(TraceHandle),
956 m_level(Level),
957 m_match_any_keyword(MatchAnyKeyword),
958 m_match_all_keyword(MatchAllKeyword),
959 m_enable_property(EnableProperty),
960 m_enable_filter_desc(EnableFilterDesc)
961 {
962 m_status = EnableTraceEx(
966 EVENT_CONTROL_CODE_ENABLE_PROVIDER,
967 m_level,
972 }
973
980 _In_ const event_session &session,
981 _In_ LPCGUID ProviderId,
982 _In_ UCHAR Level,
983 _In_opt_ ULONGLONG MatchAnyKeyword = 0,
984 _In_opt_ ULONGLONG MatchAllKeyword = 0,
985 _In_opt_ ULONG EnableProperty = 0,
986 _In_opt_ PEVENT_FILTER_DESCRIPTOR EnableFilterDesc = NULL) :
987 m_provider_id(ProviderId),
988 m_source_id(&((const EVENT_TRACE_PROPERTIES*)session)->Wnode.Guid),
989 m_trace_handle(session),
990 m_level(Level),
991 m_match_any_keyword(MatchAnyKeyword),
992 m_match_all_keyword(MatchAllKeyword),
993 m_enable_property(EnableProperty),
994 m_enable_filter_desc(EnableFilterDesc)
995 {
996 m_status = EnableTraceEx(
1000 EVENT_CONTROL_CODE_ENABLE_PROVIDER,
1001 m_level,
1006 }
1007
1013 ULONG status() const
1014 {
1015 return m_status;
1016 }
1017
1024 {
1025 if (m_status == ERROR_SUCCESS)
1026 EnableTraceEx(
1030 EVENT_CONTROL_CODE_DISABLE_PROVIDER,
1031 m_level,
1036 }
1037
1038 protected:
1039 ULONG m_status;
1041 LPCGUID m_source_id;
1042 TRACEHANDLE m_trace_handle;
1043 UCHAR m_level;
1047 PEVENT_FILTER_DESCRIPTOR m_enable_filter_desc;
1048 };
1049
1056 {
1057 public:
1061 event_fn_auto(_In_ event_provider &ep, _In_ const EVENT_DESCRIPTOR *event_cons, _In_ const EVENT_DESCRIPTOR *event_dest, _In_z_ LPCSTR pszFnName) :
1062 m_ep(ep),
1063 m_event_dest(event_dest)
1064 {
1065 EventDataDescCreate(&m_fn_name, pszFnName, (ULONG)(strlen(pszFnName) + 1)*sizeof(*pszFnName));
1066 m_ep.write(event_cons, 1, &m_fn_name);
1067 }
1068
1072 event_fn_auto(_In_ const event_fn_auto &other) :
1073 m_ep(other.m_ep),
1075 m_fn_name(other.m_fn_name)
1076 {
1077 }
1078
1082 event_fn_auto(_Inout_ event_fn_auto &&other) noexcept :
1083 m_ep(other.m_ep),
1084 m_event_dest(other.m_event_dest),
1085 m_fn_name(std::move(other.m_fn_name))
1086 {
1087 other.m_event_dest = NULL;
1088 }
1089
1094 {
1095 if (m_event_dest)
1097 }
1098
1103 {
1104 if (this != &other) {
1105 assert(&m_ep == &other.m_ep);
1106 m_event_dest = other.m_event_dest;
1107 m_fn_name = other.m_fn_name;
1108 }
1109
1110 return *this;
1111 }
1112
1116 event_fn_auto& operator=(_Inout_ event_fn_auto &&other) noexcept
1117 {
1118 if (this != &other) {
1119 assert(&m_ep == &other.m_ep);
1120 m_event_dest = other.m_event_dest;
1121 m_fn_name = std::move(other.m_fn_name);
1122 other.m_event_dest = NULL;
1123 }
1124
1125 return *this;
1126 }
1127
1128 protected:
1130 const EVENT_DESCRIPTOR *m_event_dest;
1131 EVENT_DATA_DESCRIPTOR m_fn_name;
1132 };
1133
1139 template<class T>
1141 {
1142 public:
1146 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) :
1147 m_ep(ep),
1148 m_event_dest(event_dest),
1149 m_result(result)
1150 {
1151 EventDataDescCreate(m_desc + 0, pszFnName, (ULONG)(strlen(pszFnName) + 1)*sizeof(*pszFnName));
1152 m_ep.write(event_cons, 1, m_desc);
1153 }
1154
1159 m_ep(other.m_ep),
1161 m_result(other.m_result)
1162 {
1163 m_desc[0] = other.m_desc[0];
1164 }
1165
1170 m_ep(other.m_ep),
1172 m_result(other.m_result)
1173 {
1174 m_desc[0] = std::move(other.m_desc[0]);
1175 other.m_event_dest = NULL;
1176 }
1177
1182 {
1183 if (m_event_dest) {
1184 EventDataDescCreate(m_desc + 1, &m_result, sizeof(T));
1186 }
1187 }
1188
1193 {
1194 if (this != &other) {
1195 assert(&m_ep == &other.m_ep);
1196 m_event_dest = other.m_event_dest;
1197 m_desc[0] = other.m_desc[0];
1198 assert(&m_result == &other.m_result);
1199 }
1200
1201 return *this;
1202 }
1203
1208 {
1209 if (this != &other) {
1210 assert(&m_ep == &other.m_ep);
1211 m_event_dest = other.m_event_dest;
1212 m_desc[0] = std::move(other.m_desc[0]);
1213 assert(&m_result == &other.m_result);
1214 other.m_event_dest = NULL;
1215 }
1216
1217 return *this;
1218 }
1219
1220 protected:
1222 const EVENT_DESCRIPTOR *m_event_dest;
1223 EVENT_DATA_DESCRIPTOR m_desc[2];
1225 };
1226
1228}
EVENT_DATA_DESCRIPTOR wrapper.
Definition: ETW.h:118
event_data(const char &data)
Construct class pointing to an char.
Definition: ETW.h:138
event_data(const wchar_t *data)
Construct class pointing to a wide string.
Definition: ETW.h:248
event_data(const int &data)
Construct class pointing to an int.
Definition: ETW.h:164
event_data(const void *data, ULONG size)
Construct class pointing to binary data.
Definition: ETW.h:282
event_data(const GUID &data)
Construct class pointing to a GUID.
Definition: ETW.h:216
event_data(const unsigned int &data)
Construct class pointing to an unsigned int.
Definition: ETW.h:177
event_data(const char *data)
Construct class pointing to a string.
Definition: ETW.h:229
event_data(const unsigned char &data)
Construct class pointing to an unsigned char.
Definition: ETW.h:151
event_data(const std::basic_string< _Elem, _Traits, _Ax > &data)
Template to construct pointing to a std::basic_string<>.
Definition: ETW.h:268
event_data(const unsigned long &data)
Construct class pointing to an unsigned long.
Definition: ETW.h:203
event_data()
Construct empty class.
Definition: ETW.h:123
event_data(const long &data)
Construct class pointing to a long.
Definition: ETW.h:190
Helper template to write an event on entry/exit of scope with one parameter (typically result).
Definition: ETW.h:1141
event_fn_auto_ret(const event_fn_auto_ret< T > &other)
Copies the object.
Definition: ETW.h:1158
~event_fn_auto_ret()
Writes the event_dest event.
Definition: ETW.h:1181
EVENT_DATA_DESCRIPTOR m_desc[2]
Function name and return value.
Definition: ETW.h:1223
event_provider & m_ep
Reference to event provider in use.
Definition: ETW.h:1221
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:1146
T & m_result
Function result.
Definition: ETW.h:1224
event_fn_auto_ret & operator=(const event_fn_auto_ret< T > &other)
Copies the object.
Definition: ETW.h:1192
const EVENT_DESCRIPTOR * m_event_dest
Event descriptor at destruction.
Definition: ETW.h:1222
event_fn_auto_ret(event_fn_auto_ret< T > &&other)
Moves the object.
Definition: ETW.h:1169
event_fn_auto_ret & operator=(event_fn_auto_ret< T > &&other)
Moves the object.
Definition: ETW.h:1207
Helper class to write an event on entry/exit of scope.
Definition: ETW.h:1056
const EVENT_DESCRIPTOR * m_event_dest
Event descriptor at destruction.
Definition: ETW.h:1130
event_fn_auto(event_fn_auto &&other) noexcept
Moves the object.
Definition: ETW.h:1082
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:1061
~event_fn_auto()
Writes the event_dest event.
Definition: ETW.h:1093
event_fn_auto & operator=(event_fn_auto &&other) noexcept
Moves the object.
Definition: ETW.h:1116
event_fn_auto & operator=(const event_fn_auto &other)
Copies the object.
Definition: ETW.h:1102
event_provider & m_ep
Reference to event provider in use.
Definition: ETW.h:1129
EVENT_DATA_DESCRIPTOR m_fn_name
Function name.
Definition: ETW.h:1131
event_fn_auto(const event_fn_auto &other)
Copies the object.
Definition: ETW.h:1072
ETW event provider.
Definition: ETW.h:492
ULONG write(PCEVENT_DESCRIPTOR EventDescriptor)
Writes an event with no parameters.
Definition: ETW.h:534
ULONG write(PCEVENT_DESCRIPTOR EventDescriptor, ULONG UserDataCount=0, PEVENT_DATA_DESCRIPTOR UserData=NULL)
Writes an event with parameters stored in array.
Definition: ETW.h:549
ULONG write(UCHAR Level, ULONGLONG Keyword, PCWSTR String,...)
Writes a string event.
Definition: ETW.h:662
ULONG write(PCEVENT_DESCRIPTOR EventDescriptor, va_list arg)
Writes an event with variable number of parameters.
Definition: ETW.h:620
virtual ~event_provider()
Closes the event provider.
Definition: ETW.h:501
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:694
void free_internal() noexcept override
Releases the event provider.
Definition: ETW.h:684
ULONG write(PCEVENT_DESCRIPTOR EventDescriptor, const EVENT_DATA_DESCRIPTOR param1,...)
Writes an event with one or more parameter.
Definition: ETW.h:566
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:709
ULONG create(LPCGUID ProviderId)
Registers the event provider.
Definition: ETW.h:516
EVENT_RECORD wrapper.
Definition: ETW.h:297
void set_extended_data_internal(USHORT count, const EVENT_HEADER_EXTENDED_DATA_ITEM *data)
Sets event record extended data.
Definition: ETW.h:433
void set_user_data(USHORT size, LPCVOID data)
Sets event record user data.
Definition: ETW.h:418
event_rec & operator=(event_rec &&other) noexcept
Moves the event record.
Definition: ETW.h:388
~event_rec()
Destroys event record data and frees the allocated memory.
Definition: ETW.h:342
event_rec & operator=(const EVENT_RECORD &other)
Copies an existing event record.
Definition: ETW.h:372
event_rec(const EVENT_RECORD &other)
Copies an existing event record.
Definition: ETW.h:323
event_rec & operator=(const event_rec &other)
Copies an existing event record.
Definition: ETW.h:356
void set_extended_data(USHORT count, const EVENT_HEADER_EXTENDED_DATA_ITEM *data)
Sets event record extended data.
Definition: ETW.h:404
event_rec(event_rec &&other) noexcept
Moves the event record.
Definition: ETW.h:334
event_rec()
Constructs a blank event record.
Definition: ETW.h:302
void set_user_data_internal(USHORT size, LPCVOID data)
Sets event record user data.
Definition: ETW.h:471
event_rec(const event_rec &other)
Copies an existing event record.
Definition: ETW.h:312
ETW session.
Definition: ETW.h:722
LPCTSTR name() const
Gets session name.
Definition: ETW.h:797
event_session(event_session &&other) noexcept
Move constructor.
Definition: ETW.h:751
event_session(handle_type h, const EVENT_TRACE_PROPERTIES *prop)
Initializes a new session with an already available object handle.
Definition: ETW.h:739
event_session()
Initializes a new empty session.
Definition: ETW.h:729
virtual ~event_session()
Closes the session.
Definition: ETW.h:762
void free_internal() noexcept override
Releases the session.
Definition: ETW.h:891
event_session & operator=(event_session &&other) noexcept
Move assignment.
Definition: ETW.h:773
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:870
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:846
std::unique_ptr< EVENT_TRACE_PROPERTIES > m_prop
Session properties.
Definition: ETW.h:897
ULONG create(LPCTSTR SessionName, const EVENT_TRACE_PROPERTIES *Properties)
Registers and starts an event tracing session.
Definition: ETW.h:826
void attach(handle_type h, EVENT_TRACE_PROPERTIES *prop)
Sets a new session handle for the class.
Definition: ETW.h:811
Helper class to enable event provider in constructor and disables it in destructor.
Definition: ETW.h:937
UCHAR m_level
Logging level.
Definition: ETW.h:1043
PEVENT_FILTER_DESCRIPTOR m_enable_filter_desc
Event filter descriptor.
Definition: ETW.h:1047
ULONGLONG m_match_any_keyword
Keyword match mask (any)
Definition: ETW.h:1044
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:944
ULONG m_status
Result of EnableTraceEx call.
Definition: ETW.h:1039
TRACEHANDLE m_trace_handle
Trace handle.
Definition: ETW.h:1042
virtual ~event_trace_enabler()
Disables event trace.
Definition: ETW.h:1023
ULONG status() const
Return result of EnableTraceEx() call.
Definition: ETW.h:1013
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:979
ULONGLONG m_match_all_keyword
Keyword match mask (all)
Definition: ETW.h:1045
LPCGUID m_provider_id
Provider ID.
Definition: ETW.h:1040
LPCGUID m_source_id
Session ID.
Definition: ETW.h:1041
ULONG m_enable_property
Enable property.
Definition: ETW.h:1046
ETW trace.
Definition: ETW.h:906
virtual ~event_trace()
Closes the trace.
Definition: ETW.h:915
void free_internal() noexcept override
Closes the trace.
Definition: ETW.h:927
Base abstract template class to support generic object handle keeping.
Definition: Common.h:569
handle() noexcept
Initializes a new class instance with the object handle set to INVAL.
Definition: Common.h:584
REGHANDLE handle_type
Datatype of the object handle this template class handles.
Definition: Common.h:574
handle_type m_h
Object handle.
Definition: Common.h:823
void attach(handle_type h) noexcept
Sets a new object handle for the class.
Definition: Common.h:786
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:58
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:33
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:84
static const event_data blank_event_data
Blank event data used as terminator.
Definition: ETW.h:291
#define WINSTD_NONCOPYABLE(C)
Declares a class as non-copyable.
Definition: Common.h:66
#define WINSTD_STACK_BUFFER_BYTES
Size of the stack buffer in bytes used for initial system function call.
Definition: Common.h:93
static int vsprintf(std::basic_string< _Elem, _Traits, _Ax > &str, const _Elem *format, va_list arg)
Formats string using printf().
Definition: Common.h:251
#define WINSTD_HANDLE_IMPL(C, INVAL)
Implements default constructors and operators to prevent their auto-generation by compiler.
Definition: Common.h:163
static const REGHANDLE invalid
Invalid handle value.
Definition: Common.h:579