Pojo
Pojo

Reputation: 1237

FindResourceW() returns error code 127

Okay... so I am using Visual Studio 2010 making a win32 game... thingy. I am using a third party library that handles the graphics. It reads in a png file, creates the window, displays everything, and generally does a bunch of convenient low-level things that no one wants to deal with themselves.

Well, like any aspiring OCD programmer, I am trying to embed the png inside the executable because I don't like it to just be hangin' out in the directory for everyone to see. So, I got the source code, and started modifying it to, instead of load the png from a file, load it from a resource. I added the following code:

    HRSRC   hRsrc = FindResourceW(NULL, recName, recType);
    if (GetLastError() != 0)
    {
        char b[100];
        leave("Couldn't find resource", itoa(GetLastError(), b, 10));
    }
    HGLOBAL hGlob1 = LoadResource(NULL, hRsrc);
    int size = SizeofResource(NULL, hRsrc);
    HGLOBAL hGlobal = GlobalAlloc(GMEM_FIXED, size);
    LPVOID  resPtr = LockResource(hGlob1);
    LPSTREAM pStream;
    memcpy(hGlobal, resPtr, size);
    FreeResource(hGlob1);
    CreateStreamOnHGlobal(hGlobal, true, &pStream);
    buffer.resize((size_t)size);
    pStream->Read(&buffer[0], size, NULL);
    return;

recName is the resource's name. recType is the resource's type (these are both passed in as parameters). leave is a custom function that displays a popup message. buffer is the vector into which the png contents are read.

This library is compiled out into a statically linked library that my own code uses. So, my code does the actual embedding of the resources. Now, the thing is, this works, but only on a select few computers. I am able to run it, as is precisely one of my friends. On anyone else's computer, GetLastError() returns a 127, and as a result, the program craps out. According to msdn, error 127 is The specified procedure could not be found. ...whatever that means.

I have other embedded files in my executable, including mp3s and dlls, all made the same way, and they work fine (and, again, this png even works fine on my own computer), so I know it's not an issue of embedding things; I think I've pretty much got that down.

So then... what is error code 127 trying to tell me? Do my users' computers not know how to run function FindResourceW? If so, that makes absolutely no sense, because my code uses that function in other places, for loading the mp3s, and that works as well (and in fact, has worked, before I started trying to embed the png). Basically, I have never seen this kind of problem before, and I am stumped. :|

Upvotes: 0

Views: 881

Answers (1)

Ken White
Ken White

Reputation: 125727

You are not correctly using GetLastError or FindResourceW.

The documentation for FindResourceW (linked above) clearly says that FindResourceW returns a module handle (HRSR), and that you should check GetLastError if it returns NULL (emphasis added).

Return value

Type: HRSRC

If the function succeeds, the return value is a handle to the specified resource's information block. To obtain a handle to the resource, pass this handle to the LoadResource function.

If the function fails, the return value is NULL. To get extended error information, call GetLastError.

From the documentation on GetLastError (again, linked above, and again emphasis mine:

Return value

The return value is the calling thread's last-error code.

The Return Value section of the documentation for each function that sets the last-error code notes the conditions under which the function sets the last-error code. Most functions that set the thread's last-error code set it when they fail. However, some functions also set the last-error code when they succeed. If the function is not documented to set the last-error code, the value returned by this function is simply the most recent last-error code to have been set; some functions set the last-error code to 0 on success and others do not.

This says that unless the function is documented to set the last error code when it succeeds, the error code should only be used to indicate status if the function fails. Your code makes the assumption that if GetLastError is other than 0 then FindResourceW failed, and that assumption is wrong. :-) Because of that failed assumption, your code (wrongly) enters the if block and calls leave when it shouldn't, which would logically mean that the code after the if block ends is never executed.

FindResourceW is clearly documented to only SetLastError if it fails and returns NULL. The error value you're assuming is from FindResourceW is from somewhere else in your code that's setting the error value (which your code is apparently not reading).

So this would be closer to correct use (not a C++ guy myself):

HRSRC   hRsrc = FindResourceW(NULL, recName, recType);
if (!hRsrc)
{
    char b[100];
    leave("Couldn't find resource", itoa(GetLastError(), b, 10));
}

Upvotes: 1

Related Questions