Jump to content

(Solved) Resource >> Resource


JohnOne
 Share

Recommended Posts

I have a need to update (replace) the resource (bitmap image) in my C++ executable.

I found an article showing how, but it shows how to update it from a file on disk, and I'd sooner

update it from another resource, which is the executable that will be doing the update (patch).

I'm having a bit of trouble finding out if it's even possible, so I'm hoping someone might know the

answer, have a link to info or something similar.

Appreciate your reading, thanks.

Edited by JohnOne

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

I have a need to update (replace) the resource (bitmap image) in my C++ executable.

I found an article showing how, but it shows how to update it from a file on disk, and I'd sooner

update it from another resource, which is the executable that will be doing the update (patch).

I'm having a bit of trouble finding out if it's even possible, so I'm hoping someone might know the

answer, have a link to info or something similar.

Appreciate your reading, thanks.

It's fairly easy to do that. Considering you are updaing bitmap resource it's even easier copying from one place to another than it would be to do it from a bitmap file.

First you have to lock(ate) the original resource in your executable. You do that in few easy steps,

::GetModuleHandle(NULL) -> ::FindResourceEx -> ::LoadResource -> ::LockResource + ::SizeofResource

Now you have the data to write. All you do then is

::BeginUpdateResource -> ::UpdateResource(locked_data, size_of_that_data) -> ::EndUpdateResource

... on target module.

In C++ you would write nice simple class with two constructors (default and with the file name of the target), locking method, writing method.

Then you would do something like this (boring details omitted for brevity):

SuperEasyThing oMGEasyIndeed(szDest);

DWORD dwSize = 0;
LPVOID pData = oMGEasyIndeed.LockResData(MY_RES_NAME, RT_BITMAP, &dwSize);
oMGEasyIndeed.Write(pData, dwSize, RT_BITMAP, RES_NAME_BY_YOUR_CHOICE);
Edited by trancexx

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

I'm trying to make this my first project that works first time, but I have a small concern.

SizeofResource(hExe, hRes)); returns 720 bytes, but what if its replacement bitmap is

a few bytes more or less, will that collapse the operation?

Hmmm, I'm also stuck on param 4 (Language Identifier) of UpdateResource().

I've used MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) for now but would love

some advice, as the program may be used in different locations and I don't

know how this will affect it.

Edited by JohnOne

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

API you use takes care of everything for you as far as the size is concerned, don't worry about that, just carefully read and follow MSDN documentation.

As for the language, normally you would use neutral identifier or the one module uses for the rest of the resources (if any there). In case of wrong "location" the only one existing gets loaded. Besides that, resource language idenifier is really only imporant for string resources.

On the other hand, if you are replacing, then of course you will use the same idenifiers for new bitmap as they are for the old one, including language.

Edited by trancexx

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

Thank you for the info, and tips.

I went just tried it, it looked like it worked but of course it did not :(

I never made a class for now just procedural.

It looks ok to me but the target exe fails to work after update.

The target exe is stripped of its icon also.

Think you might cast your eye across my code?

int _tmain(int argc, _TCHAR* argv[])
{
    // Get handle to source exe (self) that contains the bitmap.
    hExe = GetModuleHandle(NULL);
    if (!hExe)
    {
        ErrorOut(string("FreeLibrary: Failed."));
        return -1;
    }
    cout << "hExe: " << hExe << endl;

    // Locate the bitmap in the source exe.
    hRes = FindResource(hExe, MAKEINTRESOURCE(IDB_BITMAP1), RT_BITMAP);
    if (!hRes)
    {
        ErrorOut(string("FindResource: Failed.."));
        FreeLibrary(hExe);
        return -2;
    }
    cout << "hRes: " << hRes << endl;

    dwSizeofRes = SizeofResource(hExe, hRes);
    if (!dwSizeofRes)
    {
        ErrorOut(string("dwSizeofRes: Failed."));
        FreeLibrary(hExe);
        return -3;
    }
    cout << "dwSizeofRes: " << dwSizeofRes << endl;

    // Load the bitmap into global memory.

    hResLoad = LoadResource(hExe, hRes);
    if (!hResLoad)
    {
        ErrorOut(string("LoadResource: Failed."));
        FreeLibrary(hExe);
        return -3;
    }
    cout << "hResLoad: " << hResLoad << endl;

    // Lock the bitmap in global memory.
    lpResLock = LockResource(hResLoad);
    if (!lpResLock)
    {
        ErrorOut(string("LockResource: Failed."));
        FreeLibrary(hExe);
        return -4;
    }
    cout << "lpResLock: " << lpResLock << endl;

    // get UpdateResource handle to use on target exe.
    hUpdateRes = BeginUpdateResource(TEXT("snatch.exe"), TRUE);
    if (!hUpdateRes)
    {
        ErrorOut(string("hUpdateRes: Failed."));
        FreeLibrary(hExe);
        return -5;
    }
    cout << "hUpdateRes: " << hUpdateRes << endl;

    // Do the update
    bResult = UpdateResource(hUpdateRes, 
        MAKEINTRESOURCE(IDB_BITMAP1), 
        MAKEINTRESOURCE(115), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), 
        lpResLock, 
        dwSizeofRes);
    if (!bResult)
    {
        ErrorOut(string("bResult: Failed."));
        FreeLibrary(hExe);
        return -5;
    }
    cout << "bResult: " << bResult << endl;

    //End the update
    bResult = EndUpdateResource(hUpdateRes, FALSE);
    if (!bResult)
    {
        ErrorOut(string("bResult: Failed."));
        FreeLibrary(hExe);
        return -5;
    }
    cout << "bResult: " << bResult << endl;

    // Free handle of source exe.
    if (!FreeLibrary(hExe))
    {
        ErrorOut(string("FreeLibrary: exe Failed"));
        return -5;
    }

    return 0;
}
Edited by JohnOne

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

