ReactOS 0.4.16-dev-319-g6cf4263
vectoreh.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS sysem libraries
4 * PURPOSE: Vectored Exception Handling
5 * FILE: lib/rtl/vectoreh.c
6 * PROGRAMERS: Thomas Weidenmueller
7 */
8
9/* INCLUDES *****************************************************************/
10
11#include <rtl.h>
12
13#define NDEBUG
14#include <debug.h>
15
18
20{
25
26/* FUNCTIONS ***************************************************************/
27
28VOID
31{
32 /* Initialize our two lists and the common lock */
36}
37
42 IN PLIST_ENTRY VectoredHandlerList)
43{
44 PLIST_ENTRY CurrentEntry;
45 PRTL_VECTORED_HANDLER_ENTRY VectoredExceptionHandler;
46 PVECTORED_EXCEPTION_HANDLER VectoredHandler;
47 EXCEPTION_POINTERS ExceptionInfo;
48 BOOLEAN HandlerRemoved;
49 LONG HandlerReturn;
50
51 /*
52 * Initialize these in case there are no entries,
53 * or if no one handled the exception
54 */
55 HandlerRemoved = FALSE;
56 HandlerReturn = EXCEPTION_CONTINUE_SEARCH;
57
58 /* Set up the data to pass to the handler */
59 ExceptionInfo.ExceptionRecord = ExceptionRecord;
60 ExceptionInfo.ContextRecord = Context;
61
62 /* Grab the lock */
64
65 /* Loop entries */
66 CurrentEntry = VectoredHandlerList->Flink;
67 while (CurrentEntry != VectoredHandlerList)
68 {
69 /* Get the struct */
70 VectoredExceptionHandler = CONTAINING_RECORD(CurrentEntry,
72 ListEntry);
73
74 /* Reference it so it doesn't go away while we are using it */
75 VectoredExceptionHandler->Refs++;
76
77 /* Drop the lock before calling the handler */
79
80 /*
81 * Get the function pointer, decoding it so we will crash
82 * if malicious code has altered it. That is, if something has
83 * set VectoredHandler to a non-encoded pointer
84 */
85 VectoredHandler = RtlDecodePointer(VectoredExceptionHandler->VectoredHandler);
86
87 /* Call the handler */
88 HandlerReturn = VectoredHandler(&ExceptionInfo);
89
90 /* Handler called -- grab the lock to dereference */
92
93 /* Dereference and see if it got deleted */
94 VectoredExceptionHandler->Refs--;
95 if (VectoredExceptionHandler->Refs == 0)
96 {
97 /* It did -- do we have to free it now? */
98 if (HandlerReturn == EXCEPTION_CONTINUE_EXECUTION)
99 {
100 /* We don't, just remove it from the list and break out */
101 RemoveEntryList(&VectoredExceptionHandler->ListEntry);
102 HandlerRemoved = TRUE;
103 break;
104 }
105
106 /*
107 * Get the next entry before freeing,
108 * and remove the current one from the list
109 */
110 CurrentEntry = VectoredExceptionHandler->ListEntry.Flink;
111 RemoveEntryList(&VectoredExceptionHandler->ListEntry);
112
113 /* Free the entry outside of the lock, then reacquire it */
115 RtlFreeHeap(RtlGetProcessHeap(),
116 0,
117 VectoredExceptionHandler);
119 }
120 else
121 {
122 /* No delete -- should we continue execution? */
123 if (HandlerReturn == EXCEPTION_CONTINUE_EXECUTION)
124 {
125 /* Break out */
126 break;
127 }
128 else
129 {
130 /* Continue searching the list */
131 CurrentEntry = CurrentEntry->Flink;
132 }
133 }
134 }
135
136 /* Let go of the lock now */
138
139 /* Anything to free? */
140 if (HandlerRemoved)
141 {
142 /* Get rid of it */
143 RtlFreeHeap(RtlGetProcessHeap(),
144 0,
145 VectoredExceptionHandler);
146 }
147
148 /* Return whether to continue execution (ignored for continue handlers) */
149 return (HandlerReturn == EXCEPTION_CONTINUE_EXECUTION) ? TRUE : FALSE;
150}
151
152PVOID
153NTAPI
155 IN PVECTORED_EXCEPTION_HANDLER VectoredHandler,
156 IN PLIST_ENTRY VectoredHandlerList)
157{
158 PRTL_VECTORED_HANDLER_ENTRY VectoredHandlerEntry;
159
160 /* Allocate our structure */
161 VectoredHandlerEntry = RtlAllocateHeap(RtlGetProcessHeap(),
162 0,
164 if (!VectoredHandlerEntry) return NULL;
165
166 /* Set it up, encoding the pointer for security */
167 VectoredHandlerEntry->VectoredHandler = RtlEncodePointer(VectoredHandler);
168 VectoredHandlerEntry->Refs = 1;
169
170 /* Lock the list before modifying it */
172
173 /*
174 * While holding the list lock, insert the handler
175 * at beginning or end of list according to caller.
176 */
177 if (FirstHandler)
178 {
179 InsertHeadList(VectoredHandlerList,
180 &VectoredHandlerEntry->ListEntry);
181 }
182 else
183 {
184 InsertTailList(VectoredHandlerList,
185 &VectoredHandlerEntry->ListEntry);
186 }
187
188 /* Done with the list, unlock it */
190
191 /* Return pointer to the structure as the handle */
192 return VectoredHandlerEntry;
193}
194
195ULONG
196NTAPI
197RtlpRemoveVectoredHandler(IN PVOID VectoredHandlerHandle,
198 IN PLIST_ENTRY VectoredHandlerList)
199{
200 PLIST_ENTRY CurrentEntry;
201 PRTL_VECTORED_HANDLER_ENTRY VectoredExceptionHandler;
202 BOOLEAN HandlerRemoved;
203 BOOLEAN HandlerFound;
204
205 /* Initialize these in case we don't find anything */
206 HandlerRemoved = FALSE;
207 HandlerFound = FALSE;
208
209 /* Acquire list lock */
211
212 /* Loop the list */
213 CurrentEntry = VectoredHandlerList->Flink;
214 while (CurrentEntry != VectoredHandlerList)
215 {
216 /* Get the struct */
217 VectoredExceptionHandler = CONTAINING_RECORD(CurrentEntry,
219 ListEntry);
220
221 /* Does it match? */
222 if (VectoredExceptionHandler == VectoredHandlerHandle)
223 {
224 /*
225 * Great, this means it is a valid entry.
226 * However, it may be in use by the exception
227 * dispatcher, so we have a ref count to respect.
228 * If we can't remove it now then it will be done
229 * right after it is not in use anymore.
230 *
231 * Caller is supposed to keep track of if it has deleted the
232 * entry and should not call us twice for the same entry.
233 * We could maybe throw in some kind of ASSERT to detect this
234 * if this was to become a problem.
235 */
236 VectoredExceptionHandler->Refs--;
237 if (VectoredExceptionHandler->Refs == 0)
238 {
239 /* Not in use, ok to remove and free */
240 RemoveEntryList(&VectoredExceptionHandler->ListEntry);
241 HandlerRemoved = TRUE;
242 }
243
244 /* Found what we are looking for, stop searching */
245 HandlerFound = TRUE;
246 break;
247 }
248 else
249 {
250 /* Get the next entry */
251 CurrentEntry = CurrentEntry->Flink;
252 }
253 }
254
255 /* Done with the list, let go of the lock */
257
258 /* Can we free what we found? */
259 if (HandlerRemoved)
260 {
261 /* Do it */
262 RtlFreeHeap(RtlGetProcessHeap(),
263 0,
264 VectoredExceptionHandler);
265 }
266
267 /* Return whether we found it */
268 return (ULONG)HandlerFound;
269}
270
272NTAPI
275{
276 /* Call the shared routine */
277 return RtlpCallVectoredHandlers(ExceptionRecord,
278 Context,
280}
281
282VOID
283NTAPI
286{
287 /*
288 * Call the shared routine (ignoring result,
289 * execution always continues at this point)
290 */
291 (VOID)RtlpCallVectoredHandlers(ExceptionRecord,
292 Context,
294}
295
297PVOID
298NTAPI
300 IN PVECTORED_EXCEPTION_HANDLER VectoredHandler)
301{
302 /* Call the shared routine */
303 return RtlpAddVectoredHandler(FirstHandler,
304 VectoredHandler,
306}
307
309PVOID
310NTAPI
312 IN PVECTORED_EXCEPTION_HANDLER VectoredHandler)
313{
314 /* Call the shared routine */
315 return RtlpAddVectoredHandler(FirstHandler,
316 VectoredHandler,
318}
319
320//DECLSPEC_HOTPATCH
321ULONG
322NTAPI
324{
325 /* Call the shared routine */
326 return RtlpRemoveVectoredHandler(VectoredHandlerHandle,
328}
329
330//DECLSPEC_HOTPATCH
331ULONG
332NTAPI
334{
335 /* Call the shared routine */
336 return RtlpRemoveVectoredHandler(VectoredHandlerHandle,
338}
339
340/* EOF */
unsigned char BOOLEAN
#define VOID
Definition: acefi.h:82
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
NTSYSAPI PVOID WINAPI RtlEncodePointer(PVOID)
NTSYSAPI PVOID WINAPI RtlDecodePointer(PVOID)
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:91
#define EXCEPTION_CONTINUE_EXECUTION
Definition: excpt.h:92
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlInitializeCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
LONG(NTAPI * PVECTORED_EXCEPTION_HANDLER)(PEXCEPTION_POINTERS ExceptionPointers)
Definition: rtltypes.h:505
long LONG
Definition: pedump.c:60
#define DECLSPEC_HOTPATCH
Definition: config.h:9
PEXCEPTION_RECORD ExceptionRecord
Definition: rtltypes.h:200
PCONTEXT ContextRecord
Definition: rtltypes.h:201
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: vectoreh.c:20
PVECTORED_EXCEPTION_HANDLER VectoredHandler
Definition: vectoreh.c:22
LIST_ENTRY ListEntry
Definition: vectoreh.c:21
ULONG Refs
Definition: vectoreh.c:23
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
DECLSPEC_HOTPATCH PVOID NTAPI RtlAddVectoredExceptionHandler(IN ULONG FirstHandler, IN PVECTORED_EXCEPTION_HANDLER VectoredHandler)
Definition: vectoreh.c:299
ULONG NTAPI RtlpRemoveVectoredHandler(IN PVOID VectoredHandlerHandle, IN PLIST_ENTRY VectoredHandlerList)
Definition: vectoreh.c:197
VOID NTAPI RtlCallVectoredContinueHandlers(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT Context)
Definition: vectoreh.c:284
BOOLEAN NTAPI RtlCallVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT Context)
Definition: vectoreh.c:273
DECLSPEC_HOTPATCH PVOID NTAPI RtlAddVectoredContinueHandler(IN ULONG FirstHandler, IN PVECTORED_EXCEPTION_HANDLER VectoredHandler)
Definition: vectoreh.c:311
ULONG NTAPI RtlRemoveVectoredContinueHandler(IN PVOID VectoredHandlerHandle)
Definition: vectoreh.c:333
BOOLEAN NTAPI RtlpCallVectoredHandlers(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT Context, IN PLIST_ENTRY VectoredHandlerList)
Definition: vectoreh.c:40
LIST_ENTRY RtlpVectoredContinueList
Definition: vectoreh.c:17
struct _RTL_VECTORED_HANDLER_ENTRY * PRTL_VECTORED_HANDLER_ENTRY
VOID NTAPI RtlpInitializeVectoredExceptionHandling(VOID)
Definition: vectoreh.c:30
ULONG NTAPI RtlRemoveVectoredExceptionHandler(IN PVOID VectoredHandlerHandle)
Definition: vectoreh.c:323
RTL_CRITICAL_SECTION RtlpVectoredHandlerLock
Definition: vectoreh.c:16
PVOID NTAPI RtlpAddVectoredHandler(IN ULONG FirstHandler, IN PVECTORED_EXCEPTION_HANDLER VectoredHandler, IN PLIST_ENTRY VectoredHandlerList)
Definition: vectoreh.c:154
struct _RTL_VECTORED_HANDLER_ENTRY RTL_VECTORED_HANDLER_ENTRY
LIST_ENTRY RtlpVectoredExceptionList
Definition: vectoreh.c:17