xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/FileManager/SysIconUtils.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // SysIconUtils.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/StringConvert.h"
7*f6dc9357SAndroid Build Coastguard Worker #endif
8*f6dc9357SAndroid Build Coastguard Worker 
9*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileDir.h"
10*f6dc9357SAndroid Build Coastguard Worker 
11*f6dc9357SAndroid Build Coastguard Worker #include "SysIconUtils.h"
12*f6dc9357SAndroid Build Coastguard Worker 
13*f6dc9357SAndroid Build Coastguard Worker #if defined(__MINGW32__) || defined(__MINGW64__)
14*f6dc9357SAndroid Build Coastguard Worker #include <shlobj.h>
15*f6dc9357SAndroid Build Coastguard Worker #else
16*f6dc9357SAndroid Build Coastguard Worker #include <ShlObj.h>
17*f6dc9357SAndroid Build Coastguard Worker #endif
18*f6dc9357SAndroid Build Coastguard Worker 
19*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
20*f6dc9357SAndroid Build Coastguard Worker extern bool g_IsNT;
21*f6dc9357SAndroid Build Coastguard Worker #endif
22*f6dc9357SAndroid Build Coastguard Worker 
23*f6dc9357SAndroid Build Coastguard Worker CExtToIconMap g_Ext_to_Icon_Map;
24*f6dc9357SAndroid Build Coastguard Worker 
Shell_GetFileInfo_SysIconIndex_for_CSIDL(int csidl)25*f6dc9357SAndroid Build Coastguard Worker int Shell_GetFileInfo_SysIconIndex_for_CSIDL(int csidl)
26*f6dc9357SAndroid Build Coastguard Worker {
27*f6dc9357SAndroid Build Coastguard Worker   LPITEMIDLIST pidl = NULL;
28*f6dc9357SAndroid Build Coastguard Worker   SHGetSpecialFolderLocation(NULL, csidl, &pidl);
29*f6dc9357SAndroid Build Coastguard Worker   if (pidl)
30*f6dc9357SAndroid Build Coastguard Worker   {
31*f6dc9357SAndroid Build Coastguard Worker     SHFILEINFO shFileInfo;
32*f6dc9357SAndroid Build Coastguard Worker     shFileInfo.iIcon = -1;
33*f6dc9357SAndroid Build Coastguard Worker     const DWORD_PTR res = SHGetFileInfo((LPCTSTR)(const void *)(pidl),
34*f6dc9357SAndroid Build Coastguard Worker         FILE_ATTRIBUTE_DIRECTORY,
35*f6dc9357SAndroid Build Coastguard Worker         &shFileInfo, sizeof(shFileInfo),
36*f6dc9357SAndroid Build Coastguard Worker         SHGFI_PIDL | SHGFI_SYSICONINDEX);
37*f6dc9357SAndroid Build Coastguard Worker     /*
38*f6dc9357SAndroid Build Coastguard Worker     IMalloc *pMalloc;
39*f6dc9357SAndroid Build Coastguard Worker     SHGetMalloc(&pMalloc);
40*f6dc9357SAndroid Build Coastguard Worker     if (pMalloc)
41*f6dc9357SAndroid Build Coastguard Worker     {
42*f6dc9357SAndroid Build Coastguard Worker       pMalloc->Free(pidl);
43*f6dc9357SAndroid Build Coastguard Worker       pMalloc->Release();
44*f6dc9357SAndroid Build Coastguard Worker     }
45*f6dc9357SAndroid Build Coastguard Worker     */
46*f6dc9357SAndroid Build Coastguard Worker     // we use OLE2.dll function here
47*f6dc9357SAndroid Build Coastguard Worker     CoTaskMemFree(pidl);
48*f6dc9357SAndroid Build Coastguard Worker     if (res)
49*f6dc9357SAndroid Build Coastguard Worker       return shFileInfo.iIcon;
50*f6dc9357SAndroid Build Coastguard Worker   }
51*f6dc9357SAndroid Build Coastguard Worker   return -1;
52*f6dc9357SAndroid Build Coastguard Worker }
53*f6dc9357SAndroid Build Coastguard Worker 
54*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
55*f6dc9357SAndroid Build Coastguard Worker Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
56*f6dc9357SAndroid Build Coastguard Worker typedef DWORD_PTR (WINAPI * Func_SHGetFileInfoW)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags);
57*f6dc9357SAndroid Build Coastguard Worker 
58*f6dc9357SAndroid Build Coastguard Worker static struct C_SHGetFileInfo_Init
59*f6dc9357SAndroid Build Coastguard Worker {
60*f6dc9357SAndroid Build Coastguard Worker   Func_SHGetFileInfoW f_SHGetFileInfoW;
C_SHGetFileInfo_InitC_SHGetFileInfo_Init61*f6dc9357SAndroid Build Coastguard Worker   C_SHGetFileInfo_Init()
62*f6dc9357SAndroid Build Coastguard Worker   {
63*f6dc9357SAndroid Build Coastguard Worker        f_SHGetFileInfoW = Z7_GET_PROC_ADDRESS(
64*f6dc9357SAndroid Build Coastguard Worker     Func_SHGetFileInfoW, ::GetModuleHandleW(L"shell32.dll"),
65*f6dc9357SAndroid Build Coastguard Worker         "SHGetFileInfoW");
66*f6dc9357SAndroid Build Coastguard Worker     // f_SHGetFileInfoW = NULL; // for debug
67*f6dc9357SAndroid Build Coastguard Worker   }
68*f6dc9357SAndroid Build Coastguard Worker } g_SHGetFileInfo_Init;
69*f6dc9357SAndroid Build Coastguard Worker #endif
70*f6dc9357SAndroid Build Coastguard Worker 
71*f6dc9357SAndroid Build Coastguard Worker #ifdef _UNICODE
72*f6dc9357SAndroid Build Coastguard Worker #define My_SHGetFileInfoW SHGetFileInfoW
73*f6dc9357SAndroid Build Coastguard Worker #else
My_SHGetFileInfoW(LPCWSTR pszPath,DWORD attrib,SHFILEINFOW * psfi,UINT cbFileInfo,UINT uFlags)74*f6dc9357SAndroid Build Coastguard Worker static DWORD_PTR My_SHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags)
75*f6dc9357SAndroid Build Coastguard Worker {
76*f6dc9357SAndroid Build Coastguard Worker   if (!g_SHGetFileInfo_Init.f_SHGetFileInfoW)
77*f6dc9357SAndroid Build Coastguard Worker     return 0;
78*f6dc9357SAndroid Build Coastguard Worker   return g_SHGetFileInfo_Init.f_SHGetFileInfoW(pszPath, attrib, psfi, cbFileInfo, uFlags);
79*f6dc9357SAndroid Build Coastguard Worker }
80*f6dc9357SAndroid Build Coastguard Worker #endif
81*f6dc9357SAndroid Build Coastguard Worker 
Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(CFSTR path,DWORD attrib,int & iconIndex)82*f6dc9357SAndroid Build Coastguard Worker DWORD_PTR Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(
83*f6dc9357SAndroid Build Coastguard Worker     CFSTR path, DWORD attrib, int &iconIndex)
84*f6dc9357SAndroid Build Coastguard Worker {
85*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
86*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT || !g_SHGetFileInfo_Init.f_SHGetFileInfoW)
87*f6dc9357SAndroid Build Coastguard Worker   {
88*f6dc9357SAndroid Build Coastguard Worker     SHFILEINFO shFileInfo;
89*f6dc9357SAndroid Build Coastguard Worker     // ZeroMemory(&shFileInfo, sizeof(shFileInfo));
90*f6dc9357SAndroid Build Coastguard Worker     shFileInfo.iIcon = -1;   // optional
91*f6dc9357SAndroid Build Coastguard Worker     const DWORD_PTR res = ::SHGetFileInfo(fs2fas(path),
92*f6dc9357SAndroid Build Coastguard Worker         attrib ? attrib : FILE_ATTRIBUTE_ARCHIVE,
93*f6dc9357SAndroid Build Coastguard Worker         &shFileInfo, sizeof(shFileInfo),
94*f6dc9357SAndroid Build Coastguard Worker         SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
95*f6dc9357SAndroid Build Coastguard Worker     iconIndex = shFileInfo.iIcon;
96*f6dc9357SAndroid Build Coastguard Worker     return res;
97*f6dc9357SAndroid Build Coastguard Worker   }
98*f6dc9357SAndroid Build Coastguard Worker   else
99*f6dc9357SAndroid Build Coastguard Worker #endif
100*f6dc9357SAndroid Build Coastguard Worker   {
101*f6dc9357SAndroid Build Coastguard Worker     SHFILEINFOW shFileInfo;
102*f6dc9357SAndroid Build Coastguard Worker     // ZeroMemory(&shFileInfo, sizeof(shFileInfo));
103*f6dc9357SAndroid Build Coastguard Worker     shFileInfo.iIcon = -1;   // optional
104*f6dc9357SAndroid Build Coastguard Worker     const DWORD_PTR res = ::My_SHGetFileInfoW(fs2us(path),
105*f6dc9357SAndroid Build Coastguard Worker         attrib ? attrib : FILE_ATTRIBUTE_ARCHIVE,
106*f6dc9357SAndroid Build Coastguard Worker         &shFileInfo, sizeof(shFileInfo),
107*f6dc9357SAndroid Build Coastguard Worker         SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
108*f6dc9357SAndroid Build Coastguard Worker     // (shFileInfo.iIcon == 0) returned for unknown extensions and files without extension
109*f6dc9357SAndroid Build Coastguard Worker     iconIndex = shFileInfo.iIcon;
110*f6dc9357SAndroid Build Coastguard Worker     // we use SHGFI_USEFILEATTRIBUTES, and
111*f6dc9357SAndroid Build Coastguard Worker     //   (res != 0) is expected for main cases, even if there are no such file.
112*f6dc9357SAndroid Build Coastguard Worker     //   (res == 0) for path with kSuperPrefix "\\?\"
113*f6dc9357SAndroid Build Coastguard Worker     // Also SHGFI_USEFILEATTRIBUTES still returns icon inside exe.
114*f6dc9357SAndroid Build Coastguard Worker     // So we can use SHGFI_USEFILEATTRIBUTES for any case.
115*f6dc9357SAndroid Build Coastguard Worker     // UString temp = fs2us(path); // for debug
116*f6dc9357SAndroid Build Coastguard Worker     // UString tempName = temp.Ptr(temp.ReverseFind_PathSepar() + 1); // for debug
117*f6dc9357SAndroid Build Coastguard Worker     // iconIndex = -1; // for debug
118*f6dc9357SAndroid Build Coastguard Worker     return res;
119*f6dc9357SAndroid Build Coastguard Worker   }
120*f6dc9357SAndroid Build Coastguard Worker }
121*f6dc9357SAndroid Build Coastguard Worker 
Shell_GetFileInfo_SysIconIndex_for_Path(CFSTR path,DWORD attrib)122*f6dc9357SAndroid Build Coastguard Worker int Shell_GetFileInfo_SysIconIndex_for_Path(CFSTR path, DWORD attrib)
123*f6dc9357SAndroid Build Coastguard Worker {
124*f6dc9357SAndroid Build Coastguard Worker   int iconIndex = -1;
125*f6dc9357SAndroid Build Coastguard Worker   if (!Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(
126*f6dc9357SAndroid Build Coastguard Worker       path, attrib, iconIndex))
127*f6dc9357SAndroid Build Coastguard Worker     iconIndex = -1;
128*f6dc9357SAndroid Build Coastguard Worker   return iconIndex;
129*f6dc9357SAndroid Build Coastguard Worker }
130*f6dc9357SAndroid Build Coastguard Worker 
131*f6dc9357SAndroid Build Coastguard Worker 
Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(CFSTR path,DWORD attrib,Int32 * iconIndex)132*f6dc9357SAndroid Build Coastguard Worker HRESULT Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
133*f6dc9357SAndroid Build Coastguard Worker     CFSTR path, DWORD attrib, Int32 *iconIndex)
134*f6dc9357SAndroid Build Coastguard Worker {
135*f6dc9357SAndroid Build Coastguard Worker   *iconIndex = -1;
136*f6dc9357SAndroid Build Coastguard Worker   int iconIndexTemp;
137*f6dc9357SAndroid Build Coastguard Worker   if (Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(
138*f6dc9357SAndroid Build Coastguard Worker       path, attrib, iconIndexTemp))
139*f6dc9357SAndroid Build Coastguard Worker   {
140*f6dc9357SAndroid Build Coastguard Worker     *iconIndex = iconIndexTemp;
141*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
142*f6dc9357SAndroid Build Coastguard Worker   }
143*f6dc9357SAndroid Build Coastguard Worker   return GetLastError_noZero_HRESULT();
144*f6dc9357SAndroid Build Coastguard Worker }
145*f6dc9357SAndroid Build Coastguard Worker 
146*f6dc9357SAndroid Build Coastguard Worker /*
147*f6dc9357SAndroid Build Coastguard Worker DWORD_PTR Shell_GetFileInfo_SysIconIndex_for_Path(const UString &fileName, DWORD attrib, int &iconIndex, UString *typeName)
148*f6dc9357SAndroid Build Coastguard Worker {
149*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
150*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
151*f6dc9357SAndroid Build Coastguard Worker   {
152*f6dc9357SAndroid Build Coastguard Worker     SHFILEINFO shFileInfo;
153*f6dc9357SAndroid Build Coastguard Worker     shFileInfo.szTypeName[0] = 0;
154*f6dc9357SAndroid Build Coastguard Worker     DWORD_PTR res = ::SHGetFileInfoA(GetSystemString(fileName), FILE_ATTRIBUTE_ARCHIVE | attrib, &shFileInfo,
155*f6dc9357SAndroid Build Coastguard Worker         sizeof(shFileInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
156*f6dc9357SAndroid Build Coastguard Worker     if (typeName)
157*f6dc9357SAndroid Build Coastguard Worker       *typeName = GetUnicodeString(shFileInfo.szTypeName);
158*f6dc9357SAndroid Build Coastguard Worker     iconIndex = shFileInfo.iIcon;
159*f6dc9357SAndroid Build Coastguard Worker     return res;
160*f6dc9357SAndroid Build Coastguard Worker   }
161*f6dc9357SAndroid Build Coastguard Worker   else
162*f6dc9357SAndroid Build Coastguard Worker   #endif
163*f6dc9357SAndroid Build Coastguard Worker   {
164*f6dc9357SAndroid Build Coastguard Worker     SHFILEINFOW shFileInfo;
165*f6dc9357SAndroid Build Coastguard Worker     shFileInfo.szTypeName[0] = 0;
166*f6dc9357SAndroid Build Coastguard Worker     DWORD_PTR res = ::My_SHGetFileInfoW(fileName, FILE_ATTRIBUTE_ARCHIVE | attrib, &shFileInfo,
167*f6dc9357SAndroid Build Coastguard Worker         sizeof(shFileInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
168*f6dc9357SAndroid Build Coastguard Worker     if (typeName)
169*f6dc9357SAndroid Build Coastguard Worker       *typeName = shFileInfo.szTypeName;
170*f6dc9357SAndroid Build Coastguard Worker     iconIndex = shFileInfo.iIcon;
171*f6dc9357SAndroid Build Coastguard Worker     return res;
172*f6dc9357SAndroid Build Coastguard Worker   }
173*f6dc9357SAndroid Build Coastguard Worker }
174*f6dc9357SAndroid Build Coastguard Worker */
175*f6dc9357SAndroid Build Coastguard Worker 
FindInSorted_Attrib(const CRecordVector<CAttribIconPair> & vect,DWORD attrib,unsigned & insertPos)176*f6dc9357SAndroid Build Coastguard Worker static int FindInSorted_Attrib(const CRecordVector<CAttribIconPair> &vect, DWORD attrib, unsigned &insertPos)
177*f6dc9357SAndroid Build Coastguard Worker {
178*f6dc9357SAndroid Build Coastguard Worker   unsigned left = 0, right = vect.Size();
179*f6dc9357SAndroid Build Coastguard Worker   while (left != right)
180*f6dc9357SAndroid Build Coastguard Worker   {
181*f6dc9357SAndroid Build Coastguard Worker     const unsigned mid = (left + right) / 2;
182*f6dc9357SAndroid Build Coastguard Worker     const DWORD midAttrib = vect[mid].Attrib;
183*f6dc9357SAndroid Build Coastguard Worker     if (attrib == midAttrib)
184*f6dc9357SAndroid Build Coastguard Worker       return (int)mid;
185*f6dc9357SAndroid Build Coastguard Worker     if (attrib < midAttrib)
186*f6dc9357SAndroid Build Coastguard Worker       right = mid;
187*f6dc9357SAndroid Build Coastguard Worker     else
188*f6dc9357SAndroid Build Coastguard Worker       left = mid + 1;
189*f6dc9357SAndroid Build Coastguard Worker   }
190*f6dc9357SAndroid Build Coastguard Worker   insertPos = left;
191*f6dc9357SAndroid Build Coastguard Worker   return -1;
192*f6dc9357SAndroid Build Coastguard Worker }
193*f6dc9357SAndroid Build Coastguard Worker 
FindInSorted_Ext(const CObjectVector<CExtIconPair> & vect,const wchar_t * ext,unsigned & insertPos)194*f6dc9357SAndroid Build Coastguard Worker static int FindInSorted_Ext(const CObjectVector<CExtIconPair> &vect, const wchar_t *ext, unsigned &insertPos)
195*f6dc9357SAndroid Build Coastguard Worker {
196*f6dc9357SAndroid Build Coastguard Worker   unsigned left = 0, right = vect.Size();
197*f6dc9357SAndroid Build Coastguard Worker   while (left != right)
198*f6dc9357SAndroid Build Coastguard Worker   {
199*f6dc9357SAndroid Build Coastguard Worker     const unsigned mid = (left + right) / 2;
200*f6dc9357SAndroid Build Coastguard Worker     const int compare = MyStringCompareNoCase(ext, vect[mid].Ext);
201*f6dc9357SAndroid Build Coastguard Worker     if (compare == 0)
202*f6dc9357SAndroid Build Coastguard Worker       return (int)mid;
203*f6dc9357SAndroid Build Coastguard Worker     if (compare < 0)
204*f6dc9357SAndroid Build Coastguard Worker       right = mid;
205*f6dc9357SAndroid Build Coastguard Worker     else
206*f6dc9357SAndroid Build Coastguard Worker       left = mid + 1;
207*f6dc9357SAndroid Build Coastguard Worker   }
208*f6dc9357SAndroid Build Coastguard Worker   insertPos = left;
209*f6dc9357SAndroid Build Coastguard Worker   return -1;
210*f6dc9357SAndroid Build Coastguard Worker }
211*f6dc9357SAndroid Build Coastguard Worker 
212*f6dc9357SAndroid Build Coastguard Worker 
213*f6dc9357SAndroid Build Coastguard Worker // bool DoItemAlwaysStart(const UString &name);
214*f6dc9357SAndroid Build Coastguard Worker 
GetIconIndex(DWORD attrib,const wchar_t * fileName)215*f6dc9357SAndroid Build Coastguard Worker int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UString *typeName */)
216*f6dc9357SAndroid Build Coastguard Worker {
217*f6dc9357SAndroid Build Coastguard Worker   int dotPos = -1;
218*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
219*f6dc9357SAndroid Build Coastguard Worker   for (i = 0;; i++)
220*f6dc9357SAndroid Build Coastguard Worker   {
221*f6dc9357SAndroid Build Coastguard Worker     const wchar_t c = fileName[i];
222*f6dc9357SAndroid Build Coastguard Worker     if (c == 0)
223*f6dc9357SAndroid Build Coastguard Worker       break;
224*f6dc9357SAndroid Build Coastguard Worker     if (c == '.')
225*f6dc9357SAndroid Build Coastguard Worker       dotPos = (int)i;
226*f6dc9357SAndroid Build Coastguard Worker     // we don't need IS_PATH_SEPAR check, because (fileName) doesn't include path prefix.
227*f6dc9357SAndroid Build Coastguard Worker     // if (IS_PATH_SEPAR(c) || c == ':') dotPos = -1;
228*f6dc9357SAndroid Build Coastguard Worker   }
229*f6dc9357SAndroid Build Coastguard Worker 
230*f6dc9357SAndroid Build Coastguard Worker   /*
231*f6dc9357SAndroid Build Coastguard Worker   if (MyStringCompareNoCase(fileName, L"$Recycle.Bin") == 0)
232*f6dc9357SAndroid Build Coastguard Worker   {
233*f6dc9357SAndroid Build Coastguard Worker     char s[256];
234*f6dc9357SAndroid Build Coastguard Worker     sprintf(s, "SPEC i = %3d, attr = %7x", _attribMap.Size(), attrib);
235*f6dc9357SAndroid Build Coastguard Worker     OutputDebugStringA(s);
236*f6dc9357SAndroid Build Coastguard Worker     OutputDebugStringW(fileName);
237*f6dc9357SAndroid Build Coastguard Worker   }
238*f6dc9357SAndroid Build Coastguard Worker   */
239*f6dc9357SAndroid Build Coastguard Worker 
240*f6dc9357SAndroid Build Coastguard Worker   if ((attrib & FILE_ATTRIBUTE_DIRECTORY) || dotPos < 0)
241*f6dc9357SAndroid Build Coastguard Worker   for (unsigned k = 0;; k++)
242*f6dc9357SAndroid Build Coastguard Worker   {
243*f6dc9357SAndroid Build Coastguard Worker     if (k >= 2)
244*f6dc9357SAndroid Build Coastguard Worker       return -1;
245*f6dc9357SAndroid Build Coastguard Worker     unsigned insertPos = 0;
246*f6dc9357SAndroid Build Coastguard Worker     const int index = FindInSorted_Attrib(_attribMap, attrib, insertPos);
247*f6dc9357SAndroid Build Coastguard Worker     if (index >= 0)
248*f6dc9357SAndroid Build Coastguard Worker     {
249*f6dc9357SAndroid Build Coastguard Worker       // if (typeName) *typeName = _attribMap[index].TypeName;
250*f6dc9357SAndroid Build Coastguard Worker       return _attribMap[(unsigned)index].IconIndex;
251*f6dc9357SAndroid Build Coastguard Worker     }
252*f6dc9357SAndroid Build Coastguard Worker     CAttribIconPair pair;
253*f6dc9357SAndroid Build Coastguard Worker     pair.IconIndex = Shell_GetFileInfo_SysIconIndex_for_Path(
254*f6dc9357SAndroid Build Coastguard Worker         #ifdef UNDER_CE
255*f6dc9357SAndroid Build Coastguard Worker         FTEXT("\\")
256*f6dc9357SAndroid Build Coastguard Worker         #endif
257*f6dc9357SAndroid Build Coastguard Worker         FTEXT("__DIR__")
258*f6dc9357SAndroid Build Coastguard Worker         , attrib
259*f6dc9357SAndroid Build Coastguard Worker         // , pair.TypeName
260*f6dc9357SAndroid Build Coastguard Worker         );
261*f6dc9357SAndroid Build Coastguard Worker     if (_attribMap.Size() < (1u << 16) // we limit cache size
262*f6dc9357SAndroid Build Coastguard Worker        || attrib < (1u << 15)) // we want to put all items with basic attribs to cache
263*f6dc9357SAndroid Build Coastguard Worker     {
264*f6dc9357SAndroid Build Coastguard Worker       /*
265*f6dc9357SAndroid Build Coastguard Worker       char s[256];
266*f6dc9357SAndroid Build Coastguard Worker       sprintf(s, "i = %3d, attr = %7x", _attribMap.Size(), attrib);
267*f6dc9357SAndroid Build Coastguard Worker       OutputDebugStringA(s);
268*f6dc9357SAndroid Build Coastguard Worker       */
269*f6dc9357SAndroid Build Coastguard Worker       pair.Attrib = attrib;
270*f6dc9357SAndroid Build Coastguard Worker       _attribMap.Insert(insertPos, pair);
271*f6dc9357SAndroid Build Coastguard Worker       // if (typeName) *typeName = pair.TypeName;
272*f6dc9357SAndroid Build Coastguard Worker       return pair.IconIndex;
273*f6dc9357SAndroid Build Coastguard Worker     }
274*f6dc9357SAndroid Build Coastguard Worker     if (pair.IconIndex >= 0)
275*f6dc9357SAndroid Build Coastguard Worker       return pair.IconIndex;
276*f6dc9357SAndroid Build Coastguard Worker     attrib = (attrib & FILE_ATTRIBUTE_DIRECTORY) ?
277*f6dc9357SAndroid Build Coastguard Worker         FILE_ATTRIBUTE_DIRECTORY :
278*f6dc9357SAndroid Build Coastguard Worker         FILE_ATTRIBUTE_ARCHIVE;
279*f6dc9357SAndroid Build Coastguard Worker   }
280*f6dc9357SAndroid Build Coastguard Worker 
281*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<CExtIconPair> &map =
282*f6dc9357SAndroid Build Coastguard Worker       (attrib & FILE_ATTRIBUTE_COMPRESSED) ?
283*f6dc9357SAndroid Build Coastguard Worker           _extMap_Compressed : _extMap_Normal;
284*f6dc9357SAndroid Build Coastguard Worker   const wchar_t *ext = fileName + dotPos + 1;
285*f6dc9357SAndroid Build Coastguard Worker   unsigned insertPos = 0;
286*f6dc9357SAndroid Build Coastguard Worker   const int index = FindInSorted_Ext(map, ext, insertPos);
287*f6dc9357SAndroid Build Coastguard Worker   if (index >= 0)
288*f6dc9357SAndroid Build Coastguard Worker   {
289*f6dc9357SAndroid Build Coastguard Worker     const CExtIconPair &pa = map[index];
290*f6dc9357SAndroid Build Coastguard Worker     // if (typeName) *typeName = pa.TypeName;
291*f6dc9357SAndroid Build Coastguard Worker     return pa.IconIndex;
292*f6dc9357SAndroid Build Coastguard Worker   }
293*f6dc9357SAndroid Build Coastguard Worker 
294*f6dc9357SAndroid Build Coastguard Worker   for (i = 0;; i++)
295*f6dc9357SAndroid Build Coastguard Worker   {
296*f6dc9357SAndroid Build Coastguard Worker     const wchar_t c = ext[i];
297*f6dc9357SAndroid Build Coastguard Worker     if (c == 0)
298*f6dc9357SAndroid Build Coastguard Worker       break;
299*f6dc9357SAndroid Build Coastguard Worker     if (c < L'0' || c > L'9')
300*f6dc9357SAndroid Build Coastguard Worker       break;
301*f6dc9357SAndroid Build Coastguard Worker   }
302*f6dc9357SAndroid Build Coastguard Worker   if (i != 0 && ext[i] == 0)
303*f6dc9357SAndroid Build Coastguard Worker   {
304*f6dc9357SAndroid Build Coastguard Worker     // Shell_GetFileInfo_SysIconIndex_for_Path is too slow for big number of split extensions: .001, .002, .003
305*f6dc9357SAndroid Build Coastguard Worker     if (!SplitIconIndex_Defined)
306*f6dc9357SAndroid Build Coastguard Worker     {
307*f6dc9357SAndroid Build Coastguard Worker       Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(
308*f6dc9357SAndroid Build Coastguard Worker           #ifdef UNDER_CE
309*f6dc9357SAndroid Build Coastguard Worker           FTEXT("\\")
310*f6dc9357SAndroid Build Coastguard Worker           #endif
311*f6dc9357SAndroid Build Coastguard Worker           FTEXT("__FILE__.001"), FILE_ATTRIBUTE_ARCHIVE, SplitIconIndex);
312*f6dc9357SAndroid Build Coastguard Worker       SplitIconIndex_Defined = true;
313*f6dc9357SAndroid Build Coastguard Worker     }
314*f6dc9357SAndroid Build Coastguard Worker     return SplitIconIndex;
315*f6dc9357SAndroid Build Coastguard Worker   }
316*f6dc9357SAndroid Build Coastguard Worker 
317*f6dc9357SAndroid Build Coastguard Worker   CExtIconPair pair;
318*f6dc9357SAndroid Build Coastguard Worker   pair.Ext = ext;
319*f6dc9357SAndroid Build Coastguard Worker   pair.IconIndex = Shell_GetFileInfo_SysIconIndex_for_Path(
320*f6dc9357SAndroid Build Coastguard Worker       us2fs(fileName + dotPos),
321*f6dc9357SAndroid Build Coastguard Worker       attrib & FILE_ATTRIBUTE_COMPRESSED ?
322*f6dc9357SAndroid Build Coastguard Worker           FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_COMPRESSED:
323*f6dc9357SAndroid Build Coastguard Worker           FILE_ATTRIBUTE_ARCHIVE);
324*f6dc9357SAndroid Build Coastguard Worker   if (map.Size() < (1u << 16)  // we limit cache size
325*f6dc9357SAndroid Build Coastguard Worker       // || DoItemAlwaysStart(fileName + dotPos) // we want some popular extensions in cache
326*f6dc9357SAndroid Build Coastguard Worker       )
327*f6dc9357SAndroid Build Coastguard Worker     map.Insert(insertPos, pair);
328*f6dc9357SAndroid Build Coastguard Worker   // if (typeName) *typeName = pair.TypeName;
329*f6dc9357SAndroid Build Coastguard Worker   return pair.IconIndex;
330*f6dc9357SAndroid Build Coastguard Worker }
331*f6dc9357SAndroid Build Coastguard Worker 
332*f6dc9357SAndroid Build Coastguard Worker 
Shell_Get_SysImageList_smallIcons(bool smallIcons)333*f6dc9357SAndroid Build Coastguard Worker HIMAGELIST Shell_Get_SysImageList_smallIcons(bool smallIcons)
334*f6dc9357SAndroid Build Coastguard Worker {
335*f6dc9357SAndroid Build Coastguard Worker   SHFILEINFO shFileInfo;
336*f6dc9357SAndroid Build Coastguard Worker   // shFileInfo.hIcon = NULL; // optional
337*f6dc9357SAndroid Build Coastguard Worker   const DWORD_PTR res = SHGetFileInfo(TEXT(""),
338*f6dc9357SAndroid Build Coastguard Worker       /* FILE_ATTRIBUTE_ARCHIVE | */
339*f6dc9357SAndroid Build Coastguard Worker       FILE_ATTRIBUTE_DIRECTORY,
340*f6dc9357SAndroid Build Coastguard Worker       &shFileInfo, sizeof(shFileInfo),
341*f6dc9357SAndroid Build Coastguard Worker       SHGFI_USEFILEATTRIBUTES |
342*f6dc9357SAndroid Build Coastguard Worker       SHGFI_SYSICONINDEX |
343*f6dc9357SAndroid Build Coastguard Worker       (smallIcons ? SHGFI_SMALLICON : SHGFI_LARGEICON));
344*f6dc9357SAndroid Build Coastguard Worker #if 0
345*f6dc9357SAndroid Build Coastguard Worker   // (shFileInfo.hIcon == NULL), because we don't use SHGFI_ICON.
346*f6dc9357SAndroid Build Coastguard Worker   // so DestroyIcon() is not required
347*f6dc9357SAndroid Build Coastguard Worker   if (res && shFileInfo.hIcon) // unexpected
348*f6dc9357SAndroid Build Coastguard Worker     DestroyIcon(shFileInfo.hIcon);
349*f6dc9357SAndroid Build Coastguard Worker #endif
350*f6dc9357SAndroid Build Coastguard Worker   return (HIMAGELIST)res;
351*f6dc9357SAndroid Build Coastguard Worker }
352