1 // Copyright 2020 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 "remoting/host/win/etw_trace_controller.h"
6
7 #include <stdint.h>
8 #include <memory>
9
10 #include "base/logging.h"
11 #include "base/macros.h"
12 #include "remoting/host/logging.h"
13
14 namespace remoting {
15
16 namespace {
17
18 constexpr wchar_t kSessionName[] = L"chrome_remote_desktop_host_logger";
19 constexpr uint8_t kDefaultTracingLevel = 4;
20 constexpr uint32_t kDefaultTracingFlags = 0;
21 constexpr size_t kDefaultBufferSizeKb = 16;
22
23 } // namespace
24
25 EtwTraceController* EtwTraceController::instance_ = nullptr;
26
27 EtwTraceController::EtwTraceController() = default;
28
~EtwTraceController()29 EtwTraceController::~EtwTraceController() {
30 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
31 Stop();
32 }
33
GetActiveSessionName() const34 const wchar_t* EtwTraceController::GetActiveSessionName() const {
35 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
36 return (instance_ == this) ? kSessionName : nullptr;
37 }
38
Start()39 bool EtwTraceController::Start() {
40 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
41 DCHECK_EQ(instance_, nullptr);
42 instance_ = this;
43
44 // The shared Chromium event tracing class registers itself as a 'classic'
45 // provider which only supports one session so stop any existing sessions now.
46 // More info on ETW provider registration:
47 // https://docs.microsoft.com/en-us/windows/win32/etw/about-event-tracing#mof-classic-providers
48 base::win::EtwTraceProperties ignore;
49 HRESULT hr = base::win::EtwTraceController::Stop(kSessionName, &ignore);
50 LOG_IF(ERROR,
51 FAILED(hr) && hr != HRESULT_FROM_WIN32(ERROR_WMI_INSTANCE_NOT_FOUND))
52 << "Failed to stop previous trace session: 0x" << std::hex << hr;
53
54 hr = controller_.StartRealtimeSession(kSessionName, kDefaultBufferSizeKb);
55 if (FAILED(hr)) {
56 LOG(ERROR) << "Failed to start ETW realtime session: 0x" << std::hex << hr;
57 return false;
58 }
59
60 hr = controller_.EnableProvider(kRemotingHostLogProviderGuid,
61 kDefaultTracingLevel, kDefaultTracingFlags);
62 if (FAILED(hr)) {
63 LOG(ERROR) << "Failed to configure ETW provider: 0x" << std::hex << hr;
64 controller_.Stop(nullptr);
65 return false;
66 }
67
68 return true;
69 }
70
Stop()71 void EtwTraceController::Stop() {
72 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
73 if (instance_ != this) {
74 DCHECK_EQ(instance_, nullptr);
75 return;
76 }
77
78 // The following are all best effort, so try to stop tracing and clean up but
79 // don't skip any steps if a previous one failed.
80 HRESULT hr = controller_.DisableProvider(kRemotingHostLogProviderGuid);
81 LOG_IF(ERROR, FAILED(hr))
82 << "Failed to disable ETW provider: 0x" << std::hex << hr;
83
84 hr = controller_.Flush(nullptr);
85 LOG_IF(ERROR, FAILED(hr)) << "Failed to flush events: 0x" << std::hex << hr;
86
87 hr = controller_.Stop(nullptr);
88 LOG_IF(ERROR, FAILED(hr))
89 << "Failed to stop ETW trace session: 0x" << std::hex << hr;
90
91 instance_ = nullptr;
92 }
93
94 } // namespace remoting
95