//
// EXCEP3.C -- Sample structured exception handler
//             Demonstrates nested "try" blocks
//
#include <stdio.h>
#include <stdlib.h>
#include <pharlap.h>
#define i386 1
#define WIN32
#include <windows.h>
#include <excpt.h>

void Level2(void);
int Level2Filter(ULONG ExcepCode, struct _EXCEPTION_POINTERS *pExcepInfo);
void Level3(void);
int Level3Filter(ULONG ExcepCode);
void CauseExceptions(void);

int main()
{
	int	ExcepCode;

	try
	{
		Level2();
	}
	except (EXCEPTION_EXECUTE_HANDLER)
	{
		ExcepCode = GetExceptionCode();
		if (ExcepCode == EXCEPTION_ACCESS_VIOLATION)
			printf("main - got GP fault, terminating program\n");
		else
			printf("In main - unexpected exception: %08Xh\n",
							ExcepCode);
		exit(1);
	}

	printf("Normal termination\n");
	return 0;
}

void Level2(void)
{
	try
	{
		Level3();
	}
	except (Level2Filter(GetExceptionCode(),GetExceptionInformation()))
	{
		// shouldn't get here, we never say EXCEPTION_EXECUTE_HANDLER
		printf("In Level 2 exception handler:  terminating program\n");
		exit(1);
	}
}

int Level2Filter(ULONG ExcepCode, struct _EXCEPTION_POINTERS *pExcepInfo)
{
	EXCEPTION_RECORD *pExcepRecord;
	CONTEXT *pContext;

	pExcepRecord = pExcepInfo->ExceptionRecord;
	pContext = pExcepInfo->ContextRecord;

	if (ExcepCode == EXCEPTION_INT_DIVIDE_BY_ZERO)
	{
		printf("Level 2 - Got divide-by-zero exception\n");
		if (!pContext->ContextFlags & CONTEXT_CONTROL)
		{
			printf("  No context -- let system handler run\n");
			return EXCEPTION_CONTINUE_SEARCH;
		}
		printf("  Incrementing EIP past DIV and ignoring it\n");
		pContext->Eip += 2;
		return EXCEPTION_CONTINUE_EXECUTION;
	}
	else
	{
		printf("Level 2 - Can't handle exception: %08Xh\n", ExcepCode);
		return EXCEPTION_CONTINUE_SEARCH;
	}
}

void Level3(void)
{
	try
	{
		CauseExceptions();
	}
	except (Level3Filter(GetExceptionCode()))
	{
		// shouldn't get here, we never say EXCEPTION_EXECUTE_HANDLER
		printf("In Level 3 exception handler:  terminating program\n");
		exit(1);
	}
}

int Level3Filter(ULONG ExcepCode)
{
	if (ExcepCode == EXCEPTION_INT_OVERFLOW)
	{
		printf("Level 3 - ignoring integer overflow\n");
		return EXCEPTION_CONTINUE_EXECUTION;
	}
	else
	{
		printf("Level 3 - Can't handle exception: %08Xh\n", ExcepCode);
		return EXCEPTION_CONTINUE_SEARCH;
	}
}

int VarInDataSeg;
void CauseExceptions(void)
{
	_asm
	{
		mov	eax,7FFFFFFFh
		mov	ebx,7FFFFFFFh
		add	eax,ebx
		into			; integer overflow
	}

	_asm
	{
		xor	ebx,ebx
		div	ebx		; divide by zero
	}

	_asm
	{
		push	0
		pop	ds		; set DS to null selector
		mov	VarInDataSeg,0	; GP fault, because DS is null
	}
	return;
}
