Resource Hacker FX: Unicode support

The new version of Resource Hacker FX partially supports Unicode.

What’s supported:

  • Decompilation and compilation of: string table, message table, accelerators, menu, version info.
  • Menu and dialog preview.

What’s not supported:
Everything else, including:

  • Dialog’s control editor.
  • Search.
  • Export to .rc file.
  • Unicode file names.

Technical details: how did I do that?

So, how did I make Resource Hacker handle Unicode without having it’s source code?

Originally, Resource Hacker’s decompilation process looks more-or-less like this:
File (Unicode)
–[TO_ANSI]–>
Memory (ANSI)
–[DECOMPILE_ANSI]–>
Decompiled text (ANSI)

A native Unicode resource editor would look like this:
File (Unicode)
–>
Memory (Unicode)
–[DECOMPILE_UNICODE]–>
Decompiled text (Unicode)

But making Resource Hacker work this way would require rewriting it’s decompilation functions, as they expect ANSI text, and we want to decompile Unicode.

So, to achieve our goal of easily making Resource Hacker handle Unicode, we need the following:

  • The Unicode information must be preserved in memory.
  • The decompilation functions should work without a major change.

I was thinking about whether this is even possible, and then it hit me: UTF-8!

UTF-8 is (Wikipedia):

a variable-width encoding that can represent every character in the Unicode character set. It was designed for backward compatibility with ASCII and to avoid the complications of endianness and byte order marks in UTF-16 and UTF-32.

Exactly what we need, eh?
Now we can make the decompilation process look like this:
File (Unicode)
–[TO_UTF8]–>
Memory (UTF-8)
–[DECOMPILE_UTF8]–>
Decompiled text (UTF-8)

Making it is relatively easy, and because UTF-8 is backward compatible with ASCII, the original decompiling functions work almost without changes.

The latest question left is: how do we show the decompiled text in Resource Hacker, while it uses non-Unicode controls?
Luckily for us, Resource Hacker uses the rich edit control, which supports multiple encodings even as a non-Unicode control. (this support is not 100%, e.g. you cannot paste Unicode text copied from an external program)

Get the new Resource Hacker FXer here.

Posted in Software, Updates by RaMMicHaeL at February 1st, 2012.
Tags:

