February 10th, 2025

How does Explorer find the “first” icon in a file

An old MSDN article from 1995 talks about how Explorer chooses the icon to use for an executable.

Windows NT simply chooses the first resource listed in the application’s RC script. On the other hand, Windows 95’s algorithm is to choose the alphabetically first named group icon if one exists. If one such group resource does not exist, Windows chooses the icon with the numerically lowest identifier.

The first thing I want to do is make a correction. The description of the Windows NT algorithm is incorrect. Both Windows NT and Windows 95 use the same algorithm:

  • Choose the alphabetically first named group icon, if available.
  • Else, choose the group icon with the numerically lowest identifier.

The reason for this is that the Portable Executable file format requires resources to be listed in the resource dictionary with named resources first (sorted alphabetically), followed by numbered resources (sorted numerically). Explorer calls Enum­Resource­Names and grabs the first one, and since the icon groups are enumerated in the order they appear in the resource dictionary, the effect is the one described above.

If you want to replicate this algorithm, it’s not hard.

HICON FindFirstIcon(HMODULE hmod)
{
    HICON icon = nullptr;
    EnumResourceNamesW(hmod, RT_GROUP_ICON,
        [](HMODULE, PCWSTR, PCWSTR id, LONG_PTR param)
    {
        *reinterpret_cast<HICON*>(param) =
            LoadIconW(hmod, id);
        return FALSE;
    }, reinterpret_cast<LONG_PTR>(&icon);
    return icon;
}

The callback function tries to load the first icon it finds, and then returns FALSE to stop the enumeration. This returns control to Find­First­Icon, which returns the icon that the callback function loaded (or at least tried to load).

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

4 comments

  • Maurice Kayser 1 week ago · Edited

    Hallo Herr Chen!

    I am currently investigating how resources are loaded by Windows, and since you just wrote about locales and icon resources, would you be willing to shed some light on how non-ASCII lowercase letters in resource names work? I'm having trouble loading resource names containing e.g. an <code> character, see: Issue with Win32 API Loading of PE Resources Containing Lowercase Letters.

    I tried using <code> from your previous blog post, but without success, as I guess Win32 APIs may not be influenced by this function.

    Would be very appreciated.
    Thanks!

    Read more
    • Me Gusta

      I think that is making the assumption that it is the Win32 APIs that are at fault.

      If this is a bug in rc.exe then it will look the same.

  • Marco Comerci 1 week ago

    Hello,
    I think that the closing parenthesis of EnumResourceNamesW is missing. Should be … , reinterpret_cast(&icon));

    Regards.