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 
12 HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw();
13 HRESULT Archive_IsItem_Folder(IInArchive *arc, UInt32 index, bool &result) throw();
14 HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw();
15 HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw();
16 HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &deleted) throw();
17 
18 /*
19 struct 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 
33 struct COpenSpecFlags
34 {
35   // bool CanReturnFull;
36   bool CanReturnFrontal;
37   bool CanReturnTail;
38   bool CanReturnMid;
39 
CanReturn_NonStartCOpenSpecFlags40   bool CanReturn_NonStart() const { return CanReturnTail || CanReturnMid; }
41 
COpenSpecFlagsCOpenSpecFlags42   COpenSpecFlags():
43     // CanReturnFull(true),
44     CanReturnFrontal(false),
45     CanReturnTail(false),
46     CanReturnMid(false)
47     {}
48 };
49 
50 struct 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 
GetSpecCOpenType73   const COpenSpecFlags &GetSpec(bool isForced, bool isMain, bool isUnknown) const
74   {
75     return isForced ? SpecForcedType : (isMain ? SpecMainType : (isUnknown ? SpecUnknownExt : SpecWrongExt));
76   }
77 
COpenTypeCOpenType78   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 
104 struct 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 
COpenOptionsCOpenOptions121   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 
134 UInt32 GetOpenArcErrorFlags(const NWindows::NCOM::CPropVariant &prop, bool *isDefinedProp = NULL);
135 
136 struct 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
IsArc_After_NonOpenCArcErrorInfo157   bool IsArc_After_NonOpen() const
158   {
159     return (ErrorFlags_Defined && (ErrorFlags & kpv_ErrorFlags_IsNotArc) == 0);
160   }
161 
162 
CArcErrorInfoCArcErrorInfo163   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 
ClearErrors_FullCArcErrorInfo177   void ClearErrors_Full()
178   {
179     ErrorFormatIndex = -1;
180     ClearErrors();
181   }
182 
IsThereErrorOrWarningCArcErrorInfo183   bool IsThereErrorOrWarning() const
184   {
185     return ErrorFlags != 0
186         || WarningFlags != 0
187         || NeedTailWarning()
188         || UnexpecedEnd
189         || !ErrorMessage.IsEmpty()
190         || !WarningMessage.IsEmpty();
191   }
192 
AreThereErrorsCArcErrorInfo193   bool AreThereErrors() const { return ErrorFlags != 0 || UnexpecedEnd; }
AreThereWarningsCArcErrorInfo194   bool AreThereWarnings() const { return WarningFlags != 0 || NeedTailWarning(); }
195 
NeedTailWarningCArcErrorInfo196   bool NeedTailWarning() const { return !IgnoreTail && ThereIsTail; }
197 
GetWarningFlagsCArcErrorInfo198   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 
GetErrorFlagsCArcErrorInfo206   UInt32 GetErrorFlags() const
207   {
208     UInt32 a = ErrorFlags;
209     if (UnexpecedEnd)
210       a |= kpv_ErrorFlags_UnexpectedEnd;
211     return a;
212   }
213 };
214 
215 class 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 
221 public:
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
GetGlobalOffset()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 
CArc()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 
Close()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;
IsItemAnti(UInt32 index,bool & result)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 
311 struct 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 
CArchiveLinkCArchiveLink326   CArchiveLink(): VolumesSize(0), IsOpen(false) {}
327   void KeepModeForNextOpen();
328   HRESULT Close();
329   void Release();
~CArchiveLinkCArchiveLink330   ~CArchiveLink() { Release(); }
331 
GetArcCArchiveLink332   const CArc *GetArc() const { return &Arcs.Back(); }
GetArchiveCArchiveLink333   IInArchive *GetArchive() const { return Arcs.Back().Archive; }
GetArchiveGetRawPropsCArchiveLink334   IArchiveGetRawProps *GetArchiveGetRawProps() const { return Arcs.Back().GetRawProps; }
GetArchiveGetRootPropsCArchiveLink335   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 
344 bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);
345 
346 #endif
347