diff --git a/reactos/dll/win32/shell32/folders.cpp b/reactos/dll/win32/shell32/folders.cpp index 9df6d6d4744..5dc06b1bd7c 100644 --- a/reactos/dll/win32/shell32/folders.cpp +++ b/reactos/dll/win32/shell32/folders.cpp @@ -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, diff --git a/reactos/dll/win32/shell32/iconcache.cpp b/reactos/dll/win32/shell32/iconcache.cpp index 5027d772061..713b34b9195 100644 --- a/reactos/dll/win32/shell32/iconcache.cpp +++ b/reactos/dll/win32/shell32/iconcache.cpp @@ -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 ) diff --git a/reactos/dll/win32/shell32/shfldr.h b/reactos/dll/win32/shell32/shfldr.h index 81111ce4999..3374b19bff9 100644 --- a/reactos/dll/win32/shell32/shfldr.h +++ b/reactos/dll/win32/shell32/shfldr.h @@ -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, diff --git a/reactos/dll/win32/shell32/shlfolder.cpp b/reactos/dll/win32/shell32/shlfolder.cpp index e821066ec1d..5f9a8ecb7c7 100644 --- a/reactos/dll/win32/shell32/shlfolder.cpp +++ b/reactos/dll/win32/shell32/shlfolder.cpp @@ -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) *