exception.c


/*
	$RCSfile: exception.c $
	$Revision: 1.3 $
	$Author: doomer $
	$Date: 1997/05/20 12:07:42 $
	Copyright (c) 1997 John Dumais
*/

/*
	This file is an example to illustrate a technique for
	catching exceptions generated in a DLL.  We set up an
	exception handler that knows how to deal with divide-
	by-zero errors.  A key point is that the condition which
	caused the exception must be cleared before execution
	is returned to the application calling this DLL.
	Otherwise, the condition which caused the exception will
	still exist, and our application will react to the
	exceptional condition.

	We have used the Windows NT (tm) Structured Exception
	Handling mechanism, because the use of C++ exceptions
	in functions declared ' extern "C" ' produces undefined
	behavior in most compilers.
*/

#include "exception.h"

/*
	This is our DLL's exported function.  It divides the
	value 5 by whatever value is passed into 'divisor'.
	If 'divisor' is 0, we will generate an exception.
*/

double functionBlowsUp(double divisor){
	double x;
	unsigned int fpStatus; /* the fpu status value */

	/*
		Set up an exception handler
	*/
	
	__try{
		x=5/divisor;
	}

	/*
		This is our exception filter.  The call to 'GetExceptionCode'
		will only return valid results when called within parentheses
		following the '__except' key word.  The value returned from the
		function 'evaluateException' detemines what action our filter
		will take.  If the return value is EXCEPTION_EXECUTE_HANDLER,
		we will execute the code in the body of the '__except' block.
		Processing then continues with the next statement following
		the '__except' block.

		If our evaluation function returns EXCEPTION_CONTINUE_SEARCH,
		the OS will look for a handler willing to deal with the
		exception.  In our specific case, the exception will get passed
		back to VEE.  The default action when the OS can't find a
		handler for the exception is to terminate the process.
	*/
	
	__except(evaluateException(GetExceptionCode())){
		/*
			We need to clear the condition which caused the exception.
			In the specific case of a divide-by-zero error, we can call
			'_clearfp', which will return the floating-point processor
			status word and clear the exception condition.
		*/
		
		fpStatus=_clearfp();

		/*
			We pass back a big number to indicate that something
			went wrong.
		*/
		
		x=9.9e37;
	}

	return x;
}

/*
	This function is called from our exception filter.  If the
	exception is determined to be a divide-by-zero error, we
	return a value that will cause the code in the body of our
	'__except' block to execute.  Otherwise, we pass back a value
	indicating that the OS should look for a handler willing to deal
	with the exception.
*/

int evaluateException(DWORD exceptionCode){
	int returnVal=EXCEPTION_CONTINUE_SEARCH;

	switch(exceptionCode){
		case EXCEPTION_FLT_DIVIDE_BY_ZERO:

			returnVal=EXCEPTION_EXECUTE_HANDLER;
			break;

		default:
			break;
	}
	
	return returnVal;
}

/*
	$Log: exception.c $
	Revision 1.3  1997/05/20 12:07:42  doomer
	another typo
	Revision 1.2  1997/05/20 10:51:50  doomer
	typo
	Revision 1.1  1997/05/20 10:43:40  doomer
	Initial revision
*/