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