EXCEPTION_DISPOSITION exceptionHandler(struct _EXCEPTION_RECORD* pExceptionRec, void* pEstablisherFrame, struct _CONTEXT* pContextRecord, void* pDispatcherContext) { fflush(stderr); fflush(stdout); static int running=0; if(running) exit(1); running=1; if(mysaveFunction) mysaveFunction(); if(myFatalFunction) myFatalFunction ("Crash","Press ok to build crash info"); void* currentProcessId = GetCurrentProcess(); SymInitialize(currentProcessId, NULL, TRUE); dumpExceptionInfo(currentProcessId, pExceptionRec, pContextRecord); fflush(stdout); dumpBackTrace(currentProcessId); SymCleanup(currentProcessId); exit(1); }
void WINAPI EXC_RtlRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context ) { PEXCEPTION_FRAME frame, dispatch, nested_frame; EXCEPTION_RECORD newrec; EXCEPTION_POINTERS epointers; DWORD res, c; if (((unsigned long)(rec->ExceptionAddress) & 0xffff0000) == 0xdead0000) ERR("possibly COM stub exception at %p\n", rec->ExceptionAddress); TRACE( "code=%lx flags=%lx addr=%p\n", rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress ); for (c=0; c<rec->NumberParameters; c++) TRACE(" info[%ld]=%08lx\n", c, rec->ExceptionInformation[c]); if (rec->ExceptionCode == EXCEPTION_WINE_STUB) TRACE(" stub=%s\n", (char*)rec->ExceptionInformation[1]); /* TRACE( " backtrace %s\n", debugstack(10, context) ); */ if (send_debug_event( rec, TRUE, context ) == DBG_CONTINUE) return; /* continue execution */ SIGNAL_Unblock(); /* we may be in a signal handler, and exception handlers may jump out */ frame = NtCurrentTeb()->except; nested_frame = NULL; while (frame != (PEXCEPTION_FRAME)0xFFFFFFFF) { /* Check frame address */ if (((void*)frame < NtCurrentTeb()->stack_low) || ((void*)(frame+1) > NtCurrentTeb()->stack_top) || (int)frame & 3) { WARN ("Marking as invalid. Frame: %p, stack_low: %p, Frame+1: %p, stack_top: %p, frame&3: %d\n", (void *)frame, NtCurrentTeb ()->stack_low, (void *)(frame+1), NtCurrentTeb ()->stack_top, (int)frame & 3); rec->ExceptionFlags |= EH_STACK_INVALID; break; } /* Call handler */ res = EXC_CallHandler( rec, frame, context, &dispatch, frame->Handler, EXC_RaiseHandler ); if (frame == nested_frame) { /* no longer nested */ nested_frame = NULL; rec->ExceptionFlags &= ~EH_NESTED_CALL; } switch(res) { case ExceptionContinueExecution: if (!(rec->ExceptionFlags & EH_NONCONTINUABLE)) return; newrec.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION; newrec.ExceptionFlags = EH_NONCONTINUABLE; newrec.ExceptionRecord = rec; newrec.NumberParameters = 0; RtlRaiseException( &newrec ); /* never returns */ break; case ExceptionContinueSearch: break; case ExceptionNestedException: if (nested_frame < dispatch) nested_frame = dispatch; rec->ExceptionFlags |= EH_NESTED_CALL; break; case ExceptionCollidedUnwind: /* Check for having gotten into an infinite exception loop due to a busted exception frame somewhere */ if (rec->ExceptionCode == STATUS_INVALID_DISPOSITION) EXC_DefaultHandling (rec, context); default: newrec.ExceptionCode = STATUS_INVALID_DISPOSITION; newrec.ExceptionFlags = EH_NONCONTINUABLE; newrec.ExceptionRecord = rec; newrec.NumberParameters = 0; /* dump the crash report here since the next RtlRaiseException() call will never return and the exception info from this point on will be clobbered. */ epointers.ContextRecord = context; epointers.ExceptionRecord = rec; if (!dumpExceptionInfo(&epointers, NTDLL_CRASHREPORTFILENAME, NTDLL_MINIDUMPFILENAME)) ERR("ERROR-> could not dump the crash report\n"); RtlRaiseException( &newrec ); /* never returns */ break; } frame = frame->Prev; } EXC_DefaultHandling( rec, context ); }