Visual Studio 2010!

Read now >

View Now
DevSource RSS FEEDS
XML Want an easy way to keep up with breaking tech news? And the Get DevSource headlines delivered to your desktop with RSS.
ADVERTISEMENT
ADVERTISEMENT

 

DevSource.com: Your Source for Visual Studio on Facebook
ADVERTISEMENT
Retrieve Resources From PE Files (Part I)
By Jeff Friesen

Rate This Article: Add This Article To:

Retrieve Resources From PE Files (Part I)
( Page 3 of 4 )

Explore resource data formats

Table 1 identifies the various types of resources that can be stored in the resource section. (I'm unaware of any additional resource types.) These resource types have their own data formats, which need to be understood in order to recreate the original resource files (bitmap .bmp and cursor .cur files, for example). For brevity, this section examines only a few of these formats.

RT_BITMAP

The RT_BITMAP resource type describes the resource data as a single device-independent bitmap. The bitmap is stored as a Windows BITMAPINFOHEADER structure or OS/2 BITMAPCOREHEADER structure, optionally followed by a color table (a sequence of RGBQUAD structures for Windows; a sequence of RGBTRIPLE structures for OS/2), followed by the bitmap image data.

It doesn't matter to the utility program whether the resource data contains BITMAPINFOHEADER and RGBQUAD structures, or BITMAPCOREHEADER and RGBTRIPLE structures. However, the absence of a BITMAPFILEHEADER structure is an impediment to the program -- this structure must be present at the start of a .bmp file.

Before writing the resource data to the .bmp file, the utility program creates a BITMAPFILEHEADER structure and initializes the structure's fields appropriately (add the size of the BITMAPFILEHEADER structure to the size of the resource data, and assign the sum to the structure's bfSize field, for example). The program then writes this structure to the file.

RT_GROUP_CURSOR and RT_CURSOR

A resource script statement for a cursor resource (MyCursor CURSOR "mycursor.cur", for example) is described in a PE file via RT_GROUP_CURSOR and RT_CURSOR resource types. The former resource type stores a directory in the resource data. This directory identifies the various images comprising the cursor resource, and begins with a header structure:

typedef struct
{
WORD wReserved; // Always 0
WORD wResID; // Always 2
WORD wNumImages; // Number of cursor images/directory entries
}
CURHEADER;

This header, which also appears at the beginning of a .cur file (and is written "as is" to a .cur file by the utility program), identifies the number of cursor images that are stored elsewhere in the resource data. Each cursor image is described by one of the entries in the array of cursor directory entry structures that follows the header:

typedef struct
{
WORD wWidth;
WORD wHeight; // Divide by 2 to get the actual height.
WORD wPlanes;
WORD wBitCount;
DWORD dwBytesInImage;
WORD wID;
}
CURDIRENTRY;

Most of the directory entry's fields present values for interpreting the image data. The wID field provides an integer ID that the utility program uses to find the appropriate RT_CURSOR resource, which stores the actual cursor image in the resource data. The Name field in the only IMAGE_RESOURCE_DIRECTORY_ENTRY for this resource's instance resource directory stores the cursor image's ID.

RT_CURSOR describes a single cursor image's resource data as a two-byte x hotspot value, followed by a two-byte y hotspot value. A BITMAPINFOHEADER structure followed by a color table comes next -- I've yet to encounter a cursor image with 24-bit color. The resource data next stores the image's XOR bitmap followed by its AND bitmap. These two bitmaps are used together to support transparency.

To recreate the .cur file, the utility program first writes the values that are stored in the CURHEADER structure, located at the beginning of RT_GROUP_CURSOR's resource data, to the file. The program then converts each of the CURDIRENTRY structures and associated hotspot values to an equivalent CURSORDIRENTRY structure:

typedef struct
{
BYTE bWidth;
BYTE bHeight; // Set to CURDIRENTRY.wHeight/2.
BYTE bColorCount;
BYTE bReserved;
WORD wHotspotX;
WORD wHotspotY;
DWORD dwBytesInImage;
DWORD dwImageOffset; // Offset from start of header to the image
}
CURSORDIRENTRY;

After calculating the offset to a cursor image and assigning this value to the dwImageOffset field in the associated CURSORDIRENTRY structure, the utility program writes the CURSORDIRENTRY structure to the .cur file. After writing these structures, it writes all of the cursor images' resource data areas (without their hotspot fields) to the file.

RT_GROUP_ICON and RT_ICON

Icons are organized similarly to cursors. A resource script statement for an icon resource (MyIcon ICON "myicon.ico", for example) is described in a PE file via RT_GROUP_ICON and RT_ICON resource types. Although there are many similarities between icon and cursor resources, there are also differences, beginning with the following structures:

typedef struct
{
WORD wReserved; // Always 0
WORD wResID; // Always 1
WORD wNumImages; // Number of icon images/directory entries
}
ICOHEADER;

typedef struct
{
BYTE bWidth;
BYTE bHeight;
BYTE bColors;
BYTE bReserved;
WORD wPlanes;
WORD wBitCount;
DWORD dwBytesInImage;
WORD wID;
}
ICODIRENTRY;

As with .cur files, the header appears at the beginning of .ico files, but with 1 as its resource ID. Also, the ICODIRENTRY structure differs from its CURDIRENTRY structure counterpart in terms of new fields (bColors and bReserved) and field sizes (BYTE instead of WORD for the width and height fields).

RT_ICON is similar to RT_CURSOR in that it stores a single image, but without hotspot information. The resource data typically begins with a BITMAPINFOHEADER structure, often followed by a color table, followed by XOR and AND structures. However, if the image is specified via the Portable Network Graphics format, the image's resource data consists entirely of PNG information.

To recreate the .ico file, the utility program first writes the values that are stored in the ICOHEADER structure, located at the beginning of RT_GROUP_ICON's resource data, to the file. The program then converts each of the ICODIRENTRY structures to an equivalent ICONDIRENTRY structure:

typedef struct
{
BYTE bWidth;
BYTE bHeight;
BYTE bColorCount;
BYTE bReserved;
WORD wPlanes;
WORD wBitCount;
DWORD dwBytesInImage;
DWORD dwImageOffset; // Offset from start of header to the image
}
ICONDIRENTRY;

After calculating the offset to an icon image and assigning this value to the dwImageOffset field in the associated ICONDIRENTRY structure, the utility program writes the ICONDIRENTRY structure to the .ico file. After writing these structures, it writes all of the icon images' resource data areas to the file.

Note
To explore additional resource data formats, check out Floyd Rogers (somewhat dated) article Win32 Binary Resource Formats.



 
 
>>> More Microsoft Architecture Articles          >>> More By Jeff Friesen