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