mirror of https://github.com/PCSX2/pcsx2.git
327 lines
11 KiB
C++
327 lines
11 KiB
C++
//==========================================================================;
|
|
//
|
|
// 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 - 1996 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
// Debugging facilities, January 1995
|
|
|
|
#ifndef __WXDEBUG__
|
|
#define __WXDEBUG__
|
|
|
|
// Avoid conflict with MFC
|
|
#undef ASSERT
|
|
|
|
// 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 {
|
|
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 DbgInitKeyLevels(HKEY hKey);
|
|
void DbgInitGlobalSettings();
|
|
void DbgInitModuleSettings();
|
|
void DbgInitModuleName();
|
|
DWORD DbgRegisterObjectCreation(TCHAR *pObjectName);
|
|
BOOL DbgRegisterObjectDestruction(DWORD dwCookie);
|
|
|
|
// These are the PUBLIC entry points
|
|
|
|
BOOL DbgCheckModuleLevel(DWORD Type,DWORD Level);
|
|
void DbgSetModuleLevel(DWORD Type,DWORD Level);
|
|
|
|
// Initialise the library with the module handle
|
|
|
|
void DbgInitialise(HINSTANCE hInst);
|
|
void DbgTerminate();
|
|
|
|
void DbgDumpObjectRegister();
|
|
|
|
// Display error and logging to the user
|
|
|
|
void DbgAssert(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine);
|
|
void DbgBreakPoint(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine);
|
|
void DbgKernelAssert(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine);
|
|
void DbgLogInfo(DWORD Type,DWORD Level,const TCHAR *pFormat,...);
|
|
void DbgOutString(LPCTSTR psz);
|
|
|
|
// Debug infinite wait stuff
|
|
DWORD DbgWaitForSingleObject(HANDLE h);
|
|
DWORD DbgWaitForMultipleObjects(DWORD nCount,
|
|
CONST HANDLE *lpHandles,
|
|
BOOL bWaitAll);
|
|
void DbgSetWaitTimeout(DWORD dwTimeout);
|
|
|
|
#ifdef __strmif_h__
|
|
void DisplayType(LPSTR label, const AM_MEDIA_TYPE *pmtIn);
|
|
#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__)
|
|
|
|
#define ASSERT(_x_) if (!(_x_)) \
|
|
DbgAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
|
|
|
|
// 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_)
|
|
#define ASSERT(_x_)
|
|
#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)
|
|
|
|
#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
|
|
|
|
|
|
// 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
|
|
|
|
|
|
// 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__
|
|
|