wheatyexceptionreport.cpp

来自「一个FTP下载的源代码。代码质量非常高」· C++ 代码 · 共 1,021 行 · 第 1/3 页

CPP
1,021
字号
//==========================================
// Based upon code from
// Matt Pietrek
// MSDN Magazine, 2002
// FILE: WheatyExceptionReport.CPP
//==========================================
#define WIN32_LEAN_AND_MEAN
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <dbghelp.h>
#include "WheatyExceptionReport.h"
#include "..\version.h"
#include "ProcessorInfo.h"
#include "WindowsVersion.h"
#include "mailmsg.h"

typedef BOOL
(_stdcall *tSymFromAddr)(
    IN  HANDLE              hProcess,
    IN  DWORD64             Address,
    OUT PDWORD64            Displacement,
    IN OUT PSYMBOL_INFO     Symbol
    );

typedef DWORD
(_stdcall *tSymGetOptions)(
	);

typedef DWORD
(_stdcall *tSymSetOptions)(
    IN DWORD   SymOptions
    );

typedef BOOL
(_stdcall *tSymCleanup)(
    IN HANDLE hProcess
    );

typedef BOOL
(_stdcall *tSymInitialize)(
    IN HANDLE   hProcess,
    IN PSTR     UserSearchPath,
    IN BOOL     fInvadeProcess
    );

typedef BOOL
(_stdcall *tSymEnumSymbols)(
    IN HANDLE                       hProcess,
    IN ULONG64                      BaseOfDll,
    IN PCSTR                        Mask,
    IN PSYM_ENUMERATESYMBOLS_CALLBACK    EnumSymbolsCallback,
    IN PVOID                        UserContext
    );

typedef ULONG
(_stdcall *tSymSetContext)(
    HANDLE hProcess,
    PIMAGEHLP_STACK_FRAME StackFrame,
    PIMAGEHLP_CONTEXT Context
    );

typedef BOOL
(_stdcall *tSymGetLineFromAddr)(
    IN  HANDLE                hProcess,
    IN  DWORD                 dwAddr,
    OUT PDWORD                pdwDisplacement,
    OUT PIMAGEHLP_LINE        Line
    );

typedef BOOL
(_stdcall *tStackWalk)(
    DWORD                             MachineType,
    HANDLE                            hProcess,
    HANDLE                            hThread,
    LPSTACKFRAME                      StackFrame,
    PVOID                             ContextRecord,
    PREAD_PROCESS_MEMORY_ROUTINE      ReadMemoryRoutine,
    PFUNCTION_TABLE_ACCESS_ROUTINE    FunctionTableAccessRoutine,
    PGET_MODULE_BASE_ROUTINE          GetModuleBaseRoutine,
    PTRANSLATE_ADDRESS_ROUTINE        TranslateAddress
    );

typedef PVOID
(_stdcall *tSymFunctionTableAccess)(
    HANDLE  hProcess,
    DWORD   AddrBase
    );

typedef DWORD
(_stdcall *tSymGetModuleBase)(
    IN  HANDLE              hProcess,
    IN  DWORD               dwAddr
    );

typedef BOOL
(_stdcall *tSymGetTypeInfo)(
    IN  HANDLE          hProcess,
    IN  DWORD64         ModBase,
    IN  ULONG           TypeId,
    IN  IMAGEHLP_SYMBOL_TYPE_INFO GetType,
    OUT PVOID           pInfo
    );

typedef BOOL
(_stdcall *tMiniDumpWriteDump)(
	HANDLE hProcess,
	DWORD ProcessId,
	HANDLE hFile,
	MINIDUMP_TYPE DumpType,
	PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
	PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
	PMINIDUMP_CALLBACK_INFORMATION CallbackParam
	);

static tSymCleanup				pSymCleanup;
static tSymInitialize			pSymInitialize;
static tSymGetOptions			pSymGetOptions;
static tSymSetOptions			pSymSetOptions;
static tSymEnumSymbols			pSymEnumSymbols;
static tSymSetContext			pSymSetContext;
static tSymGetLineFromAddr		pSymGetLineFromAddr;
static tSymFromAddr			pSymFromAddr;
static tStackWalk				pStackWalk;
static tSymFunctionTableAccess	pSymFunctionTableAccess;
static tSymGetModuleBase		pSymGetModuleBase;
static tSymGetTypeInfo			pSymGetTypeInfo;
static tMiniDumpWriteDump		pMiniDumpWriteDump;



