forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			360 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			360 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | //------------------------------------------------------------------------------
 | ||
|  | // File: WXDebug.h
 | ||
|  | //
 | ||
|  | // Desc: DirectShow base classes - provides debugging facilities.
 | ||
|  | //
 | ||
|  | // Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
 | ||
|  | //------------------------------------------------------------------------------
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #ifndef __WXDEBUG__
 | ||
|  | #define __WXDEBUG__
 | ||
|  | 
 | ||
|  | // This library provides fairly straight forward debugging functionality, this
 | ||
|  | // is split into two main sections. The first is assertion handling, there are
 | ||
|  | // three types of assertions provided here. The most commonly used one is the
 | ||
|  | // ASSERT(condition) macro which will pop up a message box including the file
 | ||
|  | // and line number if the condition evaluates to FALSE. Then there is the
 | ||
|  | // EXECUTE_ASSERT macro which is the same as ASSERT except the condition will
 | ||
|  | // still be executed in NON debug builds. The final type of assertion is the
 | ||
|  | // KASSERT macro which is more suitable for pure (perhaps kernel) filters as
 | ||
|  | // the condition is printed onto the debugger rather than in a message box.
 | ||
|  | //
 | ||
|  | // The other part of the debug module facilties is general purpose logging.
 | ||
|  | // This is accessed by calling DbgLog(). The function takes a type and level
 | ||
|  | // field which define the type of informational string you are presenting and
 | ||
|  | // it's relative importance. The type field can be a combination (one or more)
 | ||
|  | // of LOG_TIMING, LOG_TRACE, LOG_MEMORY, LOG_LOCKING and LOG_ERROR. The level
 | ||
|  | // is a DWORD value where zero defines highest important. Use of zero as the
 | ||
|  | // debug logging level is to be encouraged ONLY for major errors or events as
 | ||
|  | // they will ALWAYS be displayed on the debugger. Other debug output has it's
 | ||
|  | // level matched against the current debug output level stored in the registry
 | ||
|  | // for this module and if less than the current setting it will be displayed.
 | ||
|  | //
 | ||
|  | // Each module or executable has it's own debug output level for each of the
 | ||
|  | // five types. These are read in when the DbgInitialise function is called
 | ||
|  | // for DLLs linking to STRMBASE.LIB this is done automatically when the DLL
 | ||
|  | // is loaded, executables must call it explicitely with the module instance
 | ||
|  | // handle given to them through the WINMAIN entry point. An executable must
 | ||
|  | // also call DbgTerminate when they have finished to clean up the resources
 | ||
|  | // the debug library uses, once again this is done automatically for DLLs
 | ||
|  | 
 | ||
|  | // These are the five different categories of logging information
 | ||
|  | 
 | ||
|  | enum {  LOG_TIMING = 0x01,    // Timing and performance measurements
 | ||
|  |         LOG_TRACE = 0x02,     // General step point call tracing
 | ||
|  |         LOG_MEMORY =  0x04,   // Memory and object allocation/destruction
 | ||
|  |         LOG_LOCKING = 0x08,   // Locking/unlocking of critical sections
 | ||
|  |         LOG_ERROR = 0x10,     // Debug error notification
 | ||
|  |         LOG_CUSTOM1 = 0x20, | ||
|  |         LOG_CUSTOM2 = 0x40, | ||
|  |         LOG_CUSTOM3 = 0x80, | ||
|  |         LOG_CUSTOM4 = 0x100, | ||
|  |         LOG_CUSTOM5 = 0x200, | ||
|  | }; | ||
|  | 
 | ||
|  | #define LOG_FORCIBLY_SET 0x80000000
 | ||
|  | 
 | ||
|  | enum {  CDISP_HEX = 0x01, | ||
|  |         CDISP_DEC = 0x02}; | ||
|  | 
 | ||
|  | // For each object created derived from CBaseObject (in debug builds) we
 | ||
|  | // create a descriptor that holds it's name (statically allocated memory)
 | ||
|  | // and a cookie we assign it. We keep a list of all the active objects
 | ||
