1 //------------------------------------------------------------------------------
4 // Desc: DirectShow base classes - provides debugging facilities.
6 // Copyright (c) 1992-2002 Microsoft Corporation. All rights reserved.
7 //------------------------------------------------------------------------------
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.
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.
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
42 // These are the five different categories of logging information
44 enum { 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
56 #define LOG_FORCIBLY_SET 0x80000000
58 enum { CDISP_HEX
= 0x01,
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
66 typedef struct tag_ObjectDesc
{
68 const WCHAR
*m_wszName
;
70 tag_ObjectDesc
*m_pNext
;
73 #define DLLIMPORT __declspec(dllimport)
74 #define DLLEXPORT __declspec(dllexport)
78 #define NAME(x) TEXT(x)
80 // These are used internally by the debug library (PRIVATE)
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 const CHAR
*szObjectName
, const WCHAR
*wszObjectName
);
89 BOOL WINAPI
DbgRegisterObjectDestruction(DWORD dwCookie
);
91 // These are the PUBLIC entry points
93 BOOL WINAPI
DbgCheckModuleLevel(DWORD Type
,DWORD Level
);
94 void WINAPI
DbgSetModuleLevel(DWORD Type
,DWORD Level
);
95 void WINAPI
DbgSetAutoRefreshLevels(bool fAuto
);
97 // Initialise the library with the module handle
99 void WINAPI
DbgInitialise(HINSTANCE hInst
);
100 void WINAPI
DbgTerminate();
102 void WINAPI
DbgDumpObjectRegister();
104 // Display error and logging to the user
106 void WINAPI
DbgAssert(const TCHAR
*pCondition
,const TCHAR
*pFileName
,INT iLine
);
107 void WINAPI
DbgBreakPoint(const TCHAR
*pCondition
,const TCHAR
*pFileName
,INT iLine
);
108 void WINAPI
DbgBreakPoint(const TCHAR
*pFileName
,INT iLine
,const TCHAR
* szFormatString
,...);
110 void WINAPI
DbgKernelAssert(const TCHAR
*pCondition
,const TCHAR
*pFileName
,INT iLine
);
111 void WINAPI
DbgLogInfo(DWORD Type
,DWORD Level
,const TCHAR
*pFormat
,...);
113 void WINAPI
DbgLogInfo(DWORD Type
,DWORD Level
,const CHAR
*pFormat
,...);
114 void WINAPI
DbgAssert(const CHAR
*pCondition
,const CHAR
*pFileName
,INT iLine
);
115 void WINAPI
DbgBreakPoint(const CHAR
*pCondition
,const CHAR
*pFileName
,INT iLine
);
116 void WINAPI
DbgKernelAssert(const CHAR
*pCondition
,const CHAR
*pFileName
,INT iLine
);
118 void WINAPI
DbgOutString(LPCTSTR psz
);
120 // Debug infinite wait stuff
121 DWORD WINAPI
DbgWaitForSingleObject(HANDLE h
);
122 DWORD WINAPI
DbgWaitForMultipleObjects(DWORD nCount
,
123 CONST HANDLE
*lpHandles
,
125 void WINAPI
DbgSetWaitTimeout(DWORD dwTimeout
);
128 // Display a media type: Terse at level 2, verbose at level 5
129 void WINAPI
DisplayType(LPTSTR label
, const AM_MEDIA_TYPE
*pmtIn
);
131 // Dump lots of information about a filter graph
132 void WINAPI
DumpGraph(IFilterGraph
*pGraph
, DWORD dwLevel
);
135 #define KASSERT(_x_) if (!(_x_)) \
136 DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
138 // Break on the debugger without putting up a message box
139 // message goes to debugger instead
141 #define KDbgBreak(_x_) \
142 DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
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)
149 #define ASSERT(_x_) if (!(_x_)) \
150 DbgAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
153 #define DbgAssertAligned( _ptr_, _alignment_ ) ASSERT( ((DWORD_PTR) (_ptr_)) % (_alignment_) == 0)
155 // Put up a message box informing the user of a halt
156 // condition in the program
158 #define DbgBreak(_x_) \
159 DbgBreakPoint(TEXT(#_x_),TEXT(__FILE__),__LINE__)
161 #define EXECUTE_ASSERT(_x_) ASSERT(_x_)
162 #define DbgLog(_x_) DbgLogInfo _x_
163 // MFC style trace macros
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))
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
179 #define NAME(_x_) ((TCHAR *) NULL)
181 #define DbgInitialise(hInst)
182 #define DbgTerminate()
183 #define DbgLog(_x_) 0
184 #define DbgOutString(psz)
185 #define DbgAssertAligned( _ptr_, _alignment_ ) 0
187 #define DbgRegisterObjectCreation(pObjectName)
188 #define DbgRegisterObjectDestruction(dwCookie)
189 #define DbgDumpObjectRegister()
191 #define DbgCheckModuleLevel(Type,Level)
192 #define DbgSetModuleLevel(Type,Level)
193 #define DbgSetAutoRefreshLevels(fAuto)
195 #define DbgWaitForSingleObject(h) WaitForSingleObject(h, INFINITE)
196 #define DbgWaitForMultipleObjects(nCount, lpHandles, bWaitAll) \
197 WaitForMultipleObjects(nCount, lpHandles, bWaitAll, INFINITE)
198 #define DbgSetWaitTimeout(dwTimeout)
200 #define KDbgBreak(_x_)
201 #define DbgBreak(_x_)
203 #define KASSERT(_x_) ((void)0)
205 #define ASSERT(_x_) ((void)0)
207 #define EXECUTE_ASSERT(_x_) ((void)(_x_))
209 // MFC style trace macros
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)
218 #define DisplayType(label, pmtIn) ((void)0)
219 #define DumpGraph(pGraph, label) ((void)0)
223 // Checks a pointer which should be non NULL - can be used as follows.
225 #define CheckPointer(p,ret) {if((p)==NULL) return (ret);}
227 // HRESULT Foo(VOID *pBar)
229 // CheckPointer(pBar,E_INVALIDARG)
232 // Or if the function returns a boolean
234 // BOOL Foo(VOID *pBar)
236 // CheckPointer(pBar,FALSE)
239 // These validate pointers when symbol VFWROBUST is defined
240 // This will normally be defined in debug not retail builds
248 #define ValidateReadPtr(p,cb) \
249 {if(IsBadReadPtr((PVOID)p,cb) == TRUE) \
250 DbgBreak("Invalid read pointer");}
252 #define ValidateWritePtr(p,cb) \
253 {if(IsBadWritePtr((PVOID)p,cb) == TRUE) \
254 DbgBreak("Invalid write pointer");}
256 #define ValidateReadWritePtr(p,cb) \
257 {ValidateReadPtr(p,cb) ValidateWritePtr(p,cb)}
259 #define ValidateStringPtr(p) \
260 {if(IsBadStringPtr((LPCTSTR)p,INFINITE) == TRUE) \
261 DbgBreak("Invalid string pointer");}
263 #define ValidateStringPtrA(p) \
264 {if(IsBadStringPtrA((LPCSTR)p,INFINITE) == TRUE) \
265 DbgBreak("Invalid ANSI string pointer");}
267 #define ValidateStringPtrW(p) \
268 {if(IsBadStringPtrW((LPCWSTR)p,INFINITE) == TRUE) \
269 DbgBreak("Invalid UNICODE string pointer");}
272 #define ValidateReadPtr(p,cb) 0
273 #define ValidateWritePtr(p,cb) 0
274 #define ValidateReadWritePtr(p,cb) 0
275 #define ValidateStringPtr(p) 0
276 #define ValidateStringPtrA(p) 0
277 #define ValidateStringPtrW(p) 0
283 // Outputting GUID names. If you want to include the name
284 // associated with a GUID (eg CLSID_...) then
286 // GuidNames[yourGUID]
288 // Returns the name defined in uuids.h as a string
295 class CGuidNameList
{
297 CHAR
*operator [] (const GUID
& guid
);
300 extern CGuidNameList GuidNames
;
305 // REMIND macro - generates warning as reminder to complete coding
308 // #pragma message (REMIND("Add automation support"))
312 #define QQUOTE(y) QUOTE(y)
313 #define REMIND(str) __FILE__ "(" QQUOTE(__LINE__) ") : " str
316 // Method to display objects in a useful format
318 // eg If you want to display a LONGLONG ll in a debug string do (eg)
320 // DbgLog((LOG_TRACE, n, TEXT("Value is %s"), (LPCTSTR)CDisp(ll, CDISP_HEX)));
326 CDispBasic() { m_pString
= m_String
; };
329 PTCHAR m_pString
; // normally points to m_String... unless too much data
332 class CDisp
: public CDispBasic
335 CDisp(LONGLONG ll
, int Format
= CDISP_HEX
); // Display a LONGLONG in CDISP_HEX or CDISP_DEC form
336 CDisp(REFCLSID clsid
); // Display a GUID
337 CDisp(double d
); // Display a floating point number
340 CDisp(CRefTime t
); // Display a Reference Time
342 CDisp(IPin
*pPin
); // Display a pin as {filter clsid}(pin name)
343 CDisp(IUnknown
*pUnk
); // Display a filter or pin
344 #endif // __strmif_h__
347 // Implement cast to (LPCTSTR) as parameter to logger
350 return (LPCTSTR
)m_pString
;
359 const TCHAR
* _szBlkName
;
361 static const TCHAR _szEntering
[];
362 static const TCHAR _szLeaving
[];
364 CAutoTrace(const TCHAR
* szBlkName
, const int level
= 15)
365 : _szBlkName(szBlkName
), _level(level
)
366 {DbgLog((LOG_TRACE
, _level
, _szEntering
, _szBlkName
));}
369 {DbgLog((LOG_TRACE
, _level
, _szLeaving
, _szBlkName
));}
372 #define AMTRACE(_x_) CAutoTrace __trace _x_
377 #endif // __WXDEBUG__