Hi guys, could anyone tell me why my code doesn't work:
.386
.model flat, stdcall
option casemap :none
.data
.CODE
ASSUME FS:NOTHING
handler:
invoke MessageBox,0,0,0,0
ret
start:
push DWORD ptr handler
push DWORD ptr fs:[0]
mov DWORD ptr fs:[0],esp
xor eax,eax
mov eax,DWORD ptr [eax]
pop DWORD ptr fs:[0]
add esp,4
ret
end start
my messagebox never is executed and the program crashes :P
Here is some example code written by Jeremy Gordon and translated to Masm by Dave.
;Jeremy Gordon's "Except1" SEH program, adapted for MASM by DednDave, 11-2012
;Copyright Jeremy Gordon 2002
;build with \masm32\bin\build.bat
INCLUDE \masm32\include\masm32rt.inc
.DATA
szFatalMess db 'I thoroughly enjoyed it and I have already tidied everything up - '
db 'you know, completed records, closed filehandles, '
db 'released memory, that sort of thing ..'
db 'Glad this was by design - bye, bye ..',0Dh,0Ah
db '.. but first, I expect the system will do an unwind ..',0
szExcept1a db 'Except1',0
szExcept1b db "Except1 - well it's all over for now.",0
szHappy db 'This is a very happy ending',0
szException db 'There was an exception - do you want me to swallow it?',0
szUnWind db 'The system calling the handler again for more clearing up (unwinding)',0
.CODE
ASSUME FS:Nothing
CleanUp PROC
;all clean up would be done here
ret
CleanUp ENDP
FinalHandler PROC
;system passes EXCEPTION_POINTERS
push ebx
push esi
push edi
call CleanUp
INVOKE MessageBox,NULL,offset szFatalMess,offset szExcept1b,MB_OK or MB_ICONEXCLAMATION
mov eax,TRUE ;terminate process without showing system message box
pop edi
pop esi
pop ebx
ret
FinalHandler ENDP
_main PROC
INVOKE SetUnhandledExceptionFilter,FinalHandler
call ProtectedArea
call CleanUp
INVOKE MessageBox,NULL,offset szHappy,offset szExcept1a,MB_OK or MB_ICONEXCLAMATION
INVOKE ExitProcess,0
_main ENDP
ProtectedArea PROC
push ebp
push 0 ; )create the
push 0 ; )ERR structure
push SafePlace ; )on the
push Handler ; )stack
push dword ptr fs:[0]
mov fs:[0],esp ;point to structure just established on the stack
;*********************** and now lets cause the exception
xor ecx,ecx ;set ecx to zero
div ecx ;divide by zero, causing exception
;*********************** because of the exception the code never gets to here
;but the handler will jump to here ..
SafePlace::
pop fs:[0] ;restore original exception handler from stack
add esp,14h ;throw away remainder of ERR structure made earlier
ret
ProtectedArea ENDP
Handler PROC
;This simple handler is called by the system when the divide by zero
;occurs. In this handler the user is given a choice of swallowing the
;exception by jumping to the safe-place, or not dealing with it at all,
;in which case the system will send the exception to the FINAL_HANDLER
push ebx
push esi
push edi
mov ebx,[ebp+8] ;get exception record in ebx
mov eax,[ebx+4] ;get flag sent by the system
test al,1 ;see if its a non-continuable exception
jnz NoDeal ;yes, so not allowed by system to touch it
test al,2 ;see if its the system unwinding
jnz UnWind ;yes
INVOKE MessageBox,NULL,offset szException,offset szExcept1a,MB_YESNO or MB_ICONQUESTION
cmp eax,6 ;see if yes clicked
jnz NoDeal ;no
;***************************** go to SAFE_PLACE
mov esi,[ebp+10h] ;get register context record in esi
mov edi,[ebp+0Ch] ;get pointer to ERR structure in edi
mov [esi+0C4h],edi ;insert new esp (happens to be pointer to ERR)
mov eax,[edi+8] ;get address of SAFE_PLACE given in ERR structure
mov [esi+0B8h],eax ;insert that as new eip in register context
mov eax,[edi+14h] ;get ebp at safe place given in ERR structure
mov [esi+0B4h],eax ;insert that as new ebp in register context
xor eax,eax ;FALSE = reload context and return to system
jmp short Fin
UnWind: INVOKE MessageBox,NULL,offset szUnWind,offset szExcept1a,MB_OK or MB_ICONEXCLAMATION
NoDeal: mov eax,TRUE ;TRUE = system to go to next handler
Fin: pop edi
pop esi
pop ebx
ret
Handler ENDP
END _main
yah - Jeremy calls it an "ERR" structure - there is probably a better way to label those offsets :P
with a quick search, i didn't find the name for that structure
The name of the structure is CONTEXT and it's defined in WINDOWS.INC.
thanks, Michael :t
must be a reduced version of it ?
The CONTEXT structure in WINDOWS.INC matches the x86 structure in WinNT.h from my 2003 PSDK. It's a reduced version relative to the most recent, but within limits it does do the job.
And here is some well-known example code for a per-thread exception handler:
//==================================================
// MYSEH - Matt Pietrek 1997
// Microsoft Systems Journal, January 1997
// FILE: MYSEH.CPP
// To compile: CL MYSEH.CPP
//==================================================
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
DWORD scratch;
EXCEPTION_DISPOSITION
__cdecl
_except_handler(
struct _EXCEPTION_RECORD *ExceptionRecord,
void * EstablisherFrame,
struct _CONTEXT *ContextRecord,
void * DispatcherContext )
{
unsigned i;
// Indicate that we made it to our exception handler
printf( "Hello from an exception handler\n" );
// Change EAX in the context record so that it points to someplace
// where we can successfully write
ContextRecord->Eax = (DWORD)&scratch;
// Tell the OS to restart the faulting instruction
return ExceptionContinueExecution;
}
int main()
{
DWORD handler = (DWORD)_except_handler;
__asm
{ // Build EXCEPTION_REGISTRATION record:
push handler // Address of handler function
push FS:[0] // Address of previous handler
mov FS:[0],ESP // Install new EXECEPTION_REGISTRATION
}
__asm
{
mov eax,0 // Zero out EAX
mov [eax], 1 // Write to EAX to deliberately cause a fault
}
printf( "After writing!\n" );
__asm
{ // Remove our EXECEPTION_REGISTRATION record
mov eax,[ESP] // Get pointer to previous record
mov FS:[0], EAX // Install previous record
add esp, 8 // Clean our EXECEPTION_REGISTRATION off stack
}
return 0;
}
In this case you would be changing the regEip member to a safe place to continue execution and returning ExceptionContinueExecution.
http://www.microsoft.com/msj/0197/Exception/Exception.aspx
The use of FS register is an old code who had been changed by XP.
Use:
AddVectoredExceptionHandler
RemoveVectoredExceptionHandler
The need to use FS directly was removed long before XP.
Michael,
Is that code more efficient, smaller, or work better with different windows versions ?
If so, I can convert the c code.
EXECEPTION_REGISTRATION
that's the name i was looking for, Michael :t
found this article by Matt...
http://msdn.microsoft.com/en-us/magazine/cc301714.aspx (http://msdn.microsoft.com/en-us/magazine/cc301714.aspx)
Here is some more SEH code.
; Code from samael at http://www.winasm.net/
;
;
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\comctl32.inc
include \masm32\include\gdi32.inc
include \masm32\include\masm32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comctl32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\masm32.lib
FinalExceptionHandler PROTO :DWORD
.DATA
szPTEHMessage DB "I'm displayed from SafeOffset, because an exception occured inside the area guarded by the Per-Thread Exception Handler...",0
szPTEHCaption DB "Per-thread EH",0
szFEHMessage DB "I'm displayed against all odds, tearing my way through bad code... ;)",0
szFEHCaption DB "Y-e-e-e-e-h-a !!!",0
.CODE
EntryPoint:
;int 3
;-------------------------------------------------------------------------------------
;Install Universal (Final) EH.
;-------------------------------------------------------------------------------------
INVOKE SetUnhandledExceptionFilter, OFFSET FinalExceptionHandler
;-------------------------------------------------------------------------------------
;Install per-thread EH
;-------------------------------------------------------------------------------------
ASSUME FS:NOTHING ; We use the ASSUME FS:NOTHING directive because MASM by default assumes the use of FS register to ERROR
PUSH OFFSET PTExceptionHandler
PUSH FS:[0]
MOV FS:[0], ESP
;-------------------------------------------------------------------------------------
; The code between installation and de-installation of the Per-Thread Exception
; Handler, is guarded by the handler. If exception occurs anywhere inside the guarded area,
; we will go to the SafeOffset.
;-------------------------------------------------------------------------------------
; Cause an exception by writting to a forbidden address in order to activate the per-thread EH...
; The program flow will be redirected to SafeOffset
XOR EAX,EAX
MOV DWORD PTR [EAX], EAX ;Exceptio Access Violation
@UninstallPerThreadSEH:
;-------------------------------------------------------------------------------------
;Uninstall per-thread EH
;-------------------------------------------------------------------------------------
POP FS:[0]
ADD ESP,4
;-------------------------------------------------------------------------------------
; Having uninstalled the Per-Thread Exception Handler, the code below is guarded by the
; "final" handler.
; Note that we could setup the "final" handler, to do an attempt to continue executing
; the program, rather than just terminating it...
;-------------------------------------------------------------------------------------
;Cause more exceptions in order to activate the Universal (Final) EH.
CLI ;Lets execute a privilaged instruction... ; Instruction length = 1 [This instruction is going ot be patched to NOP by the Final Exception Handler]
INT 3 ;Lets cause a breakpoint exception... ; Instruction length = 1 [This instruction is going ot be patched to NOP by the Final Exception Handler]
CLI ;Lets execute a privilaged instruction... ; Instruction length = 1 [This instruction is going ot be patched to NOP by the Final Exception Handler]
INT 3 ;Lets cause a breakpoint exception... ; Instruction length = 1 [This instruction is going ot be patched to NOP by the Final Exception Handler]
;Will this part ever be executed ?
INVOKE MessageBox, NULL, ADDR szFEHMessage, ADDR szFEHCaption,MB_OK
INVOKE ExitProcess,NULL
PTExceptionHandler proc C pExcept:DWORD, pFrame:DWORD, pContext:DWORD, pDispatch:DWORD
MOV EAX, pContext
MOV [EAX].CONTEXT.regEip, OFFSET SafeOffset
MOV EAX,ExceptionContinueExecution
RET
PTExceptionHandler endp
FinalExceptionHandler proc lpExceptionInfo:DWORD
LOCAL dwExceptionAddress : DWORD
LOCAL dwExceptionCode : DWORD
.CONST
LINE_BREAK EQU 0Dh,0Ah
DEFAULT_BUFFER_SIZE EQU 1024
.DATA
szErrorCaption DB "Universal (Final) EH",0
szErrorMessage DB "Cannot continue the normal execution of this program.",LINE_BREAK,\
"An exception was generated at address 0x%0.8lX.",LINE_BREAK,\
"Exception type: %s.",LINE_BREAK,\
"This application will now terminate.",LINE_BREAK,LINE_BREAK,\
"Or perhaps not... ;)",0
szACCESS_VIOLATION DB "EXCEPTION_ACCESS_VIOLATION",0
szARRAY_BOUNDS_EXCEEDED DB "EXCEPTION_ARRAY_BOUNDS_EXCEEDED",0
szBREAKPOINT DB "EXCEPTION_BREAKPOINT",0
szDATATYPE_MISALIGNMENT DB "EXCEPTION_DATATYPE_MISALIGNMENT",0
szFLT_DENORMAL_OPERAND DB "EXCEPTION_FLT_DENORMAL_OPERAND",0
szFLT_DIVIDE_BY_ZERO DB "EXCEPTION_FLT_DIVIDE_BY_ZERO",0
szFLT_INEXACT_RESULT DB "EXCEPTION_FLT_INEXACT_RESULT",0
szFLT_INVALID_OPERATION DB "EXCEPTION_FLT_INVALID_OPERATION",0
szFLT_OVERFLOW DB "EXCEPTION_FLT_OVERFLOW",0
szFLT_STACK_CHECK DB "EXCEPTION_FLT_STACK_CHECK",0
szFLT_UNDERFLOW DB "EXCEPTION_FLT_UNDERFLOW",0
szILLEGAL_INSTRUCTION DB "EXCEPTION_ILLEGAL_INSTRUCTION",0
szIN_PAGE_ERROR DB "EXCEPTION_IN_PAGE_ERROR",0
szINT_DIVIDE_BY_ZERO DB "EXCEPTION_INT_DIVIDE_BY_ZERO",0
szINT_OVERFLOW DB "EXCEPTION_INT_OVERFLOW",0
szINVALID_DISPOSITION DB "EXCEPTION_INVALID_DISPOSITION",0
szNONCONTINUABLE_EXCEPTION DB "EXCEPTION_NONCONTINUABLE_EXCEPTION",0
szPRIV_INSTRUCTION DB "EXCEPTION_PRIV_INSTRUCTION",0
szSINGLE_STEP DB "EXCEPTION_SINGLE_STEP",0
szSTACK_OVERFLOW DB "EXCEPTION_STACK_OVERFLOW",0
szUNKNOWN_EXCEPTION DB "EXCEPTION_UNKNOWN_EXCEPTION",0
.DATA?
hHeap HANDLE ?
pBuffer LPVOID ?
dwPreviousProtect DWORD ?
.CODE
PUSHAD
INVOKE GetProcessHeap
MOV hHeap, EAX
INVOKE HeapAlloc, hHeap , HEAP_ZERO_MEMORY, DEFAULT_BUFFER_SIZE
MOV pBuffer,EAX
MOV EAX, [lpExceptionInfo]
MOV EAX, [EAX] ;lpEXCEPTION_RECORD
MOV edi, [EAX+12] ;ExceptionAddress;
MOV dwExceptionAddress,edi
MOV edi, [EAX] ;ExceptionCode
MOV dwExceptionCode,edi
.if dwExceptionCode == EXCEPTION_ACCESS_VIOLATION
MOV ESI, OFFSET szACCESS_VIOLATION
.ELSEIF dwExceptionCode == EXCEPTION_ARRAY_BOUNDS_EXCEEDED
MOV ESI, OFFSET szARRAY_BOUNDS_EXCEEDED
.ELSEIF dwExceptionCode == EXCEPTION_BREAKPOINT
MOV ESI, OFFSET szBREAKPOINT
.ELSEIF dwExceptionCode == EXCEPTION_DATATYPE_MISALIGNMENT
MOV ESI, OFFSET szDATATYPE_MISALIGNMENT
.ELSEIF dwExceptionCode == EXCEPTION_FLT_DENORMAL_OPERAND
MOV ESI, OFFSET szFLT_DENORMAL_OPERAND
.ELSEIF dwExceptionCode == EXCEPTION_FLT_DIVIDE_BY_ZERO
MOV ESI, OFFSET szFLT_DIVIDE_BY_ZERO
.ELSEIF dwExceptionCode == EXCEPTION_FLT_INEXACT_RESULT
MOV ESI, OFFSET szFLT_INEXACT_RESULT
.ELSEIF dwExceptionCode == EXCEPTION_FLT_INVALID_OPERATION
MOV ESI, OFFSET szFLT_INVALID_OPERATION
.ELSEIF dwExceptionCode == EXCEPTION_FLT_OVERFLOW
MOV ESI, OFFSET szFLT_OVERFLOW
.ELSEIF dwExceptionCode == EXCEPTION_FLT_STACK_CHECK
MOV ESI, OFFSET szFLT_STACK_CHECK
.ELSEIF dwExceptionCode == EXCEPTION_FLT_UNDERFLOW
MOV ESI, OFFSET szFLT_UNDERFLOW
.ELSEIF dwExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION
MOV ESI, OFFSET szILLEGAL_INSTRUCTION
.ELSEIF dwExceptionCode == EXCEPTION_IN_PAGE_ERROR
MOV ESI, OFFSET szIN_PAGE_ERROR
.ELSEIF dwExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO
MOV ESI, OFFSET szINT_DIVIDE_BY_ZERO
.ELSEIF dwExceptionCode == EXCEPTION_INT_OVERFLOW
MOV ESI, OFFSET szINT_OVERFLOW
.ELSEIF dwExceptionCode == EXCEPTION_PRIV_INSTRUCTION
MOV ESI, OFFSET szPRIV_INSTRUCTION
.ELSEIF dwExceptionCode == EXCEPTION_SINGLE_STEP
MOV ESI, OFFSET szSINGLE_STEP
.ELSE
MOV ESI, OFFSET szUNKNOWN_EXCEPTION
.ENDIF
INVOKE wsprintf, ADDR pBuffer, ADDR szErrorMessage, dwExceptionAddress, ESI
INVOKE MessageBox, NULL, ADDR pBuffer, ADDR szErrorCaption, MB_ICONERROR OR MB_OK OR MB_APPLMODAL
INVOKE HeapFree,hHeap,NULL,pBuffer
;Try to patch our way through the bad code ;)
MOV EAX, [lpExceptionInfo]
MOV EAX, [EAX].EXCEPTION_POINTERS.ContextRecord
MOV esi, [EAX].CONTEXT.regEip
; A length disassembler could be used to determine the size of code to be patched...
; Now i set the instruction length to 1 (constant) because i know it will work
; with the "bad" opcodes in this program... (They all have one-byte instructions)
INVOKE VirtualProtect,ESI,1,PAGE_EXECUTE_WRITECOPY,ADDR dwPreviousProtect ;Override the READONLY atrribute of the Code segment
MOV byte ptr [ESI], 090h ;Patch the bad instruction with the NOP opcode
;INC ESI ;INC EIP (NOT REALLY NECESSARY, SINCE WE PATCH THE BAD INSTRUCTIONS...)
MOV EAX, [lpExceptionInfo]
MOV EAX, [EAX].EXCEPTION_POINTERS.ContextRecord
MOV [EAX].CONTEXT.regEip,ESI
POPAD
MOV EAX,-1 ; Reload the context record into the processor and continue execution from the eip given in the context.
RET
;INVOKE ExitProcess, NULL
FinalExceptionHandler ENDP
;---------------------------------------------------------------------------------------------------------------------
; Safe Offset for PTEH
;---------------------------------------------------------------------------------------------------------------------
SafeOffset:
INVOKE MessageBox, NULL, ADDR szPTEHMessage, ADDR szPTEHCaption,MB_OK
jmp @UninstallPerThreadSEH
end EntryPoint
Thanks guys, I see... so the use of FS register doesn't work on Windows Vista/7?
I have windows 7 and the MichaelW's code doesn't work for me...
dave masm code works fine for me btw :bgrin:
guys, so the better way is to use the FS register + SetUnhandledExceptionFilter ? :)
the new way is probably the better way
we just have to figure out how to use it - lol
it may that something changed in win 7 and the code needs a little update
Forum search does not seem to work properly - for the SEH it founds stuff that is not related, for AxEH it founds nothing.
Have a look on this (and try it under Win7), maybe it will be useful:
http://masm32.com/board/index.php?topic=350.msg2206#msg2206
Quote from: RHL on December 02, 2012, 05:55:59 PM
Hi guys, could anyone tell me why my code doesn't work:
push DWORD ptr handler
This code pushes first bytes of the handler, but it should push the offset of the handler:
push offset handler
will do the job.
thank you, alex, I have used your code on W$ xp,7,8 and it's working :biggrin:
You could easily use those macroses in AxEH.inc in your programs :t
I would be surprised if the method used here would not work under Windows Vista/7.
;==============================================================================
; try.asm
;==============================================================================
LPEXCEPTION_POINTERS TYPEDEF PTR EXCEPTION_POINTERS
;-----------------------------------------------------------------
; This macro sets the top-level exception filter for the calling
; process to our try_filter procedure, so when an unhandled
; exception reaches the UnhandledExceptionFilter function, and
; the process is not being debugged, the function will call our
; procedure. The return_address parameter specifies the address
; of a label were execution will continue if an exception occurs.
; Use this macro to begin a guarded section of code.
;-----------------------------------------------------------------
try_begin MACRO return_address
push return_address
pop _exception_return_address_
invoke SetUnhandledExceptionFilter, try_filter
mov _previous_exception_filter_, eax
ENDM
;----------------------------------------------------------------
; This macro sets the top-level exception filter for the calling
; process to what it was before the try_begin macro changed it.
; Use this macro to end a guarded section of code.
;----------------------------------------------------------------
try_end MACRO
invoke SetUnhandledExceptionFilter, _previous_exception_filter_
ENDM
;==============================================================================
.data
_exception_return_address_ dd 0
_previous_exception_filter_ dd 0
exception_record EXCEPTION_RECORD <>
.code
;==============================================================================
PEXCEPTION_RECORD TYPEDEF PTR EXCEPTION_RECORD
;-----------------------------------
; These not defined in windows.inc.
;-----------------------------------
EXCEPTION_NONCONTINUABLE_EXCEPTION equ 0C0000025h
EXCEPTION_STACK_OVERFLOW equ 0C00000FDh
EXCEPTION_INVALID_DISPOSITION equ 0C0000026h
EXCEPTION_GUARD_PAGE equ 080000001h
EXCEPTION_INVALID_HANDLE equ 0C0000008h
ShowException proc uses ebx per:PEXCEPTION_RECORD
mov ebx, per
SWITCH [ebx].EXCEPTION_RECORD.ExceptionCode
CASE EXCEPTION_ACCESS_VIOLATION
printf("EXCEPTION_ACCESS_VIOLATION")
CASE EXCEPTION_DATATYPE_MISALIGNMENT
printf("EXCEPTION_DATATYPE_MISALIGNMENT")
CASE EXCEPTION_BREAKPOINT
printf("EXCEPTION_BREAKPOINT")
CASE EXCEPTION_SINGLE_STEP
printf("EXCEPTION_SINGLE_STEP")
CASE EXCEPTION_ARRAY_BOUNDS_EXCEEDED
printf("EXCEPTION_ARRAY_BOUNDS_EXCEEDED")
CASE EXCEPTION_FLT_DENORMAL_OPERAND
printf("EXCEPTION_FLT_DENORMAL_OPERAND")
CASE EXCEPTION_FLT_DIVIDE_BY_ZERO
printf("EXCEPTION_FLT_DIVIDE_BY_ZERO")
CASE EXCEPTION_FLT_INEXACT_RESULT
printf("EXCEPTION_FLT_INEXACT_RESULT")
CASE EXCEPTION_FLT_INVALID_OPERATION
printf("EXCEPTION_FLT_INVALID_OPERATION")
CASE EXCEPTION_FLT_OVERFLOW
printf("EXCEPTION_FLT_OVERFLOW")
CASE EXCEPTION_FLT_STACK_CHECK
printf("EXCEPTION_FLT_STACK_CHECK")
CASE EXCEPTION_FLT_UNDERFLOW
printf("EXCEPTION_FLT_UNDERFLOW")
CASE EXCEPTION_INT_DIVIDE_BY_ZERO
printf("EXCEPTION_INT_DIVIDE_BY_ZERO")
CASE EXCEPTION_INT_OVERFLOW
printf("EXCEPTION_INT_OVERFLOW")
CASE EXCEPTION_PRIV_INSTRUCTION
printf("EXCEPTION_PRIV_INSTRUCTION")
CASE EXCEPTION_IN_PAGE_ERROR
printf("EXCEPTION_IN_PAGE_ERROR")
CASE EXCEPTION_ILLEGAL_INSTRUCTION
printf("EXCEPTION_ILLEGAL_INSTRUCTION")
CASE EXCEPTION_NONCONTINUABLE_EXCEPTION
printf("EXCEPTION_NONCONTINUABLE_EXCEPTION")
CASE EXCEPTION_STACK_OVERFLOW
printf("EXCEPTION_STACK_OVERFLOW")
CASE EXCEPTION_INVALID_DISPOSITION
printf("EXCEPTION_INVALID_DISPOSITION")
CASE EXCEPTION_GUARD_PAGE
printf("EXCEPTION_GUARD_PAGE")
CASE EXCEPTION_INVALID_HANDLE
printf("EXCEPTION_INVALID_HANDLE")
DEFAULT
printf("exception code ")
printf("%X",[ebx].EXCEPTION_RECORD.ExceptionCode)
ENDSW
printf(" @ %Xh\n",[ebx].EXCEPTION_RECORD.ExceptionAddress)
ret
ShowException endp
;==============================================================================
;---------------------------------------------------
; This procedure is our top-level exception filter.
;---------------------------------------------------
try_filter proc lpexception_pointers:LPEXCEPTION_POINTERS
;-------------------------------------------------------------------------
; Copy the entire EXCEPTION_RECORD structure (80 bytes) to global memory.
;-------------------------------------------------------------------------
mov edx, lpexception_pointers
mov ecx, [edx].EXCEPTION_POINTERS.pExceptionRecord
mov edx, OFFSET exception_record
DISP=0
REPEAT (SIZEOF EXCEPTION_RECORD) / 4
mov eax, [ecx+DISP]
mov [edx+DISP], eax
DISP=DISP+4
ENDM
;------------------------------------------------------------------
; Modify the EIP member of the CONTEXT structure so execution will
; continue at the address passed to the try_begin macro, instead
; of continuing at the point of the exception (which would cause
; the exception to repeat).
;------------------------------------------------------------------
mov edx, lpexception_pointers
mov eax, [edx].EXCEPTION_POINTERS.ContextRecord
push _exception_return_address_
pop [eax].CONTEXT.regEip
invoke ShowException, ADDR exception_record
;------------------------------------------------------------------------
; Returning EXCEPTION_CONTINUE_EXECUTION to the UnhandledExceptionFilter
; function will cause it to return and continue execution from the point
; specified in the EIP member of the CONTEXT structure.
;------------------------------------------------------------------------
return EXCEPTION_CONTINUE_EXECUTION
try_filter endp
;==============================================================================
;==============================================================================
include \masm32\include\masm32rt.inc
.686
include try.asm
;==============================================================================
.data
.code
;==============================================================================
start:
;==============================================================================
;--------------------------------------------------------------
; The try_ labels and the printf statements were added here to
; to verify that ExceptionAddress is being reported correctly,
; and the error handlers were placed inline as a convenience.
;--------------------------------------------------------------
try_begin eh0
try0:
int 3
eh0:
printf("%Xh\n",try0)
@@:
try_end
try_begin eh1
mov ecx, 1
mov edx, 10
try1:
div ecx
jmp @F
eh1:
printf("%Xh\n",try1)
@@:
try_end
try_begin eh2
xor ecx, ecx
try2:
div ecx
jmp @F
eh2:
printf("%Xh\n",try2)
@@:
try_end
try_begin eh3
try3:
mov cr0, eax
div ecx
jmp @F
eh3:
printf("%Xh\n",try3)
@@:
try_end
try_begin eh4
xor eax, eax
try4:
mov DWORD PTR [eax], 1
jmp @F
eh4:
printf("%Xh\n\n",try4)
@@:
try_end
inkey
exit
;==============================================================================
end start
Michael, I guess the C example you provided is "not working on Win7" just because it has some incompatibility with modern VC compilers that use many default flags which were not available at 1997, so it is not the flaws of the example/code but the build environemnt assumptions (LINK.EXE likes to make a choice instead of a programmer :biggrin:).
Quote from: Antariy on December 03, 2012, 01:12:51 PM
Michael, I guess the C example you provided is "not working on Win7" just because it has some incompatibility with modern VC compilers that use many default flags which were not available at 1997, so it is not the flaws of the example/code but the build environemnt assumptions (LINK.EXE likes to make a choice instead of a programmer :biggrin:).
There are two SEH examples in the MasmBasic library (using plain old techniques) at
\Masm32\RichMasm\RES\SkelTryCatchDetailed.asc
\Masm32\RichMasm\RES\SkelTryCatch.asc
They both work fine on Win7-32 and Win7-64, with no particular linker settings, and tested with both polink and the old linker that comes with Masm32. So apparently, the problem is not Win7.
Yes, Alex is right.
Good to see you back here, Alex. :t
Gunther
Thank you, Gunther! :biggrin: :t
Alex, you're always welcome.
Gunther
yes - good to see you, Alex :t
i had forgotten about your SEH macros :P