|  | // we have registered so that we can dump a list of remaining objects
 | ||
|  | 
 | ||
|  | typedef struct tag_ObjectDesc { | ||
|  |     LPCSTR m_szName; | ||
|  |     LPCWSTR m_wszName; | ||
|  |     DWORD m_dwCookie; | ||
|  |     tag_ObjectDesc *m_pNext; | ||
|  | } ObjectDesc; | ||
|  | 
 | ||
|  | #define DLLIMPORT __declspec(dllimport)
 | ||
|  | #define DLLEXPORT __declspec(dllexport)
 | ||
|  | 
 | ||
|  | #ifdef DEBUG
 | ||
|  | 
 | ||
|  |     #define NAME(x) TEXT(x)
 | ||
|  | 
 | ||
|  |     // These are used internally by the debug library (PRIVATE)
 | ||
|  | 
 | ||
|  |     void WINAPI DbgInitKeyLevels(HKEY hKey, bool fTakeMax); | ||
|  |     void WINAPI DbgInitGlobalSettings(bool fTakeMax); | ||
|  |     void WINAPI DbgInitModuleSettings(bool fTakeMax); | ||
|  |     void WINAPI DbgInitModuleName(); | ||
|  |     DWORD WINAPI DbgRegisterObjectCreation( | ||
|  |         LPCSTR szObjectName, LPCWSTR wszObjectName); | ||
|  | 
 | ||
|  |     BOOL WINAPI DbgRegisterObjectDestruction(DWORD dwCookie); | ||
|  | 
 | ||
|  |     // These are the PUBLIC entry points
 | ||
|  | 
 | ||
|  |     BOOL WINAPI DbgCheckModuleLevel(DWORD Type,DWORD Level); | ||
|  |     void WINAPI DbgSetModuleLevel(DWORD Type,DWORD Level); | ||
|  |     void WINAPI DbgSetAutoRefreshLevels(bool fAuto); | ||
|  | 
 | ||
|  |     // Initialise the library with the module handle
 | ||
|  | 
 | ||
|  |     void WINAPI DbgInitialise(HINSTANCE hInst); | ||
|  |     void WINAPI DbgTerminate(); | ||
|  | 
 | ||
|  |     void WINAPI DbgDumpObjectRegister(); | ||
|  | 
 | ||
|  |     // Display error and logging to the user
 | ||
|  | 
 | ||
|  |     void WINAPI DbgAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine); | ||
|  |     void WINAPI DbgBreakPoint(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine); | ||
|  |     void WINAPI DbgBreakPoint(LPCTSTR pFileName,INT iLine,__format_string LPCTSTR  szFormatString,...); | ||
|  | 
 | ||
|  |     void WINAPI DbgKernelAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine); | ||
|  |     void WINAPI DbgLogInfo(DWORD Type,DWORD Level,__format_string LPCTSTR pFormat,...); | ||
|  | #ifdef UNICODE
 | ||
|  |     void WINAPI DbgLogInfo(DWORD Type,DWORD Level,__format_string LPCSTR pFormat,...); | ||
|  |     void WINAPI DbgAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine); | ||
|  |     void WINAPI DbgBreakPoint(LPCSTR pCondition,LPCSTR pFileName,INT iLine); | ||
|  |     void WINAPI DbgKernelAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine); | ||
|  | #endif
 | ||
|  |     void WINAPI DbgOutString(LPCTSTR psz); | ||
|  | 
 | ||
|  |     //  Debug infinite wait stuff
 | ||
|  |     DWORD WINAPI DbgWaitForSingleObject(HANDLE h); | ||
|  |     DWORD WINAPI DbgWaitForMultipleObjects(DWORD nCount, | ||
|  |                                     __in_ecount(nCount) CONST HANDLE *lpHandles, | ||
|  |                                     BOOL bWaitAll); | ||
|  |     void WINAPI DbgSetWaitTimeout(DWORD dwTimeout); | ||
|  | 
 | ||
|  | #ifdef __strmif_h__
 | ||
|  |     // Display a media type: Terse at level 2, verbose at level 5
 | ||
