1 // LoadCodecs.h 2 3 #ifndef ZIP7_INC_LOAD_CODECS_H 4 #define ZIP7_INC_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 Z7_EXTERNAL_CODECS 14 --------------- 15 16 if Z7_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 Z7_EXTERNAL_CODECS defined: 23 - 7z.exe, 7zG.exe, 7zFM.exe 24 25 Note: Z7_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 Z7_EXTERNAL_CODECS: 29 - SFX modules: 7z.sfx, 7zCon.sfx 30 - standalone versions of console 7-Zip: 7za.exe, 7zr.exe 31 32 if Z7_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 Z7_EXTERNAL_CODECS 55 #include "../../../Windows/DLL.h" 56 #endif 57 58 #include "../../ICoder.h" 59 60 #include "../../Archive/IArchive.h" 61 62 63 #ifdef Z7_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 Z7_SFX 108 Func_CreateOutArchive CreateOutArchive; 109 bool UpdateEnabled; 110 bool NewInterface; 111 // UInt32 Version; 112 UInt32 SignatureOffset; 113 CObjectVector<CByteBuffer> Signatures; 114 /* 115 #ifdef NEW_FOLDER_INTERFACE 116 UStringVector AssociateExts; 117 #endif 118 */ 119 #endif 120 121 #ifdef Z7_EXTERNAL_CODECS 122 int LibIndex; 123 UInt32 FormatIndex; 124 CLSID ClassID; 125 #endif 126 CompareCArcInfoEx127 int Compare(const CArcInfoEx &a) const 128 { 129 const int res = Name.Compare(a.Name); 130 if (res != 0) 131 return res; 132 #ifdef Z7_EXTERNAL_CODECS 133 return MyCompare(LibIndex, a.LibIndex); 134 #else 135 return 0; 136 #endif 137 /* 138 if (LibIndex < a.LibIndex) return -1; 139 if (LibIndex > a.LibIndex) return 1; 140 return 0; 141 */ 142 } 143 Flags_KeepNameCArcInfoEx144 bool Flags_KeepName() const { return (Flags & NArcInfoFlags::kKeepName) != 0; } Flags_FindSignatureCArcInfoEx145 bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; } 146 Flags_AltStreamsCArcInfoEx147 bool Flags_AltStreams() const { return (Flags & NArcInfoFlags::kAltStreams) != 0; } Flags_NtSecurityCArcInfoEx148 bool Flags_NtSecurity() const { return (Flags & NArcInfoFlags::kNtSecure) != 0; } Flags_SymLinksCArcInfoEx149 bool Flags_SymLinks() const { return (Flags & NArcInfoFlags::kSymLinks) != 0; } Flags_HardLinksCArcInfoEx150 bool Flags_HardLinks() const { return (Flags & NArcInfoFlags::kHardLinks) != 0; } 151 Flags_UseGlobalOffsetCArcInfoEx152 bool Flags_UseGlobalOffset() const { return (Flags & NArcInfoFlags::kUseGlobalOffset) != 0; } Flags_StartOpenCArcInfoEx153 bool Flags_StartOpen() const { return (Flags & NArcInfoFlags::kStartOpen) != 0; } Flags_BackwardOpenCArcInfoEx154 bool Flags_BackwardOpen() const { return (Flags & NArcInfoFlags::kBackwardOpen) != 0; } Flags_PreArcCArcInfoEx155 bool Flags_PreArc() const { return (Flags & NArcInfoFlags::kPreArc) != 0; } Flags_PureStartOpenCArcInfoEx156 bool Flags_PureStartOpen() const { return (Flags & NArcInfoFlags::kPureStartOpen) != 0; } Flags_ByExtOnlyOpenCArcInfoEx157 bool Flags_ByExtOnlyOpen() const { return (Flags & NArcInfoFlags::kByExtOnlyOpen) != 0; } Flags_HashHandlerCArcInfoEx158 bool Flags_HashHandler() const { return (Flags & NArcInfoFlags::kHashHandler) != 0; } 159 Flags_CTimeCArcInfoEx160 bool Flags_CTime() const { return (Flags & NArcInfoFlags::kCTime) != 0; } Flags_ATimeCArcInfoEx161 bool Flags_ATime() const { return (Flags & NArcInfoFlags::kATime) != 0; } Flags_MTimeCArcInfoEx162 bool Flags_MTime() const { return (Flags & NArcInfoFlags::kMTime) != 0; } 163 Flags_CTime_DefaultCArcInfoEx164 bool Flags_CTime_Default() const { return (Flags & NArcInfoFlags::kCTime_Default) != 0; } Flags_ATime_DefaultCArcInfoEx165 bool Flags_ATime_Default() const { return (Flags & NArcInfoFlags::kATime_Default) != 0; } Flags_MTime_DefaultCArcInfoEx166 bool Flags_MTime_Default() const { return (Flags & NArcInfoFlags::kMTime_Default) != 0; } 167 Get_TimePrecFlagsCArcInfoEx168 UInt32 Get_TimePrecFlags() const 169 { 170 return (TimeFlags >> NArcInfoTimeFlags::kTime_Prec_Mask_bit_index) & 171 (((UInt32)1 << NArcInfoTimeFlags::kTime_Prec_Mask_num_bits) - 1); 172 } 173 Get_DefaultTimePrecCArcInfoEx174 UInt32 Get_DefaultTimePrec() const 175 { 176 return (TimeFlags >> NArcInfoTimeFlags::kTime_Prec_Default_bit_index) & 177 (((UInt32)1 << NArcInfoTimeFlags::kTime_Prec_Default_num_bits) - 1); 178 } 179 180 GetMainExtCArcInfoEx181 UString GetMainExt() const 182 { 183 if (Exts.IsEmpty()) 184 return UString(); 185 return Exts[0].Ext; 186 } 187 int FindExtension(const UString &ext) const; 188 Is_7zCArcInfoEx189 bool Is_7z() const { return Name.IsEqualTo_Ascii_NoCase("7z"); } Is_SplitCArcInfoEx190 bool Is_Split() const { return Name.IsEqualTo_Ascii_NoCase("Split"); } Is_XzCArcInfoEx191 bool Is_Xz() const { return Name.IsEqualTo_Ascii_NoCase("xz"); } Is_BZip2CArcInfoEx192 bool Is_BZip2() const { return Name.IsEqualTo_Ascii_NoCase("bzip2"); } Is_GZipCArcInfoEx193 bool Is_GZip() const { return Name.IsEqualTo_Ascii_NoCase("gzip"); } Is_TarCArcInfoEx194 bool Is_Tar() const { return Name.IsEqualTo_Ascii_NoCase("tar"); } Is_ZipCArcInfoEx195 bool Is_Zip() const { return Name.IsEqualTo_Ascii_NoCase("zip"); } Is_RarCArcInfoEx196 bool Is_Rar() const { return Name.IsEqualTo_Ascii_NoCase("rar"); } Is_ZstdCArcInfoEx197 bool Is_Zstd() const { return Name.IsEqualTo_Ascii_NoCase("zstd"); } 198 199 /* 200 UString GetAllExtensions() const 201 { 202 UString s; 203 for (int i = 0; i < Exts.Size(); i++) 204 { 205 if (i > 0) 206 s.Add_Space(); 207 s += Exts[i].Ext; 208 } 209 return s; 210 } 211 */ 212 213 void AddExts(const UString &ext, const UString &addExt); 214 215 CArcInfoExCArcInfoEx216 CArcInfoEx(): 217 Flags(0), 218 TimeFlags(0), 219 CreateInArchive(NULL), 220 IsArcFunc(NULL) 221 #ifndef Z7_SFX 222 , CreateOutArchive(NULL) 223 , UpdateEnabled(false) 224 , NewInterface(false) 225 // , Version(0) 226 , SignatureOffset(0) 227 #endif 228 #ifdef Z7_EXTERNAL_CODECS 229 , LibIndex(-1) 230 #endif 231 {} 232 }; 233 234 235 #ifdef Z7_EXTERNAL_CODECS 236 237 struct CCodecLib 238 { 239 NWindows::NDLL::CLibrary Lib; 240 FString Path; 241 242 Func_CreateObject CreateObject; 243 Func_GetMethodProperty GetMethodProperty; 244 Func_CreateDecoder CreateDecoder; 245 Func_CreateEncoder CreateEncoder; 246 Func_SetCodecs SetCodecs; 247 248 CMyComPtr<IHashers> ComHashers; 249 250 UInt32 Version; 251 252 /* 253 #ifdef NEW_FOLDER_INTERFACE 254 CCodecIcons CodecIcons; 255 void LoadIcons() { CodecIcons.LoadIcons((HMODULE)Lib); } 256 #endif 257 */ 258 CCodecLibCCodecLib259 CCodecLib(): 260 CreateObject(NULL), 261 GetMethodProperty(NULL), 262 CreateDecoder(NULL), 263 CreateEncoder(NULL), 264 SetCodecs(NULL), 265 Version(0) 266 {} 267 }; 268 269 #endif 270 271 struct CCodecError 272 { 273 FString Path; 274 HRESULT ErrorCode; 275 AString Message; CCodecErrorCCodecError276 CCodecError(): ErrorCode(0) {} 277 }; 278 279 280 struct CCodecInfoUser 281 { 282 // unsigned LibIndex; 283 // UInt32 CodecIndex; 284 // UInt64 id; 285 bool EncoderIsAssigned; 286 bool DecoderIsAssigned; 287 bool IsFilter; 288 bool IsFilter_Assigned; 289 UInt32 NumStreams; 290 AString Name; 291 }; 292 293 294 class CCodecs Z7_final: 295 #ifdef Z7_EXTERNAL_CODECS 296 public ICompressCodecsInfo, 297 public IHashers, 298 #else 299 public IUnknown, 300 #endif 301 public CMyUnknownImp 302 { 303 #ifdef Z7_EXTERNAL_CODECS 304 Z7_IFACES_IMP_UNK_2(ICompressCodecsInfo, IHashers) 305 #else 306 Z7_COM_UNKNOWN_IMP_0 307 #endif // Z7_EXTERNAL_CODECS 308 309 Z7_CLASS_NO_COPY(CCodecs) 310 public: 311 #ifdef Z7_EXTERNAL_CODECS 312 313 CObjectVector<CCodecLib> Libs; 314 FString MainDll_ErrorPath; 315 CObjectVector<CCodecError> Errors; 316 317 void AddLastError(const FString &path); 318 void CloseLibs(); 319 320 class CReleaser 321 { Z7_CLASS_NO_COPY(CReleaser)322 Z7_CLASS_NO_COPY(CReleaser) 323 324 /* CCodecsReleaser object releases CCodecs links. 325 1) CCodecs is COM object that is deleted when all links to that object will be released/ 326 2) CCodecs::Libs[i] can hold (ICompressCodecsInfo *) link to CCodecs object itself. 327 To break that reference loop, we must close all CCodecs::Libs in CCodecsReleaser desttructor. */ 328 329 CCodecs *_codecs; 330 331 public: 332 CReleaser(): _codecs(NULL) {} Set(CCodecs * codecs)333 void Set(CCodecs *codecs) { _codecs = codecs; } ~CReleaser()334 ~CReleaser() { if (_codecs) _codecs->CloseLibs(); } 335 }; 336 337 bool NeedSetLibCodecs; // = false, if we don't need to set codecs for archive handler via ISetCompressCodecsInfo 338 339 HRESULT LoadCodecs(); 340 HRESULT LoadFormats(); 341 HRESULT LoadDll(const FString &path, bool needCheckDll, bool *loadedOK = NULL); 342 HRESULT LoadDllsFromFolder(const FString &folderPrefix); 343 CreateArchiveHandler(const CArcInfoEx & ai,bool outHandler,void ** archive)344 HRESULT CreateArchiveHandler(const CArcInfoEx &ai, bool outHandler, void **archive) const 345 { 346 return Libs[(unsigned)ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive); 347 } 348 349 #endif 350 351 /* 352 #ifdef NEW_FOLDER_INTERFACE 353 CCodecIcons InternalIcons; 354 #endif 355 */ 356 357 CObjectVector<CArcInfoEx> Formats; 358 359 #ifdef Z7_EXTERNAL_CODECS 360 CRecordVector<CDllCodecInfo> Codecs; 361 CRecordVector<CDllHasherInfo> Hashers; 362 #endif 363 364 bool CaseSensitive_Change; 365 bool CaseSensitive; 366 CCodecs()367 CCodecs(): 368 #ifdef Z7_EXTERNAL_CODECS 369 NeedSetLibCodecs(true), 370 #endif 371 CaseSensitive_Change(false), 372 CaseSensitive(false) 373 {} 374 ~CCodecs()375 ~CCodecs() 376 { 377 // OutputDebugStringA("~CCodecs"); 378 } 379 GetFormatNamePtr(int formatIndex)380 const wchar_t *GetFormatNamePtr(int formatIndex) const 381 { 382 return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[(unsigned)formatIndex].Name; 383 } 384 385 HRESULT Load(); 386 387 #ifndef Z7_SFX 388 int FindFormatForArchiveName(const UString &arcPath) const; 389 int FindFormatForExtension(const UString &ext) const; 390 int FindFormatForArchiveType(const UString &arcType) const; 391 bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const; 392 #endif 393 394 #ifdef Z7_EXTERNAL_CODECS 395 396 int GetCodec_LibIndex(UInt32 index) const; 397 bool GetCodec_DecoderIsAssigned(UInt32 index) const; 398 bool GetCodec_EncoderIsAssigned(UInt32 index) const; 399 bool GetCodec_IsFilter(UInt32 index, bool &isAssigned) const; 400 UInt32 GetCodec_NumStreams(UInt32 index); 401 HRESULT GetCodec_Id(UInt32 index, UInt64 &id); 402 AString GetCodec_Name(UInt32 index); 403 404 int GetHasherLibIndex(UInt32 index); 405 UInt64 GetHasherId(UInt32 index); 406 AString GetHasherName(UInt32 index); 407 UInt32 GetHasherDigestSize(UInt32 index); 408 409 void GetCodecsErrorMessage(UString &s); 410 411 #endif 412 CreateInArchive(unsigned formatIndex,CMyComPtr<IInArchive> & archive)413 HRESULT CreateInArchive(unsigned formatIndex, CMyComPtr<IInArchive> &archive) const 414 { 415 const CArcInfoEx &ai = Formats[formatIndex]; 416 #ifdef Z7_EXTERNAL_CODECS 417 if (ai.LibIndex < 0) 418 #endif 419 { 420 COM_TRY_BEGIN 421 archive = ai.CreateInArchive(); 422 return S_OK; 423 COM_TRY_END 424 } 425 #ifdef Z7_EXTERNAL_CODECS 426 return CreateArchiveHandler(ai, false, (void **)&archive); 427 #endif 428 } 429 430 #ifndef Z7_SFX 431 CreateOutArchive(unsigned formatIndex,CMyComPtr<IOutArchive> & archive)432 HRESULT CreateOutArchive(unsigned formatIndex, CMyComPtr<IOutArchive> &archive) const 433 { 434 const CArcInfoEx &ai = Formats[formatIndex]; 435 #ifdef Z7_EXTERNAL_CODECS 436 if (ai.LibIndex < 0) 437 #endif 438 { 439 COM_TRY_BEGIN 440 archive = ai.CreateOutArchive(); 441 return S_OK; 442 COM_TRY_END 443 } 444 445 #ifdef Z7_EXTERNAL_CODECS 446 return CreateArchiveHandler(ai, true, (void **)&archive); 447 #endif 448 } 449 FindOutFormatFromName(const UString & name)450 int FindOutFormatFromName(const UString &name) const 451 { 452 FOR_VECTOR (i, Formats) 453 { 454 const CArcInfoEx &arc = Formats[i]; 455 if (!arc.UpdateEnabled) 456 continue; 457 if (arc.Name.IsEqualTo_NoCase(name)) 458 return (int)i; 459 } 460 return -1; 461 } 462 463 void Get_CodecsInfoUser_Vector(CObjectVector<CCodecInfoUser> &v); 464 465 #endif // Z7_SFX 466 }; 467 468 #ifdef Z7_EXTERNAL_CODECS 469 #define CREATE_CODECS_OBJECT \ 470 CCodecs *codecs = new CCodecs; \ 471 CExternalCodecs _externalCodecs; \ 472 _externalCodecs.GetCodecs = codecs; \ 473 _externalCodecs.GetHashers = codecs; \ 474 CCodecs::CReleaser codecsReleaser; \ 475 codecsReleaser.Set(codecs); 476 #else 477 #define CREATE_CODECS_OBJECT \ 478 CCodecs *codecs = new CCodecs; \ 479 CMyComPtr<IUnknown> _codecsRef = codecs; 480 #endif 481 482 #endif 483