PRB: Large Resources Cause Resource Corruption on Windows (182819)
The information in this article applies to:
- Microsoft Platform Software Development Kit (SDK) 1.0, when used with:
This article was previously published under Q182819 SYMPTOMS
If you add a large resource (greater than or equal to 64K in size) to a
Win32 module and you attempt to access any resource in the image from 16-
bit code under Windows 95 or Windows 98, the resource might get truncated.
Since large sections of the Windows 95 or Windows 98 user interface
manager (USER) are implemented in 16-bit code for compatibility reasons,
resource-loading functions such as LoadImage might fail or return corrupted
resources. Your access to resources from 32-bit code are not affected.
CAUSE
When a 32-bit module is loaded into memory, Windows 95 and Windows 98
create a 16-bit version of the resources in the 32-bit module so that the
resources can be accessed from 16-bit code. The "size" field of a 16-bit
resource is only a 16-bit integer. Consequently, resources larger than 64K
require special treatment.
To accommodate large resources, the file format for 16-bit modules allows
you to apply a file-wide scaling factor to resource sizes. This scaling
factor is applied to the reported sizes of all resources.
For example, suppose a module contained three resources as follows:
Resource 1 = size 15 bytes
Resource 2 = size 66123 bytes
Resource 3 = size 191231 bytes
Since Resources 2 and 3 are larger than 64K, their sizes cannot be reported
as a 16-bit integer. In the conversion of this resource table to a 16-bit
resource table, Windows 95 selects a scaling factor of 4 (scaling factors
must be a power of two) resulting in the following adjusted resource sizes:
Resource 1 = 15 bytes / 4 = 3 scaled bytes
Resource 2 = 66123 bytes / 4 = 16530 scaled bytes
Resource 3 = 191231 bytes / 4 = 47802 scaled bytes
where one scaled byte equals four real bytes. Notice that the scaled sizes
are now all less than 65536 scaled bytes, and, therefore, can be reported
as a 16-bit integer.
Also notice that due to truncation in the division, converting the number
of scaled bytes back to the number of actual bytes results in some loss of
data. For example, the size of Resource 1 is recorded as 3 scaled bytes,
which is equal to 3 * 4 = 12 real bytes (three bytes less than its original
size of 15 bytes). Consequently, if you attempt to access Resource 1 from
16-bit code you will lose three bytes of data.
Observe that the original 32-bit resources are not damaged by the
conversion process. The truncation occurs only to the 16-bit resources.
Consequently, if the resources are accessed by 32-bit code, truncation does
not occur. In particular, the 32-bit versions of FindResource,
LockResource, and SizeofResource are not affected.
Since the 32-bit version of LoadString is implemented entirely in 32-bit
code, LoadString is not affected by this problem.
RESOLUTION
Following are two methods of working around this problem.
Method 1
Since the original 32-bit resources are not damaged, use those resources
instead of the 16-bit resources. For example, to avoid a truncated dialog
box, change the following code:
DialogBox(hInstance, lpTemplate, hwndParent, DialogProc);
// Error checking deleted for expository purposes.
HRSRC hrsrc = FindResource(hInstance, lpTemplate, RT_DIALOG);
LPCDIALOGTEMPLATE lpDlgTemplate = LoadResource(hInstance, hrsrc);
DialogBoxIndirect(hInstance, lpDlgTemplate, hwndParent, DialogProc);
Method 2
Artificially pad the resources so that the truncation performed by Windows
95 does not result in the loss of significant data. This can be performed
after-the-fact by the FixRes95 tool (see the MORE INFORMATION section of
this article to see how to obtain this tool). Note that since FixRes95 uses
the UpdateResource APIs to modify the 32-bit image, it requires Windows NT
to run. (The requirement for Windows NT applies only to the conversion
program itself and not to the image file being converted.)
The FixRes95 tool is a console application that works off of command line
parameters. To use FixRes95, use the following command line:
fixres95 [-a] <module name>
The -a is optional and, if specified, will force all resources to be
updated.
The <module name> is the path and file name of the module whose resources
will be updated.
STATUS
Microsoft has confirmed this to be a problem in the Microsoft products
listed at the beginning of this article.
| Modification Type: | Minor | Last Reviewed: | 7/11/2005 |
|---|
| Keywords: | kbdownload kbfile kbprb kbResource KB182819 |
|---|
|