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