| //------------------------------------------------------------------------------ | |
| // 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); | |
| } | |