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