Win32 Resource File Format
by Marco Cocco, of d3k - The Artisan Of Ware, Italy

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

ヘッダ構造は以下のようになってます。

Offset Field Data type Description
0 DataSize DWORD
4 bytes, 32 bit unsigned integer
ヘッダに続くデータ部のサイズです。(パディングバイトを含みません)
4 HeaderSize DWORD
4 bytes, 32 bit unsigned integer
ヘッダ部のサイズです。
8 ResType Ordinal or UNICODE string
Array of 16 bit unsigned integers (2 bytes each)
リソースタイプ(ID)です。(標準ウィンドウリソース or カスタム)
OfsOf(ResType)+SizeOf(ResType)+Padding
このパディングはなくてもOK。
ResName Ordinal or UNICODE string
Array of 16 bit unsigned integers (2 bytes each)
リソース名です。
OfsOf(ResName)+SizeOf(ResName)+Padding
ここはもちろん必要。
DataVersion DWORD
4 bytes, 32 bit unsigned integer
現在使われてません。常に0です。
OfsOf(DataVersion)+4 MemoryFlags WORD
2 bytes, 16 bit unsigned integer
リソースの状態(?)です。
OfsOf(MemoryFlags)+2 LanguageID WORD
2 bytes, 16 bit unsigned integer
どこの国の言葉で(リソースが)書かれているかを表します。
OfsOf(LanguageID)+2 Version DWORD
4 bytes, 32 bit unsigned integer
意味を持たないフィールドです。リソースエディタで使われます。常に0です。
OfsOf(Version)+4 Characteristics DWORD
4 bytes, 32 bit unsigned integer
意味を持たないフィールドです。リソースエディタで使われます。常に0です。

- リソースヘッダは固定長ではありません。ヘッダの読み書きは、1度に行う必要があります。
- リソースヘッダは常に4バイト境界から始まります。
- RESファイルを読みこむ処理では、現在のファイルポインタが4バイト境界にないとき、ファイルポインタを4バイト境界に合わせる必要があります。
- RESファイルを書きこむ処理では、現在のファイルポインタが4バイト境界にないとき、パディングバイトで次の4バイト境界まで埋める必要があります。
- DataSizeとHeaderSizeを合わせたフィールドは8バイト固定。DataVersion以下のフィールドも16バイト固定長。
- ResTypeとResNameは可変長で、ResNameの終わりが4バイトアラインに沿ってないときは、パディングが必要。
- DataSizeは、純粋なデータサイズ。この値を使って次のリソースの先頭を求めることができるが・・・ヘッダの先頭+HeaderSize+DataSizeという式は誤り。 正しい計算は4バイトアラインを考慮して、ヘッダの先頭+HeaderSize+(DataSize+パディング)とやる。
- パディングが加えられた値( = 4バイトアラインされた値)を求める方法は・・
ex1) AlDataSize := (DataSize+3) div 4 * 4; // DataSizeを4バイトアライン
ex2) AlDataSize := ((DataSize+3) shr 2) shl 2; // DataSizeを4バイトアライン(高速化されてる?)

More about the resource header fields:

Field Additional information
DataSize
データサイズ
ヘッダに続くデータ部のサイズです。この値は純粋なデータサイズです。パディングバイトを加えた値ではありません。φ(..)メモメモ
データ部の形式は、リソースの種類によって異なります。DataSizeは、バイト数で表されます。
HeaderSize
ヘッダサイズ
ヘッダ部のサイズです。この値は、DataSizeとHeaderSizeのフィールドも含んでいます。
HeaderSizeはバイト数で表されます。ヘッダ部に続くリソースデータの先頭位置を求めるために使えます。(ヘッダ部の先頭番地 + HeaderSize)

