Win x86-32 Themes -> Win x86-64 Themes?

Forum for anything else which doesn't fit in the above forums. Site feedback, random talk, whatever, are welcome.
Post Reply
User avatar
crashfly
Posts: 789
Joined: Thu Mar 13, 2008 11:39 pm
Location: Arkansas, USA

Win x86-32 Themes -> Win x86-64 Themes?

Post by crashfly » Sat Jun 06, 2009 6:39 pm

Does anyone know how to make (or re-create if necessary) x86-32 themes to be able to be used on a x86-64 system?
A mind is like a parachute, it only functions when it is open.
--Anonymous

How to Ask Questions the Smart Way

User avatar
code65536
Posts: 735
Joined: Wed Mar 14, 2007 2:58 pm
Location: .us
Contact:

Post by code65536 » Sat Jun 06, 2009 10:05 pm

Yes, there is a way.

But first, a rant and a bit of background...

The current form of Microsoft's PE file format (the format that EXEs, DLLs, etc. are in) was introduced in Win32/WinNT (Win16 had a different format; the Win32 was first introduced in WinNT; it was later ported from WinNT to "regular" Windows in Win95). And the header of this Win32/NT PE file (once you stripped away the old DOS compatibility stuff) looked like this:

Code: Select all

Signature  // IMAGE_NT_HEADERS
-- Machine // -- IMAGE_FILE_HEADER ...
[...snip...]
The "Machine" is a 16-bit code that tells the system what CPU architecture this PE file was intended for. And that is the big flaw. Instead of saying "Here's a list of architectures that this PE file could be used on, and if you're Alpha, use section 1 of the file, if you're Itanium, use section 3, if you're x86-32, use section 4", it says "This entire file is intended for x86-64". This meant that the same PE file can never be used for two different architectures because the very format of the PE file meant that it can support one and only one architecture per file.

Which was an incredibly stupid design decision. In contrast, Apple got this one right: their executable file format can contain code for multiple architectures. So Apple could have a single executable that contains IBM Power PC code, Intel x86-32 code, and x86-64 code. So all that Wow64 file system redirection crap, all the shenanigans with "Program Files" vs. "Program Files (x86)" and "System32" vs. "SysWow64", all the headaches that come with having 32-bit apps not being able to access the "true" 64-bit file system locations--all that crap could've been avoided if they had a little foresight and made it possible to include multiple architectures per PE file (in order to save space, they didn't actually have to, but they could've at least designed the PE file format so that in the future if such a need arose, they could). But once the PE format was set, the ship had sailed, and they couldn't change it again without breaking all sorts of compatibility. And this is the thing that really, really ticks me off about all this: one of the original processors that NT was designed to operate on was the Alpha. And the Alpha was a 64-bit processor (though WinNT ran the Alpha processor in 32-bit mode). So it's not like they couldn't envision a future in which Windows would have to support 64-bit because the very first version of WinNT already ran on a 64-bit CPU.

Anyway, one of the really wasteful aspects of the whole one-PE-file-per-architecture thing is that not everything in a PE file is CPU-specific. Okay, so separating the 32-bit and 64-bit code into two separate files is inconvenient and means that we need the whole file system redirection thing, but at least we don't use up any extra disk space (beyond a token amount of overhead) by separating the code. But what about the stuff that isn't code? Like UI text, icons, cursors, bitmaps, etc.? Well, that stuff ends up getting duplicated. So if the original NT people designed the PE file right, 64-bit Windows would have a smaller disk/memory footprint. Oh well, no use crying over spilled milk.

So this gets to your theme thing. Themes comprise of two files: a .msstyles file and a shellstyle.dll file. Both files are, you guessed it, PE files (because PE files are easy for a process to load, parse and use). Neither file contains any code--they are comprised entirely of resources. But since they are technically PE files, they are subject to the same PE file rules, namely that they are restricted to a certain architecture. So a 32-bit theme file can't be used by a 64-bit process and vice-versa. Even if the themes are identical and don't contain anything that's specific to any CPU. I know, it's totally stupid. And so is the Wow64 file system redirection.

