1// OpenArchive.h
2
3#ifndef __OPEN_ARCHIVE_H
4#define __OPEN_ARCHIVE_H
5
6#include "../../../Windows/PropVariant.h"
7
8#include "ArchiveOpenCallback.h"
9#include "LoadCodecs.h"
10#include "Property.h"
11
12HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw();
13HRESULT Archive_IsItem_Folder(IInArchive *arc, UInt32 index, bool &result) throw();
14HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw();
15HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw();
16HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &deleted) throw();
17
18/*
19struct COptionalOpenProperties
20{
21  UString FormatName;
22  CObjectVector<CProperty> Props;
23};
24*/
25
26#ifdef _SFX
27#define OPEN_PROPS_DECL
28#else
29#define OPEN_PROPS_DECL const CObjectVector<CProperty> *props;
30// #define OPEN_PROPS_DECL , const CObjectVector<COptionalOpenProperties> *props
31#endif
32
33struct COpenSpecFlags
34{
35  // bool CanReturnFull;
36  bool CanReturnFrontal;
37  bool CanReturnTail;
38  bool CanReturnMid;
39
40  bool CanReturn_NonStart() const { return CanReturnTail || CanReturnMid; }
41
42  COpenSpecFlags():
43    // CanReturnFull(true),
44    CanReturnFrontal(false),
45    CanReturnTail(false),
46    CanReturnMid(false)
47    {}
48};
49
50struct COpenType
51{
52  int FormatIndex;
53
54  COpenSpecFlags SpecForcedType;
55  COpenSpecFlags SpecMainType;
56  COpenSpecFlags SpecWrongExt;
57  COpenSpecFlags SpecUnknownExt;
58
59  bool Recursive;
60
61  bool CanReturnArc;
62  bool CanReturnParser;
63  bool EachPos;
64
65  // bool SkipSfxStub;
66  // bool ExeAsUnknown;
67
68  bool ZerosTailIsAllowed;
69
70  bool MaxStartOffset_Defined;
71  UInt64 MaxStartOffset;
72
73  const COpenSpecFlags &GetSpec(bool isForced, bool isMain, bool isUnknown) const
74  {
75    return isForced ? SpecForcedType : (isMain ? SpecMainType : (isUnknown ? SpecUnknownExt : SpecWrongExt));
76  }
77
78  COpenType():
79      FormatIndex(-1),
80      Recursive(true),
81      EachPos(false),
82      CanReturnArc(true),
83      CanReturnParser(false),
84      // SkipSfxStub(true),
85      // ExeAsUnknown(true),
86      ZerosTailIsAllowed(false),
87      MaxStartOffset_Defined(false),
88      MaxStartOffset(0)
89  {
90    SpecForcedType.CanReturnFrontal = true;
91    SpecForcedType.CanReturnTail = true;
92    SpecForcedType.CanReturnMid = true;
93
94    SpecMainType.CanReturnFrontal = true;
95
96    SpecUnknownExt.CanReturnTail = true; // for sfx
97    SpecUnknownExt.CanReturnMid = true;
98    SpecUnknownExt.CanReturnFrontal = true; // for alt streams of sfx with pad
99
100    // ZerosTailIsAllowed = true;
101  }
102};
103
104struct COpenOptions
105{
106  CCodecs *codecs;
107  COpenType openType;
108  const CObjectVector<COpenType> *types;
109  const CIntVector *excludedFormats;
110
111  IInStream *stream;
112  ISequentialInStream *seqStream;
113  IArchiveOpenCallback *callback;
114  COpenCallbackImp *callbackSpec;
115  OPEN_PROPS_DECL
116  // bool openOnlySpecifiedByExtension,
117
118  bool stdInMode;
119  UString filePath;
120
121  COpenOptions():
122      codecs(NULL),
123      types(NULL),
124      excludedFormats(NULL),
125      stream(NULL),
126      seqStream(NULL),
127      callback(NULL),
128      callbackSpec(NULL),
129      stdInMode(false)
130    {}
131
132};
133
134UInt32 GetOpenArcErrorFlags(const NWindows::NCOM::CPropVariant &prop, bool *isDefinedProp = NULL);
135
136struct CArcErrorInfo
137{
138  bool ThereIsTail;
139  bool UnexpecedEnd;
140  bool IgnoreTail; // all are zeros
141  // bool NonZerosTail;
142  bool ErrorFlags_Defined;
143  UInt32 ErrorFlags;
144  UInt32 WarningFlags;
145  int ErrorFormatIndex; // - 1 means no Error.
146                        // if FormatIndex == ErrorFormatIndex, the archive is open with offset
147  UInt64 TailSize;
148
149  /* if CArc is Open OK with some format:
150        - ErrorFormatIndex shows error format index, if extension is incorrect
151        - other variables show message and warnings of archive that is open */
152
153  UString ErrorMessage;
154  UString WarningMessage;
155
156  // call IsArc_After_NonOpen only if Open returns S_FALSE
157  bool IsArc_After_NonOpen() const
158  {
159    return (ErrorFlags_Defined && (ErrorFlags & kpv_ErrorFlags_IsNotArc) == 0);
160  }
161
162
163  CArcErrorInfo():
164      ThereIsTail(false),
165      UnexpecedEnd(false),
166      IgnoreTail(false),
167      // NonZerosTail(false),
168      ErrorFlags_Defined(false),
169      ErrorFlags(0),
170      WarningFlags(0),
171      ErrorFormatIndex(-1),
172      TailSize(0)
173    {}
174
175  void ClearErrors();
176
177  void ClearErrors_Full()
178  {
179    ErrorFormatIndex = -1;
180    ClearErrors();
181  }
182
183  bool IsThereErrorOrWarning() const
184  {
185    return ErrorFlags != 0
186        || WarningFlags != 0
187        || NeedTailWarning()
188        || UnexpecedEnd
189        || !ErrorMessage.IsEmpty()
190        || !WarningMessage.IsEmpty();
191  }
192
193  bool AreThereErrors() const { return ErrorFlags != 0 || UnexpecedEnd; }
194  bool AreThereWarnings() const { return WarningFlags != 0 || NeedTailWarning(); }
195
196  bool NeedTailWarning() const { return !IgnoreTail && ThereIsTail; }
197
198  UInt32 GetWarningFlags() const
199  {
200    UInt32 a = WarningFlags;
201    if (NeedTailWarning() && (ErrorFlags & kpv_ErrorFlags_DataAfterEnd) == 0)
202      a |= kpv_ErrorFlags_DataAfterEnd;
203    return a;
204  }
205
206  UInt32 GetErrorFlags() const
207  {
208    UInt32 a = ErrorFlags;
209    if (UnexpecedEnd)
210      a |= kpv_ErrorFlags_UnexpectedEnd;
211    return a;
212  }
213};
214
215class CArc
216{
217  HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive);
218  HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset);
219  HRESULT OpenStream2(const COpenOptions &options);
220
221public:
222  CMyComPtr<IInArchive> Archive;
223  CMyComPtr<IInStream> InStream;
224          // we use InStream in 2 cases (ArcStreamOffset != 0):
225          // 1) if we use additional cache stream
226          // 2) we reopen sfx archive with CTailInStream
227
228  CMyComPtr<IArchiveGetRawProps> GetRawProps;
229  CMyComPtr<IArchiveGetRootProps> GetRootProps;
230
231  CArcErrorInfo ErrorInfo; // for OK archives
232  CArcErrorInfo NonOpen_ErrorInfo; // ErrorInfo for mainArchive (false OPEN)
233
234  UString Path;
235  UString filePath;
236  UString DefaultName;
237  int FormatIndex; // - 1 means Parser.
238  int SubfileIndex;
239  FILETIME MTime;
240  bool MTimeDefined;
241
242  Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler
243  UInt64 PhySize;
244  // UInt64 OkPhySize;
245  bool PhySizeDefined;
246  // bool OkPhySize_Defined;
247  UInt64 FileSize;
248  UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file
249  // bool offsetDefined;
250
251  UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler
252  Int64 GetGlobalOffset() const { return ArcStreamOffset + Offset; } // it's global offset of archive
253
254  // AString ErrorFlagsText;
255
256  bool IsParseArc;
257
258  bool IsTree;
259
260  bool Ask_Deleted;
261  bool Ask_AltStream;
262  bool Ask_Aux;
263  bool Ask_INode;
264
265  bool IgnoreSplit; // don't try split handler
266
267  // void Set_ErrorFlagsText();
268
269  CArc():
270    MTimeDefined(false),
271    IsTree(false),
272    Ask_Deleted(false),
273    Ask_AltStream(false),
274    Ask_Aux(false),
275    Ask_INode(false),
276    IgnoreSplit(false)
277    {}
278
279  HRESULT ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes);
280
281  // ~CArc();
282
283  HRESULT Close()
284  {
285    InStream.Release();
286    return Archive->Close();
287  }
288
289  // AltStream's name is concatenated with base file name in one string in parts.Back()
290  HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const;
291
292  HRESULT GetItemPath(UInt32 index, UString &result) const;
293
294  // GetItemPath2 adds [DELETED] dir prefix for deleted items.
295  HRESULT GetItemPath2(UInt32 index, UString &result) const;
296
297  HRESULT GetItemSize(UInt32 index, UInt64 &size, bool &defined) const;
298  HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const;
299  HRESULT IsItemAnti(UInt32 index, bool &result) const
300    { return Archive_GetItemBoolProp(Archive, index, kpidIsAnti, result); }
301
302
303  HRESULT OpenStream(const COpenOptions &options);
304  HRESULT OpenStreamOrFile(COpenOptions &options);
305
306  HRESULT ReOpen(const COpenOptions &options);
307
308  HRESULT CreateNewTailStream(CMyComPtr<IInStream> &stream);
309};
310
311struct CArchiveLink
312{
313  CObjectVector<CArc> Arcs;
314  UStringVector VolumePaths;
315  UInt64 VolumesSize;
316  bool IsOpen;
317
318  // int NonOpenErrorFormatIndex; // - 1 means no Error.
319  UString NonOpen_ArcPath;
320
321  CArcErrorInfo NonOpen_ErrorInfo;
322
323  // UString ErrorsText;
324  // void Set_ErrorsText();
325
326  CArchiveLink(): VolumesSize(0), IsOpen(false) {}
327  void KeepModeForNextOpen();
328  HRESULT Close();
329  void Release();
330  ~CArchiveLink() { Release(); }
331
332  const CArc *GetArc() const { return &Arcs.Back(); }
333  IInArchive *GetArchive() const { return Arcs.Back().Archive; }
334  IArchiveGetRawProps *GetArchiveGetRawProps() const { return Arcs.Back().GetRawProps; }
335  IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; }
336
337  HRESULT Open(COpenOptions &options);
338
339  HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI);
340
341  HRESULT ReOpen(COpenOptions &options);
342};
343
344bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);
345
346#endif
347