/*
 * Win32 exception functions
 *
 * Copyright (c) 1996 Onno Hovers, (onno@stack.urc.tue.nl)
 *
 * Notes:
 *  What really happens behind the scenes of those new
 *  __try{...}__except(..){....}  and
 *  __try{...}__finally{...}
 *  statements is simply not documented by Microsoft. There could be different
 *  reasons for this: 
 *  One reason could be that they try to hide the fact that exception 
 *  handling in Win32 looks almost the same as in OS/2 2.x.  
 *  Another reason could be that Microsoft does not want others to write
 *  binary compatible implementations of the Win32 API (like us).  
 *
 *  Whatever the reason, THIS SUCKS!! Ensuring portabilty or future 
 *  compatability may be valid reasons to keep some things undocumented. 
 *  But exception handling is so basic to Win32 that it should be 
 *  documented!
 *
 * Fixmes:
 *  -Most functions need better parameter checking.
 *  -I do not know how to handle exceptions within an exception handler.
 *   or what is done when ExceptionNestedException is returned from an 
 *   exception handler
 *  -Real exceptions are not yet implemented. only the exception functions
 *   are implemented. A real implementation needs some new code in
 *   loader/signal.c. There would also be a need for showing debugging
 *   information in UnhandledExceptionFilter.
 *
 */

#include <assert.h>
#include "windows.h"
#include "winerror.h"
#include "ldt.h"
#include "process.h"
#include "thread.h"
#include "debug.h"
#include "except.h"
#include "stackframe.h"

#define TEB_EXCEPTION_FRAME(pcontext) \
    ((PEXCEPTION_FRAME)((TEB *)GET_SEL_BASE((pcontext)->SegFs))->except)

/*******************************************************************
 *         RtlUnwind  (KERNEL32.443)
 *
 *  This function is undocumented. This is the general idea of 
 *  RtlUnwind, though. Note that error handling is not yet implemented.
 *
 * The real prototype is:
 * void WINAPI EXC_RtlUnwind( PEXCEPTION_FRAME pEndFrame, LPVOID unusedEip, 
 *                            PEXCEPTION_RECORD pRecord, DWORD returnEax );
 */
REGS_ENTRYPOINT(RtlUnwind)
{
    EXCEPTION_RECORD record;
    DWORD            dispatch;
    int              retval;
    PEXCEPTION_FRAME pEndFrame;
    PEXCEPTION_RECORD pRecord;

    /* get the arguments from the stack */

    DWORD ret        = STACK32_POP(context);  /* return addr */
    pEndFrame        = (PEXCEPTION_FRAME)STACK32_POP(context);
    (void)STACK32_POP(context);  /* unused arg */
    pRecord          = (PEXCEPTION_RECORD)STACK32_POP(context);
    EAX_reg(context) = STACK32_POP(context);
    STACK32_PUSH(context,ret);  /* restore return addr */
   
   /* build an exception record, if we do not have one */
   if(!pRecord)
   {
     record.ExceptionCode    = STATUS_INVALID_DISPOSITION;
     record.ExceptionFlags   = 0;
     record.ExceptionRecord  = NULL;
     record.ExceptionAddress = (LPVOID)EIP_reg(context); 
     record.NumberParameters = 0;
     pRecord = &record;
   }

   if(pEndFrame)
     pRecord->ExceptionFlags|=EH_UNWINDING;
   else
     pRecord->ExceptionFlags|=EH_UNWINDING | EH_EXIT_UNWIND;
  
   /* get chain of exception frames */      
   while ((TEB_EXCEPTION_FRAME(context) != NULL) &&
          (TEB_EXCEPTION_FRAME(context) != ((void *)0xffffffff)) &&
          (TEB_EXCEPTION_FRAME(context) != pEndFrame))
   {
       TRACE(win32, "calling exception handler at 0x%x\n",
                      (int)TEB_EXCEPTION_FRAME(context)->Handler );

       dispatch=0;       
       retval = TEB_EXCEPTION_FRAME(context)->Handler( pRecord,
                                                TEB_EXCEPTION_FRAME(context),
                                                context, &dispatch);
                                         
       TRACE(win32,"exception handler returns 0x%x, dispatch=0x%x\n",
                              retval, (int) dispatch);
  
       if (	(retval == ExceptionCollidedUnwind) &&
           	(TEB_EXCEPTION_FRAME(context) != (LPVOID)dispatch)
       )
           TEB_EXCEPTION_FRAME(context) = (LPVOID)dispatch;
       else if (	(TEB_EXCEPTION_FRAME(context) != pEndFrame) &&
           		(TEB_EXCEPTION_FRAME(context) != TEB_EXCEPTION_FRAME(context)->Prev)
       )
           TEB_EXCEPTION_FRAME(context) = TEB_EXCEPTION_FRAME(context)->Prev;
       else
          break;  
   }
}


