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 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 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 60 STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) 61 { 62 *numProps = 0; 63 return S_OK; 64 } 65 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 85 static inline char GetHex(unsigned value) 86 { 87 return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); 88 } 89 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 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 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 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 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 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 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 255 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 283 STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps) 284 { 285 *numProps = 0; 286 return S_OK; 287 } 288 289 STDMETHODIMP CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID) 290 { 291 *name = NULL; 292 *propID = kpidNtSecure; 293 return S_OK; 294 } 295 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 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 352 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 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 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 (item.AttribDefined) PropVarEm_Set_UInt32(value, item.Attrib); 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 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 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 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