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   _crcSize = 4;
40   #ifdef __7Z_SET_PROPERTIES
41   _numThreads = NSystem::GetNumberOfProcessors();
42   #endif
43   #endif
44 }
45 
GetNumberOfItems(UInt32 * numItems)46 STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
47 {
48   *numItems = _db.Files.Size();
49   return S_OK;
50 }
51 
52 #ifdef _SFX
53 
54 IMP_IInArchive_ArcProps_NO_Table
55 
GetNumberOfProperties(UInt32 * numProps)56 STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps)
57 {
58   *numProps = 0;
59   return S_OK;
60 }
61 
GetPropertyInfo(UInt32,BSTR *,PROPID *,VARTYPE *)62 STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,
63       BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
64 {
65   return E_NOTIMPL;
66 }
67 
68 #else
69 
70 static const Byte kArcProps[] =
71 {
72   kpidHeadersSize,
73   kpidMethod,
74   kpidSolid,
75   kpidNumBlocks
76   // , kpidIsTree
77 };
78 
79 IMP_IInArchive_ArcProps
80 
GetHex(unsigned value)81 static inline char GetHex(unsigned value)
82 {
83   return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
84 }
85 
ConvertMethodIdToString_Back(char * s,UInt64 id)86 static unsigned ConvertMethodIdToString_Back(char *s, UInt64 id)
87 {
88   int len = 0;
89   do
90   {
91     s[--len] = GetHex((unsigned)id & 0xF); id >>= 4;
92     s[--len] = GetHex((unsigned)id & 0xF); id >>= 4;
93   }
94   while (id != 0);
95   return (unsigned)-len;
96 }
97 
ConvertMethodIdToString(AString & res,UInt64 id)98 static void ConvertMethodIdToString(AString &res, UInt64 id)
99 {
100   const unsigned kLen = 32;
101   char s[kLen];
102   unsigned len = kLen - 1;
103   s[len] = 0;
104   res += s + len - ConvertMethodIdToString_Back(s + len, id);
105 }
106 
GetStringForSizeValue(char * s,UInt32 val)107 static unsigned GetStringForSizeValue(char *s, UInt32 val)
108 {
109   unsigned i;
110   for (i = 0; i <= 31; i++)
111     if (((UInt32)1 << i) == val)
112     {
113       if (i < 10)
114       {
115         s[0] = (char)('0' + i);
116         s[1] = 0;
117         return 1;
118       }
119            if (i < 20) { s[0] = '1'; s[1] = (char)('0' + i - 10); }
120       else if (i < 30) { s[0] = '2'; s[1] = (char)('0' + i - 20); }
121       else             { s[0] = '3'; s[1] = (char)('0' + i - 30); }
122       s[2] = 0;
123       return 2;
124     }
125   char c = 'b';
126   if      ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }
127   else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
128   ::ConvertUInt32ToString(val, s);
129   unsigned pos = MyStringLen(s);
130   s[pos++] = c;
131   s[pos] = 0;
132   return pos;
133 }
134 
135 /*
136 static inline void AddHexToString(UString &res, Byte value)
137 {
138   res += GetHex((Byte)(value >> 4));
139   res += GetHex((Byte)(value & 0xF));
140 }
141 */
142 
AddProp32(char * s,const char * name,UInt32 v)143 static char *AddProp32(char *s, const char *name, UInt32 v)
144 {
145   *s++ = ':';
146   s = MyStpCpy(s, name);
147   ::ConvertUInt32ToString(v, s);
148   return s + MyStringLen(s);
149 }
150 
AddMethodName(AString & s,UInt64 id)151 void CHandler::AddMethodName(AString &s, UInt64 id)
152 {
153   UString methodName;
154   FindMethod(EXTERNAL_CODECS_VARS id, methodName);
155   if (methodName.IsEmpty())
156   {
157     for (unsigned i = 0; i < methodName.Len(); i++)
158       if (methodName[i] >= 0x80)
159       {
160         methodName.Empty();
161         break;
162       }
163   }
164   if (methodName.IsEmpty())
165     ConvertMethodIdToString(s, id);
166   else
167     for (unsigned i = 0; i < methodName.Len(); i++)
168       s += (char)methodName[i];
169 }
170 
171 #endif
172 
GetArchiveProperty(PROPID propID,PROPVARIANT * value)173 STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
174 {
175   #ifndef _SFX
176   COM_TRY_BEGIN
177   #endif
178   NCOM::CPropVariant prop;
179   switch (propID)
180   {
181     #ifndef _SFX
182     case kpidMethod:
183     {
184       AString s;
185       const CParsedMethods &pm = _db.ParsedMethods;
186       FOR_VECTOR (i, pm.IDs)
187       {
188         UInt64 id = pm.IDs[i];
189         if (!s.IsEmpty())
190           s += ' ';
191         char temp[16];
192         if (id == k_LZMA2)
193         {
194           s += "LZMA2:";
195           if ((pm.Lzma2Prop & 1) == 0)
196             ConvertUInt32ToString((pm.Lzma2Prop >> 1) + 12, temp);
197           else
198             GetStringForSizeValue(temp, 3 << ((pm.Lzma2Prop >> 1) + 11));
199           s += temp;
200         }
201         else if (id == k_LZMA)
202         {
203           s += "LZMA:";
204           GetStringForSizeValue(temp, pm.LzmaDic);
205           s += temp;
206         }
207         else
208           AddMethodName(s, id);
209       }
210       prop = s;
211       break;
212     }
213     case kpidSolid: prop = _db.IsSolid(); break;
214     case kpidNumBlocks: prop = (UInt32)_db.NumFolders; break;
215     case kpidHeadersSize:  prop = _db.HeadersSize; break;
216     case kpidPhySize:  prop = _db.PhySize; break;
217     case kpidOffset: if (_db.ArcInfo.StartPosition != 0) prop = _db.ArcInfo.StartPosition; break;
218     /*
219     case kpidIsTree: if (_db.IsTree) prop = true; break;
220     case kpidIsAltStream: if (_db.ThereAreAltStreams) prop = true; break;
221     case kpidIsAux: if (_db.IsTree) prop = true; break;
222     */
223     // case kpidError: if (_db.ThereIsHeaderError) prop = "Header error"; break;
224     #endif
225 
226     case kpidWarningFlags:
227     {
228       UInt32 v = 0;
229       if (_db.StartHeaderWasRecovered) v |= kpv_ErrorFlags_HeadersError;
230       if (_db.UnsupportedFeatureWarning) v |= kpv_ErrorFlags_UnsupportedFeature;
231       if (v != 0)
232         prop = v;
233       break;
234     }
235 
236     case kpidErrorFlags:
237     {
238       UInt32 v = 0;
239       if (!_db.IsArc) v |= kpv_ErrorFlags_IsNotArc;
240       if (_db.ThereIsHeaderError) v |= kpv_ErrorFlags_HeadersError;
241       if (_db.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;
242       // if (_db.UnsupportedVersion) v |= kpv_ErrorFlags_Unsupported;
243       if (_db.UnsupportedFeatureError) v |= kpv_ErrorFlags_UnsupportedFeature;
244       prop = v;
245       break;
246     }
247   }
248   prop.Detach(value);
249   return S_OK;
250   #ifndef _SFX
251   COM_TRY_END
252   #endif
253 }
254 
SetFileTimeProp_From_UInt64Def(PROPVARIANT * prop,const CUInt64DefVector & v,int index)255 static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, int index)
256 {
257   UInt64 value;
258   if (v.GetItem(index, value))
259     PropVarEm_Set_FileTime64(prop, value);
260 }
261 
IsFolderEncrypted(CNum folderIndex) const262 bool CHandler::IsFolderEncrypted(CNum folderIndex) const
263 {
264   if (folderIndex == kNumNoIndex)
265     return false;
266   size_t startPos = _db.FoCodersDataOffset[folderIndex];
267   const Byte *p = _db.CodersData + startPos;
268   size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
269   CInByte2 inByte;
270   inByte.Init(p, size);
271 
272   CNum numCoders = inByte.ReadNum();
273   for (; numCoders != 0; numCoders--)
274   {
275     Byte mainByte = inByte.ReadByte();
276     unsigned idSize = (mainByte & 0xF);
277     const Byte *longID = inByte.GetPtr();
278     UInt64 id64 = 0;
279     for (unsigned j = 0; j < idSize; j++)
280       id64 = ((id64 << 8) | longID[j]);
281     inByte.SkipDataNoCheck(idSize);
282     if (id64 == k_AES)
283       return true;
284     if ((mainByte & 0x20) != 0)
285       inByte.SkipDataNoCheck(inByte.ReadNum());
286   }
287   return false;
288 }
289 
GetNumRawProps(UInt32 * numProps)290 STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps)
291 {
292   *numProps = 0;
293   return S_OK;
294 }
295 
GetRawPropInfo(UInt32,BSTR * name,PROPID * propID)296 STDMETHODIMP CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID)
297 {
298   *name = NULL;
299   *propID = kpidNtSecure;
300   return S_OK;
301 }
302 
GetParent(UInt32,UInt32 * parent,UInt32 * parentType)303 STDMETHODIMP CHandler::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType)
304 {
305   /*
306   const CFileItem &file = _db.Files[index];
307   *parentType = (file.IsAltStream ? NParentType::kAltStream : NParentType::kDir);
308   *parent = (UInt32)(Int32)file.Parent;
309   */
310   *parentType = NParentType::kDir;
311   *parent = (UInt32)(Int32)-1;
312   return S_OK;
313 }
314 
GetRawProp(UInt32 index,PROPID propID,const void ** data,UInt32 * dataSize,UInt32 * propType)315 STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)
316 {
317   *data = NULL;
318   *dataSize = 0;
319   *propType = 0;
320 
321   if (/* _db.IsTree && propID == kpidName ||
322       !_db.IsTree && */ propID == kpidPath)
323   {
324     if (_db.NameOffsets && _db.NamesBuf)
325     {
326       size_t offset = _db.NameOffsets[index];
327       size_t size = (_db.NameOffsets[index + 1] - offset) * 2;
328       if (size < ((UInt32)1 << 31))
329       {
330         *data = (const void *)(_db.NamesBuf + offset * 2);
331         *dataSize = (UInt32)size;
332         *propType = NPropDataType::kUtf16z;
333       }
334     }
335     return S_OK;
336   }
337   /*
338   if (propID == kpidNtSecure)
339   {
340     if (index < (UInt32)_db.SecureIDs.Size())
341     {
342       int id = _db.SecureIDs[index];
343       size_t offs = _db.SecureOffsets[id];
344       size_t size = _db.SecureOffsets[id + 1] - offs;
345       if (size >= 0)
346       {
347         *data = _db.SecureBuf + offs;
348         *dataSize = (UInt32)size;
349         *propType = NPropDataType::kRaw;
350       }
351     }
352   }
353   */
354   return S_OK;
355 }
356 
357 #ifndef _SFX
358 
SetMethodToProp(CNum folderIndex,PROPVARIANT * prop) const359 HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
360 {
361   PropVariant_Clear(prop);
362   if (folderIndex == kNumNoIndex)
363     return S_OK;
364   // for (int ttt = 0; ttt < 1; ttt++) {
365   const unsigned kTempSize = 256;
366   char temp[kTempSize];
367   unsigned pos = kTempSize;
368   temp[--pos] = 0;
369 
370   size_t startPos = _db.FoCodersDataOffset[folderIndex];
371   const Byte *p = _db.CodersData + startPos;
372   size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
373   CInByte2 inByte;
374   inByte.Init(p, size);
375 
376   // numCoders == 0 ???
377   CNum numCoders = inByte.ReadNum();
378   bool needSpace = false;
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 p = props[0];
439           if ((p & 1) == 0)
440             ConvertUInt32ToString((UInt32)((p >> 1) + 12), s);
441           else
442             GetStringForSizeValue(s, 3 << ((p >> 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       UString methodName;
504       FindMethod(EXTERNAL_CODECS_VARS id64, methodName);
505       if (methodName.IsEmpty())
506       {
507         for (unsigned j = 0; j < methodName.Len(); j++)
508           if (methodName[j] >= 0x80)
509           {
510             methodName.Empty();
511             break;
512           }
513       }
514       if (needSpace)
515         temp[--pos] = ' ';
516       if (methodName.IsEmpty())
517         pos -= ConvertMethodIdToString_Back(temp + pos, id64);
518       else
519       {
520         unsigned len = methodName.Len();
521         if (len + 5 > pos)
522           break;
523         pos -= len;
524         for (unsigned i = 0; i < len; i++)
525           temp[pos + i] = (char)methodName[i];
526       }
527     }
528   }
529   if (numCoders != 0 && pos >= 4)
530   {
531     temp[--pos] = ' ';
532     temp[--pos] = '.';
533     temp[--pos] = '.';
534     temp[--pos] = '.';
535   }
536   return PropVarEm_Set_Str(prop, temp + pos);
537   // }
538 }
539 
540 #endif
541 
GetProperty(UInt32 index,PROPID propID,PROPVARIANT * value)542 STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
543 {
544   PropVariant_Clear(value);
545   // COM_TRY_BEGIN
546   // NCOM::CPropVariant prop;
547 
548   /*
549   const CRef2 &ref2 = _refs[index];
550   if (ref2.Refs.IsEmpty())
551     return E_FAIL;
552   const CRef &ref = ref2.Refs.Front();
553   */
554 
555   const CFileItem &item = _db.Files[index];
556   UInt32 index2 = index;
557 
558   switch(propID)
559   {
560     case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break;
561     case kpidSize:
562     {
563       PropVarEm_Set_UInt64(value, item.Size);
564       // prop = ref2.Size;
565       break;
566     }
567     case kpidPackSize:
568     {
569       // prop = ref2.PackSize;
570       {
571         CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
572         if (folderIndex != kNumNoIndex)
573         {
574           if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2)
575             PropVarEm_Set_UInt64(value, _db.GetFolderFullPackSize(folderIndex));
576           /*
577           else
578             PropVarEm_Set_UInt64(value, 0);
579           */
580         }
581         else
582           PropVarEm_Set_UInt64(value, 0);
583       }
584       break;
585     }
586     // case kpidIsAux: prop = _db.IsItemAux(index2); break;
587     case kpidPosition:  { UInt64 v; if (_db.StartPos.GetItem(index2, v)) PropVarEm_Set_UInt64(value, v); break; }
588     case kpidCTime:  SetFileTimeProp_From_UInt64Def(value, _db.CTime, index2); break;
589     case kpidATime:  SetFileTimeProp_From_UInt64Def(value, _db.ATime, index2); break;
590     case kpidMTime:  SetFileTimeProp_From_UInt64Def(value, _db.MTime, index2); break;
591     case kpidAttrib:  if (item.AttribDefined) PropVarEm_Set_UInt32(value, item.Attrib); break;
592     case kpidCRC:  if (item.CrcDefined) PropVarEm_Set_UInt32(value, item.Crc); break;
593     case kpidEncrypted:  PropVarEm_Set_Bool(value, IsFolderEncrypted(_db.FileIndexToFolderIndexMap[index2])); break;
594     case kpidIsAnti:  PropVarEm_Set_Bool(value, _db.IsItemAnti(index2)); break;
595     /*
596     case kpidIsAltStream:  prop = item.IsAltStream; break;
597     case kpidNtSecure:
598       {
599         int id = _db.SecureIDs[index];
600         size_t offs = _db.SecureOffsets[id];
601         size_t size = _db.SecureOffsets[id + 1] - offs;
602         if (size >= 0)
603         {
604           prop.SetBlob(_db.SecureBuf + offs, (ULONG)size);
605         }
606         break;
607       }
608     */
609 
610     case kpidPath: return _db.GetPath_Prop(index, value);
611     #ifndef _SFX
612     case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value);
613     case kpidBlock:
614       {
615         CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
616         if (folderIndex != kNumNoIndex)
617           PropVarEm_Set_UInt32(value, (UInt32)folderIndex);
618       }
619       break;
620     case kpidPackedSize0:
621     case kpidPackedSize1:
622     case kpidPackedSize2:
623     case kpidPackedSize3:
624     case kpidPackedSize4:
625       {
626         /*
627         CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
628         if (folderIndex != kNumNoIndex)
629         {
630           const CFolder &folderInfo = _db.Folders[folderIndex];
631           if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
632               folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0))
633           {
634             prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);
635           }
636           else
637             prop = (UInt64)0;
638         }
639         else
640           prop = (UInt64)0;
641         */
642       }
643       break;
644     #endif
645   }
646   // prop.Detach(value);
647   return S_OK;
648   // COM_TRY_END
649 }
650 
Open(IInStream * stream,const UInt64 * maxCheckStartPosition,IArchiveOpenCallback * openArchiveCallback)651 STDMETHODIMP CHandler::Open(IInStream *stream,
652     const UInt64 *maxCheckStartPosition,
653     IArchiveOpenCallback *openArchiveCallback)
654 {
655   COM_TRY_BEGIN
656   Close();
657   #ifndef _SFX
658   _fileInfoPopIDs.Clear();
659   #endif
660 
661   try
662   {
663     CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
664 
665     #ifndef _NO_CRYPTO
666     CMyComPtr<ICryptoGetTextPassword> getTextPassword;
667     if (openArchiveCallback)
668       openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
669     #endif
670 
671     CInArchive archive;
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
681         #endif
682         );
683     RINOK(result);
684 
685     _inStream = stream;
686   }
687   catch(...)
688   {
689     Close();
690     // return E_INVALIDARG;
691     // we must return out_of_memory here
692     return S_FALSE;
693   }
694   // _inStream = stream;
695   #ifndef _SFX
696   FillPopIDs();
697   #endif
698   return S_OK;
699   COM_TRY_END
700 }
701 
Close()702 STDMETHODIMP CHandler::Close()
703 {
704   COM_TRY_BEGIN
705   _inStream.Release();
706   _db.Clear();
707   #ifndef _NO_CRYPTO
708   _isEncrypted = false;
709   _passwordIsDefined = false;
710   #endif
711   return S_OK;
712   COM_TRY_END
713 }
714 
715 #ifdef __7Z_SET_PROPERTIES
716 #ifdef EXTRACT_ONLY
717 
SetProperties(const wchar_t ** names,const PROPVARIANT * values,UInt32 numProps)718 STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
719 {
720   COM_TRY_BEGIN
721   const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
722   _numThreads = numProcessors;
723 
724   for (UInt32 i = 0; i < numProps; i++)
725   {
726     UString name = names[i];
727     name.MakeLower_Ascii();
728     if (name.IsEmpty())
729       return E_INVALIDARG;
730     const PROPVARIANT &value = values[i];
731     UInt32 number;
732     int index = ParseStringToUInt32(name, number);
733     if (index == 0)
734     {
735       if (name.IsPrefixedBy(L"mt"))
736       {
737         RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads));
738         continue;
739       }
740       else
741         return E_INVALIDARG;
742     }
743   }
744   return S_OK;
745   COM_TRY_END
746 }
747 
748 #endif
749 #endif
750 
751 IMPL_ISetCompressCodecsInfo
752 
753 }}
754