You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
437 lines
11 KiB
437 lines
11 KiB
// OpenArchive.h
|
|
|
|
#ifndef __OPEN_ARCHIVE_H
|
|
#define __OPEN_ARCHIVE_H
|
|
|
|
#include "../../../Windows/PropVariant.h"
|
|
|
|
#include "ArchiveOpenCallback.h"
|
|
#include "LoadCodecs.h"
|
|
#include "Property.h"
|
|
|
|
#ifndef _SFX
|
|
|
|
#define SUPPORT_ALT_STREAMS
|
|
|
|
#endif
|
|
|
|
HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw();
|
|
HRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw();
|
|
HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw();
|
|
HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw();
|
|
HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &deleted) throw();
|
|
|
|
#ifdef SUPPORT_ALT_STREAMS
|
|
int FindAltStreamColon_in_Path(const wchar_t *path);
|
|
#endif
|
|
|
|
/*
|
|
struct COptionalOpenProperties
|
|
{
|
|
UString FormatName;
|
|
CObjectVector<CProperty> Props;
|
|
};
|
|
*/
|
|
|
|
#ifdef _SFX
|
|
#define OPEN_PROPS_DECL
|
|
#else
|
|
#define OPEN_PROPS_DECL const CObjectVector<CProperty> *props;
|
|
// #define OPEN_PROPS_DECL , const CObjectVector<COptionalOpenProperties> *props
|
|
#endif
|
|
|
|
struct COpenSpecFlags
|
|
{
|
|
// bool CanReturnFull;
|
|
bool CanReturnFrontal;
|
|
bool CanReturnTail;
|
|
bool CanReturnMid;
|
|
|
|
bool CanReturn_NonStart() const { return CanReturnTail || CanReturnMid; }
|
|
|
|
COpenSpecFlags():
|
|
// CanReturnFull(true),
|
|
CanReturnFrontal(false),
|
|
CanReturnTail(false),
|
|
CanReturnMid(false)
|
|
{}
|
|
};
|
|
|
|
struct COpenType
|
|
{
|
|
int FormatIndex;
|
|
|
|
COpenSpecFlags SpecForcedType;
|
|
COpenSpecFlags SpecMainType;
|
|
COpenSpecFlags SpecWrongExt;
|
|
COpenSpecFlags SpecUnknownExt;
|
|
|
|
bool Recursive;
|
|
|
|
bool CanReturnArc;
|
|
bool CanReturnParser;
|
|
bool EachPos;
|
|
|
|
// bool SkipSfxStub;
|
|
// bool ExeAsUnknown;
|
|
|
|
bool ZerosTailIsAllowed;
|
|
|
|
bool MaxStartOffset_Defined;
|
|
UInt64 MaxStartOffset;
|
|
|
|
const COpenSpecFlags &GetSpec(bool isForced, bool isMain, bool isUnknown) const
|
|
{
|
|
return isForced ? SpecForcedType : (isMain ? SpecMainType : (isUnknown ? SpecUnknownExt : SpecWrongExt));
|
|
}
|
|
|
|
COpenType():
|
|
FormatIndex(-1),
|
|
Recursive(true),
|
|
EachPos(false),
|
|
CanReturnArc(true),
|
|
CanReturnParser(false),
|
|
// SkipSfxStub(true),
|
|
// ExeAsUnknown(true),
|
|
ZerosTailIsAllowed(false),
|
|
MaxStartOffset_Defined(false),
|
|
MaxStartOffset(0)
|
|
{
|
|
SpecForcedType.CanReturnFrontal = true;
|
|
SpecForcedType.CanReturnTail = true;
|
|
SpecForcedType.CanReturnMid = true;
|
|
|
|
SpecMainType.CanReturnFrontal = true;
|
|
|
|
SpecUnknownExt.CanReturnTail = true; // for sfx
|
|
SpecUnknownExt.CanReturnMid = true;
|
|
SpecUnknownExt.CanReturnFrontal = true; // for alt streams of sfx with pad
|
|
|
|
// ZerosTailIsAllowed = true;
|
|
}
|
|
};
|
|
|
|
struct COpenOptions
|
|
{
|
|
CCodecs *codecs;
|
|
COpenType openType;
|
|
const CObjectVector<COpenType> *types;
|
|
const CIntVector *excludedFormats;
|
|
|
|
IInStream *stream;
|
|
ISequentialInStream *seqStream;
|
|
IArchiveOpenCallback *callback;
|
|
COpenCallbackImp *callbackSpec;
|
|
OPEN_PROPS_DECL
|
|
// bool openOnlySpecifiedByExtension,
|
|
|
|
bool stdInMode;
|
|
UString filePath;
|
|
|
|
COpenOptions():
|
|
codecs(NULL),
|
|
types(NULL),
|
|
excludedFormats(NULL),
|
|
stream(NULL),
|
|
seqStream(NULL),
|
|
callback(NULL),
|
|
callbackSpec(NULL),
|
|
stdInMode(false)
|
|
{}
|
|
|
|
};
|
|
|
|
UInt32 GetOpenArcErrorFlags(const NWindows::NCOM::CPropVariant &prop, bool *isDefinedProp = NULL);
|
|
|
|
struct CArcErrorInfo
|
|
{
|
|
bool ThereIsTail;
|
|
bool UnexpecedEnd;
|
|
bool IgnoreTail; // all are zeros
|
|
// bool NonZerosTail;
|
|
bool ErrorFlags_Defined;
|
|
UInt32 ErrorFlags;
|
|
UInt32 WarningFlags;
|
|
int ErrorFormatIndex; // - 1 means no Error.
|
|
// if FormatIndex == ErrorFormatIndex, the archive is open with offset
|
|
UInt64 TailSize;
|
|
|
|
/* if CArc is Open OK with some format:
|
|
- ErrorFormatIndex shows error format index, if extension is incorrect
|
|
- other variables show message and warnings of archive that is open */
|
|
|
|
UString ErrorMessage;
|
|
UString WarningMessage;
|
|
|
|
// call IsArc_After_NonOpen only if Open returns S_FALSE
|
|
bool IsArc_After_NonOpen() const
|
|
{
|
|
return (ErrorFlags_Defined && (ErrorFlags & kpv_ErrorFlags_IsNotArc) == 0);
|
|
}
|
|
|
|
|
|
CArcErrorInfo():
|
|
ThereIsTail(false),
|
|
UnexpecedEnd(false),
|
|
IgnoreTail(false),
|
|
// NonZerosTail(false),
|
|
ErrorFlags_Defined(false),
|
|
ErrorFlags(0),
|
|
WarningFlags(0),
|
|
ErrorFormatIndex(-1),
|
|
TailSize(0)
|
|
{}
|
|
|
|
void ClearErrors();
|
|
|
|
void ClearErrors_Full()
|
|
{
|
|
ErrorFormatIndex = -1;
|
|
ClearErrors();
|
|
}
|
|
|
|
bool IsThereErrorOrWarning() const
|
|
{
|
|
return ErrorFlags != 0
|
|
|| WarningFlags != 0
|
|
|| NeedTailWarning()
|
|
|| UnexpecedEnd
|
|
|| !ErrorMessage.IsEmpty()
|
|
|| !WarningMessage.IsEmpty();
|
|
}
|
|
|
|
bool AreThereErrors() const { return ErrorFlags != 0 || UnexpecedEnd; }
|
|
bool AreThereWarnings() const { return WarningFlags != 0 || NeedTailWarning(); }
|
|
|
|
bool NeedTailWarning() const { return !IgnoreTail && ThereIsTail; }
|
|
|
|
UInt32 GetWarningFlags() const
|
|
{
|
|
UInt32 a = WarningFlags;
|
|
if (NeedTailWarning() && (ErrorFlags & kpv_ErrorFlags_DataAfterEnd) == 0)
|
|
a |= kpv_ErrorFlags_DataAfterEnd;
|
|
return a;
|
|
}
|
|
|
|
UInt32 GetErrorFlags() const
|
|
{
|
|
UInt32 a = ErrorFlags;
|
|
if (UnexpecedEnd)
|
|
a |= kpv_ErrorFlags_UnexpectedEnd;
|
|
return a;
|
|
}
|
|
};
|
|
|
|
struct CReadArcItem
|
|
{
|
|
UString Path; // Path from root (including alt stream name, if alt stream)
|
|
UStringVector PathParts; // without altStream name, path from root or from _baseParentFolder, if _use_baseParentFolder_mode
|
|
|
|
#ifdef SUPPORT_ALT_STREAMS
|
|
UString MainPath;
|
|
/* MainPath = Path for non-AltStream,
|
|
MainPath = Path of parent, if there is parent for AltStream. */
|
|
UString AltStreamName;
|
|
bool IsAltStream;
|
|
bool WriteToAltStreamIfColon;
|
|
#endif
|
|
|
|
bool IsDir;
|
|
bool MainIsDir;
|
|
UInt32 ParentIndex; // use it, if IsAltStream
|
|
|
|
#ifndef _SFX
|
|
bool _use_baseParentFolder_mode;
|
|
int _baseParentFolder;
|
|
#endif
|
|
|
|
CReadArcItem()
|
|
{
|
|
#ifdef SUPPORT_ALT_STREAMS
|
|
WriteToAltStreamIfColon = false;
|
|
#endif
|
|
|
|
#ifndef _SFX
|
|
_use_baseParentFolder_mode = false;
|
|
_baseParentFolder = -1;
|
|
#endif
|
|
}
|
|
};
|
|
|
|
class CArc
|
|
{
|
|
HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive);
|
|
HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset);
|
|
HRESULT OpenStream2(const COpenOptions &options);
|
|
|
|
#ifndef _SFX
|
|
// parts.Back() can contain alt stream name "nams:AltName"
|
|
HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const;
|
|
#endif
|
|
|
|
public:
|
|
CMyComPtr<IInArchive> Archive;
|
|
CMyComPtr<IInStream> InStream;
|
|
// we use InStream in 2 cases (ArcStreamOffset != 0):
|
|
// 1) if we use additional cache stream
|
|
// 2) we reopen sfx archive with CTailInStream
|
|
|
|
CMyComPtr<IArchiveGetRawProps> GetRawProps;
|
|
CMyComPtr<IArchiveGetRootProps> GetRootProps;
|
|
|
|
CArcErrorInfo ErrorInfo; // for OK archives
|
|
CArcErrorInfo NonOpen_ErrorInfo; // ErrorInfo for mainArchive (false OPEN)
|
|
|
|
UString Path;
|
|
UString filePath;
|
|
UString DefaultName;
|
|
int FormatIndex; // - 1 means Parser.
|
|
int SubfileIndex;
|
|
FILETIME MTime;
|
|
bool MTimeDefined;
|
|
|
|
Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler
|
|
UInt64 PhySize;
|
|
// UInt64 OkPhySize;
|
|
bool PhySizeDefined;
|
|
// bool OkPhySize_Defined;
|
|
UInt64 FileSize;
|
|
UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file
|
|
// bool offsetDefined;
|
|
|
|
UInt64 GetEstmatedPhySize() const { return PhySizeDefined ? PhySize : FileSize; }
|
|
|
|
UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler
|
|
Int64 GetGlobalOffset() const { return ArcStreamOffset + Offset; } // it's global offset of archive
|
|
|
|
// AString ErrorFlagsText;
|
|
|
|
bool IsParseArc;
|
|
|
|
bool IsTree;
|
|
bool IsReadOnly;
|
|
|
|
bool Ask_Deleted;
|
|
bool Ask_AltStream;
|
|
bool Ask_Aux;
|
|
bool Ask_INode;
|
|
|
|
bool IgnoreSplit; // don't try split handler
|
|
|
|
// void Set_ErrorFlagsText();
|
|
|
|
CArc():
|
|
MTimeDefined(false),
|
|
IsTree(false),
|
|
IsReadOnly(false),
|
|
Ask_Deleted(false),
|
|
Ask_AltStream(false),
|
|
Ask_Aux(false),
|
|
Ask_INode(false),
|
|
IgnoreSplit(false)
|
|
{}
|
|
|
|
HRESULT ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes);
|
|
|
|
// ~CArc();
|
|
|
|
HRESULT Close()
|
|
{
|
|
InStream.Release();
|
|
return Archive->Close();
|
|
}
|
|
|
|
HRESULT GetItemPath(UInt32 index, UString &result) const;
|
|
HRESULT GetDefaultItemPath(UInt32 index, UString &result) const;
|
|
|
|
// GetItemPath2 adds [DELETED] dir prefix for deleted items.
|
|
HRESULT GetItemPath2(UInt32 index, UString &result) const;
|
|
|
|
HRESULT GetItem(UInt32 index, CReadArcItem &item) const;
|
|
|
|
HRESULT GetItemSize(UInt32 index, UInt64 &size, bool &defined) const;
|
|
HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const;
|
|
HRESULT IsItemAnti(UInt32 index, bool &result) const
|
|
{ return Archive_GetItemBoolProp(Archive, index, kpidIsAnti, result); }
|
|
|
|
|
|
HRESULT OpenStream(const COpenOptions &options);
|
|
HRESULT OpenStreamOrFile(COpenOptions &options);
|
|
|
|
HRESULT ReOpen(const COpenOptions &options);
|
|
|
|
HRESULT CreateNewTailStream(CMyComPtr<IInStream> &stream);
|
|
};
|
|
|
|
struct CArchiveLink
|
|
{
|
|
CObjectVector<CArc> Arcs;
|
|
UStringVector VolumePaths;
|
|
UInt64 VolumesSize;
|
|
bool IsOpen;
|
|
|
|
bool PasswordWasAsked;
|
|
// UString Password;
|
|
|
|
// int NonOpenErrorFormatIndex; // - 1 means no Error.
|
|
UString NonOpen_ArcPath;
|
|
|
|
CArcErrorInfo NonOpen_ErrorInfo;
|
|
|
|
// UString ErrorsText;
|
|
// void Set_ErrorsText();
|
|
|
|
CArchiveLink():
|
|
VolumesSize(0),
|
|
IsOpen(false),
|
|
PasswordWasAsked(false)
|
|
{}
|
|
|
|
void KeepModeForNextOpen();
|
|
HRESULT Close();
|
|
void Release();
|
|
~CArchiveLink() { Release(); }
|
|
|
|
const CArc *GetArc() const { return &Arcs.Back(); }
|
|
IInArchive *GetArchive() const { return Arcs.Back().Archive; }
|
|
IArchiveGetRawProps *GetArchiveGetRawProps() const { return Arcs.Back().GetRawProps; }
|
|
IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; }
|
|
|
|
HRESULT Open(COpenOptions &options);
|
|
HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI);
|
|
HRESULT Open3(COpenOptions &options, IOpenCallbackUI *callbackUI);
|
|
|
|
HRESULT Open_Strict(COpenOptions &options, IOpenCallbackUI *callbackUI)
|
|
{
|
|
HRESULT result = Open3(options, callbackUI);
|
|
if (result == S_OK && NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
|
|
result = S_FALSE;
|
|
return result;
|
|
}
|
|
|
|
HRESULT ReOpen(COpenOptions &options);
|
|
};
|
|
|
|
bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);
|
|
|
|
|
|
struct CDirPathSortPair
|
|
{
|
|
unsigned Len;
|
|
unsigned Index;
|
|
|
|
void SetNumSlashes(const FChar *s);
|
|
|
|
int Compare(const CDirPathSortPair &a) const
|
|
{
|
|
// We need sorting order where parent items will be after child items
|
|
if (Len < a.Len) return 1;
|
|
if (Len > a.Len) return -1;
|
|
if (Index < a.Index) return -1;
|
|
if (Index > a.Index) return 1;
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
#endif
|