xref: /reactos/sdk/lib/rtl/amd64/except.c (revision 7353af1e)
1 /*
2  * PROJECT:     ReactOS Run-Time Library
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     User-mode exception support for AMD64
5  * COPYRIGHT:   Copyright 2018-2021 Timo Kreuzer <timo.kreuzer@reactos.org>
6  */
7 
8 /* INCLUDES *****************************************************************/
9 
10 #include <rtl.h>
11 #define NDEBUG
12 #include <debug.h>
13 
14 /* PUBLIC FUNCTIONS **********************************************************/
15 
16 VOID
17 NTAPI
18 RtlRaiseException(IN PEXCEPTION_RECORD ExceptionRecord)
19 {
20     CONTEXT Context;
21     NTSTATUS Status = STATUS_INVALID_DISPOSITION;
22 
23     /* Capture the current context */
24     RtlCaptureContext(&Context);
25 
26     /* Fix up Context.Rip for the caller */
27     Context.Rip = (ULONG64)_ReturnAddress();
28 
29     /* Fix up Context.Rsp for the caller */
30     Context.Rsp = (ULONG64)_AddressOfReturnAddress() + 8;
31 
32     /* Save the exception address */
33     ExceptionRecord->ExceptionAddress = (PVOID)Context.Rip;
34 
35     /* Check if user mode debugger is active */
36     if (RtlpCheckForActiveDebugger())
37     {
38         /* Raise an exception immediately */
39         Status = ZwRaiseException(ExceptionRecord, &Context, TRUE);
40     }
41     else
42     {
43         /* Dispatch the exception and check if we should continue */
44         if (!RtlDispatchException(ExceptionRecord, &Context))
45         {
46             /* Raise the exception */
47             Status = ZwRaiseException(ExceptionRecord, &Context, FALSE);
48         }
49         else
50         {
51             /* Continue, go back to previous context */
52             Status = ZwContinue(&Context, FALSE);
53         }
54     }
55 
56     /* If we returned, raise a status */
57     RtlRaiseStatus(Status);
58 }
59 
60 /*
61 * @unimplemented
62 */
63 PVOID
64 NTAPI
65 RtlpGetExceptionAddress(VOID)
66 {
67     UNIMPLEMENTED;
68     return NULL;
69 }
70 
71 BOOLEAN
72 NTAPI
73 RtlpUnwindInternal(
74     _In_opt_ PVOID TargetFrame,
75     _In_opt_ PVOID TargetIp,
76     _In_ PEXCEPTION_RECORD ExceptionRecord,
77     _In_ PVOID ReturnValue,
78     _In_ PCONTEXT ContextRecord,
79     _In_opt_ struct _UNWIND_HISTORY_TABLE *HistoryTable,
80     _In_ ULONG Flags);
81 
82 /*
83  * @unimplemented
84  */
85 BOOLEAN
86 NTAPI
87 RtlDispatchException(
88     _In_ PEXCEPTION_RECORD ExceptionRecord,
89     _In_ PCONTEXT ContextRecord)
90 {
91     BOOLEAN Handled;
92 
93     /* Perform vectored exception handling for user mode */
94     if (RtlCallVectoredExceptionHandlers(ExceptionRecord, ContextRecord))
95     {
96         /* Exception handled, now call vectored continue handlers */
97         RtlCallVectoredContinueHandlers(ExceptionRecord, ContextRecord);
98 
99         /* Continue execution */
100         return TRUE;
101     }
102 
103     /* Call the internal unwind routine */
104     Handled = RtlpUnwindInternal(NULL, // TargetFrame
105                                  NULL, // TargetIp
106                                  ExceptionRecord,
107                                  0, // ReturnValue
108                                  ContextRecord,
109                                  NULL, // HistoryTable
110                                  UNW_FLAG_EHANDLER);
111 
112     /* In user mode, call any registered vectored continue handlers */
113     RtlCallVectoredContinueHandlers(ExceptionRecord, ContextRecord);
114 
115     return Handled;
116 }
117