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.…
==============================================================================
--- 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/iconcach…
==============================================================================
--- 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/shlfolde…
==============================================================================
--- 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)