News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Extended Message Box

Started by Tight_Coder_Ex, November 22, 2007, 05:37:44 AM

Previous topic - Next topic

Tight_Coder_Ex

This procedure displays a MessageBox, but with additional information such as error #, address of call that caused the error and associated text.

I left the snippet in start so you can see how this is called. You'll need to include inc files and libraries to conform to your own system

.486
.model flat, stdcall
option casemap:none

.const

  Caption db 'MsgBox Error', 0
  Text db 'Please choose from the following', 0
  FmtText db 'Error [%d] @ %X', 13, 10, 13, 10, '%s', 13, 10, '%s', 0

.code
; ============================================================================================
  Start:
enter 0, 0 ; Empty procedure frame

BOX EQU MB_ABORTRETRYIGNORE or MB_ICONWARNING or MB_DEFBUTTON2 or MB_APPLMODAL

push 33
call SetLastError

push BOX ; uType
push offset Caption ; lpCaption
push offset Text ; lpText
push 0 ; hWnd = Desktop in this example
call MsgBox ; Display error message

leave
ret
; --------------------------------------------------------------------------------------------
  MsgBox PROC uses ebx esi edi hWnd:DWORD, Msg:DWORD, Cap:DWORD, MsgType:DWORD

  FMTM EQU FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM

        LOCAL DispBuff [512] :BYTE

; Setup stack for MessageBox call at epilogue.

push MsgType ; uType
push Cap ; lpCaption
push Msg ; lpText
push hWnd ; hWnd

; As there may not be an error associated with this call make the determination first

call GetLastError
and eax, eax
jz ShowMsg

; Now CapText can be replaced with DispBuff

lea ecx, DispBuff
mov [esp + 4], ecx ; This way so we don't alter EAX

; Begin setting up stack for wsprintf call subject to format outlined in FmtText.

push Msg ; 4th parameter of FmtText
push 0 ; We don't know exactly where this is yet
push eax ; Save temporarily

; As this call is as a result of an error usually from an API, we need to search
; backward in code to find the address at which it occured.

mov edi, [ebp + 4] ; Get callers return address
sub edi, 6 ; Bump past this calls opcode
std ; Set auto decrement of EDI
mov al, 0E8H ; Intel's call instruction
xor ecx, ecx
dec ecx ; Ridiculously large
repnz scasb ; Search backward until found
inc edi ; Bump to proper position
cld ; Set to default again, auto increment
xchg [esp], edi
push edi

; Now we are ready to get formatted text from OS

xor eax, eax
push eax ; Arguments
push eax ; nSize, not required because ALLOCATE_BUFFER
lea eax, [esp + 16]
push eax ; lpBuffer, allocated by API
xor edx, edx
mov dl, SUBLANG_DEFAULT
shl edx, 10
or edx, LANG_NEUTRAL
push edx ; dwLanguageId
mov eax, [esp + 16]
push eax ; dwMessageID
push 0
push FMTM
call FormatMessage
and eax, eax
jnz $ + 3

int 3 ; Trap this if there is an error

; Take all the elements and format them into DispBuff as per FmtText specifications

mov eax, offset FmtText
push eax
lea eax, DispBuff
push eax
call wsprintf
add esp, 24 ; Waste parameters

; Recover memory from system that was allocated by FormatMessage

push dword ptr [esp - 8]
call LocalFree

; Display message message box with extended information if applicable

  ShowMsg: call MessageBox
ret ; Return with response from operator

   MsgBox ENDP

END Start


alemao_brazil

Hi,

Could you or somebody tell me why some codes have so many push instructions (specially to call library functions) and not equivalent pop instructions ?
Do these functions do the "pop" internally or the "push pop" simetry doesn't really care in those codes ?
Tks in advance

S A

jj2007

Hi alemao,

Welcome to the Forum :thumbu

The pushs are "neutralised" by the ret at the end of the called function:

include \masm32\include\masm32rt.inc

.code
AppName   db "Masm32 is great!", 0
Hello   db "A message:", 0

MyTest proc arg1, arg2
  MsgBox 0, arg1, arg2, MB_OK
  ret
MyTest endp

start:
   push offset Hello
   push offset AppName
   call MyTest      ;invoke MyTest, offset AppName, addr Hello
   exit

end start

If you check the ret with Olly, you will find out that it is in fact a retn 8

dedndave

those are parameters, passed to the function on the stack
as JJ mentioned, the function is responsible for removing them from the stack when using the "StdCall" convention

alemao_brazil

Thanks for all  :cheekygreen: