mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-08 16:07:04 -06:00
15.05
This commit is contained in:
committed by
Kornel Lesiński
parent
0713a3ab80
commit
54490d51d5
@@ -3,7 +3,6 @@
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "../../Common/LockedStream.h"
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
#include "../../Common/StreamObjects.h"
|
||||
|
||||
@@ -12,50 +11,70 @@
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,
|
||||
CBindInfoEx &bindInfo)
|
||||
class CDecProgress:
|
||||
public ICompressProgressInfo,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
bindInfo.Clear();
|
||||
bindInfo.BindPairs.ClearAndSetSize(folder.BindPairs.Size());
|
||||
CMyComPtr<ICompressProgressInfo> _progress;
|
||||
public:
|
||||
CDecProgress(ICompressProgressInfo *progress): _progress(progress) {}
|
||||
|
||||
MY_UNKNOWN_IMP1(ICompressProgressInfo)
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
STDMETHODIMP CDecProgress::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 *outSize)
|
||||
{
|
||||
return _progress->SetRatioInfo(NULL, outSize);
|
||||
}
|
||||
|
||||
static void Convert_FolderInfo_to_BindInfo(const CFolderEx &folder, CBindInfoEx &bi)
|
||||
{
|
||||
bi.Clear();
|
||||
|
||||
bi.Bonds.ClearAndSetSize(folder.Bonds.Size());
|
||||
unsigned i;
|
||||
for (i = 0; i < folder.BindPairs.Size(); i++)
|
||||
for (i = 0; i < folder.Bonds.Size(); i++)
|
||||
{
|
||||
NCoderMixer::CBindPair &bindPair = bindInfo.BindPairs[i];
|
||||
bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;
|
||||
bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;
|
||||
NCoderMixer2::CBond &bond = bi.Bonds[i];
|
||||
const N7z::CBond &folderBond = folder.Bonds[i];
|
||||
bond.PackIndex = folderBond.PackIndex;
|
||||
bond.UnpackIndex = folderBond.UnpackIndex;
|
||||
}
|
||||
|
||||
bindInfo.Coders.ClearAndSetSize(folder.Coders.Size());
|
||||
bindInfo.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());
|
||||
|
||||
UInt32 outStreamIndex = 0;
|
||||
bi.Coders.ClearAndSetSize(folder.Coders.Size());
|
||||
bi.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());
|
||||
for (i = 0; i < folder.Coders.Size(); i++)
|
||||
{
|
||||
NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
|
||||
const CCoderInfo &coderInfo = folder.Coders[i];
|
||||
coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;
|
||||
coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;
|
||||
bindInfo.CoderMethodIDs[i] = coderInfo.MethodID;
|
||||
for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
|
||||
if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
|
||||
bindInfo.OutStreams.Add(outStreamIndex);
|
||||
bi.Coders[i].NumStreams = coderInfo.NumStreams;
|
||||
bi.CoderMethodIDs[i] = coderInfo.MethodID;
|
||||
}
|
||||
bindInfo.InStreams.ClearAndSetSize(folder.PackStreams.Size());
|
||||
|
||||
/*
|
||||
if (!bi.SetUnpackCoder())
|
||||
throw 1112;
|
||||
*/
|
||||
bi.UnpackCoder = folder.UnpackCoder;
|
||||
bi.PackStreams.ClearAndSetSize(folder.PackStreams.Size());
|
||||
for (i = 0; i < folder.PackStreams.Size(); i++)
|
||||
bindInfo.InStreams[i] = (UInt32)folder.PackStreams[i];
|
||||
bi.PackStreams[i] = folder.PackStreams[i];
|
||||
}
|
||||
|
||||
static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1,
|
||||
const NCoderMixer::CCoderStreamsInfo &a2)
|
||||
static inline bool AreCodersEqual(
|
||||
const NCoderMixer2::CCoderStreamsInfo &a1,
|
||||
const NCoderMixer2::CCoderStreamsInfo &a2)
|
||||
{
|
||||
return (a1.NumInStreams == a2.NumInStreams) &&
|
||||
(a1.NumOutStreams == a2.NumOutStreams);
|
||||
return (a1.NumStreams == a2.NumStreams);
|
||||
}
|
||||
|
||||
static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2)
|
||||
static inline bool AreBondsEqual(
|
||||
const NCoderMixer2::CBond &a1,
|
||||
const NCoderMixer2::CBond &a2)
|
||||
{
|
||||
return (a1.InIndex == a2.InIndex) &&
|
||||
(a1.OutIndex == a2.OutIndex);
|
||||
return
|
||||
(a1.PackIndex == a2.PackIndex) &&
|
||||
(a1.UnpackIndex == a2.UnpackIndex);
|
||||
}
|
||||
|
||||
static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
|
||||
@@ -66,186 +85,284 @@ static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
|
||||
for (i = 0; i < a1.Coders.Size(); i++)
|
||||
if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
|
||||
return false;
|
||||
if (a1.BindPairs.Size() != a2.BindPairs.Size())
|
||||
|
||||
if (a1.Bonds.Size() != a2.Bonds.Size())
|
||||
return false;
|
||||
for (i = 0; i < a1.BindPairs.Size(); i++)
|
||||
if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))
|
||||
for (i = 0; i < a1.Bonds.Size(); i++)
|
||||
if (!AreBondsEqual(a1.Bonds[i], a2.Bonds[i]))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
|
||||
if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
|
||||
return false;
|
||||
if (a1.InStreams.Size() != a2.InStreams.Size())
|
||||
|
||||
if (a1.PackStreams.Size() != a2.PackStreams.Size())
|
||||
return false;
|
||||
if (a1.OutStreams.Size() != a2.OutStreams.Size())
|
||||
for (i = 0; i < a1.PackStreams.Size(); i++)
|
||||
if (a1.PackStreams[i] != a2.PackStreams[i])
|
||||
return false;
|
||||
|
||||
/*
|
||||
if (a1.UnpackCoder != a2.UnpackCoder)
|
||||
return false;
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
CDecoder::CDecoder(bool multiThread)
|
||||
CDecoder::CDecoder(bool useMixerMT):
|
||||
_bindInfoPrev_Defined(false),
|
||||
_useMixerMT(useMixerMT)
|
||||
{}
|
||||
|
||||
|
||||
struct CLockedInStream:
|
||||
public IUnknown,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
#ifndef _ST_MODE
|
||||
multiThread = true;
|
||||
CMyComPtr<IInStream> Stream;
|
||||
UInt64 Pos;
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
#ifdef USE_MIXER_MT
|
||||
NWindows::NSynchronization::CCriticalSection CriticalSection;
|
||||
#endif
|
||||
_multiThread = multiThread;
|
||||
_bindInfoExPrevIsDefined = false;
|
||||
};
|
||||
|
||||
|
||||
#ifdef USE_MIXER_MT
|
||||
|
||||
class CLockedSequentialInStreamMT:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CLockedInStream *_glob;
|
||||
UInt64 _pos;
|
||||
CMyComPtr<IUnknown> _globRef;
|
||||
public:
|
||||
void Init(CLockedInStream *lockedInStream, UInt64 startPos)
|
||||
{
|
||||
_globRef = lockedInStream;
|
||||
_glob = lockedInStream;
|
||||
_pos = startPos;
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP1(ISequentialInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
STDMETHODIMP CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(_glob->CriticalSection);
|
||||
|
||||
if (_pos != _glob->Pos)
|
||||
{
|
||||
RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL));
|
||||
_glob->Pos = _pos;
|
||||
}
|
||||
|
||||
UInt32 realProcessedSize = 0;
|
||||
HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
|
||||
_pos += realProcessedSize;
|
||||
_glob->Pos = _pos;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
|
||||
class CLockedSequentialInStreamST:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CLockedInStream *_glob;
|
||||
UInt64 _pos;
|
||||
CMyComPtr<IUnknown> _globRef;
|
||||
public:
|
||||
void Init(CLockedInStream *lockedInStream, UInt64 startPos)
|
||||
{
|
||||
_globRef = lockedInStream;
|
||||
_glob = lockedInStream;
|
||||
_pos = startPos;
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP1(ISequentialInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
STDMETHODIMP CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (_pos != _glob->Pos)
|
||||
{
|
||||
RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL));
|
||||
_glob->Pos = _pos;
|
||||
}
|
||||
|
||||
UInt32 realProcessedSize = 0;
|
||||
HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
|
||||
_pos += realProcessedSize;
|
||||
_glob->Pos = _pos;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
HRESULT CDecoder::Decode(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
IInStream *inStream,
|
||||
UInt64 startPos,
|
||||
const CFolders &folders, int folderIndex,
|
||||
ISequentialOutStream *outStream,
|
||||
ICompressProgressInfo *compressProgress
|
||||
const CFolders &folders, unsigned folderIndex,
|
||||
const UInt64 *unpackSize
|
||||
|
||||
, ISequentialOutStream *outStream
|
||||
, ICompressProgressInfo *compressProgress
|
||||
, ISequentialInStream **
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
inStreamMainRes
|
||||
#endif
|
||||
|
||||
_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
, bool mtMode, UInt32 numThreads
|
||||
#endif
|
||||
)
|
||||
{
|
||||
const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]];
|
||||
CFolder folderInfo;
|
||||
folders.ParseFolderInfo(folderIndex, folderInfo);
|
||||
CFolderEx folderInfo;
|
||||
folders.ParseFolderEx(folderIndex, folderInfo);
|
||||
|
||||
if (!folderInfo.CheckStructure(folders.GetNumFolderUnpackSizes(folderIndex)))
|
||||
if (!folderInfo.IsDecodingSupported())
|
||||
return E_NOTIMPL;
|
||||
|
||||
CBindInfoEx bindInfo;
|
||||
Convert_FolderInfo_to_BindInfo(folderInfo, bindInfo);
|
||||
if (!bindInfo.CalcMapsAndCheck())
|
||||
return E_NOTIMPL;
|
||||
|
||||
UInt64 folderUnpackSize = folders.GetFolderUnpackSize(folderIndex);
|
||||
bool fullUnpack = true;
|
||||
if (unpackSize)
|
||||
{
|
||||
if (*unpackSize > folderUnpackSize)
|
||||
return E_FAIL;
|
||||
fullUnpack = (*unpackSize == folderUnpackSize);
|
||||
}
|
||||
|
||||
/*
|
||||
We don't need to init isEncrypted and passwordIsDefined
|
||||
We must upgrade them only
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
isEncrypted = false;
|
||||
passwordIsDefined = false;
|
||||
#endif
|
||||
*/
|
||||
|
||||
CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
|
||||
|
||||
CLockedInStream lockedInStream;
|
||||
lockedInStream.Init(inStream);
|
||||
|
||||
for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
|
||||
if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev))
|
||||
{
|
||||
CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp;
|
||||
CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
|
||||
lockedStreamImpSpec->Init(&lockedInStream, startPos + packPositions[j]);
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> inStream = streamSpec;
|
||||
streamSpec->SetStream(lockedStreamImp);
|
||||
streamSpec->Init(packPositions[j + 1] - packPositions[j]);
|
||||
inStreams.Add(inStream);
|
||||
}
|
||||
|
||||
unsigned numCoders = folderInfo.Coders.Size();
|
||||
|
||||
CBindInfoEx bindInfo;
|
||||
ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
|
||||
bool createNewCoders;
|
||||
if (!_bindInfoExPrevIsDefined)
|
||||
createNewCoders = true;
|
||||
else
|
||||
createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
|
||||
if (createNewCoders)
|
||||
{
|
||||
unsigned i;
|
||||
_decoders.Clear();
|
||||
// _decoders2.Clear();
|
||||
|
||||
_mixerCoder.Release();
|
||||
_mixerRef.Release();
|
||||
|
||||
if (_multiThread)
|
||||
#ifdef USE_MIXER_MT
|
||||
#ifdef USE_MIXER_ST
|
||||
if (_useMixerMT)
|
||||
#endif
|
||||
{
|
||||
_mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT;
|
||||
_mixerCoder = _mixerCoderMTSpec;
|
||||
_mixerCoderCommon = _mixerCoderMTSpec;
|
||||
_mixerMT = new NCoderMixer2::CMixerMT(false);
|
||||
_mixerRef = _mixerMT;
|
||||
_mixer = _mixerMT;
|
||||
}
|
||||
#ifdef USE_MIXER_ST
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
#ifdef _ST_MODE
|
||||
_mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST;
|
||||
_mixerCoder = _mixerCoderSTSpec;
|
||||
_mixerCoderCommon = _mixerCoderSTSpec;
|
||||
#ifdef USE_MIXER_ST
|
||||
_mixerST = new NCoderMixer2::CMixerST(false);
|
||||
_mixerRef = _mixerST;
|
||||
_mixer = _mixerST;
|
||||
#endif
|
||||
}
|
||||
RINOK(_mixerCoderCommon->SetBindInfo(bindInfo));
|
||||
|
||||
for (i = 0; i < numCoders; i++)
|
||||
RINOK(_mixer->SetBindInfo(bindInfo));
|
||||
|
||||
FOR_VECTOR(i, folderInfo.Coders)
|
||||
{
|
||||
const CCoderInfo &coderInfo = folderInfo.Coders[i];
|
||||
|
||||
|
||||
CMyComPtr<ICompressCoder> decoder;
|
||||
CMyComPtr<ICompressCoder2> decoder2;
|
||||
CCreatedCoder cod;
|
||||
RINOK(CreateCoder(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
coderInfo.MethodID, decoder, decoder2, false));
|
||||
CMyComPtr<IUnknown> decoderUnknown;
|
||||
coderInfo.MethodID, false, cod));
|
||||
|
||||
if (coderInfo.IsSimpleCoder())
|
||||
{
|
||||
if (decoder == 0)
|
||||
if (!cod.Coder)
|
||||
return E_NOTIMPL;
|
||||
|
||||
decoderUnknown = (IUnknown *)decoder;
|
||||
|
||||
if (_multiThread)
|
||||
_mixerCoderMTSpec->AddCoder(decoder);
|
||||
#ifdef _ST_MODE
|
||||
else
|
||||
_mixerCoderSTSpec->AddCoder(decoder, false);
|
||||
#endif
|
||||
// CMethodId m = coderInfo.MethodID;
|
||||
// isFilter = (IsFilterMethod(m) || m == k_AES);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (decoder2 == 0)
|
||||
if (!cod.Coder2 || cod.NumStreams != coderInfo.NumStreams)
|
||||
return E_NOTIMPL;
|
||||
decoderUnknown = (IUnknown *)decoder2;
|
||||
if (_multiThread)
|
||||
_mixerCoderMTSpec->AddCoder2(decoder2);
|
||||
#ifdef _ST_MODE
|
||||
else
|
||||
_mixerCoderSTSpec->AddCoder2(decoder2, false);
|
||||
#endif
|
||||
}
|
||||
_decoders.Add(decoderUnknown);
|
||||
_mixer->AddCoder(cod);
|
||||
|
||||
// now there is no codec that uses another external codec
|
||||
/*
|
||||
#ifdef EXTERNAL_CODECS
|
||||
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
|
||||
decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
|
||||
if (setCompressCodecsInfo)
|
||||
{
|
||||
// we must use g_ExternalCodecs also
|
||||
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
_bindInfoExPrev = bindInfo;
|
||||
_bindInfoExPrevIsDefined = true;
|
||||
|
||||
_bindInfoPrev = bindInfo;
|
||||
_bindInfoPrev_Defined = true;
|
||||
}
|
||||
unsigned i;
|
||||
_mixerCoderCommon->ReInit();
|
||||
|
||||
_mixer->ReInit();
|
||||
|
||||
UInt32 packStreamIndex = 0;
|
||||
UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex];
|
||||
UInt32 unpackStreamIndex = unpackStreamIndexStart;
|
||||
UInt32 coderIndex = 0;
|
||||
// UInt32 coder2Index = 0;
|
||||
|
||||
for (i = 0; i < numCoders; i++)
|
||||
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < folderInfo.Coders.Size(); i++)
|
||||
{
|
||||
const CCoderInfo &coderInfo = folderInfo.Coders[i];
|
||||
CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];
|
||||
|
||||
IUnknown *decoder = _mixer->GetCoder(i).GetUnknown();
|
||||
|
||||
{
|
||||
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
|
||||
decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
|
||||
decoder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);
|
||||
if (setDecoderProperties)
|
||||
{
|
||||
const CByteBuffer &props = coderInfo.Props;
|
||||
size_t size = props.Size();
|
||||
if (size > 0xFFFFFFFF)
|
||||
return E_NOTIMPL;
|
||||
// if (size > 0)
|
||||
{
|
||||
RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size));
|
||||
}
|
||||
HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size);
|
||||
if (res == E_INVALIDARG)
|
||||
res = E_NOTIMPL;
|
||||
RINOK(res);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,7 +370,7 @@ HRESULT CDecoder::Decode(
|
||||
if (mtMode)
|
||||
{
|
||||
CMyComPtr<ICompressSetCoderMt> setCoderMt;
|
||||
decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
|
||||
decoder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);
|
||||
if (setCoderMt)
|
||||
{
|
||||
RINOK(setCoderMt->SetNumberOfThreads(numThreads));
|
||||
@@ -264,7 +381,7 @@ HRESULT CDecoder::Decode(
|
||||
#ifndef _NO_CRYPTO
|
||||
{
|
||||
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
|
||||
decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
|
||||
decoder->QueryInterface(IID_ICryptoSetPassword, (void **)&cryptoSetPassword);
|
||||
if (cryptoSetPassword)
|
||||
{
|
||||
isEncrypted = true;
|
||||
@@ -273,9 +390,13 @@ HRESULT CDecoder::Decode(
|
||||
CMyComBSTR passwordBSTR;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));
|
||||
passwordIsDefined = true;
|
||||
password.Empty();
|
||||
size_t len = 0;
|
||||
if (passwordBSTR)
|
||||
len = MyStringLen((BSTR)passwordBSTR);
|
||||
{
|
||||
password = passwordBSTR;
|
||||
len = password.Len();
|
||||
}
|
||||
CByteBuffer buffer(len * 2);
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
@@ -288,56 +409,129 @@ HRESULT CDecoder::Decode(
|
||||
}
|
||||
#endif
|
||||
|
||||
coderIndex++;
|
||||
|
||||
UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;
|
||||
UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;
|
||||
CObjArray<UInt64> packSizes(numInStreams);
|
||||
CObjArray<const UInt64 *> packSizesPointers(numInStreams);
|
||||
CObjArray<const UInt64 *> unpackSizesPointers(numOutStreams);
|
||||
UInt32 j;
|
||||
|
||||
for (j = 0; j < numOutStreams; j++, unpackStreamIndex++)
|
||||
unpackSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndex];
|
||||
|
||||
for (j = 0; j < numInStreams; j++, packStreamIndex++)
|
||||
{
|
||||
int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
|
||||
if (bindPairIndex >= 0)
|
||||
packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + (UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex];
|
||||
else
|
||||
CMyComPtr<ICompressSetFinishMode> setFinishMode;
|
||||
decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode);
|
||||
if (setFinishMode)
|
||||
{
|
||||
int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
|
||||
if (index < 0)
|
||||
return S_FALSE; // check it
|
||||
packSizes[j] = packPositions[index + 1] - packPositions[index];
|
||||
packSizesPointers[j] = &packSizes[j];
|
||||
RINOK(setFinishMode->SetFinishMode(BoolToInt(fullUnpack)));
|
||||
}
|
||||
}
|
||||
|
||||
_mixerCoderCommon->SetCoderInfo(i, packSizesPointers, unpackSizesPointers);
|
||||
}
|
||||
UInt32 mainCoder, temp;
|
||||
bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
|
||||
UInt32 numStreams = (UInt32)coderInfo.NumStreams;
|
||||
|
||||
CObjArray<UInt64> packSizes(numStreams);
|
||||
CObjArray<const UInt64 *> packSizesPointers(numStreams);
|
||||
|
||||
for (UInt32 j = 0; j < numStreams; j++, packStreamIndex++)
|
||||
{
|
||||
int bond = folderInfo.FindBond_for_PackStream(packStreamIndex);
|
||||
|
||||
if (bond >= 0)
|
||||
packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + folderInfo.Bonds[(unsigned)bond].UnpackIndex];
|
||||
else
|
||||
{
|
||||
int index = folderInfo.Find_in_PackStreams(packStreamIndex);
|
||||
if (index < 0)
|
||||
return E_NOTIMPL;
|
||||
packSizes[j] = packPositions[(unsigned)index + 1] - packPositions[(unsigned)index];
|
||||
packSizesPointers[j] = &packSizes[j];
|
||||
}
|
||||
}
|
||||
|
||||
if (_multiThread)
|
||||
_mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);
|
||||
/*
|
||||
else
|
||||
_mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
|
||||
*/
|
||||
const UInt64 *unpackSizesPointer =
|
||||
(unpackSize && i == bindInfo.UnpackCoder) ?
|
||||
unpackSize :
|
||||
&folders.CoderUnpackSizes[unpackStreamIndexStart + i];
|
||||
|
||||
_mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers);
|
||||
}
|
||||
|
||||
if (outStream)
|
||||
{
|
||||
_mixer->SelectMainCoder(!fullUnpack);
|
||||
}
|
||||
|
||||
CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
|
||||
|
||||
CLockedInStream *lockedInStreamSpec = new CLockedInStream;
|
||||
CMyComPtr<IUnknown> lockedInStream = lockedInStreamSpec;
|
||||
|
||||
bool needMtLock = false;
|
||||
|
||||
if (folderInfo.PackStreams.Size() > 1)
|
||||
{
|
||||
// lockedInStream.Pos = (UInt64)(Int64)-1;
|
||||
// RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &lockedInStream.Pos));
|
||||
RINOK(inStream->Seek(startPos + packPositions[0], STREAM_SEEK_SET, &lockedInStreamSpec->Pos));
|
||||
lockedInStreamSpec->Stream = inStream;
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
if (_mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex))
|
||||
#endif
|
||||
needMtLock = true;
|
||||
}
|
||||
|
||||
for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> packStream;
|
||||
UInt64 packPos = startPos + packPositions[j];
|
||||
|
||||
if (folderInfo.PackStreams.Size() == 1)
|
||||
{
|
||||
RINOK(inStream->Seek(packPos, STREAM_SEEK_SET, NULL));
|
||||
packStream = inStream;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef USE_MIXER_MT
|
||||
#ifdef USE_MIXER_ST
|
||||
if (_useMixerMT || needMtLock)
|
||||
#endif
|
||||
{
|
||||
CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT;
|
||||
packStream = lockedStreamImpSpec;
|
||||
lockedStreamImpSpec->Init(lockedInStreamSpec, packPos);
|
||||
}
|
||||
#ifdef USE_MIXER_ST
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
#ifdef USE_MIXER_ST
|
||||
CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST;
|
||||
packStream = lockedStreamImpSpec;
|
||||
lockedStreamImpSpec->Init(lockedInStreamSpec, packPos);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
inStreams.AddNew() = streamSpec;
|
||||
streamSpec->SetStream(packStream);
|
||||
streamSpec->Init(packPositions[j + 1] - packPositions[j]);
|
||||
}
|
||||
|
||||
if (numCoders == 0)
|
||||
return 0;
|
||||
unsigned num = inStreams.Size();
|
||||
CObjArray<ISequentialInStream *> inStreamPointers(num);
|
||||
for (i = 0; i < num; i++)
|
||||
inStreamPointers[i] = inStreams[i];
|
||||
ISequentialOutStream *outStreamPointer = outStream;
|
||||
return _mixerCoder->Code(
|
||||
inStreamPointers, NULL, num,
|
||||
&outStreamPointer, NULL, 1,
|
||||
compressProgress);
|
||||
|
||||
if (outStream)
|
||||
{
|
||||
CMyComPtr<ICompressProgressInfo> progress2;
|
||||
if (compressProgress && !_mixer->Is_PackSize_Correct_for_Coder(_mixer->MainCoderIndex))
|
||||
progress2 = new CDecProgress(compressProgress);
|
||||
|
||||
ISequentialOutStream *outStreamPointer = outStream;
|
||||
return _mixer->Code(inStreamPointers, &outStreamPointer, progress2 ? (ICompressProgressInfo *)progress2 : compressProgress);
|
||||
}
|
||||
|
||||
#ifdef USE_MIXER_ST
|
||||
return _mixerST->GetMainUnpackStream(inStreamPointers, inStreamMainRes);
|
||||
#else
|
||||
return E_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user