tor-browser

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

7zHandler.cpp (19278B)


      1 // 7zHandler.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "../../../../C/CpuArch.h"
      6 
      7 #include "../../../Common/ComTry.h"
      8 #include "../../../Common/IntToString.h"
      9 
     10 #ifndef __7Z_SET_PROPERTIES
     11 #include "../../../Windows/System.h"
     12 #endif
     13 
     14 #include "../Common/ItemNameUtils.h"
     15 
     16 #include "7zHandler.h"
     17 #include "7zProperties.h"
     18 
     19 #ifdef __7Z_SET_PROPERTIES
     20 #ifdef EXTRACT_ONLY
     21 #include "../Common/ParseProperties.h"
     22 #endif
     23 #endif
     24 
     25 using namespace NWindows;
     26 using namespace NCOM;
     27 
     28 namespace NArchive {
     29 namespace N7z {
     30 
     31 CHandler::CHandler()
     32 {
     33  #ifndef _NO_CRYPTO
     34  _isEncrypted = false;
     35  _passwordIsDefined = false;
     36  #endif
     37 
     38  #ifdef EXTRACT_ONLY
     39  
     40  _crcSize = 4;
     41  
     42  #ifdef __7Z_SET_PROPERTIES
     43  _useMultiThreadMixer = true;
     44  #endif
     45  
     46  #endif
     47 }
     48 
     49 STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
     50 {
     51  *numItems = _db.Files.Size();
     52  return S_OK;
     53 }
     54 
     55 #ifdef _SFX
     56 
     57 IMP_IInArchive_ArcProps_NO_Table
     58 
     59 STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps)
     60 {
     61  *numProps = 0;
     62  return S_OK;
     63 }
     64 
     65 STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,
     66      BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
     67 {
     68  return E_NOTIMPL;
     69 }
     70 
     71 #else
     72 
     73 static const Byte kArcProps[] =
     74 {
     75  kpidHeadersSize,
     76  kpidMethod,
     77  kpidSolid,
     78  kpidNumBlocks
     79  // , kpidIsTree
     80 };
     81 
     82 IMP_IInArchive_ArcProps
     83 
     84 static inline char GetHex(unsigned value)
     85 {
     86  return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
     87 }
     88 
     89 static unsigned ConvertMethodIdToString_Back(char *s, UInt64 id)
     90 {
     91  int len = 0;
     92  do
     93  {
     94    s[--len] = GetHex((unsigned)id & 0xF); id >>= 4;
     95    s[--len] = GetHex((unsigned)id & 0xF); id >>= 4;
     96  }
     97  while (id != 0);
     98  return (unsigned)-len;
     99 }
    100 
    101 static void ConvertMethodIdToString(AString &res, UInt64 id)
    102 {
    103  const unsigned kLen = 32;
    104  char s[kLen];
    105  unsigned len = kLen - 1;
    106  s[len] = 0;
    107  res += s + len - ConvertMethodIdToString_Back(s + len, id);
    108 }
    109 
    110 static unsigned GetStringForSizeValue(char *s, UInt32 val)
    111 {
    112  unsigned i;
    113  for (i = 0; i <= 31; i++)
    114    if (((UInt32)1 << i) == val)
    115    {
    116      if (i < 10)
    117      {
    118        s[0] = (char)('0' + i);
    119        s[1] = 0;
    120        return 1;
    121      }
    122           if (i < 20) { s[0] = '1'; s[1] = (char)('0' + i - 10); }
    123      else if (i < 30) { s[0] = '2'; s[1] = (char)('0' + i - 20); }
    124      else             { s[0] = '3'; s[1] = (char)('0' + i - 30); }
    125      s[2] = 0;
    126      return 2;
    127    }
    128  char c = 'b';
    129  if      ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }
    130  else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
    131  ::ConvertUInt32ToString(val, s);
    132  unsigned pos = MyStringLen(s);
    133  s[pos++] = c;
    134  s[pos] = 0;
    135  return pos;
    136 }
    137 
    138 /*
    139 static inline void AddHexToString(UString &res, Byte value)
    140 {
    141  res += GetHex((Byte)(value >> 4));
    142  res += GetHex((Byte)(value & 0xF));
    143 }
    144 */
    145 
    146 static char *AddProp32(char *s, const char *name, UInt32 v)
    147 {
    148  *s++ = ':';
    149  s = MyStpCpy(s, name);
    150  ::ConvertUInt32ToString(v, s);
    151  return s + MyStringLen(s);
    152 }
    153 
    154 void CHandler::AddMethodName(AString &s, UInt64 id)
    155 {
    156  AString name;
    157  FindMethod(EXTERNAL_CODECS_VARS id, name);
    158  if (name.IsEmpty())
    159    ConvertMethodIdToString(s, id);
    160  else
    161    s += name;
    162 }
    163 
    164 #endif
    165 
    166 STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
    167 {
    168  #ifndef _SFX
    169  COM_TRY_BEGIN
    170  #endif
    171  NCOM::CPropVariant prop;
    172  switch (propID)
    173  {
    174    #ifndef _SFX
    175    case kpidMethod:
    176    {
    177      AString s;
    178      const CParsedMethods &pm = _db.ParsedMethods;
    179      FOR_VECTOR (i, pm.IDs)
    180      {
    181        UInt64 id = pm.IDs[i];
    182        s.Add_Space_if_NotEmpty();
    183        char temp[16];
    184        if (id == k_LZMA2)
    185        {
    186          s += "LZMA2:";
    187          if ((pm.Lzma2Prop & 1) == 0)
    188            ConvertUInt32ToString((pm.Lzma2Prop >> 1) + 12, temp);
    189          else
    190            GetStringForSizeValue(temp, 3 << ((pm.Lzma2Prop >> 1) + 11));
    191          s += temp;
    192        }
    193        else if (id == k_LZMA)
    194        {
    195          s += "LZMA:";
    196          GetStringForSizeValue(temp, pm.LzmaDic);
    197          s += temp;
    198        }
    199        else
    200          AddMethodName(s, id);
    201      }
    202      prop = s;
    203      break;
    204    }
    205    case kpidSolid: prop = _db.IsSolid(); break;
    206    case kpidNumBlocks: prop = (UInt32)_db.NumFolders; break;
    207    case kpidHeadersSize:  prop = _db.HeadersSize; break;
    208    case kpidPhySize:  prop = _db.PhySize; break;
    209    case kpidOffset: if (_db.ArcInfo.StartPosition != 0) prop = _db.ArcInfo.StartPosition; break;
    210    /*
    211    case kpidIsTree: if (_db.IsTree) prop = true; break;
    212    case kpidIsAltStream: if (_db.ThereAreAltStreams) prop = true; break;
    213    case kpidIsAux: if (_db.IsTree) prop = true; break;
    214    */
    215    // case kpidError: if (_db.ThereIsHeaderError) prop = "Header error"; break;
    216    #endif
    217    
    218    case kpidWarningFlags:
    219    {
    220      UInt32 v = 0;
    221      if (_db.StartHeaderWasRecovered) v |= kpv_ErrorFlags_HeadersError;
    222      if (_db.UnsupportedFeatureWarning) v |= kpv_ErrorFlags_UnsupportedFeature;
    223      if (v != 0)
    224        prop = v;
    225      break;
    226    }
    227    
    228    case kpidErrorFlags:
    229    {
    230      UInt32 v = 0;
    231      if (!_db.IsArc) v |= kpv_ErrorFlags_IsNotArc;
    232      if (_db.ThereIsHeaderError) v |= kpv_ErrorFlags_HeadersError;
    233      if (_db.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;
    234      // if (_db.UnsupportedVersion) v |= kpv_ErrorFlags_Unsupported;
    235      if (_db.UnsupportedFeatureError) v |= kpv_ErrorFlags_UnsupportedFeature;
    236      prop = v;
    237      break;
    238    }
    239  }
    240  prop.Detach(value);
    241  return S_OK;
    242  #ifndef _SFX
    243  COM_TRY_END
    244  #endif
    245 }
    246 
    247 static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, int index)
    248 {
    249  UInt64 value;
    250  if (v.GetItem(index, value))
    251    PropVarEm_Set_FileTime64(prop, value);
    252 }
    253 
    254 bool CHandler::IsFolderEncrypted(CNum folderIndex) const
    255 {
    256  if (folderIndex == kNumNoIndex)
    257    return false;
    258  size_t startPos = _db.FoCodersDataOffset[folderIndex];
    259  const Byte *p = _db.CodersData + startPos;
    260  size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
    261  CInByte2 inByte;
    262  inByte.Init(p, size);
    263  
    264  CNum numCoders = inByte.ReadNum();
    265  for (; numCoders != 0; numCoders--)
    266  {
    267    Byte mainByte = inByte.ReadByte();
    268    unsigned idSize = (mainByte & 0xF);
    269    const Byte *longID = inByte.GetPtr();
    270    UInt64 id64 = 0;
    271    for (unsigned j = 0; j < idSize; j++)
    272      id64 = ((id64 << 8) | longID[j]);
    273    inByte.SkipDataNoCheck(idSize);
    274    if (id64 == k_AES)
    275      return true;
    276    if ((mainByte & 0x20) != 0)
    277      inByte.SkipDataNoCheck(inByte.ReadNum());
    278  }
    279  return false;
    280 }
    281 
    282 STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps)
    283 {
    284  *numProps = 0;
    285  return S_OK;
    286 }
    287 
    288 STDMETHODIMP CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID)
    289 {
    290  *name = NULL;
    291  *propID = kpidNtSecure;
    292  return S_OK;
    293 }
    294 
    295 STDMETHODIMP CHandler::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType)
    296 {
    297  /*
    298  const CFileItem &file = _db.Files[index];
    299  *parentType = (file.IsAltStream ? NParentType::kAltStream : NParentType::kDir);
    300  *parent = (UInt32)(Int32)file.Parent;
    301  */
    302  *parentType = NParentType::kDir;
    303  *parent = (UInt32)(Int32)-1;
    304  return S_OK;
    305 }
    306 
    307 STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)
    308 {
    309  *data = NULL;
    310  *dataSize = 0;
    311  *propType = 0;
    312 
    313  if (/* _db.IsTree && propID == kpidName ||
    314      !_db.IsTree && */ propID == kpidPath)
    315  {
    316    if (_db.NameOffsets && _db.NamesBuf)
    317    {
    318      size_t offset = _db.NameOffsets[index];
    319      size_t size = (_db.NameOffsets[index + 1] - offset) * 2;
    320      if (size < ((UInt32)1 << 31))
    321      {
    322        *data = (const void *)(_db.NamesBuf + offset * 2);
    323        *dataSize = (UInt32)size;
    324        *propType = NPropDataType::kUtf16z;
    325      }
    326    }
    327    return S_OK;
    328  }
    329  /*
    330  if (propID == kpidNtSecure)
    331  {
    332    if (index < (UInt32)_db.SecureIDs.Size())
    333    {
    334      int id = _db.SecureIDs[index];
    335      size_t offs = _db.SecureOffsets[id];
    336      size_t size = _db.SecureOffsets[id + 1] - offs;
    337      if (size >= 0)
    338      {
    339        *data = _db.SecureBuf + offs;
    340        *dataSize = (UInt32)size;
    341        *propType = NPropDataType::kRaw;
    342      }
    343    }
    344  }
    345  */
    346  return S_OK;
    347 }
    348 
    349 #ifndef _SFX
    350 
    351 HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
    352 {
    353  PropVariant_Clear(prop);
    354  if (folderIndex == kNumNoIndex)
    355    return S_OK;
    356  // for (int ttt = 0; ttt < 1; ttt++) {
    357  const unsigned kTempSize = 256;
    358  char temp[kTempSize];
    359  unsigned pos = kTempSize;
    360  temp[--pos] = 0;
    361 
    362  size_t startPos = _db.FoCodersDataOffset[folderIndex];
    363  const Byte *p = _db.CodersData + startPos;
    364  size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
    365  CInByte2 inByte;
    366  inByte.Init(p, size);
    367  
    368  // numCoders == 0 ???
    369  CNum numCoders = inByte.ReadNum();
    370  bool needSpace = false;
    371  
    372  for (; numCoders != 0; numCoders--, needSpace = true)
    373  {
    374    if (pos < 32) // max size of property
    375      break;
    376    Byte mainByte = inByte.ReadByte();
    377    unsigned idSize = (mainByte & 0xF);
    378    const Byte *longID = inByte.GetPtr();
    379    UInt64 id64 = 0;
    380    for (unsigned j = 0; j < idSize; j++)
    381      id64 = ((id64 << 8) | longID[j]);
    382    inByte.SkipDataNoCheck(idSize);
    383 
    384    if ((mainByte & 0x10) != 0)
    385    {
    386      inByte.ReadNum(); // NumInStreams
    387      inByte.ReadNum(); // NumOutStreams
    388    }
    389  
    390    CNum propsSize = 0;
    391    const Byte *props = NULL;
    392    if ((mainByte & 0x20) != 0)
    393    {
    394      propsSize = inByte.ReadNum();
    395      props = inByte.GetPtr();
    396      inByte.SkipDataNoCheck(propsSize);
    397    }
    398    
    399    const char *name = NULL;
    400    char s[32];
    401    s[0] = 0;
    402    
    403    if (id64 <= (UInt32)0xFFFFFFFF)
    404    {
    405      UInt32 id = (UInt32)id64;
    406      if (id == k_LZMA)
    407      {
    408        name = "LZMA";
    409        if (propsSize == 5)
    410        {
    411          UInt32 dicSize = GetUi32((const Byte *)props + 1);
    412          char *dest = s + GetStringForSizeValue(s, dicSize);
    413          UInt32 d = props[0];
    414          if (d != 0x5D)
    415          {
    416            UInt32 lc = d % 9;
    417            d /= 9;
    418            UInt32 pb = d / 5;
    419            UInt32 lp = d % 5;
    420            if (lc != 3) dest = AddProp32(dest, "lc", lc);
    421            if (lp != 0) dest = AddProp32(dest, "lp", lp);
    422            if (pb != 2) dest = AddProp32(dest, "pb", pb);
    423          }
    424        }
    425      }
    426      else if (id == k_LZMA2)
    427      {
    428        name = "LZMA2";
    429        if (propsSize == 1)
    430        {
    431          Byte d = props[0];
    432          if ((d & 1) == 0)
    433            ConvertUInt32ToString((UInt32)((d >> 1) + 12), s);
    434          else
    435            GetStringForSizeValue(s, 3 << ((d >> 1) + 11));
    436        }
    437      }
    438      else if (id == k_PPMD)
    439      {
    440        name = "PPMD";
    441        if (propsSize == 5)
    442        {
    443          Byte order = *props;
    444          char *dest = s;
    445          *dest++ = 'o';
    446          ConvertUInt32ToString(order, dest);
    447          dest += MyStringLen(dest);
    448          dest = MyStpCpy(dest, ":mem");
    449          GetStringForSizeValue(dest, GetUi32(props + 1));
    450        }
    451      }
    452      else if (id == k_Delta)
    453      {
    454        name = "Delta";
    455        if (propsSize == 1)
    456          ConvertUInt32ToString((UInt32)props[0] + 1, s);
    457      }
    458      else if (id == k_BCJ2) name = "BCJ2";
    459      else if (id == k_BCJ) name = "BCJ";
    460      else if (id == k_AES)
    461      {
    462        name = "7zAES";
    463        if (propsSize >= 1)
    464        {
    465          Byte firstByte = props[0];
    466          UInt32 numCyclesPower = firstByte & 0x3F;
    467          ConvertUInt32ToString(numCyclesPower, s);
    468        }
    469      }
    470    }
    471    
    472    if (name)
    473    {
    474      unsigned nameLen = MyStringLen(name);
    475      unsigned propsLen = MyStringLen(s);
    476      unsigned totalLen = nameLen + propsLen;
    477      if (propsLen != 0)
    478        totalLen++;
    479      if (needSpace)
    480        totalLen++;
    481      if (totalLen + 5 >= pos)
    482        break;
    483      pos -= totalLen;
    484      MyStringCopy(temp + pos, name);
    485      if (propsLen != 0)
    486      {
    487        char *dest = temp + pos + nameLen;
    488        *dest++ = ':';
    489        MyStringCopy(dest, s);
    490      }
    491      if (needSpace)
    492        temp[pos + totalLen - 1] = ' ';
    493    }
    494    else
    495    {
    496      AString methodName;
    497      FindMethod(EXTERNAL_CODECS_VARS id64, methodName);
    498      if (needSpace)
    499        temp[--pos] = ' ';
    500      if (methodName.IsEmpty())
    501        pos -= ConvertMethodIdToString_Back(temp + pos, id64);
    502      else
    503      {
    504        unsigned len = methodName.Len();
    505        if (len + 5 > pos)
    506          break;
    507        pos -= len;
    508        for (unsigned i = 0; i < len; i++)
    509          temp[pos + i] = methodName[i];
    510      }
    511    }
    512  }
    513  
    514  if (numCoders != 0 && pos >= 4)
    515  {
    516    temp[--pos] = ' ';
    517    temp[--pos] = '.';
    518    temp[--pos] = '.';
    519    temp[--pos] = '.';
    520  }
    521  
    522  return PropVarEm_Set_Str(prop, temp + pos);
    523  // }
    524 }
    525 
    526 #endif
    527 
    528 STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
    529 {
    530  PropVariant_Clear(value);
    531  // COM_TRY_BEGIN
    532  // NCOM::CPropVariant prop;
    533  
    534  /*
    535  const CRef2 &ref2 = _refs[index];
    536  if (ref2.Refs.IsEmpty())
    537    return E_FAIL;
    538  const CRef &ref = ref2.Refs.Front();
    539  */
    540  
    541  const CFileItem &item = _db.Files[index];
    542  const UInt32 index2 = index;
    543 
    544  switch (propID)
    545  {
    546    case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break;
    547    case kpidSize:
    548    {
    549      PropVarEm_Set_UInt64(value, item.Size);
    550      // prop = ref2.Size;
    551      break;
    552    }
    553    case kpidPackSize:
    554    {
    555      // prop = ref2.PackSize;
    556      {
    557        CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
    558        if (folderIndex != kNumNoIndex)
    559        {
    560          if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2)
    561            PropVarEm_Set_UInt64(value, _db.GetFolderFullPackSize(folderIndex));
    562          /*
    563          else
    564            PropVarEm_Set_UInt64(value, 0);
    565          */
    566        }
    567        else
    568          PropVarEm_Set_UInt64(value, 0);
    569      }
    570      break;
    571    }
    572    // case kpidIsAux: prop = _db.IsItemAux(index2); break;
    573    case kpidPosition:  { UInt64 v; if (_db.StartPos.GetItem(index2, v)) PropVarEm_Set_UInt64(value, v); break; }
    574    case kpidCTime:  SetFileTimeProp_From_UInt64Def(value, _db.CTime, index2); break;
    575    case kpidATime:  SetFileTimeProp_From_UInt64Def(value, _db.ATime, index2); break;
    576    case kpidMTime:  SetFileTimeProp_From_UInt64Def(value, _db.MTime, index2); break;
    577    case kpidAttrib:  if (_db.Attrib.ValidAndDefined(index2)) PropVarEm_Set_UInt32(value, _db.Attrib.Vals[index2]); break;
    578    case kpidCRC:  if (item.CrcDefined) PropVarEm_Set_UInt32(value, item.Crc); break;
    579    case kpidEncrypted:  PropVarEm_Set_Bool(value, IsFolderEncrypted(_db.FileIndexToFolderIndexMap[index2])); break;
    580    case kpidIsAnti:  PropVarEm_Set_Bool(value, _db.IsItemAnti(index2)); break;
    581    /*
    582    case kpidIsAltStream:  prop = item.IsAltStream; break;
    583    case kpidNtSecure:
    584      {
    585        int id = _db.SecureIDs[index];
    586        size_t offs = _db.SecureOffsets[id];
    587        size_t size = _db.SecureOffsets[id + 1] - offs;
    588        if (size >= 0)
    589        {
    590          prop.SetBlob(_db.SecureBuf + offs, (ULONG)size);
    591        }
    592        break;
    593      }
    594    */
    595 
    596    case kpidPath: return _db.GetPath_Prop(index, value);
    597    
    598    #ifndef _SFX
    599    
    600    case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value);
    601    case kpidBlock:
    602      {
    603        CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
    604        if (folderIndex != kNumNoIndex)
    605          PropVarEm_Set_UInt32(value, (UInt32)folderIndex);
    606      }
    607      break;
    608    /*
    609    case kpidPackedSize0:
    610    case kpidPackedSize1:
    611    case kpidPackedSize2:
    612    case kpidPackedSize3:
    613    case kpidPackedSize4:
    614      {
    615        CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
    616        if (folderIndex != kNumNoIndex)
    617        {
    618          if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
    619              _db.FoStartPackStreamIndex[folderIndex + 1] -
    620              _db.FoStartPackStreamIndex[folderIndex] > (propID - kpidPackedSize0))
    621          {
    622            PropVarEm_Set_UInt64(value, _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0));
    623          }
    624        }
    625        else
    626          PropVarEm_Set_UInt64(value, 0);
    627      }
    628      break;
    629    */
    630    
    631    #endif
    632  }
    633  // prop.Detach(value);
    634  return S_OK;
    635  // COM_TRY_END
    636 }
    637 
    638 STDMETHODIMP CHandler::Open(IInStream *stream,
    639    const UInt64 *maxCheckStartPosition,
    640    IArchiveOpenCallback *openArchiveCallback)
    641 {
    642  COM_TRY_BEGIN
    643  Close();
    644  #ifndef _SFX
    645  _fileInfoPopIDs.Clear();
    646  #endif
    647  
    648  try
    649  {
    650    CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
    651 
    652    #ifndef _NO_CRYPTO
    653    CMyComPtr<ICryptoGetTextPassword> getTextPassword;
    654    if (openArchiveCallback)
    655      openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
    656    #endif
    657 
    658    CInArchive archive(
    659          #ifdef __7Z_SET_PROPERTIES
    660          _useMultiThreadMixer
    661          #else
    662          true
    663          #endif
    664          );
    665    _db.IsArc = false;
    666    RINOK(archive.Open(stream, maxCheckStartPosition));
    667    _db.IsArc = true;
    668    
    669    HRESULT result = archive.ReadDatabase(
    670        EXTERNAL_CODECS_VARS
    671        _db
    672        #ifndef _NO_CRYPTO
    673          , getTextPassword, _isEncrypted, _passwordIsDefined, _password
    674        #endif
    675        );
    676    RINOK(result);
    677    
    678    _inStream = stream;
    679  }
    680  catch(...)
    681  {
    682    Close();
    683    // return E_INVALIDARG;
    684    // return S_FALSE;
    685    // we must return out_of_memory here
    686    return E_OUTOFMEMORY;
    687  }
    688  // _inStream = stream;
    689  #ifndef _SFX
    690  FillPopIDs();
    691  #endif
    692  return S_OK;
    693  COM_TRY_END
    694 }
    695 
    696 STDMETHODIMP CHandler::Close()
    697 {
    698  COM_TRY_BEGIN
    699  _inStream.Release();
    700  _db.Clear();
    701  #ifndef _NO_CRYPTO
    702  _isEncrypted = false;
    703  _passwordIsDefined = false;
    704  _password.Empty();
    705  #endif
    706  return S_OK;
    707  COM_TRY_END
    708 }
    709 
    710 #ifdef __7Z_SET_PROPERTIES
    711 #ifdef EXTRACT_ONLY
    712 
    713 STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
    714 {
    715  COM_TRY_BEGIN
    716  
    717  InitCommon();
    718  _useMultiThreadMixer = true;
    719 
    720  for (UInt32 i = 0; i < numProps; i++)
    721  {
    722    UString name = names[i];
    723    name.MakeLower_Ascii();
    724    if (name.IsEmpty())
    725      return E_INVALIDARG;
    726    const PROPVARIANT &value = values[i];
    727    UInt32 number;
    728    unsigned index = ParseStringToUInt32(name, number);
    729    if (index == 0)
    730    {
    731      if (name.IsEqualTo("mtf"))
    732      {
    733        RINOK(PROPVARIANT_to_bool(value, _useMultiThreadMixer));
    734        continue;
    735      }
    736      {
    737        HRESULT hres;
    738        if (SetCommonProperty(name, value, hres))
    739        {
    740          RINOK(hres);
    741          continue;
    742        }
    743      }
    744      return E_INVALIDARG;
    745    }
    746  }
    747  return S_OK;
    748  COM_TRY_END
    749 }
    750 
    751 #endif
    752 #endif
    753 
    754 IMPL_ISetCompressCodecsInfo
    755 
    756 }}