Processing the Resource Directory
Processing the resource directory is a strictly optional task. It is a bit tedious. Benefits of processing include preserving the ever-important application icon and version information so that one's experience with Explorer can be gratifying and
fulfilling, but also so we can support various OLE features.
If you don't care about these things simply carry on. If you do care, then more 'fun' awaits.
The 'fun' that awaits is similar to what we did for exports earlier in that we walk a structure and optionally copy stuff over, adjusting the pointer when we do and leaving it pointing to the original data in the compressed section otherwise.
The difference is that this structure is more complex, with more objects and a more complex decision on what to keep. First let me briefly tell you what you want to keep uncompressed because that's the easy part to know and tedious part to figure out
experimentally. You will want to keep uncompressed the following resources:
* first RT_ICON should be kept
* first RT_GROUP_ICON should be kept
* first RT_VERSION should be kept
* first "TYPELIB" should be kept
* all "REGISTRY" should be kept
OK, that being said, keep in mind that resources are a multi-level tree of directories. You need to keep track of at what level you are to make your comparisons in order to determine whether to keep a resource or not. Also, as a perceived convenience,
all the fixed sized structures are coalesced at the beginning with variable length ones afterwards. This means all the directory structures are at the beginning, with things like string identifiers and resource data afterwards.
I do a similar thing as with the stub and build this section in memory with a managed array of bytes. Once it is constructed I write it out later.
You can walk the tree once to find where this boundary between fixed and variable sized data lays, then copy the fixed data verbatim. It's interesting to not that most of the pointers in this section are relative to the section itself, and thus do not
require translation. The exception to this is the pointers to the actual resource data, which is an RVA.
Walk the tree a second time and append all the string identifiers. Adjust the pointers to these strings keeping in mind that they are _not_ RVAs, but are rather relative offsets into the resource section.
Walk the tree a third time and copy over the resource chunks for the resources types of interest described above. Keep in mind that these actually _are_ RVAs, so you will need to add the RVA of the beginning this section. What is that? Well, it is the
RVA of the last section, plus its size, aligned up to the NT_HEADERS::OptionalHeader.SectionAlignment. The resource chunks should be aligned between appends.
Setup the section header for this additional section. It _must_ have the name .rsrc. Setup the VirtualAddress of this section to the RVA we just computed. Setup the PointerToRawData in a similar manner, except use the last sections PointerToRawData +
SizeOfRawData and align the result up by the value of IMAGE_NT_HEADERS::OptionalHeader.FileAlignment instead. Set the SizeOfRawData to the size of the resulting chunk, and the VirtualSize to the same. You can align these values up if you like.
Similar to what we did with the stub, seek to the PointerToRawData and write out the data in the buffer we've been building.
Finally, set:
IMAGE_NT_HEADERS::OptionalHeader.DataDirectoryIMAGE_DIRECTORY_ENTRY_RESOURCE.VirtualAddress
IMAGE_NT_HEADERS::OptionalHeader.DataDirectoryIMAGE_DIRECTORY_ENTRY_RESOURCE.Size
and we are done with that.