// SysIconUtils.cpp #include "StdAfx.h" #ifndef _UNICODE #include "../../../Common/StringConvert.h" #endif #include "../../../Windows/FileDir.h" #include "SysIconUtils.h" #ifndef _UNICODE extern bool g_IsNT; #endif int GetIconIndexForCSIDL(int csidl) { LPITEMIDLIST pidl = 0; SHGetSpecialFolderLocation(NULL, csidl, &pidl); if (pidl) { SHFILEINFO shellInfo; SHGetFileInfo(LPCTSTR(pidl), FILE_ATTRIBUTE_NORMAL, &shellInfo, sizeof(shellInfo), SHGFI_PIDL | SHGFI_SYSICONINDEX); IMalloc *pMalloc; SHGetMalloc(&pMalloc); if (pMalloc) { pMalloc->Free(pidl); pMalloc->Release(); } return shellInfo.iIcon; } return 0; } #ifndef _UNICODE typedef int (WINAPI * SHGetFileInfoWP)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags); struct CSHGetFileInfoInit { SHGetFileInfoWP shGetFileInfoW; CSHGetFileInfoInit() { shGetFileInfoW = (SHGetFileInfoWP) ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetFileInfoW"); } } g_SHGetFileInfoInit; #endif static DWORD_PTR MySHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags) { #ifdef _UNICODE return SHGetFileInfo #else if (g_SHGetFileInfoInit.shGetFileInfoW == 0) return 0; return g_SHGetFileInfoInit.shGetFileInfoW #endif (pszPath, attrib, psfi, cbFileInfo, uFlags); } DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex) { #ifndef _UNICODE if (!g_IsNT) { SHFILEINFO shellInfo; DWORD_PTR res = ::SHGetFileInfo(fs2fas(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX); iconIndex = shellInfo.iIcon; return res; } else #endif { SHFILEINFOW shellInfo; DWORD_PTR res = ::MySHGetFileInfoW(fs2us(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX); iconIndex = shellInfo.iIcon; return res; } } /* DWORD_PTR GetRealIconIndex(const UString &fileName, DWORD attrib, int &iconIndex, UString *typeName) { #ifndef _UNICODE if (!g_IsNT) { SHFILEINFO shellInfo; shellInfo.szTypeName[0] = 0; DWORD_PTR res = ::SHGetFileInfoA(GetSystemString(fileName), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME); if (typeName) *typeName = GetUnicodeString(shellInfo.szTypeName); iconIndex = shellInfo.iIcon; return res; } else #endif { SHFILEINFOW shellInfo; shellInfo.szTypeName[0] = 0; DWORD_PTR res = ::MySHGetFileInfoW(fileName, FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME); if (typeName) *typeName = shellInfo.szTypeName; iconIndex = shellInfo.iIcon; return res; } } */ static int FindInSorted_Attrib(const CRecordVector<CAttribIconPair> &vect, DWORD attrib, int &insertPos) { unsigned left = 0, right = vect.Size(); while (left != right) { unsigned mid = (left + right) / 2; DWORD midAttrib = vect[mid].Attrib; if (attrib == midAttrib) return mid; if (attrib < midAttrib) right = mid; else left = mid + 1; } insertPos = left; return -1; } static int FindInSorted_Ext(const CObjectVector<CExtIconPair> &vect, const wchar_t *ext, int &insertPos) { unsigned left = 0, right = vect.Size(); while (left != right) { unsigned mid = (left + right) / 2; int compare = MyStringCompareNoCase(ext, vect[mid].Ext); if (compare == 0) return mid; if (compare < 0) right = mid; else left = mid + 1; } insertPos = left; return -1; } int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UString *typeName */) { int dotPos = -1; unsigned i; for (i = 0;; i++) { wchar_t c = fileName[i]; if (c == 0) break; if (c == '.') dotPos = i; } /* if (MyStringCompareNoCase(fileName, L"$Recycle.Bin") == 0) { char s[256]; sprintf(s, "SPEC i = %3d, attr = %7x", _attribMap.Size(), attrib); OutputDebugStringA(s); OutputDebugStringW(fileName); } */ if ((attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 || dotPos < 0) { int insertPos = 0; int index = FindInSorted_Attrib(_attribMap, attrib, insertPos); if (index >= 0) { // if (typeName) *typeName = _attribMap[index].TypeName; return _attribMap[index].IconIndex; } CAttribIconPair pair; GetRealIconIndex( #ifdef UNDER_CE FTEXT("\\") #endif FTEXT("__DIR__") , attrib, pair.IconIndex // , pair.TypeName ); /* char s[256]; sprintf(s, "i = %3d, attr = %7x", _attribMap.Size(), attrib); OutputDebugStringA(s); */ pair.Attrib = attrib; _attribMap.Insert(insertPos, pair); // if (typeName) *typeName = pair.TypeName; return pair.IconIndex; } const wchar_t *ext = fileName + dotPos + 1; int insertPos = 0; int index = FindInSorted_Ext(_extMap, ext, insertPos); if (index >= 0) { const CExtIconPair &pa = _extMap[index]; // if (typeName) *typeName = pa.TypeName; return pa.IconIndex; } for (i = 0;; i++) { wchar_t c = ext[i]; if (c == 0) break; if (c < L'0' || c > L'9') break; } if (i != 0 && ext[i] == 0) { // GetRealIconIndex is too slow for big number of split extensions: .001, .002, .003 if (!SplitIconIndex_Defined) { GetRealIconIndex( #ifdef UNDER_CE FTEXT("\\") #endif FTEXT("__FILE__.001"), 0, SplitIconIndex); SplitIconIndex_Defined = true; } return SplitIconIndex; } CExtIconPair pair; pair.Ext = ext; GetRealIconIndex(us2fs(fileName + dotPos), attrib, pair.IconIndex); _extMap.Insert(insertPos, pair); // if (typeName) *typeName = pair.TypeName; return pair.IconIndex; } /* int CExtToIconMap::GetIconIndex(DWORD attrib, const UString &fileName) { return GetIconIndex(attrib, fileName, NULL); } */