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
14 extern bool g_IsNT;
15 #endif
16
GetIconIndexForCSIDL(int csidl)17 int 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
40 typedef int (WINAPI * SHGetFileInfoWP)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags);
41
42 struct CSHGetFileInfoInit
43 {
44 SHGetFileInfoWP shGetFileInfoW;
CSHGetFileInfoInitCSHGetFileInfoInit45 CSHGetFileInfoInit()
46 {
47 shGetFileInfoW = (SHGetFileInfoWP)
48 ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetFileInfoW");
49 }
50 } g_SHGetFileInfoInit;
51 #endif
52
MySHGetFileInfoW(LPCWSTR pszPath,DWORD attrib,SHFILEINFOW * psfi,UINT cbFileInfo,UINT uFlags)53 static 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
GetRealIconIndex(CFSTR path,DWORD attrib,int & iconIndex)65 DWORD_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 /*
88 DWORD_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
FindInSorted_Attrib(const CRecordVector<CAttribIconPair> & vect,DWORD attrib,int & insertPos)117 static 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
FindInSorted_Ext(const CObjectVector<CExtIconPair> & vect,const wchar_t * ext,int & insertPos)135 static 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
GetIconIndex(DWORD attrib,const wchar_t * fileName)153 int 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 /*
249 int CExtToIconMap::GetIconIndex(DWORD attrib, const UString &fileName)
250 {
251 return GetIconIndex(attrib, fileName, NULL);
252 }
253 */