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