|  |     void WINAPI DisplayType(LPCTSTR label, const AM_MEDIA_TYPE *pmtIn); | ||
|  | 
 | ||
|  |     // Dump lots of information about a filter graph
 | ||
|  |     void WINAPI DumpGraph(IFilterGraph *pGraph, DWORD dwLevel); | ||
|  | #endif
 | ||
|  | 
 | ||
|  |     #define KASSERT(_x_) if (!(_x_))         \
 | ||
|  |         DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__) | ||
|  | 
 | ||
|  |     //  Break on the debugger without putting up a message box
 | ||
|  |     //  message goes to debugger instead
 | ||
|  | 
 | ||
|  |     #define KDbgBreak(_x_)                   \
 | ||
|  |         DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__) | ||
|  | 
 | ||
|  |     // We chose a common name for our ASSERT macro, MFC also uses this name
 | ||
|  |     // So long as the implementation evaluates the condition and handles it
 | ||
|  |     // then we will be ok. Rather than override the behaviour expected we
 | ||
|  |     // will leave whatever first defines ASSERT as the handler (i.e. MFC)
 | ||
|  |     #ifndef ASSERT
 | ||
|  |         #define ASSERT(_x_) if (!(_x_))         \
 | ||
|  |             DbgAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__) | ||
|  |     #endif
 | ||
|  | 
 | ||
|  |     #define DbgAssertAligned( _ptr_, _alignment_ ) ASSERT( ((DWORD_PTR) (_ptr_)) % (_alignment_) == 0)
 | ||
|  | 
 | ||
|  |     //  Put up a message box informing the user of a halt
 | ||
|  |     //  condition in the program
 | ||
|  | 
 | ||
|  |     #define DbgBreak(_x_)                   \
 | ||
