DragonNest/Common/Utility/ExceptionReport.cpp

957 lines
33 KiB
C++
Raw Permalink Normal View History

///////////////////////////////////////////////////////////////////
// INCLUDE
///////////////////////////////////////////////////////////////////
#include "STDAFX.H"
#include "EXCEPTIONREPORT.H"
#include "TIMESET.H"
#include "COMMONMACROS.H"
#include "BASESET.H"
#include "DEBUGUTIL.H"
#include "SAFESTRINGMACROS.H"
#include "SundriesFunc.h"
///////////////////////////////////////////////////////////////////
// IMPLEMENTATION
///////////////////////////////////////////////////////////////////
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
DEFINE_SINGLETON_CLASS(CExceptionReport);
// <20>߸<EFBFBD><DFB8><EFBFBD> STL Container index <20><><EFBFBD><EFBFBD>
static void myInvalidParameterHandler(const wchar_t* expression,
const wchar_t* function,
const wchar_t* file,
unsigned int line,
uintptr_t pReserved)
{
RaiseException( EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE , 0, 0);
}
// <20>߸<EFBFBD><DFB8><EFBFBD> Pure virtual function call
static void myPurecallHandler()
{
RaiseException( EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE , 0, 0);
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CExceptionReport::CExceptionReport
//*---------------------------------------------------------------
// DESC : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// PARM : N/A
// RETV : N/A
// PRGM : B4nFter
//*---------------------------------------------------------------
CExceptionReport::CExceptionReport() : m_MiniDumpType(MiniDumpNormal), m_bDoSetFilter(TRUE), m_bDoCallStack(TRUE), m_InitSymbolEngine(FALSE), m_lpfnOutputLogProc(NULL), m_lpOutputLogProcParam(NULL), m_bIsDumping(false)
{
#if defined(_X86_)
m_MachineType = IMAGE_FILE_MACHINE_I386;
#elif defined(_AMD64_)
m_MachineType = IMAGE_FILE_MACHINE_AMD64;
#elif defined(_IA64_)
m_MachineType = IMAGE_FILE_MACHINE_IA64;
#else // !_X86 && !_AMD64_ && !_IA64_
#pragma FORCE COMPILE ABORT!
#endif // !_X86 && !_AMD64_ && !_IA64_
::memset(m_szText, 0, sizeof(m_szText));
::memset(m_szExceptionDesc, 0, sizeof(m_szExceptionDesc));
::memset(m_btSymbol, 0, sizeof(m_btSymbol));
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CExceptionReport::~CExceptionReport
//*---------------------------------------------------------------
// DESC : <20>Ҹ<EFBFBD><D2B8><EFBFBD>
// PARM : N/A
// RETV : N/A
// PRGM : B4nFter
//*---------------------------------------------------------------
CExceptionReport::~CExceptionReport()
{
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CExceptionReport::Open
//*---------------------------------------------------------------
// DESC : <20><>ü<EFBFBD>ڿ<EFBFBD> <20>ʱ<EFBFBD>ȭ
// PARM : 1 . lpszFilePath - <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20>̴ϴ<CCB4><CFB4><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
// 2 . bDoSetFilter - ó<><C3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ó<EFBFBD><C3B3> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><EFBFBD><E2BABB> TRUE)
// 3 . bDoCallStack - <20>ݽ<EFBFBD><DDBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (<28><EFBFBD><E2BABB> TRUE)
// 4 . pMiniDumpType - <20>̴ϴ<CCB4><CFB4><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// RETV : NOERROR - <20><><EFBFBD><EFBFBD> / <20>׿<EFBFBD> - <20><><EFBFBD><EFBFBD>
// PRGM : B4nFter
//*---------------------------------------------------------------
DWORD CExceptionReport::Open(LPCTSTR lpszFilePath, BOOL bDoSetFilter, BOOL bDoCallStack, MINIDUMP_TYPE pMiniDumpType)
{
DN_STRING(lpszFilePath, MAX_PATH);
/*
DWORD dwRetVal = m_Lock.Open();
if (NOERROR != dwRetVal) {
DN_RETURN(dwRetVal);
}
*/
STRNCPY(m_szFilePath, COUNT_OF(m_szFilePath), lpszFilePath);
DWORD dwRetVal = m_MiniDump.Open();
if (NOERROR != dwRetVal) {
DN_RETURN(dwRetVal);
}
m_bDoSetFilter = bDoSetFilter;
m_bDoCallStack = bDoCallStack;
m_MiniDumpType = pMiniDumpType;
if (m_bDoSetFilter) {
m_pInvalidParameterHandler = _set_invalid_parameter_handler( myInvalidParameterHandler );
m_pPureCallHandler = _set_purecall_handler( myPurecallHandler );
::SetUnhandledExceptionFilter(Proc);
}
return NOERROR;
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CExceptionReport::Close
//*---------------------------------------------------------------
// DESC : <20><>ü<EFBFBD>ڿ<EFBFBD> <20><><EFBFBD><EFBFBD>
// PARM : N/A
// RETV : N/A
// PRGM : B4nFter
//*---------------------------------------------------------------
VOID CExceptionReport::Close()
{
::SetUnhandledExceptionFilter( NULL );
_set_purecall_handler( m_pPureCallHandler );
_set_invalid_parameter_handler( m_pInvalidParameterHandler );
m_MiniDump.Close();
// m_Lock.Close();
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CExceptionReport::SetUserMessage
//*---------------------------------------------------------------
// DESC : <20>̴ϴ<CCB4><CFB4><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>Ե<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>޽<EFBFBD><DEBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
// PARM : 1 . lpszUserMessage - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>޽<EFBFBD><DEBD><EFBFBD>
// RETV : N/A
// PRGM : B4nFter
//*---------------------------------------------------------------
VOID CExceptionReport::SetUserMessage(LPCTSTR lpszUserMessage)
{
m_MiniDump.SetUserMessage(lpszUserMessage);
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CExceptionReport::SetOutputLogProc
//*---------------------------------------------------------------
// DESC : <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ܺ<EFBFBD> <20><><EFBFBD>ν<EFBFBD><CEBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
// PARM : 1 . lpfnOutputLogProc - <20>α<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ν<EFBFBD><CEBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// 2 . lpOutputLogProcParam - <20>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD>
// RETV : N/A
// PRGM : B4nFter
//*---------------------------------------------------------------
VOID CExceptionReport::SetOutputLogProc(CExceptionReport::LPFN_OUTPUT_LOGPROC lpfnOutputLogProc, LPVOID lpOutputLogProcParam)
{
m_lpfnOutputLogProc = lpfnOutputLogProc;
m_lpOutputLogProcParam = lpOutputLogProcParam;
}
DWORD WINAPI CExceptionReport::_StackOverflowException( LPVOID pParam )
{
return(ProcNoLock( static_cast<_EXCEPTION_POINTERS*>(pParam), GetInstancePtr()->GetMiniDumpType()));
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CExceptionReport::Proc
//*---------------------------------------------------------------
// DESC : <20><><EFBFBD><EFBFBD>ó<EFBFBD><C3B3> <20><><EFBFBD>Ϳ<EFBFBD><CDBF><EFBFBD> <20><><EFBFBD>ܸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20>ݹ<EFBFBD><DDB9>Լ<EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
// PARM : 1 . lpstExceptionPointers - EXCEPTION_POINTERS <20><><EFBFBD><EFBFBD>ü <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// RETV : N/A
// PRGM : B4nFter
//*---------------------------------------------------------------
LONG WINAPI CExceptionReport::Proc(LPEXCEPTION_POINTERS lpstExceptionPointers)
{
TP_LOCKAUTO aLockAuto(GetInstancePtr()->m_Lock);
if( lpstExceptionPointers->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW ) {
HANDLE hThread = ::CreateThread( 0, 0, _StackOverflowException, ( LPVOID )lpstExceptionPointers, 0, NULL );
WaitForSingleObject( hThread, INFINITE );
return EXCEPTION_EXECUTE_HANDLER;
}
return(ProcNoLock(lpstExceptionPointers, GetInstancePtr()->GetMiniDumpType()));
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CExceptionReport::Proc
//*---------------------------------------------------------------
// DESC : <20><><EFBFBD><EFBFBD>ó<EFBFBD><C3B3> <20><><EFBFBD>Ϳ<EFBFBD><CDBF><EFBFBD> <20><><EFBFBD>ܸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20>ݹ<EFBFBD><DDB9>Լ<EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
// PARM : 1 . lpstExceptionPointers - EXCEPTION_POINTERS <20><><EFBFBD><EFBFBD>ü <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// 2 . pMiniDumpType - <20>̴ϴ<CCB4><CFB4><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// RETV : N/A
// PRGM : B4nFter
//*---------------------------------------------------------------
LONG WINAPI CExceptionReport::Proc(LPEXCEPTION_POINTERS lpstExceptionPointers, MINIDUMP_TYPE pMiniDumpType)
{
TP_LOCKAUTO aLockAuto(GetInstancePtr()->m_Lock);
return(ProcNoLock(lpstExceptionPointers, pMiniDumpType));
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CExceptionReport::ProcNoLock
//*---------------------------------------------------------------
// DESC : <20><><EFBFBD><EFBFBD>ó<EFBFBD><C3B3> <20><><EFBFBD>Ϳ<EFBFBD><CDBF><EFBFBD> <20><><EFBFBD>ܸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20>ݹ<EFBFBD><DDB9>Լ<EFBFBD> (<28><><EFBFBD>ݾ<EFBFBD><DDBE><EFBFBD>)
// PARM : 1 . lpstExceptionPointers - EXCEPTION_POINTERS <20><><EFBFBD><EFBFBD>ü <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// 2 . pMiniDumpType - <20>̴ϴ<CCB4><CFB4><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// RETV : N/A
// PRGM : B4nFter
//*---------------------------------------------------------------
#pragma warning(disable:4706 4995)
LONG WINAPI CExceptionReport::ProcNoLock(LPEXCEPTION_POINTERS lpstExceptionPointers, MINIDUMP_TYPE pMiniDumpType)
{
#if defined(_SERVER)
switch(pMiniDumpType)
{
case MiniDumpWithFullMemory:
{
if (GetFreeDiskSpaceAsGigaByte() < 5)
{
wprintf(L"Insufficient DiskSpace MiniDumpWithFullMemory\n");
return EXCEPTION_EXECUTE_HANDLER;
}
}
break;
}
#endif //defined(_SERVER)
GetInstancePtr()->SetNowDump(true);
__try
{
DN_READ(lpstExceptionPointers, sizeof(LPEXCEPTION_POINTERS));
#if defined(_DEBUG)
// BreakPoint()<29><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ܴ<EFBFBD> Debugger<65><72><EFBFBD><EFBFBD> <20><EFBFBD>ǵ<EFBFBD><C7B5><EFBFBD> <20>ѱ<EFBFBD>
if (EXCEPTION_BREAKPOINT == lpstExceptionPointers->ExceptionRecord->ExceptionCode) {
return(EXCEPTION_CONTINUE_SEARCH);
}
#endif // _DEBUG
GetInstancePtr()->m_lpstExceptionPointers = lpstExceptionPointers;
DWORD dwRetVal = GetInstancePtr()->GetMiniDump().Write(lpstExceptionPointers, pMiniDumpType, GetInstancePtr()->GetFilePath());
if (NOERROR != dwRetVal) {
DN_STRING(GetInstancePtr()->GetMiniDump().GetFileName(), MAX_PATH);
}
DN_ASSERT(!GetInstancePtr()->m_File.IsOpen(), "Invalid!");
TCHAR szPrefix[128] = { _T('\0'), };
CTimeSet CurTime;
::wsprintf(szPrefix, _T("%04d%02d%02d%02d%02d%02d%03d"),
CurTime.GetYear(), CurTime.GetMonth(), CurTime.GetDay(),
CurTime.GetHour(), CurTime.GetMinute(),CurTime.GetSecond(),CurTime.GetMilliseconds());
::wsprintf(GetInstancePtr()->m_szFileName, _T("%s%s_ecp_%s.txt"),
GetInstancePtr()->m_szFilePath, CDebugUtil::GetProgramName(), szPrefix);
MAKE_STRING(GetInstancePtr()->m_szFileName);
dwRetVal = GetInstancePtr()->m_File.Open(GetInstancePtr()->m_szFileName, GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL, NULL);
if (NOERROR != dwRetVal) {
DN_ASSERT(0, "Invalid!");
}
#if defined(_UNICODE)
dwRetVal = GetInstancePtr()->m_File.WriteBOM(CFileSet::EV_BT_UTF16_LE);
#endif // _UNICODE
if (NOERROR != dwRetVal) {
DN_ASSERT(0, "Invalid!");
}
// 1 . <20><20><><EFBFBD><EFBFBD>
GetInstancePtr()->Write(_T("------------------------------------------------------------------------------\r\n"), EV_WF_FILE);
GetInstancePtr()->Write(_T(" Basic Information\r\n"), EV_WF_FILE);
GetInstancePtr()->Write(_T("------------------------------------------------------------------------------\r\n\r\n"), EV_WF_FILE);
LPTSTR szText = GetInstancePtr()->GetFaultReason(szPrefix);
if (szText) {
// <20><><EFBFBD><EFBFBD>
GetInstancePtr()->Write(szText, EV_WF_ALL);
GetInstancePtr()->Write(_T("\r\n"), EV_WF_FILE);
}
GetInstancePtr()->Write(_T("MiniDump("), EV_WF_FILE);
GetInstancePtr()->Write(szPrefix, EV_WF_FILE);
GetInstancePtr()->Write(_T(") : "), EV_WF_FILE);
GetInstancePtr()->Write(GetInstancePtr()->GetMiniDump().GetFileName(), EV_WF_FILE);
GetInstancePtr()->Write(_T("\r\n\r\n\r\n"), EV_WF_FILE);
// 2 . <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
GetInstancePtr()->Write(_T("------------------------------------------------------------------------------\r\n"), EV_WF_FILE);
#if defined(_X86_)
GetInstancePtr()->Write(_T(" Registers (X86)\r\n"), EV_WF_FILE);
#elif defined(_AMD64_)
GetInstancePtr()->Write(_T(" Registers (X64)\r\n"), EV_WF_FILE);
#elif defined(_IA64_)
#pragma message("IA64 NOT DEFINED!!")
#pragma FORCE COMPILATION ABORT!
#else // !_X86 && !_AMD64_ && !_IA64_
#pragma message("CPU NOT DEFINED!!")
#pragma FORCE COMPILATION ABORT!
#endif // !_X86 && !_AMD64_ && !_IA64_
GetInstancePtr()->Write(_T("------------------------------------------------------------------------------\r\n\r\n"), EV_WF_FILE);
szText = GetInstancePtr()->GetRegisterString();
if (szText) {
// <20><><EFBFBD><EFBFBD>
GetInstancePtr()->Write(szText, EV_WF_FILE);
}
GetInstancePtr()->Write(_T("\r\n\r\n\r\n"), EV_WF_FILE);
// 3 . <20>ݽ<EFBFBD><DDBD><EFBFBD>
GetInstancePtr()->Write(_T("------------------------------------------------------------------------------\r\n"), EV_WF_FILE);
GetInstancePtr()->Write(_T(" Call Stack\r\n"), EV_WF_FILE);
GetInstancePtr()->Write(_T("------------------------------------------------------------------------------\r\n\r\n"), EV_WF_FILE);
if (GetInstancePtr()->DoCallStack()) {
szText = GetInstancePtr()->GetFirstStackTraceString(szPrefix);
if (szText) {
// <20><><EFBFBD><EFBFBD>
GetInstancePtr()->Write(szText, EV_WF_ALL);
GetInstancePtr()->Write(_T("\r\n"), EV_WF_FILE);
}
WHILE((szText = GetInstancePtr()->GetNextStackTraceString(szPrefix)), 1000) {
// <20><><EFBFBD><EFBFBD>
GetInstancePtr()->Write(szText, EV_WF_ALL);
GetInstancePtr()->Write(_T("\r\n"), EV_WF_FILE);
}
}
GetInstancePtr()->Write(_T("\r\n\r\n\r\n"), EV_WF_FILE);
// 4. <20><><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD><DEB8><EFBFBD>
GetInstancePtr()->Write(_T("------------------------------------------------------------------------------\r\n"), EV_WF_FILE);
GetInstancePtr()->Write(_T(" User Memory\r\n"), EV_WF_FILE);
GetInstancePtr()->Write(_T("------------------------------------------------------------------------------\r\n\r\n"), EV_WF_FILE);
szText = GetInstancePtr()->GetUserMemoryString();
if (szText)
GetInstancePtr()->Write(szText, EV_WF_FILE);
GetInstancePtr()->Write(_T("\r\n"), EV_WF_FILE);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DN_ASSERT(0, "Invalid!");
}
GetInstancePtr()->m_File.Close();
GetInstancePtr()->SetNowDump(false);
return(EXCEPTION_EXECUTE_HANDLER);
}
#pragma warning(default:4706 4995)
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CExceptionReport::InitSymbolEngine
//*---------------------------------------------------------------
// DESC : <20>ɺ<EFBFBD><C9BA><EFBFBD><EFBFBD><EFBFBD> <20>ʱ<EFBFBD>ȭ
// PARM : N/A
// RETV : N/A
// PRGM : B4nFter
//*---------------------------------------------------------------
VOID CExceptionReport::InitSymbolEngine()
{
if (m_InitSymbolEngine) {
return;
}
DWORD dwOption = ::SymGetOptions();
::SymSetOptions(dwOption | SYMOPT_LOAD_LINES);
m_InitSymbolEngine = ::SymInitialize(::GetCurrentProcess(), NULL, TRUE);
DN_ASSERT(TRUE == m_InitSymbolEngine, "@err, hr");
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CExceptionReport::ReadProcessMemoryWork
//*---------------------------------------------------------------
// DESC : <20><><EFBFBD>μ<EFBFBD><CEBC><EFBFBD> <20>޸<EFBFBD><DEB8><EFBFBD><EFBFBD><EFBFBD> Ư<><C6AF> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20>о<EFBFBD><D0BE><EFBFBD><EFBFBD><EFBFBD>
// PARM : 1 . hModule - <20><><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>
// 2 . dw64BaseAddr - <20>о<EFBFBD><D0BE><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>μ<EFBFBD><CEBC><EFBFBD> <20>޸<EFBFBD><DEB8><EFBFBD>
// 3 . lpBuffer - <20><><EFBFBD><EFBFBD> <20>޸<EFBFBD><DEB8><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
// 4 . dwBufferSize - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ũ<><C5A9>
// 5 . lpReadBytesSize - <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ũ<><C5A9>
// RETV : TRUE - <20><><EFBFBD><EFBFBD> / FALSE - <20><><EFBFBD><EFBFBD>
// PRGM : B4nFter
//*---------------------------------------------------------------
BOOL __stdcall CExceptionReport::ReadProcessMemoryWork(HANDLE /*hModule*/, DWORD64 dw64BaseAddr, LPVOID lpBuffer, DWORD dwBufferSize, LPDWORD lpReadBytesSize)
{
return(::ReadProcessMemory(::GetCurrentProcess(), (LPCVOID)dw64BaseAddr, lpBuffer, dwBufferSize, (SIZE_T*)lpReadBytesSize));
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CExceptionReport::GetFaultReason
//*---------------------------------------------------------------
// DESC : <20><><EFBFBD>л<EFBFBD><D0BB><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// PARM : 1 . lpszPrefix - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ڿ<EFBFBD>
// RETV : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڿ<EFBFBD>
// PRGM : B4nFter
//*---------------------------------------------------------------
#pragma warning(disable:4995 4996)
const LPTSTR CExceptionReport::GetFaultReason(LPCTSTR lpszPrefix)
{
DN_ASSERT(NULL != lpszPrefix, "Invalid!");
DN_READ(m_lpstExceptionPointers, sizeof(EXCEPTION_POINTERS*));
const TCHAR* szResult = NULL;
__try
{
InitSymbolEngine();
INT nOffset = 0;
nOffset += ::wsprintf(m_szText, _T("Exception(%s) : "), lpszPrefix);
nOffset += ::GetModuleBaseName(::GetCurrentProcess(), NULL, m_szText+nOffset, COUNT_OF(m_szText));
nOffset += ::wsprintf(m_szText+nOffset, _T(" caused an "));
m_szExceptionDesc[0] = _T('\0');
CMiniDumpSet::GetExceptionCause(m_lpstExceptionPointers->ExceptionRecord->ExceptionCode, m_szExceptionDesc, COUNT_OF(m_szExceptionDesc));
if (_T('\0') != m_szExceptionDesc[0]) {
nOffset += ::wsprintf(m_szText+nOffset, _T("%s (ThdId:%u)"), m_szExceptionDesc, ::GetCurrentThreadId());
}
else {
nOffset += ::FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
::GetModuleHandle(_T("NTDLL.DLL")),
m_lpstExceptionPointers->ExceptionRecord->ExceptionCode,
0, m_szText+nOffset, COUNT_OF(m_szText), 0);
}
DN_ASSERT(nOffset < (COUNT_OF(m_szText)-MAX_PATH), "error!");
nOffset += ::wsprintf(m_szText+nOffset, _T(" in module "));
DWORD64 lpStrPtr = ::SymGetModuleBase64(::GetCurrentProcess(),
(DWORD64)m_lpstExceptionPointers->ExceptionRecord->ExceptionAddress);
DN_ASSERT(NULL != lpStrPtr, "error!");
if (NULL == lpStrPtr) {
nOffset += ::wsprintf(m_szText+nOffset, _T("<UNKNOWN>"));
}
else {
nOffset += ::GetModuleBaseName(::GetCurrentProcess(), (HINSTANCE)lpStrPtr,
m_szText+nOffset, COUNT_OF(m_szText)-nOffset);
}
// <20><><EFBFBD>³<EFBFBD><C2B3><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, <20><><EFBFBD>ǹ̰<C7B9> <20><><EFBFBD><EFBFBD>.
#if (0)
#if defined(_WIN64)
nOffset += ::wsprintf(m_szText+nOffset, _T(" at %016X"),
m_lpstExceptionPointers->ExceptionRecord->ExceptionAddress);
#else // _WIN64
nOffset += ::wsprintf(m_szText+nOffset, _T(" at %04X:%08X"),
m_lpstExceptionPointers->ContextRecord->SegCs,
m_lpstExceptionPointers->ExceptionRecord->ExceptionAddress);
#endif // _WIN64
DN_ASSERT(nOffset < (COUNT_OF(m_szText)-200), "error!");
#endif
// Start looking up the exception address.
PIMAGEHLP_SYMBOL64 lpSymbol = (PIMAGEHLP_SYMBOL64)&m_btSymbol;
::memset(lpSymbol, 0, sizeof(m_btSymbol));
lpSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
lpSymbol->MaxNameLength = sizeof(m_btSymbol) - sizeof(IMAGEHLP_SYMBOL64);
DWORD64 n64LineDisp;
if (TRUE == ::SymGetSymFromAddr64(::GetCurrentProcess(),
(DWORD64)m_lpstExceptionPointers->ExceptionRecord->ExceptionAddress,
&n64LineDisp, lpSymbol))
{
USES_CONVERSION;
INT nStrLen = ::lstrlenA(lpSymbol->Name);
// Make sure there's enough room for the longest symbol
// and the displacement.
if (nStrLen > (INT)((COUNT_OF(m_szText) - nOffset) - (COUNT_OF(m_btSymbol) + 50))) {
::lstrcpyn(m_szText+nOffset, A2T(lpSymbol->Name), COUNT_OF(m_szText) - nOffset - 1);
// Gotta leave now
szResult = m_szText;
__leave;
}
else {
// <20>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>.
#if (0)
if (n64LineDisp > 0) {
nOffset += ::wsprintf(m_szText+nOffset, _T(" %s()+%04d Byte(s)"), A2T(lpSymbol->Name), n64LineDisp);
}
else {
nOffset += ::wsprintf(m_szText+nOffset, _T(" %s"), A2T(lpSymbol->Name));
}
#else
nOffset += ::wsprintf(m_szText+nOffset, _T(" %s()"), A2T(lpSymbol->Name));
#endif
}
}
else {
// If the symbol wasn't found, the source and line won't be found either, so leave now.
szResult = m_szText;
__leave;
}
DN_ASSERT(nOffset < (COUNT_OF(m_szText)-200), "error!");
// Look up the source file and line number.
::memset(&m_Line , 0, sizeof(IMAGEHLP_LINE64));
m_Line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
DWORD nLineDisp;
if (TRUE == ::SymGetLineFromAddr64(::GetCurrentProcess(),
(DWORD64)m_lpstExceptionPointers->ExceptionRecord->ExceptionAddress ,
&nLineDisp, &m_Line))
{
USES_CONVERSION;
nOffset += ::wsprintf(m_szText+nOffset, _T(","));
// Copy no more of the source file and line number
// information than there's room for.
INT nStrLen = ::lstrlenA(m_Line.FileName);
if (nStrLen > (INT)(COUNT_OF(m_szText) - nOffset - MAX_PATH - 50)) {
::lstrcpyn(m_szText+nOffset, A2T(m_Line.FileName), COUNT_OF(m_szText)-nOffset-1);
// Gotta leave now
szResult = m_szText;
__leave;
}
else {
// full-path<74><68> <20>ƴ<EFBFBD> file<6C><65><EFBFBD><EFBFBD> line<6E><65>ȣ<EFBFBD><C8A3> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
#if (0)
if (nLineDisp > 0) {
nOffset += ::wsprintf(m_szText+nOffset, _T(" %s, line %04d+%04d Byte(s)"),
A2T(m_Line.FileName), m_Line.LineNumber, nLineDisp);
}
else {
nOffset += ::wsprintf(m_szText+nOffset, _T(" %s, line %04d"),
A2T(m_Line.FileName), m_Line.LineNumber);
}
#else
INT nLocalStrLen = ::lstrlenA(m_Line.FileName);
for (--nLocalStrLen ; 0 <= nLocalStrLen ; --nLocalStrLen) {
if (('\\' == m_Line.FileName[nLocalStrLen]) || ('/' == m_Line.FileName[nLocalStrLen])) {
break;
}
}
nOffset += ::wsprintf(m_szText+nOffset, _T(" Source(%s:%d)"),
A2T(&m_Line.FileName[nLocalStrLen+1]), m_Line.LineNumber);
#endif
}
}
szResult = m_szText;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DN_ASSERT(0, "Crashed in CExceptionReport::GetFaultReason()");
szResult = NULL;
}
return(const_cast<LPTSTR>(szResult));
}
#pragma warning(default:4995 4996)
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CExceptionReport::GetStackTraceString
//*---------------------------------------------------------------
// DESC : <20><><EFBFBD><EFBFBD> <20>߻<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> EXCEPTION_POINTERS <20><><EFBFBD><EFBFBD><EFBFBD>Ϳ<EFBFBD><CDBF><EFBFBD> ȣ<><EFBFBD><E2BDBA> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>о ó<><C3B3><EFBFBD><EFBFBD>
// PARM : 1 . lpszPrefix - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ڿ<EFBFBD>
// RETV : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڿ<EFBFBD>
// PRGM : B4nFter
//*---------------------------------------------------------------
#pragma warning(disable:4995 4996)
const LPTSTR CExceptionReport::GetStackTraceString(LPCTSTR lpszPrefix)
{
DN_ASSERT(NULL != lpszPrefix, "Invalid!");
// The value that is returned
const TCHAR* szResult = NULL;
// The module base address. I look this up right after the stack
// walk to ensure that the module is valid.
DWORD64 dwModBase;
__try
{
// Initialize the symbol engine in case it isn't initialized.
InitSymbolEngine();
// Note: If the source file and line number functions are used,
// StackWalk can cause an access violation.
BOOL bRetVal = ::StackWalk64(m_MachineType, ::GetCurrentProcess(), ::GetCurrentThread(),
&m_StackFame, &m_stContext,
ReadProcessMemoryWork, SymFunctionTableAccess64, SymGetModuleBase64,
NULL);
if ((FALSE == bRetVal) || (0 == m_StackFame.AddrFrame.Offset)) {
szResult = NULL;
__leave;
}
// Before I get too carried away and start calculating
// everything, I need to double-check that the address returned
// by StackWalk really exists. I've seen cases in which
// StackWalk returns TRUE but the address doesn't belong to
// a module in the process.
dwModBase = ::SymGetModuleBase64(::GetCurrentProcess(), m_StackFame.AddrPC.Offset);
if (0 == dwModBase) {
szResult = NULL;
__leave;
}
INT nOffset = 0;
nOffset += ::wsprintf(m_szText, _T("CallStack(%s) : "), lpszPrefix);
// <20><><EFBFBD>³<EFBFBD><C2B3><20><><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ȯ<><C8AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʱ⿡ <20>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD>
#if (0)
// At a minimum, put in the address.
#ifdef _WIN64
nOffset += ::wsprintf(m_szText+nOffset, _T("0x%016X"), m_StackFame.AddrPC.Offset);
#else
nOffset += ::wsprintf(m_szText+nOffset, _T("%04X:%08X"), m_stContext.SegCs, m_StackFame.AddrPC.Offset);
#endif
// Output the parameters.
nOffset += ::wsprintf(m_szText+nOffset,
#ifdef _WIN64
_T(" (0x%016X 0x%016X 0x%016X 0x%016X)"),
#else // _WIN64
_T(" (0x%08X 0x%08X 0x%08X 0x%08X)"),
#endif // _WIN64
m_StackFame.Params[0], m_StackFame.Params[1],
m_StackFame.Params[2], m_StackFame.Params[3]);
#endif
// Output the module name.
DN_ASSERT(nOffset < (COUNT_OF(m_szText) - MAX_PATH), "error!");
//nOffset += ::wsprintf(m_szText+nOffset, _T(" ")); // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> OFF <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD> <20><><EFBFBD><EFBFBD>
nOffset += ::GetModuleBaseName(::GetCurrentProcess(), (HINSTANCE)dwModBase,
m_szText+nOffset, COUNT_OF(m_szText)-nOffset);
// Output the symbol name?
DN_ASSERT(nOffset < (COUNT_OF(m_szText) - MAX_PATH), "error!");
DWORD64 n64LineDisp;
// Start looking up the exception address.
PIMAGEHLP_SYMBOL64 lpSymbol = (PIMAGEHLP_SYMBOL64)&m_btSymbol;
::memset(lpSymbol, 0, sizeof(m_btSymbol));
lpSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
lpSymbol->MaxNameLength = COUNT_OF(m_btSymbol) - sizeof(IMAGEHLP_SYMBOL64);
lpSymbol->Address = m_StackFame.AddrPC.Offset;
if (TRUE == ::SymGetSymFromAddr64(::GetCurrentProcess(), m_StackFame.AddrPC.Offset, &n64LineDisp, lpSymbol))
{
USES_CONVERSION;
// Copy no more symbol information than there's room
// for. Symbols are ANSI
INT nStrLen = ::lstrlenA(lpSymbol->Name);
if (nStrLen > (INT)(COUNT_OF(m_szText) - nOffset - (COUNT_OF(m_btSymbol) + 50)))
{
::lstrcpyn(m_szText+nOffset, A2T(lpSymbol->Name), COUNT_OF(m_szText) - nOffset - 1);
// Gotta leave now
szResult = m_szText;
__leave;
}
else
{
// <20>ؿ<EFBFBD><D8BF><EFBFBD> <20>ҽ<EFBFBD><D2BD><EFBFBD><EFBFBD><EFBFBD> line<6E><65>ȣ<EFBFBD><C8A3> <20><><EFBFBD><EFBFBD><EFBFBD>ϹǷ<CFB9> <20>̰<EFBFBD><CCB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD> <20><><EFBFBD><EFBFBD>
#if (1)
// #if (0)
if (n64LineDisp > 0)
{
nOffset += ::wsprintf(m_szText+nOffset, _T(" %s()+%04d Byte(s)"),
A2T(lpSymbol->Name), n64LineDisp);
}
else
{
nOffset += ::wsprintf(m_szText+nOffset, _T(" %s "), A2T(lpSymbol->Name));
}
#else
nOffset += ::wsprintf(m_szText+nOffset, _T(" Function(%s) "), A2T(lpSymbol->Name));
#endif
}
}
else
{
// If the symbol wasn't found, the source file and line
// number won't be found either, so leave now.
szResult = m_szText;
__leave;
}
// Output the source file and line number information?
DN_ASSERT(nOffset < (COUNT_OF(m_szText) - MAX_PATH), "error!");
::memset(&m_Line, 0, sizeof(IMAGEHLP_LINE64));
m_Line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
DWORD nLineDisp;
if (TRUE == ::SymGetLineFromAddr64(::GetCurrentProcess(), m_StackFame.AddrPC.Offset,
&nLineDisp, &m_Line))
{
USES_CONVERSION;
// m_Line.FileName<6D><65> full-path<74>̹Ƿ<CCB9> <20>׳<EFBFBD> file<6C><65><EFBFBD><EFBFBD> line<6E><65>ȣ<EFBFBD><C8A3> <20><><EFBFBD><EFBFBD>
#if (0)
// Copy no more of the source file and line number
// information than there's room for.
INT nStrLen = ::lstrlenA(m_Line.FileName);
if (nStrLen > (INT)(COUNT_OF(m_szText) - nOffset - (MAX_PATH + 50))) {
::lstrcpynA(m_szText+nOffset, m_Line.FileName, COUNT_OF(m_szText) - nOffset - 1);
// Gotta leave now
szResult = m_szText;
__leave;
}
else {
if (nLineDisp > 0) {
nOffset += ::wsprintf(m_szText+nOffset, _T(" %s, line %04d+%04d Byte(s)"),
A2T(m_Line.FileName), m_Line.LineNumber, nLineDisp);
}
else {
nOffset += ::wsprintf(m_szText+nOffset, _T(" %s, line %04d"),
A2T(m_Line.FileName), m_Line.LineNumber);
}
}
#else
int nStrLen = ::lstrlenA(m_Line.FileName);
for (--nStrLen ; 0 <= nStrLen ; --nStrLen) {
if (('\\' == m_Line.FileName[nStrLen]) || ('/' == m_Line.FileName[nStrLen])) {
break;
}
}
nOffset += ::wsprintf(m_szText+nOffset, _T(", Source(%s:%d)"),
A2T(&m_Line.FileName[nStrLen+1]), m_Line.LineNumber);
#endif
}
szResult = m_szText;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DN_ASSERT(0, "error!");
szResult = NULL;
}
return(const_cast<LPTSTR>(szResult));
}
#pragma warning(default:4995 4996)
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CExceptionReport::GetFirstStackTraceString
//*---------------------------------------------------------------
// DESC : ȣ<><EFBFBD><E2BDBA> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
// PARM : 1 . lpszPrefix - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ڿ<EFBFBD>
// RETV : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڿ<EFBFBD>
// PRGM : B4nFter
//*---------------------------------------------------------------
const LPTSTR CExceptionReport::GetFirstStackTraceString(LPCTSTR lpszPrefix)
{
DN_ASSERT(NULL != lpszPrefix, "Invalid!");
DN_READ(m_lpstExceptionPointers, sizeof(EXCEPTION_POINTERS*));
{
::memset(&m_StackFame, 0, sizeof(m_StackFame));
#ifdef _X86_
m_StackFame.AddrPC.Offset = m_lpstExceptionPointers->ContextRecord->Eip;
m_StackFame.AddrPC.Mode = AddrModeFlat;
m_StackFame.AddrStack.Offset = m_lpstExceptionPointers->ContextRecord->Esp;
m_StackFame.AddrStack.Mode = AddrModeFlat;
m_StackFame.AddrFrame.Offset = m_lpstExceptionPointers->ContextRecord->Ebp;
m_StackFame.AddrFrame.Mode = AddrModeFlat;
#elif defined(_AMD64_)
m_StackFame.AddrPC.Offset = m_lpstExceptionPointers->ContextRecord->Rip;
m_StackFame.AddrPC.Mode = AddrModeFlat;
m_StackFame.AddrStack.Offset = m_lpstExceptionPointers->ContextRecord->Rsp;
m_StackFame.AddrStack.Mode = AddrModeFlat;
m_StackFame.AddrFrame.Offset = m_lpstExceptionPointers->ContextRecord->Rbp;
m_StackFame.AddrFrame.Mode = AddrModeFlat;
#elif defined(_IA64_)
#pragma message("IA64 NOT DEFINED!!")
#pragma FORCE COMPILATION ABORT!
#else
#pragma message("CPU NOT DEFINED!!")
#pragma FORCE COMPILATION ABORT!
#endif
}
m_stContext = *(m_lpstExceptionPointers->ContextRecord);
return(GetStackTraceString(lpszPrefix));
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CExceptionReport::GetNextStackTraceString
//*---------------------------------------------------------------
// DESC : ȣ<><EFBFBD><E2BDBA> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
// PARM : 1 . lpszPrefix - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ڿ<EFBFBD>
// RETV : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڿ<EFBFBD>
// PRGM : B4nFter
//*---------------------------------------------------------------
const LPTSTR CExceptionReport::GetNextStackTraceString(LPCTSTR lpszPrefix)
{
DN_ASSERT(NULL != lpszPrefix, "Invalid!");
return(GetStackTraceString(lpszPrefix));
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CExceptionReport::GetRegisterString
//*---------------------------------------------------------------
// DESC : <20><><EFBFBD><EFBFBD> <20>߻<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> EXCEPTION_POINTERS <20><><EFBFBD><EFBFBD><EFBFBD>Ϳ<EFBFBD><CDBF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// PARM : N/A
// RETV : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڿ<EFBFBD>
// PRGM : B4nFter
//*---------------------------------------------------------------
#pragma warning(disable:4995)
const LPTSTR CExceptionReport::GetRegisterString()
{
DN_READ(m_lpstExceptionPointers, sizeof(EXCEPTION_POINTERS*));
#if defined(_X86_)
// This call puts 48 bytes on the stack, which could be a problem if
// the stack is blown.
::wsprintf(m_szText ,
_T ("EAX=%08X EBX=%08X ECX=%08X EDX=%08X ESI=%08X\r\n")\
_T ("EDI=%08X EBP=%08X ESP=%08X EIP=%08X FLG=%08X\r\n")\
_T ("CS=%04X DS=%04X SS=%04X ES=%04X ")\
_T ("FS=%04X GS=%04X" ) ,
m_lpstExceptionPointers->ContextRecord->Eax ,
m_lpstExceptionPointers->ContextRecord->Ebx ,
m_lpstExceptionPointers->ContextRecord->Ecx ,
m_lpstExceptionPointers->ContextRecord->Edx ,
m_lpstExceptionPointers->ContextRecord->Esi ,
m_lpstExceptionPointers->ContextRecord->Edi ,
m_lpstExceptionPointers->ContextRecord->Ebp ,
m_lpstExceptionPointers->ContextRecord->Esp ,
m_lpstExceptionPointers->ContextRecord->Eip ,
m_lpstExceptionPointers->ContextRecord->EFlags ,
m_lpstExceptionPointers->ContextRecord->SegCs ,
m_lpstExceptionPointers->ContextRecord->SegDs ,
m_lpstExceptionPointers->ContextRecord->SegSs ,
m_lpstExceptionPointers->ContextRecord->SegEs ,
m_lpstExceptionPointers->ContextRecord->SegFs ,
m_lpstExceptionPointers->ContextRecord->SegGs ) ;
#elif defined(_AMD64_)
::wsprintf(m_szText ,
_T ("RAX=%016X RBX=%016X RCX=%016X RDX=%016X RSI=%016X\r\n")\
_T ("RDI=%016X RBP=%016X RSP=%016X RIP=%016X FLG=%016X\r\n")\
_T (" R8=%016X R9=%016X R10=%016X R11=%016X R12=%016X\r\n")\
_T ("R13=%016X R14=%016X R15=%016X" ) ,
m_lpstExceptionPointers->ContextRecord->Rax ,
m_lpstExceptionPointers->ContextRecord->Rbx ,
m_lpstExceptionPointers->ContextRecord->Rcx ,
m_lpstExceptionPointers->ContextRecord->Rdx ,
m_lpstExceptionPointers->ContextRecord->Rsi ,
m_lpstExceptionPointers->ContextRecord->Rdi ,
m_lpstExceptionPointers->ContextRecord->Rbp ,
m_lpstExceptionPointers->ContextRecord->Rsp ,
m_lpstExceptionPointers->ContextRecord->Rip ,
m_lpstExceptionPointers->ContextRecord->EFlags ,
m_lpstExceptionPointers->ContextRecord->R8 ,
m_lpstExceptionPointers->ContextRecord->R9 ,
m_lpstExceptionPointers->ContextRecord->R10 ,
m_lpstExceptionPointers->ContextRecord->R11 ,
m_lpstExceptionPointers->ContextRecord->R12 ,
m_lpstExceptionPointers->ContextRecord->R13 ,
m_lpstExceptionPointers->ContextRecord->R14 ,
m_lpstExceptionPointers->ContextRecord->R15 ) ;
#elif defined(_IA64_)
#pragma message("IA64 NOT DEFINED!!")
#pragma FORCE COMPILATION ABORT!
#else // !_X86 && !_AMD64_ && !_IA64_
#pragma message("CPU NOT DEFINED!!")
#pragma FORCE COMPILATION ABORT!
#endif // !_X86 && !_AMD64_ && !_IA64_
return m_szText;
}
#pragma warning(default:4995)
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CExceptionReport::Write
//*---------------------------------------------------------------
// DESC : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʿ<EFBFBD><CABF><EFBFBD> <20>ؽ<EFBFBD>Ʈ<EFBFBD><C6AE> Ư<><C6AF><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
// PARM : 1 . lpszText - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ڿ<EFBFBD>
// 2 . eWriteFlag - <20><><EFBFBD><EFBFBD> <20>÷<EFBFBD><C3B7><EFBFBD>
// RETV : N/A
// PRGM : B4nFter
//*---------------------------------------------------------------
VOID CExceptionReport::Write(LPCTSTR lpszText, EF_WRITEFLAGE eWriteFlag)
{
DN_ASSERT(NULL != lpszText, "Invalid!");
ULONG uTextSize = (ULONG)::_tcslen(lpszText);
if (eWriteFlag | EV_WF_FILE) {
ULONG uIoBytes = uTextSize * (ULONG)sizeof(TCHAR);
m_File.Write(lpszText, uIoBytes);
}
if (eWriteFlag | EV_WF_LOGPROC &&
m_lpfnOutputLogProc
)
{
m_lpfnOutputLogProc(lpszText, uTextSize, m_lpOutputLogProcParam);
}
::OutputDebugString(lpszText); // !!! <20>ӽ<EFBFBD>
}
const LPTSTR CExceptionReport::GetUserMemoryString()
{
::memset(m_szText, 0, sizeof(m_szText));
::wsprintf(m_szText, _T("[ACC:%d][CHRID:%I64d][MainCmd:%d][SubCmd:%d]"), m_nAccountID, m_biCharacterDBID, m_nMainCmd, m_nSubCmd);
return m_szText;
}
void CExceptionReport::SetValues(UINT nAccountID, INT64 biCharacterDBID, int nMainCmd, int nSubCmd)
{
m_nAccountID = nAccountID;
m_biCharacterDBID = biCharacterDBID;
m_nMainCmd = nMainCmd;
m_nSubCmd = nSubCmd;
}
UINT CExceptionReport::m_nAccountID = 0;
INT64 CExceptionReport::m_biCharacterDBID = 0;
int CExceptionReport::m_nMainCmd = 0;
int CExceptionReport::m_nSubCmd = 0;