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