15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Declaration of a Windows event trace provider class, to allow using 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows Event Tracing for logging transport and control. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_WIN_EVENT_TRACE_PROVIDER_H_ 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_WIN_EVENT_TRACE_PROVIDER_H_ 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <wmistr.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <evntrace.h> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_export.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace win { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef GUID EtwEventClass; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef UCHAR EtwEventType; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef UCHAR EtwEventLevel; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef USHORT EtwEventVersion; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef ULONG EtwEventFlags; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Base class is a POD for correctness. 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <size_t N> struct EtwMofEventBase { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVENT_TRACE_HEADER header; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MOF_FIELD fields[N]; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Utility class to auto-initialize event trace header structures. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <size_t N> class EtwMofEvent: public EtwMofEventBase<N> { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef EtwMofEventBase<N> Super; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Clang and the C++ standard don't allow unqualified lookup into dependent 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // bases, hence these using decls to explicitly pull the names out. 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) using EtwMofEventBase<N>::header; 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) using EtwMofEventBase<N>::fields; 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwMofEvent() { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(static_cast<Super*>(this), 0, sizeof(Super)); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwMofEvent(const EtwEventClass& event_class, EtwEventType type, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwEventLevel level) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(static_cast<Super*>(this), 0, sizeof(Super)); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.Size = sizeof(Super); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.Guid = event_class; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.Class.Type = type; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.Class.Level = level; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.Flags = WNODE_FLAG_TRACED_GUID | WNODE_FLAG_USE_MOF_PTR; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwMofEvent(const EtwEventClass& event_class, EtwEventType type, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwEventVersion version, EtwEventLevel level) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(static_cast<Super*>(this), 0, sizeof(Super)); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.Size = sizeof(Super); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.Guid = event_class; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.Class.Type = type; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.Class.Version = version; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.Class.Level = level; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.Flags = WNODE_FLAG_TRACED_GUID | WNODE_FLAG_USE_MOF_PTR; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetField(int field, size_t size, const void *data) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DCHECK(field < N); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((field < N) && (size <= kuint32max)) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fields[field].DataPtr = reinterpret_cast<ULONG64>(data); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fields[field].Length = static_cast<ULONG>(size); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVENT_TRACE_HEADER* get() { return& header; } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(EtwMofEvent); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Trace provider with Event Tracing for Windows. The trace provider 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// registers with ETW by its name which is a GUID. ETW calls back to 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the object whenever the trace level or enable flags for this provider 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// name changes. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Users of this class can test whether logging is currently enabled at 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a particular trace level, and whether particular enable flags are set, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// before other resources are consumed to generate and issue the log 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// messages themselves. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT EtwTraceProvider { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates an event trace provider identified by provider_name, which 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will be the name registered with Event Tracing for Windows (ETW). 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit EtwTraceProvider(const GUID& provider_name); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates an unnamed event trace provider, the provider must be given 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a name before registration. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwTraceProvider(); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~EtwTraceProvider(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Registers the trace provider with Event Tracing for Windows. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: from this point forward ETW may call the provider's control 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // callback. If the provider's name is enabled in some trace session 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // already, the callback may occur recursively from this call, so 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // call this only when you're ready to handle callbacks. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG Register(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unregisters the trace provider with ETW. 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG Unregister(); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Accessors. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set_provider_name(const GUID& provider_name) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) provider_name_ = provider_name; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GUID& provider_name() const { return provider_name_; } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACEHANDLE registration_handle() const { return registration_handle_; } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACEHANDLE session_handle() const { return session_handle_; } 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwEventFlags enable_flags() const { return enable_flags_; } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwEventLevel enable_level() const { return enable_level_; } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true iff logging should be performed for "level" and "flags". 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: flags is treated as a bitmask, and should normally have a single 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bit set, to test whether to log for a particular sub "facility". 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ShouldLog(EtwEventLevel level, EtwEventFlags flags) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL != session_handle_ && level >= enable_level_ && 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (0 != (flags & enable_flags_)); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Simple wrappers to log Unicode and ANSI strings. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Do nothing if !ShouldLog(level, 0xFFFFFFFF). 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG Log(const EtwEventClass& event_class, EtwEventType type, 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwEventLevel level, const char *message); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG Log(const EtwEventClass& event_class, EtwEventType type, 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwEventLevel level, const wchar_t *message); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Log the provided event. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG Log(EVENT_TRACE_HEADER* event); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called after events have been enabled, override in subclasses 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to set up state or log at the start of a session. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: This function may be called ETW's thread and may be racy, 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bring your own locking if needed. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnEventsEnabled() {} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called just before events are disabled, override in subclasses 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to tear down state or log at the end of a session. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: This function may be called ETW's thread and may be racy, 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bring your own locking if needed. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnEventsDisabled() {} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called just after events have been disabled, override in subclasses 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to tear down state at the end of a session. At this point it's 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to late to log anything to the session. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: This function may be called ETW's thread and may be racy, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bring your own locking if needed. 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void PostEventsDisabled() {} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG EnableEvents(PVOID buffer); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG DisableEvents(); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG Callback(WMIDPREQUESTCODE request, PVOID buffer); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static ULONG WINAPI ControlCallback(WMIDPREQUESTCODE request, PVOID context, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG *reserved, PVOID buffer); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GUID provider_name_; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACEHANDLE registration_handle_; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACEHANDLE session_handle_; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwEventFlags enable_flags_; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwEventLevel enable_level_; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't use this, but on XP we're obliged to pass one in to 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RegisterTraceGuids. Non-const, because that's how the API needs it. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static TRACE_GUID_REGISTRATION obligatory_guid_registration_; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(EtwTraceProvider); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace win 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // BASE_WIN_EVENT_TRACE_PROVIDER_H_ 181