NO

Author Topic: Loading individual resources from an RCDATA  (Read 11890 times)

JohnF

  • Guest
Loading individual resources from an RCDATA
« on: April 29, 2005, 11:23:12 AM »
I thought someone may find this useful one day.

A friend and I wrote this a few years ago in Basic. The reason was that the Basic did not create proper dialogs, and we were predisposed to use API calls for most things anyway. So we added all resources into an .RES file and extracted the individual resources with this code.

One just includes an RCDATA in the .RC file and load all resources from the mainres.res

IDR_RCDATA RCDATA "mainres.res"

The code with deal with most common resources, Icon, Cursor, Menu, Dialogs, Bitmap, Accelerators, String.

John

drakoh

  • Guest
Loading individual resources from an RCDATA
« Reply #1 on: April 29, 2005, 03:15:42 PM »
why not ! thx for your contribution !

Gerome

  • Guest
Loading individual resources from an RCDATA
« Reply #2 on: April 29, 2005, 03:49:41 PM »
Hi !

Yeah that sounds nice :)

BTW i thought it was also an RES loader acting onto pure RES files and not compiled and injected ones into an EXE...

But a question came to my mind...
Is it possible to replace a RES file from an EXE and injecting an other one in a simple way ?

That way your tool would become terribly useful for custom RES ready to be replaced into an EXE file :)

Thanks for any reply,

Keep up the good work !

JohnF

  • Guest
Loading individual resources from an RCDATA
« Reply #3 on: April 29, 2005, 04:50:29 PM »
Quote from: "Gerome"
Hi !

Yeah that sounds nice :)

BTW i thought it was also an RES loader acting onto pure RES files and not compiled and injected ones into an EXE...


It would work that way. You mean loading a .RES from disk I assume. The data in a RES file is exactly the same as the data compiled into an EXE.

Just load the chunks from a file, using fread on a RES file. One would need to use fseek a few times.
 
Quote

But a question came to my mind...
Is it possible to replace a RES file from an EXE and injecting an other one in a simple way ?


It would not be difficult although I've not tried it.

Take a look at the resource API's

BeginUpdateResource()
UpdateResource()

Etc.

John

JohnF

  • Guest
Loading individual resources from an RCDATA
« Reply #4 on: April 29, 2005, 04:57:33 PM »
Here is an example of updating an EXE's resource. It's from the PSDK.

Code: [Select]

HRSRC hResLoad;     // handle to loaded resource
HANDLE hExe;        // handle to existing .EXE file
HRSRC hRes;         // handle/ptr. to res. info. in hExe
HANDLE hUpdateRes;  // update resource handle
char *lpResLock;    // pointer to resource data
BOOL result;
// Load the .EXE file that contains the dialog box you want to copy.
hExe = LoadLibrary("hand.exe");
if (hExe == NULL)
{
    ErrorHandler("Could not load exe.");
}
 
// Locate the dialog box resource in the .EXE file.
hRes = FindResource(hExe, "AboutBox", RT_DIALOG);
if (hRes == NULL)
{
    ErrorHandler("Could not locate dialog box.");
}
 
// Load the dialog box into global memory.
hResLoad = LoadResource(hExe, hRes);
if (hResLoad == NULL)
{
    ErrorHandler("Could not load dialog box.");
}
 
// Lock the dialog box into global memory.
lpResLock = LockResource(hResLoad);
if (lpResLock == NULL)
{
    ErrorHandler("Could not lock dialog box.");
}
 
// Open the file to which you want to add the dialog box resource.
hUpdateRes = BeginUpdateResource("foot.exe", FALSE);
if (hUpdateRes == NULL)
{
    ErrorHandler("Could not open file for writing.");
}
 
// Add the dialog box resource to the update list.
result = UpdateResource(hUpdateRes,       // update resource handle
     RT_DIALOG,                   // change dialog box resource
     "AboutBox",                  // dialog box name
     MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),  // neutral language
     lpResLock,                   // ptr to resource info
     SizeofResource(hExe, hRes)); // size of resource info.
if (result == FALSE)
{
    ErrorHandler("Could not add resource.");
}
 
// Write changes to FOOT.EXE and then close it.
if (!EndUpdateResource(hUpdateRes, FALSE))
{
    ErrorHandler("Could not write changes to file.");
}
 
// Clean up.
if (!FreeLibrary(hExe))
{
    ErrorHandler("Could not free executable.");
}



You can delete all resources with BeginUpdateResource() and then add the new ones.

John

Anonymous

  • Guest
Loading individual resources from an RCDATA
« Reply #5 on: April 29, 2005, 05:02:26 PM »
Quote from: "Gerome"
Hi !
But a question came to my mind...
Is it possible to replace a RES file from an EXE and injecting an other one in a simple way ?


Hi Gerome,
This can be done.  However you will run into problems if the resource definitions do not properly match the program code.  For example if you change a menuing system, any part of the menu that is not referenced in the software just becomes wasted space and any part of the menu missing from the file will cause program functions to fail.  If you change the names of things, the program will do something other than indicated.  
Certainly adding a new dialog to a resource isn't going to add new functionality to the program, as the dialog image is useless without code to drive it.  So this isn't something to do willy nilly.