「Win32 SDK」には、誤って「HeaderSizeフィールドは、この後に続く ヘッダ部のサイズを意味します」と書かれてますが、正しくは「HeaderSizeフィールドは、DataSizeとHeaderSizeを含む ヘッダ部それ自身 のサイズ」です。
ResType
リソースタイプ
リソースタイプを指定します。(整数値あるいは、英数字です。)
"The ResType field" も要参照
ResName
リソース名
リソース名を指定します。(整数値あるいは、英数字です。)
"The ResName field" も要参照
DataVersion
データバージョン
将来の拡張用に予約されたフィールドです。常に0です。
MemoryFlags
メモリーフラグ
リソースの状態を示すフラグを管理します。
"The MemoryFlags field" も要参照
LanguageID
ラングID
どの国の言葉で書かれているのかを指定します。異なる値を用意することで、1つのリソースファイルに複数の国の言葉のリソースを含めることが出来ます。アプリケーションは、(起動環境の)マシンの言語を調べ、使用するリソースを選択することができます。
ちなみにWindows 日本語版の場合は、0x411
"Language IDs" も要参照。
Version
バージョン
互換性のためだけに存在するフィールドです。リンクしても実行ファイルへは組み込まれません。
Characteristics
キャラクタリスティック
互換性のためだけに存在するフィールドです。リンクしても実行ファイルへは組み込まれません。

The ResType field

ResTypeは次のいずれかです。

# Description
1) ResType は、常に4バイトです。最初の2バイトが0xFFFFで、続く2バイトがリソースタイプを示すIDです。
ResTypeフィールドは、システムで定義されたリソース(メニュー、ダイアログ、アイコン・・)のために使用されます。リソースタイプを新たに定義することもできます。 もし、リソースタイプを新たに定義したい場合は、標準リソース用として既に予約されたIDと同じ値を使ってはいけません。 (0x8000以上の値を使うことをオススメします。). より良い方法は、整数値のIDを新たに定義しないことです。

既に定義されている標準のリソースタイプ:

0x0001 = Cursor 0x0002 = Bitmap 0x0003 = Icon 0x0004 = Menu 0x0005 = Dialog 0x0006 = String Table 0x0007 = Font Directory 0x0008 = Font 0x0009 = Accelerators Table 0x000A = RC Data (custom binary data) 0x000B = Message table 0x000C = Group Cursor 0x000E = Group Icon 0x0010 = Version Information 0x0011 = Dialog Include 0x0013 = Plug'n'Play 0x0014 = VXD 0x0015 = Animated Cursor 0x2002 = Bitmap (new version) 0x2004 = Menu (new version) 0x2005 = Dialog (new version)
2) ResType の最初の2バイトが 0xFFFF でなく、ユニコード(文字列)で始まります。
終端は、NULL(0x0000 WORD)です。4バイトアラインに満たないときは、ResName フィールドまで、NULLで埋めます。
例)JPEGの場合'4A005000450047000000'な感じになる
マイクロソフトのドキュメントには、ResType ResName の間をパディングしなくても良いと記述されてます。
ちなみに、ボーランドリソースコンパイラBRCCは、パディングしない模様。

The ResName field

ResNameは次のいずれかです。:

# Description
1) ResName は、常に4バイトです。最初の2バイトが0xFFFFで、続く2バイトがリソース名を示すIDです。 (0xFFFF WORD + ID WORD)
常に4バイトなので、パディングは必要ありません。

注意:文字列テーブルのリソースは、ユニコード文字列を使ってはいけません。IDの名前は整数でなくてはいけません。
2) ResName の最初の2バイトが 0xFFFF でなく、ユニコード(文字列)で始まります。
終端は、NULL(0x0000 WORD)です。4バイトアラインに満たないときは、DataVersion フィールドまで、NULLで埋めます。

注意:文字列テーブルのリソースは、ユニコード文字列を使ってはいけません。IDの名前は整数でなくてはいけません。

The MemoryFlags field

MemoryFlags は、リソースの状態を示すフラグを含みます。

このフィールドは、"bit set"です。それぞれのビットが異なる意味を持ちます。
Bit mask Description
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.
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).
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.
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.
- BRCCで作成、解析に使ったRESは・・4,5bitが立った0030、4,10bitが立った1010。メモリーフラッグにそれ以外の値をもつRESをまだ見ていない。

Notice:
WinNT ignores the setting of the MOVEABLE, IMPURE, and PRELOAD flags.

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).



Win32 Resource Format Guide v1.0 - Released on October 27th, 1997