Resources

Commands related to Windows file resources

SYNOPSIS

package require twapi
begin_resource_update MODULEPATH ?-deleteall?
delete_resource HMODULE RESTYPE RESNAME LANGID
end_resource_update HMODULE ?-discard?
enumerate_resource_languages HMODULE RESTYPE RESNAME
enumerate_resource_names HMODULE RESTYPE
enumerate_resource_types HMODULE
read_resource HMODULE RESTYPE RESNAME LANGID
read_resource_string HMODULE STRINGID LANGID
resource_stringblock_to_strings BINDATA
resource_stringid_to_stringblockid STRINGID
strings_to_resource_stringblock STRINGS
update_resource HMODULE RESTYPE RESNAME LANGID RESDATA

DESCRIPTION

Windows resources are binary data that can be added to executable files. Examples include icons, strings and fonts. This module provides commands related to manipulation of these resources.

Windows Resources

Resources are stored in Portable Executable format files (exe's and dll's). A resource has an associated name, type and a language. The name and type can be either integer values or strings. To retrieve a particular resource, you must know both the associated values, the type and the name, for that resource. When a resource type or name is a string, it must be explicitly enclosed in quotes. For example,

::twapi::read_resource $h 14 {"ICON3"} 0

and not

::twapi::read_resource $h 14 "ICON3" 0

or

::twapi::read_resource $h 14 ICON3 0

To support localization, there can be several resources with the same type and name, but associated with different languages. These languages are identified by a 16 bit language identifier (LANGID) as described in the TWAPI Internationalization documentation.

TWAPI provides commands to retrieve and update resources as binary data. It does not provide any functionality related to constructing the actual binary data itself. Each resource type has a specific structure and it is up to the application to construct it appropriately.

Resource Types

Windows defines certain standard resource types shown in the table below along with the corresponding #define values from the SDK.

1 RT_CURSOR - Cursor
2 RT_BITMAP - Bitmap
3 RT_ICON - Icon
4 RT_MENU - Menu
5 RT_DIALOG - Dialog
6 RT_STRING - String (see String Resources)
7 RT_FONTDIR - Font directory
8 RT_FONT - Font
9 RT_ACCELERATOR - Accelerator
10 RT_RCDATA - Application defined raw data
11 RT_MESSAGETABLE - Message table
12 RT_GROUP_CURSOR - Hardware independent cursor
14 RT_GROUP_ICON - Hardware independent icon
16 RT_VERSION - Version
17 RT_DLGINCLUDE - Name of C include file containing corresponding symbolic names of resources
19 RT_PLUGPLAY - Plug and play
20 RT_VXD - Vxd
21 RT_ANICURSOR - Animated cursor
22 RT_ANIICON - Animated icon
23 RT_HTML - HTML
24 RT_MANIFEST - Executable Manifest

Locating and Loading Resources

Manipulating a resource requires a Windows executable module handle for the corresponding executable file. The commands will accept NULL or 0 for this handle corresponding the the main executable for the process. To retrieve resources in other executables or DLL's, the module must be first loaded through the load_library call. Generally, the -datafile option should be passed to the load_library command if the only purpose is to access or update resources.

When the resources in a module are no longer required, it must be released through free_library call.

Once the module is loaded, the content of a particular resource can be retrieved using read_resource and read_resource_string.

You can also enumerate resources present in a module using the enumerate_resource_types enumerate_resource_names enumerate_resource_languages commands.

Note that resources themselves do not need to be explicitly freed up. In particular, do not try to close the resource handles through the CloseHandle or close_handles.

Updating Resources

Updating a resource in a file requires that the file not be in use by any application (including the current process). The begin_resource_update command prepares the file for update. One or more update_resource commands can be used to modify the resources in the file and delete_resource commands can be used to delete resources. Finally, the the end_resource_update command is used to commit or discard the modifications.

String Resources

Strings defined through a string table definition in a resource definition file are not directly stored in the resource binary. They are stored in string blocks, each containing 16 strings. It is therefore not possible to directly retrieve or update a string based on its string id.

