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 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 
     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 
     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 
     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 
    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 
    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 
    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
    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 
    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
    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 
    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 
    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 
    344 bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);
    345 
    346 #endif
    347