xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/XzHandler.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // XzHandler.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/Alloc.h"
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/Defs.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/IntToString.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyBuffer.h"
11*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StringToInt.h"
12*f6dc9357SAndroid Build Coastguard Worker 
13*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariant.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/System.h"
15*f6dc9357SAndroid Build Coastguard Worker 
16*f6dc9357SAndroid Build Coastguard Worker #include "../Common/CWrappers.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ProgressUtils.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
20*f6dc9357SAndroid Build Coastguard Worker 
21*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/CopyCoder.h"
22*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/XzDecoder.h"
23*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/XzEncoder.h"
24*f6dc9357SAndroid Build Coastguard Worker 
25*f6dc9357SAndroid Build Coastguard Worker #include "IArchive.h"
26*f6dc9357SAndroid Build Coastguard Worker 
27*f6dc9357SAndroid Build Coastguard Worker #include "Common/HandlerOut.h"
28*f6dc9357SAndroid Build Coastguard Worker 
29*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
30*f6dc9357SAndroid Build Coastguard Worker 
31*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
32*f6dc9357SAndroid Build Coastguard Worker namespace NXz {
33*f6dc9357SAndroid Build Coastguard Worker 
34*f6dc9357SAndroid Build Coastguard Worker #define k_LZMA2_Name "LZMA2"
35*f6dc9357SAndroid Build Coastguard Worker 
36*f6dc9357SAndroid Build Coastguard Worker 
37*f6dc9357SAndroid Build Coastguard Worker struct CBlockInfo
38*f6dc9357SAndroid Build Coastguard Worker {
39*f6dc9357SAndroid Build Coastguard Worker   unsigned StreamFlags;
40*f6dc9357SAndroid Build Coastguard Worker   UInt64 PackPos;
41*f6dc9357SAndroid Build Coastguard Worker   UInt64 PackSize; // pure value from Index record, it doesn't include pad zeros
42*f6dc9357SAndroid Build Coastguard Worker   UInt64 UnpackPos;
43*f6dc9357SAndroid Build Coastguard Worker };
44*f6dc9357SAndroid Build Coastguard Worker 
45*f6dc9357SAndroid Build Coastguard Worker 
46*f6dc9357SAndroid Build Coastguard Worker Z7_class_CHandler_final:
47*f6dc9357SAndroid Build Coastguard Worker   public IInArchive,
48*f6dc9357SAndroid Build Coastguard Worker   public IArchiveOpenSeq,
49*f6dc9357SAndroid Build Coastguard Worker   public IInArchiveGetStream,
50*f6dc9357SAndroid Build Coastguard Worker   public ISetProperties,
51*f6dc9357SAndroid Build Coastguard Worker  #ifndef Z7_EXTRACT_ONLY
52*f6dc9357SAndroid Build Coastguard Worker   public IOutArchive,
53*f6dc9357SAndroid Build Coastguard Worker  #endif
54*f6dc9357SAndroid Build Coastguard Worker   public CMyUnknownImp,
55*f6dc9357SAndroid Build Coastguard Worker  #ifndef Z7_EXTRACT_ONLY
56*f6dc9357SAndroid Build Coastguard Worker   public CMultiMethodProps
57*f6dc9357SAndroid Build Coastguard Worker  #else
58*f6dc9357SAndroid Build Coastguard Worker   public CCommonMethodProps
59*f6dc9357SAndroid Build Coastguard Worker  #endif
60*f6dc9357SAndroid Build Coastguard Worker {
61*f6dc9357SAndroid Build Coastguard Worker   Z7_COM_QI_BEGIN2(IInArchive)
62*f6dc9357SAndroid Build Coastguard Worker   Z7_COM_QI_ENTRY(IArchiveOpenSeq)
63*f6dc9357SAndroid Build Coastguard Worker   Z7_COM_QI_ENTRY(IInArchiveGetStream)
64*f6dc9357SAndroid Build Coastguard Worker   Z7_COM_QI_ENTRY(ISetProperties)
65*f6dc9357SAndroid Build Coastguard Worker  #ifndef Z7_EXTRACT_ONLY
66*f6dc9357SAndroid Build Coastguard Worker   Z7_COM_QI_ENTRY(IOutArchive)
67*f6dc9357SAndroid Build Coastguard Worker  #endif
68*f6dc9357SAndroid Build Coastguard Worker   Z7_COM_QI_END
69*f6dc9357SAndroid Build Coastguard Worker   Z7_COM_ADDREF_RELEASE
70*f6dc9357SAndroid Build Coastguard Worker 
71*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACE_COM7_IMP(IInArchive)
72*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACE_COM7_IMP(IArchiveOpenSeq)
73*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACE_COM7_IMP(IInArchiveGetStream)
74*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACE_COM7_IMP(ISetProperties)
75*f6dc9357SAndroid Build Coastguard Worker  #ifndef Z7_EXTRACT_ONLY
76*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACE_COM7_IMP(IOutArchive)
77*f6dc9357SAndroid Build Coastguard Worker  #endif
78*f6dc9357SAndroid Build Coastguard Worker 
79*f6dc9357SAndroid Build Coastguard Worker   bool _stat_defined;
80*f6dc9357SAndroid Build Coastguard Worker   bool _stat2_defined;
81*f6dc9357SAndroid Build Coastguard Worker   bool _isArc;
82*f6dc9357SAndroid Build Coastguard Worker   bool _needSeekToStart;
83*f6dc9357SAndroid Build Coastguard Worker   bool _firstBlockWasRead;
84*f6dc9357SAndroid Build Coastguard Worker   SRes _stat2_decode_SRes;
85*f6dc9357SAndroid Build Coastguard Worker 
86*f6dc9357SAndroid Build Coastguard Worker   CXzStatInfo _stat;    // it's stat from backward parsing
87*f6dc9357SAndroid Build Coastguard Worker   CXzStatInfo _stat2;   // it's data from forward parsing, if the decoder was called
88*f6dc9357SAndroid Build Coastguard Worker 
89*f6dc9357SAndroid Build Coastguard Worker   const CXzStatInfo *GetStat() const
90*f6dc9357SAndroid Build Coastguard Worker   {
91*f6dc9357SAndroid Build Coastguard Worker     if (_stat_defined) return &_stat;
92*f6dc9357SAndroid Build Coastguard Worker     if (_stat2_defined) return &_stat2;
93*f6dc9357SAndroid Build Coastguard Worker     return NULL;
94*f6dc9357SAndroid Build Coastguard Worker   }
95*f6dc9357SAndroid Build Coastguard Worker 
96*f6dc9357SAndroid Build Coastguard Worker   AString _methodsString;
97*f6dc9357SAndroid Build Coastguard Worker 
98*f6dc9357SAndroid Build Coastguard Worker 
99*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_EXTRACT_ONLY
100*f6dc9357SAndroid Build Coastguard Worker 
101*f6dc9357SAndroid Build Coastguard Worker   UInt32 _filterId;
102*f6dc9357SAndroid Build Coastguard Worker   UInt64 _numSolidBytes;
103*f6dc9357SAndroid Build Coastguard Worker 
104*f6dc9357SAndroid Build Coastguard Worker   void InitXz()
105*f6dc9357SAndroid Build Coastguard Worker   {
106*f6dc9357SAndroid Build Coastguard Worker     _filterId = 0;
107*f6dc9357SAndroid Build Coastguard Worker     _numSolidBytes = XZ_PROPS_BLOCK_SIZE_AUTO;
108*f6dc9357SAndroid Build Coastguard Worker   }
109*f6dc9357SAndroid Build Coastguard Worker 
110*f6dc9357SAndroid Build Coastguard Worker   #endif
111*f6dc9357SAndroid Build Coastguard Worker 
112*f6dc9357SAndroid Build Coastguard Worker 
113*f6dc9357SAndroid Build Coastguard Worker   void Init()
114*f6dc9357SAndroid Build Coastguard Worker   {
115*f6dc9357SAndroid Build Coastguard Worker     #ifndef Z7_EXTRACT_ONLY
116*f6dc9357SAndroid Build Coastguard Worker       InitXz();
117*f6dc9357SAndroid Build Coastguard Worker       CMultiMethodProps::Init();
118*f6dc9357SAndroid Build Coastguard Worker     #else
119*f6dc9357SAndroid Build Coastguard Worker       CCommonMethodProps::InitCommon();
120*f6dc9357SAndroid Build Coastguard Worker     #endif
121*f6dc9357SAndroid Build Coastguard Worker   }
122*f6dc9357SAndroid Build Coastguard Worker 
123*f6dc9357SAndroid Build Coastguard Worker   HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
124*f6dc9357SAndroid Build Coastguard Worker 
125*f6dc9357SAndroid Build Coastguard Worker   HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback);
126*f6dc9357SAndroid Build Coastguard Worker 
127*f6dc9357SAndroid Build Coastguard Worker   HRESULT Decode(NCompress::NXz::CDecoder &decoder,
128*f6dc9357SAndroid Build Coastguard Worker       ISequentialInStream *seqInStream,
129*f6dc9357SAndroid Build Coastguard Worker       ISequentialOutStream *outStream,
130*f6dc9357SAndroid Build Coastguard Worker       ICompressProgressInfo *progress)
131*f6dc9357SAndroid Build Coastguard Worker   {
132*f6dc9357SAndroid Build Coastguard Worker     #ifndef Z7_ST
133*f6dc9357SAndroid Build Coastguard Worker     decoder._numThreads = _numThreads;
134*f6dc9357SAndroid Build Coastguard Worker     #endif
135*f6dc9357SAndroid Build Coastguard Worker     decoder._memUsage = _memUsage_Decompress;
136*f6dc9357SAndroid Build Coastguard Worker 
137*f6dc9357SAndroid Build Coastguard Worker     const HRESULT hres = decoder.Decode(seqInStream, outStream,
138*f6dc9357SAndroid Build Coastguard Worker         NULL, // *outSizeLimit
139*f6dc9357SAndroid Build Coastguard Worker         true, // finishStream
140*f6dc9357SAndroid Build Coastguard Worker         progress);
141*f6dc9357SAndroid Build Coastguard Worker 
142*f6dc9357SAndroid Build Coastguard Worker     if (decoder.MainDecodeSRes_wasUsed
143*f6dc9357SAndroid Build Coastguard Worker         && decoder.MainDecodeSRes != SZ_ERROR_MEM
144*f6dc9357SAndroid Build Coastguard Worker         && decoder.MainDecodeSRes != SZ_ERROR_UNSUPPORTED)
145*f6dc9357SAndroid Build Coastguard Worker     {
146*f6dc9357SAndroid Build Coastguard Worker       // if (!_stat2_defined)
147*f6dc9357SAndroid Build Coastguard Worker       {
148*f6dc9357SAndroid Build Coastguard Worker         _stat2_decode_SRes = decoder.MainDecodeSRes;
149*f6dc9357SAndroid Build Coastguard Worker         _stat2 = decoder.Stat;
150*f6dc9357SAndroid Build Coastguard Worker         _stat2_defined = true;
151*f6dc9357SAndroid Build Coastguard Worker       }
152*f6dc9357SAndroid Build Coastguard Worker     }
153*f6dc9357SAndroid Build Coastguard Worker 
154*f6dc9357SAndroid Build Coastguard Worker     if (hres == S_OK && progress)
155*f6dc9357SAndroid Build Coastguard Worker     {
156*f6dc9357SAndroid Build Coastguard Worker       // RINOK(
157*f6dc9357SAndroid Build Coastguard Worker       progress->SetRatioInfo(&decoder.Stat.InSize, &decoder.Stat.OutSize);
158*f6dc9357SAndroid Build Coastguard Worker     }
159*f6dc9357SAndroid Build Coastguard Worker     return hres;
160*f6dc9357SAndroid Build Coastguard Worker   }
161*f6dc9357SAndroid Build Coastguard Worker 
162*f6dc9357SAndroid Build Coastguard Worker public:
163*f6dc9357SAndroid Build Coastguard Worker   CBlockInfo *_blocks;
164*f6dc9357SAndroid Build Coastguard Worker   size_t _blocksArraySize;
165*f6dc9357SAndroid Build Coastguard Worker   UInt64 _maxBlocksSize;
166*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IInStream> _stream;
167*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialInStream> _seqStream;
168*f6dc9357SAndroid Build Coastguard Worker 
169*f6dc9357SAndroid Build Coastguard Worker   CXzBlock _firstBlock;
170*f6dc9357SAndroid Build Coastguard Worker 
171*f6dc9357SAndroid Build Coastguard Worker   CHandler();
172*f6dc9357SAndroid Build Coastguard Worker   ~CHandler();
173*f6dc9357SAndroid Build Coastguard Worker 
174*f6dc9357SAndroid Build Coastguard Worker   HRESULT SeekToPackPos(UInt64 pos)
175*f6dc9357SAndroid Build Coastguard Worker   {
176*f6dc9357SAndroid Build Coastguard Worker     return InStream_SeekSet(_stream, pos);
177*f6dc9357SAndroid Build Coastguard Worker   }
178*f6dc9357SAndroid Build Coastguard Worker };
179*f6dc9357SAndroid Build Coastguard Worker 
180*f6dc9357SAndroid Build Coastguard Worker 
181*f6dc9357SAndroid Build Coastguard Worker CHandler::CHandler():
182*f6dc9357SAndroid Build Coastguard Worker     _blocks(NULL),
183*f6dc9357SAndroid Build Coastguard Worker     _blocksArraySize(0)
184*f6dc9357SAndroid Build Coastguard Worker {
185*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_EXTRACT_ONLY
186*f6dc9357SAndroid Build Coastguard Worker   InitXz();
187*f6dc9357SAndroid Build Coastguard Worker   #endif
188*f6dc9357SAndroid Build Coastguard Worker }
189*f6dc9357SAndroid Build Coastguard Worker 
190*f6dc9357SAndroid Build Coastguard Worker CHandler::~CHandler()
191*f6dc9357SAndroid Build Coastguard Worker {
192*f6dc9357SAndroid Build Coastguard Worker   MyFree(_blocks);
193*f6dc9357SAndroid Build Coastguard Worker }
194*f6dc9357SAndroid Build Coastguard Worker 
195*f6dc9357SAndroid Build Coastguard Worker 
196*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
197*f6dc9357SAndroid Build Coastguard Worker {
198*f6dc9357SAndroid Build Coastguard Worker   kpidSize,
199*f6dc9357SAndroid Build Coastguard Worker   kpidPackSize,
200*f6dc9357SAndroid Build Coastguard Worker   kpidMethod
201*f6dc9357SAndroid Build Coastguard Worker };
202*f6dc9357SAndroid Build Coastguard Worker 
203*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
204*f6dc9357SAndroid Build Coastguard Worker {
205*f6dc9357SAndroid Build Coastguard Worker   kpidMethod,
206*f6dc9357SAndroid Build Coastguard Worker   kpidNumStreams,
207*f6dc9357SAndroid Build Coastguard Worker   kpidNumBlocks,
208*f6dc9357SAndroid Build Coastguard Worker   kpidClusterSize,
209*f6dc9357SAndroid Build Coastguard Worker   kpidCharacts
210*f6dc9357SAndroid Build Coastguard Worker };
211*f6dc9357SAndroid Build Coastguard Worker 
212*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
213*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
214*f6dc9357SAndroid Build Coastguard Worker 
215*f6dc9357SAndroid Build Coastguard Worker static void Lzma2PropToString(AString &s, unsigned prop)
216*f6dc9357SAndroid Build Coastguard Worker {
217*f6dc9357SAndroid Build Coastguard Worker   char c = 0;
218*f6dc9357SAndroid Build Coastguard Worker   UInt32 size;
219*f6dc9357SAndroid Build Coastguard Worker   if ((prop & 1) == 0)
220*f6dc9357SAndroid Build Coastguard Worker     size = prop / 2 + 12;
221*f6dc9357SAndroid Build Coastguard Worker   else
222*f6dc9357SAndroid Build Coastguard Worker   {
223*f6dc9357SAndroid Build Coastguard Worker     c = 'k';
224*f6dc9357SAndroid Build Coastguard Worker     size = (UInt32)(2 | (prop & 1)) << (prop / 2 + 1);
225*f6dc9357SAndroid Build Coastguard Worker     if (prop > 17)
226*f6dc9357SAndroid Build Coastguard Worker     {
227*f6dc9357SAndroid Build Coastguard Worker       size >>= 10;
228*f6dc9357SAndroid Build Coastguard Worker       c = 'm';
229*f6dc9357SAndroid Build Coastguard Worker     }
230*f6dc9357SAndroid Build Coastguard Worker   }
231*f6dc9357SAndroid Build Coastguard Worker   s.Add_UInt32(size);
232*f6dc9357SAndroid Build Coastguard Worker   if (c != 0)
233*f6dc9357SAndroid Build Coastguard Worker     s.Add_Char(c);
234*f6dc9357SAndroid Build Coastguard Worker }
235*f6dc9357SAndroid Build Coastguard Worker 
236*f6dc9357SAndroid Build Coastguard Worker struct CMethodNamePair
237*f6dc9357SAndroid Build Coastguard Worker {
238*f6dc9357SAndroid Build Coastguard Worker   UInt32 Id;
239*f6dc9357SAndroid Build Coastguard Worker   const char *Name;
240*f6dc9357SAndroid Build Coastguard Worker };
241*f6dc9357SAndroid Build Coastguard Worker 
242*f6dc9357SAndroid Build Coastguard Worker static const CMethodNamePair g_NamePairs[] =
243*f6dc9357SAndroid Build Coastguard Worker {
244*f6dc9357SAndroid Build Coastguard Worker   { XZ_ID_Subblock, "SB" },
245*f6dc9357SAndroid Build Coastguard Worker   { XZ_ID_Delta, "Delta" },
246*f6dc9357SAndroid Build Coastguard Worker   { XZ_ID_X86, "BCJ" },
247*f6dc9357SAndroid Build Coastguard Worker   { XZ_ID_PPC, "PPC" },
248*f6dc9357SAndroid Build Coastguard Worker   { XZ_ID_IA64, "IA64" },
249*f6dc9357SAndroid Build Coastguard Worker   { XZ_ID_ARM, "ARM" },
250*f6dc9357SAndroid Build Coastguard Worker   { XZ_ID_ARMT, "ARMT" },
251*f6dc9357SAndroid Build Coastguard Worker   { XZ_ID_SPARC, "SPARC" },
252*f6dc9357SAndroid Build Coastguard Worker   { XZ_ID_ARM64, "ARM64" },
253*f6dc9357SAndroid Build Coastguard Worker   { XZ_ID_RISCV, "RISCV" },
254*f6dc9357SAndroid Build Coastguard Worker   { XZ_ID_LZMA2, "LZMA2" }
255*f6dc9357SAndroid Build Coastguard Worker };
256*f6dc9357SAndroid Build Coastguard Worker 
257*f6dc9357SAndroid Build Coastguard Worker static void AddMethodString(AString &s, const CXzFilter &f)
258*f6dc9357SAndroid Build Coastguard Worker {
259*f6dc9357SAndroid Build Coastguard Worker   const char *p = NULL;
260*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_NamePairs); i++)
261*f6dc9357SAndroid Build Coastguard Worker     if (g_NamePairs[i].Id == f.id)
262*f6dc9357SAndroid Build Coastguard Worker     {
263*f6dc9357SAndroid Build Coastguard Worker       p = g_NamePairs[i].Name;
264*f6dc9357SAndroid Build Coastguard Worker       break;
265*f6dc9357SAndroid Build Coastguard Worker     }
266*f6dc9357SAndroid Build Coastguard Worker   char temp[32];
267*f6dc9357SAndroid Build Coastguard Worker   if (!p)
268*f6dc9357SAndroid Build Coastguard Worker   {
269*f6dc9357SAndroid Build Coastguard Worker     ::ConvertUInt64ToString(f.id, temp);
270*f6dc9357SAndroid Build Coastguard Worker     p = temp;
271*f6dc9357SAndroid Build Coastguard Worker   }
272*f6dc9357SAndroid Build Coastguard Worker 
273*f6dc9357SAndroid Build Coastguard Worker   s += p;
274*f6dc9357SAndroid Build Coastguard Worker 
275*f6dc9357SAndroid Build Coastguard Worker   if (f.propsSize > 0)
276*f6dc9357SAndroid Build Coastguard Worker   {
277*f6dc9357SAndroid Build Coastguard Worker     s.Add_Colon();
278*f6dc9357SAndroid Build Coastguard Worker     if (f.id == XZ_ID_LZMA2 && f.propsSize == 1)
279*f6dc9357SAndroid Build Coastguard Worker       Lzma2PropToString(s, f.props[0]);
280*f6dc9357SAndroid Build Coastguard Worker     else if (f.id == XZ_ID_Delta && f.propsSize == 1)
281*f6dc9357SAndroid Build Coastguard Worker       s.Add_UInt32((UInt32)f.props[0] + 1);
282*f6dc9357SAndroid Build Coastguard Worker     else if (f.id == XZ_ID_ARM64 && f.propsSize == 1)
283*f6dc9357SAndroid Build Coastguard Worker       s.Add_UInt32((UInt32)f.props[0] + 16 + 2);
284*f6dc9357SAndroid Build Coastguard Worker     else
285*f6dc9357SAndroid Build Coastguard Worker     {
286*f6dc9357SAndroid Build Coastguard Worker       s.Add_Char('[');
287*f6dc9357SAndroid Build Coastguard Worker       for (UInt32 bi = 0; bi < f.propsSize; bi++)
288*f6dc9357SAndroid Build Coastguard Worker       {
289*f6dc9357SAndroid Build Coastguard Worker         const unsigned v = f.props[bi];
290*f6dc9357SAndroid Build Coastguard Worker         s.Add_Char(GET_HEX_CHAR_UPPER(v >> 4));
291*f6dc9357SAndroid Build Coastguard Worker         s.Add_Char(GET_HEX_CHAR_UPPER(v & 15));
292*f6dc9357SAndroid Build Coastguard Worker       }
293*f6dc9357SAndroid Build Coastguard Worker       s.Add_Char(']');
294*f6dc9357SAndroid Build Coastguard Worker     }
295*f6dc9357SAndroid Build Coastguard Worker   }
296*f6dc9357SAndroid Build Coastguard Worker }
297*f6dc9357SAndroid Build Coastguard Worker 
298*f6dc9357SAndroid Build Coastguard Worker static const char * const kChecks[] =
299*f6dc9357SAndroid Build Coastguard Worker {
300*f6dc9357SAndroid Build Coastguard Worker     "NoCheck"
301*f6dc9357SAndroid Build Coastguard Worker   , "CRC32"
302*f6dc9357SAndroid Build Coastguard Worker   , NULL
303*f6dc9357SAndroid Build Coastguard Worker   , NULL
304*f6dc9357SAndroid Build Coastguard Worker   , "CRC64"
305*f6dc9357SAndroid Build Coastguard Worker   , NULL
306*f6dc9357SAndroid Build Coastguard Worker   , NULL
307*f6dc9357SAndroid Build Coastguard Worker   , NULL
308*f6dc9357SAndroid Build Coastguard Worker   , NULL
309*f6dc9357SAndroid Build Coastguard Worker   , NULL
310*f6dc9357SAndroid Build Coastguard Worker   , "SHA256"
311*f6dc9357SAndroid Build Coastguard Worker   , NULL
312*f6dc9357SAndroid Build Coastguard Worker   , NULL
313*f6dc9357SAndroid Build Coastguard Worker   , NULL
314*f6dc9357SAndroid Build Coastguard Worker   , NULL
315*f6dc9357SAndroid Build Coastguard Worker   , NULL
316*f6dc9357SAndroid Build Coastguard Worker };
317*f6dc9357SAndroid Build Coastguard Worker 
318*f6dc9357SAndroid Build Coastguard Worker static void AddCheckString(AString &s, const CXzs &xzs)
319*f6dc9357SAndroid Build Coastguard Worker {
320*f6dc9357SAndroid Build Coastguard Worker   size_t i;
321*f6dc9357SAndroid Build Coastguard Worker   UInt32 mask = 0;
322*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < xzs.num; i++)
323*f6dc9357SAndroid Build Coastguard Worker     mask |= ((UInt32)1 << XzFlags_GetCheckType(xzs.streams[i].flags));
324*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i <= XZ_CHECK_MASK; i++)
325*f6dc9357SAndroid Build Coastguard Worker     if (((mask >> i) & 1) != 0)
326*f6dc9357SAndroid Build Coastguard Worker     {
327*f6dc9357SAndroid Build Coastguard Worker       s.Add_Space_if_NotEmpty();
328*f6dc9357SAndroid Build Coastguard Worker       if (kChecks[i])
329*f6dc9357SAndroid Build Coastguard Worker         s += kChecks[i];
330*f6dc9357SAndroid Build Coastguard Worker       else
331*f6dc9357SAndroid Build Coastguard Worker       {
332*f6dc9357SAndroid Build Coastguard Worker         s += "Check-";
333*f6dc9357SAndroid Build Coastguard Worker         s.Add_UInt32((UInt32)i);
334*f6dc9357SAndroid Build Coastguard Worker       }
335*f6dc9357SAndroid Build Coastguard Worker     }
336*f6dc9357SAndroid Build Coastguard Worker }
337*f6dc9357SAndroid Build Coastguard Worker 
338*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
339*f6dc9357SAndroid Build Coastguard Worker {
340*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
341*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
342*f6dc9357SAndroid Build Coastguard Worker 
343*f6dc9357SAndroid Build Coastguard Worker   const CXzStatInfo *stat = GetStat();
344*f6dc9357SAndroid Build Coastguard Worker 
345*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
346*f6dc9357SAndroid Build Coastguard Worker   {
347*f6dc9357SAndroid Build Coastguard Worker     case kpidPhySize: if (stat) prop = stat->InSize; break;
348*f6dc9357SAndroid Build Coastguard Worker     case kpidNumStreams: if (stat && stat->NumStreams_Defined) prop = stat->NumStreams; break;
349*f6dc9357SAndroid Build Coastguard Worker     case kpidNumBlocks: if (stat && stat->NumBlocks_Defined) prop = stat->NumBlocks; break;
350*f6dc9357SAndroid Build Coastguard Worker     case kpidUnpackSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break;
351*f6dc9357SAndroid Build Coastguard Worker     case kpidClusterSize: if (_stat_defined && _stat.NumBlocks_Defined && stat->NumBlocks > 1) prop = _maxBlocksSize; break;
352*f6dc9357SAndroid Build Coastguard Worker     case kpidCharacts:
353*f6dc9357SAndroid Build Coastguard Worker       if (_firstBlockWasRead)
354*f6dc9357SAndroid Build Coastguard Worker       {
355*f6dc9357SAndroid Build Coastguard Worker         AString s;
356*f6dc9357SAndroid Build Coastguard Worker         if (XzBlock_HasPackSize(&_firstBlock))
357*f6dc9357SAndroid Build Coastguard Worker           s.Add_OptSpaced("BlockPackSize");
358*f6dc9357SAndroid Build Coastguard Worker         if (XzBlock_HasUnpackSize(&_firstBlock))
359*f6dc9357SAndroid Build Coastguard Worker           s.Add_OptSpaced("BlockUnpackSize");
360*f6dc9357SAndroid Build Coastguard Worker         if (!s.IsEmpty())
361*f6dc9357SAndroid Build Coastguard Worker           prop = s;
362*f6dc9357SAndroid Build Coastguard Worker       }
363*f6dc9357SAndroid Build Coastguard Worker       break;
364*f6dc9357SAndroid Build Coastguard Worker 
365*f6dc9357SAndroid Build Coastguard Worker 
366*f6dc9357SAndroid Build Coastguard Worker     case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;
367*f6dc9357SAndroid Build Coastguard Worker     case kpidErrorFlags:
368*f6dc9357SAndroid Build Coastguard Worker     {
369*f6dc9357SAndroid Build Coastguard Worker       UInt32 v = 0;
370*f6dc9357SAndroid Build Coastguard Worker       SRes sres = _stat2_decode_SRes;
371*f6dc9357SAndroid Build Coastguard Worker       if (!_isArc)                      v |= kpv_ErrorFlags_IsNotArc;
372*f6dc9357SAndroid Build Coastguard Worker       if (sres == SZ_ERROR_INPUT_EOF)   v |= kpv_ErrorFlags_UnexpectedEnd;
373*f6dc9357SAndroid Build Coastguard Worker       if (_stat2_defined && _stat2.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;
374*f6dc9357SAndroid Build Coastguard Worker       if (sres == SZ_ERROR_ARCHIVE)     v |= kpv_ErrorFlags_HeadersError;
375*f6dc9357SAndroid Build Coastguard Worker       if (sres == SZ_ERROR_UNSUPPORTED) v |= kpv_ErrorFlags_UnsupportedMethod;
376*f6dc9357SAndroid Build Coastguard Worker       if (sres == SZ_ERROR_DATA)        v |= kpv_ErrorFlags_DataError;
377*f6dc9357SAndroid Build Coastguard Worker       if (sres == SZ_ERROR_CRC)         v |= kpv_ErrorFlags_CrcError;
378*f6dc9357SAndroid Build Coastguard Worker       if (v != 0)
379*f6dc9357SAndroid Build Coastguard Worker         prop = v;
380*f6dc9357SAndroid Build Coastguard Worker       break;
381*f6dc9357SAndroid Build Coastguard Worker     }
382*f6dc9357SAndroid Build Coastguard Worker 
383*f6dc9357SAndroid Build Coastguard Worker     case kpidMainSubfile:
384*f6dc9357SAndroid Build Coastguard Worker     {
385*f6dc9357SAndroid Build Coastguard Worker       // debug only, comment it:
386*f6dc9357SAndroid Build Coastguard Worker       // if (_blocks) prop = (UInt32)0;
387*f6dc9357SAndroid Build Coastguard Worker       break;
388*f6dc9357SAndroid Build Coastguard Worker     }
389*f6dc9357SAndroid Build Coastguard Worker     default: break;
390*f6dc9357SAndroid Build Coastguard Worker   }
391*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
392*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
393*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
394*f6dc9357SAndroid Build Coastguard Worker }
395*f6dc9357SAndroid Build Coastguard Worker 
396*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
397*f6dc9357SAndroid Build Coastguard Worker {
398*f6dc9357SAndroid Build Coastguard Worker   *numItems = 1;
399*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
400*f6dc9357SAndroid Build Coastguard Worker }
401*f6dc9357SAndroid Build Coastguard Worker 
402*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value))
403*f6dc9357SAndroid Build Coastguard Worker {
404*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
405*f6dc9357SAndroid Build Coastguard Worker   const CXzStatInfo *stat = GetStat();
406*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
407*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
408*f6dc9357SAndroid Build Coastguard Worker   {
409*f6dc9357SAndroid Build Coastguard Worker     case kpidSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break;
410*f6dc9357SAndroid Build Coastguard Worker     case kpidPackSize: if (stat) prop = stat->InSize; break;
411*f6dc9357SAndroid Build Coastguard Worker     case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;
412*f6dc9357SAndroid Build Coastguard Worker     default: break;
413*f6dc9357SAndroid Build Coastguard Worker   }
414*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
415*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
416*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
417*f6dc9357SAndroid Build Coastguard Worker }
418*f6dc9357SAndroid Build Coastguard Worker 
419*f6dc9357SAndroid Build Coastguard Worker 
420*f6dc9357SAndroid Build Coastguard Worker struct COpenCallbackWrap
421*f6dc9357SAndroid Build Coastguard Worker {
422*f6dc9357SAndroid Build Coastguard Worker   ICompressProgress vt;
423*f6dc9357SAndroid Build Coastguard Worker   IArchiveOpenCallback *OpenCallback;
424*f6dc9357SAndroid Build Coastguard Worker   HRESULT Res;
425*f6dc9357SAndroid Build Coastguard Worker 
426*f6dc9357SAndroid Build Coastguard Worker   // new clang shows "non-POD" warning for offsetof(), if we use constructor instead of Init()
427*f6dc9357SAndroid Build Coastguard Worker   void Init(IArchiveOpenCallback *progress);
428*f6dc9357SAndroid Build Coastguard Worker };
429*f6dc9357SAndroid Build Coastguard Worker 
430*f6dc9357SAndroid Build Coastguard Worker static SRes OpenCallbackProgress(ICompressProgressPtr pp, UInt64 inSize, UInt64 /* outSize */)
431*f6dc9357SAndroid Build Coastguard Worker {
432*f6dc9357SAndroid Build Coastguard Worker   Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(COpenCallbackWrap)
433*f6dc9357SAndroid Build Coastguard Worker   if (p->OpenCallback)
434*f6dc9357SAndroid Build Coastguard Worker     p->Res = p->OpenCallback->SetCompleted(NULL, &inSize);
435*f6dc9357SAndroid Build Coastguard Worker   return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS);
436*f6dc9357SAndroid Build Coastguard Worker }
437*f6dc9357SAndroid Build Coastguard Worker 
438*f6dc9357SAndroid Build Coastguard Worker void COpenCallbackWrap::Init(IArchiveOpenCallback *callback)
439*f6dc9357SAndroid Build Coastguard Worker {
440*f6dc9357SAndroid Build Coastguard Worker   vt.Progress = OpenCallbackProgress;
441*f6dc9357SAndroid Build Coastguard Worker   OpenCallback = callback;
442*f6dc9357SAndroid Build Coastguard Worker   Res = SZ_OK;
443*f6dc9357SAndroid Build Coastguard Worker }
444*f6dc9357SAndroid Build Coastguard Worker 
445*f6dc9357SAndroid Build Coastguard Worker 
446*f6dc9357SAndroid Build Coastguard Worker struct CXzsCPP
447*f6dc9357SAndroid Build Coastguard Worker {
448*f6dc9357SAndroid Build Coastguard Worker   CXzs p;
449*f6dc9357SAndroid Build Coastguard Worker   CXzsCPP() { Xzs_Construct(&p); }
450*f6dc9357SAndroid Build Coastguard Worker   ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); }
451*f6dc9357SAndroid Build Coastguard Worker };
452*f6dc9357SAndroid Build Coastguard Worker 
453*f6dc9357SAndroid Build Coastguard Worker #define kInputBufSize ((size_t)1 << 10)
454*f6dc9357SAndroid Build Coastguard Worker 
455*f6dc9357SAndroid Build Coastguard Worker struct CLookToRead2_CPP: public CLookToRead2
456*f6dc9357SAndroid Build Coastguard Worker {
457*f6dc9357SAndroid Build Coastguard Worker   CLookToRead2_CPP()
458*f6dc9357SAndroid Build Coastguard Worker   {
459*f6dc9357SAndroid Build Coastguard Worker     buf = NULL;
460*f6dc9357SAndroid Build Coastguard Worker     LookToRead2_CreateVTable(this,
461*f6dc9357SAndroid Build Coastguard Worker         True // Lookahead ?
462*f6dc9357SAndroid Build Coastguard Worker         );
463*f6dc9357SAndroid Build Coastguard Worker   }
464*f6dc9357SAndroid Build Coastguard Worker   void Alloc(size_t allocSize)
465*f6dc9357SAndroid Build Coastguard Worker   {
466*f6dc9357SAndroid Build Coastguard Worker     buf = (Byte *)MyAlloc(allocSize);
467*f6dc9357SAndroid Build Coastguard Worker     if (buf)
468*f6dc9357SAndroid Build Coastguard Worker       this->bufSize = allocSize;
469*f6dc9357SAndroid Build Coastguard Worker   }
470*f6dc9357SAndroid Build Coastguard Worker   ~CLookToRead2_CPP()
471*f6dc9357SAndroid Build Coastguard Worker   {
472*f6dc9357SAndroid Build Coastguard Worker     MyFree(buf);
473*f6dc9357SAndroid Build Coastguard Worker   }
474*f6dc9357SAndroid Build Coastguard Worker };
475*f6dc9357SAndroid Build Coastguard Worker 
476*f6dc9357SAndroid Build Coastguard Worker 
477*f6dc9357SAndroid Build Coastguard Worker static HRESULT SRes_to_Open_HRESULT(SRes res)
478*f6dc9357SAndroid Build Coastguard Worker {
479*f6dc9357SAndroid Build Coastguard Worker   switch (res)
480*f6dc9357SAndroid Build Coastguard Worker   {
481*f6dc9357SAndroid Build Coastguard Worker     case SZ_OK: return S_OK;
482*f6dc9357SAndroid Build Coastguard Worker     case SZ_ERROR_MEM: return E_OUTOFMEMORY;
483*f6dc9357SAndroid Build Coastguard Worker     case SZ_ERROR_PROGRESS: return E_ABORT;
484*f6dc9357SAndroid Build Coastguard Worker     /*
485*f6dc9357SAndroid Build Coastguard Worker     case SZ_ERROR_UNSUPPORTED:
486*f6dc9357SAndroid Build Coastguard Worker     case SZ_ERROR_CRC:
487*f6dc9357SAndroid Build Coastguard Worker     case SZ_ERROR_DATA:
488*f6dc9357SAndroid Build Coastguard Worker     case SZ_ERROR_ARCHIVE:
489*f6dc9357SAndroid Build Coastguard Worker     case SZ_ERROR_NO_ARCHIVE:
490*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
491*f6dc9357SAndroid Build Coastguard Worker     */
492*f6dc9357SAndroid Build Coastguard Worker     default: break;
493*f6dc9357SAndroid Build Coastguard Worker   }
494*f6dc9357SAndroid Build Coastguard Worker   return S_FALSE;
495*f6dc9357SAndroid Build Coastguard Worker }
496*f6dc9357SAndroid Build Coastguard Worker 
497*f6dc9357SAndroid Build Coastguard Worker 
498*f6dc9357SAndroid Build Coastguard Worker 
499*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback)
500*f6dc9357SAndroid Build Coastguard Worker {
501*f6dc9357SAndroid Build Coastguard Worker   _needSeekToStart = true;
502*f6dc9357SAndroid Build Coastguard Worker 
503*f6dc9357SAndroid Build Coastguard Worker   {
504*f6dc9357SAndroid Build Coastguard Worker     CXzStreamFlags st;
505*f6dc9357SAndroid Build Coastguard Worker     CSeqInStreamWrap inStreamWrap;
506*f6dc9357SAndroid Build Coastguard Worker 
507*f6dc9357SAndroid Build Coastguard Worker     inStreamWrap.Init(inStream);
508*f6dc9357SAndroid Build Coastguard Worker 
509*f6dc9357SAndroid Build Coastguard Worker     SRes res = Xz_ReadHeader(&st, &inStreamWrap.vt);
510*f6dc9357SAndroid Build Coastguard Worker 
511*f6dc9357SAndroid Build Coastguard Worker     if (inStreamWrap.Res != S_OK)
512*f6dc9357SAndroid Build Coastguard Worker       return inStreamWrap.Res;
513*f6dc9357SAndroid Build Coastguard Worker     if (res != SZ_OK)
514*f6dc9357SAndroid Build Coastguard Worker       return SRes_to_Open_HRESULT(res);
515*f6dc9357SAndroid Build Coastguard Worker 
516*f6dc9357SAndroid Build Coastguard Worker     {
517*f6dc9357SAndroid Build Coastguard Worker       CXzBlock block;
518*f6dc9357SAndroid Build Coastguard Worker       BoolInt isIndex;
519*f6dc9357SAndroid Build Coastguard Worker       UInt32 headerSizeRes;
520*f6dc9357SAndroid Build Coastguard Worker 
521*f6dc9357SAndroid Build Coastguard Worker       SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.vt, &isIndex, &headerSizeRes);
522*f6dc9357SAndroid Build Coastguard Worker 
523*f6dc9357SAndroid Build Coastguard Worker       if (inStreamWrap.Res != S_OK)
524*f6dc9357SAndroid Build Coastguard Worker         return inStreamWrap.Res;
525*f6dc9357SAndroid Build Coastguard Worker 
526*f6dc9357SAndroid Build Coastguard Worker       if (res2 != SZ_OK)
527*f6dc9357SAndroid Build Coastguard Worker       {
528*f6dc9357SAndroid Build Coastguard Worker         if (res2 == SZ_ERROR_INPUT_EOF)
529*f6dc9357SAndroid Build Coastguard Worker         {
530*f6dc9357SAndroid Build Coastguard Worker           _stat2_decode_SRes = res2;
531*f6dc9357SAndroid Build Coastguard Worker           _stream = inStream;
532*f6dc9357SAndroid Build Coastguard Worker           _seqStream = inStream;
533*f6dc9357SAndroid Build Coastguard Worker           _isArc = true;
534*f6dc9357SAndroid Build Coastguard Worker           return S_OK;
535*f6dc9357SAndroid Build Coastguard Worker         }
536*f6dc9357SAndroid Build Coastguard Worker 
537*f6dc9357SAndroid Build Coastguard Worker         if (res2 == SZ_ERROR_ARCHIVE)
538*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
539*f6dc9357SAndroid Build Coastguard Worker       }
540*f6dc9357SAndroid Build Coastguard Worker       else if (!isIndex)
541*f6dc9357SAndroid Build Coastguard Worker       {
542*f6dc9357SAndroid Build Coastguard Worker         _firstBlockWasRead = true;
543*f6dc9357SAndroid Build Coastguard Worker         _firstBlock = block;
544*f6dc9357SAndroid Build Coastguard Worker 
545*f6dc9357SAndroid Build Coastguard Worker         unsigned numFilters = XzBlock_GetNumFilters(&block);
546*f6dc9357SAndroid Build Coastguard Worker         for (unsigned i = 0; i < numFilters; i++)
547*f6dc9357SAndroid Build Coastguard Worker         {
548*f6dc9357SAndroid Build Coastguard Worker           _methodsString.Add_Space_if_NotEmpty();
549*f6dc9357SAndroid Build Coastguard Worker           AddMethodString(_methodsString, block.filters[i]);
550*f6dc9357SAndroid Build Coastguard Worker         }
551*f6dc9357SAndroid Build Coastguard Worker       }
552*f6dc9357SAndroid Build Coastguard Worker     }
553*f6dc9357SAndroid Build Coastguard Worker   }
554*f6dc9357SAndroid Build Coastguard Worker 
555*f6dc9357SAndroid Build Coastguard Worker   RINOK(InStream_GetSize_SeekToEnd(inStream, _stat.InSize))
556*f6dc9357SAndroid Build Coastguard Worker   if (callback)
557*f6dc9357SAndroid Build Coastguard Worker   {
558*f6dc9357SAndroid Build Coastguard Worker     RINOK(callback->SetTotal(NULL, &_stat.InSize))
559*f6dc9357SAndroid Build Coastguard Worker   }
560*f6dc9357SAndroid Build Coastguard Worker 
561*f6dc9357SAndroid Build Coastguard Worker   CSeekInStreamWrap inStreamImp;
562*f6dc9357SAndroid Build Coastguard Worker 
563*f6dc9357SAndroid Build Coastguard Worker   inStreamImp.Init(inStream);
564*f6dc9357SAndroid Build Coastguard Worker 
565*f6dc9357SAndroid Build Coastguard Worker   CLookToRead2_CPP lookStream;
566*f6dc9357SAndroid Build Coastguard Worker 
567*f6dc9357SAndroid Build Coastguard Worker   lookStream.Alloc(kInputBufSize);
568*f6dc9357SAndroid Build Coastguard Worker 
569*f6dc9357SAndroid Build Coastguard Worker   if (!lookStream.buf)
570*f6dc9357SAndroid Build Coastguard Worker     return E_OUTOFMEMORY;
571*f6dc9357SAndroid Build Coastguard Worker 
572*f6dc9357SAndroid Build Coastguard Worker   lookStream.realStream = &inStreamImp.vt;
573*f6dc9357SAndroid Build Coastguard Worker   LookToRead2_INIT(&lookStream)
574*f6dc9357SAndroid Build Coastguard Worker 
575*f6dc9357SAndroid Build Coastguard Worker   COpenCallbackWrap openWrap;
576*f6dc9357SAndroid Build Coastguard Worker   openWrap.Init(callback);
577*f6dc9357SAndroid Build Coastguard Worker 
578*f6dc9357SAndroid Build Coastguard Worker   CXzsCPP xzs;
579*f6dc9357SAndroid Build Coastguard Worker   Int64 startPosition;
580*f6dc9357SAndroid Build Coastguard Worker   SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.vt, &startPosition, &openWrap.vt, &g_Alloc);
581*f6dc9357SAndroid Build Coastguard Worker   if (res == SZ_ERROR_PROGRESS)
582*f6dc9357SAndroid Build Coastguard Worker     return (openWrap.Res == S_OK) ? E_FAIL : openWrap.Res;
583*f6dc9357SAndroid Build Coastguard Worker   /*
584*f6dc9357SAndroid Build Coastguard Worker   if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0)
585*f6dc9357SAndroid Build Coastguard Worker     res = SZ_OK;
586*f6dc9357SAndroid Build Coastguard Worker   */
587*f6dc9357SAndroid Build Coastguard Worker   if (res == SZ_OK && startPosition == 0)
588*f6dc9357SAndroid Build Coastguard Worker   {
589*f6dc9357SAndroid Build Coastguard Worker     _stat_defined = true;
590*f6dc9357SAndroid Build Coastguard Worker 
591*f6dc9357SAndroid Build Coastguard Worker     _stat.OutSize = Xzs_GetUnpackSize(&xzs.p);
592*f6dc9357SAndroid Build Coastguard Worker     _stat.UnpackSize_Defined = true;
593*f6dc9357SAndroid Build Coastguard Worker 
594*f6dc9357SAndroid Build Coastguard Worker     _stat.NumStreams = xzs.p.num;
595*f6dc9357SAndroid Build Coastguard Worker     _stat.NumStreams_Defined = true;
596*f6dc9357SAndroid Build Coastguard Worker 
597*f6dc9357SAndroid Build Coastguard Worker     _stat.NumBlocks = Xzs_GetNumBlocks(&xzs.p);
598*f6dc9357SAndroid Build Coastguard Worker     _stat.NumBlocks_Defined = true;
599*f6dc9357SAndroid Build Coastguard Worker 
600*f6dc9357SAndroid Build Coastguard Worker     AddCheckString(_methodsString, xzs.p);
601*f6dc9357SAndroid Build Coastguard Worker 
602*f6dc9357SAndroid Build Coastguard Worker     const size_t numBlocks = (size_t)_stat.NumBlocks + 1;
603*f6dc9357SAndroid Build Coastguard Worker     const size_t bytesAlloc = numBlocks * sizeof(CBlockInfo);
604*f6dc9357SAndroid Build Coastguard Worker 
605*f6dc9357SAndroid Build Coastguard Worker     if (bytesAlloc / sizeof(CBlockInfo) == _stat.NumBlocks + 1)
606*f6dc9357SAndroid Build Coastguard Worker     {
607*f6dc9357SAndroid Build Coastguard Worker       _blocks = (CBlockInfo *)MyAlloc(bytesAlloc);
608*f6dc9357SAndroid Build Coastguard Worker       if (_blocks)
609*f6dc9357SAndroid Build Coastguard Worker       {
610*f6dc9357SAndroid Build Coastguard Worker         unsigned blockIndex = 0;
611*f6dc9357SAndroid Build Coastguard Worker         UInt64 unpackPos = 0;
612*f6dc9357SAndroid Build Coastguard Worker 
613*f6dc9357SAndroid Build Coastguard Worker         for (size_t si = xzs.p.num; si != 0;)
614*f6dc9357SAndroid Build Coastguard Worker         {
615*f6dc9357SAndroid Build Coastguard Worker           si--;
616*f6dc9357SAndroid Build Coastguard Worker           const CXzStream &str = xzs.p.streams[si];
617*f6dc9357SAndroid Build Coastguard Worker           UInt64 packPos = str.startOffset + XZ_STREAM_HEADER_SIZE;
618*f6dc9357SAndroid Build Coastguard Worker 
619*f6dc9357SAndroid Build Coastguard Worker           for (size_t bi = 0; bi < str.numBlocks; bi++)
620*f6dc9357SAndroid Build Coastguard Worker           {
621*f6dc9357SAndroid Build Coastguard Worker             const CXzBlockSizes &bs = str.blocks[bi];
622*f6dc9357SAndroid Build Coastguard Worker             const UInt64 packSizeAligned = bs.totalSize + ((0 - (unsigned)bs.totalSize) & 3);
623*f6dc9357SAndroid Build Coastguard Worker 
624*f6dc9357SAndroid Build Coastguard Worker             if (bs.unpackSize != 0)
625*f6dc9357SAndroid Build Coastguard Worker             {
626*f6dc9357SAndroid Build Coastguard Worker               if (blockIndex >= _stat.NumBlocks)
627*f6dc9357SAndroid Build Coastguard Worker                 return E_FAIL;
628*f6dc9357SAndroid Build Coastguard Worker 
629*f6dc9357SAndroid Build Coastguard Worker               CBlockInfo &block = _blocks[blockIndex++];
630*f6dc9357SAndroid Build Coastguard Worker               block.StreamFlags = str.flags;
631*f6dc9357SAndroid Build Coastguard Worker               block.PackSize = bs.totalSize; // packSizeAligned;
632*f6dc9357SAndroid Build Coastguard Worker               block.PackPos = packPos;
633*f6dc9357SAndroid Build Coastguard Worker               block.UnpackPos = unpackPos;
634*f6dc9357SAndroid Build Coastguard Worker             }
635*f6dc9357SAndroid Build Coastguard Worker             packPos += packSizeAligned;
636*f6dc9357SAndroid Build Coastguard Worker             unpackPos += bs.unpackSize;
637*f6dc9357SAndroid Build Coastguard Worker             if (_maxBlocksSize < bs.unpackSize)
638*f6dc9357SAndroid Build Coastguard Worker               _maxBlocksSize = bs.unpackSize;
639*f6dc9357SAndroid Build Coastguard Worker           }
640*f6dc9357SAndroid Build Coastguard Worker         }
641*f6dc9357SAndroid Build Coastguard Worker 
642*f6dc9357SAndroid Build Coastguard Worker         /*
643*f6dc9357SAndroid Build Coastguard Worker         if (blockIndex != _stat.NumBlocks)
644*f6dc9357SAndroid Build Coastguard Worker         {
645*f6dc9357SAndroid Build Coastguard Worker           // there are Empty blocks;
646*f6dc9357SAndroid Build Coastguard Worker         }
647*f6dc9357SAndroid Build Coastguard Worker         */
648*f6dc9357SAndroid Build Coastguard Worker         if (_stat.OutSize != unpackPos)
649*f6dc9357SAndroid Build Coastguard Worker           return E_FAIL;
650*f6dc9357SAndroid Build Coastguard Worker         CBlockInfo &block = _blocks[blockIndex++];
651*f6dc9357SAndroid Build Coastguard Worker         block.StreamFlags = 0;
652*f6dc9357SAndroid Build Coastguard Worker         block.PackSize = 0;
653*f6dc9357SAndroid Build Coastguard Worker         block.PackPos = 0;
654*f6dc9357SAndroid Build Coastguard Worker         block.UnpackPos = unpackPos;
655*f6dc9357SAndroid Build Coastguard Worker         _blocksArraySize = blockIndex;
656*f6dc9357SAndroid Build Coastguard Worker       }
657*f6dc9357SAndroid Build Coastguard Worker     }
658*f6dc9357SAndroid Build Coastguard Worker   }
659*f6dc9357SAndroid Build Coastguard Worker   else
660*f6dc9357SAndroid Build Coastguard Worker   {
661*f6dc9357SAndroid Build Coastguard Worker     res = SZ_OK;
662*f6dc9357SAndroid Build Coastguard Worker   }
663*f6dc9357SAndroid Build Coastguard Worker 
664*f6dc9357SAndroid Build Coastguard Worker   RINOK(SRes_to_Open_HRESULT(res))
665*f6dc9357SAndroid Build Coastguard Worker 
666*f6dc9357SAndroid Build Coastguard Worker   _stream = inStream;
667*f6dc9357SAndroid Build Coastguard Worker   _seqStream = inStream;
668*f6dc9357SAndroid Build Coastguard Worker   _isArc = true;
669*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
670*f6dc9357SAndroid Build Coastguard Worker }
671*f6dc9357SAndroid Build Coastguard Worker 
672*f6dc9357SAndroid Build Coastguard Worker 
673*f6dc9357SAndroid Build Coastguard Worker 
674*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback))
675*f6dc9357SAndroid Build Coastguard Worker {
676*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
677*f6dc9357SAndroid Build Coastguard Worker   {
678*f6dc9357SAndroid Build Coastguard Worker     Close();
679*f6dc9357SAndroid Build Coastguard Worker     return Open2(inStream, callback);
680*f6dc9357SAndroid Build Coastguard Worker   }
681*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
682*f6dc9357SAndroid Build Coastguard Worker }
683*f6dc9357SAndroid Build Coastguard Worker 
684*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))
685*f6dc9357SAndroid Build Coastguard Worker {
686*f6dc9357SAndroid Build Coastguard Worker   Close();
687*f6dc9357SAndroid Build Coastguard Worker   _seqStream = stream;
688*f6dc9357SAndroid Build Coastguard Worker   _isArc = true;
689*f6dc9357SAndroid Build Coastguard Worker   _needSeekToStart = false;
690*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
691*f6dc9357SAndroid Build Coastguard Worker }
692*f6dc9357SAndroid Build Coastguard Worker 
693*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
694*f6dc9357SAndroid Build Coastguard Worker {
695*f6dc9357SAndroid Build Coastguard Worker   XzStatInfo_Clear(&_stat);
696*f6dc9357SAndroid Build Coastguard Worker   XzStatInfo_Clear(&_stat2);
697*f6dc9357SAndroid Build Coastguard Worker   _stat_defined = false;
698*f6dc9357SAndroid Build Coastguard Worker   _stat2_defined = false;
699*f6dc9357SAndroid Build Coastguard Worker   _stat2_decode_SRes = SZ_OK;
700*f6dc9357SAndroid Build Coastguard Worker 
701*f6dc9357SAndroid Build Coastguard Worker   _isArc = false;
702*f6dc9357SAndroid Build Coastguard Worker   _needSeekToStart = false;
703*f6dc9357SAndroid Build Coastguard Worker   _firstBlockWasRead = false;
704*f6dc9357SAndroid Build Coastguard Worker 
705*f6dc9357SAndroid Build Coastguard Worker    _methodsString.Empty();
706*f6dc9357SAndroid Build Coastguard Worker   _stream.Release();
707*f6dc9357SAndroid Build Coastguard Worker   _seqStream.Release();
708*f6dc9357SAndroid Build Coastguard Worker 
709*f6dc9357SAndroid Build Coastguard Worker   MyFree(_blocks);
710*f6dc9357SAndroid Build Coastguard Worker   _blocks = NULL;
711*f6dc9357SAndroid Build Coastguard Worker   _blocksArraySize = 0;
712*f6dc9357SAndroid Build Coastguard Worker   _maxBlocksSize = 0;
713*f6dc9357SAndroid Build Coastguard Worker 
714*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
715*f6dc9357SAndroid Build Coastguard Worker }
716*f6dc9357SAndroid Build Coastguard Worker 
717*f6dc9357SAndroid Build Coastguard Worker 
718*f6dc9357SAndroid Build Coastguard Worker struct CXzUnpackerCPP2
719*f6dc9357SAndroid Build Coastguard Worker {
720*f6dc9357SAndroid Build Coastguard Worker   Byte *InBuf;
721*f6dc9357SAndroid Build Coastguard Worker   // Byte *OutBuf;
722*f6dc9357SAndroid Build Coastguard Worker   CXzUnpacker p;
723*f6dc9357SAndroid Build Coastguard Worker 
724*f6dc9357SAndroid Build Coastguard Worker   CXzUnpackerCPP2();
725*f6dc9357SAndroid Build Coastguard Worker   ~CXzUnpackerCPP2();
726*f6dc9357SAndroid Build Coastguard Worker };
727*f6dc9357SAndroid Build Coastguard Worker 
728*f6dc9357SAndroid Build Coastguard Worker CXzUnpackerCPP2::CXzUnpackerCPP2(): InBuf(NULL)
729*f6dc9357SAndroid Build Coastguard Worker   // , OutBuf(NULL)
730*f6dc9357SAndroid Build Coastguard Worker {
731*f6dc9357SAndroid Build Coastguard Worker   XzUnpacker_Construct(&p, &g_Alloc);
732*f6dc9357SAndroid Build Coastguard Worker }
733*f6dc9357SAndroid Build Coastguard Worker 
734*f6dc9357SAndroid Build Coastguard Worker CXzUnpackerCPP2::~CXzUnpackerCPP2()
735*f6dc9357SAndroid Build Coastguard Worker {
736*f6dc9357SAndroid Build Coastguard Worker   XzUnpacker_Free(&p);
737*f6dc9357SAndroid Build Coastguard Worker   MidFree(InBuf);
738*f6dc9357SAndroid Build Coastguard Worker   // MidFree(OutBuf);
739*f6dc9357SAndroid Build Coastguard Worker }
740*f6dc9357SAndroid Build Coastguard Worker 
741*f6dc9357SAndroid Build Coastguard Worker 
742*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_IInStream(
743*f6dc9357SAndroid Build Coastguard Worker   CInStream
744*f6dc9357SAndroid Build Coastguard Worker )
745*f6dc9357SAndroid Build Coastguard Worker 
746*f6dc9357SAndroid Build Coastguard Worker   UInt64 _virtPos;
747*f6dc9357SAndroid Build Coastguard Worker public:
748*f6dc9357SAndroid Build Coastguard Worker   UInt64 Size;
749*f6dc9357SAndroid Build Coastguard Worker   UInt64 _cacheStartPos;
750*f6dc9357SAndroid Build Coastguard Worker   size_t _cacheSize;
751*f6dc9357SAndroid Build Coastguard Worker   CByteBuffer _cache;
752*f6dc9357SAndroid Build Coastguard Worker   // UInt64 _startPos;
753*f6dc9357SAndroid Build Coastguard Worker   CXzUnpackerCPP2 xz;
754*f6dc9357SAndroid Build Coastguard Worker 
755*f6dc9357SAndroid Build Coastguard Worker   void InitAndSeek()
756*f6dc9357SAndroid Build Coastguard Worker   {
757*f6dc9357SAndroid Build Coastguard Worker     _virtPos = 0;
758*f6dc9357SAndroid Build Coastguard Worker     _cacheStartPos = 0;
759*f6dc9357SAndroid Build Coastguard Worker     _cacheSize = 0;
760*f6dc9357SAndroid Build Coastguard Worker     // _startPos = startPos;
761*f6dc9357SAndroid Build Coastguard Worker   }
762*f6dc9357SAndroid Build Coastguard Worker 
763*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2<IInArchive, CHandler> _handlerSpec;
764*f6dc9357SAndroid Build Coastguard Worker   // ~CInStream();
765*f6dc9357SAndroid Build Coastguard Worker };
766*f6dc9357SAndroid Build Coastguard Worker 
767*f6dc9357SAndroid Build Coastguard Worker /*
768*f6dc9357SAndroid Build Coastguard Worker CInStream::~CInStream()
769*f6dc9357SAndroid Build Coastguard Worker {
770*f6dc9357SAndroid Build Coastguard Worker   // _cache.Free();
771*f6dc9357SAndroid Build Coastguard Worker }
772*f6dc9357SAndroid Build Coastguard Worker */
773*f6dc9357SAndroid Build Coastguard Worker 
774*f6dc9357SAndroid Build Coastguard Worker static size_t FindBlock(const CBlockInfo *blocks, size_t numBlocks, UInt64 pos)
775*f6dc9357SAndroid Build Coastguard Worker {
776*f6dc9357SAndroid Build Coastguard Worker   size_t left = 0, right = numBlocks;
777*f6dc9357SAndroid Build Coastguard Worker   for (;;)
778*f6dc9357SAndroid Build Coastguard Worker   {
779*f6dc9357SAndroid Build Coastguard Worker     size_t mid = (left + right) / 2;
780*f6dc9357SAndroid Build Coastguard Worker     if (mid == left)
781*f6dc9357SAndroid Build Coastguard Worker       return left;
782*f6dc9357SAndroid Build Coastguard Worker     if (pos < blocks[mid].UnpackPos)
783*f6dc9357SAndroid Build Coastguard Worker       right = mid;
784*f6dc9357SAndroid Build Coastguard Worker     else
785*f6dc9357SAndroid Build Coastguard Worker       left = mid;
786*f6dc9357SAndroid Build Coastguard Worker   }
787*f6dc9357SAndroid Build Coastguard Worker }
788*f6dc9357SAndroid Build Coastguard Worker 
789*f6dc9357SAndroid Build Coastguard Worker 
790*f6dc9357SAndroid Build Coastguard Worker 
791*f6dc9357SAndroid Build Coastguard Worker static HRESULT DecodeBlock(CXzUnpackerCPP2 &xzu,
792*f6dc9357SAndroid Build Coastguard Worker     ISequentialInStream *seqInStream,
793*f6dc9357SAndroid Build Coastguard Worker     unsigned streamFlags,
794*f6dc9357SAndroid Build Coastguard Worker     UInt64 packSize, // pure size from Index record, it doesn't include pad zeros
795*f6dc9357SAndroid Build Coastguard Worker     size_t unpackSize, Byte *dest
796*f6dc9357SAndroid Build Coastguard Worker     // , ICompressProgressInfo *progress
797*f6dc9357SAndroid Build Coastguard Worker     )
798*f6dc9357SAndroid Build Coastguard Worker {
799*f6dc9357SAndroid Build Coastguard Worker   const size_t kInBufSize = (size_t)1 << 16;
800*f6dc9357SAndroid Build Coastguard Worker 
801*f6dc9357SAndroid Build Coastguard Worker   XzUnpacker_Init(&xzu.p);
802*f6dc9357SAndroid Build Coastguard Worker 
803*f6dc9357SAndroid Build Coastguard Worker   if (!xzu.InBuf)
804*f6dc9357SAndroid Build Coastguard Worker   {
805*f6dc9357SAndroid Build Coastguard Worker     xzu.InBuf = (Byte *)MidAlloc(kInBufSize);
806*f6dc9357SAndroid Build Coastguard Worker     if (!xzu.InBuf)
807*f6dc9357SAndroid Build Coastguard Worker       return E_OUTOFMEMORY;
808*f6dc9357SAndroid Build Coastguard Worker   }
809*f6dc9357SAndroid Build Coastguard Worker 
810*f6dc9357SAndroid Build Coastguard Worker   xzu.p.streamFlags = (UInt16)streamFlags;
811*f6dc9357SAndroid Build Coastguard Worker   XzUnpacker_PrepareToRandomBlockDecoding(&xzu.p);
812*f6dc9357SAndroid Build Coastguard Worker 
813*f6dc9357SAndroid Build Coastguard Worker   XzUnpacker_SetOutBuf(&xzu.p, dest, unpackSize);
814*f6dc9357SAndroid Build Coastguard Worker 
815*f6dc9357SAndroid Build Coastguard Worker   const UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);
816*f6dc9357SAndroid Build Coastguard Worker   UInt64 packRem = packSizeAligned;
817*f6dc9357SAndroid Build Coastguard Worker 
818*f6dc9357SAndroid Build Coastguard Worker   UInt32 inSize = 0;
819*f6dc9357SAndroid Build Coastguard Worker   SizeT inPos = 0;
820*f6dc9357SAndroid Build Coastguard Worker   SizeT outPos = 0;
821*f6dc9357SAndroid Build Coastguard Worker 
822*f6dc9357SAndroid Build Coastguard Worker   HRESULT readRes = S_OK;
823*f6dc9357SAndroid Build Coastguard Worker 
824*f6dc9357SAndroid Build Coastguard Worker   for (;;)
825*f6dc9357SAndroid Build Coastguard Worker   {
826*f6dc9357SAndroid Build Coastguard Worker     if (inPos == inSize && readRes == S_OK)
827*f6dc9357SAndroid Build Coastguard Worker     {
828*f6dc9357SAndroid Build Coastguard Worker       inPos = 0;
829*f6dc9357SAndroid Build Coastguard Worker       inSize = 0;
830*f6dc9357SAndroid Build Coastguard Worker       UInt32 rem = kInBufSize;
831*f6dc9357SAndroid Build Coastguard Worker       if (rem > packRem)
832*f6dc9357SAndroid Build Coastguard Worker         rem = (UInt32)packRem;
833*f6dc9357SAndroid Build Coastguard Worker       if (rem != 0)
834*f6dc9357SAndroid Build Coastguard Worker         readRes = seqInStream->Read(xzu.InBuf, rem, &inSize);
835*f6dc9357SAndroid Build Coastguard Worker     }
836*f6dc9357SAndroid Build Coastguard Worker 
837*f6dc9357SAndroid Build Coastguard Worker     SizeT inLen = inSize - inPos;
838*f6dc9357SAndroid Build Coastguard Worker     SizeT outLen = unpackSize - outPos;
839*f6dc9357SAndroid Build Coastguard Worker 
840*f6dc9357SAndroid Build Coastguard Worker     ECoderStatus status;
841*f6dc9357SAndroid Build Coastguard Worker 
842*f6dc9357SAndroid Build Coastguard Worker     const SRes res = XzUnpacker_Code(&xzu.p,
843*f6dc9357SAndroid Build Coastguard Worker         // dest + outPos,
844*f6dc9357SAndroid Build Coastguard Worker         NULL,
845*f6dc9357SAndroid Build Coastguard Worker         &outLen,
846*f6dc9357SAndroid Build Coastguard Worker         xzu.InBuf + inPos, &inLen,
847*f6dc9357SAndroid Build Coastguard Worker         (inLen == 0), // srcFinished
848*f6dc9357SAndroid Build Coastguard Worker         CODER_FINISH_END, &status);
849*f6dc9357SAndroid Build Coastguard Worker 
850*f6dc9357SAndroid Build Coastguard Worker     // return E_OUTOFMEMORY;
851*f6dc9357SAndroid Build Coastguard Worker     // res = SZ_ERROR_CRC;
852*f6dc9357SAndroid Build Coastguard Worker 
853*f6dc9357SAndroid Build Coastguard Worker     if (res != SZ_OK)
854*f6dc9357SAndroid Build Coastguard Worker     {
855*f6dc9357SAndroid Build Coastguard Worker       if (res == SZ_ERROR_CRC)
856*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
857*f6dc9357SAndroid Build Coastguard Worker       return SResToHRESULT(res);
858*f6dc9357SAndroid Build Coastguard Worker     }
859*f6dc9357SAndroid Build Coastguard Worker 
860*f6dc9357SAndroid Build Coastguard Worker     inPos += inLen;
861*f6dc9357SAndroid Build Coastguard Worker     outPos += outLen;
862*f6dc9357SAndroid Build Coastguard Worker 
863*f6dc9357SAndroid Build Coastguard Worker     packRem -= inLen;
864*f6dc9357SAndroid Build Coastguard Worker 
865*f6dc9357SAndroid Build Coastguard Worker     const BoolInt blockFinished = XzUnpacker_IsBlockFinished(&xzu.p);
866*f6dc9357SAndroid Build Coastguard Worker 
867*f6dc9357SAndroid Build Coastguard Worker     if ((inLen == 0 && outLen == 0) || blockFinished)
868*f6dc9357SAndroid Build Coastguard Worker     {
869*f6dc9357SAndroid Build Coastguard Worker       if (packRem != 0 || !blockFinished || unpackSize != outPos)
870*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
871*f6dc9357SAndroid Build Coastguard Worker       if (XzUnpacker_GetPackSizeForIndex(&xzu.p) != packSize)
872*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
873*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
874*f6dc9357SAndroid Build Coastguard Worker     }
875*f6dc9357SAndroid Build Coastguard Worker   }
876*f6dc9357SAndroid Build Coastguard Worker }
877*f6dc9357SAndroid Build Coastguard Worker 
878*f6dc9357SAndroid Build Coastguard Worker 
879*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
880*f6dc9357SAndroid Build Coastguard Worker {
881*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
882*f6dc9357SAndroid Build Coastguard Worker 
883*f6dc9357SAndroid Build Coastguard Worker   if (processedSize)
884*f6dc9357SAndroid Build Coastguard Worker     *processedSize = 0;
885*f6dc9357SAndroid Build Coastguard Worker   if (size == 0)
886*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
887*f6dc9357SAndroid Build Coastguard Worker 
888*f6dc9357SAndroid Build Coastguard Worker   {
889*f6dc9357SAndroid Build Coastguard Worker     if (_virtPos >= Size)
890*f6dc9357SAndroid Build Coastguard Worker       return S_OK; // (Size == _virtPos) ? S_OK: E_FAIL;
891*f6dc9357SAndroid Build Coastguard Worker     {
892*f6dc9357SAndroid Build Coastguard Worker       UInt64 rem = Size - _virtPos;
893*f6dc9357SAndroid Build Coastguard Worker       if (size > rem)
894*f6dc9357SAndroid Build Coastguard Worker         size = (UInt32)rem;
895*f6dc9357SAndroid Build Coastguard Worker     }
896*f6dc9357SAndroid Build Coastguard Worker   }
897*f6dc9357SAndroid Build Coastguard Worker 
898*f6dc9357SAndroid Build Coastguard Worker   if (size == 0)
899*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
900*f6dc9357SAndroid Build Coastguard Worker 
901*f6dc9357SAndroid Build Coastguard Worker   if (_virtPos < _cacheStartPos || _virtPos >= _cacheStartPos + _cacheSize)
902*f6dc9357SAndroid Build Coastguard Worker   {
903*f6dc9357SAndroid Build Coastguard Worker     const size_t bi = FindBlock(_handlerSpec->_blocks, _handlerSpec->_blocksArraySize, _virtPos);
904*f6dc9357SAndroid Build Coastguard Worker     const CBlockInfo &block = _handlerSpec->_blocks[bi];
905*f6dc9357SAndroid Build Coastguard Worker     const UInt64 unpackSize = _handlerSpec->_blocks[bi + 1].UnpackPos - block.UnpackPos;
906*f6dc9357SAndroid Build Coastguard Worker     if (_cache.Size() < unpackSize)
907*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
908*f6dc9357SAndroid Build Coastguard Worker 
909*f6dc9357SAndroid Build Coastguard Worker     _cacheSize = 0;
910*f6dc9357SAndroid Build Coastguard Worker 
911*f6dc9357SAndroid Build Coastguard Worker     RINOK(_handlerSpec->SeekToPackPos(block.PackPos))
912*f6dc9357SAndroid Build Coastguard Worker     RINOK(DecodeBlock(xz, _handlerSpec->_seqStream, block.StreamFlags, block.PackSize,
913*f6dc9357SAndroid Build Coastguard Worker         (size_t)unpackSize, _cache))
914*f6dc9357SAndroid Build Coastguard Worker     _cacheStartPos = block.UnpackPos;
915*f6dc9357SAndroid Build Coastguard Worker     _cacheSize = (size_t)unpackSize;
916*f6dc9357SAndroid Build Coastguard Worker   }
917*f6dc9357SAndroid Build Coastguard Worker 
918*f6dc9357SAndroid Build Coastguard Worker   {
919*f6dc9357SAndroid Build Coastguard Worker     const size_t offset = (size_t)(_virtPos - _cacheStartPos);
920*f6dc9357SAndroid Build Coastguard Worker     const size_t rem = _cacheSize - offset;
921*f6dc9357SAndroid Build Coastguard Worker     if (size > rem)
922*f6dc9357SAndroid Build Coastguard Worker       size = (UInt32)rem;
923*f6dc9357SAndroid Build Coastguard Worker     memcpy(data, _cache.ConstData() + offset, size);
924*f6dc9357SAndroid Build Coastguard Worker     _virtPos += size;
925*f6dc9357SAndroid Build Coastguard Worker     if (processedSize)
926*f6dc9357SAndroid Build Coastguard Worker       *processedSize = size;
927*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
928*f6dc9357SAndroid Build Coastguard Worker   }
929*f6dc9357SAndroid Build Coastguard Worker 
930*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
931*f6dc9357SAndroid Build Coastguard Worker }
932*f6dc9357SAndroid Build Coastguard Worker 
933*f6dc9357SAndroid Build Coastguard Worker 
934*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
935*f6dc9357SAndroid Build Coastguard Worker {
936*f6dc9357SAndroid Build Coastguard Worker   switch (seekOrigin)
937*f6dc9357SAndroid Build Coastguard Worker   {
938*f6dc9357SAndroid Build Coastguard Worker     case STREAM_SEEK_SET: break;
939*f6dc9357SAndroid Build Coastguard Worker     case STREAM_SEEK_CUR: offset += _virtPos; break;
940*f6dc9357SAndroid Build Coastguard Worker     case STREAM_SEEK_END: offset += Size; break;
941*f6dc9357SAndroid Build Coastguard Worker     default: return STG_E_INVALIDFUNCTION;
942*f6dc9357SAndroid Build Coastguard Worker   }
943*f6dc9357SAndroid Build Coastguard Worker   if (offset < 0)
944*f6dc9357SAndroid Build Coastguard Worker     return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
945*f6dc9357SAndroid Build Coastguard Worker   _virtPos = (UInt64)offset;
946*f6dc9357SAndroid Build Coastguard Worker   if (newPosition)
947*f6dc9357SAndroid Build Coastguard Worker     *newPosition = (UInt64)offset;
948*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
949*f6dc9357SAndroid Build Coastguard Worker }
950*f6dc9357SAndroid Build Coastguard Worker 
951*f6dc9357SAndroid Build Coastguard Worker 
952*f6dc9357SAndroid Build Coastguard Worker 
953*f6dc9357SAndroid Build Coastguard Worker static const UInt64 kMaxBlockSize_for_GetStream = (UInt64)1 << 40;
954*f6dc9357SAndroid Build Coastguard Worker 
955*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
956*f6dc9357SAndroid Build Coastguard Worker {
957*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
958*f6dc9357SAndroid Build Coastguard Worker 
959*f6dc9357SAndroid Build Coastguard Worker   *stream = NULL;
960*f6dc9357SAndroid Build Coastguard Worker 
961*f6dc9357SAndroid Build Coastguard Worker   if (index != 0)
962*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
963*f6dc9357SAndroid Build Coastguard Worker 
964*f6dc9357SAndroid Build Coastguard Worker   if (!_stat.UnpackSize_Defined
965*f6dc9357SAndroid Build Coastguard Worker       || _maxBlocksSize == 0 // 18.02
966*f6dc9357SAndroid Build Coastguard Worker       || _maxBlocksSize > kMaxBlockSize_for_GetStream
967*f6dc9357SAndroid Build Coastguard Worker       || _maxBlocksSize != (size_t)_maxBlocksSize)
968*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
969*f6dc9357SAndroid Build Coastguard Worker 
970*f6dc9357SAndroid Build Coastguard Worker   size_t memSize;
971*f6dc9357SAndroid Build Coastguard Worker   if (!NSystem::GetRamSize(memSize))
972*f6dc9357SAndroid Build Coastguard Worker     memSize = (size_t)sizeof(size_t) << 28;
973*f6dc9357SAndroid Build Coastguard Worker   {
974*f6dc9357SAndroid Build Coastguard Worker     if (_maxBlocksSize > memSize / 4)
975*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
976*f6dc9357SAndroid Build Coastguard Worker   }
977*f6dc9357SAndroid Build Coastguard Worker 
978*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2<ISequentialInStream, CInStream> spec;
979*f6dc9357SAndroid Build Coastguard Worker   spec.Create_if_Empty();
980*f6dc9357SAndroid Build Coastguard Worker   spec->_cache.Alloc((size_t)_maxBlocksSize);
981*f6dc9357SAndroid Build Coastguard Worker   spec->_handlerSpec.SetFromCls(this);
982*f6dc9357SAndroid Build Coastguard Worker   // spec->_handler = (IInArchive *)this;
983*f6dc9357SAndroid Build Coastguard Worker   spec->Size = _stat.OutSize;
984*f6dc9357SAndroid Build Coastguard Worker   spec->InitAndSeek();
985*f6dc9357SAndroid Build Coastguard Worker 
986*f6dc9357SAndroid Build Coastguard Worker   *stream = spec.Detach();
987*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
988*f6dc9357SAndroid Build Coastguard Worker 
989*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
990*f6dc9357SAndroid Build Coastguard Worker }
991*f6dc9357SAndroid Build Coastguard Worker 
992*f6dc9357SAndroid Build Coastguard Worker 
993*f6dc9357SAndroid Build Coastguard Worker static Int32 Get_Extract_OperationResult(const NCompress::NXz::CDecoder &decoder)
994*f6dc9357SAndroid Build Coastguard Worker {
995*f6dc9357SAndroid Build Coastguard Worker   Int32 opRes;
996*f6dc9357SAndroid Build Coastguard Worker   SRes sres = decoder.MainDecodeSRes;
997*f6dc9357SAndroid Build Coastguard Worker   if (sres == SZ_ERROR_NO_ARCHIVE) // (!IsArc)
998*f6dc9357SAndroid Build Coastguard Worker     opRes = NExtract::NOperationResult::kIsNotArc;
999*f6dc9357SAndroid Build Coastguard Worker   else if (sres == SZ_ERROR_INPUT_EOF) // (UnexpectedEnd)
1000*f6dc9357SAndroid Build Coastguard Worker     opRes = NExtract::NOperationResult::kUnexpectedEnd;
1001*f6dc9357SAndroid Build Coastguard Worker   else if (decoder.Stat.DataAfterEnd)
1002*f6dc9357SAndroid Build Coastguard Worker     opRes = NExtract::NOperationResult::kDataAfterEnd;
1003*f6dc9357SAndroid Build Coastguard Worker   else if (sres == SZ_ERROR_CRC) // (CrcError)
1004*f6dc9357SAndroid Build Coastguard Worker     opRes = NExtract::NOperationResult::kCRCError;
1005*f6dc9357SAndroid Build Coastguard Worker   else if (sres == SZ_ERROR_UNSUPPORTED) // (Unsupported)
1006*f6dc9357SAndroid Build Coastguard Worker     opRes = NExtract::NOperationResult::kUnsupportedMethod;
1007*f6dc9357SAndroid Build Coastguard Worker   else if (sres == SZ_ERROR_ARCHIVE) //  (HeadersError)
1008*f6dc9357SAndroid Build Coastguard Worker     opRes = NExtract::NOperationResult::kDataError;
1009*f6dc9357SAndroid Build Coastguard Worker   else if (sres == SZ_ERROR_DATA)  // (DataError)
1010*f6dc9357SAndroid Build Coastguard Worker     opRes = NExtract::NOperationResult::kDataError;
1011*f6dc9357SAndroid Build Coastguard Worker   else if (sres != SZ_OK)
1012*f6dc9357SAndroid Build Coastguard Worker     opRes = NExtract::NOperationResult::kDataError;
1013*f6dc9357SAndroid Build Coastguard Worker   else
1014*f6dc9357SAndroid Build Coastguard Worker     opRes = NExtract::NOperationResult::kOK;
1015*f6dc9357SAndroid Build Coastguard Worker   return opRes;
1016*f6dc9357SAndroid Build Coastguard Worker }
1017*f6dc9357SAndroid Build Coastguard Worker 
1018*f6dc9357SAndroid Build Coastguard Worker 
1019*f6dc9357SAndroid Build Coastguard Worker 
1020*f6dc9357SAndroid Build Coastguard Worker 
1021*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1022*f6dc9357SAndroid Build Coastguard Worker     Int32 testMode, IArchiveExtractCallback *extractCallback))
1023*f6dc9357SAndroid Build Coastguard Worker {
1024*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
1025*f6dc9357SAndroid Build Coastguard Worker   if (numItems == 0)
1026*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
1027*f6dc9357SAndroid Build Coastguard Worker   if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
1028*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
1029*f6dc9357SAndroid Build Coastguard Worker 
1030*f6dc9357SAndroid Build Coastguard Worker   const CXzStatInfo *stat = GetStat();
1031*f6dc9357SAndroid Build Coastguard Worker 
1032*f6dc9357SAndroid Build Coastguard Worker   if (stat)
1033*f6dc9357SAndroid Build Coastguard Worker     RINOK(extractCallback->SetTotal(stat->InSize))
1034*f6dc9357SAndroid Build Coastguard Worker 
1035*f6dc9357SAndroid Build Coastguard Worker   UInt64 currentTotalPacked = 0;
1036*f6dc9357SAndroid Build Coastguard Worker   RINOK(extractCallback->SetCompleted(&currentTotalPacked))
1037*f6dc9357SAndroid Build Coastguard Worker   Int32 opRes;
1038*f6dc9357SAndroid Build Coastguard Worker  {
1039*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialOutStream> realOutStream;
1040*f6dc9357SAndroid Build Coastguard Worker   const Int32 askMode = testMode ?
1041*f6dc9357SAndroid Build Coastguard Worker       NExtract::NAskMode::kTest :
1042*f6dc9357SAndroid Build Coastguard Worker       NExtract::NAskMode::kExtract;
1043*f6dc9357SAndroid Build Coastguard Worker 
1044*f6dc9357SAndroid Build Coastguard Worker   RINOK(extractCallback->GetStream(0, &realOutStream, askMode))
1045*f6dc9357SAndroid Build Coastguard Worker 
1046*f6dc9357SAndroid Build Coastguard Worker   if (!testMode && !realOutStream)
1047*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
1048*f6dc9357SAndroid Build Coastguard Worker 
1049*f6dc9357SAndroid Build Coastguard Worker   RINOK(extractCallback->PrepareOperation(askMode))
1050*f6dc9357SAndroid Build Coastguard Worker 
1051*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1052*f6dc9357SAndroid Build Coastguard Worker   lps->Init(extractCallback, true);
1053*f6dc9357SAndroid Build Coastguard Worker 
1054*f6dc9357SAndroid Build Coastguard Worker   if (_needSeekToStart)
1055*f6dc9357SAndroid Build Coastguard Worker   {
1056*f6dc9357SAndroid Build Coastguard Worker     if (!_stream)
1057*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
1058*f6dc9357SAndroid Build Coastguard Worker     RINOK(InStream_SeekToBegin(_stream))
1059*f6dc9357SAndroid Build Coastguard Worker   }
1060*f6dc9357SAndroid Build Coastguard Worker   else
1061*f6dc9357SAndroid Build Coastguard Worker     _needSeekToStart = true;
1062*f6dc9357SAndroid Build Coastguard Worker 
1063*f6dc9357SAndroid Build Coastguard Worker 
1064*f6dc9357SAndroid Build Coastguard Worker   NCompress::NXz::CDecoder decoder;
1065*f6dc9357SAndroid Build Coastguard Worker 
1066*f6dc9357SAndroid Build Coastguard Worker   const HRESULT hres = Decode(decoder, _seqStream, realOutStream, lps);
1067*f6dc9357SAndroid Build Coastguard Worker 
1068*f6dc9357SAndroid Build Coastguard Worker   if (!decoder.MainDecodeSRes_wasUsed)
1069*f6dc9357SAndroid Build Coastguard Worker     return hres == S_OK ? E_FAIL : hres;
1070*f6dc9357SAndroid Build Coastguard Worker 
1071*f6dc9357SAndroid Build Coastguard Worker   opRes = Get_Extract_OperationResult(decoder);
1072*f6dc9357SAndroid Build Coastguard Worker   if (opRes == NExtract::NOperationResult::kOK
1073*f6dc9357SAndroid Build Coastguard Worker       && hres != S_OK)
1074*f6dc9357SAndroid Build Coastguard Worker     opRes = NExtract::NOperationResult::kDataError;
1075*f6dc9357SAndroid Build Coastguard Worker 
1076*f6dc9357SAndroid Build Coastguard Worker   // realOutStream.Release();
1077*f6dc9357SAndroid Build Coastguard Worker  }
1078*f6dc9357SAndroid Build Coastguard Worker   return extractCallback->SetOperationResult(opRes);
1079*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
1080*f6dc9357SAndroid Build Coastguard Worker }
1081*f6dc9357SAndroid Build Coastguard Worker 
1082*f6dc9357SAndroid Build Coastguard Worker 
1083*f6dc9357SAndroid Build Coastguard Worker 
1084*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_EXTRACT_ONLY
1085*f6dc9357SAndroid Build Coastguard Worker 
1086*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *timeType))
1087*f6dc9357SAndroid Build Coastguard Worker {
1088*f6dc9357SAndroid Build Coastguard Worker   *timeType = GET_FileTimeType_NotDefined_for_GetFileTimeType;
1089*f6dc9357SAndroid Build Coastguard Worker   // *timeType = NFileTimeType::kUnix;
1090*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1091*f6dc9357SAndroid Build Coastguard Worker }
1092*f6dc9357SAndroid Build Coastguard Worker 
1093*f6dc9357SAndroid Build Coastguard Worker 
1094*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
1095*f6dc9357SAndroid Build Coastguard Worker     IArchiveUpdateCallback *updateCallback))
1096*f6dc9357SAndroid Build Coastguard Worker {
1097*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
1098*f6dc9357SAndroid Build Coastguard Worker 
1099*f6dc9357SAndroid Build Coastguard Worker   if (numItems == 0)
1100*f6dc9357SAndroid Build Coastguard Worker   {
1101*f6dc9357SAndroid Build Coastguard Worker     CSeqOutStreamWrap seqOutStream;
1102*f6dc9357SAndroid Build Coastguard Worker     seqOutStream.Init(outStream);
1103*f6dc9357SAndroid Build Coastguard Worker     SRes res = Xz_EncodeEmpty(&seqOutStream.vt);
1104*f6dc9357SAndroid Build Coastguard Worker     return SResToHRESULT(res);
1105*f6dc9357SAndroid Build Coastguard Worker   }
1106*f6dc9357SAndroid Build Coastguard Worker 
1107*f6dc9357SAndroid Build Coastguard Worker   if (numItems != 1)
1108*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
1109*f6dc9357SAndroid Build Coastguard Worker 
1110*f6dc9357SAndroid Build Coastguard Worker   {
1111*f6dc9357SAndroid Build Coastguard Worker     Z7_DECL_CMyComPtr_QI_FROM(
1112*f6dc9357SAndroid Build Coastguard Worker         IStreamSetRestriction,
1113*f6dc9357SAndroid Build Coastguard Worker         setRestriction, outStream)
1114*f6dc9357SAndroid Build Coastguard Worker     if (setRestriction)
1115*f6dc9357SAndroid Build Coastguard Worker       RINOK(setRestriction->SetRestriction(0, 0))
1116*f6dc9357SAndroid Build Coastguard Worker   }
1117*f6dc9357SAndroid Build Coastguard Worker 
1118*f6dc9357SAndroid Build Coastguard Worker   Int32 newData, newProps;
1119*f6dc9357SAndroid Build Coastguard Worker   UInt32 indexInArchive;
1120*f6dc9357SAndroid Build Coastguard Worker   if (!updateCallback)
1121*f6dc9357SAndroid Build Coastguard Worker     return E_FAIL;
1122*f6dc9357SAndroid Build Coastguard Worker   RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive))
1123*f6dc9357SAndroid Build Coastguard Worker 
1124*f6dc9357SAndroid Build Coastguard Worker   if (IntToBool(newProps))
1125*f6dc9357SAndroid Build Coastguard Worker   {
1126*f6dc9357SAndroid Build Coastguard Worker     {
1127*f6dc9357SAndroid Build Coastguard Worker       NCOM::CPropVariant prop;
1128*f6dc9357SAndroid Build Coastguard Worker       RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop))
1129*f6dc9357SAndroid Build Coastguard Worker       if (prop.vt != VT_EMPTY)
1130*f6dc9357SAndroid Build Coastguard Worker         if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)
1131*f6dc9357SAndroid Build Coastguard Worker           return E_INVALIDARG;
1132*f6dc9357SAndroid Build Coastguard Worker     }
1133*f6dc9357SAndroid Build Coastguard Worker   }
1134*f6dc9357SAndroid Build Coastguard Worker 
1135*f6dc9357SAndroid Build Coastguard Worker   if (IntToBool(newData))
1136*f6dc9357SAndroid Build Coastguard Worker   {
1137*f6dc9357SAndroid Build Coastguard Worker     UInt64 dataSize;
1138*f6dc9357SAndroid Build Coastguard Worker     {
1139*f6dc9357SAndroid Build Coastguard Worker       NCOM::CPropVariant prop;
1140*f6dc9357SAndroid Build Coastguard Worker       RINOK(updateCallback->GetProperty(0, kpidSize, &prop))
1141*f6dc9357SAndroid Build Coastguard Worker       if (prop.vt != VT_UI8)
1142*f6dc9357SAndroid Build Coastguard Worker         return E_INVALIDARG;
1143*f6dc9357SAndroid Build Coastguard Worker       dataSize = prop.uhVal.QuadPart;
1144*f6dc9357SAndroid Build Coastguard Worker     }
1145*f6dc9357SAndroid Build Coastguard Worker 
1146*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr2_Create<ICompressCoder, NCompress::NXz::CEncoder> encoder;
1147*f6dc9357SAndroid Build Coastguard Worker 
1148*f6dc9357SAndroid Build Coastguard Worker     CXzProps &xzProps = encoder->xzProps;
1149*f6dc9357SAndroid Build Coastguard Worker     CLzma2EncProps &lzma2Props = xzProps.lzma2Props;
1150*f6dc9357SAndroid Build Coastguard Worker 
1151*f6dc9357SAndroid Build Coastguard Worker     lzma2Props.lzmaProps.level = GetLevel();
1152*f6dc9357SAndroid Build Coastguard Worker 
1153*f6dc9357SAndroid Build Coastguard Worker     xzProps.reduceSize = dataSize;
1154*f6dc9357SAndroid Build Coastguard Worker     /*
1155*f6dc9357SAndroid Build Coastguard Worker     {
1156*f6dc9357SAndroid Build Coastguard Worker       NCOM::CPropVariant prop = (UInt64)dataSize;
1157*f6dc9357SAndroid Build Coastguard Worker       RINOK(encoder->SetCoderProp(NCoderPropID::kReduceSize, prop))
1158*f6dc9357SAndroid Build Coastguard Worker     }
1159*f6dc9357SAndroid Build Coastguard Worker     */
1160*f6dc9357SAndroid Build Coastguard Worker 
1161*f6dc9357SAndroid Build Coastguard Worker     #ifndef Z7_ST
1162*f6dc9357SAndroid Build Coastguard Worker 
1163*f6dc9357SAndroid Build Coastguard Worker     UInt32 numThreads = _numThreads;
1164*f6dc9357SAndroid Build Coastguard Worker 
1165*f6dc9357SAndroid Build Coastguard Worker     const UInt32 kNumThreads_Max = 1024;
1166*f6dc9357SAndroid Build Coastguard Worker     if (numThreads > kNumThreads_Max)
1167*f6dc9357SAndroid Build Coastguard Worker       numThreads = kNumThreads_Max;
1168*f6dc9357SAndroid Build Coastguard Worker 
1169*f6dc9357SAndroid Build Coastguard Worker     if (!_numThreads_WasForced
1170*f6dc9357SAndroid Build Coastguard Worker         && _numThreads >= 1
1171*f6dc9357SAndroid Build Coastguard Worker         && _memUsage_WasSet)
1172*f6dc9357SAndroid Build Coastguard Worker     {
1173*f6dc9357SAndroid Build Coastguard Worker       COneMethodInfo oneMethodInfo;
1174*f6dc9357SAndroid Build Coastguard Worker       if (!_methods.IsEmpty())
1175*f6dc9357SAndroid Build Coastguard Worker         oneMethodInfo = _methods[0];
1176*f6dc9357SAndroid Build Coastguard Worker 
1177*f6dc9357SAndroid Build Coastguard Worker       SetGlobalLevelTo(oneMethodInfo);
1178*f6dc9357SAndroid Build Coastguard Worker 
1179*f6dc9357SAndroid Build Coastguard Worker       const bool numThreads_WasSpecifiedInMethod = (oneMethodInfo.Get_NumThreads() >= 0);
1180*f6dc9357SAndroid Build Coastguard Worker       if (!numThreads_WasSpecifiedInMethod)
1181*f6dc9357SAndroid Build Coastguard Worker       {
1182*f6dc9357SAndroid Build Coastguard Worker         // here we set the (NCoderPropID::kNumThreads) property in each method, only if there is no such property already
1183*f6dc9357SAndroid Build Coastguard Worker         CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(oneMethodInfo, numThreads);
1184*f6dc9357SAndroid Build Coastguard Worker       }
1185*f6dc9357SAndroid Build Coastguard Worker 
1186*f6dc9357SAndroid Build Coastguard Worker       UInt64 cs = _numSolidBytes;
1187*f6dc9357SAndroid Build Coastguard Worker       if (cs != XZ_PROPS_BLOCK_SIZE_AUTO)
1188*f6dc9357SAndroid Build Coastguard Worker         oneMethodInfo.AddProp_BlockSize2(cs);
1189*f6dc9357SAndroid Build Coastguard Worker       cs = oneMethodInfo.Get_Xz_BlockSize();
1190*f6dc9357SAndroid Build Coastguard Worker 
1191*f6dc9357SAndroid Build Coastguard Worker       if (cs != XZ_PROPS_BLOCK_SIZE_AUTO &&
1192*f6dc9357SAndroid Build Coastguard Worker           cs != XZ_PROPS_BLOCK_SIZE_SOLID)
1193*f6dc9357SAndroid Build Coastguard Worker       {
1194*f6dc9357SAndroid Build Coastguard Worker         const UInt32 lzmaThreads = oneMethodInfo.Get_Lzma_NumThreads();
1195*f6dc9357SAndroid Build Coastguard Worker         const UInt32 numBlockThreads_Original = numThreads / lzmaThreads;
1196*f6dc9357SAndroid Build Coastguard Worker 
1197*f6dc9357SAndroid Build Coastguard Worker         if (numBlockThreads_Original > 1)
1198*f6dc9357SAndroid Build Coastguard Worker         {
1199*f6dc9357SAndroid Build Coastguard Worker           UInt32 numBlockThreads = numBlockThreads_Original;
1200*f6dc9357SAndroid Build Coastguard Worker           {
1201*f6dc9357SAndroid Build Coastguard Worker             const UInt64 lzmaMemUsage = oneMethodInfo.Get_Lzma_MemUsage(false);
1202*f6dc9357SAndroid Build Coastguard Worker             for (; numBlockThreads > 1; numBlockThreads--)
1203*f6dc9357SAndroid Build Coastguard Worker             {
1204*f6dc9357SAndroid Build Coastguard Worker               UInt64 size = numBlockThreads * (lzmaMemUsage + cs);
1205*f6dc9357SAndroid Build Coastguard Worker               UInt32 numPackChunks = numBlockThreads + (numBlockThreads / 8) + 1;
1206*f6dc9357SAndroid Build Coastguard Worker               if (cs < ((UInt32)1 << 26)) numPackChunks++;
1207*f6dc9357SAndroid Build Coastguard Worker               if (cs < ((UInt32)1 << 24)) numPackChunks++;
1208*f6dc9357SAndroid Build Coastguard Worker               if (cs < ((UInt32)1 << 22)) numPackChunks++;
1209*f6dc9357SAndroid Build Coastguard Worker               size += numPackChunks * cs;
1210*f6dc9357SAndroid Build Coastguard Worker               // printf("\nnumBlockThreads = %d, size = %d\n", (unsigned)(numBlockThreads), (unsigned)(size >> 20));
1211*f6dc9357SAndroid Build Coastguard Worker               if (size <= _memUsage_Compress)
1212*f6dc9357SAndroid Build Coastguard Worker                 break;
1213*f6dc9357SAndroid Build Coastguard Worker             }
1214*f6dc9357SAndroid Build Coastguard Worker           }
1215*f6dc9357SAndroid Build Coastguard Worker           if (numBlockThreads == 0)
1216*f6dc9357SAndroid Build Coastguard Worker             numBlockThreads = 1;
1217*f6dc9357SAndroid Build Coastguard Worker           if (numBlockThreads != numBlockThreads_Original)
1218*f6dc9357SAndroid Build Coastguard Worker             numThreads = numBlockThreads * lzmaThreads;
1219*f6dc9357SAndroid Build Coastguard Worker         }
1220*f6dc9357SAndroid Build Coastguard Worker       }
1221*f6dc9357SAndroid Build Coastguard Worker     }
1222*f6dc9357SAndroid Build Coastguard Worker     xzProps.numTotalThreads = (int)numThreads;
1223*f6dc9357SAndroid Build Coastguard Worker 
1224*f6dc9357SAndroid Build Coastguard Worker     #endif // Z7_ST
1225*f6dc9357SAndroid Build Coastguard Worker 
1226*f6dc9357SAndroid Build Coastguard Worker 
1227*f6dc9357SAndroid Build Coastguard Worker     xzProps.blockSize = _numSolidBytes;
1228*f6dc9357SAndroid Build Coastguard Worker     if (_numSolidBytes == XZ_PROPS_BLOCK_SIZE_SOLID)
1229*f6dc9357SAndroid Build Coastguard Worker     {
1230*f6dc9357SAndroid Build Coastguard Worker       xzProps.lzma2Props.blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID;
1231*f6dc9357SAndroid Build Coastguard Worker     }
1232*f6dc9357SAndroid Build Coastguard Worker 
1233*f6dc9357SAndroid Build Coastguard Worker     RINOK(encoder->SetCheckSize(_crcSize))
1234*f6dc9357SAndroid Build Coastguard Worker 
1235*f6dc9357SAndroid Build Coastguard Worker     {
1236*f6dc9357SAndroid Build Coastguard Worker       CXzFilterProps &filter = xzProps.filterProps;
1237*f6dc9357SAndroid Build Coastguard Worker 
1238*f6dc9357SAndroid Build Coastguard Worker       if (_filterId == XZ_ID_Delta)
1239*f6dc9357SAndroid Build Coastguard Worker       {
1240*f6dc9357SAndroid Build Coastguard Worker         bool deltaDefined = false;
1241*f6dc9357SAndroid Build Coastguard Worker         FOR_VECTOR (j, _filterMethod.Props)
1242*f6dc9357SAndroid Build Coastguard Worker         {
1243*f6dc9357SAndroid Build Coastguard Worker           const CProp &prop = _filterMethod.Props[j];
1244*f6dc9357SAndroid Build Coastguard Worker           if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4)
1245*f6dc9357SAndroid Build Coastguard Worker           {
1246*f6dc9357SAndroid Build Coastguard Worker             UInt32 delta = (UInt32)prop.Value.ulVal;
1247*f6dc9357SAndroid Build Coastguard Worker             if (delta < 1 || delta > 256)
1248*f6dc9357SAndroid Build Coastguard Worker               return E_INVALIDARG;
1249*f6dc9357SAndroid Build Coastguard Worker             filter.delta = delta;
1250*f6dc9357SAndroid Build Coastguard Worker             deltaDefined = true;
1251*f6dc9357SAndroid Build Coastguard Worker           }
1252*f6dc9357SAndroid Build Coastguard Worker           else
1253*f6dc9357SAndroid Build Coastguard Worker             return E_INVALIDARG;
1254*f6dc9357SAndroid Build Coastguard Worker         }
1255*f6dc9357SAndroid Build Coastguard Worker         if (!deltaDefined)
1256*f6dc9357SAndroid Build Coastguard Worker           return E_INVALIDARG;
1257*f6dc9357SAndroid Build Coastguard Worker       }
1258*f6dc9357SAndroid Build Coastguard Worker       filter.id = _filterId;
1259*f6dc9357SAndroid Build Coastguard Worker     }
1260*f6dc9357SAndroid Build Coastguard Worker 
1261*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, _methods)
1262*f6dc9357SAndroid Build Coastguard Worker     {
1263*f6dc9357SAndroid Build Coastguard Worker       COneMethodInfo &m = _methods[i];
1264*f6dc9357SAndroid Build Coastguard Worker 
1265*f6dc9357SAndroid Build Coastguard Worker       FOR_VECTOR (j, m.Props)
1266*f6dc9357SAndroid Build Coastguard Worker       {
1267*f6dc9357SAndroid Build Coastguard Worker         const CProp &prop = m.Props[j];
1268*f6dc9357SAndroid Build Coastguard Worker         RINOK(encoder->SetCoderProp(prop.Id, prop.Value))
1269*f6dc9357SAndroid Build Coastguard Worker       }
1270*f6dc9357SAndroid Build Coastguard Worker     }
1271*f6dc9357SAndroid Build Coastguard Worker 
1272*f6dc9357SAndroid Build Coastguard Worker     {
1273*f6dc9357SAndroid Build Coastguard Worker       CMyComPtr<ISequentialInStream> fileInStream;
1274*f6dc9357SAndroid Build Coastguard Worker       RINOK(updateCallback->GetStream(0, &fileInStream))
1275*f6dc9357SAndroid Build Coastguard Worker       if (!fileInStream)
1276*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
1277*f6dc9357SAndroid Build Coastguard Worker       {
1278*f6dc9357SAndroid Build Coastguard Worker         CMyComPtr<IStreamGetSize> streamGetSize;
1279*f6dc9357SAndroid Build Coastguard Worker         fileInStream.QueryInterface(IID_IStreamGetSize, &streamGetSize);
1280*f6dc9357SAndroid Build Coastguard Worker         if (streamGetSize)
1281*f6dc9357SAndroid Build Coastguard Worker         {
1282*f6dc9357SAndroid Build Coastguard Worker           UInt64 size;
1283*f6dc9357SAndroid Build Coastguard Worker           if (streamGetSize->GetSize(&size) == S_OK)
1284*f6dc9357SAndroid Build Coastguard Worker             dataSize = size;
1285*f6dc9357SAndroid Build Coastguard Worker         }
1286*f6dc9357SAndroid Build Coastguard Worker       }
1287*f6dc9357SAndroid Build Coastguard Worker       RINOK(updateCallback->SetTotal(dataSize))
1288*f6dc9357SAndroid Build Coastguard Worker       CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1289*f6dc9357SAndroid Build Coastguard Worker       lps->Init(updateCallback, true);
1290*f6dc9357SAndroid Build Coastguard Worker       RINOK(encoder.Interface()->Code(fileInStream, outStream, NULL, NULL, lps))
1291*f6dc9357SAndroid Build Coastguard Worker     }
1292*f6dc9357SAndroid Build Coastguard Worker 
1293*f6dc9357SAndroid Build Coastguard Worker     return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
1294*f6dc9357SAndroid Build Coastguard Worker   }
1295*f6dc9357SAndroid Build Coastguard Worker 
1296*f6dc9357SAndroid Build Coastguard Worker   if (indexInArchive != 0)
1297*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
1298*f6dc9357SAndroid Build Coastguard Worker 
1299*f6dc9357SAndroid Build Coastguard Worker   Z7_DECL_CMyComPtr_QI_FROM(
1300*f6dc9357SAndroid Build Coastguard Worker       IArchiveUpdateCallbackFile,
1301*f6dc9357SAndroid Build Coastguard Worker       opCallback, updateCallback)
1302*f6dc9357SAndroid Build Coastguard Worker   if (opCallback)
1303*f6dc9357SAndroid Build Coastguard Worker   {
1304*f6dc9357SAndroid Build Coastguard Worker     RINOK(opCallback->ReportOperation(NEventIndexType::kInArcIndex, 0, NUpdateNotifyOp::kReplicate))
1305*f6dc9357SAndroid Build Coastguard Worker   }
1306*f6dc9357SAndroid Build Coastguard Worker 
1307*f6dc9357SAndroid Build Coastguard Worker   if (_stream)
1308*f6dc9357SAndroid Build Coastguard Worker   {
1309*f6dc9357SAndroid Build Coastguard Worker     const CXzStatInfo *stat = GetStat();
1310*f6dc9357SAndroid Build Coastguard Worker     if (stat)
1311*f6dc9357SAndroid Build Coastguard Worker     {
1312*f6dc9357SAndroid Build Coastguard Worker       RINOK(updateCallback->SetTotal(stat->InSize))
1313*f6dc9357SAndroid Build Coastguard Worker     }
1314*f6dc9357SAndroid Build Coastguard Worker     RINOK(InStream_SeekToBegin(_stream))
1315*f6dc9357SAndroid Build Coastguard Worker   }
1316*f6dc9357SAndroid Build Coastguard Worker 
1317*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1318*f6dc9357SAndroid Build Coastguard Worker   lps->Init(updateCallback, true);
1319*f6dc9357SAndroid Build Coastguard Worker 
1320*f6dc9357SAndroid Build Coastguard Worker   return NCompress::CopyStream(_stream, outStream, lps);
1321*f6dc9357SAndroid Build Coastguard Worker 
1322*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
1323*f6dc9357SAndroid Build Coastguard Worker }
1324*f6dc9357SAndroid Build Coastguard Worker 
1325*f6dc9357SAndroid Build Coastguard Worker #endif
1326*f6dc9357SAndroid Build Coastguard Worker 
1327*f6dc9357SAndroid Build Coastguard Worker 
1328*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
1329*f6dc9357SAndroid Build Coastguard Worker {
1330*f6dc9357SAndroid Build Coastguard Worker   UString name = nameSpec;
1331*f6dc9357SAndroid Build Coastguard Worker   name.MakeLower_Ascii();
1332*f6dc9357SAndroid Build Coastguard Worker   if (name.IsEmpty())
1333*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
1334*f6dc9357SAndroid Build Coastguard Worker 
1335*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_EXTRACT_ONLY
1336*f6dc9357SAndroid Build Coastguard Worker 
1337*f6dc9357SAndroid Build Coastguard Worker   if (name[0] == L's')
1338*f6dc9357SAndroid Build Coastguard Worker   {
1339*f6dc9357SAndroid Build Coastguard Worker     const wchar_t *s = name.Ptr(1);
1340*f6dc9357SAndroid Build Coastguard Worker     if (*s == 0)
1341*f6dc9357SAndroid Build Coastguard Worker     {
1342*f6dc9357SAndroid Build Coastguard Worker       bool useStr = false;
1343*f6dc9357SAndroid Build Coastguard Worker       bool isSolid;
1344*f6dc9357SAndroid Build Coastguard Worker       switch (value.vt)
1345*f6dc9357SAndroid Build Coastguard Worker       {
1346*f6dc9357SAndroid Build Coastguard Worker         case VT_EMPTY: isSolid = true; break;
1347*f6dc9357SAndroid Build Coastguard Worker         case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break;
1348*f6dc9357SAndroid Build Coastguard Worker         case VT_BSTR:
1349*f6dc9357SAndroid Build Coastguard Worker           if (!StringToBool(value.bstrVal, isSolid))
1350*f6dc9357SAndroid Build Coastguard Worker             useStr = true;
1351*f6dc9357SAndroid Build Coastguard Worker           break;
1352*f6dc9357SAndroid Build Coastguard Worker         default: return E_INVALIDARG;
1353*f6dc9357SAndroid Build Coastguard Worker       }
1354*f6dc9357SAndroid Build Coastguard Worker       if (!useStr)
1355*f6dc9357SAndroid Build Coastguard Worker       {
1356*f6dc9357SAndroid Build Coastguard Worker         _numSolidBytes = (isSolid ? XZ_PROPS_BLOCK_SIZE_SOLID : XZ_PROPS_BLOCK_SIZE_AUTO);
1357*f6dc9357SAndroid Build Coastguard Worker         return S_OK;
1358*f6dc9357SAndroid Build Coastguard Worker       }
1359*f6dc9357SAndroid Build Coastguard Worker     }
1360*f6dc9357SAndroid Build Coastguard Worker     return ParseSizeString(s, value,
1361*f6dc9357SAndroid Build Coastguard Worker         0, // percentsBase
1362*f6dc9357SAndroid Build Coastguard Worker         _numSolidBytes) ? S_OK: E_INVALIDARG;
1363*f6dc9357SAndroid Build Coastguard Worker   }
1364*f6dc9357SAndroid Build Coastguard Worker 
1365*f6dc9357SAndroid Build Coastguard Worker   return CMultiMethodProps::SetProperty(name, value);
1366*f6dc9357SAndroid Build Coastguard Worker 
1367*f6dc9357SAndroid Build Coastguard Worker   #else
1368*f6dc9357SAndroid Build Coastguard Worker 
1369*f6dc9357SAndroid Build Coastguard Worker   {
1370*f6dc9357SAndroid Build Coastguard Worker     HRESULT hres;
1371*f6dc9357SAndroid Build Coastguard Worker     if (SetCommonProperty(name, value, hres))
1372*f6dc9357SAndroid Build Coastguard Worker       return hres;
1373*f6dc9357SAndroid Build Coastguard Worker   }
1374*f6dc9357SAndroid Build Coastguard Worker 
1375*f6dc9357SAndroid Build Coastguard Worker   return E_INVALIDARG;
1376*f6dc9357SAndroid Build Coastguard Worker 
1377*f6dc9357SAndroid Build Coastguard Worker   #endif
1378*f6dc9357SAndroid Build Coastguard Worker }
1379*f6dc9357SAndroid Build Coastguard Worker 
1380*f6dc9357SAndroid Build Coastguard Worker 
1381*f6dc9357SAndroid Build Coastguard Worker 
1382*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))
1383*f6dc9357SAndroid Build Coastguard Worker {
1384*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
1385*f6dc9357SAndroid Build Coastguard Worker 
1386*f6dc9357SAndroid Build Coastguard Worker   Init();
1387*f6dc9357SAndroid Build Coastguard Worker 
1388*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < numProps; i++)
1389*f6dc9357SAndroid Build Coastguard Worker   {
1390*f6dc9357SAndroid Build Coastguard Worker     RINOK(SetProperty(names[i], values[i]))
1391*f6dc9357SAndroid Build Coastguard Worker   }
1392*f6dc9357SAndroid Build Coastguard Worker 
1393*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_EXTRACT_ONLY
1394*f6dc9357SAndroid Build Coastguard Worker 
1395*f6dc9357SAndroid Build Coastguard Worker   if (!_filterMethod.MethodName.IsEmpty())
1396*f6dc9357SAndroid Build Coastguard Worker   {
1397*f6dc9357SAndroid Build Coastguard Worker     unsigned k;
1398*f6dc9357SAndroid Build Coastguard Worker     for (k = 0; k < Z7_ARRAY_SIZE(g_NamePairs); k++)
1399*f6dc9357SAndroid Build Coastguard Worker     {
1400*f6dc9357SAndroid Build Coastguard Worker       const CMethodNamePair &pair = g_NamePairs[k];
1401*f6dc9357SAndroid Build Coastguard Worker       if (StringsAreEqualNoCase_Ascii(_filterMethod.MethodName, pair.Name))
1402*f6dc9357SAndroid Build Coastguard Worker       {
1403*f6dc9357SAndroid Build Coastguard Worker         _filterId = pair.Id;
1404*f6dc9357SAndroid Build Coastguard Worker         break;
1405*f6dc9357SAndroid Build Coastguard Worker       }
1406*f6dc9357SAndroid Build Coastguard Worker     }
1407*f6dc9357SAndroid Build Coastguard Worker     if (k == Z7_ARRAY_SIZE(g_NamePairs))
1408*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
1409*f6dc9357SAndroid Build Coastguard Worker   }
1410*f6dc9357SAndroid Build Coastguard Worker 
1411*f6dc9357SAndroid Build Coastguard Worker   _methods.DeleteFrontal(GetNumEmptyMethods());
1412*f6dc9357SAndroid Build Coastguard Worker   if (_methods.Size() > 1)
1413*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
1414*f6dc9357SAndroid Build Coastguard Worker   if (_methods.Size() == 1)
1415*f6dc9357SAndroid Build Coastguard Worker   {
1416*f6dc9357SAndroid Build Coastguard Worker     AString &methodName = _methods[0].MethodName;
1417*f6dc9357SAndroid Build Coastguard Worker     if (methodName.IsEmpty())
1418*f6dc9357SAndroid Build Coastguard Worker       methodName = k_LZMA2_Name;
1419*f6dc9357SAndroid Build Coastguard Worker     else if (
1420*f6dc9357SAndroid Build Coastguard Worker         !methodName.IsEqualTo_Ascii_NoCase(k_LZMA2_Name)
1421*f6dc9357SAndroid Build Coastguard Worker         && !methodName.IsEqualTo_Ascii_NoCase("xz"))
1422*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
1423*f6dc9357SAndroid Build Coastguard Worker   }
1424*f6dc9357SAndroid Build Coastguard Worker 
1425*f6dc9357SAndroid Build Coastguard Worker   #endif
1426*f6dc9357SAndroid Build Coastguard Worker 
1427*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1428*f6dc9357SAndroid Build Coastguard Worker 
1429*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
1430*f6dc9357SAndroid Build Coastguard Worker }
1431*f6dc9357SAndroid Build Coastguard Worker 
1432*f6dc9357SAndroid Build Coastguard Worker 
1433*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_IO(
1434*f6dc9357SAndroid Build Coastguard Worker   "xz", "xz txz", "* .tar", 0xC,
1435*f6dc9357SAndroid Build Coastguard Worker   XZ_SIG, 0
1436*f6dc9357SAndroid Build Coastguard Worker   , NArcInfoFlags::kKeepName
1437*f6dc9357SAndroid Build Coastguard Worker   , 0
1438*f6dc9357SAndroid Build Coastguard Worker   , NULL)
1439*f6dc9357SAndroid Build Coastguard Worker 
1440*f6dc9357SAndroid Build Coastguard Worker }}
1441