/*
	Copyright (c) 2008 KJK::Hyperion

	Permission is hereby granted, free of charge, to any person obtaining a
	copy of this software and associated documentation files (the "Software"),
	to deal in the Software without restriction, including without limitation
	the rights to use, copy, modify, merge, publish, distribute, sublicense,
	and/or sell copies of the Software, and to permit persons to whom the
	Software is furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
	DEALINGS IN THE SOFTWARE.
*/

#define _NTSYSTEM_ /* removes dllimport attribute from RtlUnwind */

#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include <pseh/pseh2-common.h>
#include <excpt.h>
#include <intrin.h>

#ifndef EXCEPTION_EXIT_UNWIND
#define EXCEPTION_EXIT_UNWIND 4
#endif

#ifndef EXCEPTION_UNWINDING
#define EXCEPTION_UNWINDING 2
#endif

extern DECLSPEC_NORETURN int __SEH2Handle(void *, void *, void *, void *, void *, void *);
extern int __cdecl __SEH2FrameHandler(struct _EXCEPTION_RECORD *, void *, struct _CONTEXT *, void *);
extern int __cdecl __SEH2UnwindHandler(struct _EXCEPTION_RECORD *, void *, struct _CONTEXT *, void *);

typedef struct __SEHTrampoline
{
	unsigned char STR_MovEcx;
	unsigned char * STR_Closure;
	unsigned char STR_Jmp;
	unsigned char * STR_Function;
}
__attribute__((packed))
_SEHTrampoline_t;

FORCEINLINE
int _SEHIsTrampoline(_SEHTrampoline_t * trampoline_)
{
	return trampoline_->STR_MovEcx == 0xb9 && trampoline_->STR_Jmp == 0xe9;
}

FORCEINLINE
void * _SEHFunctionFromTrampoline(_SEHTrampoline_t * trampoline_)
{
	return (int)(trampoline_ + 1) + trampoline_->STR_Function;
}

FORCEINLINE
void * _SEHClosureFromTrampoline(_SEHTrampoline_t * trampoline_)
{
	return trampoline_->STR_Closure;
}

FORCEINLINE
_SEH2Registration_t * __cdecl _SEH2CurrentRegistration(void)
{
	return (_SEH2Registration_t *)__readfsdword(0);
}

FORCEINLINE
void __cdecl __SEH2EnterFrame(_SEH2Registration_t * frame)
{
	frame->SER_Prev = _SEH2CurrentRegistration();
	__writefsdword(0, (unsigned long)frame);
}

FORCEINLINE
void __cdecl __SEH2LeaveFrame(void)
{
	__writefsdword(0, (unsigned long)_SEH2CurrentRegistration()->SER_Prev);
}

FORCEINLINE
void _SEH2GlobalUnwind(void * target)
{
	__asm__ __volatile__
	(
		"push %%ebp\n"
		"push $0\n"
		"push $0\n"
		"push $Return%=\n"
		"push %[target]\n"
		"call %c[RtlUnwind]\n"
		"Return%=: pop %%ebp\n" :
		:
		[target] "g" (target), [RtlUnwind] "g" (&RtlUnwind) :
		"eax", "ebx", "ecx", "edx", "esi", "edi", "flags", "memory"
	);
}

static
__SEH_EXCEPT_RET _SEH2Except(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * trylevel, struct _EXCEPTION_POINTERS * ep)
{
	void * filter = trylevel->ST_Filter;
	void * context = NULL;
	__SEH_EXCEPT_RET ret;

	if(filter == (void *)0)
		return 0;

	if(filter == (void *)1)
		return 1;

	if(filter == (void *)-1)
		return -1;

	if(_SEHIsTrampoline((_SEHTrampoline_t *)filter))
	{
		context = _SEHClosureFromTrampoline((_SEHTrampoline_t *)filter);
		filter = _SEHFunctionFromTrampoline((_SEHTrampoline_t *)filter);
	}

	__asm__ __volatile__
	(
		"push %[ep]\n"
		"push %[frame]\n"
		"call *%[filter]\n"
		"pop %%edx\n"
		"pop %%edx\n" :
		[ret] "=a" (ret) :
		"c" (context), [filter] "r" (filter), [frame] "g" (frame), [ep] "g" (ep) :
		"edx", "flags", "memory"
	);

	return ret;
}

static
void _SEH2Finally(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * trylevel)
{
	if(trylevel->ST_Filter == NULL && trylevel->ST_Body != NULL)
	{
		void * body = trylevel->ST_Body;
		void * context = NULL;

		if(_SEHIsTrampoline((_SEHTrampoline_t *)body))
		{
			context = _SEHClosureFromTrampoline((_SEHTrampoline_t *)body);
			body = _SEHFunctionFromTrampoline((_SEHTrampoline_t *)body);
		}

		__asm__ __volatile__("call *%1\n" : : "c" (context), "r" (body) : "eax", "edx", "flags", "memory");
	}
}

