Author: sginsberg
Date: Thu Sep 17 13:36:55 2015
New Revision: 69259
URL:
http://svn.reactos.org/svn/reactos?rev=69259&view=rev
Log:
[RTL] Add support for vectored continue handlers, complementing the vectored exception
handler support we already have, by doing some massive shared code usage: just use two
different lists for the different handler types and all the code is basically the same.
Call the "new" functionality from RtlDispatchException and stub it out for
kernel mode. Clean up the existing code and simplify it. Passes the Winetests fine, not
that they test this a a lot.
#CORE-10202
Modified:
trunk/reactos/dll/ntdll/ldr/ldrinit.c
trunk/reactos/lib/rtl/i386/except.c
trunk/reactos/lib/rtl/rtlp.h
trunk/reactos/lib/rtl/vectoreh.c
trunk/reactos/ntoskrnl/rtl/libsupp.c
Modified: trunk/reactos/dll/ntdll/ldr/ldrinit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/ldr/ldrinit.c?re…
==============================================================================
--- trunk/reactos/dll/ntdll/ldr/ldrinit.c [iso-8859-1] (original)
+++ trunk/reactos/dll/ntdll/ldr/ldrinit.c [iso-8859-1] Thu Sep 17 13:36:55 2015
@@ -77,7 +77,7 @@
//extern LIST_ENTRY RtlCriticalSectionList;
-VOID RtlpInitializeVectoredExceptionHandling(VOID);
+VOID NTAPI RtlpInitializeVectoredExceptionHandling(VOID);
VOID NTAPI RtlpInitDeferedCriticalSection(VOID);
VOID NTAPI RtlInitializeHeapManager(VOID);
extern BOOLEAN RtlpPageHeapEnabled;
Modified: trunk/reactos/lib/rtl/i386/except.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/i386/except.c?rev=…
==============================================================================
--- trunk/reactos/lib/rtl/i386/except.c [iso-8859-1] (original)
+++ trunk/reactos/lib/rtl/i386/except.c [iso-8859-1] Thu Sep 17 13:36:55 2015
@@ -74,10 +74,13 @@
ULONG_PTR StackLow, StackHigh;
ULONG_PTR RegistrationFrameEnd;
- /* Perform vectored exception handling (a dummy in kernel mode) */
+ /* Perform vectored exception handling for user mode */
if (RtlCallVectoredExceptionHandlers(ExceptionRecord, Context))
{
- /* Exception handled, continue execution */
+ /* Exception handled, now call vectored continue handlers */
+ RtlCallVectoredContinueHandlers(ExceptionRecord, Context);
+
+ /* Continue execution */
return TRUE;
}
@@ -139,7 +142,7 @@
/* Handle the dispositions */
switch (Disposition)
{
- /* Continue searching */
+ /* Continue execution */
case ExceptionContinueExecution:
/* Check if it was non-continuable */
@@ -157,7 +160,11 @@
}
else
{
- /* Return to caller */
+ /* In user mode, call any registered vectored continue handlers */
+ RtlCallVectoredContinueHandlers(ExceptionRecord,
+ Context);
+
+ /* Execution continues */
return TRUE;
}
Modified: trunk/reactos/lib/rtl/rtlp.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/rtlp.h?rev=69259&a…
==============================================================================
--- trunk/reactos/lib/rtl/rtlp.h [iso-8859-1] (original)
+++ trunk/reactos/lib/rtl/rtlp.h [iso-8859-1] Thu Sep 17 13:36:55 2015
@@ -67,6 +67,13 @@
IN PCONTEXT Context
);
+VOID
+NTAPI
+RtlCallVectoredContinueHandlers(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PCONTEXT Context
+);
+
typedef struct _DISPATCHER_CONTEXT
{
PEXCEPTION_REGISTRATION_RECORD RegistrationPointer;
Modified: trunk/reactos/lib/rtl/vectoreh.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/vectoreh.c?rev=692…
==============================================================================
--- trunk/reactos/lib/rtl/vectoreh.c [iso-8859-1] (original)
+++ trunk/reactos/lib/rtl/vectoreh.c [iso-8859-1] Thu Sep 17 13:36:55 2015
@@ -13,201 +13,328 @@
#define NDEBUG
#include <debug.h>
-static RTL_CRITICAL_SECTION RtlpVectoredExceptionLock;
-static LIST_ENTRY RtlpVectoredExceptionHead;
-static volatile LONG RtlpVectoredExceptionsInstalled;
-
-typedef struct _RTL_VECTORED_EXCEPTION_HANDLER
-{
- LIST_ENTRY ListEntry;
- PVECTORED_EXCEPTION_HANDLER VectoredHandler;
- ULONG Refs;
- BOOLEAN Deleted;
-} RTL_VECTORED_EXCEPTION_HANDLER, *PRTL_VECTORED_EXCEPTION_HANDLER;
+RTL_CRITICAL_SECTION RtlpVectoredHandlerLock;
+LIST_ENTRY RtlpVectoredExceptionList, RtlpVectoredContinueList;
+
+typedef struct _RTL_VECTORED_HANDLER_ENTRY
+{
+ LIST_ENTRY ListEntry;
+ PVECTORED_EXCEPTION_HANDLER VectoredHandler;
+ ULONG Refs;
+} RTL_VECTORED_HANDLER_ENTRY, *PRTL_VECTORED_HANDLER_ENTRY;
/* FUNCTIONS ***************************************************************/
+VOID
+NTAPI
+RtlpInitializeVectoredExceptionHandling(VOID)
+{
+ /* Initialize our two lists and the common lock */
+ RtlInitializeCriticalSection(&RtlpVectoredHandlerLock);
+ InitializeListHead(&RtlpVectoredExceptionList);
+ InitializeListHead(&RtlpVectoredContinueList);
+}
+
BOOLEAN
NTAPI
-RtlCallVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
- IN PCONTEXT Context)
-{
- PLIST_ENTRY CurrentEntry;
- PRTL_VECTORED_EXCEPTION_HANDLER veh = NULL;
- PVECTORED_EXCEPTION_HANDLER VectoredHandler;
- EXCEPTION_POINTERS ExceptionInfo;
- BOOLEAN Remove = FALSE;
- BOOLEAN Ret = FALSE;
-
- ExceptionInfo.ExceptionRecord = ExceptionRecord;
- ExceptionInfo.ContextRecord = Context;
-
- if(RtlpVectoredExceptionsInstalled)
- {
- RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
- CurrentEntry = RtlpVectoredExceptionHead.Flink;
- while (CurrentEntry != &RtlpVectoredExceptionHead)
- {
- veh = CONTAINING_RECORD(CurrentEntry,
- RTL_VECTORED_EXCEPTION_HANDLER,
- ListEntry);
- veh->Refs++;
- RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
-
- VectoredHandler = RtlDecodePointer(veh->VectoredHandler);
- if(VectoredHandler(&ExceptionInfo) == EXCEPTION_CONTINUE_EXECUTION)
- {
- RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
- if (--veh->Refs == 0)
+RtlpCallVectoredHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PCONTEXT Context,
+ IN PLIST_ENTRY VectoredHandlerList)
+{
+ PLIST_ENTRY CurrentEntry;
+ PRTL_VECTORED_HANDLER_ENTRY VectoredExceptionHandler;
+ PVECTORED_EXCEPTION_HANDLER VectoredHandler;
+ EXCEPTION_POINTERS ExceptionInfo;
+ BOOLEAN HandlerRemoved;
+ LONG HandlerReturn;
+
+ /*
+ * Initialize these in case there are no entries,
+ * or if no one handled the exception
+ */
+ HandlerRemoved = FALSE;
+ HandlerReturn = EXCEPTION_CONTINUE_SEARCH;
+
+ /* Set up the data to pass to the handler */
+ ExceptionInfo.ExceptionRecord = ExceptionRecord;
+ ExceptionInfo.ContextRecord = Context;
+
+ /* Grab the lock */
+ RtlEnterCriticalSection(&RtlpVectoredHandlerLock);
+
+ /* Loop entries */
+ CurrentEntry = VectoredHandlerList->Flink;
+ while (CurrentEntry != VectoredHandlerList)
+ {
+ /* Get the struct */
+ VectoredExceptionHandler = CONTAINING_RECORD(CurrentEntry,
+ RTL_VECTORED_HANDLER_ENTRY,
+ ListEntry);
+
+ /* Reference it so it doesn't go away while we are using it */
+ VectoredExceptionHandler->Refs++;
+
+ /* Drop the lock before calling the handler */
+ RtlLeaveCriticalSection(&RtlpVectoredHandlerLock);
+
+ /*
+ * Get the function pointer, decoding it so we will crash
+ * if malicious code has altered it. That is, if something has
+ * set VectoredHandler to a non-encoded pointer
+ */
+ VectoredHandler =
RtlDecodePointer(VectoredExceptionHandler->VectoredHandler);
+
+ /* Call the handler */
+ HandlerReturn = VectoredHandler(&ExceptionInfo);
+
+ /* Handler called -- grab the lock to dereference */
+ RtlEnterCriticalSection(&RtlpVectoredHandlerLock);
+
+ /* Dereference and see if it got deleted */
+ VectoredExceptionHandler->Refs--;
+ if (VectoredExceptionHandler->Refs == 0)
{
- RemoveEntryList (&veh->ListEntry);
- InterlockedDecrement (&RtlpVectoredExceptionsInstalled);
- Remove = TRUE;
+ /* It did -- do we have to free it now? */
+ if (HandlerReturn == EXCEPTION_CONTINUE_EXECUTION)
+ {
+ /* We don't, just remove it from the list and break out */
+ RemoveEntryList(&VectoredExceptionHandler->ListEntry);
+ HandlerRemoved = TRUE;
+ break;
+ }
+
+ /*
+ * Get the next entry before freeing,
+ * and remove the current one from the list
+ */
+ CurrentEntry = VectoredExceptionHandler->ListEntry.Flink;
+ RemoveEntryList(&VectoredExceptionHandler->ListEntry);
+
+ /* Free the entry outside of the lock, then reacquire it */
+ RtlLeaveCriticalSection(&RtlpVectoredHandlerLock);
+ RtlFreeHeap(RtlGetProcessHeap(),
+ 0,
+ VectoredExceptionHandler);
+ RtlEnterCriticalSection(&RtlpVectoredHandlerLock);
}
- Ret = TRUE;
- break;
- }
-
- RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
-
- if (--veh->Refs == 0)
- {
- CurrentEntry = veh->ListEntry.Flink;
- RemoveEntryList (&veh->ListEntry);
- InterlockedDecrement (&RtlpVectoredExceptionsInstalled);
- RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
-
+ else
+ {
+ /* No delete -- should we continue execution? */
+ if (HandlerReturn == EXCEPTION_CONTINUE_EXECUTION)
+ {
+ /* Break out */
+ break;
+ }
+ else
+ {
+ /* Continue searching the list */
+ CurrentEntry = CurrentEntry->Flink;
+ }
+ }
+ }
+
+ /* Let go of the lock now */
+ RtlLeaveCriticalSection(&RtlpVectoredHandlerLock);
+
+ /* Anything to free? */
+ if (HandlerRemoved)
+ {
+ /* Get rid of it */
RtlFreeHeap(RtlGetProcessHeap(),
0,
- veh);
- RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
- }
- else
- CurrentEntry = CurrentEntry->Flink;
- }
-
- RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
- }
-
- if (Remove)
- {
- RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- veh);
- }
-
- return Ret;
+ VectoredExceptionHandler);
+ }
+
+ /* Return whether to continue execution (ignored for continue handlers) */
+ return (HandlerReturn == EXCEPTION_CONTINUE_EXECUTION) ? TRUE : FALSE;
+}
+
+PVOID
+NTAPI
+RtlpAddVectoredHandler(IN ULONG FirstHandler,
+ IN PVECTORED_EXCEPTION_HANDLER VectoredHandler,
+ IN PLIST_ENTRY VectoredHandlerList)
+{
+ PRTL_VECTORED_HANDLER_ENTRY VectoredHandlerEntry;
+
+ /* Allocate our structure */
+ VectoredHandlerEntry = RtlAllocateHeap(RtlGetProcessHeap(),
+ 0,
+ sizeof(RTL_VECTORED_HANDLER_ENTRY));
+ if (!VectoredHandlerEntry) return NULL;
+
+ /* Set it up, encoding the pointer for security */
+ VectoredHandlerEntry->VectoredHandler = RtlEncodePointer(VectoredHandler);
+ VectoredHandlerEntry->Refs = 1;
+
+ /* Lock the list before modifying it */
+ RtlEnterCriticalSection(&RtlpVectoredHandlerLock);
+
+ /*
+ * While holding the list lock, insert the handler
+ * at beginning or end of list according to caller.
+ */
+ if (FirstHandler)
+ {
+ InsertHeadList(VectoredHandlerList,
+ &VectoredHandlerEntry->ListEntry);
+ }
+ else
+ {
+ InsertTailList(VectoredHandlerList,
+ &VectoredHandlerEntry->ListEntry);
+ }
+
+ /* Done with the list, unlock it */
+ RtlLeaveCriticalSection(&RtlpVectoredHandlerLock);
+
+ /* Return pointer to the structure as the handle */
+ return VectoredHandlerEntry;
+}
+
+ULONG
+NTAPI
+RtlpRemoveVectoredHandler(IN PVOID VectoredHandlerHandle,
+ IN PLIST_ENTRY VectoredHandlerList)
+{
+ PLIST_ENTRY CurrentEntry;
+ PRTL_VECTORED_HANDLER_ENTRY VectoredExceptionHandler;
+ BOOLEAN HandlerRemoved;
+ BOOLEAN HandlerFound;
+
+ /* Initialize these in case we don't find anything */
+ HandlerRemoved = FALSE;
+ HandlerFound = FALSE;
+
+ /* Acquire list lock */
+ RtlEnterCriticalSection(&RtlpVectoredHandlerLock);
+
+ /* Loop the list */
+ CurrentEntry = VectoredHandlerList->Flink;
+ while (CurrentEntry != VectoredHandlerList)
+ {
+ /* Get the struct */
+ VectoredExceptionHandler = CONTAINING_RECORD(CurrentEntry,
+ RTL_VECTORED_HANDLER_ENTRY,
+ ListEntry);
+
+ /* Does it match? */
+ if (VectoredExceptionHandler == VectoredHandlerHandle)
+ {
+ /*
+ * Great, this means it is a valid entry.
+ * However, it may be in use by the exception
+ * dispatcher, so we have a ref count to respect.
+ * If we can't remove it now then it will be done
+ * right after it is not in use anymore.
+ *
+ * Caller is supposed to keep track of if it has deleted the
+ * entry and should not call us twice for the same entry.
+ * We could maybe throw in some kind of ASSERT to detect this
+ * if this was to become a problem.
+ */
+ VectoredExceptionHandler->Refs--;
+ if (VectoredExceptionHandler->Refs == 0)
+ {
+ /* Not in use, ok to remove and free */
+ RemoveEntryList(&VectoredExceptionHandler->ListEntry);
+ HandlerRemoved = TRUE;
+ }
+
+ /* Found what we are looking for, stop searching */
+ HandlerFound = TRUE;
+ break;
+ }
+ else
+ {
+ /* Get the next entry */
+ CurrentEntry = CurrentEntry->Flink;
+ }
+ }
+
+ /* Done with the list, let go of the lock */
+ RtlLeaveCriticalSection(&RtlpVectoredHandlerLock);
+
+ /* Can we free what we found? */
+ if (HandlerRemoved)
+ {
+ /* Do it */
+ RtlFreeHeap(RtlGetProcessHeap(),
+ 0,
+ VectoredExceptionHandler);
+ }
+
+ /* Return whether we found it */
+ return (ULONG)HandlerFound;
+}
+
+BOOLEAN
+NTAPI
+RtlCallVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PCONTEXT Context)
+{
+ /* Call the shared routine */
+ return RtlpCallVectoredHandlers(ExceptionRecord,
+ Context,
+ &RtlpVectoredExceptionList);
}
VOID
-RtlpInitializeVectoredExceptionHandling(VOID)
-{
- InitializeListHead(&RtlpVectoredExceptionHead);
- RtlInitializeCriticalSection(&RtlpVectoredExceptionLock);
- RtlpVectoredExceptionsInstalled = 0;
-}
-
-
-/*
- * @implemented
- */
-PVOID NTAPI DECLSPEC_HOTPATCH
+NTAPI
+RtlCallVectoredContinueHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PCONTEXT Context)
+{
+ /*
+ * Call the shared routine (ignoring result,
+ * execution always continues at this point)
+ */
+ (VOID)RtlpCallVectoredHandlers(ExceptionRecord,
+ Context,
+ &RtlpVectoredContinueList);
+}
+
+DECLSPEC_HOTPATCH
+PVOID
+NTAPI
RtlAddVectoredExceptionHandler(IN ULONG FirstHandler,
IN PVECTORED_EXCEPTION_HANDLER VectoredHandler)
{
- PRTL_VECTORED_EXCEPTION_HANDLER veh;
-
- veh = RtlAllocateHeap(RtlGetProcessHeap(),
- 0,
- sizeof(RTL_VECTORED_EXCEPTION_HANDLER));
- if(veh != NULL)
- {
- veh->VectoredHandler = RtlEncodePointer(VectoredHandler);
- veh->Refs = 1;
- veh->Deleted = FALSE;
- RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
- if(FirstHandler != 0)
- {
- InsertHeadList(&RtlpVectoredExceptionHead,
- &veh->ListEntry);
- }
- else
- {
- InsertTailList(&RtlpVectoredExceptionHead,
- &veh->ListEntry);
- }
- InterlockedIncrement (&RtlpVectoredExceptionsInstalled);
- RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
- }
-
- return veh;
-}
-
-
-/*
- * @implemented
- */
-ULONG NTAPI
+ /* Call the shared routine */
+ return RtlpAddVectoredHandler(FirstHandler,
+ VectoredHandler,
+ &RtlpVectoredExceptionList);
+}
+
+DECLSPEC_HOTPATCH
+PVOID
+NTAPI
+RtlAddVectoredContinueHandler(IN ULONG FirstHandler,
+ IN PVECTORED_EXCEPTION_HANDLER VectoredHandler)
+{
+ /* Call the shared routine */
+ return RtlpAddVectoredHandler(FirstHandler,
+ VectoredHandler,
+ &RtlpVectoredContinueList);
+}
+
+//DECLSPEC_HOTPATCH
+ULONG
+NTAPI
RtlRemoveVectoredExceptionHandler(IN PVOID VectoredHandlerHandle)
{
- PLIST_ENTRY CurrentEntry;
- PRTL_VECTORED_EXCEPTION_HANDLER veh = NULL;
- BOOLEAN Remove = FALSE;
- ULONG Ret = FALSE;
-
- RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
- for(CurrentEntry = RtlpVectoredExceptionHead.Flink;
- CurrentEntry != &RtlpVectoredExceptionHead;
- CurrentEntry = CurrentEntry->Flink)
- {
- veh = CONTAINING_RECORD(CurrentEntry,
- RTL_VECTORED_EXCEPTION_HANDLER,
- ListEntry);
- if(veh == VectoredHandlerHandle)
- {
- if (!veh->Deleted)
- {
- if (--veh->Refs == 0)
- {
- RemoveEntryList (&veh->ListEntry);
- Remove = TRUE;
- }
- veh->Deleted = TRUE;
- Ret = TRUE;
- break;
- }
- }
- }
- RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
-
- if(Remove)
- {
- RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- veh);
- }
-
- return Ret;
-}
-
-PVOID
-NTAPI
-DECLSPEC_HOTPATCH
-RtlAddVectoredContinueHandler(
- IN ULONG FirstHandler,
- IN PVECTORED_EXCEPTION_HANDLER VectoredHandler)
-{
- UNIMPLEMENTED;
- return NULL;
-}
-
+ /* Call the shared routine */
+ return RtlpRemoveVectoredHandler(VectoredHandlerHandle,
+ &RtlpVectoredExceptionList);
+}
+
+//DECLSPEC_HOTPATCH
ULONG
NTAPI
-RtlRemoveVectoredContinueHandler(
- IN PVOID VectoredHandlerHandle)
-{
- UNIMPLEMENTED;
- return FALSE;
+RtlRemoveVectoredContinueHandler(IN PVOID VectoredHandlerHandle)
+{
+ /* Call the shared routine */
+ return RtlpRemoveVectoredHandler(VectoredHandlerHandle,
+ &RtlpVectoredContinueList);
}
/* EOF */
Modified: trunk/reactos/ntoskrnl/rtl/libsupp.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/rtl/libsupp.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/rtl/libsupp.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/rtl/libsupp.c [iso-8859-1] Thu Sep 17 13:36:55 2015
@@ -764,12 +764,20 @@
BOOLEAN
NTAPI
-RtlCallVectoredExceptionHandlers(
- _In_ PEXCEPTION_RECORD ExceptionRecord,
- _In_ PCONTEXT Context)
+RtlCallVectoredExceptionHandlers(_In_ PEXCEPTION_RECORD ExceptionRecord,
+ _In_ PCONTEXT Context)
{
/* In the kernel we don't have vectored exception handlers */
return FALSE;
}
+VOID
+NTAPI
+RtlCallVectoredContinueHandlers(_In_ PEXCEPTION_RECORD ExceptionRecord,
+ _In_ PCONTEXT Context)
+{
+ /* No vectored continue handlers either in kernel mode */
+ return;
+}
+
/* EOF */