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