/*
 * 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 "winuser.h"
#include "winerror.h"
#include "ldt.h"
#include "process.h"
#include "thread.h"
#include "debug.h"
#include "except.h"
#include "stackframe.h"

DECLARE_DEBUG_CHANNEL(relay)
DECLARE_DEBUG_CHANNEL(win32)

#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)))
    {
       PEXCEPTION_FRAME    prevframe; 
       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 );
       prevframe = pframe->Prev;
       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=prevframe;
   }

   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];
    PDB *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 );
    MessageBoxA( 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 )
{
    PDB *pdb = PROCESS_Current();
    LPTOP_LEVEL_EXCEPTION_FILTER old = pdb->top_filter;
    pdb->top_filter = filter;
    return old;
}
