|  | // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  | // | 
|  | // Declaration of a Windows event trace provider class, to allow using | 
|  | // Windows Event Tracing for logging transport and control. | 
|  | #ifndef BASE_WIN_EVENT_TRACE_PROVIDER_H_ | 
|  | #define BASE_WIN_EVENT_TRACE_PROVIDER_H_ | 
|  |  | 
|  | #include <windows.h> | 
|  | #include <wmistr.h> | 
|  | #include <evntrace.h> | 
|  | #include <stddef.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include <limits> | 
|  |  | 
|  | #include "base/base_export.h" | 
|  | #include "base/macros.h" | 
|  |  | 
|  | namespace base { | 
|  | namespace win { | 
|  |  | 
|  | typedef GUID EtwEventClass; | 
|  | typedef UCHAR EtwEventType; | 
|  | typedef UCHAR EtwEventLevel; | 
|  | typedef USHORT EtwEventVersion; | 
|  | typedef ULONG EtwEventFlags; | 
|  |  | 
|  | // Base class is a POD for correctness. | 
|  | template <size_t N> struct EtwMofEventBase { | 
|  | EVENT_TRACE_HEADER header; | 
|  | MOF_FIELD fields[N]; | 
|  | }; | 
|  |  | 
|  | // Utility class to auto-initialize event trace header structures. | 
|  | template <size_t N> class EtwMofEvent: public EtwMofEventBase<N> { | 
|  | public: | 
|  | typedef EtwMofEventBase<N> Super; | 
|  |  | 
|  | // Clang and the C++ standard don't allow unqualified lookup into dependent | 
|  | // bases, hence these using decls to explicitly pull the names out. | 
|  | using EtwMofEventBase<N>::header; | 
|  | using EtwMofEventBase<N>::fields; | 
|  |  | 
|  | EtwMofEvent() { | 
|  | memset(static_cast<Super*>(this), 0, sizeof(Super)); | 
|  | } | 
|  |  | 
|  | EtwMofEvent(const EtwEventClass& event_class, EtwEventType type, | 
|  | EtwEventLevel level) { | 
|  | memset(static_cast<Super*>(this), 0, sizeof(Super)); | 
|  | header.Size = sizeof(Super); | 
|  | header.Guid = event_class; | 
|  | header.Class.Type = type; | 
|  | header.Class.Level = level; | 
|  | header.Flags = WNODE_FLAG_TRACED_GUID | WNODE_FLAG_USE_MOF_PTR; | 
|  | } | 
|  |  | 
|  | EtwMofEvent(const EtwEventClass& event_class, EtwEventType type, | 
|  | EtwEventVersion version, EtwEventLevel level) { | 
|  | memset(static_cast<Super*>(this), 0, sizeof(Super)); | 
|  | header.Size = sizeof(Super); | 
|  | header.Guid = event_class; | 
|  | header.Class.Type = type; | 
|  | header.Class.Version = version; | 
|  | header.Class.Level = level; | 
|  | header.Flags = WNODE_FLAG_TRACED_GUID | WNODE_FLAG_USE_MOF_PTR; | 
|  | } | 
|  |  | 
|  | void SetField(size_t field, size_t size, const void* data) { | 
|  | // DCHECK(field < N); | 
|  | if ((field < N) && (size <= std::numeric_limits<uint32_t>::max())) { | 
|  | fields[field].DataPtr = reinterpret_cast<ULONG64>(data); | 
|  | fields[field].Length = static_cast<ULONG>(size); | 
|  | } | 
|  | } | 
|  |  | 
|  | EVENT_TRACE_HEADER* get() { return& header; } | 
|  |  | 
|  | private: | 
|  | DISALLOW_COPY_AND_ASSIGN(EtwMofEvent); | 
|  | }; | 
|  |  | 
|  | // Trace provider with Event Tracing for Windows. The trace provider | 
|  | // registers with ETW by its name which is a GUID. ETW calls back to | 
|  | // the object whenever the trace level or enable flags for this provider | 
|  | // name changes. | 
|  | // Users of this class can test whether logging is currently enabled at | 
|  | // a particular trace level, and whether particular enable flags are set, | 
|  | // before other resources are consumed to generate and issue the log | 
|  | // messages themselves. | 
|  | class BASE_EXPORT EtwTraceProvider { | 
|  | public: | 
|  | // Creates an event trace provider identified by provider_name, which | 
|  | // will be the name registered with Event Tracing for Windows (ETW). | 
|  | explicit EtwTraceProvider(const GUID& provider_name); | 
|  |  | 
|  | // Creates an unnamed event trace provider, the provider must be given | 
|  | // a name before registration. | 
|  | EtwTraceProvider(); | 
|  | virtual ~EtwTraceProvider(); | 
|  |  | 
|  | // Registers the trace provider with Event Tracing for Windows. | 
|  | // Note: from this point forward ETW may call the provider's control | 
|  | //    callback. If the provider's name is enabled in some trace session | 
|  | //    already, the callback may occur recursively from this call, so | 
|  | //    call this only when you're ready to handle callbacks. | 
|  | ULONG Register(); | 
|  | // Unregisters the trace provider with ETW. | 
|  | ULONG Unregister(); | 
|  |  | 
|  | // Accessors. | 
|  | void set_provider_name(const GUID& provider_name) { | 
|  | provider_name_ = provider_name; | 
|  | } | 
|  | const GUID& provider_name() const { return provider_name_; } | 
|  | TRACEHANDLE registration_handle() const { return registration_handle_; } | 
|  | TRACEHANDLE session_handle() const { return session_handle_; } | 
|  | EtwEventFlags enable_flags() const { return enable_flags_; } | 
|  | EtwEventLevel enable_level() const { return enable_level_; } | 
|  |  | 
|  | // Returns true iff logging should be performed for "level" and "flags". | 
|  | // Note: flags is treated as a bitmask, and should normally have a single | 
|  | //      bit set, to test whether to log for a particular sub "facility". | 
|  | bool ShouldLog(EtwEventLevel level, EtwEventFlags flags) { | 
|  | return NULL != session_handle_ && level >= enable_level_ && | 
|  | (0 != (flags & enable_flags_)); | 
|  | } | 
|  |  | 
|  | // Simple wrappers to log Unicode and ANSI strings. | 
|  | // Do nothing if !ShouldLog(level, 0xFFFFFFFF). | 
|  | ULONG Log(const EtwEventClass& event_class, EtwEventType type, | 
|  | EtwEventLevel level, const char *message); | 
|  | ULONG Log(const EtwEventClass& event_class, EtwEventType type, | 
|  | EtwEventLevel level, const wchar_t *message); | 
|  |  | 
|  | // Log the provided event. | 
|  | ULONG Log(EVENT_TRACE_HEADER* event); | 
|  |  | 
|  | protected: | 
|  | // Called after events have been enabled, override in subclasses | 
|  | // to set up state or log at the start of a session. | 
|  | // Note: This function may be called ETW's thread and may be racy, | 
|  | //    bring your own locking if needed. | 
|  | virtual void OnEventsEnabled() {} | 
|  |  | 
|  | // Called just before events are disabled, override in subclasses | 
|  | // to tear down state or log at the end of a session. | 
|  | // Note: This function may be called ETW's thread and may be racy, | 
|  | //    bring your own locking if needed. | 
|  | virtual void OnEventsDisabled() {} | 
|  |  | 
|  | // Called just after events have been disabled, override in subclasses | 
|  | // to tear down state at the end of a session. At this point it's | 
|  | // to late to log anything to the session. | 
|  | // Note: This function may be called ETW's thread and may be racy, | 
|  | //    bring your own locking if needed. | 
|  | virtual void PostEventsDisabled() {} | 
|  |  | 
|  | private: | 
|  | ULONG EnableEvents(PVOID buffer); | 
|  | ULONG DisableEvents(); | 
|  | ULONG Callback(WMIDPREQUESTCODE request, PVOID buffer); | 
|  | static ULONG WINAPI ControlCallback(WMIDPREQUESTCODE request, PVOID context, | 
|  | ULONG *reserved, PVOID buffer); | 
|  |  | 
|  | GUID provider_name_; | 
|  | TRACEHANDLE registration_handle_; | 
|  | TRACEHANDLE session_handle_; | 
|  | EtwEventFlags enable_flags_; | 
|  | EtwEventLevel enable_level_; | 
|  |  | 
|  | // We don't use this, but on XP we're obliged to pass one in to | 
|  | // RegisterTraceGuids. Non-const, because that's how the API needs it. | 
|  | static TRACE_GUID_REGISTRATION obligatory_guid_registration_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(EtwTraceProvider); | 
|  | }; | 
|  |  | 
|  | }  // namespace win | 
|  | }  // namespace base | 
|  |  | 
|  | #endif  // BASE_WIN_EVENT_TRACE_PROVIDER_H_ |