1// SysIconUtils.cpp 2 3#include "StdAfx.h" 4 5#ifndef _UNICODE 6#include "../../../Common/StringConvert.h" 7#endif 8 9#include "../../../Windows/FileDir.h" 10 11#include "SysIconUtils.h" 12 13#ifndef _UNICODE 14extern bool g_IsNT; 15#endif 16 17int GetIconIndexForCSIDL(int csidl) 18{ 19 LPITEMIDLIST pidl = 0; 20 SHGetSpecialFolderLocation(NULL, csidl, &pidl); 21 if (pidl) 22 { 23 SHFILEINFO shellInfo; 24 SHGetFileInfo(LPCTSTR(pidl), FILE_ATTRIBUTE_NORMAL, 25 &shellInfo, sizeof(shellInfo), 26 SHGFI_PIDL | SHGFI_SYSICONINDEX); 27 IMalloc *pMalloc; 28 SHGetMalloc(&pMalloc); 29 if (pMalloc) 30 { 31 pMalloc->Free(pidl); 32 pMalloc->Release(); 33 } 34 return shellInfo.iIcon; 35 } 36 return 0; 37} 38 39#ifndef _UNICODE 40typedef int (WINAPI * SHGetFileInfoWP)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags); 41 42struct CSHGetFileInfoInit 43{ 44 SHGetFileInfoWP shGetFileInfoW; 45 CSHGetFileInfoInit() 46 { 47 shGetFileInfoW = (SHGetFileInfoWP) 48 ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetFileInfoW"); 49 } 50} g_SHGetFileInfoInit; 51#endif 52 53static DWORD_PTR MySHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags) 54{ 55 #ifdef _UNICODE 56 return SHGetFileInfo 57 #else 58 if (g_SHGetFileInfoInit.shGetFileInfoW == 0) 59 return 0; 60 return g_SHGetFileInfoInit.shGetFileInfoW 61 #endif 62 (pszPath, attrib, psfi, cbFileInfo, uFlags); 63} 64 65DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex) 66{ 67 #ifndef _UNICODE 68 if (!g_IsNT) 69 { 70 SHFILEINFO shellInfo; 71 DWORD_PTR res = ::SHGetFileInfo(fs2fas(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, 72 sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX); 73 iconIndex = shellInfo.iIcon; 74 return res; 75 } 76 else 77 #endif 78 { 79 SHFILEINFOW shellInfo; 80 DWORD_PTR res = ::MySHGetFileInfoW(fs2us(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, 81 sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX); 82 iconIndex = shellInfo.iIcon; 83 return res; 84 } 85} 86 87/* 88DWORD_PTR GetRealIconIndex(const UString &fileName, DWORD attrib, int &iconIndex, UString *typeName) 89{ 90 #ifndef _UNICODE 91 if (!g_IsNT) 92 { 93 SHFILEINFO shellInfo; 94 shellInfo.szTypeName[0] = 0; 95 DWORD_PTR res = ::SHGetFileInfoA(GetSystemString(fileName), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, 96 sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME); 97 if (typeName) 98 *typeName = GetUnicodeString(shellInfo.szTypeName); 99 iconIndex = shellInfo.iIcon; 100 return res; 101 } 102 else 103 #endif 104 { 105 SHFILEINFOW shellInfo; 106 shellInfo.szTypeName[0] = 0; 107 DWORD_PTR res = ::MySHGetFileInfoW(fileName, FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, 108 sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME); 109 if (typeName) 110 *typeName = shellInfo.szTypeName; 111 iconIndex = shellInfo.iIcon; 112 return res; 113 } 114} 115*/ 116 117static int FindInSorted_Attrib(const CRecordVector<CAttribIconPair> &vect, DWORD attrib, int &insertPos) 118{ 119 unsigned left = 0, right = vect.Size(); 120 while (left != right) 121 { 122 unsigned mid = (left + right) / 2; 123 DWORD midAttrib = vect[mid].Attrib; 124 if (attrib == midAttrib) 125 return mid; 126 if (attrib < midAttrib) 127 right = mid; 128 else 129 left = mid + 1; 130 } 131 insertPos = left; 132 return -1; 133} 134 135static int FindInSorted_Ext(const CObjectVector<CExtIconPair> &vect, const wchar_t *ext, int &insertPos) 136{ 137 unsigned left = 0, right = vect.Size(); 138 while (left != right) 139 { 140 unsigned mid = (left + right) / 2; 141 int compare = MyStringCompareNoCase(ext, vect[mid].Ext); 142 if (compare == 0) 143 return mid; 144 if (compare < 0) 145 right = mid; 146 else 147 left = mid + 1; 148 } 149 insertPos = left; 150 return -1; 151} 152 153int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UString *typeName */) 154{ 155 int dotPos = -1; 156 unsigned i; 157 for (i = 0;; i++) 158 { 159 wchar_t c = fileName[i]; 160 if (c == 0) 161 break; 162 if (c == '.') 163 dotPos = i; 164 } 165 166 /* 167 if (MyStringCompareNoCase(fileName, L"$Recycle.Bin") == 0) 168 { 169 char s[256]; 170 sprintf(s, "SPEC i = %3d, attr = %7x", _attribMap.Size(), attrib); 171 OutputDebugStringA(s); 172 OutputDebugStringW(fileName); 173 } 174 */ 175 176 if ((attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 || dotPos < 0) 177 { 178 int insertPos = 0; 179 int index = FindInSorted_Attrib(_attribMap, attrib, insertPos); 180 if (index >= 0) 181 { 182 // if (typeName) *typeName = _attribMap[index].TypeName; 183 return _attribMap[index].IconIndex; 184 } 185 CAttribIconPair pair; 186 GetRealIconIndex( 187 #ifdef UNDER_CE 188 FTEXT("\\") 189 #endif 190 FTEXT("__DIR__") 191 , attrib, pair.IconIndex 192 // , pair.TypeName 193 ); 194 195 /* 196 char s[256]; 197 sprintf(s, "i = %3d, attr = %7x", _attribMap.Size(), attrib); 198 OutputDebugStringA(s); 199 */ 200 201 pair.Attrib = attrib; 202 _attribMap.Insert(insertPos, pair); 203 // if (typeName) *typeName = pair.TypeName; 204 return pair.IconIndex; 205 } 206 207 const wchar_t *ext = fileName + dotPos + 1; 208 int insertPos = 0; 209 int index = FindInSorted_Ext(_extMap, ext, insertPos); 210 if (index >= 0) 211 { 212 const CExtIconPair &pa = _extMap[index]; 213 // if (typeName) *typeName = pa.TypeName; 214 return pa.IconIndex; 215 } 216 217 for (i = 0;; i++) 218 { 219 wchar_t c = ext[i]; 220 if (c == 0) 221 break; 222 if (c < L'0' || c > L'9') 223 break; 224 } 225 if (i != 0 && ext[i] == 0) 226 { 227 // GetRealIconIndex is too slow for big number of split extensions: .001, .002, .003 228 if (!SplitIconIndex_Defined) 229 { 230 GetRealIconIndex( 231 #ifdef UNDER_CE 232 FTEXT("\\") 233 #endif 234 FTEXT("__FILE__.001"), 0, SplitIconIndex); 235 SplitIconIndex_Defined = true; 236 } 237 return SplitIconIndex; 238 } 239 240 CExtIconPair pair; 241 pair.Ext = ext; 242 GetRealIconIndex(us2fs(fileName + dotPos), attrib, pair.IconIndex); 243 _extMap.Insert(insertPos, pair); 244 // if (typeName) *typeName = pair.TypeName; 245 return pair.IconIndex; 246} 247 248/* 249int CExtToIconMap::GetIconIndex(DWORD attrib, const UString &fileName) 250{ 251 return GetIconIndex(attrib, fileName, NULL); 252} 253*/