Can anyone explain in plain English what the heck RtlUnwind is used for?
MSDN says: "Initiates an unwind of procedure call frames."
But what exactly is an unwind?
Thanks....Rags
Something to do with exception handling
"Catching an exception using __try/__except SEH handler will result in RtlUnwind being called without exception record"
it may have something to do with the prologue/epilogue
i bet Erol would know - lol
here's a guess....
an error occurs
it finds a new esp value to balance the stack to the point prior to the call
restores ebp, ebx, esi, edi (maybe - lol)
in order to do that, it has to examine the prologue in order to find those values on the stack
There is some useful information here:
http://www.jorgon.freeserve.co.uk/Except/Except.htm
Thank you for the link Michael.
Hello,
I once had to write several test cases for SEH emulation in my DOS extender (HX). Perhaps this one is useful to seen what RtlUnwind() does:
;*** Win32 Exception Handling
;*** - without help from CRT
;*** - 2 exception handlers
;*** - RtlUnwind() is called
.386
.Model flat, stdcall
option casemap:none
WIN32_LEAN_AND_MEAN equ 1
.nolist
.nocref
if 0
include windows.inc
else
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
ExceptionRecord equ <pExceptionRecord>
endif
.cref
.list
;--- 1=continue search,0=continue execution
?CONTINUE1 equ 1 ;action in unhandled exception handler
?CONTINUE2 equ 0 ;action in first exception handler
?CONTINUE3 equ 1 ;action in second exception handler
XCPT_CONTINUE_EXECUTION equ 0
XCPT_CONTINUE_SEARCH equ 1
CStr macro text
local l
.const
l db text, 0
.code
exitm <offset l>
endm
.data
g_hConOut HANDLE 0
.code
assume fs:nothing
printf proc c pszFormat:ptr byte, args:VARARG
local dwWritten:dword
local szText[256]:byte
invoke wvsprintfA, addr szText, pszFormat, addr args
lea ecx, dwWritten
invoke WriteConsole, g_hConOut, addr szText, eax, ecx, 0
ret
align 4
printf endp
myuef proc stdcall pEP:ptr EXCEPTION_POINTERS
mov ecx, pEP
mov ecx, [ecx].EXCEPTION_POINTERS.ExceptionRecord
invoke printf, CStr(<"myuef: pExcRecord=%X code=%X flags=%X addr=%X, ebp=%X",13,10>), ecx, \
[ecx].EXCEPTION_RECORD.ExceptionCode,\
[ecx].EXCEPTION_RECORD.ExceptionFlags,\
[ecx].EXCEPTION_RECORD.ExceptionAddress,\
dword ptr [ebp+0]
if ?CONTINUE1
mov eax, EXCEPTION_CONTINUE_SEARCH
else
mov eax, EXCEPTION_CONTINUE_EXECUTION
endif
ret
align 4
myuef endp
DispExcFrame proc uses esi
mov esi, fs:[0]
.while (1)
.if (esi != -1)
invoke printf, CStr(<"eh frame %X, handler=%X",13,10>),esi, dword ptr [esi+4]
.else
invoke printf, CStr(<"eh frame %X",13,10>), esi
.break
.endif
mov esi,[esi+0]
.endw
ret
align 4
DispExcFrame endp
main2_eh proc c pReport:ptr EXCEPTION_RECORD, pFrame:ptr, pContext:ptr CONTEXT
mov ecx, pReport
invoke printf, CStr(<"main2_eh: ebp=%X pExcRecord=%X [code=%X flags=%X prevRec=%X addr=%X], [ebp]=%X",13,10>), ebp, ecx,\
[ecx].EXCEPTION_RECORD.ExceptionCode,\
[ecx].EXCEPTION_RECORD.ExceptionFlags,\
[ecx].EXCEPTION_RECORD.ExceptionRecord,\
[ecx].EXCEPTION_RECORD.ExceptionAddress, \
dword ptr [ebp+0]
if ?CONTINUE3
mov eax, XCPT_CONTINUE_SEARCH
else
mov eax, XCPT_CONTINUE_EXECUTION
endif
ret
align 4
main2_eh endp
main2 proc c
local var1:dword
invoke printf, CStr(<"main2: ebp=%X",13,10>), ebp
push offset main2_eh
push dword ptr fs:[0]
mov fs:[0],esp
call DispExcFrame
invoke RaiseException, 0E2003456h, 0, 0, 0
pop dword ptr fs:[0]
pop ecx
invoke printf, CStr(<"main2: exit, ebp=%X",13,10>), ebp
ret
align 4
main2 endp
main_eh proc c pReport:ptr EXCEPTION_RECORD, pFrame:ptr, pContext:ptr CONTEXT
mov ecx, pReport
invoke printf, CStr(<"main_eh: ebp=%X pExcRecord=%X [code=%X flags=%X prevRec=%X addr=%X], [ebp]=%X",13,10>), ebp, ecx,\
[ecx].EXCEPTION_RECORD.ExceptionCode,\
[ecx].EXCEPTION_RECORD.ExceptionFlags,\
[ecx].EXCEPTION_RECORD.ExceptionRecord,\
[ecx].EXCEPTION_RECORD.ExceptionAddress,\
dword ptr [ebp+0]
mov ecx, pContext
invoke printf, CStr(<"main_eh: context.flags=%X",13,10>), [ecx].CONTEXT.ContextFlags
if ?CONTINUE2
mov eax, XCPT_CONTINUE_SEARCH
else
invoke printf, CStr(<"main_eh: calling RtlUnwind()",13,10>)
invoke RtlUnwind, pFrame, returnaddr, NULL, 0
returnaddr:
invoke printf, CStr(<"main_eh: back from RtlUnwind()",13,10>)
mov eax, XCPT_CONTINUE_EXECUTION
endif
ret
align 4
main_eh endp
main proc c
local var1:dword
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov g_hConOut, eax
invoke GetModuleHandle, CStr("KERNEL32")
.if (eax)
invoke GetProcAddress, eax, CStr("UnhandledExceptionFilter")
invoke printf, CStr(<"GetProcAddress('UnhandledExceptionFilter')=%X",13,10>),eax
.endif
invoke SetUnhandledExceptionFilter, offset myuef
invoke printf, CStr(<"SetUnhandledExceptionFilter(%X)=%X",13,10>), myuef, eax
invoke printf, CStr(<"main: ebp=%X",13,10>), ebp
push offset main_eh
push dword ptr fs:[0]
mov fs:[0],esp
call DispExcFrame
call main2
pop dword ptr fs:[0]
pop ecx
invoke printf, CStr(<"main: exit, ebp=%X",13,10>), ebp
ret
align 4
main endp
mainCRTStartup proc c
call main
invoke ExitProcess, 0
mainCRTStartup endp
end mainCRTStartup