blob: d4c69dbb0ed76460065053a8315523b6976c07ec [file] [log] [blame]
Tristan Matthews0a329cc2013-07-17 13:20:14 -04001//------------------------------------------------------------------------------
2// File: WXDebug.h
3//
4// Desc: DirectShow base classes - provides debugging facilities.
5//
6// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
7//------------------------------------------------------------------------------
8
9
10#ifndef __WXDEBUG__
11#define __WXDEBUG__
12
13// This library provides fairly straight forward debugging functionality, this
14// is split into two main sections. The first is assertion handling, there are
15// three types of assertions provided here. The most commonly used one is the
16// ASSERT(condition) macro which will pop up a message box including the file
17// and line number if the condition evaluates to FALSE. Then there is the
18// EXECUTE_ASSERT macro which is the same as ASSERT except the condition will
19// still be executed in NON debug builds. The final type of assertion is the
20// KASSERT macro which is more suitable for pure (perhaps kernel) filters as
21// the condition is printed onto the debugger rather than in a message box.
22//
23// The other part of the debug module facilties is general purpose logging.
24// This is accessed by calling DbgLog(). The function takes a type and level
25// field which define the type of informational string you are presenting and
26// it's relative importance. The type field can be a combination (one or more)
27// of LOG_TIMING, LOG_TRACE, LOG_MEMORY, LOG_LOCKING and LOG_ERROR. The level
28// is a DWORD value where zero defines highest important. Use of zero as the
29// debug logging level is to be encouraged ONLY for major errors or events as
30// they will ALWAYS be displayed on the debugger. Other debug output has it's
31// level matched against the current debug output level stored in the registry
32// for this module and if less than the current setting it will be displayed.
33//
34// Each module or executable has it's own debug output level for each of the
35// five types. These are read in when the DbgInitialise function is called
36// for DLLs linking to STRMBASE.LIB this is done automatically when the DLL
37// is loaded, executables must call it explicitely with the module instance
38// handle given to them through the WINMAIN entry point. An executable must
39// also call DbgTerminate when they have finished to clean up the resources
40// the debug library uses, once again this is done automatically for DLLs
41
42// These are the five different categories of logging information
43
44enum { LOG_TIMING = 0x01, // Timing and performance measurements
45 LOG_TRACE = 0x02, // General step point call tracing
46 LOG_MEMORY = 0x04, // Memory and object allocation/destruction
47 LOG_LOCKING = 0x08, // Locking/unlocking of critical sections
48 LOG_ERROR = 0x10, // Debug error notification
49 LOG_CUSTOM1 = 0x20,
50 LOG_CUSTOM2 = 0x40,
51 LOG_CUSTOM3 = 0x80,
52 LOG_CUSTOM4 = 0x100,
53 LOG_CUSTOM5 = 0x200,
54};
55
56#define LOG_FORCIBLY_SET 0x80000000
57
58enum { CDISP_HEX = 0x01,
59 CDISP_DEC = 0x02};
60
61// For each object created derived from CBaseObject (in debug builds) we
62// create a descriptor that holds it's name (statically allocated memory)
63// and a cookie we assign it. We keep a list of all the active objects
64// we have registered so that we can dump a list of remaining objects
65
66typedef struct tag_ObjectDesc {
67 LPCSTR m_szName;
68 LPCWSTR m_wszName;
69 DWORD m_dwCookie;
70 tag_ObjectDesc *m_pNext;
71} ObjectDesc;
72
73#define DLLIMPORT __declspec(dllimport)
74#define DLLEXPORT __declspec(dllexport)
75
76#ifdef DEBUG
77
78 #define NAME(x) TEXT(x)
79
80 // These are used internally by the debug library (PRIVATE)
81
82 void WINAPI DbgInitKeyLevels(HKEY hKey, bool fTakeMax);
83 void WINAPI DbgInitGlobalSettings(bool fTakeMax);
84 void WINAPI DbgInitModuleSettings(bool fTakeMax);
85 void WINAPI DbgInitModuleName();
86 DWORD WINAPI DbgRegisterObjectCreation(
87 LPCSTR szObjectName, LPCWSTR wszObjectName);
88
89 BOOL WINAPI DbgRegisterObjectDestruction(DWORD dwCookie);
90
91 // These are the PUBLIC entry points
92
93 BOOL WINAPI DbgCheckModuleLevel(DWORD Type,DWORD Level);
94 void WINAPI DbgSetModuleLevel(DWORD Type,DWORD Level);
95 void WINAPI DbgSetAutoRefreshLevels(bool fAuto);
96
97 // Initialise the library with the module handle
98
99 void WINAPI DbgInitialise(HINSTANCE hInst);
100 void WINAPI DbgTerminate();
101
102 void WINAPI DbgDumpObjectRegister();
103
104 // Display error and logging to the user
105
106 void WINAPI DbgAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine);
107 void WINAPI DbgBreakPoint(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine);
108 void WINAPI DbgBreakPoint(LPCTSTR pFileName,INT iLine,__format_string LPCTSTR szFormatString,...);
109
110 void WINAPI DbgKernelAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine);
111 void WINAPI DbgLogInfo(DWORD Type,DWORD Level,__format_string LPCTSTR pFormat,...);
112#ifdef UNICODE
113 void WINAPI DbgLogInfo(DWORD Type,DWORD Level,__format_string LPCSTR pFormat,...);
114 void WINAPI DbgAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine);
115 void WINAPI DbgBreakPoint(LPCSTR pCondition,LPCSTR pFileName,INT iLine);
116 void WINAPI DbgKernelAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine);
117#endif
118 void WINAPI DbgOutString(LPCTSTR psz);
119
120 // Debug infinite wait stuff
121 DWORD WINAPI DbgWaitForSingleObject(HANDLE h);
122 DWORD WINAPI DbgWaitForMultipleObjects(DWORD nCount,
123 __in_ecount(nCount) CONST HANDLE *lpHandles,
124 BOOL bWaitAll);
125 void WINAPI DbgSetWaitTimeout(DWORD dwTimeout);
126
127#ifdef __strmif_h__
128 // Display a media type: Terse at level 2, verbose at level 5
129 void WINAPI DisplayType(LPCTSTR label, const AM_MEDIA_TYPE *pmtIn);
130
131 // Dump lots of information about a filter graph
132 void WINAPI DumpGraph(IFilterGraph *pGraph, DWORD dwLevel);
133#endif
134
135 #define KASSERT(_x_) if (!(_x_)) \
136 DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
137
138 // Break on the debugger without putting up a message box
139 // message goes to debugger instead
140
141 #define KDbgBreak(_x_) \
142 DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
143
144 // We chose a common name for our ASSERT macro, MFC also uses this name
145 // So long as the implementation evaluates the condition and handles it
146 // then we will be ok. Rather than override the behaviour expected we
147 // will leave whatever first defines ASSERT as the handler (i.e. MFC)
148 #ifndef ASSERT
149 #define ASSERT(_x_) if (!(_x_)) \
150 DbgAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
151 #endif
152
153 #define DbgAssertAligned( _ptr_, _alignment_ ) ASSERT( ((DWORD_PTR) (_ptr_)) % (_alignment_) == 0)
154
155 // Put up a message box informing the user of a halt
156 // condition in the program
157
158 #define DbgBreak(_x_) \
159 DbgBreakPoint(TEXT(#_x_),TEXT(__FILE__),__LINE__)
160
161 #define EXECUTE_ASSERT(_x_) ASSERT(_x_)
162 #define DbgLog(_x_) DbgLogInfo _x_
163 // MFC style trace macros
164
165 #define NOTE(_x_) DbgLog((LOG_TRACE,5,TEXT(_x_)))
166 #define NOTE1(_x_,a) DbgLog((LOG_TRACE,5,TEXT(_x_),a))
167 #define NOTE2(_x_,a,b) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b))
168 #define NOTE3(_x_,a,b,c) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c))
169 #define NOTE4(_x_,a,b,c,d) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d))
170 #define NOTE5(_x_,a,b,c,d,e) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d,e))
171
172#else
173
174 // Retail builds make public debug functions inert - WARNING the source
175 // files do not define or build any of the entry points in debug builds
176 // (public entry points compile to nothing) so if you go trying to call
177 // any of the private entry points in your source they won't compile
178
179 #define NAME(_x_) ((LPTSTR) NULL)
180
181 #define DbgInitialise(hInst)
182 #define DbgTerminate()
183 #define DbgLog(_x_) 0
184 #define DbgOutString(psz)
185 #define DbgAssertAligned( _ptr_, _alignment_ ) 0
186
187 #define DbgRegisterObjectCreation(pObjectName)
188 #define DbgRegisterObjectDestruction(dwCookie)
189 #define DbgDumpObjectRegister()
190
191 #define DbgCheckModuleLevel(Type,Level)
192 #define DbgSetModuleLevel(Type,Level)
193 #define DbgSetAutoRefreshLevels(fAuto)
194
195 #define DbgWaitForSingleObject(h) WaitForSingleObject(h, INFINITE)
196 #define DbgWaitForMultipleObjects(nCount, lpHandles, bWaitAll) \
197 WaitForMultipleObjects(nCount, lpHandles, bWaitAll, INFINITE)
198 #define DbgSetWaitTimeout(dwTimeout)
199
200 #define KDbgBreak(_x_)
201 #define DbgBreak(_x_)
202
203 #define KASSERT(_x_) ((void)0)
204 #ifndef ASSERT
205 #define ASSERT(_x_) ((void)0)
206 #endif
207 #define EXECUTE_ASSERT(_x_) ((void)(_x_))
208
209 // MFC style trace macros
210
211 #define NOTE(_x_) ((void)0)
212 #define NOTE1(_x_,a) ((void)0)
213 #define NOTE2(_x_,a,b) ((void)0)
214 #define NOTE3(_x_,a,b,c) ((void)0)
215 #define NOTE4(_x_,a,b,c,d) ((void)0)
216 #define NOTE5(_x_,a,b,c,d,e) ((void)0)
217
218 #define DisplayType(label, pmtIn) ((void)0)
219 #define DumpGraph(pGraph, label) ((void)0)
220#endif
221
222
223// Checks a pointer which should be non NULL - can be used as follows.
224
225#define CheckPointer(p,ret) {if((p)==NULL) return (ret);}
226
227// HRESULT Foo(VOID *pBar)
228// {
229// CheckPointer(pBar,E_INVALIDARG)
230// }
231//
232// Or if the function returns a boolean
233//
234// BOOL Foo(VOID *pBar)
235// {
236// CheckPointer(pBar,FALSE)
237// }
238
239#define ValidateReadPtr(p,cb) 0
240#define ValidateWritePtr(p,cb) 0
241#define ValidateReadWritePtr(p,cb) 0
242#define ValidateStringPtr(p) 0
243#define ValidateStringPtrA(p) 0
244#define ValidateStringPtrW(p) 0
245
246
247#ifdef _OBJBASE_H_
248
249 // Outputting GUID names. If you want to include the name
250 // associated with a GUID (eg CLSID_...) then
251 //
252 // GuidNames[yourGUID]
253 //
254 // Returns the name defined in uuids.h as a string
255
256 typedef struct {
257 CHAR *szName;
258 GUID guid;
259 } GUID_STRING_ENTRY;
260
261 class CGuidNameList {
262 public:
263 CHAR *operator [] (const GUID& guid);
264 };
265
266 extern CGuidNameList GuidNames;
267
268#endif
269
270#ifndef REMIND
271 // REMIND macro - generates warning as reminder to complete coding
272 // (eg) usage:
273 //
274 // #pragma message (REMIND("Add automation support"))
275
276
277 #define QUOTE(x) #x
278 #define QQUOTE(y) QUOTE(y)
279 #define REMIND(str) __FILE__ "(" QQUOTE(__LINE__) ") : " str
280#endif
281
282// Method to display objects in a useful format
283//
284// eg If you want to display a LONGLONG ll in a debug string do (eg)
285//
286// DbgLog((LOG_TRACE, n, TEXT("Value is %s"), (LPCTSTR)CDisp(ll, CDISP_HEX)));
287
288
289class CDispBasic
290{
291public:
292 CDispBasic() { m_pString = m_String; };
293 ~CDispBasic();
294protected:
295 PTCHAR m_pString; // normally points to m_String... unless too much data
296 TCHAR m_String[50];
297};
298class CDisp : public CDispBasic
299{
300public:
301 CDisp(LONGLONG ll, int Format = CDISP_HEX); // Display a LONGLONG in CDISP_HEX or CDISP_DEC form
302 CDisp(REFCLSID clsid); // Display a GUID
303 CDisp(double d); // Display a floating point number
304#ifdef __strmif_h__
305#ifdef __STREAMS__
306 CDisp(CRefTime t); // Display a Reference Time
307#endif
308 CDisp(IPin *pPin); // Display a pin as {filter clsid}(pin name)
309 CDisp(IUnknown *pUnk); // Display a filter or pin
310#endif // __strmif_h__
311 ~CDisp();
312
313 // Implement cast to (LPCTSTR) as parameter to logger
314 operator LPCTSTR()
315 {
316 return (LPCTSTR)m_pString;
317 };
318};
319
320
321#if defined(DEBUG)
322class CAutoTrace
323{
324private:
325 LPCTSTR _szBlkName;
326 const int _level;
327 static const TCHAR _szEntering[];
328 static const TCHAR _szLeaving[];
329public:
330 CAutoTrace(LPCTSTR szBlkName, const int level = 15)
331 : _szBlkName(szBlkName), _level(level)
332 {DbgLog((LOG_TRACE, _level, _szEntering, _szBlkName));}
333
334 ~CAutoTrace()
335 {DbgLog((LOG_TRACE, _level, _szLeaving, _szBlkName));}
336};
337
338#if defined (__FUNCTION__)
339
340#define AMTRACEFN() CAutoTrace __trace(TEXT(__FUNCTION__))
341#define AMTRACE(_x_) CAutoTrace __trace(TEXT(__FUNCTION__))
342
343#else
344
345#define AMTRACE(_x_) CAutoTrace __trace _x_
346#define AMTRACEFN()
347
348#endif
349
350#else
351
352#define AMTRACE(_x_)
353#define AMTRACEFN()
354
355#endif
356
357#endif // __WXDEBUG__
358
359