Commit 409dafc9 authored by Joe Downing's avatar Joe Downing Committed by Commit Bot

[Windows][Host] Adding HostEventWindowsEventLogger class

This CL adds the class which logs any ETW events received to the
Windows event log.

Bug: 1144185
Change-Id: I3972e2c5ef91ace511f5bebfa41fa00ff68ac521
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2545564
Commit-Queue: Joe Downing <joedow@chromium.org>
Reviewed-by: default avatarJamie Walch <jamiewalch@chromium.org>
Cr-Commit-Position: refs/heads/master@{#829862}
parent 63281970
......@@ -42,6 +42,7 @@
#include "remoting/host/switches.h"
#include "remoting/host/win/etw_trace_consumer.h"
#include "remoting/host/win/host_event_file_logger.h"
#include "remoting/host/win/host_event_windows_event_logger.h"
#include "remoting/host/win/launch_process_with_token.h"
#include "remoting/host/win/security_descriptor.h"
#include "remoting/host/win/unprivileged_process_delegate.h"
......@@ -70,6 +71,7 @@ constexpr wchar_t kLoggingRegistryKeyName[] = L"SOFTWARE\\Chromoting\\logging";
#endif
constexpr wchar_t kLogToFileRegistryValue[] = L"LogToFile";
constexpr wchar_t kLogToEventLogRegistryValue[] = L"LogToEventLog";
} // namespace
......@@ -437,7 +439,21 @@ void DaemonProcessWin::ConfigureHostLogging() {
}
}
// TODO(joedow): Hook up a Windows Event Logger here.
// Check to see if Windows event logging has been enabled.
if (logging_reg_key.HasValue(kLogToEventLogRegistryValue)) {
DWORD enabled = 0;
result = logging_reg_key.ReadValueDW(kLogToEventLogRegistryValue, &enabled);
if (result == ERROR_SUCCESS) {
auto event_logger = HostEventWindowsEventLogger::Create();
if (event_logger) {
loggers.push_back(std::move(event_logger));
}
} else {
::SetLastError(result);
PLOG(ERROR) << "Failed to read HKLM\\" << kLoggingRegistryKeyName << "\\"
<< kLogToEventLogRegistryValue;
}
}
if (loggers.empty()) {
VLOG(1) << "No host event loggers have been configured.";
......
......@@ -169,7 +169,8 @@
CategoryMessageFile="[#$(var.CoreBinary)]"
EventMessageFile="[#$(var.CoreBinary)]"
SupportsErrors="yes"
SupportsInformationals="yes"/>
SupportsInformationals="yes"
SupportsWarnings="yes"/>
</Component>
<Component Id="remoting_desktop" Guid="*">
......
......@@ -387,6 +387,8 @@ shared_library("remoting_core") {
"host_event_file_logger.cc",
"host_event_file_logger.h",
"host_event_logger.h",
"host_event_windows_event_logger.cc",
"host_event_windows_event_logger.h",
"host_service.cc",
"host_service.h",
"launch_native_messaging_host_process.cc",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/host/win/host_event_windows_event_logger.h"
#include <utility>
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "remoting/host/win/event_trace_data.h"
#include "remoting/host/win/remoting_host_messages.h"
constexpr char kApplicationName[] = "chromoting";
namespace remoting {
namespace {
WORD SeverityToEventLogType(logging::LogSeverity severity) {
// The Windows event log only has 3 log levels so some severity levels will
// need to be combined (info and verbose, error and fatal).
switch (severity) {
case logging::LOG_WARNING:
return EVENTLOG_WARNING_TYPE;
case logging::LOG_FATAL:
case logging::LOG_ERROR:
// Fatal or Error event.
return EVENTLOG_ERROR_TYPE;
case logging::LOG_INFO:
default:
// Info or Verbose event.
return EVENTLOG_INFORMATION_TYPE;
}
}
} // namespace
HostEventWindowsEventLogger::HostEventWindowsEventLogger(
WindowsEventLogger event_logger)
: event_logger_(std::move(event_logger)) {}
HostEventWindowsEventLogger::~HostEventWindowsEventLogger() = default;
void HostEventWindowsEventLogger::LogEvent(const EventTraceData& data) {
DCHECK(event_logger_.IsRegistered());
// The first message will be displayed in the general tab in EventViewer. The
// additional fields will be logged as part of the EventData which can be
// viewed in 'details' or queried for in Powershell.
// Note: The Data elements logged will not have a 'Name' attribute so any
// scripts which query for these events will need to be updated if the order
// changes. This is due to the event logging mechanism we are using.
// If having a stable query is important in the future, then we will need to
// change from a MOF based provider to a manifest based provider and define an
// event schema.
std::vector<std::string> payload(
{data.message.c_str(),
base::StringPrintf("pid: %d", data.process_id),
base::StringPrintf("tid: %d", data.thread_id),
EventTraceData::SeverityToString(data.severity),
base::StringPrintf("%s(%d)", data.file_name.c_str(), data.line),
base::StringPrintf("%4d-%02d-%02d - %02d:%02d:%02d.%03d",
data.time_stamp.year, data.time_stamp.month,
data.time_stamp.day_of_month, data.time_stamp.hour,
data.time_stamp.minute, data.time_stamp.second,
data.time_stamp.millisecond)});
WORD type = SeverityToEventLogType(data.severity);
if (!event_logger_.Log(type, MSG_HOST_LOG_EVENT, payload)) {
// Don't log a write error more than once. We don't want to create a
// loopback effect and fill up the log for other active event loggers.
static bool logged_once = false;
// The LOG statement below should get pushed to the Windows ETW queue and
// will be delivered to the event trace consumer asynchronously. Just to be
// safe, we store and then update the static value to prevent any potential
// reentrancy issues.
bool local_logged_once = logged_once;
logged_once = true;
PLOG_IF(ERROR, !local_logged_once) << "Failed to write to the event log";
}
}
// static.
std::unique_ptr<HostEventLogger> HostEventWindowsEventLogger::Create() {
WindowsEventLogger event_logger(kApplicationName);
if (!event_logger.IsRegistered()) {
return nullptr;
}
return std::make_unique<HostEventWindowsEventLogger>(std::move(event_logger));
}
} // namespace remoting
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef REMOTING_HOST_WIN_HOST_EVENT_WINDOWS_EVENT_LOGGER_H_
#define REMOTING_HOST_WIN_HOST_EVENT_WINDOWS_EVENT_LOGGER_H_
#include <windows.h>
#include <memory>
#include "remoting/host/win/host_event_logger.h"
#include "remoting/host/win/windows_event_logger.h"
namespace remoting {
// Logs ETW event trace data to the Windows event log.
class HostEventWindowsEventLogger : public HostEventLogger {
public:
// Helper function which creates a HostEventLogger instance which will log
// to the Windows event log. Returns nullptr if an error occurs while
// configuring the logger.
static std::unique_ptr<HostEventLogger> Create();
explicit HostEventWindowsEventLogger(WindowsEventLogger event_logger);
HostEventWindowsEventLogger(const HostEventWindowsEventLogger&) = delete;
HostEventWindowsEventLogger& operator=(const HostEventWindowsEventLogger&) =
delete;
~HostEventWindowsEventLogger() override;
// HostEventLogger implementation.
void LogEvent(const EventTraceData& data) override;
private:
WindowsEventLogger event_logger_;
};
} // namespace remoting
#endif // REMOTING_HOST_WIN_HOST_EVENT_WINDOWS_EVENT_LOGGER_H_
......@@ -23,6 +23,19 @@ WindowsEventLogger::WindowsEventLogger(const std::string& application_name) {
}
}
WindowsEventLogger::WindowsEventLogger(WindowsEventLogger&& other)
: event_log_(other.event_log_) {
other.event_log_ = nullptr;
}
WindowsEventLogger& WindowsEventLogger::operator=(WindowsEventLogger&& other) {
if (this != &other) {
event_log_ = other.event_log_;
other.event_log_ = nullptr;
}
return *this;
}
WindowsEventLogger::~WindowsEventLogger() {
if (event_log_ != nullptr) {
::DeregisterEventSource(event_log_);
......
......@@ -15,8 +15,8 @@ namespace remoting {
class WindowsEventLogger {
public:
explicit WindowsEventLogger(const std::string& application_name);
WindowsEventLogger(const WindowsEventLogger&) = delete;
WindowsEventLogger& operator=(const WindowsEventLogger&) = delete;
WindowsEventLogger(WindowsEventLogger&&);
WindowsEventLogger& operator=(WindowsEventLogger&&);
~WindowsEventLogger();
// Indicates whether the instance has successfully registered itself with the
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment