15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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)#include "base/win/event_trace_provider.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cguid.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace win { 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TRACE_GUID_REGISTRATION EtwTraceProvider::obligatory_guid_registration_ = { 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &GUID_NULL, 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EtwTraceProvider::EtwTraceProvider(const GUID& provider_name) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : provider_name_(provider_name), registration_handle_(NULL), 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session_handle_(NULL), enable_flags_(0), enable_level_(0) { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EtwTraceProvider::EtwTraceProvider() 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : provider_name_(GUID_NULL), registration_handle_(NULL), 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session_handle_(NULL), enable_flags_(0), enable_level_(0) { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EtwTraceProvider::~EtwTraceProvider() { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Unregister(); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ULONG EtwTraceProvider::EnableEvents(void* buffer) { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session_handle_ = ::GetTraceLoggerHandle(buffer); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL == session_handle_) { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ::GetLastError(); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enable_flags_ = ::GetTraceEnableFlags(session_handle_); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enable_level_ = ::GetTraceEnableLevel(session_handle_); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Give subclasses a chance to digest the state change. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnEventsEnabled(); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERROR_SUCCESS; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ULONG EtwTraceProvider::DisableEvents() { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Give subclasses a chance to digest the state change. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnEventsDisabled(); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enable_level_ = 0; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enable_flags_ = 0; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session_handle_ = NULL; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PostEventsDisabled(); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERROR_SUCCESS; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ULONG EtwTraceProvider::Callback(WMIDPREQUESTCODE request, void* buffer) { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (request) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WMI_ENABLE_EVENTS: 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return EnableEvents(buffer); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WMI_DISABLE_EVENTS: 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DisableEvents(); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERROR_INVALID_PARAMETER; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Not reached. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ULONG WINAPI EtwTraceProvider::ControlCallback(WMIDPREQUESTCODE request, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* context, ULONG *reserved, void* buffer) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwTraceProvider *provider = reinterpret_cast<EtwTraceProvider*>(context); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return provider->Callback(request, buffer); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ULONG EtwTraceProvider::Register() { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (provider_name_ == GUID_NULL) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERROR_INVALID_NAME; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ::RegisterTraceGuids(ControlCallback, this, &provider_name_, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, &obligatory_guid_registration_, NULL, NULL, ®istration_handle_); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ULONG EtwTraceProvider::Unregister() { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a session is active, notify subclasses that it's going away. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (session_handle_ != NULL) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DisableEvents(); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG ret = ::UnregisterTraceGuids(registration_handle_); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registration_handle_ = NULL; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ULONG EtwTraceProvider::Log(const EtwEventClass& event_class, 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwEventType type, EtwEventLevel level, const char *message) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL == session_handle_ || enable_level_ < level) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERROR_SUCCESS; // No one listening. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwMofEvent<1> event(event_class, type, level); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.fields[0].DataPtr = reinterpret_cast<ULONG64>(message); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.fields[0].Length = message ? 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<ULONG>(sizeof(message[0]) * (1 + strlen(message))) : 0; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ::TraceEvent(session_handle_, &event.header); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ULONG EtwTraceProvider::Log(const EtwEventClass& event_class, 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwEventType type, EtwEventLevel level, const wchar_t *message) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL == session_handle_ || enable_level_ < level) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERROR_SUCCESS; // No one listening. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EtwMofEvent<1> event(event_class, type, level); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.fields[0].DataPtr = reinterpret_cast<ULONG64>(message); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.fields[0].Length = message ? 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<ULONG>(sizeof(message[0]) * (1 + wcslen(message))) : 0; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ::TraceEvent(session_handle_, &event.header); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ULONG EtwTraceProvider::Log(EVENT_TRACE_HEADER* event) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (enable_level_ < event->Class.Level) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERROR_SUCCESS; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ::TraceEvent(session_handle_, event); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace win 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 135