1 // LoadCodecs.cpp 2 3 #include "StdAfx.h" 4 5 #include "../../../../C/7zVersion.h" 6 7 #include "../../../Common/MyCom.h" 8 #include "../../../Common/StringToInt.h" 9 #include "../../../Common/StringConvert.h" 10 11 #include "../../../Windows/PropVariant.h" 12 13 #include "LoadCodecs.h" 14 15 using namespace NWindows; 16 17 #ifdef NEW_FOLDER_INTERFACE 18 #include "../../../Common/StringToInt.h" 19 #endif 20 21 #include "../../ICoder.h" 22 #include "../../Common/RegisterArc.h" 23 24 #ifdef EXTERNAL_CODECS 25 26 #include "../../../Windows/FileFind.h" 27 #include "../../../Windows/DLL.h" 28 #ifdef NEW_FOLDER_INTERFACE 29 #include "../../../Windows/ResourceString.h" 30 static const UINT kIconTypesResId = 100; 31 #endif 32 33 #ifdef _WIN32 34 #include "../../../Windows/FileName.h" 35 #include "../../../Windows/Registry.h" 36 #endif 37 38 using namespace NFile; 39 40 #ifdef _WIN32 41 extern HINSTANCE g_hInstance; 42 #endif 43 44 #define kCodecsFolderName FTEXT("Codecs") 45 #define kFormatsFolderName FTEXT("Formats") 46 static CFSTR kMainDll = FTEXT("7z.dll"); 47 48 #ifdef _WIN32 49 50 static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip"); 51 static LPCWSTR kProgramPathValue = L"Path"; 52 static LPCWSTR kProgramPath2Value = L"Path" 53 #ifdef _WIN64 54 L"64"; 55 #else 56 L"32"; 57 #endif 58 59 static bool ReadPathFromRegistry(HKEY baseKey, LPCWSTR value, FString &path) 60 { 61 NRegistry::CKey key; 62 if (key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS) 63 { 64 UString pathU; 65 if (key.QueryValue(value, pathU) == ERROR_SUCCESS) 66 { 67 path = us2fs(pathU); 68 NName::NormalizeDirPathPrefix(path); 69 return NFind::DoesFileExist(path + kMainDll); 70 } 71 } 72 return false; 73 } 74 75 #endif // _WIN32 76 77 #endif // EXTERNAL_CODECS 78 79 80 static const unsigned kNumArcsMax = 48; 81 static unsigned g_NumArcs = 0; 82 static const CArcInfo *g_Arcs[kNumArcsMax]; 83 84 void RegisterArc(const CArcInfo *arcInfo) throw() 85 { 86 if (g_NumArcs < kNumArcsMax) 87 { 88 g_Arcs[g_NumArcs] = arcInfo; 89 g_NumArcs++; 90 } 91 } 92 93 static void SplitString(const UString &srcString, UStringVector &destStrings) 94 { 95 destStrings.Clear(); 96 UString s; 97 unsigned len = srcString.Len(); 98 if (len == 0) 99 return; 100 for (unsigned i = 0; i < len; i++) 101 { 102 wchar_t c = srcString[i]; 103 if (c == L' ') 104 { 105 if (!s.IsEmpty()) 106 { 107 destStrings.Add(s); 108 s.Empty(); 109 } 110 } 111 else 112 s += c; 113 } 114 if (!s.IsEmpty()) 115 destStrings.Add(s); 116 } 117 118 int CArcInfoEx::FindExtension(const UString &ext) const 119 { 120 FOR_VECTOR (i, Exts) 121 if (ext.IsEqualToNoCase(Exts[i].Ext)) 122 return i; 123 return -1; 124 } 125 126 void CArcInfoEx::AddExts(const UString &ext, const UString &addExt) 127 { 128 UStringVector exts, addExts; 129 SplitString(ext, exts); 130 SplitString(addExt, addExts); 131 FOR_VECTOR (i, exts) 132 { 133 CArcExtInfo extInfo; 134 extInfo.Ext = exts[i]; 135 if (i < addExts.Size()) 136 { 137 extInfo.AddExt = addExts[i]; 138 if (extInfo.AddExt == L"*") 139 extInfo.AddExt.Empty(); 140 } 141 Exts.Add(extInfo); 142 } 143 } 144 145 #ifndef _SFX 146 147 static bool ParseSignatures(const Byte *data, unsigned size, CObjectVector<CByteBuffer> &signatures) 148 { 149 signatures.Clear(); 150 while (size > 0) 151 { 152 unsigned len = *data++; 153 size--; 154 if (len > size) 155 return false; 156 signatures.AddNew().CopyFrom(data, len); 157 data += len; 158 size -= len; 159 } 160 return true; 161 } 162 163 #endif // _SFX 164 165 #ifdef EXTERNAL_CODECS 166 167 static FString GetBaseFolderPrefixFromRegistry() 168 { 169 FString moduleFolderPrefix = NDLL::GetModuleDirPrefix(); 170 #ifdef _WIN32 171 if (!NFind::DoesFileExist(moduleFolderPrefix + kMainDll) && 172 !NFind::DoesDirExist(moduleFolderPrefix + kCodecsFolderName) && 173 !NFind::DoesDirExist(moduleFolderPrefix + kFormatsFolderName)) 174 { 175 FString path; 176 if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPath2Value, path)) return path; 177 if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPath2Value, path)) return path; 178 if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPathValue, path)) return path; 179 if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPathValue, path)) return path; 180 } 181 #endif 182 return moduleFolderPrefix; 183 } 184 185 static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 index, 186 PROPID propId, CLSID &clsId, bool &isAssigned) 187 { 188 NCOM::CPropVariant prop; 189 isAssigned = false; 190 RINOK(getMethodProperty(index, propId, &prop)); 191 if (prop.vt == VT_BSTR) 192 { 193 if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID)) 194 return E_FAIL; 195 isAssigned = true; 196 clsId = *(const GUID *)prop.bstrVal; 197 } 198 else if (prop.vt != VT_EMPTY) 199 return E_FAIL; 200 return S_OK; 201 } 202 203 HRESULT CCodecs::LoadCodecs() 204 { 205 CCodecLib &lib = Libs.Back(); 206 lib.GetMethodProperty = (Func_GetMethodProperty)lib.Lib.GetProc("GetMethodProperty"); 207 if (lib.GetMethodProperty) 208 { 209 UInt32 numMethods = 1; 210 Func_GetNumberOfMethods getNumberOfMethodsFunc = (Func_GetNumberOfMethods)lib.Lib.GetProc("GetNumberOfMethods"); 211 if (getNumberOfMethodsFunc) 212 { 213 RINOK(getNumberOfMethodsFunc(&numMethods)); 214 } 215 for (UInt32 i = 0; i < numMethods; i++) 216 { 217 CDllCodecInfo info; 218 info.LibIndex = Libs.Size() - 1; 219 info.CodecIndex = i; 220 RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned)); 221 RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned)); 222 Codecs.Add(info); 223 } 224 } 225 226 Func_GetHashers getHashers = (Func_GetHashers)lib.Lib.GetProc("GetHashers"); 227 if (getHashers) 228 { 229 RINOK(getHashers(&lib.Hashers)); 230 if (lib.Hashers) 231 { 232 UInt32 numMethods = lib.Hashers->GetNumHashers(); 233 for (UInt32 i = 0; i < numMethods; i++) 234 { 235 CDllHasherInfo info; 236 info.LibIndex = Libs.Size() - 1; 237 info.HasherIndex = i; 238 Hashers.Add(info); 239 } 240 } 241 } 242 return S_OK; 243 } 244 245 static HRESULT GetProp( 246 Func_GetHandlerProperty getProp, 247 Func_GetHandlerProperty2 getProp2, 248 UInt32 index, PROPID propID, NCOM::CPropVariant &prop) 249 { 250 if (getProp2) 251 return getProp2(index, propID, &prop);; 252 return getProp(propID, &prop); 253 } 254 255 static HRESULT GetProp_Bool( 256 Func_GetHandlerProperty getProp, 257 Func_GetHandlerProperty2 getProp2, 258 UInt32 index, PROPID propID, bool &res) 259 { 260 res = false; 261 NCOM::CPropVariant prop; 262 RINOK(GetProp(getProp, getProp2, index, propID, prop)); 263 if (prop.vt == VT_BOOL) 264 res = VARIANT_BOOLToBool(prop.boolVal); 265 else if (prop.vt != VT_EMPTY) 266 return E_FAIL; 267 return S_OK; 268 } 269 270 static HRESULT GetProp_UInt32( 271 Func_GetHandlerProperty getProp, 272 Func_GetHandlerProperty2 getProp2, 273 UInt32 index, PROPID propID, UInt32 &res, bool &defined) 274 { 275 res = 0; 276 defined = false; 277 NCOM::CPropVariant prop; 278 RINOK(GetProp(getProp, getProp2, index, propID, prop)); 279 if (prop.vt == VT_UI4) 280 { 281 res = prop.ulVal; 282 defined = true; 283 } 284 else if (prop.vt != VT_EMPTY) 285 return E_FAIL; 286 return S_OK; 287 } 288 289 static HRESULT GetProp_String( 290 Func_GetHandlerProperty getProp, 291 Func_GetHandlerProperty2 getProp2, 292 UInt32 index, PROPID propID, UString &res) 293 { 294 res.Empty(); 295 NCOM::CPropVariant prop; 296 RINOK(GetProp(getProp, getProp2, index, propID, prop)); 297 if (prop.vt == VT_BSTR) 298 res = prop.bstrVal; 299 else if (prop.vt != VT_EMPTY) 300 return E_FAIL; 301 return S_OK; 302 } 303 304 static HRESULT GetProp_RawData( 305 Func_GetHandlerProperty getProp, 306 Func_GetHandlerProperty2 getProp2, 307 UInt32 index, PROPID propID, CByteBuffer &bb) 308 { 309 bb.Free(); 310 NCOM::CPropVariant prop; 311 RINOK(GetProp(getProp, getProp2, index, propID, prop)); 312 if (prop.vt == VT_BSTR) 313 { 314 UINT len = ::SysStringByteLen(prop.bstrVal); 315 bb.CopyFrom((const Byte *)prop.bstrVal, len); 316 } 317 else if (prop.vt != VT_EMPTY) 318 return E_FAIL; 319 return S_OK; 320 } 321 322 static const UInt32 kArcFlagsPars[] = 323 { 324 NArchive::NHandlerPropID::kKeepName, NArcInfoFlags::kKeepName, 325 NArchive::NHandlerPropID::kAltStreams, NArcInfoFlags::kAltStreams, 326 NArchive::NHandlerPropID::kNtSecure, NArcInfoFlags::kNtSecure 327 }; 328 329 HRESULT CCodecs::LoadFormats() 330 { 331 const NDLL::CLibrary &lib = Libs.Back().Lib; 332 333 Func_GetHandlerProperty getProp = NULL; 334 Func_GetHandlerProperty2 getProp2 = (Func_GetHandlerProperty2)lib.GetProc("GetHandlerProperty2"); 335 Func_GetIsArc getIsArc = (Func_GetIsArc)lib.GetProc("GetIsArc"); 336 337 UInt32 numFormats = 1; 338 339 if (getProp2) 340 { 341 Func_GetNumberOfFormats getNumberOfFormats = (Func_GetNumberOfFormats)lib.GetProc("GetNumberOfFormats"); 342 if (getNumberOfFormats) 343 { 344 RINOK(getNumberOfFormats(&numFormats)); 345 } 346 } 347 else 348 { 349 getProp = (Func_GetHandlerProperty)lib.GetProc("GetHandlerProperty"); 350 if (!getProp) 351 return S_OK; 352 } 353 354 for (UInt32 i = 0; i < numFormats; i++) 355 { 356 CArcInfoEx item; 357 item.LibIndex = Libs.Size() - 1; 358 item.FormatIndex = i; 359 360 RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kName, item.Name)); 361 362 { 363 NCOM::CPropVariant prop; 364 if (GetProp(getProp, getProp2, i, NArchive::NHandlerPropID::kClassID, prop) != S_OK) 365 continue; 366 if (prop.vt != VT_BSTR) 367 continue; 368 if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID)) 369 return E_FAIL; 370 item.ClassID = *(const GUID *)prop.bstrVal; 371 prop.Clear(); 372 } 373 374 UString ext, addExt; 375 RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kExtension, ext)); 376 RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kAddExtension, addExt)); 377 item.AddExts(ext, addExt); 378 379 GetProp_Bool(getProp, getProp2, i, NArchive::NHandlerPropID::kUpdate, item.UpdateEnabled); 380 bool flags_Defined = false; 381 RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kFlags, item.Flags, flags_Defined)); 382 item.NewInterface = flags_Defined; 383 if (!flags_Defined) // && item.UpdateEnabled 384 { 385 // support for DLL version before 9.31: 386 for (unsigned j = 0; j < ARRAY_SIZE(kArcFlagsPars); j += 2) 387 { 388 bool val = false; 389 GetProp_Bool(getProp, getProp2, i, kArcFlagsPars[j], val); 390 if (val) 391 item.Flags |= kArcFlagsPars[j + 1]; 392 } 393 } 394 395 CByteBuffer sig; 396 RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kSignature, sig)); 397 if (sig.Size() != 0) 398 item.Signatures.Add(sig); 399 else 400 { 401 RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kMultiSignature, sig)); 402 ParseSignatures(sig, (unsigned)sig.Size(), item.Signatures); 403 } 404 405 bool signatureOffset_Defined; 406 RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kSignatureOffset, item.SignatureOffset, signatureOffset_Defined)); 407 408 // bool version_Defined; 409 // RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kVersion, item.Version, version_Defined)); 410 411 if (getIsArc) 412 getIsArc(i, &item.IsArcFunc); 413 414 Formats.Add(item); 415 } 416 return S_OK; 417 } 418 419 #ifdef NEW_FOLDER_INTERFACE 420 void CCodecIcons::LoadIcons(HMODULE m) 421 { 422 UString iconTypes; 423 MyLoadString(m, kIconTypesResId, iconTypes); 424 UStringVector pairs; 425 SplitString(iconTypes, pairs); 426 FOR_VECTOR (i, pairs) 427 { 428 const UString &s = pairs[i]; 429 int pos = s.Find(L':'); 430 CIconPair iconPair; 431 iconPair.IconIndex = -1; 432 if (pos < 0) 433 pos = s.Len(); 434 else 435 { 436 UString num = s.Ptr(pos + 1); 437 if (!num.IsEmpty()) 438 { 439 const wchar_t *end; 440 iconPair.IconIndex = ConvertStringToUInt32(num, &end); 441 if (*end != 0) 442 continue; 443 } 444 } 445 iconPair.Ext = s.Left(pos); 446 IconPairs.Add(iconPair); 447 } 448 } 449 450 bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const 451 { 452 iconIndex = -1; 453 FOR_VECTOR (i, IconPairs) 454 { 455 const CIconPair &pair = IconPairs[i]; 456 if (ext.IsEqualToNoCase(pair.Ext)) 457 { 458 iconIndex = pair.IconIndex; 459 return true; 460 } 461 } 462 return false; 463 } 464 465 #endif // EXTERNAL_CODECS 466 467 #ifdef _7ZIP_LARGE_PAGES 468 extern "C" 469 { 470 extern SIZE_T g_LargePageSize; 471 } 472 #endif 473 474 HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll) 475 { 476 if (needCheckDll) 477 { 478 NDLL::CLibrary library; 479 if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE)) 480 return S_OK; 481 } 482 Libs.Add(CCodecLib()); 483 CCodecLib &lib = Libs.Back(); 484 lib.Path = dllPath; 485 bool used = false; 486 HRESULT res = S_OK; 487 if (lib.Lib.Load(dllPath)) 488 { 489 #ifdef NEW_FOLDER_INTERFACE 490 lib.LoadIcons(); 491 #endif 492 493 #ifdef _7ZIP_LARGE_PAGES 494 if (g_LargePageSize != 0) 495 { 496 Func_SetLargePageMode setLargePageMode = (Func_SetLargePageMode)lib.Lib.GetProc("SetLargePageMode"); 497 if (setLargePageMode) 498 setLargePageMode(); 499 } 500 #endif 501 502 if (CaseSensitiveChange) 503 { 504 Func_SetCaseSensitive setCaseSensitive = (Func_SetCaseSensitive)lib.Lib.GetProc("SetCaseSensitive"); 505 if (setCaseSensitive) 506 setCaseSensitive(CaseSensitive ? 1 : 0); 507 } 508 509 lib.CreateObject = (Func_CreateObject)lib.Lib.GetProc("CreateObject"); 510 if (lib.CreateObject) 511 { 512 unsigned startSize = Codecs.Size() + Hashers.Size(); 513 res = LoadCodecs(); 514 used = (startSize != Codecs.Size() + Hashers.Size()); 515 if (res == S_OK) 516 { 517 startSize = Formats.Size(); 518 res = LoadFormats(); 519 if (startSize != Formats.Size()) 520 used = true; 521 } 522 } 523 } 524 if (!used) 525 Libs.DeleteBack(); 526 return res; 527 } 528 529 HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPrefix) 530 { 531 NFile::NFind::CEnumerator enumerator(folderPrefix + FCHAR_ANY_MASK); 532 NFile::NFind::CFileInfo fi; 533 while (enumerator.Next(fi)) 534 { 535 if (fi.IsDir()) 536 continue; 537 RINOK(LoadDll(folderPrefix + fi.Name, true)); 538 } 539 return S_OK; 540 } 541 542 #endif 543 544 HRESULT CCodecs::Load() 545 { 546 #ifdef NEW_FOLDER_INTERFACE 547 InternalIcons.LoadIcons(g_hInstance); 548 #endif 549 550 Formats.Clear(); 551 552 #ifdef EXTERNAL_CODECS 553 Codecs.Clear(); 554 Hashers.Clear(); 555 #endif 556 557 for (UInt32 i = 0; i < g_NumArcs; i++) 558 { 559 const CArcInfo &arc = *g_Arcs[i]; 560 CArcInfoEx item; 561 562 item.Name.SetFromAscii(arc.Name); 563 item.CreateInArchive = arc.CreateInArchive; 564 item.IsArcFunc = arc.IsArc; 565 item.Flags = arc.Flags; 566 567 { 568 UString e, ae; 569 if (arc.Ext) 570 e.SetFromAscii(arc.Ext); 571 if (arc.AddExt) 572 ae.SetFromAscii(arc.AddExt); 573 item.AddExts(e, ae); 574 } 575 576 #ifndef _SFX 577 578 item.CreateOutArchive = arc.CreateOutArchive; 579 item.UpdateEnabled = (arc.CreateOutArchive != NULL); 580 item.SignatureOffset = arc.SignatureOffset; 581 // item.Version = MY_VER_MIX; 582 item.NewInterface = true; 583 584 if (arc.IsMultiSignature()) 585 ParseSignatures(arc.Signature, arc.SignatureSize, item.Signatures); 586 else 587 item.Signatures.AddNew().CopyFrom(arc.Signature, arc.SignatureSize); 588 589 #endif 590 591 Formats.Add(item); 592 } 593 594 #ifdef EXTERNAL_CODECS 595 const FString baseFolder = GetBaseFolderPrefixFromRegistry(); 596 RINOK(LoadDll(baseFolder + kMainDll, false)); 597 RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName FSTRING_PATH_SEPARATOR)); 598 RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName FSTRING_PATH_SEPARATOR)); 599 #endif 600 601 return S_OK; 602 } 603 604 #ifndef _SFX 605 606 int CCodecs::FindFormatForArchiveName(const UString &arcPath) const 607 { 608 int slashPos = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR); 609 int dotPos = arcPath.ReverseFind(L'.'); 610 if (dotPos < 0 || dotPos < slashPos) 611 return -1; 612 const UString ext = arcPath.Ptr(dotPos + 1); 613 if (ext.IsEmpty()) 614 return -1; 615 if (ext.IsEqualToNoCase(L"exe")) 616 return -1; 617 FOR_VECTOR (i, Formats) 618 { 619 const CArcInfoEx &arc = Formats[i]; 620 /* 621 if (!arc.UpdateEnabled) 622 continue; 623 */ 624 if (arc.FindExtension(ext) >= 0) 625 return i; 626 } 627 return -1; 628 } 629 630 int CCodecs::FindFormatForExtension(const UString &ext) const 631 { 632 if (ext.IsEmpty()) 633 return -1; 634 FOR_VECTOR (i, Formats) 635 if (Formats[i].FindExtension(ext) >= 0) 636 return i; 637 return -1; 638 } 639 640 int CCodecs::FindFormatForArchiveType(const UString &arcType) const 641 { 642 FOR_VECTOR (i, Formats) 643 if (Formats[i].Name.IsEqualToNoCase(arcType)) 644 return i; 645 return -1; 646 } 647 648 bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const 649 { 650 formatIndices.Clear(); 651 for (unsigned pos = 0; pos < arcType.Len();) 652 { 653 int pos2 = arcType.Find('.', pos); 654 if (pos2 < 0) 655 pos2 = arcType.Len(); 656 const UString name = arcType.Mid(pos, pos2 - pos); 657 if (name.IsEmpty()) 658 return false; 659 int index = FindFormatForArchiveType(name); 660 if (index < 0 && name != L"*") 661 { 662 formatIndices.Clear(); 663 return false; 664 } 665 formatIndices.Add(index); 666 pos = pos2 + 1; 667 } 668 return true; 669 } 670 671 #endif // _SFX 672 673 674 #ifdef EXTERNAL_CODECS 675 676 // #define EXPORT_CODECS 677 678 #ifdef EXPORT_CODECS 679 680 extern unsigned g_NumCodecs; 681 STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject); 682 STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); 683 #define NUM_EXPORT_CODECS g_NumCodecs 684 685 extern unsigned g_NumHashers; 686 STDAPI CreateHasher(UInt32 index, IHasher **hasher); 687 STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); 688 #define NUM_EXPORT_HASHERS g_NumHashers 689 690 #else // EXPORT_CODECS 691 692 #define NUM_EXPORT_CODECS 0 693 #define NUM_EXPORT_HASHERS 0 694 695 #endif // EXPORT_CODECS 696 697 STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods) 698 { 699 *numMethods = NUM_EXPORT_CODECS 700 #ifdef EXTERNAL_CODECS 701 + Codecs.Size() 702 #endif 703 ; 704 return S_OK; 705 } 706 707 STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) 708 { 709 #ifdef EXPORT_CODECS 710 if (index < g_NumCodecs) 711 return GetMethodProperty(index, propID, value); 712 #endif 713 714 #ifdef EXTERNAL_CODECS 715 const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; 716 717 if (propID == NMethodPropID::kDecoderIsAssigned || 718 propID == NMethodPropID::kEncoderIsAssigned) 719 { 720 NCOM::CPropVariant prop; 721 prop = (propID == NMethodPropID::kDecoderIsAssigned) ? 722 ci.DecoderIsAssigned : 723 ci.EncoderIsAssigned; 724 prop.Detach(value); 725 return S_OK; 726 } 727 return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value); 728 #else 729 return E_FAIL; 730 #endif 731 } 732 733 STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder) 734 { 735 #ifdef EXPORT_CODECS 736 if (index < g_NumCodecs) 737 return CreateCoder2(false, index, iid, coder); 738 #endif 739 #ifdef EXTERNAL_CODECS 740 const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; 741 if (ci.DecoderIsAssigned) 742 return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder); 743 return S_OK; 744 #else 745 return E_FAIL; 746 #endif 747 } 748 749 STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder) 750 { 751 #ifdef EXPORT_CODECS 752 if (index < g_NumCodecs) 753 return CreateCoder2(true, index, iid, coder); 754 #endif 755 #ifdef EXTERNAL_CODECS 756 const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; 757 if (ci.EncoderIsAssigned) 758 return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder); 759 return S_OK; 760 #else 761 return E_FAIL; 762 #endif 763 } 764 765 766 STDMETHODIMP_(UInt32) CCodecs::GetNumHashers() 767 { 768 return NUM_EXPORT_HASHERS 769 #ifdef EXTERNAL_CODECS 770 + Hashers.Size() 771 #endif 772 ; 773 } 774 775 STDMETHODIMP CCodecs::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value) 776 { 777 #ifdef EXPORT_CODECS 778 if (index < g_NumHashers) 779 return ::GetHasherProp(index, propID, value); 780 #endif 781 782 #ifdef EXTERNAL_CODECS 783 const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; 784 return Libs[ci.LibIndex].Hashers->GetHasherProp(ci.HasherIndex, propID, value); 785 #else 786 return E_FAIL; 787 #endif 788 } 789 790 STDMETHODIMP CCodecs::CreateHasher(UInt32 index, IHasher **hasher) 791 { 792 #ifdef EXPORT_CODECS 793 if (index < g_NumHashers) 794 return CreateHasher(index, hasher); 795 #endif 796 #ifdef EXTERNAL_CODECS 797 const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; 798 return Libs[ci.LibIndex].Hashers->CreateHasher(ci.HasherIndex, hasher); 799 #else 800 return E_FAIL; 801 #endif 802 } 803 804 int CCodecs::GetCodecLibIndex(UInt32 index) 805 { 806 #ifdef EXPORT_CODECS 807 if (index < g_NumCodecs) 808 return -1; 809 #endif 810 #ifdef EXTERNAL_CODECS 811 const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; 812 return ci.LibIndex; 813 #else 814 return -1; 815 #endif 816 } 817 818 int CCodecs::GetHasherLibIndex(UInt32 index) 819 { 820 #ifdef EXPORT_CODECS 821 if (index < g_NumHashers) 822 return -1; 823 #endif 824 #ifdef EXTERNAL_CODECS 825 const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; 826 return ci.LibIndex; 827 #else 828 return -1; 829 #endif 830 } 831 832 bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index) 833 { 834 #ifdef EXPORT_CODECS 835 if (index < g_NumCodecs) 836 { 837 NCOM::CPropVariant prop; 838 if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK) 839 if (prop.vt != VT_EMPTY) 840 return true; 841 return false; 842 } 843 #endif 844 #ifdef EXTERNAL_CODECS 845 const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; 846 return ci.EncoderIsAssigned; 847 #else 848 return false; 849 #endif 850 } 851 852 HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id) 853 { 854 NCOM::CPropVariant prop; 855 RINOK(GetProperty(index, NMethodPropID::kID, &prop)); 856 if (prop.vt != VT_UI8) 857 return E_INVALIDARG; 858 id = prop.uhVal.QuadPart; 859 return S_OK; 860 } 861 862 UString CCodecs::GetCodecName(UInt32 index) 863 { 864 UString s; 865 NCOM::CPropVariant prop; 866 if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK) 867 if (prop.vt == VT_BSTR) 868 s = prop.bstrVal; 869 return s; 870 } 871 872 UInt64 CCodecs::GetHasherId(UInt32 index) 873 { 874 NCOM::CPropVariant prop; 875 RINOK(GetHasherProp(index, NMethodPropID::kID, &prop)); 876 if (prop.vt != VT_UI8) 877 return 0; 878 return prop.uhVal.QuadPart; 879 } 880 881 UString CCodecs::GetHasherName(UInt32 index) 882 { 883 UString s; 884 NCOM::CPropVariant prop; 885 if (GetHasherProp(index, NMethodPropID::kName, &prop) == S_OK) 886 if (prop.vt == VT_BSTR) 887 s = prop.bstrVal; 888 return s; 889 } 890 891 UInt32 CCodecs::GetHasherDigestSize(UInt32 index) 892 { 893 NCOM::CPropVariant prop; 894 RINOK(GetHasherProp(index, NMethodPropID::kDigestSize, &prop)); 895 if (prop.vt != VT_UI4) 896 return 0; 897 return prop.ulVal; 898 } 899 900 #endif // EXTERNAL_CODECS 901