1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// OpenArchive.cpp
2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "StdAfx.h"
4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Common/Wildcard.h"
6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Windows/FileDir.h"
8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Windows/PropVariant.h"
9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../Common/FileStreams.h"
11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../Common/StreamUtils.h"
12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "DefaultName.h"
14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "OpenArchive.h"
15baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
16baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing namespace NWindows;
17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// Static-SFX (for Linux) can be big.
19baa3858d3f5d128a5c8466b700098109edcad5f2repo syncconst UInt64 kMaxCheckStartPosition = 1 << 22;
20baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
21baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)
22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  NCOM::CPropVariant prop;
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  result = false;
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(archive->GetProperty(index, propID, &prop));
26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (prop.vt == VT_BOOL)
27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    result = VARIANT_BOOLToBool(prop.boolVal);
28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else if (prop.vt != VT_EMPTY)
29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_FAIL;
30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
33baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)
34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return GetArchiveItemBoolProp(archive, index, kpidIsDir, result);
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
38baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT CArc::GetItemPath(UInt32 index, UString &result) const
39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NCOM::CPropVariant prop;
42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(Archive->GetProperty(index, kpidPath, &prop));
43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (prop.vt == VT_BSTR)
44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      result = prop.bstrVal;
45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else if (prop.vt == VT_EMPTY)
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      result.Empty();
47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
48baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return E_FAIL;
49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (result.IsEmpty())
51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    result = DefaultName;
53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NCOM::CPropVariant prop;
54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(Archive->GetProperty(index, kpidExtension, &prop));
55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (prop.vt == VT_BSTR)
56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      result += L'.';
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      result += prop.bstrVal;
59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else if (prop.vt != VT_EMPTY)
61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return E_FAIL;
62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
66baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  NCOM::CPropVariant prop;
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  defined = false;
70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ft.dwHighDateTime = ft.dwLowDateTime = 0;
71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(Archive->GetProperty(index, kpidMTime, &prop));
72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (prop.vt == VT_FILETIME)
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    ft = prop.filetime;
75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    defined = true;
76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else if (prop.vt != VT_EMPTY)
78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_FAIL;
79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else if (MTimeDefined)
80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    ft = MTime;
82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    defined = true;
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifndef _SFX
88baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size)
89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (size_t i = 0; i < size; i++)
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (p1[i] != p2[i])
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return false;
93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return true;
94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifdef UNDER_CE
98baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const int kNumHashBytes = 1;
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define HASH_VAL(buf, pos) ((buf)[pos])
100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#else
101baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const int kNumHashBytes = 2;
102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define HASH_VAL(buf, pos) ((buf)[pos] | ((UInt32)(buf)[pos + 1] << 8))
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
106baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT CArc::OpenStream(
107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CCodecs *codecs,
108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int formatIndex,
109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IInStream *stream,
110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    ISequentialInStream *seqStream,
111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IArchiveOpenCallback *callback)
112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Archive.Release();
114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ErrorMessage.Empty();
115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  const UString fileName = ExtractFileNameFromPath(Path);
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UString extension;
117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int dotPos = fileName.ReverseFind(L'.');
119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (dotPos >= 0)
120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      extension = fileName.Mid(dotPos + 1);
121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CIntVector orderIndices;
123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (formatIndex >= 0)
124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    orderIndices.Add(formatIndex);
125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else
126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int i;
129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int numFinded = 0;
130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < codecs->Formats.Size(); i++)
131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (codecs->Formats[i].FindExtension(extension) >= 0)
132baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      orderIndices.Insert(numFinded++, i);
133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      orderIndices.Add(i);
135baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!stream)
137baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (numFinded != 1)
139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return E_NOTIMPL;
140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    orderIndices.DeleteFrom(1);
141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifndef _SFX
144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (orderIndices.Size() >= 2 && (numFinded == 0 || extension.CompareNoCase(L"exe") == 0))
145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CIntVector orderIndices2;
147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CByteBuffer byteBuffer;
148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const size_t kBufferSize = (1 << 21);
149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    byteBuffer.SetCapacity(kBufferSize);
150baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
151baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    size_t processedSize = kBufferSize;
152baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(ReadStream(stream, byteBuffer, &processedSize));
153baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (processedSize == 0)
154baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return S_FALSE;
155baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
156baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const Byte *buf = byteBuffer;
157baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CByteBuffer hashBuffer;
158baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UInt32 kNumVals = 1 << (kNumHashBytes * 8);
159baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    hashBuffer.SetCapacity(kNumVals);
160baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Byte *hash = hashBuffer;
161baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    memset(hash, 0xFF, kNumVals);
162baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Byte prevs[256];
163baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (orderIndices.Size() >= 256)
164baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return S_FALSE;
165baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int i;
166baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (i = 0; i < orderIndices.Size(); i++)
167baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
168baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      const CArcInfoEx &ai = codecs->Formats[orderIndices[i]];
169baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      const CByteBuffer &sig = ai.StartSignature;
170baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (sig.GetCapacity() < kNumHashBytes)
171baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        continue;
172baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UInt32 v = HASH_VAL(sig, 0);
173baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      prevs[i] = hash[v];
174baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      hash[v] = (Byte)i;
175baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
176baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
177baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    processedSize -= (kNumHashBytes - 1);
178baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (UInt32 pos = 0; pos < processedSize; pos++)
179baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
180baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      for (; pos < processedSize && hash[HASH_VAL(buf, pos)] == 0xFF; pos++);
181baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (pos == processedSize)
182baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        break;
183baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UInt32 v = HASH_VAL(buf, pos);
184baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      Byte *ptr = &hash[v];
185baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      int i = *ptr;
186baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      do
187baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
188baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        int index = orderIndices[i];
189baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        const CArcInfoEx &ai = codecs->Formats[index];
190baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        const CByteBuffer &sig = ai.StartSignature;
191baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (sig.GetCapacity() != 0 && pos + sig.GetCapacity() <= processedSize + (kNumHashBytes - 1) &&
192baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            TestSignature(buf + pos, sig, sig.GetCapacity()))
193baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
194baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          orderIndices2.Add(index);
195baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          orderIndices[i] = 0xFF;
196baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          *ptr = prevs[i];
197baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
198baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        else
199baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          ptr = &prevs[i];
200baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        i = *ptr;
201baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
202baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      while (i != 0xFF);
203baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
204baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
205baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (i = 0; i < orderIndices.Size(); i++)
206baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
207baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      int val = orderIndices[i];
208baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (val != 0xFF)
209baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        orderIndices2.Add(val);
210baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
211baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    orderIndices = orderIndices2;
212baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
213baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else if (extension == L"000" || extension == L"001")
214baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
215baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CByteBuffer byteBuffer;
216baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const size_t kBufferSize = (1 << 10);
217baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    byteBuffer.SetCapacity(kBufferSize);
218baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Byte *buffer = byteBuffer;
219baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
220baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    size_t processedSize = kBufferSize;
221baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(ReadStream(stream, buffer, &processedSize));
222baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (processedSize >= 16)
223baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
224baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00};
225baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (TestSignature(buffer, kRarHeader, 7) && buffer[9] == 0x73 && (buffer[10] & 1) != 0)
226baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
227baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        for (int i = 0; i < orderIndices.Size(); i++)
228baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
229baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          int index = orderIndices[i];
230baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          const CArcInfoEx &ai = codecs->Formats[index];
231baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          if (ai.Name.CompareNoCase(L"rar") != 0)
232baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            continue;
233baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          orderIndices.Delete(i--);
234baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          orderIndices.Insert(0, index);
235baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          break;
236baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
237baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
238baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
239baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
240baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (orderIndices.Size() >= 2)
241baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
242baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int isoIndex = codecs->FindFormatForArchiveType(L"iso");
243baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int udfIndex = codecs->FindFormatForArchiveType(L"udf");
244baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int iIso = -1;
245baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int iUdf = -1;
246baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (int i = 0; i < orderIndices.Size(); i++)
247baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
248baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (orderIndices[i] == isoIndex) iIso = i;
249baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (orderIndices[i] == udfIndex) iUdf = i;
250baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
251baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (iUdf > iIso && iIso >= 0)
252baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
253baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      orderIndices[iUdf] = isoIndex;
254baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      orderIndices[iIso] = udfIndex;
255baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
256baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
257baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
258baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
259baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
260baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
261baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (int i = 0; i < orderIndices.Size(); i++)
262baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
263baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (stream)
264baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
265baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
266baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
267baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<IInArchive> archive;
268baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
269baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    FormatIndex = orderIndices[i];
270baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(codecs->CreateInArchive(FormatIndex, archive));
271baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!archive)
272baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      continue;
273baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
274baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifdef EXTERNAL_CODECS
275baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
276baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
277baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
278baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (setCompressCodecsInfo)
279baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
280baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs));
281baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
282baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
283baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
284baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
285baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    // OutputDebugStringW(codecs->Formats[FormatIndex].Name);
286baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
287baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    HRESULT result;
288baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (stream)
289baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      result = archive->Open(stream, &kMaxCheckStartPosition, callback);
290baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
291baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
292baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CMyComPtr<IArchiveOpenSeq> openSeq;
293baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq);
294baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (!openSeq)
295baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return E_NOTIMPL;
296baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      result = openSeq->OpenSeq(seqStream);
297baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
298baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
299baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (result == S_FALSE)
300baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      continue;
301baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(result);
302baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
303baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
304baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      NCOM::CPropVariant prop;
305baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      archive->GetArchiveProperty(kpidError, &prop);
306baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (prop.vt != VT_EMPTY)
307baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        ErrorMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown error";
308baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
309baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
310baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Archive = archive;
311baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CArcInfoEx &format = codecs->Formats[FormatIndex];
312baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (format.Exts.Size() == 0)
313baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      DefaultName = GetDefaultName2(fileName, L"", L"");
314baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
315baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
316baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      int subExtIndex = format.FindExtension(extension);
317baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (subExtIndex < 0)
318baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        subExtIndex = 0;
319baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      const CArcExtInfo &extInfo = format.Exts[subExtIndex];
320baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt);
321baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
322baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return S_OK;
323baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
324baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_FALSE;
325baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
326baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
327baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT CArc::OpenStreamOrFile(
328baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CCodecs *codecs,
329baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int formatIndex,
330baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bool stdInMode,
331baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IInStream *stream,
332baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IArchiveOpenCallback *callback)
333baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
334baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<IInStream> fileStream;
335baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<ISequentialInStream> seqStream;
336baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (stdInMode)
337baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    seqStream = new CStdInFileStream;
338baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else if (!stream)
339baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
340baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CInFileStream *fileStreamSpec = new CInFileStream;
341baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    fileStream = fileStreamSpec;
342baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!fileStreamSpec->Open(Path))
343baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return GetLastError();
344baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    stream = fileStream;
345baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
346baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
347baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  /*
348baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (callback)
349baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
350baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt64 fileSize;
351baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize));
352baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(callback->SetTotal(NULL, &fileSize))
353baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
354baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  */
355baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
356baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return OpenStream(codecs, formatIndex, stream, seqStream, callback);
357baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
358baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
359baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT CArchiveLink::Close()
360baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
361baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (int i = Arcs.Size() - 1;  i >= 0; i--)
362baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
363baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(Arcs[i].Archive->Close());
364baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
365baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  IsOpen = false;
366baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
367baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
368baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
369baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid CArchiveLink::Release()
370baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
371baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  while (!Arcs.IsEmpty())
372baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Arcs.DeleteBack();
373baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
374baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
375baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT CArchiveLink::Open(
376baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CCodecs *codecs,
377baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CIntVector &formatIndices,
378baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bool stdInMode,
379baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IInStream *stream,
380baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UString &filePath,
381baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IArchiveOpenCallback *callback)
382baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
383baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Release();
384baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (formatIndices.Size() >= 32)
385baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_NOTIMPL;
386baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
387baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT resSpec;
388baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
389baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (;;)
390baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
391baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    resSpec = S_OK;
392baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int formatIndex = -1;
393baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (formatIndices.Size() >= 1)
394baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
395baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (Arcs.Size() >= formatIndices.Size())
396baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        break;
397baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      formatIndex = formatIndices[formatIndices.Size() - Arcs.Size() - 1];
398baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
399baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else if (Arcs.Size() >= 32)
400baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      break;
401baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
402baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (Arcs.IsEmpty())
403baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
404baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CArc arc;
405baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      arc.Path = filePath;
406baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      arc.SubfileIndex = (UInt32)(Int32)-1;
407baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(arc.OpenStreamOrFile(codecs, formatIndex, stdInMode, stream, callback));
408baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      Arcs.Add(arc);
409baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      continue;
410baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
411baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
412baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CArc &arc = Arcs.Back();
413baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
414baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL);
415baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
416baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 mainSubfile;
417baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
418baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      NCOM::CPropVariant prop;
419baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(arc.Archive->GetArchiveProperty(kpidMainSubfile, &prop));
420baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (prop.vt == VT_UI4)
421baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        mainSubfile = prop.ulVal;
422baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      else
423baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        break;
424baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UInt32 numItems;
425baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(arc.Archive->GetNumberOfItems(&numItems));
426baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (mainSubfile >= numItems)
427baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        break;
428baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
429baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
430baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
431baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<IInArchiveGetStream> getStream;
432baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (arc.Archive->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream) != S_OK || !getStream)
433baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      break;
434baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
435baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<ISequentialInStream> subSeqStream;
436baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (getStream->GetStream(mainSubfile, &subSeqStream) != S_OK || !subSeqStream)
437baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      break;
438baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
439baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<IInStream> subStream;
440baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK || !subStream)
441baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      break;
442baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
443baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CArc arc2;
444baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(arc.GetItemPath(mainSubfile, arc2.Path));
445baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
446baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName;
447baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName);
448baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (setSubArchiveName)
449baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      setSubArchiveName->SetSubArchiveName(arc2.Path);
450baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
451baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    arc2.SubfileIndex = mainSubfile;
452baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    HRESULT result = arc2.OpenStream(codecs, formatIndex, subStream, NULL, callback);
453baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE);
454baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (result == S_FALSE)
455baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      break;
456baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(result);
457baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(arc.GetItemMTime(mainSubfile, arc2.MTime, arc2.MTimeDefined));
458baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Arcs.Add(arc2);
459baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
460baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  IsOpen = !Arcs.IsEmpty();
461baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
462baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
463baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
464baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void SetCallback(const UString &filePath,
465baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IOpenCallbackUI *callbackUI,
466baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IArchiveOpenCallback *reOpenCallback,
467baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<IArchiveOpenCallback> &callback)
468baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
469baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;
470baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  callback = openCallbackSpec;
471baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  openCallbackSpec->Callback = callbackUI;
472baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  openCallbackSpec->ReOpenCallback = reOpenCallback;
473baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
474baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UString fullName;
475baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int fileNamePartStartIndex;
476baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex);
477baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  openCallbackSpec->Init(
478baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      fullName.Left(fileNamePartStartIndex),
479baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      fullName.Mid(fileNamePartStartIndex));
480baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
481baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
482baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT CArchiveLink::Open2(CCodecs *codecs,
483baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CIntVector &formatIndices,
484baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bool stdInMode,
485baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IInStream *stream,
486baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UString &filePath,
487baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IOpenCallbackUI *callbackUI)
488baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
489baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  VolumesSize = 0;
490baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;
491baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<IArchiveOpenCallback> callback = openCallbackSpec;
492baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  openCallbackSpec->Callback = callbackUI;
493baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
494baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UString fullName, prefix, name;
495baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!stream && !stdInMode)
496baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
497baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int fileNamePartStartIndex;
498baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex))
499baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return GetLastError();
500baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    prefix = fullName.Left(fileNamePartStartIndex);
501baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    name = fullName.Mid(fileNamePartStartIndex);
502baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    openCallbackSpec->Init(prefix, name);
503baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
504baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else
505baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
506baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    openCallbackSpec->SetSubArchiveName(filePath);
507baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
508baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
509baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(Open(codecs, formatIndices, stdInMode, stream, filePath, callback));
510baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  VolumePaths.Add(prefix + name);
511baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++)
512baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    VolumePaths.Add(prefix + openCallbackSpec->FileNames[i]);
513baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  VolumesSize = openCallbackSpec->TotalSize;
514baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
515baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
516baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
517baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT CArchiveLink::ReOpen(CCodecs *codecs, const UString &filePath,
518baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    IArchiveOpenCallback *callback)
519baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
520baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (Arcs.Size() > 1)
521baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_NOTIMPL;
522baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
523baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (Arcs.Size() == 0)
524baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return Open2(codecs, CIntVector(), false, NULL, filePath, 0);
525baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
526baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<IArchiveOpenCallback> openCallbackNew;
527baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  SetCallback(filePath, NULL, callback, openCallbackNew);
528baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
529baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CInFileStream *fileStreamSpec = new CInFileStream;
530baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<IInStream> stream(fileStreamSpec);
531baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!fileStreamSpec->Open(filePath))
532baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return GetLastError();
533baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT res = GetArchive()->Open(stream, &kMaxCheckStartPosition, callback);
534baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  IsOpen = (res == S_OK);
535baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return res;
536baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
537