72 Responses to “Resource Hacker FX: Unicode support”

  1. VEG says:

    Are you tried to contact author of Resource Hacker for getting the source code?

    • RaMMicHaeL says:

      No, but I’ve read the help file, including the “Show me the source!” section :)
      Also, I’m not really interested in the source, I do not know Delphi.

      I would contact him to ask about publishing the FX version on the official page, but I didn’t find any contact info.

  2. Zero Dubby says:

    Wow… such a huge list… I’m a little bit lost now…

    It’s very Great improvement Dude… :)
    You really did it…
    congratulation… :D

    maybe the ‘paste’ problem is the EM_CANPASTE message…?
    not check them yet… as I’m unable to boot into my another machine which I’m using for modding purposes… :(

    eh by the way if you have IDA signatures you can apply them into Olly…. with ida_sigs plugins, it will make the codes more clearer…

    • RaMMicHaeL says:

      maybe the ‘paste’ problem is the EM_CANPASTE message…?

      The main “problem” is that the control is not a Unicode control, and thus has an ANSI Window Procedure. Every message that goes through marshalling gets its strings converted to ANSI, even if you use e.g. SendMessageW.

      if you have IDA signatures you can apply them into Olly….

      I’d recommend IDR and mapimp :)

      • Zero Dubby says:

        I think this may help you….
        http://sourceforge.net/projects/utf8vcl/

        but it does not have a compiled executable….
        so I compiled it (using delphi7) here http://www.mediafire.com/?15uer0i2a1fgjax

        take a look at SetWindowlongA…. also CallWindowProcA….
        hope this help….. :)

        • RaMMicHaeL says:

          So I’m not the first one to come up with the UTF-8 idea :)

          The example doesn’t work too good for me (edit1 shows garbage when I try to edit it, the FatalAppExit button shows a message with question marks).

          Also, I can’t see how this can help me without actually having reshacker’s source code.

          • Zero Dubby says:

            Yup…. I knew that… maybe it’s editing feature is unimplemented…. also there is an unsupported feature if the example is compiled using delphi7…..
            I don’t know delphi much…

            uhm… I mean the implementation of Wide Character (the ‘W’ function) could be useful…
            Delphi always subclass all it’s child procedure in their own procedure (in ANSI)… so that’s why the ‘W’ function e.g. SendMessageW always return in ANSI….

            a few days ago I was able to force the dialog control editor to show in Unicode by using wide version of SetWindowLong in delphi Form child procedure and CallWindowProcW… but as any other text still in ANSI they incorrectly showed…

            • RaMMicHaeL says:

              a few days ago I was able to force the dialog control editor to show in Unicode by using wide version of SetWindowLong in delphi Form child procedure and CallWindowProcW… but as any other text still in ANSI they incorrectly showed…

              Other than SetWindowLong and CallWindowProc, there’s (I believe) plenty of code to change. I didn’t look at it thoroughly, but it has about five custom wndproc callbacks, everyone of which potentially excepts ANSI text.

              The dialog editor, on the other side, is more low level: it has a small custom wndproc, which doesn’t handle messages with text.
              A->W of CreateDialogIndirectParam, SetWindowLong and CallWindowProc was enough here.

  3. Zero Dubby says:

    Hello it’s me again….

    finally I managed to build a small dev system…
    anyway…
    The paste problem is caused by Rich edit control…. the resource hacker uses (partially) the FIRST version of Rich edit… so just update it… it will be able to paste unicode text from external application….

    just replace string “Riched32.dll” with “Riched20.dll” and update string “RICHEDIT” with “RichEdit20A” also replace the CR,LF with CR only….

    Hope this help…. but I still doesn’t know what’s the side effects…

    • RaMMicHaeL says:

      That fixes the pasting issues, but one thing I’ve noticed is that it’s slower on loading long texts, e.g. try reshacker’s TDlgEdForm.

      Update: This happens only when using Unicode with the richedit, and happens also to the first version.

      • Zero Dubby says:

        I’m wondering if the EditStreamCallback function (what should it be called actually…?) was optimized with ANSI only text…??

        • RaMMicHaeL says:

          I didn’t understand the question…
          Instead of forwarding chunks of ANSI text, I changed it to convert UTF-8 chunks to Unicode and forward them.

          • Zero Dubby says:

            I mean The EditStreamCallback, the function which “read” the text from stream into a buffer to be flushed into rich edit window…. the 3rd parameter inside lParam in em_streamin messages….

            • RaMMicHaeL says:

              OK, I understood what function you’re talking about, but didn’t understand the “optimized with ANSI only text”.

              Again:
              Instead of forwarding chunks of ANSI text, i.e.:
              dwCookie: a memory stream (ANSI) –> pbBuff (ANSI)
              I changed the function to convert UTF-8 chunks to Unicode and forward them:
              dwCookie: a memory stream (UTF-8) –> pbBuff (Unicode)

              • Zero Dubby says:

                well nevermind ’bout that a bit silly question….

                anyway I don’t know it’s useful or not…. I have compiled the previous UTF8 examples into DLL (stripped out not important part) it will replace the import table in reshaker when loaded…. but the MAIN problem is the Treeview is stop working…. :(

                http://www.mediafire.com/?5o7r12uqu4x7s3d

    • RaMMicHaeL says:

      just replace string “Riched32.dll” with “Riched20.dll” and update string “RICHEDIT” with “RichEdit20A” also replace the CR,LF with CR only….

      Done in v1.4.1

      Also, I got your mail with fully Unicode reshacker, but haven’t had a chance to look at it thoroughly yet.

  4. Alex says:

    Hi,
    I’ve a couple of questions
    I’m trying to browse one .exe that has Chinese, Japan, etc strings
    so, what font shall be used in order to display it correctly? (Win XP SP3)
    I’ve tried Arial Unicode MS but still no correct display of it.
    Also this error is show on every click in strings:

    —————————
    Resource Hacker
    —————————
    RichEdit line insertion error.
    —————————
    OK
    —————————

    • RaMMicHaeL says:

      Can you please upload the exe file?

      • Zero Dubby says:

        Can you please upload the exe file?

        Firstly… I’m deeply sorry Alex….
        I just want to help…

        you can load windows XP common control library (inside winsxs folder) and browse the string table and the error will encountered when reshack try load Chinese, Japananese, mostly Asian character….

        also this may helps for speeding up…
        http://bellsouthpwp2.net/r/e/rediv/FAQS/Faqs.html#Bmk039

        also for breaking text limit….
        http://bellsouthpwp2.net/r/e/rediv/FAQS/Faqs.html#Bmk015

        • RaMMicHaeL says:

          you can load windows XP common control library (inside winsxs folder) and browse the string table and the error will encountered when reshack try load Chinese, Japananese, mostly Asian character….

          I don’t have these (or maybe I don’t look in the right place), but I think it should work with v1.4.1. Can you check it?

          • Zero Dubby says:

            I don’t have these (or maybe I don’t look in the right place), but I think it should work with v1.4.1. Can you check it?

            the folder is inside windows folder… I think only XP have multilingual language in one dll….
            the other windows after XP have been separated….

            Yup working properly right now…. but in dialog editor… there is no more red star mark… while the cursor is inside rich edit text… or while individual control is being selected in dialog editor… because the original uses CR,LF for string compare between dialog and the editor…

            Hint: search for “*” (star mark…) there more than 1 occurance though but not so much….
            I’m so sorry I can’t point you directly.. I’m unable to boot into my virtual machine….

            anyway awesome Work…. :D

  5. Zero Dubby says:

    Finally I got it works….
    http://i.imgur.com/uGKIy.jpg

    I have sent the details into your email…. :D

  6. Alex says:

    RaMMicHaeL
    rerards my message from February 14, 2012 at 12:37 pm
    it all fine!
    my fault, sorry, did some steps wrong.

  7. Alex says:

    one more issue report:

    when opening Delphi2007 app in patched FX:

    —————————
    Resource Hacker FX
    —————————
    Stream read error.
    —————————
    OK
    —————————

    other RCData (dfm forms) just hangs, others do not show the full dfm content!

    example of hang case:

    app starts to eat 100% of CPU time
    here is the stack (as from Process Explorer v15.13)

    ntdll.dll+0x19d27
    kernel32.dll+0x1251c
    ResHacker.exe+0x62a0
    ResHacker.exe+0x10350

  8. Zero Dubby says:

    http://www.installationexcellence.com/articles/VistaWithDelphi/Original/Index.html

    the final compiled executables in that website also causes reshacker to be hang up (endless loop) (DFM resources..)…..

    • RaMMicHaeL says:

      I looked at it, and the problem is that the DFM resource of the application has new element types that reshacker doesn’t recognize.

      The function that decompiles the DMF resource: 004145AC (Probably ObjectBinaryToText).

      If you have the latest version of Delphi, a simple compiled program that uses ObjectBinaryToText and ObjectTextToBinary might help.

      A POC patch that allows to decompile the DFM resource of the application above:
      004145E0: DF 03 -> 7C 02

      P.S. Fixing this will probably also fix the limitation described on reshacker’s homepage:

      Limitation:
      Resource HackerTM was compiled using Delphi 3.02. When decompiling and recompiling Borland’s Delphi forms in applications compiled with later version of Delphi, there may be errors in the recompiled forms if frames have been used to create the form. This error is due to new language syntax not being recognized.

      Status:
      I have no plans to recompile Resource HackerTM using a newer version of Delphi.

      • Zero Dubby says:

        Great….. :D
        but I notice that there is a ‘sign’ that incorrectly interpret-ed…
        this sign ==> ” become this ==> {}
        but it should be easy to fix….
        (try to find “DFM explorer”… it should be appear in the first page….)

        thanks again…..

    • RaMMicHaeL says:

      Fixed in v1.4.3.

      • Alex says:

        Hi, author

        what could be the reason of this error of your tooL?

        —————————
        Resource Hacker FX
        —————————
        RichEdit line insertion error.
        —————————
        OK
        —————————

        this errror was shown when clicking on
        Version Info – 1 [2052] tree view item node

        ohhhhhh

        also same error:

        —————————
        Resource Hacker FX
        —————————
        RichEdit line insertion error.
        —————————
        OK
        —————————

        when clicking on String table 7 [2025] item node

  9. Alex says:

    OK, forget it, all is just perfect in latest 1.4.3 edition!
    Long live rammichael!

  10. Alex says:

    new issue found on latest FX ver 1.4.5

    —————————
    Resource Hacker FX
    —————————
    Access violation at address 00402791 in module ‘ResHacker.exe’. Write of address 01FFB000.
    —————————
    OK
    —————————

    link to file http://rghost.net/40368026

    navigate to bmp with ID 8034 and watch the beautifull crash
    cheers

  11. Alex says:

    Thanks
    fix works just like a charm
    good luck, mate!

  12. Alex says:

    One new issue found

    —————————
    Resource Hacker FX
    —————————
    No MCI device open.
    —————————
    OK
    —————————

    how to:

    goto AVI
    2275
    2325 Stop
    WAVE node -> issue (reproduced not 100% but often)

    http://rghost.net/40429257

    • RaMMicHaeL says:

      Fixed in v4.1.7.

      The issue was that reshacker tried to continue looping after the AVI preview was stopped/closed. The bug can be easily reproduced with the first AVI video: exactly when the green square comes back to the computer on the left (the last frame), navigate out, and you’ll see the error message box. Also, if you click stop on the last frame, the preview doesn’t actually stop.

  13. Alex says:

    Thanks, working like a charm

    one more note (not sure why it is so)
    please look at following picture
    pay attention to painted area
    http://rghost.net/40449137
    the question is: why does Reshacker put 0x01 instead of real sublang define?
    for example for english it prints like
    LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

    let me know what you think regards this micro issue :)

    cheers!

  14. Alex says:

    One thing that I’ve seen today:
    I’ve dropped by mistake a huge DVD iso (~4GB) only ResHackerFX and…
    it started to eat all my RAM + page file so it was not possible even to drag the mouse…… :(

    Question: is it possible to rewrite the way how ResHackerFX reads the input file? I guess it reads (tries to) the full file (oh mamma mia) and then sees if it is Win32 PE or not

    I’ve two ideas:
    1) limit by size – eg 100 MB exe
    2) read first 4..20K and check by MZ/PE header

    again, just an idea in the air!
    cheers
    Alex

  15. Alex says:

    One more idea:

    You know the left hand Tree view that shows all the objects
    what about showing as hint or maybe to the right the number of records in each section? for example:

    [+]AVI-34
    [+]Icon-123
    [+]Dialog-200
    ….

    Thanks

  16. Redde says:

    Does anyone know in where Aero’s Copying and Moving animations are located?

  17. Alex says:

    sw used: 1.4.7
    some dfm forms are putting strange errors when clicking on it,
    eg: click on TFORMABOUT, TFORMCHCONFTABABS,

    —————————
    Resource Hacker FX
    —————————
    Invalid floating point operation.
    —————————
    OK
    —————————

    Other error on clicking the TFORMCHCONFTABRAG resource:

    —————————
    Resource Hacker FX
    —————————
    Stream read error.
    —————————
    OK
    —————————

    wow, TFORMCONFTAB is hanging the app up! (eating 100% of the poors CPU guy :)

    bits are here: http://rghost.net/41503029
    pass is 123

  18. Alex says:

    thanks a lot

  19. adoxa says:

    Would it be possible to support Unicode HTML (23) resources (I have DLLs with UTF-16 XML files there)? Renaming 23 to HTML and 24 to Manifest would be nice, too.

    • RaMMicHaeL says:

      Would it be possible to support Unicode HTML (23) resources (I have DLLs with UTF-16 XML files there)?

      How can it be detected? Does it have a BOM?
      Could you upload a file?

      Renaming 23 to HTML and 24 to Manifest would be nice, too.

      Will do.

      • adoxa says:

        How can it be detected? Does it have a BOM?
        Could you upload a file?

        Some have a BOM, some don’t. Of course, for those that have a BOM, that would be sufficient. For those that don’t, use IsUnicodeText if you can, otherwise (length > 2 && text[1] == '\0') is probably good enough. Here’s a sample DLL with two Unicode HTML resources – one with BOM, one without.

        • RaMMicHaeL says:

          Done.

          I use BOM detection, and if it’s absent, I try IsTextUnicode. It’s not perfect (i.e. “1” (31 00) isn’t treated as Unicode), but it’s good enough I guess. For most typical texts, it should read it correctly.

          Writing isn’t as good, though. Because of the way reshacker fetches the text from the richedit control, it treats it as ASCII, and all non-ASCII characters are replaced with question marks. This can be fixed, but will require more effort, and I already spent way more time on it than I originally planned. It preserves the BOM and the null terminator, though, if those exist.

          • Michel says:

            hi! Your latest modification is not compatible with Windows 98 SE.

            Can you correct this ?

            Access violation at address 004D0467 in module ‘RESHACKERFX.EXE’ Write of address 02306078.

          • adoxa says:

            Thanks, that looks much better (when it works ;) ), as does having HTML/Manifest.

            To be pedantic, it treats it as ANSI.

            • adoxa says:

              Oops, I also meant to ask for word-wrapping…

              • RaMMicHaeL says:

                Shouldn’t be difficult to implement, but I don’t want it to be on by default, and adding a GUI option is time consuming.
                Maybe you’d like to implement this yourself? :)
                I can give you the multiasm sources if you’re interested.

                • adoxa says:

                  Sure, I’ll give it a go.

                  • RaMMicHaeL says:

                    OK, here are the files:
                    https://www.dropbox.com/sh/v5nw4vx39ihv0og/1dmiroMdj1

                    The .asm files in the asm directory are Multiline Ultimate Assembler files.
                    There are small patches which were made directly, without multiasm. All of those should be mentioned in Patches.txt.
                    ResHacker.map contains symbols of the reshacker executable, generated by Interactive Delphi Reconstructor. You can use e.g. mapimp for OllyDbg to import those.
                    update.res contains updated resources.

                    Good luck :)

                    • adoxa says:

                      Here you go. Replace TMAINFORM with that supplied, increase .extra to 1800 and assemble (btw, I use ODBG2 should that make a difference). Too much trouble to add a new menu item, so I replaced the separator between Find Next and Editor Font. The wrap state is stored in the ini, so you can choose your own default.

                      The access violation at 4d0467 is because of [ebx+edx] (where edx is a pointer to the length, hence the crash), but I see in your code you have [ebx+ecx]. Post-release update?

                    • RaMMicHaeL says:

                      Great. I took a quick look. Will do the merging later.

                      About the menu item: I saw that you’ve added a new item to the dispatch array, which is tricky (that’s why you found it troublesome to add a new item, right?). I think you can as well reuse an existing callback function, and check the menu id name.

                      The access violation at 4d0467 is because of [ebx+edx] (where edx is a pointer to the length, hence the crash), but I see in your code you have [ebx+ecx]. Post-release update?

                      I’ve released a new version, v1.4.14, two days ago, which fixes the bug.

                    • adoxa says:

                      I thought adding an item would be tricky because there’s no extra space, so the whole table would have to be duplicated; for the dispatch table, I simply reduced the size of a long name (which was lucky) to fit my new one. Just had another look and the separators can be added to TMAINFORM with no need for anything else, so you might like to put them back.

                    • RaMMicHaeL says:

                      Just had another look and the separators can be added to TMAINFORM with no need for anything else, so you might like to put them back.

                      How can it be done?
                      I’m not too familiar with VCL.

                    • adoxa says:

                      How can it be done?
                      I’m not too familiar with VCL.

                      Here’s a diff – it’s just a matter of adding them to TMainForm.dfm (or directly to TMAINFORM) and compiling it from within ResHacker.

                      --- TMainForm.dfm	2014-05-06 23:39:35 +1000
                      +++ TMainForm-sep.dfm	2014-05-10 17:04:28 +1000
                      @@ -325,10 +325,16 @@
                               ShortCut = 114
                               OnClick = FindNext1Click
                             end
                      +      object N2a: TMenuItem
                      +        Caption = '-'
                      +      end
                             object N2: TMenuItem
                               Caption = '&Wrap'
                               OnClick = Wrap1Click
                             end
                      +      object N2b: TMenuItem
                      +        Caption = '-'
                      +      end
                             object EditorFont1: TMenuItem
                               Caption = 'Editor &Font ...'
                               OnClick = EditorFont1Click
                      
              • RaMMicHaeL says:

                Done in v1.4.15.
                If you want to implement more stuff, I can put the files on GitHub.

    • RaMMicHaeL says:

      Renaming 23 to HTML and 24 to Manifest would be nice, too.

      Done!

  20. Michel says:

    Here you can find another English version of help file in new .chm format:
    http://rusfolder.com/38081874

    Another patch exist for make the modification in ResHacker.
    http://www.upload.ee/files/4039678/reshacker.3.6.0.92.switch.to.chm.help-patch.7z.html

    (The result of this specific patch is not compatible with Windows 98 SE.
    A fatal error (0D: General protection fault) occurred at
    the address 0028:C005990C in VXD VMCPD(01) + 00000360.)

    Have you planned to make an update to your patch for .chm help file (only if .chm is present in the directory when you apply) ?

Leave a Reply