//
// Copyright (c) 2002
// Ronald Kevin Burton
//
// Z poniższym kodem nie jest związana żadna gwarancja poprawności działania.
// Program został dołączony do książki ".NET CLR. Księga eksperta" w celu
// ilustracji koncepcji i zasad przedstawionych w tej książce. Program może być 
// używany na własne ryzyko.
//
// Przyznaje się prawo do użycia lub kopiowania tego oprogramowania do dowolnego celu
// bez konieczności ponoszenia żadnych opłat pod warunkiem, że powyższe uwagi zostaną 
// zachowane we wszystkich kopiach. Przyznaje się także prawo do modyfikacji kodu
// i dystrybucji zmodyfikowanego kodu pod warunkiem zachowania powyższych uwag
// oraz dołączenia informacji mówiącej o modyfikacji kodu.
//
// 
#include <iostream>

#using <mscorlib.dll>
using namespace System;

struct UnmanagedException
{
	UnmanagedException(int e) : err(e)
	{
	}
	int Error()
	{
		return err;
	}
private:
	int err;
};

void ExceptionGenerator(int i)
{
   if (i == 0)
   {
	   // Zgłasza wyjątek, który nie jest oparty o SystemException,
	   // przez co nie jest to zarządzany wyjątek
	   UnmanagedException *e = new UnmanagedException(10);
	   throw (e);
   }
   else if(i == 1)
   {
	   //  Zarządzany wyjątek
	   Exception *e = new Exception;
	   throw e;
   }
   else if(i == 2)
   {
	   // Dzielenie przez zero
	   int a = 0;
	   int b = 1;
	   int c = b/a;
   }
   else if(i == 3)
   {
	   // Puste odwołanie
	   int *pint = 0;
	   std::cout << pint[10] << std::endl;
   }
   else if(i == 4)
   {
	   // Przepełnienie stosu
	   ExceptionGenerator(4);
   }
   else if(i == 5)
   {
	   // Nieokreślony
	   throw;
   }
}

void FilterTest()
{
	for (int i = 0; i < 1; i++)
	{
		__try
		{
			throw new InvalidOperationException("To jest test");
		}
		__except (i == 0)
		{
			Console::WriteLine(S"\nPrzechwycono i==0 wyjątek\n");
		}
	}
}

int main()
{
	for (int i = 0; i < 6; i++)
	{
		try
		{
			ExceptionGenerator(i);
		}
		catch (UnmanagedException* u)
		{
			Console::WriteLine(S"\nPrzechwycono niezarządzany wyjątek\n");
			std::cout << u->Error() << std::endl;
		}
		catch (Exception* e)
		{
			Console::WriteLine(S"\nPrzechwycono zarządzany wyjątek\n");
			Console::WriteLine(e->ToString());
		}
		catch (...)
		{
			Console::WriteLine(S"\nPrzechwycono ogólny wyjątek\n");
		}
	}

	FilterTest();

	return 0;
}
