- refactor icon cache
- display icon overlays in Explorer tree view
Modified: trunk/reactos/subsys/system/explorer/dialogs/searchprogram.cpp
Modified: trunk/reactos/subsys/system/explorer/doc/changes.txt
Modified: trunk/reactos/subsys/system/explorer/explorer.cpp
Modified: trunk/reactos/subsys/system/explorer/globals.h
Modified: trunk/reactos/subsys/system/explorer/shell/entries.cpp
Modified: trunk/reactos/subsys/system/explorer/shell/entries.h
Modified: trunk/reactos/subsys/system/explorer/shell/mainframe.cpp
Modified: trunk/reactos/subsys/system/explorer/shell/shellbrowser.cpp
Modified: trunk/reactos/subsys/system/explorer/shell/shellbrowser.h
Modified: trunk/reactos/subsys/system/explorer/shell/shellfs.cpp
Modified: trunk/reactos/subsys/system/explorer/shell/shellfs.h
Modified: trunk/reactos/subsys/system/explorer/taskbar/desktopbar.cpp
Modified: trunk/reactos/subsys/system/explorer/taskbar/quicklaunch.cpp
Modified: trunk/reactos/subsys/system/explorer/taskbar/startmenu.cpp
Modified: trunk/reactos/subsys/system/explorer/taskbar/startmenu.h
Modified: trunk/reactos/subsys/system/explorer/utility/utility.h

Modified: trunk/reactos/subsys/system/explorer/dialogs/searchprogram.cpp
--- trunk/reactos/subsys/system/explorer/dialogs/searchprogram.cpp	2005-12-28 14:55:22 UTC (rev 20395)
+++ trunk/reactos/subsys/system/explorer/dialogs/searchprogram.cpp	2005-12-28 16:14:10 UTC (rev 20396)
@@ -344,7 +344,7 @@
 				Entry* entry = cache_entry._entry;
 
 				if (entry->_icon_id == ICID_UNKNOWN)
-					entry->extract_icon(false);
+					entry->_icon_id = entry->extract_icon(ICF_SYSCACHE);
 
 				pDispInfo->item.iImage = g_Globals._icon_cache.get_icon(entry->_icon_id).get_sysiml_idx();
 				pDispInfo->item.mask |= LVIF_DI_SETITEM;

Modified: trunk/reactos/subsys/system/explorer/doc/changes.txt
--- trunk/reactos/subsys/system/explorer/doc/changes.txt	2005-12-28 14:55:22 UTC (rev 20395)
+++ trunk/reactos/subsys/system/explorer/doc/changes.txt	2005-12-28 16:14:10 UTC (rev 20396)
@@ -166,3 +166,4 @@
 			m. fuchs	replace "search computer" start menu entry by a "not yet implemented" message
 01.11.2005	m. fuchs	String::str(), String::toLower() to allow conventient and WINE compatible string conversions
 29.11.2005	m. fuchs	Adjustments for Visual Studio 2005: use new secure CT functions, COUNTOF for buffer sizes
+28.12.2005	m. fuchs	display icon overlays in Explorer tree view

Modified: trunk/reactos/subsys/system/explorer/explorer.cpp
--- trunk/reactos/subsys/system/explorer/explorer.cpp	2005-12-28 14:55:22 UTC (rev 20395)
+++ trunk/reactos/subsys/system/explorer/explorer.cpp	2005-12-28 16:14:10 UTC (rev 20396)
@@ -322,7 +322,7 @@
 	return ret;
 }
 
-HBITMAP create_bitmap_from_icon(HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd/*, bool big_icons*/)
+HBITMAP create_bitmap_from_icon(HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd/*, bool large_icons*/)
 {
 	int cx = GetSystemMetrics(SM_CXSMICON);	//ICON_SIZE_X;
 	int cy = GetSystemMetrics(SM_CYSMICON);	//ICON_SIZE_Y;
@@ -396,27 +396,65 @@
 }
 
 
-const Icon& IconCache::extract(LPCTSTR path, bool big_icons)
+const Icon& IconCache::extract(LPCTSTR path, ICONCACHE_FLAGS flags)
 {
-	PathMap::iterator found = _pathMap.find(path);
+	 // search for matching icon with unchanged flags in the cache
+	CacheKey mapkey(path, flags);
+	PathCacheMap::iterator found = _pathCache.find(mapkey);
 
-	if (found != _pathMap.end())
+	if (found != _pathCache.end())
 		return _icons[found->second];
 
+	 // search for matching icon with handle
+	CacheKey mapkey_hicon(path, flags|ICF_HICON);
+	if (flags != mapkey_hicon.second) {
+		found = _pathCache.find(mapkey_hicon);
+
+		if (found != _pathCache.end())
+			return _icons[found->second];
+	}
+
+	 // search for matching icon in the system image list cache
+	CacheKey mapkey_syscache(path, flags|ICF_SYSCACHE);
+	if (flags != mapkey_syscache.second) {
+		found = _pathCache.find(mapkey_syscache);
+
+		if (found != _pathCache.end())
+			return _icons[found->second];
+	}
+
 	SHFILEINFO sfi;
 
-	if (big_icons) {
-		if (SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_ICON)) {
+	int shgfi_flags = 0;
+
+	if (flags & ICF_OPEN)
+		shgfi_flags |= SHGFI_OPENICON;
+
+	if ((flags&(ICF_LARGE|ICF_OVERLAYS|ICF_HICON)) && !(flags&ICF_SYSCACHE)) {
+		shgfi_flags |= SHGFI_ICON;
+
+		if (!(flags & ICF_LARGE))
+			shgfi_flags |= SHGFI_SMALLICON;
+
+		if (flags & ICF_OVERLAYS)
+			shgfi_flags |= SHGFI_ADDOVERLAYS;
+
+		 // get small/big icons with/without overlays
+		if (SHGetFileInfo(path, 0, &sfi, sizeof(sfi), shgfi_flags)) {
 			const Icon& icon = add(sfi.hIcon, IT_CACHED);
 
 			///@todo limit cache size
-			_pathMap[path] = icon;
+			_pathCache[mapkey_hicon] = icon;
 
 			return icon;
 		}
 	} else {
+		assert(!(flags&ICF_OVERLAYS));
+
+		shgfi_flags |= SHGFI_SYSICONINDEX|SHGFI_SMALLICON;
+
 		 // use system image list - the "search program dialog" needs it
-		HIMAGELIST himlSys_small = (HIMAGELIST) SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX|SHGFI_SMALLICON);
+		HIMAGELIST himlSys_small = (HIMAGELIST) SHGetFileInfo(path, 0, &sfi, sizeof(sfi), shgfi_flags);
 
 		if (himlSys_small) {
 			_himlSys_small = himlSys_small;
@@ -424,7 +462,7 @@
 			const Icon& icon = add(sfi.iIcon/*, IT_SYSCACHE*/);
 
 			///@todo limit cache size
-			_pathMap[path] = icon;
+			_pathCache[mapkey_syscache] = icon;
 
 			return icon;
 		}
@@ -433,15 +471,15 @@
 	return _icons[ICID_NONE];
 }
 
-const Icon& IconCache::extract(LPCTSTR path, int idx)
+const Icon& IconCache::extract(LPCTSTR path, int idx, ICONCACHE_FLAGS flags)
 {
-	CachePair key(path, idx);
+	IdxCacheKey key(path, make_pair(idx, (flags|ICF_HICON)&~ICF_SYSCACHE));
 
 	key.first.toLower();
 
-	PathIdxMap::iterator found = _pathIdxMap.find(key);
+	IdxCacheMap::iterator found = _idxCache.find(key);
 
-	if (found != _pathIdxMap.end())
+	if (found != _idxCache.end())
 		return _icons[found->second];
 
 	HICON hIcon;
@@ -449,7 +487,7 @@
 	if ((int)ExtractIconEx(path, idx, NULL, &hIcon, 1) > 0) {
 		const Icon& icon = add(hIcon, IT_CACHED);
 
-		_pathIdxMap[key] = icon;
+		_idxCache[key] = icon;
 
 		return icon;
 	} else {
@@ -460,15 +498,16 @@
 	}
 }
 
-const Icon& IconCache::extract(IExtractIcon* pExtract, LPCTSTR path, int idx, bool big_icons)
+const Icon& IconCache::extract(IExtractIcon* pExtract, LPCTSTR path, int idx, ICONCACHE_FLAGS flags)
 {
 	HICON hIconLarge = 0;
 	HICON hIcon;
 
+	bool large_icons = flags & ICF_LARGE;
 	HRESULT hr = pExtract->Extract(path, idx, &hIconLarge, &hIcon, MAKELONG(GetSystemMetrics(SM_CXICON), ICON_SIZE_X));
 
 	if (hr == NOERROR) {	//@@ oder SUCCEEDED(hr) ?
-		if (big_icons) {	//@@ OK?
+		if (large_icons) {	//@@ OK?
 			if (hIcon)
 				DestroyIcon(hIcon);
 
@@ -479,7 +518,7 @@
 		}
 
 		if (hIcon)
-			return add(hIcon);
+			return add(hIcon);	//@@ When do we want not to free this icons?
 	}
 
 	return _icons[ICID_NONE];

Modified: trunk/reactos/subsys/system/explorer/globals.h
--- trunk/reactos/subsys/system/explorer/globals.h	2005-12-28 14:55:22 UTC (rev 20395)
+++ trunk/reactos/subsys/system/explorer/globals.h	2005-12-28 16:14:10 UTC (rev 20396)
@@ -98,6 +98,7 @@
 	int		add_to_imagelist(HIMAGELIST himl, HDC hdc_wnd, COLORREF bk_color=GetSysColor(COLOR_WINDOW), HBRUSH bk_brush=GetSysColorBrush(COLOR_WINDOW)) const;
 
 	int		get_sysiml_idx() const {return _itype==IT_SYSCACHE? _sys_idx: -1;}
+	HICON	get_hicon() const {return _itype!=IT_SYSCACHE? _hicon: 0;}
 
 	bool	destroy() {if (_itype == IT_DYNAMIC) {DestroyIcon(_hicon); return true;} else return false;}
 
@@ -118,9 +119,9 @@
 
 	void	init();
 
-	const Icon&	extract(LPCTSTR path, bool big_icons);
-	const Icon&	extract(LPCTSTR path, int idx);
-	const Icon&	extract(IExtractIcon* pExtract, LPCTSTR path, int idx, bool big_icons);
+	const Icon&	extract(LPCTSTR path, ICONCACHE_FLAGS flags=ICF_NORMAL);
+	const Icon&	extract(LPCTSTR path, int idx, ICONCACHE_FLAGS flags=ICF_HICON);
+	const Icon&	extract(IExtractIcon* pExtract, LPCTSTR path, int idx, ICONCACHE_FLAGS flags=ICF_HICON);
 
 	const Icon&	add(HICON hIcon, ICON_TYPE type=IT_DYNAMIC);
 	const Icon&	add(int sys_idx/*, ICON_TYPE type=IT_SYSCACHE*/);
@@ -137,23 +138,24 @@
 	typedef map<int, Icon> IconMap;
 	IconMap	_icons;
 
-	typedef map<String, ICON_ID> PathMap;
-	PathMap	_pathMap;
+	typedef pair<String,int/*ICONCACHE_FLAGS*/> CacheKey;
+	typedef map<CacheKey, ICON_ID> PathCacheMap;
+	PathCacheMap _pathCache;
 
-	typedef pair<String, int> CachePair;
-	typedef map<CachePair, ICON_ID> PathIdxMap;
-	PathIdxMap _pathIdxMap;
+	typedef pair<String,pair<int,int/*ICONCACHE_FLAGS*/> > IdxCacheKey;
+	typedef map<IdxCacheKey, ICON_ID> IdxCacheMap;
+	IdxCacheMap _idxCache;
 
 	HIMAGELIST _himlSys_small;
 };
 
 
-#define	ICON_SIZE_X		GetSystemMetrics(big_icons? SM_CXICON: SM_CXSMICON)
-#define	ICON_SIZE_Y		GetSystemMetrics(big_icons? SM_CYICON: SM_CYSMICON)
+#define	ICON_SIZE_X		GetSystemMetrics(large_icons? SM_CXICON: SM_CXSMICON)
+#define	ICON_SIZE_Y		GetSystemMetrics(large_icons? SM_CYICON: SM_CYSMICON)
 
 
  /// create a bitmap from an icon
-extern HBITMAP create_bitmap_from_icon(HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd/*, bool big_icons*/);
+extern HBITMAP create_bitmap_from_icon(HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd/*, bool large_icons*/);
 
  /// add icon with alpha channel to imagelist using the specified background color
 extern int ImageList_AddAlphaIcon(HIMAGELIST himl, HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd);

Modified: trunk/reactos/subsys/system/explorer/shell/entries.cpp
--- trunk/reactos/subsys/system/explorer/shell/entries.cpp	2005-12-28 14:55:22 UTC (rev 20395)
+++ trunk/reactos/subsys/system/explorer/shell/entries.cpp	2005-12-28 16:14:10 UTC (rev 20396)
@@ -319,52 +319,55 @@
 }
 
 
-void Entry::extract_icon(bool big_icons)
+
+int Entry::extract_icon(ICONCACHE_FLAGS flags)
 {
 	TCHAR path[MAX_PATH];
 
 	ICON_ID icon_id = ICID_NONE;
 
 	if (get_path(path, COUNTOF(path)) && _tcsncmp(path,TEXT("::{"),3))
-		icon_id = g_Globals._icon_cache.extract(path, big_icons);
+		icon_id = g_Globals._icon_cache.extract(path, flags);
 
 	if (icon_id == ICID_NONE) {
-		IExtractIcon* pExtract;
-		if (SUCCEEDED(GetUIObjectOf(0, IID_IExtractIcon, (LPVOID*)&pExtract))) {
-			unsigned flags;
-			int idx;
+		if (!(flags & (ICF_OPEN|ICF_OVERLAYS))) {
+			IExtractIcon* pExtract;
+			if (SUCCEEDED(GetUIObjectOf(0, IID_IExtractIcon, (LPVOID*)&pExtract))) {
+				unsigned gil_flags;
+				int idx;
 
-			if (SUCCEEDED(pExtract->GetIconLocation(GIL_FORSHELL, path, COUNTOF(path), &idx, &flags))) {
-				if (flags & GIL_NOTFILENAME)
-					icon_id = g_Globals._icon_cache.extract(pExtract, path, idx, big_icons);
-				else {
-					if (idx == -1)
-						idx = 0;	// special case for some control panel applications ("System")
+				if (SUCCEEDED(pExtract->GetIconLocation(GIL_FORSHELL, path, COUNTOF(path), &idx, &gil_flags))) {
+					if (gil_flags & GIL_NOTFILENAME)
+						icon_id = g_Globals._icon_cache.extract(pExtract, path, idx, flags);
+					else {
+						if (idx == -1)
+							idx = 0;	// special case for some control panel applications ("System")
 
-					icon_id = g_Globals._icon_cache.extract(path, idx);
-				}
+						icon_id = g_Globals._icon_cache.extract(path, idx, flags);
+					}
 
-			/* using create_absolute_pidl() [see below] results in more correct icons for some control panel applets ("NVidia").
-				if (icon_id == ICID_NONE) {
-					SHFILEINFO sfi;
+				/* using create_absolute_pidl() [see below] results in more correct icons for some control panel applets (NVidia display driver).
+					if (icon_id == ICID_NONE) {
+						SHFILEINFO sfi;
 
-					if (SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_ICON|SHGFI_SMALLICON))
-						icon_id = g_Globals._icon_cache.add(sfi.hIcon)._id;
-				} */
-			/*
-				if (icon_id == ICID_NONE) {
-					LPBYTE b = (LPBYTE) alloca(0x10000);
-					SHFILEINFO sfi;
+						if (SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_ICON|SHGFI_SMALLICON))
+							icon_id = g_Globals._icon_cache.add(sfi.hIcon)._id;
+					} */
+				/*
+					if (icon_id == ICID_NONE) {
+						LPBYTE b = (LPBYTE) alloca(0x10000);
+						SHFILEINFO sfi;
 
-					FILE* file = fopen(path, "rb");
-					if (file) {
-						int l = fread(b, 1, 0x10000, file);
-						fclose(file);
+						FILE* file = fopen(path, "rb");
+						if (file) {
+							int l = fread(b, 1, 0x10000, file);
+							fclose(file);
 
-						if (l)
-							icon_id = g_Globals._icon_cache.add(CreateIconFromResourceEx(b, l, TRUE, 0x00030000, 16, 16, LR_DEFAULTCOLOR));
-					}
-				} */
+							if (l)
+								icon_id = g_Globals._icon_cache.add(CreateIconFromResourceEx(b, l, TRUE, 0x00030000, 16, 16, LR_DEFAULTCOLOR));
+						}
+					} */
+				}
 			}
 		}
 
@@ -374,20 +377,41 @@
 			const ShellPath& pidl_abs = create_absolute_pidl();
 			LPCITEMIDLIST pidl = pidl_abs;
 
-			HIMAGELIST himlSys = (HIMAGELIST) SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX|SHGFI_PIDL|(big_icons? SHGFI_SMALLICON: 0));
+			int shgfi_flags = SHGFI_SYSICONINDEX|SHGFI_PIDL;
+
+			if (!(flags & ICF_LARGE))
+				shgfi_flags |= SHGFI_SMALLICON;
+
+			if (flags & ICF_OPEN)
+				shgfi_flags |= SHGFI_OPENICON;
+
+			// ICF_OVERLAYS is not supported in this case.
+
+			HIMAGELIST himlSys = (HIMAGELIST) SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), shgfi_flags);
 			if (himlSys)
 				icon_id = g_Globals._icon_cache.add(sfi.iIcon);
 			/*
-			if (SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL|SHGFI_ICON|(g_Globals._big_icons? SHGFI_SMALLICON: 0)))
+			if (SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL|SHGFI_ICON|(g_Globals._large_icons? SHGFI_SMALLICON: 0)))
 				icon_id = g_Globals._icon_cache.add(sfi.hIcon)._id;
 			*/
 		}
 	}
 
-	_icon_id = icon_id;
+	return icon_id;
 }
 
+int Entry::safe_extract_icon(ICONCACHE_FLAGS flags)
+{
+	try {
+		return extract_icon(flags);
+	} catch(COMException&) {
+		// ignore unexpected exceptions while extracting icons
+	}
 
+	return ICID_NONE;
+}
+
+
 BOOL Entry::launch_entry(HWND hwnd, UINT nCmdShow)
 {
 	TCHAR cmd[MAX_PATH];

Modified: trunk/reactos/subsys/system/explorer/shell/entries.h
--- trunk/reactos/subsys/system/explorer/shell/entries.h	2005-12-28 14:55:22 UTC (rev 20395)
+++ trunk/reactos/subsys/system/explorer/shell/entries.h	2005-12-28 16:14:10 UTC (rev 20396)
@@ -64,7 +64,20 @@
 #define	ATTRIBUTE_EXECUTABLE		0x80000000
 #endif
 
+enum ICONCACHE_FLAGS {
+	ICF_NORMAL	 =  0,
+	ICF_LARGE	 =  1,
+	ICF_OPEN	 =  2,
+	ICF_OVERLAYS =  4,
+	ICF_HICON	 =  8,
+	ICF_SYSCACHE = 16
+};
 
+#ifndef SHGFI_ADDOVERLAYS // missing in MinGW (as of 28.12.2005)
+#define SHGFI_ADDOVERLAYS 0x000000020
+#endif
+
+
  /// base of all file and directory entries
 struct Entry
 {
@@ -103,7 +116,8 @@
 	Entry*	read_tree(const void* path, SORT_ORDER sortOrder=SORT_NAME, int scan_flags=SCAN_ALL);
 	void	sort_directory(SORT_ORDER sortOrder);
 	void	smart_scan(SORT_ORDER sortOrder=SORT_NAME, int scan_flags=SCAN_ALL);
-	void	extract_icon(bool big_icons);
+	int		extract_icon(ICONCACHE_FLAGS flags=ICF_NORMAL);
+	int		safe_extract_icon(ICONCACHE_FLAGS flags=ICF_NORMAL);
 
 	virtual void		read_directory(int scan_flags=SCAN_ALL) {}
 	virtual const void*	get_next_path_component(const void*) const {return NULL;}

Modified: trunk/reactos/subsys/system/explorer/shell/mainframe.cpp
--- trunk/reactos/subsys/system/explorer/shell/mainframe.cpp	2005-12-28 14:55:22 UTC (rev 20395)
+++ trunk/reactos/subsys/system/explorer/shell/mainframe.cpp	2005-12-28 16:14:10 UTC (rev 20396)
@@ -1335,9 +1335,6 @@
 	_split_pos = DEFAULT_SPLIT_POS;
 	_last_split = DEFAULT_SPLIT_POS;
 
-	 // create image list for explorer tree view
-	init_himl();
-
 	/* wait for PM_OPEN_WINDOW message before creating a shell view
 	update_shell_browser();*/
 }
@@ -1647,12 +1644,12 @@
 	}
 
 	_shellBrowser = auto_ptr<ShellBrowser>(new ShellBrowser(_hwnd, _left_hwnd, _right_hwnd,
-												_shellpath_info, _himlSmall, this, _cm_ifs));
+												_shellpath_info, this, _cm_ifs));
 
 	_shellBrowser->Init(_hwnd);
 
 	if (_left_hwnd)
-		_shellBrowser->Init(_himlSmall);
+		_shellBrowser->Init();
 
 	 // update _clnt_rect and set size of new created shell view windows
 	update_clnt_rect();

Modified: trunk/reactos/subsys/system/explorer/shell/shellbrowser.cpp
--- trunk/reactos/subsys/system/explorer/shell/shellbrowser.cpp	2005-12-28 14:55:22 UTC (rev 20395)
+++ trunk/reactos/subsys/system/explorer/shell/shellbrowser.cpp	2005-12-28 16:14:10 UTC (rev 20396)
@@ -38,7 +38,7 @@
 
 
 ShellBrowser::ShellBrowser(HWND hwnd, HWND left_hwnd, WindowHandle& right_hwnd, ShellPathInfo& create_info,
-							HIMAGELIST himl, BrowserCallback* cb, CtxMenuInterfaces& cm_ifs)
+							BrowserCallback* cb, CtxMenuInterfaces& cm_ifs)
 #ifndef __MINGW32__	// IShellFolderViewCB missing in MinGW (as of 25.09.2005)
  :	super(IID_IShellFolderViewCB),
 #else
@@ -48,7 +48,6 @@
 	_left_hwnd(left_hwnd),
 	_right_hwnd(right_hwnd),
 	_create_info(create_info),
-	_himl(himl),
 	_callback(cb),
 	_cm_ifs(cm_ifs)
 {
@@ -57,11 +56,15 @@
 	_last_sel = 0;
 
 	_cur_dir = NULL;
+
+	_himl = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_MASK|ILC_COLOR24, 2, 0);
+	ImageList_SetBkColor(_himl, GetSysColor(COLOR_WINDOW));
 }
 
 ShellBrowser::~ShellBrowser()
 {
 	(void)TreeView_SetImageList(_left_hwnd, _himl_old, TVSIL_NORMAL);
+	ImageList_Destroy(_himl);
 
 	if (_pShellView)
 		_pShellView->Release();
@@ -148,22 +151,22 @@
 }
 
 
-void ShellBrowser::InitializeTree(HIMAGELIST himl)
+void ShellBrowser::InitializeTree()
 {
 	CONTEXT("ShellBrowserChild::InitializeTree()");
 
-	_himl_old = TreeView_SetImageList(_left_hwnd, himl, TVSIL_NORMAL);
+	_himl_old = TreeView_SetImageList(_left_hwnd, _himl, TVSIL_NORMAL);
 	TreeView_SetScrollTime(_left_hwnd, 100);
 
 	TV_INSERTSTRUCT tvInsert;
+	TV_ITEM& tvItem = tvInsert.item;
 
 	tvInsert.hParent = 0;
 	tvInsert.hInsertAfter = TVI_LAST;
 
-	TV_ITEM& tvItem = tvInsert.item;
 	tvItem.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN;
 	tvItem.lParam = (LPARAM)_root._entry;
-	tvItem.pszText = LPSTR_TEXTCALLBACK;
+	tvItem.pszText = _root._volname; //LPSTR_TEXTCALLBACK;
 	tvItem.iImage = tvItem.iSelectedImage = I_IMAGECALLBACK;
 	tvItem.cChildren = 1;
 
@@ -239,33 +242,43 @@
 		if (lpdi->item.mask & TVIF_TEXT)
 			lpdi->item.pszText = entry->_display_name;
 
-		if (lpdi->item.mask & (/*TVIF_TEXT|*/TVIF_IMAGE|TVIF_SELECTEDIMAGE)) {
-			ShellPath pidl_abs = entry->create_absolute_pidl();	// Caching of absolute PIDLs could enhance performance.
-			LPCITEMIDLIST pidl = pidl_abs;
-
-			SHFILEINFO sfi;
-/*
-			if (lpdi->item.mask & TVIF_TEXT)
-				if (SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL|SHGFI_DISPLAYNAME))
-					lstrcpy(lpdi->item.pszText, sfi.szDisplayName);	///@todo look at cchTextMax if there is enough space available
-				else
-					lpdi->item.pszText = entry->_data.cFileName;
-*/
+		if (lpdi->item.mask & (TVIF_IMAGE|TVIF_SELECTEDIMAGE)) {
 			if (lpdi->item.mask & TVIF_IMAGE)
-				if ((HIMAGELIST)SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL|SHGFI_SYSICONINDEX|SHGFI_LINKOVERLAY|SHGFI_SMALLICON) == _himl)
-					lpdi->item.iImage = sfi.iIcon;
-				else
-					lpdi->item.iImage = -1;
+				lpdi->item.iImage = get_image_idx(
+						entry->safe_extract_icon((ICONCACHE_FLAGS)(ICF_HICON|ICF_OVERLAYS)));
 
 			if (lpdi->item.mask & TVIF_SELECTEDIMAGE)
-				if ((HIMAGELIST)SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL|SHGFI_SYSICONINDEX|SHGFI_OPENICON|SHGFI_SMALLICON) == _himl)
-					lpdi->item.iSelectedImage = sfi.iIcon;
-				else
-					lpdi->item.iSelectedImage = -1;
+				lpdi->item.iSelectedImage = get_image_idx(
+						entry->safe_extract_icon((ICONCACHE_FLAGS)(ICF_HICON|ICF_OVERLAYS|ICF_OPEN)));
 		}
 	}
 }
 
+int ShellBrowser::get_image_idx(int icon_id)
+{
+	if (icon_id != ICID_NONE) {
+		map<int,int>::const_iterator found = _image_map.find(icon_id);
+
+		if (found != _image_map.end())
+			return found->second;
+
+		int idx = ImageList_AddIcon(_himl, g_Globals._icon_cache.get_icon(icon_id).get_hicon());
+
+		_image_map[icon_id] = idx;
+
+		return idx;
+	} else
+		return -1;
+}
+
+void ShellBrowser::invalidate_cache()
+{
+	for(map<int,int>::const_iterator it=_image_map.begin(); it!=_image_map.end(); ++it)
+		g_Globals._icon_cache.free_icon(it->first);
+
+	_image_map.clear();
+}
+
 void ShellBrowser::OnTreeItemExpanding(int idCtrl, LPNMTREEVIEW pnmtv)
 {
 	CONTEXT("ShellBrowser::OnTreeItemExpanding()");
@@ -554,13 +567,11 @@
 	if (super::Init(pcs))
 		return 1;
 
-	init_himl();
-
 	update_shell_browser();
 
 	if (_shellBrowser.get())
 		if (_left_hwnd)
-			_shellBrowser->Init(_himlSmall);
+			_shellBrowser->Init();
 		else
 			_shellBrowser->UpdateFolderView(_create_info._shell_path.get_folder());
 
@@ -579,6 +590,7 @@
 
 		  case ID_REFRESH:
 			//@todo refresh shell child
+			_shellBrowser->invalidate_cache();
 			break;
 
 		  case ID_VIEW_SDI:
@@ -626,7 +638,7 @@
 	}
 
 	_shellBrowser = auto_ptr<ShellBrowser>(new ShellBrowser(_hwnd, _left_hwnd, _right_hwnd,
-												_shellpath_info, _himlSmall, this, _cm_ifs));
+												_shellpath_info, this, _cm_ifs));
 
 	_shellBrowser->Init(_hwndFrame);
 }

Modified: trunk/reactos/subsys/system/explorer/shell/shellbrowser.h
--- trunk/reactos/subsys/system/explorer/shell/shellbrowser.h	2005-12-28 14:55:22 UTC (rev 20395)
+++ trunk/reactos/subsys/system/explorer/shell/shellbrowser.h	2005-12-28 16:14:10 UTC (rev 20396)
@@ -62,7 +62,7 @@
 #endif
 {
 	ShellBrowser(HWND hwnd, HWND left_hwnd, WindowHandle& right_hwnd, ShellPathInfo& create_info,
-					HIMAGELIST himl, BrowserCallback* cb, CtxMenuInterfaces& cm_ifs);
+					BrowserCallback* cb, CtxMenuInterfaces& cm_ifs);
 	virtual ~ShellBrowser();
 
 	//IOleWindow
@@ -124,9 +124,9 @@
 
 	LRESULT	Init(HWND hWndFrame);
 
-	void	Init(HIMAGELIST himl)
+	void	Init()
 	{
-		InitializeTree(himl);
+		InitializeTree();
 		InitDragDrop();
 	}
 
@@ -142,6 +142,8 @@
 	 // for SDIMainFrame
 	void	jump_to(LPCITEMIDLIST pidl);
 
+	void	invalidate_cache();
+
 protected:
 	HWND	_hwnd;
 	HWND	_left_hwnd;
@@ -164,7 +166,7 @@
 
 	CtxMenuInterfaces& _cm_ifs;
 
-	void	InitializeTree(HIMAGELIST himl);
+	void	InitializeTree();
 	bool	InitDragDrop();
 
 #ifndef __MINGW32__	// IShellFolderViewCB missing in MinGW (as of 25.09.2005)
@@ -173,6 +175,10 @@
 	 // IShellFolderViewCB
 	virtual HRESULT STDMETHODCALLTYPE MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam);
 #endif
+
+	map<int, int> _image_map;
+
+	int		get_image_idx(int icon_id);
 };
 
 
@@ -194,29 +200,15 @@
 	ShellBrowserChildT(HWND hwnd)
 	 :	super(hwnd)
 	{
-		_himlSmall = 0;
 	}
 
 	 // constructor for MDIShellBrowserChild
 	ShellBrowserChildT(HWND hwnd, const ShellChildWndInfo& info)
 	 :	super(hwnd, info)
 	{
-		_himlSmall = 0;
 	}
 
-	void init_himl()
-	{
-		SHFILEINFO sfi;
-
-		_himlSmall = (HIMAGELIST)SHGetFileInfo(C_DRIVE, 0, &sfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX|SHGFI_SMALLICON);
-//		_himlLarge = (HIMAGELIST)SHGetFileInfo(C_DRIVE, 0, &sfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX|SHGFI_LARGEICON);
-	}
-
 protected:
-	HIMAGELIST	_himlSmall;		// list
-//	HIMAGELIST	_himlLarge;		// shell image
-
-protected:
 	auto_ptr<ShellBrowser> _shellBrowser;
 
 	LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)

Modified: trunk/reactos/subsys/system/explorer/shell/shellfs.cpp
--- trunk/reactos/subsys/system/explorer/shell/shellfs.cpp	2005-12-28 14:55:22 UTC (rev 20395)
+++ trunk/reactos/subsys/system/explorer/shell/shellfs.cpp	2005-12-28 16:14:10 UTC (rev 20396)
@@ -325,11 +325,7 @@
 				if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
 					entry->_icon_id = ICID_FOLDER;
 /*				else if (scan_flags & SCAN_EXTRACT_ICONS)
-					try {
-						entry->extract_icon(big_icons);
-					} catch(COMException&) {
-						// ignore unexpected exceptions while extracting icons
-					}
+					entry->safe_extract_icon(large_icons);
 */
 				last = entry;
 			} while(FindNextFile(hFind, &w32fd));
@@ -431,11 +427,7 @@
 					if (!(entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
 						!(attribs & SFGAO_FILESYSTEM)) {
 /*						if (scan_flags & SCAN_EXTRACT_ICONS)
-							try {
-								entry->extract_icon(big_icons);
-							} catch(COMException&) {
-								// ignore unexpected exceptions while extracting icons
-							}
+							entry->extract_icon(large_icons);
 */					} else if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
 						entry->_icon_id = ICID_FOLDER;
 					else
@@ -488,13 +480,13 @@
 	return NULL;
 }
 
-int ShellDirectory::extract_icons(bool big_icons)
+int ShellDirectory::extract_icons(ICONCACHE_FLAGS flags)
 {
 	int cnt = 0;
 
 	for(Entry*entry=_down; entry; entry=entry->_next)
 		if (entry->_icon_id == ICID_UNKNOWN) {
-			entry->extract_icon(big_icons);
+			entry->_icon_id = entry->extract_icon(flags);
 
 			if (entry->_icon_id != ICID_NONE)
 				++cnt;

Modified: trunk/reactos/subsys/system/explorer/shell/shellfs.h
--- trunk/reactos/subsys/system/explorer/shell/shellfs.h	2005-12-28 14:55:22 UTC (rev 20395)
+++ trunk/reactos/subsys/system/explorer/shell/shellfs.h	2005-12-28 16:14:10 UTC (rev 20396)
@@ -105,7 +105,7 @@
 
 	virtual bool get_path(PTSTR path, size_t path_count) const;
 
-	int	extract_icons(bool big_icons);
+	int	extract_icons(ICONCACHE_FLAGS flags);
 
 	ShellFolder _folder;
 	HWND	_hwnd;

Modified: trunk/reactos/subsys/system/explorer/taskbar/desktopbar.cpp
--- trunk/reactos/subsys/system/explorer/taskbar/desktopbar.cpp	2005-12-28 14:55:22 UTC (rev 20395)
+++ trunk/reactos/subsys/system/explorer/taskbar/desktopbar.cpp	2005-12-28 16:14:10 UTC (rev 20396)
@@ -161,7 +161,7 @@
 	RegisterHotkeys();
 
 	 // prepare Startmenu, but hide it for now
-	_startMenuRoot = GET_WINDOW(StartMenuRoot, StartMenuRoot::Create(_hwnd, true));	//@@ _big_icons
+	_startMenuRoot = GET_WINDOW(StartMenuRoot, StartMenuRoot::Create(_hwnd, true));	//@@ _large_icons
 
 	return 0;
 }

Modified: trunk/reactos/subsys/system/explorer/taskbar/quicklaunch.cpp
--- trunk/reactos/subsys/system/explorer/taskbar/quicklaunch.cpp	2005-12-28 14:55:22 UTC (rev 20395)
+++ trunk/reactos/subsys/system/explorer/taskbar/quicklaunch.cpp	2005-12-28 16:14:10 UTC (rev 20396)
@@ -109,11 +109,7 @@
 
 		 // immediatelly extract the shortcut icons
 		for(Entry*entry=_dir->_down; entry; entry=entry->_next)
-			try {
-				entry->extract_icon(false);
-			} catch(COMException&) {
-				// ignore unexpected exceptions while extracting icons
-			}
+			entry->_icon_id = entry->safe_extract_icon(ICF_NORMAL);
 	} catch(COMException&) {
 		return;
 	}

Modified: trunk/reactos/subsys/system/explorer/taskbar/startmenu.cpp
--- trunk/reactos/subsys/system/explorer/taskbar/startmenu.cpp	2005-12-28 14:55:22 UTC (rev 20395)
+++ trunk/reactos/subsys/system/explorer/taskbar/startmenu.cpp	2005-12-28 16:14:10 UTC (rev 20396)
@@ -46,9 +46,9 @@
 #define	SHELLPATH_NET_CONNECTIONS	TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{7007ACC7-3202-11D1-AAD2-00805FC1270E}")
 
 
-StartMenu::StartMenu(HWND hwnd, bool big_icons)
+StartMenu::StartMenu(HWND hwnd, bool large_icons)
  :	super(hwnd),
-	_big_icons(big_icons)
+	_large_icons(large_icons)
 {
 	_next_id = IDC_FIRST_MENU;
 	_submenu_id = 0;
@@ -70,10 +70,10 @@
 #endif
 }
 
-StartMenu::StartMenu(HWND hwnd, const StartMenuCreateInfo& create_info, bool big_icons)
+StartMenu::StartMenu(HWND hwnd, const StartMenuCreateInfo& create_info, bool large_icons)
  :	super(hwnd),
 	_create_info(create_info),
-	_big_icons(big_icons)
+	_large_icons(large_icons)
 {
 	for(StartMenuFolders::const_iterator it=create_info._folders.begin(); it!=create_info._folders.end(); ++it)
 		if (*it)
@@ -117,7 +117,7 @@
 
 Window::CREATORFUNC_INFO StartMenu::s_def_creator = STARTMENU_CREATOR(StartMenu);
 
-HWND StartMenu::Create(int x, int y, const StartMenuFolders& folders, HWND hwndParent, LPCTSTR title, bool parent_big_icons,
+HWND StartMenu::Create(int x, int y, const StartMenuFolders& folders, HWND hwndParent, LPCTSTR title,
 						CREATORFUNC_INFO creator, void* info, const String& filter)
 {
 	UINT style, ex_style;
@@ -133,7 +133,7 @@
 		top_height = 0;
 	}
 
-	bool big_icons = false;
+	bool large_icons = false;
 	RECT rect = {x, y-STARTMENU_LINE_HEIGHT-top_height, x+STARTMENU_WIDTH_MIN, y};
 
 #ifndef _LIGHT_STARTMENU
@@ -348,7 +348,7 @@
  			WindowRect pos(_hwnd);
 
 			///@todo do something similar to StartMenuRoot::TrackStartmenu() in order to automatically close submenus when clicking on the desktop background
-			StartMenu::Create(pos.left+3, pos.bottom-3, _create_info._folders, 0, _create_info._title, _big_icons, _create_info._creator, _create_info._info);
+			StartMenu::Create(pos.left+3, pos.bottom-3, _create_info._folders, 0, _create_info._title, _create_info._creator, _create_info._info);
 			CloseStartMenu();
 		}
 
@@ -391,7 +391,7 @@
 			if (_arrow_btns) {
 				RECT rect_up, rect_down;
 
-				GetArrowButtonRects(&rect_up, &rect_down, _big_icons);
+				GetArrowButtonRects(&rect_up, &rect_down, _large_icons);
 
 				SCROLL_MODE scroll_mode = SCROLL_NOT;
 
@@ -515,7 +515,7 @@
 int StartMenu::ButtonHitTest(POINT pt)
 {
 	ClientRect clnt(_hwnd);
-	const bool big_icons = _big_icons;
+	const bool large_icons = _large_icons;
 	RECT rect = {_border_left, _border_top, clnt.right, STARTMENU_LINE_HEIGHT};
 
 	if (pt.x<rect.left || pt.x>rect.right)
@@ -547,7 +547,7 @@
 		return;
 
 	ClientRect clnt(_hwnd);
-	const bool big_icons = _big_icons;
+	const bool large_icons = _large_icons;
 	RECT rect = {_border_left, _border_top, clnt.right, STARTMENU_LINE_HEIGHT};
 
 	for(SMBtnVector::const_iterator it=_buttons.begin()+_scroll_pos; it!=_buttons.end(); ++it) {
@@ -773,7 +773,7 @@
 {
 #ifdef _LIGHT_STARTMENU
 	ClientRect clnt(_hwnd);
-	const bool big_icons = _big_icons;
+	const bool large_icons = _large_icons;
 	RECT rect = {_border_left, _border_top, clnt.right, STARTMENU_LINE_HEIGHT};
 
 	for(SMBtnVector::const_iterator it=_buttons.begin()+_scroll_pos; it!=_buttons.end(); ++it) {
@@ -823,10 +823,10 @@
 }
 
 
-void StartMenu::DrawArrows(HDC hdc, bool big_icons)
+void StartMenu::DrawArrows(HDC hdc, bool large_icons)
 {
-	int cx = big_icons? 16: 8;
-	int cy = big_icons? 8: 4;
+	int cx = large_icons? 16: 8;
+	int cy = large_icons? 8: 4;
 
 	ResIconEx arrowUpIcon(IDI_ARROW_UP, cx, cy);
 	ResIconEx arrowDownIcon(IDI_ARROW_DOWN, cx, cy);
@@ -837,10 +837,10 @@
 	DrawIconEx(hdc, clnt.right/2-cx/2, clnt.bottom-cy-1, arrowDownIcon, cx, cy, 0, 0, DI_NORMAL);
 }
 
-void StartMenu::GetArrowButtonRects(LPRECT prect_up, LPRECT prect_down, bool big_icons)
+void StartMenu::GetArrowButtonRects(LPRECT prect_up, LPRECT prect_down, bool large_icons)
 {
-	int cx = big_icons? 16: 8;
-	int cy = big_icons? 8: 4;
+	int cx = large_icons? 16: 8;
+	int cy = large_icons? 8: 4;
 
 	GetClientRect(_hwnd, prect_up);
 	*prect_down = *prect_up;
@@ -865,10 +865,10 @@
 
 #ifdef _LIGHT_STARTMENU
 	if (_arrow_btns)
-		DrawArrows(canvas, _big_icons);
+		DrawArrows(canvas, _large_icons);
 
 	ClientRect clnt(_hwnd);
-	const bool big_icons = _big_icons;
+	const bool large_icons = _large_icons;
 	RECT rect = {_border_left, _border_top, clnt.right, STARTMENU_LINE_HEIGHT};
 
 	int sep_width = rect.right-rect.left - 4;
@@ -900,7 +900,7 @@
 				break;
 
 			if (rect.top >= canvas.rcPaint.top)
-				DrawStartMenuButton(canvas, rect, btn._title, btn, btn._id==_selected_id, false, _big_icons);
+				DrawStartMenuButton(canvas, rect, btn._title, btn, btn._id==_selected_id, false, _large_icons);
 		}
 
 		rect.top = rect.bottom;
@@ -930,11 +930,7 @@
 				Entry* entry = *it;
 
 				if (entry->_icon_id == ICID_UNKNOWN)
-					try {
-						entry->extract_icon(_big_icons);
-					} catch(COMException&) {
-						// ignore unexpected exceptions while extracting icons
-					}
+					entry->_icon_id = entry->safe_extract_icon(_large_icons? ICF_LARGE: ICF_NORMAL);
 
 				if (entry->_icon_id > ICID_NONE) {
 					btn._icon_id = (ICON_ID)/*@@*/ entry->_icon_id;
@@ -947,7 +943,7 @@
 						break;
 
 					WindowCanvas canvas(_hwnd);
-					DrawStartMenuButton(canvas, rect, NULL, btn, btn._id==_selected_id, false, _big_icons);
+					DrawStartMenuButton(canvas, rect, NULL, btn, btn._id==_selected_id, false, _large_icons);
 
 					//InvalidateRect(_hwnd, &rect, FALSE);
 					//UpdateWindow(_hwnd);
@@ -1266,7 +1262,7 @@
 		ClientToScreen(_hwnd, &rect);
 
 		x = rect.right;	// Submenus should overlap their parent a bit.
-		const bool big_icons = _big_icons;
+		const bool large_icons = _large_icons;
 		y = rect.top+STARTMENU_LINE_HEIGHT +_border_top/*own border*/ -STARTMENU_TOP_BTN_SPACE/*border of new submenu*/;
 	} else {
 		WindowRect pos(_hwnd);
@@ -1276,7 +1272,7 @@
 	}
 
 	_submenu_id = id;
-	_submenu = StartMenu::Create(x, y, new_folders, _hwnd, title, _big_icons, creator, info, _create_info._filter);
+	_submenu = StartMenu::Create(x, y, new_folders, _hwnd, title, creator, info, _create_info._filter);
 }
 
 
@@ -1368,10 +1364,10 @@
 }
 
 #ifdef _LIGHT_STARTMENU
-void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, const SMBtnInfo& btn, bool has_focus, bool pushed, bool big_icons)
+void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, const SMBtnInfo& btn, bool has_focus, bool pushed, bool large_icons)
 #else
 void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, HICON hIcon,
-								bool hasSubmenu, bool enabled, bool has_focus, bool pushed, bool big_icons);
+								bool hasSubmenu, bool enabled, bool has_focus, bool pushed, bool large_icons);
 #endif
 {
 	UINT style = DFCS_BUTTONPUSH;
@@ -1404,7 +1400,7 @@
 		FillRect(hdc, &rect, bk_brush);
 
 	if (btn._icon_id > ICID_NONE)
-		g_Globals._icon_cache.get_icon(btn._icon_id).draw(hdc, iconPos.x, iconPos.y, ICON_SIZE_X, ICON_SIZE_Y, bk_color, bk_brush/*, big_icons*/);
+		g_Globals._icon_cache.get_icon(btn._icon_id).draw(hdc, iconPos.x, iconPos.y, ICON_SIZE_X, ICON_SIZE_Y, bk_color, bk_brush/*, large_icons*/);
 
 	 // draw submenu arrow at the right
 	if (btn._hasSubmenu) {
@@ -1438,7 +1434,7 @@
 	WindowCanvas canvas(_hwnd);
 	FontSelection font(canvas, GetStockFont(DEFAULT_GUI_FONT));
 
-	const bool big_icons = _big_icons;
+	const bool large_icons = _large_icons;
 
 	int max_width = STARTMENU_WIDTH_MIN;
 	int height = 0;
@@ -1583,7 +1579,7 @@
 }
 
 
-static void CalculateStartPos(HWND hwndOwner, RECT& rect, bool big_icons)
+static void CalculateStartPos(HWND hwndOwner, RECT& rect, bool large_icons)
 {
 	WindowRect pos(hwndOwner);
 
@@ -1599,11 +1595,11 @@
 	AdjustWindowRectEx(&rect, WS_POPUP|WS_THICKFRAME|WS_CLIPCHILDREN|WS_VISIBLE, FALSE, 0);
 }
 
-HWND StartMenuRoot::Create(HWND hwndOwner, bool big_icons)
+HWND StartMenuRoot::Create(HWND hwndOwner, bool large_icons)
 {
 	RECT rect;
 
-	CalculateStartPos(hwndOwner, rect, big_icons);
+	CalculateStartPos(hwndOwner, rect, large_icons);
 
[truncated at 1000 lines; 106 more skipped]