| | |
Extended Message Box for Win32
There are numerous calls to Win32 API that return detailed information as to failure via GetLastError (). I've devised a method by which to get the textual information corresponding to error and the address of the call that caused the violation. If GetLastError () returns null, then it can serve as possibly a simpler way to use MessageBox (). I've only tested this on XP, but it failed miserably on a Sony Lapton running ME.
What you need to define is; style for message box, Caption & Text. If last error was not null, then you'll see
Error < 128> @ [ 40103A ]
Message from system
What you defined as message body text
and then dependant upon MessageBox style buttons for your response
What you need to define is; style for message box, Caption & Text. If last error was not null, then you'll see
Error < 128> @ [ 40103A ]
Message from system
What you defined as message body text
and then dependant upon MessageBox style buttons for your response
; Message definition in .rdata Errm01 dd MB_YESNO | MB_ICONSTOP | MB_DEFBUTTON2 | MB_APPLMODAL db 'MESSAGE BOX DEMO', 0 db 13, 10, 9, 'Do you want to continue', 0 ; Example of how you would call function xor eax, eax ; hWnd, owners window handle mov edx, Errm01 ; Message definition call MsgBox ; ============================================================================================ ; *** MSGBOX *** ; ENTRY: EAX = hWnd ; EDX = Base pointer ot message parameters ; LEAVE EAX = Users response as defined in MessageBox ; ............................................................................................. FMTM EQU FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM MsgBox push esi push edi ; Save essential registers push ebx enter 0x1c8, 0 ; Frame for MessageBox parameters mov ebx, esp ; Let EBX point to base of these params add ebx, byte 24 mov esi, edx cld ; Assure auto increment of indices ; Due to the two modes of operation of this procedure, default to simple message ; box without extended information from GetLastError. mov [ebx], eax ; hWnd, handle of owner window lodsd ; Get style mov [ebx+12], eax ; uType, style of message box mov [ebx+8], esi ; lpCaption, title of message box push esi call _lstrlenA@4 ; Determine length of title text inc eax ; Bump past strings terminating byte add esi, eax mov [ebx+4], esi ; lpText, text in message box ; The single determining factor whether procedure operates in extended mode or not ; is return value from GetLastError. If it isn't null, then that means we want ; to show error code, address of offending call, systems text associated with error ; and message box text from parameter 2 of MessgeBox. call _GetLastError@0 ; Get error code if it exists. and eax, eax jnz .Ext_Mode ; NOTE: I've choosen to use this method because Extended Mode code is ; greater than 128 bytes which puts it past a near jump. ; Display message box in either simple or extended mode, get response from ; operator and let calling procedure determine appropriate action. .Done lea esp, [ebp - 0x1b0] ; Point to parameters intialized earlier. call _MessageBoxA@16 leave pop ebx pop edi ; Restore essential registers pop esi ret ; EAX = Return value of MessageBox call. ; ------------------------------------------------------------------------------------------- ; Normally I would put this in .rdata, but sake of this demonstration I'll leave it in ; this segment .OutFmt db 9, 'Error < %d > @ [ %X ] ', 13, 10, 13, 10, '%s%s', 0 ; ------------------------------------------------------------------------------------------- ; To create the extended string contents for message box, establish the 6 params ; that are required by wsprint being; OutputBuffer, FormatStr, ErrorCode, ; CallAddress, ErrorCodeStr, MsgBoxText. .Ext_Mode mov edi, esp ; Establish pointer to wsprintf params push eax ; Save error code from GetLastError mov eax, esp add eax, byte 0x3c ; Base of Destination Ascii buffer stosd ; 1st Param for wsprintf mov eax, .OutFmt ; Formatting definition stosd ; 2nd Param for wsprintf pop eax ; Restore Error code stosd ; 3rd Param for wsprintf ; Procedure assumes that the first occurence of E8 before the call to MSGBOX was ; the API function that generated this error. mov esi, edi ; Save next pointer to wsprintf param mov edi, [ebp+16] ; Get callers return sub edi, byte 6 ; Point to just before call to MSGBOX mov al, 0xE8 ; Searching for call instruction xor ecx, ecx dec ecx ; Kind of large but no matter std ; We want to search backward repnz scasb inc edi ; Points to call to API cld ; Re-establish direction to default mov eax, edi xchg esi, edi stosd ; 4th Param for wsprintf (Offending call). ; Use FormatMessage to determine text associated with this error from system xor eax, eax push eax ; Arguments = NULL (No insertion points) push eax ; nSize, not required push edi ; We'll use this location temporaritly push dword SUBLANG_DEFAULT << 10 | LANG_NEUTRAL push dword [edi - 8] ; Error code push eax push dword FMTM call _FormatMessageA@28 and eax, eax jnz $+4 int 3 ; In the unlikely event FormatMessage fails. mov eax, [edi+12] add edi, byte 4 ; Jump over value just save by FormatMessage stosd ; Save address to string call _wsprintfA ; Format entire message pop eax ; Point to newly created string mov [edi+4], eax ; and save for MessageBox API push dword [edi-8] ; Recover memory allocated by FormatMessage call _LocalFree@4 jmp .Done ; Complete display and operators response.
Similar Threads
- Message Box in C (C)
- message box (ASP.NET)
- Multicolumn combo box using win32 API (Visual Basic 4 / 5 / 6)
- message box (ASP.NET)
- WIN32 GUI application - Problem popping up dialog box (C++)
| Thread Tools | Search this Thread |