I've gotten a little further, where the bitmap is being added to the target

but alongside it, is the original.

The original has a code next to it (2057)

Whereas the new bitmap has the code (0).

There is something I'm missing here, just cannot put my finger on it.

EDIT:

I'm wondering if it's to do with the target app and settings some how.

I was reading about restrictions on type of RC data, unfortunately

I don't even know what that is, to change settings in target exe.

int _tmain(int argc, _TCHAR* argv[])
{
    // Get handle to source exe (self) that contains the bitmap.
    hExe = GetModuleHandle(NULL);
    if (!hExe)
    {
        ErrorOut(string("FreeLibrary: Failed."));
        return -1;
    }
    cout << "hExe: " << hExe << endl;

    // Locate the bitmap in the source exe.
    hRes = FindResource(hExe, MAKEINTRESOURCE(IDB_BITMAP1), RT_BITMAP);
    if (!hRes)
    {
        ErrorOut(string("FindResource: Failed.."));
        FreeLibrary(hExe);
        return -2;
    }
    cout << "hRes: " << hRes << endl;

    dwSizeofRes = SizeofResource(hExe, hRes);
    if (!dwSizeofRes)
    {
        ErrorOut(string("dwSizeofRes: Failed."));
        FreeLibrary(hExe);
        return -3;
    }
    cout << "dwSizeofRes: " << dwSizeofRes << endl;

    // Load the bitmap into global memory.
    hResLoad = LoadResource(hExe, hRes);
    if (!hResLoad)
    {
        ErrorOut(string("LoadResource: Failed."));
        FreeLibrary(hExe);
        return -3;
    }
    cout << "hResLoad: " << hResLoad << endl;

    // Lock the bitmap in global memory.
    lpResLock = LockResource(hResLoad);
    if (!lpResLock)
    {
        ErrorOut(string("LockResource: Failed."));
        FreeLibrary(hExe);
        return -4;
    }
    cout << "lpResLock: " << lpResLock << endl;
    */

    // get UpdateResource handle to use on target exe.
    hUpdateRes = BeginUpdateResource(TEXT("snatch.exe"), FALSE);
    if (!hUpdateRes)
    {
        ErrorOut(string("hUpdateRes: Failed."));
        FreeLibrary(hExe);
        return -5;
    }
    cout << "hUpdateRes: " << hUpdateRes << endl;

    // Do the update
    bResult = UpdateResource(hUpdateRes, 
        MAKEINTRESOURCE(2), 
        MAKEINTRESOURCE(115), 
        NULL, 
        lpResLock, 
        dwSizeofRes);
    if (!bResult)
    {
        ErrorOut(string("bResult: Failed."));
        FreeLibrary(hExe);
        return -6;
    }

    hExe = NULL;

    cout << "bResult: " << bResult << endl;
    /*
    // Free handle of source exe.
    if (!FreeLibrary(hExe))
    {
        ErrorOut(string("FreeLibrary: exe Failed"));
        return -5;
    }
    */
    //End the update
    bResult = EndUpdateResource(hUpdateRes, FALSE);
    if (!bResult)
    {
        ErrorOut(string("bResult: Failed."));
        FreeLibrary(hExe);
        return -7;
    }
    cout << "bResult: " << bResult << endl;



    return 0;
}
Edited by JohnOne

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...