[ros-diffs] [martinf] 35: explorer: add icon cache mapped by shell paths (PIDLs) to fix GDI handle leaks

martinf at svn.reactos.org martinf at svn.reactos.org
Sun Jan 29 16:28:22 CET 2006


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);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.reactos.org/pipermail/ros-diffs/attachments/20060129/1617ed34/attachment-0002.html


More information about the Ros-diffs mailing list