#include "remoting/host/win/etw_trace_controller.h"
#include <stdint.h>
#include <memory>
#include "base/check_op.h"
#include "base/logging.h"
#include "base/sequence_checker.h"
#include "remoting/base/logging.h"
namespace remoting {
namespace {
constexpr wchar_t kSessionName[] = L"chrome_remote_desktop_host_logger";
constexpr uint8_t kDefaultTracingLevel = 4;
constexpr uint32_t kDefaultTracingFlags = 0;
constexpr size_t kDefaultBufferSizeKb = 16;
}
EtwTraceController* EtwTraceController::instance_ = nullptr;
EtwTraceController::EtwTraceController() = default;
EtwTraceController::~EtwTraceController() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Stop();
}
const wchar_t* EtwTraceController::GetActiveSessionName() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return (instance_ == this) ? kSessionName : nullptr;
}
bool EtwTraceController::Start() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(instance_, nullptr);
instance_ = this;
base::win::EtwTraceProperties ignore;
HRESULT hr = base::win::EtwTraceController::Stop(kSessionName, &ignore);
LOG_IF(ERROR,
FAILED(hr) && hr != HRESULT_FROM_WIN32(ERROR_WMI_INSTANCE_NOT_FOUND))
<< "Failed to stop previous trace session: 0x" << std::hex << hr;
hr = controller_.StartRealtimeSession(kSessionName, kDefaultBufferSizeKb);
if (FAILED(hr)) {
LOG(ERROR) << "Failed to start ETW realtime session: 0x" << std::hex << hr;
return false;
}
hr = controller_.EnableProvider(kRemotingHostLogProviderGuid,
kDefaultTracingLevel, kDefaultTracingFlags);
if (FAILED(hr)) {
LOG(ERROR) << "Failed to configure ETW provider: 0x" << std::hex << hr;
controller_.Stop(nullptr);
return false;
}
return true;
}
void EtwTraceController::Stop() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (instance_ != this) {
DCHECK_EQ(instance_, nullptr);
return;
}
HRESULT hr = controller_.DisableProvider(kRemotingHostLogProviderGuid);
LOG_IF(ERROR, FAILED(hr))
<< "Failed to disable ETW provider: 0x" << std::hex << hr;
hr = controller_.Flush(nullptr);
LOG_IF(ERROR, FAILED(hr)) << "Failed to flush events: 0x" << std::hex << hr;
hr = controller_.Stop(nullptr);
LOG_IF(ERROR, FAILED(hr))
<< "Failed to stop ETW trace session: 0x" << std::hex << hr;
instance_ = nullptr;
}
}