• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "DirItem.h"
12 
13 #ifndef _SFX
14 
15 #define SUPPORT_ALT_STREAMS
16 
17 #endif
18 
19 HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw();
20 HRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw();
21 HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw();
22 HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw();
23 HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &deleted) throw();
24 
25 #ifdef SUPPORT_ALT_STREAMS
26 int FindAltStreamColon_in_Path(const wchar_t *path);
27 #endif
28 
29 /*
30 struct COptionalOpenProperties
31 {
32   UString FormatName;
33   CObjectVector<CProperty> Props;
34 };
35 */
36 
37 #ifdef _SFX
38 #define OPEN_PROPS_DECL
39 #else
40 #define OPEN_PROPS_DECL const CObjectVector<CProperty> *props;
41 // #define OPEN_PROPS_DECL , const CObjectVector<COptionalOpenProperties> *props
42 #endif
43 
44 struct COpenSpecFlags
45 {
46   // bool CanReturnFull;
47   bool CanReturnFrontal;
48   bool CanReturnTail;
49   bool CanReturnMid;
50 
CanReturn_NonStartCOpenSpecFlags51   bool CanReturn_NonStart() const { return CanReturnTail || CanReturnMid; }
52 
COpenSpecFlagsCOpenSpecFlags53   COpenSpecFlags():
54     // CanReturnFull(true),
55     CanReturnFrontal(false),
56     CanReturnTail(false),
57     CanReturnMid(false)
58     {}
59 };
60 
61 struct COpenType
62 {
63   int FormatIndex;
64 
65   COpenSpecFlags SpecForcedType;
66   COpenSpecFlags SpecMainType;
67   COpenSpecFlags SpecWrongExt;
68   COpenSpecFlags SpecUnknownExt;
69 
70   bool Recursive;
71 
72   bool CanReturnArc;
73   bool CanReturnParser;
74   bool IsHashType;
75   bool EachPos;
76 
77   // bool SkipSfxStub;
78   // bool ExeAsUnknown;
79 
80   bool ZerosTailIsAllowed;
81 
82   bool MaxStartOffset_Defined;
83   UInt64 MaxStartOffset;
84 
GetSpecCOpenType85   const COpenSpecFlags &GetSpec(bool isForced, bool isMain, bool isUnknown) const
86   {
87     return isForced ? SpecForcedType : (isMain ? SpecMainType : (isUnknown ? SpecUnknownExt : SpecWrongExt));
88   }
89 
COpenTypeCOpenType90   COpenType():
91       FormatIndex(-1),
92       Recursive(true),
93       CanReturnArc(true),
94       CanReturnParser(false),
95       IsHashType(false),
96       EachPos(false),
97       // SkipSfxStub(true),
98       // ExeAsUnknown(true),
99       ZerosTailIsAllowed(false),
100       MaxStartOffset_Defined(false),
101       MaxStartOffset(0)
102   {
103     SpecForcedType.CanReturnFrontal = true;
104     SpecForcedType.CanReturnTail = true;
105     SpecForcedType.CanReturnMid = true;
106 
107     SpecMainType.CanReturnFrontal = true;
108 
109     SpecUnknownExt.CanReturnTail = true; // for sfx
110     SpecUnknownExt.CanReturnMid = true;
111     SpecUnknownExt.CanReturnFrontal = true; // for alt streams of sfx with pad
112 
113     // ZerosTailIsAllowed = true;
114   }
115 };
116 
117 struct COpenOptions
118 {
119   CCodecs *codecs;
120   COpenType openType;
121   const CObjectVector<COpenType> *types;
122   const CIntVector *excludedFormats;
123 
124   IInStream *stream;
125   ISequentialInStream *seqStream;
126   IArchiveOpenCallback *callback;
127   COpenCallbackImp *callbackSpec; // it's used for SFX only
128   OPEN_PROPS_DECL
129   // bool openOnlySpecifiedByExtension,
130 
131   bool stdInMode;
132   UString filePath;
133 
COpenOptionsCOpenOptions134   COpenOptions():
135       codecs(NULL),
136       types(NULL),
137       excludedFormats(NULL),
138       stream(NULL),
139       seqStream(NULL),
140       callback(NULL),
141       callbackSpec(NULL),
142       stdInMode(false)
143     {}
144 
145 };
146 
147 UInt32 GetOpenArcErrorFlags(const NWindows::NCOM::CPropVariant &prop, bool *isDefinedProp = NULL);
148 
149 struct CArcErrorInfo
150 {
151   bool ThereIsTail;
152   bool UnexpecedEnd;
153   bool IgnoreTail; // all are zeros
154   // bool NonZerosTail;
155   bool ErrorFlags_Defined;
156   UInt32 ErrorFlags;
157   UInt32 WarningFlags;
158   int ErrorFormatIndex; // - 1 means no Error.
159                         // if FormatIndex == ErrorFormatIndex, the archive is open with offset
160   UInt64 TailSize;
161 
162   /* if CArc is Open OK with some format:
163         - ErrorFormatIndex shows error format index, if extension is incorrect
164         - other variables show message and warnings of archive that is open */
165 
166   UString ErrorMessage;
167   UString WarningMessage;
168 
169   // call IsArc_After_NonOpen only if Open returns S_FALSE
IsArc_After_NonOpenCArcErrorInfo170   bool IsArc_After_NonOpen() const
171   {
172     return (ErrorFlags_Defined && (ErrorFlags & kpv_ErrorFlags_IsNotArc) == 0);
173   }
174 
175 
CArcErrorInfoCArcErrorInfo176   CArcErrorInfo():
177       ThereIsTail(false),
178       UnexpecedEnd(false),
179       IgnoreTail(false),
180       // NonZerosTail(false),
181       ErrorFlags_Defined(false),
182       ErrorFlags(0),
183       WarningFlags(0),
184       ErrorFormatIndex(-1),
185       TailSize(0)
186     {}
187 
188   void ClearErrors();
189 
ClearErrors_FullCArcErrorInfo190   void ClearErrors_Full()
191   {
192     ErrorFormatIndex = -1;
193     ClearErrors();
194   }
195 
IsThereErrorOrWarningCArcErrorInfo196   bool IsThereErrorOrWarning() const
197   {
198     return ErrorFlags != 0
199         || WarningFlags != 0
200         || NeedTailWarning()
201         || UnexpecedEnd
202         || !ErrorMessage.IsEmpty()
203         || !WarningMessage.IsEmpty();
204   }
205 
AreThereErrorsCArcErrorInfo206   bool AreThereErrors() const { return ErrorFlags != 0 || UnexpecedEnd; }
AreThereWarningsCArcErrorInfo207   bool AreThereWarnings() const { return WarningFlags != 0 || NeedTailWarning(); }
208 
NeedTailWarningCArcErrorInfo209   bool NeedTailWarning() const { return !IgnoreTail && ThereIsTail; }
210 
GetWarningFlagsCArcErrorInfo211   UInt32 GetWarningFlags() const
212   {
213     UInt32 a = WarningFlags;
214     if (NeedTailWarning() && (ErrorFlags & kpv_ErrorFlags_DataAfterEnd) == 0)
215       a |= kpv_ErrorFlags_DataAfterEnd;
216     return a;
217   }
218 
GetErrorFlagsCArcErrorInfo219   UInt32 GetErrorFlags() const
220   {
221     UInt32 a = ErrorFlags;
222     if (UnexpecedEnd)
223       a |= kpv_ErrorFlags_UnexpectedEnd;
224     return a;
225   }
226 };
227 
228 struct CReadArcItem
229 {
230   UString Path;            // Path from root (including alt stream name, if alt stream)
231   UStringVector PathParts; // without altStream name, path from root or from _baseParentFolder, if _use_baseParentFolder_mode
232 
233   #ifdef SUPPORT_ALT_STREAMS
234   UString MainPath;
235                 /* MainPath = Path for non-AltStream,
236                    MainPath = Path of parent, if there is parent for AltStream. */
237   UString AltStreamName;
238   bool IsAltStream;
239   bool WriteToAltStreamIfColon;
240   #endif
241 
242   bool IsDir;
243   bool MainIsDir;
244   UInt32 ParentIndex; // use it, if IsAltStream
245 
246   #ifndef _SFX
247   bool _use_baseParentFolder_mode;
248   int _baseParentFolder;
249   #endif
250 
CReadArcItemCReadArcItem251   CReadArcItem()
252   {
253     #ifdef SUPPORT_ALT_STREAMS
254     WriteToAltStreamIfColon = false;
255     #endif
256 
257     #ifndef _SFX
258     _use_baseParentFolder_mode = false;
259     _baseParentFolder = -1;
260     #endif
261   }
262 };
263 
264 
265 
266 
267 class CArc
268 {
269   HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive);
270   HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset);
271   HRESULT OpenStream2(const COpenOptions &options);
272 
273   #ifndef _SFX
274   // parts.Back() can contain alt stream name "nams:AltName"
275   HRESULT GetItem_PathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const;
276   #endif
277 
278 public:
279   CMyComPtr<IInArchive> Archive;
280   CMyComPtr<IInStream> InStream;
281           // we use InStream in 2 cases (ArcStreamOffset != 0):
282           // 1) if we use additional cache stream
283           // 2) we reopen sfx archive with CTailInStream
284 
285   CMyComPtr<IArchiveGetRawProps> GetRawProps;
286   CMyComPtr<IArchiveGetRootProps> GetRootProps;
287 
288   CArcErrorInfo ErrorInfo; // for OK archives
289   CArcErrorInfo NonOpen_ErrorInfo; // ErrorInfo for mainArchive (false OPEN)
290 
291   UString Path;
292   UString filePath;
293   UString DefaultName;
294   int FormatIndex;     // -1 means Parser
295   UInt32 SubfileIndex; // (UInt32)(Int32)-1; means no subfile
296 
297   // CFiTime MTime;
298   // bool MTime_Defined;
299   CArcTime MTime;
300 
301   Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler
302   UInt64 PhySize;
303   // UInt64 OkPhySize;
304   bool PhySize_Defined;
305   // bool OkPhySize_Defined;
306   UInt64 FileSize;
307   UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file
308   // bool offsetDefined;
309 
GetEstmatedPhySize()310   UInt64 GetEstmatedPhySize() const { return PhySize_Defined ? PhySize : FileSize; }
311 
312   UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler
GetGlobalOffset()313   Int64 GetGlobalOffset() const { return (Int64)ArcStreamOffset + Offset; } // it's global offset of archive
314 
315   // AString ErrorFlagsText;
316 
317   bool IsParseArc;
318 
319   bool IsTree;
320   bool IsReadOnly;
321 
322   bool Ask_Deleted;
323   bool Ask_AltStream;
324   bool Ask_Aux;
325   bool Ask_INode;
326 
327   bool IgnoreSplit; // don't try split handler
328 
329   // void Set_ErrorFlagsText();
330 
CArc()331   CArc():
332     // MTime_Defined(false),
333     IsTree(false),
334     IsReadOnly(false),
335     Ask_Deleted(false),
336     Ask_AltStream(false),
337     Ask_Aux(false),
338     Ask_INode(false),
339     IgnoreSplit(false)
340     {}
341 
342   HRESULT ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes);
343 
344   // ~CArc();
345 
Close()346   HRESULT Close()
347   {
348     InStream.Release();
349     return Archive->Close();
350   }
351 
352   HRESULT GetItem_Path(UInt32 index, UString &result) const;
353   HRESULT GetItem_DefaultPath(UInt32 index, UString &result) const;
354 
355   // GetItemPath2 adds [DELETED] dir prefix for deleted items.
356   HRESULT GetItem_Path2(UInt32 index, UString &result) const;
357 
358   HRESULT GetItem(UInt32 index, CReadArcItem &item) const;
359 
360   HRESULT GetItem_Size(UInt32 index, UInt64 &size, bool &defined) const;
361 
362   /* if (GetProperty() returns vt==VT_EMPTY), this function sets
363      timestamp from archive file timestamp (MTime).
364      So (at) will be set in most cases (at.Def == true)
365      if (at.Prec == 0)
366      {
367        it means that (Prec == 0) was returned for (kpidMTime),
368        and no value was returned for (kpidTimeType).
369        it can mean Windows precision or unknown precision.
370      }
371   */
372   HRESULT GetItem_MTime(UInt32 index, CArcTime &at) const;
373 
IsItem_Anti(UInt32 index,bool & result)374   HRESULT IsItem_Anti(UInt32 index, bool &result) const
375     { return Archive_GetItemBoolProp(Archive, index, kpidIsAnti, result); }
376 
377 
378   HRESULT OpenStream(const COpenOptions &options);
379   HRESULT OpenStreamOrFile(COpenOptions &options);
380 
381   HRESULT ReOpen(const COpenOptions &options, IArchiveOpenCallback *openCallback_Additional);
382 
383   HRESULT CreateNewTailStream(CMyComPtr<IInStream> &stream);
384 
IsHashHandler(const COpenOptions & options)385   bool IsHashHandler(const COpenOptions &options) const
386   {
387     if (FormatIndex < 0)
388       return false;
389     return options.codecs->Formats[(unsigned)FormatIndex].Flags_HashHandler();
390   }
391 };
392 
393 struct CArchiveLink
394 {
395   CObjectVector<CArc> Arcs;
396   UStringVector VolumePaths;
397   UInt64 VolumesSize;
398   bool IsOpen;
399 
400   bool PasswordWasAsked;
401   // UString Password;
402 
403   // int NonOpenErrorFormatIndex; // - 1 means no Error.
404   UString NonOpen_ArcPath;
405 
406   CArcErrorInfo NonOpen_ErrorInfo;
407 
408   // UString ErrorsText;
409   // void Set_ErrorsText();
410 
CArchiveLinkCArchiveLink411   CArchiveLink():
412       VolumesSize(0),
413       IsOpen(false),
414       PasswordWasAsked(false)
415       {}
416 
417   void KeepModeForNextOpen();
418   HRESULT Close();
419   void Release();
~CArchiveLinkCArchiveLink420   ~CArchiveLink() { Release(); }
421 
GetArcCArchiveLink422   const CArc *GetArc() const { return &Arcs.Back(); }
GetArchiveCArchiveLink423   IInArchive *GetArchive() const { return Arcs.Back().Archive; }
GetArchiveGetRawPropsCArchiveLink424   IArchiveGetRawProps *GetArchiveGetRawProps() const { return Arcs.Back().GetRawProps; }
GetArchiveGetRootPropsCArchiveLink425   IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; }
426 
427   /*
428   Open() opens archive and COpenOptions::callback
429   Open2() uses COpenCallbackImp that implements Volumes and password callback
430   Open3() calls Open2() and callbackUI->Open_Finished();
431   Open_Strict() returns S_FALSE also in case, if there is non-open expected nested archive.
432   */
433 
434   HRESULT Open(COpenOptions &options);
435   HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI);
436   HRESULT Open3(COpenOptions &options, IOpenCallbackUI *callbackUI);
437 
Open_StrictCArchiveLink438   HRESULT Open_Strict(COpenOptions &options, IOpenCallbackUI *callbackUI)
439   {
440     HRESULT result = Open3(options, callbackUI);
441     if (result == S_OK && NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
442       result = S_FALSE;
443     return result;
444   }
445 
446   HRESULT ReOpen(COpenOptions &options);
447 };
448 
449 bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);
450 
451 // bool IsHashType(const CObjectVector<COpenType> &types);
452 
453 
454 struct CDirPathSortPair
455 {
456   unsigned Len;
457   unsigned Index;
458 
459   void SetNumSlashes(const FChar *s);
460 
CompareCDirPathSortPair461   int Compare(const CDirPathSortPair &a) const
462   {
463     // We need sorting order where parent items will be after child items
464     if (Len < a.Len) return 1;
465     if (Len > a.Len) return -1;
466     if (Index < a.Index) return -1;
467     if (Index > a.Index) return 1;
468     return 0;
469   }
470 };
471 
472 #endif
473