News:

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

LoadString from resource file

Started by jj2007, October 01, 2009, 11:04:46 PM

Previous topic - Next topic

jj2007

I was playing with string tables, and it seems to be very crappy. The example below works, though, and produces this output:

101     1600    This is the first resource string, ID 1600
102     1616    This is #3, ID 1616 - but where is #2, ID 1608??
103     1632    And the last one, ID 1632


include \masm32\include\masm32rt.inc

MyResCB PROTO:DWORD,:DWORD,:DWORD,:DWORD

.code
start: invoke EnumResourceNames, 0, RT_STRING, MyResCB, 0
exit

MyResCB proc uses esi edi hModule:DWORD, lpszType:DWORD, lpszName:DWORD, lParam:DWORD
LOCAL LocBuffer[260]:BYTE
  mov esi, lpszName ; the "name" of the resource: a DWORD integer, starting with 101
  print str$(esi), 9
  lea edi, LocBuffer
  dec esi
  imul esi, esi, 16 ; magic formula: (name-1)*16
  invoke LoadString, 0, esi, edi, 260
  print str$(esi), 9
  print edi, 13, 10
  or eax, -1
  ret
MyResCB endp

end start


The contents of the resource file:
STRINGTABLE MOVEABLE IMPURE LOADONCALL DISCARDABLE
BEGIN
    1600,   "This is the first resource string, ID 1600"
    1608,   "This is the second string, ID 1608"
    1616,   "This is #3, ID 1616 - but where is #2, ID 1608??"
    1632,   "And the last one, ID 1632"
END


Note the silent omission of 1608...
Googling for EnumResourceNames yielded nothing useful, very few entries, and most of them are complaining that it is not working. Apparently the reason is that resource string IDs must be multiples of 16. Oh Billieboy... ::)

jj2007

Apparently, the reason for this misbehaviour of EnumResourceNames is that this function is supposed to find only the first string in each block of resources, see here for more detail. Only true geniuses would deduct that from the official MSDN documentation.

This behaviour has to do with Microsoft's incredibly clever way of storing these strings. One side effect over which I stumbled when implementing the Res$(ID) macro is that the ID's you give to the strings matter, in a way that is, hrmmpff, surprising ::).

Take this harmless example:

STRINGTABLE  ; Version A
BEGIN
1001,   "First resource string, ID 1001"
1002,   "String 1002"
1003, "String 1003"
1004, "String 1004"
1005, "String 1005"
1006, "String 1006"
1007, "String 1007"
1008, "String 1008"
1009, "String 1009"
1010, "String 1010"
1011, "String 1011"
1012, "String 1012"
1013, "String 1013"
1014, "String 1014"
1015, "String 1015"
1016, "String 1016"
1017, "String 1017"
1018, "String 1018"
1019, "String 1019"
1020, "String 1020"
END

STRINGTABLE  ; Version B
BEGIN
1000,   "First resource string, ID 1001"
2000, "String 1002"
3000, "String 1003"
4000, "String 1004"
5000, "String 1005"
6000, "String 1006"
7000, "String 1007"
8000, "String 1008"
9000, "String 1009"
10000, "String 1010"
11000, "String 1011"
12000, "String 1012"
13000, "String 1013"
14000, "String 1014"
15000, "String 1015"
16000, "String 1016"
17000, "String 1017"
18000, "String 1018"
19000, "String 1019"
20000, "String 1020"
END


No difference, except for the ID's? Assemble the two versions, look at their sizes, and use PEview to see what's happening...!

Code attached.

qWord

FPU in a trice: SmplMath
It's that simple!

sinsi

QuoteRC allocates 16 strings per section and uses the identifier value to determine which section is to contain the string. Strings whose identifiers differ only in the bottom 4 bits are placed in the same section.
Light travels faster than sound, that's why some people seem bright until you hear them.

jj2007

Yes, I have seen that. Microsoft geniuses at work.

clive

Quote from: jj2007
Yes, I have seen that. Microsoft geniuses at work.

A design choice dating back to 1987, or earlier. Probably made sense to someone then.

-Clive
It could be a random act of randomness. Those happen a lot as well.