LoadCodecs.cpp (27198B)
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 const 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 const kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip"); 95 static LPCWSTR const kProgramPathValue = L"Path"; 96 static LPCWSTR const 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 { 520 unsigned startSize = Codecs.Size() + Hashers.Size(); 521 res = LoadCodecs(); 522 used = (startSize != Codecs.Size() + Hashers.Size()); 523 if (res == S_OK && lib.CreateObject) 524 { 525 startSize = Formats.Size(); 526 res = LoadFormats(); 527 if (startSize != Formats.Size()) 528 used = true; 529 } 530 } 531 } 532 533 if (!used) 534 Libs.DeleteBack(); 535 536 return res; 537 } 538 539 HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPrefix) 540 { 541 NFile::NFind::CEnumerator enumerator; 542 enumerator.SetDirPrefix(folderPrefix); 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 = 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 = arc.Ext; 607 if (arc.AddExt) 608 ae = 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 if (lib.CreateObject) 870 return lib.CreateObject(&ci.Decoder, iid, (void **)coder); 871 } 872 return S_OK; 873 #else 874 return E_FAIL; 875 #endif 876 } 877 878 STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder) 879 { 880 #ifdef EXPORT_CODECS 881 if (index < g_NumCodecs) 882 return CreateEncoder(index, iid, coder); 883 #endif 884 885 #ifdef EXTERNAL_CODECS 886 const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; 887 if (ci.EncoderIsAssigned) 888 { 889 const CCodecLib &lib = Libs[ci.LibIndex]; 890 if (lib.CreateEncoder) 891 return lib.CreateEncoder(ci.CodecIndex, iid, (void **)coder); 892 if (lib.CreateObject) 893 return lib.CreateObject(&ci.Encoder, iid, (void **)coder); 894 } 895 return S_OK; 896 #else 897 return E_FAIL; 898 #endif 899 } 900 901 902 STDMETHODIMP_(UInt32) CCodecs::GetNumHashers() 903 { 904 return NUM_EXPORT_HASHERS 905 #ifdef EXTERNAL_CODECS 906 + Hashers.Size() 907 #endif 908 ; 909 } 910 911 STDMETHODIMP CCodecs::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value) 912 { 913 #ifdef EXPORT_CODECS 914 if (index < g_NumHashers) 915 return ::GetHasherProp(index, propID, value); 916 #endif 917 918 #ifdef EXTERNAL_CODECS 919 const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; 920 return Libs[ci.LibIndex].ComHashers->GetHasherProp(ci.HasherIndex, propID, value); 921 #else 922 return E_FAIL; 923 #endif 924 } 925 926 STDMETHODIMP CCodecs::CreateHasher(UInt32 index, IHasher **hasher) 927 { 928 #ifdef EXPORT_CODECS 929 if (index < g_NumHashers) 930 return CreateHasher(index, hasher); 931 #endif 932 #ifdef EXTERNAL_CODECS 933 const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; 934 return Libs[ci.LibIndex].ComHashers->CreateHasher(ci.HasherIndex, hasher); 935 #else 936 return E_FAIL; 937 #endif 938 } 939 940 int CCodecs::GetCodec_LibIndex(UInt32 index) const 941 { 942 #ifdef EXPORT_CODECS 943 if (index < g_NumCodecs) 944 return -1; 945 #endif 946 947 #ifdef EXTERNAL_CODECS 948 const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; 949 return ci.LibIndex; 950 #else 951 return -1; 952 #endif 953 } 954 955 int CCodecs::GetHasherLibIndex(UInt32 index) 956 { 957 #ifdef EXPORT_CODECS 958 if (index < g_NumHashers) 959 return -1; 960 #endif 961 962 #ifdef EXTERNAL_CODECS 963 const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; 964 return ci.LibIndex; 965 #else 966 return -1; 967 #endif 968 } 969 970 bool CCodecs::GetCodec_DecoderIsAssigned(UInt32 index) const 971 { 972 #ifdef EXPORT_CODECS 973 if (index < g_NumCodecs) 974 { 975 NCOM::CPropVariant prop; 976 if (GetProperty(index, NMethodPropID::kDecoderIsAssigned, &prop) == S_OK) 977 { 978 if (prop.vt == VT_BOOL) 979 return VARIANT_BOOLToBool(prop.boolVal); 980 } 981 return false; 982 } 983 #endif 984 985 #ifdef EXTERNAL_CODECS 986 return Codecs[index - NUM_EXPORT_CODECS].DecoderIsAssigned; 987 #else 988 return false; 989 #endif 990 } 991 992 bool CCodecs::GetCodec_EncoderIsAssigned(UInt32 index) const 993 { 994 #ifdef EXPORT_CODECS 995 if (index < g_NumCodecs) 996 { 997 NCOM::CPropVariant prop; 998 if (GetProperty(index, NMethodPropID::kEncoderIsAssigned, &prop) == S_OK) 999 { 1000 if (prop.vt == VT_BOOL) 1001 return VARIANT_BOOLToBool(prop.boolVal); 1002 } 1003 return false; 1004 } 1005 #endif 1006 1007 #ifdef EXTERNAL_CODECS 1008 return Codecs[index - NUM_EXPORT_CODECS].EncoderIsAssigned; 1009 #else 1010 return false; 1011 #endif 1012 } 1013 1014 UInt32 CCodecs::GetCodec_NumStreams(UInt32 index) 1015 { 1016 NCOM::CPropVariant prop; 1017 RINOK(GetProperty(index, NMethodPropID::kPackStreams, &prop)); 1018 if (prop.vt == VT_UI4) 1019 return (UInt32)prop.ulVal; 1020 if (prop.vt == VT_EMPTY) 1021 return 1; 1022 return 0; 1023 } 1024 1025 HRESULT CCodecs::GetCodec_Id(UInt32 index, UInt64 &id) 1026 { 1027 NCOM::CPropVariant prop; 1028 RINOK(GetProperty(index, NMethodPropID::kID, &prop)); 1029 if (prop.vt != VT_UI8) 1030 return E_INVALIDARG; 1031 id = prop.uhVal.QuadPart; 1032 return S_OK; 1033 } 1034 1035 AString CCodecs::GetCodec_Name(UInt32 index) 1036 { 1037 AString s; 1038 NCOM::CPropVariant prop; 1039 if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK) 1040 if (prop.vt == VT_BSTR) 1041 s.SetFromWStr_if_Ascii(prop.bstrVal); 1042 return s; 1043 } 1044 1045 UInt64 CCodecs::GetHasherId(UInt32 index) 1046 { 1047 NCOM::CPropVariant prop; 1048 if (GetHasherProp(index, NMethodPropID::kID, &prop) != S_OK) 1049 return 0; 1050 if (prop.vt != VT_UI8) 1051 return 0; 1052 return prop.uhVal.QuadPart; 1053 } 1054 1055 AString CCodecs::GetHasherName(UInt32 index) 1056 { 1057 AString s; 1058 NCOM::CPropVariant prop; 1059 if (GetHasherProp(index, NMethodPropID::kName, &prop) == S_OK) 1060 if (prop.vt == VT_BSTR) 1061 s.SetFromWStr_if_Ascii(prop.bstrVal); 1062 return s; 1063 } 1064 1065 UInt32 CCodecs::GetHasherDigestSize(UInt32 index) 1066 { 1067 NCOM::CPropVariant prop; 1068 RINOK(GetHasherProp(index, NMethodPropID::kDigestSize, &prop)); 1069 if (prop.vt != VT_UI4) 1070 return 0; 1071 return prop.ulVal; 1072 } 1073 1074 #endif // EXTERNAL_CODECS