//------------------------------------------------------------------------------ | |
// File: perflog.cpp | |
// | |
// Desc: Macros for DirectShow performance logging. | |
// | |
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. | |
//------------------------------------------------------------------------------ | |
#pragma warning (disable:4201) | |
#include <streams.h> | |
#include <windows.h> | |
#include <tchar.h> | |
#include <winperf.h> | |
#include <wmistr.h> | |
#include <evntrace.h> | |
#include <strsafe.h> | |
#include "perflog.h" | |
// | |
// Local function prototypes. | |
// | |
ULONG | |
WINAPI | |
PerflogCallback ( | |
WMIDPREQUESTCODE RequestCode, | |
__in PVOID Context, | |
__out ULONG* BufferSize, | |
__in PVOID Buffer | |
); | |
// | |
// Event tracing function pointers. | |
// We have to do this to run on down-level platforms. | |
// | |
#ifdef UNICODE | |
ULONG | |
(__stdcall * _RegisterTraceGuids) ( | |
__in IN WMIDPREQUEST RequestAddress, | |
__in IN PVOID RequestContext, | |
IN LPCGUID ControlGuid, | |
IN ULONG GuidCount, | |
__in IN PTRACE_GUID_REGISTRATION TraceGuidReg, | |
IN LPCWSTR MofImagePath, | |
IN LPCWSTR MofResourceName, | |
OUT PTRACEHANDLE RegistrationHandle | |
); | |
#define REGISTERTRACEGUIDS_NAME "RegisterTraceGuidsW" | |
#else | |
ULONG | |
(__stdcall * _RegisterTraceGuids) ( | |
__in IN WMIDPREQUEST RequestAddress, | |
__in IN PVOID RequestContext, | |
IN LPCGUID ControlGuid, | |
IN ULONG GuidCount, | |
__in IN PTRACE_GUID_REGISTRATION TraceGuidReg, | |
IN LPCSTR MofImagePath, | |
IN LPCSTR MofResourceName, | |
__out OUT PTRACEHANDLE RegistrationHandle | |
); | |
#define REGISTERTRACEGUIDS_NAME "RegisterTraceGuidsA" | |
#endif | |
ULONG | |
(__stdcall * _UnregisterTraceGuids) ( | |
TRACEHANDLE RegistrationHandle | |
); | |
TRACEHANDLE | |
(__stdcall * _GetTraceLoggerHandle) ( | |
__in PVOID Buffer | |
); | |
UCHAR | |
(__stdcall * _GetTraceEnableLevel) ( | |
TRACEHANDLE TraceHandle | |
); | |
ULONG | |
(__stdcall * _GetTraceEnableFlags) ( | |
TRACEHANDLE TraceHandle | |
); | |
ULONG | |
(__stdcall * _TraceEvent) ( | |
TRACEHANDLE TraceHandle, | |
__in PEVENT_TRACE_HEADER EventTrace | |
); | |
HINSTANCE _Advapi32; | |
// | |
// Global variables. | |
// | |
BOOL EventTracingAvailable=FALSE; | |
ULONG PerflogEnableFlags; | |
UCHAR PerflogEnableLevel; | |
ULONG PerflogModuleLevel = 0; | |
void (*OnStateChanged)(void); | |
TRACEHANDLE PerflogTraceHandle=NULL; | |
TRACEHANDLE PerflogRegHandle; | |
// The Win32 wsprintf() function writes a maximum of 1024 characters to it's output buffer. | |
// See the documentation for wsprintf()'s lpOut parameter for more information. | |
const INT iDEBUGINFO = 1024; // Used to format strings | |
// | |
// This routine initializes performance logging. | |
// It should be called from DllMain(). | |
// | |
VOID | |
PerflogReadModuleLevel( | |
HINSTANCE hInstance | |
) | |
{ | |
LONG lReturn; // Create key return value | |
TCHAR szInfo[iDEBUGINFO]; // Constructs key names | |
TCHAR szFullName[iDEBUGINFO]; // Load the full path and module name | |
HKEY hModuleKey; // Module key handle | |
LPTSTR pName; // Searches from the end for a backslash | |
DWORD dwKeySize, dwKeyType, dwKeyValue; | |
DWORD dwSize = GetModuleFileName( | |
(hInstance ? hInstance : GetModuleHandle( NULL )), | |
szFullName, | |
iDEBUGINFO ); | |
if (0 == dwSize || iDEBUGINFO == dwSize) { | |
return; | |
} | |
pName = _tcsrchr(szFullName,'\\'); | |
if (pName == NULL) { | |
pName = szFullName; | |
} else { | |
pName++; | |
} | |
/* Construct the base key name */ | |
(void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("SOFTWARE\\Debug\\%s"),pName); | |
/* Open the key for this module */ | |
lReturn = | |
RegOpenKeyEx( | |
HKEY_LOCAL_MACHINE, // Handle of an open key | |
szInfo, // Address of subkey name | |
(DWORD) 0, // Reserved value | |
KEY_QUERY_VALUE, // Desired security access | |
&hModuleKey ); // Opened handle buffer | |
if (lReturn != ERROR_SUCCESS) { | |
return; | |
} | |
dwKeySize = sizeof(DWORD); | |
lReturn = RegQueryValueEx( | |
hModuleKey, // Handle to an open key | |
TEXT("PERFLOG"), | |
NULL, // Reserved field | |
&dwKeyType, // Returns the field type | |
(LPBYTE) &dwKeyValue, // Returns the field's value | |
&dwKeySize ); // Number of bytes transferred | |
if ((lReturn == ERROR_SUCCESS) && (dwKeyType == REG_DWORD)) | |
{ | |
PerflogModuleLevel = dwKeyValue; | |
} | |
RegCloseKey(hModuleKey); | |
} | |
BOOL PerflogInitIfEnabled( | |
IN HINSTANCE hInstance, | |
__in IN PPERFLOG_LOGGING_PARAMS LogParams | |
) | |
{ | |
PerflogReadModuleLevel( hInstance ); | |
if (PerflogModuleLevel) | |
{ | |
return PerflogInitialize( LogParams ); | |
} | |
else | |
{ | |
return FALSE; | |
} | |
} | |
BOOL | |
PerflogInitialize ( | |
__in IN PPERFLOG_LOGGING_PARAMS LogParams | |
) | |
{ | |
ULONG status; | |
// | |
// If we're running on a recent-enough platform, this will get | |
// pointers to the event tracing routines. | |
// | |
_Advapi32 = GetModuleHandle (_T("ADVAPI32.DLL")); | |
if (_Advapi32 == NULL) { | |
return FALSE; | |
} | |
*((FARPROC*) &_RegisterTraceGuids) = GetProcAddress (_Advapi32, REGISTERTRACEGUIDS_NAME); | |
*((FARPROC*) &_UnregisterTraceGuids) = GetProcAddress (_Advapi32, "UnregisterTraceGuids"); | |
*((FARPROC*) &_GetTraceLoggerHandle) = GetProcAddress (_Advapi32, "GetTraceLoggerHandle"); | |
*((FARPROC*) &_GetTraceEnableLevel) = GetProcAddress (_Advapi32, "GetTraceEnableLevel"); | |
*((FARPROC*) &_GetTraceEnableFlags) = GetProcAddress (_Advapi32, "GetTraceEnableFlags"); | |
*((FARPROC*) &_TraceEvent) = GetProcAddress (_Advapi32, "TraceEvent"); | |
if (_RegisterTraceGuids == NULL || | |
_UnregisterTraceGuids == NULL || | |
_GetTraceEnableLevel == NULL || | |
_GetTraceEnableFlags == NULL || | |
_TraceEvent == NULL) { | |
return FALSE; | |
} | |
EventTracingAvailable = TRUE; | |
OnStateChanged = LogParams->OnStateChanged; | |
// | |
// Register our GUIDs. | |
// | |
status = _RegisterTraceGuids (PerflogCallback, | |
LogParams, | |
&LogParams->ControlGuid, | |
LogParams->NumberOfTraceGuids, | |
LogParams->TraceGuids, | |
NULL, | |
NULL, | |
&PerflogRegHandle); | |
return (status == ERROR_SUCCESS); | |
} | |
// | |
// This routine shuts down performance logging. | |
// | |
VOID | |
PerflogShutdown ( | |
VOID | |
) | |
{ | |
if (!EventTracingAvailable) { | |
return; | |
} | |
_UnregisterTraceGuids (PerflogRegHandle); | |
PerflogRegHandle = NULL; | |
PerflogTraceHandle = NULL; | |
} | |
// | |
// Event tracing callback routine. | |
// It's called when controllers call event tracing control functions. | |
// | |
ULONG | |
WINAPI | |
PerflogCallback ( | |
WMIDPREQUESTCODE RequestCode, | |
__in PVOID Context, | |
__out ULONG* BufferSize, | |
__in PVOID Buffer | |
) | |
{ | |
ULONG status; | |
UNREFERENCED_PARAMETER (Context); | |
ASSERT (EventTracingAvailable); | |
status = ERROR_SUCCESS; | |
switch (RequestCode) { | |
case WMI_ENABLE_EVENTS: | |
PerflogTraceHandle = _GetTraceLoggerHandle (Buffer); | |
PerflogEnableFlags = _GetTraceEnableFlags (PerflogTraceHandle); | |
PerflogEnableLevel = _GetTraceEnableLevel (PerflogTraceHandle); | |
break; | |
case WMI_DISABLE_EVENTS: | |
PerflogTraceHandle = NULL; | |
PerflogEnableFlags = 0; | |
PerflogEnableLevel = 0; | |
break; | |
default: | |
status = ERROR_INVALID_PARAMETER; | |
} | |
if (OnStateChanged != NULL) { | |
OnStateChanged(); | |
} | |
*BufferSize = 0; | |
return status; | |
} | |
// | |
// Logging routine. | |
// | |
VOID | |
PerflogTraceEvent ( | |
__in PEVENT_TRACE_HEADER Event | |
) | |
{ | |
if (!EventTracingAvailable) { | |
return; | |
} | |
_TraceEvent (PerflogTraceHandle, Event); | |
} | |
VOID | |
PerflogTraceEventLevel( | |
ULONG Level, | |
__in PEVENT_TRACE_HEADER Event | |
) | |
{ | |
if ((!EventTracingAvailable) || (Level <= PerflogModuleLevel)) { | |
return; | |
} | |
_TraceEvent (PerflogTraceHandle, Event); | |
} | |