////////////////////////////////////////////////////////////////////////////////
//
// FilterChain.cpp 
//
// Author: Oleg Starodumov (www.debuginfo.com)
//


////////////////////////////////////////////////////////////////////////////////
//
// This example demonstrates filter chaining. It installs three custom filters 
// for unhandled exceptions, one after another. When called, each filter 
// attempts to call the previously registered filter. Console output 
// allows to verify that all three custom filters are called. 
// 
//


////////////////////////////////////////////////////////////////////////////////
// Include files 
//

#include <windows.h>
#include <tchar.h>
#include <stdio.h>


////////////////////////////////////////////////////////////////////////////////
// Function declarations
//

	// Custom filters 
LONG __stdcall FirstFilter( EXCEPTION_POINTERS* pep ); 
LONG __stdcall SecondFilter( EXCEPTION_POINTERS* pep ); 
LONG __stdcall ThirdFilter( EXCEPTION_POINTERS* pep ); 

	// Test function 
void FaultyFunc(); 


////////////////////////////////////////////////////////////////////////////////
// Global variables 
//

	// Previous filter pointers 
LPTOP_LEVEL_EXCEPTION_FILTER FirstFilter_Prev = 0;
LPTOP_LEVEL_EXCEPTION_FILTER SecondFilter_Prev = 0;
LPTOP_LEVEL_EXCEPTION_FILTER ThirdFilter_Prev = 0;


////////////////////////////////////////////////////////////////////////////////
// main() function
//

int main() 
{
	// Register custom filters, one after another, and save information 
	// about previously registered filters 

	FirstFilter_Prev   = SetUnhandledExceptionFilter( FirstFilter ); 
	SecondFilter_Prev  = SetUnhandledExceptionFilter( SecondFilter ); 
	ThirdFilter_Prev   = SetUnhandledExceptionFilter( ThirdFilter ); 

	// Simulate an exception 

	FaultyFunc();

	return 0; 
}


////////////////////////////////////////////////////////////////////////////////
// Custom filters for unhandled exceptions
// 
// Each of these filters calls the previously registered filter 
//

LONG __stdcall FirstFilter( EXCEPTION_POINTERS* pep ) 
{
	_tprintf( _T("FirstFilter()...\n") );

	if( FirstFilter_Prev != 0 )
		return (FirstFilter_Prev)(pep);
	else
		return EXCEPTION_EXECUTE_HANDLER; 
}

LONG __stdcall SecondFilter( EXCEPTION_POINTERS* pep ) 
{
	_tprintf( _T("SecondFilter()...\n") );

	if( SecondFilter_Prev != 0 )
		return (SecondFilter_Prev)(pep);
	else
		return EXCEPTION_EXECUTE_HANDLER; 
}

LONG __stdcall ThirdFilter( EXCEPTION_POINTERS* pep ) 
{
	_tprintf( _T("ThirdFilter()...\n") );

	if( ThirdFilter_Prev != 0 )
		return (ThirdFilter_Prev)(pep);
	else
		return EXCEPTION_EXECUTE_HANDLER; 
}


////////////////////////////////////////////////////////////////////////////////
// Faulty function
//

void FaultyFunc()
{
	_tprintf( _T("We will crash now...\n") );

	*(int*)0 = 1;
}

