Virtual Developer Workshop: Containerized Development with Docker

Download Source Code and Example

Click here for larger image

Environment: VC6 95/98/Me/NT/2000/XP


I personally find the Win32 Resource API to be overly complex for performing simple operations such as enumerating and copying resources. Some operations like deleting resources is even missing from the standard Win32 API set. The classes presented in this article provides a simple interface for enumerating, adding and removing resources from Win32 image files (.dll/.exe).

Understanding Win32 Resources

This section gives you a conceptual overview of the Win32 resource layout. We will not go into details about the format of the .rsrc section here.

The diagram above shows an example of a conceptual view of the Win32 resource tree. Each resource instance (leaf-level) contains the following attributes:

Type cursors, dialogs, bitmaps, etc
Name a Unicode string or a 2-byte numeric identifier
Language a 2-byte numeric value indicating the language of the resource instance. E.g., English (U.S.) = 1033, Chinese (Traditional) = 1028
Data the actual data of the resource (e.g. a bitmap image)

These resource instances live in a Win32 image file as a tree structure. Top level of the tree hosts the resource types. For each resource type, there can be multiple resources with the same name, but different language IDs. Those are organized at the 2nd and 3rd levels of the resource tree. At the leaf-level is the actual resource data itself.

The Win32 Resource API

Windows NT (Yes, and I mean only NT/2000/XP. Windows 95/98/Me do not support these APIs. To get cross-platform functionality, check out the Geeworks Win32 Resource Library) provides some useful APIs for modifying resources in Win32 image files. For instance, to copy resources from one image file to another involves the following step:

1. Set up a recursive loop (using EnumResourceTypes, EnumResourceNames, EnumResourceLanguages) to navigate the resource tree of the source image file and collect the resource attributes.
2. Use BeginUpdateResource to open the destination iamge file (not supported on Win9x).
3. Load resource data into memory using FindResource and LoadResource (partially supported on Win9x).
4. Copy the resource data using UpdateResource (again, not supported on Win9x).
5. Close the destination image file to write the changes to the destination image file.

Not only are they overly complicated, they are not even supported on Win9x platforms. Details see Microsoft KB article Q271442 and documentation for BeginUpdateResource(), UpdateResource(), or EditUpdateResource().

The Win32 Resource API C++ Wrapper

Two C++ classes are presented here for manipulating Win32 resources. CWin32ResourceSrc encapsulates a read-only source for resource copying. It provides a simple, non-recursive interface for resource enumeration. CWin32ResourceDest provides functions for adding and removing resources from a Win32 image file.



Open a Win32 image file for resource enumeration.

BOOL Close();

Close an opened image file.

BOOL EnumTypes(RSRC_TYPE_ARRAY & Array);

Returns all the types in a RSRC_TYPE_ARRAY which is defined as a LPCTSTR vector. The caller of the function passes in a RSRC_TYPE_ARRAY and is also responsible for cleaning up the array with EmptyIdArray when done using the array.


Returns all the names for a particular type in a RSRC_NAME_ARRAY which is defined as a LPCTSTR vector. The caller of the function passes in a RSRC_NAME_ARRAY and is also responsible for cleaning up the array with EmptyIdArray when done using the array.


Returns all the language IDs for a particular resource with the given type and name in a RSRC_LANG_ARRAY which is defined as a WORD vector . The caller of the function passes in a RSRC_LANG_ARRAY. This array does not require cleanup.


BOOL Open(LPCTSTR Image, BOOL bDeleteExistingResources = FALSE);

Open a Win32 image file for resource editing. bDeleteExistingResources specifies whether to delete the pFileName parameter's existing resources.

BOOL Close(BOOL DiscardChanges);

Close an opened image file. fDiscard specifies whether to write resource updates to an executable file.

BOOL Add(CWin32ResourceSrc & Resource, LPCTSTR lpType, LPCTSTR lpName, WORD wLang);

Takes a CWin32ResourceSrc as a parameter, the Add function copies the resource specified by lpType, lpName and wLang from Resource. Resource must be a reference to an opened CWin32ResourceSrc.

BOOL Del(LPCTSTR lpType, LPCTSTR lpName, WORD wLang);

