mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-30 05:31:15 +00:00
42bdeaf52c
Original repo is here: https://github.com/microsoft/Windows-classic-samples Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1577>
347 lines
8.3 KiB
C++
347 lines
8.3 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);
|
|
}
|
|
|
|
|