/*********************************************************************** * RtlRaiseStatus (NTDLL.@) * * Raise an exception with ExceptionCode = status */ void WINAPI RtlRaiseStatus( NTSTATUS status ) { EXCEPTION_RECORD ExceptionRec; ExceptionRec.ExceptionCode = status; ExceptionRec.ExceptionFlags = EH_NONCONTINUABLE; ExceptionRec.ExceptionRecord = NULL; ExceptionRec.NumberParameters = 0; RtlRaiseException( &ExceptionRec ); }
/******************************************************************* * RaiseException (KERNEL32.@) */ void WINAPI RaiseException( DWORD code, DWORD flags, DWORD nbargs, const ULONG_PTR *args ) { EXCEPTION_RECORD record; /* Compose an exception record */ record.ExceptionCode = code; record.ExceptionFlags = flags & EH_NONCONTINUABLE; record.ExceptionRecord = NULL; record.ExceptionAddress = RaiseException; if (nbargs && args) { if (nbargs > EXCEPTION_MAXIMUM_PARAMETERS) nbargs = EXCEPTION_MAXIMUM_PARAMETERS; record.NumberParameters = nbargs; memcpy( record.ExceptionInformation, args, nbargs * sizeof(*args) ); } else record.NumberParameters = 0; RtlRaiseException( &record ); }
VOID RtlRaiseStatus ( IN NTSTATUS Status ) /*++ Routine Description: This function raises an exception with the specified status value. The exception is marked as continuable with no parameters. Arguments: Status - Supplies the status value to be used as the exception code for the exception that is to be raised. Return Value: None. --*/ { EXCEPTION_RECORD ExceptionRecord; // // Construct an exception record. // ExceptionRecord.ExceptionCode = Status; ExceptionRecord.ExceptionRecord = (PEXCEPTION_RECORD)NULL; ExceptionRecord.NumberParameters = 0; ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE; RtlRaiseException(&ExceptionRecord); return; }
/* * @implemented */ BOOLEAN NTAPI RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT Context) { PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, NestedFrame = NULL; DISPATCHER_CONTEXT DispatcherContext; EXCEPTION_RECORD ExceptionRecord2; EXCEPTION_DISPOSITION Disposition; ULONG_PTR StackLow, StackHigh; ULONG_PTR RegistrationFrameEnd; /* Perform vectored exception handling (a dummy in kernel mode) */ if (RtlCallVectoredExceptionHandlers(ExceptionRecord, Context)) { /* Exception handled, continue execution */ return TRUE; } /* Get the current stack limits and registration frame */ RtlpGetStackLimits(&StackLow, &StackHigh); RegistrationFrame = RtlpGetExceptionList(); /* Now loop every frame */ while (RegistrationFrame != EXCEPTION_CHAIN_END) { /* Registration chain entries are never NULL */ ASSERT(RegistrationFrame != NULL); /* Find out where it ends */ RegistrationFrameEnd = (ULONG_PTR)RegistrationFrame + sizeof(EXCEPTION_REGISTRATION_RECORD); /* Make sure the registration frame is located within the stack */ if ((RegistrationFrameEnd > StackHigh) || ((ULONG_PTR)RegistrationFrame < StackLow) || ((ULONG_PTR)RegistrationFrame & 0x3)) { /* Check if this happened in the DPC Stack */ if (RtlpHandleDpcStackException(RegistrationFrame, RegistrationFrameEnd, &StackLow, &StackHigh)) { /* Use DPC Stack Limits and restart */ continue; } /* Set invalid stack and return false */ ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID; return FALSE; } /* Check if logging is enabled */ RtlpCheckLogException(ExceptionRecord, Context, RegistrationFrame, sizeof(*RegistrationFrame)); /* Call the handler */ Disposition = RtlpExecuteHandlerForException(ExceptionRecord, RegistrationFrame, Context, &DispatcherContext, RegistrationFrame->Handler); /* Check if this is a nested frame */ if (RegistrationFrame == NestedFrame) { /* Mask out the flag and the nested frame */ ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NESTED_CALL; NestedFrame = NULL; } /* Handle the dispositions */ switch (Disposition) { /* Continue searching */ case ExceptionContinueExecution: /* Check if it was non-continuable */ if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) { /* Set up the exception record */ ExceptionRecord2.ExceptionRecord = ExceptionRecord; ExceptionRecord2.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION; ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; ExceptionRecord2.NumberParameters = 0; /* Raise the exception */ RtlRaiseException(&ExceptionRecord2); } else { /* Return to caller */ return TRUE; } /* Continue searching */ case ExceptionContinueSearch: break; /* Nested exception */ case ExceptionNestedException: /* Turn the nested flag on */ ExceptionRecord->ExceptionFlags |= EXCEPTION_NESTED_CALL; /* Update the current nested frame */ if (DispatcherContext.RegistrationPointer > NestedFrame) { /* Get the frame from the dispatcher context */ NestedFrame = DispatcherContext.RegistrationPointer; } break; /* Anything else */ default: /* Set up the exception record */ ExceptionRecord2.ExceptionRecord = ExceptionRecord; ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION; ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; ExceptionRecord2.NumberParameters = 0; /* Raise the exception */ RtlRaiseException(&ExceptionRecord2); break; } /* Go to the next frame */ RegistrationFrame = RegistrationFrame->Next; } /* Unhandled, return false */ return FALSE; }
/* * @implemented */ VOID NTAPI RtlUnwind(IN PVOID TargetFrame OPTIONAL, IN PVOID TargetIp OPTIONAL, IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL, IN PVOID ReturnValue) { PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, OldFrame; DISPATCHER_CONTEXT DispatcherContext; EXCEPTION_RECORD ExceptionRecord2, ExceptionRecord3; EXCEPTION_DISPOSITION Disposition; ULONG_PTR StackLow, StackHigh; ULONG_PTR RegistrationFrameEnd; CONTEXT LocalContext; PCONTEXT Context; /* Get the current stack limits */ RtlpGetStackLimits(&StackLow, &StackHigh); /* Check if we don't have an exception record */ if (!ExceptionRecord) { /* Overwrite the argument */ ExceptionRecord = &ExceptionRecord3; /* Setup a local one */ ExceptionRecord3.ExceptionFlags = 0; ExceptionRecord3.ExceptionCode = STATUS_UNWIND; ExceptionRecord3.ExceptionRecord = NULL; ExceptionRecord3.ExceptionAddress = _ReturnAddress(); ExceptionRecord3.NumberParameters = 0; } /* Check if we have a frame */ if (TargetFrame) { /* Set it as unwinding */ ExceptionRecord->ExceptionFlags |= EXCEPTION_UNWINDING; } else { /* Set the Exit Unwind flag as well */ ExceptionRecord->ExceptionFlags |= (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND); } /* Now capture the context */ Context = &LocalContext; LocalContext.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS; RtlpCaptureContext(Context); /* Pop the current arguments off */ Context->Esp += sizeof(TargetFrame) + sizeof(TargetIp) + sizeof(ExceptionRecord) + sizeof(ReturnValue); /* Set the new value for EAX */ Context->Eax = (ULONG)ReturnValue; /* Get the current frame */ RegistrationFrame = RtlpGetExceptionList(); /* Now loop every frame */ while (RegistrationFrame != EXCEPTION_CHAIN_END) { /* Registration chain entries are never NULL */ ASSERT(RegistrationFrame != NULL); /* If this is the target */ if (RegistrationFrame == TargetFrame) ZwContinue(Context, FALSE); /* Check if the frame is too low */ if ((TargetFrame) && ((ULONG_PTR)TargetFrame < (ULONG_PTR)RegistrationFrame)) { /* Create an invalid unwind exception */ ExceptionRecord2.ExceptionCode = STATUS_INVALID_UNWIND_TARGET; ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; ExceptionRecord2.ExceptionRecord = ExceptionRecord; ExceptionRecord2.NumberParameters = 0; /* Raise the exception */ RtlRaiseException(&ExceptionRecord2); } /* Find out where it ends */ RegistrationFrameEnd = (ULONG_PTR)RegistrationFrame + sizeof(EXCEPTION_REGISTRATION_RECORD); /* Make sure the registration frame is located within the stack */ if ((RegistrationFrameEnd > StackHigh) || ((ULONG_PTR)RegistrationFrame < StackLow) || ((ULONG_PTR)RegistrationFrame & 0x3)) { /* Check if this happened in the DPC Stack */ if (RtlpHandleDpcStackException(RegistrationFrame, RegistrationFrameEnd, &StackLow, &StackHigh)) { /* Use DPC Stack Limits and restart */ continue; } /* Create an invalid stack exception */ ExceptionRecord2.ExceptionCode = STATUS_BAD_STACK; ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; ExceptionRecord2.ExceptionRecord = ExceptionRecord; ExceptionRecord2.NumberParameters = 0; /* Raise the exception */ RtlRaiseException(&ExceptionRecord2); } else { /* Call the handler */ Disposition = RtlpExecuteHandlerForUnwind(ExceptionRecord, RegistrationFrame, Context, &DispatcherContext, RegistrationFrame->Handler); switch(Disposition) { /* Continue searching */ case ExceptionContinueSearch: break; /* Collission */ case ExceptionCollidedUnwind : /* Get the original frame */ RegistrationFrame = DispatcherContext.RegistrationPointer; break; /* Anything else */ default: /* Set up the exception record */ ExceptionRecord2.ExceptionRecord = ExceptionRecord; ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION; ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; ExceptionRecord2.NumberParameters = 0; /* Raise the exception */ RtlRaiseException(&ExceptionRecord2); break; } /* Go to the next frame */ OldFrame = RegistrationFrame; RegistrationFrame = RegistrationFrame->Next; /* Remove this handler */ RtlpSetExceptionList(OldFrame); } } /* Check if we reached the end */ if (TargetFrame == EXCEPTION_CHAIN_END) { /* Unwind completed, so we don't exit */ ZwContinue(Context, FALSE); } else { /* This is an exit_unwind or the frame wasn't present in the list */ ZwRaiseException(ExceptionRecord, Context, FALSE); } }
DWORD CtrlRoutine( IN LPVOID lpThreadParameter ) /*++ Routine Description: This thread is created when ctrl-c or ctrl-break is entered, or when close is selected. it calls the appropriate handlers. Arguments: lpThreadParameter - what type of event happened. Return Value: STATUS_SUCCESS --*/ { ULONG i; ULONG EventNumber,OriginalEventNumber; DWORD fNoExit; DWORD dwExitCode; EXCEPTION_RECORD ExceptionRecord; SetThreadPriority(NtCurrentThread(), THREAD_PRIORITY_HIGHEST); OriginalEventNumber = EventNumber = PtrToUlong(lpThreadParameter); // // If this bit is set, it means we don't want to cause this process // to exit itself if it is a logoff or shutdown event. // fNoExit = 0x80000000 & EventNumber; EventNumber &= ~0x80000000; // // the ctrl_close event is set when the user selects the window // close option from the system menu, or EndTask, or Settings-Terminate. // the system close event is used when another ctrl-thread times out. // switch (EventNumber) { default: ASSERT (EventNumber < NUMBER_OF_CTRL_EVENTS); if (EventNumber >= NUMBER_OF_CTRL_EVENTS) return (DWORD)STATUS_UNSUCCESSFUL; break; case CTRL_C_EVENT: case CTRL_BREAK_EVENT: // // If the process is being debugged, give the debugger // a shot. If the debugger handles the exception, then // go back and wait. // if (!IsDebuggerPresent()) break; if ( EventNumber == CTRL_C_EVENT ) { ExceptionRecord.ExceptionCode = DBG_CONTROL_C; } else { ExceptionRecord.ExceptionCode = DBG_CONTROL_BREAK; } ExceptionRecord.ExceptionFlags = 0; ExceptionRecord.ExceptionRecord = NULL; ExceptionRecord.ExceptionAddress = (PVOID)DefaultHandler; ExceptionRecord.NumberParameters = 0; try { RtlRaiseException(&ExceptionRecord); } except (EXCEPTION_EXECUTE_HANDLER) { LockDll(); try { if (EventNumber != CTRL_C_EVENT || NtCurrentPeb()->ProcessParameters->ConsoleFlags != IGNORE_CTRL_C) { for (i=HandlerListLength; i>0; i--) { if ((HandlerList[i-1])(EventNumber)) { break; } } } } finally { UnlockDll(); } } ExitThread(0); break; case SYSTEM_CLOSE_EVENT: ExitProcess((DWORD)CONTROL_C_EXIT); break; case SYSTEM_ROOT_CONSOLE_EVENT: if (!LastConsoleEventActive) ExitThread(0); break; case CTRL_CLOSE_EVENT: case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: //if (LastConsoleEventActive) //EventNumber = SYSTEM_ROOT_CONSOLE_EVENT; break; } LockDll(); dwExitCode = 0; try { if (EventNumber != CTRL_C_EVENT || NtCurrentPeb()->ProcessParameters->ConsoleFlags != IGNORE_CTRL_C) { for (i=HandlerListLength; i>0; i--) { // // Don't call the last handler (the default one which calls // ExitProcess() if this process isn't supposed to exit (system // process are not supposed to exit because of shutdown or // logoff event notification). // if ((i-1) == 0 && fNoExit) { if (EventNumber == CTRL_LOGOFF_EVENT || EventNumber == CTRL_SHUTDOWN_EVENT) { break; } } if ((HandlerList[i-1])(EventNumber)) { switch (EventNumber) { case CTRL_CLOSE_EVENT: case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: case SYSTEM_ROOT_CONSOLE_EVENT: dwExitCode = OriginalEventNumber; break; } break; } } } } finally { UnlockDll(); } ExitThread(dwExitCode); return STATUS_SUCCESS; }
void WINAPI EXC_RtlUnwind( PEXCEPTION_FRAME pEndFrame, LPVOID unusedEip, PEXCEPTION_RECORD pRecord, DWORD returnEax, CONTEXT *context ) { EXCEPTION_RECORD record, newrec; PEXCEPTION_FRAME frame, dispatch; #ifdef __i386__ context->Eax = returnEax; #endif /* build an exception record, if we do not have one */ if (!pRecord) { record.ExceptionCode = STATUS_UNWIND; record.ExceptionFlags = 0; record.ExceptionRecord = NULL; record.ExceptionAddress = GET_IP(context); record.NumberParameters = 0; pRecord = &record; } pRecord->ExceptionFlags |= EH_UNWINDING | (pEndFrame ? 0 : EH_EXIT_UNWIND); TRACE( "code=%lx flags=%lx\n", pRecord->ExceptionCode, pRecord->ExceptionFlags ); /* get chain of exception frames */ frame = NtCurrentTeb()->except; while ((frame != (PEXCEPTION_FRAME)0xffffffff) && (frame != pEndFrame)) { /* Check frame address */ if (pEndFrame && (frame > pEndFrame)) { newrec.ExceptionCode = STATUS_INVALID_UNWIND_TARGET; newrec.ExceptionFlags = EH_NONCONTINUABLE; newrec.ExceptionRecord = pRecord; newrec.NumberParameters = 0; RtlRaiseException( &newrec ); /* never returns */ } if (((void*)frame < NtCurrentTeb()->stack_low) || ((void*)(frame+1) > NtCurrentTeb()->stack_top) || (int)frame & 3) { newrec.ExceptionCode = STATUS_BAD_STACK; newrec.ExceptionFlags = EH_NONCONTINUABLE; newrec.ExceptionRecord = pRecord; newrec.NumberParameters = 0; RtlRaiseException( &newrec ); /* never returns */ } /* Call handler */ switch(EXC_CallHandler( pRecord, frame, context, &dispatch, frame->Handler, EXC_UnwindHandler )) { case ExceptionContinueSearch: break; case ExceptionCollidedUnwind: frame = dispatch; break; default: newrec.ExceptionCode = STATUS_INVALID_DISPOSITION; newrec.ExceptionFlags = EH_NONCONTINUABLE; newrec.ExceptionRecord = pRecord; newrec.NumberParameters = 0; RtlRaiseException( &newrec ); /* never returns */ break; } frame = __wine_pop_frame( frame ); } }
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 ); }
__CxxThrowException( #endif void* pExceptionObject, // The object thrown _ThrowInfo* pThrowInfo // Everything we need to know about it ) { EHTRACE_ENTER_FMT1("Throwing object @ 0x%p", pExceptionObject); static const EHExceptionRecord ExceptionTemplate = { // A generic exception record EH_EXCEPTION_NUMBER, // Exception number EXCEPTION_NONCONTINUABLE, // Exception flags (we don't do resume) NULL, // Additional record (none) NULL, // Address of exception (OS fills in) EH_EXCEPTION_PARAMETERS, // Number of parameters { EH_MAGIC_NUMBER1, // Our version control magic number NULL, // pExceptionObject NULL, #if _EH_RELATIVE_OFFSETS NULL // Image base of thrown object #endif } // pThrowInfo }; EHExceptionRecord ThisException = ExceptionTemplate; // This exception ThrowInfo* pTI = (ThrowInfo*)pThrowInfo; if (pTI && (THROW_ISWINRT( (*pTI) ) ) ) { ULONG_PTR *exceptionInfoPointer = *reinterpret_cast<ULONG_PTR**>(pExceptionObject); exceptionInfoPointer--; // The pointer to the ExceptionInfo structure is stored sizeof(void*) infront of each WinRT Exception Info. WINRTEXCEPTIONINFO* wei = reinterpret_cast<WINRTEXCEPTIONINFO*>(*exceptionInfoPointer); pTI = wei->throwInfo; } // // Fill in the blanks: // ThisException.params.pExceptionObject = pExceptionObject; ThisException.params.pThrowInfo = pTI; #if _EH_RELATIVE_OFFSETS PVOID ThrowImageBase = RtlPcToFileHeader((PVOID)pTI, &ThrowImageBase); ThisException.params.pThrowImageBase = ThrowImageBase; #endif // // If the throw info indicates this throw is from a pure region, // set the magic number to the Pure one, so only a pure-region // catch will see it. // // Also use the Pure magic number on Win64 if we were unable to // determine an image base, since that was the old way to determine // a pure throw, before the TI_IsPure bit was added to the FuncInfo // attributes field. // if (pTI != NULL) { if (THROW_ISPURE(*pTI)) { ThisException.params.magicNumber = EH_PURE_MAGIC_NUMBER1; } #if _EH_RELATIVE_OFFSETS else if (ThrowImageBase == NULL) { ThisException.params.magicNumber = EH_PURE_MAGIC_NUMBER1; } #endif } // // Hand it off to the OS: // EHTRACE_EXIT; #if defined(_M_X64) && defined(_NTSUBSET_) RtlRaiseException( (PEXCEPTION_RECORD) &ThisException ); #else RaiseException( ThisException.ExceptionCode, ThisException.ExceptionFlags, ThisException.NumberParameters, (PULONG_PTR)&ThisException.params ); #endif }