fileicon.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 27k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //---------------------------------------------------------------------------
  2. //
  3. // Copyright (c) Microsoft Corporation 1991-1992
  4. //
  5. // File: fileicon.c
  6. //
  7. //---------------------------------------------------------------------------
  8. #include "shellprv.h"
  9. #pragma  hdrstop
  10. #include "ovrlaymn.h"
  11. #include "fstreex.h"
  12. // REVIEW: More clean up should be done.
  13. BOOL _ShellImageListInit(int cxIcon, int cyIcon, int cxSmIcon, int cySmIcon, UINT flags, BOOL fRestore);
  14. BOOL _ShellImageListTerm(void);
  15. // global shell image lists owned by shelldll
  16. #pragma data_seg(DATASEG_SHARED)
  17. HIMAGELIST g_himlIcons = NULL;            // ImageList of large icons
  18. HIMAGELIST g_himlIconsSmall = NULL;       // ImageList of small icons
  19. int        g_ccIcon = 0;                // color depth of ImageLists
  20. int        g_MaxIcons = DEF_MAX_ICONS;  // panic limit for icons in cache
  21. int        g_lrFlags = 0;
  22. int g_cxIcon = 0;
  23. int g_cyIcon = 0;
  24. int g_cxSmIcon = 0;
  25. int g_cySmIcon = 0;
  26. #pragma data_seg()
  27. TCHAR const g_szMaxCachedIcons[]      = TEXT("Max Cached Icons");
  28. TCHAR const g_szShellIconSize[]       = TEXT("Shell Icon Size");
  29. TCHAR const g_szShellSmallIconSize[]  = TEXT("Shell Small Icon Size");
  30. TCHAR const g_szShellIconDepth[]      = TEXT("Shell Icon Bpp");
  31. TCHAR const g_szShellIcons[]          = TEXT("Shell Icons");
  32. TCHAR const g_szD[]                   = TEXT("%d");
  33. //
  34. // System imagelist - Don't change the order of this list.
  35. // If you need to add a new icon, add it to the end of the
  36. // array, and update shellp.h.
  37. //
  38. UINT const c_SystemImageListIndexes[] = { IDI_DOCUMENT,
  39.                                           IDI_DOCASSOC,
  40.                                           IDI_APP,
  41.                                           IDI_FOLDER,
  42.                                           IDI_FOLDEROPEN,
  43.                                           IDI_DRIVE525,
  44.                                           IDI_DRIVE35,
  45.                                           IDI_DRIVEREMOVE,
  46.                                           IDI_DRIVEFIXED,
  47.                                           IDI_DRIVENET,
  48.                                           IDI_DRIVENETDISABLED,
  49.                                           IDI_DRIVECD,
  50.                                           IDI_DRIVERAM,
  51.                                           IDI_WORLD,
  52.                                           IDI_NETWORK,
  53.                                           IDI_SERVER,
  54.                                           IDI_PRINTER,
  55.                                           IDI_MYNETWORK,
  56.                                           IDI_GROUP,
  57.                                           IDI_STPROGS,
  58.                                           IDI_STDOCS,
  59.                                           IDI_STSETNGS,
  60.                                           IDI_STFIND,
  61.                                           IDI_STHELP,
  62.                                           IDI_STRUN,
  63.                                           IDI_STSUSPEND,
  64.                                           IDI_STEJECT,
  65.                                           IDI_STSHUTD,
  66.                                           IDI_SHARE,
  67.                                           IDI_LINK,
  68.                                           IDI_SLOWFILE,
  69.                                           IDI_RECYCLER,
  70.                                           IDI_RECYCLERFULL,
  71.                                           IDI_RNA,
  72.                                           IDI_DESKTOP,
  73.                                           IDI_CPLFLD,
  74.                                           IDI_STSPROGS,
  75.                                           IDI_PRNFLD,
  76.                                           IDI_STFONTS,
  77.                                           IDI_STTASKBR,
  78.                                           IDI_CDAUDIO,
  79.                                           IDI_TREE,
  80.                                           IDI_STCPROGS,
  81.                                           IDI_STFAV,
  82.                                           IDI_STLOGOFF,
  83.                                           IDI_STFLDRPROP,
  84.                                           IDI_WINUPDATE
  85. #ifdef WINNT // hydra specific stuff
  86.                                           ,IDI_MU_SECURITY,
  87.                                           IDI_MU_DISCONN
  88. #endif
  89.                                           };
  90. int GetRegInt(HKEY hk, LPCTSTR szKey, int def)
  91. {
  92.     DWORD cb;
  93.     TCHAR ach[20];
  94.     if (hk == NULL)
  95.         return def;
  96.     ach[0] = 0;
  97.     cb = SIZEOF(ach);
  98.     SHQueryValueEx(hk, szKey, NULL, NULL, (LPBYTE)ach, &cb);
  99.     if (ach[0] >= TEXT('0') && ach[0] <= TEXT('9'))
  100.         return (int)StrToLong(ach);
  101.     else
  102.         return def;
  103. }
  104. //
  105. // get g_MaxIcons from the registry, returning TRUE if it has changed
  106. //
  107. BOOL QueryNewMaxIcons(void)
  108. {
  109.     int MaxIcons, OldMaxIcons;
  110.     MaxIcons = GetRegInt(g_hklmExplorer, g_szMaxCachedIcons, DEF_MAX_ICONS);
  111.     if (MaxIcons < 0)
  112.         MaxIcons = DEF_MAX_ICONS;
  113.     OldMaxIcons = InterlockedExchange(&g_MaxIcons, MaxIcons);
  114.     return (OldMaxIcons != MaxIcons);
  115. }
  116. //
  117. // Initializes shared resources for Shell_GetIconIndex and others
  118. //
  119. BOOL WINAPI FileIconInit( BOOL fRestoreCache )
  120. {
  121.     BOOL fNotify = FALSE;
  122.     BOOL fInit = FALSE;
  123.     HKEY hkey;
  124.     int cxIcon, cyIcon, ccIcon, cxSmIcon, cySmIcon, res;
  125. #ifndef WINNT
  126.     // Try always restoring cache because of:
  127.     //   BUGBUG (kurte): there appears to be a race condition on first boot
  128.     //   to initialize properly.  This started happening after our 3rd NT
  129.     //   merge.
  130.     //
  131.     // BOBDAY: Don't restore the cache always, it makes every NT process
  132.     // have a complete copy of the shell's icon cache (a very bad thing).
  133.     fRestoreCache=TRUE;
  134. #endif
  135.     QueryNewMaxIcons(); // in case the size of the icon cache has changed
  136.     ccIcon   = 0;
  137.     cxIcon   = GetSystemMetrics(SM_CXICON);
  138.     cyIcon   = GetSystemMetrics(SM_CYICON);
  139. ////cxSmIcon = GetSystemMetrics(SM_CXSMICON);
  140. ////cySmIcon = GetSystemMetrics(SM_CYSMICON);
  141.     cxSmIcon = GetSystemMetrics(SM_CXICON) / 2;
  142.     cySmIcon = GetSystemMetrics(SM_CYICON) / 2;
  143.     //
  144.     //  get the user prefered icon size (and color depth) from the
  145.     //  registry.
  146.     //
  147.     if (RegOpenKey(HKEY_CURRENT_USER, REGSTR_PATH_METRICS, &hkey) == 0)
  148.     {
  149.         cxIcon   = GetRegInt(hkey, g_szShellIconSize, cxIcon);
  150.         cxSmIcon = GetRegInt(hkey, g_szShellSmallIconSize, cxSmIcon);
  151.         ccIcon   = GetRegInt(hkey, g_szShellIconDepth, ccIcon);
  152.         cyIcon   = cxIcon;      // icons are always square
  153.         cySmIcon = cxSmIcon;
  154.         RegCloseKey(hkey);
  155.     }
  156.     res = (int)GetCurColorRes();
  157.     if (ccIcon > res)
  158.         ccIcon = 0;
  159.     if (res <= 8)
  160.         ccIcon = 0; // wouldn't have worked anyway
  161. #if 0
  162.     //
  163.     // use a 8bpp imagelist on a HiColor device iff we will
  164.     // be stretching icons.
  165.     //
  166.     if (res > 8 && ccIcon == 0 && (cxIcon != GetSystemMetrics(SM_CXICON) ||
  167.          cxSmIcon != GetSystemMetrics(SM_CXICON)/2))
  168.     {
  169.         ccIcon = 8;
  170.     }
  171. #endif
  172.     ENTERCRITICAL;
  173.     //
  174.     // if we already have a icon cache make sure it is the right size etc.
  175.     //
  176.     if (g_himlIcons)
  177.     {
  178.         // we now support changing the colour depth...
  179.         if (g_cxIcon   == cxIcon &&
  180.             g_cyIcon   == cyIcon &&
  181.             g_cxSmIcon == cxSmIcon &&
  182.             g_cySmIcon == cySmIcon &&
  183.             g_ccIcon   == ccIcon)
  184.         {
  185.             fInit = TRUE;
  186.             goto Exit;
  187.         }
  188.         FlushIconCache();
  189.         FlushFileClass();
  190.         // make sure every one updates.
  191.         fNotify = TRUE;
  192.     }
  193.     // if we are the desktop process (explorer.exe), then force us to re-init the cache, so we get
  194.     // the basic set of icons in the right order....
  195.     if ( !fRestoreCache && g_himlIcons && GetInProcDesktop() )
  196.     {
  197.         fRestoreCache = TRUE;
  198.     }
  199.     
  200.     g_cxIcon   = cxIcon;
  201.     g_cyIcon   = cyIcon;
  202.     g_ccIcon   = ccIcon;
  203.     g_cxSmIcon = cxSmIcon;
  204.     g_cySmIcon = cySmIcon;
  205.     if (res > 4 && g_ccIcon <= 4)
  206.         g_lrFlags = LR_VGACOLOR;
  207.     else
  208.         g_lrFlags = 0;
  209.     DebugMsg(DM_TRACE, TEXT("IconCache: Size=%dx%d SmSize=%dx%d Bpp=%d"), cxIcon, cyIcon, cxSmIcon, cySmIcon, (ccIcon&ILC_COLOR));
  210.     if (g_iLastSysIcon == 0)        // Keep track of which icons are perm.
  211.     {
  212.         if (fRestoreCache)
  213.             g_iLastSysIcon = II_LASTSYSICON;
  214.         else
  215.             g_iLastSysIcon = (II_OVERLAYLAST - II_OVERLAYFIRST) + 1;
  216.     }
  217.     // try to restore the icon cache (if we have not loaded it yet)
  218.     if (g_himlIcons != NULL || !fRestoreCache || !_IconCacheRestore(g_cxIcon, g_cyIcon, g_cxSmIcon, g_cySmIcon, g_ccIcon))
  219.     {
  220.         if (!_ShellImageListInit(g_cxIcon, g_cyIcon, g_cxSmIcon, g_cySmIcon, g_ccIcon, fRestoreCache))
  221.             goto Exit;
  222.     }
  223.     fInit = TRUE;
  224. Exit:
  225.     LEAVECRITICAL;
  226.     if (fInit && fNotify)
  227.     {
  228.         DebugMsg(DM_TRACE, TEXT("IconCache: icon size has changed sending SHCNE_UPDATEIMAGE(-1)..."));
  229.         SHChangeNotify(SHCNE_UPDATEIMAGE, SHCNF_DWORD, (LPCVOID)-1, NULL);
  230.     }
  231.     return fInit;
  232. }
  233. void FileIconTerm(void)
  234. {
  235.     ENTERCRITICAL;
  236.     _ShellImageListTerm();
  237.     LEAVECRITICAL;
  238. }
  239. /*************************************************************************
  240.  *************************************************************************/
  241. BOOL _ShellImageListInit(int cxIcon, int cyIcon, int cxSmIcon, int cySmIcon, UINT flags, BOOL fRestore)
  242. {
  243.     int  i;
  244.     IShellIconOverlayManager *psiom;
  245.     ASSERTCRITICAL;
  246.     //
  247.     // Check if we need to create a mirrored imagelist. [samera]
  248.     //
  249.     if (IS_BIDI_LOCALIZED_SYSTEM())
  250.     {
  251.         flags |= ILC_MIRROR;
  252.     }
  253.     
  254.     if (g_himlIcons == NULL) 
  255.     {
  256.         g_himlIcons = ImageList_Create(cxIcon, cyIcon, ILC_MASK|ILC_SHARED|flags, 0, 32);
  257.     }
  258.     else
  259.     {
  260.         // set the flags incase the colour depth has changed...
  261.         // ImageList_setFlags already calls ImageList_remove on success
  262.         if (!ImageList_SetFlags( g_himlIcons, ILC_MASK|ILC_SHARED|flags ))
  263.         {
  264.             // Couldn't change flags; tough.  At least remove them all.
  265.             ImageList_Remove(g_himlIcons, -1);
  266.         }
  267.         ImageList_SetIconSize(g_himlIcons, cxIcon, cyIcon);
  268.     }
  269.     if (g_himlIcons == NULL) 
  270.     {
  271.         return FALSE;
  272.     }
  273.     if (g_himlIconsSmall == NULL) 
  274.     {
  275.         g_himlIconsSmall = ImageList_Create(cxSmIcon, cySmIcon, ILC_MASK|ILC_SHARED|flags, 0, 32);
  276.     }
  277.     else 
  278.     {
  279.         // ImageList_setFlags already calls ImageList_remove on success
  280.         if (!ImageList_SetFlags( g_himlIconsSmall, ILC_MASK|ILC_SHARED|flags ))
  281.         {
  282.             // Couldn't change flags; tough.  At least remove them all.
  283.             ImageList_Remove(g_himlIconsSmall, -1);
  284.         }
  285.         ImageList_SetIconSize(g_himlIconsSmall, cxSmIcon, cySmIcon);
  286.     }
  287.     if (g_himlIconsSmall == NULL) 
  288.     {
  289.         ImageList_Destroy(g_himlIcons);
  290.         g_himlIcons = NULL;
  291.         return FALSE;
  292.     }
  293.     // set the bk colors to COLOR_WINDOW since this is what will
  294.     // be used most of the time as the bk for these lists (cabinet, tray)
  295.     // this avoids having to do ROPs when drawing, thus making it fast
  296.     ImageList_SetBkColor(g_himlIcons, GetSysColor(COLOR_WINDOW));
  297.     ImageList_SetBkColor(g_himlIconsSmall, GetSysColor(COLOR_WINDOW));
  298.     // Load all of the icons with fRestore == TRUE
  299.     if (fRestore)
  300.     {
  301.         TCHAR szModule[MAX_PATH];
  302.         HKEY hkeyIcons;
  303.         GetModuleFileName(HINST_THISDLL, szModule, ARRAYSIZE(szModule));
  304.         // WARNING: this code assumes that these icons are the first in
  305.         // our RC file and are in this order and these indexes correspond
  306.         // to the II_ constants in shell.h.
  307.         hkeyIcons = SHGetExplorerSubHkey(HKEY_LOCAL_MACHINE, g_szShellIcons, FALSE);
  308.         for (i = 0; i < ARRAYSIZE(c_SystemImageListIndexes); i++) 
  309.         {
  310.             HICON hIcon=NULL;
  311.             HICON hSmallIcon=NULL;
  312.             int iIndex;
  313.             // check to see if icon is overridden in the registry
  314.             if (hkeyIcons)
  315.             {
  316.                 TCHAR val[10];
  317.                 TCHAR ach[MAX_PATH];
  318.                 DWORD cb = SIZEOF(ach);
  319.                 wsprintf(val, g_szD, i);
  320.                 ach[0] = 0;
  321.                 SHQueryValueEx(hkeyIcons, val, NULL, NULL, (LPBYTE)ach, &cb);
  322.                 if (ach[0])
  323.                 {
  324.                     HICON hIcons[2] = {0, 0};
  325.                     int iIcon = PathParseIconLocation(ach);
  326.                     ExtractIcons(ach, iIcon,
  327.                                  MAKELONG(g_cxIcon,g_cxSmIcon),
  328.                                  MAKELONG(g_cyIcon,g_cySmIcon),
  329.                                  hIcons, NULL, 2, g_lrFlags);
  330.                     hIcon = hIcons[0];
  331.                     hSmallIcon = hIcons[1];
  332.                     if (hIcon)
  333.                     {
  334.                         DebugMsg(DM_TRACE, TEXT("ShellImageListInit: Got default icon #%d from registry: %s,%d"), i, ach, iIcon);
  335.                     }
  336.                 }
  337.             }
  338.             if (hIcon == NULL)
  339.             {
  340.                 hIcon      = LoadImage(HINST_THISDLL, MAKEINTRESOURCE(c_SystemImageListIndexes[i]), IMAGE_ICON, cxIcon, cyIcon, g_lrFlags);
  341.                 hSmallIcon = LoadImage(HINST_THISDLL, MAKEINTRESOURCE(c_SystemImageListIndexes[i]), IMAGE_ICON, cxSmIcon, cySmIcon, g_lrFlags);
  342.             }
  343.             if (hIcon)
  344.             {
  345.                 iIndex = SHAddIconsToCache(hIcon, hSmallIcon, szModule, i, 0);
  346.                 ASSERT(!fRestore || (iIndex == i));     // assume index
  347.             }
  348.         }
  349.         if (hkeyIcons)
  350.             RegCloseKey(hkeyIcons);
  351.     }
  352.     //
  353.     // Refresh the overlay image so that the overlays are added to the imaglist.
  354.     // GetIconOverlayManager() will initialize the overlay manager if necessary.
  355.     //
  356.     if (SUCCEEDED(GetIconOverlayManager(&psiom)))
  357.     {
  358.         psiom->lpVtbl->RefreshOverlayImages(psiom, SIOM_OVERLAYINDEX | SIOM_ICONINDEX);
  359.         psiom->lpVtbl->Release(psiom);
  360.     }
  361.     return TRUE;
  362. }
  363. BOOL _ShellImageListTerm(void)
  364. {
  365.     ENTERCRITICAL;
  366.     if (g_himlIcons) {
  367.         ImageList_Destroy(g_himlIcons);
  368.         g_himlIcons = NULL;
  369.     }
  370.     if (g_himlIconsSmall) {
  371.         ImageList_Destroy(g_himlIconsSmall);
  372.         g_himlIconsSmall = NULL;
  373.     }
  374.     LEAVECRITICAL;
  375.     return TRUE;
  376. }
  377. // get a hold of the system image lists
  378. BOOL WINAPI Shell_GetImageLists(HIMAGELIST *phiml, HIMAGELIST *phimlSmall)
  379. {
  380.     FileIconInit( FALSE );  // make sure they are created and the right size.
  381.     if (phiml)
  382.         *phiml = g_himlIcons;
  383.     if (phimlSmall)
  384.         *phimlSmall = g_himlIconsSmall;
  385.     return TRUE;
  386. }
  387. void WINAPI Shell_SysColorChange(void)
  388. {
  389.     COLORREF clrWindow;
  390.     ENTERCRITICAL;
  391.     clrWindow = GetSysColor(COLOR_WINDOW);
  392.     ImageList_SetBkColor(g_himlIcons     , clrWindow);
  393.     ImageList_SetBkColor(g_himlIconsSmall, clrWindow);
  394.     LEAVECRITICAL;
  395. }
  396. // simulate the document icon by crunching a copy of an icon and putting it in the
  397. // middle of our default document icon, then add it to the passsed image list
  398. //
  399. // in:
  400. //      hIcon   icon to use as a basis for the simulation
  401. //
  402. // returns:
  403. //      hicon
  404. HICON SimulateDocIcon(HIMAGELIST himl, HICON hIcon, BOOL fSmall)
  405. {
  406.     int cx = fSmall ? g_cxSmIcon : g_cxIcon;
  407.     int cy = fSmall ? g_cxSmIcon : g_cxIcon;
  408.     HDC hdc;
  409.     HDC hdcMem;
  410.     HBITMAP hbmMask;
  411.     HBITMAP hbmColor;
  412.     HBITMAP hbmT;
  413.     ICONINFO ii;
  414.     UINT iIndex;
  415.     if (himl == NULL || hIcon == NULL)
  416.         return NULL;
  417.     hdc = GetDC(NULL);
  418.     hdcMem = CreateCompatibleDC(hdc);
  419.     hbmColor = CreateCompatibleBitmap(hdc, cx, cy);
  420.     hbmMask = CreateBitmap(cx, cy, 1, 1, NULL);
  421.     ReleaseDC(NULL, hdc);
  422.     hbmT = SelectObject(hdcMem, hbmMask);
  423.     iIndex = Shell_GetCachedImageIndex(c_szShell32Dll, II_DOCNOASSOC, 0);
  424.     ImageList_Draw(himl, iIndex, hdcMem, 0, 0, ILD_MASK);
  425.     SelectObject(hdcMem, hbmColor);
  426.     ImageList_DrawEx(himl, iIndex, hdcMem, 0, 0, 0, 0, RGB(0,0,0), CLR_DEFAULT, ILD_NORMAL);
  427.     //BUGBUG this assumes the generic icon is white
  428.     PatBlt(hdcMem, cx/4-1, cy/4-1, cx/2+(fSmall?2:4), cy/2+2, WHITENESS);
  429.     DrawIconEx(hdcMem, cx/4, cy/4, hIcon, cx/2, cy/2, 0, NULL, DI_NORMAL);
  430.     SelectObject(hdcMem, hbmT);
  431.     DeleteDC(hdcMem);
  432.     ii.fIcon    = TRUE;
  433.     ii.xHotspot = 0;
  434.     ii.yHotspot = 0;
  435.     ii.hbmColor = hbmColor;
  436.     ii.hbmMask  = hbmMask;
  437.     hIcon = CreateIconIndirect(&ii);
  438.     DeleteObject(hbmColor);
  439.     DeleteObject(hbmMask);
  440.     return hIcon;
  441. }
  442. // add icons to the system imagelist (icon cache) and put the location
  443. // in the location cache
  444. //
  445. // in:
  446. //      hIcon, hIconSmall       the icons, hIconSmall can be NULL
  447. //      pszIconPath             locations (for location cache)
  448. //      iIconIndex              index in pszIconPath (for location cache)
  449. //      uIconFlags              GIL_ flags (for location cahce)
  450. // returns:
  451. //      location in system image list
  452. //
  453. int SHAddIconsToCache(HICON hIcon, HICON hIconSmall, LPCTSTR pszIconPath, int iIconIndex, UINT uIconFlags)
  454. {
  455.     int iImage;
  456.     int iImageSmall;
  457.     int iImageFree;
  458.     ASSERT(g_himlIcons);
  459.     if (hIcon == NULL)
  460.     {
  461.         SHDefExtractIcon(pszIconPath, iIconIndex, uIconFlags, &hIcon, &hIconSmall, 0);
  462.     }
  463.     if (hIcon == NULL)
  464.         return -1;
  465.     if (g_himlIcons == NULL)  // If we ran out of memory initing the icon cache
  466.         return -1;          // We'd better not play with the NULL image list.
  467.     if (hIconSmall == NULL)
  468.         hIconSmall = hIcon;  // ImageList_AddIcon will shrink for us
  469.     ENTERCRITICAL;
  470.     iImageFree = GetFreeImageIndex();
  471.     iImage = ImageList_ReplaceIcon(g_himlIcons, iImageFree, hIcon);
  472.     if (iImage >= 0)
  473.     {
  474.         iImageSmall = ImageList_ReplaceIcon(g_himlIconsSmall, iImageFree, hIconSmall);
  475.         if (iImageSmall < 0)
  476.         {
  477.             DebugMsg(DM_TRACE, TEXT("AddIconsToCache() ImageList_AddIcon failed (small)"));
  478.             // only remove it if it was added at the end otherwise all the
  479.             // index's above iImage will change.
  480.             // ImageList_ReplaceIcon should only fail on the end anyway.
  481.             if (iImageFree == -1)
  482.                 ImageList_Remove(g_himlIcons, iImage);   // remove big
  483.             iImage = -1;
  484.         }
  485.         else
  486.         {
  487.             ASSERT(iImageSmall == iImage);
  488.         }
  489.     }
  490.     else
  491.     {
  492.         DebugMsg(DM_TRACE, TEXT("AddIconsToCache() ImageList_AddIcon failed"));
  493.         iImage = -1;
  494.     }
  495.     if (iImage >= 0)
  496.         AddToIconTable(pszIconPath, iIconIndex, uIconFlags, iImage);
  497.     LEAVECRITICAL;
  498.     if (hIcon)
  499.         DestroyIcon(hIcon);
  500.     if (hIconSmall && hIcon != hIconSmall)
  501.         DestroyIcon(hIconSmall);
  502.     return iImage;
  503. }
  504. //
  505. //  default handler to extract a icon from a file
  506. //
  507. //  supports GIL_SIMULATEDOC
  508. //
  509. //  returns S_OK if success
  510. //  returns S_FALSE if the file has no icons (or not the asked for icon)
  511. //  returns E_FAIL for files on a slow link.
  512. //  returns E_FAIL if cant access the file
  513. //
  514. //  LOWORD(nIconSize) = normal icon size
  515. //  HIWORD(nIconSize) = smal icon size
  516. //
  517. STDAPI
  518. SHDefExtractIcon(LPCTSTR pszIconFile, int iIndex, UINT uFlags,
  519.         HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize)
  520. {
  521.     HICON hIcons[2] = {0, 0};
  522.     UINT u;
  523. #ifdef DEBUG
  524.     TCHAR ach[128];
  525.     GetModuleFileName(HINST_THISDLL, ach, ARRAYSIZE(ach));
  526.     if (lstrcmpi(pszIconFile, ach) == 0 && iIndex >= 0)
  527.     {
  528.         TraceMsg(TF_WARNING, "Re-extracting %d from SHELL32.DLL", iIndex);
  529.     }
  530. #endif
  531.     if (NULL == g_himlIcons)
  532.         FileIconInit( FALSE );  // make sure they are created and the right size.
  533.     //
  534.     //  get the icon from the file
  535.     //
  536.     if (PathIsSlow(pszIconFile, -1))
  537.     {
  538.         DebugMsg(DM_TRACE, TEXT("not extracting icon from '%s' because of slow link"), pszIconFile);
  539.         return E_FAIL;
  540.     }
  541. #ifdef XXDEBUG
  542.     TraceMsg(TF_ALWAYS, "Extracting icon %d from %s.", iIndex, pszIconFile);
  543.     Sleep(500);
  544. #endif
  545.     //
  546.     // nIconSize == 0 means use the default size.
  547.     // Backup is passing nIconSize == 1 need to support them too.
  548.     //
  549.     if (nIconSize <= 2)
  550.         nIconSize = MAKELONG(g_cxIcon, g_cxSmIcon);
  551.     if (uFlags & GIL_SIMULATEDOC)
  552.     {
  553.         HICON hIconSmall;
  554.         u = ExtractIcons(pszIconFile, iIndex, g_cxSmIcon, g_cySmIcon,
  555.             &hIconSmall, NULL, 1, g_lrFlags);
  556.         if (u == -1)
  557.             return E_FAIL;
  558.         hIcons[0] = SimulateDocIcon(g_himlIcons, hIconSmall, FALSE);
  559.         hIcons[1] = SimulateDocIcon(g_himlIconsSmall, hIconSmall, TRUE);
  560.         if (hIconSmall)
  561.             DestroyIcon(hIconSmall);
  562.     }
  563.     else
  564.     {
  565.         u = ExtractIcons(pszIconFile, iIndex, nIconSize, nIconSize,
  566.             hIcons, NULL, 2, g_lrFlags);
  567.         if (-1 == u)
  568.             return E_FAIL;
  569. #ifdef DEBUG
  570.         if (0 == u)
  571.         {
  572.             TraceMsg(TF_WARNING, "Failed to extract icon %d from %s.", iIndex, pszIconFile);    
  573.         }
  574. #endif
  575.     }
  576.     *phiconLarge = hIcons[0];
  577.     *phiconSmall = hIcons[1];
  578.     return u==0 ? S_FALSE : S_OK;
  579. }
  580. #ifdef UNICODE
  581. STDAPI
  582. SHDefExtractIconA(
  583.     LPCSTR pszIconFile,
  584.     int iIndex,
  585.     UINT uFlags,
  586.     HICON *phiconLarge,
  587.     HICON *phiconSmall,
  588.     UINT nIconSize)
  589. {
  590.     HRESULT hres = E_INVALIDARG;
  591.     if (IS_VALID_STRING_PTRA(pszIconFile, -1))
  592.     {
  593.         WCHAR wsz[MAX_PATH];
  594.         SHAnsiToUnicode(pszIconFile, wsz, ARRAYSIZE(wsz));
  595.         hres = SHDefExtractIcon(wsz, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
  596.     }
  597.     return hres;
  598. }
  599. #else
  600. STDAPI
  601. SHDefExtractIconW(
  602.     LPCWSTR pszIconFile,
  603.     int iIndex,
  604.     UINT uFlags,
  605.     HICON *phiconLarge,
  606.     HICON *phiconSmall,
  607.     UINT nIconSize)
  608. {
  609.     HRESULT hres = E_INVALIDARG;
  610.     if (IS_VALID_STRING_PTRW(pszIconFile, -1))
  611.     {
  612.         char sz[MAX_PATH];
  613.         SHUnicodeToAnsi(pszIconFile, sz, ARRAYSIZE(sz));
  614.         hres = SHDefExtractIcon(sz, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
  615.     }
  616.     return hres;
  617. }
  618. #endif
  619. //
  620. // in:
  621. //      pszIconPath     file to get icon from (eg. cabinet.exe)
  622. //      iIconIndex      icon index in pszIconPath to get
  623. //      uIconFlags      GIL_ values indicating simulate doc icon, etc.
  624. int WINAPI Shell_GetCachedImageIndex(LPCTSTR pszIconPath, int iIconIndex, UINT uIconFlags)
  625. {
  626.     int iImageIndex;
  627.     // lots of random codepaths from APIs end up here before init
  628.     if (g_himlIcons == NULL)
  629.         FileIconInit( FALSE );
  630.     iImageIndex = LookupIconIndex(PathFindFileName(pszIconPath), iIconIndex, uIconFlags);
  631.     if (iImageIndex == -1)
  632.     {
  633.         iImageIndex = SHAddIconsToCache(NULL, NULL, pszIconPath, iIconIndex, uIconFlags);
  634.     }
  635.     return iImageIndex;
  636. }
  637. STDAPI_(void) FixPlusIcons()
  638. {
  639.     int i;
  640.     // nuke all of the shell internal icons
  641.     {
  642.         HKEY hkeyIcons = SHGetExplorerSubHkey(HKEY_LOCAL_MACHINE, g_szShellIcons, FALSE);
  643.         if (hkeyIcons)
  644.         {
  645.             for (i = 0; i < ARRAYSIZE(c_SystemImageListIndexes); i++) 
  646.             {
  647.                 TCHAR szRegPath[10], szBuf[MAX_PATH];
  648.                 DWORD cb = SIZEOF(szBuf);
  649.                 wsprintf(szRegPath, g_szD, i);
  650.                 if (SHQueryValueEx(hkeyIcons, szRegPath, NULL, NULL, (LPBYTE)szBuf, &cb) == ERROR_SUCCESS &&
  651.                     StrStrI(szBuf, TEXT("cool.dll")))
  652.                 {
  653.                     RegDeleteValue(hkeyIcons, szRegPath);
  654.                 }
  655.             }
  656.             RegCloseKey(hkeyIcons);
  657.         }
  658.     }
  659.     // all of the DefaultIcons under the CLSIDs for shell folders
  660.     {
  661.         static const struct {
  662.             REFCLSID clsid;
  663.             LPCTSTR pszIcon;
  664.         } c_rgCLSID[] = {
  665.             { &CLSID_NetworkPlaces,     TEXT("shell32.dll,17") },
  666.             { &CLSID_ControlPanel,      TEXT("shell32.dll,-137") },
  667.             { &CLSID_Printers,          TEXT("shell32.dll,-138") },
  668.             { &CLSID_MyComputer,        TEXT("explorer.exe,0") },
  669.             { &CLSID_Remote,            TEXT("rnaui.dll,0") },
  670.             { &CLSID_CFonts,            TEXT("fontext.dll,-101") },
  671.             { &CLSID_RecycleBin,        NULL },
  672.             { &CLSID_Briefcase,         NULL },
  673.         };
  674.         for (i = 0; i < ARRAYSIZE(c_rgCLSID); i++)
  675.         {
  676.             TCHAR szCLSID[64], szRegPath[128], szBuf[MAX_PATH];
  677.             DWORD cb = SIZEOF(szBuf);
  678.             SHStringFromGUID(c_rgCLSID[i].clsid, szCLSID, ARRAYSIZE(szCLSID));
  679.             wsprintf(szRegPath, TEXT("CLSID\%s\DefaultIcon"), szCLSID);
  680.             if (SHRegQueryValue(HKEY_CLASSES_ROOT, szRegPath, szBuf, &cb) == ERROR_SUCCESS &&
  681.                 StrStrI(szBuf, TEXT("cool.dll")))
  682.             {
  683.                 if (IsEqualGUID(c_rgCLSID[i].clsid, &CLSID_RecycleBin))
  684.                 {
  685.                     RegSetValueString(HKEY_CLASSES_ROOT, szRegPath, TEXT("Empty"), TEXT("shell32.dll,31"));
  686.                     RegSetValueString(HKEY_CLASSES_ROOT, szRegPath, TEXT("Full"), TEXT("shell32.dll,32"));
  687.                     if (StrStr(szBuf, TEXT("20")))
  688.                         RegSetString(HKEY_CLASSES_ROOT, szRegPath, TEXT("shell32.dll,31")); // empty
  689.                     else
  690.                         RegSetString(HKEY_CLASSES_ROOT, szRegPath, TEXT("shell32.dll,32")); // full
  691.                 }
  692.                 else
  693.                 {
  694.                     if (c_rgCLSID[i].pszIcon)
  695.                         RegSetString(HKEY_CLASSES_ROOT, szRegPath, c_rgCLSID[i].pszIcon);
  696.                     else
  697.                         RegDeleteValue(HKEY_CLASSES_ROOT, szRegPath);
  698.                 }
  699.             }
  700.         }
  701.     }
  702.     // all of the DefaultIcons under the ProgIDs for file types
  703.     {
  704.         static const struct {
  705.             LPCTSTR pszProgID;
  706.             LPCTSTR pszIcon;
  707.         } c_rgProgID[] = {
  708.             { TEXT("Folder"),   TEXT("shell32.dll,3") },
  709.             { TEXT("Directory"),TEXT("shell32.dll,3") },
  710.             { TEXT("Drive"),    TEXT("shell32.dll,8") },
  711.             { TEXT("drvfile"),  TEXT("shell32.dll,-154") },
  712.             { TEXT("vxdfile"),  TEXT("shell32.dll,-154") },
  713.             { TEXT("dllfile"),  TEXT("shell32.dll,-154") },
  714.             { TEXT("sysfile"),  TEXT("shell32.dll,-154") },
  715.             { TEXT("txtfile"),  TEXT("shell32.dll,-152") },
  716.             { TEXT("inifile"),  TEXT("shell32.dll,-151") },
  717.             { TEXT("inffile"),  TEXT("shell32.dll,-151") },
  718.         };
  719.         for (i = 0; i < ARRAYSIZE(c_rgProgID); i++)
  720.         {
  721.             TCHAR szRegPath[128], szBuf[MAX_PATH];
  722.             DWORD cb = SIZEOF(szBuf);
  723.             wsprintf(szRegPath, TEXT("%s\DefaultIcon"), c_rgProgID[i].pszProgID);
  724.             if (SHRegQueryValue(HKEY_CLASSES_ROOT, szRegPath, szBuf, &cb) == ERROR_SUCCESS &&
  725.                 StrStrI(szBuf, TEXT("cool.dll")))
  726.             {
  727.                 RegSetString(HKEY_CLASSES_ROOT, szRegPath, c_rgProgID[i].pszIcon);
  728.             }
  729.         }
  730.     }
  731.     FlushIconCache();
  732. }