// SysIconUtils.cpp | |
#include "StdAfx.h" | |
#ifndef _UNICODE | |
#include "../../../Common/StringConvert.h" | |
#endif | |
#include "../../../Windows/FileDir.h" | |
#include "SysIconUtils.h" | |
#ifndef _UNICODE | |
extern bool g_IsNT; | |
#endif | |
int GetIconIndexForCSIDL(int csidl) | |
{ | |
LPITEMIDLIST pidl = 0; | |
SHGetSpecialFolderLocation(NULL, csidl, &pidl); | |
if (pidl) | |
{ | |
SHFILEINFO shellInfo; | |
SHGetFileInfo(LPCTSTR(pidl), FILE_ATTRIBUTE_NORMAL, | |
&shellInfo, sizeof(shellInfo), | |
SHGFI_PIDL | SHGFI_SYSICONINDEX); | |
IMalloc *pMalloc; | |
SHGetMalloc(&pMalloc); | |
if (pMalloc) | |
{ | |
pMalloc->Free(pidl); | |
pMalloc->Release(); | |
} | |
return shellInfo.iIcon; | |
} | |
return 0; | |
} | |
#ifndef _UNICODE | |
typedef int (WINAPI * SHGetFileInfoWP)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags); | |
struct CSHGetFileInfoInit | |
{ | |
SHGetFileInfoWP shGetFileInfoW; | |
CSHGetFileInfoInit() | |
{ | |
shGetFileInfoW = (SHGetFileInfoWP) | |
::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetFileInfoW"); | |
} | |
} g_SHGetFileInfoInit; | |
#endif | |
static DWORD_PTR MySHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags) | |
{ | |
#ifdef _UNICODE | |
return SHGetFileInfo | |
#else | |
if (g_SHGetFileInfoInit.shGetFileInfoW == 0) | |
return 0; | |
return g_SHGetFileInfoInit.shGetFileInfoW | |
#endif | |
(pszPath, attrib, psfi, cbFileInfo, uFlags); | |
} | |
DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex) | |
{ | |
#ifndef _UNICODE | |
if (!g_IsNT) | |
{ | |
SHFILEINFO shellInfo; | |
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; | |
DWORD_PTR res = ::MySHGetFileInfoW(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 = ::MySHGetFileInfoW(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<CAttribIconPair> &vect, DWORD attrib, int &insertPos) | |
{ | |
unsigned left = 0, right = vect.Size(); | |
while (left != right) | |
{ | |
unsigned mid = (left + right) / 2; | |
DWORD midAttrib = vect[mid].Attrib; | |
if (attrib == midAttrib) | |
return mid; | |
if (attrib < midAttrib) | |
right = mid; | |
else | |
left = mid + 1; | |
} | |
insertPos = left; | |
return -1; | |
} | |
static int FindInSorted_Ext(const CObjectVector<CExtIconPair> &vect, const wchar_t *ext, int &insertPos) | |
{ | |
unsigned left = 0, right = vect.Size(); | |
while (left != right) | |
{ | |
unsigned mid = (left + right) / 2; | |
int compare = MyStringCompareNoCase(ext, vect[mid].Ext); | |
if (compare == 0) | |
return 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++) | |
{ | |
wchar_t c = fileName[i]; | |
if (c == 0) | |
break; | |
if (c == '.') | |
dotPos = 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) | |
{ | |
int insertPos = 0; | |
int index = FindInSorted_Attrib(_attribMap, attrib, insertPos); | |
if (index >= 0) | |
{ | |
// if (typeName) *typeName = _attribMap[index].TypeName; | |
return _attribMap[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; | |
int insertPos = 0; | |
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++) | |
{ | |
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); | |
} | |
*/ |