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