Home | History | Annotate | Download | only in Common
      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   CLSID Encoder;
     72   CLSID Decoder;
     73 };
     74 
     75 struct CDllHasherInfo
     76 {
     77   unsigned LibIndex;
     78   UInt32 HasherIndex;
     79 };
     80 
     81 #endif
     82 
     83 struct CArcExtInfo
     84 {
     85   UString Ext;
     86   UString AddExt;
     87 
     88   CArcExtInfo() {}
     89   CArcExtInfo(const UString &ext): Ext(ext) {}
     90   CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {}
     91 };
     92 
     93 
     94 struct CArcInfoEx
     95 {
     96   UInt32 Flags;
     97 
     98   Func_CreateInArchive CreateInArchive;
     99   Func_IsArc IsArcFunc;
    100 
    101   UString Name;
    102   CObjectVector<CArcExtInfo> Exts;
    103 
    104   #ifndef _SFX
    105     Func_CreateOutArchive CreateOutArchive;
    106     bool UpdateEnabled;
    107     bool NewInterface;
    108     // UInt32 Version;
    109     UInt32 SignatureOffset;
    110     CObjectVector<CByteBuffer> Signatures;
    111     #ifdef NEW_FOLDER_INTERFACE
    112       UStringVector AssociateExts;
    113     #endif
    114   #endif
    115 
    116   #ifdef EXTERNAL_CODECS
    117     int LibIndex;
    118     UInt32 FormatIndex;
    119     CLSID ClassID;
    120   #endif
    121 
    122   bool Flags_KeepName() const { return (Flags & NArcInfoFlags::kKeepName) != 0; }
    123   bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; }
    124 
    125   bool Flags_AltStreams() const { return (Flags & NArcInfoFlags::kAltStreams) != 0; }
    126   bool Flags_NtSecure() const { return (Flags & NArcInfoFlags::kNtSecure) != 0; }
    127   bool Flags_SymLinks() const { return (Flags & NArcInfoFlags::kSymLinks) != 0; }
    128   bool Flags_HardLinks() const { return (Flags & NArcInfoFlags::kHardLinks) != 0; }
    129 
    130   bool Flags_UseGlobalOffset() const { return (Flags & NArcInfoFlags::kUseGlobalOffset) != 0; }
    131   bool Flags_StartOpen() const { return (Flags & NArcInfoFlags::kStartOpen) != 0; }
    132   bool Flags_BackwardOpen() const { return (Flags & NArcInfoFlags::kBackwardOpen) != 0; }
    133   bool Flags_PreArc() const { return (Flags & NArcInfoFlags::kPreArc) != 0; }
    134   bool Flags_PureStartOpen() const { return (Flags & NArcInfoFlags::kPureStartOpen) != 0; }
    135 
    136   UString GetMainExt() const
    137   {
    138     if (Exts.IsEmpty())
    139       return UString();
    140     return Exts[0].Ext;
    141   }
    142   int FindExtension(const UString &ext) const;
    143 
    144   /*
    145   UString GetAllExtensions() const
    146   {
    147     UString s;
    148     for (int i = 0; i < Exts.Size(); i++)
    149     {
    150       if (i > 0)
    151         s += ' ';
    152       s += Exts[i].Ext;
    153     }
    154     return s;
    155   }
    156   */
    157 
    158   void AddExts(const UString &ext, const UString &addExt);
    159 
    160   bool IsSplit() const { return StringsAreEqualNoCase_Ascii(Name, "Split"); }
    161   // bool IsRar() const { return StringsAreEqualNoCase_Ascii(Name, "Rar"); }
    162 
    163   CArcInfoEx():
    164       Flags(0),
    165       CreateInArchive(NULL),
    166       IsArcFunc(NULL)
    167       #ifndef _SFX
    168       , CreateOutArchive(NULL)
    169       , UpdateEnabled(false)
    170       , NewInterface(false)
    171       // , Version(0)
    172       , SignatureOffset(0)
    173       #endif
    174       #ifdef EXTERNAL_CODECS
    175       , LibIndex(-1)
    176       #endif
    177   {}
    178 };
    179 
    180 #ifdef NEW_FOLDER_INTERFACE
    181 
    182 struct CCodecIcons
    183 {
    184   struct CIconPair
    185   {
    186     UString Ext;
    187     int IconIndex;
    188   };
    189   CObjectVector<CIconPair> IconPairs;
    190 
    191   void LoadIcons(HMODULE m);
    192   bool FindIconIndex(const UString &ext, int &iconIndex) const;
    193 };
    194 
    195 #endif
    196 
    197 #ifdef EXTERNAL_CODECS
    198 
    199 struct CCodecLib
    200   #ifdef NEW_FOLDER_INTERFACE
    201     : public CCodecIcons
    202   #endif
    203 {
    204   NWindows::NDLL::CLibrary Lib;
    205   FString Path;
    206 
    207   Func_CreateObject CreateObject;
    208   Func_GetMethodProperty GetMethodProperty;
    209   Func_CreateDecoder CreateDecoder;
    210   Func_CreateEncoder CreateEncoder;
    211   Func_SetCodecs SetCodecs;
    212 
    213   CMyComPtr<IHashers> ComHashers;
    214 
    215   #ifdef NEW_FOLDER_INTERFACE
    216   void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); }
    217   #endif
    218 
    219   CCodecLib():
    220       CreateObject(NULL),
    221       GetMethodProperty(NULL),
    222       CreateDecoder(NULL),
    223       CreateEncoder(NULL),
    224       SetCodecs(NULL)
    225       {}
    226 };
    227 
    228 #endif
    229 
    230 
    231 class CCodecs:
    232   #ifdef EXTERNAL_CODECS
    233     public ICompressCodecsInfo,
    234     public IHashers,
    235   #else
    236     public IUnknown,
    237   #endif
    238   public CMyUnknownImp
    239 {
    240   CLASS_NO_COPY(CCodecs);
    241 public:
    242   #ifdef EXTERNAL_CODECS
    243 
    244   CObjectVector<CCodecLib> Libs;
    245   FString MainDll_ErrorPath;
    246 
    247   void CloseLibs();
    248 
    249   class CReleaser
    250   {
    251     CLASS_NO_COPY(CReleaser);
    252 
    253     /* CCodecsReleaser object releases CCodecs links.
    254          1) CCodecs is COM object that is deleted when all links to that object will be released/
    255          2) CCodecs::Libs[i] can hold (ICompressCodecsInfo *) link to CCodecs object itself.
    256        To break that reference loop, we must close all CCodecs::Libs in CCodecsReleaser desttructor. */
    257 
    258     CCodecs *_codecs;
    259 
    260     public:
    261     CReleaser(): _codecs(NULL) {}
    262     void Set(CCodecs *codecs) { _codecs = codecs; }
    263     ~CReleaser() { if (_codecs) _codecs->CloseLibs(); }
    264   };
    265 
    266   bool NeedSetLibCodecs; // = false, if we don't need to set codecs for archive handler via ISetCompressCodecsInfo
    267 
    268   HRESULT LoadCodecs();
    269   HRESULT LoadFormats();
    270   HRESULT LoadDll(const FString &path, bool needCheckDll, bool *loadedOK = NULL);
    271   HRESULT LoadDllsFromFolder(const FString &folderPrefix);
    272 
    273   HRESULT CreateArchiveHandler(const CArcInfoEx &ai, bool outHandler, void **archive) const
    274   {
    275     return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive);
    276   }
    277 
    278   #endif
    279 
    280   #ifdef NEW_FOLDER_INTERFACE
    281   CCodecIcons InternalIcons;
    282   #endif
    283 
    284   CObjectVector<CArcInfoEx> Formats;
    285 
    286   #ifdef EXTERNAL_CODECS
    287   CRecordVector<CDllCodecInfo> Codecs;
    288   CRecordVector<CDllHasherInfo> Hashers;
    289   #endif
    290 
    291   bool CaseSensitiveChange;
    292   bool CaseSensitive;
    293 
    294   CCodecs():
    295       #ifdef EXTERNAL_CODECS
    296       NeedSetLibCodecs(true),
    297       #endif
    298       CaseSensitiveChange(false),
    299       CaseSensitive(false)
    300       {}
    301 
    302   ~CCodecs()
    303   {
    304     // OutputDebugStringA("~CCodecs");
    305   }
    306 
    307   const wchar_t *GetFormatNamePtr(int formatIndex) const
    308   {
    309     return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[formatIndex].Name;
    310   }
    311 
    312   HRESULT Load();
    313 
    314   #ifndef _SFX
    315   int FindFormatForArchiveName(const UString &arcPath) const;
    316   int FindFormatForExtension(const UString &ext) const;
    317   int FindFormatForArchiveType(const UString &arcType) const;
    318   bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const;
    319   #endif
    320 
    321   #ifdef EXTERNAL_CODECS
    322 
    323   MY_UNKNOWN_IMP2(ICompressCodecsInfo, IHashers)
    324 
    325   STDMETHOD(GetNumMethods)(UInt32 *numMethods);
    326   STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
    327   STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder);
    328   STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder);
    329 
    330   STDMETHOD_(UInt32, GetNumHashers)();
    331   STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value);
    332   STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher);
    333 
    334   #else
    335 
    336   MY_UNKNOWN_IMP
    337 
    338   #endif // EXTERNAL_CODECS
    339 
    340 
    341   #ifdef EXTERNAL_CODECS
    342 
    343   int GetCodec_LibIndex(UInt32 index) const;
    344   bool GetCodec_DecoderIsAssigned(UInt32 index) const;
    345   bool GetCodec_EncoderIsAssigned(UInt32 index) const;
    346   UInt32 GetCodec_NumStreams(UInt32 index);
    347   HRESULT GetCodec_Id(UInt32 index, UInt64 &id);
    348   AString GetCodec_Name(UInt32 index);
    349 
    350   int GetHasherLibIndex(UInt32 index);
    351   UInt64 GetHasherId(UInt32 index);
    352   AString GetHasherName(UInt32 index);
    353   UInt32 GetHasherDigestSize(UInt32 index);
    354 
    355   #endif
    356 
    357   HRESULT CreateInArchive(unsigned formatIndex, CMyComPtr<IInArchive> &archive) const
    358   {
    359     const CArcInfoEx &ai = Formats[formatIndex];
    360     #ifdef EXTERNAL_CODECS
    361     if (ai.LibIndex < 0)
    362     #endif
    363     {
    364       COM_TRY_BEGIN
    365       archive = ai.CreateInArchive();
    366       return S_OK;
    367       COM_TRY_END
    368     }
    369     #ifdef EXTERNAL_CODECS
    370     return CreateArchiveHandler(ai, false, (void **)&archive);
    371     #endif
    372   }
    373 
    374   #ifndef _SFX
    375 
    376   HRESULT CreateOutArchive(unsigned formatIndex, CMyComPtr<IOutArchive> &archive) const
    377   {
    378     const CArcInfoEx &ai = Formats[formatIndex];
    379     #ifdef EXTERNAL_CODECS
    380     if (ai.LibIndex < 0)
    381     #endif
    382     {
    383       COM_TRY_BEGIN
    384       archive = ai.CreateOutArchive();
    385       return S_OK;
    386       COM_TRY_END
    387     }
    388 
    389     #ifdef EXTERNAL_CODECS
    390     return CreateArchiveHandler(ai, true, (void **)&archive);
    391     #endif
    392   }
    393 
    394   int FindOutFormatFromName(const UString &name) const
    395   {
    396     FOR_VECTOR (i, Formats)
    397     {
    398       const CArcInfoEx &arc = Formats[i];
    399       if (!arc.UpdateEnabled)
    400         continue;
    401       if (arc.Name.IsEqualTo_NoCase(name))
    402         return i;
    403     }
    404     return -1;
    405   }
    406 
    407   #endif // _SFX
    408 };
    409 
    410 #ifdef EXTERNAL_CODECS
    411   #define CREATE_CODECS_OBJECT \
    412     CCodecs *codecs = new CCodecs; \
    413     CExternalCodecs __externalCodecs; \
    414     __externalCodecs.GetCodecs = codecs; \
    415     __externalCodecs.GetHashers = codecs; \
    416     CCodecs::CReleaser codecsReleaser; \
    417     codecsReleaser.Set(codecs);
    418 #else
    419   #define CREATE_CODECS_OBJECT \
    420     CCodecs *codecs = new CCodecs; \
    421     CMyComPtr<IUnknown> __codecsRef = codecs;
    422 #endif
    423 
    424 #endif
    425