1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 // 5 #include "base/win/event_trace_provider.h" 6 #include <windows.h> 7 #include <cguid.h> 8 9 namespace base { 10 namespace win { 11 12 TRACE_GUID_REGISTRATION EtwTraceProvider::obligatory_guid_registration_ = { 13 &GUID_NULL, 14 NULL 15 }; 16 17 EtwTraceProvider::EtwTraceProvider(const GUID& provider_name) 18 : provider_name_(provider_name), registration_handle_(NULL), 19 session_handle_(NULL), enable_flags_(0), enable_level_(0) { 20 } 21 22 EtwTraceProvider::EtwTraceProvider() 23 : provider_name_(GUID_NULL), registration_handle_(NULL), 24 session_handle_(NULL), enable_flags_(0), enable_level_(0) { 25 } 26 27 EtwTraceProvider::~EtwTraceProvider() { 28 Unregister(); 29 } 30 31 ULONG EtwTraceProvider::EnableEvents(void* buffer) { 32 session_handle_ = ::GetTraceLoggerHandle(buffer); 33 if (NULL == session_handle_) { 34 return ::GetLastError(); 35 } 36 37 enable_flags_ = ::GetTraceEnableFlags(session_handle_); 38 enable_level_ = ::GetTraceEnableLevel(session_handle_); 39 40 // Give subclasses a chance to digest the state change. 41 OnEventsEnabled(); 42 43 return ERROR_SUCCESS; 44 } 45 46 ULONG EtwTraceProvider::DisableEvents() { 47 // Give subclasses a chance to digest the state change. 48 OnEventsDisabled(); 49 50 enable_level_ = 0; 51 enable_flags_ = 0; 52 session_handle_ = NULL; 53 54 PostEventsDisabled(); 55 56 return ERROR_SUCCESS; 57 } 58 59 ULONG EtwTraceProvider::Callback(WMIDPREQUESTCODE request, void* buffer) { 60 switch (request) { 61 case WMI_ENABLE_EVENTS: 62 return EnableEvents(buffer); 63 case WMI_DISABLE_EVENTS: 64 return DisableEvents(); 65 default: 66 return ERROR_INVALID_PARAMETER; 67 } 68 // Not reached. 69 } 70 71 ULONG WINAPI EtwTraceProvider::ControlCallback(WMIDPREQUESTCODE request, 72 void* context, ULONG *reserved, void* buffer) { 73 EtwTraceProvider *provider = reinterpret_cast<EtwTraceProvider*>(context); 74 75 return provider->Callback(request, buffer); 76 } 77 78 ULONG EtwTraceProvider::Register() { 79 if (provider_name_ == GUID_NULL) 80 return ERROR_INVALID_NAME; 81 82 return ::RegisterTraceGuids(ControlCallback, this, &provider_name_, 83 1, &obligatory_guid_registration_, NULL, NULL, ®istration_handle_); 84 } 85 86 ULONG EtwTraceProvider::Unregister() { 87 // If a session is active, notify subclasses that it's going away. 88 if (session_handle_ != NULL) 89 DisableEvents(); 90 91 ULONG ret = ::UnregisterTraceGuids(registration_handle_); 92 93 registration_handle_ = NULL; 94 95 return ret; 96 } 97 98 ULONG EtwTraceProvider::Log(const EtwEventClass& event_class, 99 EtwEventType type, EtwEventLevel level, const char *message) { 100 if (NULL == session_handle_ || enable_level_ < level) 101 return ERROR_SUCCESS; // No one listening. 102 103 EtwMofEvent<1> event(event_class, type, level); 104 105 event.fields[0].DataPtr = reinterpret_cast<ULONG64>(message); 106 event.fields[0].Length = message ? 107 static_cast<ULONG>(sizeof(message[0]) * (1 + strlen(message))) : 0; 108 109 return ::TraceEvent(session_handle_, &event.header); 110 } 111 112 ULONG EtwTraceProvider::Log(const EtwEventClass& event_class, 113 EtwEventType type, EtwEventLevel level, const wchar_t *message) { 114 if (NULL == session_handle_ || enable_level_ < level) 115 return ERROR_SUCCESS; // No one listening. 116 117 EtwMofEvent<1> event(event_class, type, level); 118 119 event.fields[0].DataPtr = reinterpret_cast<ULONG64>(message); 120 event.fields[0].Length = message ? 121 static_cast<ULONG>(sizeof(message[0]) * (1 + wcslen(message))) : 0; 122 123 return ::TraceEvent(session_handle_, &event.header); 124 } 125 126 ULONG EtwTraceProvider::Log(EVENT_TRACE_HEADER* event) { 127 if (enable_level_ < event->Class.Level) 128 return ERROR_SUCCESS; 129 130 return ::TraceEvent(session_handle_, event); 131 } 132 133 } // namespace win 134 } // namespace base 135