1 // LoadCodecs.h 2 3 #ifndef __LOAD_CODECS_H 4 #define __LOAD_CODECS_H 5 6 /* 7 Client application uses LoadCodecs.* to load plugins to 8 CCodecs object, that contains 3 lists of plugins: 9 1) Formats - internal and external archive handlers 10 2) Codecs - external codecs 11 3) Hashers - external hashers 12 13 EXTERNAL_CODECS 14 --------------- 15 16 if EXTERNAL_CODECS is defined, then the code tries to load external 17 plugins from DLL files (shared libraries). 18 19 There are two types of executables in 7-Zip: 20 21 1) Executable that uses external plugins must be compiled 22 with EXTERNAL_CODECS defined: 23 - 7z.exe, 7zG.exe, 7zFM.exe 24 25 Note: EXTERNAL_CODECS is used also in CPP/7zip/Common/CreateCoder.h 26 that code is used in plugin module (7z.dll). 27 28 2) Standalone modules are compiled without EXTERNAL_CODECS: 29 - SFX modules: 7z.sfx, 7zCon.sfx 30 - standalone versions of console 7-Zip: 7za.exe, 7zr.exe 31 32 if EXTERNAL_CODECS is defined, CCodecs class implements interfaces: 33 - ICompressCodecsInfo : for Codecs 34 - IHashers : for Hashers 35 36 The client application can send CCodecs object to each plugin module. 37 And plugin module can use ICompressCodecsInfo or IHashers interface to access 38 another plugins. 39 40 There are 2 ways to send (ICompressCodecsInfo * compressCodecsInfo) to plugin 41 1) for old versions: 42 a) request ISetCompressCodecsInfo from created archive handler. 43 b) call ISetCompressCodecsInfo::SetCompressCodecsInfo(compressCodecsInfo) 44 2) for new versions: 45 a) request "SetCodecs" function from DLL file 46 b) call SetCodecs(compressCodecsInfo) function from DLL file 47 */ 48 49 #include "../../../Common/MyBuffer.h" 50 #include "../../../Common/MyCom.h" 51 #include "../../../Common/MyString.h" 52 #include "../../../Common/ComTry.h" 53 54 #ifdef EXTERNAL_CODECS 55 #include "../../../Windows/DLL.h" 56 #endif 57 58 #include "../../ICoder.h" 59 60 #include "../../Archive/IArchive.h" 61 62 63 #ifdef EXTERNAL_CODECS 64 65 struct CDllCodecInfo 66 { 67 unsigned LibIndex; 68 UInt32 CodecIndex; 69 bool EncoderIsAssigned; 70 bool DecoderIsAssigned; 71 bool IsFilter; 72 bool IsFilter_Assigned; 73 CLSID Encoder; 74 CLSID Decoder; 75 }; 76 77 struct CDllHasherInfo 78 { 79 unsigned LibIndex; 80 UInt32 HasherIndex; 81 }; 82 83 #endif 84 85 struct CArcExtInfo 86 { 87 UString Ext; 88 UString AddExt; 89 CArcExtInfoCArcExtInfo90 CArcExtInfo() {} CArcExtInfoCArcExtInfo91 CArcExtInfo(const UString &ext): Ext(ext) {} CArcExtInfoCArcExtInfo92 CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {} 93 }; 94 95 96 struct CArcInfoEx 97 { 98 UInt32 Flags; 99 UInt32 TimeFlags; 100 101 Func_CreateInArchive CreateInArchive; 102 Func_IsArc IsArcFunc; 103 104 UString Name; 105 CObjectVector<CArcExtInfo> Exts; 106 107 #ifndef _SFX 108 Func_CreateOutArchive CreateOutArchive; 109 bool UpdateEnabled; 110 bool NewInterface; 111 // UInt32 Version; 112 UInt32 SignatureOffset; 113 CObjectVector<CByteBuffer> Signatures; 114 #ifdef NEW_FOLDER_INTERFACE 115 UStringVector AssociateExts; 116 #endif 117 #endif 118 119 #ifdef EXTERNAL_CODECS 120 int LibIndex; 121 UInt32 FormatIndex; 122 CLSID ClassID; 123 #endif 124 CompareCArcInfoEx125 int Compare(const CArcInfoEx &a) const 126 { 127 int res = Name.Compare(a.Name); 128 if (res != 0) 129 return res; 130 #ifdef EXTERNAL_CODECS 131 return MyCompare(LibIndex, a.LibIndex); 132 #else 133 return 0; 134 #endif 135 /* 136 if (LibIndex < a.LibIndex) return -1; 137 if (LibIndex > a.LibIndex) return 1; 138 return 0; 139 */ 140 } 141 Flags_KeepNameCArcInfoEx142 bool Flags_KeepName() const { return (Flags & NArcInfoFlags::kKeepName) != 0; } Flags_FindSignatureCArcInfoEx143 bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; } 144 Flags_AltStreamsCArcInfoEx145 bool Flags_AltStreams() const { return (Flags & NArcInfoFlags::kAltStreams) != 0; } Flags_NtSecurityCArcInfoEx146 bool Flags_NtSecurity() const { return (Flags & NArcInfoFlags::kNtSecure) != 0; } Flags_SymLinksCArcInfoEx147 bool Flags_SymLinks() const { return (Flags & NArcInfoFlags::kSymLinks) != 0; } Flags_HardLinksCArcInfoEx148 bool Flags_HardLinks() const { return (Flags & NArcInfoFlags::kHardLinks) != 0; } 149 Flags_UseGlobalOffsetCArcInfoEx150 bool Flags_UseGlobalOffset() const { return (Flags & NArcInfoFlags::kUseGlobalOffset) != 0; } Flags_StartOpenCArcInfoEx151 bool Flags_StartOpen() const { return (Flags & NArcInfoFlags::kStartOpen) != 0; } Flags_BackwardOpenCArcInfoEx152 bool Flags_BackwardOpen() const { return (Flags & NArcInfoFlags::kBackwardOpen) != 0; } Flags_PreArcCArcInfoEx153 bool Flags_PreArc() const { return (Flags & NArcInfoFlags::kPreArc) != 0; } Flags_PureStartOpenCArcInfoEx154 bool Flags_PureStartOpen() const { return (Flags & NArcInfoFlags::kPureStartOpen) != 0; } Flags_ByExtOnlyOpenCArcInfoEx155 bool Flags_ByExtOnlyOpen() const { return (Flags & NArcInfoFlags::kByExtOnlyOpen) != 0; } Flags_HashHandlerCArcInfoEx156 bool Flags_HashHandler() const { return (Flags & NArcInfoFlags::kHashHandler) != 0; } 157 Flags_CTimeCArcInfoEx158 bool Flags_CTime() const { return (Flags & NArcInfoFlags::kCTime) != 0; } Flags_ATimeCArcInfoEx159 bool Flags_ATime() const { return (Flags & NArcInfoFlags::kATime) != 0; } Flags_MTimeCArcInfoEx160 bool Flags_MTime() const { return (Flags & NArcInfoFlags::kMTime) != 0; } 161 Flags_CTime_DefaultCArcInfoEx162 bool Flags_CTime_Default() const { return (Flags & NArcInfoFlags::kCTime_Default) != 0; } Flags_ATime_DefaultCArcInfoEx163 bool Flags_ATime_Default() const { return (Flags & NArcInfoFlags::kATime_Default) != 0; } Flags_MTime_DefaultCArcInfoEx164 bool Flags_MTime_Default() const { return (Flags & NArcInfoFlags::kMTime_Default) != 0; } 165 Get_TimePrecFlagsCArcInfoEx166 UInt32 Get_TimePrecFlags() const 167 { 168 return (TimeFlags >> NArcInfoTimeFlags::kTime_Prec_Mask_bit_index) & 169 (((UInt32)1 << NArcInfoTimeFlags::kTime_Prec_Mask_num_bits) - 1); 170 } 171 Get_DefaultTimePrecCArcInfoEx172 UInt32 Get_DefaultTimePrec() const 173 { 174 return (TimeFlags >> NArcInfoTimeFlags::kTime_Prec_Default_bit_index) & 175 (((UInt32)1 << NArcInfoTimeFlags::kTime_Prec_Default_num_bits) - 1); 176 } 177 178 GetMainExtCArcInfoEx179 UString GetMainExt() const 180 { 181 if (Exts.IsEmpty()) 182 return UString(); 183 return Exts[0].Ext; 184 } 185 int FindExtension(const UString &ext) const; 186 Is_7zCArcInfoEx187 bool Is_7z() const { return Name.IsEqualTo_Ascii_NoCase("7z"); } Is_SplitCArcInfoEx188 bool Is_Split() const { return Name.IsEqualTo_Ascii_NoCase("Split"); } Is_XzCArcInfoEx189 bool Is_Xz() const { return Name.IsEqualTo_Ascii_NoCase("xz"); } Is_BZip2CArcInfoEx190 bool Is_BZip2() const { return Name.IsEqualTo_Ascii_NoCase("bzip2"); } Is_GZipCArcInfoEx191 bool Is_GZip() const { return Name.IsEqualTo_Ascii_NoCase("gzip"); } Is_TarCArcInfoEx192 bool Is_Tar() const { return Name.IsEqualTo_Ascii_NoCase("tar"); } Is_ZipCArcInfoEx193 bool Is_Zip() const { return Name.IsEqualTo_Ascii_NoCase("zip"); } Is_RarCArcInfoEx194 bool Is_Rar() const { return Name.IsEqualTo_Ascii_NoCase("rar"); } 195 196 /* 197 UString GetAllExtensions() const 198 { 199 UString s; 200 for (int i = 0; i < Exts.Size(); i++) 201 { 202 if (i > 0) 203 s += ' '; 204 s += Exts[i].Ext; 205 } 206 return s; 207 } 208 */ 209 210 void AddExts(const UString &ext, const UString &addExt); 211 212 CArcInfoExCArcInfoEx213 CArcInfoEx(): 214 Flags(0), 215 TimeFlags(0), 216 CreateInArchive(NULL), 217 IsArcFunc(NULL) 218 #ifndef _SFX 219 , CreateOutArchive(NULL) 220 , UpdateEnabled(false) 221 , NewInterface(false) 222 // , Version(0) 223 , SignatureOffset(0) 224 #endif 225 #ifdef EXTERNAL_CODECS 226 , LibIndex(-1) 227 #endif 228 {} 229 }; 230 231 #ifdef NEW_FOLDER_INTERFACE 232 233 struct CCodecIcons 234 { 235 struct CIconPair 236 { 237 UString Ext; 238 int IconIndex; 239 }; 240 CObjectVector<CIconPair> IconPairs; 241 242 void LoadIcons(HMODULE m); 243 bool FindIconIndex(const UString &ext, int &iconIndex) const; 244 }; 245 246 #endif 247 248 #ifdef EXTERNAL_CODECS 249 250 struct CCodecLib 251 #ifdef NEW_FOLDER_INTERFACE 252 : public CCodecIcons 253 #endif 254 { 255 NWindows::NDLL::CLibrary Lib; 256 FString Path; 257 258 Func_CreateObject CreateObject; 259 Func_GetMethodProperty GetMethodProperty; 260 Func_CreateDecoder CreateDecoder; 261 Func_CreateEncoder CreateEncoder; 262 Func_SetCodecs SetCodecs; 263 264 CMyComPtr<IHashers> ComHashers; 265 266 #ifdef NEW_FOLDER_INTERFACE LoadIconsCCodecLib267 void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); } 268 #endif 269 CCodecLibCCodecLib270 CCodecLib(): 271 CreateObject(NULL), 272 GetMethodProperty(NULL), 273 CreateDecoder(NULL), 274 CreateEncoder(NULL), 275 SetCodecs(NULL) 276 {} 277 }; 278 279 #endif 280 281 struct CCodecError 282 { 283 FString Path; 284 HRESULT ErrorCode; 285 AString Message; CCodecErrorCCodecError286 CCodecError(): ErrorCode(0) {} 287 }; 288 289 290 struct CCodecInfoUser 291 { 292 // unsigned LibIndex; 293 // UInt32 CodecIndex; 294 // UInt64 id; 295 bool EncoderIsAssigned; 296 bool DecoderIsAssigned; 297 bool IsFilter; 298 bool IsFilter_Assigned; 299 UInt32 NumStreams; 300 AString Name; 301 }; 302 303 304 class CCodecs: 305 #ifdef EXTERNAL_CODECS 306 public ICompressCodecsInfo, 307 public IHashers, 308 #else 309 public IUnknown, 310 #endif 311 public CMyUnknownImp 312 { 313 CLASS_NO_COPY(CCodecs); 314 public: 315 #ifdef EXTERNAL_CODECS 316 317 CObjectVector<CCodecLib> Libs; 318 FString MainDll_ErrorPath; 319 CObjectVector<CCodecError> Errors; 320 321 void AddLastError(const FString &path); 322 void CloseLibs(); 323 324 class CReleaser 325 { 326 CLASS_NO_COPY(CReleaser); 327 328 /* CCodecsReleaser object releases CCodecs links. 329 1) CCodecs is COM object that is deleted when all links to that object will be released/ 330 2) CCodecs::Libs[i] can hold (ICompressCodecsInfo *) link to CCodecs object itself. 331 To break that reference loop, we must close all CCodecs::Libs in CCodecsReleaser desttructor. */ 332 333 CCodecs *_codecs; 334 335 public: CReleaser()336 CReleaser(): _codecs(NULL) {} Set(CCodecs * codecs)337 void Set(CCodecs *codecs) { _codecs = codecs; } ~CReleaser()338 ~CReleaser() { if (_codecs) _codecs->CloseLibs(); } 339 }; 340 341 bool NeedSetLibCodecs; // = false, if we don't need to set codecs for archive handler via ISetCompressCodecsInfo 342 343 HRESULT LoadCodecs(); 344 HRESULT LoadFormats(); 345 HRESULT LoadDll(const FString &path, bool needCheckDll, bool *loadedOK = NULL); 346 HRESULT LoadDllsFromFolder(const FString &folderPrefix); 347 CreateArchiveHandler(const CArcInfoEx & ai,bool outHandler,void ** archive)348 HRESULT CreateArchiveHandler(const CArcInfoEx &ai, bool outHandler, void **archive) const 349 { 350 return Libs[(unsigned)ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive); 351 } 352 353 #endif 354 355 #ifdef NEW_FOLDER_INTERFACE 356 CCodecIcons InternalIcons; 357 #endif 358 359 CObjectVector<CArcInfoEx> Formats; 360 361 #ifdef EXTERNAL_CODECS 362 CRecordVector<CDllCodecInfo> Codecs; 363 CRecordVector<CDllHasherInfo> Hashers; 364 #endif 365 366 bool CaseSensitive_Change; 367 bool CaseSensitive; 368 CCodecs()369 CCodecs(): 370 #ifdef EXTERNAL_CODECS 371 NeedSetLibCodecs(true), 372 #endif 373 CaseSensitive_Change(false), 374 CaseSensitive(false) 375 {} 376 ~CCodecs()377 ~CCodecs() 378 { 379 // OutputDebugStringA("~CCodecs"); 380 } 381 GetFormatNamePtr(int formatIndex)382 const wchar_t *GetFormatNamePtr(int formatIndex) const 383 { 384 return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[(unsigned)formatIndex].Name; 385 } 386 387 HRESULT Load(); 388 389 #ifndef _SFX 390 int FindFormatForArchiveName(const UString &arcPath) const; 391 int FindFormatForExtension(const UString &ext) const; 392 int FindFormatForArchiveType(const UString &arcType) const; 393 bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const; 394 #endif 395 396 #ifdef EXTERNAL_CODECS 397 398 MY_UNKNOWN_IMP2(ICompressCodecsInfo, IHashers) 399 400 STDMETHOD(GetNumMethods)(UInt32 *numMethods); 401 STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); 402 STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder); 403 STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder); 404 405 STDMETHOD_(UInt32, GetNumHashers)(); 406 STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value); 407 STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher); 408 409 #else 410 411 MY_UNKNOWN_IMP 412 413 #endif // EXTERNAL_CODECS 414 415 416 #ifdef EXTERNAL_CODECS 417 418 int GetCodec_LibIndex(UInt32 index) const; 419 bool GetCodec_DecoderIsAssigned(UInt32 index) const; 420 bool GetCodec_EncoderIsAssigned(UInt32 index) const; 421 bool GetCodec_IsFilter(UInt32 index, bool &isAssigned) const; 422 UInt32 GetCodec_NumStreams(UInt32 index); 423 HRESULT GetCodec_Id(UInt32 index, UInt64 &id); 424 AString GetCodec_Name(UInt32 index); 425 426 int GetHasherLibIndex(UInt32 index); 427 UInt64 GetHasherId(UInt32 index); 428 AString GetHasherName(UInt32 index); 429 UInt32 GetHasherDigestSize(UInt32 index); 430 431 void GetCodecsErrorMessage(UString &s); 432 433 #endif 434 CreateInArchive(unsigned formatIndex,CMyComPtr<IInArchive> & archive)435 HRESULT CreateInArchive(unsigned formatIndex, CMyComPtr<IInArchive> &archive) const 436 { 437 const CArcInfoEx &ai = Formats[formatIndex]; 438 #ifdef EXTERNAL_CODECS 439 if (ai.LibIndex < 0) 440 #endif 441 { 442 COM_TRY_BEGIN 443 archive = ai.CreateInArchive(); 444 return S_OK; 445 COM_TRY_END 446 } 447 #ifdef EXTERNAL_CODECS 448 return CreateArchiveHandler(ai, false, (void **)&archive); 449 #endif 450 } 451 452 #ifndef _SFX 453 CreateOutArchive(unsigned formatIndex,CMyComPtr<IOutArchive> & archive)454 HRESULT CreateOutArchive(unsigned formatIndex, CMyComPtr<IOutArchive> &archive) const 455 { 456 const CArcInfoEx &ai = Formats[formatIndex]; 457 #ifdef EXTERNAL_CODECS 458 if (ai.LibIndex < 0) 459 #endif 460 { 461 COM_TRY_BEGIN 462 archive = ai.CreateOutArchive(); 463 return S_OK; 464 COM_TRY_END 465 } 466 467 #ifdef EXTERNAL_CODECS 468 return CreateArchiveHandler(ai, true, (void **)&archive); 469 #endif 470 } 471 FindOutFormatFromName(const UString & name)472 int FindOutFormatFromName(const UString &name) const 473 { 474 FOR_VECTOR (i, Formats) 475 { 476 const CArcInfoEx &arc = Formats[i]; 477 if (!arc.UpdateEnabled) 478 continue; 479 if (arc.Name.IsEqualTo_NoCase(name)) 480 return (int)i; 481 } 482 return -1; 483 } 484 485 void Get_CodecsInfoUser_Vector(CObjectVector<CCodecInfoUser> &v); 486 487 #endif // _SFX 488 }; 489 490 #ifdef EXTERNAL_CODECS 491 #define CREATE_CODECS_OBJECT \ 492 CCodecs *codecs = new CCodecs; \ 493 CExternalCodecs __externalCodecs; \ 494 __externalCodecs.GetCodecs = codecs; \ 495 __externalCodecs.GetHashers = codecs; \ 496 CCodecs::CReleaser codecsReleaser; \ 497 codecsReleaser.Set(codecs); 498 #else 499 #define CREATE_CODECS_OBJECT \ 500 CCodecs *codecs = new CCodecs; \ 501 CMyComPtr<IUnknown> __codecsRef = codecs; 502 #endif 503 504 #endif 505