/* -----------------------------------------------------------------------------
*
* (c) The GHC Team 1998-2000
*
* Header for windows Error Handling implementations
*
* ---------------------------------------------------------------------------*/

#ifndef WIN32_VEH_EXCN_H
#define WIN32_VEH_EXCN_H

#include <stdio.h>
#include <stdlib.h>
#include <Rts.h>

// Stuff needed to install and use VEH exception handlers
#include <excpt.h>
#include <windows.h>

// Exception handling.
//
// On Windows, the default action for things like division by zero and
// segfaults is to pop up a Dr. Watson error reporting dialog if the exception
// is unhandled by the user code.
//
// This is a pain when we are SSHed into a Windows machine, or when we
// want to debug a problem with gdb (gdb will get a first and second chance to
// handle the exception, but if it doesn't the pop-up will show).
//
// 
// Previously this code was handled using SEH (Structured Exception Handlers)
// however each compiler and platform have different ways of dealing with SEH.
// 
// MSVC compilers have the keywords __try, __catch and __except to have the 
// compiler generate the appropriate SEH handler code for you.
//
// MinGW compilers have no such keywords and require you to manually set the
// SEH Handlers, however because SEH is implemented differently in x86 and x64
// the methods to use them in GCC differs.
//
// x86: SEH is based on the stack, the SEH handlers are available at FS[0].
//      On startup one would only need to add a new handler there. This has 
//      a number of issues such as hard to share handlers and it can be exploited.
//
// x64: In order to fix the issues with the way SEH worked in x86, on x64 SEH handlers
//      are statically compiled and added to the .pdata section by the compiler.
//      Instead of being thread global they can now be Image global since you have to 
//      specify the RVA of the region of code that the handlers govern.
//
// You can on x64 Dynamically allocate SEH handlers, but it seems that (based on
// experimentation and it's very under-documented) that the dynamic calls cannot override
// static SEH handlers in the .pdata section. 
//
// Because of this and because GHC no longer needs to support < windows XP, the better 
// alternative for handling errors would be using the in XP introduced VEH.
// 
// The bonus is because VEH (Vectored Exception Handler) are a runtime construct the API
// is the same for both x86 and x64 (note that the Context object does contain CPU specific 
// structures) and the calls are the same cross compilers. Which means this file can be 
// simplified quite a bit.
// Using VEH also means we don't have to worry about the dynamic code generated by GHCi.

// Prototype of the VEH callback function.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms681419(v=vs.85).aspx
//
long WINAPI __hs_exception_handler( struct _EXCEPTION_POINTERS *exception_data );

// prototypes to the functions doing the registration and unregistration of the VEH handlers
void __register_hs_exception_handler( void );
void __unregister_hs_exception_handler( void );

#endif /* WIN32_VEH_EXCN_H */

