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