15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2009 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implementation of a Windows event trace controller class.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/event_trace_controller.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace win {
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EtwTraceProperties::EtwTraceProperties() {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(buffer_, 0, sizeof(buffer_));
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EVENT_TRACE_PROPERTIES* prop = get();
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prop->Wnode.BufferSize = sizeof(buffer_);
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prop->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prop->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prop->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) +
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            sizeof(wchar_t) * kMaxStringLen;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT EtwTraceProperties::SetLoggerName(const wchar_t* logger_name) {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t len = wcslen(logger_name) + 1;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (kMaxStringLen < len)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return E_INVALIDARG;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(buffer_ + get()->LoggerNameOffset,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         logger_name,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         sizeof(wchar_t) * len);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return S_OK;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT EtwTraceProperties::SetLoggerFileName(const wchar_t* logger_file_name) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t len = wcslen(logger_file_name) + 1;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (kMaxStringLen < len)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return E_INVALIDARG;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(buffer_ + get()->LogFileNameOffset,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         logger_file_name,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         sizeof(wchar_t) * len);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return S_OK;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EtwTraceController::EtwTraceController() : session_(NULL) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EtwTraceController::~EtwTraceController() {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Stop(NULL);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT EtwTraceController::Start(const wchar_t* session_name,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EtwTraceProperties* prop) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(NULL == session_ && session_name_.empty());
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EtwTraceProperties ignore;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prop == NULL)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prop = &ignore;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = Start(session_name, prop, &session_);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SUCCEEDED(hr))
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_name_ = session_name;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return hr;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT EtwTraceController::StartFileSession(const wchar_t* session_name,
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const wchar_t* logfile_path, bool realtime) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(NULL == session_ && session_name_.empty());
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EtwTraceProperties prop;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prop.SetLoggerFileName(logfile_path);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EVENT_TRACE_PROPERTIES& p = *prop.get();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p.Wnode.ClientContext = 1;  // QPC timer accuracy.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p.LogFileMode = EVENT_TRACE_FILE_MODE_SEQUENTIAL;  // Sequential log.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (realtime)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p.LogFileMode |= EVENT_TRACE_REAL_TIME_MODE;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p.MaximumFileSize = 100;  // 100M file size.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p.FlushTimer = 30;  // 30 seconds flush lag.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Start(session_name, &prop);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT EtwTraceController::StartRealtimeSession(const wchar_t* session_name,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t buffer_size) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(NULL == session_ && session_name_.empty());
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EtwTraceProperties prop;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EVENT_TRACE_PROPERTIES& p = *prop.get();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p.LogFileMode = EVENT_TRACE_REAL_TIME_MODE | EVENT_TRACE_USE_PAGED_MEMORY;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p.FlushTimer = 1;  // flush every second.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p.BufferSize = 16;  // 16 K buffers.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p.LogFileNameOffset = 0;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Start(session_name, &prop);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT EtwTraceController::EnableProvider(REFGUID provider, UCHAR level,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ULONG flags) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG error = ::EnableTrace(TRUE, flags, level, &provider, session_);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HRESULT_FROM_WIN32(error);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT EtwTraceController::DisableProvider(REFGUID provider) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG error = ::EnableTrace(FALSE, 0, 0, &provider, session_);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HRESULT_FROM_WIN32(error);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT EtwTraceController::Stop(EtwTraceProperties* properties) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EtwTraceProperties ignore;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (properties == NULL)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    properties = &ignore;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG error = ::ControlTrace(session_, NULL, properties->get(),
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EVENT_TRACE_CONTROL_STOP);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ERROR_SUCCESS != error)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return HRESULT_FROM_WIN32(error);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_ = NULL;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_name_.clear();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return S_OK;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT EtwTraceController::Flush(EtwTraceProperties* properties) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EtwTraceProperties ignore;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (properties == NULL)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    properties = &ignore;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG error = ::ControlTrace(session_, NULL, properties->get(),
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               EVENT_TRACE_CONTROL_FLUSH);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ERROR_SUCCESS != error)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return HRESULT_FROM_WIN32(error);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return S_OK;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT EtwTraceController::Start(const wchar_t* session_name,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EtwTraceProperties* properties, TRACEHANDLE* session_handle) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(properties != NULL);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG err = ::StartTrace(session_handle, session_name, properties->get());
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HRESULT_FROM_WIN32(err);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT EtwTraceController::Query(const wchar_t* session_name,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EtwTraceProperties* properties) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG err = ::ControlTrace(NULL, session_name, properties->get(),
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             EVENT_TRACE_CONTROL_QUERY);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HRESULT_FROM_WIN32(err);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT EtwTraceController::Update(const wchar_t* session_name,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EtwTraceProperties* properties) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(properties != NULL);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG err = ::ControlTrace(NULL, session_name, properties->get(),
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             EVENT_TRACE_CONTROL_UPDATE);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HRESULT_FROM_WIN32(err);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT EtwTraceController::Stop(const wchar_t* session_name,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EtwTraceProperties* properties) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(properties != NULL);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG err = ::ControlTrace(NULL, session_name, properties->get(),
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             EVENT_TRACE_CONTROL_STOP);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HRESULT_FROM_WIN32(err);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT EtwTraceController::Flush(const wchar_t* session_name,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EtwTraceProperties* properties) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(properties != NULL);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG err = ::ControlTrace(NULL, session_name, properties->get(),
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             EVENT_TRACE_CONTROL_FLUSH);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HRESULT_FROM_WIN32(err);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace win
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
174