1 // Copyright (c) 2009 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/event_trace_provider_win.h"
6 #include <windows.h>
7 #include <cguid.h>
8
9 TRACE_GUID_REGISTRATION EtwTraceProvider::obligatory_guid_registration_ = {
10 &GUID_NULL,
11 NULL
12 };
13
EtwTraceProvider(const GUID & provider_name)14 EtwTraceProvider::EtwTraceProvider(const GUID& provider_name)
15 : provider_name_(provider_name), registration_handle_(NULL),
16 session_handle_(NULL), enable_flags_(0), enable_level_(0) {
17 }
18
EtwTraceProvider()19 EtwTraceProvider::EtwTraceProvider()
20 : provider_name_(GUID_NULL), registration_handle_(NULL),
21 session_handle_(NULL), enable_flags_(0), enable_level_(0) {
22 }
23
~EtwTraceProvider()24 EtwTraceProvider::~EtwTraceProvider() {
25 Unregister();
26 }
27
EnableEvents(void * buffer)28 ULONG EtwTraceProvider::EnableEvents(void* buffer) {
29 session_handle_ = ::GetTraceLoggerHandle(buffer);
30 if (NULL == session_handle_) {
31 return ::GetLastError();
32 }
33
34 enable_flags_ = ::GetTraceEnableFlags(session_handle_);
35 enable_level_ = ::GetTraceEnableLevel(session_handle_);
36
37 // Give subclasses a chance to digest the state change.
38 OnEventsEnabled();
39
40 return ERROR_SUCCESS;
41 }
42
DisableEvents()43 ULONG EtwTraceProvider::DisableEvents() {
44 enable_level_ = 0;
45 enable_flags_ = 0;
46 session_handle_ = NULL;
47
48 // Give subclasses a chance to digest the state change.
49 OnEventsDisabled();
50
51 return ERROR_SUCCESS;
52 }
53
Callback(WMIDPREQUESTCODE request,void * buffer)54 ULONG EtwTraceProvider::Callback(WMIDPREQUESTCODE request, void* buffer) {
55 switch (request) {
56 case WMI_ENABLE_EVENTS:
57 return EnableEvents(buffer);
58 case WMI_DISABLE_EVENTS:
59 return DisableEvents();
60 default:
61 return ERROR_INVALID_PARAMETER;
62 }
63 // Not reached.
64 }
65
ControlCallback(WMIDPREQUESTCODE request,void * context,ULONG * reserved,void * buffer)66 ULONG WINAPI EtwTraceProvider::ControlCallback(WMIDPREQUESTCODE request,
67 void* context, ULONG *reserved, 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_,
78 1, &obligatory_guid_registration_, NULL, NULL, ®istration_handle_);
79 }
80
Unregister()81 ULONG EtwTraceProvider::Unregister() {
82 ULONG ret = ::UnregisterTraceGuids(registration_handle_);
83
84 // Make sure we don't log anything from here on.
85 enable_level_ = 0;
86 enable_flags_ = 0;
87 session_handle_ = NULL;
88 registration_handle_ = NULL;
89
90 return ret;
91 }
92
Log(const EtwEventClass & event_class,EtwEventType type,EtwEventLevel level,const char * message)93 ULONG EtwTraceProvider::Log(const EtwEventClass& event_class,
94 EtwEventType type, EtwEventLevel level, const char *message) {
95 if (NULL == session_handle_ || enable_level_ < level)
96 return ERROR_SUCCESS; // No one listening.
97
98 EtwMofEvent<1> event(event_class, type, level);
99
100 event.fields[0].DataPtr = reinterpret_cast<ULONG64>(message);
101 event.fields[0].Length = message ?
102 static_cast<ULONG>(sizeof(message[0]) * (1 + strlen(message))) : 0;
103
104 return ::TraceEvent(session_handle_, &event.header);
105 }
106
Log(const EtwEventClass & event_class,EtwEventType type,EtwEventLevel level,const wchar_t * message)107 ULONG EtwTraceProvider::Log(const EtwEventClass& event_class,
108 EtwEventType type, EtwEventLevel level, const wchar_t *message) {
109 if (NULL == session_handle_ || enable_level_ < level)
110 return ERROR_SUCCESS; // No one listening.
111
112 EtwMofEvent<1> event(event_class, type, level);
113
114 event.fields[0].DataPtr = reinterpret_cast<ULONG64>(message);
115 event.fields[0].Length = message ?
116 static_cast<ULONG>(sizeof(message[0]) * (1 + wcslen(message))) : 0;
117
118 return ::TraceEvent(session_handle_, &event.header);
119 }
120
Log(EVENT_TRACE_HEADER * event)121 ULONG EtwTraceProvider::Log(EVENT_TRACE_HEADER* event) {
122 if (enable_level_ < event->Class.Level)
123 return ERROR_SUCCESS;
124
125 return ::TraceEvent(session_handle_, event);
126 }
127