So to make a 32-bit theme work on Win64, all you have to do is edit the PE file header so that it's recognized as a 64-bit PE file; since the content of theme files are completely CPU-neutral, the only part of the file that needs to change is the PE header.

Unfortunately, this is a bit tricky to do because it involves more than just changing the machine ID from x86-32 to x86-64 because there are a few fields of the "Optional Header" (which isn't actually optional) that are 4 bytes wider in x86-64 because, well, it's 64-bit (did I just use "because" three times in one sentence?). And AFAIK, there isn't a tool that would do this for you.

What I would do, if I were you...
1) Open up the 32-bit theme file and a comparable 64-bit theme file in a hex editor
2) Also open up a copy of both theme files in PEBrowse (open two copies of PEBrowse)
3) Using the PEBrowse structure viewer as a guide for where things are, overwrite the 32-bit PE header with the 64-bit PE header, while preserving the the data in the the following fields: SizeOfInitializedData, SizeOfImage, and the VirutalAddress and Size of the IMAGE_DIRECTORY_ENTRY_RESOURCE section

If you are comfortable with hex, it should be relatively straightforward, though perhaps a bit tedious (unless the size change of the Optional Header bumps the headers across a section boundary, in which case, things can get messy, but that shouldn't be a problem in this particular case).
My addons: CmdOpen - HashCheck - Notepad2 - MS Runtimes - DirectX

Into the breach, meatbags!

User avatar
crashfly
Posts: 789
Joined: Thu Mar 13, 2008 11:39 pm
Location: Arkansas, USA

Post by crashfly » Sat Jun 06, 2009 11:35 pm

All I can say is .... *WOW*!

I have always appreciated your insight into code and design code65536. I will try what you have suggested. If I can get it to work correctly, then I am going to talk with a few people around here that make the themes. Maybe at least I could convert a few over for them.

Thank you once again code65536.
A mind is like a parachute, it only functions when it is open.
--Anonymous

How to Ask Questions the Smart Way

User avatar
code65536
Posts: 735
Joined: Wed Mar 14, 2007 2:58 pm
Location: .us
Contact:

Post by code65536 » Sun Jun 07, 2009 3:43 am

A few extra notes to help you along:

0) Before you begin, you want to do a "sanity check" to make sure that the 64-bit "donor" file is compatible with the 32-bit file that you are trying to convert. To do this, open the files in PEBrowse and expand the "Sections" node on the left. Make sure that the "Sections" node contains only one child item: ".rsrc". Then select the ".rsrc" node and click the "Display structure of the item" toolbar button. The important things to note here are the VirtualAddress and PointerToRawData. These two entries should be identical between the two files (they should be 0x1000 and 0x200). Next, select the "Optional Header" node on the left and click the structure button. Make sure that section alignment and file alignment are 0x1000 and 0x200, respectively, for both files. If these sanity checks pass, you're good to go; otherwise, PM me.

1) The PE header starts the start of the file and will run for 0x200 bytes (if it runs for 0x400 bytes instead, then the PointerToRawData of .rsrc would've been 0x400). You can just transplant this entire 0x200 byte section from the donor to your target. This corresponds to the first part of the step 3 in my earlier post; this is the easy part.

2) Unless the the VirtualSizes (SizeOfRawData is just VirtualSize rounded up to the next 0x200 byte boundary, so VirtualSize is a more precise figure and is what you should be most aware of) of the donor and target .rsrc sections are identical (unlikely unless the themes are the same), you will need to update the size information in the new donor header that you just copied. This is the second part of the step 3 from above, and this is the tedious part...

3) To update the new header, you will need copy these values from the original 32-bit header:
Optional Header:
- SizeOfInitializedData
- SizeOfImage
- IMAGE_DIRECTORY_ENTRY_RESOURCE -> Size
.rsrc entry:
- VirtualSize
- SizeOfRawData

