How the shell converts an icon location into an icon


A customer had trouble getting an icon to display for a registered file type.

In my resource file, I specify the icon like this:

101 ICON awesome.ico

And when I register my file type, I set it like this:

[HKEY_CLASSES_ROOT\.xyz\DefaultIcon]
@="C:\path\to\awesome.exe,101"

However, when I view an .xyz file, my awesome icon doesn’t appear. On the other hand, if I change the 101 to a 0, then it works. Why? Isn’t the number in the resource file the resource ID?

Why yes, in fact, the number in the resource file is indeed the resource ID. But the number after the comma in the Default­Icon isn’t.

The format of shell icon locations (used most visibly by Default­Icon, but also used in other places) is «file»,«index», where the index is a zero-based index of the icon in your resources. In other words, an index of zero means “Give me the first icon in the file.” The resource compiler sorts icons numerically by resource ID, so the first icon in the file is the icon with the numerically lowest resource ID. In the above example, apparently there are no icons with resource IDs less than 101; that would explain why asking for icon index zero results in the awesome icon.

The function behind all this icon hunting is Extract­Icon. The icon location string is split up at the comma into a path and an integer, and that path and integer are passed to the Extract­Icon function. Since the Extract­Icon function interprets the integer as the icon index, that’s what the integer in your icon location string means.

In Windows 95, the Extract­Icon function was enhanced so that you could also specify an icon by its resource ID by passing its negative as the icon index. In other words, if you place a negative number after the comma, then its absolute value is interpreted as the resource ID.

We learned some time ago that there’s a hole in this model: It doesn’t work if you want a resource ID of 1, because the value −1 has a special meaning to Extract­Icon: Instead of extracting an icon, it tells you how many icons there are.

The workaround for this is actually straightforward, and you should be able to figure it out on your own based on information provided in this article. How do you specify that you want the icon whose resource ID is 1?

