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