1 // Copyright 2011 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifdef UNSAFE_BUFFERS_BUILD 6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors. 7 #pragma allow_unsafe_buffers 8 #endif 9 10 // Declaration of a Windows event trace provider class, to allow using 11 // Windows Event Tracing for logging transport and control. 12 #ifndef BASE_WIN_EVENT_TRACE_PROVIDER_H_ 13 #define BASE_WIN_EVENT_TRACE_PROVIDER_H_ 14 15 #include <windows.h> 16 17 #include <cguid.h> 18 #include <evntrace.h> 19 #include <stddef.h> 20 #include <stdint.h> 21 #include <wmistr.h> 22 23 #include <limits> 24 25 #include "base/base_export.h" 26 #include "base/compiler_specific.h" 27 28 namespace base { 29 namespace win { 30 31 using EtwEventClass = GUID; 32 using EtwEventType = UCHAR; 33 using EtwEventLevel = UCHAR; 34 using EtwEventVersion = USHORT; 35 using EtwEventFlags = ULONG; 36 37 // Base class is a POD for correctness. 38 template <size_t N> 39 struct EtwMofEventBase { 40 EVENT_TRACE_HEADER header; 41 MOF_FIELD fields[N]; 42 }; 43 44 // Utility class to auto-initialize event trace header structures. 45 template <size_t N> 46 class EtwMofEvent : public EtwMofEventBase<N> { 47 public: 48 using Super = EtwMofEventBase<N>; 49 50 // Clang and the C++ standard don't allow unqualified lookup into dependent 51 // bases, hence these using decls to explicitly pull the names out. 52 using EtwMofEventBase<N>::header; 53 using EtwMofEventBase<N>::fields; 54 EtwMofEvent()55 EtwMofEvent() { memset(static_cast<Super*>(this), 0, sizeof(Super)); } 56 EtwMofEvent(const EtwEventClass & event_class,EtwEventType type,EtwEventLevel level)57 EtwMofEvent(const EtwEventClass& event_class, 58 EtwEventType type, 59 EtwEventLevel level) { 60 memset(static_cast<Super*>(this), 0, sizeof(Super)); 61 header.Size = sizeof(Super); 62 header.Guid = event_class; 63 header.Class.Type = type; 64 header.Class.Level = level; 65 header.Flags = WNODE_FLAG_TRACED_GUID | WNODE_FLAG_USE_MOF_PTR; 66 } 67 EtwMofEvent(const EtwEventClass & event_class,EtwEventType type,EtwEventVersion version,EtwEventLevel level)68 EtwMofEvent(const EtwEventClass& event_class, 69 EtwEventType type, 70 EtwEventVersion version, 71 EtwEventLevel level) { 72 memset(static_cast<Super*>(this), 0, sizeof(Super)); 73 header.Size = sizeof(Super); 74 header.Guid = event_class; 75 header.Class.Type = type; 76 header.Class.Version = version; 77 header.Class.Level = level; 78 header.Flags = WNODE_FLAG_TRACED_GUID | WNODE_FLAG_USE_MOF_PTR; 79 } 80 81 EtwMofEvent(const EtwMofEvent&) = delete; 82 EtwMofEvent& operator=(const EtwMofEvent&) = delete; 83 SetField(size_t field,size_t size,const void * data)84 void SetField(size_t field, size_t size, const void* data) { 85 // DCHECK(field < N); 86 if ((field < N) && (size <= std::numeric_limits<uint32_t>::max())) { 87 fields[field].DataPtr = reinterpret_cast<ULONG64>(data); 88 fields[field].Length = static_cast<ULONG>(size); 89 } 90 } 91 get()92 EVENT_TRACE_HEADER* get() { return &header; } 93 }; 94 95 // Trace provider with Event Tracing for Windows. The trace provider 96 // registers with ETW by its name which is a GUID. ETW calls back to 97 // the object whenever the trace level or enable flags for this provider 98 // name changes. 99 // Users of this class can test whether logging is currently enabled at 100 // a particular trace level, and whether particular enable flags are set, 101 // before other resources are consumed to generate and issue the log 102 // messages themselves. 103 class BASE_EXPORT EtwTraceProvider { 104 public: 105 // Creates an event trace provider identified by provider_name, which 106 // will be the name registered with Event Tracing for Windows (ETW). 107 explicit EtwTraceProvider(const GUID& provider_name); 108 109 // Creates an unnamed event trace provider, the provider must be given 110 // a name before registration. 111 EtwTraceProvider(); 112 113 EtwTraceProvider(const EtwTraceProvider&) = delete; 114 EtwTraceProvider& operator=(const EtwTraceProvider&) = delete; 115 116 virtual ~EtwTraceProvider(); 117 118 // Registers the trace provider with Event Tracing for Windows. 119 // Note: from this point forward ETW may call the provider's control 120 // callback. If the provider's name is enabled in some trace session 121 // already, the callback may occur recursively from this call, so 122 // call this only when you're ready to handle callbacks. 123 ULONG Register(); 124 // Unregisters the trace provider with ETW. 125 ULONG Unregister(); 126 127 // Accessors. set_provider_name(const GUID & provider_name)128 void set_provider_name(const GUID& provider_name) { 129 provider_name_ = provider_name; 130 } provider_name()131 const GUID& provider_name() const LIFETIME_BOUND { return provider_name_; } registration_handle()132 TRACEHANDLE registration_handle() const { return registration_handle_; } session_handle()133 TRACEHANDLE session_handle() const { return session_handle_; } enable_flags()134 EtwEventFlags enable_flags() const { return enable_flags_; } enable_level()135 EtwEventLevel enable_level() const { return enable_level_; } 136 137 // Returns true iff logging should be performed for "level" and "flags". 138 // Note: flags is treated as a bitmask, and should normally have a single 139 // bit set, to test whether to log for a particular sub "facility". ShouldLog(EtwEventLevel level,EtwEventFlags flags)140 bool ShouldLog(EtwEventLevel level, EtwEventFlags flags) { 141 return NULL != session_handle_ && level >= enable_level_ && 142 (0 != (flags & enable_flags_)); 143 } 144 145 // Simple wrappers to log Unicode and ANSI strings. 146 // Do nothing if !ShouldLog(level, 0xFFFFFFFF). 147 ULONG Log(const EtwEventClass& event_class, 148 EtwEventType type, 149 EtwEventLevel level, 150 const char* message); 151 ULONG Log(const EtwEventClass& event_class, 152 EtwEventType type, 153 EtwEventLevel level, 154 const wchar_t* message); 155 156 // Log the provided event. 157 ULONG Log(EVENT_TRACE_HEADER* event); 158 159 protected: 160 // Called after events have been enabled, override in subclasses 161 // to set up state or log at the start of a session. 162 // Note: This function may be called ETW's thread and may be racy, 163 // bring your own locking if needed. OnEventsEnabled()164 virtual void OnEventsEnabled() {} 165 166 // Called just before events are disabled, override in subclasses 167 // to tear down state or log at the end of a session. 168 // Note: This function may be called ETW's thread and may be racy, 169 // bring your own locking if needed. OnEventsDisabled()170 virtual void OnEventsDisabled() {} 171 172 // Called just after events have been disabled, override in subclasses 173 // to tear down state at the end of a session. At this point it's 174 // to late to log anything to the session. 175 // Note: This function may be called ETW's thread and may be racy, 176 // bring your own locking if needed. PostEventsDisabled()177 virtual void PostEventsDisabled() {} 178 179 private: 180 ULONG EnableEvents(PVOID buffer); 181 ULONG DisableEvents(); 182 ULONG Callback(WMIDPREQUESTCODE request, PVOID buffer); 183 static ULONG WINAPI ControlCallback(WMIDPREQUESTCODE request, 184 PVOID context, 185 ULONG* reserved, 186 PVOID buffer); 187 188 GUID provider_name_ = GUID_NULL; 189 TRACEHANDLE registration_handle_ = NULL; 190 TRACEHANDLE session_handle_ = NULL; 191 EtwEventFlags enable_flags_ = 0; 192 EtwEventLevel enable_level_ = 0; 193 194 // We don't use this, but on XP we're obliged to pass one in to 195 // RegisterTraceGuids. Non-const, because that's how the API needs it. 196 static TRACE_GUID_REGISTRATION obligatory_guid_registration_; 197 }; 198 199 } // namespace win 200 } // namespace base 201 202 #endif // BASE_WIN_EVENT_TRACE_PROVIDER_H_ 203