As the name implies, the Del function allows you to delete resources from an image file. This function requires Geeworks Win32 Resource Library.


See how simple it can be to copy Win32 resources...

void CopyResources(LPCTSTR Source, LPCTSTR Dest)


    CWin32ResourceSrc src;

    CWin32ResourceDest dest;


    if (!src.Open(Source))  // open the source file for resource enumeration


        HandleError("unable to open source file for copying\n");




    if (!dest.Open(Dest)) // open the target file for resource copying


        HandleError("unable to open destination file for copying\n");




    RSRC_TYPE_ARRAY types;

    src.EnumTypes(types);   // get a list of all the types


    // go through each type in the source image file

    for (RSRC_TYPE_ITOR iType = types.begin(); iType != types.end(); iType++)


        RSRC_NAME_ARRAY names;


        // get a list of names for the particular type

        src.EnumNames(*iType, names);


        // go through each name within this type

        for (RSRC_NAME_ITOR iName = names.begin(); iName != names.end(); iName++)


            RSRC_LANG_ARRAY langs;


            // get a list of all the language IDs

            src.EnumLangs(*iType, *iName, langs);


            // go through each lang ID

            for (RSRC_LANG_ITOR iLang = langs.begin(); iLang != langs.end(); iLang++)


                LPCTSTR type = *iType;

                LPCTSTR name = *iName;

                WORD lang = *iLang;


                // Add each resource instance with a particular lang ID

                dest.Add(src, type, name, lang);




        // clean up the names array




    // clean up the types array







Download - 11 Kb


  • Resources can be deleted

    Posted by Legacy on 09/17/2003 07:00am

    Originally posted by: David

    UpdateResource() can delete resources if the fifth parameter is NULL, so I'm not quite sure what you meant by "Some operations like deleting resources is even missing from the standard Win32 API set."

  • Look

    Posted by Legacy on 06/25/2003 07:00am

    Originally posted by: LiLiang


  • Alternative to Geeworks???

    Posted by Legacy on 10/03/2002 07:00am

    Originally posted by: Nikko

    Does anyone has an alternate solution (cheaper) to use update resources in EXE??

  • UpdateResource() on win9x ...problem seems to be solved by MS with MSLU project

    Posted by Legacy on 08/06/2002 07:00am

    Originally posted by: Christi G

    At this moment the function have some bugs but ...let's hope a fix will be done soon :)
    ..so...GeeWorks bye bye... ;p


  • Geeworks Outrage

    Posted by Legacy on 07/22/2002 07:00am

    Originally posted by: Matthew Bonner

    I am bitterly disappointed by Geeworks making their Win32 Resource Library available only at a ridiculous cost.
    Surely implementing the UpdateResource() and other functions can't be _that_ hard. Hell, Angus Johnsonn didn't pay hundreds of dollars to create his Resource Hacker utility. Maybe Angus could offer us a cheaper alternative to Geeworks...

  • Alrite

    Posted by Legacy on 12/14/2001 08:00am

    Originally posted by: Alrite!

    Alrite man!
    you are da best!


  • Compilation Instructions

    Posted by Legacy on 11/02/2001 08:00am

    Originally posted by: Peter Chiu

    You need to download the latest Platform SDK headers from Microsoft that contains the definition of the resource-related macros such as IS_INTRESOURCE. You also need to write your own HandleError function (or remove it, or define it as _tprintf). Alternatively, you can download the complete VC6 demo project included with this article.


  • Error

    Posted by Legacy on 11/01/2001 08:00am

    Originally posted by: Sikander Rafiq

    It can't compile.

  • How to get this to work for NT, MSVC6

    Posted by Legacy on 11/01/2001 08:00am

    Originally posted by: Larry Leonard

    First, add these two lines to the bottom of STDAFX.H, right after the "using namespace std":

    #define ULONG_PTR unsigned long
    #define IS_INTRESOURCE(_r) (((ULONG_PTR)(_r) >> 16) == 0)

    Second, at the top of NTCOPYRES.CPP, you'll see this line:

    #define HandleError _tprintf

    Comment that line out, and add this line:

    #define HandleError TRACE

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date