mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 00:45:24 +00:00
[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. svn path=/trunk/; revision=63845
This commit is contained in:
parent
f9a6eb7bc4
commit
de7b63edc1
4 changed files with 82 additions and 35 deletions
|
@ -28,6 +28,7 @@ static HRESULT getIconLocationForFolder(LPCITEMIDLIST pidl, UINT uFlags,
|
|||
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 HRESULT getIconLocationForFolder(LPCITEMIDLIST pidl, UINT uFlags,
|
|||
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))
|
||||
/*
|
||||
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))
|
||||
{
|
||||
WCHAR wszIconIndex[10];
|
||||
SHELL32_GetCustomFolderAttribute(pidl, shellClassInfo, iconIndex,
|
||||
wszIconIndex, 10);
|
||||
*piIndex = _wtoi(wszIconIndex);
|
||||
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;
|
||||
}
|
||||
}
|
||||
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
|
||||
if (cont)
|
||||
{
|
||||
static const WCHAR folder[] = { 'F', 'o', 'l', 'd', 'e', 'r', 0 };
|
||||
|
||||
|
@ -322,6 +336,10 @@ IExtractIconW* IExtractIconW_Constructor(LPCITEMIDLIST pidl)
|
|||
&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 @@ IExtractIconW* IExtractIconW_Constructor(LPCITEMIDLIST pidl)
|
|||
{
|
||||
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,
|
||||
|
|
|
@ -64,14 +64,14 @@ static INT CALLBACK SIC_CompareEntries( LPVOID p1, LPVOID p2, LPARAM lparam)
|
|||
* 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;
|
||||
/* first the faster one */
|
||||
if (e1->dwSourceIndex != e2->dwSourceIndex)
|
||||
return (e1->dwSourceIndex < e2->dwSourceIndex) ? -1 : 1;
|
||||
|
||||
if (wcsicmp(e1->sSourceFile,e2->sSourceFile))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
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 @@ static INT SIC_IconAppend (LPCWSTR sSourceFile, INT dwSourceIndex, HICON hSmallI
|
|||
|
||||
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 @@ INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags )
|
|||
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 )
|
||||
|
|
|
@ -37,6 +37,7 @@ typedef struct {
|
|||
#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,
|
||||
|
|
|
@ -81,6 +81,33 @@ BOOL SHELL32_GetCustomFolderAttribute(
|
|||
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)
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue