flat assembler
Message board for the users of flat assembler.

Index > Windows > MESSAGETABLE resources

Author
Thread Post new topic Reply to topic
MattDiesel



Joined: 31 Oct 2010
Posts: 34
Location: England
MattDiesel
FASM has kept me hooked for a few months now, and I am getting the hang of asm Smile But that also means I'm now trying to write larger programs.

Amongst other problems I'm facing is how to handle errors. Using lot's of strings is not easy in asm like it is at higher levels, so I looked for other solutions and found MESSAGETABLEs. These are exactly what I want, as it means I can use Get/SetLastError with system codes AND my own errors as well. Unfortunately they do not feature in the fasm resource macros (yet Rolling Eyes ), so I have to write the .mc files and compiling becomes a 3 stage process.

Msdn has structures which should show how they are arranged in the exe, here, so it should be possible for me to write some macros that end up with a load of db's... Unfortunately I can't see how those structures results in the numbers I get...

Here's a little demo I put together that needs no other files to run:
Code:
format PE GUI 4.0
entry start

include 'win32a.inc'

ERROR_MYERROR = 0xC0020001 ; Generated by MC.EXE

section '.text' code readable executable

  start:
        pushd    1              ; System Error (ERROR_INVALID_FUNCTION)
        call     ShowErr

        pushd    ERROR_MYERROR  ; App error
        call     ShowErr

        invoke   ExitProcess,0

  ; Simple error handling proc
  proc ShowErr,iErr
    local lpBuffer:DWORD
        lea     eax,[lpBuffer]
        invoke  FormatMessage,\
                        FORMAT_MESSAGE_ALLOCATE_BUFFER+\
                        FORMAT_MESSAGE_FROM_HMODULE+\ ; Using FROM_HMODULE | FROM_SYSTEM means
                        FORMAT_MESSAGE_FROM_SYSTEM,\  ; it will check both for the error.
                        NULL,\
                        [iErr],\
                        LANG_NEUTRAL,\
                        eax,\
                        0,\
                        0
        invoke  MessageBox,NULL,[lpBuffer],NULL,MB_OK+MB_SYSTEMMODAL+MB_ICONERROR
        invoke  LocalFree,[lpBuffer]
        ret
  endp

section '.idata' import data readable writeable

  library kernel32,'KERNEL32.DLL',\
          user32,'USER32.DLL'

  include 'api\kernel32.inc'
  include 'api\user32.inc'

section '.rsrc' data readable resource

  directory RT_MESSAGETABLE,errors

  resource errors,\
           1,LANG_ENGLISH+SUBLANG_DEFAULT,error_table ; Must be 1.

  ; Data generated by MC.EXE.
  ; Would normally use: file 'MSG00409.bin'
  resdata error_table
          db   0x01,0x00,0x00,0x00,0x01,0x00,0x02,0xC0,0x01,0x00,0x02,0xC0,0x10,0x00,0x00,0x00,\
               0x84,0x00,0x01,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x69,0x00,\
               0x73,0x00,0x20,0x00,0x70,0x00,0x72,0x00,0x6F,0x00,0x62,0x00,0x61,0x00,0x62,0x00,\
               0x6C,0x00,0x79,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x6F,0x00,\
               0x6E,0x00,0x6C,0x00,0x79,0x00,0x20,0x00,0x65,0x00,0x72,0x00,0x72,0x00,0x6F,0x00,\
               0x72,0x00,0x20,0x00,0x6D,0x00,0x65,0x00,0x73,0x00,0x73,0x00,0x61,0x00,0x67,0x00,\
               0x65,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x61,0x00,0x74,0x00,0x20,0x00,0x6D,0x00,\
               0x65,0x00,0x61,0x00,0x6E,0x00,0x73,0x00,0x20,0x00,0x53,0x00,0x75,0x00,0x63,0x00,\
               0x63,0x00,0x65,0x00,0x73,0x00,0x73,0x00,0x20,0x00,0x3A,0x00,0x29,0x00,0x0D,0x00,\
               0x0A,0x00,0x00,0x00
  endres
    


That table was made from this (Slightly modified from msdn's example file):
Code:
MessageIdTypedef=DWORD

SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS
Informational=0x1:STATUS_SEVERITY_INFORMATIONAL
Warning=0x2:STATUS_SEVERITY_WARNING
Error=0x3:STATUS_SEVERITY_ERROR
)

FacilityNames=(System=0x0:FACILITY_SYSTEM
Runtime=0x2:FACILITY_RUNTIME
Stubs=0x3:FACILITY_STUBS
Io=0x4:FACILITY_IO_ERROR_CODE
)