There are tools for updating and replacing resources in EXE files.  One of the nicer ones is Resource Hacker.  ( http://www.users.on.net/johnson/resourcehacker/ ).  With RH you can view, test and replace any resource.  You can also write them out to disk files and load them back.

I used it just this morning to make a custom sign-on screen for windows 2000.  It's easily done, all you do is use Resource Hacker to save the bitmap to disk, edit/replace it with your own (same size, 16 colours, of course) and then load it back into a copy of ntoskrnl.exe.  You will have to mess about with a DOS boot to overwrite the active one, and voila... win2000 with a custom sign-on screen.

Gerome

  • Guest
Loading individual resources from an RCDATA
« Reply #6 on: April 29, 2005, 09:44:18 PM »
Hi John and Ldblake,

Thanks for your examples :)
I used and im familiar with Reshacker for a long time :)
BTW my goal is simple : as far as i don't want to update a precise resource, i just want to update the WHOLE resource of an EXE by another one.

I have TEST.EXE with resources that contains 2 dialogs and 2 bitmaps and 1 menu.
I have a compiled RES that contains other RESources.
I want to inject the whole second RES into the 1st EXE.
If i use loadres, how can i update the whole target EXE file with the second RES file ?

Thanks for your help and advice :)

JohnF

  • Guest
Loading individual resources from an RCDATA
« Reply #7 on: April 30, 2005, 07:45:14 AM »
Quote from: "Gerome"
Hi John and Ldblake,

Thanks for your examples :)
I used and im familiar with Reshacker for a long time :)
BTW my goal is simple : as far as i don't want to update a precise resource, i just want to update the WHOLE resource of an EXE by another one.

I have TEST.EXE with resources that contains 2 dialogs and 2 bitmaps and 1 menu.
I have a compiled RES that contains other RESources.
I want to inject the whole second RES into the 1st EXE.
If i use loadres, how can i update the whole target EXE file with the second RES file ?

Thanks for your help and advice :)


To do it the dirty way, (using brute force), would require you doing some research. For example, the EXE header would need updating, offset of the resource, sizes, other things too probably.

Here is a quote from an M.S. doc.
=======================
Windows Header

The Windows (new-style) executable-file header contains information that the loader requires for segmented executable files.
This information includes the linker version number, data specified by the linker, data specified by the resource compiler, tables
of segment data, tables of resource data, and so on. The following illustration shows the Windows executable-file header:
The following sections describe the entries in the Windows executable-file header.

Information Block

The information block in the Windows header contains the linker version number, the lengths of various tables that further
describe the executable file, the offsets from the beginning of the header to the beginning of these tables, the heap and stack
sizes, and so on. The following list summarizes the contents of the header information block (the locations are relative to the
beginning of the block):
==================

Etc.

If you want to know more look at http://www.wotsit.org/ for the EXE format.

The way I would do it is to delete all the resources in the target EXE using BeginUpdateResource(), enumerate all the resources in the source EXE (EnumResourceTypes, EnumResourceNames), extract each resource singly and add each one to the target EXE with UpdateResource(). Finally use EndUpdateResource() to complete the process.

John

Anonymous

  • Guest
Loading individual resources from an RCDATA
« Reply #8 on: September 12, 2005, 08:53:44 PM »
Quote from: "JohnF"
Here is an example of updating an EXE's resource. It's from the PSDK.

Code: [Select]

HRSRC hResLoad;     // handle to loaded resource
HANDLE hExe;        // handle to existing .EXE file
HRSRC hRes;         // handle/ptr. to res. info. in hExe
HANDLE hUpdateRes;  // update resource handle
char *lpResLock;    // pointer to resource data
BOOL result;
// Load the .EXE file that contains the dialog box you want to copy.
hExe = LoadLibrary("hand.exe");
if (hExe == NULL)
{
    ErrorHandler("Could not load exe.");
}
 
// Locate the dialog box resource in the .EXE file.
hRes = FindResource(hExe, "AboutBox", RT_DIALOG);
if (hRes == NULL)
{
    ErrorHandler("Could not locate dialog box.");
}
 
// Load the dialog box into global memory.
hResLoad = LoadResource(hExe, hRes);
if (hResLoad == NULL)
{
    ErrorHandler("Could not load dialog box.");
}
 
// Lock the dialog box into global memory.
lpResLock = LockResource(hResLoad);
if (lpResLock == NULL)
{
    ErrorHandler("Could not lock dialog box.");
}
 
// Open the file to which you want to add the dialog box resource.
hUpdateRes = BeginUpdateResource("foot.exe", FALSE);
if (hUpdateRes == NULL)
{
    ErrorHandler("Could not open file for writing.");
}
 
// Add the dialog box resource to the update list.
result = UpdateResource(hUpdateRes,       // update resource handle
     RT_DIALOG,                   // change dialog box resource
     "AboutBox",                  // dialog box name
     MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),  // neutral language
     lpResLock,                   // ptr to resource info
     SizeofResource(hExe, hRes)); // size of resource info.
if (result == FALSE)
{
    ErrorHandler("Could not add resource.");
}
 
// Write changes to FOOT.EXE and then close it.
if (!EndUpdateResource(hUpdateRes, FALSE))
{
    ErrorHandler("Could not write changes to file.");
}
 
// Clean up.
if (!FreeLibrary(hExe))
{
    ErrorHandler("Could not free executable.");
}



You can delete all resources with BeginUpdateResource() and then add the new ones.

John