mirror of
https://github.com/reactos/reactos.git
synced 2025-05-19 09:10:56 +00:00
[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 svn path=/trunk/; revision=69259
This commit is contained in:
parent
2e0a23b373
commit
259f15f48a
5 changed files with 320 additions and 171 deletions
|
@ -77,7 +77,7 @@ ULONG LdrpActiveUnloadCount;
|
|||
|
||||
//extern LIST_ENTRY RtlCriticalSectionList;
|
||||
|
||||
VOID RtlpInitializeVectoredExceptionHandling(VOID);
|
||||
VOID NTAPI RtlpInitializeVectoredExceptionHandling(VOID);
|
||||
VOID NTAPI RtlpInitDeferedCriticalSection(VOID);
|
||||
VOID NTAPI RtlInitializeHeapManager(VOID);
|
||||
extern BOOLEAN RtlpPageHeapEnabled;
|
||||
|
|
|
@ -74,10 +74,13 @@ RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
|
|||
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 @@ RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
|
|||
/* Handle the dispositions */
|
||||
switch (Disposition)
|
||||
{
|
||||
/* Continue searching */
|
||||
/* Continue execution */
|
||||
case ExceptionContinueExecution:
|
||||
|
||||
/* Check if it was non-continuable */
|
||||
|
@ -157,7 +160,11 @@ RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Return to caller */
|
||||
/* In user mode, call any registered vectored continue handlers */
|
||||
RtlCallVectoredContinueHandlers(ExceptionRecord,
|
||||
Context);
|
||||
|
||||
/* Execution continues */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,13 @@ RtlCallVectoredExceptionHandlers(
|
|||
IN PCONTEXT Context
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
RtlCallVectoredContinueHandlers(
|
||||
IN PEXCEPTION_RECORD ExceptionRecord,
|
||||
IN PCONTEXT Context
|
||||
);
|
||||
|
||||
typedef struct _DISPATCHER_CONTEXT
|
||||
{
|
||||
PEXCEPTION_REGISTRATION_RECORD RegistrationPointer;
|
||||
|
|
|
@ -13,201 +13,328 @@
|
|||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
static RTL_CRITICAL_SECTION RtlpVectoredExceptionLock;
|
||||
static LIST_ENTRY RtlpVectoredExceptionHead;
|
||||
static volatile LONG RtlpVectoredExceptionsInstalled;
|
||||
RTL_CRITICAL_SECTION RtlpVectoredHandlerLock;
|
||||
LIST_ENTRY RtlpVectoredExceptionList, RtlpVectoredContinueList;
|
||||
|
||||
typedef struct _RTL_VECTORED_EXCEPTION_HANDLER
|
||||
typedef struct _RTL_VECTORED_HANDLER_ENTRY
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
PVECTORED_EXCEPTION_HANDLER VectoredHandler;
|
||||
ULONG Refs;
|
||||
BOOLEAN Deleted;
|
||||
} RTL_VECTORED_EXCEPTION_HANDLER, *PRTL_VECTORED_EXCEPTION_HANDLER;
|
||||
LIST_ENTRY ListEntry;
|
||||
PVECTORED_EXCEPTION_HANDLER VectoredHandler;
|
||||
ULONG Refs;
|
||||
} RTL_VECTORED_HANDLER_ENTRY, *PRTL_VECTORED_HANDLER_ENTRY;
|
||||
|
||||
/* FUNCTIONS ***************************************************************/
|
||||
|
||||
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)
|
||||
{
|
||||
RemoveEntryList (&veh->ListEntry);
|
||||
InterlockedDecrement (&RtlpVectoredExceptionsInstalled);
|
||||
Remove = TRUE;
|
||||
}
|
||||
Ret = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
|
||||
|
||||
if (--veh->Refs == 0)
|
||||
{
|
||||
CurrentEntry = veh->ListEntry.Flink;
|
||||
RemoveEntryList (&veh->ListEntry);
|
||||
InterlockedDecrement (&RtlpVectoredExceptionsInstalled);
|
||||
RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
|
||||
|
||||
RtlFreeHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
veh);
|
||||
RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
|
||||
}
|
||||
else
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
}
|
||||
|
||||
RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
|
||||
}
|
||||
|
||||
if (Remove)
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
veh);
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
RtlpInitializeVectoredExceptionHandling(VOID)
|
||||
{
|
||||
InitializeListHead(&RtlpVectoredExceptionHead);
|
||||
RtlInitializeCriticalSection(&RtlpVectoredExceptionLock);
|
||||
RtlpVectoredExceptionsInstalled = 0;
|
||||
/* Initialize our two lists and the common lock */
|
||||
RtlInitializeCriticalSection(&RtlpVectoredHandlerLock);
|
||||
InitializeListHead(&RtlpVectoredExceptionList);
|
||||
InitializeListHead(&RtlpVectoredContinueList);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
PVOID NTAPI DECLSPEC_HOTPATCH
|
||||
RtlAddVectoredExceptionHandler(IN ULONG FirstHandler,
|
||||
IN PVECTORED_EXCEPTION_HANDLER VectoredHandler)
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
RtlpCallVectoredHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
|
||||
IN PCONTEXT Context,
|
||||
IN PLIST_ENTRY VectoredHandlerList)
|
||||
{
|
||||
PRTL_VECTORED_EXCEPTION_HANDLER veh;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PRTL_VECTORED_HANDLER_ENTRY VectoredExceptionHandler;
|
||||
PVECTORED_EXCEPTION_HANDLER VectoredHandler;
|
||||
EXCEPTION_POINTERS ExceptionInfo;
|
||||
BOOLEAN HandlerRemoved;
|
||||
LONG HandlerReturn;
|
||||
|
||||
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)
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
InsertHeadList(&RtlpVectoredExceptionHead,
|
||||
&veh->ListEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
InsertTailList(&RtlpVectoredExceptionHead,
|
||||
&veh->ListEntry);
|
||||
}
|
||||
InterlockedIncrement (&RtlpVectoredExceptionsInstalled);
|
||||
RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
|
||||
}
|
||||
/* Get the struct */
|
||||
VectoredExceptionHandler = CONTAINING_RECORD(CurrentEntry,
|
||||
RTL_VECTORED_HANDLER_ENTRY,
|
||||
ListEntry);
|
||||
|
||||
return veh;
|
||||
}
|
||||
/* Reference it so it doesn't go away while we are using it */
|
||||
VectoredExceptionHandler->Refs++;
|
||||
|
||||
/* Drop the lock before calling the handler */
|
||||
RtlLeaveCriticalSection(&RtlpVectoredHandlerLock);
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
ULONG NTAPI
|
||||
RtlRemoveVectoredExceptionHandler(IN PVOID VectoredHandlerHandle)
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PRTL_VECTORED_EXCEPTION_HANDLER veh = NULL;
|
||||
BOOLEAN Remove = FALSE;
|
||||
ULONG Ret = FALSE;
|
||||
/*
|
||||
* 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);
|
||||
|
||||
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)
|
||||
/* 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);
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No delete -- should we continue execution? */
|
||||
if (HandlerReturn == EXCEPTION_CONTINUE_EXECUTION)
|
||||
{
|
||||
/* Break out */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Continue searching the list */
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
}
|
||||
}
|
||||
veh->Deleted = TRUE;
|
||||
Ret = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
|
||||
|
||||
if(Remove)
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
veh);
|
||||
}
|
||||
/* Let go of the lock now */
|
||||
RtlLeaveCriticalSection(&RtlpVectoredHandlerLock);
|
||||
|
||||
return Ret;
|
||||
/* Anything to free? */
|
||||
if (HandlerRemoved)
|
||||
{
|
||||
/* Get rid of it */
|
||||
RtlFreeHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
VectoredExceptionHandler);
|
||||
}
|
||||
|
||||
/* Return whether to continue execution (ignored for continue handlers) */
|
||||
return (HandlerReturn == EXCEPTION_CONTINUE_EXECUTION) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
DECLSPEC_HOTPATCH
|
||||
RtlAddVectoredContinueHandler(
|
||||
IN ULONG FirstHandler,
|
||||
IN PVECTORED_EXCEPTION_HANDLER VectoredHandler)
|
||||
RtlpAddVectoredHandler(IN ULONG FirstHandler,
|
||||
IN PVECTORED_EXCEPTION_HANDLER VectoredHandler,
|
||||
IN PLIST_ENTRY VectoredHandlerList)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return NULL;
|
||||
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
|
||||
RtlRemoveVectoredContinueHandler(
|
||||
IN PVOID VectoredHandlerHandle)
|
||||
RtlpRemoveVectoredHandler(IN PVOID VectoredHandlerHandle,
|
||||
IN PLIST_ENTRY VectoredHandlerList)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
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
|
||||
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)
|
||||
{
|
||||
/* 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)
|
||||
{
|
||||
/* Call the shared routine */
|
||||
return RtlpRemoveVectoredHandler(VectoredHandlerHandle,
|
||||
&RtlpVectoredExceptionList);
|
||||
}
|
||||
|
||||
//DECLSPEC_HOTPATCH
|
||||
ULONG
|
||||
NTAPI
|
||||
RtlRemoveVectoredContinueHandler(IN PVOID VectoredHandlerHandle)
|
||||
{
|
||||
/* Call the shared routine */
|
||||
return RtlpRemoveVectoredHandler(VectoredHandlerHandle,
|
||||
&RtlpVectoredContinueList);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -764,12 +764,20 @@ RtlpSafeCopyMemory(
|
|||
|
||||
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 */
|
||||
|
|
Loading…
Reference in a new issue