1*f6dc9357SAndroid Build Coastguard Worker // LzhHandler.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/AutoPtr.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyBuffer.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StringConvert.h"
11*f6dc9357SAndroid Build Coastguard Worker
12*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariant.h"
13*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariantUtils.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/TimeUtils.h"
15*f6dc9357SAndroid Build Coastguard Worker
16*f6dc9357SAndroid Build Coastguard Worker #include "../ICoder.h"
17*f6dc9357SAndroid Build Coastguard Worker
18*f6dc9357SAndroid Build Coastguard Worker #include "../Common/LimitedStreams.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ProgressUtils.h"
20*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
21*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
22*f6dc9357SAndroid Build Coastguard Worker
23*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/CopyCoder.h"
24*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/LzhDecoder.h"
25*f6dc9357SAndroid Build Coastguard Worker
26*f6dc9357SAndroid Build Coastguard Worker #include "IArchive.h"
27*f6dc9357SAndroid Build Coastguard Worker
28*f6dc9357SAndroid Build Coastguard Worker #include "Common/ItemNameUtils.h"
29*f6dc9357SAndroid Build Coastguard Worker
30*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
31*f6dc9357SAndroid Build Coastguard Worker using namespace NTime;
32*f6dc9357SAndroid Build Coastguard Worker
33*f6dc9357SAndroid Build Coastguard Worker #define Get16(p) GetUi16(p)
34*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetUi32(p)
35*f6dc9357SAndroid Build Coastguard Worker
36*f6dc9357SAndroid Build Coastguard Worker
37*f6dc9357SAndroid Build Coastguard Worker // CRC-16 (-IBM, -ANSI). The poly is 0x8005 (x^16 + x^15 + x^2 + 1)
38*f6dc9357SAndroid Build Coastguard Worker
39*f6dc9357SAndroid Build Coastguard Worker static const UInt16 kCrc16Poly = 0xA001;
40*f6dc9357SAndroid Build Coastguard Worker
41*f6dc9357SAndroid Build Coastguard Worker MY_ALIGN(64)
42*f6dc9357SAndroid Build Coastguard Worker static UInt16 g_LzhCrc16Table[256];
43*f6dc9357SAndroid Build Coastguard Worker
44*f6dc9357SAndroid Build Coastguard Worker #define CRC16_UPDATE_BYTE(crc, b) (g_LzhCrc16Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
45*f6dc9357SAndroid Build Coastguard Worker
46*f6dc9357SAndroid Build Coastguard Worker UInt32 LzhCrc16Update(UInt32 crc, const void *data, size_t size);
LzhCrc16Update(UInt32 crc,const void * data,size_t size)47*f6dc9357SAndroid Build Coastguard Worker UInt32 LzhCrc16Update(UInt32 crc, const void *data, size_t size)
48*f6dc9357SAndroid Build Coastguard Worker {
49*f6dc9357SAndroid Build Coastguard Worker const Byte *p = (const Byte *)data;
50*f6dc9357SAndroid Build Coastguard Worker const Byte *pEnd = p + size;
51*f6dc9357SAndroid Build Coastguard Worker for (; p != pEnd; p++)
52*f6dc9357SAndroid Build Coastguard Worker crc = CRC16_UPDATE_BYTE(crc, *p);
53*f6dc9357SAndroid Build Coastguard Worker return crc;
54*f6dc9357SAndroid Build Coastguard Worker }
55*f6dc9357SAndroid Build Coastguard Worker
56*f6dc9357SAndroid Build Coastguard Worker static struct CLzhCrc16TableInit
57*f6dc9357SAndroid Build Coastguard Worker {
CLzhCrc16TableInitCLzhCrc16TableInit58*f6dc9357SAndroid Build Coastguard Worker CLzhCrc16TableInit()
59*f6dc9357SAndroid Build Coastguard Worker {
60*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < 256; i++)
61*f6dc9357SAndroid Build Coastguard Worker {
62*f6dc9357SAndroid Build Coastguard Worker UInt32 r = i;
63*f6dc9357SAndroid Build Coastguard Worker for (unsigned j = 0; j < 8; j++)
64*f6dc9357SAndroid Build Coastguard Worker r = (r >> 1) ^ (kCrc16Poly & ((UInt32)0 - (r & 1)));
65*f6dc9357SAndroid Build Coastguard Worker g_LzhCrc16Table[i] = (UInt16)r;
66*f6dc9357SAndroid Build Coastguard Worker }
67*f6dc9357SAndroid Build Coastguard Worker }
68*f6dc9357SAndroid Build Coastguard Worker } g_LzhCrc16TableInit;
69*f6dc9357SAndroid Build Coastguard Worker
70*f6dc9357SAndroid Build Coastguard Worker
71*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
72*f6dc9357SAndroid Build Coastguard Worker namespace NLzh{
73*f6dc9357SAndroid Build Coastguard Worker
74*f6dc9357SAndroid Build Coastguard Worker const unsigned kMethodIdSize = 5;
75*f6dc9357SAndroid Build Coastguard Worker
76*f6dc9357SAndroid Build Coastguard Worker const Byte kExtIdFileName = 0x01;
77*f6dc9357SAndroid Build Coastguard Worker const Byte kExtIdDirName = 0x02;
78*f6dc9357SAndroid Build Coastguard Worker const Byte kExtIdUnixTime = 0x54;
79*f6dc9357SAndroid Build Coastguard Worker
80*f6dc9357SAndroid Build Coastguard Worker struct CExtension
81*f6dc9357SAndroid Build Coastguard Worker {
82*f6dc9357SAndroid Build Coastguard Worker Byte Type;
83*f6dc9357SAndroid Build Coastguard Worker CByteBuffer Data;
84*f6dc9357SAndroid Build Coastguard Worker
GetStringNArchive::NLzh::CExtension85*f6dc9357SAndroid Build Coastguard Worker AString GetString() const
86*f6dc9357SAndroid Build Coastguard Worker {
87*f6dc9357SAndroid Build Coastguard Worker AString s;
88*f6dc9357SAndroid Build Coastguard Worker s.SetFrom_CalcLen((const char *)(const Byte *)Data, (unsigned)Data.Size());
89*f6dc9357SAndroid Build Coastguard Worker return s;
90*f6dc9357SAndroid Build Coastguard Worker }
91*f6dc9357SAndroid Build Coastguard Worker };
92*f6dc9357SAndroid Build Coastguard Worker
93*f6dc9357SAndroid Build Coastguard Worker const UInt32 kBasicPartSize = 22;
94*f6dc9357SAndroid Build Coastguard Worker
IsArc_Lzh(const Byte * p,size_t size)95*f6dc9357SAndroid Build Coastguard Worker API_FUNC_static_IsArc IsArc_Lzh(const Byte *p, size_t size)
96*f6dc9357SAndroid Build Coastguard Worker {
97*f6dc9357SAndroid Build Coastguard Worker if (size < 2 + kBasicPartSize)
98*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
99*f6dc9357SAndroid Build Coastguard Worker if (p[2] != '-' || p[3] != 'l' || p[4] != 'h' || p[6] != '-')
100*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
101*f6dc9357SAndroid Build Coastguard Worker Byte n = p[5];
102*f6dc9357SAndroid Build Coastguard Worker if (n != 'd')
103*f6dc9357SAndroid Build Coastguard Worker if (n < '0' || n > '7')
104*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
105*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_YES;
106*f6dc9357SAndroid Build Coastguard Worker }
107*f6dc9357SAndroid Build Coastguard Worker }
108*f6dc9357SAndroid Build Coastguard Worker
109*f6dc9357SAndroid Build Coastguard Worker struct CItem
110*f6dc9357SAndroid Build Coastguard Worker {
111*f6dc9357SAndroid Build Coastguard Worker AString Name;
112*f6dc9357SAndroid Build Coastguard Worker Byte Method[kMethodIdSize];
113*f6dc9357SAndroid Build Coastguard Worker Byte Attributes;
114*f6dc9357SAndroid Build Coastguard Worker Byte Level;
115*f6dc9357SAndroid Build Coastguard Worker Byte OsId;
116*f6dc9357SAndroid Build Coastguard Worker UInt32 PackSize;
117*f6dc9357SAndroid Build Coastguard Worker UInt32 Size;
118*f6dc9357SAndroid Build Coastguard Worker UInt32 ModifiedTime;
119*f6dc9357SAndroid Build Coastguard Worker UInt16 CRC;
120*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CExtension> Extensions;
121*f6dc9357SAndroid Build Coastguard Worker
IsValidMethodNArchive::CItem122*f6dc9357SAndroid Build Coastguard Worker bool IsValidMethod() const { return (Method[0] == '-' && Method[1] == 'l' && Method[4] == '-'); }
IsLhMethodNArchive::CItem123*f6dc9357SAndroid Build Coastguard Worker bool IsLhMethod() const {return (IsValidMethod() && Method[2] == 'h'); }
IsDirNArchive::CItem124*f6dc9357SAndroid Build Coastguard Worker bool IsDir() const {return (IsLhMethod() && Method[3] == 'd'); }
125*f6dc9357SAndroid Build Coastguard Worker
IsCopyMethodNArchive::CItem126*f6dc9357SAndroid Build Coastguard Worker bool IsCopyMethod() const
127*f6dc9357SAndroid Build Coastguard Worker {
128*f6dc9357SAndroid Build Coastguard Worker return (IsLhMethod() && Method[3] == '0') ||
129*f6dc9357SAndroid Build Coastguard Worker (IsValidMethod() && Method[2] == 'z' && Method[3] == '4');
130*f6dc9357SAndroid Build Coastguard Worker }
131*f6dc9357SAndroid Build Coastguard Worker
IsLh1GroupMethodNArchive::CItem132*f6dc9357SAndroid Build Coastguard Worker bool IsLh1GroupMethod() const
133*f6dc9357SAndroid Build Coastguard Worker {
134*f6dc9357SAndroid Build Coastguard Worker if (!IsLhMethod())
135*f6dc9357SAndroid Build Coastguard Worker return false;
136*f6dc9357SAndroid Build Coastguard Worker switch (Method[3])
137*f6dc9357SAndroid Build Coastguard Worker {
138*f6dc9357SAndroid Build Coastguard Worker case '1':
139*f6dc9357SAndroid Build Coastguard Worker return true;
140*f6dc9357SAndroid Build Coastguard Worker }
141*f6dc9357SAndroid Build Coastguard Worker return false;
142*f6dc9357SAndroid Build Coastguard Worker }
143*f6dc9357SAndroid Build Coastguard Worker
IsLh4GroupMethodNArchive::CItem144*f6dc9357SAndroid Build Coastguard Worker bool IsLh4GroupMethod() const
145*f6dc9357SAndroid Build Coastguard Worker {
146*f6dc9357SAndroid Build Coastguard Worker if (!IsLhMethod())
147*f6dc9357SAndroid Build Coastguard Worker return false;
148*f6dc9357SAndroid Build Coastguard Worker switch (Method[3])
149*f6dc9357SAndroid Build Coastguard Worker {
150*f6dc9357SAndroid Build Coastguard Worker case '4':
151*f6dc9357SAndroid Build Coastguard Worker case '5':
152*f6dc9357SAndroid Build Coastguard Worker case '6':
153*f6dc9357SAndroid Build Coastguard Worker case '7':
154*f6dc9357SAndroid Build Coastguard Worker return true;
155*f6dc9357SAndroid Build Coastguard Worker }
156*f6dc9357SAndroid Build Coastguard Worker return false;
157*f6dc9357SAndroid Build Coastguard Worker }
158*f6dc9357SAndroid Build Coastguard Worker
GetNumDictBitsNArchive::CItem159*f6dc9357SAndroid Build Coastguard Worker unsigned GetNumDictBits() const
160*f6dc9357SAndroid Build Coastguard Worker {
161*f6dc9357SAndroid Build Coastguard Worker if (!IsLhMethod())
162*f6dc9357SAndroid Build Coastguard Worker return 0;
163*f6dc9357SAndroid Build Coastguard Worker switch (Method[3])
164*f6dc9357SAndroid Build Coastguard Worker {
165*f6dc9357SAndroid Build Coastguard Worker case '1': return 12;
166*f6dc9357SAndroid Build Coastguard Worker case '2': return 13;
167*f6dc9357SAndroid Build Coastguard Worker case '3': return 13;
168*f6dc9357SAndroid Build Coastguard Worker case '4': return 12;
169*f6dc9357SAndroid Build Coastguard Worker case '5': return 13;
170*f6dc9357SAndroid Build Coastguard Worker case '6': return 15;
171*f6dc9357SAndroid Build Coastguard Worker case '7': return 16;
172*f6dc9357SAndroid Build Coastguard Worker }
173*f6dc9357SAndroid Build Coastguard Worker return 0;
174*f6dc9357SAndroid Build Coastguard Worker }
175*f6dc9357SAndroid Build Coastguard Worker
FindExtNArchive::CItem176*f6dc9357SAndroid Build Coastguard Worker int FindExt(Byte type) const
177*f6dc9357SAndroid Build Coastguard Worker {
178*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, Extensions)
179*f6dc9357SAndroid Build Coastguard Worker if (Extensions[i].Type == type)
180*f6dc9357SAndroid Build Coastguard Worker return (int)i;
181*f6dc9357SAndroid Build Coastguard Worker return -1;
182*f6dc9357SAndroid Build Coastguard Worker }
183*f6dc9357SAndroid Build Coastguard Worker
GetUnixTimeNArchive::CItem184*f6dc9357SAndroid Build Coastguard Worker bool GetUnixTime(UInt32 &value) const
185*f6dc9357SAndroid Build Coastguard Worker {
186*f6dc9357SAndroid Build Coastguard Worker value = 0;
187*f6dc9357SAndroid Build Coastguard Worker int index = FindExt(kExtIdUnixTime);
188*f6dc9357SAndroid Build Coastguard Worker if (index < 0
189*f6dc9357SAndroid Build Coastguard Worker || Extensions[index].Data.Size() < 4)
190*f6dc9357SAndroid Build Coastguard Worker {
191*f6dc9357SAndroid Build Coastguard Worker if (Level == 2)
192*f6dc9357SAndroid Build Coastguard Worker {
193*f6dc9357SAndroid Build Coastguard Worker value = ModifiedTime;
194*f6dc9357SAndroid Build Coastguard Worker return true;
195*f6dc9357SAndroid Build Coastguard Worker }
196*f6dc9357SAndroid Build Coastguard Worker return false;
197*f6dc9357SAndroid Build Coastguard Worker }
198*f6dc9357SAndroid Build Coastguard Worker const Byte *data = (const Byte *)(Extensions[index].Data);
199*f6dc9357SAndroid Build Coastguard Worker value = GetUi32(data);
200*f6dc9357SAndroid Build Coastguard Worker return true;
201*f6dc9357SAndroid Build Coastguard Worker }
202*f6dc9357SAndroid Build Coastguard Worker
GetDirNameNArchive::CItem203*f6dc9357SAndroid Build Coastguard Worker AString GetDirName() const
204*f6dc9357SAndroid Build Coastguard Worker {
205*f6dc9357SAndroid Build Coastguard Worker int index = FindExt(kExtIdDirName);
206*f6dc9357SAndroid Build Coastguard Worker if (index < 0)
207*f6dc9357SAndroid Build Coastguard Worker return AString();
208*f6dc9357SAndroid Build Coastguard Worker return Extensions[index].GetString();
209*f6dc9357SAndroid Build Coastguard Worker }
210*f6dc9357SAndroid Build Coastguard Worker
GetFileNameNArchive::CItem211*f6dc9357SAndroid Build Coastguard Worker AString GetFileName() const
212*f6dc9357SAndroid Build Coastguard Worker {
213*f6dc9357SAndroid Build Coastguard Worker int index = FindExt(kExtIdFileName);
214*f6dc9357SAndroid Build Coastguard Worker if (index < 0)
215*f6dc9357SAndroid Build Coastguard Worker return Name;
216*f6dc9357SAndroid Build Coastguard Worker return Extensions[index].GetString();
217*f6dc9357SAndroid Build Coastguard Worker }
218*f6dc9357SAndroid Build Coastguard Worker
GetNameNArchive::CItem219*f6dc9357SAndroid Build Coastguard Worker AString GetName() const
220*f6dc9357SAndroid Build Coastguard Worker {
221*f6dc9357SAndroid Build Coastguard Worker AString s (GetDirName());
222*f6dc9357SAndroid Build Coastguard Worker const char kDirSeparator = '\\';
223*f6dc9357SAndroid Build Coastguard Worker // check kDirSeparator in Linux
224*f6dc9357SAndroid Build Coastguard Worker s.Replace((char)(Byte)0xFF, kDirSeparator);
225*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty() && s.Back() != kDirSeparator)
226*f6dc9357SAndroid Build Coastguard Worker s += kDirSeparator;
227*f6dc9357SAndroid Build Coastguard Worker s += GetFileName();
228*f6dc9357SAndroid Build Coastguard Worker return s;
229*f6dc9357SAndroid Build Coastguard Worker }
230*f6dc9357SAndroid Build Coastguard Worker };
231*f6dc9357SAndroid Build Coastguard Worker
ReadUInt16(const Byte * p,UInt16 & v)232*f6dc9357SAndroid Build Coastguard Worker static const Byte *ReadUInt16(const Byte *p, UInt16 &v)
233*f6dc9357SAndroid Build Coastguard Worker {
234*f6dc9357SAndroid Build Coastguard Worker v = Get16(p);
235*f6dc9357SAndroid Build Coastguard Worker return p + 2;
236*f6dc9357SAndroid Build Coastguard Worker }
237*f6dc9357SAndroid Build Coastguard Worker
ReadString(const Byte * p,size_t size,AString & s)238*f6dc9357SAndroid Build Coastguard Worker static const Byte *ReadString(const Byte *p, size_t size, AString &s)
239*f6dc9357SAndroid Build Coastguard Worker {
240*f6dc9357SAndroid Build Coastguard Worker s.Empty();
241*f6dc9357SAndroid Build Coastguard Worker for (size_t i = 0; i < size; i++)
242*f6dc9357SAndroid Build Coastguard Worker {
243*f6dc9357SAndroid Build Coastguard Worker const Byte c = p[i];
244*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
245*f6dc9357SAndroid Build Coastguard Worker break;
246*f6dc9357SAndroid Build Coastguard Worker s += (char)c;
247*f6dc9357SAndroid Build Coastguard Worker }
248*f6dc9357SAndroid Build Coastguard Worker return p + size;
249*f6dc9357SAndroid Build Coastguard Worker }
250*f6dc9357SAndroid Build Coastguard Worker
CalcSum(const Byte * data,size_t size)251*f6dc9357SAndroid Build Coastguard Worker static Byte CalcSum(const Byte *data, size_t size)
252*f6dc9357SAndroid Build Coastguard Worker {
253*f6dc9357SAndroid Build Coastguard Worker Byte sum = 0;
254*f6dc9357SAndroid Build Coastguard Worker for (size_t i = 0; i < size; i++)
255*f6dc9357SAndroid Build Coastguard Worker sum = (Byte)(sum + data[i]);
256*f6dc9357SAndroid Build Coastguard Worker return sum;
257*f6dc9357SAndroid Build Coastguard Worker }
258*f6dc9357SAndroid Build Coastguard Worker
GetNextItem(ISequentialInStream * stream,bool & filled,CItem & item)259*f6dc9357SAndroid Build Coastguard Worker static HRESULT GetNextItem(ISequentialInStream *stream, bool &filled, CItem &item)
260*f6dc9357SAndroid Build Coastguard Worker {
261*f6dc9357SAndroid Build Coastguard Worker filled = false;
262*f6dc9357SAndroid Build Coastguard Worker
263*f6dc9357SAndroid Build Coastguard Worker size_t processedSize = 2;
264*f6dc9357SAndroid Build Coastguard Worker Byte startHeader[2];
265*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream(stream, startHeader, &processedSize))
266*f6dc9357SAndroid Build Coastguard Worker if (processedSize == 0)
267*f6dc9357SAndroid Build Coastguard Worker return S_OK;
268*f6dc9357SAndroid Build Coastguard Worker if (processedSize == 1)
269*f6dc9357SAndroid Build Coastguard Worker return (startHeader[0] == 0) ? S_OK: S_FALSE;
270*f6dc9357SAndroid Build Coastguard Worker if (startHeader[0] == 0 && startHeader[1] == 0)
271*f6dc9357SAndroid Build Coastguard Worker return S_OK;
272*f6dc9357SAndroid Build Coastguard Worker
273*f6dc9357SAndroid Build Coastguard Worker Byte header[256];
274*f6dc9357SAndroid Build Coastguard Worker processedSize = kBasicPartSize;
275*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream(stream, header, &processedSize))
276*f6dc9357SAndroid Build Coastguard Worker if (processedSize != kBasicPartSize)
277*f6dc9357SAndroid Build Coastguard Worker return (startHeader[0] == 0) ? S_OK: S_FALSE;
278*f6dc9357SAndroid Build Coastguard Worker
279*f6dc9357SAndroid Build Coastguard Worker const Byte *p = header;
280*f6dc9357SAndroid Build Coastguard Worker memcpy(item.Method, p, kMethodIdSize);
281*f6dc9357SAndroid Build Coastguard Worker if (!item.IsValidMethod())
282*f6dc9357SAndroid Build Coastguard Worker return S_OK;
283*f6dc9357SAndroid Build Coastguard Worker p += kMethodIdSize;
284*f6dc9357SAndroid Build Coastguard Worker item.PackSize = Get32(p);
285*f6dc9357SAndroid Build Coastguard Worker item.Size = Get32(p + 4);
286*f6dc9357SAndroid Build Coastguard Worker item.ModifiedTime = Get32(p + 8);
287*f6dc9357SAndroid Build Coastguard Worker item.Attributes = p[12];
288*f6dc9357SAndroid Build Coastguard Worker item.Level = p[13];
289*f6dc9357SAndroid Build Coastguard Worker p += 14;
290*f6dc9357SAndroid Build Coastguard Worker if (item.Level > 2)
291*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
292*f6dc9357SAndroid Build Coastguard Worker UInt32 headerSize;
293*f6dc9357SAndroid Build Coastguard Worker if (item.Level < 2)
294*f6dc9357SAndroid Build Coastguard Worker {
295*f6dc9357SAndroid Build Coastguard Worker headerSize = startHeader[0];
296*f6dc9357SAndroid Build Coastguard Worker if (headerSize < kBasicPartSize)
297*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
298*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, header + kBasicPartSize, headerSize - kBasicPartSize))
299*f6dc9357SAndroid Build Coastguard Worker if (startHeader[1] != CalcSum(header, headerSize))
300*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
301*f6dc9357SAndroid Build Coastguard Worker const size_t nameLength = *p++;
302*f6dc9357SAndroid Build Coastguard Worker if ((size_t)(p - header) + nameLength + 2 > headerSize)
303*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
304*f6dc9357SAndroid Build Coastguard Worker p = ReadString(p, nameLength, item.Name);
305*f6dc9357SAndroid Build Coastguard Worker }
306*f6dc9357SAndroid Build Coastguard Worker else
307*f6dc9357SAndroid Build Coastguard Worker headerSize = startHeader[0] | ((UInt32)startHeader[1] << 8);
308*f6dc9357SAndroid Build Coastguard Worker p = ReadUInt16(p, item.CRC);
309*f6dc9357SAndroid Build Coastguard Worker if (item.Level != 0)
310*f6dc9357SAndroid Build Coastguard Worker {
311*f6dc9357SAndroid Build Coastguard Worker if (item.Level == 2)
312*f6dc9357SAndroid Build Coastguard Worker {
313*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, header + kBasicPartSize, 2))
314*f6dc9357SAndroid Build Coastguard Worker }
315*f6dc9357SAndroid Build Coastguard Worker if ((size_t)(p - header) + 3 > headerSize)
316*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
317*f6dc9357SAndroid Build Coastguard Worker item.OsId = *p++;
318*f6dc9357SAndroid Build Coastguard Worker UInt16 nextSize;
319*f6dc9357SAndroid Build Coastguard Worker p = ReadUInt16(p, nextSize);
320*f6dc9357SAndroid Build Coastguard Worker while (nextSize != 0)
321*f6dc9357SAndroid Build Coastguard Worker {
322*f6dc9357SAndroid Build Coastguard Worker if (nextSize < 3)
323*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
324*f6dc9357SAndroid Build Coastguard Worker if (item.Level == 1)
325*f6dc9357SAndroid Build Coastguard Worker {
326*f6dc9357SAndroid Build Coastguard Worker if (item.PackSize < nextSize)
327*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
328*f6dc9357SAndroid Build Coastguard Worker item.PackSize -= nextSize;
329*f6dc9357SAndroid Build Coastguard Worker }
330*f6dc9357SAndroid Build Coastguard Worker if (item.Extensions.Size() >= (1 << 8))
331*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
332*f6dc9357SAndroid Build Coastguard Worker CExtension ext;
333*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, &ext.Type, 1))
334*f6dc9357SAndroid Build Coastguard Worker nextSize = (UInt16)(nextSize - 3);
335*f6dc9357SAndroid Build Coastguard Worker ext.Data.Alloc(nextSize);
336*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, (Byte *)ext.Data, nextSize))
337*f6dc9357SAndroid Build Coastguard Worker item.Extensions.Add(ext);
338*f6dc9357SAndroid Build Coastguard Worker Byte hdr2[2];
339*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, hdr2, 2))
340*f6dc9357SAndroid Build Coastguard Worker ReadUInt16(hdr2, nextSize);
341*f6dc9357SAndroid Build Coastguard Worker }
342*f6dc9357SAndroid Build Coastguard Worker }
343*f6dc9357SAndroid Build Coastguard Worker filled = true;
344*f6dc9357SAndroid Build Coastguard Worker return S_OK;
345*f6dc9357SAndroid Build Coastguard Worker }
346*f6dc9357SAndroid Build Coastguard Worker
347*f6dc9357SAndroid Build Coastguard Worker
348*f6dc9357SAndroid Build Coastguard Worker static const CUInt32PCharPair g_OsPairs[] =
349*f6dc9357SAndroid Build Coastguard Worker {
350*f6dc9357SAndroid Build Coastguard Worker { 0, "MS-DOS" },
351*f6dc9357SAndroid Build Coastguard Worker { 'M', "MS-DOS" },
352*f6dc9357SAndroid Build Coastguard Worker { '2', "OS/2" },
353*f6dc9357SAndroid Build Coastguard Worker { '9', "OS9" },
354*f6dc9357SAndroid Build Coastguard Worker { 'K', "OS/68K" },
355*f6dc9357SAndroid Build Coastguard Worker { '3', "OS/386" },
356*f6dc9357SAndroid Build Coastguard Worker { 'H', "HUMAN" },
357*f6dc9357SAndroid Build Coastguard Worker { 'U', "UNIX" },
358*f6dc9357SAndroid Build Coastguard Worker { 'C', "CP/M" },
359*f6dc9357SAndroid Build Coastguard Worker { 'F', "FLEX" },
360*f6dc9357SAndroid Build Coastguard Worker { 'm', "Mac" },
361*f6dc9357SAndroid Build Coastguard Worker { 'R', "Runser" },
362*f6dc9357SAndroid Build Coastguard Worker { 'T', "TownsOS" },
363*f6dc9357SAndroid Build Coastguard Worker { 'X', "XOSK" },
364*f6dc9357SAndroid Build Coastguard Worker { 'w', "Windows 95" },
365*f6dc9357SAndroid Build Coastguard Worker { 'W', "Windows NT" },
366*f6dc9357SAndroid Build Coastguard Worker { 'J', "Java VM" }
367*f6dc9357SAndroid Build Coastguard Worker };
368*f6dc9357SAndroid Build Coastguard Worker
369*f6dc9357SAndroid Build Coastguard Worker
370*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
371*f6dc9357SAndroid Build Coastguard Worker {
372*f6dc9357SAndroid Build Coastguard Worker kpidPath,
373*f6dc9357SAndroid Build Coastguard Worker kpidIsDir,
374*f6dc9357SAndroid Build Coastguard Worker kpidSize,
375*f6dc9357SAndroid Build Coastguard Worker kpidPackSize,
376*f6dc9357SAndroid Build Coastguard Worker kpidMTime,
377*f6dc9357SAndroid Build Coastguard Worker // kpidAttrib,
378*f6dc9357SAndroid Build Coastguard Worker kpidCRC,
379*f6dc9357SAndroid Build Coastguard Worker kpidMethod,
380*f6dc9357SAndroid Build Coastguard Worker kpidHostOS
381*f6dc9357SAndroid Build Coastguard Worker };
382*f6dc9357SAndroid Build Coastguard Worker
383*f6dc9357SAndroid Build Coastguard Worker
384*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_NOQIB_1(
385*f6dc9357SAndroid Build Coastguard Worker COutStreamWithCRC
386*f6dc9357SAndroid Build Coastguard Worker , ISequentialOutStream
387*f6dc9357SAndroid Build Coastguard Worker )
388*f6dc9357SAndroid Build Coastguard Worker UInt32 _crc;
389*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> _stream;
390*f6dc9357SAndroid Build Coastguard Worker public:
391*f6dc9357SAndroid Build Coastguard Worker void Init(ISequentialOutStream *stream)
392*f6dc9357SAndroid Build Coastguard Worker {
393*f6dc9357SAndroid Build Coastguard Worker _stream = stream;
394*f6dc9357SAndroid Build Coastguard Worker _crc = 0;
395*f6dc9357SAndroid Build Coastguard Worker }
396*f6dc9357SAndroid Build Coastguard Worker void ReleaseStream() { _stream.Release(); }
397*f6dc9357SAndroid Build Coastguard Worker UInt32 GetCRC() const { return _crc; }
398*f6dc9357SAndroid Build Coastguard Worker };
399*f6dc9357SAndroid Build Coastguard Worker
400*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize))
401*f6dc9357SAndroid Build Coastguard Worker {
402*f6dc9357SAndroid Build Coastguard Worker HRESULT res = S_OK;
403*f6dc9357SAndroid Build Coastguard Worker if (_stream)
404*f6dc9357SAndroid Build Coastguard Worker res = _stream->Write(data, size, &size);
405*f6dc9357SAndroid Build Coastguard Worker _crc = LzhCrc16Update(_crc, data, size);
406*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
407*f6dc9357SAndroid Build Coastguard Worker *processedSize = size;
408*f6dc9357SAndroid Build Coastguard Worker return res;
409*f6dc9357SAndroid Build Coastguard Worker }
410*f6dc9357SAndroid Build Coastguard Worker
411*f6dc9357SAndroid Build Coastguard Worker
412*f6dc9357SAndroid Build Coastguard Worker struct CItemEx: public CItem
413*f6dc9357SAndroid Build Coastguard Worker {
414*f6dc9357SAndroid Build Coastguard Worker UInt64 DataPosition;
415*f6dc9357SAndroid Build Coastguard Worker };
416*f6dc9357SAndroid Build Coastguard Worker
417*f6dc9357SAndroid Build Coastguard Worker
418*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_CHandler_IInArchive_0
419*f6dc9357SAndroid Build Coastguard Worker
420*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CItemEx> _items;
421*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> _stream;
422*f6dc9357SAndroid Build Coastguard Worker UInt64 _phySize;
423*f6dc9357SAndroid Build Coastguard Worker UInt32 _errorFlags;
424*f6dc9357SAndroid Build Coastguard Worker bool _isArc;
425*f6dc9357SAndroid Build Coastguard Worker public:
426*f6dc9357SAndroid Build Coastguard Worker CHandler();
427*f6dc9357SAndroid Build Coastguard Worker };
428*f6dc9357SAndroid Build Coastguard Worker
429*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
430*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps_NO_Table
431*f6dc9357SAndroid Build Coastguard Worker
432*f6dc9357SAndroid Build Coastguard Worker CHandler::CHandler() {}
433*f6dc9357SAndroid Build Coastguard Worker
434*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
435*f6dc9357SAndroid Build Coastguard Worker {
436*f6dc9357SAndroid Build Coastguard Worker *numItems = _items.Size();
437*f6dc9357SAndroid Build Coastguard Worker return S_OK;
438*f6dc9357SAndroid Build Coastguard Worker }
439*f6dc9357SAndroid Build Coastguard Worker
440*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
441*f6dc9357SAndroid Build Coastguard Worker {
442*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
443*f6dc9357SAndroid Build Coastguard Worker switch (propID)
444*f6dc9357SAndroid Build Coastguard Worker {
445*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize: prop = _phySize; break;
446*f6dc9357SAndroid Build Coastguard Worker
447*f6dc9357SAndroid Build Coastguard Worker case kpidErrorFlags:
448*f6dc9357SAndroid Build Coastguard Worker UInt32 v = _errorFlags;
449*f6dc9357SAndroid Build Coastguard Worker if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
450*f6dc9357SAndroid Build Coastguard Worker prop = v;
451*f6dc9357SAndroid Build Coastguard Worker break;
452*f6dc9357SAndroid Build Coastguard Worker }
453*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
454*f6dc9357SAndroid Build Coastguard Worker return S_OK;
455*f6dc9357SAndroid Build Coastguard Worker }
456*f6dc9357SAndroid Build Coastguard Worker
457*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
458*f6dc9357SAndroid Build Coastguard Worker {
459*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
460*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
461*f6dc9357SAndroid Build Coastguard Worker const CItemEx &item = _items[index];
462*f6dc9357SAndroid Build Coastguard Worker switch (propID)
463*f6dc9357SAndroid Build Coastguard Worker {
464*f6dc9357SAndroid Build Coastguard Worker case kpidPath:
465*f6dc9357SAndroid Build Coastguard Worker {
466*f6dc9357SAndroid Build Coastguard Worker UString s = NItemName::WinPathToOsPath(MultiByteToUnicodeString(item.GetName(), CP_OEMCP));
467*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty())
468*f6dc9357SAndroid Build Coastguard Worker {
469*f6dc9357SAndroid Build Coastguard Worker if (s.Back() == WCHAR_PATH_SEPARATOR)
470*f6dc9357SAndroid Build Coastguard Worker s.DeleteBack();
471*f6dc9357SAndroid Build Coastguard Worker prop = s;
472*f6dc9357SAndroid Build Coastguard Worker }
473*f6dc9357SAndroid Build Coastguard Worker break;
474*f6dc9357SAndroid Build Coastguard Worker }
475*f6dc9357SAndroid Build Coastguard Worker case kpidIsDir: prop = item.IsDir(); break;
476*f6dc9357SAndroid Build Coastguard Worker case kpidSize: prop = (UInt64)item.Size; break;
477*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize: prop = (UInt64)item.PackSize; break;
478*f6dc9357SAndroid Build Coastguard Worker case kpidCRC: prop = (UInt32)item.CRC; break;
479*f6dc9357SAndroid Build Coastguard Worker case kpidHostOS: PAIR_TO_PROP(g_OsPairs, item.OsId, prop); break;
480*f6dc9357SAndroid Build Coastguard Worker case kpidMTime:
481*f6dc9357SAndroid Build Coastguard Worker {
482*f6dc9357SAndroid Build Coastguard Worker UInt32 unixTime;
483*f6dc9357SAndroid Build Coastguard Worker if (item.GetUnixTime(unixTime))
484*f6dc9357SAndroid Build Coastguard Worker PropVariant_SetFrom_UnixTime(prop, unixTime);
485*f6dc9357SAndroid Build Coastguard Worker else
486*f6dc9357SAndroid Build Coastguard Worker PropVariant_SetFrom_DosTime(prop, item.ModifiedTime);
487*f6dc9357SAndroid Build Coastguard Worker break;
488*f6dc9357SAndroid Build Coastguard Worker }
489*f6dc9357SAndroid Build Coastguard Worker // case kpidAttrib: prop = (UInt32)item.Attributes; break;
490*f6dc9357SAndroid Build Coastguard Worker case kpidMethod:
491*f6dc9357SAndroid Build Coastguard Worker {
492*f6dc9357SAndroid Build Coastguard Worker char method2[kMethodIdSize + 1];
493*f6dc9357SAndroid Build Coastguard Worker method2[kMethodIdSize] = 0;
494*f6dc9357SAndroid Build Coastguard Worker memcpy(method2, item.Method, kMethodIdSize);
495*f6dc9357SAndroid Build Coastguard Worker prop = method2;
496*f6dc9357SAndroid Build Coastguard Worker break;
497*f6dc9357SAndroid Build Coastguard Worker }
498*f6dc9357SAndroid Build Coastguard Worker }
499*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
500*f6dc9357SAndroid Build Coastguard Worker return S_OK;
501*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
502*f6dc9357SAndroid Build Coastguard Worker }
503*f6dc9357SAndroid Build Coastguard Worker
504*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
505*f6dc9357SAndroid Build Coastguard Worker const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *callback))
506*f6dc9357SAndroid Build Coastguard Worker {
507*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
508*f6dc9357SAndroid Build Coastguard Worker Close();
509*f6dc9357SAndroid Build Coastguard Worker try
510*f6dc9357SAndroid Build Coastguard Worker {
511*f6dc9357SAndroid Build Coastguard Worker _items.Clear();
512*f6dc9357SAndroid Build Coastguard Worker
513*f6dc9357SAndroid Build Coastguard Worker UInt64 endPos;
514*f6dc9357SAndroid Build Coastguard Worker bool needSetTotal = true;
515*f6dc9357SAndroid Build Coastguard Worker
516*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_AtBegin_GetSize(stream, endPos))
517*f6dc9357SAndroid Build Coastguard Worker
518*f6dc9357SAndroid Build Coastguard Worker for (;;)
519*f6dc9357SAndroid Build Coastguard Worker {
520*f6dc9357SAndroid Build Coastguard Worker CItemEx item;
521*f6dc9357SAndroid Build Coastguard Worker bool filled;
522*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = GetNextItem(stream, filled, item);
523*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_GetPos(stream, item.DataPosition))
524*f6dc9357SAndroid Build Coastguard Worker if (res == S_FALSE)
525*f6dc9357SAndroid Build Coastguard Worker {
526*f6dc9357SAndroid Build Coastguard Worker _errorFlags = kpv_ErrorFlags_HeadersError;
527*f6dc9357SAndroid Build Coastguard Worker break;
528*f6dc9357SAndroid Build Coastguard Worker }
529*f6dc9357SAndroid Build Coastguard Worker
530*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
531*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
532*f6dc9357SAndroid Build Coastguard Worker _phySize = item.DataPosition;
533*f6dc9357SAndroid Build Coastguard Worker if (!filled)
534*f6dc9357SAndroid Build Coastguard Worker break;
535*f6dc9357SAndroid Build Coastguard Worker _items.Add(item);
536*f6dc9357SAndroid Build Coastguard Worker
537*f6dc9357SAndroid Build Coastguard Worker _isArc = true;
538*f6dc9357SAndroid Build Coastguard Worker
539*f6dc9357SAndroid Build Coastguard Worker UInt64 newPostion;
540*f6dc9357SAndroid Build Coastguard Worker RINOK(stream->Seek(item.PackSize, STREAM_SEEK_CUR, &newPostion))
541*f6dc9357SAndroid Build Coastguard Worker if (newPostion > endPos)
542*f6dc9357SAndroid Build Coastguard Worker {
543*f6dc9357SAndroid Build Coastguard Worker _phySize = endPos;
544*f6dc9357SAndroid Build Coastguard Worker _errorFlags = kpv_ErrorFlags_UnexpectedEnd;
545*f6dc9357SAndroid Build Coastguard Worker break;
546*f6dc9357SAndroid Build Coastguard Worker }
547*f6dc9357SAndroid Build Coastguard Worker _phySize = newPostion;
548*f6dc9357SAndroid Build Coastguard Worker if (callback)
549*f6dc9357SAndroid Build Coastguard Worker {
550*f6dc9357SAndroid Build Coastguard Worker if (needSetTotal)
551*f6dc9357SAndroid Build Coastguard Worker {
552*f6dc9357SAndroid Build Coastguard Worker RINOK(callback->SetTotal(NULL, &endPos))
553*f6dc9357SAndroid Build Coastguard Worker needSetTotal = false;
554*f6dc9357SAndroid Build Coastguard Worker }
555*f6dc9357SAndroid Build Coastguard Worker if (_items.Size() % 100 == 0)
556*f6dc9357SAndroid Build Coastguard Worker {
557*f6dc9357SAndroid Build Coastguard Worker const UInt64 numFiles = _items.Size();
558*f6dc9357SAndroid Build Coastguard Worker const UInt64 numBytes = item.DataPosition;
559*f6dc9357SAndroid Build Coastguard Worker RINOK(callback->SetCompleted(&numFiles, &numBytes))
560*f6dc9357SAndroid Build Coastguard Worker }
561*f6dc9357SAndroid Build Coastguard Worker }
562*f6dc9357SAndroid Build Coastguard Worker }
563*f6dc9357SAndroid Build Coastguard Worker if (_items.IsEmpty())
564*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
565*f6dc9357SAndroid Build Coastguard Worker
566*f6dc9357SAndroid Build Coastguard Worker _stream = stream;
567*f6dc9357SAndroid Build Coastguard Worker }
568*f6dc9357SAndroid Build Coastguard Worker catch(...)
569*f6dc9357SAndroid Build Coastguard Worker {
570*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
571*f6dc9357SAndroid Build Coastguard Worker }
572*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
573*f6dc9357SAndroid Build Coastguard Worker return S_OK;
574*f6dc9357SAndroid Build Coastguard Worker }
575*f6dc9357SAndroid Build Coastguard Worker
576*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
577*f6dc9357SAndroid Build Coastguard Worker {
578*f6dc9357SAndroid Build Coastguard Worker _isArc = false;
579*f6dc9357SAndroid Build Coastguard Worker _phySize = 0;
580*f6dc9357SAndroid Build Coastguard Worker _errorFlags = 0;
581*f6dc9357SAndroid Build Coastguard Worker _items.Clear();
582*f6dc9357SAndroid Build Coastguard Worker _stream.Release();
583*f6dc9357SAndroid Build Coastguard Worker return S_OK;
584*f6dc9357SAndroid Build Coastguard Worker }
585*f6dc9357SAndroid Build Coastguard Worker
586*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
587*f6dc9357SAndroid Build Coastguard Worker Int32 testMode, IArchiveExtractCallback *extractCallback))
588*f6dc9357SAndroid Build Coastguard Worker {
589*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
590*f6dc9357SAndroid Build Coastguard Worker const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
591*f6dc9357SAndroid Build Coastguard Worker if (allFilesMode)
592*f6dc9357SAndroid Build Coastguard Worker numItems = _items.Size();
593*f6dc9357SAndroid Build Coastguard Worker if (numItems == 0)
594*f6dc9357SAndroid Build Coastguard Worker return S_OK;
595*f6dc9357SAndroid Build Coastguard Worker UInt64 totalUnPacked = 0 /* , totalPacked = 0 */;
596*f6dc9357SAndroid Build Coastguard Worker UInt32 i;
597*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++)
598*f6dc9357SAndroid Build Coastguard Worker {
599*f6dc9357SAndroid Build Coastguard Worker const CItemEx &item = _items[allFilesMode ? i : indices[i]];
600*f6dc9357SAndroid Build Coastguard Worker totalUnPacked += item.Size;
601*f6dc9357SAndroid Build Coastguard Worker // totalPacked += item.PackSize;
602*f6dc9357SAndroid Build Coastguard Worker }
603*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetTotal(totalUnPacked))
604*f6dc9357SAndroid Build Coastguard Worker
605*f6dc9357SAndroid Build Coastguard Worker UInt32 cur_Unpacked, cur_Packed;
606*f6dc9357SAndroid Build Coastguard Worker
607*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
608*f6dc9357SAndroid Build Coastguard Worker lps->Init(extractCallback, false);
609*f6dc9357SAndroid Build Coastguard Worker CMyUniquePtr<NCompress::NLzh::NDecoder::CCoder> lzhDecoder;
610*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
611*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
612*f6dc9357SAndroid Build Coastguard Worker inStream->SetStream(_stream);
613*f6dc9357SAndroid Build Coastguard Worker
614*f6dc9357SAndroid Build Coastguard Worker for (i = 0;; i++,
615*f6dc9357SAndroid Build Coastguard Worker lps->OutSize += cur_Unpacked,
616*f6dc9357SAndroid Build Coastguard Worker lps->InSize += cur_Packed)
617*f6dc9357SAndroid Build Coastguard Worker {
618*f6dc9357SAndroid Build Coastguard Worker cur_Unpacked = 0;
619*f6dc9357SAndroid Build Coastguard Worker cur_Packed = 0;
620*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
621*f6dc9357SAndroid Build Coastguard Worker if (i >= numItems)
622*f6dc9357SAndroid Build Coastguard Worker break;
623*f6dc9357SAndroid Build Coastguard Worker
624*f6dc9357SAndroid Build Coastguard Worker Int32 opRes;
625*f6dc9357SAndroid Build Coastguard Worker {
626*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> realOutStream;
627*f6dc9357SAndroid Build Coastguard Worker const Int32 askMode = testMode ?
628*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest :
629*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract;
630*f6dc9357SAndroid Build Coastguard Worker const UInt32 index = allFilesMode ? i : indices[i];
631*f6dc9357SAndroid Build Coastguard Worker const CItemEx &item = _items[index];
632*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
633*f6dc9357SAndroid Build Coastguard Worker
634*f6dc9357SAndroid Build Coastguard Worker if (item.IsDir())
635*f6dc9357SAndroid Build Coastguard Worker {
636*f6dc9357SAndroid Build Coastguard Worker // if (!testMode)
637*f6dc9357SAndroid Build Coastguard Worker {
638*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
639*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
640*f6dc9357SAndroid Build Coastguard Worker }
641*f6dc9357SAndroid Build Coastguard Worker continue;
642*f6dc9357SAndroid Build Coastguard Worker }
643*f6dc9357SAndroid Build Coastguard Worker
644*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !realOutStream)
645*f6dc9357SAndroid Build Coastguard Worker continue;
646*f6dc9357SAndroid Build Coastguard Worker
647*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
648*f6dc9357SAndroid Build Coastguard Worker cur_Unpacked = item.Size;
649*f6dc9357SAndroid Build Coastguard Worker cur_Packed = item.PackSize;
650*f6dc9357SAndroid Build Coastguard Worker
651*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> outStream;
652*f6dc9357SAndroid Build Coastguard Worker outStream->Init(realOutStream);
653*f6dc9357SAndroid Build Coastguard Worker realOutStream.Release();
654*f6dc9357SAndroid Build Coastguard Worker
655*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(_stream, item.DataPosition))
656*f6dc9357SAndroid Build Coastguard Worker
657*f6dc9357SAndroid Build Coastguard Worker inStream->Init(item.PackSize);
658*f6dc9357SAndroid Build Coastguard Worker
659*f6dc9357SAndroid Build Coastguard Worker HRESULT res = S_OK;
660*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kOK;
661*f6dc9357SAndroid Build Coastguard Worker
662*f6dc9357SAndroid Build Coastguard Worker if (item.IsCopyMethod())
663*f6dc9357SAndroid Build Coastguard Worker {
664*f6dc9357SAndroid Build Coastguard Worker res = copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps);
665*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK && copyCoder->TotalSize != item.PackSize)
666*f6dc9357SAndroid Build Coastguard Worker res = S_FALSE;
667*f6dc9357SAndroid Build Coastguard Worker }
668*f6dc9357SAndroid Build Coastguard Worker else if (item.IsLh4GroupMethod())
669*f6dc9357SAndroid Build Coastguard Worker {
670*f6dc9357SAndroid Build Coastguard Worker lzhDecoder.Create_if_Empty();
671*f6dc9357SAndroid Build Coastguard Worker // lzhDecoder->FinishMode = true;
672*f6dc9357SAndroid Build Coastguard Worker lzhDecoder->SetDictSize((UInt32)1 << item.GetNumDictBits());
673*f6dc9357SAndroid Build Coastguard Worker res = lzhDecoder->Code(inStream, outStream, cur_Unpacked, lps);
674*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK && lzhDecoder->GetInputProcessedSize() != item.PackSize)
675*f6dc9357SAndroid Build Coastguard Worker res = S_FALSE;
676*f6dc9357SAndroid Build Coastguard Worker }
677*f6dc9357SAndroid Build Coastguard Worker /*
678*f6dc9357SAndroid Build Coastguard Worker else if (item.IsLh1GroupMethod())
679*f6dc9357SAndroid Build Coastguard Worker {
680*f6dc9357SAndroid Build Coastguard Worker if (!lzh1Decoder)
681*f6dc9357SAndroid Build Coastguard Worker {
682*f6dc9357SAndroid Build Coastguard Worker lzh1DecoderSpec = new NCompress::NLzh1::NDecoder::CCoder;
683*f6dc9357SAndroid Build Coastguard Worker lzh1Decoder = lzh1DecoderSpec;
684*f6dc9357SAndroid Build Coastguard Worker }
685*f6dc9357SAndroid Build Coastguard Worker lzh1DecoderSpec->SetDictionary(item.GetNumDictBits());
686*f6dc9357SAndroid Build Coastguard Worker res = lzh1Decoder->Code(inStream, outStream, NULL, &cur_Unpacked, progress);
687*f6dc9357SAndroid Build Coastguard Worker }
688*f6dc9357SAndroid Build Coastguard Worker */
689*f6dc9357SAndroid Build Coastguard Worker else
690*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kUnsupportedMethod;
691*f6dc9357SAndroid Build Coastguard Worker
692*f6dc9357SAndroid Build Coastguard Worker if (opRes == NExtract::NOperationResult::kOK)
693*f6dc9357SAndroid Build Coastguard Worker {
694*f6dc9357SAndroid Build Coastguard Worker if (res == S_FALSE)
695*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kDataError;
696*f6dc9357SAndroid Build Coastguard Worker else
697*f6dc9357SAndroid Build Coastguard Worker {
698*f6dc9357SAndroid Build Coastguard Worker RINOK(res)
699*f6dc9357SAndroid Build Coastguard Worker if (outStream->GetCRC() != item.CRC)
700*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kCRCError;
701*f6dc9357SAndroid Build Coastguard Worker }
702*f6dc9357SAndroid Build Coastguard Worker }
703*f6dc9357SAndroid Build Coastguard Worker }
704*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(opRes))
705*f6dc9357SAndroid Build Coastguard Worker }
706*f6dc9357SAndroid Build Coastguard Worker return S_OK;
707*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
708*f6dc9357SAndroid Build Coastguard Worker }
709*f6dc9357SAndroid Build Coastguard Worker
710*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] = { '-', 'l', 'h' };
711*f6dc9357SAndroid Build Coastguard Worker
712*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
713*f6dc9357SAndroid Build Coastguard Worker "Lzh", "lzh lha", NULL, 6,
714*f6dc9357SAndroid Build Coastguard Worker k_Signature,
715*f6dc9357SAndroid Build Coastguard Worker 2,
716*f6dc9357SAndroid Build Coastguard Worker 0,
717*f6dc9357SAndroid Build Coastguard Worker IsArc_Lzh)
718*f6dc9357SAndroid Build Coastguard Worker
719*f6dc9357SAndroid Build Coastguard Worker }}
720