425 lines
10 KiB
C++
425 lines
10 KiB
C++
// LoadCodecs.h
|
|
|
|
#ifndef __LOAD_CODECS_H
|
|
#define __LOAD_CODECS_H
|
|
|
|
/*
|
|
Client application uses LoadCodecs.* to load plugins to
|
|
CCodecs object, that contains 3 lists of plugins:
|
|
1) Formats - internal and external archive handlers
|
|
2) Codecs - external codecs
|
|
3) Hashers - external hashers
|
|
|
|
EXTERNAL_CODECS
|
|
---------------
|
|
|
|
if EXTERNAL_CODECS is defined, then the code tries to load external
|
|
plugins from DLL files (shared libraries).
|
|
|
|
There are two types of executables in 7-Zip:
|
|
|
|
1) Executable that uses external plugins must be compiled
|
|
with EXTERNAL_CODECS defined:
|
|
- 7z.exe, 7zG.exe, 7zFM.exe
|
|
|
|
Note: EXTERNAL_CODECS is used also in CPP/7zip/Common/CreateCoder.h
|
|
that code is used in plugin module (7z.dll).
|
|
|
|
2) Standalone modules are compiled without EXTERNAL_CODECS:
|
|
- SFX modules: 7z.sfx, 7zCon.sfx
|
|
- standalone versions of console 7-Zip: 7za.exe, 7zr.exe
|
|
|
|
if EXTERNAL_CODECS is defined, CCodecs class implements interfaces:
|
|
- ICompressCodecsInfo : for Codecs
|
|
- IHashers : for Hashers
|
|
|
|
The client application can send CCodecs object to each plugin module.
|
|
And plugin module can use ICompressCodecsInfo or IHashers interface to access
|
|
another plugins.
|
|
|
|
There are 2 ways to send (ICompressCodecsInfo * compressCodecsInfo) to plugin
|
|
1) for old versions:
|
|
a) request ISetCompressCodecsInfo from created archive handler.
|
|
b) call ISetCompressCodecsInfo::SetCompressCodecsInfo(compressCodecsInfo)
|
|
2) for new versions:
|
|
a) request "SetCodecs" function from DLL file
|
|
b) call SetCodecs(compressCodecsInfo) function from DLL file
|
|
*/
|
|
|
|
#include "../../../Common/MyBuffer.h"
|
|
#include "../../../Common/MyCom.h"
|
|
#include "../../../Common/MyString.h"
|
|
#include "../../../Common/ComTry.h"
|
|
|
|
#ifdef EXTERNAL_CODECS
|
|
#include "../../../Windows/DLL.h"
|
|
#endif
|
|
|
|
#include "../../ICoder.h"
|
|
|
|
#include "../../Archive/IArchive.h"
|
|
|
|
|
|
#ifdef EXTERNAL_CODECS
|
|
|
|
struct CDllCodecInfo
|
|
{
|
|
unsigned LibIndex;
|
|
UInt32 CodecIndex;
|
|
bool EncoderIsAssigned;
|
|
bool DecoderIsAssigned;
|
|
CLSID Encoder;
|
|
CLSID Decoder;
|
|
};
|
|
|
|
struct CDllHasherInfo
|
|
{
|
|
unsigned LibIndex;
|
|
UInt32 HasherIndex;
|
|
};
|
|
|
|
#endif
|
|
|
|
struct CArcExtInfo
|
|
{
|
|
UString Ext;
|
|
UString AddExt;
|
|
|
|
CArcExtInfo() {}
|
|
CArcExtInfo(const UString &ext): Ext(ext) {}
|
|
CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {}
|
|
};
|
|
|
|
|
|
struct CArcInfoEx
|
|
{
|
|
UInt32 Flags;
|
|
|
|
Func_CreateInArchive CreateInArchive;
|
|
Func_IsArc IsArcFunc;
|
|
|
|
UString Name;
|
|
CObjectVector<CArcExtInfo> Exts;
|
|
|
|
#ifndef _SFX
|
|
Func_CreateOutArchive CreateOutArchive;
|
|
bool UpdateEnabled;
|
|
bool NewInterface;
|
|
// UInt32 Version;
|
|
UInt32 SignatureOffset;
|
|
CObjectVector<CByteBuffer> Signatures;
|
|
#ifdef NEW_FOLDER_INTERFACE
|
|
UStringVector AssociateExts;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef EXTERNAL_CODECS
|
|
int LibIndex;
|
|
UInt32 FormatIndex;
|
|
CLSID ClassID;
|
|
#endif
|
|
|
|
bool Flags_KeepName() const { return (Flags & NArcInfoFlags::kKeepName) != 0; }
|
|
bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; }
|
|
|
|
bool Flags_AltStreams() const { return (Flags & NArcInfoFlags::kAltStreams) != 0; }
|
|
bool Flags_NtSecure() const { return (Flags & NArcInfoFlags::kNtSecure) != 0; }
|
|
bool Flags_SymLinks() const { return (Flags & NArcInfoFlags::kSymLinks) != 0; }
|
|
bool Flags_HardLinks() const { return (Flags & NArcInfoFlags::kHardLinks) != 0; }
|
|
|
|
bool Flags_UseGlobalOffset() const { return (Flags & NArcInfoFlags::kUseGlobalOffset) != 0; }
|
|
bool Flags_StartOpen() const { return (Flags & NArcInfoFlags::kStartOpen) != 0; }
|
|
bool Flags_BackwardOpen() const { return (Flags & NArcInfoFlags::kBackwardOpen) != 0; }
|
|
bool Flags_PreArc() const { return (Flags & NArcInfoFlags::kPreArc) != 0; }
|
|
bool Flags_PureStartOpen() const { return (Flags & NArcInfoFlags::kPureStartOpen) != 0; }
|
|
|
|
UString GetMainExt() const
|
|
{
|
|
if (Exts.IsEmpty())
|
|
return UString();
|
|
return Exts[0].Ext;
|
|
}
|
|
int FindExtension(const UString &ext) const;
|
|
|
|
/*
|
|
UString GetAllExtensions() const
|
|
{
|
|
UString s;
|
|
for (int i = 0; i < Exts.Size(); i++)
|
|
{
|
|
if (i > 0)
|
|
s += ' ';
|
|
s += Exts[i].Ext;
|
|
}
|
|
return s;
|
|
}
|
|
*/
|
|
|
|
void AddExts(const UString &ext, const UString &addExt);
|
|
|
|
bool IsSplit() const { return StringsAreEqualNoCase_Ascii(Name, "Split"); }
|
|
// bool IsRar() const { return StringsAreEqualNoCase_Ascii(Name, "Rar"); }
|
|
|
|
CArcInfoEx():
|
|
Flags(0),
|
|
CreateInArchive(NULL),
|
|
IsArcFunc(NULL)
|
|
#ifndef _SFX
|
|
, CreateOutArchive(NULL)
|
|
, UpdateEnabled(false)
|
|
, NewInterface(false)
|
|
// , Version(0)
|
|
, SignatureOffset(0)
|
|
#endif
|
|
#ifdef EXTERNAL_CODECS
|
|
, LibIndex(-1)
|
|
#endif
|
|
{}
|
|
};
|
|
|
|
#ifdef NEW_FOLDER_INTERFACE
|
|
|
|
struct CCodecIcons
|
|
{
|
|
struct CIconPair
|
|
{
|
|
UString Ext;
|
|
int IconIndex;
|
|
};
|
|
CObjectVector<CIconPair> IconPairs;
|
|
|
|
void LoadIcons(HMODULE m);
|
|
bool FindIconIndex(const UString &ext, int &iconIndex) const;
|
|
};
|
|
|
|
#endif
|
|
|
|
#ifdef EXTERNAL_CODECS
|
|
|
|
struct CCodecLib
|
|
#ifdef NEW_FOLDER_INTERFACE
|
|
: public CCodecIcons
|
|
#endif
|
|
{
|
|
NWindows::NDLL::CLibrary Lib;
|
|
FString Path;
|
|
|
|
Func_CreateObject CreateObject;
|
|
Func_GetMethodProperty GetMethodProperty;
|
|
Func_CreateDecoder CreateDecoder;
|
|
Func_CreateEncoder CreateEncoder;
|
|
Func_SetCodecs SetCodecs;
|
|
|
|
CMyComPtr<IHashers> ComHashers;
|
|
|
|
#ifdef NEW_FOLDER_INTERFACE
|
|
void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); }
|
|
#endif
|
|
|
|
CCodecLib():
|
|
CreateObject(NULL),
|
|
GetMethodProperty(NULL),
|
|
CreateDecoder(NULL),
|
|
CreateEncoder(NULL),
|
|
SetCodecs(NULL)
|
|
{}
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
class CCodecs:
|
|
#ifdef EXTERNAL_CODECS
|
|
public ICompressCodecsInfo,
|
|
public IHashers,
|
|
#else
|
|
public IUnknown,
|
|
#endif
|
|
public CMyUnknownImp
|
|
{
|
|
CLASS_NO_COPY(CCodecs);
|
|
public:
|
|
#ifdef EXTERNAL_CODECS
|
|
|
|
CObjectVector<CCodecLib> Libs;
|
|
FString MainDll_ErrorPath;
|
|
|
|
void CloseLibs();
|
|
|
|
class CReleaser
|
|
{
|
|
CLASS_NO_COPY(CReleaser);
|
|
|
|
/* CCodecsReleaser object releases CCodecs links.
|
|
1) CCodecs is COM object that is deleted when all links to that object will be released/
|
|
2) CCodecs::Libs[i] can hold (ICompressCodecsInfo *) link to CCodecs object itself.
|
|
To break that reference loop, we must close all CCodecs::Libs in CCodecsReleaser desttructor. */
|
|
|
|
CCodecs *_codecs;
|
|
|
|
public:
|
|
CReleaser(): _codecs(NULL) {}
|
|
void Set(CCodecs *codecs) { _codecs = codecs; }
|
|
~CReleaser() { if (_codecs) _codecs->CloseLibs(); }
|
|
};
|
|
|
|
bool NeedSetLibCodecs; // = false, if we don't need to set codecs for archive handler via ISetCompressCodecsInfo
|
|
|
|
HRESULT LoadCodecs();
|
|
HRESULT LoadFormats();
|
|
HRESULT LoadDll(const FString &path, bool needCheckDll, bool *loadedOK = NULL);
|
|
HRESULT LoadDllsFromFolder(const FString &folderPrefix);
|
|
|
|
HRESULT CreateArchiveHandler(const CArcInfoEx &ai, bool outHandler, void **archive) const
|
|
{
|
|
return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive);
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef NEW_FOLDER_INTERFACE
|
|
CCodecIcons InternalIcons;
|
|
#endif
|
|
|
|
CObjectVector<CArcInfoEx> Formats;
|
|
|
|
#ifdef EXTERNAL_CODECS
|
|
CRecordVector<CDllCodecInfo> Codecs;
|
|
CRecordVector<CDllHasherInfo> Hashers;
|
|
#endif
|
|
|
|
bool CaseSensitiveChange;
|
|
bool CaseSensitive;
|
|
|
|
CCodecs():
|
|
#ifdef EXTERNAL_CODECS
|
|
NeedSetLibCodecs(true),
|
|
#endif
|
|
CaseSensitiveChange(false),
|
|
CaseSensitive(false)
|
|
{}
|
|
|
|
~CCodecs()
|
|
{
|
|
// OutputDebugStringA("~CCodecs");
|
|
}
|
|
|
|
const wchar_t *GetFormatNamePtr(int formatIndex) const
|
|
{
|
|
return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[formatIndex].Name;
|
|
}
|
|
|
|
HRESULT Load();
|
|
|
|
#ifndef _SFX
|
|
int FindFormatForArchiveName(const UString &arcPath) const;
|
|
int FindFormatForExtension(const UString &ext) const;
|
|
int FindFormatForArchiveType(const UString &arcType) const;
|
|
bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const;
|
|
#endif
|
|
|
|
#ifdef EXTERNAL_CODECS
|
|
|
|
MY_UNKNOWN_IMP2(ICompressCodecsInfo, IHashers)
|
|
|
|
STDMETHOD(GetNumMethods)(UInt32 *numMethods);
|
|
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
|
|
STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder);
|
|
STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder);
|
|
|
|
STDMETHOD_(UInt32, GetNumHashers)();
|
|
STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value);
|
|
STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher);
|
|
|
|
#else
|
|
|
|
MY_UNKNOWN_IMP
|
|
|
|
#endif // EXTERNAL_CODECS
|
|
|
|
|
|
#ifdef EXTERNAL_CODECS
|
|
|
|
int GetCodec_LibIndex(UInt32 index) const;
|
|
bool GetCodec_DecoderIsAssigned(UInt32 index) const;
|
|
bool GetCodec_EncoderIsAssigned(UInt32 index) const;
|
|
UInt32 GetCodec_NumStreams(UInt32 index);
|
|
HRESULT GetCodec_Id(UInt32 index, UInt64 &id);
|
|
AString GetCodec_Name(UInt32 index);
|
|
|
|
int GetHasherLibIndex(UInt32 index);
|
|
UInt64 GetHasherId(UInt32 index);
|
|
AString GetHasherName(UInt32 index);
|
|
UInt32 GetHasherDigestSize(UInt32 index);
|
|
|
|
#endif
|
|
|
|
HRESULT CreateInArchive(unsigned formatIndex, CMyComPtr<IInArchive> &archive) const
|
|
{
|
|
const CArcInfoEx &ai = Formats[formatIndex];
|
|
#ifdef EXTERNAL_CODECS
|
|
if (ai.LibIndex < 0)
|
|
#endif
|
|
{
|
|
COM_TRY_BEGIN
|
|
archive = ai.CreateInArchive();
|
|
return S_OK;
|
|
COM_TRY_END
|
|
}
|
|
#ifdef EXTERNAL_CODECS
|
|
return CreateArchiveHandler(ai, false, (void **)&archive);
|
|
#endif
|
|
}
|
|
|
|
#ifndef _SFX
|
|
|
|
HRESULT CreateOutArchive(unsigned formatIndex, CMyComPtr<IOutArchive> &archive) const
|
|
{
|
|
const CArcInfoEx &ai = Formats[formatIndex];
|
|
#ifdef EXTERNAL_CODECS
|
|
if (ai.LibIndex < 0)
|
|
#endif
|
|
{
|
|
COM_TRY_BEGIN
|
|
archive = ai.CreateOutArchive();
|
|
return S_OK;
|
|
COM_TRY_END
|
|
}
|
|
|
|
#ifdef EXTERNAL_CODECS
|
|
return CreateArchiveHandler(ai, true, (void **)&archive);
|
|
#endif
|
|
}
|
|
|
|
int FindOutFormatFromName(const UString &name) const
|
|
{
|
|
FOR_VECTOR (i, Formats)
|
|
{
|
|
const CArcInfoEx &arc = Formats[i];
|
|
if (!arc.UpdateEnabled)
|
|
continue;
|
|
if (arc.Name.IsEqualTo_NoCase(name))
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
#endif // _SFX
|
|
};
|
|
|
|
#ifdef EXTERNAL_CODECS
|
|
#define CREATE_CODECS_OBJECT \
|
|
CCodecs *codecs = new CCodecs; \
|
|
CExternalCodecs __externalCodecs; \
|
|
__externalCodecs.GetCodecs = codecs; \
|
|
__externalCodecs.GetHashers = codecs; \
|
|
CCodecs::CReleaser codecsReleaser; \
|
|
codecsReleaser.Set(codecs);
|
|
#else
|
|
#define CREATE_CODECS_OBJECT \
|
|
CCodecs *codecs = new CCodecs; \
|
|
CMyComPtr<IUnknown> __codecsRef = codecs;
|
|
#endif
|
|
|
|
#endif
|