windows-nt/Source/XPSP1/NT/printscan/ui/wiadebug/wiadebug.cpp
2020-09-26 16:20:57 +08:00

1679 lines
48 KiB
C++

/*******************************************************************************
*
* (C) COPYRIGHT MICROSOFT CORPORATION, 1998
*
* TITLE: WIADBG.CPP
*
* VERSION: 1.0
*
* AUTHOR: ShaunIv
*
* DATE: 9/6/1999
*
* DESCRIPTION: Implementation of debug code
*
*******************************************************************************/
//
// need to define this so we don't get any recursion on our calls to "new"
//
#define WIA_DONT_DO_LEAK_CHECKS 1
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include "wianew.h"
#include "wiadebug.h"
#include "simstr.h"
#include "miscutil.h"
#include <shlguid.h>
#include <shlobj.h>
#include <shellapi.h>
#include <wia.h>
#include <dbghelp.h>
#define STACK_TRACE_DB_NAME TEXT("ntdll!RtlpStackTraceDataBase")
#define SYMBOL_BUFFER_LEN 256
#define READVM(Addr, Buf, Sz) ReadVa(__FILE__, __LINE__, (Globals.Target), (Addr), (Buf), (Sz))
#ifdef UNICODE
#define PrintDebugMessage PrintDebugMessageW
#else
#define PrintDebugMessage PrintDebugMessageA
#endif
/******************************************************************************
*
* Class definitions
*
******************************************************************************/
static CGlobalDebugState g_GlobalDebugState;
class CWiaDebugWindowThreadState
{
private:
int m_nIndentLevel;
DWORD m_nDebugMask;
private:
// Not implemented
CWiaDebugWindowThreadState( const CWiaDebugWindowThreadState & );
CWiaDebugWindowThreadState &operator=( const CWiaDebugWindowThreadState & );
public:
CWiaDebugWindowThreadState(void);
DWORD DebugMask(void) const;
DWORD DebugMask( DWORD nDebugMask );
int IndentLevel(void) const;
int IncrementIndentLevel(void);
int DecrementIndentLevel(void);
};
class CProcessGlobalDebugData
{
private:
DWORD m_dwTlsIndex;
BOOL m_bSymLookupInitialized;
PVOID m_pDatabase;
HANDLE m_hProcess;
CSimpleCriticalSection m_CriticalSection;
typedef struct _STACK_NODE
{
LPVOID pKeyAddress;
size_t Size;
PVOID aStack[32];
ULONG ulNumTraces;
_STACK_NODE * pNext;
} STACK_NODE, *PSTACK_NODE;
PSTACK_NODE m_pStackList;
PSTACK_NODE m_pStackListEnd;
LONG m_Leaks;
private:
static CProcessGlobalDebugData *m_pTheProcessGlobalDebugData;
private:
// Not implemented
CProcessGlobalDebugData( const CProcessGlobalDebugData & );
CProcessGlobalDebugData &operator=( const CProcessGlobalDebugData & );
private:
// Sole implemented constructor
CProcessGlobalDebugData(void);
// resolve symbols address into symbols names...
LPTSTR GetSymbolicNameForAddress( ULONG_PTR Address );
BOOL IsSymbolLookupInitialized();
public:
~CProcessGlobalDebugData(void);
DWORD TlsIndex(void) const;
bool IsValid(void) const;
void DoRecordAllocation( LPVOID pv, size_t Size );
void DoRecordFree( LPVOID pv );
void GenerateLeakReport( LPTSTR pszModuleName );
HANDLE ProcessHandle( ) { return m_hProcess; }
static CProcessGlobalDebugData *Allocate(void);
static CProcessGlobalDebugData *ProcessData(void);
static void Free(void);
};
/******************************************************************************
*
* Symbol functions
*
******************************************************************************/
BOOL
EnumerateModules(
IN LPSTR ModuleName,
IN ULONG_PTR BaseOfDll,
IN PVOID UserContext
)
/*
* EnumerateModules
*
* Module enumeration 'proc' for imagehlp. Call SymLoadModule on the
* specified module and if that succeeds cache the module name.
*
* ModuleName is an LPSTR indicating the name of the module imagehlp is
* enumerating for us;
* BaseOfDll is the load address of the DLL, which we don't care about, but
* SymLoadModule does;
* UserContext is a pointer to the relevant SYMINFO, which identifies
* our connection.
*/
{
DWORD64 Result;
CProcessGlobalDebugData *pProcessData = CProcessGlobalDebugData::ProcessData();
if (pProcessData && pProcessData->IsValid())
{
Result = SymLoadModule(pProcessData->ProcessHandle(),
NULL, // hFile not used
NULL, // use symbol search path
ModuleName, // ModuleName from Enum
BaseOfDll, // LoadAddress from Enum
0); // Let ImageHlp figure out DLL size
// SilviuC: need to understand exactly what does this function return
if (Result)
{
return FALSE;
}
return TRUE;
}
return FALSE;
}
/******************************************************************************
*
* CWiaDebugWindowThreadState
*
******************************************************************************/
CWiaDebugWindowThreadState::CWiaDebugWindowThreadState(void)
: m_nIndentLevel(0),
m_nDebugMask(0xFFFFFFFF)
{
}
DWORD CWiaDebugWindowThreadState::DebugMask(void) const
{
return m_nDebugMask;
}
DWORD CWiaDebugWindowThreadState::DebugMask( DWORD nDebugMask )
{
DWORD nOldDebugMask = m_nDebugMask;
m_nDebugMask = nDebugMask;
return nOldDebugMask;
}
int CWiaDebugWindowThreadState::IndentLevel(void) const
{
return m_nIndentLevel;
}
int CWiaDebugWindowThreadState::IncrementIndentLevel(void)
{
return (++m_nIndentLevel);
}
int CWiaDebugWindowThreadState::DecrementIndentLevel(void)
{
--m_nIndentLevel;
if (m_nIndentLevel < 0)
m_nIndentLevel = 0;
return m_nIndentLevel;
}
/******************************************************************************
*
* CProcessGlobalDebugData
*
******************************************************************************/
// Sole implemented constructor
CProcessGlobalDebugData::CProcessGlobalDebugData(void)
: m_dwTlsIndex(TLS_OUT_OF_INDEXES),
m_hProcess(NULL),
m_pDatabase(NULL),
m_bSymLookupInitialized(FALSE),
m_pStackList(NULL),
m_pStackListEnd(NULL),
m_Leaks(0)
{
m_dwTlsIndex = TlsAlloc();
}
CProcessGlobalDebugData::~CProcessGlobalDebugData(void)
{
if (m_dwTlsIndex != TLS_OUT_OF_INDEXES)
TlsFree(m_dwTlsIndex);
m_dwTlsIndex = TLS_OUT_OF_INDEXES;
if (m_hProcess)
{
CloseHandle(m_hProcess);
m_hProcess = NULL;
}
m_bSymLookupInitialized = FALSE;
CAutoCriticalSection cs(m_CriticalSection);
if (m_pStackList)
{
PSTACK_NODE pNextNode = NULL;
for (PSTACK_NODE pNode = m_pStackList; pNode; )
{
if (pNode)
{
pNextNode = pNode->pNext;
LocalFree( pNode );
}
pNode = pNextNode;
pNextNode = NULL;
}
}
}
DWORD CProcessGlobalDebugData::TlsIndex(void) const
{
return m_dwTlsIndex;
}
bool CProcessGlobalDebugData::IsValid(void) const
{
return (m_dwTlsIndex != TLS_OUT_OF_INDEXES);
}
//
// Caller must free returned string via LocalFree
//
LPTSTR CProcessGlobalDebugData::GetSymbolicNameForAddress( ULONG_PTR Address )
{
IMAGEHLP_MODULE ModuleInfo;
TCHAR SymbolBuffer[512];
PIMAGEHLP_SYMBOL Symbol;
ULONG_PTR Offset;
LPTSTR pName;
BOOL bResult;
if (!IsSymbolLookupInitialized())
{
return NULL;
}
if (Address == (ULONG_PTR)-1)
{
*SymbolBuffer = 0;
lstrcpy( SymbolBuffer, TEXT("<< FUZZY STACK TRACE >>") );
pName = (LPTSTR)LocalAlloc( LPTR, (lstrlen( SymbolBuffer ) + 1) * sizeof(TCHAR) );
if (pName)
{
lstrcpy( pName, SymbolBuffer );
}
return pName;
}
ModuleInfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE);
if (!SymGetModuleInfo( m_hProcess, Address, &ModuleInfo ))
{
//
// can't get the module info, so give back an error message...
//
*SymbolBuffer = 0;
wsprintf( SymbolBuffer, TEXT("<< cannot identify module for address %p >>"), Address );
pName = (LPTSTR)LocalAlloc( LPTR, (lstrlen( SymbolBuffer ) + 1) * sizeof(TCHAR) );
if (pName)
{
lstrcpy( pName, SymbolBuffer );
}
return pName;
}
Symbol = (PIMAGEHLP_SYMBOL)SymbolBuffer;
Symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL) - 1;
if (SymGetSymFromAddr( m_hProcess, Address, &Offset, Symbol ))
{
IMAGEHLP_LINE LineInfo;
DWORD Displacement;
BOOL bLineInfoPresent;
CHAR szString[ 1024 ];
bLineInfoPresent = SymGetLineFromAddr (m_hProcess,
Address,
&Displacement,
&LineInfo);
if (bLineInfoPresent)
{
//
// construct string w/filename & linenumber...
//
wsprintfA( szString, "%s!%s (%s, line %u)", ModuleInfo.ModuleName, Symbol->Name, LineInfo.FileName, LineInfo.LineNumber );
}
else
{
//
// no line numbers, so just show symbol + offset
//
wsprintfA( szString, "%s!%s+%08X", ModuleInfo.ModuleName, Symbol->Name, Offset );
}
INT iLen = (lstrlenA(szString)+1);
pName = (LPTSTR) LocalAlloc( LPTR, (iLen * sizeof(TCHAR)) );
if (pName == NULL)
{
return NULL;
}
#ifdef UNICODE
MultiByteToWideChar( CP_ACP, 0, szString, -1, pName, iLen );
#else
lstrcpy( pName, szString);
#endif
return pName;
}
else
{
//
// can't get the address info, so give back an error message...
//
*SymbolBuffer = 0;
#ifdef UNICODE
TCHAR szModW[ MAX_PATH ];
MultiByteToWideChar( CP_ACP, 0, ModuleInfo.ModuleName, -1, szModW, MAX_PATH );
wsprintf( SymbolBuffer, TEXT("<< incorrect symbols for module %s (address %p)"), szModW, Address );
#else
wsprintf( SymbolBuffer, TEXT("<< incorrect symbols for module %s (address %p)"), ModuleInfo.ModuleName, Address );
#endif
pName = (LPTSTR)LocalAlloc( LPTR, (lstrlen( SymbolBuffer ) + 1) * sizeof(TCHAR) );
if (pName)
{
lstrcpy( pName, SymbolBuffer );
}
return pName;
}
return NULL;
}
void CProcessGlobalDebugData::DoRecordAllocation( LPVOID pv, size_t Size )
{
if (!pv)
{
return;
}
PVOID StackTrace[32];
ULONG Count;
ULONG Index;
ULONG Hash;
//
// Capture stack trace up to 32 items deep, but skip last three items
// (because they'll always be the same)
//
Count = RtlCaptureStackBackTrace( 4, 32, StackTrace, NULL );
if (Count)
{
CAutoCriticalSection cs(m_CriticalSection);
//
// Add this stack trace to list
//
PSTACK_NODE pNewNode = (PSTACK_NODE)LocalAlloc( LPTR, sizeof(STACK_NODE) );
if (pNewNode)
{
pNewNode->pKeyAddress = pv;
pNewNode->Size = Size;
pNewNode->ulNumTraces = Count;
memcpy( pNewNode->aStack, StackTrace, sizeof(pNewNode->aStack) );
}
if (!m_pStackList)
{
m_pStackList = pNewNode;
m_pStackListEnd = pNewNode;
}
else
{
m_pStackListEnd->pNext = pNewNode;
m_pStackListEnd = pNewNode;
}
m_Leaks++;
}
}
void CProcessGlobalDebugData::DoRecordFree( LPVOID pv )
{
if (!pv)
{
return;
}
CAutoCriticalSection cs(m_CriticalSection);
//
// Find item in allocation list...
//
PSTACK_NODE pNode = NULL;
PSTACK_NODE pTrail = NULL;
for ( pNode = m_pStackList;
pNode && (pNode->pKeyAddress!=pv);
pTrail = pNode, pNode = pNode->pNext
)
{
;
}
if (pNode)
{
//
// Remove this node from the list...
//
if (!pTrail)
{
//
// It's the first item in list
//
m_pStackList = pNode->pNext;
if (m_pStackListEnd == pNode)
{
m_pStackListEnd = NULL;
}
LocalFree( (HLOCAL) pNode );
m_Leaks--;
}
else
{
//
// We're somewhere in the middle of the list...
//
pTrail->pNext = pNode->pNext;
if (m_pStackListEnd == pNode)
{
m_pStackListEnd = pTrail;
}
LocalFree( (HLOCAL) pNode );
m_Leaks--;
}
}
}
void CProcessGlobalDebugData::GenerateLeakReport(LPTSTR pszModuleName)
{
CAutoCriticalSection cs(m_CriticalSection);
//
// Report the numer of leaks...
//
TCHAR sz[ 512 ];
TCHAR szNewLine[ 3 ];
COLORREF crFore = static_cast<COLORREF>(0xFFFFFFFF), crBack = static_cast<COLORREF>(0xFFFFFFFF);
if (m_Leaks > 0)
{
crFore = RGB(0x00,0x00,0x00);
crBack = RGB(0xFF,0x7F,0x7F);
}
lstrcpy( szNewLine, TEXT("\n") );
PrintDebugMessage( 2, 0xFFFFFFFF, crFore, crBack, pszModuleName, szNewLine );
wsprintf( sz, TEXT("**** Reporting leaks -- %d leaks found ****"), m_Leaks );
PrintDebugMessage( 2, 0xFFFFFFFF, crFore, crBack, pszModuleName, sz );
//
// Loop through the list...
//
LPTSTR pSymbol = NULL;
PSTACK_NODE pNode = m_pStackList;
INT i = 1;
while (pNode)
{
PrintDebugMessage( 2, 0xFFFFFFFF, crFore, crBack, pszModuleName, szNewLine );
wsprintf( sz, TEXT("Leak %d - %d bytes allocated by:"), i++, pNode->Size );
PrintDebugMessage( 2, 0xFFFFFFFF, crFore, crBack, pszModuleName, sz );
for (INT j=0; (j < (INT)pNode->ulNumTraces) && (pNode->aStack[j]); j++)
{
pSymbol = GetSymbolicNameForAddress( (ULONG_PTR)pNode->aStack[j] );
if (pSymbol)
{
PrintDebugMessage( 2, 0xFFFFFFFF, crFore, crBack, pszModuleName, pSymbol );
LocalFree( (HLOCAL)pSymbol );
}
else
{
wsprintf( sz, TEXT("< could not resolve symbols for address %p >"),pNode->aStack[j] );
PrintDebugMessage( 2, 0xFFFFFFFF, crFore, crBack, pszModuleName, sz );
}
}
pNode = pNode->pNext;
}
PrintDebugMessage( 2, 0xFFFFFFFF, crFore, crBack, pszModuleName, szNewLine );
PrintDebugMessage( 2, 0xFFFFFFFF, crFore, crBack, pszModuleName, TEXT("**** End Leak Report ****") );
PrintDebugMessage( 2, 0xFFFFFFFF, crFore, crBack, pszModuleName, szNewLine );
}
BOOL
CProcessGlobalDebugData::IsSymbolLookupInitialized()
{
CAutoCriticalSection cs(m_CriticalSection);
if (!m_bSymLookupInitialized)
{
if (m_hProcess)
{
CloseHandle( m_hProcess );
m_hProcess = NULL;
}
m_hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE,
GetCurrentProcessId()
);
if (m_hProcess)
{
if (SymInitialize( m_hProcess, NULL, TRUE ))
{
SymSetOptions(SYMOPT_CASE_INSENSITIVE |
SYMOPT_DEFERRED_LOADS |
SYMOPT_LOAD_LINES |
SYMOPT_UNDNAME);
if (SymEnumerateModules( m_hProcess, EnumerateModules, m_hProcess))
{
m_bSymLookupInitialized = TRUE;
}
}
}
}
return m_bSymLookupInitialized;
}
CProcessGlobalDebugData *CProcessGlobalDebugData::Allocate(void)
{
if (!m_pTheProcessGlobalDebugData)
m_pTheProcessGlobalDebugData = new CProcessGlobalDebugData;
return (m_pTheProcessGlobalDebugData);
}
CProcessGlobalDebugData *CProcessGlobalDebugData::ProcessData(void)
{
return Allocate();
}
void CProcessGlobalDebugData::Free(void)
{
if (m_pTheProcessGlobalDebugData)
{
delete m_pTheProcessGlobalDebugData;
m_pTheProcessGlobalDebugData = NULL;
}
}
CProcessGlobalDebugData *CProcessGlobalDebugData::m_pTheProcessGlobalDebugData = NULL;
/******************************************************************************
*
* DllMain
*
******************************************************************************/
BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID )
{
BOOL bResult = FALSE;
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
{
bResult = (CProcessGlobalDebugData::Allocate() != NULL);
}
break;
case DLL_PROCESS_DETACH:
{
CProcessGlobalDebugData::Free();
bResult = TRUE;
}
break;
case DLL_THREAD_ATTACH:
{
CProcessGlobalDebugData *pProcessData = CProcessGlobalDebugData::ProcessData();
if (pProcessData && pProcessData->IsValid())
{
CWiaDebugWindowThreadState *pThreadData = new CWiaDebugWindowThreadState;
TlsSetValue( pProcessData->TlsIndex(), pThreadData );
bResult = (pThreadData != NULL);
}
}
break;
case DLL_THREAD_DETACH:
{
CProcessGlobalDebugData *pProcessData = CProcessGlobalDebugData::ProcessData();
if (pProcessData && pProcessData->IsValid())
{
CWiaDebugWindowThreadState *pThreadData = reinterpret_cast<CWiaDebugWindowThreadState*>(TlsGetValue( pProcessData->TlsIndex()));
if (pThreadData)
{
delete pThreadData;
TlsSetValue( pProcessData->TlsIndex(), NULL );
}
}
bResult = TRUE;
}
break;
}
return bResult;
}
/******************************************************************************
*
* Global Helper Functions
*
******************************************************************************/
static bool IsProcessDebugFlagSet( DWORD dwModuleMask )
{
bool bResult = false;
CProcessGlobalDebugData *pProcessData = CProcessGlobalDebugData::ProcessData();
if (pProcessData && pProcessData->IsValid())
{
CWiaDebugWindowThreadState *pThreadData = reinterpret_cast<CWiaDebugWindowThreadState *>(TlsGetValue(pProcessData->TlsIndex()));
if (pThreadData)
{
bResult = ((pThreadData->DebugMask() & dwModuleMask) != 0);
}
}
return (bResult);
}
static CWiaDebugWindowThreadState *ThreadData(void)
{
CWiaDebugWindowThreadState *pThreadData = NULL;
CProcessGlobalDebugData *pProcessData = CProcessGlobalDebugData::ProcessData();
if (pProcessData && pProcessData->IsValid())
{
pThreadData = reinterpret_cast<CWiaDebugWindowThreadState *>(TlsGetValue(pProcessData->TlsIndex()));
if (!pThreadData)
{
pThreadData = new CWiaDebugWindowThreadState;
TlsSetValue( pProcessData->TlsIndex(), pThreadData );
}
}
return (pThreadData);
}
template <class T>
static BOOL ContainsNonWhitespace( T *lpszMsg )
{
for (T *lpszPtr = lpszMsg;*lpszPtr;lpszPtr++)
if (*lpszPtr != ' ' && *lpszPtr != '\n' && *lpszPtr != '\r' && *lpszPtr != '\t')
return TRUE;
return FALSE;
}
static void InsertStackLevelIndent( LPSTR lpszMsg, int nStackLevel )
{
const LPSTR lpszIndent = " ";
CHAR szTmp[1024], *pstrTmp, *pstrPtr;
pstrTmp=szTmp;
pstrPtr=lpszMsg;
while (pstrPtr && *pstrPtr)
{
// if the current character is a newline and it isn't the
// last character, append the indent string
if (*pstrPtr=='\n' && ContainsNonWhitespace(pstrPtr))
{
*pstrTmp++ = *pstrPtr++;
for (int i=0;i<WiaUiUtil::Min(nStackLevel,20);i++)
{
lstrcpyA(pstrTmp,lpszIndent);
pstrTmp += lstrlenA(lpszIndent);
}
}
// If this is the first character, insert the indent string before the
// first character
else if (pstrPtr == lpszMsg && ContainsNonWhitespace(pstrPtr))
{
for (int i=0;i<WiaUiUtil::Min(nStackLevel,20);i++)
{
lstrcpyA(pstrTmp,lpszIndent);
pstrTmp += lstrlenA(lpszIndent);
}
*pstrTmp++ = *pstrPtr++;
}
else *pstrTmp++ = *pstrPtr++;
}
*pstrTmp = '\0';
lstrcpyA( lpszMsg, szTmp );
}
static void InsertStackLevelIndent( LPWSTR lpszMsg, int nStackLevel )
{
const LPWSTR lpszIndent = L" ";
WCHAR szTmp[1024], *pstrTmp, *pstrPtr;
pstrTmp=szTmp;
pstrPtr=lpszMsg;
while (pstrPtr && *pstrPtr)
{
// if the current character is a newline and it isn't the
// last character, append the indent string
if (*pstrPtr==L'\n' && ContainsNonWhitespace(pstrPtr))
{
*pstrTmp++ = *pstrPtr++;
for (int i=0;i<WiaUiUtil::Min(nStackLevel,20);i++)
{
lstrcpyW(pstrTmp,lpszIndent);
pstrTmp += lstrlenW(lpszIndent);
}
}
// If this is the first character, insert the indent string before the
// first character
else if (pstrPtr == lpszMsg && ContainsNonWhitespace(pstrPtr))
{
for (int i=0;i<WiaUiUtil::Min(nStackLevel,20);i++)
{
lstrcpyW(pstrTmp,lpszIndent);
pstrTmp += lstrlenW(lpszIndent);
}
*pstrTmp++ = *pstrPtr++;
}
else *pstrTmp++ = *pstrPtr++;
}
*pstrTmp = L'\0';
lstrcpyW( lpszMsg, szTmp );
}
static void PrependString( LPTSTR lpszTgt, LPCTSTR lpszStr )
{
if (ContainsNonWhitespace(lpszTgt))
{
int iLen = lstrlen(lpszTgt);
int iThreadIdLen = lstrlen(lpszStr);
LPTSTR lpszTmp = (LPTSTR)LocalAlloc( LPTR, (iLen + iThreadIdLen + 2)*sizeof(TCHAR));
if (lpszTmp)
{
lstrcpy( lpszTmp, lpszStr );
lstrcat( lpszTmp, TEXT(" ") );
lstrcat( lpszTmp, lpszTgt );
lstrcpy( lpszTgt, lpszTmp );
LocalFree(lpszTmp);
}
}
}
static void PrependThreadId( LPTSTR lpszMsg )
{
if (ContainsNonWhitespace(lpszMsg))
{
TCHAR szThreadId[20];
wsprintf( szThreadId, TEXT("[%08X]"), GetCurrentThreadId() );
PrependString( lpszMsg, szThreadId );
}
}
/******************************************************************************
*
* Exported Functions
*
******************************************************************************/
int WINAPI IncrementDebugIndentLevel(void)
{
CProcessGlobalDebugData *pProcessData = CProcessGlobalDebugData::ProcessData();
if (pProcessData && pProcessData->IsValid())
{
CWiaDebugWindowThreadState *pThreadData = reinterpret_cast<CWiaDebugWindowThreadState *>(TlsGetValue(pProcessData->TlsIndex()));
if (pThreadData)
{
return pThreadData->IncrementIndentLevel();
}
}
return 0;
}
int WINAPI DecrementDebugIndentLevel(void)
{
CProcessGlobalDebugData *pProcessData = CProcessGlobalDebugData::ProcessData();
if (pProcessData && pProcessData->IsValid())
{
CWiaDebugWindowThreadState *pThreadData = reinterpret_cast<CWiaDebugWindowThreadState *>(TlsGetValue(pProcessData->TlsIndex()));
if (pThreadData)
{
return pThreadData->DecrementIndentLevel();
}
}
return 0;
}
DWORD WINAPI GetDebugMask(void)
{
CProcessGlobalDebugData *pProcessData = CProcessGlobalDebugData::ProcessData();
if (pProcessData && pProcessData->IsValid())
{
CWiaDebugWindowThreadState *pThreadData = reinterpret_cast<CWiaDebugWindowThreadState *>(TlsGetValue(pProcessData->TlsIndex()));
if (pThreadData)
{
return pThreadData->DebugMask();
}
}
return 0;
}
DWORD WINAPI SetDebugMask( DWORD dwNewMask )
{
CProcessGlobalDebugData *pProcessData = CProcessGlobalDebugData::ProcessData();
if (pProcessData && pProcessData->IsValid())
{
CWiaDebugWindowThreadState *pThreadData = reinterpret_cast<CWiaDebugWindowThreadState *>(TlsGetValue(pProcessData->TlsIndex()));
if (pThreadData)
{
return pThreadData->DebugMask(dwNewMask);
}
}
return 0;
}
BOOL WINAPI PrintDebugMessageW( DWORD dwSeverity, DWORD dwModuleMask, COLORREF crForeground, COLORREF crBackground, LPCWSTR pszModuleName, LPCWSTR pszMsg )
{
BOOL bResult = FALSE;
#ifdef UNICODE
CWiaDebugWindowThreadState *pThreadData = ThreadData();
if (pThreadData && (dwSeverity || IsProcessDebugFlagSet(dwModuleMask)))
{
WCHAR szMsg[1024]=L"";
// Print thread id
wsprintfW( szMsg, L"[%ws-%08X] %ws", pszModuleName, GetCurrentThreadId(), pszMsg );
InsertStackLevelIndent( szMsg, pThreadData->IndentLevel() );
lstrcatW( szMsg, L"\n" );
OutputDebugStringW( szMsg );
// Make sure it is a valid window
if (g_GlobalDebugState.DebugWindow())
{
CDebugStringMessageData DebugStringMessageData;
DebugStringMessageData.crBackground = crBackground;
DebugStringMessageData.crForeground = crForeground;
DebugStringMessageData.bUnicode = TRUE;
lstrcpyW( reinterpret_cast<LPWSTR>(DebugStringMessageData.szString), szMsg );
COPYDATASTRUCT CopyDataStruct;
CopyDataStruct.dwData = COPYDATA_DEBUG_MESSAGE_ID;
CopyDataStruct.cbData = sizeof(DebugStringMessageData);
CopyDataStruct.lpData = &DebugStringMessageData;
g_GlobalDebugState.SendDebugWindowMessage( WM_COPYDATA, 0, reinterpret_cast<LPARAM>(&CopyDataStruct) );
}
bResult = TRUE;
}
#else
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
#endif
return bResult;
}
BOOL WINAPI PrintDebugMessageA( DWORD dwSeverity, DWORD dwModuleMask, COLORREF crForeground, COLORREF crBackground, LPCSTR pszModuleName, LPCSTR pszMsg )
{
BOOL bResult = FALSE;
CWiaDebugWindowThreadState *pThreadData = ThreadData();
if (pThreadData && (dwSeverity || IsProcessDebugFlagSet(dwModuleMask)))
{
CHAR szMsg[1024]="";
// Print thread id
wsprintfA( szMsg, "[%hs-%08X] %hs", pszModuleName, GetCurrentThreadId(), pszMsg );
InsertStackLevelIndent( szMsg, pThreadData->IndentLevel() );
lstrcatA( szMsg, "\n" );
OutputDebugStringA( szMsg );
// Make sure it is a valid window
if (g_GlobalDebugState.DebugWindow())
{
CDebugStringMessageData DebugStringMessageData;
DebugStringMessageData.crBackground = crBackground;
DebugStringMessageData.crForeground = crForeground;
DebugStringMessageData.bUnicode = FALSE;
lstrcpyA( static_cast<LPSTR>(DebugStringMessageData.szString), szMsg );
COPYDATASTRUCT CopyDataStruct;
CopyDataStruct.dwData = COPYDATA_DEBUG_MESSAGE_ID;
CopyDataStruct.cbData = sizeof(DebugStringMessageData);
CopyDataStruct.lpData = &DebugStringMessageData;
g_GlobalDebugState.SendDebugWindowMessage( WM_COPYDATA, 0, reinterpret_cast<LPARAM>(&CopyDataStruct) );
}
bResult = TRUE;
}
return bResult;
}
COLORREF WINAPI AllocateDebugColor(void)
{
DWORD dwIndex = g_GlobalDebugState.AllocateNextColorIndex();
return g_GlobalDebugState.GetColorFromIndex( dwIndex );
}
#define GUID_DEBUG_ENTRY(guid) { &guid, ""#guid }
static const struct
{
const GUID *pGuid;
LPCSTR pszName;
}
s_GuidDebugStrings[] =
{
GUID_DEBUG_ENTRY(IID_IClassFactory),
GUID_DEBUG_ENTRY(IID_ICommDlgBrowser),
GUID_DEBUG_ENTRY(IID_IContextMenu),
GUID_DEBUG_ENTRY(IID_IContextMenu2),
GUID_DEBUG_ENTRY(IID_IDataObject),
GUID_DEBUG_ENTRY(IID_IDropTarget),
GUID_DEBUG_ENTRY(IID_IEnumIDList),
GUID_DEBUG_ENTRY(IID_IExtractIconA),
GUID_DEBUG_ENTRY(IID_IExtractIconW),
GUID_DEBUG_ENTRY(IID_IFileViewerA),
GUID_DEBUG_ENTRY(IID_IFileViewerSite),
GUID_DEBUG_ENTRY(IID_IFileViewerW),
GUID_DEBUG_ENTRY(IID_IMoniker),
GUID_DEBUG_ENTRY(IID_INewShortcutHookA),
GUID_DEBUG_ENTRY(IID_INewShortcutHookW),
GUID_DEBUG_ENTRY(IID_IOleWindow),
GUID_DEBUG_ENTRY(IID_IPersist),
GUID_DEBUG_ENTRY(IID_IPersistFile),
GUID_DEBUG_ENTRY(IID_IPersistFolder),
GUID_DEBUG_ENTRY(IID_IPersistFolder2),
GUID_DEBUG_ENTRY(IID_IPropSheetPage),
GUID_DEBUG_ENTRY(IID_IQueryInfo),
GUID_DEBUG_ENTRY(IID_ISequentialStream),
GUID_DEBUG_ENTRY(IID_IShellBrowser),
GUID_DEBUG_ENTRY(IID_IShellCopyHookA),
GUID_DEBUG_ENTRY(IID_IShellCopyHookW),
GUID_DEBUG_ENTRY(IID_IShellDetails),
GUID_DEBUG_ENTRY(IID_IShellExecuteHookA),
GUID_DEBUG_ENTRY(IID_IShellExecuteHookW),
GUID_DEBUG_ENTRY(IID_IShellExtInit),
GUID_DEBUG_ENTRY(IID_IShellExtInit),
GUID_DEBUG_ENTRY(IID_IShellFolder),
GUID_DEBUG_ENTRY(IID_IShellIcon),
GUID_DEBUG_ENTRY(IID_IShellIconOverlay),
GUID_DEBUG_ENTRY(IID_IShellIconOverlay),
GUID_DEBUG_ENTRY(IID_IShellLinkA),
GUID_DEBUG_ENTRY(IID_IShellLinkW),
GUID_DEBUG_ENTRY(IID_IShellPropSheetExt),
GUID_DEBUG_ENTRY(IID_IShellPropSheetExt),
GUID_DEBUG_ENTRY(IID_IShellView),
GUID_DEBUG_ENTRY(IID_IShellView2),
GUID_DEBUG_ENTRY(IID_IShellView2),
GUID_DEBUG_ENTRY(IID_IStream),
GUID_DEBUG_ENTRY(IID_IUniformResourceLocator),
GUID_DEBUG_ENTRY(IID_IUnknown),
GUID_DEBUG_ENTRY(WiaImgFmt_UNDEFINED),
GUID_DEBUG_ENTRY(WiaImgFmt_MEMORYBMP),
GUID_DEBUG_ENTRY(WiaImgFmt_BMP),
GUID_DEBUG_ENTRY(WiaImgFmt_EMF),
GUID_DEBUG_ENTRY(WiaImgFmt_WMF),
GUID_DEBUG_ENTRY(WiaImgFmt_JPEG),
GUID_DEBUG_ENTRY(WiaImgFmt_PNG),
GUID_DEBUG_ENTRY(WiaImgFmt_GIF),
GUID_DEBUG_ENTRY(WiaImgFmt_TIFF),
GUID_DEBUG_ENTRY(WiaImgFmt_EXIF),
GUID_DEBUG_ENTRY(WiaImgFmt_PHOTOCD),
GUID_DEBUG_ENTRY(WiaImgFmt_FLASHPIX),
GUID_DEBUG_ENTRY(WiaImgFmt_ICO),
GUID_DEBUG_ENTRY(WiaImgFmt_CIFF),
GUID_DEBUG_ENTRY(WiaImgFmt_PICT),
GUID_DEBUG_ENTRY(WiaImgFmt_JPEG2K),
GUID_DEBUG_ENTRY(WiaImgFmt_JPEG2KX),
GUID_DEBUG_ENTRY(WiaImgFmt_RTF),
GUID_DEBUG_ENTRY(WiaImgFmt_XML),
GUID_DEBUG_ENTRY(WiaImgFmt_HTML),
GUID_DEBUG_ENTRY(WiaImgFmt_TXT),
GUID_DEBUG_ENTRY(WiaImgFmt_MPG),
GUID_DEBUG_ENTRY(WiaImgFmt_AVI),
GUID_DEBUG_ENTRY(WiaImgFmt_ASF),
GUID_DEBUG_ENTRY(WiaImgFmt_SCRIPT),
GUID_DEBUG_ENTRY(WiaImgFmt_EXEC),
GUID_DEBUG_ENTRY(WiaImgFmt_UNICODE16),
GUID_DEBUG_ENTRY(WiaImgFmt_DPOF),
GUID_DEBUG_ENTRY(WiaAudFmt_WAV),
GUID_DEBUG_ENTRY(WiaAudFmt_MP3),
GUID_DEBUG_ENTRY(WiaAudFmt_AIFF),
GUID_DEBUG_ENTRY(WiaAudFmt_WMA),
GUID_DEBUG_ENTRY(WIA_EVENT_DEVICE_DISCONNECTED),
GUID_DEBUG_ENTRY(WIA_EVENT_DEVICE_CONNECTED),
GUID_DEBUG_ENTRY(WIA_EVENT_ITEM_DELETED),
GUID_DEBUG_ENTRY(WIA_EVENT_ITEM_CREATED),
GUID_DEBUG_ENTRY(WIA_EVENT_TREE_UPDATED),
GUID_DEBUG_ENTRY(WIA_EVENT_VOLUME_INSERT),
GUID_DEBUG_ENTRY(WIA_EVENT_SCAN_IMAGE),
GUID_DEBUG_ENTRY(WIA_EVENT_SCAN_PRINT_IMAGE),
GUID_DEBUG_ENTRY(WIA_EVENT_SCAN_FAX_IMAGE),
GUID_DEBUG_ENTRY(WIA_EVENT_STORAGE_CREATED),
GUID_DEBUG_ENTRY(WIA_EVENT_STORAGE_DELETED),
GUID_DEBUG_ENTRY(WIA_EVENT_STI_PROXY),
GUID_DEBUG_ENTRY(WIA_EVENT_HANDLER_NO_ACTION),
GUID_DEBUG_ENTRY(WIA_EVENT_HANDLER_PROMPT),
GUID_DEBUG_ENTRY(WIA_CMD_SYNCHRONIZE),
GUID_DEBUG_ENTRY(WIA_CMD_TAKE_PICTURE),
GUID_DEBUG_ENTRY(WIA_CMD_DELETE_ALL_ITEMS),
GUID_DEBUG_ENTRY(WIA_CMD_CHANGE_DOCUMENT),
GUID_DEBUG_ENTRY(WIA_CMD_UNLOAD_DOCUMENT),
GUID_DEBUG_ENTRY(WIA_CMD_DIAGNOSTIC),
GUID_DEBUG_ENTRY(WIA_CMD_DELETE_DEVICE_TREE),
GUID_DEBUG_ENTRY(WIA_CMD_BUILD_DEVICE_TREE),
GUID_DEBUG_ENTRY(IID_IWiaDevMgr),
GUID_DEBUG_ENTRY(IID_IEnumWIA_DEV_INFO),
GUID_DEBUG_ENTRY(IID_IWiaEventCallback),
GUID_DEBUG_ENTRY(IID_IWiaDataCallback),
GUID_DEBUG_ENTRY(IID_IWiaDataTransfer),
GUID_DEBUG_ENTRY(IID_IWiaItem),
GUID_DEBUG_ENTRY(IID_IWiaPropertyStorage),
GUID_DEBUG_ENTRY(IID_IEnumWiaItem),
GUID_DEBUG_ENTRY(IID_IEnumWIA_DEV_CAPS),
GUID_DEBUG_ENTRY(IID_IEnumWIA_FORMAT_INFO),
GUID_DEBUG_ENTRY(IID_IWiaLog),
GUID_DEBUG_ENTRY(IID_IWiaLogEx),
GUID_DEBUG_ENTRY(IID_IWiaNotifyDevMgr),
GUID_DEBUG_ENTRY(LIBID_WiaDevMgr),
GUID_DEBUG_ENTRY(CLSID_WiaDevMgr),
GUID_DEBUG_ENTRY(CLSID_WiaLog),
GUID_DEBUG_ENTRY(IID_IExtractImage2),
GUID_DEBUG_ENTRY(IID_IExtractImage),
GUID_DEBUG_ENTRY(IID_IShellDetails3),
GUID_DEBUG_ENTRY(IID_IShellFolder2)
};
#define GUID_DEBUG_MAP_SIZE (sizeof(s_GuidDebugStrings)/sizeof(s_GuidDebugStrings[0]))
BOOL WINAPI GetStringFromGuidA( const IID *pGuid, LPSTR pszString, int nMaxLen )
{
if (!pGuid || !pszString || !nMaxLen)
return FALSE;
for (int i=0;i<GUID_DEBUG_MAP_SIZE;i++)
{
if (*pGuid == *s_GuidDebugStrings[i].pGuid)
{
lstrcpynA( pszString, s_GuidDebugStrings[i].pszName, nMaxLen );
return TRUE;
}
}
LPOLESTR pszGuid = NULL;
HRESULT hr = StringFromCLSID( *pGuid, &pszGuid );
if (SUCCEEDED(hr))
{
if (pszGuid)
{
CSimpleStringAnsi strGuid = CSimpleStringConvert::AnsiString(CSimpleStringWide(pszGuid));
lstrcpynA( pszString, strGuid, nMaxLen );
CoTaskMemFree(pszGuid);
return TRUE;
}
}
return FALSE;
}
BOOL WINAPI GetStringFromGuidW( const IID *pGuid, LPWSTR pszString, int nMaxLen )
{
BOOL bResult = FALSE;
#ifdef UNICODE
if (!pGuid || !pszString || !nMaxLen)
return FALSE;
CHAR szGuid[MAX_PATH];
if (!GetStringFromGuidA(pGuid,szGuid,MAX_PATH))
return FALSE;
lstrcpynW( pszString, CSimpleStringConvert::WideString(CSimpleStringAnsi(szGuid)), nMaxLen );
bResult = TRUE;
#else
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
#endif
return bResult;
}
#define MSG_DEBUG_ENTRY(msg) { msg, ""#msg }
static const struct
{
UINT uMsg;
LPCSTR pszName;
}
s_MsgDebugStrings[] =
{
MSG_DEBUG_ENTRY(BM_CLICK),
MSG_DEBUG_ENTRY(BM_GETCHECK),
MSG_DEBUG_ENTRY(BM_GETIMAGE),
MSG_DEBUG_ENTRY(BM_GETSTATE),
MSG_DEBUG_ENTRY(BM_SETCHECK),
MSG_DEBUG_ENTRY(BM_SETIMAGE),
MSG_DEBUG_ENTRY(BM_SETSTATE),
MSG_DEBUG_ENTRY(BM_SETSTYLE),
MSG_DEBUG_ENTRY(CB_ADDSTRING),
MSG_DEBUG_ENTRY(CB_DELETESTRING),
MSG_DEBUG_ENTRY(CB_DIR),
MSG_DEBUG_ENTRY(CB_FINDSTRING),
MSG_DEBUG_ENTRY(CB_FINDSTRINGEXACT),
MSG_DEBUG_ENTRY(CB_GETCOMBOBOXINFO),
MSG_DEBUG_ENTRY(CB_GETCOUNT),
MSG_DEBUG_ENTRY(CB_GETCURSEL),
MSG_DEBUG_ENTRY(CB_GETDROPPEDCONTROLRECT),
MSG_DEBUG_ENTRY(CB_GETDROPPEDSTATE),
MSG_DEBUG_ENTRY(CB_GETEDITSEL),
MSG_DEBUG_ENTRY(CB_GETEXTENDEDUI),
MSG_DEBUG_ENTRY(CB_GETITEMDATA),
MSG_DEBUG_ENTRY(CB_GETITEMHEIGHT),
MSG_DEBUG_ENTRY(CB_GETLBTEXT),
MSG_DEBUG_ENTRY(CB_GETLBTEXTLEN),
MSG_DEBUG_ENTRY(CB_GETLOCALE),
MSG_DEBUG_ENTRY(CB_INITSTORAGE),
MSG_DEBUG_ENTRY(CB_INSERTSTRING),
MSG_DEBUG_ENTRY(CB_LIMITTEXT),
MSG_DEBUG_ENTRY(CB_MSGMAX),
MSG_DEBUG_ENTRY(CB_MSGMAX),
MSG_DEBUG_ENTRY(CB_MSGMAX),
MSG_DEBUG_ENTRY(CB_MSGMAX),
MSG_DEBUG_ENTRY(CB_RESETCONTENT),
MSG_DEBUG_ENTRY(CB_SELECTSTRING),
MSG_DEBUG_ENTRY(CB_SETCURSEL),
MSG_DEBUG_ENTRY(CB_SETDROPPEDWIDTH),
MSG_DEBUG_ENTRY(CB_SETEDITSEL),
MSG_DEBUG_ENTRY(CB_SETEXTENDEDUI),
MSG_DEBUG_ENTRY(CB_SETITEMDATA),
MSG_DEBUG_ENTRY(CB_SETITEMHEIGHT),
MSG_DEBUG_ENTRY(CB_SETLOCALE),
MSG_DEBUG_ENTRY(CB_SHOWDROPDOWN),
MSG_DEBUG_ENTRY(EM_CANUNDO),
MSG_DEBUG_ENTRY(EM_CHARFROMPOS),
MSG_DEBUG_ENTRY(EM_EMPTYUNDOBUFFER),
MSG_DEBUG_ENTRY(EM_FMTLINES),
MSG_DEBUG_ENTRY(EM_GETFIRSTVISIBLELINE),
MSG_DEBUG_ENTRY(EM_GETHANDLE),
MSG_DEBUG_ENTRY(EM_GETIMESTATUS),
MSG_DEBUG_ENTRY(EM_GETLIMITTEXT),
MSG_DEBUG_ENTRY(EM_GETLINE),
MSG_DEBUG_ENTRY(EM_GETLINECOUNT),
MSG_DEBUG_ENTRY(EM_GETMARGINS),
MSG_DEBUG_ENTRY(EM_GETMODIFY),
MSG_DEBUG_ENTRY(EM_GETPASSWORDCHAR),
MSG_DEBUG_ENTRY(EM_GETRECT),
MSG_DEBUG_ENTRY(EM_GETSEL),
MSG_DEBUG_ENTRY(EM_GETTHUMB),
MSG_DEBUG_ENTRY(EM_GETWORDBREAKPROC),
MSG_DEBUG_ENTRY(EM_LIMITTEXT),
MSG_DEBUG_ENTRY(EM_LINEFROMCHAR),
MSG_DEBUG_ENTRY(EM_LINEINDEX),
MSG_DEBUG_ENTRY(EM_LINELENGTH),
MSG_DEBUG_ENTRY(EM_LINESCROLL),
MSG_DEBUG_ENTRY(EM_POSFROMCHAR),
MSG_DEBUG_ENTRY(EM_REPLACESEL),
MSG_DEBUG_ENTRY(EM_SCROLL),
MSG_DEBUG_ENTRY(EM_SCROLLCARET),
MSG_DEBUG_ENTRY(EM_SETHANDLE),
MSG_DEBUG_ENTRY(EM_SETIMESTATUS),
MSG_DEBUG_ENTRY(EM_SETMARGINS),
MSG_DEBUG_ENTRY(EM_SETMODIFY),
MSG_DEBUG_ENTRY(EM_SETPASSWORDCHAR),
MSG_DEBUG_ENTRY(EM_SETREADONLY),
MSG_DEBUG_ENTRY(EM_SETRECT),
MSG_DEBUG_ENTRY(EM_SETRECTNP),
MSG_DEBUG_ENTRY(EM_SETSEL),
MSG_DEBUG_ENTRY(EM_SETTABSTOPS),
MSG_DEBUG_ENTRY(EM_SETWORDBREAKPROC),
MSG_DEBUG_ENTRY(EM_UNDO),
MSG_DEBUG_ENTRY(LB_ADDFILE),
MSG_DEBUG_ENTRY(LB_ADDSTRING),
MSG_DEBUG_ENTRY(LB_DELETESTRING),
MSG_DEBUG_ENTRY(LB_DIR),
MSG_DEBUG_ENTRY(LB_FINDSTRING),
MSG_DEBUG_ENTRY(LB_FINDSTRINGEXACT),
MSG_DEBUG_ENTRY(LB_GETANCHORINDEX),
MSG_DEBUG_ENTRY(LB_GETCARETINDEX),
MSG_DEBUG_ENTRY(LB_GETCOUNT),
MSG_DEBUG_ENTRY(LB_GETCURSEL),
MSG_DEBUG_ENTRY(LB_GETHORIZONTALEXTENT),
MSG_DEBUG_ENTRY(LB_GETITEMDATA),
MSG_DEBUG_ENTRY(LB_GETITEMHEIGHT),
MSG_DEBUG_ENTRY(LB_GETITEMRECT),
MSG_DEBUG_ENTRY(LB_GETLISTBOXINFO),
MSG_DEBUG_ENTRY(LB_GETLOCALE),
MSG_DEBUG_ENTRY(LB_GETSEL),
MSG_DEBUG_ENTRY(LB_GETSELCOUNT),
MSG_DEBUG_ENTRY(LB_GETSELITEMS),
MSG_DEBUG_ENTRY(LB_GETTEXT),
MSG_DEBUG_ENTRY(LB_GETTEXTLEN),
MSG_DEBUG_ENTRY(LB_GETTOPINDEX),
MSG_DEBUG_ENTRY(LB_INITSTORAGE),
MSG_DEBUG_ENTRY(LB_INSERTSTRING),
MSG_DEBUG_ENTRY(LB_ITEMFROMPOINT),
MSG_DEBUG_ENTRY(LB_MSGMAX),
MSG_DEBUG_ENTRY(LB_MSGMAX),
MSG_DEBUG_ENTRY(LB_MSGMAX),
MSG_DEBUG_ENTRY(LB_MSGMAX),
MSG_DEBUG_ENTRY(LB_RESETCONTENT),
MSG_DEBUG_ENTRY(LB_SELECTSTRING),
MSG_DEBUG_ENTRY(LB_SELITEMRANGE),
MSG_DEBUG_ENTRY(LB_SELITEMRANGEEX),
MSG_DEBUG_ENTRY(LB_SETANCHORINDEX),
MSG_DEBUG_ENTRY(LB_SETCARETINDEX),
MSG_DEBUG_ENTRY(LB_SETCOLUMNWIDTH),
MSG_DEBUG_ENTRY(LB_SETCOUNT),
MSG_DEBUG_ENTRY(LB_SETCURSEL),
MSG_DEBUG_ENTRY(LB_SETHORIZONTALEXTENT),
MSG_DEBUG_ENTRY(LB_SETITEMDATA),
MSG_DEBUG_ENTRY(LB_SETITEMHEIGHT),
MSG_DEBUG_ENTRY(LB_SETLOCALE),
MSG_DEBUG_ENTRY(LB_SETSEL),
MSG_DEBUG_ENTRY(LB_SETTABSTOPS),
MSG_DEBUG_ENTRY(LB_SETTOPINDEX),
MSG_DEBUG_ENTRY(PBT_APMBATTERYLOW),
MSG_DEBUG_ENTRY(PBT_APMOEMEVENT),
MSG_DEBUG_ENTRY(PBT_APMPOWERSTATUSCHANGE),
MSG_DEBUG_ENTRY(PBT_APMQUERYSTANDBY),
MSG_DEBUG_ENTRY(PBT_APMQUERYSTANDBYFAILED),
MSG_DEBUG_ENTRY(PBT_APMQUERYSUSPEND),
MSG_DEBUG_ENTRY(PBT_APMQUERYSUSPENDFAILED),
MSG_DEBUG_ENTRY(PBT_APMRESUMEAUTOMATIC),
MSG_DEBUG_ENTRY(PBT_APMRESUMECRITICAL),
MSG_DEBUG_ENTRY(PBT_APMRESUMESTANDBY),
MSG_DEBUG_ENTRY(PBT_APMRESUMESUSPEND),
MSG_DEBUG_ENTRY(PBT_APMSTANDBY),
MSG_DEBUG_ENTRY(PBT_APMSUSPEND),
MSG_DEBUG_ENTRY(SBM_GETSCROLLBARINFO),
MSG_DEBUG_ENTRY(SBM_GETSCROLLINFO),
MSG_DEBUG_ENTRY(SBM_SETSCROLLINFO),
MSG_DEBUG_ENTRY(STM_GETICON),
MSG_DEBUG_ENTRY(STM_GETIMAGE),
MSG_DEBUG_ENTRY(STM_MSGMAX),
MSG_DEBUG_ENTRY(STM_SETICON),
MSG_DEBUG_ENTRY(STM_SETIMAGE),
MSG_DEBUG_ENTRY(WM_ACTIVATE),
MSG_DEBUG_ENTRY(WM_ACTIVATEAPP),
MSG_DEBUG_ENTRY(WM_APP),
MSG_DEBUG_ENTRY(WM_APPCOMMAND),
MSG_DEBUG_ENTRY(WM_ASKCBFORMATNAME),
MSG_DEBUG_ENTRY(WM_CANCELJOURNAL),
MSG_DEBUG_ENTRY(WM_CANCELMODE),
MSG_DEBUG_ENTRY(WM_CAPTURECHANGED),
MSG_DEBUG_ENTRY(WM_CHANGECBCHAIN),
MSG_DEBUG_ENTRY(WM_CHANGEUISTATE),
MSG_DEBUG_ENTRY(WM_CHAR),
MSG_DEBUG_ENTRY(WM_CHARTOITEM),
MSG_DEBUG_ENTRY(WM_CHILDACTIVATE),
MSG_DEBUG_ENTRY(WM_CLEAR),
MSG_DEBUG_ENTRY(WM_CLOSE),
MSG_DEBUG_ENTRY(WM_COMMAND),
MSG_DEBUG_ENTRY(WM_COMPACTING),
MSG_DEBUG_ENTRY(WM_COMPAREITEM),
MSG_DEBUG_ENTRY(WM_CONTEXTMENU),
MSG_DEBUG_ENTRY(WM_COPY),
MSG_DEBUG_ENTRY(WM_COPYDATA),
MSG_DEBUG_ENTRY(WM_CREATE),
MSG_DEBUG_ENTRY(WM_CTLCOLORBTN),
MSG_DEBUG_ENTRY(WM_CTLCOLORDLG),
MSG_DEBUG_ENTRY(WM_CTLCOLOREDIT),
MSG_DEBUG_ENTRY(WM_CTLCOLORLISTBOX),
MSG_DEBUG_ENTRY(WM_CTLCOLORMSGBOX),
MSG_DEBUG_ENTRY(WM_CTLCOLORSCROLLBAR),
MSG_DEBUG_ENTRY(WM_CTLCOLORSTATIC),
MSG_DEBUG_ENTRY(WM_CUT),
MSG_DEBUG_ENTRY(WM_DEADCHAR),
MSG_DEBUG_ENTRY(WM_DELETEITEM),
MSG_DEBUG_ENTRY(WM_DESTROY),
MSG_DEBUG_ENTRY(WM_DESTROYCLIPBOARD),
MSG_DEBUG_ENTRY(WM_DEVICECHANGE),
MSG_DEBUG_ENTRY(WM_DEVMODECHANGE),
MSG_DEBUG_ENTRY(WM_DISPLAYCHANGE),
MSG_DEBUG_ENTRY(WM_DRAWCLIPBOARD),
MSG_DEBUG_ENTRY(WM_DRAWITEM),
MSG_DEBUG_ENTRY(WM_DROPFILES),
MSG_DEBUG_ENTRY(WM_ENABLE),
MSG_DEBUG_ENTRY(WM_ENDSESSION),
MSG_DEBUG_ENTRY(WM_ENTERIDLE),
MSG_DEBUG_ENTRY(WM_ENTERMENULOOP),
MSG_DEBUG_ENTRY(WM_ENTERSIZEMOVE),
MSG_DEBUG_ENTRY(WM_ERASEBKGND),
MSG_DEBUG_ENTRY(WM_EXITMENULOOP),
MSG_DEBUG_ENTRY(WM_EXITSIZEMOVE),
MSG_DEBUG_ENTRY(WM_FONTCHANGE),
MSG_DEBUG_ENTRY(WM_GETDLGCODE),
MSG_DEBUG_ENTRY(WM_GETFONT),
MSG_DEBUG_ENTRY(WM_GETHOTKEY),
MSG_DEBUG_ENTRY(WM_GETICON),
MSG_DEBUG_ENTRY(WM_GETMINMAXINFO),
MSG_DEBUG_ENTRY(WM_GETOBJECT),
MSG_DEBUG_ENTRY(WM_GETTEXT),
MSG_DEBUG_ENTRY(WM_GETTEXTLENGTH),
MSG_DEBUG_ENTRY(WM_HELP),
MSG_DEBUG_ENTRY(WM_HOTKEY),
MSG_DEBUG_ENTRY(WM_HSCROLL),
MSG_DEBUG_ENTRY(WM_HSCROLLCLIPBOARD),
MSG_DEBUG_ENTRY(WM_ICONERASEBKGND),
MSG_DEBUG_ENTRY(WM_IME_CHAR),
MSG_DEBUG_ENTRY(WM_IME_COMPOSITION),
MSG_DEBUG_ENTRY(WM_IME_COMPOSITIONFULL),
MSG_DEBUG_ENTRY(WM_IME_CONTROL),
MSG_DEBUG_ENTRY(WM_IME_ENDCOMPOSITION),
MSG_DEBUG_ENTRY(WM_IME_KEYDOWN),
MSG_DEBUG_ENTRY(WM_IME_KEYLAST),
MSG_DEBUG_ENTRY(WM_IME_KEYUP),
MSG_DEBUG_ENTRY(WM_IME_NOTIFY),
MSG_DEBUG_ENTRY(WM_IME_REQUEST),
MSG_DEBUG_ENTRY(WM_IME_SELECT),
MSG_DEBUG_ENTRY(WM_IME_SETCONTEXT),
MSG_DEBUG_ENTRY(WM_IME_STARTCOMPOSITION),
MSG_DEBUG_ENTRY(WM_INITDIALOG),
MSG_DEBUG_ENTRY(WM_INITMENU),
MSG_DEBUG_ENTRY(WM_INITMENUPOPUP),
MSG_DEBUG_ENTRY(WM_INPUT),
MSG_DEBUG_ENTRY(WM_INPUTLANGCHANGE),
MSG_DEBUG_ENTRY(WM_INPUTLANGCHANGEREQUEST),
MSG_DEBUG_ENTRY(WM_KEYDOWN),
MSG_DEBUG_ENTRY(WM_KEYUP),
MSG_DEBUG_ENTRY(WM_KILLFOCUS),
MSG_DEBUG_ENTRY(WM_LBUTTONDBLCLK),
MSG_DEBUG_ENTRY(WM_LBUTTONDOWN),
MSG_DEBUG_ENTRY(WM_LBUTTONUP),
MSG_DEBUG_ENTRY(WM_MBUTTONDBLCLK),
MSG_DEBUG_ENTRY(WM_MBUTTONDOWN),
MSG_DEBUG_ENTRY(WM_MBUTTONUP),
MSG_DEBUG_ENTRY(WM_MDIACTIVATE),
MSG_DEBUG_ENTRY(WM_MDICASCADE),
MSG_DEBUG_ENTRY(WM_MDICREATE),
MSG_DEBUG_ENTRY(WM_MDIDESTROY),
MSG_DEBUG_ENTRY(WM_MDIGETACTIVE),
MSG_DEBUG_ENTRY(WM_MDIICONARRANGE),
MSG_DEBUG_ENTRY(WM_MDIMAXIMIZE),
MSG_DEBUG_ENTRY(WM_MDINEXT),
MSG_DEBUG_ENTRY(WM_MDIREFRESHMENU),
MSG_DEBUG_ENTRY(WM_MDIRESTORE),
MSG_DEBUG_ENTRY(WM_MDISETMENU),
MSG_DEBUG_ENTRY(WM_MDITILE),
MSG_DEBUG_ENTRY(WM_MEASUREITEM),
MSG_DEBUG_ENTRY(WM_MENUCHAR),
MSG_DEBUG_ENTRY(WM_MENUCOMMAND),
MSG_DEBUG_ENTRY(WM_MENUDRAG),
MSG_DEBUG_ENTRY(WM_MENUGETOBJECT),
MSG_DEBUG_ENTRY(WM_MENURBUTTONUP),
MSG_DEBUG_ENTRY(WM_MENUSELECT),
MSG_DEBUG_ENTRY(WM_MOUSEACTIVATE),
MSG_DEBUG_ENTRY(WM_MOUSEHOVER),
MSG_DEBUG_ENTRY(WM_MOUSELEAVE),
MSG_DEBUG_ENTRY(WM_MOUSEMOVE),
MSG_DEBUG_ENTRY(WM_MOUSEWHEEL),
MSG_DEBUG_ENTRY(WM_MOVE),
MSG_DEBUG_ENTRY(WM_MOVING),
MSG_DEBUG_ENTRY(WM_NCACTIVATE),
MSG_DEBUG_ENTRY(WM_NCCALCSIZE),
MSG_DEBUG_ENTRY(WM_NCCREATE),
MSG_DEBUG_ENTRY(WM_NCDESTROY),
MSG_DEBUG_ENTRY(WM_NCHITTEST),
MSG_DEBUG_ENTRY(WM_NCLBUTTONDBLCLK),
MSG_DEBUG_ENTRY(WM_NCLBUTTONDOWN),
MSG_DEBUG_ENTRY(WM_NCLBUTTONUP),
MSG_DEBUG_ENTRY(WM_NCMBUTTONDBLCLK),
MSG_DEBUG_ENTRY(WM_NCMBUTTONDOWN),
MSG_DEBUG_ENTRY(WM_NCMBUTTONUP),
MSG_DEBUG_ENTRY(WM_NCMOUSEHOVER),
MSG_DEBUG_ENTRY(WM_NCMOUSELEAVE),
MSG_DEBUG_ENTRY(WM_NCMOUSEMOVE),
MSG_DEBUG_ENTRY(WM_NCPAINT),
MSG_DEBUG_ENTRY(WM_NCRBUTTONDBLCLK),
MSG_DEBUG_ENTRY(WM_NCRBUTTONDOWN),
MSG_DEBUG_ENTRY(WM_NCRBUTTONUP),
MSG_DEBUG_ENTRY(WM_NCXBUTTONDBLCLK),
MSG_DEBUG_ENTRY(WM_NCXBUTTONDOWN),
MSG_DEBUG_ENTRY(WM_NCXBUTTONUP),
MSG_DEBUG_ENTRY(WM_NEXTDLGCTL),
MSG_DEBUG_ENTRY(WM_NEXTMENU),
MSG_DEBUG_ENTRY(WM_NOTIFY),
MSG_DEBUG_ENTRY(WM_NOTIFYFORMAT),
MSG_DEBUG_ENTRY(WM_NULL),
MSG_DEBUG_ENTRY(WM_PAINT),
MSG_DEBUG_ENTRY(WM_PAINTCLIPBOARD),
MSG_DEBUG_ENTRY(WM_PAINTICON),
MSG_DEBUG_ENTRY(WM_PALETTECHANGED),
MSG_DEBUG_ENTRY(WM_PALETTEISCHANGING),
MSG_DEBUG_ENTRY(WM_PARENTNOTIFY),
MSG_DEBUG_ENTRY(WM_PASTE),
MSG_DEBUG_ENTRY(WM_POWER),
MSG_DEBUG_ENTRY(WM_POWERBROADCAST),
MSG_DEBUG_ENTRY(WM_PRINT),
MSG_DEBUG_ENTRY(WM_PRINTCLIENT),
MSG_DEBUG_ENTRY(WM_QUERYDRAGICON),
MSG_DEBUG_ENTRY(WM_QUERYENDSESSION),
MSG_DEBUG_ENTRY(WM_QUERYNEWPALETTE),
MSG_DEBUG_ENTRY(WM_QUERYOPEN),
MSG_DEBUG_ENTRY(WM_QUERYUISTATE),
MSG_DEBUG_ENTRY(WM_QUEUESYNC),
MSG_DEBUG_ENTRY(WM_QUIT),
MSG_DEBUG_ENTRY(WM_RBUTTONDBLCLK),
MSG_DEBUG_ENTRY(WM_RBUTTONDOWN),
MSG_DEBUG_ENTRY(WM_RBUTTONUP),
MSG_DEBUG_ENTRY(WM_RENDERALLFORMATS),
MSG_DEBUG_ENTRY(WM_RENDERFORMAT),
MSG_DEBUG_ENTRY(WM_SETCURSOR),
MSG_DEBUG_ENTRY(WM_SETFOCUS),
MSG_DEBUG_ENTRY(WM_SETFONT),
MSG_DEBUG_ENTRY(WM_SETHOTKEY),
MSG_DEBUG_ENTRY(WM_SETICON),
MSG_DEBUG_ENTRY(WM_SETREDRAW),
MSG_DEBUG_ENTRY(WM_SETTEXT),
MSG_DEBUG_ENTRY(WM_SHOWWINDOW),
MSG_DEBUG_ENTRY(WM_SIZE),
MSG_DEBUG_ENTRY(WM_SIZECLIPBOARD),
MSG_DEBUG_ENTRY(WM_SIZING),
MSG_DEBUG_ENTRY(WM_SPOOLERSTATUS),
MSG_DEBUG_ENTRY(WM_STYLECHANGED),
MSG_DEBUG_ENTRY(WM_STYLECHANGING),
MSG_DEBUG_ENTRY(WM_SYNCPAINT),
MSG_DEBUG_ENTRY(WM_SYSCHAR),
MSG_DEBUG_ENTRY(WM_SYSCOLORCHANGE),
MSG_DEBUG_ENTRY(WM_SYSCOMMAND),
MSG_DEBUG_ENTRY(WM_SYSDEADCHAR),
MSG_DEBUG_ENTRY(WM_SYSKEYDOWN),
MSG_DEBUG_ENTRY(WM_SYSKEYUP),
MSG_DEBUG_ENTRY(WM_TCARD),
MSG_DEBUG_ENTRY(WM_THEMECHANGED),
MSG_DEBUG_ENTRY(WM_TIMECHANGE),
MSG_DEBUG_ENTRY(WM_TIMER),
MSG_DEBUG_ENTRY(WM_UNDO),
MSG_DEBUG_ENTRY(WM_UNICHAR),
MSG_DEBUG_ENTRY(WM_UNINITMENUPOPUP),
MSG_DEBUG_ENTRY(WM_UPDATEUISTATE),
MSG_DEBUG_ENTRY(WM_USER),
MSG_DEBUG_ENTRY(WM_USERCHANGED),
MSG_DEBUG_ENTRY(WM_VKEYTOITEM),
MSG_DEBUG_ENTRY(WM_VSCROLL),
MSG_DEBUG_ENTRY(WM_VSCROLLCLIPBOARD),
MSG_DEBUG_ENTRY(WM_WINDOWPOSCHANGED),
MSG_DEBUG_ENTRY(WM_WINDOWPOSCHANGING),
MSG_DEBUG_ENTRY(WM_WININICHANGE),
MSG_DEBUG_ENTRY(WM_WTSSESSION_CHANGE),
MSG_DEBUG_ENTRY(WM_XBUTTONDBLCLK),
MSG_DEBUG_ENTRY(WM_XBUTTONDOWN),
MSG_DEBUG_ENTRY(WM_XBUTTONUP)
};
#define MSG_DEBUG_MAP_SIZE (sizeof(s_MsgDebugStrings)/sizeof(s_MsgDebugStrings[0]))
BOOL WINAPI GetStringFromMsgA( UINT uMsg, LPSTR pszString, int nMaxLen )
{
if (!pszString || !nMaxLen)
{
return FALSE;
}
for (int i=0;i<MSG_DEBUG_MAP_SIZE;i++)
{
if (uMsg == s_MsgDebugStrings[i].uMsg)
{
lstrcpynA( pszString, s_MsgDebugStrings[i].pszName, nMaxLen );
return TRUE;
}
}
lstrcpynA( pszString, CSimpleStringAnsi().Format("Unknown Message: 0x%08X", uMsg ), nMaxLen );
return TRUE;
}
BOOL WINAPI GetStringFromMsgW( UINT uMsg, LPWSTR pszString, int nMaxLen )
{
BOOL bResult = FALSE;
#ifdef UNICODE
if (!pszString || !nMaxLen)
{
return FALSE;
}
CHAR szMessage[MAX_PATH];
if (!GetStringFromMsgA(uMsg,szMessage,MAX_PATH))
{
return FALSE;
}
lstrcpynW( pszString, CSimpleStringConvert::WideString(CSimpleStringAnsi(szMessage)), nMaxLen );
bResult = TRUE;
#else
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
#endif
return bResult;
}
VOID WINAPI DoRecordAllocation( LPVOID pv, size_t Size )
{
if (pv)
{
CProcessGlobalDebugData *pProcessData = CProcessGlobalDebugData::ProcessData();
if (pProcessData && pProcessData->IsValid())
{
pProcessData->DoRecordAllocation( pv, Size );
}
}
}
VOID WINAPI DoRecordFree( LPVOID pv )
{
if (pv)
{
CProcessGlobalDebugData *pProcessData = CProcessGlobalDebugData::ProcessData();
if (pProcessData && pProcessData->IsValid())
{
pProcessData->DoRecordFree( pv );
}
}
}
VOID WINAPI DoReportLeaks( LPTSTR pszModuleName )
{
if (pszModuleName)
{
CProcessGlobalDebugData *pProcessData = CProcessGlobalDebugData::ProcessData();
if (pProcessData && pProcessData->IsValid())
{
pProcessData->GenerateLeakReport( pszModuleName );
}
}
}