typedef struct __SEH2UnwindFrame
{
	_SEH2Registration_t SUF_Registration;
	_SEH2Frame_t * SUF_Frame;
	volatile _SEH2TryLevel_t * SUF_TargetTryLevel;
}
_SEH2UnwindFrame_t;

static void _SEH2LocalUnwind(_SEH2Frame_t *, volatile _SEH2TryLevel_t *);

extern
int __cdecl _SEH2UnwindHandler
(
	struct _EXCEPTION_RECORD * ExceptionRecord,
	void * EstablisherFrame,
	struct _CONTEXT * ContextRecord,
	void * DispatcherContext
)
{
	if(ExceptionRecord->ExceptionFlags & (EXCEPTION_EXIT_UNWIND | EXCEPTION_UNWINDING))
	{
		_SEH2UnwindFrame_t * unwindframe = CONTAINING_RECORD(EstablisherFrame, _SEH2UnwindFrame_t, SUF_Registration);
		_SEH2LocalUnwind(unwindframe->SUF_Frame, unwindframe->SUF_TargetTryLevel);
		*((void **)DispatcherContext) = EstablisherFrame;
		return ExceptionCollidedUnwind;
	}

	return ExceptionContinueSearch;
}

static
void _SEH2LocalUnwind(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * dsttrylevel)
{
	volatile _SEH2TryLevel_t * trylevel;
	_SEH2UnwindFrame_t unwindframe;

	unwindframe.SUF_Frame = frame;
	unwindframe.SUF_TargetTryLevel = dsttrylevel;

	unwindframe.SUF_Registration.SER_Handler = &__SEH2UnwindHandler;
	__SEH2EnterFrame(&unwindframe.SUF_Registration);

	for(trylevel = frame->SF_TopTryLevel; trylevel && trylevel != dsttrylevel; trylevel = trylevel->ST_Next)
	{
		frame->SF_TopTryLevel = trylevel->ST_Next;
		_SEH2Finally(frame, trylevel);
	}

	__SEH2LeaveFrame();
}

static DECLSPEC_NORETURN
void _SEH2Handle(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * trylevel)
{
	volatile _SEH2HandleTryLevel_t * fulltrylevel = CONTAINING_RECORD(trylevel, _SEH2HandleTryLevel_t, SHT_Common);

	_SEH2GlobalUnwind(frame);
	_SEH2LocalUnwind(frame, &fulltrylevel->SHT_Common);
	frame->SF_TopTryLevel = fulltrylevel->SHT_Common.ST_Next;

	__SEH2Handle
	(
		fulltrylevel->SHT_Common.ST_Body,
		fulltrylevel->SHT_Esp,
		fulltrylevel->SHT_Ebp,
		fulltrylevel->SHT_Ebx,
		fulltrylevel->SHT_Esi,
		fulltrylevel->SHT_Edi
	);
}

extern
int __cdecl _SEH2FrameHandler
(
	struct _EXCEPTION_RECORD * ExceptionRecord,
	void * EstablisherFrame,
	struct _CONTEXT * ContextRecord,
	void * DispatcherContext
)
{
	_SEH2Frame_t * frame;

	frame = EstablisherFrame;

	/* Unwinding */
	if(ExceptionRecord->ExceptionFlags & (EXCEPTION_EXIT_UNWIND | EXCEPTION_UNWINDING))
	{
		_SEH2LocalUnwind(frame, NULL);
	}
	/* Handling */
	else
	{
		int ret = 0;
		volatile _SEH2TryLevel_t * trylevel;
		EXCEPTION_POINTERS ep;

		ep.ExceptionRecord = ExceptionRecord;
		ep.ContextRecord = ContextRecord;

		frame->SF_Code = ExceptionRecord->ExceptionCode;

		for(trylevel = frame->SF_TopTryLevel; trylevel != NULL; trylevel = trylevel->ST_Next)
		{
			ret = _SEH2Except(frame, trylevel, &ep);

			if(ret < 0)
				return ExceptionContinueExecution;
			else if(ret > 0)
				_SEH2Handle(frame, trylevel);
		}
	}

	return ExceptionContinueSearch;
}

extern
void __cdecl _SEH2EnterFrame(_SEH2Frame_t * frame)
{
	frame->SF_Registration.SER_Handler = __SEH2FrameHandler;
	frame->SF_Code = 0;
	__SEH2EnterFrame(&frame->SF_Registration);
}

extern
int __cdecl _SEH2EnterFrameAndTrylevel(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * trylevel)
{
	frame->SF_TopTryLevel = trylevel;
	_SEH2EnterFrame(frame);
	return 0;
}

extern
void __cdecl _SEH2LeaveFrame(void)
{
	__SEH2LeaveFrame();
}

extern
void __cdecl _SEH2Return(void)
{
	_SEH2LocalUnwind(CONTAINING_RECORD(_SEH2CurrentRegistration(), _SEH2Frame_t, SF_Registration), NULL);
	_SEH2LeaveFrame();
}

/* EOF */
