PRB: Large Resources Cause Resource Corruption on Windows 95

Last reviewed: March 20, 1998
Article ID: Q182819
The information in this article applies to:
  • Microsoft Win32 Software Development Kit (SDK) on the following platform:

    - Windows 95

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, the resource might get truncated. Since large sections of the Windows 95 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 creates 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  65123 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 =  65123 bytes / 4 = 16280 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, replace:

    DialogBox(hInstance, lpTemplate, hwndParent, DialogProc);

With:

    // 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

This problem is only present in Windows 95.

MORE INFORMATION

You can use the FixRes95 tool to perform an after-the-fact artificial padding of the resources so that the truncation performed by Windows 95 does not result in the loss of significant data. The following file is available for download from the Microsoft Software Library:

 ~ FixRes.exe (size: 30152 bytes) 
                 Release Date: Mar-20-1998

For more information about downloading files from the Microsoft Software Library, please see the following article in the Microsoft Knowledge Base:

   ARTICLE-ID: Q119591
   TITLE     : How to Obtain Microsoft Support Files from Online Services
Keywords          : UsrRes
Version           : WIN95
Platform          : Win95
Issue type        : kbprb


================================================================================


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: March 20, 1998
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.