//============================== Global Variables =============================

//
// Declare the static variables of the WheatyExceptionReport class
//
TCHAR WheatyExceptionReport::m_szLogFileName[MAX_PATH];
TCHAR WheatyExceptionReport::m_szDmpFileName[MAX_PATH];
LPTOP_LEVEL_EXCEPTION_FILTER WheatyExceptionReport::m_previousFilter;
HANDLE WheatyExceptionReport::m_hReportFile;
HANDLE WheatyExceptionReport::m_hDumpFile;
HANDLE WheatyExceptionReport::m_hProcess;
BOOL WheatyExceptionReport::m_bFirstRun;

// Declare global instance of class
static WheatyExceptionReport g_WheatyExceptionReport;

//============================== Class Methods =============================

WheatyExceptionReport::WheatyExceptionReport( )   // Constructor
{
	m_bFirstRun = TRUE;

    // Install the unhandled exception filter function
    m_previousFilter =
        SetUnhandledExceptionFilter(WheatyUnhandledExceptionFilter);

    // Figure out what the report file will be named, and store it away
    GetModuleFileName( 0, m_szLogFileName, MAX_PATH );

    // Look for the '.' before the "EXE" extension.  Replace the extension
    // with "RPT"
    PTSTR pszDot = _tcsrchr( m_szLogFileName, _T('.') );
    if ( pszDot )
    {
        pszDot++;   // Advance past the '.'
		*pszDot = 0;
		_tcscpy( m_szDmpFileName, m_szLogFileName );
        _tcscpy( pszDot, _T("rpt") );   // "rpt" -> "Report"
		_tcscat( m_szDmpFileName, _T("dmp") );   // "dmp" -> "Dump"
    }

    m_hProcess = GetCurrentProcess();
}

//============
// Destructor 
//============
WheatyExceptionReport::~WheatyExceptionReport( )
{
    SetUnhandledExceptionFilter( m_previousFilter );
}

//==============================================================
// Lets user change the name of the report file to be generated 
//==============================================================
void WheatyExceptionReport::SetLogFileName( PTSTR pszLogFileName )
{
    _tcscpy( m_szLogFileName, pszLogFileName );
}

