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