WXDEBUG.H
//==========================================================================; 
// 
//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR 
//  PURPOSE. 
// 
//  Copyright (c) 1992 - 1997  Microsoft Corporation.  All Rights Reserved. 
// 
//--------------------------------------------------------------------------; 
 
// Debugging facilities, January 1995 
 
#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 
 
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 { 
    const TCHAR *m_pName; 
    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); 
    void WINAPI DbgInitGlobalSettings(); 
    void WINAPI DbgInitModuleSettings(); 
    void WINAPI DbgInitModuleName(); 
    DWORD WINAPI DbgRegisterObjectCreation(const TCHAR *pObjectName); 
    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); 
 
    // 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(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine); 
    void WINAPI DbgBreakPoint(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine); 
    void WINAPI DbgKernelAssert(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine); 
    void WINAPI DbgLogInfo(DWORD Type,DWORD Level,const TCHAR *pFormat,...); 
    void WINAPI DbgOutString(LPCTSTR psz); 
 
    //  Debug infinite wait stuff 
    DWORD WINAPI DbgWaitForSingleObject(HANDLE h); 
    DWORD WINAPI DbgWaitForMultipleObjects(DWORD 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(LPSTR 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 
 
    //  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_) NULL 
 
    #define DbgInitialise(hInst) 
    #define DbgTerminate() 
    #define DbgLog(_x_) 
    #define DbgOutString(psz) 
 
    #define DbgRegisterObjectCreation(pObjectName) 
    #define DbgRegisterObjectDestruction(dwCookie) 
    #define DbgDumpObjectRegister() 
 
    #define DbgCheckModuleLevel(Type,Level) 
    #define DbgSetModuleLevel(Type,Level) 
 
    #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_) 
    #ifndef ASSERT 
#define ASSERT(_x_) 
    #endif 
    #define EXECUTE_ASSERT(_x_) _x_ 
 
    // MFC style trace macros 
 
    #define NOTE(_x_) 
    #define NOTE1(_x_,a) 
    #define NOTE2(_x_,a,b) 
    #define NOTE3(_x_,a,b,c) 
    #define NOTE4(_x_,a,b,c,d) 
    #define NOTE5(_x_,a,b,c,d,e) 
 
    #define DisplayType(label, pmtIn) 
    #define DumpGraph(pGraph, label) 
#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) 
//   } 
 
// These validate pointers when symbol VFWROBUST is defined 
// This will normally be defined in debug not retail builds 
 
#ifdef DEBUG 
    #define VFWROBUST 
#endif 
 
#ifdef VFWROBUST 
 
    #define ValidateReadPtr(p,cb) \ 
        {if(IsBadReadPtr((PVOID)p,cb) == TRUE) \ 
            DbgBreak("Invalid read pointer");} 
 
    #define ValidateWritePtr(p,cb) \ 
        {if(IsBadWritePtr((PVOID)p,cb) == TRUE) \ 
            DbgBreak("Invalid write pointer");} 
 
    #define ValidateReadWritePtr(p,cb) \ 
        {ValidateReadPtr(p,cb) ValidateWritePtr(p,cb)} 
 
    #define ValidateStringPtr(p) \ 
        {if(IsBadStringPtr((LPCTSTR)p,INFINITE) == TRUE) \ 
            DbgBreak("Invalid string pointer");} 
 
    #define ValidateStringPtrA(p) \ 
        {if(IsBadStringPtrA((LPCSTR)p,INFINITE) == TRUE) \ 
            DbgBreak("Invalid ANSII string pointer");} 
 
    #define ValidateStringPtrW(p) \ 
        {if(IsBadStringPtrW((LPCWSTR)p,INFINITE) == TRUE) \ 
            DbgBreak("Invalid UNICODE string pointer");} 
 
#else 
    #define ValidateReadPtr(p,cb) 
    #define ValidateWritePtr(p,cb) 
    #define ValidateReadWritePtr(p,cb) 
    #define ValidateStringPtr(p) 
    #define ValidateStringPtrA(p) 
    #define ValidateStringPtrW(p) 
#endif 
 
 
#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 { 
        TCHAR   *szName; 
        GUID    guid; 
    } GUID_STRING_ENTRY; 
 
    class CGuidNameList { 
    public: 
        TCHAR *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 
 
//  Hack 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) 
#endif // __strmif_h__ 
    ~CDisp(); 
 
    //  Implement cast to (LPCTSTR) as parameter to logger 
    operator LPCTSTR() 
    { 
        return (LPCTSTR)m_pString; 
    }; 
}; 
 
#endif // __WXDEBUG__