|  |         DbgBreakPoint(TEXT(#_x_),TEXT(__FILE__),__LINE__) | ||
|  | 
 | ||
|  |     #define EXECUTE_ASSERT(_x_) ASSERT(_x_)
 | ||
|  |     #define DbgLog(_x_) DbgLogInfo _x_
 | ||
|  |     // MFC style trace macros
 | ||
|  | 
 | ||
|  |     #define NOTE(_x_)             DbgLog((LOG_TRACE,5,TEXT(_x_)))
 | ||
|  |     #define NOTE1(_x_,a)          DbgLog((LOG_TRACE,5,TEXT(_x_),a))
 | ||
|  |     #define NOTE2(_x_,a,b)        DbgLog((LOG_TRACE,5,TEXT(_x_),a,b))
 | ||
|  |     #define NOTE3(_x_,a,b,c)      DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c))
 | ||
|  |     #define NOTE4(_x_,a,b,c,d)    DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d))
 | ||
|  |     #define NOTE5(_x_,a,b,c,d,e)  DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d,e))
 | ||
|  | 
 | ||
|  | #else
 | ||
|  | 
 | ||
|  |     // Retail builds make public debug functions inert  - WARNING the source
 | ||
|  |     // files do not define or build any of the entry points in debug builds
 | ||
|  |     // (public entry points compile to nothing) so if you go trying to call
 | ||
|  |     // any of the private entry points in your source they won't compile
 | ||
|  | 
 | ||
|  |     #define NAME(_x_) ((LPTSTR) NULL)
 | ||
|  | 
 | ||
|  |     #define DbgInitialise(hInst)
 | ||
|  |     #define DbgTerminate()
 | ||
|  |     #define DbgLog(_x_) 0
 | ||
|  |     #define DbgOutString(psz)
 | ||
|  |     #define DbgAssertAligned( _ptr_, _alignment_ ) 0
 | ||
|  | 
 | ||
|  |     #define DbgRegisterObjectCreation(pObjectName)
 | ||
|  |     #define DbgRegisterObjectDestruction(dwCookie)
 | ||
|  |     #define DbgDumpObjectRegister()
 | ||
|  | 
 | ||
|  |     #define DbgCheckModuleLevel(Type,Level)
 | ||
|  |     #define DbgSetModuleLevel(Type,Level)
 | ||
|  |     #define DbgSetAutoRefreshLevels(fAuto)
 | ||
|  | 
 | ||
|  |     #define DbgWaitForSingleObject(h)  WaitForSingleObject(h, INFINITE)
 | ||
|  |     #define DbgWaitForMultipleObjects(nCount, lpHandles, bWaitAll)     \
 | ||
|  |                WaitForMultipleObjects(nCount, lpHandles, bWaitAll, INFINITE) | ||
|  |     #define DbgSetWaitTimeout(dwTimeout)
 | ||
|  | 
 | ||
|  |     #define KDbgBreak(_x_)
 | ||
|  |     #define DbgBreak(_x_)
 | ||
|  | 
 | ||
|  |     #define KASSERT(_x_) ((void)0)
 | ||
|  |     #ifndef ASSERT
 | ||
|  | 	#define ASSERT(_x_) ((void)0)
 | ||
|  |     #endif
 | ||
|  |     #define EXECUTE_ASSERT(_x_) ((void)(_x_))
 | ||
|  | 
 | ||
|  |     // MFC style trace macros
 | ||
|  | 
 | ||
|  |     #define NOTE(_x_) ((void)0)
 | ||
|  |     #define NOTE1(_x_,a) ((void)0)
 | ||
|  |     #define NOTE2(_x_,a,b) ((void)0)
 | ||
|  |     #define NOTE3(_x_,a,b,c) ((void)0)
 | ||
|  |     #define NOTE4(_x_,a,b,c,d) ((void)0)
 | ||
|  |     #define NOTE5(_x_,a,b,c,d,e) ((void)0)
 | ||
|  | 
 | ||
|  |     #define DisplayType(label, pmtIn) ((void)0)
 | ||
|  |     #define DumpGraph(pGraph, label) ((void)0)
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | 
 | ||
|  | // Checks a pointer which should be non NULL - can be used as follows.
 | ||
|  | 
 | ||
|  | #define CheckPointer(p,ret) {if((p)==NULL) return (ret);}
 | ||
|  | 
 | ||
|  | //   HRESULT Foo(VOID *pBar)
 | ||
|  | //   {
 | ||
|  | //       CheckPointer(pBar,E_INVALIDARG)
 | ||
|  | //   }
 | ||
|  | //
 | ||
|  | //   Or if the function returns a boolean
 | ||
|  | //
 | ||
|  | //   BOOL Foo(VOID *pBar)
 | ||
|  | //   {
 | ||
|  | //       CheckPointer(pBar,FALSE)
 | ||
|  | //   }
 | ||
|  | 
 | ||
|  | #define ValidateReadPtr(p,cb) 0
 | ||
|  | #define ValidateWritePtr(p,cb) 0
 | ||
|  | #define ValidateReadWritePtr(p,cb) 0
 | ||
|  | #define ValidateStringPtr(p) 0
 | ||
|  | #define ValidateStringPtrA(p) 0
 | ||
|  | #define ValidateStringPtrW(p) 0
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #ifdef _OBJBASE_H_
 | ||
|  | 
 | ||
|  |     //  Outputting GUID names.  If you want to include the name
 | ||
|  |     //  associated with a GUID (eg CLSID_...) then
 | ||
|  |     //
 | ||
|  |     //      GuidNames[yourGUID]
 | ||
|  |     //
 | ||
|  |     //  Returns the name defined in uuids.h as a string
 | ||
|  | 
 | ||
|  |     typedef struct { | ||
|  |         const CHAR   *szName; | ||
|  |         GUID    guid; | ||
|  |     } GUID_STRING_ENTRY; | ||
|  | 
 | ||
|  |     class CGuidNameList { | ||
|  |     public: | ||
|  |         const CHAR *operator [] (const GUID& guid); | ||
|  |     }; | ||
|  | 
 | ||
|  |     extern CGuidNameList GuidNames; | ||
|  | 
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifndef REMIND
 | ||
|  |     //  REMIND macro - generates warning as reminder to complete coding
 | ||
|  |     //  (eg) usage:
 | ||
|  |     //
 | ||
|  |     //  #pragma message (REMIND("Add automation support"))
 | ||
|  | 
 | ||
|  | 
 | ||
|  |     #define QUOTE(x) #x
 | ||
|  |     #define QQUOTE(y) QUOTE(y)
 | ||
|  |     #define REMIND(str) __FILE__ "(" QQUOTE(__LINE__) ") :  " str
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | //  Method to display objects in a useful format
 | ||
|  | //
 | ||
|  | //  eg If you want to display a LONGLONG ll in a debug string do (eg)
 | ||
|  | //
 | ||
|  | //  DbgLog((LOG_TRACE, n, TEXT("Value is %s"), (LPCTSTR)CDisp(ll, CDISP_HEX)));
 | ||
|  | 
 | ||
|  | 
 | ||
|  | class CDispBasic | ||
|  | { | ||
|  | public: | ||
|  |     CDispBasic() { m_pString = m_String; }; | ||
|  |     ~CDispBasic(); | ||
|  | protected: | ||
|  |     PTCHAR m_pString;  // normally points to m_String... unless too much data
 | ||
|  |     TCHAR m_String[50]; | ||
|  | }; | ||
|  | class CDisp : public CDispBasic | ||
|  | { | ||
|  | public: | ||
|  |     CDisp(LONGLONG ll, int Format = CDISP_HEX); // Display a LONGLONG in CDISP_HEX or CDISP_DEC form
 | ||
|  |     CDisp(REFCLSID clsid);      // Display a GUID
 | ||
|  |     CDisp(double d);            // Display a floating point number
 | ||
|  | #ifdef __strmif_h__
 | ||
|  | #ifdef __STREAMS__
 | ||
|  |     CDisp(CRefTime t);          // Display a Reference Time
 | ||
|  | #endif
 | ||
|  |     CDisp(IPin *pPin);          // Display a pin as {filter clsid}(pin name)
 | ||
|  |     CDisp(IUnknown *pUnk);      // Display a filter or pin
 | ||
|  | #endif // __strmif_h__
 | ||
|  |     ~CDisp(); | ||
|  | 
 | ||
|  |     //  Implement cast to (LPCTSTR) as parameter to logger
 | ||
|  |     operator LPCTSTR() | ||
|  |     { | ||
|  |         return (LPCTSTR)m_pString; | ||
|  |     }; | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | #if defined(DEBUG)
 | ||
|  | class CAutoTrace | ||
|  | { | ||
|  | private: | ||
|  |     LPCTSTR  _szBlkName; | ||
|  |     const int _level; | ||
|  |     static const TCHAR _szEntering[]; | ||
|  |     static const TCHAR _szLeaving[]; | ||
|  | public: | ||
|  |     CAutoTrace(LPCTSTR szBlkName, const int level = 15) | ||
|  |         : _szBlkName(szBlkName), _level(level) | ||
|  |     {DbgLog((LOG_TRACE, _level, _szEntering, _szBlkName));} | ||
|  | 
 | ||
|  |     ~CAutoTrace() | ||
|  |     {DbgLog((LOG_TRACE, _level, _szLeaving, _szBlkName));} | ||
|  | }; | ||
|  | 
 | ||
|  | #if defined (__FUNCTION__)
 | ||
|  | 
 | ||
|  | #define AMTRACEFN()  CAutoTrace __trace(TEXT(__FUNCTION__))
 | ||
|  | #define AMTRACE(_x_) CAutoTrace __trace(TEXT(__FUNCTION__))
 | ||
|  | 
 | ||
|  | #else
 | ||
|  | 
 | ||
|  | #define AMTRACE(_x_) CAutoTrace __trace _x_
 | ||
|  | #define AMTRACEFN()
 | ||
|  | 
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #else
 | ||
|  | 
 | ||
|  | #define AMTRACE(_x_)
 | ||
|  | #define AMTRACEFN()
 | ||
|  | 
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #endif // __WXDEBUG__
 | ||
|  | 
 | ||
|  | 
 |