Sun Oct 12 15:03:01 1997 Alexandre Julliard <julliard@lrc.epfl.ch> * [if1632/builtin.c] [if1632/relay.c] Relay debugging entry points are now generated on the fly for Win32 DLLs. * [include/stackframe.h] Added VA_LIST16 type and macros to access arguments on the 16-bit stack. * [memory/global.c] Fixed GlobalHandle32 to work with fixed blocks. * [misc/ddeml.c] (New file) Added a lot of stubs for DDEML functions. * [objects/dc.c] Added Get/SetGraphicsMode(). * [objects/gdiobj.c] [windows/winpos.c] Added a few stubs. * [tools/build.c] Removed 'byte', 'word', 'long' and 'return' entry points for Win32. 'register' functions can no longer take arguments in Win32. The Win32 NE module is now generated by MODULE_CreateDummyModule. CallFrom32 callbacks removed except for register functions. Fri Oct 10 18:22:18 1997 John Harvey <john@division.co.uk> * [graphics/win16drv/Makefile.in] [graphics/win16drv/brush.c] [graphics/win16drv/graphics.c] [graphics/win16drv/init.c] [graphics/win16drv/objects.c] [graphics/win16drv/pen.c] [graphics/win16drv/prtdrv.c] [graphics/win16drv/text.c] [include/callback.h] [include/win16drv.h] Added support for pens and brushes in SelectObject. Added support for LineTo, MoveToEx, PatBlt (very preliminary), Polygon and Rectangle. Text is drawn in the correct place more often. These changes may only work with the Windows Postscript driver since many other drivers now need more GDI support. Tue Oct 7 21:06:23 1997 Kristian Nielsen <kristian.nielsen@risoe.dk> * [debugger/expr.c] Fixed typo for the >> operator. * [loader/task.c] Fixed SwitchStackTo(); it used to return with the new stack placed four bytes too high in memory. * [loader/ne_resource.c] Removed problematic nametable code introduced in Wine 970914. Tue Oct 7 02:24:12 1997 Dimitrie O. Paun <dimi@cs.toronto.edu> * [controls/commctrl.c] Added this files to hold functions from the comctl32.dll Added to this files some functions scattered in different places (such as InitCommonControls) and added some new ones as well. * [include/syscolor.h] [windows/syscolor.c] Added proper entries for all possible COLOR_* values. * [objects/brush.c] Modified GetSysColorBrush to return the correct brush for all possible COLOR_* constants. Sat Oct 4 23:35:20 1997 U.Bonnes <bon@elektron.ikp.physik.th-darmstadt.de> * [loader/module.c] [scheduler/process.c] [win32/environment.c] Another approach to get access to an unrestricted commandline. * [misc/crtdll.c] Make fclose work again. * [if1632/crtdll.spec] Use sprintf for crtdll-sprintf again as e.g. %g is not available for wsprintf. * [misc/wsprintf.c] Make WPR_STRING work in more situations. Added debug output for the wsprintf functions. * [misc/crtdll.c] [misc/main.c] Use argv[0] as comand with CRTDLL_system. Fri Oct 3 14:00:29 MET DST 1997 Jan Willamowius <jan@janhh.shnet.org> * [*/*] Removed some compiler warnings. * [msdos/int15.c] New INT 15 handler.
219 lines
8 KiB
C
219 lines
8 KiB
C
/*
|
|
* 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 <stdio.h>
|
|
#include "windows.h"
|
|
#include "winerror.h"
|
|
#include "ldt.h"
|
|
#include "process.h"
|
|
#include "thread.h"
|
|
#include "stddebug.h"
|
|
#include "debug.h"
|
|
#include "except.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.
|
|
*/
|
|
void WINAPI RtlUnwind( PEXCEPTION_FRAME pEndFrame, LPVOID unusedEip,
|
|
PEXCEPTION_RECORD pRecord, DWORD returnEax,
|
|
PCONTEXT pcontext /* Wine additional parameter */ )
|
|
{
|
|
EXCEPTION_RECORD record;
|
|
DWORD dispatch;
|
|
int retval;
|
|
|
|
EAX_reg(pcontext) = returnEax;
|
|
|
|
/* 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(pcontext);
|
|
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(pcontext) != NULL) &&
|
|
(TEB_EXCEPTION_FRAME(pcontext) != ((void *)0xffffffff)) &&
|
|
(TEB_EXCEPTION_FRAME(pcontext) != pEndFrame))
|
|
{
|
|
dprintf_win32( stddeb, "calling exception handler at 0x%x\n",
|
|
(int)TEB_EXCEPTION_FRAME(pcontext)->Handler );
|
|
|
|
dispatch=0;
|
|
retval = TEB_EXCEPTION_FRAME(pcontext)->Handler( pRecord,
|
|
TEB_EXCEPTION_FRAME(pcontext),
|
|
pcontext, &dispatch);
|
|
|
|
dprintf_win32(stddeb,"exception handler returns 0x%x, dispatch=0x%x\n",
|
|
retval, (int) dispatch);
|
|
|
|
if ( (retval == ExceptionCollidedUnwind) &&
|
|
(TEB_EXCEPTION_FRAME(pcontext) != (LPVOID)dispatch)
|
|
)
|
|
TEB_EXCEPTION_FRAME(pcontext) = (LPVOID)dispatch;
|
|
else if ( (TEB_EXCEPTION_FRAME(pcontext) != pEndFrame) &&
|
|
(TEB_EXCEPTION_FRAME(pcontext) != TEB_EXCEPTION_FRAME(pcontext)->Prev)
|
|
)
|
|
TEB_EXCEPTION_FRAME(pcontext) = TEB_EXCEPTION_FRAME(pcontext)->Prev;
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* This is the real entry point called by relay debugging code */
|
|
void EXC_RtlUnwind( CONTEXT *context )
|
|
{
|
|
/* Retrieve the arguments (args[0] is return addr, args[1] is first arg) */
|
|
DWORD *args = (DWORD *)ESP_reg(context);
|
|
ESP_reg(context) += 4 * sizeof(DWORD); /* Pop the arguments */
|
|
RtlUnwind( (PEXCEPTION_FRAME)args[1], (LPVOID)args[2],
|
|
(PEXCEPTION_RECORD)args[3], args[4], context );
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
* RaiseException (KERNEL32.418)
|
|
*/
|
|
void WINAPI RaiseException(DWORD dwExceptionCode,
|
|
DWORD dwExceptionFlags,
|
|
DWORD cArguments,
|
|
const LPDWORD lpArguments,
|
|
PCONTEXT pcontext /* Wine additional parameter */ )
|
|
{
|
|
PEXCEPTION_FRAME pframe;
|
|
EXCEPTION_RECORD record;
|
|
DWORD dispatch; /* is this used in raising exceptions ?? */
|
|
int retval;
|
|
int i;
|
|
|
|
/* compose an exception record */
|
|
|
|
record.ExceptionCode = dwExceptionCode;
|
|
record.ExceptionFlags = dwExceptionFlags;
|
|
record.ExceptionRecord = NULL;
|
|
record.NumberParameters = cArguments;
|
|
record.ExceptionAddress = (LPVOID)EIP_reg(pcontext);
|
|
|
|
if (lpArguments) for( i = 0; i < cArguments; i++)
|
|
record.ExceptionInformation[i] = lpArguments[i];
|
|
|
|
/* get chain of exception frames */
|
|
|
|
retval = ExceptionContinueSearch;
|
|
pframe = TEB_EXCEPTION_FRAME( pcontext );
|
|
|
|
while((pframe!=NULL)&&(pframe!=((void *)0xFFFFFFFF)))
|
|
{
|
|
dprintf_win32(stddeb,"calling exception handler at 0x%x\n",
|
|
(int) pframe->Handler);
|
|
dispatch=0;
|
|
dprintf_relay(stddeb,"CallTo32(except=%p,record=%p,frame=%p,context=%p,dispatch=%p)\n",
|
|
pframe->Handler, &record, pframe, pcontext, &dispatch );
|
|
retval=pframe->Handler(&record,pframe,pcontext,&dispatch);
|
|
|
|
dprintf_win32(stddeb,"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? */
|
|
dprintf_win32(stddeb,"no handler wanted to handle the exception, exiting\n");
|
|
ExitProcess(dwExceptionCode); /* what status should be used here ? */
|
|
}
|
|
}
|
|
|
|
/* This is the real entry point called by relay debugging code */
|
|
void EXC_RaiseException( CONTEXT *context )
|
|
{
|
|
/* Retrieve the arguments (args[0] is return addr, args[1] is first arg) */
|
|
DWORD *args = (DWORD *)ESP_reg(context);
|
|
ESP_reg(context) += 4 * sizeof(DWORD); /* Pop the arguments */
|
|
RaiseException( args[1], args[2], args[3], (LPDWORD)args[4], context );
|
|
}
|
|
|
|
/*******************************************************************
|
|
* UnhandledExceptionFilter (KERNEL32.537)
|
|
*/
|
|
DWORD WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS epointers)
|
|
{
|
|
char message[80];
|
|
|
|
/* FIXME: Should check if the process is being debugged */
|
|
|
|
if (pCurrentProcess && pCurrentProcess->top_filter)
|
|
{
|
|
DWORD ret = pCurrentProcess->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 )
|
|
{
|
|
LPTOP_LEVEL_EXCEPTION_FILTER old = pCurrentProcess->top_filter;
|
|
pCurrentProcess->top_filter = filter;
|
|
return old;
|
|
}
|