/*******************************************************************
 *         RaiseException  (KERNEL32.418)
 *
 * The real prototype is:
 * void WINAPI EXC_RaiseException(DWORD dwExceptionCode,
 *                                DWORD dwExceptionFlags,
 *                                DWORD cArguments,
 *                                const LPDWORD lpArguments );
 */
REGS_ENTRYPOINT(RaiseException)
{
    PEXCEPTION_FRAME    pframe; 
    EXCEPTION_RECORD    record;
    DWORD               dispatch; /* is this used in raising exceptions ?? */
    int                 retval;
    int                 i;

    /* Get the arguments from the stack */

    DWORD ret                 = STACK32_POP(context);  /* return addr */
    DWORD dwExceptionCode     = STACK32_POP(context);
    DWORD dwExceptionFlags    = STACK32_POP(context);
    DWORD cArguments          = STACK32_POP(context);
    const LPDWORD lpArguments = (LPDWORD)STACK32_POP(context);
    STACK32_PUSH(context,ret);  /* Restore the return address */

    /* compose an exception record */ 
    
    record.ExceptionCode       = dwExceptionCode;   
    record.ExceptionFlags      = dwExceptionFlags;
    record.ExceptionRecord     = NULL;
    record.NumberParameters    = cArguments;
    record.ExceptionAddress    = (LPVOID)EIP_reg(context);
    
    if (lpArguments) for( i = 0; i < cArguments; i++)
        record.ExceptionInformation[i] = lpArguments[i];
    
    /* get chain of exception frames */    
    
    retval = ExceptionContinueSearch;    
    pframe = TEB_EXCEPTION_FRAME( context );
    
    while((pframe!=NULL)&&(pframe!=((void *)0xFFFFFFFF)))
    {
       TRACE(win32,"calling exception handler at 0x%x\n",
                                                (int) pframe->Handler);
       dispatch=0;  
       TRACE(relay,"(except=%p,record=%p,frame=%p,context=%p,dispatch=%p)\n",
                     pframe->Handler, &record, pframe, context, &dispatch );
       retval=pframe->Handler(&record,pframe,context,&dispatch);
 
       TRACE(win32,"exception handler returns 0x%x, dispatch=0x%x\n",
                              retval, (int) dispatch);
                              
       if(retval==ExceptionContinueExecution)
          break;
       pframe=pframe->Prev;
   }

   if (retval!=ExceptionContinueExecution)
   {    
       /* FIXME: what should we do here? */
       TRACE(win32,"no handler wanted to handle the exception, exiting\n");
       ExitProcess(dwExceptionCode); /* what status should be used here ? */
   }
}


/*******************************************************************
 *         UnhandledExceptionFilter   (KERNEL32.537)
 */
DWORD WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS epointers)
{
    char message[80];
    PDB32 *pdb = PROCESS_Current();

    /* FIXME: Should check if the process is being debugged */

    if (pdb->top_filter)
    {
        DWORD ret = pdb->top_filter( epointers );
        if (ret != EXCEPTION_CONTINUE_SEARCH) return ret;
    }

    /* FIXME: Should check the current error mode */

    sprintf( message, "Unhandled exception 0x%08lx at address 0x%08lx.",
             epointers->ExceptionRecord->ExceptionCode,
             (DWORD)epointers->ExceptionRecord->ExceptionAddress );
    MessageBox32A( 0, message, "Error", MB_OK | MB_ICONHAND );
    return EXCEPTION_EXECUTE_HANDLER;
}


/*************************************************************
 *            SetUnhandledExceptionFilter   (KERNEL32.516)
 */
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter(
                                          LPTOP_LEVEL_EXCEPTION_FILTER filter )
{
    PDB32 *pdb = PROCESS_Current();
    LPTOP_LEVEL_EXCEPTION_FILTER old = pdb->top_filter;
    pdb->top_filter = filter;
    return old;
}
