xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/MslzHandler.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // MslzHandler.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 "../../../C/CpuArch.h"
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyString.h"
9*f6dc9357SAndroid Build Coastguard Worker 
10*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariant.h"
11*f6dc9357SAndroid Build Coastguard Worker 
12*f6dc9357SAndroid Build Coastguard Worker #include "../Common/InBuffer.h"
13*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ProgressUtils.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
16*f6dc9357SAndroid Build Coastguard Worker 
17*f6dc9357SAndroid Build Coastguard Worker #include "Common/DummyOutStream.h"
18*f6dc9357SAndroid Build Coastguard Worker 
19*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
20*f6dc9357SAndroid Build Coastguard Worker namespace NMslz {
21*f6dc9357SAndroid Build Coastguard Worker 
22*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kUnpackSizeMax = 0xFFFFFFE0;
23*f6dc9357SAndroid Build Coastguard Worker 
24*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_CHandler_IInArchive_1(
25*f6dc9357SAndroid Build Coastguard Worker   IArchiveOpenSeq
26*f6dc9357SAndroid Build Coastguard Worker )
27*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IInStream> _inStream;
28*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialInStream> _seqStream;
29*f6dc9357SAndroid Build Coastguard Worker 
30*f6dc9357SAndroid Build Coastguard Worker   bool _isArc;
31*f6dc9357SAndroid Build Coastguard Worker   bool _needSeekToStart;
32*f6dc9357SAndroid Build Coastguard Worker   bool _dataAfterEnd;
33*f6dc9357SAndroid Build Coastguard Worker   bool _needMoreInput;
34*f6dc9357SAndroid Build Coastguard Worker 
35*f6dc9357SAndroid Build Coastguard Worker   bool _packSize_Defined;
36*f6dc9357SAndroid Build Coastguard Worker   bool _unpackSize_Defined;
37*f6dc9357SAndroid Build Coastguard Worker 
38*f6dc9357SAndroid Build Coastguard Worker   UInt32 _unpackSize;
39*f6dc9357SAndroid Build Coastguard Worker   UInt64 _packSize;
40*f6dc9357SAndroid Build Coastguard Worker   UInt64 _originalFileSize;
41*f6dc9357SAndroid Build Coastguard Worker   UString _name;
42*f6dc9357SAndroid Build Coastguard Worker 
43*f6dc9357SAndroid Build Coastguard Worker   void ParseName(Byte replaceByte, IArchiveOpenCallback *callback);
44*f6dc9357SAndroid Build Coastguard Worker };
45*f6dc9357SAndroid Build Coastguard Worker 
46*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
47*f6dc9357SAndroid Build Coastguard Worker {
48*f6dc9357SAndroid Build Coastguard Worker   kpidPath,
49*f6dc9357SAndroid Build Coastguard Worker   kpidSize,
50*f6dc9357SAndroid Build Coastguard Worker   kpidPackSize,
51*f6dc9357SAndroid Build Coastguard Worker };
52*f6dc9357SAndroid Build Coastguard Worker 
53*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
54*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps_NO_Table
55*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::GetNumberOfItems (UInt32 * numItems))56*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
57*f6dc9357SAndroid Build Coastguard Worker {
58*f6dc9357SAndroid Build Coastguard Worker   *numItems = 1;
59*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
60*f6dc9357SAndroid Build Coastguard Worker }
61*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::GetArchiveProperty (PROPID propID,PROPVARIANT * value))62*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
63*f6dc9357SAndroid Build Coastguard Worker {
64*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
65*f6dc9357SAndroid Build Coastguard Worker   NWindows::NCOM::CPropVariant prop;
66*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
67*f6dc9357SAndroid Build Coastguard Worker   {
68*f6dc9357SAndroid Build Coastguard Worker     case kpidExtension: prop = "mslz"; break;
69*f6dc9357SAndroid Build Coastguard Worker     case kpidIsNotArcType: prop = true; break;
70*f6dc9357SAndroid Build Coastguard Worker     case kpidPhySize: if (_packSize_Defined) prop = _packSize; break;
71*f6dc9357SAndroid Build Coastguard Worker     case kpidErrorFlags:
72*f6dc9357SAndroid Build Coastguard Worker     {
73*f6dc9357SAndroid Build Coastguard Worker       UInt32 v = 0;
74*f6dc9357SAndroid Build Coastguard Worker       if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
75*f6dc9357SAndroid Build Coastguard Worker       if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;
76*f6dc9357SAndroid Build Coastguard Worker       if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;
77*f6dc9357SAndroid Build Coastguard Worker       prop = v;
78*f6dc9357SAndroid Build Coastguard Worker       break;
79*f6dc9357SAndroid Build Coastguard Worker     }
80*f6dc9357SAndroid Build Coastguard Worker   }
81*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
82*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
83*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
84*f6dc9357SAndroid Build Coastguard Worker }
85*f6dc9357SAndroid Build Coastguard Worker 
86*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::GetProperty (UInt32,PROPID propID,PROPVARIANT * value))87*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))
88*f6dc9357SAndroid Build Coastguard Worker {
89*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
90*f6dc9357SAndroid Build Coastguard Worker   NWindows::NCOM::CPropVariant prop;
91*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
92*f6dc9357SAndroid Build Coastguard Worker   {
93*f6dc9357SAndroid Build Coastguard Worker     case kpidPath: if (!_name.IsEmpty()) prop = _name; break;
94*f6dc9357SAndroid Build Coastguard Worker     case kpidSize: if (_unpackSize_Defined || _inStream) prop = _unpackSize; break;
95*f6dc9357SAndroid Build Coastguard Worker     case kpidPackSize: if (_packSize_Defined || _inStream) prop = _packSize; break;
96*f6dc9357SAndroid Build Coastguard Worker   }
97*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
98*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
99*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
100*f6dc9357SAndroid Build Coastguard Worker }
101*f6dc9357SAndroid Build Coastguard Worker 
102*f6dc9357SAndroid Build Coastguard Worker static const unsigned kSignatureSize = 9;
103*f6dc9357SAndroid Build Coastguard Worker static const unsigned kHeaderSize = kSignatureSize + 1 + 4;
104*f6dc9357SAndroid Build Coastguard Worker #define MSLZ_SIGNATURE { 0x53, 0x5A, 0x44, 0x44, 0x88, 0xF0, 0x27, 0x33, 0x41 }
105*f6dc9357SAndroid Build Coastguard Worker // old signature: 53 5A 20 88 F0 27 33
106*f6dc9357SAndroid Build Coastguard Worker static const Byte kSignature[kSignatureSize] = MSLZ_SIGNATURE;
107*f6dc9357SAndroid Build Coastguard Worker 
108*f6dc9357SAndroid Build Coastguard Worker // we support only 3 chars strings here
109*f6dc9357SAndroid Build Coastguard Worker static const char * const g_Exts[] =
110*f6dc9357SAndroid Build Coastguard Worker {
111*f6dc9357SAndroid Build Coastguard Worker     "bin"
112*f6dc9357SAndroid Build Coastguard Worker   , "dll"
113*f6dc9357SAndroid Build Coastguard Worker   , "exe"
114*f6dc9357SAndroid Build Coastguard Worker   , "kmd"
115*f6dc9357SAndroid Build Coastguard Worker   , "pdf"
116*f6dc9357SAndroid Build Coastguard Worker   , "sys"
117*f6dc9357SAndroid Build Coastguard Worker };
118*f6dc9357SAndroid Build Coastguard Worker 
ParseName(Byte replaceByte,IArchiveOpenCallback * callback)119*f6dc9357SAndroid Build Coastguard Worker void CHandler::ParseName(Byte replaceByte, IArchiveOpenCallback *callback)
120*f6dc9357SAndroid Build Coastguard Worker {
121*f6dc9357SAndroid Build Coastguard Worker   if (!callback)
122*f6dc9357SAndroid Build Coastguard Worker     return;
123*f6dc9357SAndroid Build Coastguard Worker   Z7_DECL_CMyComPtr_QI_FROM(IArchiveOpenVolumeCallback, volumeCallback, callback)
124*f6dc9357SAndroid Build Coastguard Worker   if (!volumeCallback)
125*f6dc9357SAndroid Build Coastguard Worker     return;
126*f6dc9357SAndroid Build Coastguard Worker 
127*f6dc9357SAndroid Build Coastguard Worker   NWindows::NCOM::CPropVariant prop;
128*f6dc9357SAndroid Build Coastguard Worker   if (volumeCallback->GetProperty(kpidName, &prop) != S_OK || prop.vt != VT_BSTR)
129*f6dc9357SAndroid Build Coastguard Worker     return;
130*f6dc9357SAndroid Build Coastguard Worker 
131*f6dc9357SAndroid Build Coastguard Worker   UString s = prop.bstrVal;
132*f6dc9357SAndroid Build Coastguard Worker   if (s.IsEmpty() ||
133*f6dc9357SAndroid Build Coastguard Worker       s.Back() != L'_')
134*f6dc9357SAndroid Build Coastguard Worker     return;
135*f6dc9357SAndroid Build Coastguard Worker 
136*f6dc9357SAndroid Build Coastguard Worker   s.DeleteBack();
137*f6dc9357SAndroid Build Coastguard Worker   _name = s;
138*f6dc9357SAndroid Build Coastguard Worker 
139*f6dc9357SAndroid Build Coastguard Worker   if (replaceByte == 0)
140*f6dc9357SAndroid Build Coastguard Worker   {
141*f6dc9357SAndroid Build Coastguard Worker     if (s.Len() < 3 || s[s.Len() - 3] != '.')
142*f6dc9357SAndroid Build Coastguard Worker       return;
143*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_Exts); i++)
144*f6dc9357SAndroid Build Coastguard Worker     {
145*f6dc9357SAndroid Build Coastguard Worker       const char *ext = g_Exts[i];
146*f6dc9357SAndroid Build Coastguard Worker       if (s[s.Len() - 2] == (Byte)ext[0] &&
147*f6dc9357SAndroid Build Coastguard Worker           s[s.Len() - 1] == (Byte)ext[1])
148*f6dc9357SAndroid Build Coastguard Worker       {
149*f6dc9357SAndroid Build Coastguard Worker         replaceByte = (Byte)ext[2];
150*f6dc9357SAndroid Build Coastguard Worker         break;
151*f6dc9357SAndroid Build Coastguard Worker       }
152*f6dc9357SAndroid Build Coastguard Worker     }
153*f6dc9357SAndroid Build Coastguard Worker   }
154*f6dc9357SAndroid Build Coastguard Worker 
155*f6dc9357SAndroid Build Coastguard Worker   if (replaceByte >= 0x20 && replaceByte < 0x80)
156*f6dc9357SAndroid Build Coastguard Worker     _name.Add_Char((char)replaceByte);
157*f6dc9357SAndroid Build Coastguard Worker }
158*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::Open (IInStream * stream,const UInt64 *,IArchiveOpenCallback * callback))159*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */,
160*f6dc9357SAndroid Build Coastguard Worker     IArchiveOpenCallback *callback))
161*f6dc9357SAndroid Build Coastguard Worker {
162*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
163*f6dc9357SAndroid Build Coastguard Worker   {
164*f6dc9357SAndroid Build Coastguard Worker     Close();
165*f6dc9357SAndroid Build Coastguard Worker     _needSeekToStart = true;
166*f6dc9357SAndroid Build Coastguard Worker     Byte buffer[kHeaderSize];
167*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadStream_FALSE(stream, buffer, kHeaderSize))
168*f6dc9357SAndroid Build Coastguard Worker     if (memcmp(buffer, kSignature, kSignatureSize) != 0)
169*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
170*f6dc9357SAndroid Build Coastguard Worker     _unpackSize = GetUi32(buffer + 10);
171*f6dc9357SAndroid Build Coastguard Worker     if (_unpackSize > kUnpackSizeMax)
172*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
173*f6dc9357SAndroid Build Coastguard Worker     RINOK(InStream_GetSize_SeekToEnd(stream, _originalFileSize))
174*f6dc9357SAndroid Build Coastguard Worker     _packSize = _originalFileSize;
175*f6dc9357SAndroid Build Coastguard Worker 
176*f6dc9357SAndroid Build Coastguard Worker     ParseName(buffer[kSignatureSize], callback);
177*f6dc9357SAndroid Build Coastguard Worker 
178*f6dc9357SAndroid Build Coastguard Worker     _isArc = true;
179*f6dc9357SAndroid Build Coastguard Worker     _unpackSize_Defined = true;
180*f6dc9357SAndroid Build Coastguard Worker     _inStream = stream;
181*f6dc9357SAndroid Build Coastguard Worker     _seqStream = stream;
182*f6dc9357SAndroid Build Coastguard Worker   }
183*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
184*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
185*f6dc9357SAndroid Build Coastguard Worker }
186*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::Close ())187*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
188*f6dc9357SAndroid Build Coastguard Worker {
189*f6dc9357SAndroid Build Coastguard Worker   _originalFileSize = 0;
190*f6dc9357SAndroid Build Coastguard Worker   _packSize = 0;
191*f6dc9357SAndroid Build Coastguard Worker   _unpackSize = 0;
192*f6dc9357SAndroid Build Coastguard Worker 
193*f6dc9357SAndroid Build Coastguard Worker   _isArc = false;
194*f6dc9357SAndroid Build Coastguard Worker   _needSeekToStart = false;
195*f6dc9357SAndroid Build Coastguard Worker   _dataAfterEnd = false;
196*f6dc9357SAndroid Build Coastguard Worker   _needMoreInput = false;
197*f6dc9357SAndroid Build Coastguard Worker 
198*f6dc9357SAndroid Build Coastguard Worker   _packSize_Defined = false;
199*f6dc9357SAndroid Build Coastguard Worker   _unpackSize_Defined =  false;
200*f6dc9357SAndroid Build Coastguard Worker 
201*f6dc9357SAndroid Build Coastguard Worker   _seqStream.Release();
202*f6dc9357SAndroid Build Coastguard Worker   _inStream.Release();
203*f6dc9357SAndroid Build Coastguard Worker   _name.Empty();
204*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
205*f6dc9357SAndroid Build Coastguard Worker }
206*f6dc9357SAndroid Build Coastguard Worker 
207*f6dc9357SAndroid Build Coastguard Worker // MslzDec is modified LZSS algorithm of Haruhiko Okumura:
208*f6dc9357SAndroid Build Coastguard Worker //   maxLen = 18; Okumura
209*f6dc9357SAndroid Build Coastguard Worker //   maxLen = 16; MS
210*f6dc9357SAndroid Build Coastguard Worker 
211*f6dc9357SAndroid Build Coastguard Worker #define PROGRESS_AND_WRITE \
212*f6dc9357SAndroid Build Coastguard Worker   if ((dest & kMask) == 0) { if (outStream) RINOK(WriteStream(outStream, buf, kBufSize)); \
213*f6dc9357SAndroid Build Coastguard Worker     if ((dest & ((1 << 20) - 1)) == 0) \
214*f6dc9357SAndroid Build Coastguard Worker     if (progress) \
215*f6dc9357SAndroid Build Coastguard Worker       { UInt64 inSize = inStream.GetProcessedSize(); UInt64 outSize = dest; \
216*f6dc9357SAndroid Build Coastguard Worker         RINOK(progress->SetRatioInfo(&inSize, &outSize)); }}
217*f6dc9357SAndroid Build Coastguard Worker 
MslzDec(CInBuffer & inStream,ISequentialOutStream * outStream,UInt32 unpackSize,bool & needMoreData,ICompressProgressInfo * progress)218*f6dc9357SAndroid Build Coastguard Worker static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UInt32 unpackSize, bool &needMoreData, ICompressProgressInfo *progress)
219*f6dc9357SAndroid Build Coastguard Worker {
220*f6dc9357SAndroid Build Coastguard Worker   const unsigned kBufSize = (1 << 12);
221*f6dc9357SAndroid Build Coastguard Worker   const unsigned kMask = kBufSize - 1;
222*f6dc9357SAndroid Build Coastguard Worker   Byte buf[kBufSize];
223*f6dc9357SAndroid Build Coastguard Worker   UInt32 dest = 0;
224*f6dc9357SAndroid Build Coastguard Worker   memset(buf, ' ', kBufSize);
225*f6dc9357SAndroid Build Coastguard Worker 
226*f6dc9357SAndroid Build Coastguard Worker   while (dest < unpackSize)
227*f6dc9357SAndroid Build Coastguard Worker   {
228*f6dc9357SAndroid Build Coastguard Worker     Byte b;
229*f6dc9357SAndroid Build Coastguard Worker     if (!inStream.ReadByte(b))
230*f6dc9357SAndroid Build Coastguard Worker     {
231*f6dc9357SAndroid Build Coastguard Worker       needMoreData = true;
232*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
233*f6dc9357SAndroid Build Coastguard Worker     }
234*f6dc9357SAndroid Build Coastguard Worker 
235*f6dc9357SAndroid Build Coastguard Worker     for (unsigned mask = (unsigned)b | 0x100; mask > 1 && dest < unpackSize; mask >>= 1)
236*f6dc9357SAndroid Build Coastguard Worker     {
237*f6dc9357SAndroid Build Coastguard Worker       if (!inStream.ReadByte(b))
238*f6dc9357SAndroid Build Coastguard Worker       {
239*f6dc9357SAndroid Build Coastguard Worker         needMoreData = true;
240*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
241*f6dc9357SAndroid Build Coastguard Worker       }
242*f6dc9357SAndroid Build Coastguard Worker 
243*f6dc9357SAndroid Build Coastguard Worker       if (mask & 1)
244*f6dc9357SAndroid Build Coastguard Worker       {
245*f6dc9357SAndroid Build Coastguard Worker         buf[dest++ & kMask] = b;
246*f6dc9357SAndroid Build Coastguard Worker         PROGRESS_AND_WRITE
247*f6dc9357SAndroid Build Coastguard Worker       }
248*f6dc9357SAndroid Build Coastguard Worker       else
249*f6dc9357SAndroid Build Coastguard Worker       {
250*f6dc9357SAndroid Build Coastguard Worker         Byte b1;
251*f6dc9357SAndroid Build Coastguard Worker         if (!inStream.ReadByte(b1))
252*f6dc9357SAndroid Build Coastguard Worker         {
253*f6dc9357SAndroid Build Coastguard Worker           needMoreData = true;
254*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
255*f6dc9357SAndroid Build Coastguard Worker         }
256*f6dc9357SAndroid Build Coastguard Worker         const unsigned kMaxLen = 16; // 18 in Okumura's code.
257*f6dc9357SAndroid Build Coastguard Worker         unsigned src = (((((unsigned)b1 & 0xF0) << 4) | b) + kMaxLen) & kMask;
258*f6dc9357SAndroid Build Coastguard Worker         unsigned len = (b1 & 0xF) + 3;
259*f6dc9357SAndroid Build Coastguard Worker         if (len > kMaxLen || dest + len > unpackSize)
260*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
261*f6dc9357SAndroid Build Coastguard Worker 
262*f6dc9357SAndroid Build Coastguard Worker         do
263*f6dc9357SAndroid Build Coastguard Worker         {
264*f6dc9357SAndroid Build Coastguard Worker           buf[dest++ & kMask] = buf[src++ & kMask];
265*f6dc9357SAndroid Build Coastguard Worker           PROGRESS_AND_WRITE
266*f6dc9357SAndroid Build Coastguard Worker         }
267*f6dc9357SAndroid Build Coastguard Worker         while (--len != 0);
268*f6dc9357SAndroid Build Coastguard Worker       }
269*f6dc9357SAndroid Build Coastguard Worker     }
270*f6dc9357SAndroid Build Coastguard Worker   }
271*f6dc9357SAndroid Build Coastguard Worker 
272*f6dc9357SAndroid Build Coastguard Worker   if (outStream)
273*f6dc9357SAndroid Build Coastguard Worker     RINOK(WriteStream(outStream, buf, dest & kMask))
274*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
275*f6dc9357SAndroid Build Coastguard Worker }
276*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::OpenSeq (ISequentialInStream * stream))277*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))
278*f6dc9357SAndroid Build Coastguard Worker {
279*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
280*f6dc9357SAndroid Build Coastguard Worker   Close();
281*f6dc9357SAndroid Build Coastguard Worker   _isArc = true;
282*f6dc9357SAndroid Build Coastguard Worker   _seqStream = stream;
283*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
284*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
285*f6dc9357SAndroid Build Coastguard Worker }
286*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::Extract (const UInt32 * indices,UInt32 numItems,Int32 testMode,IArchiveExtractCallback * extractCallback))287*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
288*f6dc9357SAndroid Build Coastguard Worker     Int32 testMode, IArchiveExtractCallback *extractCallback))
289*f6dc9357SAndroid Build Coastguard Worker {
290*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
291*f6dc9357SAndroid Build Coastguard Worker   if (numItems == 0)
292*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
293*f6dc9357SAndroid Build Coastguard Worker   if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
294*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
295*f6dc9357SAndroid Build Coastguard Worker 
296*f6dc9357SAndroid Build Coastguard Worker   // RINOK(extractCallback->SetTotal(_unpackSize))
297*f6dc9357SAndroid Build Coastguard Worker   Int32 opRes;
298*f6dc9357SAndroid Build Coastguard Worker   {
299*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialOutStream> realOutStream;
300*f6dc9357SAndroid Build Coastguard Worker   const Int32 askMode = testMode ?
301*f6dc9357SAndroid Build Coastguard Worker       NExtract::NAskMode::kTest :
302*f6dc9357SAndroid Build Coastguard Worker       NExtract::NAskMode::kExtract;
303*f6dc9357SAndroid Build Coastguard Worker   RINOK(extractCallback->GetStream(0, &realOutStream, askMode))
304*f6dc9357SAndroid Build Coastguard Worker   if (!testMode && !realOutStream)
305*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
306*f6dc9357SAndroid Build Coastguard Worker 
307*f6dc9357SAndroid Build Coastguard Worker   RINOK(extractCallback->PrepareOperation(askMode))
308*f6dc9357SAndroid Build Coastguard Worker 
309*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<ISequentialOutStream, CDummyOutStream> outStream;
310*f6dc9357SAndroid Build Coastguard Worker   outStream->SetStream(realOutStream);
311*f6dc9357SAndroid Build Coastguard Worker   outStream->Init();
312*f6dc9357SAndroid Build Coastguard Worker   // realOutStream.Release();
313*f6dc9357SAndroid Build Coastguard Worker 
314*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
315*f6dc9357SAndroid Build Coastguard Worker   lps->Init(extractCallback, false);
316*f6dc9357SAndroid Build Coastguard Worker 
317*f6dc9357SAndroid Build Coastguard Worker   if (_needSeekToStart)
318*f6dc9357SAndroid Build Coastguard Worker   {
319*f6dc9357SAndroid Build Coastguard Worker     if (!_inStream)
320*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
321*f6dc9357SAndroid Build Coastguard Worker     RINOK(InStream_SeekToBegin(_inStream))
322*f6dc9357SAndroid Build Coastguard Worker   }
323*f6dc9357SAndroid Build Coastguard Worker   else
324*f6dc9357SAndroid Build Coastguard Worker     _needSeekToStart = true;
325*f6dc9357SAndroid Build Coastguard Worker 
326*f6dc9357SAndroid Build Coastguard Worker   opRes = NExtract::NOperationResult::kDataError;
327*f6dc9357SAndroid Build Coastguard Worker 
328*f6dc9357SAndroid Build Coastguard Worker   bool isArc = false;
329*f6dc9357SAndroid Build Coastguard Worker   bool needMoreInput = false;
330*f6dc9357SAndroid Build Coastguard Worker   try
331*f6dc9357SAndroid Build Coastguard Worker   {
332*f6dc9357SAndroid Build Coastguard Worker     CInBuffer s;
333*f6dc9357SAndroid Build Coastguard Worker     if (!s.Create(1 << 20))
334*f6dc9357SAndroid Build Coastguard Worker       return E_OUTOFMEMORY;
335*f6dc9357SAndroid Build Coastguard Worker     s.SetStream(_seqStream);
336*f6dc9357SAndroid Build Coastguard Worker     s.Init();
337*f6dc9357SAndroid Build Coastguard Worker 
338*f6dc9357SAndroid Build Coastguard Worker     Byte buffer[kHeaderSize];
339*f6dc9357SAndroid Build Coastguard Worker     if (s.ReadBytes(buffer, kHeaderSize) == kHeaderSize)
340*f6dc9357SAndroid Build Coastguard Worker     {
341*f6dc9357SAndroid Build Coastguard Worker       UInt32 unpackSize;
342*f6dc9357SAndroid Build Coastguard Worker       if (memcmp(buffer, kSignature, kSignatureSize) == 0)
343*f6dc9357SAndroid Build Coastguard Worker       {
344*f6dc9357SAndroid Build Coastguard Worker         unpackSize = GetUi32(buffer + 10);
345*f6dc9357SAndroid Build Coastguard Worker         if (unpackSize <= kUnpackSizeMax)
346*f6dc9357SAndroid Build Coastguard Worker         {
347*f6dc9357SAndroid Build Coastguard Worker           const HRESULT result = MslzDec(s, outStream, unpackSize, needMoreInput, lps);
348*f6dc9357SAndroid Build Coastguard Worker           if (result == S_OK)
349*f6dc9357SAndroid Build Coastguard Worker             opRes = NExtract::NOperationResult::kOK;
350*f6dc9357SAndroid Build Coastguard Worker           else if (result != S_FALSE)
351*f6dc9357SAndroid Build Coastguard Worker             return result;
352*f6dc9357SAndroid Build Coastguard Worker           _unpackSize = unpackSize;
353*f6dc9357SAndroid Build Coastguard Worker           _unpackSize_Defined = true;
354*f6dc9357SAndroid Build Coastguard Worker 
355*f6dc9357SAndroid Build Coastguard Worker           _packSize = s.GetProcessedSize();
356*f6dc9357SAndroid Build Coastguard Worker           _packSize_Defined = true;
357*f6dc9357SAndroid Build Coastguard Worker 
358*f6dc9357SAndroid Build Coastguard Worker           if (_inStream && _packSize < _originalFileSize)
359*f6dc9357SAndroid Build Coastguard Worker             _dataAfterEnd = true;
360*f6dc9357SAndroid Build Coastguard Worker 
361*f6dc9357SAndroid Build Coastguard Worker           isArc = true;
362*f6dc9357SAndroid Build Coastguard Worker         }
363*f6dc9357SAndroid Build Coastguard Worker       }
364*f6dc9357SAndroid Build Coastguard Worker     }
365*f6dc9357SAndroid Build Coastguard Worker   }
366*f6dc9357SAndroid Build Coastguard Worker   catch (CInBufferException &e) { return e.ErrorCode; }
367*f6dc9357SAndroid Build Coastguard Worker 
368*f6dc9357SAndroid Build Coastguard Worker   _isArc = isArc;
369*f6dc9357SAndroid Build Coastguard Worker   if (isArc)
370*f6dc9357SAndroid Build Coastguard Worker     _needMoreInput = needMoreInput;
371*f6dc9357SAndroid Build Coastguard Worker   if (!_isArc)
372*f6dc9357SAndroid Build Coastguard Worker     opRes = NExtract::NOperationResult::kIsNotArc;
373*f6dc9357SAndroid Build Coastguard Worker   else if (_needMoreInput)
374*f6dc9357SAndroid Build Coastguard Worker     opRes = NExtract::NOperationResult::kUnexpectedEnd;
375*f6dc9357SAndroid Build Coastguard Worker   else if (_dataAfterEnd)
376*f6dc9357SAndroid Build Coastguard Worker     opRes = NExtract::NOperationResult::kDataAfterEnd;
377*f6dc9357SAndroid Build Coastguard Worker   }
378*f6dc9357SAndroid Build Coastguard Worker   return extractCallback->SetOperationResult(opRes);
379*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
380*f6dc9357SAndroid Build Coastguard Worker }
381*f6dc9357SAndroid Build Coastguard Worker 
382*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
383*f6dc9357SAndroid Build Coastguard Worker   "MsLZ", "mslz", NULL, 0xD5,
384*f6dc9357SAndroid Build Coastguard Worker   kSignature,
385*f6dc9357SAndroid Build Coastguard Worker   0,
386*f6dc9357SAndroid Build Coastguard Worker   0,
387*f6dc9357SAndroid Build Coastguard Worker   NULL)
388*f6dc9357SAndroid Build Coastguard Worker 
389*f6dc9357SAndroid Build Coastguard Worker }}
390