diff --git a/reactos/lib/pseh/.cvsignore b/reactos/lib/pseh/.cvsignore new file mode 100644 index 00000000000..6142305dc12 --- /dev/null +++ b/reactos/lib/pseh/.cvsignore @@ -0,0 +1,2 @@ +*.o +*.d diff --git a/reactos/lib/pseh/framebased.c b/reactos/lib/pseh/framebased.c new file mode 100644 index 00000000000..1fe1cfef9d0 --- /dev/null +++ b/reactos/lib/pseh/framebased.c @@ -0,0 +1,103 @@ +#define STRICT +#define WIN32_LEAN_AND_MEAN +#include + +#include +#include + +/* Assembly helpers, see i386/framebased.asm */ +extern void __cdecl _SEHCleanHandlerEnvironment(void); +extern void __cdecl _SEHRegisterFrame(_SEHRegistration_t *); +extern void __cdecl _SEHUnregisterFrame(const _SEHRegistration_t *); +extern void __cdecl _SEHUnwind(_SEHPortableFrame_t *); + +__declspec(noreturn) void __cdecl _SEHCallHandler(_SEHPortableFrame_t * frame) +{ + frame->SPF_Handling = 1; + _SEHUnwind(frame); + frame->SPF_Handlers->SH_Handler(frame); +} + +int __cdecl _SEHFrameHandler +( + struct _EXCEPTION_RECORD * ExceptionRecord, + void * EstablisherFrame, + struct _CONTEXT * ContextRecord, + void * DispatcherContext +) +{ + _SEHPortableFrame_t * frame; + + _SEHCleanHandlerEnvironment(); + + frame = EstablisherFrame; + + /* Unwinding */ + if(ExceptionRecord->ExceptionFlags & (4 | 2)) + { + if(frame->SPF_Handlers->SH_Finally && !frame->SPF_Handling) + frame->SPF_Handlers->SH_Finally(frame); + } + /* Handling */ + else + { + if(ExceptionRecord->ExceptionCode) + frame->SPF_Code = ExceptionRecord->ExceptionCode; + else + frame->SPF_Code = 0xC0000001; + + if(frame->SPF_Handlers->SH_Filter) + { + int ret; + + switch((UINT_PTR)frame->SPF_Handlers->SH_Filter) + { + case EXCEPTION_EXECUTE_HANDLER + 1: + case EXCEPTION_CONTINUE_SEARCH + 1: + case EXCEPTION_CONTINUE_EXECUTION + 1: + { + ret = (int)((UINT_PTR)frame->SPF_Handlers->SH_Filter) - 1; + break; + } + + default: + { + EXCEPTION_POINTERS ep; + + ep.ExceptionRecord = ExceptionRecord; + ep.ContextRecord = ContextRecord; + + ret = frame->SPF_Handlers->SH_Filter(&ep, frame); + break; + } + } + + /* EXCEPTION_CONTINUE_EXECUTION */ + if(ret < 0) + return ExceptionContinueExecution; + /* EXCEPTION_EXECUTE_HANDLER */ + else if(ret > 0) + _SEHCallHandler(frame); + /* EXCEPTION_CONTINUE_SEARCH */ + else + /* fall through */; + } + } + + return ExceptionContinueSearch; +} + +void __stdcall _SEHEnter(_SEHPortableFrame_t * frame) +{ + frame->SPF_Registration.SER_Handler = _SEHFrameHandler; + frame->SPF_Code = 0; + frame->SPF_Handling = 0; + _SEHRegisterFrame(&frame->SPF_Registration); +} + +void __stdcall _SEHLeave(_SEHPortableFrame_t * frame) +{ + _SEHUnregisterFrame(&frame->SPF_Registration); +} + +/* EOF */ diff --git a/reactos/lib/pseh/i386/.cvsignore b/reactos/lib/pseh/i386/.cvsignore new file mode 100644 index 00000000000..6142305dc12 --- /dev/null +++ b/reactos/lib/pseh/i386/.cvsignore @@ -0,0 +1,2 @@ +*.o +*.d diff --git a/reactos/lib/pseh/i386/framebased.asm b/reactos/lib/pseh/i386/framebased.asm new file mode 100644 index 00000000000..f9201bdd6ad --- /dev/null +++ b/reactos/lib/pseh/i386/framebased.asm @@ -0,0 +1,48 @@ +cpu 486 +segment .text use32 + +global __SEHCleanHandlerEnvironment +__SEHCleanHandlerEnvironment: + cld + ret + +global __SEHRegisterFrame +__SEHRegisterFrame: + mov ecx, [esp+4] + mov eax, [fs:0] + mov [ecx+0], eax + mov [fs:0], ecx + ret + +global __SEHUnregisterFrame +__SEHUnregisterFrame: + mov ecx, [esp+4] + mov ecx, [ecx] + mov [fs:0], ecx + ret + +global __SEHUnwind +__SEHUnwind: + + extern RtlUnwind + + mov ecx, [esp+4] + +; RtlUnwind clobbers all the "don't clobber" registers, so we save them + push esi + push edi + push ebx + + push eax + push eax + push eax + push ecx + call RtlUnwind + + pop ebx + pop edi + pop esi + + ret + +; EOF diff --git a/reactos/lib/pseh/makefile b/reactos/lib/pseh/makefile new file mode 100644 index 00000000000..b64033639bd --- /dev/null +++ b/reactos/lib/pseh/makefile @@ -0,0 +1,21 @@ +# $Id: makefile,v 1.1 2004/06/02 18:36:55 hyperion Exp $ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = library + +TARGET_NAME = pseh + +TARGET_CFLAGS += -D_DISABLE_TIDENTS -Werror -Wall -D__USE_W32API + +include $(PATH_TO_TOP)/config +include makefile.$(ARCH) + +TARGET_OBJECTS = framebased.o $(TARGET_ARCH_OBJECTS) +DEP_OBJECTS = $(TARGET_OBJECTS) + +include $(PATH_TO_TOP)/rules.mak +include $(TOOLS_PATH)/helper.mk +include $(TOOLS_PATH)/depend.mk + +# EOF diff --git a/reactos/lib/pseh/makefile.i386 b/reactos/lib/pseh/makefile.i386 new file mode 100644 index 00000000000..1fde404d8d8 --- /dev/null +++ b/reactos/lib/pseh/makefile.i386 @@ -0,0 +1,5 @@ +# $Id: makefile.i386,v 1.1 2004/06/02 18:36:55 hyperion Exp $ + +TARGET_ARCH_OBJECTS = $(ARCH)/framebased.o + +# EOF