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 100 Func_CreateInArchive CreateInArchive; 101 Func_IsArc IsArcFunc; 102 103 UString Name; 104 CObjectVector<CArcExtInfo> Exts; 105 106 #ifndef _SFX 107 Func_CreateOutArchive CreateOutArchive; 108 bool UpdateEnabled; 109 bool NewInterface; 110 // UInt32 Version; 111 UInt32 SignatureOffset; 112 CObjectVector<CByteBuffer> Signatures; 113 #ifdef NEW_FOLDER_INTERFACE 114 UStringVector AssociateExts; 115 #endif 116 #endif 117 118 #ifdef EXTERNAL_CODECS 119 int LibIndex; 120 UInt32 FormatIndex; 121 CLSID ClassID; 122 #endif 123 CompareCArcInfoEx124 int Compare(const CArcInfoEx &a) const 125 { 126 int res = Name.Compare(a.Name); 127 if (res != 0) 128 return res; 129 #ifdef EXTERNAL_CODECS 130 return MyCompare(LibIndex, a.LibIndex); 131 #else 132 return 0; 133 #endif 134 /* 135 if (LibIndex < a.LibIndex) return -1; 136 if (LibIndex > a.LibIndex) return 1; 137 return 0; 138 */ 139 } 140 Flags_KeepNameCArcInfoEx141 bool Flags_KeepName() const { return (Flags & NArcInfoFlags::kKeepName) != 0; } Flags_FindSignatureCArcInfoEx142 bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; } 143 Flags_AltStreamsCArcInfoEx144 bool Flags_AltStreams() const { return (Flags & NArcInfoFlags::kAltStreams) != 0; } Flags_NtSecureCArcInfoEx145 bool Flags_NtSecure() const { return (Flags & NArcInfoFlags::kNtSecure) != 0; } Flags_SymLinksCArcInfoEx146 bool Flags_SymLinks() const { return (Flags & NArcInfoFlags::kSymLinks) != 0; } Flags_HardLinksCArcInfoEx147 bool Flags_HardLinks() const { return (Flags & NArcInfoFlags::kHardLinks) != 0; } 148 Flags_UseGlobalOffsetCArcInfoEx149 bool Flags_UseGlobalOffset() const { return (Flags & NArcInfoFlags::kUseGlobalOffset) != 0; } Flags_StartOpenCArcInfoEx150 bool Flags_StartOpen() const { return (Flags & NArcInfoFlags::kStartOpen) != 0; } Flags_BackwardOpenCArcInfoEx151 bool Flags_BackwardOpen() const { return (Flags & NArcInfoFlags::kBackwardOpen) != 0; } Flags_PreArcCArcInfoEx152 bool Flags_PreArc() const { return (Flags & NArcInfoFlags::kPreArc) != 0; } Flags_PureStartOpenCArcInfoEx153 bool Flags_PureStartOpen() const { return (Flags & NArcInfoFlags::kPureStartOpen) != 0; } Flags_ByExtOnlyOpenCArcInfoEx154 bool Flags_ByExtOnlyOpen() const { return (Flags & NArcInfoFlags::kByExtOnlyOpen) != 0; } Flags_HashHandlerCArcInfoEx155 bool Flags_HashHandler() const { return (Flags & NArcInfoFlags::kHashHandler) != 0; } 156 GetMainExtCArcInfoEx157 UString GetMainExt() const 158 { 159 if (Exts.IsEmpty()) 160 return UString(); 161 return Exts[0].Ext; 162 } 163 int FindExtension(const UString &ext) const; 164 165 /* 166 UString GetAllExtensions() const 167 { 168 UString s; 169 for (int i = 0; i < Exts.Size(); i++) 170 { 171 if (i > 0) 172 s += ' '; 173 s += Exts[i].Ext; 174 } 175 return s; 176 } 177 */ 178 179 void AddExts(const UString &ext, const UString &addExt); 180 IsSplitCArcInfoEx181 bool IsSplit() const { return StringsAreEqualNoCase_Ascii(Name, "Split"); } 182 // bool IsRar() const { return StringsAreEqualNoCase_Ascii(Name, "Rar"); } 183 CArcInfoExCArcInfoEx184 CArcInfoEx(): 185 Flags(0), 186 CreateInArchive(NULL), 187 IsArcFunc(NULL) 188 #ifndef _SFX 189 , CreateOutArchive(NULL) 190 , UpdateEnabled(false) 191 , NewInterface(false) 192 // , Version(0) 193 , SignatureOffset(0) 194 #endif 195 #ifdef EXTERNAL_CODECS 196 , LibIndex(-1) 197 #endif 198 {} 199 }; 200 201 #ifdef NEW_FOLDER_INTERFACE 202 203 struct CCodecIcons 204 { 205 struct CIconPair 206 { 207 UString Ext; 208 int IconIndex; 209 }; 210 CObjectVector<CIconPair> IconPairs; 211 212 void LoadIcons(HMODULE m); 213 bool FindIconIndex(const UString &ext, int &iconIndex) const; 214 }; 215 216 #endif 217 218 #ifdef EXTERNAL_CODECS 219 220 struct CCodecLib 221 #ifdef NEW_FOLDER_INTERFACE 222 : public CCodecIcons 223 #endif 224 { 225 NWindows::NDLL::CLibrary Lib; 226 FString Path; 227 228 Func_CreateObject CreateObject; 229 Func_GetMethodProperty GetMethodProperty; 230 Func_CreateDecoder CreateDecoder; 231 Func_CreateEncoder CreateEncoder; 232 Func_SetCodecs SetCodecs; 233 234 CMyComPtr<IHashers> ComHashers; 235 236 #ifdef NEW_FOLDER_INTERFACE LoadIconsCCodecLib237 void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); } 238 #endif 239 CCodecLibCCodecLib240 CCodecLib(): 241 CreateObject(NULL), 242 GetMethodProperty(NULL), 243 CreateDecoder(NULL), 244 CreateEncoder(NULL), 245 SetCodecs(NULL) 246 {} 247 }; 248 249 #endif 250 251 struct CCodecError 252 { 253 FString Path; 254 HRESULT ErrorCode; 255 AString Message; CCodecErrorCCodecError256 CCodecError(): ErrorCode(0) {} 257 }; 258 259 260 struct CCodecInfoUser 261 { 262 // unsigned LibIndex; 263 // UInt32 CodecIndex; 264 // UInt64 id; 265 bool EncoderIsAssigned; 266 bool DecoderIsAssigned; 267 bool IsFilter; 268 bool IsFilter_Assigned; 269 UInt32 NumStreams; 270 AString Name; 271 }; 272 273 274 class CCodecs: 275 #ifdef EXTERNAL_CODECS 276 public ICompressCodecsInfo, 277 public IHashers, 278 #else 279 public IUnknown, 280 #endif 281 public CMyUnknownImp 282 { 283 CLASS_NO_COPY(CCodecs); 284 public: 285 #ifdef EXTERNAL_CODECS 286 287 CObjectVector<CCodecLib> Libs; 288 FString MainDll_ErrorPath; 289 CObjectVector<CCodecError> Errors; 290 291 void AddLastError(const FString &path); 292 void CloseLibs(); 293 294 class CReleaser 295 { 296 CLASS_NO_COPY(CReleaser); 297 298 /* CCodecsReleaser object releases CCodecs links. 299 1) CCodecs is COM object that is deleted when all links to that object will be released/ 300 2) CCodecs::Libs[i] can hold (ICompressCodecsInfo *) link to CCodecs object itself. 301 To break that reference loop, we must close all CCodecs::Libs in CCodecsReleaser desttructor. */ 302 303 CCodecs *_codecs; 304 305 public: CReleaser()306 CReleaser(): _codecs(NULL) {} Set(CCodecs * codecs)307 void Set(CCodecs *codecs) { _codecs = codecs; } ~CReleaser()308 ~CReleaser() { if (_codecs) _codecs->CloseLibs(); } 309 }; 310 311 bool NeedSetLibCodecs; // = false, if we don't need to set codecs for archive handler via ISetCompressCodecsInfo 312 313 HRESULT LoadCodecs(); 314 HRESULT LoadFormats(); 315 HRESULT LoadDll(const FString &path, bool needCheckDll, bool *loadedOK = NULL); 316 HRESULT LoadDllsFromFolder(const FString &folderPrefix); 317 CreateArchiveHandler(const CArcInfoEx & ai,bool outHandler,void ** archive)318 HRESULT CreateArchiveHandler(const CArcInfoEx &ai, bool outHandler, void **archive) const 319 { 320 return Libs[(unsigned)ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive); 321 } 322 323 #endif 324 325 #ifdef NEW_FOLDER_INTERFACE 326 CCodecIcons InternalIcons; 327 #endif 328 329 CObjectVector<CArcInfoEx> Formats; 330 331 #ifdef EXTERNAL_CODECS 332 CRecordVector<CDllCodecInfo> Codecs; 333 CRecordVector<CDllHasherInfo> Hashers; 334 #endif 335 336 bool CaseSensitiveChange; 337 bool CaseSensitive; 338 CCodecs()339 CCodecs(): 340 #ifdef EXTERNAL_CODECS 341 NeedSetLibCodecs(true), 342 #endif 343 CaseSensitiveChange(false), 344 CaseSensitive(false) 345 {} 346 ~CCodecs()347 ~CCodecs() 348 { 349 // OutputDebugStringA("~CCodecs"); 350 } 351 GetFormatNamePtr(int formatIndex)352 const wchar_t *GetFormatNamePtr(int formatIndex) const 353 { 354 return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[(unsigned)formatIndex].Name; 355 } 356 357 HRESULT Load(); 358 359 #ifndef _SFX 360 int FindFormatForArchiveName(const UString &arcPath) const; 361 int FindFormatForExtension(const UString &ext) const; 362 int FindFormatForArchiveType(const UString &arcType) const; 363 bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const; 364 #endif 365 366 #ifdef EXTERNAL_CODECS 367 368 MY_UNKNOWN_IMP2(ICompressCodecsInfo, IHashers) 369 370 STDMETHOD(GetNumMethods)(UInt32 *numMethods); 371 STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); 372 STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder); 373 STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder); 374 375 STDMETHOD_(UInt32, GetNumHashers)(); 376 STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value); 377 STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher); 378 379 #else 380 381 MY_UNKNOWN_IMP 382 383 #endif // EXTERNAL_CODECS 384 385 386 #ifdef EXTERNAL_CODECS 387 388 int GetCodec_LibIndex(UInt32 index) const; 389 bool GetCodec_DecoderIsAssigned(UInt32 index) const; 390 bool GetCodec_EncoderIsAssigned(UInt32 index) const; 391 bool GetCodec_IsFilter(UInt32 index, bool &isAssigned) const; 392 UInt32 GetCodec_NumStreams(UInt32 index); 393 HRESULT GetCodec_Id(UInt32 index, UInt64 &id); 394 AString GetCodec_Name(UInt32 index); 395 396 int GetHasherLibIndex(UInt32 index); 397 UInt64 GetHasherId(UInt32 index); 398 AString GetHasherName(UInt32 index); 399 UInt32 GetHasherDigestSize(UInt32 index); 400 401 void GetCodecsErrorMessage(UString &s); 402 403 #endif 404 CreateInArchive(unsigned formatIndex,CMyComPtr<IInArchive> & archive)405 HRESULT CreateInArchive(unsigned formatIndex, CMyComPtr<IInArchive> &archive) const 406 { 407 const CArcInfoEx &ai = Formats[formatIndex]; 408 #ifdef EXTERNAL_CODECS 409 if (ai.LibIndex < 0) 410 #endif 411 { 412 COM_TRY_BEGIN 413 archive = ai.CreateInArchive(); 414 return S_OK; 415 COM_TRY_END 416 } 417 #ifdef EXTERNAL_CODECS 418 return CreateArchiveHandler(ai, false, (void **)&archive); 419 #endif 420 } 421 422 #ifndef _SFX 423 CreateOutArchive(unsigned formatIndex,CMyComPtr<IOutArchive> & archive)424 HRESULT CreateOutArchive(unsigned formatIndex, CMyComPtr<IOutArchive> &archive) const 425 { 426 const CArcInfoEx &ai = Formats[formatIndex]; 427 #ifdef EXTERNAL_CODECS 428 if (ai.LibIndex < 0) 429 #endif 430 { 431 COM_TRY_BEGIN 432 archive = ai.CreateOutArchive(); 433 return S_OK; 434 COM_TRY_END 435 } 436 437 #ifdef EXTERNAL_CODECS 438 return CreateArchiveHandler(ai, true, (void **)&archive); 439 #endif 440 } 441 FindOutFormatFromName(const UString & name)442 int FindOutFormatFromName(const UString &name) const 443 { 444 FOR_VECTOR (i, Formats) 445 { 446 const CArcInfoEx &arc = Formats[i]; 447 if (!arc.UpdateEnabled) 448 continue; 449 if (arc.Name.IsEqualTo_NoCase(name)) 450 return (int)i; 451 } 452 return -1; 453 } 454 455 void Get_CodecsInfoUser_Vector(CObjectVector<CCodecInfoUser> &v); 456 457 #endif // _SFX 458 }; 459 460 #ifdef EXTERNAL_CODECS 461 #define CREATE_CODECS_OBJECT \ 462 CCodecs *codecs = new CCodecs; \ 463 CExternalCodecs __externalCodecs; \ 464 __externalCodecs.GetCodecs = codecs; \ 465 __externalCodecs.GetHashers = codecs; \ 466 CCodecs::CReleaser codecsReleaser; \ 467 codecsReleaser.Set(codecs); 468 #else 469 #define CREATE_CODECS_OBJECT \ 470 CCodecs *codecs = new CCodecs; \ 471 CMyComPtr<IUnknown> __codecsRef = codecs; 472 #endif 473 474 #endif 475