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