The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: rags on August 29, 2009, 12:33:12 AM

Title: Use of RtlUnwind ?
Post by: rags on August 29, 2009, 12:33:12 AM
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
Title: Re: Use of RtlUnwind ?
Post by: ecube on August 29, 2009, 12:50:24 AM
Something to do with exception handling

"Catching an exception using __try/__except SEH handler will result in RtlUnwind being called without exception record"
Title: Re: Use of RtlUnwind ?
Post by: dedndave on August 29, 2009, 03:10:25 AM
it may have something to do with the prologue/epilogue
i bet Erol would know - lol
Title: Re: Use of RtlUnwind ?
Post by: dedndave on August 29, 2009, 03:52:32 AM
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
Title: Re: Use of RtlUnwind ?
Post by: MichaelW on August 29, 2009, 04:26:27 AM
There is some useful information here:

http://www.jorgon.freeserve.co.uk/Except/Except.htm
Title: Re: Use of RtlUnwind ?
Post by: rags on August 31, 2009, 12:03:27 AM
Thank you for the link Michael.
Title: Re: Use of RtlUnwind ?
Post by: japheth on August 31, 2009, 06:48:52 AM
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