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