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