text: // 7zProperties.cpp
  
  #include "StdAfx.h"
  
  #include "7zProperties.h"
  #include "7zHeader.h"
  #include "7zHandler.h"
  
  // #define _MULTI_PACK
  
  namespace NArchive {
  namespace N7z {
  
  struct CPropMap
  {
    UInt64 FilePropID;
    STATPROPSTG StatPROPSTG;
  };
  
  CPropMap kPropMap[] = 
  {
    { NID::kName, NULL, kpidPath, VT_BSTR},
    { NID::kSize, NULL, kpidSize, VT_UI8},
    { NID::kPackInfo, NULL, kpidPackedSize, VT_UI8},
    
    #ifdef _MULTI_PACK
    { 100, L"Pack0", kpidPackedSize0, VT_UI8},
    { 101, L"Pack1", kpidPackedSize1, VT_UI8},
    { 102, L"Pack2", kpidPackedSize2, VT_UI8},
    { 103, L"Pack3", kpidPackedSize3, VT_UI8},
    { 104, L"Pack4", kpidPackedSize4, VT_UI8},
    #endif
  
    { NID::kCreationTime, NULL, kpidCreationTime, VT_FILETIME},
    { NID::kLastWriteTime, NULL, kpidLastWriteTime, VT_FILETIME},
    { NID::kLastAccessTime, NULL, kpidLastAccessTime, VT_FILETIME},
    { NID::kWinAttributes, NULL, kpidAttributes, VT_UI4},
    { NID::kStartPos, NULL, kpidPosition, VT_UI4},
  
  
    { NID::kCRC, NULL, kpidCRC, VT_UI4},
    
    { NID::kAnti, L"Anti", kpidIsAnti, VT_BOOL},
    // { 97, NULL, kpidSolid, VT_BOOL},
    #ifndef _SFX
    { 98, NULL, kpidMethod, VT_BSTR},
    { 99, L"Block", kpidBlock, VT_UI4}
    #endif
    // { L"ID", kpidID, VT_BSTR},
    // { L"UnPack Version", kpidUnPackVersion, VT_UI1},
    // { L"Host OS", kpidHostOS, VT_BSTR}
  };
  
  static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]);
  
  static int FindPropInMap(UInt64 filePropID)
  {
    for (int i = 0; i < kPropMapSize; i++)
      if (kPropMap[i].FilePropID == filePropID)
        return i;
    return -1;
  }
  
  static void CopyOneItem(CRecordVector<UInt64> &src, 
      CRecordVector<UInt64> &dest, UInt32 item)
  {
    for (int i = 0; i < src.Size(); i++)
      if (src[i] == item)
      {
        dest.Add(item);
        src.Delete(i);
        return;
      }
  }
  
  static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item)
  {
    for (int i = 0; i < src.Size(); i++)
      if (src[i] == item)
      {
        src.Delete(i);
        return;
      }
  }
  
  static void InsertToHead(CRecordVector<UInt64> &dest, UInt32 item)
  {
    for (int i = 0; i < dest.Size(); i++)
      if (dest[i] == item)
      {
        dest.Delete(i);
        break;
      }
    dest.Insert(0, item);
  }
  
  void CHandler::FillPopIDs()
  { 
    _fileInfoPopIDs.Clear();
  
    #ifdef _7Z_VOL
    if(_volumes.Size() < 1)
      return;
    const CVolume &volume = _volumes.Front();
    const CArchiveDatabaseEx &_database = volume.Database;
    #endif
  
    CRecordVector<UInt64> fileInfoPopIDs = _database.ArchiveInfo.FileInfoPopIDs;
  
    RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream);
    RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile);
  
    CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName);
    CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti);
    CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize);
    CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo);
    CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCreationTime);
    CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kLastWriteTime);
    CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kLastAccessTime);
    CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes);
    CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC);
    CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kComment);
    _fileInfoPopIDs += fileInfoPopIDs; 
   
    #ifndef _SFX
    _fileInfoPopIDs.Add(98);
    _fileInfoPopIDs.Add(99);
    #endif
    #ifdef _MULTI_PACK
    _fileInfoPopIDs.Add(100);
    _fileInfoPopIDs.Add(101);
    _fileInfoPopIDs.Add(102);
    _fileInfoPopIDs.Add(103);
    _fileInfoPopIDs.Add(104);
    #endif
  
    #ifndef _SFX
    InsertToHead(_fileInfoPopIDs, NID::kLastWriteTime);
    InsertToHead(_fileInfoPopIDs, NID::kPackInfo);
    InsertToHead(_fileInfoPopIDs, NID::kSize);
    InsertToHead(_fileInfoPopIDs, NID::kName);
    #endif
  }
  
  STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties)
  {
    *numProperties = _fileInfoPopIDs.Size();
    return S_OK;
  }
  
  STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index,     
        BSTR *name, PROPID *propID, VARTYPE *varType)
  {
    if((int)index >= _fileInfoPopIDs.Size())
      return E_INVALIDARG;
    int indexInMap = FindPropInMap(_fileInfoPopIDs[index]);
    if (indexInMap == -1)
      return E_INVALIDARG;
    const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG;
    *propID = srcItem.propid;
    *varType = srcItem.vt;
    *name = 0;
    return S_OK;
  }
  
  }}
  