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 
GetStringForSizeValue(char * s,UInt32 val)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 
AddProp32(char * s,const char * name,UInt32 v)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 
AddMethodName(AString & s,UInt64 id)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 
GetArchiveProperty(PROPID propID,PROPVARIANT * value)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     case kpidReadOnly:
241     {
242       if (!_db.CanUpdate())
243         prop = true;
244       break;
245     }
246   }
247   prop.Detach(value);
248   return S_OK;
249   #ifndef _SFX
250   COM_TRY_END
251   #endif
252 }
253 
SetFileTimeProp_From_UInt64Def(PROPVARIANT * prop,const CUInt64DefVector & v,int index)254 static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, int index)
255 {
256   UInt64 value;
257   if (v.GetItem(index, value))
258     PropVarEm_Set_FileTime64(prop, value);
259 }
260 
IsFolderEncrypted(CNum folderIndex) const261 bool CHandler::IsFolderEncrypted(CNum folderIndex) const
262 {
263   if (folderIndex == kNumNoIndex)
264     return false;
265   size_t startPos = _db.FoCodersDataOffset[folderIndex];
266   const Byte *p = _db.CodersData + startPos;
267   size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
268   CInByte2 inByte;
269   inByte.Init(p, size);
270 
271   CNum numCoders = inByte.ReadNum();
272   for (; numCoders != 0; numCoders--)
273   {
274     Byte mainByte = inByte.ReadByte();
275     unsigned idSize = (mainByte & 0xF);
276     const Byte *longID = inByte.GetPtr();
277     UInt64 id64 = 0;
278     for (unsigned j = 0; j < idSize; j++)
279       id64 = ((id64 << 8) | longID[j]);
280     inByte.SkipDataNoCheck(idSize);
281     if (id64 == k_AES)
282       return true;
283     if ((mainByte & 0x20) != 0)
284       inByte.SkipDataNoCheck(inByte.ReadNum());
285   }
286   return false;
287 }
288 
GetNumRawProps(UInt32 * numProps)289 STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps)
290 {
291   *numProps = 0;
292   return S_OK;
293 }
294 
GetRawPropInfo(UInt32,BSTR * name,PROPID * propID)295 STDMETHODIMP CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID)
296 {
297   *name = NULL;
298   *propID = kpidNtSecure;
299   return S_OK;
300 }
301 
GetParent(UInt32,UInt32 * parent,UInt32 * parentType)302 STDMETHODIMP CHandler::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType)
303 {
304   /*
305   const CFileItem &file = _db.Files[index];
306   *parentType = (file.IsAltStream ? NParentType::kAltStream : NParentType::kDir);
307   *parent = (UInt32)(Int32)file.Parent;
308   */
309   *parentType = NParentType::kDir;
310   *parent = (UInt32)(Int32)-1;
311   return S_OK;
312 }
313 
GetRawProp(UInt32 index,PROPID propID,const void ** data,UInt32 * dataSize,UInt32 * propType)314 STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)
315 {
316   *data = NULL;
317   *dataSize = 0;
318   *propType = 0;
319 
320   if (/* _db.IsTree && propID == kpidName ||
321       !_db.IsTree && */ propID == kpidPath)
322   {
323     if (_db.NameOffsets && _db.NamesBuf)
324     {
325       size_t offset = _db.NameOffsets[index];
326       size_t size = (_db.NameOffsets[index + 1] - offset) * 2;
327       if (size < ((UInt32)1 << 31))
328       {
329         *data = (const void *)(_db.NamesBuf + offset * 2);
330         *dataSize = (UInt32)size;
331         *propType = NPropDataType::kUtf16z;
332       }
333     }
334     return S_OK;
335   }
336   /*
337   if (propID == kpidNtSecure)
338   {
339     if (index < (UInt32)_db.SecureIDs.Size())
340     {
341       int id = _db.SecureIDs[index];
342       size_t offs = _db.SecureOffsets[id];
343       size_t size = _db.SecureOffsets[id + 1] - offs;
344       if (size >= 0)
345       {
346         *data = _db.SecureBuf + offs;
347         *dataSize = (UInt32)size;
348         *propType = NPropDataType::kRaw;
349       }
350     }
351   }
352   */
353   return S_OK;
354 }
355 
356 #ifndef _SFX
357 
SetMethodToProp(CNum folderIndex,PROPVARIANT * prop) const358 HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
359 {
360   PropVariant_Clear(prop);
361   if (folderIndex == kNumNoIndex)
362     return S_OK;
363   // for (int ttt = 0; ttt < 1; ttt++) {
364   const unsigned kTempSize = 256;
365   char temp[kTempSize];
366   unsigned pos = kTempSize;
367   temp[--pos] = 0;
368 
369   size_t startPos = _db.FoCodersDataOffset[folderIndex];
370   const Byte *p = _db.CodersData + startPos;
371   size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
372   CInByte2 inByte;
373   inByte.Init(p, size);
374 
375   // numCoders == 0 ???
376   CNum numCoders = inByte.ReadNum();
377   bool needSpace = false;
378 
379   for (; numCoders != 0; numCoders--, needSpace = true)
380   {
381     if (pos < 32) // max size of property
382       break;
383     Byte mainByte = inByte.ReadByte();
384     unsigned idSize = (mainByte & 0xF);
385     const Byte *longID = inByte.GetPtr();
386     UInt64 id64 = 0;
387     for (unsigned j = 0; j < idSize; j++)
388       id64 = ((id64 << 8) | longID[j]);
389     inByte.SkipDataNoCheck(idSize);
390 
391     if ((mainByte & 0x10) != 0)
392     {
393       inByte.ReadNum(); // NumInStreams
394       inByte.ReadNum(); // NumOutStreams
395     }
396 
397     CNum propsSize = 0;
398     const Byte *props = NULL;
399     if ((mainByte & 0x20) != 0)
400     {
401       propsSize = inByte.ReadNum();
402       props = inByte.GetPtr();
403       inByte.SkipDataNoCheck(propsSize);
404     }
405 
406     const char *name = NULL;
407     char s[32];
408     s[0] = 0;
409 
410     if (id64 <= (UInt32)0xFFFFFFFF)
411     {
412       UInt32 id = (UInt32)id64;
413       if (id == k_LZMA)
414       {
415         name = "LZMA";
416         if (propsSize == 5)
417         {
418           UInt32 dicSize = GetUi32((const Byte *)props + 1);
419           char *dest = s + GetStringForSizeValue(s, dicSize);
420           UInt32 d = props[0];
421           if (d != 0x5D)
422           {
423             UInt32 lc = d % 9;
424             d /= 9;
425             UInt32 pb = d / 5;
426             UInt32 lp = d % 5;
427             if (lc != 3) dest = AddProp32(dest, "lc", lc);
428             if (lp != 0) dest = AddProp32(dest, "lp", lp);
429             if (pb != 2) dest = AddProp32(dest, "pb", pb);
430           }
431         }
432       }
433       else if (id == k_LZMA2)
434       {
435         name = "LZMA2";
436         if (propsSize == 1)
437         {
438           Byte d = props[0];
439           if ((d & 1) == 0)
440             ConvertUInt32ToString((UInt32)((d >> 1) + 12), s);
441           else
442             GetStringForSizeValue(s, 3 << ((d >> 1) + 11));
443         }
444       }
445       else if (id == k_PPMD)
446       {
447         name = "PPMD";
448         if (propsSize == 5)
449         {
450           Byte order = *props;
451           char *dest = s;
452           *dest++ = 'o';
453           ConvertUInt32ToString(order, dest);
454           dest += MyStringLen(dest);
455           dest = MyStpCpy(dest, ":mem");
456           GetStringForSizeValue(dest, GetUi32(props + 1));
457         }
458       }
459       else if (id == k_Delta)
460       {
461         name = "Delta";
462         if (propsSize == 1)
463           ConvertUInt32ToString((UInt32)props[0] + 1, s);
464       }
465       else if (id == k_BCJ2) name = "BCJ2";
466       else if (id == k_BCJ) name = "BCJ";
467       else if (id == k_AES)
468       {
469         name = "7zAES";
470         if (propsSize >= 1)
471         {
472           Byte firstByte = props[0];
473           UInt32 numCyclesPower = firstByte & 0x3F;
474           ConvertUInt32ToString(numCyclesPower, s);
475         }
476       }
477     }
478 
479     if (name)
480     {
481       unsigned nameLen = MyStringLen(name);
482       unsigned propsLen = MyStringLen(s);
483       unsigned totalLen = nameLen + propsLen;
484       if (propsLen != 0)
485         totalLen++;
486       if (needSpace)
487         totalLen++;
488       if (totalLen + 5 >= pos)
489         break;
490       pos -= totalLen;
491       MyStringCopy(temp + pos, name);
492       if (propsLen != 0)
493       {
494         char *dest = temp + pos + nameLen;
495         *dest++ = ':';
496         MyStringCopy(dest, s);
497       }
498       if (needSpace)
499         temp[pos + totalLen - 1] = ' ';
500     }
501     else
502     {
503       AString methodName;
504       FindMethod(EXTERNAL_CODECS_VARS id64, methodName);
505       if (needSpace)
506         temp[--pos] = ' ';
507       if (methodName.IsEmpty())
508         pos -= ConvertMethodIdToString_Back(temp + pos, id64);
509       else
510       {
511         unsigned len = methodName.Len();
512         if (len + 5 > pos)
513           break;
514         pos -= len;
515         for (unsigned i = 0; i < len; i++)
516           temp[pos + i] = methodName[i];
517       }
518     }
519   }
520 
521   if (numCoders != 0 && pos >= 4)
522   {
523     temp[--pos] = ' ';
524     temp[--pos] = '.';
525     temp[--pos] = '.';
526     temp[--pos] = '.';
527   }
528 
529   return PropVarEm_Set_Str(prop, temp + pos);
530   // }
531 }
532 
533 #endif
534 
GetProperty(UInt32 index,PROPID propID,PROPVARIANT * value)535 STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
536 {
537   PropVariant_Clear(value);
538   // COM_TRY_BEGIN
539   // NCOM::CPropVariant prop;
540 
541   /*
542   const CRef2 &ref2 = _refs[index];
543   if (ref2.Refs.IsEmpty())
544     return E_FAIL;
545   const CRef &ref = ref2.Refs.Front();
546   */
547 
548   const CFileItem &item = _db.Files[index];
549   const UInt32 index2 = index;
550 
551   switch (propID)
552   {
553     case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break;
554     case kpidSize:
555     {
556       PropVarEm_Set_UInt64(value, item.Size);
557       // prop = ref2.Size;
558       break;
559     }
560     case kpidPackSize:
561     {
562       // prop = ref2.PackSize;
563       {
564         CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
565         if (folderIndex != kNumNoIndex)
566         {
567           if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2)
568             PropVarEm_Set_UInt64(value, _db.GetFolderFullPackSize(folderIndex));
569           /*
570           else
571             PropVarEm_Set_UInt64(value, 0);
572           */
573         }
574         else
575           PropVarEm_Set_UInt64(value, 0);
576       }
577       break;
578     }
579     // case kpidIsAux: prop = _db.IsItemAux(index2); break;
580     case kpidPosition:  { UInt64 v; if (_db.StartPos.GetItem(index2, v)) PropVarEm_Set_UInt64(value, v); break; }
581     case kpidCTime:  SetFileTimeProp_From_UInt64Def(value, _db.CTime, index2); break;
582     case kpidATime:  SetFileTimeProp_From_UInt64Def(value, _db.ATime, index2); break;
583     case kpidMTime:  SetFileTimeProp_From_UInt64Def(value, _db.MTime, index2); break;
584     case kpidAttrib:  if (_db.Attrib.ValidAndDefined(index2)) PropVarEm_Set_UInt32(value, _db.Attrib.Vals[index2]); break;
585     case kpidCRC:  if (item.CrcDefined) PropVarEm_Set_UInt32(value, item.Crc); break;
586     case kpidEncrypted:  PropVarEm_Set_Bool(value, IsFolderEncrypted(_db.FileIndexToFolderIndexMap[index2])); break;
587     case kpidIsAnti:  PropVarEm_Set_Bool(value, _db.IsItemAnti(index2)); break;
588     /*
589     case kpidIsAltStream:  prop = item.IsAltStream; break;
590     case kpidNtSecure:
591       {
592         int id = _db.SecureIDs[index];
593         size_t offs = _db.SecureOffsets[id];
594         size_t size = _db.SecureOffsets[id + 1] - offs;
595         if (size >= 0)
596         {
597           prop.SetBlob(_db.SecureBuf + offs, (ULONG)size);
598         }
599         break;
600       }
601     */
602 
603     case kpidPath: return _db.GetPath_Prop(index, value);
604 
605     #ifndef _SFX
606 
607     case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value);
608     case kpidBlock:
609       {
610         CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
611         if (folderIndex != kNumNoIndex)
612           PropVarEm_Set_UInt32(value, (UInt32)folderIndex);
613       }
614       break;
615     /*
616     case kpidPackedSize0:
617     case kpidPackedSize1:
618     case kpidPackedSize2:
619     case kpidPackedSize3:
620     case kpidPackedSize4:
621       {
622         CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
623         if (folderIndex != kNumNoIndex)
624         {
625           if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
626               _db.FoStartPackStreamIndex[folderIndex + 1] -
627               _db.FoStartPackStreamIndex[folderIndex] > (propID - kpidPackedSize0))
628           {
629             PropVarEm_Set_UInt64(value, _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0));
630           }
631         }
632         else
633           PropVarEm_Set_UInt64(value, 0);
634       }
635       break;
636     */
637 
638     #endif
639   }
640   // prop.Detach(value);
641   return S_OK;
642   // COM_TRY_END
643 }
644 
Open(IInStream * stream,const UInt64 * maxCheckStartPosition,IArchiveOpenCallback * openArchiveCallback)645 STDMETHODIMP CHandler::Open(IInStream *stream,
646     const UInt64 *maxCheckStartPosition,
647     IArchiveOpenCallback *openArchiveCallback)
648 {
649   COM_TRY_BEGIN
650   Close();
651   #ifndef _SFX
652   _fileInfoPopIDs.Clear();
653   #endif
654 
655   try
656   {
657     CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
658 
659     #ifndef _NO_CRYPTO
660     CMyComPtr<ICryptoGetTextPassword> getTextPassword;
661     if (openArchiveCallback)
662       openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
663     #endif
664 
665     CInArchive archive(
666           #ifdef __7Z_SET_PROPERTIES
667           _useMultiThreadMixer
668           #else
669           true
670           #endif
671           );
672     _db.IsArc = false;
673     RINOK(archive.Open(stream, maxCheckStartPosition));
674     _db.IsArc = true;
675 
676     HRESULT result = archive.ReadDatabase(
677         EXTERNAL_CODECS_VARS
678         _db
679         #ifndef _NO_CRYPTO
680           , getTextPassword, _isEncrypted, _passwordIsDefined, _password
681         #endif
682         );
683     RINOK(result);
684 
685     _inStream = stream;
686   }
687   catch(...)
688   {
689     Close();
690     // return E_INVALIDARG;
691     // return S_FALSE;
692     // we must return out_of_memory here
693     return E_OUTOFMEMORY;
694   }
695   // _inStream = stream;
696   #ifndef _SFX
697   FillPopIDs();
698   #endif
699   return S_OK;
700   COM_TRY_END
701 }
702 
Close()703 STDMETHODIMP CHandler::Close()
704 {
705   COM_TRY_BEGIN
706   _inStream.Release();
707   _db.Clear();
708   #ifndef _NO_CRYPTO
709   _isEncrypted = false;
710   _passwordIsDefined = false;
711   _password.Empty();
712   #endif
713   return S_OK;
714   COM_TRY_END
715 }
716 
717 #ifdef __7Z_SET_PROPERTIES
718 #ifdef EXTRACT_ONLY
719 
SetProperties(const wchar_t * const * names,const PROPVARIANT * values,UInt32 numProps)720 STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
721 {
722   COM_TRY_BEGIN
723 
724   InitCommon();
725   _useMultiThreadMixer = true;
726 
727   for (UInt32 i = 0; i < numProps; i++)
728   {
729     UString name = names[i];
730     name.MakeLower_Ascii();
731     if (name.IsEmpty())
732       return E_INVALIDARG;
733     const PROPVARIANT &value = values[i];
734     UInt32 number;
735     unsigned index = ParseStringToUInt32(name, number);
736     if (index == 0)
737     {
738       if (name.IsEqualTo("mtf"))
739       {
740         RINOK(PROPVARIANT_to_bool(value, _useMultiThreadMixer));
741         continue;
742       }
743       {
744         HRESULT hres;
745         if (SetCommonProperty(name, value, hres))
746         {
747           RINOK(hres);
748           continue;
749         }
750       }
751       return E_INVALIDARG;
752     }
753   }
754   return S_OK;
755   COM_TRY_END
756 }
757 
758 #endif
759 #endif
760 
761 IMPL_ISetCompressCodecsInfo
762 
763 }}
764