mirror of
https://github.com/jmarshall23/Hellfire.git
synced 2026-08-12 07:50:53 +02:00
Initial commit.
This commit is contained in:
+286
@@ -0,0 +1,286 @@
|
||||
//******************************************************************
|
||||
// except.cpp
|
||||
//******************************************************************
|
||||
|
||||
|
||||
#include "diablo.h"
|
||||
#pragma hdrstop
|
||||
#include <tchar.h>
|
||||
|
||||
|
||||
//******************************************************************
|
||||
// private
|
||||
//******************************************************************
|
||||
class CExcept {
|
||||
public:
|
||||
CExcept();
|
||||
~CExcept();
|
||||
|
||||
private:
|
||||
// entry point where control comes on an unhandled exception
|
||||
static LONG WINAPI ExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo);
|
||||
|
||||
// variables used by the class
|
||||
static TCHAR m_szLogFileName[MAX_PATH];
|
||||
static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter;
|
||||
};
|
||||
|
||||
TCHAR CExcept::m_szLogFileName[MAX_PATH];
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER CExcept::m_previousFilter;
|
||||
static CExcept g_CExcept;
|
||||
|
||||
|
||||
//******************************************************************
|
||||
//******************************************************************
|
||||
static void __cdecl tprintf(HANDLE hFile,LPCTSTR pszFmt,...) {
|
||||
va_list argptr;
|
||||
DWORD cbWritten;
|
||||
TCHAR szBuf[1024];
|
||||
va_start(argptr,pszFmt);
|
||||
int nChars = wvsprintf(szBuf,pszFmt,argptr);
|
||||
WriteFile(hFile,szBuf,nChars * sizeof(TCHAR),&cbWritten,0);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
|
||||
//******************************************************************
|
||||
// Given a linear address,locates the module,section,and offset containing
|
||||
// that address.
|
||||
//
|
||||
// Note: the szModule paramater buffer is an output buffer of length specified
|
||||
// by the len parameter (in characters!)
|
||||
//******************************************************************
|
||||
static BOOL GetLogicalAddress(
|
||||
PVOID addr,
|
||||
PTSTR szModule,
|
||||
DWORD len,
|
||||
DWORD *pdwSection,
|
||||
DWORD *pdwOffset
|
||||
) {
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
if (!VirtualQuery(addr,&mbi,sizeof(mbi)))
|
||||
return FALSE;
|
||||
|
||||
DWORD hMod = (DWORD)mbi.AllocationBase;
|
||||
if (!GetModuleFileName((HMODULE)hMod,szModule,len))
|
||||
return FALSE;
|
||||
|
||||
// Point to the DOS header in memory
|
||||
PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod;
|
||||
|
||||
// From the DOS header,find the NT (PE) header
|
||||
PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(hMod + pDosHdr->e_lfanew);
|
||||
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHdr);
|
||||
DWORD rva = (DWORD)addr - hMod; // RVA is offset from module load address
|
||||
|
||||
// Iterate through the section table,looking for the one that encompasses
|
||||
// the linear address.
|
||||
for (
|
||||
unsigned i = 0;
|
||||
i < pNtHdr->FileHeader.NumberOfSections;
|
||||
i++,pSection++
|
||||
) {
|
||||
DWORD sectionStart = pSection->VirtualAddress;
|
||||
DWORD sectionEnd = sectionStart
|
||||
+ max(pSection->SizeOfRawData,pSection->Misc.VirtualSize);
|
||||
|
||||
// Is the address in this section???
|
||||
if ((rva >= sectionStart) && (rva <= sectionEnd)) {
|
||||
// Yes,address is in the section. Calculate section and offset
|
||||
*pdwSection = i+1;
|
||||
*pdwOffset = rva - sectionStart;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE; // Should never get here!
|
||||
}
|
||||
|
||||
|
||||
//******************************************************************
|
||||
//******************************************************************
|
||||
static void IntelStackWalk(HANDLE hFile,PCONTEXT pContext) {
|
||||
tprintf(hFile,_T("\r\nCall stack:\r\n"));
|
||||
tprintf(hFile,_T("Address Frame Logical addr Module\r\n"));
|
||||
|
||||
DWORD pc = pContext->Eip;
|
||||
PDWORD pFrame,pPrevFrame;
|
||||
pFrame = (PDWORD)pContext->Ebp;
|
||||
while (1) {
|
||||
TCHAR szModule[MAX_PATH] = _T("");
|
||||
DWORD section = 0,offset = 0;
|
||||
|
||||
GetLogicalAddress((PVOID)pc,szModule,sizeof(szModule),§ion,&offset);
|
||||
tprintf(hFile,_T("%08X %08X %04X:%08X %s\r\n"),
|
||||
pc,pFrame,section,offset,szModule);
|
||||
|
||||
// precede to next higher frame on stack
|
||||
pc = pFrame[1];
|
||||
pPrevFrame = pFrame;
|
||||
pFrame = (PDWORD)pFrame[0];
|
||||
// Frame pointer must be aligned on a DWORD boundary
|
||||
if ((DWORD)pFrame & 3) break;
|
||||
if (pFrame <= pPrevFrame) break;
|
||||
|
||||
// Can two DWORDs be read from the supposed frame address?
|
||||
if (IsBadWritePtr(pFrame,sizeof(PVOID)*2)) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//******************************************************************
|
||||
//******************************************************************
|
||||
static LPTSTR GetExceptionString(DWORD dwCode) {
|
||||
#define EXCEPTION(x) case EXCEPTION_##x: return _T(#x);
|
||||
switch (dwCode) {
|
||||
EXCEPTION(ACCESS_VIOLATION)
|
||||
EXCEPTION(DATATYPE_MISALIGNMENT)
|
||||
EXCEPTION(BREAKPOINT)
|
||||
EXCEPTION(SINGLE_STEP)
|
||||
EXCEPTION(ARRAY_BOUNDS_EXCEEDED)
|
||||
EXCEPTION(FLT_DENORMAL_OPERAND)
|
||||
EXCEPTION(FLT_DIVIDE_BY_ZERO)
|
||||
EXCEPTION(FLT_INEXACT_RESULT)
|
||||
EXCEPTION(FLT_INVALID_OPERATION)
|
||||
EXCEPTION(FLT_OVERFLOW)
|
||||
EXCEPTION(FLT_STACK_CHECK)
|
||||
EXCEPTION(FLT_UNDERFLOW)
|
||||
EXCEPTION(INT_DIVIDE_BY_ZERO)
|
||||
EXCEPTION(INT_OVERFLOW)
|
||||
EXCEPTION(PRIV_INSTRUCTION)
|
||||
EXCEPTION(IN_PAGE_ERROR)
|
||||
EXCEPTION(ILLEGAL_INSTRUCTION)
|
||||
EXCEPTION(NONCONTINUABLE_EXCEPTION)
|
||||
EXCEPTION(STACK_OVERFLOW)
|
||||
EXCEPTION(INVALID_DISPOSITION)
|
||||
EXCEPTION(GUARD_PAGE)
|
||||
EXCEPTION(INVALID_HANDLE)
|
||||
}
|
||||
#undef EXCEPTION
|
||||
|
||||
// If not one of the "known" exceptions, try to
|
||||
// get the string from NTDLL.DLL's message table.
|
||||
static TCHAR szBuf[512] = { 0 };
|
||||
FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
|
||||
GetModuleHandle(_T("NTDLL.DLL")),
|
||||
dwCode,0,szBuf,sizeof(szBuf),0);
|
||||
return szBuf;
|
||||
}
|
||||
|
||||
|
||||
//******************************************************************
|
||||
//******************************************************************
|
||||
static void GenerateExceptionReport(HANDLE hFile,PEXCEPTION_POINTERS pExceptionInfo) {
|
||||
PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
|
||||
|
||||
// First print information about the type of fault
|
||||
tprintf(hFile,_T("Exception code: %08X %s\r\n"),
|
||||
pExceptionRecord->ExceptionCode,
|
||||
GetExceptionString(pExceptionRecord->ExceptionCode));
|
||||
|
||||
// Now print information about where the fault occured
|
||||
TCHAR szFaultingModule[MAX_PATH];
|
||||
DWORD section,offset;
|
||||
GetLogicalAddress(pExceptionRecord->ExceptionAddress,
|
||||
szFaultingModule,
|
||||
sizeof(szFaultingModule),
|
||||
§ion,&offset);
|
||||
|
||||
tprintf(hFile,_T("Fault address: %08X %02X:%08X %s\r\n"),
|
||||
pExceptionRecord->ExceptionAddress,
|
||||
section,offset,szFaultingModule);
|
||||
|
||||
PCONTEXT pCtx = pExceptionInfo->ContextRecord;
|
||||
|
||||
// Show the registers
|
||||
#ifdef _M_IX86 // Intel Only!
|
||||
tprintf(hFile,_T("\r\nRegisters:\r\n"));
|
||||
|
||||
tprintf(hFile,_T("EAX:%08X\r\nEBX:%08X\r\nECX:%08X\r\nEDX:%08X\r\nESI:%08X\r\nEDI:%08X\r\n"),
|
||||
pCtx->Eax,pCtx->Ebx,pCtx->Ecx,pCtx->Edx,pCtx->Esi,pCtx->Edi);
|
||||
|
||||
tprintf(hFile,_T("CS:EIP:%04X:%08X\r\n"),pCtx->SegCs,pCtx->Eip);
|
||||
tprintf(hFile,_T("SS:ESP:%04X:%08X EBP:%08X\r\n"),
|
||||
pCtx->SegSs,pCtx->Esp,pCtx->Ebp);
|
||||
tprintf(hFile,_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"),
|
||||
pCtx->SegDs,pCtx->SegEs,pCtx->SegFs,pCtx->SegGs);
|
||||
tprintf(hFile,_T("Flags:%08X\r\n"),pCtx->EFlags);
|
||||
|
||||
// Walk the stack using x86 specific code
|
||||
IntelStackWalk(hFile,pCtx);
|
||||
|
||||
#endif
|
||||
|
||||
tprintf(hFile,_T("\r\n"));
|
||||
}
|
||||
|
||||
|
||||
//******************************************************************
|
||||
//******************************************************************
|
||||
LONG WINAPI CExcept::ExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo) {
|
||||
|
||||
// try opening the error report file in the program directory
|
||||
// if we can't open the file, it may be because the app
|
||||
// is running from a CDROM drive -- try opening a file
|
||||
// with the same name in c:
|
||||
HANDLE hFile;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
hFile = CreateFile(
|
||||
m_szLogFileName,
|
||||
GENERIC_WRITE,
|
||||
0,
|
||||
0,
|
||||
OPEN_ALWAYS,
|
||||
FILE_FLAG_WRITE_THROUGH,
|
||||
0
|
||||
);
|
||||
if (hFile != INVALID_HANDLE_VALUE) break;
|
||||
|
||||
// extract the file name
|
||||
LPTSTR lpFName = _tcsrchr(m_szLogFileName,_T('\\'));
|
||||
if (! lpFName) break;
|
||||
|
||||
// create full path to file in C:
|
||||
TCHAR szTemp[MAX_PATH] = _T("c:\\");
|
||||
_tcscat(szTemp,lpFName);
|
||||
_tcscpy(m_szLogFileName,szTemp);
|
||||
}
|
||||
|
||||
if (hFile != INVALID_HANDLE_VALUE) {
|
||||
SetFilePointer(hFile,0,0,FILE_END);
|
||||
GenerateExceptionReport(hFile,pExceptionInfo);
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
||||
if (m_previousFilter) return m_previousFilter(pExceptionInfo);
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
|
||||
//******************************************************************
|
||||
//******************************************************************
|
||||
CExcept::CExcept() {
|
||||
// Install the unhandled exception filter function
|
||||
m_previousFilter = SetUnhandledExceptionFilter(ExceptionFilter);
|
||||
|
||||
// Figure out what the report file will be named,and store it away
|
||||
GetModuleFileName(0,m_szLogFileName,MAX_PATH);
|
||||
|
||||
// replace .EXE with .ERR
|
||||
PTSTR pszDot = _tcsrchr(m_szLogFileName,_T('.'));
|
||||
if (pszDot) {
|
||||
pszDot++;
|
||||
if (_tcslen(pszDot) >= 3)
|
||||
_tcscpy(pszDot,_T("ERR"));
|
||||
}
|
||||
|
||||
// delete any old exception reports
|
||||
DeleteFile(m_szLogFileName);
|
||||
}
|
||||
|
||||
|
||||
//******************************************************************
|
||||
//******************************************************************
|
||||
CExcept::~CExcept() {
|
||||
SetUnhandledExceptionFilter(m_previousFilter);
|
||||
}
|
||||
Reference in New Issue
Block a user