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