Comments (33)
  1. Bob says:

    The only reasonable answer to your question is 0, which also teaches that resource IDs must be positive integers.

  2. Alexandre B. says:

    From the information in the text, I’d guess that ResourceIDs are strictly positive (that is, positive integers excluding 0). Negative numbers are reserved in ExtractIcon for accessing by ResourceID and 0 is used as an index.

    Therefore, the icon with resourceID 1 is always at index 0 (assuming it exists) because no ID can be less than it.

  3. Bob says:

    @Alexandre:

    No guesses are necessary.

    You can rule out 0 because Raymond clearly says that there is "a hole in this model" which implies exactly one hole. If 0 were a legal resource ID, then the text would have allowed for more than one hole in the model (as it cannot be determined whether 0 is negated or not).  A similar argument eliminates negative resource IDs.

    Other sorts of resource IDs (strings, complex numbers, brainwave patterns) are eliminated because the compiler is able to sort them numerically.

    However, I had to rely on the fact that Raymond implied there was a guaranteed way to access the resource with resource ID 1 to eliminate the possibility of non-integer numeric resource IDs.

  4. SMW says:

    Use ExtractIconEx, just as the MSDN page on ExtractIcon says.

    [You misunderstood the question. -Raymond]
  5. configurator says:

    I don’t know about you, but Extracticon sounds like some kind of Transformer to me.

  6. Wilfried says:

    I wonder if this works correctly if the user decides to install into a path which includes a comma.

  7. Leo Davidson says:

    Thanks for posting this. I had wondered why resources in the registry had negative IDs and this explains it.

    (I wrote a little LoadString.exe that looks up the string resources referenced in the registry and ran into the negated IDs there. Wish RegEdit displayed the strings automatically these days, since they are used so much for localised strings.)

  8. peter says:

    > I wonder if this works correctly if the user decides to install into a path which includes a comma.

    Just a guess: Perhaps the function splits at the last ‘,’ it finds…

  9. kog999 says:

    "is «file»,«index», where the index is a zero-based index of the icon in your resources. In other words, an index of zero means "Give me the first icon in the file." The resource compiler sorts icons numerically by resource ID, so the first icon in the file is the icon with the numerically lowest resource ID"

    based on this text i would also say to specify 0 as the index. This is assuming that resource ID’s are not zero based but start at one. as the text says an index of zero means give me the first icon in the file and the "file" is sorted by resoure ID assendenly. so if the first resource ID is 1 it would be the first icon in the file.

  10. kog999 says:

    However if the resource ID is zero based (which i dont think it is)then you would specify 1 for the index as the resource ID 1 would be the second in the is list of icons.

  11. Will says:

    It must have to be something like causing the integer to roll over by using a value of -65536. Because the line is parsed to pass everything after the – sign to Extract­Icon which takes an unsigned int. Max int value is 65535.

  12. Will says:

    Or maybe it’s -65537 because rolling an unsigned int from 65536 is 0.

  13. SMW says:

    “Use ExtractIconEx, just as the MSDN page on ExtractIcon says.

    [You misunderstood the question. -Raymond]”

    Maybe, but it will work, won’t it?  :-)

    [if you’re suggesting “change the way Explorer extracts icons” then yes this fixes Explorer. Now you get to fix all the other apps that extract icons. Let me know when you’re done. -Raymond]
  14. No One says:

    @Bob, @kog999

    If resource IDs can be 0, 0 would get you the icon with resource ID 0, since 0 would be numerically lowest.

    Likewise, if resource IDs can be 0 then 1 does not guarantee getting an icon with resource ID of 1 because if you have an icon with resource ID x>1 and no icon with resource ID 0 then 1 is the 0-indexed icon and x would be the 1-indexed icon.

    So I have to say that resource IDs probably can’t be 0 and it’s really easy to look up whether that’s true.

  15. Marquess says:

    But how would you specify the icon ID of 1 so that you’d get an error if it didn’t exist?

    (Back to ExtractIconEx, I guess.)

  16. kog999 says:

    “Likewise, if resource IDs can be 0 then 1 does not guarantee getting an icon with resource ID of 1 because if you have an icon with resource ID x>1 and no icon with resource ID 0 then 1 is the 0-indexed icon and x would be the 1-indexed icon.”

    Hmm I was assuming that you could not create resource ID 1 unless you had already created resource ID 0 and so on. In which case my original statement would have been valid, but I suppose that is quite a big assumption for me to make.

    [If that were the case, then how did this guy manage to create icon 101 as the 0th icon? -Raymond]
  17. Mike says:

    The answer is to be found in the embedded link about the special meaning of -1: "The format of the icon registration is a filename, optionally followed by a comma and a decimal number."

    Couple that with the fact that the resource compiler sorts icons numerically by resource ID, I will surmize that omitting the optional numeric paramter will default to the first resource, which will be resource #1.

  18. Brian says:

    "[If that were the case, then how did this guy manage to create icon 101 as the 0th icon? -Raymond]"

    Because its a highly redacted example, resource IDs and filenames changed to protect the innocent?  Kidding of coruse, please dont hurt me.

    I like that 65537 trick, but that is just the kind of hack that leads to shims getting written in Windows 9 when 128bit numbers become standard.  "My program no longer shows its add/remove icon, it’s Microsoft’s fault, fix it."

  19. Tihiy says:

    0xFFFF i guess?

  20. SMW says:

    I provided an answer for the question “How do you specify that you want the icon whose resource ID is 1?”  Are you saying my answer is not valid for that particular question?

    [How do you, the person writing the icon registration (the .reg file), specify that you want the icon whose resource ID is 1? -Raymond]
  21. Dracula says:

    The fact that icons are sorted by resource ID will surely be key to the answer. Assuming that resource IDs are per definition greater than zero, the resource with ID #1 will always be found at index 0.

  22. Koro says:

    It’s not the resource compiler that does the "sort icon by resource IDs" magic last time I checked. It was the Visual Studio resource editor.

    Last time I checked (a few VS / PSDK versions ago I might specify), there was still this comment in every generated .rc file about how ICON resources had to be declared in resource ID order for consistency between Windows 9x and Windows NT (one of which, apparently, used the lowest ID whereas the other used the first icon).

  23. Anonymous Coward says:

    Configurator, you made my day! Thanks.

  24. SMW says:

    Oh, I don’t care… I just found an answer to that particular question.  I think the sarcasm of my first answer was not obvious.

  25. Cheong says:

    Btw, this is usually not a problem.

    I’ve yet to see an application that uses resource id less than 100 for image. (most of them use hundred/thousand digit to seperate id for different resource types.)

  26. Miral says:

    It’s actually fairly common to have the app icon have a resource id of 1 — primarily because that ensures that it’ll get used as the "main" icon for the app, since it’ll come first (assuming they’re stored in order of id).

    But yes, like Koro said, there are a whole bunch of warnings in generated .rc files and even in some of the PSDK docs that imply that icons are stored in the order they’re defined, which is not necessarily in id order.

  27. indices says:

    You can load the icon with resource ID=1 if you use it’s index instad of it’s resource ID.

  28. mnerec says:

    -01?

  29. Matt says:

    The answer is in the question. Ask for it by name and pass ‘0’ after the comma.

  30. anonymous says:

    Please fix the 16-bit EXE icon showing capability in 32-bit Windows 7 and 32-bit Vista.

  31. David Walker says:

    @anonymous:  Another “please fix” directed at Raymond.  How rude.  He is not “the” one and only Windows programmer in charge of fixing everything that is demanded of him.  I will venture to guess that he couldn’t fix things like this if he wanted to.  (I suspect it’s out of his direct area of responsibility.)

    Raymond has made it clear that he writes these posts on his own time.  I think they are fascinating, and it annoys me to see someone interject a “please fix such and such” into the comments.

    Try http://wfp.microsoft.com/ or http://support.microsoft.com/common/survey.aspx?scid=sw;en;1076.

    [Don’t worry about “anonymous”. He repeats this request about once a month via private email, both to me and to other Microsoft bloggers. It’s sort of like this buzzing mosquito noise we barely hear any more. Dear anonymous: Like I already said, your request has already been submitted to the appropriate people. Repeat requests accomplish nothing aside from annoying the people who approve/deny requests. (Tip: You don’t want to annoy the person who can help you.) And thank you for comment-hijacking yet another article. -Raymond]
  32. anonymous says:

    It automatically uses icon with resource id 1? Just type the path.

  33. Navarr says:

    It depends.. if it takes simply -1 as a special, could specifying -01 change the way it reacts to it?

    Though they’re the same number, they might be handled differently?

Comments are closed.