ReactOS  0.4.14-dev-323-g6fe6a88
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 
28 VOID
29 NTAPI
31 {
32  /* Initialize our two lists and the common lock */
36 }
37 
38 BOOLEAN
39 NTAPI
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 
152 PVOID
153 NTAPI
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 
195 ULONG
196 NTAPI
197 RtlpRemoveVectoredHandler(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 
271 BOOLEAN
272 NTAPI
275 {
276  /* Call the shared routine */
277  return RtlpCallVectoredHandlers(ExceptionRecord,
278  Context,
280 }
281 
282 VOID
283 NTAPI
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 
297 PVOID
298 NTAPI
300  IN PVECTORED_EXCEPTION_HANDLER VectoredHandler)
301 {
302  /* Call the shared routine */
303  return RtlpAddVectoredHandler(FirstHandler,
304  VectoredHandler,
306 }
307 
309 PVOID
310 NTAPI
312  IN PVECTORED_EXCEPTION_HANDLER VectoredHandler)
313 {
314  /* Call the shared routine */
315  return RtlpAddVectoredHandler(FirstHandler,
316  VectoredHandler,
318 }
319 
320 //DECLSPEC_HOTPATCH
321 ULONG
322 NTAPI
324 {
325  /* Call the shared routine */
326  return RtlpRemoveVectoredHandler(VectoredHandlerHandle,
328 }
329 
330 //DECLSPEC_HOTPATCH
331 ULONG
332 NTAPI
334 {
335  /* Call the shared routine */
336  return RtlpRemoveVectoredHandler(VectoredHandlerHandle,
338 }
339 
340 /* EOF */
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
PVECTORED_EXCEPTION_HANDLER VectoredHandler
Definition: vectoreh.c:22
struct _RTL_VECTORED_HANDLER_ENTRY RTL_VECTORED_HANDLER_ENTRY
DECLSPEC_HOTPATCH PVOID NTAPI RtlAddVectoredContinueHandler(IN ULONG FirstHandler, IN PVECTORED_EXCEPTION_HANDLER VectoredHandler)
Definition: vectoreh.c:311
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
LONG(NTAPI * PVECTORED_EXCEPTION_HANDLER)(PEXCEPTION_POINTERS ExceptionPointers)
Definition: rtltypes.h:501
LIST_ENTRY ListEntry
Definition: vectoreh.c:21
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
Definition: vectoreh.c:19
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI PVOID WINAPI RtlDecodePointer(PVOID)
VOID NTAPI RtlCallVectoredContinueHandlers(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT Context)
Definition: vectoreh.c:284
#define InsertTailList(ListHead, Entry)
ULONG NTAPI RtlRemoveVectoredExceptionHandler(IN PVOID VectoredHandlerHandle)
Definition: vectoreh.c:323
ULONG NTAPI RtlpRemoveVectoredHandler(IN PVOID VectoredHandlerHandle, IN PLIST_ENTRY VectoredHandlerList)
Definition: vectoreh.c:197
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
BOOLEAN NTAPI RtlpCallVectoredHandlers(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT Context, IN PLIST_ENTRY VectoredHandlerList)
Definition: vectoreh.c:40
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:86
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
long LONG
Definition: pedump.c:60
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
ULONG NTAPI RtlRemoveVectoredContinueHandler(IN PVOID VectoredHandlerHandle)
Definition: vectoreh.c:333
RTL_CRITICAL_SECTION RtlpVectoredHandlerLock
Definition: vectoreh.c:16
unsigned char BOOLEAN
NTSYSAPI PVOID WINAPI RtlEncodePointer(PVOID)
smooth NULL
Definition: ftsmooth.c:416
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
LIST_ENTRY RtlpVectoredContinueList
Definition: vectoreh.c:17
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
#define DECLSPEC_HOTPATCH
Definition: _mingw.h:240
PCONTEXT ContextRecord
Definition: rtltypes.h:197
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
struct _RTL_VECTORED_HANDLER_ENTRY * PRTL_VECTORED_HANDLER_ENTRY
BOOLEAN NTAPI RtlCallVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT Context)
Definition: vectoreh.c:273
NTSYSAPI NTSTATUS NTAPI RtlInitializeCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
VOID NTAPI RtlpInitializeVectoredExceptionHandling(VOID)
Definition: vectoreh.c:30
DECLSPEC_HOTPATCH PVOID NTAPI RtlAddVectoredExceptionHandler(IN ULONG FirstHandler, IN PVECTORED_EXCEPTION_HANDLER VectoredHandler)
Definition: vectoreh.c:299
#define VOID
Definition: acefi.h:82
Definition: typedefs.h:117
ULONG Refs
Definition: vectoreh.c:23
PVOID NTAPI RtlpAddVectoredHandler(IN ULONG FirstHandler, IN PVECTORED_EXCEPTION_HANDLER VectoredHandler, IN PLIST_ENTRY VectoredHandlerList)
Definition: vectoreh.c:154
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
LIST_ENTRY RtlpVectoredExceptionList
Definition: vectoreh.c:17
struct tagContext Context
Definition: acpixf.h:1024
unsigned int ULONG
Definition: retypes.h:1
PEXCEPTION_RECORD ExceptionRecord
Definition: rtltypes.h:196
#define EXCEPTION_CONTINUE_EXECUTION
Definition: excpt.h:87