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.
Tags: resource hacker fx
Are you tried to contact author of Resource Hacker for getting the source code?
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.
Wow… such a huge list… I’m a little bit lost now…
It’s very Great improvement Dude… 🙂
You really did it…
congratulation… 😀
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…
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.
I’d recommend IDR and mapimp 🙂
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….. 🙂
So I’m not the first one to come up with the UTF-8 idea 🙂
The example doesn’t work too well 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.
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…
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 expects 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.
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…
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.
I’m wondering if the EditStreamCallback function (what should it be called actually…?) was optimized with ANSI only text…??
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.
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….
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)
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
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.
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
—————————
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
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…. 😀
Fixed in v1.4.2
Finally I got it works….
http://i.imgur.com/uGKIy.jpg
I have sent the details into your email…. 😀
RaMMicHaeL
rerards my message from February 14, 2012 at 12:37 pm
it all fine!
my fault, sorry, did some steps wrong.
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
Can you upload one, so I could reproduce the issue?
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..)…..
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:
Great….. 😀
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…..
Fixed in v1.4.3.
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
OK, forget it, all is just perfect in latest 1.4.3 edition!
Long live rammichael!
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
Fixed in v1.4.6.
Thanks
fix works just like a charm
good luck, mate!
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
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.
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!
Chinese sublanguages (and many others) are not defined in reshacker.
OK, next question
what should I put once I’d like to define non-English sublanguage?
I mean I reall y saw a situation when I’ve changed text of button to non-eng and it was seen as a set of funny characters, not the correct ones…
You need to know the (sub)language identifiers.
http://msdn.microsoft.com/en-us/library/windows/desktop/dd318693(v=vs.85).aspx
That’s another issue. Resource Hacker FX doesn’t support Unicode for the dialog’s control editor.
Thanks for update
Alex.
One more observations:
It is not that ResHacker does not support sublangs!
I’ve seen German, French, Italian, etc sublangs!
but, it looks like it does not want to decode sublang codes for value 0x1, 0x2 and 0x3
Could I ask you to review once again that part of code?
The idea is to decode it as text value, not as code one (as it is now)
here is a proof of what I’m saying
http://rghost.net/40474096
Thanks!
The sublang support of ResHacker is limited to specific languages (about 5 of them). The others are shown as language identifiers.
RaMMicHaeL, thanks for your repeatedly Work.
German ResHackerFX are on http://www.win-lite.de/
http://www.win-lite.de/wbb/board208-specials/board33-software/board99-software-aktuelle-news/p152991-resource-hacker-deutsch/#post152991
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
I don’t think it’s worth the effort…
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
Does anyone know in where Aero’s Copying and Moving animations are located?
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
Same issue as here:
http://rammichael.com/resource-hacker-fx/comment-page-1#comment-1764
I’ve released FXer v1.4.8, which makes Resource Hacker show an appropriate error message instead of randomly crashing (or eating 100% of the poor guy).
thanks a lot
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.
How can it be detected? Does it have a BOM?
Could you upload a file?
Will do.
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.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.
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.
Not just 98. 🙁 It looks to be something like
text[pLen] = '\0'
– the dereference is missing. Until it’s fixed, use a hex editor to go to offset 0xC8469 and change 0x1A to 0x18.Fixed, thanks.
Thanks, that looks much better (when it works 😉 ), as does having HTML/Manifest.
To be pedantic, it treats it as ANSI.
Oops, I also meant to ask for word-wrapping…
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.
Sure, I’ll give it a go.
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 🙂
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?
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.
I’ve released a new version, v1.4.14, two days ago, which fixes the bug.
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.
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.
Done in v1.4.15.
If you want to implement more stuff, I can put the files on GitHub.
Done!
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) ?
Thank you for sharing this tutorial by the way, especially that part about technical details. This is totally helping!