If you call read_resource with a resource type of 6 (STRING), the resource name or id has to actually be the id of the string block, not the string. The command resource_stringid_to_stringblockid will take a string id and return a pair consisting of the id of the corresponding block and the index of the string within the block. The block id can be passed to read_resource to read the string block. Since this is in binary format, it needs to be converted into a list of strings using resource_stringblock_to_strings. The string index returned from resource_stringid_to_stringblockid can be used to then pick out the appropriate string from the this list.

If you are only interested in a single string, the command read_resource_string encapsulates this entire process.

Updating strings in a resource involves multiple steps for the same reason. First, the string block has to be retrieved and converted to a list of strings as described above. The list must then be modified as desired and converted back to a string block using strings_to_resource_stringblock and then written out using update_resource.

Deleting a string resource is similar. Once the list of strings in the appropriate block is retrieved, set the corresponding element in the list to an empty string before writing it back using update_resource.

A peculiarity in the storage format for resource strings means it is not always possible to distinguish between a resource string that is not defined and a resource string that is defined with an empty value. An attempt to read an undefined resource string may either result in an error being generated, or in the return of an empty string.

Commands

begin_resource_update MODULEPATH ?-deleteall?
Returns a handle to the file MODULEPATH to be updated. The returned handle must be closed through the end_resource_update command. If the option -deleteall is specified, all existing resources in the file are deleted.
delete_resource HMODULE RESTYPE RESNAME LANGID
Deletes a resource from the specified module HMODULE which must be a handle previously retrieved via begin_resource_update. The resource is not actually deleted from the file until the end_resource_update command is called.
end_resource_update HMODULE ?-discard?
Closes a handle previously returned by the begin_resource_update command. Any modifications made through update_resource are written to the file unless the -discard option is specified in which case they are discarded.
enumerate_resource_languages HMODULE RESTYPE RESNAME
Returns a list of language identifiers for which the specified module contains a resource of type RESTYPE with name RESNAME. HMODULE must be a handle previously retrieved via load_library.
enumerate_resource_names HMODULE RESTYPE
Returns a list of the names of resources of type RESTYPE in the specified module. HMODULE must be a handle previously retrieved via load_library.
enumerate_resource_types HMODULE
Returns a list of the types of resources in the specified module. HMODULE must be a handle previously retrieved via load_library.
read_resource HMODULE RESTYPE RESNAME LANGID
Returns the content of a resource from the specified module HMODULE which must be a handle previously retrieved via load_library.

Note that If RESTYPE is 6, specifying a STRING resource, RESTYPE is the id for a string block, not an individual string. The returned value is the binary data corresponding to the string block. To retrieve individual strings, use the read_resource_string command.
read_resource_string HMODULE STRINGID LANGID
Returns the string in the resource table for the module specified by HMODULE which must be a handle previously retrieved via load_library.

Because of the storage format used in string resources, it is not always possible to distinguish between a resource string that is not defined and a resource string that is defined with an empty value. An attempt to read an undefined resource string may either result in an error being generated, or in the return of an empty string.
resource_stringblock_to_strings BINDATA
Converts a binary resource string block to a list of strings. As every string block contains 16 strings, the returned list as exactly 16 strings.
resource_stringid_to_stringblockid STRINGID
Maps a string resource id to a list containing the id of the corresponding string block in the resource and the index of the string within the block as described in String Resources.
strings_to_resource_stringblock STRINGS
Converts the list of strings in STRINGS to a binary resource string block that can be passed to update_resource. The number of strings in STRINGS must not be more than 16 which is the number stored in a single resource string block. If fewer than 16 strings are provided, they are stored as empty strings.
update_resource HMODULE RESTYPE RESNAME LANGID RESDATA
Updates a resource from the specified module HMODULE which must be a handle previously retrieved via begin_resource_update. RESDATA should be the raw binary data for the resource in the type-specific format.

The resource is not actually written out to the file until the end_resource_update command is called.

COPYRIGHT

Copyright © 2010 Ashok P. Nadkarni

Tcl Windows API 3.0.29 Privacy policy