int FunctionC(int x, int y)
{
char *p = (char *)0xBADC0DE; // Ummm!!, a dirty bad thing
// Create a access violation
char c = *p;
return 0;
}
int FunctionB(int x)
{
return FunctionC(x, 16);
}
int FunctionA()
{
return FunctionB(100);
}
int main(int argc, char *argv[])
{
InstallWin32FaultHandler();
FunctionA();
return 0;
}
Listing One: FaultApp, with three functions calling each other.
LONG Win32FaultHandler(struct _EXCEPTION_POINTERS * ExInfo)
{ char *FaultTx = "";
switch(ExInfo->ExceptionRecord->ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION :
FaultTx = "ACCESS VIOLATION" ; break;
case EXCEPTION_DATATYPE_MISALIGNMENT :
FaultTx = "DATATYPE MISALIGNMENT" ; break;
case EXCEPTION_FLT_DIVIDE_BY_ZERO :
FaultTx = "FLT DIVIDE BY ZERO" ; break;
...
default: FaultTx = "(unknown)"; break;
}
sgLogFile = fopen("Win32Fault.log", "w");
int wsFault = ExInfo->ExceptionRecord->ExceptionCode;
PVOID CodeAdress = ExInfo->ExceptionRecord->ExceptionAddress;
sgLogFile = fopen("Win32Fault.log", "w");
if(sgLogFile != NULL)
{
fprintf(sgLogFile, "****************************************************\n");
fprintf(sgLogFile, "*** A Program Fault occurred:\n");
fprintf(sgLogFile, "*** Error code %08X: %s\n", wsFault, FaultTx);
fprintf(sgLogFile, "****************************************************\n");
fprintf(sgLogFile, "*** Address: %08X\n", (int)CodeAdress);
fprintf(sgLogFile, "*** Flags: %08X\n",
ExInfo->ExceptionRecord->ExceptionFlags);
LogStackFrames(CodeAddress, (char *)ExInfo->ContextRecord->Ebp);
fclose(sgLogFile);
}
/*if(want to continue)
{
ExInfo->ContextRecord->Eip++;
return EXCEPTION_CONTINUE_EXECUTION;
}
*/
return EXCEPTION_EXECUTE_HANDLER;
}
Listing Two: Win32FaultHandler.
void InstallFaultHandler()
{
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER) Win32FaultHandler);
}
Listing Three: InstallFaultHandler().
void LogStackFrames(PVOID FaultAddress, char *eNextBP)
{ char *p, *pBP;
unsigned i, x, BpPassed;
static int CurrentlyInTheStackDump = 0;
...
BpPassed = (eNextBP != NULL);
if(! eNextBP)
{
_asm mov eNextBP, eBp
}
else
fprintf(sgLogFile, "\n Fault Occurred At $ADDRESS:%08LX\n",
(int)FaultAddress);
// prevent infinite loops
for(i = 0; eNextBP && i < 100; i++)
{
pBP = eNextBP; // keep current BasePointer
eNextBP = *(char **)pBP; // dereference next BP
p = pBP + 8;
// Write 20 Bytes of potential arguments
fprintf(sgLogFile, " with ");
for(x = 0; p < eNextBP && x < 20; p++, x++)
fprintf(sgLogFile, "%02X ", *(unsigned char *)p);
fprintf(sgLogFile, "\n\n");
if(i == 1 && ! BpPassed)
fprintf(sgLogFile, "*************************************\n"
" Fault Occurred Here:\n");
// Write the backjump address
fprintf(sgLogFile, "*** %2d called from $ADDRESS:%08LX\n",
i, *(char **)(pBP + 4));
if(*(char **)(pBP + 4) == NULL)
break;
}
...
}
Listing Four: LogStackFrames.