explorer: add icon cache mapped by shell paths (PIDLs) to fix GDI handle
leaks
Modified: trunk/reactos/base/shell/explorer/explorer.cpp
Modified: trunk/reactos/base/shell/explorer/globals.h
Modified: trunk/reactos/base/shell/explorer/notifyhook/notifyhook.dsp
Modified: trunk/reactos/base/shell/explorer/shell/entries.cpp
Modified: trunk/reactos/base/shell/explorer/utility/shellclasses.h
Modified: trunk/reactos/base/shell/explorer/utility/window.cpp
  _____
Modified: trunk/reactos/base/shell/explorer/explorer.cpp
--- trunk/reactos/base/shell/explorer/explorer.cpp      2006-01-29
15:15:23 UTC (rev 34)
+++ trunk/reactos/base/shell/explorer/explorer.cpp      2006-01-29
15:28:15 UTC (rev 35)
@@ -95,7 +95,7 @@
        if (!_cfg.read(_cfg_path)) {
                if (_cfg._last_error != XML_ERROR_NO_ELEMENTS)
-                       MessageBox(g_Globals._hwndDesktop,
String(_cfg._last_error_msg.c_str()),
+                       MessageBox(_hwndDesktop,
String(_cfg._last_error_msg.c_str()),
                                                TEXT("ROS Explorer -
reading user settings"), MB_OK);
                _cfg.read(TEXT("explorer-cfg-template.xml"));
@@ -540,6 +540,73 @@
        return _icons[ICID_NONE];
 }
+const Icon&        IconCache::extract(LPCITEMIDLIST pidl, ICONCACHE_FLAGS
flags)
+{
+        // search for matching icon with unchanged flags in the cache
+       PidlCacheKey mapkey(pidl, flags);
+       PidlCacheMap::iterator found = _pidlcache.find(mapkey);
+
+       if (found != _pidlcache.end())
+               return _icons[found->second];
+
+        // search for matching icon with handle
+       PidlCacheKey mapkey_hicon(pidl, flags|ICF_HICON);
+       if (flags != mapkey_hicon.second) {
+               found = _pidlcache.find(mapkey_hicon);
+
+               if (found != _pidlcache.end())
+                       return _icons[found->second];
+       }
+
+        // search for matching icon in the system image list cache
+       PidlCacheKey mapkey_syscache(pidl, flags|ICF_SYSCACHE);
+       if (flags != mapkey_syscache.second) {
+               found = _pidlcache.find(mapkey_syscache);
+
+               if (found != _pidlcache.end())
+                       return _icons[found->second];
+       }
+
+       SHFILEINFO sfi;
+
+       int shgfi_flags = SHGFI_PIDL;
+
+       if (!(flags & (ICF_LARGE|ICF_MIDDLE)))
+               shgfi_flags |= SHGFI_SMALLICON;
+
+       if (flags & ICF_OPEN)
+               shgfi_flags |= SHGFI_OPENICON;
+
+       if (flags & ICF_SYSCACHE) {
+               assert(!(flags&ICF_OVERLAYS));
+
+               HIMAGELIST himlSys = (HIMAGELIST)
SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi),
SHGFI_SYSICONINDEX|shgfi_flags);
+               if (himlSys) {
+                       const Icon& icon = add(sfi.iIcon/*,
IT_SYSCACHE*/);
+
+                       ///@todo limit cache size
+                       _pidlcache[mapkey_syscache] = icon;
+
+                       return icon;
+               }
+       } else {
+               if (flags & ICF_OVERLAYS)
+                       shgfi_flags |= SHGFI_ADDOVERLAYS;
+
+               if (SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi),
SHGFI_ICON|shgfi_flags)) {
+                       const Icon& icon = add(sfi.hIcon, IT_CACHED);
+
+                       ///@todo limit cache size
+                       _pidlcache[mapkey_hicon] = icon;
+
+                       return icon;
+               }
+       }
+
+       return _icons[ICID_NONE];
+}
+
+
 const Icon& IconCache::add(HICON hIcon, ICON_TYPE type)
 {
        int id = ++s_next_id;
  _____
Modified: trunk/reactos/base/shell/explorer/globals.h
--- trunk/reactos/base/shell/explorer/globals.h 2006-01-29 15:15:23 UTC
(rev 34)
+++ trunk/reactos/base/shell/explorer/globals.h 2006-01-29 15:28:15 UTC
(rev 35)
@@ -130,6 +130,7 @@
        const Icon& extract(LPCTSTR path, ICONCACHE_FLAGS
flags=ICF_NORMAL);
        const Icon& extract(LPCTSTR path, int icon_idx,
ICONCACHE_FLAGS flags=ICF_HICON);
        const Icon& extract(IExtractIcon* pExtract, LPCTSTR path,
int icon_idx, ICONCACHE_FLAGS flags=ICF_HICON);
+       const Icon& extract(LPCITEMIDLIST pidl, ICONCACHE_FLAGS
flags=ICF_NORMAL);
        const Icon& add(HICON hIcon, ICON_TYPE type=IT_DYNAMIC);
        const Icon& add(int sys_idx/*, ICON_TYPE
type=IT_SYSCACHE*/);
@@ -154,6 +155,10 @@
        typedef map<IdxCacheKey, ICON_ID> IdxCacheMap;
        IdxCacheMap _idxCache;
+       typedef pair<ShellPath,int/*ICONCACHE_FLAGS*/> PidlCacheKey;
+       typedef map<PidlCacheKey, ICON_ID> PidlCacheMap;
+       PidlCacheMap _pidlcache;
+
        HIMAGELIST _himlSys_small;
 };
