blob: e642538706ca670a33b3d4975026a2b7cac17616 [file] [log] [blame]
andrew@webrtc.org373e9272012-11-21 18:14:051//------------------------------------------------------------------------------
2// File: perflog.cpp
3//
4// Desc: Macros for DirectShow performance logging.
5//
6// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
7//------------------------------------------------------------------------------
8
9#pragma warning (disable:4201)
10
11#include <streams.h>
12#include <windows.h>
13#include <tchar.h>
14#include <winperf.h>
15#include <wmistr.h>
16#include <evntrace.h>
17#include <strsafe.h>
18#include "perflog.h"
19
20//
21// Local function prototypes.
22//
23
24ULONG
25WINAPI
26PerflogCallback (
27 WMIDPREQUESTCODE RequestCode,
28 __in PVOID Context,
29 __out ULONG* BufferSize,
30 __in PVOID Buffer
31 );
32
33//
34// Event tracing function pointers.
35// We have to do this to run on down-level platforms.
36//
37
38#ifdef UNICODE
39
40ULONG
41(__stdcall * _RegisterTraceGuids) (
42 __in IN WMIDPREQUEST RequestAddress,
43 __in IN PVOID RequestContext,
44 IN LPCGUID ControlGuid,
45 IN ULONG GuidCount,
46 __in IN PTRACE_GUID_REGISTRATION TraceGuidReg,
47 IN LPCWSTR MofImagePath,
48 IN LPCWSTR MofResourceName,
49 OUT PTRACEHANDLE RegistrationHandle
50 );
51
52#define REGISTERTRACEGUIDS_NAME "RegisterTraceGuidsW"
53
54#else
55
56ULONG
57(__stdcall * _RegisterTraceGuids) (
58 __in IN WMIDPREQUEST RequestAddress,
59 __in IN PVOID RequestContext,
60 IN LPCGUID ControlGuid,
61 IN ULONG GuidCount,
62 __in IN PTRACE_GUID_REGISTRATION TraceGuidReg,
63 IN LPCSTR MofImagePath,
64 IN LPCSTR MofResourceName,
65 __out OUT PTRACEHANDLE RegistrationHandle
66 );
67
68#define REGISTERTRACEGUIDS_NAME "RegisterTraceGuidsA"
69
70#endif
71
72ULONG
73(__stdcall * _UnregisterTraceGuids) (
74 TRACEHANDLE RegistrationHandle
75 );
76
77TRACEHANDLE
78(__stdcall * _GetTraceLoggerHandle) (
79 __in PVOID Buffer
80 );
81
82UCHAR
83(__stdcall * _GetTraceEnableLevel) (
84 TRACEHANDLE TraceHandle
85 );
86
87ULONG
88(__stdcall * _GetTraceEnableFlags) (
89 TRACEHANDLE TraceHandle
90 );
91
92ULONG
93(__stdcall * _TraceEvent) (
94 TRACEHANDLE TraceHandle,
95 __in PEVENT_TRACE_HEADER EventTrace
96 );
97
98HINSTANCE _Advapi32;
99
100//
101// Global variables.
102//
103
104BOOL EventTracingAvailable=FALSE;
105ULONG PerflogEnableFlags;
106UCHAR PerflogEnableLevel;
107ULONG PerflogModuleLevel = 0;
108void (*OnStateChanged)(void);
109TRACEHANDLE PerflogTraceHandle=NULL;
110TRACEHANDLE PerflogRegHandle;
111
112// The Win32 wsprintf() function writes a maximum of 1024 characters to it's output buffer.
113// See the documentation for wsprintf()'s lpOut parameter for more information.
114const INT iDEBUGINFO = 1024; // Used to format strings
115
116//
117// This routine initializes performance logging.
118// It should be called from DllMain().
119//
120
121
122VOID
123PerflogReadModuleLevel(
124 HINSTANCE hInstance
125 )
126{
127 LONG lReturn; // Create key return value
128 TCHAR szInfo[iDEBUGINFO]; // Constructs key names
129 TCHAR szFullName[iDEBUGINFO]; // Load the full path and module name
130 HKEY hModuleKey; // Module key handle
131 LPTSTR pName; // Searches from the end for a backslash
132 DWORD dwKeySize, dwKeyType, dwKeyValue;
133
134 DWORD dwSize = GetModuleFileName(
135 (hInstance ? hInstance : GetModuleHandle( NULL )),
136 szFullName,
137 iDEBUGINFO );
138
139 if (0 == dwSize || iDEBUGINFO == dwSize) {
140 return;
141 }
142
143 pName = _tcsrchr(szFullName,'\\');
144 if (pName == NULL) {
145 pName = szFullName;
146 } else {
147 pName++;
148 }
149
150 /* Construct the base key name */
151 (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("SOFTWARE\\Debug\\%s"),pName);
152
153 /* Open the key for this module */
154 lReturn =
155 RegOpenKeyEx(
156 HKEY_LOCAL_MACHINE, // Handle of an open key
157 szInfo, // Address of subkey name
158 (DWORD) 0, // Reserved value
159 KEY_QUERY_VALUE, // Desired security access
160 &hModuleKey ); // Opened handle buffer
161
162 if (lReturn != ERROR_SUCCESS) {
163 return;
164 }
165
166 dwKeySize = sizeof(DWORD);
167 lReturn = RegQueryValueEx(
168 hModuleKey, // Handle to an open key
169 TEXT("PERFLOG"),
170 NULL, // Reserved field
171 &dwKeyType, // Returns the field type
172 (LPBYTE) &dwKeyValue, // Returns the field's value
173 &dwKeySize ); // Number of bytes transferred
174
175 if ((lReturn == ERROR_SUCCESS) && (dwKeyType == REG_DWORD))
176 {
177 PerflogModuleLevel = dwKeyValue;
178 }
179
180 RegCloseKey(hModuleKey);
181}
182
183BOOL PerflogInitIfEnabled(
184 IN HINSTANCE hInstance,
185 __in IN PPERFLOG_LOGGING_PARAMS LogParams
186 )
187{
188 PerflogReadModuleLevel( hInstance );
189 if (PerflogModuleLevel)
190 {
191 return PerflogInitialize( LogParams );
192 }
193 else
194 {
195 return FALSE;
196 }
197}
198
199BOOL
200PerflogInitialize (
201 __in IN PPERFLOG_LOGGING_PARAMS LogParams
202 )
203{
204 ULONG status;
205
206 //
207 // If we're running on a recent-enough platform, this will get
208 // pointers to the event tracing routines.
209 //
210
211 _Advapi32 = GetModuleHandle (_T("ADVAPI32.DLL"));
212 if (_Advapi32 == NULL) {
213 return FALSE;
214 }
215
216 *((FARPROC*) &_RegisterTraceGuids) = GetProcAddress (_Advapi32, REGISTERTRACEGUIDS_NAME);
217 *((FARPROC*) &_UnregisterTraceGuids) = GetProcAddress (_Advapi32, "UnregisterTraceGuids");
218 *((FARPROC*) &_GetTraceLoggerHandle) = GetProcAddress (_Advapi32, "GetTraceLoggerHandle");
219 *((FARPROC*) &_GetTraceEnableLevel) = GetProcAddress (_Advapi32, "GetTraceEnableLevel");
220 *((FARPROC*) &_GetTraceEnableFlags) = GetProcAddress (_Advapi32, "GetTraceEnableFlags");
221 *((FARPROC*) &_TraceEvent) = GetProcAddress (_Advapi32, "TraceEvent");
222
223 if (_RegisterTraceGuids == NULL ||
224 _UnregisterTraceGuids == NULL ||
225 _GetTraceEnableLevel == NULL ||
226 _GetTraceEnableFlags == NULL ||
227 _TraceEvent == NULL) {
228
229 return FALSE;
230 }
231
232 EventTracingAvailable = TRUE;
233
234 OnStateChanged = LogParams->OnStateChanged;
235
236 //
237 // Register our GUIDs.
238 //
239
240 status = _RegisterTraceGuids (PerflogCallback,
241 LogParams,
242 &LogParams->ControlGuid,
243 LogParams->NumberOfTraceGuids,
244 LogParams->TraceGuids,
245 NULL,
246 NULL,
247 &PerflogRegHandle);
248
249 return (status == ERROR_SUCCESS);
250}
251
252//
253// This routine shuts down performance logging.
254//
255
256VOID
257PerflogShutdown (
258 VOID
259 )
260{
261 if (!EventTracingAvailable) {
262 return;
263 }
264
265 _UnregisterTraceGuids (PerflogRegHandle);
266 PerflogRegHandle = NULL;
267 PerflogTraceHandle = NULL;
268}
269
270//
271// Event tracing callback routine.
272// It's called when controllers call event tracing control functions.
273//
274
275ULONG
276WINAPI
277PerflogCallback (
278 WMIDPREQUESTCODE RequestCode,
279 __in PVOID Context,
280 __out ULONG* BufferSize,
281 __in PVOID Buffer
282 )
283{
284 ULONG status;
285
286 UNREFERENCED_PARAMETER (Context);
287
288 ASSERT (EventTracingAvailable);
289
290 status = ERROR_SUCCESS;
291
292 switch (RequestCode) {
293
294 case WMI_ENABLE_EVENTS:
295 PerflogTraceHandle = _GetTraceLoggerHandle (Buffer);
296 PerflogEnableFlags = _GetTraceEnableFlags (PerflogTraceHandle);
297 PerflogEnableLevel = _GetTraceEnableLevel (PerflogTraceHandle);
298 break;
299
300 case WMI_DISABLE_EVENTS:
301 PerflogTraceHandle = NULL;
302 PerflogEnableFlags = 0;
303 PerflogEnableLevel = 0;
304 break;
305
306 default:
307 status = ERROR_INVALID_PARAMETER;
308 }
309
310 if (OnStateChanged != NULL) {
311 OnStateChanged();
312 }
313
314 *BufferSize = 0;
315 return status;
316}
317
318//
319// Logging routine.
320//
321
322VOID
323PerflogTraceEvent (
324 __in PEVENT_TRACE_HEADER Event
325 )
326{
327 if (!EventTracingAvailable) {
328 return;
329 }
330
331 _TraceEvent (PerflogTraceHandle, Event);
332}
333
334VOID
335PerflogTraceEventLevel(
336 ULONG Level,
337 __in PEVENT_TRACE_HEADER Event
338 )
339{
340 if ((!EventTracingAvailable) || (Level <= PerflogModuleLevel)) {
341 return;
342 }
343
344 _TraceEvent (PerflogTraceHandle, Event);
345}
346
347