1370b324cSopenharmony_ci// OpenArchive.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci// #define SHOW_DEBUG_INFO
6370b324cSopenharmony_ci
7370b324cSopenharmony_ci#ifdef SHOW_DEBUG_INFO
8370b324cSopenharmony_ci#include <stdio.h>
9370b324cSopenharmony_ci#endif
10370b324cSopenharmony_ci
11370b324cSopenharmony_ci#include "../../../../C/CpuArch.h"
12370b324cSopenharmony_ci
13370b324cSopenharmony_ci#include "../../../Common/ComTry.h"
14370b324cSopenharmony_ci#include "../../../Common/IntToString.h"
15370b324cSopenharmony_ci#include "../../../Common/StringConvert.h"
16370b324cSopenharmony_ci#include "../../../Common/StringToInt.h"
17370b324cSopenharmony_ci#include "../../../Common/UTFConvert.h"
18370b324cSopenharmony_ci#include "../../../Common/Wildcard.h"
19370b324cSopenharmony_ci
20370b324cSopenharmony_ci#include "../../../Windows/FileDir.h"
21370b324cSopenharmony_ci
22370b324cSopenharmony_ci#include "../../Common/FileStreams.h"
23370b324cSopenharmony_ci#include "../../Common/LimitedStreams.h"
24370b324cSopenharmony_ci#include "../../Common/ProgressUtils.h"
25370b324cSopenharmony_ci#include "../../Common/StreamUtils.h"
26370b324cSopenharmony_ci
27370b324cSopenharmony_ci#include "../../Compress/CopyCoder.h"
28370b324cSopenharmony_ci
29370b324cSopenharmony_ci#include "DefaultName.h"
30370b324cSopenharmony_ci#include "OpenArchive.h"
31370b324cSopenharmony_ci
32370b324cSopenharmony_ci#ifndef Z7_SFX
33370b324cSopenharmony_ci#include "SetProperties.h"
34370b324cSopenharmony_ci#endif
35370b324cSopenharmony_ci
36370b324cSopenharmony_ci#ifndef Z7_SFX
37370b324cSopenharmony_ci#ifdef SHOW_DEBUG_INFO
38370b324cSopenharmony_ci#define PRF(x) x
39370b324cSopenharmony_ci#else
40370b324cSopenharmony_ci#define PRF(x)
41370b324cSopenharmony_ci#endif
42370b324cSopenharmony_ci#endif
43370b324cSopenharmony_ci
44370b324cSopenharmony_ci// increase it, if you need to support larger SFX stubs
45370b324cSopenharmony_cistatic const UInt64 kMaxCheckStartPosition = 1 << 23;
46370b324cSopenharmony_ci
47370b324cSopenharmony_ci/*
48370b324cSopenharmony_ciOpen:
49370b324cSopenharmony_ci  - formatIndex >= 0 (exact Format)
50370b324cSopenharmony_ci       1) Open with main type. Archive handler is allowed to use archive start finder.
51370b324cSopenharmony_ci          Warning, if there is tail.
52370b324cSopenharmony_ci
53370b324cSopenharmony_ci  - formatIndex = -1 (Parser:0) (default)
54370b324cSopenharmony_ci    - same as #1 but doesn't return Parser
55370b324cSopenharmony_ci
56370b324cSopenharmony_ci  - formatIndex = -2 (#1)
57370b324cSopenharmony_ci    - file has supported extension (like a.7z)
58370b324cSopenharmony_ci      Open with that main type (only starting from start of file).
59370b324cSopenharmony_ci        - open OK:
60370b324cSopenharmony_ci            - if there is no tail - return OK
61370b324cSopenharmony_ci            - if there is tail:
62370b324cSopenharmony_ci              - archive is not "Self Exe" - return OK with Warning, that there is tail
63370b324cSopenharmony_ci              - archive is "Self Exe"
64370b324cSopenharmony_ci                ignore "Self Exe" stub, and tries to open tail
65370b324cSopenharmony_ci                  - tail can be open as archive - shows that archive and stub size property.
66370b324cSopenharmony_ci                  - tail can't be open as archive - shows Parser ???
67370b324cSopenharmony_ci        - open FAIL:
68370b324cSopenharmony_ci           Try to open with all other types from offset 0 only.
69370b324cSopenharmony_ci           If some open type is OK and physical archive size is uequal or larger
70370b324cSopenharmony_ci           than file size, then return that archive with warning that cannot be open as [extension type].
71370b324cSopenharmony_ci           If extension was EXE, it will try to open as unknown_extension case
72370b324cSopenharmony_ci    - file has unknown extension (like a.hhh)
73370b324cSopenharmony_ci       It tries to open via parser code.
74370b324cSopenharmony_ci         - if there is full archive or tail archive and unknown block or "Self Exe"
75370b324cSopenharmony_ci           at front, it shows tail archive and stub size property.
76370b324cSopenharmony_ci         - in another cases, if there is some archive inside file, it returns parser/
77370b324cSopenharmony_ci         - in another cases, it retuens S_FALSE
78370b324cSopenharmony_ci
79370b324cSopenharmony_ci
80370b324cSopenharmony_ci  - formatIndex = -3 (#2)
81370b324cSopenharmony_ci    - same as #1, but
82370b324cSopenharmony_ci    - stub (EXE) + archive is open in Parser
83370b324cSopenharmony_ci
84370b324cSopenharmony_ci  - formatIndex = -4 (#3)
85370b324cSopenharmony_ci    - returns only Parser. skip full file archive. And show other sub-archives
86370b324cSopenharmony_ci
87370b324cSopenharmony_ci  - formatIndex = -5 (#4)
88370b324cSopenharmony_ci    - returns only Parser. skip full file archive. And show other sub-archives for each byte pos
89370b324cSopenharmony_ci
90370b324cSopenharmony_ci*/
91370b324cSopenharmony_ci
92370b324cSopenharmony_ci
93370b324cSopenharmony_ci
94370b324cSopenharmony_ci
95370b324cSopenharmony_ciusing namespace NWindows;
96370b324cSopenharmony_ci
97370b324cSopenharmony_ci/*
98370b324cSopenharmony_ci#ifdef Z7_SFX
99370b324cSopenharmony_ci#define OPEN_PROPS_PARAM
100370b324cSopenharmony_ci#else
101370b324cSopenharmony_ci#define OPEN_PROPS_PARAM  , props
102370b324cSopenharmony_ci#endif
103370b324cSopenharmony_ci*/
104370b324cSopenharmony_ci
105370b324cSopenharmony_ci/*
106370b324cSopenharmony_ciCArc::~CArc()
107370b324cSopenharmony_ci{
108370b324cSopenharmony_ci  GetRawProps.Release();
109370b324cSopenharmony_ci  Archive.Release();
110370b324cSopenharmony_ci  printf("\nCArc::~CArc()\n");
111370b324cSopenharmony_ci}
112370b324cSopenharmony_ci*/
113370b324cSopenharmony_ci
114370b324cSopenharmony_ci#ifndef Z7_SFX
115370b324cSopenharmony_ci
116370b324cSopenharmony_cinamespace NArchive {
117370b324cSopenharmony_cinamespace NParser {
118370b324cSopenharmony_ci
119370b324cSopenharmony_cistruct CParseItem
120370b324cSopenharmony_ci{
121370b324cSopenharmony_ci  UInt64 Offset;
122370b324cSopenharmony_ci  UInt64 Size;
123370b324cSopenharmony_ci  // UInt64 OkSize;
124370b324cSopenharmony_ci  UString Name;
125370b324cSopenharmony_ci  UString Extension;
126370b324cSopenharmony_ci  FILETIME FileTime;
127370b324cSopenharmony_ci  UString Comment;
128370b324cSopenharmony_ci  UString ArcType;
129370b324cSopenharmony_ci
130370b324cSopenharmony_ci  bool FileTime_Defined;
131370b324cSopenharmony_ci  bool UnpackSize_Defined;
132370b324cSopenharmony_ci  bool NumSubDirs_Defined;
133370b324cSopenharmony_ci  bool NumSubFiles_Defined;
134370b324cSopenharmony_ci
135370b324cSopenharmony_ci  bool IsSelfExe;
136370b324cSopenharmony_ci  bool IsNotArcType;
137370b324cSopenharmony_ci
138370b324cSopenharmony_ci  UInt64 UnpackSize;
139370b324cSopenharmony_ci  UInt64 NumSubDirs;
140370b324cSopenharmony_ci  UInt64 NumSubFiles;
141370b324cSopenharmony_ci
142370b324cSopenharmony_ci  int FormatIndex;
143370b324cSopenharmony_ci
144370b324cSopenharmony_ci  bool LenIsUnknown;
145370b324cSopenharmony_ci
146370b324cSopenharmony_ci  CParseItem():
147370b324cSopenharmony_ci      // OkSize(0),
148370b324cSopenharmony_ci      FileTime_Defined(false),
149370b324cSopenharmony_ci      UnpackSize_Defined(false),
150370b324cSopenharmony_ci      NumSubDirs_Defined(false),
151370b324cSopenharmony_ci      NumSubFiles_Defined(false),
152370b324cSopenharmony_ci      IsSelfExe(false),
153370b324cSopenharmony_ci      IsNotArcType(false),
154370b324cSopenharmony_ci      LenIsUnknown(false)
155370b324cSopenharmony_ci    {}
156370b324cSopenharmony_ci
157370b324cSopenharmony_ci  /*
158370b324cSopenharmony_ci  bool IsEqualTo(const CParseItem &item) const
159370b324cSopenharmony_ci  {
160370b324cSopenharmony_ci    return Offset == item.Offset && Size == item.Size;
161370b324cSopenharmony_ci  }
162370b324cSopenharmony_ci  */
163370b324cSopenharmony_ci
164370b324cSopenharmony_ci  void NormalizeOffset()
165370b324cSopenharmony_ci  {
166370b324cSopenharmony_ci    if ((Int64)Offset < 0)
167370b324cSopenharmony_ci    {
168370b324cSopenharmony_ci      Size += Offset;
169370b324cSopenharmony_ci      // OkSize += Offset;
170370b324cSopenharmony_ci      Offset = 0;
171370b324cSopenharmony_ci    }
172370b324cSopenharmony_ci  }
173370b324cSopenharmony_ci};
174370b324cSopenharmony_ci
175370b324cSopenharmony_ciZ7_CLASS_IMP_CHandler_IInArchive_1(
176370b324cSopenharmony_ci  IInArchiveGetStream
177370b324cSopenharmony_ci)
178370b324cSopenharmony_cipublic:
179370b324cSopenharmony_ci  CObjectVector<CParseItem> _items;
180370b324cSopenharmony_ci  UInt64 _maxEndOffset;
181370b324cSopenharmony_ci  CMyComPtr<IInStream> _stream;
182370b324cSopenharmony_ci
183370b324cSopenharmony_ci  UInt64 GetLastEnd() const
184370b324cSopenharmony_ci  {
185370b324cSopenharmony_ci    if (_items.IsEmpty())
186370b324cSopenharmony_ci      return 0;
187370b324cSopenharmony_ci    const CParseItem &back = _items.Back();
188370b324cSopenharmony_ci    return back.Offset + back.Size;
189370b324cSopenharmony_ci  }
190370b324cSopenharmony_ci
191370b324cSopenharmony_ci  void AddUnknownItem(UInt64 next);
192370b324cSopenharmony_ci  int FindInsertPos(const CParseItem &item) const;
193370b324cSopenharmony_ci  void AddItem(const CParseItem &item);
194370b324cSopenharmony_ci
195370b324cSopenharmony_ci  CHandler(): _maxEndOffset(0) {}
196370b324cSopenharmony_ci};
197370b324cSopenharmony_ci
198370b324cSopenharmony_ciint CHandler::FindInsertPos(const CParseItem &item) const
199370b324cSopenharmony_ci{
200370b324cSopenharmony_ci  unsigned left = 0, right = _items.Size();
201370b324cSopenharmony_ci  while (left != right)
202370b324cSopenharmony_ci  {
203370b324cSopenharmony_ci    const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
204370b324cSopenharmony_ci    const CParseItem &midItem = _items[mid];
205370b324cSopenharmony_ci    if (item.Offset < midItem.Offset)
206370b324cSopenharmony_ci      right = mid;
207370b324cSopenharmony_ci    else if (item.Offset > midItem.Offset)
208370b324cSopenharmony_ci      left = mid + 1;
209370b324cSopenharmony_ci    else if (item.Size < midItem.Size)
210370b324cSopenharmony_ci      right = mid;
211370b324cSopenharmony_ci    /*
212370b324cSopenharmony_ci    else if (item.Size > midItem.Size)
213370b324cSopenharmony_ci      left = mid + 1;
214370b324cSopenharmony_ci    */
215370b324cSopenharmony_ci    else
216370b324cSopenharmony_ci    {
217370b324cSopenharmony_ci      left = mid + 1;
218370b324cSopenharmony_ci      // return -1;
219370b324cSopenharmony_ci    }
220370b324cSopenharmony_ci  }
221370b324cSopenharmony_ci  return (int)left;
222370b324cSopenharmony_ci}
223370b324cSopenharmony_ci
224370b324cSopenharmony_civoid CHandler::AddUnknownItem(UInt64 next)
225370b324cSopenharmony_ci{
226370b324cSopenharmony_ci  /*
227370b324cSopenharmony_ci  UInt64 prevEnd = 0;
228370b324cSopenharmony_ci  if (!_items.IsEmpty())
229370b324cSopenharmony_ci  {
230370b324cSopenharmony_ci    const CParseItem &back = _items.Back();
231370b324cSopenharmony_ci    prevEnd = back.Offset + back.Size;
232370b324cSopenharmony_ci  }
233370b324cSopenharmony_ci  */
234370b324cSopenharmony_ci  if (_maxEndOffset < next)
235370b324cSopenharmony_ci  {
236370b324cSopenharmony_ci    CParseItem item2;
237370b324cSopenharmony_ci    item2.Offset = _maxEndOffset;
238370b324cSopenharmony_ci    item2.Size = next - _maxEndOffset;
239370b324cSopenharmony_ci    _maxEndOffset = next;
240370b324cSopenharmony_ci    _items.Add(item2);
241370b324cSopenharmony_ci  }
242370b324cSopenharmony_ci  else if (_maxEndOffset > next && !_items.IsEmpty())
243370b324cSopenharmony_ci  {
244370b324cSopenharmony_ci    CParseItem &back = _items.Back();
245370b324cSopenharmony_ci    if (back.LenIsUnknown)
246370b324cSopenharmony_ci    {
247370b324cSopenharmony_ci      back.Size = next - back.Offset;
248370b324cSopenharmony_ci      _maxEndOffset = next;
249370b324cSopenharmony_ci    }
250370b324cSopenharmony_ci  }
251370b324cSopenharmony_ci}
252370b324cSopenharmony_ci
253370b324cSopenharmony_civoid CHandler::AddItem(const CParseItem &item)
254370b324cSopenharmony_ci{
255370b324cSopenharmony_ci  AddUnknownItem(item.Offset);
256370b324cSopenharmony_ci  const int pos = FindInsertPos(item);
257370b324cSopenharmony_ci  if (pos != -1)
258370b324cSopenharmony_ci  {
259370b324cSopenharmony_ci    _items.Insert((unsigned)pos, item);
260370b324cSopenharmony_ci    UInt64 next = item.Offset + item.Size;
261370b324cSopenharmony_ci    if (_maxEndOffset < next)
262370b324cSopenharmony_ci      _maxEndOffset = next;
263370b324cSopenharmony_ci  }
264370b324cSopenharmony_ci}
265370b324cSopenharmony_ci
266370b324cSopenharmony_ci/*
267370b324cSopenharmony_cistatic const CStatProp kProps[] =
268370b324cSopenharmony_ci{
269370b324cSopenharmony_ci  { NULL, kpidPath, VT_BSTR},
270370b324cSopenharmony_ci  { NULL, kpidSize, VT_UI8},
271370b324cSopenharmony_ci  { NULL, kpidMTime, VT_FILETIME},
272370b324cSopenharmony_ci  { NULL, kpidType, VT_BSTR},
273370b324cSopenharmony_ci  { NULL, kpidComment, VT_BSTR},
274370b324cSopenharmony_ci  { NULL, kpidOffset, VT_UI8},
275370b324cSopenharmony_ci  { NULL, kpidUnpackSize, VT_UI8},
276370b324cSopenharmony_ci//   { NULL, kpidNumSubDirs, VT_UI8},
277370b324cSopenharmony_ci};
278370b324cSopenharmony_ci*/
279370b324cSopenharmony_ci
280370b324cSopenharmony_cistatic const Byte kProps[] =
281370b324cSopenharmony_ci{
282370b324cSopenharmony_ci  kpidPath,
283370b324cSopenharmony_ci  kpidSize,
284370b324cSopenharmony_ci  kpidMTime,
285370b324cSopenharmony_ci  kpidType,
286370b324cSopenharmony_ci  kpidComment,
287370b324cSopenharmony_ci  kpidOffset,
288370b324cSopenharmony_ci  kpidUnpackSize
289370b324cSopenharmony_ci};
290370b324cSopenharmony_ci
291370b324cSopenharmony_ciIMP_IInArchive_Props
292370b324cSopenharmony_ciIMP_IInArchive_ArcProps_NO
293370b324cSopenharmony_ci
294370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* openArchiveCallback */))
295370b324cSopenharmony_ci{
296370b324cSopenharmony_ci  COM_TRY_BEGIN
297370b324cSopenharmony_ci  {
298370b324cSopenharmony_ci    Close();
299370b324cSopenharmony_ci    _stream = stream;
300370b324cSopenharmony_ci  }
301370b324cSopenharmony_ci  return S_OK;
302370b324cSopenharmony_ci  COM_TRY_END
303370b324cSopenharmony_ci}
304370b324cSopenharmony_ci
305370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::Close())
306370b324cSopenharmony_ci{
307370b324cSopenharmony_ci  _items.Clear();
308370b324cSopenharmony_ci  _stream.Release();
309370b324cSopenharmony_ci  return S_OK;
310370b324cSopenharmony_ci}
311370b324cSopenharmony_ci
312370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
313370b324cSopenharmony_ci{
314370b324cSopenharmony_ci  *numItems = _items.Size();
315370b324cSopenharmony_ci  return S_OK;
316370b324cSopenharmony_ci}
317370b324cSopenharmony_ci
318370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
319370b324cSopenharmony_ci{
320370b324cSopenharmony_ci  COM_TRY_BEGIN
321370b324cSopenharmony_ci  NCOM::CPropVariant prop;
322370b324cSopenharmony_ci
323370b324cSopenharmony_ci  const CParseItem &item = _items[index];
324370b324cSopenharmony_ci
325370b324cSopenharmony_ci  switch (propID)
326370b324cSopenharmony_ci  {
327370b324cSopenharmony_ci    case kpidPath:
328370b324cSopenharmony_ci    {
329370b324cSopenharmony_ci      char sz[32];
330370b324cSopenharmony_ci      ConvertUInt32ToString(index + 1, sz);
331370b324cSopenharmony_ci      UString s(sz);
332370b324cSopenharmony_ci      if (!item.Name.IsEmpty())
333370b324cSopenharmony_ci      {
334370b324cSopenharmony_ci        s.Add_Dot();
335370b324cSopenharmony_ci        s += item.Name;
336370b324cSopenharmony_ci      }
337370b324cSopenharmony_ci      if (!item.Extension.IsEmpty())
338370b324cSopenharmony_ci      {
339370b324cSopenharmony_ci        s.Add_Dot();
340370b324cSopenharmony_ci        s += item.Extension;
341370b324cSopenharmony_ci      }
342370b324cSopenharmony_ci      prop = s; break;
343370b324cSopenharmony_ci    }
344370b324cSopenharmony_ci    case kpidSize:
345370b324cSopenharmony_ci    case kpidPackSize: prop = item.Size; break;
346370b324cSopenharmony_ci    case kpidOffset: prop = item.Offset; break;
347370b324cSopenharmony_ci    case kpidUnpackSize: if (item.UnpackSize_Defined) prop = item.UnpackSize; break;
348370b324cSopenharmony_ci    case kpidNumSubFiles: if (item.NumSubFiles_Defined) prop = item.NumSubFiles; break;
349370b324cSopenharmony_ci    case kpidNumSubDirs: if (item.NumSubDirs_Defined) prop = item.NumSubDirs; break;
350370b324cSopenharmony_ci    case kpidMTime: if (item.FileTime_Defined) prop = item.FileTime; break;
351370b324cSopenharmony_ci    case kpidComment: if (!item.Comment.IsEmpty()) prop = item.Comment; break;
352370b324cSopenharmony_ci    case kpidType: if (!item.ArcType.IsEmpty()) prop = item.ArcType; break;
353370b324cSopenharmony_ci  }
354370b324cSopenharmony_ci  prop.Detach(value);
355370b324cSopenharmony_ci  return S_OK;
356370b324cSopenharmony_ci  COM_TRY_END
357370b324cSopenharmony_ci}
358370b324cSopenharmony_ci
359370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
360370b324cSopenharmony_ci    Int32 testMode, IArchiveExtractCallback *extractCallback))
361370b324cSopenharmony_ci{
362370b324cSopenharmony_ci  COM_TRY_BEGIN
363370b324cSopenharmony_ci
364370b324cSopenharmony_ci  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
365370b324cSopenharmony_ci  if (allFilesMode)
366370b324cSopenharmony_ci    numItems = _items.Size();
367370b324cSopenharmony_ci  if (_stream && numItems == 0)
368370b324cSopenharmony_ci    return S_OK;
369370b324cSopenharmony_ci  UInt64 totalSize = 0;
370370b324cSopenharmony_ci  UInt32 i;
371370b324cSopenharmony_ci  for (i = 0; i < numItems; i++)
372370b324cSopenharmony_ci    totalSize += _items[allFilesMode ? i : indices[i]].Size;
373370b324cSopenharmony_ci  extractCallback->SetTotal(totalSize);
374370b324cSopenharmony_ci
375370b324cSopenharmony_ci  totalSize = 0;
376370b324cSopenharmony_ci
377370b324cSopenharmony_ci  CLocalProgress *lps = new CLocalProgress;
378370b324cSopenharmony_ci  CMyComPtr<ICompressProgressInfo> progress = lps;
379370b324cSopenharmony_ci  lps->Init(extractCallback, false);
380370b324cSopenharmony_ci
381370b324cSopenharmony_ci  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
382370b324cSopenharmony_ci  CMyComPtr<ISequentialInStream> inStream(streamSpec);
383370b324cSopenharmony_ci  streamSpec->SetStream(_stream);
384370b324cSopenharmony_ci
385370b324cSopenharmony_ci  CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream;
386370b324cSopenharmony_ci  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
387370b324cSopenharmony_ci
388370b324cSopenharmony_ci  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
389370b324cSopenharmony_ci  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
390370b324cSopenharmony_ci
391370b324cSopenharmony_ci  for (i = 0; i < numItems; i++)
392370b324cSopenharmony_ci  {
393370b324cSopenharmony_ci    lps->InSize = totalSize;
394370b324cSopenharmony_ci    lps->OutSize = totalSize;
395370b324cSopenharmony_ci    RINOK(lps->SetCur())
396370b324cSopenharmony_ci    CMyComPtr<ISequentialOutStream> realOutStream;
397370b324cSopenharmony_ci    const Int32 askMode = testMode ?
398370b324cSopenharmony_ci        NExtract::NAskMode::kTest :
399370b324cSopenharmony_ci        NExtract::NAskMode::kExtract;
400370b324cSopenharmony_ci    const UInt32 index = allFilesMode ? i : indices[i];
401370b324cSopenharmony_ci    const CParseItem &item = _items[index];
402370b324cSopenharmony_ci
403370b324cSopenharmony_ci    RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
404370b324cSopenharmony_ci    UInt64 unpackSize = item.Size;
405370b324cSopenharmony_ci    totalSize += unpackSize;
406370b324cSopenharmony_ci    bool skipMode = false;
407370b324cSopenharmony_ci    if (!testMode && !realOutStream)
408370b324cSopenharmony_ci      continue;
409370b324cSopenharmony_ci    RINOK(extractCallback->PrepareOperation(askMode))
410370b324cSopenharmony_ci
411370b324cSopenharmony_ci    outStreamSpec->SetStream(realOutStream);
412370b324cSopenharmony_ci    realOutStream.Release();
413370b324cSopenharmony_ci    outStreamSpec->Init(skipMode ? 0 : unpackSize, true);
414370b324cSopenharmony_ci
415370b324cSopenharmony_ci    Int32 opRes = NExtract::NOperationResult::kOK;
416370b324cSopenharmony_ci    RINOK(InStream_SeekSet(_stream, item.Offset))
417370b324cSopenharmony_ci    streamSpec->Init(unpackSize);
418370b324cSopenharmony_ci    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress))
419370b324cSopenharmony_ci
420370b324cSopenharmony_ci    if (outStreamSpec->GetRem() != 0)
421370b324cSopenharmony_ci      opRes = NExtract::NOperationResult::kDataError;
422370b324cSopenharmony_ci    outStreamSpec->ReleaseStream();
423370b324cSopenharmony_ci    RINOK(extractCallback->SetOperationResult(opRes))
424370b324cSopenharmony_ci  }
425370b324cSopenharmony_ci
426370b324cSopenharmony_ci  return S_OK;
427370b324cSopenharmony_ci
428370b324cSopenharmony_ci  COM_TRY_END
429370b324cSopenharmony_ci}
430370b324cSopenharmony_ci
431370b324cSopenharmony_ci
432370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
433370b324cSopenharmony_ci{
434370b324cSopenharmony_ci  COM_TRY_BEGIN
435370b324cSopenharmony_ci  const CParseItem &item = _items[index];
436370b324cSopenharmony_ci  return CreateLimitedInStream(_stream, item.Offset, item.Size, stream);
437370b324cSopenharmony_ci  COM_TRY_END
438370b324cSopenharmony_ci}
439370b324cSopenharmony_ci
440370b324cSopenharmony_ci}}
441370b324cSopenharmony_ci
442370b324cSopenharmony_ci#endif
443370b324cSopenharmony_ci
444370b324cSopenharmony_ciHRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw()
445370b324cSopenharmony_ci{
446370b324cSopenharmony_ci  NCOM::CPropVariant prop;
447370b324cSopenharmony_ci  result = false;
448370b324cSopenharmony_ci  RINOK(arc->GetProperty(index, propID, &prop))
449370b324cSopenharmony_ci  if (prop.vt == VT_BOOL)
450370b324cSopenharmony_ci    result = VARIANT_BOOLToBool(prop.boolVal);
451370b324cSopenharmony_ci  else if (prop.vt != VT_EMPTY)
452370b324cSopenharmony_ci    return E_FAIL;
453370b324cSopenharmony_ci  return S_OK;
454370b324cSopenharmony_ci}
455370b324cSopenharmony_ci
456370b324cSopenharmony_ciHRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw()
457370b324cSopenharmony_ci{
458370b324cSopenharmony_ci  return Archive_GetItemBoolProp(arc, index, kpidIsDir, result);
459370b324cSopenharmony_ci}
460370b324cSopenharmony_ci
461370b324cSopenharmony_ciHRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw()
462370b324cSopenharmony_ci{
463370b324cSopenharmony_ci  return Archive_GetItemBoolProp(arc, index, kpidIsAux, result);
464370b324cSopenharmony_ci}
465370b324cSopenharmony_ci
466370b324cSopenharmony_ciHRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw()
467370b324cSopenharmony_ci{
468370b324cSopenharmony_ci  return Archive_GetItemBoolProp(arc, index, kpidIsAltStream, result);
469370b324cSopenharmony_ci}
470370b324cSopenharmony_ci
471370b324cSopenharmony_ciHRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &result) throw()
472370b324cSopenharmony_ci{
473370b324cSopenharmony_ci  return Archive_GetItemBoolProp(arc, index, kpidIsDeleted, result);
474370b324cSopenharmony_ci}
475370b324cSopenharmony_ci
476370b324cSopenharmony_cistatic HRESULT Archive_GetArcProp_Bool(IInArchive *arc, PROPID propid, bool &result) throw()
477370b324cSopenharmony_ci{
478370b324cSopenharmony_ci  NCOM::CPropVariant prop;
479370b324cSopenharmony_ci  result = false;
480370b324cSopenharmony_ci  RINOK(arc->GetArchiveProperty(propid, &prop))
481370b324cSopenharmony_ci  if (prop.vt == VT_BOOL)
482370b324cSopenharmony_ci    result = VARIANT_BOOLToBool(prop.boolVal);
483370b324cSopenharmony_ci  else if (prop.vt != VT_EMPTY)
484370b324cSopenharmony_ci    return E_FAIL;
485370b324cSopenharmony_ci  return S_OK;
486370b324cSopenharmony_ci}
487370b324cSopenharmony_ci
488370b324cSopenharmony_cistatic HRESULT Archive_GetArcProp_UInt(IInArchive *arc, PROPID propid, UInt64 &result, bool &defined)
489370b324cSopenharmony_ci{
490370b324cSopenharmony_ci  defined = false;
491370b324cSopenharmony_ci  NCOM::CPropVariant prop;
492370b324cSopenharmony_ci  RINOK(arc->GetArchiveProperty(propid, &prop))
493370b324cSopenharmony_ci  switch (prop.vt)
494370b324cSopenharmony_ci  {
495370b324cSopenharmony_ci    case VT_UI4: result = prop.ulVal; break;
496370b324cSopenharmony_ci    case VT_I4:  result = (UInt64)(Int64)prop.lVal; break;
497370b324cSopenharmony_ci    case VT_UI8: result = (UInt64)prop.uhVal.QuadPart; break;
498370b324cSopenharmony_ci    case VT_I8:  result = (UInt64)prop.hVal.QuadPart; break;
499370b324cSopenharmony_ci    case VT_EMPTY: return S_OK;
500370b324cSopenharmony_ci    default: return E_FAIL;
501370b324cSopenharmony_ci  }
502370b324cSopenharmony_ci  defined = true;
503370b324cSopenharmony_ci  return S_OK;
504370b324cSopenharmony_ci}
505370b324cSopenharmony_ci
506370b324cSopenharmony_cistatic HRESULT Archive_GetArcProp_Int(IInArchive *arc, PROPID propid, Int64 &result, bool &defined)
507370b324cSopenharmony_ci{
508370b324cSopenharmony_ci  defined = false;
509370b324cSopenharmony_ci  NCOM::CPropVariant prop;
510370b324cSopenharmony_ci  RINOK(arc->GetArchiveProperty(propid, &prop))
511370b324cSopenharmony_ci  switch (prop.vt)
512370b324cSopenharmony_ci  {
513370b324cSopenharmony_ci    case VT_UI4: result = prop.ulVal; break;
514370b324cSopenharmony_ci    case VT_I4:  result = prop.lVal; break;
515370b324cSopenharmony_ci    case VT_UI8: result = (Int64)prop.uhVal.QuadPart; break;
516370b324cSopenharmony_ci    case VT_I8:  result = (Int64)prop.hVal.QuadPart; break;
517370b324cSopenharmony_ci    case VT_EMPTY: return S_OK;
518370b324cSopenharmony_ci    default: return E_FAIL;
519370b324cSopenharmony_ci  }
520370b324cSopenharmony_ci  defined = true;
521370b324cSopenharmony_ci  return S_OK;
522370b324cSopenharmony_ci}
523370b324cSopenharmony_ci
524370b324cSopenharmony_ci#ifndef Z7_SFX
525370b324cSopenharmony_ci
526370b324cSopenharmony_ciHRESULT CArc::GetItem_PathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const
527370b324cSopenharmony_ci{
528370b324cSopenharmony_ci  if (!GetRawProps)
529370b324cSopenharmony_ci    return E_FAIL;
530370b324cSopenharmony_ci  if (index == parent)
531370b324cSopenharmony_ci    return S_OK;
532370b324cSopenharmony_ci  UInt32 curIndex = index;
533370b324cSopenharmony_ci
534370b324cSopenharmony_ci  UString s;
535370b324cSopenharmony_ci
536370b324cSopenharmony_ci  bool prevWasAltStream = false;
537370b324cSopenharmony_ci
538370b324cSopenharmony_ci  for (;;)
539370b324cSopenharmony_ci  {
540370b324cSopenharmony_ci    #ifdef MY_CPU_LE
541370b324cSopenharmony_ci    const void *p;
542370b324cSopenharmony_ci    UInt32 size;
543370b324cSopenharmony_ci    UInt32 propType;
544370b324cSopenharmony_ci    RINOK(GetRawProps->GetRawProp(curIndex, kpidName, &p, &size, &propType))
545370b324cSopenharmony_ci    if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE)
546370b324cSopenharmony_ci      s = (const wchar_t *)p;
547370b324cSopenharmony_ci    else
548370b324cSopenharmony_ci    #endif
549370b324cSopenharmony_ci    {
550370b324cSopenharmony_ci      NCOM::CPropVariant prop;
551370b324cSopenharmony_ci      RINOK(Archive->GetProperty(curIndex, kpidName, &prop))
552370b324cSopenharmony_ci      if (prop.vt == VT_BSTR && prop.bstrVal)
553370b324cSopenharmony_ci        s.SetFromBstr(prop.bstrVal);
554370b324cSopenharmony_ci      else if (prop.vt == VT_EMPTY)
555370b324cSopenharmony_ci        s.Empty();
556370b324cSopenharmony_ci      else
557370b324cSopenharmony_ci        return E_FAIL;
558370b324cSopenharmony_ci    }
559370b324cSopenharmony_ci
560370b324cSopenharmony_ci    UInt32 curParent = (UInt32)(Int32)-1;
561370b324cSopenharmony_ci    UInt32 parentType = 0;
562370b324cSopenharmony_ci    RINOK(GetRawProps->GetParent(curIndex, &curParent, &parentType))
563370b324cSopenharmony_ci
564370b324cSopenharmony_ci    // 18.06: fixed : we don't want to split name to parts
565370b324cSopenharmony_ci    /*
566370b324cSopenharmony_ci    if (parentType != NParentType::kAltStream)
567370b324cSopenharmony_ci    {
568370b324cSopenharmony_ci      for (;;)
569370b324cSopenharmony_ci      {
570370b324cSopenharmony_ci        int pos = s.ReverseFind_PathSepar();
571370b324cSopenharmony_ci        if (pos < 0)
572370b324cSopenharmony_ci        {
573370b324cSopenharmony_ci          break;
574370b324cSopenharmony_ci        }
575370b324cSopenharmony_ci        parts.Insert(0, s.Ptr(pos + 1));
576370b324cSopenharmony_ci        s.DeleteFrom(pos);
577370b324cSopenharmony_ci      }
578370b324cSopenharmony_ci    }
579370b324cSopenharmony_ci    */
580370b324cSopenharmony_ci
581370b324cSopenharmony_ci    parts.Insert(0, s);
582370b324cSopenharmony_ci
583370b324cSopenharmony_ci    if (prevWasAltStream)
584370b324cSopenharmony_ci    {
585370b324cSopenharmony_ci      {
586370b324cSopenharmony_ci        UString &s2 = parts[parts.Size() - 2];
587370b324cSopenharmony_ci        s2 += ':';
588370b324cSopenharmony_ci        s2 += parts.Back();
589370b324cSopenharmony_ci      }
590370b324cSopenharmony_ci      parts.DeleteBack();
591370b324cSopenharmony_ci    }
592370b324cSopenharmony_ci
593370b324cSopenharmony_ci    if (parent == curParent)
594370b324cSopenharmony_ci      return S_OK;
595370b324cSopenharmony_ci
596370b324cSopenharmony_ci    prevWasAltStream = false;
597370b324cSopenharmony_ci    if (parentType == NParentType::kAltStream)
598370b324cSopenharmony_ci      prevWasAltStream = true;
599370b324cSopenharmony_ci
600370b324cSopenharmony_ci    if (curParent == (UInt32)(Int32)-1)
601370b324cSopenharmony_ci      return E_FAIL;
602370b324cSopenharmony_ci    curIndex = curParent;
603370b324cSopenharmony_ci  }
604370b324cSopenharmony_ci}
605370b324cSopenharmony_ci
606370b324cSopenharmony_ci#endif
607370b324cSopenharmony_ci
608370b324cSopenharmony_ci
609370b324cSopenharmony_ci
610370b324cSopenharmony_ciHRESULT CArc::GetItem_Path(UInt32 index, UString &result) const
611370b324cSopenharmony_ci{
612370b324cSopenharmony_ci  #ifdef MY_CPU_LE
613370b324cSopenharmony_ci  if (GetRawProps)
614370b324cSopenharmony_ci  {
615370b324cSopenharmony_ci    const void *p;
616370b324cSopenharmony_ci    UInt32 size;
617370b324cSopenharmony_ci    UInt32 propType;
618370b324cSopenharmony_ci    if (!IsTree)
619370b324cSopenharmony_ci    {
620370b324cSopenharmony_ci      if (GetRawProps->GetRawProp(index, kpidPath, &p, &size, &propType) == S_OK &&
621370b324cSopenharmony_ci          propType == NPropDataType::kUtf16z)
622370b324cSopenharmony_ci      {
623370b324cSopenharmony_ci        unsigned len = size / 2 - 1;
624370b324cSopenharmony_ci        // (len) doesn't include null terminator
625370b324cSopenharmony_ci
626370b324cSopenharmony_ci        /*
627370b324cSopenharmony_ci        #if WCHAR_MAX > 0xffff
628370b324cSopenharmony_ci        len = (unsigned)Utf16LE__Get_Num_WCHARs(p, len);
629370b324cSopenharmony_ci
630370b324cSopenharmony_ci        wchar_t *s = result.GetBuf(len);
631370b324cSopenharmony_ci        wchar_t *sEnd = Utf16LE__To_WCHARs_Sep(p, len, s);
632370b324cSopenharmony_ci        if (s + len != sEnd) return E_FAIL;
633370b324cSopenharmony_ci        *sEnd = 0;
634370b324cSopenharmony_ci
635370b324cSopenharmony_ci        #else
636370b324cSopenharmony_ci        */
637370b324cSopenharmony_ci
638370b324cSopenharmony_ci        wchar_t *s = result.GetBuf(len);
639370b324cSopenharmony_ci        for (unsigned i = 0; i < len; i++)
640370b324cSopenharmony_ci        {
641370b324cSopenharmony_ci          wchar_t c = GetUi16(p);
642370b324cSopenharmony_ci          p = (const void *)((const Byte *)p + 2);
643370b324cSopenharmony_ci
644370b324cSopenharmony_ci          #if WCHAR_PATH_SEPARATOR != L'/'
645370b324cSopenharmony_ci          if (c == L'/')
646370b324cSopenharmony_ci            c = WCHAR_PATH_SEPARATOR;
647370b324cSopenharmony_ci          else if (c == L'\\')
648370b324cSopenharmony_ci            c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme
649370b324cSopenharmony_ci          #endif
650370b324cSopenharmony_ci
651370b324cSopenharmony_ci          *s++ = c;
652370b324cSopenharmony_ci        }
653370b324cSopenharmony_ci        *s = 0;
654370b324cSopenharmony_ci
655370b324cSopenharmony_ci        // #endif
656370b324cSopenharmony_ci
657370b324cSopenharmony_ci        result.ReleaseBuf_SetLen(len);
658370b324cSopenharmony_ci
659370b324cSopenharmony_ci        Convert_UnicodeEsc16_To_UnicodeEscHigh(result);
660370b324cSopenharmony_ci        if (len != 0)
661370b324cSopenharmony_ci          return S_OK;
662370b324cSopenharmony_ci      }
663370b324cSopenharmony_ci    }
664370b324cSopenharmony_ci    /*
665370b324cSopenharmony_ci    else if (GetRawProps->GetRawProp(index, kpidName, &p, &size, &propType) == S_OK &&
666370b324cSopenharmony_ci        p && propType == NPropDataType::kUtf16z)
667370b324cSopenharmony_ci    {
668370b324cSopenharmony_ci      size -= 2;
669370b324cSopenharmony_ci      UInt32 totalSize = size;
670370b324cSopenharmony_ci      bool isOK = false;
671370b324cSopenharmony_ci
672370b324cSopenharmony_ci      {
673370b324cSopenharmony_ci        UInt32 index2 = index;
674370b324cSopenharmony_ci        for (;;)
675370b324cSopenharmony_ci        {
676370b324cSopenharmony_ci          UInt32 parent = (UInt32)(Int32)-1;
677370b324cSopenharmony_ci          UInt32 parentType = 0;
678370b324cSopenharmony_ci          if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK)
679370b324cSopenharmony_ci            break;
680370b324cSopenharmony_ci          if (parent == (UInt32)(Int32)-1)
681370b324cSopenharmony_ci          {
682370b324cSopenharmony_ci            if (parentType != 0)
683370b324cSopenharmony_ci              totalSize += 2;
684370b324cSopenharmony_ci            isOK = true;
685370b324cSopenharmony_ci            break;
686370b324cSopenharmony_ci          }
687370b324cSopenharmony_ci          index2 = parent;
688370b324cSopenharmony_ci          UInt32 size2;
689370b324cSopenharmony_ci          const void *p2;
690370b324cSopenharmony_ci          if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK &&
691370b324cSopenharmony_ci              p2 && propType == NPropDataType::kUtf16z)
692370b324cSopenharmony_ci            break;
693370b324cSopenharmony_ci          totalSize += size2;
694370b324cSopenharmony_ci        }
695370b324cSopenharmony_ci      }
696370b324cSopenharmony_ci
697370b324cSopenharmony_ci      if (isOK)
698370b324cSopenharmony_ci      {
699370b324cSopenharmony_ci        wchar_t *sz = result.GetBuf_SetEnd(totalSize / 2);
700370b324cSopenharmony_ci        UInt32 pos = totalSize - size;
701370b324cSopenharmony_ci        memcpy((Byte *)sz + pos, p, size);
702370b324cSopenharmony_ci        UInt32 index2 = index;
703370b324cSopenharmony_ci        for (;;)
704370b324cSopenharmony_ci        {
705370b324cSopenharmony_ci          UInt32 parent = (UInt32)(Int32)-1;
706370b324cSopenharmony_ci          UInt32 parentType = 0;
707370b324cSopenharmony_ci          if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK)
708370b324cSopenharmony_ci            break;
709370b324cSopenharmony_ci          if (parent == (UInt32)(Int32)-1)
710370b324cSopenharmony_ci          {
711370b324cSopenharmony_ci            if (parentType != 0)
712370b324cSopenharmony_ci              sz[pos / 2 - 1] = L':';
713370b324cSopenharmony_ci            break;
714370b324cSopenharmony_ci          }
715370b324cSopenharmony_ci          index2 = parent;
716370b324cSopenharmony_ci          UInt32 size2;
717370b324cSopenharmony_ci          const void *p2;
718370b324cSopenharmony_ci          if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK)
719370b324cSopenharmony_ci            break;
720370b324cSopenharmony_ci          pos -= size2;
721370b324cSopenharmony_ci          memcpy((Byte *)sz + pos, p2, size2);
722370b324cSopenharmony_ci          sz[(pos + size2 - 2) / 2] = (parentType == 0) ? WCHAR_PATH_SEPARATOR : L':';
723370b324cSopenharmony_ci        }
724370b324cSopenharmony_ci        #ifdef _WIN32
725370b324cSopenharmony_ci        // result.Replace(L'/', WCHAR_PATH_SEPARATOR);
726370b324cSopenharmony_ci        #endif
727370b324cSopenharmony_ci        return S_OK;
728370b324cSopenharmony_ci      }
729370b324cSopenharmony_ci    }
730370b324cSopenharmony_ci    */
731370b324cSopenharmony_ci  }
732370b324cSopenharmony_ci  #endif
733370b324cSopenharmony_ci
734370b324cSopenharmony_ci  {
735370b324cSopenharmony_ci    NCOM::CPropVariant prop;
736370b324cSopenharmony_ci    RINOK(Archive->GetProperty(index, kpidPath, &prop))
737370b324cSopenharmony_ci    if (prop.vt == VT_BSTR && prop.bstrVal)
738370b324cSopenharmony_ci      result.SetFromBstr(prop.bstrVal);
739370b324cSopenharmony_ci    else if (prop.vt == VT_EMPTY)
740370b324cSopenharmony_ci      result.Empty();
741370b324cSopenharmony_ci    else
742370b324cSopenharmony_ci      return E_FAIL;
743370b324cSopenharmony_ci  }
744370b324cSopenharmony_ci
745370b324cSopenharmony_ci  if (result.IsEmpty())
746370b324cSopenharmony_ci    return GetItem_DefaultPath(index, result);
747370b324cSopenharmony_ci
748370b324cSopenharmony_ci  Convert_UnicodeEsc16_To_UnicodeEscHigh(result);
749370b324cSopenharmony_ci  return S_OK;
750370b324cSopenharmony_ci}
751370b324cSopenharmony_ci
752370b324cSopenharmony_ciHRESULT CArc::GetItem_DefaultPath(UInt32 index, UString &result) const
753370b324cSopenharmony_ci{
754370b324cSopenharmony_ci  result.Empty();
755370b324cSopenharmony_ci  bool isDir;
756370b324cSopenharmony_ci  RINOK(Archive_IsItem_Dir(Archive, index, isDir))
757370b324cSopenharmony_ci  if (!isDir)
758370b324cSopenharmony_ci  {
759370b324cSopenharmony_ci    result = DefaultName;
760370b324cSopenharmony_ci    NCOM::CPropVariant prop;
761370b324cSopenharmony_ci    RINOK(Archive->GetProperty(index, kpidExtension, &prop))
762370b324cSopenharmony_ci    if (prop.vt == VT_BSTR)
763370b324cSopenharmony_ci    {
764370b324cSopenharmony_ci      result.Add_Dot();
765370b324cSopenharmony_ci      result += prop.bstrVal;
766370b324cSopenharmony_ci    }
767370b324cSopenharmony_ci    else if (prop.vt != VT_EMPTY)
768370b324cSopenharmony_ci      return E_FAIL;
769370b324cSopenharmony_ci  }
770370b324cSopenharmony_ci  return S_OK;
771370b324cSopenharmony_ci}
772370b324cSopenharmony_ci
773370b324cSopenharmony_ciHRESULT CArc::GetItem_Path2(UInt32 index, UString &result) const
774370b324cSopenharmony_ci{
775370b324cSopenharmony_ci  RINOK(GetItem_Path(index, result))
776370b324cSopenharmony_ci  if (Ask_Deleted)
777370b324cSopenharmony_ci  {
778370b324cSopenharmony_ci    bool isDeleted = false;
779370b324cSopenharmony_ci    RINOK(Archive_IsItem_Deleted(Archive, index, isDeleted))
780370b324cSopenharmony_ci    if (isDeleted)
781370b324cSopenharmony_ci      result.Insert(0, L"[DELETED]" WSTRING_PATH_SEPARATOR);
782370b324cSopenharmony_ci  }
783370b324cSopenharmony_ci  return S_OK;
784370b324cSopenharmony_ci}
785370b324cSopenharmony_ci
786370b324cSopenharmony_ci#ifdef SUPPORT_ALT_STREAMS
787370b324cSopenharmony_ci
788370b324cSopenharmony_ciint FindAltStreamColon_in_Path(const wchar_t *path)
789370b324cSopenharmony_ci{
790370b324cSopenharmony_ci  unsigned i = 0;
791370b324cSopenharmony_ci  int colonPos = -1;
792370b324cSopenharmony_ci  for (;; i++)
793370b324cSopenharmony_ci  {
794370b324cSopenharmony_ci    wchar_t c = path[i];
795370b324cSopenharmony_ci    if (c == 0)
796370b324cSopenharmony_ci      return colonPos;
797370b324cSopenharmony_ci    if (c == ':')
798370b324cSopenharmony_ci    {
799370b324cSopenharmony_ci      if (colonPos < 0)
800370b324cSopenharmony_ci        colonPos = (int)i;
801370b324cSopenharmony_ci      continue;
802370b324cSopenharmony_ci    }
803370b324cSopenharmony_ci    if (c == WCHAR_PATH_SEPARATOR)
804370b324cSopenharmony_ci      colonPos = -1;
805370b324cSopenharmony_ci  }
806370b324cSopenharmony_ci}
807370b324cSopenharmony_ci
808370b324cSopenharmony_ci#endif
809370b324cSopenharmony_ci
810370b324cSopenharmony_ciHRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const
811370b324cSopenharmony_ci{
812370b324cSopenharmony_ci  #ifdef SUPPORT_ALT_STREAMS
813370b324cSopenharmony_ci  item.IsAltStream = false;
814370b324cSopenharmony_ci  item.AltStreamName.Empty();
815370b324cSopenharmony_ci  item.MainPath.Empty();
816370b324cSopenharmony_ci  #endif
817370b324cSopenharmony_ci
818370b324cSopenharmony_ci  item.IsDir = false;
819370b324cSopenharmony_ci  item.Path.Empty();
820370b324cSopenharmony_ci  item.ParentIndex = (UInt32)(Int32)-1;
821370b324cSopenharmony_ci
822370b324cSopenharmony_ci  item.PathParts.Clear();
823370b324cSopenharmony_ci
824370b324cSopenharmony_ci  RINOK(Archive_IsItem_Dir(Archive, index, item.IsDir))
825370b324cSopenharmony_ci  item.MainIsDir = item.IsDir;
826370b324cSopenharmony_ci
827370b324cSopenharmony_ci  RINOK(GetItem_Path2(index, item.Path))
828370b324cSopenharmony_ci
829370b324cSopenharmony_ci  #ifndef Z7_SFX
830370b324cSopenharmony_ci  UInt32 mainIndex = index;
831370b324cSopenharmony_ci  #endif
832370b324cSopenharmony_ci
833370b324cSopenharmony_ci  #ifdef SUPPORT_ALT_STREAMS
834370b324cSopenharmony_ci
835370b324cSopenharmony_ci  item.MainPath = item.Path;
836370b324cSopenharmony_ci  if (Ask_AltStream)
837370b324cSopenharmony_ci  {
838370b324cSopenharmony_ci    RINOK(Archive_IsItem_AltStream(Archive, index, item.IsAltStream))
839370b324cSopenharmony_ci  }
840370b324cSopenharmony_ci
841370b324cSopenharmony_ci  bool needFindAltStream = false;
842370b324cSopenharmony_ci
843370b324cSopenharmony_ci  if (item.IsAltStream)
844370b324cSopenharmony_ci  {
845370b324cSopenharmony_ci    needFindAltStream = true;
846370b324cSopenharmony_ci    if (GetRawProps)
847370b324cSopenharmony_ci    {
848370b324cSopenharmony_ci      UInt32 parentType = 0;
849370b324cSopenharmony_ci      UInt32 parentIndex;
850370b324cSopenharmony_ci      RINOK(GetRawProps->GetParent(index, &parentIndex, &parentType))
851370b324cSopenharmony_ci      if (parentType == NParentType::kAltStream)
852370b324cSopenharmony_ci      {
853370b324cSopenharmony_ci        NCOM::CPropVariant prop;
854370b324cSopenharmony_ci        RINOK(Archive->GetProperty(index, kpidName, &prop))
855370b324cSopenharmony_ci        if (prop.vt == VT_BSTR && prop.bstrVal)
856370b324cSopenharmony_ci          item.AltStreamName.SetFromBstr(prop.bstrVal);
857370b324cSopenharmony_ci        else if (prop.vt != VT_EMPTY)
858370b324cSopenharmony_ci          return E_FAIL;
859370b324cSopenharmony_ci        else
860370b324cSopenharmony_ci        {
861370b324cSopenharmony_ci          // item.IsAltStream = false;
862370b324cSopenharmony_ci        }
863370b324cSopenharmony_ci        /*
864370b324cSopenharmony_ci        if (item.AltStreamName.IsEmpty())
865370b324cSopenharmony_ci          item.IsAltStream = false;
866370b324cSopenharmony_ci        */
867370b324cSopenharmony_ci
868370b324cSopenharmony_ci        needFindAltStream = false;
869370b324cSopenharmony_ci        item.ParentIndex = parentIndex;
870370b324cSopenharmony_ci        mainIndex = parentIndex;
871370b324cSopenharmony_ci
872370b324cSopenharmony_ci        if (parentIndex == (UInt32)(Int32)-1)
873370b324cSopenharmony_ci        {
874370b324cSopenharmony_ci          item.MainPath.Empty();
875370b324cSopenharmony_ci          item.MainIsDir = true;
876370b324cSopenharmony_ci        }
877370b324cSopenharmony_ci        else
878370b324cSopenharmony_ci        {
879370b324cSopenharmony_ci          RINOK(GetItem_Path2(parentIndex, item.MainPath))
880370b324cSopenharmony_ci          RINOK(Archive_IsItem_Dir(Archive, parentIndex, item.MainIsDir))
881370b324cSopenharmony_ci        }
882370b324cSopenharmony_ci      }
883370b324cSopenharmony_ci    }
884370b324cSopenharmony_ci  }
885370b324cSopenharmony_ci
886370b324cSopenharmony_ci  if (item.WriteToAltStreamIfColon || needFindAltStream)
887370b324cSopenharmony_ci  {
888370b324cSopenharmony_ci    /* Good handler must support GetRawProps::GetParent for alt streams.
889370b324cSopenharmony_ci       So the following code currently is not used */
890370b324cSopenharmony_ci    int colon = FindAltStreamColon_in_Path(item.Path);
891370b324cSopenharmony_ci    if (colon >= 0)
892370b324cSopenharmony_ci    {
893370b324cSopenharmony_ci      item.MainPath.DeleteFrom((unsigned)colon);
894370b324cSopenharmony_ci      item.AltStreamName = item.Path.Ptr((unsigned)(colon + 1));
895370b324cSopenharmony_ci      item.MainIsDir = (colon == 0 || IsPathSepar(item.Path[(unsigned)colon - 1]));
896370b324cSopenharmony_ci      item.IsAltStream = true;
897370b324cSopenharmony_ci    }
898370b324cSopenharmony_ci  }
899370b324cSopenharmony_ci
900370b324cSopenharmony_ci  #endif
901370b324cSopenharmony_ci
902370b324cSopenharmony_ci  #ifndef Z7_SFX
903370b324cSopenharmony_ci  if (item._use_baseParentFolder_mode)
904370b324cSopenharmony_ci  {
905370b324cSopenharmony_ci    RINOK(GetItem_PathToParent(mainIndex, (unsigned)item._baseParentFolder, item.PathParts))
906370b324cSopenharmony_ci
907370b324cSopenharmony_ci    #ifdef SUPPORT_ALT_STREAMS
908370b324cSopenharmony_ci    if ((item.WriteToAltStreamIfColon || needFindAltStream) && !item.PathParts.IsEmpty())
909370b324cSopenharmony_ci    {
910370b324cSopenharmony_ci      int colon;
911370b324cSopenharmony_ci      {
912370b324cSopenharmony_ci        UString &s = item.PathParts.Back();
913370b324cSopenharmony_ci        colon = FindAltStreamColon_in_Path(s);
914370b324cSopenharmony_ci        if (colon >= 0)
915370b324cSopenharmony_ci        {
916370b324cSopenharmony_ci          item.AltStreamName = s.Ptr((unsigned)(colon + 1));
917370b324cSopenharmony_ci          item.MainIsDir = (colon == 0 || IsPathSepar(s[(unsigned)colon - 1]));
918370b324cSopenharmony_ci          item.IsAltStream = true;
919370b324cSopenharmony_ci          s.DeleteFrom((unsigned)colon);
920370b324cSopenharmony_ci        }
921370b324cSopenharmony_ci      }
922370b324cSopenharmony_ci      if (colon == 0)
923370b324cSopenharmony_ci        item.PathParts.DeleteBack();
924370b324cSopenharmony_ci    }
925370b324cSopenharmony_ci    #endif
926370b324cSopenharmony_ci
927370b324cSopenharmony_ci  }
928370b324cSopenharmony_ci  else
929370b324cSopenharmony_ci  #endif
930370b324cSopenharmony_ci    SplitPathToParts(
931370b324cSopenharmony_ci          #ifdef SUPPORT_ALT_STREAMS
932370b324cSopenharmony_ci            item.MainPath
933370b324cSopenharmony_ci          #else
934370b324cSopenharmony_ci            item.Path
935370b324cSopenharmony_ci          #endif
936370b324cSopenharmony_ci      , item.PathParts);
937370b324cSopenharmony_ci
938370b324cSopenharmony_ci  return S_OK;
939370b324cSopenharmony_ci}
940370b324cSopenharmony_ci
941370b324cSopenharmony_ci#ifndef Z7_SFX
942370b324cSopenharmony_ci
943370b324cSopenharmony_cistatic HRESULT Archive_GetItem_Size(IInArchive *archive, UInt32 index, UInt64 &size, bool &defined)
944370b324cSopenharmony_ci{
945370b324cSopenharmony_ci  NCOM::CPropVariant prop;
946370b324cSopenharmony_ci  defined = false;
947370b324cSopenharmony_ci  size = 0;
948370b324cSopenharmony_ci  RINOK(archive->GetProperty(index, kpidSize, &prop))
949370b324cSopenharmony_ci  switch (prop.vt)
950370b324cSopenharmony_ci  {
951370b324cSopenharmony_ci    case VT_UI1: size = prop.bVal; break;
952370b324cSopenharmony_ci    case VT_UI2: size = prop.uiVal; break;
953370b324cSopenharmony_ci    case VT_UI4: size = prop.ulVal; break;
954370b324cSopenharmony_ci    case VT_UI8: size = (UInt64)prop.uhVal.QuadPart; break;
955370b324cSopenharmony_ci    case VT_EMPTY: return S_OK;
956370b324cSopenharmony_ci    default: return E_FAIL;
957370b324cSopenharmony_ci  }
958370b324cSopenharmony_ci  defined = true;
959370b324cSopenharmony_ci  return S_OK;
960370b324cSopenharmony_ci}
961370b324cSopenharmony_ci
962370b324cSopenharmony_ci#endif
963370b324cSopenharmony_ci
964370b324cSopenharmony_ciHRESULT CArc::GetItem_Size(UInt32 index, UInt64 &size, bool &defined) const
965370b324cSopenharmony_ci{
966370b324cSopenharmony_ci  NCOM::CPropVariant prop;
967370b324cSopenharmony_ci  defined = false;
968370b324cSopenharmony_ci  size = 0;
969370b324cSopenharmony_ci  RINOK(Archive->GetProperty(index, kpidSize, &prop))
970370b324cSopenharmony_ci  switch (prop.vt)
971370b324cSopenharmony_ci  {
972370b324cSopenharmony_ci    case VT_UI1: size = prop.bVal; break;
973370b324cSopenharmony_ci    case VT_UI2: size = prop.uiVal; break;
974370b324cSopenharmony_ci    case VT_UI4: size = prop.ulVal; break;
975370b324cSopenharmony_ci    case VT_UI8: size = (UInt64)prop.uhVal.QuadPart; break;
976370b324cSopenharmony_ci    case VT_EMPTY: return S_OK;
977370b324cSopenharmony_ci    default: return E_FAIL;
978370b324cSopenharmony_ci  }
979370b324cSopenharmony_ci  defined = true;
980370b324cSopenharmony_ci  return S_OK;
981370b324cSopenharmony_ci}
982370b324cSopenharmony_ci
983370b324cSopenharmony_ciHRESULT CArc::GetItem_MTime(UInt32 index, CArcTime &at) const
984370b324cSopenharmony_ci{
985370b324cSopenharmony_ci  at.Clear();
986370b324cSopenharmony_ci  NCOM::CPropVariant prop;
987370b324cSopenharmony_ci  RINOK(Archive->GetProperty(index, kpidMTime, &prop))
988370b324cSopenharmony_ci
989370b324cSopenharmony_ci  if (prop.vt == VT_FILETIME)
990370b324cSopenharmony_ci  {
991370b324cSopenharmony_ci    /*
992370b324cSopenharmony_ci    // for debug
993370b324cSopenharmony_ci    if (FILETIME_IsZero(prop.at) && MTime.Def)
994370b324cSopenharmony_ci    {
995370b324cSopenharmony_ci      at = MTime;
996370b324cSopenharmony_ci      return S_OK;
997370b324cSopenharmony_ci    }
998370b324cSopenharmony_ci    */
999370b324cSopenharmony_ci    at.Set_From_Prop(prop);
1000370b324cSopenharmony_ci    if (at.Prec == 0)
1001370b324cSopenharmony_ci    {
1002370b324cSopenharmony_ci      // (at.Prec == 0) before version 22.
1003370b324cSopenharmony_ci      // so kpidTimeType is required for that code
1004370b324cSopenharmony_ci      prop.Clear();
1005370b324cSopenharmony_ci      RINOK(Archive->GetProperty(index, kpidTimeType, &prop))
1006370b324cSopenharmony_ci      if (prop.vt == VT_UI4)
1007370b324cSopenharmony_ci      {
1008370b324cSopenharmony_ci        UInt32 val = prop.ulVal;
1009370b324cSopenharmony_ci        if (val == NFileTimeType::kWindows)
1010370b324cSopenharmony_ci          val = k_PropVar_TimePrec_100ns;
1011370b324cSopenharmony_ci        /*
1012370b324cSopenharmony_ci        else if (val > k_PropVar_TimePrec_1ns)
1013370b324cSopenharmony_ci        {
1014370b324cSopenharmony_ci          val = k_PropVar_TimePrec_100ns;
1015370b324cSopenharmony_ci          // val = k_PropVar_TimePrec_1ns;
1016370b324cSopenharmony_ci          // return E_FAIL; // for debug
1017370b324cSopenharmony_ci        }
1018370b324cSopenharmony_ci        */
1019370b324cSopenharmony_ci        at.Prec = (UInt16)val;
1020370b324cSopenharmony_ci      }
1021370b324cSopenharmony_ci    }
1022370b324cSopenharmony_ci    return S_OK;
1023370b324cSopenharmony_ci  }
1024370b324cSopenharmony_ci
1025370b324cSopenharmony_ci  if (prop.vt != VT_EMPTY)
1026370b324cSopenharmony_ci    return E_FAIL;
1027370b324cSopenharmony_ci  if (MTime.Def)
1028370b324cSopenharmony_ci    at = MTime;
1029370b324cSopenharmony_ci  return S_OK;
1030370b324cSopenharmony_ci}
1031370b324cSopenharmony_ci
1032370b324cSopenharmony_ci#ifndef Z7_SFX
1033370b324cSopenharmony_ci
1034370b324cSopenharmony_cistatic inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size)
1035370b324cSopenharmony_ci{
1036370b324cSopenharmony_ci  for (size_t i = 0; i < size; i++)
1037370b324cSopenharmony_ci    if (p1[i] != p2[i])
1038370b324cSopenharmony_ci      return false;
1039370b324cSopenharmony_ci  return true;
1040370b324cSopenharmony_ci}
1041370b324cSopenharmony_ci
1042370b324cSopenharmony_ci
1043370b324cSopenharmony_cistatic void MakeCheckOrder(CCodecs *codecs,
1044370b324cSopenharmony_ci    CIntVector &orderIndices, unsigned numTypes, CIntVector &orderIndices2,
1045370b324cSopenharmony_ci    const Byte *data, size_t dataSize)
1046370b324cSopenharmony_ci{
1047370b324cSopenharmony_ci  for (unsigned i = 0; i < numTypes; i++)
1048370b324cSopenharmony_ci  {
1049370b324cSopenharmony_ci    const int index = orderIndices[i];
1050370b324cSopenharmony_ci    if (index < 0)
1051370b324cSopenharmony_ci      continue;
1052370b324cSopenharmony_ci    const CArcInfoEx &ai = codecs->Formats[(unsigned)index];
1053370b324cSopenharmony_ci    if (ai.SignatureOffset == 0)
1054370b324cSopenharmony_ci    {
1055370b324cSopenharmony_ci      if (ai.Signatures.IsEmpty())
1056370b324cSopenharmony_ci      {
1057370b324cSopenharmony_ci        if (dataSize != 0) // 21.04: no Signature means Empty Signature
1058370b324cSopenharmony_ci          continue;
1059370b324cSopenharmony_ci      }
1060370b324cSopenharmony_ci      else
1061370b324cSopenharmony_ci      {
1062370b324cSopenharmony_ci        unsigned k;
1063370b324cSopenharmony_ci        const CObjectVector<CByteBuffer> &sigs = ai.Signatures;
1064370b324cSopenharmony_ci        for (k = 0; k < sigs.Size(); k++)
1065370b324cSopenharmony_ci        {
1066370b324cSopenharmony_ci          const CByteBuffer &sig = sigs[k];
1067370b324cSopenharmony_ci          if (sig.Size() <= dataSize && TestSignature(data, sig, sig.Size()))
1068370b324cSopenharmony_ci            break;
1069370b324cSopenharmony_ci        }
1070370b324cSopenharmony_ci        if (k == sigs.Size())
1071370b324cSopenharmony_ci          continue;
1072370b324cSopenharmony_ci      }
1073370b324cSopenharmony_ci    }
1074370b324cSopenharmony_ci    orderIndices2.Add(index);
1075370b324cSopenharmony_ci    orderIndices[i] = -1;
1076370b324cSopenharmony_ci  }
1077370b324cSopenharmony_ci}
1078370b324cSopenharmony_ci
1079370b324cSopenharmony_ci#ifdef UNDER_CE
1080370b324cSopenharmony_ci  static const unsigned kNumHashBytes = 1;
1081370b324cSopenharmony_ci  #define HASH_VAL(buf) ((buf)[0])
1082370b324cSopenharmony_ci#else
1083370b324cSopenharmony_ci  static const unsigned kNumHashBytes = 2;
1084370b324cSopenharmony_ci  // #define HASH_VAL(buf) ((buf)[0] | ((UInt32)(buf)[1] << 8))
1085370b324cSopenharmony_ci  #define HASH_VAL(buf) GetUi16(buf)
1086370b324cSopenharmony_ci#endif
1087370b324cSopenharmony_ci
1088370b324cSopenharmony_cistatic bool IsExeExt(const UString &ext)
1089370b324cSopenharmony_ci{
1090370b324cSopenharmony_ci  return ext.IsEqualTo_Ascii_NoCase("exe");
1091370b324cSopenharmony_ci}
1092370b324cSopenharmony_ci
1093370b324cSopenharmony_cistatic const char * const k_PreArcFormats[] =
1094370b324cSopenharmony_ci{
1095370b324cSopenharmony_ci    "pe"
1096370b324cSopenharmony_ci  , "elf"
1097370b324cSopenharmony_ci  , "macho"
1098370b324cSopenharmony_ci  , "mub"
1099370b324cSopenharmony_ci  , "te"
1100370b324cSopenharmony_ci};
1101370b324cSopenharmony_ci
1102370b324cSopenharmony_cistatic bool IsNameFromList(const UString &s, const char * const names[], size_t num)
1103370b324cSopenharmony_ci{
1104370b324cSopenharmony_ci  for (unsigned i = 0; i < num; i++)
1105370b324cSopenharmony_ci    if (StringsAreEqualNoCase_Ascii(s, names[i]))
1106370b324cSopenharmony_ci      return true;
1107370b324cSopenharmony_ci  return false;
1108370b324cSopenharmony_ci}
1109370b324cSopenharmony_ci
1110370b324cSopenharmony_ci
1111370b324cSopenharmony_cistatic bool IsPreArcFormat(const CArcInfoEx &ai)
1112370b324cSopenharmony_ci{
1113370b324cSopenharmony_ci  if (ai.Flags_PreArc())
1114370b324cSopenharmony_ci    return true;
1115370b324cSopenharmony_ci  return IsNameFromList(ai.Name, k_PreArcFormats, Z7_ARRAY_SIZE(k_PreArcFormats));
1116370b324cSopenharmony_ci}
1117370b324cSopenharmony_ci
1118370b324cSopenharmony_cistatic const char * const k_Formats_with_simple_signuature[] =
1119370b324cSopenharmony_ci{
1120370b324cSopenharmony_ci    "7z"
1121370b324cSopenharmony_ci  , "xz"
1122370b324cSopenharmony_ci  , "rar"
1123370b324cSopenharmony_ci  , "bzip2"
1124370b324cSopenharmony_ci  , "gzip"
1125370b324cSopenharmony_ci  , "cab"
1126370b324cSopenharmony_ci  , "wim"
1127370b324cSopenharmony_ci  , "rpm"
1128370b324cSopenharmony_ci  , "vhd"
1129370b324cSopenharmony_ci  , "xar"
1130370b324cSopenharmony_ci};
1131370b324cSopenharmony_ci
1132370b324cSopenharmony_cistatic bool IsNewStyleSignature(const CArcInfoEx &ai)
1133370b324cSopenharmony_ci{
1134370b324cSopenharmony_ci  // if (ai.Version >= 0x91F)
1135370b324cSopenharmony_ci  if (ai.NewInterface)
1136370b324cSopenharmony_ci    return true;
1137370b324cSopenharmony_ci  return IsNameFromList(ai.Name, k_Formats_with_simple_signuature, Z7_ARRAY_SIZE(k_Formats_with_simple_signuature));
1138370b324cSopenharmony_ci}
1139370b324cSopenharmony_ci
1140370b324cSopenharmony_ci
1141370b324cSopenharmony_ci
1142370b324cSopenharmony_ciclass CArchiveOpenCallback_Offset Z7_final:
1143370b324cSopenharmony_ci  public IArchiveOpenCallback,
1144370b324cSopenharmony_ci  public IArchiveOpenVolumeCallback,
1145370b324cSopenharmony_ci #ifndef Z7_NO_CRYPTO
1146370b324cSopenharmony_ci  public ICryptoGetTextPassword,
1147370b324cSopenharmony_ci #endif
1148370b324cSopenharmony_ci  public CMyUnknownImp
1149370b324cSopenharmony_ci{
1150370b324cSopenharmony_ci  Z7_COM_QI_BEGIN2(IArchiveOpenCallback)
1151370b324cSopenharmony_ci  Z7_COM_QI_ENTRY(IArchiveOpenVolumeCallback)
1152370b324cSopenharmony_ci #ifndef Z7_NO_CRYPTO
1153370b324cSopenharmony_ci  Z7_COM_QI_ENTRY(ICryptoGetTextPassword)
1154370b324cSopenharmony_ci #endif
1155370b324cSopenharmony_ci  Z7_COM_QI_END
1156370b324cSopenharmony_ci  Z7_COM_ADDREF_RELEASE
1157370b324cSopenharmony_ci
1158370b324cSopenharmony_ci  Z7_IFACE_COM7_IMP(IArchiveOpenCallback)
1159370b324cSopenharmony_ci  Z7_IFACE_COM7_IMP(IArchiveOpenVolumeCallback)
1160370b324cSopenharmony_ci #ifndef Z7_NO_CRYPTO
1161370b324cSopenharmony_ci  Z7_IFACE_COM7_IMP(ICryptoGetTextPassword)
1162370b324cSopenharmony_ci #endif
1163370b324cSopenharmony_ci
1164370b324cSopenharmony_cipublic:
1165370b324cSopenharmony_ci  CMyComPtr<IArchiveOpenCallback> Callback;
1166370b324cSopenharmony_ci  CMyComPtr<IArchiveOpenVolumeCallback> OpenVolumeCallback;
1167370b324cSopenharmony_ci  UInt64 Files;
1168370b324cSopenharmony_ci  UInt64 Offset;
1169370b324cSopenharmony_ci
1170370b324cSopenharmony_ci  #ifndef Z7_NO_CRYPTO
1171370b324cSopenharmony_ci  CMyComPtr<ICryptoGetTextPassword> GetTextPassword;
1172370b324cSopenharmony_ci  #endif
1173370b324cSopenharmony_ci};
1174370b324cSopenharmony_ci
1175370b324cSopenharmony_ci#ifndef Z7_NO_CRYPTO
1176370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveOpenCallback_Offset::CryptoGetTextPassword(BSTR *password))
1177370b324cSopenharmony_ci{
1178370b324cSopenharmony_ci  COM_TRY_BEGIN
1179370b324cSopenharmony_ci  if (GetTextPassword)
1180370b324cSopenharmony_ci    return GetTextPassword->CryptoGetTextPassword(password);
1181370b324cSopenharmony_ci  return E_NOTIMPL;
1182370b324cSopenharmony_ci  COM_TRY_END
1183370b324cSopenharmony_ci}
1184370b324cSopenharmony_ci#endif
1185370b324cSopenharmony_ci
1186370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveOpenCallback_Offset::SetTotal(const UInt64 *, const UInt64 *))
1187370b324cSopenharmony_ci{
1188370b324cSopenharmony_ci  return S_OK;
1189370b324cSopenharmony_ci}
1190370b324cSopenharmony_ci
1191370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveOpenCallback_Offset::SetCompleted(const UInt64 *, const UInt64 *bytes))
1192370b324cSopenharmony_ci{
1193370b324cSopenharmony_ci  if (!Callback)
1194370b324cSopenharmony_ci    return S_OK;
1195370b324cSopenharmony_ci  UInt64 value = Offset;
1196370b324cSopenharmony_ci  if (bytes)
1197370b324cSopenharmony_ci    value += *bytes;
1198370b324cSopenharmony_ci  return Callback->SetCompleted(&Files, &value);
1199370b324cSopenharmony_ci}
1200370b324cSopenharmony_ci
1201370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveOpenCallback_Offset::GetProperty(PROPID propID, PROPVARIANT *value))
1202370b324cSopenharmony_ci{
1203370b324cSopenharmony_ci  if (OpenVolumeCallback)
1204370b324cSopenharmony_ci    return OpenVolumeCallback->GetProperty(propID, value);
1205370b324cSopenharmony_ci  NCOM::PropVariant_Clear(value);
1206370b324cSopenharmony_ci  return S_OK;
1207370b324cSopenharmony_ci  // return E_NOTIMPL;
1208370b324cSopenharmony_ci}
1209370b324cSopenharmony_ci
1210370b324cSopenharmony_ciZ7_COM7F_IMF(CArchiveOpenCallback_Offset::GetStream(const wchar_t *name, IInStream **inStream))
1211370b324cSopenharmony_ci{
1212370b324cSopenharmony_ci  if (OpenVolumeCallback)
1213370b324cSopenharmony_ci    return OpenVolumeCallback->GetStream(name, inStream);
1214370b324cSopenharmony_ci  return S_FALSE;
1215370b324cSopenharmony_ci}
1216370b324cSopenharmony_ci
1217370b324cSopenharmony_ci#endif
1218370b324cSopenharmony_ci
1219370b324cSopenharmony_ci
1220370b324cSopenharmony_ciUInt32 GetOpenArcErrorFlags(const NCOM::CPropVariant &prop, bool *isDefinedProp)
1221370b324cSopenharmony_ci{
1222370b324cSopenharmony_ci  if (isDefinedProp != NULL)
1223370b324cSopenharmony_ci    *isDefinedProp = false;
1224370b324cSopenharmony_ci
1225370b324cSopenharmony_ci  switch (prop.vt)
1226370b324cSopenharmony_ci  {
1227370b324cSopenharmony_ci    case VT_UI8: if (isDefinedProp) *isDefinedProp = true; return (UInt32)prop.uhVal.QuadPart;
1228370b324cSopenharmony_ci    case VT_UI4: if (isDefinedProp) *isDefinedProp = true; return prop.ulVal;
1229370b324cSopenharmony_ci    case VT_EMPTY: return 0;
1230370b324cSopenharmony_ci    default: throw 151199;
1231370b324cSopenharmony_ci  }
1232370b324cSopenharmony_ci}
1233370b324cSopenharmony_ci
1234370b324cSopenharmony_civoid CArcErrorInfo::ClearErrors()
1235370b324cSopenharmony_ci{
1236370b324cSopenharmony_ci  // ErrorFormatIndex = -1; // we don't need to clear ErrorFormatIndex here !!!
1237370b324cSopenharmony_ci
1238370b324cSopenharmony_ci  ThereIsTail = false;
1239370b324cSopenharmony_ci  UnexpecedEnd = false;
1240370b324cSopenharmony_ci  IgnoreTail = false;
1241370b324cSopenharmony_ci  // NonZerosTail = false;
1242370b324cSopenharmony_ci  ErrorFlags_Defined = false;
1243370b324cSopenharmony_ci  ErrorFlags = 0;
1244370b324cSopenharmony_ci  WarningFlags = 0;
1245370b324cSopenharmony_ci  TailSize = 0;
1246370b324cSopenharmony_ci
1247370b324cSopenharmony_ci  ErrorMessage.Empty();
1248370b324cSopenharmony_ci  WarningMessage.Empty();
1249370b324cSopenharmony_ci}
1250370b324cSopenharmony_ci
1251370b324cSopenharmony_ciHRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes)
1252370b324cSopenharmony_ci{
1253370b324cSopenharmony_ci  // OkPhySize_Defined = false;
1254370b324cSopenharmony_ci  PhySize_Defined = false;
1255370b324cSopenharmony_ci  PhySize = 0;
1256370b324cSopenharmony_ci  Offset = 0;
1257370b324cSopenharmony_ci  AvailPhySize = FileSize - startPos;
1258370b324cSopenharmony_ci
1259370b324cSopenharmony_ci  ErrorInfo.ClearErrors();
1260370b324cSopenharmony_ci  {
1261370b324cSopenharmony_ci    NCOM::CPropVariant prop;
1262370b324cSopenharmony_ci    RINOK(archive->GetArchiveProperty(kpidErrorFlags, &prop))
1263370b324cSopenharmony_ci    ErrorInfo.ErrorFlags = GetOpenArcErrorFlags(prop, &ErrorInfo.ErrorFlags_Defined);
1264370b324cSopenharmony_ci  }
1265370b324cSopenharmony_ci  {
1266370b324cSopenharmony_ci    NCOM::CPropVariant prop;
1267370b324cSopenharmony_ci    RINOK(archive->GetArchiveProperty(kpidWarningFlags, &prop))
1268370b324cSopenharmony_ci    ErrorInfo.WarningFlags = GetOpenArcErrorFlags(prop);
1269370b324cSopenharmony_ci  }
1270370b324cSopenharmony_ci
1271370b324cSopenharmony_ci  {
1272370b324cSopenharmony_ci    NCOM::CPropVariant prop;
1273370b324cSopenharmony_ci    RINOK(archive->GetArchiveProperty(kpidError, &prop))
1274370b324cSopenharmony_ci    if (prop.vt != VT_EMPTY)
1275370b324cSopenharmony_ci      ErrorInfo.ErrorMessage = (prop.vt == VT_BSTR ? prop.bstrVal : L"Unknown error");
1276370b324cSopenharmony_ci  }
1277370b324cSopenharmony_ci
1278370b324cSopenharmony_ci  {
1279370b324cSopenharmony_ci    NCOM::CPropVariant prop;
1280370b324cSopenharmony_ci    RINOK(archive->GetArchiveProperty(kpidWarning, &prop))
1281370b324cSopenharmony_ci    if (prop.vt != VT_EMPTY)
1282370b324cSopenharmony_ci      ErrorInfo.WarningMessage = (prop.vt == VT_BSTR ? prop.bstrVal : L"Unknown warning");
1283370b324cSopenharmony_ci  }
1284370b324cSopenharmony_ci
1285370b324cSopenharmony_ci  if (openRes == S_OK || ErrorInfo.IsArc_After_NonOpen())
1286370b324cSopenharmony_ci  {
1287370b324cSopenharmony_ci    RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, PhySize, PhySize_Defined))
1288370b324cSopenharmony_ci    /*
1289370b324cSopenharmony_ci    RINOK(Archive_GetArcProp_UInt(archive, kpidOkPhySize, OkPhySize, OkPhySize_Defined));
1290370b324cSopenharmony_ci    if (!OkPhySize_Defined)
1291370b324cSopenharmony_ci    {
1292370b324cSopenharmony_ci      OkPhySize_Defined = PhySize_Defined;
1293370b324cSopenharmony_ci      OkPhySize = PhySize;
1294370b324cSopenharmony_ci    }
1295370b324cSopenharmony_ci    */
1296370b324cSopenharmony_ci
1297370b324cSopenharmony_ci    bool offsetDefined;
1298370b324cSopenharmony_ci    RINOK(Archive_GetArcProp_Int(archive, kpidOffset, Offset, offsetDefined))
1299370b324cSopenharmony_ci
1300370b324cSopenharmony_ci    Int64 globalOffset = (Int64)startPos + Offset;
1301370b324cSopenharmony_ci    AvailPhySize = (UInt64)((Int64)FileSize - globalOffset);
1302370b324cSopenharmony_ci    if (PhySize_Defined)
1303370b324cSopenharmony_ci    {
1304370b324cSopenharmony_ci      UInt64 endPos = (UInt64)(globalOffset + (Int64)PhySize);
1305370b324cSopenharmony_ci      if (endPos < FileSize)
1306370b324cSopenharmony_ci      {
1307370b324cSopenharmony_ci        AvailPhySize = PhySize;
1308370b324cSopenharmony_ci        ErrorInfo.ThereIsTail = true;
1309370b324cSopenharmony_ci        ErrorInfo.TailSize = FileSize - endPos;
1310370b324cSopenharmony_ci      }
1311370b324cSopenharmony_ci      else if (endPos > FileSize)
1312370b324cSopenharmony_ci        ErrorInfo.UnexpecedEnd = true;
1313370b324cSopenharmony_ci    }
1314370b324cSopenharmony_ci  }
1315370b324cSopenharmony_ci
1316370b324cSopenharmony_ci  return S_OK;
1317370b324cSopenharmony_ci}
1318370b324cSopenharmony_ci
1319370b324cSopenharmony_ci/*
1320370b324cSopenharmony_cistatic void PrintNumber(const char *s, int n)
1321370b324cSopenharmony_ci{
1322370b324cSopenharmony_ci  char temp[100];
1323370b324cSopenharmony_ci  sprintf(temp, "%s %d", s, n);
1324370b324cSopenharmony_ci  // OutputDebugStringA(temp);
1325370b324cSopenharmony_ci  printf(temp);
1326370b324cSopenharmony_ci}
1327370b324cSopenharmony_ci*/
1328370b324cSopenharmony_ci
1329370b324cSopenharmony_ciHRESULT CArc::PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive)
1330370b324cSopenharmony_ci{
1331370b324cSopenharmony_ci  // OutputDebugStringA("a1");
1332370b324cSopenharmony_ci  // PrintNumber("formatIndex", formatIndex);
1333370b324cSopenharmony_ci
1334370b324cSopenharmony_ci  RINOK(op.codecs->CreateInArchive(formatIndex, archive))
1335370b324cSopenharmony_ci  // OutputDebugStringA("a2");
1336370b324cSopenharmony_ci  if (!archive)
1337370b324cSopenharmony_ci    return S_OK;
1338370b324cSopenharmony_ci
1339370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
1340370b324cSopenharmony_ci  if (op.codecs->NeedSetLibCodecs)
1341370b324cSopenharmony_ci  {
1342370b324cSopenharmony_ci    const CArcInfoEx &ai = op.codecs->Formats[formatIndex];
1343370b324cSopenharmony_ci    if (ai.LibIndex >= 0 ?
1344370b324cSopenharmony_ci        !op.codecs->Libs[(unsigned)ai.LibIndex].SetCodecs :
1345370b324cSopenharmony_ci        !op.codecs->Libs.IsEmpty())
1346370b324cSopenharmony_ci    {
1347370b324cSopenharmony_ci      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
1348370b324cSopenharmony_ci      archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
1349370b324cSopenharmony_ci      if (setCompressCodecsInfo)
1350370b324cSopenharmony_ci      {
1351370b324cSopenharmony_ci        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(op.codecs))
1352370b324cSopenharmony_ci      }
1353370b324cSopenharmony_ci    }
1354370b324cSopenharmony_ci  }
1355370b324cSopenharmony_ci  #endif
1356370b324cSopenharmony_ci
1357370b324cSopenharmony_ci
1358370b324cSopenharmony_ci  #ifndef Z7_SFX
1359370b324cSopenharmony_ci
1360370b324cSopenharmony_ci  const CArcInfoEx &ai = op.codecs->Formats[formatIndex];
1361370b324cSopenharmony_ci
1362370b324cSopenharmony_ci  // OutputDebugStringW(ai.Name);
1363370b324cSopenharmony_ci  // OutputDebugStringA("a3");
1364370b324cSopenharmony_ci
1365370b324cSopenharmony_ci  if (ai.Flags_PreArc())
1366370b324cSopenharmony_ci  {
1367370b324cSopenharmony_ci    /* we notify parsers that extract executables, that they don't need
1368370b324cSopenharmony_ci       to open archive, if there is tail after executable (for SFX cases) */
1369370b324cSopenharmony_ci    CMyComPtr<IArchiveAllowTail> allowTail;
1370370b324cSopenharmony_ci    archive.QueryInterface(IID_IArchiveAllowTail, (void **)&allowTail);
1371370b324cSopenharmony_ci    if (allowTail)
1372370b324cSopenharmony_ci      allowTail->AllowTail(BoolToInt(true));
1373370b324cSopenharmony_ci  }
1374370b324cSopenharmony_ci
1375370b324cSopenharmony_ci  if (op.props)
1376370b324cSopenharmony_ci  {
1377370b324cSopenharmony_ci    /*
1378370b324cSopenharmony_ci    FOR_VECTOR (y, op.props)
1379370b324cSopenharmony_ci    {
1380370b324cSopenharmony_ci      const COptionalOpenProperties &optProps = (*op.props)[y];
1381370b324cSopenharmony_ci      if (optProps.FormatName.IsEmpty() || optProps.FormatName.CompareNoCase(ai.Name) == 0)
1382370b324cSopenharmony_ci      {
1383370b324cSopenharmony_ci        RINOK(SetProperties(archive, optProps.Props));
1384370b324cSopenharmony_ci        break;
1385370b324cSopenharmony_ci      }
1386370b324cSopenharmony_ci    }
1387370b324cSopenharmony_ci    */
1388370b324cSopenharmony_ci    RINOK(SetProperties(archive, *op.props))
1389370b324cSopenharmony_ci  }
1390370b324cSopenharmony_ci
1391370b324cSopenharmony_ci  #endif
1392370b324cSopenharmony_ci  return S_OK;
1393370b324cSopenharmony_ci}
1394370b324cSopenharmony_ci
1395370b324cSopenharmony_ci#ifndef Z7_SFX
1396370b324cSopenharmony_ci
1397370b324cSopenharmony_cistatic HRESULT ReadParseItemProps(IInArchive *archive, const CArcInfoEx &ai, NArchive::NParser::CParseItem &pi)
1398370b324cSopenharmony_ci{
1399370b324cSopenharmony_ci  pi.Extension = ai.GetMainExt();
1400370b324cSopenharmony_ci  pi.FileTime_Defined = false;
1401370b324cSopenharmony_ci  pi.ArcType = ai.Name;
1402370b324cSopenharmony_ci
1403370b324cSopenharmony_ci  RINOK(Archive_GetArcProp_Bool(archive, kpidIsNotArcType, pi.IsNotArcType))
1404370b324cSopenharmony_ci
1405370b324cSopenharmony_ci  // RINOK(Archive_GetArcProp_Bool(archive, kpidIsSelfExe, pi.IsSelfExe));
1406370b324cSopenharmony_ci  pi.IsSelfExe = ai.Flags_PreArc();
1407370b324cSopenharmony_ci
1408370b324cSopenharmony_ci  {
1409370b324cSopenharmony_ci    NCOM::CPropVariant prop;
1410370b324cSopenharmony_ci    RINOK(archive->GetArchiveProperty(kpidMTime, &prop))
1411370b324cSopenharmony_ci    if (prop.vt == VT_FILETIME)
1412370b324cSopenharmony_ci    {
1413370b324cSopenharmony_ci      pi.FileTime_Defined = true;
1414370b324cSopenharmony_ci      pi.FileTime = prop.filetime;
1415370b324cSopenharmony_ci    }
1416370b324cSopenharmony_ci  }
1417370b324cSopenharmony_ci
1418370b324cSopenharmony_ci  if (!pi.FileTime_Defined)
1419370b324cSopenharmony_ci  {
1420370b324cSopenharmony_ci    NCOM::CPropVariant prop;
1421370b324cSopenharmony_ci    RINOK(archive->GetArchiveProperty(kpidCTime, &prop))
1422370b324cSopenharmony_ci    if (prop.vt == VT_FILETIME)
1423370b324cSopenharmony_ci    {
1424370b324cSopenharmony_ci      pi.FileTime_Defined = true;
1425370b324cSopenharmony_ci      pi.FileTime = prop.filetime;
1426370b324cSopenharmony_ci    }
1427370b324cSopenharmony_ci  }
1428370b324cSopenharmony_ci
1429370b324cSopenharmony_ci  {
1430370b324cSopenharmony_ci    NCOM::CPropVariant prop;
1431370b324cSopenharmony_ci    RINOK(archive->GetArchiveProperty(kpidName, &prop))
1432370b324cSopenharmony_ci    if (prop.vt == VT_BSTR)
1433370b324cSopenharmony_ci    {
1434370b324cSopenharmony_ci      pi.Name.SetFromBstr(prop.bstrVal);
1435370b324cSopenharmony_ci      pi.Extension.Empty();
1436370b324cSopenharmony_ci    }
1437370b324cSopenharmony_ci    else
1438370b324cSopenharmony_ci    {
1439370b324cSopenharmony_ci      RINOK(archive->GetArchiveProperty(kpidExtension, &prop))
1440370b324cSopenharmony_ci      if (prop.vt == VT_BSTR)
1441370b324cSopenharmony_ci        pi.Extension.SetFromBstr(prop.bstrVal);
1442370b324cSopenharmony_ci    }
1443370b324cSopenharmony_ci  }
1444370b324cSopenharmony_ci
1445370b324cSopenharmony_ci  {
1446370b324cSopenharmony_ci    NCOM::CPropVariant prop;
1447370b324cSopenharmony_ci    RINOK(archive->GetArchiveProperty(kpidShortComment, &prop))
1448370b324cSopenharmony_ci    if (prop.vt == VT_BSTR)
1449370b324cSopenharmony_ci      pi.Comment.SetFromBstr(prop.bstrVal);
1450370b324cSopenharmony_ci  }
1451370b324cSopenharmony_ci
1452370b324cSopenharmony_ci
1453370b324cSopenharmony_ci  UInt32 numItems;
1454370b324cSopenharmony_ci  RINOK(archive->GetNumberOfItems(&numItems))
1455370b324cSopenharmony_ci
1456370b324cSopenharmony_ci  // pi.NumSubFiles = numItems;
1457370b324cSopenharmony_ci  // RINOK(Archive_GetArcProp_UInt(archive, kpidUnpackSize, pi.UnpackSize, pi.UnpackSize_Defined));
1458370b324cSopenharmony_ci  // if (!pi.UnpackSize_Defined)
1459370b324cSopenharmony_ci  {
1460370b324cSopenharmony_ci    pi.NumSubFiles = 0;
1461370b324cSopenharmony_ci    pi.NumSubDirs = 0;
1462370b324cSopenharmony_ci    pi.UnpackSize = 0;
1463370b324cSopenharmony_ci    for (UInt32 i = 0; i < numItems; i++)
1464370b324cSopenharmony_ci    {
1465370b324cSopenharmony_ci      UInt64 size = 0;
1466370b324cSopenharmony_ci      bool defined = false;
1467370b324cSopenharmony_ci      Archive_GetItem_Size(archive, i, size, defined);
1468370b324cSopenharmony_ci      if (defined)
1469370b324cSopenharmony_ci      {
1470370b324cSopenharmony_ci        pi.UnpackSize_Defined = true;
1471370b324cSopenharmony_ci        pi.UnpackSize += size;
1472370b324cSopenharmony_ci      }
1473370b324cSopenharmony_ci
1474370b324cSopenharmony_ci      bool isDir = false;
1475370b324cSopenharmony_ci      Archive_IsItem_Dir(archive, i, isDir);
1476370b324cSopenharmony_ci      if (isDir)
1477370b324cSopenharmony_ci        pi.NumSubDirs++;
1478370b324cSopenharmony_ci      else
1479370b324cSopenharmony_ci        pi.NumSubFiles++;
1480370b324cSopenharmony_ci    }
1481370b324cSopenharmony_ci    if (pi.NumSubDirs != 0)
1482370b324cSopenharmony_ci      pi.NumSubDirs_Defined = true;
1483370b324cSopenharmony_ci    pi.NumSubFiles_Defined = true;
1484370b324cSopenharmony_ci  }
1485370b324cSopenharmony_ci
1486370b324cSopenharmony_ci  return S_OK;
1487370b324cSopenharmony_ci}
1488370b324cSopenharmony_ci
1489370b324cSopenharmony_ci#endif
1490370b324cSopenharmony_ci
1491370b324cSopenharmony_ciHRESULT CArc::CheckZerosTail(const COpenOptions &op, UInt64 offset)
1492370b324cSopenharmony_ci{
1493370b324cSopenharmony_ci  if (!op.stream)
1494370b324cSopenharmony_ci    return S_OK;
1495370b324cSopenharmony_ci  RINOK(InStream_SeekSet(op.stream, offset))
1496370b324cSopenharmony_ci  const UInt32 kBufSize = 1 << 11;
1497370b324cSopenharmony_ci  Byte buf[kBufSize];
1498370b324cSopenharmony_ci
1499370b324cSopenharmony_ci  for (;;)
1500370b324cSopenharmony_ci  {
1501370b324cSopenharmony_ci    UInt32 processed = 0;
1502370b324cSopenharmony_ci    RINOK(op.stream->Read(buf, kBufSize, &processed))
1503370b324cSopenharmony_ci    if (processed == 0)
1504370b324cSopenharmony_ci    {
1505370b324cSopenharmony_ci      // ErrorInfo.NonZerosTail = false;
1506370b324cSopenharmony_ci      ErrorInfo.IgnoreTail = true;
1507370b324cSopenharmony_ci      return S_OK;
1508370b324cSopenharmony_ci    }
1509370b324cSopenharmony_ci    for (size_t i = 0; i < processed; i++)
1510370b324cSopenharmony_ci    {
1511370b324cSopenharmony_ci      if (buf[i] != 0)
1512370b324cSopenharmony_ci      {
1513370b324cSopenharmony_ci        // ErrorInfo.IgnoreTail = false;
1514370b324cSopenharmony_ci        // ErrorInfo.NonZerosTail = true;
1515370b324cSopenharmony_ci        return S_OK;
1516370b324cSopenharmony_ci      }
1517370b324cSopenharmony_ci    }
1518370b324cSopenharmony_ci  }
1519370b324cSopenharmony_ci}
1520370b324cSopenharmony_ci
1521370b324cSopenharmony_ci
1522370b324cSopenharmony_ci
1523370b324cSopenharmony_ci#ifndef Z7_SFX
1524370b324cSopenharmony_ci
1525370b324cSopenharmony_ciZ7_CLASS_IMP_COM_2(
1526370b324cSopenharmony_ci  CExtractCallback_To_OpenCallback
1527370b324cSopenharmony_ci  , IArchiveExtractCallback
1528370b324cSopenharmony_ci  , ICompressProgressInfo
1529370b324cSopenharmony_ci)
1530370b324cSopenharmony_ci  Z7_IFACE_COM7_IMP(IProgress)
1531370b324cSopenharmony_cipublic:
1532370b324cSopenharmony_ci  CMyComPtr<IArchiveOpenCallback> Callback;
1533370b324cSopenharmony_ci  UInt64 Files;
1534370b324cSopenharmony_ci  UInt64 Offset;
1535370b324cSopenharmony_ci
1536370b324cSopenharmony_ci  void Init(IArchiveOpenCallback *callback)
1537370b324cSopenharmony_ci  {
1538370b324cSopenharmony_ci    Callback = callback;
1539370b324cSopenharmony_ci    Files = 0;
1540370b324cSopenharmony_ci    Offset = 0;
1541370b324cSopenharmony_ci  }
1542370b324cSopenharmony_ci};
1543370b324cSopenharmony_ci
1544370b324cSopenharmony_ciZ7_COM7F_IMF(CExtractCallback_To_OpenCallback::SetTotal(UInt64 /* size */))
1545370b324cSopenharmony_ci{
1546370b324cSopenharmony_ci  return S_OK;
1547370b324cSopenharmony_ci}
1548370b324cSopenharmony_ci
1549370b324cSopenharmony_ciZ7_COM7F_IMF(CExtractCallback_To_OpenCallback::SetCompleted(const UInt64 * /* completeValue */))
1550370b324cSopenharmony_ci{
1551370b324cSopenharmony_ci  return S_OK;
1552370b324cSopenharmony_ci}
1553370b324cSopenharmony_ci
1554370b324cSopenharmony_ciZ7_COM7F_IMF(CExtractCallback_To_OpenCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */))
1555370b324cSopenharmony_ci{
1556370b324cSopenharmony_ci  if (Callback)
1557370b324cSopenharmony_ci  {
1558370b324cSopenharmony_ci    UInt64 value = Offset;
1559370b324cSopenharmony_ci    if (inSize)
1560370b324cSopenharmony_ci      value += *inSize;
1561370b324cSopenharmony_ci    return Callback->SetCompleted(&Files, &value);
1562370b324cSopenharmony_ci  }
1563370b324cSopenharmony_ci  return S_OK;
1564370b324cSopenharmony_ci}
1565370b324cSopenharmony_ci
1566370b324cSopenharmony_ciZ7_COM7F_IMF(CExtractCallback_To_OpenCallback::GetStream(UInt32 /* index */, ISequentialOutStream **outStream, Int32 /* askExtractMode */))
1567370b324cSopenharmony_ci{
1568370b324cSopenharmony_ci  *outStream = NULL;
1569370b324cSopenharmony_ci  return S_OK;
1570370b324cSopenharmony_ci}
1571370b324cSopenharmony_ci
1572370b324cSopenharmony_ciZ7_COM7F_IMF(CExtractCallback_To_OpenCallback::PrepareOperation(Int32 /* askExtractMode */))
1573370b324cSopenharmony_ci{
1574370b324cSopenharmony_ci  return S_OK;
1575370b324cSopenharmony_ci}
1576370b324cSopenharmony_ci
1577370b324cSopenharmony_ciZ7_COM7F_IMF(CExtractCallback_To_OpenCallback::SetOperationResult(Int32 /* operationResult */))
1578370b324cSopenharmony_ci{
1579370b324cSopenharmony_ci  return S_OK;
1580370b324cSopenharmony_ci}
1581370b324cSopenharmony_ci
1582370b324cSopenharmony_ci
1583370b324cSopenharmony_cistatic HRESULT OpenArchiveSpec(IInArchive *archive, bool needPhySize,
1584370b324cSopenharmony_ci    IInStream *stream, const UInt64 *maxCheckStartPosition,
1585370b324cSopenharmony_ci    IArchiveOpenCallback *openCallback,
1586370b324cSopenharmony_ci    IArchiveExtractCallback *extractCallback)
1587370b324cSopenharmony_ci{
1588370b324cSopenharmony_ci  /*
1589370b324cSopenharmony_ci  if (needPhySize)
1590370b324cSopenharmony_ci  {
1591370b324cSopenharmony_ci    Z7_DECL_CMyComPtr_QI_FROM(
1592370b324cSopenharmony_ci        IArchiveOpen2,
1593370b324cSopenharmony_ci        open2, archive)
1594370b324cSopenharmony_ci    if (open2)
1595370b324cSopenharmony_ci      return open2->ArcOpen2(stream, kOpenFlags_RealPhySize, openCallback);
1596370b324cSopenharmony_ci  }
1597370b324cSopenharmony_ci  */
1598370b324cSopenharmony_ci  RINOK(archive->Open(stream, maxCheckStartPosition, openCallback))
1599370b324cSopenharmony_ci  if (needPhySize)
1600370b324cSopenharmony_ci  {
1601370b324cSopenharmony_ci    bool phySize_Defined = false;
1602370b324cSopenharmony_ci    UInt64 phySize = 0;
1603370b324cSopenharmony_ci    RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, phySize, phySize_Defined))
1604370b324cSopenharmony_ci    if (phySize_Defined)
1605370b324cSopenharmony_ci      return S_OK;
1606370b324cSopenharmony_ci
1607370b324cSopenharmony_ci    bool phySizeCantBeDetected = false;
1608370b324cSopenharmony_ci    RINOK(Archive_GetArcProp_Bool(archive, kpidPhySizeCantBeDetected, phySizeCantBeDetected))
1609370b324cSopenharmony_ci
1610370b324cSopenharmony_ci    if (!phySizeCantBeDetected)
1611370b324cSopenharmony_ci    {
1612370b324cSopenharmony_ci      PRF(printf("\n-- !phySize_Defined after Open, call archive->Extract()"));
1613370b324cSopenharmony_ci      // It's for bzip2/gz and some xz archives, where Open operation doesn't know phySize.
1614370b324cSopenharmony_ci      // But the Handler will know phySize after full archive testing.
1615370b324cSopenharmony_ci      RINOK(archive->Extract(NULL, (UInt32)(Int32)-1, BoolToInt(true), extractCallback))
1616370b324cSopenharmony_ci      PRF(printf("\n-- OK"));
1617370b324cSopenharmony_ci    }
1618370b324cSopenharmony_ci  }
1619370b324cSopenharmony_ci  return S_OK;
1620370b324cSopenharmony_ci}
1621370b324cSopenharmony_ci
1622370b324cSopenharmony_ci
1623370b324cSopenharmony_ci
1624370b324cSopenharmony_cistatic int FindFormatForArchiveType(CCodecs *codecs, CIntVector orderIndices, const char *name)
1625370b324cSopenharmony_ci{
1626370b324cSopenharmony_ci  FOR_VECTOR (i, orderIndices)
1627370b324cSopenharmony_ci  {
1628370b324cSopenharmony_ci    int oi = orderIndices[i];
1629370b324cSopenharmony_ci    if (oi >= 0)
1630370b324cSopenharmony_ci      if (StringsAreEqualNoCase_Ascii(codecs->Formats[(unsigned)oi].Name, name))
1631370b324cSopenharmony_ci        return (int)i;
1632370b324cSopenharmony_ci  }
1633370b324cSopenharmony_ci  return -1;
1634370b324cSopenharmony_ci}
1635370b324cSopenharmony_ci
1636370b324cSopenharmony_ci#endif
1637370b324cSopenharmony_ci
1638370b324cSopenharmony_ciHRESULT CArc::OpenStream2(const COpenOptions &op)
1639370b324cSopenharmony_ci{
1640370b324cSopenharmony_ci  // fprintf(stdout, "\nOpen: %S", Path); fflush(stdout);
1641370b324cSopenharmony_ci
1642370b324cSopenharmony_ci  Archive.Release();
1643370b324cSopenharmony_ci  GetRawProps.Release();
1644370b324cSopenharmony_ci  GetRootProps.Release();
1645370b324cSopenharmony_ci
1646370b324cSopenharmony_ci  ErrorInfo.ClearErrors();
1647370b324cSopenharmony_ci  ErrorInfo.ErrorFormatIndex = -1;
1648370b324cSopenharmony_ci
1649370b324cSopenharmony_ci  IsParseArc = false;
1650370b324cSopenharmony_ci  ArcStreamOffset = 0;
1651370b324cSopenharmony_ci
1652370b324cSopenharmony_ci  // OutputDebugStringA("1");
1653370b324cSopenharmony_ci  // OutputDebugStringW(Path);
1654370b324cSopenharmony_ci
1655370b324cSopenharmony_ci  const UString fileName = ExtractFileNameFromPath(Path);
1656370b324cSopenharmony_ci  UString extension;
1657370b324cSopenharmony_ci  {
1658370b324cSopenharmony_ci    const int dotPos = fileName.ReverseFind_Dot();
1659370b324cSopenharmony_ci    if (dotPos >= 0)
1660370b324cSopenharmony_ci      extension = fileName.Ptr((unsigned)(dotPos + 1));
1661370b324cSopenharmony_ci  }
1662370b324cSopenharmony_ci
1663370b324cSopenharmony_ci  CIntVector orderIndices;
1664370b324cSopenharmony_ci
1665370b324cSopenharmony_ci  bool searchMarkerInHandler = false;
1666370b324cSopenharmony_ci  #ifdef Z7_SFX
1667370b324cSopenharmony_ci    searchMarkerInHandler = true;
1668370b324cSopenharmony_ci  #endif
1669370b324cSopenharmony_ci
1670370b324cSopenharmony_ci  CBoolArr isMainFormatArr(op.codecs->Formats.Size());
1671370b324cSopenharmony_ci  {
1672370b324cSopenharmony_ci    FOR_VECTOR(i, op.codecs->Formats)
1673370b324cSopenharmony_ci      isMainFormatArr[i] = false;
1674370b324cSopenharmony_ci  }
1675370b324cSopenharmony_ci
1676370b324cSopenharmony_ci  const UInt64 maxStartOffset =
1677370b324cSopenharmony_ci      op.openType.MaxStartOffset_Defined ?
1678370b324cSopenharmony_ci      op.openType.MaxStartOffset :
1679370b324cSopenharmony_ci      kMaxCheckStartPosition;
1680370b324cSopenharmony_ci
1681370b324cSopenharmony_ci  #ifndef Z7_SFX
1682370b324cSopenharmony_ci  bool isUnknownExt = false;
1683370b324cSopenharmony_ci  #endif
1684370b324cSopenharmony_ci
1685370b324cSopenharmony_ci  #ifndef Z7_SFX
1686370b324cSopenharmony_ci  bool isForced = false;
1687370b324cSopenharmony_ci  #endif
1688370b324cSopenharmony_ci
1689370b324cSopenharmony_ci  unsigned numMainTypes = 0;
1690370b324cSopenharmony_ci  const int formatIndex = op.openType.FormatIndex;
1691370b324cSopenharmony_ci
1692370b324cSopenharmony_ci  if (formatIndex >= 0)
1693370b324cSopenharmony_ci  {
1694370b324cSopenharmony_ci    #ifndef Z7_SFX
1695370b324cSopenharmony_ci    isForced = true;
1696370b324cSopenharmony_ci    #endif
1697370b324cSopenharmony_ci    orderIndices.Add(formatIndex);
1698370b324cSopenharmony_ci    numMainTypes = 1;
1699370b324cSopenharmony_ci    isMainFormatArr[(unsigned)formatIndex] = true;
1700370b324cSopenharmony_ci
1701370b324cSopenharmony_ci    searchMarkerInHandler = true;
1702370b324cSopenharmony_ci  }
1703370b324cSopenharmony_ci  else
1704370b324cSopenharmony_ci  {
1705370b324cSopenharmony_ci    unsigned numFinded = 0;
1706370b324cSopenharmony_ci    #ifndef Z7_SFX
1707370b324cSopenharmony_ci    bool isPrearcExt = false;
1708370b324cSopenharmony_ci    #endif
1709370b324cSopenharmony_ci
1710370b324cSopenharmony_ci    {
1711370b324cSopenharmony_ci      #ifndef Z7_SFX
1712370b324cSopenharmony_ci
1713370b324cSopenharmony_ci      bool isZip = false;
1714370b324cSopenharmony_ci      bool isRar = false;
1715370b324cSopenharmony_ci
1716370b324cSopenharmony_ci      const wchar_t c = extension[0];
1717370b324cSopenharmony_ci      if (c == 'z' || c == 'Z' || c == 'r' || c == 'R')
1718370b324cSopenharmony_ci      {
1719370b324cSopenharmony_ci        bool isNumber = false;
1720370b324cSopenharmony_ci        for (unsigned k = 1;; k++)
1721370b324cSopenharmony_ci        {
1722370b324cSopenharmony_ci          const wchar_t d = extension[k];
1723370b324cSopenharmony_ci          if (d == 0)
1724370b324cSopenharmony_ci            break;
1725370b324cSopenharmony_ci          if (d < '0' || d > '9')
1726370b324cSopenharmony_ci          {
1727370b324cSopenharmony_ci            isNumber = false;
1728370b324cSopenharmony_ci            break;
1729370b324cSopenharmony_ci          }
1730370b324cSopenharmony_ci          isNumber = true;
1731370b324cSopenharmony_ci        }
1732370b324cSopenharmony_ci        if (isNumber)
1733370b324cSopenharmony_ci        {
1734370b324cSopenharmony_ci          if (c == 'z' || c == 'Z')
1735370b324cSopenharmony_ci            isZip = true;
1736370b324cSopenharmony_ci          else
1737370b324cSopenharmony_ci            isRar = true;
1738370b324cSopenharmony_ci        }
1739370b324cSopenharmony_ci      }
1740370b324cSopenharmony_ci
1741370b324cSopenharmony_ci      #endif
1742370b324cSopenharmony_ci
1743370b324cSopenharmony_ci      FOR_VECTOR (i, op.codecs->Formats)
1744370b324cSopenharmony_ci      {
1745370b324cSopenharmony_ci        const CArcInfoEx &ai = op.codecs->Formats[i];
1746370b324cSopenharmony_ci
1747370b324cSopenharmony_ci        if (IgnoreSplit || !op.openType.CanReturnArc)
1748370b324cSopenharmony_ci          if (ai.Is_Split())
1749370b324cSopenharmony_ci            continue;
1750370b324cSopenharmony_ci        if (op.excludedFormats->FindInSorted((int)i) >= 0)
1751370b324cSopenharmony_ci          continue;
1752370b324cSopenharmony_ci
1753370b324cSopenharmony_ci        #ifndef Z7_SFX
1754370b324cSopenharmony_ci        if (IsPreArcFormat(ai))
1755370b324cSopenharmony_ci          isPrearcExt = true;
1756370b324cSopenharmony_ci        #endif
1757370b324cSopenharmony_ci
1758370b324cSopenharmony_ci        if (ai.FindExtension(extension) >= 0
1759370b324cSopenharmony_ci            #ifndef Z7_SFX
1760370b324cSopenharmony_ci            || (isZip && ai.Is_Zip())
1761370b324cSopenharmony_ci            || (isRar && ai.Is_Rar())
1762370b324cSopenharmony_ci            #endif
1763370b324cSopenharmony_ci            )
1764370b324cSopenharmony_ci        {
1765370b324cSopenharmony_ci          // PrintNumber("orderIndices.Insert", i);
1766370b324cSopenharmony_ci          orderIndices.Insert(numFinded++, (int)i);
1767370b324cSopenharmony_ci          isMainFormatArr[i] = true;
1768370b324cSopenharmony_ci        }
1769370b324cSopenharmony_ci        else
1770370b324cSopenharmony_ci          orderIndices.Add((int)i);
1771370b324cSopenharmony_ci      }
1772370b324cSopenharmony_ci    }
1773370b324cSopenharmony_ci
1774370b324cSopenharmony_ci    if (!op.stream)
1775370b324cSopenharmony_ci    {
1776370b324cSopenharmony_ci      if (numFinded != 1)
1777370b324cSopenharmony_ci        return E_NOTIMPL;
1778370b324cSopenharmony_ci      orderIndices.DeleteFrom(1);
1779370b324cSopenharmony_ci    }
1780370b324cSopenharmony_ci    // PrintNumber("numFinded", numFinded );
1781370b324cSopenharmony_ci
1782370b324cSopenharmony_ci    /*
1783370b324cSopenharmony_ci    if (op.openOnlySpecifiedByExtension)
1784370b324cSopenharmony_ci    {
1785370b324cSopenharmony_ci      if (numFinded != 0 && !IsExeExt(extension))
1786370b324cSopenharmony_ci        orderIndices.DeleteFrom(numFinded);
1787370b324cSopenharmony_ci    }
1788370b324cSopenharmony_ci    */
1789370b324cSopenharmony_ci
1790370b324cSopenharmony_ci    #ifndef Z7_SFX
1791370b324cSopenharmony_ci
1792370b324cSopenharmony_ci      if (op.stream && orderIndices.Size() >= 2)
1793370b324cSopenharmony_ci      {
1794370b324cSopenharmony_ci        RINOK(InStream_SeekToBegin(op.stream))
1795370b324cSopenharmony_ci        CByteBuffer byteBuffer;
1796370b324cSopenharmony_ci        CIntVector orderIndices2;
1797370b324cSopenharmony_ci        if (numFinded == 0 || IsExeExt(extension))
1798370b324cSopenharmony_ci        {
1799370b324cSopenharmony_ci          // signature search was here
1800370b324cSopenharmony_ci        }
1801370b324cSopenharmony_ci        else if (extension.IsEqualTo("000") || extension.IsEqualTo("001"))
1802370b324cSopenharmony_ci        {
1803370b324cSopenharmony_ci          const int i = FindFormatForArchiveType(op.codecs, orderIndices, "rar");
1804370b324cSopenharmony_ci          if (i >= 0)
1805370b324cSopenharmony_ci          {
1806370b324cSopenharmony_ci            const size_t kBufSize = (1 << 10);
1807370b324cSopenharmony_ci            byteBuffer.Alloc(kBufSize);
1808370b324cSopenharmony_ci            size_t processedSize = kBufSize;
1809370b324cSopenharmony_ci            RINOK(ReadStream(op.stream, byteBuffer, &processedSize))
1810370b324cSopenharmony_ci            if (processedSize >= 16)
1811370b324cSopenharmony_ci            {
1812370b324cSopenharmony_ci              const Byte *buf = byteBuffer;
1813370b324cSopenharmony_ci              const Byte kRarHeader[] = { 0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 };
1814370b324cSopenharmony_ci              if (TestSignature(buf, kRarHeader, 7) && buf[9] == 0x73 && (buf[10] & 1) != 0)
1815370b324cSopenharmony_ci              {
1816370b324cSopenharmony_ci                orderIndices2.Add(orderIndices[(unsigned)i]);
1817370b324cSopenharmony_ci                orderIndices[(unsigned)i] = -1;
1818370b324cSopenharmony_ci                if (i >= (int)numFinded)
1819370b324cSopenharmony_ci                  numFinded++;
1820370b324cSopenharmony_ci              }
1821370b324cSopenharmony_ci            }
1822370b324cSopenharmony_ci          }
1823370b324cSopenharmony_ci        }
1824370b324cSopenharmony_ci        else
1825370b324cSopenharmony_ci        {
1826370b324cSopenharmony_ci          const size_t kBufSize = (1 << 10);
1827370b324cSopenharmony_ci          byteBuffer.Alloc(kBufSize);
1828370b324cSopenharmony_ci          size_t processedSize = kBufSize;
1829370b324cSopenharmony_ci          RINOK(ReadStream(op.stream, byteBuffer, &processedSize))
1830370b324cSopenharmony_ci          if (processedSize == 0)
1831370b324cSopenharmony_ci            return S_FALSE;
1832370b324cSopenharmony_ci
1833370b324cSopenharmony_ci          /*
1834370b324cSopenharmony_ci          check type order:
1835370b324cSopenharmony_ci            0) matched_extension && Backward
1836370b324cSopenharmony_ci            1) matched_extension && (no_signuature || SignatureOffset != 0)
1837370b324cSopenharmony_ci            2) matched_extension && (matched_signature)
1838370b324cSopenharmony_ci            // 3) no signuature
1839370b324cSopenharmony_ci            // 4) matched signuature
1840370b324cSopenharmony_ci          */
1841370b324cSopenharmony_ci          // we move index from orderIndices to orderIndices2 for priority handlers.
1842370b324cSopenharmony_ci
1843370b324cSopenharmony_ci          for (unsigned i = 0; i < numFinded; i++)
1844370b324cSopenharmony_ci          {
1845370b324cSopenharmony_ci            const int index = orderIndices[i];
1846370b324cSopenharmony_ci            if (index < 0)
1847370b324cSopenharmony_ci              continue;
1848370b324cSopenharmony_ci            const CArcInfoEx &ai = op.codecs->Formats[(unsigned)index];
1849370b324cSopenharmony_ci            if (ai.Flags_BackwardOpen())
1850370b324cSopenharmony_ci            {
1851370b324cSopenharmony_ci              // backward doesn't need start signatures
1852370b324cSopenharmony_ci              orderIndices2.Add(index);
1853370b324cSopenharmony_ci              orderIndices[i] = -1;
1854370b324cSopenharmony_ci            }
1855370b324cSopenharmony_ci          }
1856370b324cSopenharmony_ci
1857370b324cSopenharmony_ci          MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, NULL, 0);
1858370b324cSopenharmony_ci          MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, byteBuffer, processedSize);
1859370b324cSopenharmony_ci          // MakeCheckOrder(op.codecs, orderIndices, orderIndices.Size(), orderIndices2, NULL, 0);
1860370b324cSopenharmony_ci          // MakeCheckOrder(op.codecs, orderIndices, orderIndices.Size(), orderIndices2, byteBuffer, processedSize);
1861370b324cSopenharmony_ci        }
1862370b324cSopenharmony_ci
1863370b324cSopenharmony_ci        FOR_VECTOR (i, orderIndices)
1864370b324cSopenharmony_ci        {
1865370b324cSopenharmony_ci          const int val = orderIndices[i];
1866370b324cSopenharmony_ci          if (val != -1)
1867370b324cSopenharmony_ci            orderIndices2.Add(val);
1868370b324cSopenharmony_ci        }
1869370b324cSopenharmony_ci        orderIndices = orderIndices2;
1870370b324cSopenharmony_ci      }
1871370b324cSopenharmony_ci
1872370b324cSopenharmony_ci      if (orderIndices.Size() >= 2)
1873370b324cSopenharmony_ci      {
1874370b324cSopenharmony_ci        const int iIso = FindFormatForArchiveType(op.codecs, orderIndices, "iso");
1875370b324cSopenharmony_ci        const int iUdf = FindFormatForArchiveType(op.codecs, orderIndices, "udf");
1876370b324cSopenharmony_ci        if (iUdf > iIso && iIso >= 0)
1877370b324cSopenharmony_ci        {
1878370b324cSopenharmony_ci          const int isoIndex = orderIndices[(unsigned)iIso];
1879370b324cSopenharmony_ci          const int udfIndex = orderIndices[(unsigned)iUdf];
1880370b324cSopenharmony_ci          orderIndices[(unsigned)iUdf] = isoIndex;
1881370b324cSopenharmony_ci          orderIndices[(unsigned)iIso] = udfIndex;
1882370b324cSopenharmony_ci        }
1883370b324cSopenharmony_ci      }
1884370b324cSopenharmony_ci
1885370b324cSopenharmony_ci      numMainTypes = numFinded;
1886370b324cSopenharmony_ci      isUnknownExt = (numMainTypes == 0) || isPrearcExt;
1887370b324cSopenharmony_ci
1888370b324cSopenharmony_ci    #else // Z7_SFX
1889370b324cSopenharmony_ci
1890370b324cSopenharmony_ci      numMainTypes = orderIndices.Size();
1891370b324cSopenharmony_ci
1892370b324cSopenharmony_ci      // we need correct numMainTypes for mutlivolume SFX (if some volume is missing)
1893370b324cSopenharmony_ci      if (numFinded != 0)
1894370b324cSopenharmony_ci        numMainTypes = numFinded;
1895370b324cSopenharmony_ci
1896370b324cSopenharmony_ci    #endif
1897370b324cSopenharmony_ci  }
1898370b324cSopenharmony_ci
1899370b324cSopenharmony_ci  UInt64 fileSize = 0;
1900370b324cSopenharmony_ci  if (op.stream)
1901370b324cSopenharmony_ci  {
1902370b324cSopenharmony_ci    RINOK(InStream_GetSize_SeekToBegin(op.stream, fileSize))
1903370b324cSopenharmony_ci  }
1904370b324cSopenharmony_ci  FileSize = fileSize;
1905370b324cSopenharmony_ci
1906370b324cSopenharmony_ci
1907370b324cSopenharmony_ci  #ifndef Z7_SFX
1908370b324cSopenharmony_ci
1909370b324cSopenharmony_ci  CBoolArr skipFrontalFormat(op.codecs->Formats.Size());
1910370b324cSopenharmony_ci  {
1911370b324cSopenharmony_ci    FOR_VECTOR(i, op.codecs->Formats)
1912370b324cSopenharmony_ci      skipFrontalFormat[i] = false;
1913370b324cSopenharmony_ci  }
1914370b324cSopenharmony_ci
1915370b324cSopenharmony_ci  #endif
1916370b324cSopenharmony_ci
1917370b324cSopenharmony_ci  const COpenType &mode = op.openType;
1918370b324cSopenharmony_ci
1919370b324cSopenharmony_ci
1920370b324cSopenharmony_ci
1921370b324cSopenharmony_ci
1922370b324cSopenharmony_ci
1923370b324cSopenharmony_ci  if (mode.CanReturnArc)
1924370b324cSopenharmony_ci  {
1925370b324cSopenharmony_ci    // ---------- OPEN main type by extenssion ----------
1926370b324cSopenharmony_ci
1927370b324cSopenharmony_ci    unsigned numCheckTypes = orderIndices.Size();
1928370b324cSopenharmony_ci    if (formatIndex >= 0)
1929370b324cSopenharmony_ci      numCheckTypes = numMainTypes;
1930370b324cSopenharmony_ci
1931370b324cSopenharmony_ci    for (unsigned i = 0; i < numCheckTypes; i++)
1932370b324cSopenharmony_ci    {
1933370b324cSopenharmony_ci      FormatIndex = orderIndices[i];
1934370b324cSopenharmony_ci
1935370b324cSopenharmony_ci      // orderIndices[] item cannot be negative here
1936370b324cSopenharmony_ci
1937370b324cSopenharmony_ci      bool exactOnly = false;
1938370b324cSopenharmony_ci
1939370b324cSopenharmony_ci      #ifndef Z7_SFX
1940370b324cSopenharmony_ci
1941370b324cSopenharmony_ci      const CArcInfoEx &ai = op.codecs->Formats[(unsigned)FormatIndex];
1942370b324cSopenharmony_ci      // OutputDebugStringW(ai.Name);
1943370b324cSopenharmony_ci      if (i >= numMainTypes)
1944370b324cSopenharmony_ci      {
1945370b324cSopenharmony_ci        // here we allow mismatched extension only for backward handlers
1946370b324cSopenharmony_ci        if (!ai.Flags_BackwardOpen()
1947370b324cSopenharmony_ci            // && !ai.Flags_PureStartOpen()
1948370b324cSopenharmony_ci            )
1949370b324cSopenharmony_ci          continue;
1950370b324cSopenharmony_ci        exactOnly = true;
1951370b324cSopenharmony_ci      }
1952370b324cSopenharmony_ci
1953370b324cSopenharmony_ci      #endif
1954370b324cSopenharmony_ci
1955370b324cSopenharmony_ci      // Some handlers do not set total bytes. So we set it here
1956370b324cSopenharmony_ci      if (op.callback)
1957370b324cSopenharmony_ci        RINOK(op.callback->SetTotal(NULL, &fileSize))
1958370b324cSopenharmony_ci
1959370b324cSopenharmony_ci      if (op.stream)
1960370b324cSopenharmony_ci      {
1961370b324cSopenharmony_ci        RINOK(InStream_SeekToBegin(op.stream))
1962370b324cSopenharmony_ci      }
1963370b324cSopenharmony_ci
1964370b324cSopenharmony_ci      CMyComPtr<IInArchive> archive;
1965370b324cSopenharmony_ci
1966370b324cSopenharmony_ci      RINOK(PrepareToOpen(op, (unsigned)FormatIndex, archive))
1967370b324cSopenharmony_ci      if (!archive)
1968370b324cSopenharmony_ci        continue;
1969370b324cSopenharmony_ci
1970370b324cSopenharmony_ci      HRESULT result;
1971370b324cSopenharmony_ci      if (op.stream)
1972370b324cSopenharmony_ci      {
1973370b324cSopenharmony_ci        UInt64 searchLimit = (!exactOnly && searchMarkerInHandler) ? maxStartOffset: 0;
1974370b324cSopenharmony_ci        result = archive->Open(op.stream, &searchLimit, op.callback);
1975370b324cSopenharmony_ci      }
1976370b324cSopenharmony_ci      else
1977370b324cSopenharmony_ci      {
1978370b324cSopenharmony_ci        CMyComPtr<IArchiveOpenSeq> openSeq;
1979370b324cSopenharmony_ci        archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq);
1980370b324cSopenharmony_ci        if (!openSeq)
1981370b324cSopenharmony_ci          return E_NOTIMPL;
1982370b324cSopenharmony_ci        result = openSeq->OpenSeq(op.seqStream);
1983370b324cSopenharmony_ci      }
1984370b324cSopenharmony_ci
1985370b324cSopenharmony_ci      RINOK(ReadBasicProps(archive, 0, result))
1986370b324cSopenharmony_ci
1987370b324cSopenharmony_ci      if (result == S_FALSE)
1988370b324cSopenharmony_ci      {
1989370b324cSopenharmony_ci        bool isArc = ErrorInfo.IsArc_After_NonOpen();
1990370b324cSopenharmony_ci
1991370b324cSopenharmony_ci        #ifndef Z7_SFX
1992370b324cSopenharmony_ci        // if it's archive, we allow another open attempt for parser
1993370b324cSopenharmony_ci        if (!mode.CanReturnParser || !isArc)
1994370b324cSopenharmony_ci          skipFrontalFormat[(unsigned)FormatIndex] = true;
1995370b324cSopenharmony_ci        #endif
1996370b324cSopenharmony_ci
1997370b324cSopenharmony_ci        if (exactOnly)
1998370b324cSopenharmony_ci          continue;
1999370b324cSopenharmony_ci
2000370b324cSopenharmony_ci        if (i == 0 && numMainTypes == 1)
2001370b324cSopenharmony_ci        {
2002370b324cSopenharmony_ci          // we set NonOpenErrorInfo, only if there is only one main format (defined by extension).
2003370b324cSopenharmony_ci          ErrorInfo.ErrorFormatIndex = FormatIndex;
2004370b324cSopenharmony_ci          NonOpen_ErrorInfo = ErrorInfo;
2005370b324cSopenharmony_ci
2006370b324cSopenharmony_ci          if (!mode.CanReturnParser && isArc)
2007370b324cSopenharmony_ci          {
2008370b324cSopenharmony_ci            // if (formatIndex < 0 && !searchMarkerInHandler)
2009370b324cSopenharmony_ci            {
2010370b324cSopenharmony_ci              // if bad archive was detected, we don't need additional open attempts
2011370b324cSopenharmony_ci              #ifndef Z7_SFX
2012370b324cSopenharmony_ci              if (!IsPreArcFormat(ai) /* || !mode.SkipSfxStub */)
2013370b324cSopenharmony_ci              #endif
2014370b324cSopenharmony_ci                return S_FALSE;
2015370b324cSopenharmony_ci            }
2016370b324cSopenharmony_ci          }
2017370b324cSopenharmony_ci        }
2018370b324cSopenharmony_ci
2019370b324cSopenharmony_ci        /*
2020370b324cSopenharmony_ci        #ifndef Z7_SFX
2021370b324cSopenharmony_ci        if (IsExeExt(extension) || ai.Flags_PreArc())
2022370b324cSopenharmony_ci        {
2023370b324cSopenharmony_ci        // openOnlyFullArc = false;
2024370b324cSopenharmony_ci        // canReturnTailArc = true;
2025370b324cSopenharmony_ci        // limitSignatureSearch = true;
2026370b324cSopenharmony_ci        }
2027370b324cSopenharmony_ci        #endif
2028370b324cSopenharmony_ci        */
2029370b324cSopenharmony_ci
2030370b324cSopenharmony_ci        continue;
2031370b324cSopenharmony_ci      }
2032370b324cSopenharmony_ci
2033370b324cSopenharmony_ci      RINOK(result)
2034370b324cSopenharmony_ci
2035370b324cSopenharmony_ci      #ifndef Z7_SFX
2036370b324cSopenharmony_ci
2037370b324cSopenharmony_ci      bool isMainFormat = isMainFormatArr[(unsigned)FormatIndex];
2038370b324cSopenharmony_ci      const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);
2039370b324cSopenharmony_ci
2040370b324cSopenharmony_ci      bool thereIsTail = ErrorInfo.ThereIsTail;
2041370b324cSopenharmony_ci      if (thereIsTail && mode.ZerosTailIsAllowed)
2042370b324cSopenharmony_ci      {
2043370b324cSopenharmony_ci        RINOK(CheckZerosTail(op, (UInt64)(Offset + (Int64)PhySize)))
2044370b324cSopenharmony_ci        if (ErrorInfo.IgnoreTail)
2045370b324cSopenharmony_ci          thereIsTail = false;
2046370b324cSopenharmony_ci      }
2047370b324cSopenharmony_ci
2048370b324cSopenharmony_ci      if (Offset > 0)
2049370b324cSopenharmony_ci      {
2050370b324cSopenharmony_ci        if (exactOnly
2051370b324cSopenharmony_ci            || !searchMarkerInHandler
2052370b324cSopenharmony_ci            || !specFlags.CanReturn_NonStart()
2053370b324cSopenharmony_ci            || (mode.MaxStartOffset_Defined && (UInt64)Offset > mode.MaxStartOffset))
2054370b324cSopenharmony_ci          continue;
2055370b324cSopenharmony_ci      }
2056370b324cSopenharmony_ci      if (thereIsTail)
2057370b324cSopenharmony_ci      {
2058370b324cSopenharmony_ci        if (Offset > 0)
2059370b324cSopenharmony_ci        {
2060370b324cSopenharmony_ci          if (!specFlags.CanReturnMid)
2061370b324cSopenharmony_ci            continue;
2062370b324cSopenharmony_ci        }
2063370b324cSopenharmony_ci        else if (!specFlags.CanReturnFrontal)
2064370b324cSopenharmony_ci          continue;
2065370b324cSopenharmony_ci      }
2066370b324cSopenharmony_ci
2067370b324cSopenharmony_ci      if (Offset > 0 || thereIsTail)
2068370b324cSopenharmony_ci      {
2069370b324cSopenharmony_ci        if (formatIndex < 0)
2070370b324cSopenharmony_ci        {
2071370b324cSopenharmony_ci          if (IsPreArcFormat(ai))
2072370b324cSopenharmony_ci          {
2073370b324cSopenharmony_ci            // openOnlyFullArc = false;
2074370b324cSopenharmony_ci            // canReturnTailArc = true;
2075370b324cSopenharmony_ci            /*
2076370b324cSopenharmony_ci            if (mode.SkipSfxStub)
2077370b324cSopenharmony_ci            limitSignatureSearch = true;
2078370b324cSopenharmony_ci            */
2079370b324cSopenharmony_ci            // if (mode.SkipSfxStub)
2080370b324cSopenharmony_ci            {
2081370b324cSopenharmony_ci              // skipFrontalFormat[FormatIndex] = true;
2082370b324cSopenharmony_ci              continue;
2083370b324cSopenharmony_ci            }
2084370b324cSopenharmony_ci          }
2085370b324cSopenharmony_ci        }
2086370b324cSopenharmony_ci      }
2087370b324cSopenharmony_ci
2088370b324cSopenharmony_ci      #endif
2089370b324cSopenharmony_ci
2090370b324cSopenharmony_ci      Archive = archive;
2091370b324cSopenharmony_ci      return S_OK;
2092370b324cSopenharmony_ci    }
2093370b324cSopenharmony_ci  }
2094370b324cSopenharmony_ci
2095370b324cSopenharmony_ci
2096370b324cSopenharmony_ci
2097370b324cSopenharmony_ci  #ifndef Z7_SFX
2098370b324cSopenharmony_ci
2099370b324cSopenharmony_ci  if (!op.stream)
2100370b324cSopenharmony_ci    return S_FALSE;
2101370b324cSopenharmony_ci
2102370b324cSopenharmony_ci  if (formatIndex >= 0 && !mode.CanReturnParser)
2103370b324cSopenharmony_ci  {
2104370b324cSopenharmony_ci    if (mode.MaxStartOffset_Defined)
2105370b324cSopenharmony_ci    {
2106370b324cSopenharmony_ci      if (mode.MaxStartOffset == 0)
2107370b324cSopenharmony_ci        return S_FALSE;
2108370b324cSopenharmony_ci    }
2109370b324cSopenharmony_ci    else
2110370b324cSopenharmony_ci    {
2111370b324cSopenharmony_ci      const CArcInfoEx &ai = op.codecs->Formats[(unsigned)formatIndex];
2112370b324cSopenharmony_ci      if (ai.FindExtension(extension) >= 0)
2113370b324cSopenharmony_ci      {
2114370b324cSopenharmony_ci        if (ai.Flags_FindSignature() && searchMarkerInHandler)
2115370b324cSopenharmony_ci          return S_FALSE;
2116370b324cSopenharmony_ci      }
2117370b324cSopenharmony_ci    }
2118370b324cSopenharmony_ci  }
2119370b324cSopenharmony_ci
2120370b324cSopenharmony_ci  NArchive::NParser::CHandler *handlerSpec = new NArchive::NParser::CHandler;
2121370b324cSopenharmony_ci  CMyComPtr<IInArchive> handler = handlerSpec;
2122370b324cSopenharmony_ci
2123370b324cSopenharmony_ci  CExtractCallback_To_OpenCallback *extractCallback_To_OpenCallback_Spec = new CExtractCallback_To_OpenCallback;
2124370b324cSopenharmony_ci  CMyComPtr<IArchiveExtractCallback> extractCallback_To_OpenCallback = extractCallback_To_OpenCallback_Spec;
2125370b324cSopenharmony_ci  extractCallback_To_OpenCallback_Spec->Init(op.callback);
2126370b324cSopenharmony_ci
2127370b324cSopenharmony_ci  {
2128370b324cSopenharmony_ci    // ---------- Check all possible START archives ----------
2129370b324cSopenharmony_ci    // this code is better for full file archives than Parser's code.
2130370b324cSopenharmony_ci
2131370b324cSopenharmony_ci    CByteBuffer byteBuffer;
2132370b324cSopenharmony_ci    bool endOfFile = false;
2133370b324cSopenharmony_ci    size_t processedSize;
2134370b324cSopenharmony_ci    {
2135370b324cSopenharmony_ci      size_t bufSize = 1 << 20; // it must be larger than max signature offset or IsArcFunc offset ((1 << 19) + x for UDF)
2136370b324cSopenharmony_ci      if (bufSize > fileSize)
2137370b324cSopenharmony_ci      {
2138370b324cSopenharmony_ci        bufSize = (size_t)fileSize;
2139370b324cSopenharmony_ci        endOfFile = true;
2140370b324cSopenharmony_ci      }
2141370b324cSopenharmony_ci      byteBuffer.Alloc(bufSize);
2142370b324cSopenharmony_ci      RINOK(InStream_SeekToBegin(op.stream))
2143370b324cSopenharmony_ci      processedSize = bufSize;
2144370b324cSopenharmony_ci      RINOK(ReadStream(op.stream, byteBuffer, &processedSize))
2145370b324cSopenharmony_ci      if (processedSize == 0)
2146370b324cSopenharmony_ci        return S_FALSE;
2147370b324cSopenharmony_ci      if (processedSize < bufSize)
2148370b324cSopenharmony_ci        endOfFile = true;
2149370b324cSopenharmony_ci    }
2150370b324cSopenharmony_ci    CUIntVector sortedFormats;
2151370b324cSopenharmony_ci
2152370b324cSopenharmony_ci    unsigned i;
2153370b324cSopenharmony_ci
2154370b324cSopenharmony_ci    int splitIndex = -1;
2155370b324cSopenharmony_ci
2156370b324cSopenharmony_ci    for (i = 0; i < orderIndices.Size(); i++)
2157370b324cSopenharmony_ci    {
2158370b324cSopenharmony_ci      // orderIndices[] item cannot be negative here
2159370b324cSopenharmony_ci      unsigned form = (unsigned)orderIndices[i];
2160370b324cSopenharmony_ci      if (skipFrontalFormat[form])
2161370b324cSopenharmony_ci        continue;
2162370b324cSopenharmony_ci
2163370b324cSopenharmony_ci      const CArcInfoEx &ai = op.codecs->Formats[form];
2164370b324cSopenharmony_ci
2165370b324cSopenharmony_ci      if (ai.Is_Split())
2166370b324cSopenharmony_ci      {
2167370b324cSopenharmony_ci        splitIndex = (int)form;
2168370b324cSopenharmony_ci        continue;
2169370b324cSopenharmony_ci      }
2170370b324cSopenharmony_ci
2171370b324cSopenharmony_ci      if (ai.Flags_ByExtOnlyOpen())
2172370b324cSopenharmony_ci        continue;
2173370b324cSopenharmony_ci
2174370b324cSopenharmony_ci      if (ai.IsArcFunc)
2175370b324cSopenharmony_ci      {
2176370b324cSopenharmony_ci        UInt32 isArcRes = ai.IsArcFunc(byteBuffer, processedSize);
2177370b324cSopenharmony_ci        if (isArcRes == k_IsArc_Res_NO)
2178370b324cSopenharmony_ci          continue;
2179370b324cSopenharmony_ci        if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile)
2180370b324cSopenharmony_ci          continue;
2181370b324cSopenharmony_ci        // if (isArcRes == k_IsArc_Res_YES_LOW_PROB) continue;
2182370b324cSopenharmony_ci        sortedFormats.Insert(0, form);
2183370b324cSopenharmony_ci        continue;
2184370b324cSopenharmony_ci      }
2185370b324cSopenharmony_ci
2186370b324cSopenharmony_ci      const bool isNewStyleSignature = IsNewStyleSignature(ai);
2187370b324cSopenharmony_ci      bool needCheck = !isNewStyleSignature
2188370b324cSopenharmony_ci          || ai.Signatures.IsEmpty()
2189370b324cSopenharmony_ci          || ai.Flags_PureStartOpen()
2190370b324cSopenharmony_ci          || ai.Flags_StartOpen()
2191370b324cSopenharmony_ci          || ai.Flags_BackwardOpen();
2192370b324cSopenharmony_ci
2193370b324cSopenharmony_ci      if (isNewStyleSignature && !ai.Signatures.IsEmpty())
2194370b324cSopenharmony_ci      {
2195370b324cSopenharmony_ci        unsigned k;
2196370b324cSopenharmony_ci        for (k = 0; k < ai.Signatures.Size(); k++)
2197370b324cSopenharmony_ci        {
2198370b324cSopenharmony_ci          const CByteBuffer &sig = ai.Signatures[k];
2199370b324cSopenharmony_ci          if (processedSize < ai.SignatureOffset + sig.Size())
2200370b324cSopenharmony_ci          {
2201370b324cSopenharmony_ci            if (!endOfFile)
2202370b324cSopenharmony_ci              needCheck = true;
2203370b324cSopenharmony_ci          }
2204370b324cSopenharmony_ci          else if (TestSignature(sig, byteBuffer + ai.SignatureOffset, sig.Size()))
2205370b324cSopenharmony_ci            break;
2206370b324cSopenharmony_ci        }
2207370b324cSopenharmony_ci        if (k != ai.Signatures.Size())
2208370b324cSopenharmony_ci        {
2209370b324cSopenharmony_ci          sortedFormats.Insert(0, form);
2210370b324cSopenharmony_ci          continue;
2211370b324cSopenharmony_ci        }
2212370b324cSopenharmony_ci      }
2213370b324cSopenharmony_ci      if (needCheck)
2214370b324cSopenharmony_ci        sortedFormats.Add(form);
2215370b324cSopenharmony_ci    }
2216370b324cSopenharmony_ci
2217370b324cSopenharmony_ci    if (splitIndex >= 0)
2218370b324cSopenharmony_ci      sortedFormats.Insert(0, (unsigned)splitIndex);
2219370b324cSopenharmony_ci
2220370b324cSopenharmony_ci    for (i = 0; i < sortedFormats.Size(); i++)
2221370b324cSopenharmony_ci    {
2222370b324cSopenharmony_ci      FormatIndex = (int)sortedFormats[i];
2223370b324cSopenharmony_ci      const CArcInfoEx &ai = op.codecs->Formats[(unsigned)FormatIndex];
2224370b324cSopenharmony_ci
2225370b324cSopenharmony_ci      if (op.callback)
2226370b324cSopenharmony_ci        RINOK(op.callback->SetTotal(NULL, &fileSize))
2227370b324cSopenharmony_ci
2228370b324cSopenharmony_ci      RINOK(InStream_SeekToBegin(op.stream))
2229370b324cSopenharmony_ci
2230370b324cSopenharmony_ci      CMyComPtr<IInArchive> archive;
2231370b324cSopenharmony_ci      RINOK(PrepareToOpen(op, (unsigned)FormatIndex, archive))
2232370b324cSopenharmony_ci      if (!archive)
2233370b324cSopenharmony_ci        continue;
2234370b324cSopenharmony_ci
2235370b324cSopenharmony_ci      PRF(printf("\nSorted Open %S", (const wchar_t *)ai.Name));
2236370b324cSopenharmony_ci      HRESULT result;
2237370b324cSopenharmony_ci      {
2238370b324cSopenharmony_ci        UInt64 searchLimit = 0;
2239370b324cSopenharmony_ci        /*
2240370b324cSopenharmony_ci        if (mode.CanReturnArc)
2241370b324cSopenharmony_ci          result = archive->Open(op.stream, &searchLimit, op.callback);
2242370b324cSopenharmony_ci        else
2243370b324cSopenharmony_ci        */
2244370b324cSopenharmony_ci        // if (!CanReturnArc), it's ParserMode, and we need phy size
2245370b324cSopenharmony_ci        result = OpenArchiveSpec(archive,
2246370b324cSopenharmony_ci            !mode.CanReturnArc, // needPhySize
2247370b324cSopenharmony_ci            op.stream, &searchLimit, op.callback, extractCallback_To_OpenCallback);
2248370b324cSopenharmony_ci      }
2249370b324cSopenharmony_ci
2250370b324cSopenharmony_ci      if (result == S_FALSE)
2251370b324cSopenharmony_ci      {
2252370b324cSopenharmony_ci        skipFrontalFormat[(unsigned)FormatIndex] = true;
2253370b324cSopenharmony_ci        // FIXME: maybe we must use LenIsUnknown.
2254370b324cSopenharmony_ci        // printf("  OpenForSize Error");
2255370b324cSopenharmony_ci        continue;
2256370b324cSopenharmony_ci      }
2257370b324cSopenharmony_ci      RINOK(result)
2258370b324cSopenharmony_ci
2259370b324cSopenharmony_ci      RINOK(ReadBasicProps(archive, 0, result))
2260370b324cSopenharmony_ci
2261370b324cSopenharmony_ci      if (Offset > 0)
2262370b324cSopenharmony_ci      {
2263370b324cSopenharmony_ci        continue; // good handler doesn't return such Offset > 0
2264370b324cSopenharmony_ci        // but there are some cases like false prefixed PK00 archive, when
2265370b324cSopenharmony_ci        // we can support it?
2266370b324cSopenharmony_ci      }
2267370b324cSopenharmony_ci
2268370b324cSopenharmony_ci      NArchive::NParser::CParseItem pi;
2269370b324cSopenharmony_ci      pi.Offset = (UInt64)Offset;
2270370b324cSopenharmony_ci      pi.Size = AvailPhySize;
2271370b324cSopenharmony_ci
2272370b324cSopenharmony_ci      // bool needScan = false;
2273370b324cSopenharmony_ci
2274370b324cSopenharmony_ci      if (!PhySize_Defined)
2275370b324cSopenharmony_ci      {
2276370b324cSopenharmony_ci        // it's for Z format
2277370b324cSopenharmony_ci        pi.LenIsUnknown = true;
2278370b324cSopenharmony_ci        // needScan = true;
2279370b324cSopenharmony_ci        // phySize = arcRem;
2280370b324cSopenharmony_ci        // nextNeedCheckStartOpen = false;
2281370b324cSopenharmony_ci      }
2282370b324cSopenharmony_ci
2283370b324cSopenharmony_ci      /*
2284370b324cSopenharmony_ci      if (OkPhySize_Defined)
2285370b324cSopenharmony_ci        pi.OkSize = pi.OkPhySize;
2286370b324cSopenharmony_ci      else
2287370b324cSopenharmony_ci        pi.OkSize = pi.Size;
2288370b324cSopenharmony_ci      */
2289370b324cSopenharmony_ci
2290370b324cSopenharmony_ci      pi.NormalizeOffset();
2291370b324cSopenharmony_ci      // printf("  phySize = %8d", (unsigned)phySize);
2292370b324cSopenharmony_ci
2293370b324cSopenharmony_ci
2294370b324cSopenharmony_ci      if (mode.CanReturnArc)
2295370b324cSopenharmony_ci      {
2296370b324cSopenharmony_ci        const bool isMainFormat = isMainFormatArr[(unsigned)FormatIndex];
2297370b324cSopenharmony_ci        const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);
2298370b324cSopenharmony_ci        bool openCur = false;
2299370b324cSopenharmony_ci
2300370b324cSopenharmony_ci        if (!ErrorInfo.ThereIsTail)
2301370b324cSopenharmony_ci          openCur = true;
2302370b324cSopenharmony_ci        else
2303370b324cSopenharmony_ci        {
2304370b324cSopenharmony_ci          if (mode.ZerosTailIsAllowed)
2305370b324cSopenharmony_ci          {
2306370b324cSopenharmony_ci            RINOK(CheckZerosTail(op, (UInt64)(Offset + (Int64)PhySize)))
2307370b324cSopenharmony_ci            if (ErrorInfo.IgnoreTail)
2308370b324cSopenharmony_ci              openCur = true;
2309370b324cSopenharmony_ci          }
2310370b324cSopenharmony_ci          if (!openCur)
2311370b324cSopenharmony_ci          {
2312370b324cSopenharmony_ci            openCur = specFlags.CanReturnFrontal;
2313370b324cSopenharmony_ci            if (formatIndex < 0) // format is not forced
2314370b324cSopenharmony_ci            {
2315370b324cSopenharmony_ci              if (IsPreArcFormat(ai))
2316370b324cSopenharmony_ci              {
2317370b324cSopenharmony_ci                // if (mode.SkipSfxStub)
2318370b324cSopenharmony_ci                {
2319370b324cSopenharmony_ci                  openCur = false;
2320370b324cSopenharmony_ci                }
2321370b324cSopenharmony_ci              }
2322370b324cSopenharmony_ci            }
2323370b324cSopenharmony_ci          }
2324370b324cSopenharmony_ci        }
2325370b324cSopenharmony_ci
2326370b324cSopenharmony_ci        if (openCur)
2327370b324cSopenharmony_ci        {
2328370b324cSopenharmony_ci          InStream = op.stream;
2329370b324cSopenharmony_ci          Archive = archive;
2330370b324cSopenharmony_ci          return S_OK;
2331370b324cSopenharmony_ci        }
2332370b324cSopenharmony_ci      }
2333370b324cSopenharmony_ci
2334370b324cSopenharmony_ci      skipFrontalFormat[(unsigned)FormatIndex] = true;
2335370b324cSopenharmony_ci
2336370b324cSopenharmony_ci
2337370b324cSopenharmony_ci      // if (!mode.CanReturnArc)
2338370b324cSopenharmony_ci      /*
2339370b324cSopenharmony_ci      if (!ErrorInfo.ThereIsTail)
2340370b324cSopenharmony_ci          continue;
2341370b324cSopenharmony_ci      */
2342370b324cSopenharmony_ci      if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize)
2343370b324cSopenharmony_ci        continue;
2344370b324cSopenharmony_ci
2345370b324cSopenharmony_ci      // printf("\nAdd offset = %d", (int)pi.Offset);
2346370b324cSopenharmony_ci      RINOK(ReadParseItemProps(archive, ai, pi))
2347370b324cSopenharmony_ci      handlerSpec->AddItem(pi);
2348370b324cSopenharmony_ci    }
2349370b324cSopenharmony_ci  }
2350370b324cSopenharmony_ci
2351370b324cSopenharmony_ci
2352370b324cSopenharmony_ci
2353370b324cSopenharmony_ci
2354370b324cSopenharmony_ci
2355370b324cSopenharmony_ci  // ---------- PARSER ----------
2356370b324cSopenharmony_ci
2357370b324cSopenharmony_ci  CUIntVector arc2sig; // formatIndex to signatureIndex
2358370b324cSopenharmony_ci  CUIntVector sig2arc; // signatureIndex to formatIndex;
2359370b324cSopenharmony_ci  {
2360370b324cSopenharmony_ci    unsigned sum = 0;
2361370b324cSopenharmony_ci    FOR_VECTOR (i, op.codecs->Formats)
2362370b324cSopenharmony_ci    {
2363370b324cSopenharmony_ci      arc2sig.Add(sum);
2364370b324cSopenharmony_ci      const CObjectVector<CByteBuffer> &sigs = op.codecs->Formats[i].Signatures;
2365370b324cSopenharmony_ci      sum += sigs.Size();
2366370b324cSopenharmony_ci      FOR_VECTOR (k, sigs)
2367370b324cSopenharmony_ci        sig2arc.Add(i);
2368370b324cSopenharmony_ci    }
2369370b324cSopenharmony_ci  }
2370370b324cSopenharmony_ci
2371370b324cSopenharmony_ci  {
2372370b324cSopenharmony_ci    const size_t kBeforeSize = 1 << 16;
2373370b324cSopenharmony_ci    const size_t kAfterSize  = 1 << 20;
2374370b324cSopenharmony_ci    const size_t kBufSize = 1 << 22; // it must be more than kBeforeSize + kAfterSize
2375370b324cSopenharmony_ci
2376370b324cSopenharmony_ci    const UInt32 kNumVals = (UInt32)1 << (kNumHashBytes * 8);
2377370b324cSopenharmony_ci    CByteArr hashBuffer(kNumVals);
2378370b324cSopenharmony_ci    Byte *hash = hashBuffer;
2379370b324cSopenharmony_ci    memset(hash, 0xFF, kNumVals);
2380370b324cSopenharmony_ci    Byte prevs[256];
2381370b324cSopenharmony_ci    memset(prevs, 0xFF, sizeof(prevs));
2382370b324cSopenharmony_ci    if (sig2arc.Size() >= 0xFF)
2383370b324cSopenharmony_ci      return S_FALSE;
2384370b324cSopenharmony_ci
2385370b324cSopenharmony_ci    CUIntVector difficultFormats;
2386370b324cSopenharmony_ci    CBoolArr difficultBools(256);
2387370b324cSopenharmony_ci    {
2388370b324cSopenharmony_ci      for (unsigned i = 0; i < 256; i++)
2389370b324cSopenharmony_ci        difficultBools[i] = false;
2390370b324cSopenharmony_ci    }
2391370b324cSopenharmony_ci
2392370b324cSopenharmony_ci    bool thereAreHandlersForSearch = false;
2393370b324cSopenharmony_ci
2394370b324cSopenharmony_ci    // UInt32 maxSignatureEnd = 0;
2395370b324cSopenharmony_ci
2396370b324cSopenharmony_ci    FOR_VECTOR (i, orderIndices)
2397370b324cSopenharmony_ci    {
2398370b324cSopenharmony_ci      int index = orderIndices[i];
2399370b324cSopenharmony_ci      if (index < 0)
2400370b324cSopenharmony_ci        continue;
2401370b324cSopenharmony_ci      const CArcInfoEx &ai = op.codecs->Formats[(unsigned)index];
2402370b324cSopenharmony_ci      if (ai.Flags_ByExtOnlyOpen())
2403370b324cSopenharmony_ci        continue;
2404370b324cSopenharmony_ci      bool isDifficult = false;
2405370b324cSopenharmony_ci      // if (ai.Version < 0x91F) // we don't use parser with old DLL (before 9.31)
2406370b324cSopenharmony_ci      if (!ai.NewInterface)
2407370b324cSopenharmony_ci        isDifficult = true;
2408370b324cSopenharmony_ci      else
2409370b324cSopenharmony_ci      {
2410370b324cSopenharmony_ci        if (ai.Flags_StartOpen())
2411370b324cSopenharmony_ci          isDifficult = true;
2412370b324cSopenharmony_ci        FOR_VECTOR (k, ai.Signatures)
2413370b324cSopenharmony_ci        {
2414370b324cSopenharmony_ci          const CByteBuffer &sig = ai.Signatures[k];
2415370b324cSopenharmony_ci          /*
2416370b324cSopenharmony_ci          UInt32 signatureEnd = ai.SignatureOffset + (UInt32)sig.Size();
2417370b324cSopenharmony_ci          if (maxSignatureEnd < signatureEnd)
2418370b324cSopenharmony_ci            maxSignatureEnd = signatureEnd;
2419370b324cSopenharmony_ci          */
2420370b324cSopenharmony_ci          if (sig.Size() < kNumHashBytes)
2421370b324cSopenharmony_ci          {
2422370b324cSopenharmony_ci            isDifficult = true;
2423370b324cSopenharmony_ci            continue;
2424370b324cSopenharmony_ci          }
2425370b324cSopenharmony_ci          thereAreHandlersForSearch = true;
2426370b324cSopenharmony_ci          UInt32 v = HASH_VAL(sig);
2427370b324cSopenharmony_ci          unsigned sigIndex = arc2sig[(unsigned)index] + k;
2428370b324cSopenharmony_ci          prevs[sigIndex] = hash[v];
2429370b324cSopenharmony_ci          hash[v] = (Byte)sigIndex;
2430370b324cSopenharmony_ci        }
2431370b324cSopenharmony_ci      }
2432370b324cSopenharmony_ci      if (isDifficult)
2433370b324cSopenharmony_ci      {
2434370b324cSopenharmony_ci        difficultFormats.Add((unsigned)index);
2435370b324cSopenharmony_ci        difficultBools[(unsigned)index] = true;
2436370b324cSopenharmony_ci      }
2437370b324cSopenharmony_ci    }
2438370b324cSopenharmony_ci
2439370b324cSopenharmony_ci    if (!thereAreHandlersForSearch)
2440370b324cSopenharmony_ci    {
2441370b324cSopenharmony_ci      // openOnlyFullArc = true;
2442370b324cSopenharmony_ci      // canReturnTailArc = true;
2443370b324cSopenharmony_ci    }
2444370b324cSopenharmony_ci
2445370b324cSopenharmony_ci    RINOK(InStream_SeekToBegin(op.stream))
2446370b324cSopenharmony_ci
2447370b324cSopenharmony_ci    CLimitedCachedInStream *limitedStreamSpec = new CLimitedCachedInStream;
2448370b324cSopenharmony_ci    CMyComPtr<IInStream> limitedStream = limitedStreamSpec;
2449370b324cSopenharmony_ci    limitedStreamSpec->SetStream(op.stream);
2450370b324cSopenharmony_ci
2451370b324cSopenharmony_ci    CArchiveOpenCallback_Offset *openCallback_Offset_Spec = NULL;
2452370b324cSopenharmony_ci    CMyComPtr<IArchiveOpenCallback> openCallback_Offset;
2453370b324cSopenharmony_ci    if (op.callback)
2454370b324cSopenharmony_ci    {
2455370b324cSopenharmony_ci      openCallback_Offset_Spec = new CArchiveOpenCallback_Offset;
2456370b324cSopenharmony_ci      openCallback_Offset = openCallback_Offset_Spec;
2457370b324cSopenharmony_ci      openCallback_Offset_Spec->Callback = op.callback;
2458370b324cSopenharmony_ci      openCallback_Offset_Spec->Callback.QueryInterface(IID_IArchiveOpenVolumeCallback, &openCallback_Offset_Spec->OpenVolumeCallback);
2459370b324cSopenharmony_ci      #ifndef Z7_NO_CRYPTO
2460370b324cSopenharmony_ci      openCallback_Offset_Spec->Callback.QueryInterface(IID_ICryptoGetTextPassword, &openCallback_Offset_Spec->GetTextPassword);
2461370b324cSopenharmony_ci      #endif
2462370b324cSopenharmony_ci    }
2463370b324cSopenharmony_ci
2464370b324cSopenharmony_ci    if (op.callback)
2465370b324cSopenharmony_ci      RINOK(op.callback->SetTotal(NULL, &fileSize))
2466370b324cSopenharmony_ci
2467370b324cSopenharmony_ci    CByteBuffer &byteBuffer = limitedStreamSpec->Buffer;
2468370b324cSopenharmony_ci    byteBuffer.Alloc(kBufSize);
2469370b324cSopenharmony_ci
2470370b324cSopenharmony_ci    UInt64 callbackPrev = 0;
2471370b324cSopenharmony_ci    bool needCheckStartOpen = true; // = true, if we need to test all archives types for current pos.
2472370b324cSopenharmony_ci
2473370b324cSopenharmony_ci    bool endOfFile = false;
2474370b324cSopenharmony_ci    UInt64 bufPhyPos = 0;
2475370b324cSopenharmony_ci    size_t bytesInBuf = 0;
2476370b324cSopenharmony_ci    // UInt64 prevPos = 0;
2477370b324cSopenharmony_ci
2478370b324cSopenharmony_ci    // ---------- Main Scan Loop ----------
2479370b324cSopenharmony_ci
2480370b324cSopenharmony_ci    UInt64 pos = 0;
2481370b324cSopenharmony_ci
2482370b324cSopenharmony_ci    if (!mode.EachPos && handlerSpec->_items.Size() == 1)
2483370b324cSopenharmony_ci    {
2484370b324cSopenharmony_ci      NArchive::NParser::CParseItem &pi = handlerSpec->_items[0];
2485370b324cSopenharmony_ci      if (!pi.LenIsUnknown && pi.Offset == 0)
2486370b324cSopenharmony_ci        pos = pi.Size;
2487370b324cSopenharmony_ci    }
2488370b324cSopenharmony_ci
2489370b324cSopenharmony_ci    for (;;)
2490370b324cSopenharmony_ci    {
2491370b324cSopenharmony_ci      // printf("\nPos = %d", (int)pos);
2492370b324cSopenharmony_ci      UInt64 posInBuf = pos - bufPhyPos;
2493370b324cSopenharmony_ci
2494370b324cSopenharmony_ci      // if (pos > ((UInt64)1 << 35)) break;
2495370b324cSopenharmony_ci
2496370b324cSopenharmony_ci      if (!endOfFile)
2497370b324cSopenharmony_ci      {
2498370b324cSopenharmony_ci        if (bytesInBuf < kBufSize)
2499370b324cSopenharmony_ci        {
2500370b324cSopenharmony_ci          size_t processedSize = kBufSize - bytesInBuf;
2501370b324cSopenharmony_ci          // printf("\nRead ask = %d", (unsigned)processedSize);
2502370b324cSopenharmony_ci          UInt64 seekPos = bufPhyPos + bytesInBuf;
2503370b324cSopenharmony_ci          RINOK(InStream_SeekSet(op.stream, bufPhyPos + bytesInBuf))
2504370b324cSopenharmony_ci          RINOK(ReadStream(op.stream, byteBuffer + bytesInBuf, &processedSize))
2505370b324cSopenharmony_ci          // printf("   processed = %d", (unsigned)processedSize);
2506370b324cSopenharmony_ci          if (processedSize == 0)
2507370b324cSopenharmony_ci          {
2508370b324cSopenharmony_ci            fileSize = seekPos;
2509370b324cSopenharmony_ci            endOfFile = true;
2510370b324cSopenharmony_ci          }
2511370b324cSopenharmony_ci          else
2512370b324cSopenharmony_ci          {
2513370b324cSopenharmony_ci            bytesInBuf += processedSize;
2514370b324cSopenharmony_ci            limitedStreamSpec->SetCache(processedSize, (size_t)bufPhyPos);
2515370b324cSopenharmony_ci          }
2516370b324cSopenharmony_ci          continue;
2517370b324cSopenharmony_ci        }
2518370b324cSopenharmony_ci
2519370b324cSopenharmony_ci        if (bytesInBuf < posInBuf)
2520370b324cSopenharmony_ci        {
2521370b324cSopenharmony_ci          UInt64 skipSize = posInBuf - bytesInBuf;
2522370b324cSopenharmony_ci          if (skipSize <= kBeforeSize)
2523370b324cSopenharmony_ci          {
2524370b324cSopenharmony_ci            size_t keepSize = (size_t)(kBeforeSize - skipSize);
2525370b324cSopenharmony_ci            // printf("\nmemmove skip = %d", (int)keepSize);
2526370b324cSopenharmony_ci            memmove(byteBuffer, byteBuffer + bytesInBuf - keepSize, keepSize);
2527370b324cSopenharmony_ci            bytesInBuf = keepSize;
2528370b324cSopenharmony_ci            bufPhyPos = pos - keepSize;
2529370b324cSopenharmony_ci            continue;
2530370b324cSopenharmony_ci          }
2531370b324cSopenharmony_ci          // printf("\nSkip %d", (int)(skipSize - kBeforeSize));
2532370b324cSopenharmony_ci          // RINOK(op.stream->Seek(skipSize - kBeforeSize, STREAM_SEEK_CUR, NULL));
2533370b324cSopenharmony_ci          bytesInBuf = 0;
2534370b324cSopenharmony_ci          bufPhyPos = pos - kBeforeSize;
2535370b324cSopenharmony_ci          continue;
2536370b324cSopenharmony_ci        }
2537370b324cSopenharmony_ci
2538370b324cSopenharmony_ci        if (bytesInBuf - posInBuf < kAfterSize)
2539370b324cSopenharmony_ci        {
2540370b324cSopenharmony_ci          size_t beg = (size_t)posInBuf - kBeforeSize;
2541370b324cSopenharmony_ci          // printf("\nmemmove for after beg = %d", (int)beg);
2542370b324cSopenharmony_ci          memmove(byteBuffer, byteBuffer + beg, bytesInBuf - beg);
2543370b324cSopenharmony_ci          bufPhyPos += beg;
2544370b324cSopenharmony_ci          bytesInBuf -= beg;
2545370b324cSopenharmony_ci          continue;
2546370b324cSopenharmony_ci        }
2547370b324cSopenharmony_ci      }
2548370b324cSopenharmony_ci
2549370b324cSopenharmony_ci      if (bytesInBuf <= (size_t)posInBuf)
2550370b324cSopenharmony_ci        break;
2551370b324cSopenharmony_ci
2552370b324cSopenharmony_ci      bool useOffsetCallback = false;
2553370b324cSopenharmony_ci      if (openCallback_Offset)
2554370b324cSopenharmony_ci      {
2555370b324cSopenharmony_ci        openCallback_Offset_Spec->Files = handlerSpec->_items.Size();
2556370b324cSopenharmony_ci        openCallback_Offset_Spec->Offset = pos;
2557370b324cSopenharmony_ci
2558370b324cSopenharmony_ci        useOffsetCallback = (!op.openType.CanReturnArc || handlerSpec->_items.Size() > 1);
2559370b324cSopenharmony_ci
2560370b324cSopenharmony_ci        if (pos >= callbackPrev + (1 << 23))
2561370b324cSopenharmony_ci        {
2562370b324cSopenharmony_ci          RINOK(openCallback_Offset->SetCompleted(NULL, NULL))
2563370b324cSopenharmony_ci          callbackPrev = pos;
2564370b324cSopenharmony_ci        }
2565370b324cSopenharmony_ci      }
2566370b324cSopenharmony_ci
2567370b324cSopenharmony_ci      {
2568370b324cSopenharmony_ci        UInt64 endPos = bufPhyPos + bytesInBuf;
2569370b324cSopenharmony_ci        if (fileSize < endPos)
2570370b324cSopenharmony_ci        {
2571370b324cSopenharmony_ci          FileSize = fileSize; // why ????
2572370b324cSopenharmony_ci          fileSize = endPos;
2573370b324cSopenharmony_ci        }
2574370b324cSopenharmony_ci      }
2575370b324cSopenharmony_ci
2576370b324cSopenharmony_ci      const size_t availSize = bytesInBuf - (size_t)posInBuf;
2577370b324cSopenharmony_ci      if (availSize < kNumHashBytes)
2578370b324cSopenharmony_ci        break;
2579370b324cSopenharmony_ci      size_t scanSize = availSize -
2580370b324cSopenharmony_ci          ((availSize >= kAfterSize) ? kAfterSize : kNumHashBytes);
2581370b324cSopenharmony_ci
2582370b324cSopenharmony_ci      {
2583370b324cSopenharmony_ci        /*
2584370b324cSopenharmony_ci        UInt64 scanLimit = openOnlyFullArc ?
2585370b324cSopenharmony_ci            maxSignatureEnd :
2586370b324cSopenharmony_ci            op.openType.ScanSize + maxSignatureEnd;
2587370b324cSopenharmony_ci        */
2588370b324cSopenharmony_ci        if (!mode.CanReturnParser)
2589370b324cSopenharmony_ci        {
2590370b324cSopenharmony_ci          if (pos > maxStartOffset)
2591370b324cSopenharmony_ci            break;
2592370b324cSopenharmony_ci          UInt64 remScan = maxStartOffset - pos;
2593370b324cSopenharmony_ci          if (scanSize > remScan)
2594370b324cSopenharmony_ci            scanSize = (size_t)remScan;
2595370b324cSopenharmony_ci        }
2596370b324cSopenharmony_ci      }
2597370b324cSopenharmony_ci
2598370b324cSopenharmony_ci      scanSize++;
2599370b324cSopenharmony_ci
2600370b324cSopenharmony_ci      const Byte *buf = byteBuffer + (size_t)posInBuf;
2601370b324cSopenharmony_ci      const Byte *bufLimit = buf + scanSize;
2602370b324cSopenharmony_ci      size_t ppp = 0;
2603370b324cSopenharmony_ci
2604370b324cSopenharmony_ci      if (!needCheckStartOpen)
2605370b324cSopenharmony_ci      {
2606370b324cSopenharmony_ci        for (; buf < bufLimit && hash[HASH_VAL(buf)] == 0xFF; buf++);
2607370b324cSopenharmony_ci        ppp = (size_t)(buf - (byteBuffer + (size_t)posInBuf));
2608370b324cSopenharmony_ci        pos += ppp;
2609370b324cSopenharmony_ci        if (buf == bufLimit)
2610370b324cSopenharmony_ci          continue;
2611370b324cSopenharmony_ci      }
2612370b324cSopenharmony_ci
2613370b324cSopenharmony_ci      UInt32 v = HASH_VAL(buf);
2614370b324cSopenharmony_ci      bool nextNeedCheckStartOpen = true;
2615370b324cSopenharmony_ci      unsigned i = hash[v];
2616370b324cSopenharmony_ci      unsigned indexOfDifficult = 0;
2617370b324cSopenharmony_ci
2618370b324cSopenharmony_ci      // ---------- Open Loop for Current Pos ----------
2619370b324cSopenharmony_ci      bool wasOpen = false;
2620370b324cSopenharmony_ci
2621370b324cSopenharmony_ci      for (;;)
2622370b324cSopenharmony_ci      {
2623370b324cSopenharmony_ci        unsigned index;
2624370b324cSopenharmony_ci        bool isDifficult;
2625370b324cSopenharmony_ci        if (needCheckStartOpen && indexOfDifficult < difficultFormats.Size())
2626370b324cSopenharmony_ci        {
2627370b324cSopenharmony_ci          index = difficultFormats[indexOfDifficult++];
2628370b324cSopenharmony_ci          isDifficult = true;
2629370b324cSopenharmony_ci        }
2630370b324cSopenharmony_ci        else
2631370b324cSopenharmony_ci        {
2632370b324cSopenharmony_ci          if (i == 0xFF)
2633370b324cSopenharmony_ci            break;
2634370b324cSopenharmony_ci          index = sig2arc[i];
2635370b324cSopenharmony_ci          unsigned sigIndex = i - arc2sig[index];
2636370b324cSopenharmony_ci          i = prevs[i];
2637370b324cSopenharmony_ci          if (needCheckStartOpen && difficultBools[index])
2638370b324cSopenharmony_ci            continue;
2639370b324cSopenharmony_ci          const CArcInfoEx &ai = op.codecs->Formats[index];
2640370b324cSopenharmony_ci
2641370b324cSopenharmony_ci          if (pos < ai.SignatureOffset)
2642370b324cSopenharmony_ci            continue;
2643370b324cSopenharmony_ci
2644370b324cSopenharmony_ci          /*
2645370b324cSopenharmony_ci          if (openOnlyFullArc)
2646370b324cSopenharmony_ci            if (pos != ai.SignatureOffset)
2647370b324cSopenharmony_ci              continue;
2648370b324cSopenharmony_ci          */
2649370b324cSopenharmony_ci
2650370b324cSopenharmony_ci          const CByteBuffer &sig = ai.Signatures[sigIndex];
2651370b324cSopenharmony_ci
2652370b324cSopenharmony_ci          if (ppp + sig.Size() > availSize
2653370b324cSopenharmony_ci              || !TestSignature(buf, sig, sig.Size()))
2654370b324cSopenharmony_ci            continue;
2655370b324cSopenharmony_ci          // printf("\nSignature OK: %10S %8x %5d", (const wchar_t *)ai.Name, (int)pos, (int)(pos - prevPos));
2656370b324cSopenharmony_ci          // prevPos = pos;
2657370b324cSopenharmony_ci          isDifficult = false;
2658370b324cSopenharmony_ci        }
2659370b324cSopenharmony_ci
2660370b324cSopenharmony_ci        const CArcInfoEx &ai = op.codecs->Formats[index];
2661370b324cSopenharmony_ci
2662370b324cSopenharmony_ci
2663370b324cSopenharmony_ci        if ((isDifficult && pos == 0) || ai.SignatureOffset == pos)
2664370b324cSopenharmony_ci        {
2665370b324cSopenharmony_ci          // we don't check same archive second time */
2666370b324cSopenharmony_ci          if (skipFrontalFormat[index])
2667370b324cSopenharmony_ci            continue;
2668370b324cSopenharmony_ci        }
2669370b324cSopenharmony_ci
2670370b324cSopenharmony_ci        UInt64 startArcPos = pos;
2671370b324cSopenharmony_ci        if (!isDifficult)
2672370b324cSopenharmony_ci        {
2673370b324cSopenharmony_ci          if (pos < ai.SignatureOffset)
2674370b324cSopenharmony_ci            continue;
2675370b324cSopenharmony_ci          startArcPos = pos - ai.SignatureOffset;
2676370b324cSopenharmony_ci          /*
2677370b324cSopenharmony_ci          // we don't need the check for Z files
2678370b324cSopenharmony_ci          if (startArcPos < handlerSpec->GetLastEnd())
2679370b324cSopenharmony_ci            continue;
2680370b324cSopenharmony_ci          */
2681370b324cSopenharmony_ci        }
2682370b324cSopenharmony_ci
2683370b324cSopenharmony_ci        if (ai.IsArcFunc && startArcPos >= bufPhyPos)
2684370b324cSopenharmony_ci        {
2685370b324cSopenharmony_ci          const size_t offsetInBuf = (size_t)(startArcPos - bufPhyPos);
2686370b324cSopenharmony_ci          if (offsetInBuf < bytesInBuf)
2687370b324cSopenharmony_ci          {
2688370b324cSopenharmony_ci            const UInt32 isArcRes = ai.IsArcFunc(byteBuffer + offsetInBuf, bytesInBuf - offsetInBuf);
2689370b324cSopenharmony_ci            if (isArcRes == k_IsArc_Res_NO)
2690370b324cSopenharmony_ci              continue;
2691370b324cSopenharmony_ci            if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile)
2692370b324cSopenharmony_ci              continue;
2693370b324cSopenharmony_ci            /*
2694370b324cSopenharmony_ci            if (isArcRes == k_IsArc_Res_YES_LOW_PROB)
2695370b324cSopenharmony_ci            {
2696370b324cSopenharmony_ci              // if (pos != ai.SignatureOffset)
2697370b324cSopenharmony_ci              continue;
2698370b324cSopenharmony_ci            }
2699370b324cSopenharmony_ci            */
2700370b324cSopenharmony_ci          }
2701370b324cSopenharmony_ci          // printf("\nIsArc OK: %S", (const wchar_t *)ai.Name);
2702370b324cSopenharmony_ci        }
2703370b324cSopenharmony_ci
2704370b324cSopenharmony_ci        PRF(printf("\npos = %9I64d : %S", pos, (const wchar_t *)ai.Name));
2705370b324cSopenharmony_ci
2706370b324cSopenharmony_ci        const bool isMainFormat = isMainFormatArr[index];
2707370b324cSopenharmony_ci        const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);
2708370b324cSopenharmony_ci
2709370b324cSopenharmony_ci        CMyComPtr<IInArchive> archive;
2710370b324cSopenharmony_ci        RINOK(PrepareToOpen(op, index, archive))
2711370b324cSopenharmony_ci        if (!archive)
2712370b324cSopenharmony_ci          return E_FAIL;
2713370b324cSopenharmony_ci
2714370b324cSopenharmony_ci        // OutputDebugStringW(ai.Name);
2715370b324cSopenharmony_ci
2716370b324cSopenharmony_ci        const UInt64 rem = fileSize - startArcPos;
2717370b324cSopenharmony_ci
2718370b324cSopenharmony_ci        UInt64 arcStreamOffset = 0;
2719370b324cSopenharmony_ci
2720370b324cSopenharmony_ci        if (ai.Flags_UseGlobalOffset())
2721370b324cSopenharmony_ci        {
2722370b324cSopenharmony_ci          RINOK(limitedStreamSpec->InitAndSeek(0, fileSize))
2723370b324cSopenharmony_ci          RINOK(InStream_SeekSet(limitedStream, startArcPos))
2724370b324cSopenharmony_ci        }
2725370b324cSopenharmony_ci        else
2726370b324cSopenharmony_ci        {
2727370b324cSopenharmony_ci          RINOK(limitedStreamSpec->InitAndSeek(startArcPos, rem))
2728370b324cSopenharmony_ci          arcStreamOffset = startArcPos;
2729370b324cSopenharmony_ci        }
2730370b324cSopenharmony_ci
2731370b324cSopenharmony_ci        UInt64 maxCheckStartPosition = 0;
2732370b324cSopenharmony_ci
2733370b324cSopenharmony_ci        if (openCallback_Offset)
2734370b324cSopenharmony_ci        {
2735370b324cSopenharmony_ci          openCallback_Offset_Spec->Files = handlerSpec->_items.Size();
2736370b324cSopenharmony_ci          openCallback_Offset_Spec->Offset = startArcPos;
2737370b324cSopenharmony_ci        }
2738370b324cSopenharmony_ci
2739370b324cSopenharmony_ci        // HRESULT result = archive->Open(limitedStream, &maxCheckStartPosition, openCallback_Offset);
2740370b324cSopenharmony_ci        extractCallback_To_OpenCallback_Spec->Files = 0;
2741370b324cSopenharmony_ci        extractCallback_To_OpenCallback_Spec->Offset = startArcPos;
2742370b324cSopenharmony_ci
2743370b324cSopenharmony_ci        HRESULT result = OpenArchiveSpec(archive,
2744370b324cSopenharmony_ci            true, // needPhySize
2745370b324cSopenharmony_ci            limitedStream, &maxCheckStartPosition,
2746370b324cSopenharmony_ci            useOffsetCallback ? (IArchiveOpenCallback *)openCallback_Offset : (IArchiveOpenCallback *)op.callback,
2747370b324cSopenharmony_ci            extractCallback_To_OpenCallback);
2748370b324cSopenharmony_ci
2749370b324cSopenharmony_ci        RINOK(ReadBasicProps(archive, ai.Flags_UseGlobalOffset() ? 0 : startArcPos, result))
2750370b324cSopenharmony_ci
2751370b324cSopenharmony_ci        bool isOpen = false;
2752370b324cSopenharmony_ci
2753370b324cSopenharmony_ci        if (result == S_FALSE)
2754370b324cSopenharmony_ci        {
2755370b324cSopenharmony_ci          if (!mode.CanReturnParser)
2756370b324cSopenharmony_ci          {
2757370b324cSopenharmony_ci            if (formatIndex < 0 && ErrorInfo.IsArc_After_NonOpen())
2758370b324cSopenharmony_ci            {
2759370b324cSopenharmony_ci              ErrorInfo.ErrorFormatIndex = (int)index;
2760370b324cSopenharmony_ci              NonOpen_ErrorInfo = ErrorInfo;
2761370b324cSopenharmony_ci              // if archive was detected, we don't need additional open attempts
2762370b324cSopenharmony_ci              return S_FALSE;
2763370b324cSopenharmony_ci            }
2764370b324cSopenharmony_ci            continue;
2765370b324cSopenharmony_ci          }
2766370b324cSopenharmony_ci          if (!ErrorInfo.IsArc_After_NonOpen() || !PhySize_Defined || PhySize == 0)
2767370b324cSopenharmony_ci            continue;
2768370b324cSopenharmony_ci        }
2769370b324cSopenharmony_ci        else
2770370b324cSopenharmony_ci        {
2771370b324cSopenharmony_ci          if (PhySize_Defined && PhySize == 0)
2772370b324cSopenharmony_ci          {
2773370b324cSopenharmony_ci            PRF(printf("  phySize_Defined && PhySize == 0 "));
2774370b324cSopenharmony_ci            // we skip that epmty archive case with unusual unexpected (PhySize == 0) from Code function.
2775370b324cSopenharmony_ci            continue;
2776370b324cSopenharmony_ci          }
2777370b324cSopenharmony_ci          isOpen = true;
2778370b324cSopenharmony_ci          RINOK(result)
2779370b324cSopenharmony_ci          PRF(printf("  OK "));
2780370b324cSopenharmony_ci        }
2781370b324cSopenharmony_ci
2782370b324cSopenharmony_ci        // fprintf(stderr, "\n %8X  %S", startArcPos, Path);
2783370b324cSopenharmony_ci        // printf("\nOpen OK: %S", ai.Name);
2784370b324cSopenharmony_ci
2785370b324cSopenharmony_ci
2786370b324cSopenharmony_ci        NArchive::NParser::CParseItem pi;
2787370b324cSopenharmony_ci        pi.Offset = startArcPos;
2788370b324cSopenharmony_ci
2789370b324cSopenharmony_ci        if (ai.Flags_UseGlobalOffset())
2790370b324cSopenharmony_ci          pi.Offset = (UInt64)Offset;
2791370b324cSopenharmony_ci        else if (Offset != 0)
2792370b324cSopenharmony_ci          return E_FAIL;
2793370b324cSopenharmony_ci
2794370b324cSopenharmony_ci        const UInt64 arcRem = FileSize - pi.Offset;
2795370b324cSopenharmony_ci        UInt64 phySize = arcRem;
2796370b324cSopenharmony_ci        const bool phySize_Defined = PhySize_Defined;
2797370b324cSopenharmony_ci        if (phySize_Defined)
2798370b324cSopenharmony_ci        {
2799370b324cSopenharmony_ci          if (pi.Offset + PhySize > FileSize)
2800370b324cSopenharmony_ci          {
2801370b324cSopenharmony_ci            // ErrorInfo.ThereIsTail = true;
2802370b324cSopenharmony_ci            PhySize = FileSize - pi.Offset;
2803370b324cSopenharmony_ci          }
2804370b324cSopenharmony_ci          phySize = PhySize;
2805370b324cSopenharmony_ci        }
2806370b324cSopenharmony_ci        if (phySize == 0 || (UInt64)phySize > ((UInt64)1 << 63))
2807370b324cSopenharmony_ci          return E_FAIL;
2808370b324cSopenharmony_ci
2809370b324cSopenharmony_ci        /*
2810370b324cSopenharmony_ci        if (!ai.UseGlobalOffset)
2811370b324cSopenharmony_ci        {
2812370b324cSopenharmony_ci          if (phySize > arcRem)
2813370b324cSopenharmony_ci          {
2814370b324cSopenharmony_ci            ThereIsTail = true;
2815370b324cSopenharmony_ci            phySize = arcRem;
2816370b324cSopenharmony_ci          }
2817370b324cSopenharmony_ci        }
2818370b324cSopenharmony_ci        */
2819370b324cSopenharmony_ci
2820370b324cSopenharmony_ci        bool needScan = false;
2821370b324cSopenharmony_ci
2822370b324cSopenharmony_ci
2823370b324cSopenharmony_ci        if (isOpen && !phySize_Defined)
2824370b324cSopenharmony_ci        {
2825370b324cSopenharmony_ci          // it's for Z format, or bzip2,gz,xz with phySize that was not detected
2826370b324cSopenharmony_ci          pi.LenIsUnknown = true;
2827370b324cSopenharmony_ci          needScan = true;
2828370b324cSopenharmony_ci          phySize = arcRem;
2829370b324cSopenharmony_ci          nextNeedCheckStartOpen = false;
2830370b324cSopenharmony_ci        }
2831370b324cSopenharmony_ci
2832370b324cSopenharmony_ci        pi.Size = phySize;
2833370b324cSopenharmony_ci        /*
2834370b324cSopenharmony_ci        if (OkPhySize_Defined)
2835370b324cSopenharmony_ci          pi.OkSize = OkPhySize;
2836370b324cSopenharmony_ci        */
2837370b324cSopenharmony_ci        pi.NormalizeOffset();
2838370b324cSopenharmony_ci        // printf("  phySize = %8d", (unsigned)phySize);
2839370b324cSopenharmony_ci
2840370b324cSopenharmony_ci        /*
2841370b324cSopenharmony_ci        if (needSkipFullArc)
2842370b324cSopenharmony_ci          if (pi.Offset == 0 && phySize_Defined && pi.Size >= fileSize)
2843370b324cSopenharmony_ci            continue;
2844370b324cSopenharmony_ci        */
2845370b324cSopenharmony_ci        if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize)
2846370b324cSopenharmony_ci        {
2847370b324cSopenharmony_ci          // it's possible for dmg archives
2848370b324cSopenharmony_ci          if (!mode.CanReturnArc)
2849370b324cSopenharmony_ci            continue;
2850370b324cSopenharmony_ci        }
2851370b324cSopenharmony_ci
2852370b324cSopenharmony_ci        if (mode.EachPos)
2853370b324cSopenharmony_ci          pos++;
2854370b324cSopenharmony_ci        else if (needScan)
2855370b324cSopenharmony_ci        {
2856370b324cSopenharmony_ci          pos++;
2857370b324cSopenharmony_ci          /*
2858370b324cSopenharmony_ci          if (!OkPhySize_Defined)
2859370b324cSopenharmony_ci            pos++;
2860370b324cSopenharmony_ci          else
2861370b324cSopenharmony_ci            pos = pi.Offset + pi.OkSize;
2862370b324cSopenharmony_ci          */
2863370b324cSopenharmony_ci        }
2864370b324cSopenharmony_ci        else
2865370b324cSopenharmony_ci          pos = pi.Offset + pi.Size;
2866370b324cSopenharmony_ci
2867370b324cSopenharmony_ci
2868370b324cSopenharmony_ci        RINOK(ReadParseItemProps(archive, ai, pi))
2869370b324cSopenharmony_ci
2870370b324cSopenharmony_ci        if (pi.Offset < startArcPos && !mode.EachPos /* && phySize_Defined */)
2871370b324cSopenharmony_ci        {
2872370b324cSopenharmony_ci          /* It's for DMG format.
2873370b324cSopenharmony_ci          This code deletes all previous items that are included to current item */
2874370b324cSopenharmony_ci
2875370b324cSopenharmony_ci          while (!handlerSpec->_items.IsEmpty())
2876370b324cSopenharmony_ci          {
2877370b324cSopenharmony_ci            {
2878370b324cSopenharmony_ci              const NArchive::NParser::CParseItem &back = handlerSpec->_items.Back();
2879370b324cSopenharmony_ci              if (back.Offset < pi.Offset)
2880370b324cSopenharmony_ci                break;
2881370b324cSopenharmony_ci              if (back.Offset + back.Size > pi.Offset + pi.Size)
2882370b324cSopenharmony_ci                break;
2883370b324cSopenharmony_ci            }
2884370b324cSopenharmony_ci            handlerSpec->_items.DeleteBack();
2885370b324cSopenharmony_ci          }
2886370b324cSopenharmony_ci        }
2887370b324cSopenharmony_ci
2888370b324cSopenharmony_ci
2889370b324cSopenharmony_ci        if (isOpen && mode.CanReturnArc && phySize_Defined)
2890370b324cSopenharmony_ci        {
2891370b324cSopenharmony_ci          // if (pi.Offset + pi.Size >= fileSize)
2892370b324cSopenharmony_ci          bool openCur = false;
2893370b324cSopenharmony_ci
2894370b324cSopenharmony_ci          bool thereIsTail = ErrorInfo.ThereIsTail;
2895370b324cSopenharmony_ci          if (thereIsTail && mode.ZerosTailIsAllowed)
2896370b324cSopenharmony_ci          {
2897370b324cSopenharmony_ci            RINOK(CheckZerosTail(op, (UInt64)((Int64)arcStreamOffset + Offset + (Int64)PhySize)))
2898370b324cSopenharmony_ci            if (ErrorInfo.IgnoreTail)
2899370b324cSopenharmony_ci              thereIsTail = false;
2900370b324cSopenharmony_ci          }
2901370b324cSopenharmony_ci
2902370b324cSopenharmony_ci          if (pi.Offset != 0)
2903370b324cSopenharmony_ci          {
2904370b324cSopenharmony_ci            if (!pi.IsNotArcType)
2905370b324cSopenharmony_ci            {
2906370b324cSopenharmony_ci              if (thereIsTail)
2907370b324cSopenharmony_ci                openCur = specFlags.CanReturnMid;
2908370b324cSopenharmony_ci              else
2909370b324cSopenharmony_ci                openCur = specFlags.CanReturnTail;
2910370b324cSopenharmony_ci            }
2911370b324cSopenharmony_ci          }
2912370b324cSopenharmony_ci          else
2913370b324cSopenharmony_ci          {
2914370b324cSopenharmony_ci            if (!thereIsTail)
2915370b324cSopenharmony_ci              openCur = true;
2916370b324cSopenharmony_ci            else
2917370b324cSopenharmony_ci              openCur = specFlags.CanReturnFrontal;
2918370b324cSopenharmony_ci
2919370b324cSopenharmony_ci            if (formatIndex >= -2)
2920370b324cSopenharmony_ci              openCur = true;
2921370b324cSopenharmony_ci          }
2922370b324cSopenharmony_ci
2923370b324cSopenharmony_ci          if (formatIndex < 0 && pi.IsSelfExe /* && mode.SkipSfxStub */)
2924370b324cSopenharmony_ci            openCur = false;
2925370b324cSopenharmony_ci
2926370b324cSopenharmony_ci          // We open file as SFX, if there is front archive or first archive is "Self Executable"
2927370b324cSopenharmony_ci          if (!openCur && !pi.IsSelfExe && !thereIsTail &&
2928370b324cSopenharmony_ci              (!pi.IsNotArcType || pi.Offset == 0))
2929370b324cSopenharmony_ci          {
2930370b324cSopenharmony_ci            if (handlerSpec->_items.IsEmpty())
2931370b324cSopenharmony_ci            {
2932370b324cSopenharmony_ci              if (specFlags.CanReturnTail)
2933370b324cSopenharmony_ci                openCur = true;
2934370b324cSopenharmony_ci            }
2935370b324cSopenharmony_ci            else if (handlerSpec->_items.Size() == 1)
2936370b324cSopenharmony_ci            {
2937370b324cSopenharmony_ci              if (handlerSpec->_items[0].IsSelfExe)
2938370b324cSopenharmony_ci              {
2939370b324cSopenharmony_ci                if (mode.SpecUnknownExt.CanReturnTail)
2940370b324cSopenharmony_ci                  openCur = true;
2941370b324cSopenharmony_ci              }
2942370b324cSopenharmony_ci            }
2943370b324cSopenharmony_ci          }
2944370b324cSopenharmony_ci
2945370b324cSopenharmony_ci          if (openCur)
2946370b324cSopenharmony_ci          {
2947370b324cSopenharmony_ci            InStream = op.stream;
2948370b324cSopenharmony_ci            Archive = archive;
2949370b324cSopenharmony_ci            FormatIndex = (int)index;
2950370b324cSopenharmony_ci            ArcStreamOffset = arcStreamOffset;
2951370b324cSopenharmony_ci            return S_OK;
2952370b324cSopenharmony_ci          }
2953370b324cSopenharmony_ci        }
2954370b324cSopenharmony_ci
2955370b324cSopenharmony_ci        /*
2956370b324cSopenharmony_ci        if (openOnlyFullArc)
2957370b324cSopenharmony_ci        {
2958370b324cSopenharmony_ci          ErrorInfo.ClearErrors();
2959370b324cSopenharmony_ci          return S_FALSE;
2960370b324cSopenharmony_ci        }
2961370b324cSopenharmony_ci        */
2962370b324cSopenharmony_ci
2963370b324cSopenharmony_ci        pi.FormatIndex = (int)index;
2964370b324cSopenharmony_ci
2965370b324cSopenharmony_ci        // printf("\nAdd offset = %d", (int)pi.Offset);
2966370b324cSopenharmony_ci        handlerSpec->AddItem(pi);
2967370b324cSopenharmony_ci        wasOpen = true;
2968370b324cSopenharmony_ci        break;
2969370b324cSopenharmony_ci      }
2970370b324cSopenharmony_ci      // ---------- End of Open Loop for Current Pos ----------
2971370b324cSopenharmony_ci
2972370b324cSopenharmony_ci      if (!wasOpen)
2973370b324cSopenharmony_ci        pos++;
2974370b324cSopenharmony_ci      needCheckStartOpen = (nextNeedCheckStartOpen && wasOpen);
2975370b324cSopenharmony_ci    }
2976370b324cSopenharmony_ci    // ---------- End of Main Scan Loop ----------
2977370b324cSopenharmony_ci
2978370b324cSopenharmony_ci    /*
2979370b324cSopenharmony_ci    if (handlerSpec->_items.Size() == 1)
2980370b324cSopenharmony_ci    {
2981370b324cSopenharmony_ci      const NArchive::NParser::CParseItem &pi = handlerSpec->_items[0];
2982370b324cSopenharmony_ci      if (pi.Size == fileSize && pi.Offset == 0)
2983370b324cSopenharmony_ci      {
2984370b324cSopenharmony_ci        Archive = archive;
2985370b324cSopenharmony_ci        FormatIndex2 = pi.FormatIndex;
2986370b324cSopenharmony_ci        return S_OK;
2987370b324cSopenharmony_ci      }
2988370b324cSopenharmony_ci    }
2989370b324cSopenharmony_ci    */
2990370b324cSopenharmony_ci
2991370b324cSopenharmony_ci    if (mode.CanReturnParser)
2992370b324cSopenharmony_ci    {
2993370b324cSopenharmony_ci      bool returnParser = (handlerSpec->_items.Size() == 1); // it's possible if fileSize was not correct at start of parsing
2994370b324cSopenharmony_ci      handlerSpec->AddUnknownItem(fileSize);
2995370b324cSopenharmony_ci      if (handlerSpec->_items.Size() == 0)
2996370b324cSopenharmony_ci        return S_FALSE;
2997370b324cSopenharmony_ci      if (returnParser || handlerSpec->_items.Size() != 1)
2998370b324cSopenharmony_ci      {
2999370b324cSopenharmony_ci        // return S_FALSE;
3000370b324cSopenharmony_ci        handlerSpec->_stream = op.stream;
3001370b324cSopenharmony_ci        Archive = handler;
3002370b324cSopenharmony_ci        ErrorInfo.ClearErrors();
3003370b324cSopenharmony_ci        IsParseArc = true;
3004370b324cSopenharmony_ci        FormatIndex = -1; // It's parser
3005370b324cSopenharmony_ci        Offset = 0;
3006370b324cSopenharmony_ci        return S_OK;
3007370b324cSopenharmony_ci      }
3008370b324cSopenharmony_ci    }
3009370b324cSopenharmony_ci  }
3010370b324cSopenharmony_ci
3011370b324cSopenharmony_ci  #endif
3012370b324cSopenharmony_ci
3013370b324cSopenharmony_ci  if (!Archive)
3014370b324cSopenharmony_ci    return S_FALSE;
3015370b324cSopenharmony_ci  return S_OK;
3016370b324cSopenharmony_ci}
3017370b324cSopenharmony_ci
3018370b324cSopenharmony_ci
3019370b324cSopenharmony_ci
3020370b324cSopenharmony_ci
3021370b324cSopenharmony_ciHRESULT CArc::OpenStream(const COpenOptions &op)
3022370b324cSopenharmony_ci{
3023370b324cSopenharmony_ci  RINOK(OpenStream2(op))
3024370b324cSopenharmony_ci  // PrintNumber("op.formatIndex 3", op.formatIndex);
3025370b324cSopenharmony_ci
3026370b324cSopenharmony_ci  if (Archive)
3027370b324cSopenharmony_ci  {
3028370b324cSopenharmony_ci    GetRawProps.Release();
3029370b324cSopenharmony_ci    GetRootProps.Release();
3030370b324cSopenharmony_ci    Archive->QueryInterface(IID_IArchiveGetRawProps, (void **)&GetRawProps);
3031370b324cSopenharmony_ci    Archive->QueryInterface(IID_IArchiveGetRootProps, (void **)&GetRootProps);
3032370b324cSopenharmony_ci
3033370b324cSopenharmony_ci    RINOK(Archive_GetArcProp_Bool(Archive, kpidIsTree, IsTree))
3034370b324cSopenharmony_ci    RINOK(Archive_GetArcProp_Bool(Archive, kpidIsDeleted, Ask_Deleted))
3035370b324cSopenharmony_ci    RINOK(Archive_GetArcProp_Bool(Archive, kpidIsAltStream, Ask_AltStream))
3036370b324cSopenharmony_ci    RINOK(Archive_GetArcProp_Bool(Archive, kpidIsAux, Ask_Aux))
3037370b324cSopenharmony_ci    RINOK(Archive_GetArcProp_Bool(Archive, kpidINode, Ask_INode))
3038370b324cSopenharmony_ci    RINOK(Archive_GetArcProp_Bool(Archive, kpidReadOnly, IsReadOnly))
3039370b324cSopenharmony_ci
3040370b324cSopenharmony_ci    const UString fileName = ExtractFileNameFromPath(Path);
3041370b324cSopenharmony_ci    UString extension;
3042370b324cSopenharmony_ci    {
3043370b324cSopenharmony_ci      int dotPos = fileName.ReverseFind_Dot();
3044370b324cSopenharmony_ci      if (dotPos >= 0)
3045370b324cSopenharmony_ci        extension = fileName.Ptr((unsigned)(dotPos + 1));
3046370b324cSopenharmony_ci    }
3047370b324cSopenharmony_ci
3048370b324cSopenharmony_ci    DefaultName.Empty();
3049370b324cSopenharmony_ci    if (FormatIndex >= 0)
3050370b324cSopenharmony_ci    {
3051370b324cSopenharmony_ci      const CArcInfoEx &ai = op.codecs->Formats[(unsigned)FormatIndex];
3052370b324cSopenharmony_ci      if (ai.Exts.Size() == 0)
3053370b324cSopenharmony_ci        DefaultName = GetDefaultName2(fileName, UString(), UString());
3054370b324cSopenharmony_ci      else
3055370b324cSopenharmony_ci      {
3056370b324cSopenharmony_ci        int subExtIndex = ai.FindExtension(extension);
3057370b324cSopenharmony_ci        if (subExtIndex < 0)
3058370b324cSopenharmony_ci          subExtIndex = 0;
3059370b324cSopenharmony_ci        const CArcExtInfo &extInfo = ai.Exts[(unsigned)subExtIndex];
3060370b324cSopenharmony_ci        DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt);
3061370b324cSopenharmony_ci      }
3062370b324cSopenharmony_ci    }
3063370b324cSopenharmony_ci  }
3064370b324cSopenharmony_ci
3065370b324cSopenharmony_ci  return S_OK;
3066370b324cSopenharmony_ci}
3067370b324cSopenharmony_ci
3068370b324cSopenharmony_ci#ifdef Z7_SFX
3069370b324cSopenharmony_ci
3070370b324cSopenharmony_ci#ifdef _WIN32
3071370b324cSopenharmony_ci  #define k_ExeExt ".exe"
3072370b324cSopenharmony_ci  static const unsigned k_ExeExt_Len = 4;
3073370b324cSopenharmony_ci#else
3074370b324cSopenharmony_ci  #define k_ExeExt ""
3075370b324cSopenharmony_ci  static const unsigned k_ExeExt_Len = 0;
3076370b324cSopenharmony_ci#endif
3077370b324cSopenharmony_ci
3078370b324cSopenharmony_ci#endif
3079370b324cSopenharmony_ci
3080370b324cSopenharmony_ciHRESULT CArc::OpenStreamOrFile(COpenOptions &op)
3081370b324cSopenharmony_ci{
3082370b324cSopenharmony_ci  CMyComPtr<IInStream> fileStream;
3083370b324cSopenharmony_ci  CMyComPtr<ISequentialInStream> seqStream;
3084370b324cSopenharmony_ci  CInFileStream *fileStreamSpec = NULL;
3085370b324cSopenharmony_ci
3086370b324cSopenharmony_ci  if (op.stdInMode)
3087370b324cSopenharmony_ci  {
3088370b324cSopenharmony_ci    seqStream = new CStdInFileStream;
3089370b324cSopenharmony_ci    op.seqStream = seqStream;
3090370b324cSopenharmony_ci  }
3091370b324cSopenharmony_ci  else if (!op.stream)
3092370b324cSopenharmony_ci  {
3093370b324cSopenharmony_ci    fileStreamSpec = new CInFileStream;
3094370b324cSopenharmony_ci    fileStream = fileStreamSpec;
3095370b324cSopenharmony_ci    Path = filePath;
3096370b324cSopenharmony_ci    if (!fileStreamSpec->Open(us2fs(Path)))
3097370b324cSopenharmony_ci      return GetLastError_noZero_HRESULT();
3098370b324cSopenharmony_ci    op.stream = fileStream;
3099370b324cSopenharmony_ci    #ifdef Z7_SFX
3100370b324cSopenharmony_ci    IgnoreSplit = true;
3101370b324cSopenharmony_ci    #endif
3102370b324cSopenharmony_ci  }
3103370b324cSopenharmony_ci
3104370b324cSopenharmony_ci  /*
3105370b324cSopenharmony_ci  if (callback)
3106370b324cSopenharmony_ci  {
3107370b324cSopenharmony_ci    UInt64 fileSize;
3108370b324cSopenharmony_ci    RINOK(InStream_GetSize_SeekToEnd(op.stream, fileSize));
3109370b324cSopenharmony_ci    RINOK(op.callback->SetTotal(NULL, &fileSize))
3110370b324cSopenharmony_ci  }
3111370b324cSopenharmony_ci  */
3112370b324cSopenharmony_ci
3113370b324cSopenharmony_ci  HRESULT res = OpenStream(op);
3114370b324cSopenharmony_ci  IgnoreSplit = false;
3115370b324cSopenharmony_ci
3116370b324cSopenharmony_ci  #ifdef Z7_SFX
3117370b324cSopenharmony_ci
3118370b324cSopenharmony_ci  if (res != S_FALSE
3119370b324cSopenharmony_ci      || !fileStreamSpec
3120370b324cSopenharmony_ci      || !op.callbackSpec
3121370b324cSopenharmony_ci      || NonOpen_ErrorInfo.IsArc_After_NonOpen())
3122370b324cSopenharmony_ci    return res;
3123370b324cSopenharmony_ci
3124370b324cSopenharmony_ci  {
3125370b324cSopenharmony_ci    if (filePath.Len() > k_ExeExt_Len
3126370b324cSopenharmony_ci        && StringsAreEqualNoCase_Ascii(filePath.RightPtr(k_ExeExt_Len), k_ExeExt))
3127370b324cSopenharmony_ci    {
3128370b324cSopenharmony_ci      const UString path2 = filePath.Left(filePath.Len() - k_ExeExt_Len);
3129370b324cSopenharmony_ci      FOR_VECTOR (i, op.codecs->Formats)
3130370b324cSopenharmony_ci      {
3131370b324cSopenharmony_ci        const CArcInfoEx &ai = op.codecs->Formats[i];
3132370b324cSopenharmony_ci        if (ai.Is_Split())
3133370b324cSopenharmony_ci          continue;
3134370b324cSopenharmony_ci        UString path3 = path2;
3135370b324cSopenharmony_ci        path3.Add_Dot();
3136370b324cSopenharmony_ci        path3 += ai.GetMainExt(); // "7z"  for SFX.
3137370b324cSopenharmony_ci        Path = path3;
3138370b324cSopenharmony_ci        Path += ".001";
3139370b324cSopenharmony_ci        bool isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path));
3140370b324cSopenharmony_ci        if (!isOk)
3141370b324cSopenharmony_ci        {
3142370b324cSopenharmony_ci          Path = path3;
3143370b324cSopenharmony_ci          isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path));
3144370b324cSopenharmony_ci        }
3145370b324cSopenharmony_ci        if (isOk)
3146370b324cSopenharmony_ci        {
3147370b324cSopenharmony_ci          if (fileStreamSpec->Open(us2fs(Path)))
3148370b324cSopenharmony_ci          {
3149370b324cSopenharmony_ci            op.stream = fileStream;
3150370b324cSopenharmony_ci            NonOpen_ErrorInfo.ClearErrors_Full();
3151370b324cSopenharmony_ci            if (OpenStream(op) == S_OK)
3152370b324cSopenharmony_ci              return S_OK;
3153370b324cSopenharmony_ci          }
3154370b324cSopenharmony_ci        }
3155370b324cSopenharmony_ci      }
3156370b324cSopenharmony_ci    }
3157370b324cSopenharmony_ci  }
3158370b324cSopenharmony_ci
3159370b324cSopenharmony_ci  #endif
3160370b324cSopenharmony_ci
3161370b324cSopenharmony_ci  return res;
3162370b324cSopenharmony_ci}
3163370b324cSopenharmony_ci
3164370b324cSopenharmony_civoid CArchiveLink::KeepModeForNextOpen()
3165370b324cSopenharmony_ci{
3166370b324cSopenharmony_ci  for (unsigned i = Arcs.Size(); i != 0;)
3167370b324cSopenharmony_ci  {
3168370b324cSopenharmony_ci    i--;
3169370b324cSopenharmony_ci    CMyComPtr<IArchiveKeepModeForNextOpen> keep;
3170370b324cSopenharmony_ci    Arcs[i].Archive->QueryInterface(IID_IArchiveKeepModeForNextOpen, (void **)&keep);
3171370b324cSopenharmony_ci    if (keep)
3172370b324cSopenharmony_ci      keep->KeepModeForNextOpen();
3173370b324cSopenharmony_ci  }
3174370b324cSopenharmony_ci}
3175370b324cSopenharmony_ci
3176370b324cSopenharmony_ciHRESULT CArchiveLink::Close()
3177370b324cSopenharmony_ci{
3178370b324cSopenharmony_ci  for (unsigned i = Arcs.Size(); i != 0;)
3179370b324cSopenharmony_ci  {
3180370b324cSopenharmony_ci    i--;
3181370b324cSopenharmony_ci    RINOK(Arcs[i].Close())
3182370b324cSopenharmony_ci  }
3183370b324cSopenharmony_ci  IsOpen = false;
3184370b324cSopenharmony_ci  // ErrorsText.Empty();
3185370b324cSopenharmony_ci  return S_OK;
3186370b324cSopenharmony_ci}
3187370b324cSopenharmony_ci
3188370b324cSopenharmony_civoid CArchiveLink::Release()
3189370b324cSopenharmony_ci{
3190370b324cSopenharmony_ci  // NonOpenErrorFormatIndex = -1;
3191370b324cSopenharmony_ci  NonOpen_ErrorInfo.ClearErrors();
3192370b324cSopenharmony_ci  NonOpen_ArcPath.Empty();
3193370b324cSopenharmony_ci  while (!Arcs.IsEmpty())
3194370b324cSopenharmony_ci    Arcs.DeleteBack();
3195370b324cSopenharmony_ci}
3196370b324cSopenharmony_ci
3197370b324cSopenharmony_ci/*
3198370b324cSopenharmony_civoid CArchiveLink::Set_ErrorsText()
3199370b324cSopenharmony_ci{
3200370b324cSopenharmony_ci  FOR_VECTOR(i, Arcs)
3201370b324cSopenharmony_ci  {
3202370b324cSopenharmony_ci    const CArc &arc = Arcs[i];
3203370b324cSopenharmony_ci    if (!arc.ErrorFlagsText.IsEmpty())
3204370b324cSopenharmony_ci    {
3205370b324cSopenharmony_ci      if (!ErrorsText.IsEmpty())
3206370b324cSopenharmony_ci        ErrorsText.Add_LF();
3207370b324cSopenharmony_ci      ErrorsText += GetUnicodeString(arc.ErrorFlagsText);
3208370b324cSopenharmony_ci    }
3209370b324cSopenharmony_ci    if (!arc.ErrorMessage.IsEmpty())
3210370b324cSopenharmony_ci    {
3211370b324cSopenharmony_ci      if (!ErrorsText.IsEmpty())
3212370b324cSopenharmony_ci        ErrorsText.Add_LF();
3213370b324cSopenharmony_ci      ErrorsText += arc.ErrorMessage;
3214370b324cSopenharmony_ci    }
3215370b324cSopenharmony_ci
3216370b324cSopenharmony_ci    if (!arc.WarningMessage.IsEmpty())
3217370b324cSopenharmony_ci    {
3218370b324cSopenharmony_ci      if (!ErrorsText.IsEmpty())
3219370b324cSopenharmony_ci        ErrorsText.Add_LF();
3220370b324cSopenharmony_ci      ErrorsText += arc.WarningMessage;
3221370b324cSopenharmony_ci    }
3222370b324cSopenharmony_ci  }
3223370b324cSopenharmony_ci}
3224370b324cSopenharmony_ci*/
3225370b324cSopenharmony_ci
3226370b324cSopenharmony_ciHRESULT CArchiveLink::Open(COpenOptions &op)
3227370b324cSopenharmony_ci{
3228370b324cSopenharmony_ci  Release();
3229370b324cSopenharmony_ci  if (op.types->Size() >= 32)
3230370b324cSopenharmony_ci    return E_NOTIMPL;
3231370b324cSopenharmony_ci
3232370b324cSopenharmony_ci  HRESULT resSpec;
3233370b324cSopenharmony_ci
3234370b324cSopenharmony_ci  for (;;)
3235370b324cSopenharmony_ci  {
3236370b324cSopenharmony_ci    resSpec = S_OK;
3237370b324cSopenharmony_ci
3238370b324cSopenharmony_ci    op.openType = COpenType();
3239370b324cSopenharmony_ci    if (op.types->Size() >= 1)
3240370b324cSopenharmony_ci    {
3241370b324cSopenharmony_ci      COpenType latest;
3242370b324cSopenharmony_ci      if (Arcs.Size() < op.types->Size())
3243370b324cSopenharmony_ci        latest = (*op.types)[op.types->Size() - Arcs.Size() - 1];
3244370b324cSopenharmony_ci      else
3245370b324cSopenharmony_ci      {
3246370b324cSopenharmony_ci        latest = (*op.types)[0];
3247370b324cSopenharmony_ci        if (!latest.Recursive)
3248370b324cSopenharmony_ci          break;
3249370b324cSopenharmony_ci      }
3250370b324cSopenharmony_ci      op.openType = latest;
3251370b324cSopenharmony_ci    }
3252370b324cSopenharmony_ci    else if (Arcs.Size() >= 32)
3253370b324cSopenharmony_ci      break;
3254370b324cSopenharmony_ci
3255370b324cSopenharmony_ci    /*
3256370b324cSopenharmony_ci    op.formatIndex = -1;
3257370b324cSopenharmony_ci    if (op.types->Size() >= 1)
3258370b324cSopenharmony_ci    {
3259370b324cSopenharmony_ci      int latest;
3260370b324cSopenharmony_ci      if (Arcs.Size() < op.types->Size())
3261370b324cSopenharmony_ci        latest = (*op.types)[op.types->Size() - Arcs.Size() - 1];
3262370b324cSopenharmony_ci      else
3263370b324cSopenharmony_ci      {
3264370b324cSopenharmony_ci        latest = (*op.types)[0];
3265370b324cSopenharmony_ci        if (latest != -2 && latest != -3)
3266370b324cSopenharmony_ci          break;
3267370b324cSopenharmony_ci      }
3268370b324cSopenharmony_ci      if (latest >= 0)
3269370b324cSopenharmony_ci        op.formatIndex = latest;
3270370b324cSopenharmony_ci      else if (latest == -1 || latest == -2)
3271370b324cSopenharmony_ci      {
3272370b324cSopenharmony_ci        // default
3273370b324cSopenharmony_ci      }
3274370b324cSopenharmony_ci      else if (latest == -3)
3275370b324cSopenharmony_ci        op.formatIndex = -2;
3276370b324cSopenharmony_ci      else
3277370b324cSopenharmony_ci        op.formatIndex = latest + 2;
3278370b324cSopenharmony_ci    }
3279370b324cSopenharmony_ci    else if (Arcs.Size() >= 32)
3280370b324cSopenharmony_ci      break;
3281370b324cSopenharmony_ci    */
3282370b324cSopenharmony_ci
3283370b324cSopenharmony_ci    if (Arcs.IsEmpty())
3284370b324cSopenharmony_ci    {
3285370b324cSopenharmony_ci      CArc arc;
3286370b324cSopenharmony_ci      arc.filePath = op.filePath;
3287370b324cSopenharmony_ci      arc.Path = op.filePath;
3288370b324cSopenharmony_ci      arc.SubfileIndex = (UInt32)(Int32)-1;
3289370b324cSopenharmony_ci      HRESULT result = arc.OpenStreamOrFile(op);
3290370b324cSopenharmony_ci      if (result != S_OK)
3291370b324cSopenharmony_ci      {
3292370b324cSopenharmony_ci        if (result == S_FALSE)
3293370b324cSopenharmony_ci        {
3294370b324cSopenharmony_ci          NonOpen_ErrorInfo = arc.NonOpen_ErrorInfo;
3295370b324cSopenharmony_ci          // NonOpenErrorFormatIndex = arc.ErrorFormatIndex;
3296370b324cSopenharmony_ci          NonOpen_ArcPath = arc.Path;
3297370b324cSopenharmony_ci        }
3298370b324cSopenharmony_ci        return result;
3299370b324cSopenharmony_ci      }
3300370b324cSopenharmony_ci      Arcs.Add(arc);
3301370b324cSopenharmony_ci      continue;
3302370b324cSopenharmony_ci    }
3303370b324cSopenharmony_ci
3304370b324cSopenharmony_ci    // PrintNumber("op.formatIndex 11", op.formatIndex);
3305370b324cSopenharmony_ci
3306370b324cSopenharmony_ci    const CArc &arc = Arcs.Back();
3307370b324cSopenharmony_ci
3308370b324cSopenharmony_ci    if (op.types->Size() > Arcs.Size())
3309370b324cSopenharmony_ci      resSpec = E_NOTIMPL;
3310370b324cSopenharmony_ci
3311370b324cSopenharmony_ci    UInt32 mainSubfile;
3312370b324cSopenharmony_ci    {
3313370b324cSopenharmony_ci      NCOM::CPropVariant prop;
3314370b324cSopenharmony_ci      RINOK(arc.Archive->GetArchiveProperty(kpidMainSubfile, &prop))
3315370b324cSopenharmony_ci      if (prop.vt == VT_UI4)
3316370b324cSopenharmony_ci        mainSubfile = prop.ulVal;
3317370b324cSopenharmony_ci      else
3318370b324cSopenharmony_ci        break;
3319370b324cSopenharmony_ci      UInt32 numItems;
3320370b324cSopenharmony_ci      RINOK(arc.Archive->GetNumberOfItems(&numItems))
3321370b324cSopenharmony_ci      if (mainSubfile >= numItems)
3322370b324cSopenharmony_ci        break;
3323370b324cSopenharmony_ci    }
3324370b324cSopenharmony_ci
3325370b324cSopenharmony_ci
3326370b324cSopenharmony_ci    CMyComPtr<IInArchiveGetStream> getStream;
3327370b324cSopenharmony_ci    if (arc.Archive->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream) != S_OK || !getStream)
3328370b324cSopenharmony_ci      break;
3329370b324cSopenharmony_ci
3330370b324cSopenharmony_ci    CMyComPtr<ISequentialInStream> subSeqStream;
3331370b324cSopenharmony_ci    if (getStream->GetStream(mainSubfile, &subSeqStream) != S_OK || !subSeqStream)
3332370b324cSopenharmony_ci      break;
3333370b324cSopenharmony_ci
3334370b324cSopenharmony_ci    CMyComPtr<IInStream> subStream;
3335370b324cSopenharmony_ci    if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK || !subStream)
3336370b324cSopenharmony_ci      break;
3337370b324cSopenharmony_ci
3338370b324cSopenharmony_ci    CArc arc2;
3339370b324cSopenharmony_ci    RINOK(arc.GetItem_Path(mainSubfile, arc2.Path))
3340370b324cSopenharmony_ci
3341370b324cSopenharmony_ci    bool zerosTailIsAllowed;
3342370b324cSopenharmony_ci    RINOK(Archive_GetItemBoolProp(arc.Archive, mainSubfile, kpidZerosTailIsAllowed, zerosTailIsAllowed))
3343370b324cSopenharmony_ci
3344370b324cSopenharmony_ci
3345370b324cSopenharmony_ci    if (op.callback)
3346370b324cSopenharmony_ci    {
3347370b324cSopenharmony_ci      Z7_DECL_CMyComPtr_QI_FROM(
3348370b324cSopenharmony_ci          IArchiveOpenSetSubArchiveName,
3349370b324cSopenharmony_ci          setSubArchiveName, op.callback)
3350370b324cSopenharmony_ci      if (setSubArchiveName)
3351370b324cSopenharmony_ci        setSubArchiveName->SetSubArchiveName(arc2.Path);
3352370b324cSopenharmony_ci    }
3353370b324cSopenharmony_ci
3354370b324cSopenharmony_ci    arc2.SubfileIndex = mainSubfile;
3355370b324cSopenharmony_ci
3356370b324cSopenharmony_ci    // CIntVector incl;
3357370b324cSopenharmony_ci    CIntVector excl;
3358370b324cSopenharmony_ci
3359370b324cSopenharmony_ci    COpenOptions op2;
3360370b324cSopenharmony_ci    #ifndef Z7_SFX
3361370b324cSopenharmony_ci    op2.props = op.props;
3362370b324cSopenharmony_ci    #endif
3363370b324cSopenharmony_ci    op2.codecs = op.codecs;
3364370b324cSopenharmony_ci    // op2.types = &incl;
3365370b324cSopenharmony_ci    op2.openType = op.openType;
3366370b324cSopenharmony_ci    op2.openType.ZerosTailIsAllowed = zerosTailIsAllowed;
3367370b324cSopenharmony_ci    op2.excludedFormats = &excl;
3368370b324cSopenharmony_ci    op2.stdInMode = false;
3369370b324cSopenharmony_ci    op2.stream = subStream;
3370370b324cSopenharmony_ci    op2.filePath = arc2.Path;
3371370b324cSopenharmony_ci    op2.callback = op.callback;
3372370b324cSopenharmony_ci    op2.callbackSpec = op.callbackSpec;
3373370b324cSopenharmony_ci
3374370b324cSopenharmony_ci
3375370b324cSopenharmony_ci    HRESULT result = arc2.OpenStream(op2);
3376370b324cSopenharmony_ci    resSpec = (op.types->Size() == 0 ? S_OK : S_FALSE);
3377370b324cSopenharmony_ci    if (result == S_FALSE)
3378370b324cSopenharmony_ci    {
3379370b324cSopenharmony_ci      NonOpen_ErrorInfo = arc2.ErrorInfo;
3380370b324cSopenharmony_ci      NonOpen_ArcPath = arc2.Path;
3381370b324cSopenharmony_ci      break;
3382370b324cSopenharmony_ci    }
3383370b324cSopenharmony_ci    RINOK(result)
3384370b324cSopenharmony_ci    RINOK(arc.GetItem_MTime(mainSubfile, arc2.MTime))
3385370b324cSopenharmony_ci    Arcs.Add(arc2);
3386370b324cSopenharmony_ci  }
3387370b324cSopenharmony_ci  IsOpen = !Arcs.IsEmpty();
3388370b324cSopenharmony_ci  return resSpec;
3389370b324cSopenharmony_ci}
3390370b324cSopenharmony_ci
3391370b324cSopenharmony_ciHRESULT CArchiveLink::Open2(COpenOptions &op, IOpenCallbackUI *callbackUI)
3392370b324cSopenharmony_ci{
3393370b324cSopenharmony_ci  VolumesSize = 0;
3394370b324cSopenharmony_ci  COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;
3395370b324cSopenharmony_ci  CMyComPtr<IArchiveOpenCallback> callback = openCallbackSpec;
3396370b324cSopenharmony_ci  openCallbackSpec->Callback = callbackUI;
3397370b324cSopenharmony_ci
3398370b324cSopenharmony_ci  FString prefix, name;
3399370b324cSopenharmony_ci
3400370b324cSopenharmony_ci  if (!op.stream && !op.stdInMode)
3401370b324cSopenharmony_ci  {
3402370b324cSopenharmony_ci    NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), prefix, name);
3403370b324cSopenharmony_ci    RINOK(openCallbackSpec->Init2(prefix, name))
3404370b324cSopenharmony_ci  }
3405370b324cSopenharmony_ci  else
3406370b324cSopenharmony_ci  {
3407370b324cSopenharmony_ci    openCallbackSpec->SetSubArchiveName(op.filePath);
3408370b324cSopenharmony_ci  }
3409370b324cSopenharmony_ci
3410370b324cSopenharmony_ci  op.callback = callback;
3411370b324cSopenharmony_ci  op.callbackSpec = openCallbackSpec;
3412370b324cSopenharmony_ci
3413370b324cSopenharmony_ci  HRESULT res = Open(op);
3414370b324cSopenharmony_ci
3415370b324cSopenharmony_ci  PasswordWasAsked = openCallbackSpec->PasswordWasAsked;
3416370b324cSopenharmony_ci  // Password = openCallbackSpec->Password;
3417370b324cSopenharmony_ci
3418370b324cSopenharmony_ci  RINOK(res)
3419370b324cSopenharmony_ci  // VolumePaths.Add(fs2us(prefix + name));
3420370b324cSopenharmony_ci
3421370b324cSopenharmony_ci  FOR_VECTOR (i, openCallbackSpec->FileNames_WasUsed)
3422370b324cSopenharmony_ci  {
3423370b324cSopenharmony_ci    if (openCallbackSpec->FileNames_WasUsed[i])
3424370b324cSopenharmony_ci    {
3425370b324cSopenharmony_ci      VolumePaths.Add(fs2us(prefix) + openCallbackSpec->FileNames[i]);
3426370b324cSopenharmony_ci      VolumesSize += openCallbackSpec->FileSizes[i];
3427370b324cSopenharmony_ci    }
3428370b324cSopenharmony_ci  }
3429370b324cSopenharmony_ci  // VolumesSize = openCallbackSpec->TotalSize;
3430370b324cSopenharmony_ci  return S_OK;
3431370b324cSopenharmony_ci}
3432370b324cSopenharmony_ci
3433370b324cSopenharmony_ciHRESULT CArc::ReOpen(const COpenOptions &op, IArchiveOpenCallback *openCallback_Additional)
3434370b324cSopenharmony_ci{
3435370b324cSopenharmony_ci  ErrorInfo.ClearErrors();
3436370b324cSopenharmony_ci  ErrorInfo.ErrorFormatIndex = -1;
3437370b324cSopenharmony_ci
3438370b324cSopenharmony_ci  UInt64 fileSize = 0;
3439370b324cSopenharmony_ci  if (op.stream)
3440370b324cSopenharmony_ci  {
3441370b324cSopenharmony_ci    RINOK(InStream_SeekToBegin(op.stream))
3442370b324cSopenharmony_ci    RINOK(InStream_AtBegin_GetSize(op.stream, fileSize))
3443370b324cSopenharmony_ci    // RINOK(InStream_GetSize_SeekToBegin(op.stream, fileSize))
3444370b324cSopenharmony_ci  }
3445370b324cSopenharmony_ci  FileSize = fileSize;
3446370b324cSopenharmony_ci
3447370b324cSopenharmony_ci  CMyComPtr<IInStream> stream2;
3448370b324cSopenharmony_ci  Int64 globalOffset = GetGlobalOffset();
3449370b324cSopenharmony_ci  if (globalOffset <= 0)
3450370b324cSopenharmony_ci    stream2 = op.stream;
3451370b324cSopenharmony_ci  else
3452370b324cSopenharmony_ci  {
3453370b324cSopenharmony_ci    CTailInStream *tailStreamSpec = new CTailInStream;
3454370b324cSopenharmony_ci    stream2 = tailStreamSpec;
3455370b324cSopenharmony_ci    tailStreamSpec->Stream = op.stream;
3456370b324cSopenharmony_ci    tailStreamSpec->Offset = (UInt64)globalOffset;
3457370b324cSopenharmony_ci    tailStreamSpec->Init();
3458370b324cSopenharmony_ci    RINOK(tailStreamSpec->SeekToStart())
3459370b324cSopenharmony_ci  }
3460370b324cSopenharmony_ci
3461370b324cSopenharmony_ci  // There are archives with embedded STUBs (like ZIP), so we must support signature scanning
3462370b324cSopenharmony_ci  // But for another archives we can use 0 here. So the code can be fixed !!!
3463370b324cSopenharmony_ci  UInt64 maxStartPosition = kMaxCheckStartPosition;
3464370b324cSopenharmony_ci  IArchiveOpenCallback *openCallback = openCallback_Additional;
3465370b324cSopenharmony_ci  if (!openCallback)
3466370b324cSopenharmony_ci    openCallback = op.callback;
3467370b324cSopenharmony_ci  HRESULT res = Archive->Open(stream2, &maxStartPosition, openCallback);
3468370b324cSopenharmony_ci
3469370b324cSopenharmony_ci  if (res == S_OK)
3470370b324cSopenharmony_ci  {
3471370b324cSopenharmony_ci    RINOK(ReadBasicProps(Archive, (UInt64)globalOffset, res))
3472370b324cSopenharmony_ci    ArcStreamOffset = (UInt64)globalOffset;
3473370b324cSopenharmony_ci    if (ArcStreamOffset != 0)
3474370b324cSopenharmony_ci      InStream = op.stream;
3475370b324cSopenharmony_ci  }
3476370b324cSopenharmony_ci  return res;
3477370b324cSopenharmony_ci}
3478370b324cSopenharmony_ci
3479370b324cSopenharmony_ciHRESULT CArchiveLink::Open3(COpenOptions &op, IOpenCallbackUI *callbackUI)
3480370b324cSopenharmony_ci{
3481370b324cSopenharmony_ci  HRESULT res = Open2(op, callbackUI);
3482370b324cSopenharmony_ci  if (callbackUI)
3483370b324cSopenharmony_ci  {
3484370b324cSopenharmony_ci    RINOK(callbackUI->Open_Finished())
3485370b324cSopenharmony_ci  }
3486370b324cSopenharmony_ci  return res;
3487370b324cSopenharmony_ci}
3488370b324cSopenharmony_ci
3489370b324cSopenharmony_ciHRESULT CArchiveLink::ReOpen(COpenOptions &op)
3490370b324cSopenharmony_ci{
3491370b324cSopenharmony_ci  if (Arcs.Size() > 1)
3492370b324cSopenharmony_ci    return E_NOTIMPL;
3493370b324cSopenharmony_ci
3494370b324cSopenharmony_ci  CObjectVector<COpenType> inc;
3495370b324cSopenharmony_ci  CIntVector excl;
3496370b324cSopenharmony_ci
3497370b324cSopenharmony_ci  op.types = &inc;
3498370b324cSopenharmony_ci  op.excludedFormats = &excl;
3499370b324cSopenharmony_ci  op.stdInMode = false;
3500370b324cSopenharmony_ci  op.stream = NULL;
3501370b324cSopenharmony_ci  if (Arcs.Size() == 0) // ???
3502370b324cSopenharmony_ci    return Open2(op, NULL);
3503370b324cSopenharmony_ci
3504370b324cSopenharmony_ci  /* if archive is multivolume (unsupported here still)
3505370b324cSopenharmony_ci     COpenCallbackImp object will exist after Open stage. */
3506370b324cSopenharmony_ci  COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;
3507370b324cSopenharmony_ci  CMyComPtr<IArchiveOpenCallback> openCallbackNew = openCallbackSpec;
3508370b324cSopenharmony_ci
3509370b324cSopenharmony_ci  openCallbackSpec->Callback = NULL;
3510370b324cSopenharmony_ci  openCallbackSpec->ReOpenCallback = op.callback;
3511370b324cSopenharmony_ci  {
3512370b324cSopenharmony_ci    FString dirPrefix, fileName;
3513370b324cSopenharmony_ci    NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), dirPrefix, fileName);
3514370b324cSopenharmony_ci    RINOK(openCallbackSpec->Init2(dirPrefix, fileName))
3515370b324cSopenharmony_ci  }
3516370b324cSopenharmony_ci
3517370b324cSopenharmony_ci
3518370b324cSopenharmony_ci  CInFileStream *fileStreamSpec = new CInFileStream;
3519370b324cSopenharmony_ci  CMyComPtr<IInStream> stream(fileStreamSpec);
3520370b324cSopenharmony_ci  if (!fileStreamSpec->Open(us2fs(op.filePath)))
3521370b324cSopenharmony_ci    return GetLastError_noZero_HRESULT();
3522370b324cSopenharmony_ci  op.stream = stream;
3523370b324cSopenharmony_ci
3524370b324cSopenharmony_ci  CArc &arc = Arcs[0];
3525370b324cSopenharmony_ci  const HRESULT res = arc.ReOpen(op, openCallbackNew);
3526370b324cSopenharmony_ci
3527370b324cSopenharmony_ci  openCallbackSpec->ReOpenCallback = NULL;
3528370b324cSopenharmony_ci
3529370b324cSopenharmony_ci  PasswordWasAsked = openCallbackSpec->PasswordWasAsked;
3530370b324cSopenharmony_ci  // Password = openCallbackSpec->Password;
3531370b324cSopenharmony_ci
3532370b324cSopenharmony_ci  IsOpen = (res == S_OK);
3533370b324cSopenharmony_ci  return res;
3534370b324cSopenharmony_ci}
3535370b324cSopenharmony_ci
3536370b324cSopenharmony_ci#ifndef Z7_SFX
3537370b324cSopenharmony_ci
3538370b324cSopenharmony_cibool ParseComplexSize(const wchar_t *s, UInt64 &result);
3539370b324cSopenharmony_cibool ParseComplexSize(const wchar_t *s, UInt64 &result)
3540370b324cSopenharmony_ci{
3541370b324cSopenharmony_ci  result = 0;
3542370b324cSopenharmony_ci  const wchar_t *end;
3543370b324cSopenharmony_ci  UInt64 number = ConvertStringToUInt64(s, &end);
3544370b324cSopenharmony_ci  if (end == s)
3545370b324cSopenharmony_ci    return false;
3546370b324cSopenharmony_ci  if (*end == 0)
3547370b324cSopenharmony_ci  {
3548370b324cSopenharmony_ci    result = number;
3549370b324cSopenharmony_ci    return true;
3550370b324cSopenharmony_ci  }
3551370b324cSopenharmony_ci  if (end[1] != 0)
3552370b324cSopenharmony_ci    return false;
3553370b324cSopenharmony_ci  unsigned numBits;
3554370b324cSopenharmony_ci  switch (MyCharLower_Ascii(*end))
3555370b324cSopenharmony_ci  {
3556370b324cSopenharmony_ci    case 'b': result = number; return true;
3557370b324cSopenharmony_ci    case 'k': numBits = 10; break;
3558370b324cSopenharmony_ci    case 'm': numBits = 20; break;
3559370b324cSopenharmony_ci    case 'g': numBits = 30; break;
3560370b324cSopenharmony_ci    case 't': numBits = 40; break;
3561370b324cSopenharmony_ci    default: return false;
3562370b324cSopenharmony_ci  }
3563370b324cSopenharmony_ci  if (number >= ((UInt64)1 << (64 - numBits)))
3564370b324cSopenharmony_ci    return false;
3565370b324cSopenharmony_ci  result = number << numBits;
3566370b324cSopenharmony_ci  return true;
3567370b324cSopenharmony_ci}
3568370b324cSopenharmony_ci
3569370b324cSopenharmony_cistatic bool ParseTypeParams(const UString &s, COpenType &type)
3570370b324cSopenharmony_ci{
3571370b324cSopenharmony_ci  if (s[0] == 0)
3572370b324cSopenharmony_ci    return true;
3573370b324cSopenharmony_ci  if (s[1] == 0)
3574370b324cSopenharmony_ci  {
3575370b324cSopenharmony_ci    switch ((unsigned)(Byte)s[0])
3576370b324cSopenharmony_ci    {
3577370b324cSopenharmony_ci      case 'e': type.EachPos = true; return true;
3578370b324cSopenharmony_ci      case 'a': type.CanReturnArc = true; return true;
3579370b324cSopenharmony_ci      case 'r': type.Recursive = true; return true;
3580370b324cSopenharmony_ci    }
3581370b324cSopenharmony_ci    return false;
3582370b324cSopenharmony_ci  }
3583370b324cSopenharmony_ci  if (s[0] == 's')
3584370b324cSopenharmony_ci  {
3585370b324cSopenharmony_ci    UInt64 result;
3586370b324cSopenharmony_ci    if (!ParseComplexSize(s.Ptr(1), result))
3587370b324cSopenharmony_ci      return false;
3588370b324cSopenharmony_ci    type.MaxStartOffset = result;
3589370b324cSopenharmony_ci    type.MaxStartOffset_Defined = true;
3590370b324cSopenharmony_ci    return true;
3591370b324cSopenharmony_ci  }
3592370b324cSopenharmony_ci
3593370b324cSopenharmony_ci  return false;
3594370b324cSopenharmony_ci}
3595370b324cSopenharmony_ci
3596370b324cSopenharmony_cistatic bool ParseType(CCodecs &codecs, const UString &s, COpenType &type)
3597370b324cSopenharmony_ci{
3598370b324cSopenharmony_ci  int pos2 = s.Find(L':');
3599370b324cSopenharmony_ci
3600370b324cSopenharmony_ci  {
3601370b324cSopenharmony_ci  UString name;
3602370b324cSopenharmony_ci  if (pos2 < 0)
3603370b324cSopenharmony_ci  {
3604370b324cSopenharmony_ci    name = s;
3605370b324cSopenharmony_ci    pos2 = (int)s.Len();
3606370b324cSopenharmony_ci  }
3607370b324cSopenharmony_ci  else
3608370b324cSopenharmony_ci  {
3609370b324cSopenharmony_ci    name = s.Left((unsigned)pos2);
3610370b324cSopenharmony_ci    pos2++;
3611370b324cSopenharmony_ci  }
3612370b324cSopenharmony_ci
3613370b324cSopenharmony_ci  int index = codecs.FindFormatForArchiveType(name);
3614370b324cSopenharmony_ci  type.Recursive = false;
3615370b324cSopenharmony_ci
3616370b324cSopenharmony_ci  if (index < 0)
3617370b324cSopenharmony_ci  {
3618370b324cSopenharmony_ci    if (name[0] == '*')
3619370b324cSopenharmony_ci    {
3620370b324cSopenharmony_ci      if (name[1] != 0)
3621370b324cSopenharmony_ci        return false;
3622370b324cSopenharmony_ci    }
3623370b324cSopenharmony_ci    else if (name[0] == '#')
3624370b324cSopenharmony_ci    {
3625370b324cSopenharmony_ci      if (name[1] != 0)
3626370b324cSopenharmony_ci        return false;
3627370b324cSopenharmony_ci      type.CanReturnArc = false;
3628370b324cSopenharmony_ci      type.CanReturnParser = true;
3629370b324cSopenharmony_ci    }
3630370b324cSopenharmony_ci    else if (name.IsEqualTo_Ascii_NoCase("hash"))
3631370b324cSopenharmony_ci    {
3632370b324cSopenharmony_ci      // type.CanReturnArc = false;
3633370b324cSopenharmony_ci      // type.CanReturnParser = false;
3634370b324cSopenharmony_ci      type.IsHashType = true;
3635370b324cSopenharmony_ci    }
3636370b324cSopenharmony_ci    else
3637370b324cSopenharmony_ci      return false;
3638370b324cSopenharmony_ci  }
3639370b324cSopenharmony_ci
3640370b324cSopenharmony_ci  type.FormatIndex = index;
3641370b324cSopenharmony_ci
3642370b324cSopenharmony_ci  }
3643370b324cSopenharmony_ci
3644370b324cSopenharmony_ci  for (unsigned i = (unsigned)pos2; i < s.Len();)
3645370b324cSopenharmony_ci  {
3646370b324cSopenharmony_ci    int next = s.Find(L':', i);
3647370b324cSopenharmony_ci    if (next < 0)
3648370b324cSopenharmony_ci      next = (int)s.Len();
3649370b324cSopenharmony_ci    const UString name = s.Mid(i, (unsigned)next - i);
3650370b324cSopenharmony_ci    if (name.IsEmpty())
3651370b324cSopenharmony_ci      return false;
3652370b324cSopenharmony_ci    if (!ParseTypeParams(name, type))
3653370b324cSopenharmony_ci      return false;
3654370b324cSopenharmony_ci    i = (unsigned)next + 1;
3655370b324cSopenharmony_ci  }
3656370b324cSopenharmony_ci
3657370b324cSopenharmony_ci  return true;
3658370b324cSopenharmony_ci}
3659370b324cSopenharmony_ci
3660370b324cSopenharmony_cibool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types)
3661370b324cSopenharmony_ci{
3662370b324cSopenharmony_ci  types.Clear();
3663370b324cSopenharmony_ci  bool isHashType = false;
3664370b324cSopenharmony_ci  for (unsigned pos = 0; pos < s.Len();)
3665370b324cSopenharmony_ci  {
3666370b324cSopenharmony_ci    int pos2 = s.Find(L'.', pos);
3667370b324cSopenharmony_ci    if (pos2 < 0)
3668370b324cSopenharmony_ci      pos2 = (int)s.Len();
3669370b324cSopenharmony_ci    UString name = s.Mid(pos, (unsigned)pos2 - pos);
3670370b324cSopenharmony_ci    if (name.IsEmpty())
3671370b324cSopenharmony_ci      return false;
3672370b324cSopenharmony_ci    COpenType type;
3673370b324cSopenharmony_ci    if (!ParseType(codecs, name, type))
3674370b324cSopenharmony_ci      return false;
3675370b324cSopenharmony_ci    if (isHashType)
3676370b324cSopenharmony_ci      return false;
3677370b324cSopenharmony_ci    if (type.IsHashType)
3678370b324cSopenharmony_ci      isHashType = true;
3679370b324cSopenharmony_ci    types.Add(type);
3680370b324cSopenharmony_ci    pos = (unsigned)pos2 + 1;
3681370b324cSopenharmony_ci  }
3682370b324cSopenharmony_ci  return true;
3683370b324cSopenharmony_ci}
3684370b324cSopenharmony_ci
3685370b324cSopenharmony_ci/*
3686370b324cSopenharmony_cibool IsHashType(const CObjectVector<COpenType> &types)
3687370b324cSopenharmony_ci{
3688370b324cSopenharmony_ci  if (types.Size() != 1)
3689370b324cSopenharmony_ci    return false;
3690370b324cSopenharmony_ci  return types[0].IsHashType;
3691370b324cSopenharmony_ci}
3692370b324cSopenharmony_ci*/
3693370b324cSopenharmony_ci
3694370b324cSopenharmony_ci
3695370b324cSopenharmony_ci#endif
3696