@@ -165,7 +170,7 @@
 #define STARTMENUROOT_ICON_SIZE                ICON_SIZE_MIDDLE
// ICON_SIZE_LARGE
 #define ICON_SIZE_FROM_ICF(flags)      (flags&ICF_LARGE?
ICON_SIZE_LARGE: flags&ICF_MIDDLE? ICON_SIZE_MIDDLE: ICON_SIZE_SMALL)
-#define ICF_FROM_ICON_SIZE(size)       (size>=ICON_SIZE_LARGE?
ICF_LARGE: size>=ICON_SIZE_MIDDLE? ICF_MIDDLE: ICF_NORMAL)
+#define ICF_FROM_ICON_SIZE(size)       (size>=ICON_SIZE_LARGE?
ICF_LARGE: size>=ICON_SIZE_MIDDLE? ICF_MIDDLE: (ICONCACHE_FLAGS)0)
  /// create a bitmap from an icon
  _____
Modified: trunk/reactos/base/shell/explorer/notifyhook/notifyhook.dsp
--- trunk/reactos/base/shell/explorer/notifyhook/notifyhook.dsp
2006-01-29 15:15:23 UTC (rev 34)
+++ trunk/reactos/base/shell/explorer/notifyhook/notifyhook.dsp
2006-01-29 15:28:15 UTC (rev 35)
@@ -132,5 +132,9 @@
 SOURCE=.\notifyhook.rbuild
 # End Source File
+# Begin Source File
+
+SOURCE=..\utility\utility.h
+# End Source File
 # End Target
 # End Project
  _____
Modified: trunk/reactos/base/shell/explorer/shell/entries.cpp
--- trunk/reactos/base/shell/explorer/shell/entries.cpp 2006-01-29
15:15:23 UTC (rev 34)
+++ trunk/reactos/base/shell/explorer/shell/entries.cpp 2006-01-29
15:28:15 UTC (rev 35)
@@ -413,32 +413,10 @@
                }
                if (icon_id == ICID_NONE) {
-                       SHFILEINFO sfi;
-
                        const ShellPath& pidl_abs =
create_absolute_pidl();
                        LPCITEMIDLIST pidl = pidl_abs;
-                       int shgfi_flags = SHGFI_PIDL;
-
-                       if (!(flags & (ICF_LARGE|ICF_MIDDLE)))
-                               shgfi_flags |= SHGFI_SMALLICON;
-
-                       if (flags & ICF_OPEN)
-                               shgfi_flags |= SHGFI_OPENICON;
-
-                       if (flags & ICF_SYSCACHE) {
-                               assert(!(flags&ICF_OVERLAYS));
-
-                               HIMAGELIST himlSys = (HIMAGELIST)
SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi),
SHGFI_SYSICONINDEX|shgfi_flags);
-                               if (himlSys)
-                                       icon_id =
g_Globals._icon_cache.add(sfi.iIcon);
-                       } else {
-                               if (flags & ICF_OVERLAYS)
-                                       shgfi_flags |=
SHGFI_ADDOVERLAYS;
-
-                               if (SHGetFileInfo((LPCTSTR)pidl, 0,
&sfi, sizeof(sfi), SHGFI_ICON|shgfi_flags))
-                                       icon_id =
g_Globals._icon_cache.add(sfi.hIcon);
-                       }
+                       icon_id = g_Globals._icon_cache.extract(pidl,
flags);
                }
        }
  _____
Modified: trunk/reactos/base/shell/explorer/utility/shellclasses.h
--- trunk/reactos/base/shell/explorer/utility/shellclasses.h
2006-01-29 15:15:23 UTC (rev 34)
+++ trunk/reactos/base/shell/explorer/utility/shellclasses.h
2006-01-29 15:28:15 UTC (rev 35)
@@ -791,6 +791,18 @@
                _p = (ITEMIDLIST*)p;
        }
+       friend bool operator<(const ShellPath& a, const ShellPath& b)
+       {
+               int la = ILGetSize(a._p);
+               int lb = ILGetSize(b._p);
+
+               int r = memcmp(a._p, b._p, min(la, lb));
+               if (r)
+                       return r < 0;
+               else
+                       return la < lb;
+       }
+
        void assign(LPCITEMIDLIST pidl, size_t size)
        {
                //CONTEXT("ShellPath::assign(LPCITEMIDLIST, size_t)");
  _____
Modified: trunk/reactos/base/shell/explorer/utility/window.cpp
--- trunk/reactos/base/shell/explorer/utility/window.cpp
2006-01-29 15:15:23 UTC (rev 34)
+++ trunk/reactos/base/shell/explorer/utility/window.cpp
2006-01-29 15:28:15 UTC (rev 35)
@@ -392,7 +392,7 @@
                ClientRect rt(_hwnd);
                rt.left = _split_pos-SPLIT_WIDTH/2;
                rt.right = _split_pos+SPLIT_WIDTH/2+1;
-               HBRUSH lastBrush = SelectBrush(canvas,
GetStockBrush(LTGRAY_BRUSH));
+               HBRUSH lastBrush = SelectBrush(canvas,
GetStockBrush(COLOR_SPLITBAR));
                Rectangle(canvas, rt.left, rt.top-1, rt.right,
rt.bottom+1);
         SetRect(&rc, rt.left, rt.top-1, rt.right, rt.bottom+1);
         DrawEdge(canvas, &rc, EDGE_RAISED, BF_RECT);