//////////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 1999-2001 Microsoft Corporation
//
//  Module Name:
//      Debug.h
//
//  Description:
//      Debugging utilities header.
//
//  Maintained By:
//      Galen Barbee (GalenB) 22-NOV-1999
//
//////////////////////////////////////////////////////////////////////////////

#pragma once

//
// KB: USES_SYSALLOCSTRING gpease 8-NOV-1999
//      Turn this on if you are going to use the OLE automation
//      functions: SysAllocString, SysFreeString, etc..
//
// #define USES_SYSALLOCSTRING

//
// Trace Flags
//
typedef enum _TRACEFLAGS
{
    mtfALWAYS           = 0xFFFFFFFF,
    mtfNEVER            = 0x00000000,
    // function entry/exits, call, scoping
    mtfASSERT_HR        = 0x00000001,   // Halt if HRESULT is an error
    mtfQUERYINTERFACE   = 0x00000002,   // Query Interface details and halt on error
    // Asserts
    mtfSHOWASSERTS      = 0x00000004,   // Show assert message box
    //                  = 0x00000008,
    // other
    mtfCALLS            = 0x00000010,   // Function calls that use the TraceMsgDo macro
    mtfFUNC             = 0x00000020,   // Functions entrances w/parameters
    mtfSTACKSCOPE       = 0x00000040,   // if set, debug spew will generate bar/space for level each of the call stack
    mtfPERTHREADTRACE   = 0x00000080,   // Enables per thread tracing, excludes memory tracking.
    // specific
    mtfDLL              = 0x00000100,   // DLL specific
    mtfWM               = 0x00000200,   // Window Messages
    mtfFLOW             = 0x00000400,   // Control flow
    //                  = 0x00000800
    // citracker spew
    mtfCITRACKERS       = 0x00001000,   // CITrackers will spew entrances and exits
    //                  = 0x00002000,
    //                  = 0x00004000,
    //                  = 0x00008000,
    //                  = 0x00010000,
    //                  = 0x00020000,
    //                  = 0x00040000,
    //                  = 0x00080000,
    //                  = 0x00100000,
    //                  = 0x00200000,
    //                  = 0x00400000,
    //                  = 0x00800000,
    // memory
    mtfMEMORYLEAKS      = 0x01000000,   // Halts when a memory leak is detected on thread exit
    mtfMEMORYINIT       = 0x02000000,   // Initializes new memory allocations to non-zero value
    mtfMEMORYALLOCS     = 0x04000000,   // Turns on spew to display each de/allocation.
    //                  = 0x08000000,
    // output prefixes
    mtfADDTIMEDATE      = 0x10000000,   // Replaces Filepath(Line) with Date/Time
    mtfBYMODULENAME     = 0x20000000,   // Puts the module name at the beginning of the line
    //                  = 0x40000000,
    mtfOUTPUTTODISK     = 0x80000000,   // Writes output to disk
} TRACEFLAGS;

typedef DWORD TRACEFLAG;

#define ASZ_NEWLINE         "\r\n"
#define SZ_NEWLINE          TEXT( ASZ_NEWLINE )
#define SIZEOF_ASZ_NEWLINE  ( sizeof( ASZ_NEWLINE ) - sizeof( CHAR ) )
#define SIZEOF_SZ_NEWLINE   ( sizeof( SZ_NEWLINE ) - sizeof( TCHAR ) )
#define FREE_ADDRESS        0xFA
#define FREE_BLOCK          0xFB
#define AVAILABLE_ADDRESS   0xAA

#ifdef DEBUG

#pragma message( "BUILD: DEBUG macros being built" )

//
// Globals
//
extern DWORD         g_TraceMemoryIndex;    // TLS index for the memory tracking link list
extern DWORD         g_dwCounter;           // Stack depth counter
extern TRACEFLAG     g_tfModule;            // Global tracing flags
extern const LPCTSTR g_pszModuleIn;         // Local module name - use DEFINE_MODULE
extern const TCHAR   g_szTrue[];            // Array "TRUE"
extern const TCHAR   g_szFalse[];           // Array "FALSE"

//
// Definition Macros
//
#define DEFINE_MODULE( _module )    const LPCTSTR g_pszModuleIn = TEXT(_module);
#define __MODULE__                  g_pszModuleIn
#define DEFINE_THISCLASS( _class )  static const TCHAR g_szClass[] = TEXT(_class);
#define __THISCLASS__               g_szClass

//
// ImageHlp Stuff - not ready for prime time yet.
//
#if defined( IMAGEHLP_ENABLED )
#include <imagehlp.h>
typedef BOOL ( * PFNSYMGETSYMFROMADDR )( HANDLE, DWORD, PDWORD, PIMAGEHLP_SYMBOL );
typedef BOOL ( * PFNSYMGETLINEFROMADDR )( HANDLE, DWORD, PDWORD, PIMAGEHLP_LINE );
typedef BOOL ( * PFNSYMGETMODULEINFO )( HANDLE, DWORD, PIMAGEHLP_MODULE );

extern HINSTANCE                g_hImageHlp;                // IMAGEHLP.DLL instance handle
extern PFNSYMGETSYMFROMADDR     g_pfnSymGetSymFromAddr;
extern PFNSYMGETLINEFROMADDR    g_pfnSymGetLineFromAddr;
extern PFNSYMGETMODULEINFO      g_pfnSymGetModuleInfo;
#endif // IMAGEHLP_ENABLED

void
DebugIncrementStackDepthCounter( void );

