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