mirror of
https://github.com/reactos/reactos.git
synced 2025-06-27 06:09:44 +00:00
- After bugfixing, more complete except_nt exception handling implementation could be used, so get rid of the old one and thus code duplication.
- Move cpp/cppexcept.c to /except directory, and add a specific note in README.WINE that those files are shared with Wine. - I moved PowerPC stubs too, but it will most probably break anyway, due to more missing stubs, my apologize. See issue #2371 for more details. svn path=/trunk/; revision=30359
This commit is contained in:
parent
f0c9da09e2
commit
2db7ea2321
13 changed files with 427 additions and 851 deletions
|
@ -40,7 +40,8 @@
|
||||||
</directory>
|
</directory>
|
||||||
<directory name="except">
|
<directory name="except">
|
||||||
<file>abnorter.c</file>
|
<file>abnorter.c</file>
|
||||||
<file>exhand2.c</file>
|
<file>cpp.c</file>
|
||||||
|
<file>cppexcept.c</file>
|
||||||
<file>matherr.c</file>
|
<file>matherr.c</file>
|
||||||
<if property="ARCH" value="i386">
|
<if property="ARCH" value="i386">
|
||||||
<directory name="i386">
|
<directory name="i386">
|
||||||
|
@ -49,6 +50,12 @@
|
||||||
<file>unwind.c</file>
|
<file>unwind.c</file>
|
||||||
</directory>
|
</directory>
|
||||||
</if>
|
</if>
|
||||||
|
<if property="ARCH" value="powerpc">
|
||||||
|
<directory name="powerpc">
|
||||||
|
<file>seh.s</file>
|
||||||
|
<file>chkstk_asm.s</file>
|
||||||
|
</directory>
|
||||||
|
</if>
|
||||||
<file>xcptfil.c</file>
|
<file>xcptfil.c</file>
|
||||||
</directory>
|
</directory>
|
||||||
<directory name="float">
|
<directory name="float">
|
||||||
|
@ -475,8 +482,6 @@
|
||||||
<file>wlasttok.c</file>
|
<file>wlasttok.c</file>
|
||||||
</directory>
|
</directory>
|
||||||
<directory name="wine">
|
<directory name="wine">
|
||||||
<file>cpp.c</file>
|
|
||||||
<file>cppexcept.c</file>
|
|
||||||
<file>heap.c</file>
|
<file>heap.c</file>
|
||||||
<file>scanf.c</file>
|
<file>scanf.c</file>
|
||||||
<file>thread.c</file>
|
<file>thread.c</file>
|
||||||
|
|
|
@ -1,16 +1 @@
|
||||||
#include <precomp.h>
|
#include <precomp.h>
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @unimplemented
|
|
||||||
*/
|
|
||||||
int _abnormal_termination(void)
|
|
||||||
{
|
|
||||||
printf("Abnormal Termination\n");
|
|
||||||
// return AbnormalTermination();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
#include <precomp.h>
|
|
||||||
#include <excpt.h>
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#else
|
|
||||||
ULONG DbgPrint(PCH Format,...)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
VOID STDCALL
|
|
||||||
MsvcrtDebug(ULONG Value)
|
|
||||||
{
|
|
||||||
//DbgPrint("MsvcrtDebug 0x%.08x\n", Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct _EXCEPTION_RECORD;
|
|
||||||
struct _CONTEXT;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
EXCEPTION_DISPOSITION
|
|
||||||
_except_handler2(
|
|
||||||
struct _EXCEPTION_RECORD *ExceptionRecord,
|
|
||||||
void *Frame,
|
|
||||||
struct _CONTEXT *ContextRecord,
|
|
||||||
void *DispatcherContext)
|
|
||||||
{
|
|
||||||
//printf("_except_handler2()\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
729
reactos/lib/sdk/crt/except/i386/seh.s
Executable file → Normal file
729
reactos/lib/sdk/crt/except/i386/seh.s
Executable file → Normal file
|
@ -1,367 +1,468 @@
|
||||||
/* $Id$
|
/*
|
||||||
*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS MSVCRT Runtime Library
|
* PROJECT: ReactOS CRT
|
||||||
* PURPOSE: Runtime library exception support for IA-32
|
* FILE: lib/crt/misc/i386/seh.S
|
||||||
* FILE: lib/msvcrt/except/seh.s
|
* PURPOSE: SEH Support for the CRT
|
||||||
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
* NOTES: This file is shared with ntoskrnl/rtl/i386/seh.s.
|
|
||||||
* Please keep them in sync.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define ExceptionContinueExecution 0
|
/* INCLUDES ******************************************************************/
|
||||||
#define ExceptionContinueSearch 1
|
|
||||||
#define ExceptionNestedException 2
|
|
||||||
#define ExceptionCollidedUnwind 3
|
|
||||||
|
|
||||||
#define EXCEPTION_NONCONTINUABLE 0x01
|
#include <ndk/asm.h>
|
||||||
#define EXCEPTION_UNWINDING 0x02
|
.intel_syntax noprefix
|
||||||
#define EXCEPTION_EXIT_UNWIND 0x04
|
|
||||||
#define EXCEPTION_STACK_INVALID 0x08
|
|
||||||
#define EXCEPTION_NESTED_CALL 0x10
|
|
||||||
#define EXCEPTION_TARGET_UNWIND 0x20
|
|
||||||
#define EXCEPTION_COLLIDED_UNWIND 0x40
|
|
||||||
|
|
||||||
#define EXCEPTION_UNWIND_MODE \
|
#define DISPOSITION_DISMISS 0
|
||||||
( EXCEPTION_UNWINDING \
|
#define DISPOSITION_CONTINUE_SEARCH 1
|
||||||
| EXCEPTION_EXIT_UNWIND \
|
#define DISPOSITION_COLLIDED_UNWIND 3
|
||||||
| EXCEPTION_TARGET_UNWIND \
|
|
||||||
| EXCEPTION_COLLIDED_UNWIND)
|
|
||||||
|
|
||||||
#define EREC_CODE 0x00
|
/* GLOBALS *******************************************************************/
|
||||||
#define EREC_FLAGS 0x04
|
|
||||||
#define EREC_RECORD 0x08
|
|
||||||
#define EREC_ADDRESS 0x0C
|
|
||||||
#define EREC_NUMPARAMS 0x10
|
|
||||||
#define EREC_INFO 0x14
|
|
||||||
|
|
||||||
#define TRYLEVEL_NONE -1
|
|
||||||
#define TRYLEVEL_INVALID -2
|
|
||||||
|
|
||||||
#define ER_STANDARDESP -0x08
|
|
||||||
#define ER_EPOINTERS -0x04
|
|
||||||
#define ER_PREVFRAME 0x00
|
|
||||||
#define ER_HANDLER 0x04
|
|
||||||
#define ER_SCOPETABLE 0x08
|
|
||||||
#define ER_TRYLEVEL 0x0C
|
|
||||||
#define ER_EBP 0x10
|
|
||||||
|
|
||||||
#define ST_TRYLEVEL 0x00
|
|
||||||
#define ST_FILTER 0x04
|
|
||||||
#define ST_HANDLER 0x08
|
|
||||||
|
|
||||||
#define CONTEXT_EDI 0x9C
|
|
||||||
#define CONTEXT_EBX 0xA4
|
|
||||||
#define CONTEXT_EIP 0xB8
|
|
||||||
|
|
||||||
|
.globl __global_unwind2
|
||||||
.globl __local_unwind2
|
.globl __local_unwind2
|
||||||
|
.globl __abnormal_termination
|
||||||
|
.globl __except_handler2
|
||||||
.globl __except_handler3
|
.globl __except_handler3
|
||||||
|
|
||||||
// EAX = value to print
|
/* FUNCTIONS *****************************************************************/
|
||||||
_do_debug:
|
|
||||||
pushal
|
.func unwind_handler
|
||||||
pushl %eax
|
_unwind_handler:
|
||||||
call _MsvcrtDebug@4
|
|
||||||
popal
|
/* Check if we were unwinding and continue search if not */
|
||||||
|
mov ecx, [esp+4]
|
||||||
|
test dword ptr [ecx+4], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
|
||||||
|
mov eax, DISPOSITION_CONTINUE_SEARCH
|
||||||
|
jz unwind_handler_return
|
||||||
|
|
||||||
|
/* We have a collision, do a local unwind */
|
||||||
|
mov eax, [esp+20]
|
||||||
|
push ebp
|
||||||
|
mov ebp, [eax+16]
|
||||||
|
mov edx, [eax+40]
|
||||||
|
push edx
|
||||||
|
mov edx, [eax+36]
|
||||||
|
push edx
|
||||||
|
call __local_unwind2
|
||||||
|
add esp, 8
|
||||||
|
pop ebp
|
||||||
|
|
||||||
|
/* Set new try level */
|
||||||
|
mov eax, [esp+8]
|
||||||
|
mov edx, [esp+16]
|
||||||
|
mov [edx], eax
|
||||||
|
|
||||||
|
/* Return collided unwind */
|
||||||
|
mov eax, DISPOSITION_COLLIDED_UNWIND
|
||||||
|
|
||||||
|
unwind_handler_return:
|
||||||
ret
|
ret
|
||||||
|
.endfunc
|
||||||
|
|
||||||
#define LU2_TRYLEVEL 0x08
|
.func _global_unwind2
|
||||||
#define LU2_REGFRAME 0x04
|
__global_unwind2:
|
||||||
|
|
||||||
//
|
/* Create stack and save all registers */
|
||||||
// void
|
push ebp
|
||||||
// _local_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame,
|
mov ebp, esp
|
||||||
// LONG TryLevel)
|
push ebx
|
||||||
//
|
push esi
|
||||||
// Parameters:
|
push edi
|
||||||
// [EDX+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
|
push ebp
|
||||||
// [EDX+04h] - LONG TryLevel
|
|
||||||
// Registers:
|
/* Call unwind */
|
||||||
// EBP - EBP of call frame we are unwinding
|
push 0
|
||||||
// Returns:
|
push 0
|
||||||
// Nothing
|
push glu_return
|
||||||
// Notes:
|
push [ebp+8]
|
||||||
// Run all termination handlers for a call frame from the current
|
call _RtlUnwind@16
|
||||||
// try-level up to (but not including) the given stop try-level.
|
|
||||||
|
glu_return:
|
||||||
|
/* Restore registers and return */
|
||||||
|
pop ebp
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
pop ebx
|
||||||
|
mov esp, ebp
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
.endfunc
|
||||||
|
|
||||||
|
.func _abnormal_termination
|
||||||
|
__abnormal_termination:
|
||||||
|
|
||||||
|
/* Assume false */
|
||||||
|
xor eax, eax
|
||||||
|
|
||||||
|
/* Check if the handler is the unwind handler */
|
||||||
|
mov ecx, fs:0
|
||||||
|
cmp dword ptr [ecx+4], offset _unwind_handler
|
||||||
|
jne short ab_return
|
||||||
|
|
||||||
|
/* Get the try level */
|
||||||
|
mov edx, [ecx+12]
|
||||||
|
mov edx, [edx+12]
|
||||||
|
|
||||||
|
/* Compare it */
|
||||||
|
cmp [ecx+8], edx
|
||||||
|
jne ab_return
|
||||||
|
|
||||||
|
/* Return true */
|
||||||
|
mov eax, 1
|
||||||
|
|
||||||
|
/* Return */
|
||||||
|
ab_return:
|
||||||
|
ret
|
||||||
|
.endfunc
|
||||||
|
|
||||||
|
.func _local_unwind2
|
||||||
__local_unwind2:
|
__local_unwind2:
|
||||||
// Setup our call frame so we can access parameters using EDX
|
|
||||||
//pushl %ebp
|
|
||||||
movl %esp, %edx
|
|
||||||
|
|
||||||
// FIXME: Setup an EXCEPTION_REGISTRATION entry to protect the
|
/* Save volatiles */
|
||||||
// unwinding in case something goes wrong
|
push ebx
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
|
||||||
.lu2_next_scope:
|
/* Get the exception registration */
|
||||||
|
mov eax, [esp+16]
|
||||||
|
|
||||||
// Keep a pointer to the exception registration in EBX
|
/* Setup SEH to protect the unwind */
|
||||||
movl LU2_REGFRAME(%edx), %ebx
|
push ebp
|
||||||
|
push eax
|
||||||
|
push -2
|
||||||
|
push offset _unwind_handler
|
||||||
|
push fs:0
|
||||||
|
mov fs:0, esp
|
||||||
|
|
||||||
// If we have reached the end of the chain or we're asked to stop here
|
unwind_loop:
|
||||||
// by the caller then exit
|
/* Get the exception registration and try level */
|
||||||
test %ebx, %ebx
|
mov eax, [esp+36]
|
||||||
je .lu2_done
|
mov ebx, [eax+8]
|
||||||
|
mov esi, [eax+12]
|
||||||
|
|
||||||
movl ER_TRYLEVEL(%ebx), %eax
|
/* Validate the unwind */
|
||||||
cmpl $-1, %eax
|
cmp esi, -1
|
||||||
je .lu2_done
|
je unwind_return
|
||||||
|
cmp dword ptr [esp+40], -1
|
||||||
|
je unwind_ok
|
||||||
|
cmp esi, [esp+40]
|
||||||
|
jbe unwind_return
|
||||||
|
|
||||||
cmpl LU2_TRYLEVEL(%edx), %eax
|
unwind_ok:
|
||||||
je .lu2_done
|
/* Get the new enclosing level and save it */
|
||||||
|
lea esi, [esi+esi*2]
|
||||||
|
mov ecx, [ebx+esi*4]
|
||||||
|
mov [esp+8], ecx
|
||||||
|
mov [eax+12], ecx
|
||||||
|
|
||||||
// Keep a pointer to the scopetable in ESI
|
/* Check the filter type */
|
||||||
movl ER_SCOPETABLE(%ebx), %esi
|
cmp dword ptr [ebx+esi*4+4], 0
|
||||||
|
jnz __NLG_Return2
|
||||||
|
|
||||||
// Compute the offset of the entry in the scopetable that describes
|
/* FIXME: NLG Notification */
|
||||||
// the scope that is to be unwound. Put the offset in EDI.
|
|
||||||
movl ST_TRYLEVEL(%esi), %edi
|
|
||||||
lea (%edi, %edi, 2), %edi
|
|
||||||
shll $2, %edi
|
|
||||||
addl %esi, %edi
|
|
||||||
|
|
||||||
// If this is not a termination handler then skip it
|
/* Call the handler */
|
||||||
cmpl $0, ST_FILTER(%edi)
|
call dword ptr [ebx+esi*4+8]
|
||||||
jne .lu2_next_scope
|
|
||||||
|
|
||||||
// Save the previous try-level in the exception registration structure
|
__NLG_Return2:
|
||||||
movl ST_TRYLEVEL(%edi), %eax
|
/* Unwind again */
|
||||||
movl %eax, ER_TRYLEVEL(%ebx)
|
jmp unwind_loop
|
||||||
|
|
||||||
// Fetch the address of the termination handler
|
unwind_return:
|
||||||
movl ST_HANDLER(%edi), %eax
|
/* Cleanup SEH */
|
||||||
|
pop fs:0
|
||||||
// Termination handlers may trash all registers so save the
|
add esp, 16
|
||||||
// important ones and then call the handler
|
pop edi
|
||||||
pushl %edx
|
pop esi
|
||||||
call *%eax
|
pop ebx
|
||||||
|
|
||||||
// Get our base pointer back
|
|
||||||
popl %edx
|
|
||||||
|
|
||||||
jmp .lu2_next_scope
|
|
||||||
|
|
||||||
.lu2_done:
|
|
||||||
|
|
||||||
// FIXME: Tear down the EXCEPTION_REGISTRATION entry setup to protect
|
|
||||||
// the unwinding
|
|
||||||
|
|
||||||
//movl %esi, %esp
|
|
||||||
//popl %ebp
|
|
||||||
ret
|
ret
|
||||||
|
.endfunc
|
||||||
|
|
||||||
#define EH3_DISPCONTEXT 0x14
|
.func _except_handler2
|
||||||
#define EH3_CONTEXT 0x10
|
__except_handler2:
|
||||||
#define EH3_REGFRAME 0x0C
|
|
||||||
#define EH3_ERECORD 0x08
|
|
||||||
|
|
||||||
// Parameters:
|
/* Setup stack and save volatiles */
|
||||||
// [ESP+14h] - PVOID DispatcherContext
|
push ebp
|
||||||
// [ESP+10h] - PCONTEXT Context
|
mov ebp, esp
|
||||||
// [ESP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame
|
sub esp, 8
|
||||||
// [ESP+08h] - PEXCEPTION_RECORD ExceptionRecord
|
push ebx
|
||||||
// Registers:
|
push esi
|
||||||
// Unknown
|
push edi
|
||||||
// Returns:
|
push ebp
|
||||||
// EXCEPTION_DISPOSITION - How this handler handled the exception
|
|
||||||
// Notes:
|
|
||||||
// Try to find an exception handler that will handle the exception.
|
|
||||||
// Traverse the entries in the scopetable that is associated with the
|
|
||||||
// exception registration passed as a parameter to this function.
|
|
||||||
// If an exception handler that will handle the exception is found, it
|
|
||||||
// is called and this function never returns
|
|
||||||
__except_handler3:
|
|
||||||
// Setup our call frame so we can access parameters using EBP
|
|
||||||
pushl %ebp // Standard ESP in frame (considered part of EXCEPTION_REGISTRATION)
|
|
||||||
movl %esp, %ebp
|
|
||||||
|
|
||||||
// Don't trust the direction flag to be cleared
|
/* Clear direction flag */
|
||||||
cld
|
cld
|
||||||
|
|
||||||
// Either we're called to handle an exception or we're called to unwind
|
/* Get exception registration and record */
|
||||||
movl EH3_ERECORD(%ebp), %eax
|
mov ebx, [ebp+12]
|
||||||
testl $EXCEPTION_UNWIND_MODE, EREC_FLAGS(%eax)
|
mov eax, [ebp+8]
|
||||||
jnz .eh3_unwind
|
|
||||||
|
|
||||||
// Keep a pointer to the exception registration in EBX
|
/* Check if this is an unwind */
|
||||||
movl EH3_REGFRAME(%ebp), %ebx
|
test dword ptr [eax+4], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
|
||||||
|
jnz except_unwind2
|
||||||
|
|
||||||
// Build an EXCEPTION_POINTERS structure on the stack and store it's
|
/* Save exception pointers structure */
|
||||||
// address in the EXCEPTION_REGISTRATION structure
|
mov [ebp-8], eax
|
||||||
movl EH3_CONTEXT(%esp), %eax
|
mov eax, [ebp+16]
|
||||||
pushl %ebx // Registration frame
|
mov [ebp-4], eax
|
||||||
pushl %eax // Context
|
lea eax, [ebp-8]
|
||||||
movl %esp, ER_EPOINTERS(%ebx) // Pointer to EXCEPTION_REGISTRATION on the stack
|
mov [ebx+20], eax
|
||||||
|
|
||||||
// Keep current try-level in EDI
|
/* Get the try level and scope table */
|
||||||
movl ER_TRYLEVEL(%ebx), %edi
|
mov esi, [ebx+12]
|
||||||
|
mov edi, [ebx+8]
|
||||||
|
|
||||||
// Keep a pointer to the scopetable in ESI
|
except_loop2:
|
||||||
movl ER_SCOPETABLE(%ebx), %esi
|
/* Validate try level */
|
||||||
|
cmp esi, -1
|
||||||
|
je except_search2
|
||||||
|
|
||||||
.eh3_next_scope:
|
/* Check if this is the termination handler */
|
||||||
|
lea ecx, [esi+esi*2]
|
||||||
|
cmp dword ptr [edi+ecx*4+4], 0
|
||||||
|
jz except_continue2
|
||||||
|
|
||||||
// If we have reached the end of the chain then exit
|
/* Save registers and call filter, then restore them */
|
||||||
cmpl $-1, %edi
|
push esi
|
||||||
je .eh3_search
|
push ebp
|
||||||
|
mov ebp, [ebx+16]
|
||||||
|
call dword ptr [edi+ecx*4+4]
|
||||||
|
pop ebp
|
||||||
|
pop esi
|
||||||
|
|
||||||
// Compute the offset of the entry in the scopetable and store
|
/* Restore ebx and check the result */
|
||||||
// the absolute address in EAX
|
mov ebx, [ebp+12]
|
||||||
lea (%edi, %edi, 2), %eax
|
or eax, eax
|
||||||
shll $2, %eax
|
jz except_continue2
|
||||||
addl %esi, %eax
|
js except_dismiss2
|
||||||
|
|
||||||
// Fetch the address of the filter routine
|
/* So this is an accept, call the termination handlers */
|
||||||
movl ST_FILTER(%eax), %eax
|
mov edi, [ebx+8]
|
||||||
|
push ebx
|
||||||
// If this is a termination handler then skip it
|
|
||||||
cmpl $0, %eax
|
|
||||||
je .eh3_continue
|
|
||||||
|
|
||||||
// Filter routines may trash all registers so save the important
|
|
||||||
// ones before restoring the call frame ebp and calling the handler
|
|
||||||
pushl %ebp
|
|
||||||
pushl %edi // Stop try-level
|
|
||||||
lea ER_EBP(%ebx), %ebp
|
|
||||||
call *%eax
|
|
||||||
popl %edi // Stop try-level
|
|
||||||
popl %ebp
|
|
||||||
|
|
||||||
// Reload EBX with registration frame address
|
|
||||||
movl EH3_REGFRAME(%ebp), %ebx
|
|
||||||
|
|
||||||
// Be more flexible here by checking if the return value is less than
|
|
||||||
// zero, equal to zero, or larger than zero instead of the defined
|
|
||||||
// values:
|
|
||||||
// -1 (EXCEPTION_CONTINUE_EXECUTION)
|
|
||||||
// 0 (EXCEPTION_CONTINUE_SEARCH)
|
|
||||||
// +1 (EXCEPTION_EXECUTE_HANDLER)
|
|
||||||
orl %eax, %eax
|
|
||||||
jz .eh3_continue
|
|
||||||
js .eh3_dismiss
|
|
||||||
|
|
||||||
// Filter returned: EXCEPTION_EXECUTE_HANDLER
|
|
||||||
|
|
||||||
// Ask the OS to perform global unwinding.
|
|
||||||
pushl %edi // Save stop try-level
|
|
||||||
pushl %ebx // Save registration frame address
|
|
||||||
pushl %ebx // Registration frame address
|
|
||||||
call __global_unwind2
|
call __global_unwind2
|
||||||
popl %eax // Remove parameter to __global_unwind2
|
add esp, 4
|
||||||
popl %ebx // Restore registration frame address
|
|
||||||
popl %edi // Restore stop try-level
|
|
||||||
|
|
||||||
// Change the context structure so _except_finish is called in the
|
/* Restore ebp */
|
||||||
// correct context since we return ExceptionContinueExecution.
|
mov ebp, [ebx+16]
|
||||||
movl EH3_CONTEXT(%ebp), %eax
|
|
||||||
|
|
||||||
movl %edi, CONTEXT_EDI(%eax) // Stop try-level
|
/* Do local unwind */
|
||||||
movl %ebx, CONTEXT_EBX(%eax) // Registration frame address
|
push esi
|
||||||
movl $_except_finish, CONTEXT_EIP(%eax)
|
push ebx
|
||||||
|
|
||||||
movl $ExceptionContinueExecution, %eax
|
|
||||||
jmp .eh3_return
|
|
||||||
|
|
||||||
// Filter returned: EXCEPTION_CONTINUE_SEARCH
|
|
||||||
.eh3_continue:
|
|
||||||
|
|
||||||
// Reload ESI because the filter routine may have trashed it
|
|
||||||
movl ER_SCOPETABLE(%ebx), %esi
|
|
||||||
|
|
||||||
// Go one try-level closer to the top
|
|
||||||
lea (%edi, %edi, 2), %edi
|
|
||||||
shll $2, %edi
|
|
||||||
addl %esi, %edi
|
|
||||||
movl ST_TRYLEVEL(%edi), %edi
|
|
||||||
|
|
||||||
jmp .eh3_next_scope
|
|
||||||
|
|
||||||
// Filter returned: EXCEPTION_CONTINUE_EXECUTION
|
|
||||||
// Continue execution like nothing happened
|
|
||||||
.eh3_dismiss:
|
|
||||||
movl $ExceptionContinueExecution, %eax
|
|
||||||
jmp .eh3_return
|
|
||||||
|
|
||||||
// Tell the OS to search for another handler that will handle the exception
|
|
||||||
.eh3_search:
|
|
||||||
|
|
||||||
movl $ExceptionContinueSearch, %eax
|
|
||||||
jmp .eh3_return
|
|
||||||
|
|
||||||
// Perform local unwinding
|
|
||||||
.eh3_unwind:
|
|
||||||
|
|
||||||
testl $EXCEPTION_TARGET_UNWIND, EREC_FLAGS(%eax)
|
|
||||||
jnz .eh3_return
|
|
||||||
|
|
||||||
// Save some important registers
|
|
||||||
pushl %ebp
|
|
||||||
|
|
||||||
lea ER_EBP(%ebx), %ebp
|
|
||||||
pushl $-1
|
|
||||||
pushl %ebx
|
|
||||||
call __local_unwind2
|
call __local_unwind2
|
||||||
addl $8, %esp
|
add esp, 8
|
||||||
|
|
||||||
// Restore some important registers
|
/* Set new try level */
|
||||||
popl %ebp
|
lea ecx, [esi+esi*2]
|
||||||
|
mov eax, [edi+ecx*4]
|
||||||
|
mov [ebx+12], eax
|
||||||
|
|
||||||
movl $ExceptionContinueSearch, %eax
|
/* Call except handler */
|
||||||
|
call [edi+ecx*4+8]
|
||||||
|
|
||||||
// Get me out of here
|
except_continue2:
|
||||||
.eh3_return:
|
/* Reload try level and except again */
|
||||||
|
mov edi, [ebx+8]
|
||||||
|
lea ecx, [esi+esi*2]
|
||||||
|
mov esi, [edi+ecx*4]
|
||||||
|
jmp except_loop2
|
||||||
|
|
||||||
movl %ebp, %esp
|
except_dismiss2:
|
||||||
popl %ebp
|
/* Dismiss it */
|
||||||
ret
|
mov eax, DISPOSITION_DISMISS
|
||||||
|
jmp except_return2
|
||||||
|
|
||||||
// Parameters:
|
except_search2:
|
||||||
// None
|
/* Continue searching */
|
||||||
// Registers:
|
mov eax, DISPOSITION_CONTINUE_SEARCH
|
||||||
// EBX - Pointer to exception registration structure
|
jmp except_return2
|
||||||
// EDI - Stop try-level
|
|
||||||
// Returns:
|
|
||||||
// -
|
|
||||||
// Notes:
|
|
||||||
// -
|
|
||||||
_except_finish:
|
|
||||||
|
|
||||||
// Setup EBP for the exception handler. By doing this the exception
|
/* Do local unwind */
|
||||||
// handler can access local variables as normal
|
except_unwind2:
|
||||||
lea ER_EBP(%ebx), %ebp
|
push ebp
|
||||||
|
mov ebp, [ebx+16]
|
||||||
// Save some important registers
|
push -1
|
||||||
pushl %ebp
|
push ebx
|
||||||
pushl %ebx
|
|
||||||
pushl %edi
|
|
||||||
|
|
||||||
// Stop try-level
|
|
||||||
pushl %edi
|
|
||||||
|
|
||||||
// Pointer to exception registration structure
|
|
||||||
pushl %ebx
|
|
||||||
call __local_unwind2
|
call __local_unwind2
|
||||||
addl $8, %esp
|
add esp, 8
|
||||||
|
|
||||||
// Restore some important registers
|
/* Retore EBP and set return disposition */
|
||||||
popl %edi
|
pop ebp
|
||||||
popl %ebx
|
mov eax, DISPOSITION_CONTINUE_SEARCH
|
||||||
popl %ebp
|
|
||||||
|
|
||||||
// Keep a pointer to the scopetable in ESI
|
except_return2:
|
||||||
movl ER_SCOPETABLE(%ebx), %esi
|
/* Restore registers and stack */
|
||||||
|
pop ebp
|
||||||
// Compute the offset of the entry in the scopetable and store
|
pop edi
|
||||||
// the absolute address in EDI
|
pop esi
|
||||||
lea (%edi, %edi, 2), %edi
|
pop ebx
|
||||||
shll $2, %edi
|
mov esp, ebp
|
||||||
addl %esi, %edi
|
pop ebp
|
||||||
|
|
||||||
// Set the current try-level to the previous try-level and call
|
|
||||||
// the exception handler
|
|
||||||
movl ST_TRYLEVEL(%edi), %eax
|
|
||||||
movl %eax, ER_TRYLEVEL(%ebx)
|
|
||||||
movl ST_HANDLER(%edi), %eax
|
|
||||||
|
|
||||||
call *%eax
|
|
||||||
|
|
||||||
// We should never get here
|
|
||||||
ret
|
ret
|
||||||
|
.endfunc
|
||||||
|
|
||||||
|
.func _except_handler3
|
||||||
|
__except_handler3:
|
||||||
|
|
||||||
|
/* Setup stack and save volatiles */
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
sub esp, 8
|
||||||
|
push ebx
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
push ebp
|
||||||
|
|
||||||
|
/* Clear direction flag */
|
||||||
|
cld
|
||||||
|
|
||||||
|
/* Get exception registration and record */
|
||||||
|
mov ebx, [ebp+12]
|
||||||
|
mov eax, [ebp+8]
|
||||||
|
|
||||||
|
/* Check if this is an unwind */
|
||||||
|
test dword ptr [eax+4], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
|
||||||
|
jnz except_unwind3
|
||||||
|
|
||||||
|
/* Save exception pointers structure */
|
||||||
|
mov [ebp-8], eax
|
||||||
|
mov eax, [ebp+16]
|
||||||
|
mov [ebp-4], eax
|
||||||
|
lea eax, [ebp-8]
|
||||||
|
mov [ebx-4], eax
|
||||||
|
|
||||||
|
/* Get the try level and scope table */
|
||||||
|
mov esi, [ebx+12]
|
||||||
|
mov edi, [ebx+8]
|
||||||
|
|
||||||
|
/* FIXME: Validate the SEH exception */
|
||||||
|
|
||||||
|
except_loop3:
|
||||||
|
/* Validate try level */
|
||||||
|
cmp esi, -1
|
||||||
|
je except_search3
|
||||||
|
|
||||||
|
/* Check if this is the termination handler */
|
||||||
|
lea ecx, [esi+esi*2]
|
||||||
|
mov eax, [edi+ecx*4+4]
|
||||||
|
or eax, eax
|
||||||
|
jz except_continue3
|
||||||
|
|
||||||
|
/* Save registers clear them all */
|
||||||
|
push esi
|
||||||
|
push ebp
|
||||||
|
lea ebp, [ebx+16]
|
||||||
|
xor ebx, ebx
|
||||||
|
xor ecx, ecx
|
||||||
|
xor edx, edx
|
||||||
|
xor esi, esi
|
||||||
|
xor edi, edi
|
||||||
|
|
||||||
|
/* Call the filter and restore our registers */
|
||||||
|
call eax
|
||||||
|
pop ebp
|
||||||
|
pop esi
|
||||||
|
|
||||||
|
/* Restore ebx and check the result */
|
||||||
|
mov ebx, [ebp+12]
|
||||||
|
or eax, eax
|
||||||
|
jz except_continue3
|
||||||
|
js except_dismiss3
|
||||||
|
|
||||||
|
/* So this is an accept, call the termination handlers */
|
||||||
|
mov edi, [ebx+8]
|
||||||
|
push ebx
|
||||||
|
call __global_unwind2
|
||||||
|
add esp, 4
|
||||||
|
|
||||||
|
/* Restore ebp */
|
||||||
|
lea ebp, [ebx+16]
|
||||||
|
|
||||||
|
/* Do local unwind */
|
||||||
|
push esi
|
||||||
|
push ebx
|
||||||
|
call __local_unwind2
|
||||||
|
add esp, 8
|
||||||
|
|
||||||
|
/* FIXME: Do NLG Notification */
|
||||||
|
|
||||||
|
/* Set new try level */
|
||||||
|
lea ecx, [esi+esi*2]
|
||||||
|
mov eax, [edi+ecx*4]
|
||||||
|
mov [ebx+12], eax
|
||||||
|
|
||||||
|
/* Clear registers and call except handler */
|
||||||
|
mov eax, [edi+ecx*4+8]
|
||||||
|
xor ebx, ebx
|
||||||
|
xor ecx, ecx
|
||||||
|
xor edx, edx
|
||||||
|
xor esi, esi
|
||||||
|
xor edi, edi
|
||||||
|
call eax
|
||||||
|
|
||||||
|
except_continue3:
|
||||||
|
/* Reload try level and except again */
|
||||||
|
mov edi, [ebx+8]
|
||||||
|
lea ecx, [esi+esi*2]
|
||||||
|
mov esi, [edi+ecx*4]
|
||||||
|
jmp except_loop3
|
||||||
|
|
||||||
|
except_dismiss3:
|
||||||
|
/* Dismiss it */
|
||||||
|
mov eax, DISPOSITION_DISMISS
|
||||||
|
jmp except_return3
|
||||||
|
|
||||||
|
except_search3:
|
||||||
|
/* Continue searching */
|
||||||
|
mov eax, DISPOSITION_CONTINUE_SEARCH
|
||||||
|
jmp except_return3
|
||||||
|
|
||||||
|
/* Do local unwind */
|
||||||
|
except_unwind3:
|
||||||
|
push ebp
|
||||||
|
mov ebp, [ebx+16]
|
||||||
|
push -1
|
||||||
|
push ebx
|
||||||
|
call __local_unwind2
|
||||||
|
add esp, 8
|
||||||
|
|
||||||
|
/* Retore EBP and set return disposition */
|
||||||
|
pop ebp
|
||||||
|
mov eax, DISPOSITION_CONTINUE_SEARCH
|
||||||
|
|
||||||
|
except_return3:
|
||||||
|
/* Restore registers and stack */
|
||||||
|
pop ebp
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
pop ebx
|
||||||
|
mov esp, ebp
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
.endfunc
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// REMOVE ME REMOVE ME REMOVE ME REMOVE ME REMOVE ME REMOVE ME REMOVE ME
|
||||||
|
//
|
||||||
|
//
|
||||||
|
.func RtlpGetStackLimits@8
|
||||||
|
.globl _RtlpGetStackLimits@8
|
||||||
|
_RtlpGetStackLimits@8:
|
||||||
|
|
||||||
|
/* Get the current thread */
|
||||||
|
mov eax, [fs:KPCR_CURRENT_THREAD]
|
||||||
|
|
||||||
|
/* Get the stack limits */
|
||||||
|
mov ecx, [eax+KTHREAD_STACK_LIMIT]
|
||||||
|
mov edx, [eax+KTHREAD_INITIAL_STACK]
|
||||||
|
sub edx, SIZEOF_FX_SAVE_AREA
|
||||||
|
|
||||||
|
/* Return them */
|
||||||
|
mov eax, [esp+4]
|
||||||
|
mov [eax], ecx
|
||||||
|
|
||||||
|
mov eax, [esp+8]
|
||||||
|
mov [eax], edx
|
||||||
|
|
||||||
|
/* return */
|
||||||
|
ret 8
|
||||||
|
.endfunc
|
||||||
|
|
|
@ -6,22 +6,6 @@
|
||||||
#include <ndk/extypes.h>
|
#include <ndk/extypes.h>
|
||||||
#include <ndk/rtlfuncs.h>
|
#include <ndk/rtlfuncs.h>
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
void __cdecl
|
|
||||||
_global_unwind2(PEXCEPTION_REGISTRATION_RECORD RegistrationFrame)
|
|
||||||
{
|
|
||||||
#ifdef __GNUC__
|
|
||||||
RtlUnwind(RegistrationFrame, &&__ret_label, NULL, 0);
|
|
||||||
__ret_label:
|
|
||||||
// return is important
|
|
||||||
return;
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* VC++ extensions to Win32 SEH */
|
/* VC++ extensions to Win32 SEH */
|
||||||
typedef struct _SCOPETABLE
|
typedef struct _SCOPETABLE
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,468 +0,0 @@
|
||||||
/*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
|
||||||
* PROJECT: ReactOS CRT
|
|
||||||
* FILE: lib/crt/misc/i386/seh.S
|
|
||||||
* PURPOSE: SEH Support for the CRT
|
|
||||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
|
||||||
|
|
||||||
#include <ndk/asm.h>
|
|
||||||
.intel_syntax noprefix
|
|
||||||
|
|
||||||
#define DISPOSITION_DISMISS 0
|
|
||||||
#define DISPOSITION_CONTINUE_SEARCH 1
|
|
||||||
#define DISPOSITION_COLLIDED_UNWIND 3
|
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
|
||||||
|
|
||||||
.globl __global_unwind2
|
|
||||||
.globl __local_unwind2
|
|
||||||
.globl __abnormal_termination
|
|
||||||
.globl __except_handler2
|
|
||||||
.globl __except_handler3
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
|
||||||
|
|
||||||
.func unwind_handler
|
|
||||||
_unwind_handler:
|
|
||||||
|
|
||||||
/* Check if we were unwinding and continue search if not */
|
|
||||||
mov ecx, [esp+4]
|
|
||||||
test dword ptr [ecx+4], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
|
|
||||||
mov eax, DISPOSITION_CONTINUE_SEARCH
|
|
||||||
jz unwind_handler_return
|
|
||||||
|
|
||||||
/* We have a collision, do a local unwind */
|
|
||||||
mov eax, [esp+20]
|
|
||||||
push ebp
|
|
||||||
mov ebp, [eax+16]
|
|
||||||
mov edx, [eax+40]
|
|
||||||
push edx
|
|
||||||
mov edx, [eax+36]
|
|
||||||
push edx
|
|
||||||
call __local_unwind2
|
|
||||||
add esp, 8
|
|
||||||
pop ebp
|
|
||||||
|
|
||||||
/* Set new try level */
|
|
||||||
mov eax, [esp+8]
|
|
||||||
mov edx, [esp+16]
|
|
||||||
mov [edx], eax
|
|
||||||
|
|
||||||
/* Return collided unwind */
|
|
||||||
mov eax, DISPOSITION_COLLIDED_UNWIND
|
|
||||||
|
|
||||||
unwind_handler_return:
|
|
||||||
ret
|
|
||||||
.endfunc
|
|
||||||
|
|
||||||
.func _global_unwind2
|
|
||||||
__global_unwind2:
|
|
||||||
|
|
||||||
/* Create stack and save all registers */
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
push ebx
|
|
||||||
push esi
|
|
||||||
push edi
|
|
||||||
push ebp
|
|
||||||
|
|
||||||
/* Call unwind */
|
|
||||||
push 0
|
|
||||||
push 0
|
|
||||||
push glu_return
|
|
||||||
push [ebp+8]
|
|
||||||
call _RtlUnwind@16
|
|
||||||
|
|
||||||
glu_return:
|
|
||||||
/* Restore registers and return */
|
|
||||||
pop ebp
|
|
||||||
pop edi
|
|
||||||
pop esi
|
|
||||||
pop ebx
|
|
||||||
mov esp, ebp
|
|
||||||
pop ebp
|
|
||||||
ret
|
|
||||||
.endfunc
|
|
||||||
|
|
||||||
.func _abnormal_termination
|
|
||||||
__abnormal_termination:
|
|
||||||
|
|
||||||
/* Assume false */
|
|
||||||
xor eax, eax
|
|
||||||
|
|
||||||
/* Check if the handler is the unwind handler */
|
|
||||||
mov ecx, fs:0
|
|
||||||
cmp dword ptr [ecx+4], offset _unwind_handler
|
|
||||||
jne short ab_return
|
|
||||||
|
|
||||||
/* Get the try level */
|
|
||||||
mov edx, [ecx+12]
|
|
||||||
mov edx, [edx+12]
|
|
||||||
|
|
||||||
/* Compare it */
|
|
||||||
cmp [ecx+8], edx
|
|
||||||
jne ab_return
|
|
||||||
|
|
||||||
/* Return true */
|
|
||||||
mov eax, 1
|
|
||||||
|
|
||||||
/* Return */
|
|
||||||
ab_return:
|
|
||||||
ret
|
|
||||||
.endfunc
|
|
||||||
|
|
||||||
.func _local_unwind2
|
|
||||||
__local_unwind2:
|
|
||||||
|
|
||||||
/* Save volatiles */
|
|
||||||
push ebx
|
|
||||||
push esi
|
|
||||||
push edi
|
|
||||||
|
|
||||||
/* Get the exception registration */
|
|
||||||
mov eax, [esp+16]
|
|
||||||
|
|
||||||
/* Setup SEH to protect the unwind */
|
|
||||||
push ebp
|
|
||||||
push eax
|
|
||||||
push -2
|
|
||||||
push offset _unwind_handler
|
|
||||||
push fs:0
|
|
||||||
mov fs:0, esp
|
|
||||||
|
|
||||||
unwind_loop:
|
|
||||||
/* Get the exception registration and try level */
|
|
||||||
mov eax, [esp+36]
|
|
||||||
mov ebx, [eax+8]
|
|
||||||
mov esi, [eax+12]
|
|
||||||
|
|
||||||
/* Validate the unwind */
|
|
||||||
cmp esi, -1
|
|
||||||
je unwind_return
|
|
||||||
cmp dword ptr [esp+40], -1
|
|
||||||
je unwind_ok
|
|
||||||
cmp esi, [esp+40]
|
|
||||||
jbe unwind_return
|
|
||||||
|
|
||||||
unwind_ok:
|
|
||||||
/* Get the new enclosing level and save it */
|
|
||||||
lea esi, [esi+esi*2]
|
|
||||||
mov ecx, [ebx+esi*4]
|
|
||||||
mov [esp+8], ecx
|
|
||||||
mov [eax+12], ecx
|
|
||||||
|
|
||||||
/* Check the filter type */
|
|
||||||
cmp dword ptr [ebx+esi*4+4], 0
|
|
||||||
jnz __NLG_Return2
|
|
||||||
|
|
||||||
/* FIXME: NLG Notification */
|
|
||||||
|
|
||||||
/* Call the handler */
|
|
||||||
call dword ptr [ebx+esi*4+8]
|
|
||||||
|
|
||||||
__NLG_Return2:
|
|
||||||
/* Unwind again */
|
|
||||||
jmp unwind_loop
|
|
||||||
|
|
||||||
unwind_return:
|
|
||||||
/* Cleanup SEH */
|
|
||||||
pop fs:0
|
|
||||||
add esp, 16
|
|
||||||
pop edi
|
|
||||||
pop esi
|
|
||||||
pop ebx
|
|
||||||
ret
|
|
||||||
.endfunc
|
|
||||||
|
|
||||||
.func _except_handler2
|
|
||||||
__except_handler2:
|
|
||||||
|
|
||||||
/* Setup stack and save volatiles */
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
sub esp, 8
|
|
||||||
push ebx
|
|
||||||
push esi
|
|
||||||
push edi
|
|
||||||
push ebp
|
|
||||||
|
|
||||||
/* Clear direction flag */
|
|
||||||
cld
|
|
||||||
|
|
||||||
/* Get exception registration and record */
|
|
||||||
mov ebx, [ebp+12]
|
|
||||||
mov eax, [ebp+8]
|
|
||||||
|
|
||||||
/* Check if this is an unwind */
|
|
||||||
test dword ptr [eax+4], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
|
|
||||||
jnz except_unwind2
|
|
||||||
|
|
||||||
/* Save exception pointers structure */
|
|
||||||
mov [ebp-8], eax
|
|
||||||
mov eax, [ebp+16]
|
|
||||||
mov [ebp-4], eax
|
|
||||||
lea eax, [ebp-8]
|
|
||||||
mov [ebx+20], eax
|
|
||||||
|
|
||||||
/* Get the try level and scope table */
|
|
||||||
mov esi, [ebx+12]
|
|
||||||
mov edi, [ebx+8]
|
|
||||||
|
|
||||||
except_loop2:
|
|
||||||
/* Validate try level */
|
|
||||||
cmp esi, -1
|
|
||||||
je except_search2
|
|
||||||
|
|
||||||
/* Check if this is the termination handler */
|
|
||||||
lea ecx, [esi+esi*2]
|
|
||||||
cmp dword ptr [edi+ecx*4+4], 0
|
|
||||||
jz except_continue2
|
|
||||||
|
|
||||||
/* Save registers and call filter, then restore them */
|
|
||||||
push esi
|
|
||||||
push ebp
|
|
||||||
mov ebp, [ebx+16]
|
|
||||||
call dword ptr [edi+ecx*4+4]
|
|
||||||
pop ebp
|
|
||||||
pop esi
|
|
||||||
|
|
||||||
/* Restore ebx and check the result */
|
|
||||||
mov ebx, [ebp+12]
|
|
||||||
or eax, eax
|
|
||||||
jz except_continue2
|
|
||||||
js except_dismiss2
|
|
||||||
|
|
||||||
/* So this is an accept, call the termination handlers */
|
|
||||||
mov edi, [ebx+8]
|
|
||||||
push ebx
|
|
||||||
call __global_unwind2
|
|
||||||
add esp, 4
|
|
||||||
|
|
||||||
/* Restore ebp */
|
|
||||||
mov ebp, [ebx+16]
|
|
||||||
|
|
||||||
/* Do local unwind */
|
|
||||||
push esi
|
|
||||||
push ebx
|
|
||||||
call __local_unwind2
|
|
||||||
add esp, 8
|
|
||||||
|
|
||||||
/* Set new try level */
|
|
||||||
lea ecx, [esi+esi*2]
|
|
||||||
mov eax, [edi+ecx*4]
|
|
||||||
mov [ebx+12], eax
|
|
||||||
|
|
||||||
/* Call except handler */
|
|
||||||
call [edi+ecx*4+8]
|
|
||||||
|
|
||||||
except_continue2:
|
|
||||||
/* Reload try level and except again */
|
|
||||||
mov edi, [ebx+8]
|
|
||||||
lea ecx, [esi+esi*2]
|
|
||||||
mov esi, [edi+ecx*4]
|
|
||||||
jmp except_loop2
|
|
||||||
|
|
||||||
except_dismiss2:
|
|
||||||
/* Dismiss it */
|
|
||||||
mov eax, DISPOSITION_DISMISS
|
|
||||||
jmp except_return2
|
|
||||||
|
|
||||||
except_search2:
|
|
||||||
/* Continue searching */
|
|
||||||
mov eax, DISPOSITION_CONTINUE_SEARCH
|
|
||||||
jmp except_return2
|
|
||||||
|
|
||||||
/* Do local unwind */
|
|
||||||
except_unwind2:
|
|
||||||
push ebp
|
|
||||||
mov ebp, [ebx+16]
|
|
||||||
push -1
|
|
||||||
push ebx
|
|
||||||
call __local_unwind2
|
|
||||||
add esp, 8
|
|
||||||
|
|
||||||
/* Retore EBP and set return disposition */
|
|
||||||
pop ebp
|
|
||||||
mov eax, DISPOSITION_CONTINUE_SEARCH
|
|
||||||
|
|
||||||
except_return2:
|
|
||||||
/* Restore registers and stack */
|
|
||||||
pop ebp
|
|
||||||
pop edi
|
|
||||||
pop esi
|
|
||||||
pop ebx
|
|
||||||
mov esp, ebp
|
|
||||||
pop ebp
|
|
||||||
ret
|
|
||||||
.endfunc
|
|
||||||
|
|
||||||
.func _except_handler3
|
|
||||||
__except_handler3:
|
|
||||||
|
|
||||||
/* Setup stack and save volatiles */
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
sub esp, 8
|
|
||||||
push ebx
|
|
||||||
push esi
|
|
||||||
push edi
|
|
||||||
push ebp
|
|
||||||
|
|
||||||
/* Clear direction flag */
|
|
||||||
cld
|
|
||||||
|
|
||||||
/* Get exception registration and record */
|
|
||||||
mov ebx, [ebp+12]
|
|
||||||
mov eax, [ebp+8]
|
|
||||||
|
|
||||||
/* Check if this is an unwind */
|
|
||||||
test dword ptr [eax+4], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
|
|
||||||
jnz except_unwind3
|
|
||||||
|
|
||||||
/* Save exception pointers structure */
|
|
||||||
mov [ebp-8], eax
|
|
||||||
mov eax, [ebp+16]
|
|
||||||
mov [ebp-4], eax
|
|
||||||
lea eax, [ebp-8]
|
|
||||||
mov [ebx-4], eax
|
|
||||||
|
|
||||||
/* Get the try level and scope table */
|
|
||||||
mov esi, [ebx+12]
|
|
||||||
mov edi, [ebx+8]
|
|
||||||
|
|
||||||
/* FIXME: Validate the SEH exception */
|
|
||||||
|
|
||||||
except_loop3:
|
|
||||||
/* Validate try level */
|
|
||||||
cmp esi, -1
|
|
||||||
je except_search3
|
|
||||||
|
|
||||||
/* Check if this is the termination handler */
|
|
||||||
lea ecx, [esi+esi*2]
|
|
||||||
mov eax, [edi+ecx*4+4]
|
|
||||||
or eax, eax
|
|
||||||
jz except_continue3
|
|
||||||
|
|
||||||
/* Save registers clear them all */
|
|
||||||
push esi
|
|
||||||
push ebp
|
|
||||||
lea ebp, [ebx+16]
|
|
||||||
xor ebx, ebx
|
|
||||||
xor ecx, ecx
|
|
||||||
xor edx, edx
|
|
||||||
xor esi, esi
|
|
||||||
xor edi, edi
|
|
||||||
|
|
||||||
/* Call the filter and restore our registers */
|
|
||||||
call eax
|
|
||||||
pop ebp
|
|
||||||
pop esi
|
|
||||||
|
|
||||||
/* Restore ebx and check the result */
|
|
||||||
mov ebx, [ebp+12]
|
|
||||||
or eax, eax
|
|
||||||
jz except_continue3
|
|
||||||
js except_dismiss3
|
|
||||||
|
|
||||||
/* So this is an accept, call the termination handlers */
|
|
||||||
mov edi, [ebx+8]
|
|
||||||
push ebx
|
|
||||||
call __global_unwind2
|
|
||||||
add esp, 4
|
|
||||||
|
|
||||||
/* Restore ebp */
|
|
||||||
lea ebp, [ebx+16]
|
|
||||||
|
|
||||||
/* Do local unwind */
|
|
||||||
push esi
|
|
||||||
push ebx
|
|
||||||
call __local_unwind2
|
|
||||||
add esp, 8
|
|
||||||
|
|
||||||
/* FIXME: Do NLG Notification */
|
|
||||||
|
|
||||||
/* Set new try level */
|
|
||||||
lea ecx, [esi+esi*2]
|
|
||||||
mov eax, [edi+ecx*4]
|
|
||||||
mov [ebx+12], eax
|
|
||||||
|
|
||||||
/* Clear registers and call except handler */
|
|
||||||
mov eax, [edi+ecx*4+8]
|
|
||||||
xor ebx, ebx
|
|
||||||
xor ecx, ecx
|
|
||||||
xor edx, edx
|
|
||||||
xor esi, esi
|
|
||||||
xor edi, edi
|
|
||||||
call eax
|
|
||||||
|
|
||||||
except_continue3:
|
|
||||||
/* Reload try level and except again */
|
|
||||||
mov edi, [ebx+8]
|
|
||||||
lea ecx, [esi+esi*2]
|
|
||||||
mov esi, [edi+ecx*4]
|
|
||||||
jmp except_loop3
|
|
||||||
|
|
||||||
except_dismiss3:
|
|
||||||
/* Dismiss it */
|
|
||||||
mov eax, DISPOSITION_DISMISS
|
|
||||||
jmp except_return3
|
|
||||||
|
|
||||||
except_search3:
|
|
||||||
/* Continue searching */
|
|
||||||
mov eax, DISPOSITION_CONTINUE_SEARCH
|
|
||||||
jmp except_return3
|
|
||||||
|
|
||||||
/* Do local unwind */
|
|
||||||
except_unwind3:
|
|
||||||
push ebp
|
|
||||||
mov ebp, [ebx+16]
|
|
||||||
push -1
|
|
||||||
push ebx
|
|
||||||
call __local_unwind2
|
|
||||||
add esp, 8
|
|
||||||
|
|
||||||
/* Retore EBP and set return disposition */
|
|
||||||
pop ebp
|
|
||||||
mov eax, DISPOSITION_CONTINUE_SEARCH
|
|
||||||
|
|
||||||
except_return3:
|
|
||||||
/* Restore registers and stack */
|
|
||||||
pop ebp
|
|
||||||
pop edi
|
|
||||||
pop esi
|
|
||||||
pop ebx
|
|
||||||
mov esp, ebp
|
|
||||||
pop ebp
|
|
||||||
ret
|
|
||||||
.endfunc
|
|
||||||
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// REMOVE ME REMOVE ME REMOVE ME REMOVE ME REMOVE ME REMOVE ME REMOVE ME
|
|
||||||
//
|
|
||||||
//
|
|
||||||
.func RtlpGetStackLimits@8
|
|
||||||
.globl _RtlpGetStackLimits@8
|
|
||||||
_RtlpGetStackLimits@8:
|
|
||||||
|
|
||||||
/* Get the current thread */
|
|
||||||
mov eax, [fs:KPCR_CURRENT_THREAD]
|
|
||||||
|
|
||||||
/* Get the stack limits */
|
|
||||||
mov ecx, [eax+KTHREAD_STACK_LIMIT]
|
|
||||||
mov edx, [eax+KTHREAD_INITIAL_STACK]
|
|
||||||
sub edx, SIZEOF_FX_SAVE_AREA
|
|
||||||
|
|
||||||
/* Return them */
|
|
||||||
mov eax, [esp+4]
|
|
||||||
mov [eax], ecx
|
|
||||||
|
|
||||||
mov eax, [esp+8]
|
|
||||||
mov [eax], edx
|
|
||||||
|
|
||||||
/* return */
|
|
||||||
ret 8
|
|
||||||
.endfunc
|
|
|
@ -13,7 +13,7 @@
|
||||||
<define name="__MINGW_IMPORT">"extern __attribute__ ((dllexport))"</define>
|
<define name="__MINGW_IMPORT">"extern __attribute__ ((dllexport))"</define>
|
||||||
</if>
|
</if>
|
||||||
|
|
||||||
<directory name="except_nt">
|
<directory name="except">
|
||||||
<if property="ARCH" value="i386">
|
<if property="ARCH" value="i386">
|
||||||
<directory name="i386">
|
<directory name="i386">
|
||||||
<file>chkstk_asm.s</file>
|
<file>chkstk_asm.s</file>
|
||||||
|
|
|
@ -119,6 +119,8 @@ kernel32 -
|
||||||
|
|
||||||
msvcrt -
|
msvcrt -
|
||||||
reactos/dll/win32/msvcrt/wine/*.c # Out of sync
|
reactos/dll/win32/msvcrt/wine/*.c # Out of sync
|
||||||
|
reactos/lib/sdk/crt/except # Synced at XXXXXXXX
|
||||||
|
reactos/lib/sdk/crt/wine # Synced at XXXXXXXX
|
||||||
|
|
||||||
User32 -
|
User32 -
|
||||||
reactos/dll/win32/user32/controls/button.c # Synced at 20071022
|
reactos/dll/win32/user32/controls/button.c # Synced at 20071022
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue