INTRODUCTION
Preface
Welcome to the Win32 Resource File Format reference guide !
This document is a guide to reading/writing Windows 95 and Windows NT resource files (RES extension).
This guide has been written by M.Cocco (of d3k - The Artisan Of Ware, Italy) while developing the
MakeRes Resource Editor, a tool of the "Photoshop Plug-in Toolkit" for Delphi 2.0.
Copyright (c) 1997, Marco Cocco. All rights reserved.
Copyright (c) 1997, d3k - The Artisan Of Ware. All rights reserved.
Audience
This guide is for any programmers who have written applications for Windows systems and wish to understand how to work with standalone binary resource file (RES files, not in-EXE resources).
This guide assumes you are proficient in the Windows programming and have worked in any development environments such as Borland Delphi 2.0,
Borland Delphi 3.0, Borland C++ Builder, Microsoft Visual C++ (on Windows 95 or Windows NT).
You should have a working knowledge of the different resource types, and understand how handle binary files. This guide assumes you understand terminology
such as records (structures), WORD and DWORD types, strings (ANSI and UNICODE), record (structure) alignment, etc.
Remarks
This documentation is made to provide specific information on implementation and structuring issues for Win32 resource files only. Win16 resource files
are not explained in this guide.
The best way to use this guide is to read it all without skipping any chapter.
Should you have any question, feel free to contact the author.
GETTING STARTED
This document details the structure of the resource binary file (.RES) format for Win32 platforms (W95 and WNT).
The structure is very similar to the existing Win16 (W3/W3.1/3.11) structure, but it supports some new data types and data structures.
One important enhancement is the DWORD/WORD alignment of structures/fields which increases performance of new 32 bit microprocessors but
makes resource reading/writing a bit more complex (structures are of dynamic size). The order of the fields of resource data structures is not changed due to alignment,
but some padding is required between fields.
The Win32 resource file contains one or more binary resources merged in a single file and aligned on DWORD boundaries. Each resource has its own
header structure followed by resource data. Immediately after the resource data comes the header for the next resource followed by resource data, and so on.
To read/write resource files you must have knowledge of binary files handling. Resource files cannot be read using text mode file routines.
THE RESOURCE HEADER
The structure of the header is as follows:
Offset | Field | Data type | Description |
0 | DataSize |
DWORD 4 bytes, 32 bit unsigned integer |
The size of the data that follows the header (not including any padding). |
4 | HeaderSize |
DWORD 4 bytes, 32 bit unsigned integer |
The size of the header structure. |
8 | ResType |
Ordinal or UNICODE string Array of 16 bit unsigned integers (2 bytes each) |
Resource Type ID (standard or custom). |
OfsOf(ResType)+SizeOf(ResType)+Padding | ResName |
Ordinal or UNICODE string Array of 16 bit unsigned integers (2 bytes each) |
Resource name. |
OfsOf(ResName)+SizeOf(ResName)+Padding | DataVersion |
DWORD 4 bytes, 32 bit unsigned integer |
Determines the format of the information within the resource header that follows. Not currently used. Should be zeroed. |
OfsOf(DataVersion)+4 | MemoryFlags |
WORD 2 bytes, 16 bit unsigned integer |
The state of the resource. |
OfsOf(MemoryFlags)+2 | LanguageID |
WORD 2 bytes, 16 bit unsigned integer |
The language that the strings are written with. |
OfsOf(LanguageID)+2 | Version |
DWORD 4 bytes, 32 bit unsigned integer |
It has no significance to the system. Used by resource editors. Usually zeroed. |
OfsOf(Version)+4 | Characteristics |
DWORD 4 bytes, 32 bit unsigned integer |
It has no significance to the system. Used by resource editors. Usually zeroed. |
Field | Additional information |
DataSize |
The size of the data that follows the header. This value does not include any file padding bytes added after the actual data. The format of the data is different for any of the possible resource types. Data size is expressed in BYTEs (8 bit unsigned integer). |
HeaderSize |
The size of the resource header structure. This value includes the size of the DataSize and HeaderSize fields. The value of HeaderSize is expressed in BYTEs and can be used to seek directly to resource data following the resource header (seek to FilePos(DataSize) + HeaderSize). The Win32 SDK wrongly says: "The HeaderSize field gives the size of the resource header structure that follows". This should be read: "The HeaderSize field gives the size of the resource header structure, including the DataSize field and the HeaderSize field itself". |
ResType |
Specifies the resource type (its integer code or its alphabetic name). Further explanation of this field can be found in "The ResType field" chapter. |
ResName |
Specifies the name of resource (its integer name-code or its alphabetic name). Further explanation of this field can be found in "The ResName field" chapter. |
DataVersion |
Determines the format of the information within the resource header that follows. Reserved for future expansion. This field is always zeroed but is supposed to change on next version of Win32. Resource editors should check this field and maintan unchaged the resource data if the format is not supported. |
MemoryFlags |
Contains flags about the state of the resource. Further explanation of this field can be found in "The MemoryFlags field" chapter. |
LanguageID |
Specifies the language that the strings are written. By providing different values for this field it is possible to store different
language versions of the same resource. The application can then choose the set of resources to load based on the currently system language. Further explanation of this field can be found in "Language IDs" chapter. |
Version |
This field can be used to store custom version information. This lets resource editors to keep backward compatibility
whith other version of the same resource editor. This value is stripped out when the resource is linked to the application executable file. |
Characteristics |
Like the Version field, this field can be used to store custom information flags. This value is stripped out when the resource is linked to the application executable file. |
The ResType field
The ResType field can either be:
# | Description |
1) | The first WORD of the ResType field is 0xFFFF and the second WORD contains the resource type ID. The ResType field is always 4 bytes long (0xFFFF WORD + ID WORD), thus it doesn't require any padding for DWORD boundary alignment. This kind of ResType field is used for system defined resources (menu, dialogs, icons,...) but is can also be used for custom resource types. If you are going to use this kind of ResType for your custom resources, be sure to use ID values not already reserved for standard resources (I suggest you using IDs greater than 0x8000 or like). Or better: never use non numeric IDs for your custom resources. All standard Windows resource types have been assigned numeric IDs as follows: |
2) |
The first WORD of the ResType field is not 0xFFFF. The ResType field is an array of UNICODE characters (a string) terminated by a NULL (0x0000 WORD). An additional WORD may be inserted after the terminating NULL to make next field (ResName) start on a DWORD boundary. CORRECTION: From Microsoft's documentation: You do not need to add padding for DWORD alignment between the TYPE and NAME members because they contain WORD data. However, you may need to add a WORD of padding after the NAME member to align the rest of the header on DWORD boundaries. If your application is not using the set of UNICODE API calls you have to convert the resource name to ANSI encoding. Standard resources never use this kind of ResType field. |
The ResName field
The ResName field can either be:
# | Description |
1) | The first WORD of the ResName field is 0xFFFF and the second WORD contains the resource name ID. The ResName field is always 4 bytes long (0xFFFF WORD + ID WORD), thus it doesn't require any padding for DWORD boundary alignment. Notice: String Table resources are not allowed to be named using a UNICODE string: they must be have a numeric name ID (case 1). |
2) |
The first WORD of the ResName field is not 0xFFFF. The ResName field is an array of UNICODE characters (a string) terminated by a NULL (0x0000 WORD). An additional WORD may be inserted after the terminating NULL to make next field (DataVersion) start on a DWORD boundary. If your application is not using the set of UNICODE API calls you have to convert the resource name to ANSI encoding. Notice: String Table resources are not allowed to be named using a UNICODE string: they must be have a numeric name ID (case 1). |
The MemoryFlags field
The MemoryFlags field contains flags about the state of a the resource.
This field is a "bit set", that is, each single bit of its value have a different meaning as follows:
Bit # | Bit mask | Description |
4 | 0x0010 |
If set: the resource is MOVEABLE, that is, the system can move the resource in memory. If not set: the resource is FIXED, that is, the system cannot move the resource in memory. |
5 | 0x0020 |
If set: the resource is PURE, that is, the resource contains DWORD aligned data (padding is not needed). If not set: the resource is IMPURE, that is, the resource contains non DWORD aligned data (padding is needed). |
6 | 0x0040 |
If set: the resource must to be PRELOADed, that is, the resource must be loaded in memory just after the application has been loaded from disk. If not set: the resource must not be PRELOADed, that is, the resource must be loaded in memory only when the application requires it. |
10 | 0x1000 |
If set: the resource is DISCARDABLE, that is, on low memory conditions, the resource can be removed from memory and then reloaded when the application needs it. If not set: the resource isn't DISCARDABLE, that is, on low memory conditions, the resource cannot be removed from memory. |
Language IDs
The LanguageID field, included in each resource header, specifies the language that the strings (of String Tables and Message Tables) are written with.
The system must be informed of the language because it needs to know how to convert characters from UNICODE to ANSI (from double-byte to single-byte characters).
The LanguageID field (found in any resource header) if a 16 bin unsigned integer (WORD) containing not only the language ID but also a sub-language ID. The lower 10 bits
(bits 0-9) of this value contain the LanguageID, remaining bits contain the SubLanguageID (bits 11-15).
The LanguageID specifies the code of the primary language. The SubLanguageID specifies a variation of the primary language (a dialect).