• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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