348 lines
7.9 KiB
C++
348 lines
7.9 KiB
C++
|
//------------------------------------------------------------------------------
|
||
|
// 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);
|
||
|
}
|
||
|
|
||
|
|