Help and Support
 

powered byLive Search

PRB: System Image List Does Not Contain Overlay Images

Article ID:192055
Last Review:July 11, 2005
Revision:1.2
This article was previously published under Q192055

SYMPTOMS

When you are using the system image list in an application, you might want to be able to use the standard overlay images, such as the shared and shortcut overlay images. However, when you have the Internet Explorer 4.0x Desktop Update installed on Windows NT 4.0, the standard overlay images are not contained in the process' copy of the system image list.

Back to the top

CAUSE

You can obtain the handle to the system image list with a function call similar to the following:
   HIMAGELIST  himl;
   SHFILEINFO  sfi;

   himl = (HIMAGELIST)SHGetFileInfo(TEXT("C:\\"), 0, &sfi,
      sizeof(SHFILEINFO), SHGFI_SYSICONINDEX);
				
On Windows 95 and Windows 98, this function returns the handle of the actual system image list. However, on Windows NT version 4.0 this function returns a handle to a copy of the system image. Each process gets its own copy of the system image list. Windows NT does this to maintain security requirements so that one application cannot destroy the system image list. The proper images are added to the process' copy of the system image list whenever a call to SHGetFileInfo is made to retrieve the icon index for a specific item type.

The copy of the system image list on Windows NT version 4.0 initially contains the standard document and folder icons, as well as the shared and shortcut overlay images. However, when you have the Internet Explorer 4.0x Desktop Update installed then the standard overlay images are not included in the copy of the system image list. You cannot add them by calling SHGetFileInfo because the Internet Explorer 4.0x desktop Update implements the IShellIconOverlay interface to provide callers with the proper overlay index.

Back to the top

RESOLUTION

To add the standard overlay images to the process' copy of the system image list with the Desktop Update, you need to get an IShellIconOverlay interface pointer for a file system folder and call its GetOverlayIndex method for a shortcut (.lnk) file that is contained in the folder. This causes both standard overlay images to be added to the process' copy of the system image list. GetOverlayIndex also registers the overlay images using the ImageList_SetOverlayImage function.

