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