// SysIconUtils.cpp #include "StdAfx.h" #ifndef _UNICODE #include "../../../Common/StringConvert.h" #endif #include "../../../Windows/FileDir.h" #include "SysIconUtils.h" #if defined(__MINGW32__) || defined(__MINGW64__) #include #else #include #endif #ifndef _UNICODE extern bool g_IsNT; #endif int GetIconIndexForCSIDL(int csidl) { LPITEMIDLIST pidl = NULL; SHGetSpecialFolderLocation(NULL, csidl, &pidl); if (pidl) { SHFILEINFO shellInfo; shellInfo.iIcon = 0; const DWORD_PTR res = SHGetFileInfo((LPCTSTR)(const void *)(pidl), FILE_ATTRIBUTE_NORMAL, &shellInfo, sizeof(shellInfo), SHGFI_PIDL | SHGFI_SYSICONINDEX); /* IMalloc *pMalloc; SHGetMalloc(&pMalloc); if (pMalloc) { pMalloc->Free(pidl); pMalloc->Release(); } */ // we use OLE2.dll function here CoTaskMemFree(pidl); if (res) return shellInfo.iIcon; } return 0; } #ifndef _UNICODE typedef DWORD_PTR (WINAPI * Func_SHGetFileInfoW)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags); static struct C_SHGetFileInfo_Init { Func_SHGetFileInfoW f_SHGetFileInfoW; C_SHGetFileInfo_Init() { f_SHGetFileInfoW = Z7_GET_PROC_ADDRESS( Func_SHGetFileInfoW, ::GetModuleHandleW(L"shell32.dll"), "SHGetFileInfoW"); } } g_SHGetFileInfo_Init; #endif static DWORD_PTR My_SHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags) { #ifdef _UNICODE return SHGetFileInfo #else if (!g_SHGetFileInfo_Init.f_SHGetFileInfoW) return 0; return g_SHGetFileInfo_Init.f_SHGetFileInfoW #endif (pszPath, attrib, psfi, cbFileInfo, uFlags); } DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex) { #ifndef _UNICODE if (!g_IsNT) { SHFILEINFO shellInfo; const 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; const DWORD_PTR res = ::My_SHGetFileInfoW(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 = ::My_SHGetFileInfoW(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 &vect, DWORD attrib, unsigned &insertPos) { unsigned left = 0, right = vect.Size(); while (left != right) { const unsigned mid = (left + right) / 2; const DWORD midAttrib = vect[mid].Attrib; if (attrib == midAttrib) return (int)mid; if (attrib < midAttrib) right = mid; else left = mid + 1; } insertPos = left; return -1; } static int FindInSorted_Ext(const CObjectVector &vect, const wchar_t *ext, unsigned &insertPos) { unsigned left = 0, right = vect.Size(); while (left != right) { const unsigned mid = (left + right) / 2; const int compare = MyStringCompareNoCase(ext, vect[mid].Ext); if (compare == 0) return (int)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++) { const wchar_t c = fileName[i]; if (c == 0) break; if (c == '.') dotPos = (int)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) { unsigned insertPos = 0; const int index = FindInSorted_Attrib(_attribMap, attrib, insertPos); if (index >= 0) { // if (typeName) *typeName = _attribMap[index].TypeName; return _attribMap[(unsigned)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; unsigned insertPos = 0; const 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++) { const 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); } */ HIMAGELIST GetSysImageList(bool smallIcons) { SHFILEINFO shellInfo; return (HIMAGELIST)SHGetFileInfo(TEXT(""), FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY, &shellInfo, sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | (smallIcons ? SHGFI_SMALLICON : SHGFI_ICON)); }