void
DebugDecrementStackDepthCounter( void );

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TraceInitializeProcess(
//      _rgControl
//      _sizeofControl
//      _fGlobalMemoryTackingIn
//      )
//
//  Description:
//      Should be called in the DLL main on process attach or in the entry
//      routine of an EXE. Initializes debugging globals and TLS. Registers
//      the WMI tracing facilities (if WMI support is enabled).
//
//  Arguments:
//      _rgControl      WMI control block (see DEBUG_WMI_CONTROL_GUIDS)
//      _sizeofControl  The sizeof( _rgControl )
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
#if defined( DEBUG_SW_TRACING_ENABLED )
#define TraceInitializeProcess( _rgControl, _sizeofControl, _fGlobalMemoryTackingIn ) \
    do \
    { \
        DebugInitializeTraceFlags( _fGlobalMemoryTackingIn ); \
        WMIInitializeTracing( _rgControl, _sizeofControl ); \
    } while ( 0 )
#else // ! DEBUG_SW_TRACING_ENABLED
#define TraceInitializeProcess( _fGlobalMemoryTackingIn ) \
    do \
    { \
        DebugInitializeTraceFlags( _fGlobalMemoryTackingIn ); \
} while ( 0 )
#endif // DEBUG_SW_TRACING_ENABLED

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TraceInitializeThread(
//      _name
//      )
//
//  Description:
//      Should be called in the DLL thread attach or when a new thread is
//      created. Sets up the memory tracing for that thread as well as
//      establishing the tfThread for each thread (if mtfPERTHREADTRACE
//      is set in g_tfModule).
//
//  Arguments:
//      _name       NULL or the name of the thread.
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define TraceInitializeThread( _name ) \
    do \
    { \
        TlsSetValue( g_TraceMemoryIndex, NULL ); \
        DebugInitializeThreadTraceFlags( _name ); \
    } while ( 0 )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TraceThreadRundown( void )
//
//  Description:
//      Should be called before a thread terminates. It will check to make
//      sure all memory allocated by the thread was released properly. It
//      will also cleanup any per thread structures.
//
//  Arguments:
//      None.
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define TraceThreadRundown() \
    do \
    { \
        DebugMemoryCheck( NULL, NULL ); \
        DebugThreadRundownTraceFlags(); \
    } while ( 0 )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TraceCreateMemoryList(
//      _pmbIn
//      )
//
//  Description:
//      Creates a thread-independent list to track objects.
//
//      _pmbIn should be an LPVOID.
//
//  Arguments:
//      _pmbIn - Pointer to store the head of the list.
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define TraceCreateMemoryList( _pmbIn ) \
    DebugCreateMemoryList( TEXT(__FILE__), __LINE__, __MODULE__, &_pmbIn, TEXT(#_pmbIn) );

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TraceTerminateMemoryList(
//      _pmbIn
//      )
//
//  Description:
//      Checks to make sure the list is empty before destroying the list.
//
//      _pmbIn should be an LPVOID.
//
//  Arguments:
//      _pmbIn - Pointer to store the head of the list.
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
// BUGBUG:  DavidP 09-DEC-1999
//          _pmbIn is evaluated multiple times but the name of the
//          macro is mixed case.
#define TraceTerminateMemoryList( _pmbIn ) \
    do \
    { \
        DebugMemoryCheck( _pmbIn, TEXT(#_pmbIn) ); \
        HeapFree( GetProcessHeap(), 0, _pmbIn ); \
    } while ( 0 )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TraceMoveToMemoryList(
//      _addr
//      _pmbIn
//      )
//
//  Description:
//      Moves an object from the thread tracking list to a thread independent
//      memory list (_pmbIn).
//
//      _pmbIn should be castable to an LPVOID.
//
//  Arguments:
//      _addr  - Address of object to move.
//      _pmbIn - Pointer to store the head of the list.
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
//#define TraceMoveToMemoryList( _addr, _pmbIn ) \
//    DebugMoveToMemoryList( TEXT(__FILE__), __LINE__, __MODULE__, _addr, _pmbIn, TEXT(#_pmbIn) );
#define TraceMoveToMemoryList( _addr, _pmbIn )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TraceMoveFromMemoryList(
//      _addr
//      _pmbIn
//      )
//
//  Description:
//      Moves an object from a thread independent memory list (_pmbIn) to the
//      per thread tracking list.
//
//      _pmbIn should be castable to an LPVOID.
//
//  Arguments:
//      _addr  - Address of object to move.
//      _pmbIn - Pointer to store the head of the list.
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
//#define TraceMoveFromMemoryList( _addr, _pmbIn ) \
//    DebugMoveFromMemoryList( TEXT(__FILE__), __LINE__, __MODULE__, _addr, _pmbIn, TEXT(#_pmbIn) );
#define TraceMoveFromMemoryList( _addr, _pmbIn )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TraceMemoryListDelete(
//      _addr
//      _pmbIn
//      )
//
//  Description:
//      Moves and object from the thread tracking list to a thread independent
//      memory list (_pmbIn).
//
//      _pmbIn should be an LPVOID.
//
//  Arguments:
//      _addr  - Address of object to delete.
//      _pmbIn - Pointer to store the head of the list.
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
//#define TraceMemoryListDelete( _addr, _pmbIn, _fClobberIn ) \
//    DebugMemoryListDelete( TEXT(__FILE__), __LINE__, __MODULE__, _addr, _pmbIn, TEXT(#_pmbIn), _fClobberIn );

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TraceTerminateProcess
//
//  Description:
//      Should be called before a process terminates. It cleans up anything
//      that the Debug APIs created. It will check to make sure all memory
//      allocated by the main thread was released properly. It will also
//      terminate WMI tracing (if WMI support is enabled). It also closes
//      the logging handle.
//
//  Arguments:
//      _rgControl     - WMI control block (see DEBUG_WMI_CONTROL_GUIDS)
//      _sizeofControl - the sizeof( _rgControl )
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
#if defined( DEBUG_SW_TRACING_ENABLED )
#define TraceTerminateProcess( _rgControl, _sizeofControl ) \
    do \
    { \
        LogTerminateProcess(); \
        WMITerminateTracing( _rgControl, _sizeofControl ); \
        DebugMemoryCheck( NULL, NULL ); \
        DebugTerminateProcess(); \
    } while ( 0 )
#else // ! DEBUG_SW_TRACING_ENABLED
//
//  TODO:   11 DEC 2000 GalenB
//
//  LogTerminateProcess() needs to be available for retail builds.
//  Since it doesn't yet do anything this isn't a problem, but that
//  of course can change...
//
#define TraceTerminateProcess() \
    do \
    { \
        LogTerminateProcess(); \
        DebugMemoryCheck( NULL, NULL ); \
        DebugTerminateProcess(); \
    } while ( 0 )
#endif // DEBUG_SW_TRACING_ENABLED

//****************************************************************************
//
// Debug initialization routines
//
// Uses should use the TraceInitializeXXX and TraceTerminateXXX macros, not
// these routines.
//
//****************************************************************************
void
DebugInitializeTraceFlags( BOOL fGlobalMemoryTackingIn = TRUE );

void
DebugInitializeThreadTraceFlags(
    LPCTSTR pszThreadNameIn
    );

void
DebugTerminateProcess( void );

void
DebugThreadRundownTraceFlags( void );

void
DebugCreateMemoryList(
    LPCTSTR     pszFileIn,
    const int   nLineIn,
    LPCTSTR     pszModuleIn,
    LPVOID *    ppvListOut,
    LPCTSTR     pszListNameIn
    );

void
DebugMemoryListDelete(
    LPCTSTR pszFileIn,
    const int nLineIn,
    LPCTSTR pszModuleIn,
    void *  pvMemIn,
    LPVOID  pvListIn,
    LPCTSTR pszListNameIn,
    BOOL    fClobberIn
    );

void
DebugMoveToMemoryList(
    LPCTSTR     pszFileIn,
    const int   nLineIn,
    LPCTSTR     pszModuleIn,
    void *      pvMemIn,
    LPVOID      pmbListIn,
    LPCTSTR     pszListNameIn
    );

void
DebugMoveFromMemoryList(
    LPCTSTR     pszFileIn,
    const int   nLineIn,
    LPCTSTR     pszModuleIn,
    HGLOBAL     hGlobal,
    LPVOID      pmbListIn,
    LPCTSTR     pszListNameIn
    );

//****************************************************************************
//
// Memmory Allocation Subsitution Macros
//
// Replaces LocalAlloc/LocalFree, GlobalAlloc/GlobalFree, and malloc/free
//
//****************************************************************************
#define TraceAlloc( _flags, _size )             DebugAlloc( TEXT(__FILE__), __LINE__, __MODULE__, _flags, _size, TEXT(#_size) )
#define TraceReAlloc( _pvmem, _size, _flags )   DebugReAlloc( TEXT(__FILE__), __LINE__, __MODULE__, _pvmem, _flags, _size, TEXT(#_size) )
#define TraceFree( _hmem )                      DebugFree( _hmem, TEXT(__FILE__), __LINE__, __MODULE__ )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TraceAllocString(
//      _flags,
//      _size
//      )
//
//  Description:
//      Quick way to allocation a string that is the proper size and that will
//      be tracked by memory tracking.
//
//  Arguments:
//      _flags  - Allocation attributes.
//      _size   - Number of characters in the string to be allocated.
//
//  Return Values:
//      Handle/pointer to memory to be used as a string.
//
//////////////////////////////////////////////////////////////////////////////
#define TraceAllocString( _flags, _size ) \
    (LPTSTR) DebugAlloc( TEXT(__FILE__), \
                         __LINE__, \
                         __MODULE__, \
                         _flags, \
                         (_size) * sizeof( TCHAR ), \
                         TEXT(#_size) \
                         )

//****************************************************************************
//
// Code Tracing Macros
//
//****************************************************************************

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TraceFunc(
//      _szArgs
//      )
//
//  Description:
//      Displays file, line number, module and "_szArgs" only if the mtfFUNC is
//      set in g_tfModule. "_szArgs" is the name of the function just
//      entered. It also increments the stack counter.
//
//  Arguments:
//      _szArgs     - Arguments for the function just entered.
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define TraceFunc( _szArgs ) \
    HRESULT __MissingTraceFunc; \
    if ( g_tfModule != 0 ) \
    { \
        DebugIncrementStackDepthCounter(); \
        TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFUNC, TEXT("+ ") TEXT(__FUNCTION__) TEXT("( ") TEXT(_szArgs) TEXT(" )")  ); \
    }

//
// These next macros are just like TraceFunc except they take additional
// arguments to display the values passed into the function call. "_szArgs"
// should contain a printf string on how to display the arguments.
//
#define TraceFunc1( _szArgs, _arg1 ) \
    HRESULT __MissingTraceFunc; \
    if ( g_tfModule != 0 ) \
    { \
        DebugIncrementStackDepthCounter(); \
        TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFUNC, TEXT("+ ") TEXT(__FUNCTION__) TEXT("( ") TEXT(_szArgs) TEXT(" )"), _arg1 ); \
    }

#define TraceFunc2( _szArgs, _arg1, _arg2 ) \
    HRESULT __MissingTraceFunc; \
    if ( g_tfModule != 0 ) \
    { \
        DebugIncrementStackDepthCounter(); \
        TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFUNC, TEXT("+ ") TEXT(__FUNCTION__) TEXT("( ") TEXT(_szArgs) TEXT(" )"), _arg1, _arg2 ); \
    }

#define TraceFunc3( _szArgs, _arg1, _arg2, _arg3 ) \
    HRESULT __MissingTraceFunc; \
    if ( g_tfModule != 0 ) \
    { \
        DebugIncrementStackDepthCounter(); \
        TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFUNC, TEXT("+ ") TEXT(__FUNCTION__) TEXT("( ") TEXT(_szArgs) TEXT(" )"), _arg1, _arg2, _arg3 ); \
    }

#define TraceFunc4( _szArgs, _arg1, _arg2, _arg3, _arg4 ) \
    HRESULT __MissingTraceFunc; \
    if ( g_tfModule != 0 ) \
    { \
        DebugIncrementStackDepthCounter(); \
        TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFUNC, TEXT("+ ") TEXT(__FUNCTION__) TEXT("( ") TEXT(_szArgs) TEXT(" )"), _arg1, _arg2, _arg3, _arg4 ); \
    }

#define TraceFunc5( _szArgs, _arg1, _arg2, _arg3, _arg4, _arg5 ) \
    HRESULT __MissingTraceFunc; \
    if ( g_tfModule != 0 ) \
    { \
        DebugIncrementStackDepthCounter(); \
        TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFUNC, TEXT("+ ") TEXT(__FUNCTION__) TEXT("( ") TEXT(_szArgs) TEXT(" )"), _arg1, _arg2, _arg3, _arg4, arg5 ); \
    }

#define TraceFunc6( _szArgs, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6 ) \
    HRESULT __MissingTraceFunc; \
    if ( g_tfModule != 0 ) \
    { \
        DebugIncrementStackDepthCounter(); \
        TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFUNC, TEXT("+ ") TEXT(__FUNCTION__) TEXT("( ") TEXT(_szArgs) TEXT(" )"), _arg1, _arg2, _arg3, _arg4, arg5, arg6 ); \
    }


//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TraceQIFunc(
//      _szArgs,
//      riid,
//      ppv
//      )
//
//  Description:
//      Just like TraceFunc but customized for QueryInterface.  Specifically,
//      displays the name of the interface and the value of the return pointer.
//
//  Arguments:
//      _riid       - Interface ID.
//      _ppv        - Return pointer.
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define TraceQIFunc( _riid, _ppv ) \
    HRESULT __MissingTraceFunc; \
    if ( g_tfModule != 0 ) \
    { \
        TCHAR szGuid[ cchGUID_STRING_SIZE ]; \
        DebugIncrementStackDepthCounter(); \
        TraceMessage( TEXT(__FILE__), \
                      __LINE__, \
                      __MODULE__, \
                      mtfFUNC, \
                      TEXT("+ ") TEXT(__FUNCTION__) TEXT("( [IUnknown] %s, ppv = %#x )"), \
                      PszTraceFindInterface( _riid, szGuid ), \
                      _ppv \
                      ); \
    }


//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TraceFlow(
//      _pszFormat
//      )
//
//  Description:
//      This macro outputs a string that is indented to the current depth.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define TraceFlow( _pszFormat ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFLOW, TEXT("| ") TEXT(_pszFormat) ); \
        } \
    } while ( 0 )

//
// These next macros are just like TraceFunc except they take additional
// arguments to display the values passed into the function call. "_pszFormat"
// should contain a printf string on how to display the arguments.
//

#define TraceFlow1( _pszFormat, _arg1 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFLOW, TEXT("| ") TEXT(_pszFormat), _arg1 ); \
        } \
    } while ( 0 )

