mirror of
https://github.com/reactos/reactos.git
synced 2025-06-10 20:34:59 +00:00
Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.
This commit is contained in:
parent
b94e2d8ca0
commit
c2c66aff7d
24198 changed files with 0 additions and 37285 deletions
340
sdk/lib/rtl/vectoreh.c
Normal file
340
sdk/lib/rtl/vectoreh.c
Normal file
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS sysem libraries
|
||||
* PURPOSE: Vectored Exception Handling
|
||||
* FILE: lib/rtl/vectoreh.c
|
||||
* PROGRAMERS: Thomas Weidenmueller
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <rtl.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
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
|
||||
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)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Let go of the lock now */
|
||||
RtlLeaveCriticalSection(&RtlpVectoredHandlerLock);
|
||||
|
||||
/* 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
|
||||
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
|
||||
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 */
|
Loading…
Add table
Add a link
Reference in a new issue