tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SysIconUtils.cpp (6423B)


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