LanguageNames=(English=0x409:MSG00409)

; // The following are message definitions.

MessageId=0x1
Severity=Error
Facility=Runtime
SymbolicName=ERROR_MYERROR
Language=English
This is probably the only error message that means Success Smile
.
    


Any pointers?

Mat
Post 19 Jan 2011, 23:13
View user's profile Send private message Send e-mail Visit poster's website MSN Messenger Reply with quote
MattDiesel



Joined: 31 Oct 2010
Posts: 34
Location: England
MattDiesel
I've spent all day and finally got something to show... It's not great, but it works.

The problems are that you cannot define blocks, severity+facility codes... All it does is make a single block of error strings, and you then need to make sure that your error constants stay in sync with your strings. It also only works in ANSI at the moment, I imagine someone who had a vague idea what they are doing (aka not me) could write one that looked at sizeof.TCHAR and used that somehow.

It's almost certainly not the best way to do it... I cringe at all the look aheads...
Code:
format PE GUI 4.0
entry start

include 'win32a.inc'

CR = 13
LF = 10

struc error id
{
   . = id or 0xC0020000
}

ERROR_MYERROR error 1
ERROR_TWO     error 2
ERROR_THREE   error 3

macro messagetable label,[strings*]
{
 common
   local data,size
   label dd RVA data,size,0,0
   data = $
   strt = $

   dd 1 ; Only use 1 block

   tbl_size equ size = $ - data

   lowid = 1
   highid = 0

 ; Find the highest id
 forward
   highid = highid + 1

 ; MESSAGE_RESOURCE_BLOCK
 common
   dd lowid or 0xC0020000
   dd highid or 0xC0020000
   dd $ - strt + 4         ; Offset to block

 ; Each MESSAGE_RESOURCE_ENTRY
 forward
   local stringLen
   virtual at 0 
      db strings
      stringLen=$
   end virtual

   dw stringLen+7   ; 7 because dw + dw + CR,LF,0
   dw 0      ; ANSI
   db strings,CR,LF,0

 common
   tbl_size
   align 4
}

section '.text' code readable executable

  start:
        pushd    1              ; System Error (ERROR_INVALID_FUNCTION)
        call     ShowErr

        pushd    ERROR_MYERROR
        call     ShowErr

        pushd    ERROR_TWO
        call     ShowErr

        pushd    ERROR_THREE
        call     ShowErr

        invoke   ExitProcess,0

  ; Simple error handling proc
  proc ShowErr,iErr
    local lpBuffer:DWORD
        lea     eax,[lpBuffer]
        invoke  FormatMessage,\
                        FORMAT_MESSAGE_ALLOCATE_BUFFER+\
                        FORMAT_MESSAGE_FROM_HMODULE+\ ; Using FROM_HMODULE | FROM_SYSTEM means
                        FORMAT_MESSAGE_FROM_SYSTEM,\  ; it will check both for the error.
                        NULL,\
                        [iErr],\
                        LANG_NEUTRAL,\
                        eax,\
                        0,\
                        0
        invoke  MessageBox,NULL,[lpBuffer],NULL,MB_OK+MB_SYSTEMMODAL+MB_ICONERROR
        invoke  LocalFree,[lpBuffer]
        ret
  endp

section '.idata' import data readable writeable

  library kernel32,'KERNEL32.DLL',\
          user32,'USER32.DLL'

  import kernel32,\
         FormatMessage,'FormatMessageA',\
         ExitProcess,'ExitProcess',\
         LocalFree,'LocalFree'

  import user32,\
         MessageBox,'MessageBoxA'

section '.rsrc' data readable resource

  directory RT_MESSAGETABLE,errors

  resource errors,\
           1,LANG_ENGLISH+SUBLANG_DEFAULT,error_table ; Must be 1.

  messagetable error_table,<'This is probably the only error message that means Success :)'>,\
                           <'This is a second error message!!'>,\
                           <'This is a third error message!!'>
    



Mat
Post 20 Jan 2011, 22:42
View user's profile Send private message Send e-mail Visit poster's website MSN Messenger Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2913
Location: 0x77760000
typedef
Nice, I'll be able to use this piece of code one day. I need to study more on macros Very Happy. It looks like you can almost do anything in FASM(ASM in general) just like you would in any other Higher Language. I love macros but just when I thought I knew them, it's when I realized I don't. Very Happy

Off topic
The thing I like thte most is the speed and size.
Post 26 Jan 2011, 19:56
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.