//===========================================================
// Entry point where control comes on an unhandled exception 
//===========================================================
LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter(
                                    PEXCEPTION_POINTERS pExceptionInfo )
{
	if (!m_bFirstRun)
	{
		if (m_previousFilter)
			return m_previousFilter( pExceptionInfo );
		else
			return EXCEPTION_CONTINUE_SEARCH;
	}
	else
		m_bFirstRun = FALSE;
		
	HMODULE hDll = LoadLibrary( _T("dbghelp.dll") );
	if (!hDll)
	{
		if ( m_previousFilter )
			return m_previousFilter( pExceptionInfo );
		else
			return EXCEPTION_CONTINUE_SEARCH;
	}
	
	pSymCleanup				= (tSymCleanup)GetProcAddress(hDll, "SymCleanup");
	pSymInitialize			= (tSymInitialize)GetProcAddress(hDll, "SymInitialize");
	pSymGetOptions			= (tSymGetOptions)GetProcAddress(hDll, "SymGetOptions");
	pSymSetOptions			= (tSymSetOptions)GetProcAddress(hDll, "SymSetOptions");
	pSymEnumSymbols			= (tSymEnumSymbols)GetProcAddress(hDll, "SymEnumSymbols");
	pSymSetContext			= (tSymSetContext)GetProcAddress(hDll, "SymSetContext");
	pSymGetLineFromAddr		= (tSymGetLineFromAddr)GetProcAddress(hDll, "SymGetLineFromAddr");
	pSymFromAddr			= (tSymFromAddr)GetProcAddress(hDll, "SymFromAddr");
	pStackWalk				= (tStackWalk)GetProcAddress(hDll, "StackWalk");
	pSymFunctionTableAccess	= (tSymFunctionTableAccess)GetProcAddress(hDll, "SymFunctionTableAccess");
	pSymGetModuleBase		= (tSymGetModuleBase)GetProcAddress(hDll, "SymGetModuleBase");
	pSymGetTypeInfo			= (tSymGetTypeInfo)GetProcAddress(hDll, "SymGetTypeInfo");
	pMiniDumpWriteDump		= (tMiniDumpWriteDump)GetProcAddress(hDll, "MiniDumpWriteDump");
	
	if (!pSymCleanup			||
		!pSymInitialize			||
		!pSymGetOptions			||
		!pSymSetOptions			||
		!pSymEnumSymbols		||
		!pSymSetContext			||
		!pSymGetLineFromAddr	||
		!pSymFromAddr			||
		!pStackWalk				||
		!pSymFunctionTableAccess||
		!pSymGetModuleBase		||
		!pSymGetTypeInfo		||
		!pMiniDumpWriteDump)
	{
		FreeLibrary(hDll);
		if ( m_previousFilter )
			return m_previousFilter( pExceptionInfo );
		else
			return EXCEPTION_CONTINUE_SEARCH;
	}
	
	if (::MessageBox( NULL, 
_T("An unhandled exception has occurred in FileZilla\r\n\
FileZilla has to be closed.\r\n\r\n\
Would you like to generate an exception report?\r\n\
The report contains all neccessary information about the exception,\r\n\
including a call stack with function parameters and local variables.\r\n\r\n\
If you're using the latest version of FileZilla, please send the generated exception record to the following mail address: Tim.Kosse@gmx.de\r\n\
The report will be analyzed and the reason for this exception will be fixed in the next version of FileZilla.\r\n\r\n\
Please note: It may be possible - though unlikely - that the exception report may contain personal and or confidential information. All exception reports will be processed higly confidential and solely to analyze the crash. The reports will be deleted immediately after processing.\r\n"),
		_T("FileZilla - Unhandled exception"), MB_APPLMODAL | MB_YESNO | MB_ICONSTOP)==IDYES)
	{
		m_hReportFile = CreateFile( m_szLogFileName,
										GENERIC_WRITE,
										FILE_SHARE_READ,
										0,
										CREATE_ALWAYS,
										FILE_FLAG_WRITE_THROUGH,
										0 );
		
		m_hDumpFile = CreateFile( m_szDmpFileName,
										GENERIC_WRITE,
										FILE_SHARE_READ,
										0,
										CREATE_ALWAYS,
										FILE_FLAG_WRITE_THROUGH,
										0 );
		
		if (!m_hReportFile)
		{
			TCHAR tmp[MAX_PATH];
			_tcscpy(tmp, m_szLogFileName);
			TCHAR *pos=_tcsrchr(tmp, '\\');
			if (pos)
			{
				pos++;
				_stprintf(m_szLogFileName, _T("c:\\%s"), pos);
			}
			else
				_stprintf(m_szLogFileName, _T("c:\\%s"), tmp);
			
			m_hReportFile = CreateFile( m_szLogFileName,
										GENERIC_WRITE,
										0,
										0,
										CREATE_ALWAYS,
										FILE_FLAG_WRITE_THROUGH,
										0 );
		
		}
		if (!m_hDumpFile && m_hReportFile)
		{
			TCHAR tmp[MAX_PATH];
			_tcscpy(tmp, m_szDmpFileName);
			TCHAR *pos=_tcsrchr(tmp, '\\');
			if (pos)
			{
				pos++;
				_stprintf(m_szDmpFileName, _T("c:\\%s"), pos);
			}
			else
				_stprintf(m_szDmpFileName, _T("c:\\%s"), tmp);
			
			m_hDumpFile = CreateFile( m_szDmpFileName,
										GENERIC_WRITE,
										0,
										0,
										CREATE_ALWAYS,
										FILE_FLAG_WRITE_THROUGH,
										0 );
		
		}
	
		int nError=0;
	    if ( m_hReportFile && m_hDumpFile)
	    {
		  #ifdef TRY
			TRY
		  #endif
			{
				writeMiniDump(pExceptionInfo);
				GenerateExceptionReport( pExceptionInfo );
	
				CloseHandle( m_hReportFile );
				m_hReportFile = 0;
			}
          #ifdef TRY
			CATCH_ALL(e);
			{
				nError=GetLastError();

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?