diff --git a/reactos/lib/rtl/amd64/unwind.c b/reactos/lib/rtl/amd64/unwind.c index 276981df6cb..fabda830821 100644 --- a/reactos/lib/rtl/amd64/unwind.c +++ b/reactos/lib/rtl/amd64/unwind.c @@ -1,7 +1,7 @@ /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries - * PURPOSE: Exception related functions + * PURPOSE: Unwinding related functions * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) */ @@ -28,6 +28,11 @@ #define UWOP_SAVE_XMM128_FAR 9 #define UWOP_PUSH_MACHFRAME 10 +#define UNW_FLAG_NHANDLER 0 +#define UNW_FLAG_EHANDLER 1 +#define UNW_FLAG_UHANDLER 2 +#define UNW_FLAG_CHAININFO 4 + typedef unsigned char UBYTE; typedef union _UNWIND_CODE @@ -611,3 +616,69 @@ RtlGetCallersAddress( return; } + +// FIXME: move to different file +VOID +NTAPI +RtlRaiseException(IN PEXCEPTION_RECORD ExceptionRecord) +{ + CONTEXT Context; + NTSTATUS Status; + ULONG64 ImageBase; + PRUNTIME_FUNCTION FunctionEntry; + PVOID HandlerData; + ULONG64 EstablisherFrame; + + /* Capture the context */ + RtlCaptureContext(&Context); + + /* Get the function entry for this function */ + FunctionEntry = RtlLookupFunctionEntry(Context.Rip, + &ImageBase, + NULL); + + /* Check if we found it */ + if (FunctionEntry) + { + /* Unwind to the caller of this function */ + RtlVirtualUnwind(UNW_FLAG_NHANDLER, + ImageBase, + Context.Rip, + FunctionEntry, + &Context, + &HandlerData, + &EstablisherFrame, + NULL); + + /* Save the exception address */ + ExceptionRecord->ExceptionAddress = (PVOID)Context.Rip; + + /* Write the context flag */ + Context.ContextFlags = CONTEXT_FULL; + + /* Check if user mode debugger is active */ + if (RtlpCheckForActiveDebugger()) + { + /* Raise an exception immediately */ + Status = ZwRaiseException(ExceptionRecord, &Context, TRUE); + } + else + { + /* Dispatch the exception and check if we should continue */ + if (!RtlDispatchException(ExceptionRecord, &Context)) + { + /* Raise the exception */ + Status = ZwRaiseException(ExceptionRecord, &Context, FALSE); + } + else + { + /* Continue, go back to previous context */ + Status = ZwContinue(&Context, FALSE); + } + } + } + + /* If we returned, raise a status */ + RtlRaiseStatus(Status); +} + diff --git a/reactos/lib/rtl/exception.c b/reactos/lib/rtl/exception.c index d4462e32111..e0970d182e7 100644 --- a/reactos/lib/rtl/exception.c +++ b/reactos/lib/rtl/exception.c @@ -17,7 +17,7 @@ /* FUNCTIONS ***************************************************************/ -#if !defined(_M_IX86) +#if !defined(_M_IX86) && !defined(_M_AMD64) /* * @implemented @@ -63,6 +63,10 @@ RtlRaiseException(IN PEXCEPTION_RECORD ExceptionRecord) RtlRaiseStatus(Status); } +#endif + +#if !defined(_M_IX86) + #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4717) // RtlRaiseStatus is recursive by design