1 // SysIconUtils.h
2 
3 #include "StdAfx.h"
4 
5 #include "SysIconUtils.h"
6 #ifndef _UNICODE
7 #include "Common/StringConvert.h"
8 #endif
9 
10 #ifndef _UNICODE
11 extern bool g_IsNT;
12 #endif
13 
GetIconIndexForCSIDL(int csidl)14 int GetIconIndexForCSIDL(int csidl)
15 {
16 #ifdef _WIN32
17   LPITEMIDLIST pidl = 0;
18   SHGetSpecialFolderLocation(NULL, csidl, &pidl);
19   if (pidl)
20   {
21     SHFILEINFO shellInfo;
22     SHGetFileInfo(LPCTSTR(pidl),  FILE_ATTRIBUTE_NORMAL,
23       &shellInfo, sizeof(shellInfo),
24       SHGFI_PIDL | SHGFI_SYSICONINDEX);
25     IMalloc  *pMalloc;
26     SHGetMalloc(&pMalloc);
27     if(pMalloc)
28     {
29       pMalloc->Free(pidl);
30       pMalloc->Release();
31     }
32     return shellInfo.iIcon;
33   }
34 #endif // FIXME -1 ?
35   return 0;
36 }
37 
GetRealIconIndex(LPCTSTR path,DWORD attributes,int & iconIndex)38 DWORD_PTR GetRealIconIndex(LPCTSTR path, DWORD attributes, int &iconIndex)
39 {
40 #ifdef _WIN32
41   SHFILEINFO shellInfo;
42   DWORD_PTR res = ::SHGetFileInfo(path, FILE_ATTRIBUTE_NORMAL | attributes, &shellInfo,
43       sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
44   iconIndex = shellInfo.iIcon;
45   return res;
46 #else
47   return -1;
48 #endif
49 }
50 
51 
52 #ifdef _WIN32
53 
54 #ifndef _UNICODE
55 typedef int (WINAPI * SHGetFileInfoWP)(LPCWSTR pszPath, DWORD dwFileAttributes, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags);
56 
57 struct CSHGetFileInfoInit
58 {
59   SHGetFileInfoWP shGetFileInfoW;
CSHGetFileInfoInitCSHGetFileInfoInit60   CSHGetFileInfoInit()
61   {
62     shGetFileInfoW = (SHGetFileInfoWP)
63     ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetFileInfoW");
64   }
65 } g_SHGetFileInfoInit;
66 #endif
67 
MySHGetFileInfoW(LPCWSTR pszPath,DWORD dwFileAttributes,SHFILEINFOW * psfi,UINT cbFileInfo,UINT uFlags)68 DWORD_PTR MySHGetFileInfoW(LPCWSTR pszPath, DWORD dwFileAttributes, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags)
69 {
70   #ifdef _UNICODE
71   return SHGetFileInfoW(
72   #else
73   if (g_SHGetFileInfoInit.shGetFileInfoW == 0)
74     return 0;
75   return g_SHGetFileInfoInit.shGetFileInfoW(
76   #endif
77   pszPath, dwFileAttributes, psfi, cbFileInfo, uFlags);
78 }
79 
80 #ifndef _UNICODE
81 // static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }
GetRealIconIndex(LPCWSTR path,DWORD attributes,int & iconIndex)82 DWORD_PTR GetRealIconIndex(LPCWSTR path, DWORD attributes, int &iconIndex)
83 {
84   if(g_IsNT)
85   {
86     SHFILEINFOW shellInfo;
87     DWORD_PTR res = ::MySHGetFileInfoW(path, FILE_ATTRIBUTE_NORMAL | attributes, &shellInfo,
88       sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
89     iconIndex = shellInfo.iIcon;
90     return res;
91   }
92   else
93     return GetRealIconIndex(UnicodeStringToMultiByte(path), attributes, iconIndex);
94 }
95 #endif
96 
GetRealIconIndex(const UString & fileName,DWORD attributes,int & iconIndex,UString & typeName)97 DWORD_PTR GetRealIconIndex(const UString &fileName, DWORD attributes,
98     int &iconIndex, UString &typeName)
99 {
100   #ifndef _UNICODE
101   if(!g_IsNT)
102   {
103     SHFILEINFO shellInfo;
104     shellInfo.szTypeName[0] = 0;
105     DWORD_PTR res = ::SHGetFileInfoA(GetSystemString(fileName), FILE_ATTRIBUTE_NORMAL | attributes, &shellInfo,
106       sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX
107       | SHGFI_TYPENAME);
108     typeName = GetUnicodeString(shellInfo.szTypeName);
109     iconIndex = shellInfo.iIcon;
110     return res;
111   }
112   else
113   #endif
114   {
115     SHFILEINFOW shellInfo;
116     shellInfo.szTypeName[0] = 0;
117     DWORD_PTR res = ::MySHGetFileInfoW(fileName, FILE_ATTRIBUTE_NORMAL | attributes, &shellInfo,
118       sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX
119       | SHGFI_TYPENAME);
120     typeName = shellInfo.szTypeName;
121     iconIndex = shellInfo.iIcon;
122     return res;
123   }
124 }
125 
GetIconIndex(UINT32 attributes,const UString & fileNameSpec,UString & typeName)126 int CExtToIconMap::GetIconIndex(UINT32 attributes, const UString &fileNameSpec, UString &typeName)
127 {
128   UString fileName = fileNameSpec;
129   if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
130   {
131     fileName = L"__Fldr__";
132     if (_dirIconIndex < 0)
133       GetRealIconIndex(fileName, attributes, _dirIconIndex, _dirTypeName);
134     typeName = _dirTypeName;
135     return _dirIconIndex;
136   }
137   int dotPos = fileName.ReverseFind('.');
138   if (dotPos < 0)
139   {
140     fileName = L"__File__";
141     if (_noExtIconIndex < 0)
142     {
143       int iconIndexTemp;
144       GetRealIconIndex(fileName, attributes, iconIndexTemp, _noExtTypeName);
145     }
146     typeName = _noExtTypeName;
147     return _noExtIconIndex;
148   }
149   CExtIconPair extIconPair;
150   extIconPair.Ext = fileName.Mid(dotPos + 1);
151   int anIndex = _map.FindInSorted(extIconPair);
152   if (anIndex >= 0)
153     return _map[anIndex].IconIndex;
154   fileName = fileName.Mid(dotPos);
155   GetRealIconIndex(fileName, attributes, extIconPair.IconIndex, extIconPair.TypeName);
156   _map.AddToSorted(extIconPair);
157   typeName = extIconPair.TypeName;
158   return extIconPair.IconIndex;
159 }
160 
GetIconIndex(UINT32 attributes,const UString & fileName)161 int CExtToIconMap::GetIconIndex(UINT32 attributes, const UString &fileName)
162 {
163   UString typeName;
164   return GetIconIndex(attributes, fileName, typeName);
165 }
166 #endif
167 
168