1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// 7zDecode.cpp
2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "StdAfx.h"
4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../Common/LimitedStreams.h"
6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../Common/LockedStream.h"
7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../Common/ProgressUtils.h"
8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../Common/StreamObjects.h"
9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "7zDecode.h"
11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
12baa3858d3f5d128a5c8466b700098109edcad5f2repo syncnamespace NArchive {
13baa3858d3f5d128a5c8466b700098109edcad5f2repo syncnamespace N7z {
14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
15baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void ConvertFolderItemInfoToBindInfo(const CFolder &folder,
16baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CBindInfoEx &bindInfo)
17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bindInfo.Clear();
19cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  bindInfo.BindPairs.ClearAndSetSize(folder.BindPairs.Size());
20cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  unsigned i;
21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < folder.BindPairs.Size(); i++)
22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
23cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    NCoderMixer::CBindPair &bindPair = bindInfo.BindPairs[i];
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;
26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
27cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
28cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  bindInfo.Coders.ClearAndSetSize(folder.Coders.Size());
29cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  bindInfo.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());
30cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 outStreamIndex = 0;
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < folder.Coders.Size(); i++)
33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
34cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CCoderInfo &coderInfo = folder.Coders[i];
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;
37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;
38cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    bindInfo.CoderMethodIDs[i] = coderInfo.MethodID;
39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        bindInfo.OutStreams.Add(outStreamIndex);
42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
43cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  bindInfo.InStreams.ClearAndSetSize(folder.PackStreams.Size());
44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < folder.PackStreams.Size(); i++)
45cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    bindInfo.InStreams[i] = (UInt32)folder.PackStreams[i];
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
48baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1,
49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const NCoderMixer::CCoderStreamsInfo &a2)
50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return (a1.NumInStreams == a2.NumInStreams) &&
52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    (a1.NumOutStreams == a2.NumOutStreams);
53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
55baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2)
56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return (a1.InIndex == a2.InIndex) &&
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    (a1.OutIndex == a2.OutIndex);
59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
61baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (a1.Coders.Size() != a2.Coders.Size())
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return false;
65cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  unsigned i;
66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < a1.Coders.Size(); i++)
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return false;
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (a1.BindPairs.Size() != a2.BindPairs.Size())
70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return false;
71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < a1.BindPairs.Size(); i++)
72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return false;
74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return false;
77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (a1.InStreams.Size() != a2.InStreams.Size())
78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return false;
79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (a1.OutStreams.Size() != a2.OutStreams.Size())
80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return false;
81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return true;
82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
84baa3858d3f5d128a5c8466b700098109edcad5f2repo syncCDecoder::CDecoder(bool multiThread)
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifndef _ST_MODE
87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  multiThread = true;
88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _multiThread = multiThread;
90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _bindInfoExPrevIsDefined = false;
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
93baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT CDecoder::Decode(
94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    DECL_EXTERNAL_CODECS_LOC_VARS
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IInStream *inStream,
96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt64 startPos,
97cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    const CFolders &folders, int folderIndex,
98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    ISequentialOutStream *outStream,
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    ICompressProgressInfo *compressProgress
100cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    _7Z_DECODER_CRYPRO_VARS_DECL
101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #if !defined(_7ZIP_ST) && !defined(_SFX)
102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    , bool mtMode, UInt32 numThreads
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    )
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
106cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]];
107cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CFolder folderInfo;
108cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  folders.ParseFolderInfo(folderIndex, folderInfo);
109cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
110cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (!folderInfo.CheckStructure(folders.GetNumFolderUnpackSizes(folderIndex)))
111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_NOTIMPL;
112cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
113cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  /*
114cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  We don't need to init isEncrypted and passwordIsDefined
115cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  We must upgrade them only
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifndef _NO_CRYPTO
117cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  isEncrypted = false;
118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  passwordIsDefined = false;
119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
120cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  */
121cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CLockedInStream lockedInStream;
125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  lockedInStream.Init(inStream);
126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
127cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
129cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp;
130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
131cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    lockedStreamImpSpec->Init(&lockedInStream, startPos + packPositions[j]);
132cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<ISequentialInStream> inStream = streamSpec;
134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    streamSpec->SetStream(lockedStreamImp);
135cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    streamSpec->Init(packPositions[j + 1] - packPositions[j]);
136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    inStreams.Add(inStream);
137baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
139cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  unsigned numCoders = folderInfo.Coders.Size();
140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBindInfoEx bindInfo;
142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bool createNewCoders;
144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!_bindInfoExPrevIsDefined)
145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    createNewCoders = true;
146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else
147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (createNewCoders)
149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
150cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    unsigned i;
151baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _decoders.Clear();
152baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    // _decoders2.Clear();
153baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
154baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _mixerCoder.Release();
155baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
156baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (_multiThread)
157baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
158baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT;
159baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _mixerCoder = _mixerCoderMTSpec;
160baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _mixerCoderCommon = _mixerCoderMTSpec;
161baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
162baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
163baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
164baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      #ifdef _ST_MODE
165baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST;
166baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _mixerCoder = _mixerCoderSTSpec;
167baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _mixerCoderCommon = _mixerCoderSTSpec;
168baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      #endif
169baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
170baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(_mixerCoderCommon->SetBindInfo(bindInfo));
171baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
172baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (i = 0; i < numCoders; i++)
173baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
174baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      const CCoderInfo &coderInfo = folderInfo.Coders[i];
175baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
176baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
177baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CMyComPtr<ICompressCoder> decoder;
178baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CMyComPtr<ICompressCoder2> decoder2;
179baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(CreateCoder(
180baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          EXTERNAL_CODECS_LOC_VARS
181baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          coderInfo.MethodID, decoder, decoder2, false));
182baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CMyComPtr<IUnknown> decoderUnknown;
183baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (coderInfo.IsSimpleCoder())
184baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
185baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (decoder == 0)
186baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          return E_NOTIMPL;
187baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
188baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        decoderUnknown = (IUnknown *)decoder;
189baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
190baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (_multiThread)
191baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          _mixerCoderMTSpec->AddCoder(decoder);
192baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        #ifdef _ST_MODE
193baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        else
194baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          _mixerCoderSTSpec->AddCoder(decoder, false);
195baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        #endif
196baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
197baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      else
198baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
199baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (decoder2 == 0)
200baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          return E_NOTIMPL;
201baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        decoderUnknown = (IUnknown *)decoder2;
202baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (_multiThread)
203baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          _mixerCoderMTSpec->AddCoder2(decoder2);
204baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        #ifdef _ST_MODE
205baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        else
206baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          _mixerCoderSTSpec->AddCoder2(decoder2, false);
207baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        #endif
208baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
209baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _decoders.Add(decoderUnknown);
210baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      #ifdef EXTERNAL_CODECS
211baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
212baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
213baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (setCompressCodecsInfo)
214baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
215cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));
216baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
217baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      #endif
218baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
219baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _bindInfoExPrev = bindInfo;
220baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _bindInfoExPrevIsDefined = true;
221baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
222cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  unsigned i;
223baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _mixerCoderCommon->ReInit();
224baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
225cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  UInt32 packStreamIndex = 0;
226cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex];
227cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  UInt32 unpackStreamIndex = unpackStreamIndexStart;
228baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 coderIndex = 0;
229baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  // UInt32 coder2Index = 0;
230baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
231baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < numCoders; i++)
232baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
233baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CCoderInfo &coderInfo = folderInfo.Coders[i];
234baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];
235baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
236baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
237baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
238baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
239baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (setDecoderProperties)
240baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
241baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        const CByteBuffer &props = coderInfo.Props;
242cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        size_t size = props.Size();
243baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (size > 0xFFFFFFFF)
244baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          return E_NOTIMPL;
245baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        // if (size > 0)
246baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
247baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size));
248baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
249baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
250baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
251baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
252baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #if !defined(_7ZIP_ST) && !defined(_SFX)
253baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (mtMode)
254baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
255baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CMyComPtr<ICompressSetCoderMt> setCoderMt;
256baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
257baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (setCoderMt)
258baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
259baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        RINOK(setCoderMt->SetNumberOfThreads(numThreads));
260baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
261baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
262baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
263baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
264baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifndef _NO_CRYPTO
265baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
266baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
267baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
268baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (cryptoSetPassword)
269baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
270cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        isEncrypted = true;
271cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        if (!getTextPassword)
272cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky          return E_NOTIMPL;
273baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        CMyComBSTR passwordBSTR;
274baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));
275baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        passwordIsDefined = true;
276cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        size_t len = 0;
277cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        if (passwordBSTR)
278cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky          len = MyStringLen((BSTR)passwordBSTR);
279cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        CByteBuffer buffer(len * 2);
280cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        for (size_t i = 0; i < len; i++)
281baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
282cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky          wchar_t c = passwordBSTR[i];
283baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          ((Byte *)buffer)[i * 2] = (Byte)c;
284baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
285baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
286cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()));
287baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
288baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
289baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
290baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
291baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    coderIndex++;
292baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
293baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;
294baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;
295cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    CObjArray<UInt64> packSizes(numInStreams);
296cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    CObjArray<const UInt64 *> packSizesPointers(numInStreams);
297cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    CObjArray<const UInt64 *> unpackSizesPointers(numOutStreams);
298baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 j;
299cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
300baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (j = 0; j < numOutStreams; j++, unpackStreamIndex++)
301cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      unpackSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndex];
302baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
303baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (j = 0; j < numInStreams; j++, packStreamIndex++)
304baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
305baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
306baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (bindPairIndex >= 0)
307cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + (UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex];
308baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      else
309baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
310baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
311baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (index < 0)
312cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky          return S_FALSE; // check it
313cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        packSizes[j] = packPositions[index + 1] - packPositions[index];
314cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        packSizesPointers[j] = &packSizes[j];
315baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
316baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
317baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
318cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    _mixerCoderCommon->SetCoderInfo(i, packSizesPointers, unpackSizesPointers);
319baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
320baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 mainCoder, temp;
321baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
322baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
323baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (_multiThread)
324baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);
325baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  /*
326baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else
327baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
328baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  */
329baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
330baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (numCoders == 0)
331baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return 0;
332cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  unsigned num = inStreams.Size();
333cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CObjArray<ISequentialInStream *> inStreamPointers(num);
334cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  for (i = 0; i < num; i++)
335cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    inStreamPointers[i] = inStreams[i];
336baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ISequentialOutStream *outStreamPointer = outStream;
337cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  return _mixerCoder->Code(
338cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      inStreamPointers, NULL, num,
339cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      &outStreamPointer, NULL, 1,
340cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      compressProgress);
341baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
342baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
343baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}}
344