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 _crcSize = 4; 40 #ifdef __7Z_SET_PROPERTIES 41 _numThreads = NSystem::GetNumberOfProcessors(); 42 #endif 43 #endif 44 } 45 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 56 STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) 57 { 58 *numProps = 0; 59 return S_OK; 60 } 61 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 81 static inline char GetHex(unsigned value) 82 { 83 return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); 84 } 85 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 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 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 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 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 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 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 262 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 290 STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps) 291 { 292 *numProps = 0; 293 return S_OK; 294 } 295 296 STDMETHODIMP CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID) 297 { 298 *name = NULL; 299 *propID = kpidNtSecure; 300 return S_OK; 301 } 302 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 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 359 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 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 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 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 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