diff --git a/plugins/arclite/7z/h/CPP/7zip/ICoder.h b/plugins/arclite/7z/h/CPP/7zip/ICoder.h new file mode 100644 index 0000000000..75db939937 --- /dev/null +++ b/plugins/arclite/7z/h/CPP/7zip/ICoder.h @@ -0,0 +1,371 @@ +// ICoder.h + +#ifndef __ICODER_H +#define __ICODER_H + +#include "IStream.h" + +#define CODER_INTERFACE(i, x) DECL_INTERFACE(i, 4, x) + +CODER_INTERFACE(ICompressProgressInfo, 0x04) +{ + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; + + /* (inSize) can be NULL, if unknown + (outSize) can be NULL, if unknown + + returns: + S_OK + E_ABORT : Break by user + another error codes + */ +}; + +CODER_INTERFACE(ICompressCoder, 0x05) +{ + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress) PURE; +}; + +CODER_INTERFACE(ICompressCoder2, 0x18) +{ + STDMETHOD(Code)(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, + ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams, + ICompressProgressInfo *progress) PURE; +}; + +/* + ICompressCoder::Code + ICompressCoder2::Code + + returns: + S_OK : OK + S_FALSE : data error (for decoders) + E_OUTOFMEMORY : memory allocation error + another error code : some error. For example, it can be error code received from inStream or outStream function. + + Parameters: + (inStream != NULL) + (outStream != NULL) + + if (inSize != NULL) + { + Encoders in 7-Zip ignore (inSize). + Decoder can use (*inSize) to check that stream was decoded correctly. + Some decoder in 7-Zip check it, if (full_decoding mode was set via ICompressSetFinishMode) + } + + If it's required to limit the reading from input stream (inStream), it can + be done with ISequentialInStream implementation. + + if (outSize != NULL) + { + Encoders in 7-Zip ignore (outSize). + Decoder unpacks no more than (*outSize) bytes. + } + + (progress == NULL) is allowed. + + + Decoding with Code() function + ----------------------------- + + You can request some interfaces before decoding + - ICompressSetDecoderProperties2 + - ICompressSetFinishMode + + If you need to decode full stream: + { + 1) try to set full_decoding mode with ICompressSetFinishMode::SetFinishMode(1); + 2) call the Code() function with specified (inSize) and (outSize), if these sizes are known. + } + + If you need to decode only part of stream: + { + 1) try to set partial_decoding mode with ICompressSetFinishMode::SetFinishMode(0); + 2) Call the Code() function with specified (inSize = NULL) and specified (outSize). + } + + Encoding with Code() function + ----------------------------- + + You can request some interfaces : + - ICompressSetCoderProperties - use it before encoding to set properties + - ICompressWriteCoderProperties - use it before or after encoding to request encoded properties. + + ICompressCoder2 is used when (numInStreams != 1 || numOutStreams != 1) + The rules are similar to ICompressCoder rules +*/ + + +namespace NCoderPropID +{ + enum EEnum + { + kDefaultProp = 0, + kDictionarySize, + kUsedMemorySize, + kOrder, + kBlockSize, + kPosStateBits, + kLitContextBits, + kLitPosBits, + kNumFastBytes, + kMatchFinder, + kMatchFinderCycles, + kNumPasses, + kAlgorithm, + kNumThreads, + kEndMarker, + kLevel, + kReduceSize // estimated size of data that will be compressed. Encoder can use this value to reduce dictionary size. + }; +} + +CODER_INTERFACE(ICompressSetCoderProperties, 0x20) +{ + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) PURE; +}; + +/* +CODER_INTERFACE(ICompressSetCoderProperties, 0x21) +{ + STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE; +}; +*/ + +CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) +{ + /* returns: + S_OK + E_NOTIMP : unsupported properties + E_INVALIDARG : incorrect (or unsupported) properties + E_OUTOFMEMORY : memory allocation error + */ + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) +{ + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream) PURE; +}; + +CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) +{ + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE; +}; + +CODER_INTERFACE(ICompressSetCoderMt, 0x25) +{ + STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE; +}; + +CODER_INTERFACE(ICompressSetFinishMode, 0x26) +{ + STDMETHOD(SetFinishMode)(UInt32 finishMode) PURE; + + /* finishMode: + 0 : partial decoding is allowed. It's default mode for ICompressCoder::Code(), if (outSize) is defined. + 1 : full decoding. The stream must be finished at the end of decoding. */ +}; + + +CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) +{ + STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; + + /* returns: + S_OK : (*value) contains the size or estimated size (can be incorrect size) + S_FALSE : size is undefined + E_NOTIMP : the feature is not implemented + + Let's (read_size) is size of data that was already read by ISequentialInStream::Read(). + The caller should call GetSubStreamSize() after each Read() and check sizes: + if (start_of_subStream + *value < read_size) + { + // (*value) is correct, and it's allowed to call GetSubStreamSize() for next subStream: + start_of_subStream += *value; + subStream++; + } + */ +}; + +CODER_INTERFACE(ICompressSetInStream, 0x31) +{ + STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE; + STDMETHOD(ReleaseInStream)() PURE; +}; + +CODER_INTERFACE(ICompressSetOutStream, 0x32) +{ + STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE; + STDMETHOD(ReleaseOutStream)() PURE; +}; + +/* +CODER_INTERFACE(ICompressSetInStreamSize, 0x33) +{ + STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; +}; +*/ + +CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) +{ + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; + + /* That function initializes decoder structures. + Call this function only for stream version of decoder. + if (outSize == NULL), then output size is unknown + if (outSize != NULL), then the decoder must stop decoding after (*outSize) bytes. */ +}; + +CODER_INTERFACE(ICompressSetBufSize, 0x35) +{ + STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size) PURE; + STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICompressInitEncoder, 0x36) +{ + STDMETHOD(InitEncoder)() PURE; + + /* That function initializes encoder structures. + Call this function only for stream version of encoder. */ +}; + +CODER_INTERFACE(ICompressSetInStream2, 0x37) +{ + STDMETHOD(SetInStream2)(UInt32 streamIndex, ISequentialInStream *inStream) PURE; + STDMETHOD(ReleaseInStream2)(UInt32 streamIndex) PURE; +}; + +/* +CODER_INTERFACE(ICompressSetOutStream2, 0x38) +{ + STDMETHOD(SetOutStream2)(UInt32 streamIndex, ISequentialOutStream *outStream) PURE; + STDMETHOD(ReleaseOutStream2)(UInt32 streamIndex) PURE; +}; + +CODER_INTERFACE(ICompressSetInStreamSize2, 0x39) +{ + STDMETHOD(SetInStreamSize2)(UInt32 streamIndex, const UInt64 *inSize) PURE; +}; +*/ + + +/* + ICompressFilter + Filter() converts as most as possible bytes + returns: (outSize): + if (outSize <= size) : Filter have converted outSize bytes + if (outSize > size) : Filter have not converted anything. + and it needs at least outSize bytes to convert one block + (it's for crypto block algorithms). +*/ + +#define INTERFACE_ICompressFilter(x) \ + STDMETHOD(Init)() x; \ + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) x; \ + +CODER_INTERFACE(ICompressFilter, 0x40) +{ + INTERFACE_ICompressFilter(PURE); +}; + + +CODER_INTERFACE(ICompressCodecsInfo, 0x60) +{ + STDMETHOD(GetNumMethods)(UInt32 *numMethods) PURE; + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; + STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE; + STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE; +}; + +CODER_INTERFACE(ISetCompressCodecsInfo, 0x61) +{ + STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE; +}; + +CODER_INTERFACE(ICryptoProperties, 0x80) +{ + STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE; + STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE; +}; + +/* +CODER_INTERFACE(ICryptoResetSalt, 0x88) +{ + STDMETHOD(ResetSalt)() PURE; +}; +*/ + +CODER_INTERFACE(ICryptoResetInitVector, 0x8C) +{ + STDMETHOD(ResetInitVector)() PURE; + + /* Call ResetInitVector() only for encoding. + Call ResetInitVector() before encoding and before WriteCoderProperties(). + Crypto encoder can create random IV in that function. */ +}; + +CODER_INTERFACE(ICryptoSetPassword, 0x90) +{ + STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICryptoSetCRC, 0xA0) +{ + STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; +}; + + +namespace NMethodPropID +{ + enum EEnum + { + kID, + kName, + kDecoder, + kEncoder, + kPackStreams, + kUnpackStreams, + kDescription, + kDecoderIsAssigned, + kEncoderIsAssigned, + kDigestSize + }; +} + + +#define INTERFACE_IHasher(x) \ + STDMETHOD_(void, Init)() throw() x; \ + STDMETHOD_(void, Update)(const void *data, UInt32 size) throw() x; \ + STDMETHOD_(void, Final)(Byte *digest) throw() x; \ + STDMETHOD_(UInt32, GetDigestSize)() throw() x; \ + +CODER_INTERFACE(IHasher, 0xC0) +{ + INTERFACE_IHasher(PURE) +}; + +CODER_INTERFACE(IHashers, 0xC1) +{ + STDMETHOD_(UInt32, GetNumHashers)() PURE; + STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; + STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher) PURE; +}; + +extern "C" +{ + typedef HRESULT (WINAPI *Func_GetNumberOfMethods)(UInt32 *numMethods); + typedef HRESULT (WINAPI *Func_GetMethodProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); + typedef HRESULT (WINAPI *Func_CreateDecoder)(UInt32 index, const GUID *iid, void **outObject); + typedef HRESULT (WINAPI *Func_CreateEncoder)(UInt32 index, const GUID *iid, void **outObject); + + typedef HRESULT (WINAPI *Func_GetHashers)(IHashers **hashers); + + typedef HRESULT (WINAPI *Func_SetCodecs)(ICompressCodecsInfo *compressCodecsInfo); +} + +#endif diff --git a/plugins/arclite/archive.cpp b/plugins/arclite/archive.cpp index b97e46695f..08d1ad9aca 100644 --- a/plugins/arclite/archive.cpp +++ b/plugins/arclite/archive.cpp @@ -103,7 +103,6 @@ wstring ArcFormat::default_extension() const { return extension_list.front(); } - ArcTypes ArcFormats::get_arc_types() const { ArcTypes types; for (const_iterator fmt = begin(); fmt != end(); fmt++) { @@ -158,10 +157,66 @@ wstring ArcChain::to_string() const { return result; } +class MyCompressCodecsInfo : public ICompressCodecsInfo, private ComBase { +private: + const ArcLibs& libs_; + const vector &codecs_; +public: + MyCompressCodecsInfo(const ArcLibs& libs, const vector &codecs) + : libs_(libs), codecs_(codecs) {} + + ~MyCompressCodecsInfo() {} + + UNKNOWN_IMPL_BEGIN + UNKNOWN_IMPL_ITF(ICompressCodecsInfo) + UNKNOWN_IMPL_END + + STDMETHODIMP GetNumMethods(UInt32 *numMethods) { + *numMethods = static_cast(codecs_.size()); + return S_OK; + } + + STDMETHODIMP GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { + const CDllCodecInfo &ci = codecs_[index]; + if (propID == NMethodPropID::kDecoderIsAssigned || propID == NMethodPropID::kEncoderIsAssigned) { + PropVariant prop; + prop = (bool)((propID == NMethodPropID::kDecoderIsAssigned) ? ci.DecoderIsAssigned : ci.EncoderIsAssigned); + prop.detach(value); + return S_OK; + } + const auto &lib = libs_[ci.LibIndex]; + return lib.GetMethodProperty(ci.CodecIndex, propID, value); + } + + STDMETHODIMP CreateDecoder(UInt32 index, const GUID *iid, void **coder) { + const CDllCodecInfo &ci = codecs_[index]; + if (ci.DecoderIsAssigned) { + const auto &lib = libs_[ci.LibIndex]; + if (lib.CreateDecoder) + return lib.CreateDecoder(ci.CodecIndex, iid, (void **)coder); + else + return lib.CreateObject(&ci.Decoder, iid, (void **)coder); + } + return S_OK; + } + + STDMETHODIMP CreateEncoder(UInt32 index, const GUID *iid, void **coder) { + const CDllCodecInfo &ci = codecs_[index]; + if (ci.EncoderIsAssigned) { + const auto &lib = libs_[ci.LibIndex]; + if (lib.CreateEncoder) + return lib.CreateEncoder(ci.CodecIndex, iid, (void **)coder); + else + return lib.CreateObject(&ci.Encoder, iid, (void **)coder); + } + return S_OK; + } +}; ArcAPI* ArcAPI::arc_api = nullptr; ArcAPI::~ArcAPI() { + delete compressinfo; for_each(arc_libs.begin(), arc_libs.end(), [&] (const ArcLib& arc_lib) { if (arc_lib.h_module) FreeLibrary(arc_lib.h_module); @@ -177,6 +232,33 @@ ArcAPI* ArcAPI::get() { return arc_api; } +static bool GetCoderInfo(ArcLib::FGetMethodProperty getMethodProperty, UInt32 index, CDllCodecInfo& info) { + info.DecoderIsAssigned = info.EncoderIsAssigned = false; + std::fill((char *)&info.Decoder, sizeof(info.Decoder) + (char *)&info.Decoder, 0); + info.Encoder = info.Decoder; + PropVariant prop1, prop2, prop3; + if (S_OK != getMethodProperty(index, NMethodPropID::kDecoder, prop1.ref())) + return false; + if (prop1.vt != VT_EMPTY) { + if (prop1.vt != VT_BSTR || (size_t)SysStringByteLen(prop1.bstrVal) < sizeof(CLSID)) + return false; + info.Decoder = *(const GUID *)prop1.bstrVal; + info.DecoderIsAssigned = true; + } + if (S_OK != getMethodProperty(index, NMethodPropID::kEncoder, prop2.ref())) + return false; + if (prop2.vt != VT_EMPTY) { + if (prop2.vt != VT_BSTR || (size_t)SysStringByteLen(prop2.bstrVal) < sizeof(CLSID)) + return false; + info.Encoder = *(const GUID *)prop2.bstrVal; + info.EncoderIsAssigned = true; + } + if (S_OK != getMethodProperty(index, NMethodPropID::kName, prop3.ref()) || !prop3.is_str()) + return false; + info.Name = prop3.get_str(); + return info.DecoderIsAssigned || info.EncoderIsAssigned; +} + void ArcAPI::load_libs(const wstring& path) { FileEnum file_enum(path); wstring dir = extract_file_path(path); @@ -187,19 +269,73 @@ void ArcAPI::load_libs(const wstring& path) { arc_lib.h_module = LoadLibraryW(arc_lib.module_path.c_str()); if (arc_lib.h_module == nullptr) continue; - arc_lib.CreateObject = reinterpret_cast(GetProcAddress(arc_lib.h_module, "CreateObject")); + arc_lib.CreateObject = reinterpret_cast(GetProcAddress(arc_lib.h_module, "CreateObject")); arc_lib.GetNumberOfMethods = reinterpret_cast(GetProcAddress(arc_lib.h_module, "GetNumberOfMethods")); arc_lib.GetMethodProperty = reinterpret_cast(GetProcAddress(arc_lib.h_module, "GetMethodProperty")); arc_lib.GetNumberOfFormats = reinterpret_cast(GetProcAddress(arc_lib.h_module, "GetNumberOfFormats")); arc_lib.GetHandlerProperty = reinterpret_cast(GetProcAddress(arc_lib.h_module, "GetHandlerProperty")); arc_lib.GetHandlerProperty2 = reinterpret_cast(GetProcAddress(arc_lib.h_module, "GetHandlerProperty2")); arc_lib.GetIsArc = reinterpret_cast(GetProcAddress(arc_lib.h_module, "GetIsArc")); - if (arc_lib.CreateObject && ((arc_lib.GetNumberOfFormats && arc_lib.GetHandlerProperty2) || arc_lib.GetHandlerProperty)) { + arc_lib.SetCodecs = reinterpret_cast(GetProcAddress(arc_lib.h_module, "SetCodecs")); + arc_lib.CreateDecoder = nullptr; + arc_lib.CreateEncoder = nullptr; + if (arc_lib.CreateObject && ((arc_lib.GetNumberOfFormats && arc_lib.GetHandlerProperty2) || arc_lib.GetHandlerProperty)) { arc_lib.version = get_module_version(arc_lib.module_path); arc_libs.push_back(arc_lib); } else FreeLibrary(arc_lib.h_module); + + // load codecs + n_format_libs = arc_libs.size(); + if (n_format_libs >= 1) { + dir = add_trailing_slash(dir) + L"Codecs"; + auto look_codecs = add_trailing_slash(dir) + L"*"; + FileEnum codecs_enum(look_codecs); + while (codecs_enum.next_nt(more) && more && !codecs_enum.data().is_dir()) { + ArcLib arc_lib; + arc_lib.module_path = add_trailing_slash(dir) + codecs_enum.data().cFileName; + arc_lib.h_module = LoadLibraryW(arc_lib.module_path.c_str()); + if (arc_lib.h_module == nullptr) + continue; + arc_lib.CreateObject = reinterpret_cast(GetProcAddress(arc_lib.h_module, "CreateObject")); + arc_lib.CreateDecoder = reinterpret_cast(GetProcAddress(arc_lib.h_module, "CreateDecoder")); + arc_lib.CreateEncoder = reinterpret_cast(GetProcAddress(arc_lib.h_module, "CreateEncoder")); + arc_lib.GetNumberOfMethods = reinterpret_cast(GetProcAddress(arc_lib.h_module, "GetNumberOfMethods")); + arc_lib.GetMethodProperty = reinterpret_cast(GetProcAddress(arc_lib.h_module, "GetMethodProperty")); + arc_lib.GetNumberOfFormats = nullptr; + arc_lib.GetHandlerProperty = nullptr; + arc_lib.GetHandlerProperty2 = nullptr; + arc_lib.GetIsArc = nullptr; + arc_lib.SetCodecs = nullptr; + arc_lib.version = 0; + auto n_start_codecs = codecs.size(); + if ((arc_lib.CreateObject || arc_lib.CreateDecoder || arc_lib.CreateEncoder) && arc_lib.GetMethodProperty) { + UInt32 numMethods = 1; + bool ok = true; + if (arc_lib.GetNumberOfMethods) + ok = S_OK == arc_lib.GetNumberOfMethods(&numMethods); + for (UInt32 i = 0; ok && i < numMethods; ++i) { + CDllCodecInfo info; + info.LibIndex = static_cast(arc_libs.size()); + info.CodecIndex = i; + if (GetCoderInfo(arc_lib.GetMethodProperty, i, info)) + codecs.push_back(info); + } + } + if (n_start_codecs < codecs.size()) + arc_libs.push_back(arc_lib); + else + FreeLibrary(arc_lib.h_module); + } + } + if (codecs.size() > 0) { + compressinfo = new MyCompressCodecsInfo(arc_libs, codecs); + for (size_t i = 0; i < n_format_libs; ++i) { + if (arc_libs[i].SetCodecs) + arc_libs[i].SetCodecs(compressinfo); + } + } } } @@ -306,7 +442,7 @@ void ArcAPI::load() { if (!_7z_dll_path.empty()) load_libs(_7z_dll_path); } - for (unsigned i = 0; i < arc_libs.size(); i++) { + for (unsigned i = 0; i < n_format_libs; i++) { const ArcLib& arc_lib = arc_libs[i]; UInt32 num_formats; @@ -383,7 +519,7 @@ void ArcAPI::load() { for_each(arc_formats.begin(), arc_formats.end(), [&] (const pair& arc_format) { used_libs.insert(arc_format.second.lib_index); }); - for (unsigned i = 0; i < arc_libs.size(); i++) { + for (unsigned i = 0; i < n_format_libs; i++) { if (used_libs.count(i) == 0) { FreeLibrary(arc_libs[i].h_module); arc_libs[i].h_module = nullptr; diff --git a/plugins/arclite/archive.hpp b/plugins/arclite/archive.hpp index 1b7bc141ff..d704d7a69d 100644 --- a/plugins/arclite/archive.hpp +++ b/plugins/arclite/archive.hpp @@ -24,23 +24,30 @@ extern const unsigned __int64 c_min_volume_size; extern const wchar_t* c_sfx_ext; extern const wchar_t* c_volume_ext; +struct ICompressCodecsInfo; + struct ArcLib { HMODULE h_module; unsigned __int64 version; wstring module_path; - typedef UInt32 (WINAPI *FCreateObject)(const GUID *clsID, const GUID *interfaceID, void **outObject); typedef UInt32 (WINAPI *FGetNumberOfMethods)(UInt32 *numMethods); typedef UInt32 (WINAPI *FGetMethodProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *FGetNumberOfFormats)(UInt32 *numFormats); typedef UInt32 (WINAPI *FGetHandlerProperty)(PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *FGetHandlerProperty2)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *FSetLargePageMode)(); - FCreateObject CreateObject; + typedef HRESULT(WINAPI *FSetCodecs)(ICompressCodecsInfo *compressCodecsInfo); + typedef HRESULT(WINAPI *FCreateDecoder)(UInt32 index, const GUID *iid, void **object); + typedef HRESULT(WINAPI *FCreateEncoder)(UInt32 index, const GUID *iid, void **object); + Func_CreateObject CreateObject; FGetNumberOfMethods GetNumberOfMethods; FGetMethodProperty GetMethodProperty; FGetNumberOfFormats GetNumberOfFormats; FGetHandlerProperty GetHandlerProperty; FGetHandlerProperty2 GetHandlerProperty2; + FSetCodecs SetCodecs; + FCreateDecoder CreateDecoder; + FCreateEncoder CreateEncoder; Func_GetIsArc GetIsArc; HRESULT get_prop(UInt32 index, PROPID prop_id, PROPVARIANT* prop) const; @@ -88,6 +95,16 @@ struct ArcFormat { typedef vector ArcLibs; +struct CDllCodecInfo { + unsigned LibIndex; + UInt32 CodecIndex; + bool EncoderIsAssigned; + bool DecoderIsAssigned; + CLSID Encoder; + CLSID Decoder; + wstring Name; +}; + class ArcFormats: public map { public: ArcTypes get_arc_types() const; @@ -107,13 +124,18 @@ class SfxModules: public vector { uintptr_t find_by_name(const wstring& name) const; }; +class MyCompressCodecsInfo; + class ArcAPI { private: ArcLibs arc_libs; + size_t n_format_libs; + vector codecs; + MyCompressCodecsInfo *compressinfo; ArcFormats arc_formats; SfxModules sfx_modules; static ArcAPI* arc_api; - ArcAPI() {} + ArcAPI() { compressinfo = nullptr; } ~ArcAPI(); void load_libs(const wstring& path); void find_sfx_modules(const wstring& path); diff --git a/plugins/arclite/changelog b/plugins/arclite/changelog index d43d9fd23a..15ff080af9 100644 --- a/plugins/arclite/changelog +++ b/plugins/arclite/changelog @@ -1,3 +1,10 @@ +w17 15.03.2016 22:20:12 +0300 - build 231 + +1. Поддержка внешних кодеков. + dll кодеков грузятся из каталога \Codecs + Чтобы фар не пытался их грузить как свои плагины, можно (но не обязательно) + пререименовать, например *.codec + w17 26.02.2016 13:32:33 +0300 - build 230 1. Нельзя было зайти в пустые архивы (частичный откат 224). diff --git a/plugins/arclite/headers.hpp b/plugins/arclite/headers.hpp index 457589a45c..0ae36953bc 100644 --- a/plugins/arclite/headers.hpp +++ b/plugins/arclite/headers.hpp @@ -29,6 +29,7 @@ using namespace std; #include #include "CPP/7zip/Archive/IArchive.h" #include "CPP/7zip/IPassword.h" +#include "CPP/7Zip/ICoder.h" #include "plugin.hpp" #include "farcolor.hpp" diff --git a/plugins/arclite/project.ini b/plugins/arclite/project.ini index a144f24e3e..0cd760baea 100644 --- a/plugins/arclite/project.ini +++ b/plugins/arclite/project.ini @@ -2,4 +2,4 @@ MODULE = arclite VER_MAJOR = 3 VER_MINOR = 0 -VER_BUILD = 230 +VER_BUILD = 231