This is bugging the shit out of me.
I've done this many times before: embed a bitmap in a program using the resource compiler, then loading the bitmap and using it. Works fine.
Now, all of a sudden for some strange reason I can't do that. When I try to load the bitmap I get an error.
Here's what I'm doing:
- Creating the bitmap (I use Paint Shop Pro, which has always worked for me in the past)
- Create a resource (.rc) file with the name of the bitmap file and a resource ID:
500 bitmap "some picture.bmp"
- Define a constant for that bitmap in the program source:
$somePictureID EQU 500
- Assemble the program
- Run the resource compiler against the .rc file
- Run the cvtres program against the resulting .res file to create an .obj file
- Link everything together into an .exe
- In the program code, load the bitmap as a resource:
INVOKE LoadImage, InstanceHandle, $somePictureID, IMAGE_BITMAP, 0, 0, LR_SHARED
This has worked every time up to now. But now I get an error from
LoadImage():
The specified resource type cannot be found in the image file.
WTF?????So far as I can tell everything's the same as it's always been. But now
every single program I write that uses this method fails. It's like there's some kind of gremlin loose in the machine.
I've tried a lot of things:
- Something wrong with the BMP? I save it with Microsoft Paint; it still fails.
- Tried taking out the LR_SHARED and replacing it with zero: still fails. (See note below.)
- I checked all my MASM tool executables (ml, link, rc, cvtres) to see if they might have gotten corrupted somehow: nope.
- Tried making different size BMPs; makes no difference.
If you run PE Explorer against the .exe it always finds the bitmap resources, no problem.
I have an older program that uses the exact same method to load BMPs. I remade it (reassemble, re-resource compile, relink); it still works. ?????
I say everything's the same, but obviously it's not; but what could be different?
I've attached an exe for testing. Could someone run this and report what it says? All it does is try to open a bitmap resource in the .exe, and report on the result using
GetLastError() and
FormatMessage() (result appears in the status bar at bottom).
If you felt like it you could load this up in a debugger and see what happens when
LoadImage() executes (it's only in there one time).
Thanks!
Note: I've always used
LR_SHARED with
LoadImage(), which has this advantage according to Microsoft:
QuoteWhen you use this flag, the system will destroy the resource when it is no longer needed.
But then they throw this wrench into the works:
QuoteDo not use LR_SHARED for images that have non-standard sizes, that may change after loading, or that are loaded from a file.
Now I don't think that's even true; I've loaded lots and lots of bitmaps with definitely nonstandard sizes with nary a problem.
But I tried removing this flag anyhow; as I said above, it made no difference.
No resource file?
Works okay here.
include \masm32\include\masm32rt.inc
.data
hInstance dd 0
.code
start:
invoke GetModuleHandle, 0
mov hInstance, eax
invoke LoadImage, hInstance, 500, IMAGE_BITMAP, 0, 0, LR_SHARED
invoke ExitProcess, eax
end start
Running in olly, LoadImage returns the bitmap handle
The exe you attached NoCforMe, has a bitmap with resource ID of 504 not 500
(https://i.postimg.cc/90jFpDpv/untitled.png)
Okay, I see that you ARE trying to load the bitmap with resource ID of 504. Apologies. I looked at it in olly.
Your post was mentioning ID 500 that is why I noted it.
There are times when I save an indexed bitmap with GIMP, I have to check the option "Do not write color space information" for compatibility. Maybe that is the case for your image? Is it RGB or indexed?
How about for images that were not created with Paint Shop Pro??? I am think that there is some option/setting in Paint Shop Pro (that you had inadvertantly changed causing you this grief) which you said has always worked for you in the past... until recently.
---- later ---- I have extracted the bitmap from your executable ---------
I have resaved the image using GIMP, without writing color space information (attached)
See if it makes a difference for you.. it is in 504.zip
Also I made a test using that image.. in Bitmap_504,zip. Run it in olly - it is not a GUI program - only for demonstration that the bitmap loads successfully.
And I notice in your executable, you are NOT using LR_SHARED when loading the bitmap! :wink2:
I tweaked your exe in ollydbg... The image then loads (with LR_SHARED)
Sorry 'bout the 504/500 mixup. I changed it to 504 at the last minute (both the resource file and the ID used for LoadImage()) out of superstition, as I used that # to load the very same image in another program (which worked).
Dunno if you missed it, but I wrote that I saved the image with Microsoft Paint before making the project, so the problem has nothing to do with Paint Shop Pro.
The bitmap is an ordinary 16-color BMP, so it has a palette. The exact same BMP loads perfectly in another program.
There's a resource file. If anyone likes I can attach the whole shebang.
No, I am satisfied that LoadImage works with LR_SHARED. Even in your attached exe from your post above. (patched in ollydbg) Dunno what happened on your end though, as mentioned in your first post...
You can post it though, for anyone else that might like to explore it. :thumbsup:
Now if you do discover what caused the issues for you in the first place, I am sure that others will be interested in what had happened.
So I'm not sure what result you got when you ran my .exe; did it fail or not?
Complete project attached here.
Originally it failed since LR_SHARED was not used. I added it in ollydbg then the image loaded okay, while stepping the code. (the changes made to that piece of code corrupted the code that followed, though) so had to abort. :tongue:
Well, it still fails for me both ways (using LR_SHARED or not). You can play with the source now to change that.
Quote from: NoCforMe on May 12, 2024, 10:29:29 AMYou can play with the source now to change that.
I made a few minor changes .bat file, .rc file, and removed the .list - .nolist in the asm file
and resaved the bitmap file with the GIMP - saved it as "fixed.bmp"...
OK, so you made a few cosmetic changes. (Uppercasing "BITMAP"? really?)
But you failed to mention: what was the result?
Deleting the .rsrc and .obj files is NOT gonna make this work, believe me.
Well, I ran your .exe and guess what? it worked.
Question now is, why?
I'm 120% sure it has nothing to do with removing .nolist/.list, but what the hell, I'll try that ...
That's the only change you made to the source, right?
It works.
Also the resource ID then "BITMAP" in the .rc file. You had "bitmap" then the resource ID.
The .bat file is from one of my templates, hence renaming the resource file to rsrc.rc.
I only delete the .res and .obj files, if succesfully assembled and linked.
Use your own batch file, its okay with me. I only made adjustments to what I am more familiar with, hence no cvtres either - not needed. The .res file gets linked just fine.
Here this should be more to your liking. It also uses the original bitmap. But I still adjusted the rc file
I did however need to fix the paths in your batch file. Not all of us have masm32 in our environment 'PATH' or however your setup is configured.
Quote from: NoCforMe on May 12, 2024, 11:35:54 AMI'm 120% sure it has nothing to do with removing .nolist/.list, but what the hell, I'll try that ...
That's the only change you made to the source, right?
Yes, the only change there. I have no need for the listing file. Nor the debugging stuff.
Check your .rc file
Quote from: sudoku on May 12, 2024, 11:50:33 AMI did however need to fix the paths in your batch file. Not all of us have masm32 in our environment 'PATH' or however your setup is configured.
Some "fix". You used forward slashes instead of backslashes:
/masm32/bin/link /SUBSYSTEM:WINDOWS LoadImageTest LoadImageTest_resources
Doesn't work at all.
Quote from: sinsi on May 12, 2024, 11:58:30 AMCheck your .rc file
I checked it. I've checked it like a thousand times. What do you think I've been doing here all this time, jerking off?
Can you be a little more specific?
Total contents of rsrc.rc (which has been renamed thanks to sudoku):
btmap 504 "fixed.bmp"
OK, I didn't notice it was mispled.
Total confusion since sudoku waded in and posted umpteen versions, many with errors.
I FIXED IT.
It still doesn't fucking work.
Any more brilliant ideas?
I'm dyslexic like that. :biggrin:
Ok. Just remove that for your own path arrangement. It did work for me though, I'm surprised that it did actually.
Nevermind the batch file, just look at the rc file as sinsi also suggested.
Put the resource ID first, then resource type. Then the filename plus extension. :smiley:
Calm down and think. Doesn't a resource script usually go ID, Type, Data?
Your .rc
BITMAP 504 "Plus circle no border (14x14x16).bmp"
My .rc
504 BITMAP "Plus circle no border (14x14x16).bmp"
You should also check for a valid handle from LoadImage before you call GetLastError, as GetLastError returns whatever was left over.
Quote from: sinsi on May 12, 2024, 12:08:22 PMCalm down and think.
:thumbsup:
504 BITMAP "Plus circle no border (14x14x16).bmp"
/* #define MANIFEST 24 */
/* #define IDR_XPMANIFEST1 1 */
/* IDR_XPMANIFEST1 MANIFEST "xpmanifest.xml" */
:biggrin:
You, my friend, just nailed it.
Talk about dyslexic: I had (in another resource file)
bitmap 500 "Plus circle no border (14x14x16).bmp"
bitmap 501 "test 32x32.bmp"
bitmap 502 "test 48x48.bmp"
bitmap 503 "test 96x96.bmp"
bitmap 504 "test 128x128.bmp"
bitmap 505 "test 256x256.bmp"
bitmap 506 "test 64x200.bmp"
bitmap 507 "test 64x300.bmp"
bitmap 508 "test 64x400.bmp"
bitmap 509 "test 200x400.bmp"
bitmap 510 "test 200x500.bmp"
bitmap 511 "test 200x600.bmp"
#define MANIFEST 24
#define IDR_XPMANIFEST1 1
IDR_XPMANIFEST1 MANIFEST "xpmanifest.xml"
Too obvious, I guess.
Just to clear things up:
This had NOTHING to do with "BITMAP" vs "bitmap".
This had NOTHING to do with .nolist/.list.
OK, I guess the drama is over ...
Was fun while it lasted though. :greensml: never minding my own errors. :tongue:
I always use upper case out of convention, I suppose. I just removed the list stuff cause it wasn't needed during testing...
Quote from: sinsi on May 12, 2024, 12:08:22 PMYou should also check for a valid handle from LoadImage before you call GetLastError, as GetLastError returns whatever was left over.
That's not the way I understand how that works.
GetLastError() will report the "The specified resource type cannot be found ..." in case of that error from
LoadImage(). It will report "The operation completed successfully" in the case of success. So no need to check before calling it.
Quote from: sudoku on May 12, 2024, 12:15:12 PMWas fun while it lasted though. :greensml: never minding my own errors. :tongue:
BTW, all I can say is that I absolutely
hate your batch file. What, it closes my DOS command window that I had to steer to the right folder and everything?
Other than that, no problemo.
Lemme guess, you run batch files by opening the command prompt and then opening the batch file? Just double click on the batch file, much easier. If it closes, it means assembly was successful, else it pauses for you to see the errors. :cool: To each, their own I suppose.
OK, there is one remaining mystery:
So I used completely wrong syntax in my resource file. And yet, somehow those bitmaps did end up in the .exe (use PE Explorer if you don't believe me). With the correct IDs, no less.
So how is it that the PE program could find them but not LoadImage()?
Probably because the actual resource entries were somehow malformed, and all that PE Explorer is doing is locating blocks of data that it thinks must be a resource without actually validating it.
Although PE Explorer was able to display the bitmaps correctly ...
Quote from: sudoku on May 12, 2024, 12:20:30 PMLemme guess, you run batch files by opening the command prompt and then opening the batch file? Just double click on the batch file, much easier. If it closes, it means assembly was successful, else it pauses for you to see the errors. :cool: To each, their own I suppose.
I like to leave the command window open because I can do other things than just run batch files there. Don't like that whole having to "hit any key to continue" thing.
Instead of navigating to different folders in Explorer to work on different projects (well, I do that too, to open different source files), I use 4DOS's indispensible
pushd/popd facility, where I can zip over to another folder, work on a project there, then
popd to get back to where I was before.
So much nicer than the Windows cmd.exe.
Sounds like a big mystery to be solved. Yes, the original exe did have the bitmap. Odd that rc.exe (or cvtres) did not complain about it. Okay, so you're not using cmd.exe like I had thought. Interesting.
Quote from: NoCforMe on May 12, 2024, 12:15:43 PMQuote from: sinsi on May 12, 2024, 12:08:22 PMYou should also check for a valid handle from LoadImage before you call GetLastError, as GetLastError returns whatever was left over.
That's not the way I understand how that works.
GetLastError() will report the "The specified resource type cannot be found ..." in case of that error from LoadImage(). It will report "The operation completed successfully" in the case of success. So no need to check before calling it.
Quote from: GetLastErrorsome functions set the last-error code to 0 on success and others do not.
Quote from: sudoku on May 12, 2024, 12:26:02 PMSounds like a big mystery to be solved. Yes, the original exe did have the bitmap. Odd that rc.exe (or cvtres) did not complain about it.
rc.exe just assumed that you knew what you were doing :biggrin: and used bitmap as the ID and 504 as the Type (see the "manifest" example, it uses 24 as the Type)
Stop masturbating so much, it makes you blind
to your mistakes, obviously
@sinsi:
1 24 "manifest.xml"
Yes, 24 is the type. :biggrin:
1 is the ID.
Quote from: sudoku on May 12, 2024, 12:37:46 PM@sinsi:
1 24 "manifest.xml"
Yes, 24 is the type. :biggrin:
1 is the ID.
That's my point, 504 could be "RT_SILLYPUTTY" and the resource compiler will just put it down as 504.
:joking:
Just to add text to the post, I will add...
You might just be right.
Quote from: sinsi on May 12, 2024, 12:31:54 PMrc.exe just assumed that you knew what you were doing :biggrin: and used bitmap as the ID and 504 as the Type (see the "manifest" example, it uses 24 as the Type)
Hmm, that makes me think: I wonder if it would've worked if I had done this instead:
INVOKE LoadImage, InstanceHandle, BITMAP, <file ID>, 0, 0, LR_SHARED
Switching the resource type and the resource ID? (probly have to define
BITMAP in the source, as I don't think that's a windows.inc equate)
Because you can load other resources with
LoadImage(), maybe not restricted to the known universe of typical types (
IMAGE_BITMAP, etc.).
Not about to attempt this just yet. Wait until I get really bored ...
Quote from: NoCforMe on May 12, 2024, 12:53:59 PMQuote from: sinsi on May 12, 2024, 12:31:54 PMrc.exe just assumed that you knew what you were doing :biggrin: and used bitmap as the ID and 504 as the Type (see the "manifest" example, it uses 24 as the Type)
Hmm, that makes me think: I wonder if it would've worked if I had done this instead:
INVOKE LoadImage, InstanceHandle, BITMAP, <file ID>, 0, 0, LR_SHARED
Switching the resource type and the resource ID? (probly have to define BITMAP in the source, as I don't think that's a windows.inc equate)
Because you can load other resources with LoadImage(), maybe not restricted to the known universe of typical types (IMAGE_BITMAP, etc.).
Not about to attempt this just yet. Wait until I get really bored ...
Not sure about LoadImage, but LoadResource with a type of 504 and an ID "BITMAP" as a string should work.
Quote from: sinsi on May 12, 2024, 01:12:07 PMNot sure about LoadImage, but LoadResource with a type of 504 and an ID "BITMAP" as a string should work.
That's what I was thinking. Think about it: neither of those functions really knows anything about the actual thing (resource) that they're loading, just where it is and how big it is in the executable image.
Oh, and just one more thing:
You can definitely use the LR_SHARED flag on "nonstandard" bitmaps (like my meter, which is 313 x 325 pixels).