4) To find the location of Optional Header values, note the hex offsets on the left in the structure view of the OH. These are offsets from the start of the OH. To get the start of the OH, select the OH and click the memory dump button and note the starting address of the first byte (just pay attention to the last two digits of that address).

5) To find the location of the .rsrc entry values, note the hex offsets from the structure view for .rsrc. The start of the .rsrc section is the first byte of the ASCII string ".rsrc" in the header.

6) Note that everything is in Little Endian. So the number 0x12345678 will appear in the hex editor as 78 56 34 12.
My addons: CmdOpen - HashCheck - Notepad2 - MS Runtimes - DirectX

Into the breach, meatbags!

User avatar
crashfly
Posts: 789
Joined: Thu Mar 13, 2008 11:39 pm
Location: Arkansas, USA

Post by crashfly » Tue Jun 09, 2009 1:23 am

Well .... you know code 65536, I have been looking at those resource dlls and it appears more complicated than I thought it would be.

On the flip side though, I found a program that may be able to "remove" those resources, and then "load" them into another file. It appearantly reads both 32 and 64 bit files. I just need to locate a "good" 64 bit theme. Assuming that the program can do what it says, I should be able to export from the 32 bit file and import (or overwrite) in the 64 bit file. If so, I will let you (and everyone else) know how it goes.

All of this "hex editing" and "code modification" makes me wish for the good ole days of BASIC programming. lol
A mind is like a parachute, it only functions when it is open.
--Anonymous

How to Ask Questions the Smart Way

User avatar
code65536
Posts: 735
Joined: Wed Mar 14, 2007 2:58 pm
Location: .us
Contact:

Post by code65536 » Tue Jun 09, 2009 7:14 am

Okay, that should work, then.
My addons: CmdOpen - HashCheck - Notepad2 - MS Runtimes - DirectX

Into the breach, meatbags!

User avatar
crashfly
Posts: 789
Joined: Thu Mar 13, 2008 11:39 pm
Location: Arkansas, USA

Post by crashfly » Wed Jun 10, 2009 6:29 pm

How is that for irony?

Investigating some of themes already established on my computer, I have come to the conclusion that the "type" of dll used for themes are irrelevant. I selected an already installed theme on an x86-32 computer. I checked and verified that both the .theme file and the .dll file that goes with it were PE 32 (as code65536 explained above). I then went to the display properties and selected that theme. It loaded without any difficulties.

I see though, that the majority of the "issue" is going to be with the way themes are installed. I see at the top of .inf files that the following is specified:

Code: Select all

[Version]
signature="$CHICAGO$"
I wonder what the signature is for x86-64?

That and I noticed the theme pack I am interested in having SourceDisksNames.x86 listed. I will see about tweaking the theme file to get it to work.
A mind is like a parachute, it only functions when it is open.
--Anonymous

How to Ask Questions the Smart Way

User avatar
5eraph
Site Admin
Posts: 4618
Joined: Tue Jul 05, 2005 9:38 pm
Location: Riverview, MI USA

Post by 5eraph » Wed Jun 10, 2009 6:49 pm

You may find this enlightening:I also posted about addon compatibility between x86-32 and x86-64 sources on WinCert a while back. It's not perfect and won't always work, but it's a start.

User avatar
crashfly
Posts: 789
Joined: Thu Mar 13, 2008 11:39 pm
Location: Arkansas, USA

Post by crashfly » Wed Jun 10, 2009 6:59 pm

Surprising enough 5eraph, the only thing that I needed to do was remove the ".x86" off of "SourceDisksNames". Now the themes install just fine on an x86-64 system. I guess I just need to get Siginet to stop with the ".x86" now (on his themes). :D

Also, I had already considered your tutorial on inf files and found it quite enlightening.
A mind is like a parachute, it only functions when it is open.
--Anonymous

How to Ask Questions the Smart Way

Post Reply