Storage location of yellow-blue shield icon Storage location of yellow-blue shield icon windows windows

Storage location of yellow-blue shield icon


I wanted to point it out explicitly.

You are supposed to put a shield on UI elements that will trigger an elevation: MSDN: Step 4: Redesign Your UI for UAC Compatibility.

Of course, you don't have to go spelunking around DLLs to extract images (although it certainly does make it easier at design time when you can design your design with a design time interface).

Microsoft provides a couple of supported (and therefore guaranteed) ways that you can get ahold of the shield icon at runtime:

  • Add a shield icon to the user interface?:

    • Extract a small icon

      SHSTOCKICONINFO sii;sii.cbSize = sizeof(sii);SHGetStockIconInfo(SIID_SHIELD, SHGSI_ICON | SHGSI_SMALLICON, &sii);hiconShield  = sii.hIcon;
    • Extract a large icon

      SHSTOCKICONINFO sii;sii.cbSize = sizeof(sii);SHGetStockIconInfo(SIID_SHIELD, SHGSI_ICON | SHGSI_LARGEICON, &sii);hiconShield  = sii.hIcon;
    • Extract an icon of custom size

      SHSTOCKICONINFO sii;sii.cbSize = sizeof(sii);SHGetStockIconInfo(SIID_SHIELD, SHGSI_ICONLOCATION, &sii);hiconShield  = ExtractIconEx(sii. ...);
  • Add a Shield Icon to a Button

    Button_SetElevationRequiredState(hwndButton, TRUE);

The article forgot to mention LoadIcon:

hIconShield = LoadIcon(0, IDI_SHIELD);

Although LoadIcon has been "superseded" by LoadImage:

hIconShield = LoadImage(0, IDI_SHIELD, IMAGE_ICON, desiredWith, desiredHeight, LR_SHARED); //passing LR_SHARED causes size to be ignored. And you must pass LR_SHARED

Loading the size you want - by avoiding shared images

In order to avoid loading a "shared" version of the icon, you have to load the icon directly out of the file.

We all know that the shield exists in user32.dll as resource id 106:

| Icon             | Standard Icon ID  | Real Resource ID ||------------------|-------------------|------------------|| IDI_APPLICATION  | 32512             | 100              || IDI_QUESTION     | 32514             | 102              || IDI_WINLOGO      | 32517             | 105              || IDI_WARNING      | 32515             | 101              || IDI_ERROR        | 32513             | 103              || IDI_INFORMATION  | 32516             | 104              || IDI_SHIELD       | 32518             | 106              |

That was undocumented spellunking.

SHGetStockIconInfo can give us the actual, current, guaranteed to change in the future, path and index:

TSHStockIconInfo sii;ZeroMemory(@sii, SizeOf(sii));sii.cbSize := SizeOf(sii);SHGetStockIconInfo(SIID_SHIELD, SHGSI_ICONLOCATION, {var}sii);

resulting in:

  • sii.szPath: C:\WINDOWS\System32\imageres.dll
  • sii.iIcon: -78

You can load this image for the size you desire using LoadImage:

HMODULE hmod := LoadLibrary(sii.szPath);Integer nIconIndex := Abs(sii.iIcon); //-78 --> 78ico = LoadImage(hmod, MAKEINTRESOURCE(nIconIndex), IMAGE_ICON, 256, 256, 0);

Another slightly easier way is to use SHDefExtractIcon:

HICON GetStockIcon(DWORD StockIconID, Integer IconSize){    HRESULT hr;    TSHStockIconInfo sii;    ZeroMemory(@sii, SizeOf(sii));    sii.cbSize := SizeOf(sii);    hr = SHGetStockIconInfo(SIID_SHIELD, SHGSI_ICONLOCATION, {var}sii);    OleCheck(hr);    HICON ico;    hr = SHDefExtractIcon(sii.szPath, sii.iIcon, 0, ref ico, null, IconSize);    OleCheck(hr);    return ico;}

It does the loading for you, and it handles the negative icon index (and the secret meaning that has):

HICON shieldIcon = GetStockIcon(SIID_SHIELD, 256);

Personally, i then use WIC to wrap that into a IWICBitmap:

IWICBitmap GetStockWicBitmap(DWORD StockIconID, Integer IconSize){   HICON ico = GetStockIcon(StockIconID, IconSize);   IWICBitmap bitmap;   IWICImagingFactory factory = new WICImagingFactory();   HRESULT hr = factory.CreateBitmapFromHICON(ico, out bitmap);   OleCheck(hr);   return bitmap;}

and so:

IWICBitmap bmp = GetStockWicBitmap(SIID_SHIELD, 256);

Now that you have the bitmap, at runtime, do with it what you want.

Small and Large

The problem with ExtractIconEx is that you're again stuck with the two shell sizes:

  • "small" (i.e. GetSystemMetrics(SM_CXSMICON))
  • "large" (i.e. GetSystemMetrics(SM_CXICON))

Loading icons is something that is quite a dark art in Windows:

  • LoadIcon
  • LoadImage
  • LoadImage(..., LR_SHARED)
  • ExtractIcon
  • ExtractIconEx
  • IExtractImage
  • SHDefExtractIcon
  • SHGetFileInfo(..., SHGFI_ICON, ...);
  • SHGetFileInfo(..., SHGFI_SYSICONINDEX, ...);
  • SHGetFileInfo(..., SHGFI_ICONLOCATION, ...);
  • IThumbnailProvider

Icons available through SHGetStockIconInfo

Microsoft gives a handy page that gives an example, and description, of all the stock icons.

And the 256px shield icon (as of Windows 10):

enter image description here


The shield icon is located in the file C:\Windows\System32\imageres.dll (at least, in my copy of English 32-bit Windows 7). There are several versions of the shield icon there, including the blue and yellow version you have above (icon 78).


Icons extracted from Windows 7 x64 SP1 English:

16x16 shield icon:

24x24 shield icon:

32x32 shield icon: