Author: aandrejevic Date: Sat Aug 9 13:40:13 2014 New Revision: 63845
URL: http://svn.reactos.org/svn/reactos?rev=63845&view=rev Log: [SHELL32] - Greatly optimize file icon retrieval by reducing the times we try to access the disk. - Store icons in a binary tree in the shell icon cache for faster retrieval. Patch by Huw Campbell committed at the request of Giannis Adamopoulos.
Modified: trunk/reactos/dll/win32/shell32/folders.cpp trunk/reactos/dll/win32/shell32/iconcache.cpp trunk/reactos/dll/win32/shell32/shfldr.h trunk/reactos/dll/win32/shell32/shlfolder.cpp
Modified: trunk/reactos/dll/win32/shell32/folders.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/folders.c... ============================================================================== --- trunk/reactos/dll/win32/shell32/folders.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/folders.cpp [iso-8859-1] Sat Aug 9 13:40:13 2014 @@ -28,6 +28,7 @@ LPWSTR szIconFile, UINT cchMax, int *piIndex, UINT *pwFlags) { int icon_idx; + bool cont=TRUE; WCHAR wszPath[MAX_PATH]; WCHAR wszCLSIDValue[CHARS_IN_GUID]; static const WCHAR shellClassInfo[] = { '.', 'S', 'h', 'e', 'l', 'l', 'C', 'l', 'a', 's', 's', 'I', 'n', 'f', 'o', 0 }; @@ -36,27 +37,40 @@ static const WCHAR clsid2[] = { 'C', 'L', 'S', 'I', 'D', '2', 0 }; static const WCHAR iconIndex[] = { 'I', 'c', 'o', 'n', 'I', 'n', 'd', 'e', 'x', 0 };
- if (SHELL32_GetCustomFolderAttribute(pidl, shellClassInfo, iconFile, - wszPath, MAX_PATH)) - { - WCHAR wszIconIndex[10]; - SHELL32_GetCustomFolderAttribute(pidl, shellClassInfo, iconIndex, - wszIconIndex, 10); - *piIndex = _wtoi(wszIconIndex); - } - else if (SHELL32_GetCustomFolderAttribute(pidl, shellClassInfo, clsid, - wszCLSIDValue, CHARS_IN_GUID) && - HCR_GetIconW(wszCLSIDValue, szIconFile, NULL, cchMax, &icon_idx)) - { - *piIndex = icon_idx; - } - else if (SHELL32_GetCustomFolderAttribute(pidl, shellClassInfo, clsid2, - wszCLSIDValue, CHARS_IN_GUID) && - HCR_GetIconW(wszCLSIDValue, szIconFile, NULL, cchMax, &icon_idx)) - { - *piIndex = icon_idx; - } - else + /* + Optimisation. GetCustomFolderAttribute has a critical lock on it, and isn't fast. + Test the water (i.e., see if the attribute exists) before questioning it three times + when most folders don't use it at all. + */ + WCHAR wszBigToe[3]; + if (!(uFlags & GIL_DEFAULTICON) && SHELL32_GetCustomFolderAttributes(pidl, shellClassInfo, + wszBigToe, 3)) + { + if (SHELL32_GetCustomFolderAttribute(pidl, shellClassInfo, iconFile, + wszPath, MAX_PATH)) + { + WCHAR wszIconIndex[10]; + SHELL32_GetCustomFolderAttribute(pidl, shellClassInfo, iconIndex, + wszIconIndex, 10); + *piIndex = _wtoi(wszIconIndex); + cont=FALSE; + } + else if (SHELL32_GetCustomFolderAttribute(pidl, shellClassInfo, clsid, + wszCLSIDValue, CHARS_IN_GUID) && + HCR_GetIconW(wszCLSIDValue, szIconFile, NULL, cchMax, &icon_idx)) + { + *piIndex = icon_idx; + cont=FALSE; + } + else if (SHELL32_GetCustomFolderAttribute(pidl, shellClassInfo, clsid2, + wszCLSIDValue, CHARS_IN_GUID) && + HCR_GetIconW(wszCLSIDValue, szIconFile, NULL, cchMax, &icon_idx)) + { + *piIndex = icon_idx; + cont=FALSE; + } + } + if (cont) { static const WCHAR folder[] = { 'F', 'o', 'l', 'd', 'e', 'r', 0 };
@@ -322,6 +336,10 @@ &flags))) { initIcon->SetNormalIcon(wTemp, icon_idx); + // FIXME: if/when getIconLocationForFolder does something for + // GIL_FORSHORTCUT, code below should be uncommented. and + // the following line removed. + initIcon->SetShortcutIcon(wTemp, icon_idx); } if (SUCCEEDED(getIconLocationForFolder( pidl, GIL_DEFAULTICON, wTemp, MAX_PATH, @@ -330,13 +348,13 @@ { initIcon->SetDefaultIcon(wTemp, icon_idx); } - if (SUCCEEDED(getIconLocationForFolder( - pidl, GIL_FORSHORTCUT, wTemp, MAX_PATH, - &icon_idx, - &flags))) - { - initIcon->SetShortcutIcon(wTemp, icon_idx); - } + // if (SUCCEEDED(getIconLocationForFolder( + // pidl, GIL_FORSHORTCUT, wTemp, MAX_PATH, + // &icon_idx, + // &flags))) + // { + // initIcon->SetShortcutIcon(wTemp, icon_idx); + // } if (SUCCEEDED(getIconLocationForFolder( pidl, GIL_OPENICON, wTemp, MAX_PATH, &icon_idx,
Modified: trunk/reactos/dll/win32/shell32/iconcache.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/iconcache... ============================================================================== --- trunk/reactos/dll/win32/shell32/iconcache.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/iconcache.cpp [iso-8859-1] Sat Aug 9 13:40:13 2014 @@ -64,14 +64,14 @@ * loaded from, their resource index and the fact if they have a shortcut * icon overlay or not. */ - if (e1->dwSourceIndex != e2->dwSourceIndex || /* first the faster one */ - (e1->dwFlags & GIL_FORSHORTCUT) != (e2->dwFlags & GIL_FORSHORTCUT)) - return 1; - - if (wcsicmp(e1->sSourceFile,e2->sSourceFile)) - return 1; - - return 0; + /* first the faster one */ + if (e1->dwSourceIndex != e2->dwSourceIndex) + return (e1->dwSourceIndex < e2->dwSourceIndex) ? -1 : 1; + + if ((e1->dwFlags & GIL_FORSHORTCUT) != (e2->dwFlags & GIL_FORSHORTCUT)) + return ((e1->dwFlags & GIL_FORSHORTCUT) < (e2->dwFlags & GIL_FORSHORTCUT)) ? -1 : 1; + + return wcsicmp(e1->sSourceFile,e2->sSourceFile); }
/* declare SIC_LoadOverlayIcon() */ @@ -338,7 +338,8 @@
EnterCriticalSection(&SHELL32_SicCS);
- indexDPA = DPA_InsertPtr(sic_hdpa, 0x7fff, lpsice); + indexDPA = DPA_Search (sic_hdpa, lpsice, 0, SIC_CompareEntries, 0, DPAS_SORTED|DPAS_INSERTAFTER); + indexDPA = DPA_InsertPtr(sic_hdpa, indexDPA, lpsice); if ( -1 == indexDPA ) { ret = INVALID_INDEX; @@ -468,7 +469,7 @@ if (NULL != DPA_GetPtr (sic_hdpa, 0)) { /* search linear from position 0*/ - index = DPA_Search (sic_hdpa, &sice, 0, SIC_CompareEntries, 0, 0); + index = DPA_Search (sic_hdpa, &sice, 0, SIC_CompareEntries, 0, DPAS_SORTED); }
if ( INVALID_INDEX == index )
Modified: trunk/reactos/dll/win32/shell32/shfldr.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shfldr.h?... ============================================================================== --- trunk/reactos/dll/win32/shell32/shfldr.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/shfldr.h [iso-8859-1] Sat Aug 9 13:40:13 2014 @@ -37,6 +37,7 @@ #define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)
BOOL SHELL32_GetCustomFolderAttribute (LPCITEMIDLIST pidl, LPCWSTR pwszHeading, LPCWSTR pwszAttribute, LPWSTR pwszValue, DWORD cchValue); +BOOL SHELL32_GetCustomFolderAttributes (LPCITEMIDLIST pidl, LPCWSTR pwszHeading, LPWSTR pwszValue, DWORD cchValue);
LPCWSTR GetNextElementW (LPCWSTR pszNext, LPWSTR pszOut, DWORD dwOut); HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, LPITEMIDLIST * pidlInOut,
Modified: trunk/reactos/dll/win32/shell32/shlfolder.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shlfolder... ============================================================================== --- trunk/reactos/dll/win32/shell32/shlfolder.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/shlfolder.cpp [iso-8859-1] Sat Aug 9 13:40:13 2014 @@ -80,6 +80,33 @@ } return FALSE; } + +BOOL SHELL32_GetCustomFolderAttributes( + LPCITEMIDLIST pidl, LPCWSTR pwszHeading, + LPWSTR pwszValue, DWORD cchValue) +{ + DWORD dwAttrib = FILE_ATTRIBUTE_SYSTEM; + WCHAR wszFolderPath[MAX_PATH]; + + /* Hack around not having system attribute on non-Windows file systems */ + if (0) + dwAttrib = _ILGetFileAttributes(pidl, NULL, 0); + + if (dwAttrib & FILE_ATTRIBUTE_SYSTEM) + { + if (!SHGetPathFromIDListW(pidl, wszFolderPath)) + return FALSE; + + static const WCHAR wszDesktopIni[] = + {'d','e','s','k','t','o','p','.','i','n','i',0}; + + PathAddBackslashW(wszFolderPath); + PathAppendW(wszFolderPath, wszDesktopIni); + return GetPrivateProfileSectionW(pwszHeading, pwszValue, cchValue, wszFolderPath); + } + return FALSE; +} +
/*************************************************************************** * GetNextElement (internal function)