blob: e642538706ca670a33b3d4975026a2b7cac17616 [file] [log] [blame]
//------------------------------------------------------------------------------
// 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);
}