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