The following function retrieves the handle of the system image list, and, if you are running under Windows NT version 4.0, it creates a temporary .lnk file. Then it gets the IShellIconOverlay interface from the parent folder and calls IShellIconOverlay::GetOverlayIndex, passing the PIDL for the temporary .lnk file. Finally, the handle to the system image list is returned from the function. The fSmall flag indicates if the small or large image list is being requested. If fSmall is zero, the system image list that contains large icons is retrieved. If fSmall is non-zero, the system image list that contains large icons is retrieved. If Internet Explorer 4.0 with the Desktop Update is not installed on your computer, the function cannot retrieve the IShellIconOverlay interface, so the function will simply return the image list handle.
   /********************************************************************

      GetSystemImageList()

   ********************************************************************/ 

   HIMAGELIST GetSystemImageList(BOOL fSmall)
   {
   HIMAGELIST  himl;
   SHFILEINFO  sfi;

   himl = (HIMAGELIST)SHGetFileInfo(TEXT("C:\\"), 0, &sfi,
      sizeof(SHFILEINFO), SHGFI_SYSICONINDEX |
         (fSmall ? SHGFI_SMALLICON : SHGFI_LARGEICON));

   /*
   Do a version check first because you only need to use this code on
   Windows NT version 4.0.
   */ 
   OSVERSIONINFO vi;
   vi.dwOSVersionInfoSize = sizeof(vi);
   GetVersionEx(&vi);
   if(VER_PLATFORM_WIN32_WINDOWS == vi.dwPlatformId)
      return himl;

   /*
   You need to create a temporary, empty .lnk file that you can use to
   pass to IShellIconOverlay::GetOverlayIndex. You could just enumerate
   down from the Start Menu folder to find an existing .lnk file, but
   there is a very remote chance that you will not find one. By creating
   your own, you know this code will always work.
   */ 
   HRESULT           hr;
   IShellFolder      *psfDesktop = NULL;
   IShellFolder      *psfTempDir = NULL;
   IMalloc           *pMalloc = NULL;
   LPITEMIDLIST      pidlTempDir = NULL;
   LPITEMIDLIST      pidlTempFile = NULL;
   TCHAR             szTempDir[MAX_PATH];
   TCHAR             szTempFile[MAX_PATH] = TEXT("");
   TCHAR             szFile[MAX_PATH];
   HANDLE            hFile;
   int               i;
   OLECHAR           szOle[MAX_PATH];
   DWORD             dwAttributes;
   DWORD             dwEaten;
   IShellIconOverlay *psio = NULL;
   int               nIndex;

   // Get the desktop folder.
   hr = SHGetDesktopFolder(&psfDesktop);
   if(FAILED(hr))
      goto exit;

   // Get the shell's allocator.
   hr = SHGetMalloc(&pMalloc);
   if(FAILED(hr))
      goto exit;

   // Get the TEMP directory.
   if(!GetTempPath(MAX_PATH, szTempDir))
      {
      /*
      There might not be a TEMP directory. If this is the case, use the
      Windows directory.
      */ 
      if(!GetWindowsDirectory(szTempDir, MAX_PATH))
         {
         hr = E_FAIL;
         goto exit;
         }
      }

   // Create a temporary .lnk file.
   if(szTempDir[lstrlen(szTempDir) - 1] != '\\')
      lstrcat(szTempDir, TEXT("\\"));
   for(i = 0, hFile = INVALID_HANDLE_VALUE;
      INVALID_HANDLE_VALUE == hFile;
      i++)
      {
      lstrcpy(szTempFile, szTempDir);
      wsprintf(szFile, TEXT("temp%d.lnk"), i);
      lstrcat(szTempFile, szFile);

      hFile = CreateFile(  szTempFile,
                           GENERIC_WRITE,
                           0,
                           NULL,
                           CREATE_NEW,
                           FILE_ATTRIBUTE_NORMAL,
                           NULL);

      // Do not try this more than 100 times.
      if(i > 100)
         {
         hr = E_FAIL;
         goto exit;
         }
      }

   // Close the file you just created.
   CloseHandle(hFile);
   hFile = INVALID_HANDLE_VALUE;

   // Get the PIDL for the directory.
   LocalToWideChar(szOle, szTempDir, MAX_PATH);
   hr = psfDesktop->ParseDisplayName(  NULL,
                                       NULL,
                                       szOle,
                                       &dwEaten,
                                       &pidlTempDir,
                                       &dwAttributes);
   if(FAILED(hr))
      goto exit;

   // Get the IShellFolder for the TEMP directory.
   hr = psfDesktop->BindToObject(   pidlTempDir,
                                    NULL,
                                    IID_IShellFolder,
                                    (LPVOID*)&psfTempDir);
   if(FAILED(hr))
      goto exit;

   /*
   Get the IShellIconOverlay interface for this folder. If this fails,
   it could indicate that you are running on a pre-Internet Explorer 4.0
   shell, which doesn't support this interface. If this is the case, the
   overlay icons are already in the system image list.
   */ 
   hr = psfTempDir->QueryInterface(IID_IShellIconOverlay, (LPVOID*)&psio);
   if(FAILED(hr))
      goto exit;

   // Get the PIDL for the temporary .lnk file.
   LocalToWideChar(szOle, szFile, MAX_PATH);
   hr = psfTempDir->ParseDisplayName(  NULL,
                                       NULL,
                                       szOle,
                                       &dwEaten,
                                       &pidlTempFile,
                                       &dwAttributes);
   if(FAILED(hr))
      goto exit;

   /*
   Get the overlay icon for the .lnk file. This causes the shell
   to put all of the standard overlay icons into your copy of the system
   image list.
   */ 
   hr = psio->GetOverlayIndex(pidlTempFile, &nIndex);

   exit:
   // Delete the temporary file.
   DeleteFile(szTempFile);

   if(psio)
      psio->Release();

   if(INVALID_HANDLE_VALUE != hFile)
      CloseHandle(hFile);

   if(psfTempDir)
      psfTempDir->Release();

   if(pMalloc)
      {
      if(pidlTempFile)
         pMalloc->Free(pidlTempFile);

      if(pidlTempDir)
         pMalloc->Free(pidlTempDir);

      pMalloc->Release();
      }

   if(psfDesktop)
      psfDesktop->Release();

   return himl;
   }
				

Back to the top

STATUS

This behavior is by design.

Back to the top

MORE INFORMATION

On computers that do not have the Internet Explorer 4.0x Desktop Update installed, the overlay indexes (not to be confused with the image index-- see the documentation for ImageList_SetOverlayImage for more information) for the two standard overlay images are fixed. On these systems, one is the overlay index for the shared overlay and two is the overlay index for the shortcut overlay. However, if the installed shell exposes the IShellIconOverlay interface for folders, you should use IShellIconOverlay::GetOverlayIndex to obtain the overlay index. This will allow you to add additional overlay images in the future and allow applications to retrieve the correct overlay index without having to hard- code these indexes.

To maintain backward compatibility, the overlay indexes for the shared and shortcut overlays remain fixed.

Back to the top


APPLIES TO
Microsoft Platform Software Development Kit-January 2000 Edition, when used with:
  Microsoft Windows NT 4.0
Microsoft Windows NT Server 4.0 Standard Edition
Microsoft Windows NT Workstation 4.0 Developer Edition
Microsoft Internet Explorer 4.0 128-Bit Edition
Microsoft Internet Explorer 4.01 Service Pack 2

Back to the top

Keywords: 
kbshell kbprb KB192055

Back to the top

Article Translations

 

Other Support Options

  • Need More Help?
    Contact a Support professional by Email, Online or Phone.
  • Customer Service
    For non-technical assistance with product purchases, subscriptions, online services, events, training courses, corporate sales, piracy issues, and more.
  • Newsgroups
    Pose a question to other users. Discussion groups and Forums about specific Microsoft products, technologies, and services.