#define TraceFlow2( _pszFormat, _arg1, _arg2 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFLOW, TEXT("| ") TEXT(_pszFormat), _arg1, _arg2 ); \
        } \
    } while ( 0 )
#define TraceFlow3( _pszFormat, _arg1, _arg2, _arg3 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFLOW, TEXT("| ") TEXT(_pszFormat), _arg1, _arg2, _arg3 ); \
        } \
    } while ( 0 )
#define TraceFlow4( _pszFormat, _arg1, _arg2, _arg3, _arg4 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFLOW, TEXT("| ") TEXT(_pszFormat), _arg1, _arg2, _arg3, _arg4 ); \
        } \
    } while ( 0 )
#define TraceFlow5( _pszFormat, _arg1, _arg2, _arg3, _arg4, _arg5 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFLOW, TEXT("| ") TEXT(_pszFormat), _arg1, _arg2, _arg3, _arg4, _arg5 ); \
        } \
    } while ( 0 )

#define TraceFlow6( _pszFormat, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFLOW, TEXT("| ") TEXT(_pszFormat), _arg1, _arg2, _arg3, _arg4, _arg5, _arg6 ); \
        } \
    } while ( 0 )


//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TraceFuncExit( void )
//
//  Description:
//      Return macro for TraceFunc() if the return type is void.  It also
//      decrements the stack counter.
//
//  Arguments:
//      None.
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define TraceFuncExit() \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            __MissingTraceFunc = 0; \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFUNC, TEXT("V") ); \
            DebugDecrementStackDepthCounter(); \
        } \
        return; \
    } while ( 0 )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  RETURN(
//      _rval
//      )
//
//  Description:
//      Return macro for TraceFunc(). The _rval will be returned as the
//      result of the function. It also decrements the stack counter.
//
//  Arguments:
//      _rval   - Result of the function.
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define RETURN( _rval ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            __MissingTraceFunc = 0; \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFUNC, TEXT("V") ); \
            DebugDecrementStackDepthCounter(); \
        } \
        return _rval; \
    } while ( 0 )


/*
    return ( ( g_tfModule != 0 ) \
                ? ( TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFUNC, TEXT("V") ) \
                    , DebugDecrementStackDepthCounter() \
                    , _rval ) \
                : _rval )
*/

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  FRETURN(
//      _rval
//      )
//
//  Description:
//      This is a fake version of the return macro for TraceFunc().
//      *** This doesn't return. *** It also decrements the stack counter.
//
//  Arguments:
//      _rval   - Result of the function.
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define FRETURN( _rval ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            __MissingTraceFunc = 0; \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFUNC, TEXT("V") ); \
            DebugDecrementStackDepthCounter(); \
        } \
    } while ( 0 )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  HRETURN(
//      _hr
//      )
//
//  Description:
//      Return macro for TraceFunc(). The _hr will be returned as the result
//      of the function. If the value is not S_OK, it will be displayed in
//      the debugger. It also decrements the stack counter.
//
//  Arguments:
//      _hr - Result of the function.
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define HRETURN( _hr ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            __MissingTraceFunc = 0; \
            if ( _hr != S_OK ) \
            { \
                DebugReturnMessage( TEXT(__FILE__), __LINE__, __MODULE__, TEXT( "V hr = 0x%08x (%s)"), _hr ); \
            } \
            else \
            { \
                TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFUNC, TEXT("V") ); \
            } \
            DebugDecrementStackDepthCounter(); \
        } \
        return _hr; \
    } while ( 0 )

//
// These next macros are just like HRETURN except they allow other
// exceptable values to be passed.back without causing extra spew.
//
#define HRETURN1( _hr, _arg1 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            __MissingTraceFunc = 0; \
            if ( ( _hr != S_OK ) && ( _hr != _arg1 ) ) \
            { \
                DebugReturnMessage( TEXT(__FILE__), __LINE__, __MODULE__, TEXT( "V hr = 0x%08x (%s)"), _hr ); \
            } \
            else \
            { \
                TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFUNC, TEXT("V") ); \
            } \
            DebugDecrementStackDepthCounter(); \
        } \
        return _hr; \
    } while ( 0 )

#define HRETURN2( _hr, _arg1, _arg2 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            __MissingTraceFunc = 0; \
            if ( ( _hr != S_OK ) && ( _hr != _arg1 ) && ( _hr != _arg2 ) ) \
            { \
                DebugReturnMessage( TEXT(__FILE__), __LINE__, __MODULE__, TEXT( "V hr = 0x%08x (%s)"), _hr ); \
            } \
            else \
            { \
                TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFUNC, TEXT("V") ); \
            } \
            DebugDecrementStackDepthCounter(); \
        } \
        return _hr; \
    } while ( 0 )

#define HRETURN3( _hr, _arg1, _arg2, _arg3 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            __MissingTraceFunc = 0; \
            if ( ( _hr != S_OK ) && ( _hr != _arg1 ) && ( _hr != _arg2 ) && ( _hr != _arg3 ) ) \
            { \
                DebugReturnMessage( TEXT(__FILE__), __LINE__, __MODULE__, TEXT( "V hr = 0x%08x (%s)"), _hr ); \
            } \
            else \
            { \
                TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFUNC, TEXT("V") ); \
            } \
            DebugDecrementStackDepthCounter(); \
        } \
        return _hr; \
    } while ( 0 )


//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TraceDo(
//      _szExp
//      )
//
//  Description:
//      Displays the file, line number, module and function call and return
//      from the function call (no return value displayed) for "_szExp" only
//      if the mtfCALLS is set in g_tfModule. Note return value is not
//      displayed. _szExp will be in RETAIL version of the product.
//
//  Arguments:
//      _szExp
//          The expression to be traced including assigment to the return
//          variable.
//
//  Return Values:
//      None. The return value should be defined within _szExp.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define TraceDo( _szExp ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            DebugIncrementStackDepthCounter(); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("+ ") TEXT(#_szExp ) ); \
            _szExp; \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("V") ); \
            DebugDecrementStackDepthCounter(); \
        } \
        else \
        { \
            _szExp; \
        } \
    } while ( 0 )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TraceMsgDo(
//      _pszExp,
//      _pszReturnMsg
//      )
//
//  Description:
//      Displays the file, line number, module and function call and return
//      value which is formatted in "_pszReturnMsg" for "_pszExp" only if the
//      mtfCALLS is set in g_tfModule. _pszExp will be in the RETAIL version
//      of the product.
//
//  Arguments:
//      _pszExp
//          The expression to be traced including assigment to the return
//          variable.
//      _pszReturnMsg
//          A format string for displaying the return value.
//
//  Return Values:
//      None. The return value should be defined within _szExp.
//
//  Example:
//      TraceMsgDo( hr = HrDoSomething(), "0x%08.8x" );
//
//--
//////////////////////////////////////////////////////////////////////////////
#define TraceMsgDo( _pszExp, _pszReturnMsg ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            DebugIncrementStackDepthCounter(); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("+ ") TEXT(#_pszExp) ); \
            TraceMessageDo( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT(_pszReturnMsg), TEXT(#_pszExp), _pszExp ); \
            DebugDecrementStackDepthCounter(); \
        } \
        else \
        { \
            _pszExp; \
        } \
    } while ( 0 )

//
// These next macros are just like TraceMsgDo except they take additional
// arguments to display the values passed into the function call. "_pszReturnMsg"
// should contain a printf format string describing how to display the
// arguments.
//
#define TraceMsgDo1( _pszExp, _pszReturnMsg, _arg1 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            DebugIncrementStackDepthCounter(); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("+ ") TEXT(#_pszExp) ); \
            TraceMessageDo( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT(_pszReturnMsg), TEXT(#_pszExp), _pszExp, _arg1 ); \
            DebugDecrementStackDepthCounter(); \
        } \
        else \
        { \
            _pszExp; \
        } \
    } while ( 0 )

#define TraceMsgDo2( _pszExp, _pszReturnMsg, _arg1, _arg2 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            DebugIncrementStackDepthCounter(); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("+ ") TEXT(#_pszExp) ); \
            TraceMessageDo( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT(_pszReturnMsg), TEXT(#_pszExp), _pszExp, _arg1, _arg2 ); \
            DebugDecrementStackDepthCounter(); \
        } \
        else \
        { \
            _pszExp; \
        } \
    } while ( 0 )

#define TraceMsgDo3( _pszExp, _pszReturnMsg, _arg1, _arg2, _arg3 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            DebugIncrementStackDepthCounter(); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("+ ") TEXT(#_pszExp) ); \
            TraceMessageDo( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT(_pszReturnMsg), TEXT(#_pszExp), _pszExp, _arg1, _arg2, _arg3 ); \
            DebugDecrementStackDepthCounter(); \
        } \
        else \
        { \
            _pszExp; \
        } \
    } while ( 0 )

#define TraceMsgDo4( _pszExp, _pszReturnMsg, _arg1, _arg2, _arg3, _arg4 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            DebugIncrementStackDepthCounter(); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("+ ") TEXT(#_pszExp) ); \
            TraceMessageDo( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT(_pszReturnMsg), TEXT(#_pszExp), _pszExp, _arg1, _arg2, _arg3, _arg4 ); \
            DebugDecrementStackDepthCounter(); \
        } \
        else \
        { \
            _pszExp; \
        } \
    } while ( 0 )

#define TraceMsgDo5( _pszExp, _pszReturnMsg, _arg1, _arg2, _arg3, _arg4, _arg5 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            DebugIncrementStackDepthCounter(); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("+ ") TEXT(#_pszExp) ); \
            TraceMessageDo( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT(_pszReturnMsg), TEXT(#_pszExp), _pszExp, _arg1, _arg2, _arg3, _arg4, _arg5 ); \
            DebugDecrementStackDepthCounter(); \
        } \
        else \
        { \
            _pszExp; \
        } \
    } while ( 0 )

#define TraceMsgDo6( _pszExp, _pszReturnMsg, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            DebugIncrementStackDepthCounter(); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("+ ") TEXT(#_pszExp) ); \
            TraceMessageDo( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT(_pszReturnMsg), TEXT(#_pszExp), _pszExp, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6 ); \
            DebugDecrementStackDepthCounter(); \
        } \
        else \
        { \
            _pszExp; \
        } \
    } while ( 0 )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TraceMsgPreDo(
//      _pszExp,
//      _pszPreMsg
//      _pszReturnMsg,
//      )
//
//  Description:
//      Displays the file, line number, module and function call and return
//      value which is formatted in "_pszReturnMsg" for "_pszExp" only if the
//      mtfCALLS is set in g_tfModule. _pszExp will be in the RETAIL version
//      of the product.
//
//      Same as TraceMsgDo except it displays the formatted message before
//      executing the expression.  Arguments for TraceMsgPreDo1, etc. are
//      applied to both _pszPreMsg and _pszReturnMsg.  The first substitution
//      string in _pszReturnMsg is for the return value from the function.
//
//  Arguments:
//      _pszExp
//          The expression to be traced including assigment to the return
//          variable.
//      _pszPreMsg
//          A format string for displaying a message before the expression
//          is evaluated.
//      _pszReturnMsg
//          A format string for displaying the return value.
//
//  Return Values:
//      None. The return value should be defined within _szExp.
//
//  Example:
//      TraceMsgPreDo1( hr = HrDoSomething( bstrName ),
//                      "Name = '%ls'",
//                      "0x%08.8x, Name = '%ls'",
//                      bstrName
//                      );
//
//--
//////////////////////////////////////////////////////////////////////////////
#define TraceMsgPreDo( _pszExp, _pszPreMsg, _pszReturnMsg ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            DebugIncrementStackDepthCounter(); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("+ ") TEXT(#_pszExp) ); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("| ") TEXT(_pszPreMsg) ); \
            TraceMessageDo( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT(_pszReturnMsg), TEXT(#_pszExp), _pszExp ); \
            DebugDecrementStackDepthCounter(); \
        } \
        else \
        { \
            _pszExp; \
        } \
    } while ( 0 )

//
// These next macros are just like TraceMsgPreDo except they take additional
// arguments to display the values passed into the function call. "_pszPreMsg"
// should contain a printf format string describing how to display the
// arguments.
//
#define TraceMsgPreDo1( _pszExp, _pszPreMsg, _pszReturnMsg, _arg1 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            DebugIncrementStackDepthCounter(); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("+ ") TEXT(#_pszExp) ); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("| ") TEXT(_pszPreMsg), _arg1 ); \
            TraceMessageDo( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT(_pszReturnMsg), TEXT(#_pszExp), _pszExp, _arg1 ); \
            DebugDecrementStackDepthCounter(); \
        } \
        else \
        { \
            _pszExp; \
        } \
    } while ( 0 )

#define TraceMsgPreDo2( _pszExp, _pszPreMsg, _pszReturnMsg, _arg1, _arg2 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            DebugIncrementStackDepthCounter(); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("+ ") TEXT(#_pszExp) ); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("| ") TEXT(_pszPreMsg), _arg1, _arg2 ); \
            TraceMessageDo( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT(_pszReturnMsg), TEXT(#_pszExp), _pszExp, _arg1, _arg2 ); \
            DebugDecrementStackDepthCounter(); \
        } \
        else \
        { \
            _pszExp; \
        } \
    } while ( 0 )

#define TraceMsgPreDo3( _pszExp, _pszPreMsg, _pszReturnMsg, _arg1, _arg2, _arg3 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            DebugIncrementStackDepthCounter(); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("+ ") TEXT(#_pszExp) ); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("| ") TEXT(_pszPreMsg), _arg1, _arg2, _arg3 ); \
            TraceMessageDo( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT(_pszReturnMsg), TEXT(#_pszExp), _pszExp, _arg1, _arg2, _arg3 ); \
            DebugDecrementStackDepthCounter(); \
        } \
        else \
        { \
            _pszExp; \
        } \
    } while ( 0 )

#define TraceMsgPreDo4( _pszExp, _pszPreMsg, _pszReturnMsg, _arg1, _arg2, _arg3, _arg4 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            DebugIncrementStackDepthCounter(); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("+ ") TEXT(#_pszExp) ); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("| ") TEXT(_pszPreMsg), _arg1, _arg2, _arg3, _arg4 ); \
            TraceMessageDo( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT(_pszReturnMsg), TEXT(#_pszExp), _pszExp, _arg1, _arg2, _arg3, _arg4 ); \
            DebugDecrementStackDepthCounter(); \
        } \
        else \
        { \
            _pszExp; \
        } \
    } while ( 0 )

#define TraceMsgPreDo5( _pszExp, _pszPreMsg, _pszReturnMsg, _arg1, _arg2, _arg3, _arg4, _arg5 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            DebugIncrementStackDepthCounter(); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("+ ") TEXT(#_pszExp) ); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("| ") TEXT(_pszPreMsg), _arg1, _arg2, _arg3, _arg4, _arg5 ); \
            TraceMessageDo( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT(_pszReturnMsg), TEXT(#_pszExp), _pszExp, _arg1, _arg2, _arg3, _arg4, _arg5 ); \
            DebugDecrementStackDepthCounter(); \
        } \
        else \
        { \
            _pszExp; \
        } \
    } while ( 0 )

#define TraceMsgPreDo6( _pszExp, _pszPreMsg, _pszReturnMsg, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6 ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            DebugIncrementStackDepthCounter(); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("+ ") TEXT(#_pszExp) ); \
            TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT("| ") TEXT(_pszPreMsg), _arg1, _arg2, _arg3, _arg4, _arg5, _arg6 ); \
            TraceMessageDo( TEXT(__FILE__), __LINE__, __MODULE__, mtfCALLS, TEXT(_pszReturnMsg), TEXT(#_pszExp), _pszExp, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6 ); \
            DebugDecrementStackDepthCounter(); \
        } \
        else \
        { \
            _pszExp; \
        } \
    } while ( 0 )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TraceMsgGUID(
//      _flags,
//      _msg
//      _guid
//      )
//
//  Description:
//      Dumps a GUID to the debugger only if one of the flags in _flags is
//      set in g_tfModule.
//
//  Arguments:
//      _flags   - Flags to check
//      _msg     - msg to print before GUID
//      _guid    - GUID to dump
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
// BUGBUG:  DavidP 09-DEC-1999
//          _guid is evaluated multiple times but the name of the
//          macro is mixed case.
#define TraceMsgGUID( _flags, _msg, _guid ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            TraceMessage( TEXT(__FILE__), \
                          __LINE__, \
                          __MODULE__, \
                          _flags, \
                          TEXT("%s {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"), \
                          TEXT(_msg), \
                          _guid.Data1, _guid.Data2, _guid.Data3,  \
                          _guid.Data4[ 0 ], _guid.Data4[ 1 ], _guid.Data4[ 2 ], _guid.Data4[ 3 ], \
                          _guid.Data4[ 4 ], _guid.Data4[ 5 ], _guid.Data4[ 6 ], _guid.Data4[ 7 ] ); \
        } \
    } while ( 0 )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  ErrorMsg(
//      _szMsg,
//      _err
//      )
//
//  Description:
//      Print an error out. Can be used to write errors to a file. Note that
//      it will also print the source filename, line number and module name.
//
//  Arguments:
//      _szMsg  - Format string to be displayed.
//      _err    - Error code of the error.
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define ErrorMsg( _szMsg, _err ) \
    TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfALWAYS, TEXT(__FUNCTION__) TEXT(": ") TEXT(_szMsg), _err );

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  WndMsg(
//      _hwnd,
//      _umsg,
//      _wparam,
//      _lparam
//      )
//
//  Description:
//      Prints out a message to trace windows messages.
//
//  Arguments:
//      _hwnd   - The HWND
//      _umsg   - The uMsg
//      _wparam - The WPARAM
//      _lparam _ The LPARAM
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
// BUGBUG:  DavidP 09-DEC-1999
//          _wparam and _lparam are evaluated multiple times but the name
//          of the macro is mixed case.
#define WndMsg( _hwnd, _umsg, _wparam, _lparam ) \
    do \
    { \
        if ( g_tfModule & mtfWM ) \
        { \
            DebugMsg( TEXT("%s: WM   : hWnd = 0x%08x, uMsg = %u, wParam = 0x%08x (%u), lParam = 0x%08x (%u)"), __MODULE__, _hwnd, _umsg, _wparam, _wparam, _lparam, _lparam ); \
        } \
    } while ( 0 )

//****************************************************************************
//
//  Debug Macros
//
//  These calls are only compiled in DEBUG. They are a NOP in RETAIL
//  (not even compiled in).
//
//****************************************************************************

//
// Same as TraceDo() but only compiled in DEBUG.
//
#define DebugDo( _fn ) \
    do \
    { \
        DebugIncrementStackDepthCounter(); \
        DebugMessage( TEXT(__FILE__), __LINE__, __MODULE__, TEXT("+ ") TEXT(#_fn ) ); \
        _fn; \
        DebugMessage( TEXT(__FILE__), __LINE__, __MODULE__, TEXT("V") ); \
        DebugDecrementStackDepthCounter(); \
    } while ( 0 )


//
// Same as TraceMsgDo() but only compiled in DEBUG.
//
#define DebugMsgDo( _fn, _msg ) \
    do \
    { \
        DebugIncrementStackDepthCounter(); \
        DebugMessage( TEXT(__FILE__), __LINE__, __MODULE__, TEXT("+ ") TEXT(#_fn) ); \
        DebugMessageDo( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(_msg), TEXT(#_fn), _fn ); \
        DebugDecrementStackDepthCounter(); \
    } while ( 0 )

//****************************************************************************
//
//  HRESULT testing macros
//
//  These functions check HRESULT return values and display UI if conditions
//  warrant only in DEBUG.
//
//****************************************************************************

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  IsTraceFlagSet(
//      _flag
//      )
//
//  Description:
//      Checks to see of the flag is set in the global flags or in the per
//      thread flags. If you specify more than one flag and if any of them are
//      set, it will return TRUE.
//
//      In RETAIL this always return FALSE thereby effectively deleting the
//      block of the if statement. Example:
//
//          if ( IsTraceFlagSet( mtfPERTHREADTRACE ) )
//          {
//              //
//              // This code only exists in DEBUG.
//              .
//              .
//              .
//          }
//
//  Arguments:
//      _flags  - Flag to check for.
//
//  Return Values:
//      TRUE    - If DEBUG and flag set.
//      FLASE   - If RETAIL or flag not set.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define IsTraceFlagSet( _flag )    ( g_tfModule && IsDebugFlagSet( _flag ) )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  THR(
//      _hr
//      )
//
//  Description:
//      Warning is display if HRESULT is anything but S_OK (0). This can be
//      use in an expression. Example:
//
//      hr = THR( pSomething->DoSomething( arg ) );
//
//  Arguments:
//      _hr - Function expression to check.
//
//  Return Values:
//      Result of the "_hr" expression.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define THR( _hr ) \
    TraceHR( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(#_hr), _hr, FALSE, S_OK )

#define THRMSG( _hr, _msg ) \
    TraceHR( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(_msg), _hr, FALSE, S_OK )
#define THRMSG1( _hr, _msg, _arg1 ) \
    TraceHR( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(_msg), _hr, FALSE, S_OK, _arg1 )

#define THRE( _hr, _hrIgnore ) \
    TraceHR( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(#_hr), _hr, FALSE, _hrIgnore )

#define THREMSG( _hr, _hrIgnore, _msg ) \
    TraceHR( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(_msg), _hr, FALSE, _hrIgnore )
#define THREMSG1( _hr, _hrIgnore, _msg, _arg1 ) \
    TraceHR( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(_msg), _hr, FALSE, _hrIgnore, _arg1 )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  STHR(
//      _hr
//      )
//
//  Description:
//      Warning is display if FAILED( _hr ) is TRUE. This can be use in an
//      expression. Example:
//
//      hr = STHR( pSomething->DoSomething( arg ) );
//
//  Arguments:
//      _hr - Function expression to check.
//
//  Return Values:
//      Result of the "_hr" expression.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define STHR( _hr ) \
    TraceHR( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(#_hr), _hr, TRUE, S_OK )

#define STHRMSG( _hr, _msg ) \
    TraceHR( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(_msg), _hr, TRUE, S_OK )
#define STHRMSG1( _hr, _msg, _arg1 ) \
    TraceHR( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(_msg), _hr, TRUE, S_OK, _arg1 )

#define STHRE( _hr, _hrIgnore ) \
    TraceHR( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(#_hr), _hr, TRUE, _hrIgnore )

#define STHREMSG( _hr, _hrIgnore, _msg ) \
    TraceHR( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(_msg), _hr, TRUE, _hrIgnore )
#define STHREMSG1( _hr, _hrIgnore, _msg, _arg1 ) \
    TraceHR( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(_msg), _hr, TRUE, _hrIgnore, _arg1 )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  TW32(
//      _fn
//      )
//
//  Description:
//      Warning is display if result is anything but ERROR_SUCCESS (0). This
//      can be use in an expression. Example:
//
//      dwErr = TW32( RegOpenKey( HKLM, "foobar", &hkey ) );
//
//  Arguments:
//      _fn - Function expression to check.
//
//  Return Values:
//      Result of the "_fn" expression.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define TW32( _fn ) \
    TraceWin32( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(#_fn), _fn, ERROR_SUCCESS )

#define TW32MSG( _fn, _msg ) \
    TraceWin32( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(_msg), _fn, ERROR_SUCCESS )
#define TW32MSG1( _fn, _msg, _arg1 ) \
    TraceWin32( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(_msg), _fn, ERROR_SUCCESS, _arg1 )

#define TW32E( _fn, _errIgnore ) \
    TraceWin32( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(#_fn), _fn, _errIgnore )

#define TW32EMSG( _fn, _errIgnore, _msg ) \
    TraceWin32( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(_msg), _fn, _errIgnore )
#define TW32EMSG1( _fn, _errIgnore, _msg, _arg1 ) \
    TraceWin32( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(_msg), _fn, _errIgnore, _arg1 )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  RRETURN(
//      _fn
//      )
//
//  Description:
//      Warning is display if return value is anything but ERROR_SUCCESS (0).
//
//  Argument:
//      _fn - Value to return.
//
//  Return Values:
//      _fn always.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define RRETURN( _fn ) \
    do \
    { \
        if ( g_tfModule != 0 ) \
        { \
            __MissingTraceFunc = 0; \
            if ( _fn != ERROR_SUCCESS ) \
            { \
                DebugReturnMessage( TEXT(__FILE__), __LINE__, __MODULE__, TEXT( "V ") TEXT(#_fn) TEXT(" = 0x%08x (%s)"), _fn ); \
            } \
            else \
            { \
                TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, mtfFUNC, TEXT("V") ); \
            } \
            DebugDecrementStackDepthCounter(); \
        } \
        return _fn; \
    } while ( 0 )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  QIRETURN(
//      _hr,
//      _riid
//      )
//
//  Description:
//      Warning is display if HRESULT is anything but S_OK (0) only if
//      mtfQUERYINTERFACE is set in g_tfModule, otherwise only a debug
//      message will be printed. Note that TraceFunc() must have been called
//      on the call stack counter must be incremented prior to using.
//
//      QIRETURNx will ignore E_NOINTERFACE errors for the interfaces
//      specified.
//
//  Arguments:
//      _hr     - Result of the query interface call.
//      _riid   - The reference ID of the interfaced queried for.
//
//  Return Values:
//      None - calls RETURN macro.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define QIRETURN( _hr, _riid ) \
    do \
    { \
        if ( _hr ) \
        { \
            TCHAR szGuid[ 40 ]; \
            TCHAR szSymbolicName[ 64 ]; \
            DWORD cchSymbolicName = 64; \
            DebugFindWinerrorSymbolicName( _hr, szSymbolicName, &cchSymbolicName ); \
            Assert( cchSymbolicName != 64 ); \
            DebugMessage( TEXT(__FILE__), \
                          __LINE__, \
                          __MODULE__, \
                          TEXT("*HRESULT* QueryInterface( %s, ppv ) failed(), hr = 0x%08x (%s)"), \
                          PszDebugFindInterface( _riid, szGuid ), \
                          _hr, \
                          szSymbolicName \
                          ); \
        } \
        if ( g_tfModule & mtfQUERYINTERFACE ) \
        { \
            __MissingTraceFunc = 0; \
            TraceHR( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(#_hr), _hr, FALSE, S_OK ); \
        } \
        HRETURN( _hr ); \
    } while ( 0 )

#define QIRETURN1( _hr, _riid, _riidIgnored1 ) \
    do \
    { \
        if ( _hr == E_NOINTERFACE \
          && IsEqualIID( _riid, _riidIgnored1 ) \
           ) \
        { \
            FRETURN( S_OK ); \
            return( _hr ); \
        } \
        QIRETURN( _hr, _riid ); \
    } while ( 0 )

#define QIRETURN2( _hr, _riid, _riidIgnored1, _riidIgnored2 ) \
    do \
    { \
        if ( _hr == E_NOINTERFACE \
          &&    ( IsEqualIID( _riid, _riidIgnored1 ) \
               || IsEqualIID( _riid, _riidIgnored2 ) \
                ) \
           ) \
        { \
            FRETURN( S_OK ); \
            return( _hr ); \
        } \
        QIRETURN( _hr, _riid ); \
    } while ( 0 )

#define QIRETURN3( _hr, _riid, _riidIgnored1, _riidIgnored2, _riidIgnored3 ) \
    do \
    { \
        if ( _hr == E_NOINTERFACE \
          &&    ( IsEqualIID( _riid, _riidIgnored1 ) \
               || IsEqualIID( _riid, _riidIgnored2 ) \
               || IsEqualIID( _riid, _riidIgnored3 ) \
                ) \
           ) \
        { \
            FRETURN( S_OK ); \
            return( _hr ); \
        } \
        QIRETURN( _hr, _riid ); \
    } while ( 0 )

#define QIRETURN4( _hr, _riid, _riidIgnored1, _riidIgnored2, _riidIgnored3, _riidIgnored4 ) \
    do \
    { \
        if ( _hr == E_NOINTERFACE \
          &&    ( IsEqualIID( _riid, _riidIgnored1 ) \
               || IsEqualIID( _riid, _riidIgnored2 ) \
               || IsEqualIID( _riid, _riidIgnored3 ) \
               || IsEqualIID( _riid, _riidIgnored4 ) \
                ) \
           ) \
        { \
            FRETURN( S_OK ); \
            return( _hr ); \
        } \
        QIRETURN( _hr, _riid ); \
    } while ( 0 )

#define QIRETURN5( _hr, _riid, _riidIgnored1, _riidIgnored2, _riidIgnored3, _riidIgnored4, _riidIgnored5 ) \
    do \
    { \
        if ( _hr == E_NOINTERFACE \
          &&    ( IsEqualIID( _riid, _riidIgnored1 ) \
               || IsEqualIID( _riid, _riidIgnored2 ) \
               || IsEqualIID( _riid, _riidIgnored3 ) \
               || IsEqualIID( _riid, _riidIgnored4 ) \
               || IsEqualIID( _riid, _riidIgnored5 ) \
                ) \
           ) \
        { \
            FRETURN( S_OK ); \
            return( _hr ); \
        } \
        QIRETURN( _hr, _riid ); \
    } while ( 0 )

#define QIRETURN6( _hr, _riid, _riidIgnored1, _riidIgnored2, _riidIgnored3, _riidIgnored4, _riidIgnored5, _riidIgnored6 ) \
    do \
    { \
        if ( _hr == E_NOINTERFACE \
          &&    ( IsEqualIID( _riid, _riidIgnored1 ) \
               || IsEqualIID( _riid, _riidIgnored2 ) \
               || IsEqualIID( _riid, _riidIgnored3 ) \
               || IsEqualIID( _riid, _riidIgnored4 ) \
               || IsEqualIID( _riid, _riidIgnored5 ) \
               || IsEqualIID( _riid, _riidIgnored6 ) \
                ) \
           ) \
        { \
            FRETURN( S_OK ); \
            return( _hr ); \
        } \
        QIRETURN( _hr, _riid ); \
    } while ( 0 )

#define QIRETURN7( _hr, _riid, _riidIgnored1, _riidIgnored2, _riidIgnored3, _riidIgnored4, _riidIgnored5, _riidIgnored6, _riidIgnored7 ) \
    do \
    { \
        if ( _hr == E_NOINTERFACE \
          &&    ( IsEqualIID( _riid, _riidIgnored1 ) \
               || IsEqualIID( _riid, _riidIgnored2 ) \
               || IsEqualIID( _riid, _riidIgnored3 ) \
               || IsEqualIID( _riid, _riidIgnored4 ) \
               || IsEqualIID( _riid, _riidIgnored5 ) \
               || IsEqualIID( _riid, _riidIgnored6 ) \
               || IsEqualIID( _riid, _riidIgnored7 ) \
                ) \
           ) \
        { \
            FRETURN( S_OK ); \
            return( _hr ); \
        } \
        QIRETURN( _hr, _riid ); \
    } while ( 0 )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  QIRETURN_IGNORESTDMARSHALLING(
//      _hr,
//      _riid
//      )
//
//  Description:
//      Works like QIRETURN (see QIRETURN above), but ignores E_NOINTERFACE for
//      the standard marshalling interfaces.
//
//  Arguments:
//      _hr     - Result of the query interface call.
//      _riid   - The reference ID of the interfaced queried for.
//
//  Return Values:
//      None - calls QIRETURN5 macro.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define QIRETURN_IGNORESTDMARSHALLING( _hr, _riid ) \
    do \
    { \
        const GUID _COCLASS_IdentityUnmarshall = { 0x0000001b, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 }; \
        const GUID _IID_IMarshalOptions_ =       { 0x4c1e39e1, 0xe3e3, 0x4296, 0xaa, 0x86, 0xec, 0x93, 0x8d, 0x89, 0x6e, 0x92 }; \
        QIRETURN6( _hr, _riid, IID_IMarshal, _COCLASS_IdentityUnmarshall, IID_IStdMarshalInfo, IID_IExternalConnection, IID_ICallFactory, _IID_IMarshalOptions_ ); \
    } while ( 0 )

#define QIRETURN_IGNORESTDMARSHALLING1( _hr, _riid, _riid1 ) \
    do \
    { \
        const GUID _COCLASS_IdentityUnmarshall = { 0x0000001b, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 }; \
        const GUID _IID_IMarshalOptions_ =       { 0x4c1e39e1, 0xe3e3, 0x4296, 0xaa, 0x86, 0xec, 0x93, 0x8d, 0x89, 0x6e, 0x92 }; \
        QIRETURN7( _hr, _riid, IID_IMarshal, _COCLASS_IdentityUnmarshall, IID_IStdMarshalInfo, IID_IExternalConnection, IID_ICallFactory, _riid1, _IID_IMarshalOptions_ ); \
    } while ( 0 )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  BOOLTOSTRING(
//      _fBool
//      )
//
//  Desfription:
//      If _fBool is true, returns address of "TRUE" else returns address of
//      "FALSE".
//
//  Argument:
//      _fBool  - Expression to evaluate.
//
//  Return Values:
//      address of "TRUE" if _fBool is true.
//      address of "FALSE" if _fBool is false.
//
//--
//////////////////////////////////////////////////////////////////////////////
#define BOOLTOSTRING( _fBool ) ( (_fBool) ? g_szTrue : g_szFalse )

//****************************************************************************
//
// Trace/Debug Functions - these do not exist in RETAIL.
//
//****************************************************************************

BOOL
IsDebugFlagSet(
    TRACEFLAG   tfIn
    );

void
__cdecl
TraceMsg(
    TRACEFLAG   tfIn,
    LPCSTR      pszFormatIn,
    ...
    );

void
__cdecl
TraceMsg(
    TRACEFLAG   tfIn,
    LPCWSTR     pszFormatIn,
    ...
    );

void
__cdecl
DebugMsg(
    LPCSTR      pszFormatIn,
    ...
    );

void
__cdecl
DebugMsg(
    LPCWSTR     pszFormatIn,
    ...
    );

void
__cdecl
DebugMsgNoNewline(
    LPCSTR      pszFormatIn,
    ...
    );

void
__cdecl
DebugMsgNoNewline(
    LPCWSTR     pszFormatIn,
    ...
    );

void
__cdecl
TraceMessage(
    LPCTSTR     pszFileIn,
    const int   nLineIn,
    LPCTSTR     pszModuleIn,
    TRACEFLAG   tfIn,
    LPCTSTR     pszFormatIn,
    ...
    );

void
__cdecl
TraceMessageDo(
    LPCTSTR     pszFileIn,
    const int   nLineIn,
    LPCTSTR     pszModuleIn,
    TRACEFLAG   tfIn,
    LPCTSTR     pszFormatIn,
    LPCTSTR     pszFuncIn,
    ...
    );

void
__cdecl
DebugMessage(
    LPCTSTR     pszFileIn,
    const int   nLineIn,
    LPCTSTR     pszModuleIn,
    LPCTSTR     pszFormatIn,
    ...
    );

void
__cdecl
DebugMessageDo(
    LPCTSTR     pszFileIn,
    const int   nLineIn,
    LPCTSTR     pszModuleIn,
    LPCTSTR     pszFormatIn,
    LPCTSTR     pszFuncIn,
    ...
    );

BOOL
AssertMessage(
    LPCTSTR     pszFileIn,
    const int   nLineIn,
    LPCTSTR     pszModuleIn,
    LPCTSTR     pszfnIn,
    BOOL        fTrueIn,
    ...
    );

HRESULT
TraceHR(
    LPCTSTR     pszFileIn,
    const int   nLineIn,
    LPCTSTR     pszModuleIn,
    LPCTSTR     pszfnIn,
    HRESULT     hrIn,
    BOOL        fSuccessIn,
    HRESULT     hrIgnoreIn,
    ...
    );

ULONG
TraceWin32(
    LPCTSTR     pszFileIn,
    const int   nLineIn,
    LPCTSTR     pszModuleIn,
    LPCTSTR     pszfnIn,
    ULONG       ulErrIn,
    ULONG       ulErrIgnoreIn,
    ...
    );

void
__cdecl
TraceLogMsgNoNewline(
    LPCSTR  pszFormatIn,
    ...
    );

void
__cdecl
TraceLogMsgNoNewline(
    LPCWSTR pszFormatIn,
    ...
    );

#if 0
//
// Trying to get the NTSTATUS stuff to play in "user world"
// is just about impossible. This is here in case it is needed
// and one could find the right combination of headers to
// make it work. Inflicting such pain on others is the reason
// why this function is #ifdef'fed.
//
void
DebugFindNTStatusSymbolicName(
    NTSTATUS dwStatusIn,
    LPTSTR   pszNameOut,
    LPDWORD  pcchNameInout
    );
#endif

void
DebugFindWinerrorSymbolicName(
    DWORD dwErrIn,
    LPTSTR  pszNameOut,
    LPDWORD pcchNameInout
    );

void
DebugReturnMessage(
    LPCTSTR     pszFileIn,
    const int   nLineIn,
    LPCTSTR     pszModuleIn,
    LPCTSTR     pszMessageIn,
    DWORD       dwErrIn
    );

//****************************************************************************
//
//  Use the TraceMemoryXXX wrappers, not the DebugMemoryXXX functions.
//  The memory tracking functions do not exist in RETAIL (converted to NOP).
//
//****************************************************************************

typedef enum EMEMORYBLOCKTYPE
{
    mmbtUNKNOWN = 0,           // Never used
    mmbtMEMORYALLOCATION,      // GlobalAlloc/LocalAlloc/malloc
    mmbtOBJECT,                // Object pointer
    mmbtHANDLE,                // Object handle
    mmbtPUNK,                  // IUnknown pointer
    mmbtSYSALLOCSTRING         // SysAllocString
} EMEMORYBLOCKTYPE;

#define TraceMemoryAdd( _mbtType, _hGlobalIn, _pszFileIn, _nLineIn, _pszModuleIn, _dwBytesIn, _pszCommentIn ) \
    DebugMemoryAdd( _mbtType, _hGlobalIn, _pszFileIn, _nLineIn, _pszModuleIn, _dwBytesIn, _pszCommentIn )

#define TraceMemoryAddAddress( _pv ) \
    DebugMemoryAdd( mmbtMEMORYALLOCATION, _pv, TEXT(__FILE__), __LINE__, __MODULE__, 0, TEXT(#_pv) )

#define TraceMemoryAddHandle( _handle ) \
    DebugMemoryAdd( mmbtHANDLE, _handle, TEXT(__FILE__), __LINE__, __MODULE__, 0, TEXT(#_handle) )

#define TraceMemoryAddObject( _pv ) \
    DebugMemoryAdd( mmbtOBJECT, _pv, TEXT(__FILE__), __LINE__, __MODULE__, 0, TEXT(#_pv) )

#define TraceMemoryAddPunk( _punk ) \
    DebugMemoryAdd( mmbtPUNK, _punk, TEXT(__FILE__), __LINE__, __MODULE__, 0, TEXT(#_punk) )

#define TraceMemoryAddBSTR( _pv ) \
    DebugMemoryAdd( mmbtSYSALLOCSTRING, _pv, TEXT(__FILE__), __LINE__, __MODULE__, 0, TEXT(#_pv) )

#define TraceMemoryDelete( _hGlobalIn, _fClobberIn ) \
    DebugMemoryDelete( mmbtUNKNOWN, _hGlobalIn, TEXT(__FILE__), __LINE__, __MODULE__, _fClobberIn )

#define TraceStrDup( _sz ) \
    (LPTSTR) DebugMemoryAdd( mmbtMEMORYALLOCATION, StrDup( _sz ), TEXT(__FILE__), __LINE__, __MODULE__, 0, TEXT("StrDup( ") TEXT(#_sz) TEXT(" )") )

#if defined( USES_SYSALLOCSTRING )
// BUGBUG:  DavidP 09-DEC-1999
//          _sz is evaluated multiple times but the name of the
//          macro is mixed case.
#define TraceSysAllocString( _sz ) \
(BSTR) DebugMemoryAdd( mmbtSYSALLOCSTRING, SysAllocString( _sz ), TEXT(__FILE__), __LINE__, __MODULE__, ((DWORD)( *(&_sz) == NULL ? 0 : wcslen( _sz ) + 1 )), TEXT("SysAllocString( ") TEXT(#_sz) TEXT(")") )

// BUGBUG:  DavidP 09-DEC-1999
//          _sz and _len are evaluated multiple times but the name of the
//          macro is mixed case.
#define TraceSysAllocStringByteLen( _sz, _len ) \
    (BSTR) DebugMemoryAdd( mmbtSYSALLOCSTRING, SysAllocStringByteLen( _sz, _len ), TEXT(__FILE__), __LINE__, __MODULE__, _len, TEXT("SysAllocStringByteLen( ") TEXT(#_sz) TEXT(")") )

// BUGBUG:  DavidP 09-DEC-1999
//          _sz and _len are evaluated multiple times but the name of the
//          macro is mixed case.
#define TraceSysAllocStringLen( _sz, _len ) \
    (BSTR) DebugMemoryAdd( mmbtSYSALLOCSTRING, SysAllocStringLen( _sz, _len ), TEXT(__FILE__), __LINE__, __MODULE__, _len + 1, TEXT("SysAllocStringLen( ") TEXT(#_sz) TEXT(")") )

#define TraceSysReAllocString( _bstrOrg, _bstrNew ) \
    DebugSysReAllocString( TEXT(__FILE__), __LINE__, __MODULE__, _bstrOrg, _bstrNew, TEXT("TraceSysReAllocString(") TEXT(#_bstrOrg) TEXT(", ") TEXT(#_bstrNew) TEXT(" )") )

#define TraceSysReAllocStringLen( _bstrOrg, _bstrNew, _cch ) \
    DebugSysReAllocStringLen( TEXT(__FILE__), __LINE__, __MODULE__, _bstrOrg, _bstrNew, _cch, TEXT("TraceSysReAllocString(") TEXT(#_bstrOrg) TEXT(", ") TEXT(#_bstrNew) TEXT(", ") TEXT(#_cch) TEXT(" )") )

#define TraceSysFreeString( _bstr ) \
    DebugMemoryDelete( mmbtSYSALLOCSTRING, _bstr, TEXT(__FILE__), __LINE__, __MODULE__, TRUE ); \
    SysFreeString( _bstr )
#endif // USES_SYSALLOCSTRING

//****************************************************************************
//
//  Memory tracing functions - these are remapped to the GlobalAlloc/GlobalFree
//  heap functions when in RETAIL. Use the TraceMemoryXXX wrappers, not the
//  DebugMemoryXXX functions.
//
//****************************************************************************
void *
DebugAlloc(
    LPCTSTR     pszFileIn,
    const int   nLineIn,
    LPCTSTR     pszModuleIn,
    UINT        uFlagsIn,
    DWORD       dwBytesIn,
    LPCTSTR     pszCommentIn
    );

void *
DebugReAlloc(
    LPCTSTR     pszFileIn,
    const int   nLineIn,
    LPCTSTR     pszModuleIn,
    void *      pvMemIn,
    UINT        uFlagsIn,
    DWORD       dwBytesIn,
    LPCTSTR     pszCommentIn
    );

BOOL
DebugFree(
    void *      pvMemIn,
    LPCTSTR     pszFileIn,
    const int   nLineIn,
    LPCTSTR     pszModuleIn
    );

void *
DebugMemoryAdd(
      EMEMORYBLOCKTYPE  mbtType
    , void *            pvMemIn
    , LPCTSTR           pszFileIn
    , const int         nLineIn
    , LPCTSTR           pszModuleIn
    , DWORD             dwBytesIn
    , LPCTSTR           pszCommentIn
    );

void
DebugMemoryDelete(
      EMEMORYBLOCKTYPE  mbtTypeIn
    , void *            pvMemIn
    , LPCTSTR           pszFileIn
    , const int         nLineIn
    , LPCTSTR           pszModuleIn
    , BOOL              fClobberIn
    );

#if defined( USES_SYSALLOCSTRING )

INT
DebugSysReAllocString(
    LPCTSTR         pszFileIn,
    const int       nLineIn,
    LPCTSTR         pszModuleIn,
    BSTR *          pbstrIn,
    const OLECHAR * pszIn,
    LPCTSTR         pszCommentIn
    );

INT
DebugSysReAllocStringLen(
    LPCTSTR         pszFileIn,
    const int       nLineIn,
    LPCTSTR         pszModuleIn,
    BSTR *          pbstrIn,
    const OLECHAR * pszIn,
    unsigned int    ucchIn,
    LPCTSTR         pszCommentIn
    );

#endif // USES_SYSALLOCSTRING

void
DebugMemoryCheck(
    LPVOID  pvListIn,
    LPCTSTR pszListNameIn
    );

//****************************************************************************
//
//  operator new() for C++
//
//****************************************************************************
#ifdef __cplusplus
extern
void *
__cdecl
operator new(
    size_t      nSizeIn,
    LPCTSTR     pszFileIn,
    const int   nLineIn,
    LPCTSTR     pszModuleIn
    );
/*
//****************************************************************************
//
//  operator new []() for C++
//
//****************************************************************************
extern
void *
__cdecl
operator new [](
    size_t      nSizeIn,
    LPCTSTR     pszFileIn,
    const int   nLineIn,
    LPCTSTR     pszModuleIn
    );
*/
//****************************************************************************
//
//  operator delete() for C++
//
//****************************************************************************
extern
void
__cdecl
operator delete(
    void *      pMem,
    LPCTSTR     pszFileIn,
    const int   nLineIn,
    LPCTSTR     pszModuleIn
    );
/*
//****************************************************************************
//
//  operator delete []() for C++
//
//****************************************************************************
extern
void
__cdecl
operator delete [](
    void *      pMemIn,
    size_t      stSizeIn,
    LPCTSTR     pszFileIn,
    const int   nLineIn,
    LPCTSTR     pszModuleIn
    );
*/
//
// Remap "new" to our macro so "we" don't have to type anything extra and
// so it magically dissappears in RETAIL.
//
#define new new( TEXT(__FILE__), __LINE__, __MODULE__ )
#endif

//****************************************************************************
//
//
#else // it's RETAIL    ******************************************************
//
//
//****************************************************************************

#pragma message("BUILD: RETAIL macros being built")

//
// Debugging -> NOPs
//
#define DEFINE_MODULE( _module )
#define __MODULE__                                  NULL
#define DEFINE_THISCLASS( _class )
#define __THISCLASS__                               NULL
//#define DEFINE_SUPER( _super )
//#define __SUPERCLASS__                              NULL
#define BOOLTOSTRING( _fBool )                      NULL

#define DebugDo( _fn )
#define DebugMsgDo( _fn, _msg )
#define TraceMsgGUID( _f, _m, _g )

#define AssertMessage               TRUE


//
// TODO: gpease 08-NOV-1999
//  We probably want to do something special for ErrorMsg()
//
#define ErrorMsg                    1 ? (void)0 : (void)__noop

#define TraceMsg                    1 ? (void)0 : (void)__noop
#define WndMsg                      1 ? (void)0 : (void)__noop
#define DebugMsg                    1 ? (void)0 : (void)__noop
#define DebugMsgNoNewline           1 ? (void)0 : (void)__noop
#define TraceMessage                1 ? (void)0 : (void)__noop
#define DebugMessage                1 ? (void)0 : (void)__noop
#define TraceHR                     1 ? (void)0 : (void)__noop
#define TraceFunc                   1 ? (void)0 : (void)__noop
#define TraceFunc1                  1 ? (void)0 : (void)__noop
#define TraceFunc2                  1 ? (void)0 : (void)__noop
#define TraceFunc3                  1 ? (void)0 : (void)__noop
#define TraceFunc4                  1 ? (void)0 : (void)__noop
#define TraceFunc5                  1 ? (void)0 : (void)__noop
#define TraceFunc6                  1 ? (void)0 : (void)__noop
#define TraceQIFunc                 1 ? (void)0 : (void)__noop
#define TraceFlow                   1 ? (void)0 : (void)__noop
#define TraceFlow1                  1 ? (void)0 : (void)__noop
#define TraceFlow2                  1 ? (void)0 : (void)__noop
#define TraceFlow3                  1 ? (void)0 : (void)__noop
#define TraceFlow4                  1 ? (void)0 : (void)__noop
#define TraceFlow5                  1 ? (void)0 : (void)__noop
#define TraceFlow6                  1 ? (void)0 : (void)__noop
#define TraceFuncExit()             return
#if defined( DEBUG_SW_TRACING_ENABLED )
#define TraceInitializeProcess( _rgControl, _sizeofControl, _fGlobalMemoryTackingIn )
#define TraceTerminateProcess( _rgControl, _sizeofControl )
#else // ! DEBUG_SW_TRACING_ENABLED
#define TraceInitializeProcess( _fGlobalMemoryTackingIn )
#define TraceTerminateProcess()
#endif // DEBUG_SW_TRACING_ENABLED
#define TraceInitializeThread( _name )
#define TraceThreadRundown()
#define TraceMemoryAdd( _mbtType, _hGlobalIn, _pszFileIn, _nLineIn, _pszModuleIn, _uFlagsIn, _dwBytesIn, _pszCommentIn ) _hGlobalIn
#define TraceMemoryAddHandle( _handle ) _handle
#define TraceMemoryAddBSTR( _bstr ) _bstr
#define TraceMemoryAddAddress( _pv )    _pv
#define TraceMemoryAddHandle( _obj )    _obj
#define TraceMemoryAddPunk( _punk )     _punk
#define TraceMemoryDelete( _h, _b )     _h
#define TraceMemoryAddObject( _pv )     _pv
#define IsTraceFlagSet( _flag )         FALSE

//
// Tracing -> just do operation
//
#define TraceDo( _fn )  _fn

#define TraceMsgDo( _fn, _msg )                                             _fn
#define TraceMsgDo1( _fn, _msg, _arg1 )                                     _fn
#define TraceMsgDo2( _fn, _msg, _arg1, _arg2 )                              _fn
#define TraceMsgDo3( _fn, _msg, _arg1, _arg2, _arg3 )                       _fn
#define TraceMsgDo4( _fn, _msg, _arg1, _arg2, _arg3, _arg4 )                _fn
#define TraceMsgDo5( _fn, _msg, _arg1, _arg2, _arg3, _arg4, _arg5 )         _fn
#define TraceMsgDo6( _fn, _msg, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6 )  _fn

#define TraceMsgPreDo( _fn, _msg1, _msg2 )                                              _fn
#define TraceMsgPreDo1( _fn, _msg1, _msg2, _arg1 )                                      _fn
#define TraceMsgPreDo2( _fn, _msg1, _msg2, _arg1, _arg2 )                               _fn
#define TraceMsgPreDo3( _fn, _msg1, _msg2, _arg1, _arg2, _arg3 )                        _fn
#define TraceMsgPreDo4( _fn, _msg1, _msg2, _arg1, _arg2, _arg3, _arg4 )                 _fn
#define TraceMsgPreDo5( _fn, _msg1, _msg2, _arg1, _arg2, _arg3, _arg4, _arg5 )          _fn
#define TraceMsgPreDo6( _fn, _msg1, _msg2, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6 )   _fn

#define TraceAssertIfZero( _fn )    _fn

//
// RETURN testing -> do retail
//
#define THR( _hr )                                  _hr
#define THRMSG( _hr, _msg )                         _hr
#define THRMSG1( _hr, _msg, _arg1 )                 _hr
#define THRE( _hr, _hrIgnore )                      _hr
#define THREMSG( _hr, _hrIgnore, _msg )             _hr
#define THREMSG1( _hr, _hrIgnore, _msg, _arg1 )     _hr
#define STHR( _hr )                                 _hr
#define STHRMSG( _hr, _msg )                        _hr
#define STHRMSG1( _hr, _msg, _arg1 )                _hr
#define STHRE( _hr, _hrIgnore )                     _hr
#define STHREMSG( _hr, _hrIgnore, _msg )            _hr
#define STHREMSG1( _hr, _hrIgnore, _msg, _arg1 )    _hr
#define TW32( _fn )                                 _fn
#define TW32MSG( _fn, _msg )                        _fn
#define TW32MSG1( _fn, _msg, _arg1 )                _fn
#define TW32E( _fn, _errIgnore )                    _fn
#define TW32EMSG( _fn, _errIgnore, _msg )           _fn
#define TW32EMSG1( _fn, _errIgnore, _msg, _arg1 )   _fn
#define RETURN( _fn )               return _fn
#define FRETURN( _fn )
#define RRETURN( _fn )              return _fn
#define HRETURN( _hr )              return _hr
#define QIRETURN( _qi, _riid )      return _qi
#define QIRETURN1( _qi, _riid, _riid1 )      return _qi
#define QIRETURN2( _qi, _riid, _riid1, _riid2 )      return _qi
#define QIRETURN3( _qi, _riid, _riid1, _riid2, _riid3 )      return _qi
#define QIRETURN4( _qi, _riid, _riid1, _riid2, _riid3, _riid4 )      return _qi
#define QIRETURN5( _qi, _riid, _riid1, _riid2, _riid3, _riid4, _riid5 )      return _qi
#define QIRETURN6( _qi, _riid, _riid1, _riid2, _riid3, _riid4, _riid5, _riid6 )      return _qi
#define QIRETURN7( _qi, _riid, _riid1, _riid2, _riid3, _riid4, _riid5, _riid6, _riid7 )      return _qi
#define QIRETURN_IGNORESTDMARSHALLING( _qi, _riid ) return _qi
#define QIRETURN_IGNORESTDMARSHALLING1( _qi, _riid, _riid1 ) return _qi

//
// Memory Functions -> do retail
//
#define TraceAlloc( _flags, _size )                             HeapAlloc( GetProcessHeap(), _flags, _size )
#define TraceAllocString( _flags, _size )                       (LPTSTR) HeapAlloc( GetProcessHeap(), flags, (_size) * sizeof( TCHAR ) )
#define TraceReAlloc( _pvMem, _uBytes, _uFlags )                ( ( _pvMem == NULL ) \
                                                                ? HeapAlloc( GetProcessHeap(), _uFlags, _uBytes ) \
                                                                : HeapReAlloc( GetProcessHeap(), _uFlags, _pvMem, _uBytes ) )
#define TraceFree( _pv )                                        HeapFree( GetProcessHeap(), 0, _pv )
#define TraceStrDup( _sz )                                      StrDup( _sz )
#define TraceSysAllocString( _sz )                              SysAllocString( _sz )
#define TraceSysAllocStringByteLen( _sz, _len )                 SysAllocStringByteLen( _sz, _len )
#define TraceSysAllocStringLen( _sz, _len )                     SysAllocStringLen( _sz, _len )
#define TraceSysReAllocString( _bstrOrg, _bstrNew )             SysReAllocString( _bstrOrg, _bstrNew )
#define TraceSysReAllocStringLen( _bstrOrg, _bstrNew, _cch )    SysReAllocStringLen( _bstrOrg, _bstrNew, _cch )
#define TraceSysFreeString( _bstr )                             SysFreeString( _bstr )
#define TraceCreateMemoryList( _pvIn )
#define TraceMoveToMemoryList( _addr, _pvIn )
//#define TraceMemoryListDelete( _addr, _pvIn, _fClobber )
#define TraceTerminateMemoryList( _pvIn )
#define TraceMoveFromMemoryList( _addr, _pmbIn )

#endif // DEBUG

#if DBG==1 || defined( _DEBUG )
//////////////////////////////////////////////////////////////////////////////
//
// MACRO
// DEBUG_BREAK
//
// Description:
//      Because the system expection handler can hick-up over INT 3s and
//      DebugBreak()s, This x86 only macro causes the program to break in the
//      right spot.
//
//////////////////////////////////////////////////////////////////////////////
#if defined( _X86_ )
#define DEBUG_BREAK         do { _try { _asm int 3 } _except (EXCEPTION_EXECUTE_HANDLER) {;} } while ( 0 )
#else
#define DEBUG_BREAK         DebugBreak()
#endif

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  Assert(
//      _fn
//      )
//
//  Description:
//      Checks to see if the Expression is TRUE. If not, a message will be
//      displayed to the user on wether the program should break or continue.
//
//  Arguments:
//      _fn     - Expression being asserted.
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
#ifdef Assert
#undef Assert
#endif
// BUGBUG:  DavidP 09-DEC-1999
//          __fn is evaluated multiple times but the name of the
//          macro is mixed case.
#define Assert( _fn ) \
    do \
    { \
        if ( ! (_fn) && AssertMessage( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(#_fn), !!(_fn) ) ) \
        { \
            DEBUG_BREAK; \
        } \
    } while ( 0 )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  AssertMsg(
//      _fn,
//      _msg
//      )
//
//  Descrption:
//      Just like an Assert but has an (hopefully) informative message
//      associated with it.
//
//  Arguments:
//      _fn     - Expression to be evaluated.
//      _msg    - Message to be display if assertion fails.
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
#ifdef AssertMsg
#undef AssertMsg
#undef AssertMsg1
#endif
// BUGBUG:  DavidP 09-DEC-1999
//          _fn is evaluated multiple times but the name of the
//          macro is mixed case.
#define AssertMsg( _fn, _msg ) \
    do \
    { \
        if ( ! (_fn) && AssertMessage( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(_msg), !!(_fn) ) ) \
        { \
            DEBUG_BREAK; \
        } \
    } while ( 0 )
#define AssertMsg1( _fn, _msg, _arg1 ) \
    do \
    { \
        if ( ! (_fn) && AssertMessage( TEXT(__FILE__), __LINE__, __MODULE__, TEXT(_msg), !!(_fn), _arg1 ) ) \
        { \
            DEBUG_BREAK; \
        } \
    } while ( 0 )

//////////////////////////////////////////////////////////////////////////////
//++
//
//  MACRO
//  AssertString(
//      _fn,
//      _msg
//      )
//
//  Descrption:
//      Just like an Assert but has a (hopefully) informative string
//      associated with it.
//
//  Arguments:
//      _fn     - Expression to be evaluated.
//      _msg    - String to be display if assertion fails.
//
//  Return Values:
//      None.
//
//--
//////////////////////////////////////////////////////////////////////////////
#ifdef AssertString
#undef AssertString
#endif
// BUGBUG:  DavidP 09-DEC-1999
//          _fn is evaluated multiple times but the name of the
//          macro is mixed case.
#define AssertString( _fn, _str ) \
    do \
    { \
        if ( ! (_fn) && AssertMessage( TEXT(__FILE__), __LINE__, __MODULE__, _str, !!(_fn) ) ) \
        { \
            DEBUG_BREAK; \
        } \
    } while ( 0 )

#undef VERIFY
#undef VERIFYMSG
#undef VERIFYMSG1
#undef VERIFYSTRING

#define VERIFY( _fn )                   Assert( _fn )
#define VERIFYMSG( _fn, _msg )          AssertMsg( _fn, _msg )
#define VERIFYMSG1( _fn, _msg, _arg1 )  AssertMsg1( _fn, _msg, _arg1 )
#define VERIFYSTRING( _fn, _str )       AssertString( _fn, _str )

#else // DBG!=1 && !_DEBUG

#define DEBUG_BREAK DebugBreak()

#ifndef Assert
#define Assert( _fn )
#endif

#ifndef AssertMsg
#define AssertMsg( _fn, _msg )
#endif

#ifndef AssertMsg1
#define AssertMsg1( _fn, _msg, _arg1 )
#endif

#ifndef AssertString
#define AssertString( _fn, _msg )
#endif

#ifndef VERIFY
#define VERIFY( _fn ) _fn
#endif

#ifndef VERIFYMSG
#define VERIFYMSG( _fn, _msg ) _fn
#endif

#ifndef VERIFYMSG1
#define VERIFYMSG1( _fn, _msg, _arg1 ) _fn
#endif

#ifndef VERIFYSTRING
#define VERIFYSTRING( _fn, _str ) _fn
#endif

#endif // DBG==1 || _DEBUG
