1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// SplitHandler.cpp
2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "StdAfx.h"
4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Common/ComTry.h"
6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Common/MyString.h"
7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Windows/PropVariant.h"
9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../Common/ProgressUtils.h"
11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../Common/RegisterArc.h"
12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../Compress/CopyCoder.h"
14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
15baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Common/MultiStream.h"
16baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
17baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing namespace NWindows;
18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
19baa3858d3f5d128a5c8466b700098109edcad5f2repo syncnamespace NArchive {
20baa3858d3f5d128a5c8466b700098109edcad5f2repo syncnamespace NSplit {
21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
22baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTATPROPSTG kProps[] =
23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  { NULL, kpidPath, VT_BSTR},
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  { NULL, kpidSize, VT_UI8}
26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
28baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTATPROPSTG kArcProps[] =
29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  { NULL, kpidNumVolumes, VT_UI4}
31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
33baa3858d3f5d128a5c8466b700098109edcad5f2repo syncclass CHandler:
34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  public IInArchive,
35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  public IInArchiveGetStream,
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  public CMyUnknownImp
37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UString _subName;
39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CObjectVector<CMyComPtr<IInStream> > _streams;
40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CRecordVector<UInt64> _sizes;
41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 _totalSize;
42baa3858d3f5d128a5c8466b700098109edcad5f2repo syncpublic:
43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  INTERFACE_IInArchive(;)
45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
48baa3858d3f5d128a5c8466b700098109edcad5f2repo syncIMP_IInArchive_Props
49baa3858d3f5d128a5c8466b700098109edcad5f2repo syncIMP_IInArchive_ArcProps
50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
51baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  NCOM::CPropVariant prop;
54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  switch(propID)
55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case kpidMainSubfile: prop = (UInt32)0; break;
57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case kpidNumVolumes: prop = (UInt32)_streams.Size(); break;
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  prop.Detach(value);
60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
63baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstruct CSeqName
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UString _unchangedPart;
66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UString _changedPart;
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bool _splitStyle;
68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UString GetNextName()
70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UString newName;
72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (_splitStyle)
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      int i;
75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      int numLetters = _changedPart.Length();
76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      for (i = numLetters - 1; i >= 0; i--)
77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        wchar_t c = _changedPart[i];
79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (c == 'z')
80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          c = 'a';
82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          newName = c + newName;
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          continue;
84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        else if (c == 'Z')
86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          c = 'A';
88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          newName = c + newName;
89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          continue;
90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        c++;
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if ((c == 'z' || c == 'Z') && i == 0)
93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          _unchangedPart += c;
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          wchar_t newChar = (c == 'z') ? L'a' : L'A';
96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          newName.Empty();
97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          numLetters++;
98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          for (int k = 0; k < numLetters; k++)
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            newName += newChar;
100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          break;
101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        newName = c + newName;
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        i--;
104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        for (; i >= 0; i--)
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          newName = _changedPart[i] + newName;
106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        break;
107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      int i;
112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      int numLetters = _changedPart.Length();
113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      for (i = numLetters - 1; i >= 0; i--)
114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        wchar_t c = _changedPart[i];
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (c == L'9')
117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          c = L'0';
119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          newName = c + newName;
120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          if (i == 0)
121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            newName = UString(L'1') + newName;
122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          continue;
123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        c++;
125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        newName = c + newName;
126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        i--;
127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        for (; i >= 0; i--)
128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          newName = _changedPart[i] + newName;
129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        break;
130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
132baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _changedPart = newName;
133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return _unchangedPart + _changedPart;
134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
135baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
137baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CHandler::Open(IInStream *stream,
138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UInt64 * /* maxCheckStartPosition */,
139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IArchiveOpenCallback *openArchiveCallback)
140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  COM_TRY_BEGIN
142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Close();
143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (openArchiveCallback == 0)
144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return S_FALSE;
145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  // try
146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback;
149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback,
150baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        &openVolumeCallback) != S_OK)
151baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return S_FALSE;
152baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
153baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UString name;
154baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
155baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      NCOM::CPropVariant prop;
156baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
157baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (prop.vt != VT_BSTR)
158baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return S_FALSE;
159baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      name = prop.bstrVal;
160baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
161baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
162baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int dotPos = name.ReverseFind('.');
163baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UString prefix, ext;
164baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (dotPos >= 0)
165baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
166baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      prefix = name.Left(dotPos + 1);
167baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      ext = name.Mid(dotPos + 1);
168baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
169baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
170baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      ext = name;
171baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UString extBig = ext;
172baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    extBig.MakeUpper();
173baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
174baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CSeqName seqName;
175baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
176baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int numLetters = 2;
177baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bool splitStyle = false;
178baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (extBig.Right(2) == L"AA")
179baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
180baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      splitStyle = true;
181baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      while (numLetters < extBig.Length())
182baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
183baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (extBig[extBig.Length() - numLetters - 1] != 'A')
184baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          break;
185baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        numLetters++;
186baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
187baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
188baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else if (ext.Right(2) == L"01")
189baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
190baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      while (numLetters < extBig.Length())
191baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
192baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (extBig[extBig.Length() - numLetters - 1] != '0')
193baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          break;
194baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        numLetters++;
195baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
196baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (numLetters != ext.Length())
197baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return S_FALSE;
198baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
199baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
200baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return S_FALSE;
201baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
202baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _streams.Add(stream);
203baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
204baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    seqName._unchangedPart = prefix + ext.Left(extBig.Length() - numLetters);
205baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    seqName._changedPart = ext.Right(numLetters);
206baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    seqName._splitStyle = splitStyle;
207baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
208baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (prefix.Length() < 1)
209baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _subName = L"file";
210baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
211baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _subName = prefix.Left(prefix.Length() - 1);
212baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
213baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _totalSize = 0;
214baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt64 size;
215baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
216baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      NCOM::CPropVariant prop;
217baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(openVolumeCallback->GetProperty(kpidSize, &prop));
218baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (prop.vt != VT_UI8)
219baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return E_INVALIDARG;
220baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      size = prop.uhVal.QuadPart;
221baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
222baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _totalSize += size;
223baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _sizes.Add(size);
224baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
225baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (openArchiveCallback != NULL)
226baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
227baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UInt64 numFiles = _streams.Size();
228baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
229baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
230baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
231baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (;;)
232baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
233baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UString fullName = seqName.GetNextName();
234baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CMyComPtr<IInStream> nextStream;
235baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream);
236baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (result == S_FALSE)
237baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        break;
238baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (result != S_OK)
239baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return result;
240baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (!stream)
241baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        break;
242baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
243baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        NCOM::CPropVariant prop;
244baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        RINOK(openVolumeCallback->GetProperty(kpidSize, &prop));
245baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (prop.vt != VT_UI8)
246baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          return E_INVALIDARG;
247baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        size = prop.uhVal.QuadPart;
248baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
249baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _totalSize += size;
250baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _sizes.Add(size);
251baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _streams.Add(nextStream);
252baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (openArchiveCallback != NULL)
253baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
254baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        UInt64 numFiles = _streams.Size();
255baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
256baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
257baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
258baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
259baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  /*
260baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  catch(...)
261baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
262baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return S_FALSE;
263baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
264baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  */
265baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
266baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  COM_TRY_END
267baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
268baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
269baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CHandler::Close()
270baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
271baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _sizes.Clear();
272baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _streams.Clear();
273baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
274baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
275baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
276baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
277baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
278baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  *numItems = _streams.IsEmpty() ? 0 : 1;
279baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
280baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
281baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
282baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
283baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
284baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  NWindows::NCOM::CPropVariant prop;
285baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  switch(propID)
286baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
287baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case kpidPath: prop = _subName; break;
288baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case kpidSize:
289baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case kpidPackSize:
290baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      prop = _totalSize;
291baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      break;
292baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
293baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  prop.Detach(value);
294baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
295baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
296baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
297baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
298baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Int32 testMode, IArchiveExtractCallback *extractCallback)
299baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
300baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  COM_TRY_BEGIN
301baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (numItems == 0)
302baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return S_OK;
303baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
304baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_INVALIDARG;
305baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
306baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 currentTotalSize = 0;
307baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(extractCallback->SetTotal(_totalSize));
308baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<ISequentialOutStream> outStream;
309baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Int32 askMode = testMode ?
310baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      NExtract::NAskMode::kTest :
311baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      NExtract::NAskMode::kExtract;
312baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(extractCallback->GetStream(0, &outStream, askMode));
313baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!testMode && !outStream)
314baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return S_OK;
315baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(extractCallback->PrepareOperation(askMode));
316baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
317baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
318baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
319baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
320baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CLocalProgress *lps = new CLocalProgress;
321baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<ICompressProgressInfo> progress = lps;
322baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  lps->Init(extractCallback, false);
323baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
324baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (int i = 0; i < _streams.Size(); i++)
325baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
326baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    lps->InSize = lps->OutSize = currentTotalSize;
327baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(lps->SetCur());
328baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IInStream *inStream = _streams[i];
329baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
330baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
331baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    currentTotalSize += copyCoderSpec->TotalSize;
332baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
333baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  outStream.Release();
334baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return extractCallback->SetOperationResult(NExtract::NOperationResult::kOK);
335baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  COM_TRY_END
336baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
337baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
338baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
339baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
340baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  COM_TRY_BEGIN
341baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (index != 0)
342baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_INVALIDARG;
343baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  *stream = 0;
344baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMultiStream *streamSpec = new CMultiStream;
345baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
346baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (int i = 0; i < _streams.Size(); i++)
347baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
348baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMultiStream::CSubStreamInfo subStreamInfo;
349baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    subStreamInfo.Stream = _streams[i];
350baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    subStreamInfo.Size = _sizes[i];
351baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    streamSpec->Streams.Add(subStreamInfo);
352baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
353baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  streamSpec->Init();
354baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  *stream = streamTemp.Detach();
355baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
356baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  COM_TRY_END
357baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
358baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
359baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic IInArchive *CreateArc() { return new CHandler; }
360baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
361baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic CArcInfo g_ArcInfo =
362baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{ L"Split", L"001", 0, 0xEA, { 0 }, 0, false, CreateArc, 0 };
363baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
364baa3858d3f5d128a5c8466b700098109edcad5f2repo syncREGISTER_ARC(Split)
365baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
366baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}}
367