mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-08 02:07:06 -06:00
9.17
This commit is contained in:
committed by
Kornel Lesiński
parent
044e4bb741
commit
2eb60a0598
@@ -120,7 +120,7 @@ public:
|
||||
kUnsupportedVersion = 0,
|
||||
kUnsupported,
|
||||
kIncorrect,
|
||||
kEndOfData,
|
||||
kEndOfData
|
||||
} Cause;
|
||||
CInArchiveException(CCauseType cause): Cause(cause) {};
|
||||
};
|
||||
|
||||
@@ -19,32 +19,33 @@ struct CPropMap
|
||||
|
||||
CPropMap kPropMap[] =
|
||||
{
|
||||
{ NID::kName, NULL, kpidPath, VT_BSTR},
|
||||
{ NID::kSize, NULL, kpidSize, VT_UI8},
|
||||
{ NID::kPackInfo, NULL, kpidPackSize, VT_UI8},
|
||||
{ NID::kName, { NULL, kpidPath, VT_BSTR } },
|
||||
{ NID::kSize, { NULL, kpidSize, VT_UI8 } },
|
||||
{ NID::kPackInfo, { NULL, kpidPackSize, VT_UI8 } },
|
||||
|
||||
#ifdef _MULTI_PACK
|
||||
{ 100, L"Pack0", kpidPackedSize0, VT_UI8},
|
||||
{ 101, L"Pack1", kpidPackedSize1, VT_UI8},
|
||||
{ 102, L"Pack2", kpidPackedSize2, VT_UI8},
|
||||
{ 103, L"Pack3", kpidPackedSize3, VT_UI8},
|
||||
{ 104, L"Pack4", kpidPackedSize4, VT_UI8},
|
||||
{ 100, { L"Pack0", kpidPackedSize0, VT_UI8 } },
|
||||
{ 101, { L"Pack1", kpidPackedSize1, VT_UI8 } },
|
||||
{ 102, { L"Pack2", kpidPackedSize2, VT_UI8 } },
|
||||
{ 103, { L"Pack3", kpidPackedSize3, VT_UI8 } },
|
||||
{ 104, { L"Pack4", kpidPackedSize4, VT_UI8 } },
|
||||
#endif
|
||||
|
||||
{ NID::kCTime, NULL, kpidCTime, VT_FILETIME},
|
||||
{ NID::kMTime, NULL, kpidMTime, VT_FILETIME},
|
||||
{ NID::kATime, NULL, kpidATime, VT_FILETIME},
|
||||
{ NID::kWinAttributes, NULL, kpidAttrib, VT_UI4},
|
||||
{ NID::kStartPos, NULL, kpidPosition, VT_UI4},
|
||||
{ NID::kCTime, { NULL, kpidCTime, VT_FILETIME } },
|
||||
{ NID::kMTime, { NULL, kpidMTime, VT_FILETIME } },
|
||||
{ NID::kATime, { NULL, kpidATime, VT_FILETIME } },
|
||||
{ NID::kWinAttributes, { NULL, kpidAttrib, VT_UI4 } },
|
||||
{ NID::kStartPos, { NULL, kpidPosition, VT_UI4 } },
|
||||
|
||||
{ NID::kCRC, NULL, kpidCRC, VT_UI4},
|
||||
{ NID::kCRC, { NULL, kpidCRC, VT_UI4 } },
|
||||
|
||||
{ NID::kAnti, NULL, kpidIsAnti, VT_BOOL},
|
||||
{ NID::kAnti, { NULL, kpidIsAnti, VT_BOOL } }
|
||||
|
||||
#ifndef _SFX
|
||||
{ 97, NULL, kpidEncrypted, VT_BOOL},
|
||||
{ 98, NULL, kpidMethod, VT_BSTR},
|
||||
{ 99, NULL, kpidBlock, VT_UI4}
|
||||
,
|
||||
{ 97, { NULL,kpidEncrypted, VT_BOOL } },
|
||||
{ 98, { NULL,kpidMethod, VT_BSTR } },
|
||||
{ 99, { NULL,kpidBlock, VT_UI4 } }
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -264,7 +264,7 @@ struct CInArchiveException
|
||||
{
|
||||
kUnexpectedEndOfArchive = 0,
|
||||
kCRCError,
|
||||
kIncorrectArchive,
|
||||
kIncorrectArchive
|
||||
}
|
||||
Cause;
|
||||
CInArchiveException(CCauseType cause): Cause(cause) {};
|
||||
|
||||
@@ -9,18 +9,15 @@
|
||||
|
||||
#include "ChmIn.h"
|
||||
|
||||
namespace NArchive{
|
||||
namespace NChm{
|
||||
namespace NArchive {
|
||||
namespace NChm {
|
||||
|
||||
// define CHM_LOW, if you want to see low level items
|
||||
// #define CHM_LOW
|
||||
|
||||
static const GUID kChmLzxGuid =
|
||||
{ 0x7FC28940, 0x9D31, 0x11D0, 0x9B, 0x27, 0x00, 0xA0, 0xC9, 0x1E, 0x9C, 0x7C };
|
||||
static const GUID kHelp2LzxGuid =
|
||||
{ 0x0A9007C6, 0x4076, 0x11D3, 0x87, 0x89, 0x00, 0x00, 0xF8, 0x10, 0x57, 0x54 };
|
||||
static const GUID kDesGuid =
|
||||
{ 0x67F6E4A2, 0x60BF, 0x11D3, 0x85, 0x40, 0x00, 0xC0, 0x4F, 0x58, 0xC3, 0xCF };
|
||||
static const GUID kChmLzxGuid = { 0x7FC28940, 0x9D31, 0x11D0, { 0x9B, 0x27, 0x00, 0xA0, 0xC9, 0x1E, 0x9C, 0x7C } };
|
||||
static const GUID kHelp2LzxGuid = { 0x0A9007C6, 0x4076, 0x11D3, { 0x87, 0x89, 0x00, 0x00, 0xF8, 0x10, 0x57, 0x54 } };
|
||||
static const GUID kDesGuid = { 0x67F6E4A2, 0x60BF, 0x11D3, { 0x85, 0x40, 0x00, 0xC0, 0x4F, 0x58, 0xC3, 0xCF } };
|
||||
|
||||
static bool AreGuidsEqual(REFGUID g1, REFGUID g2)
|
||||
{
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Common/ComTry.h"
|
||||
#include "Common/StringToInt.h"
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Common/StringToInt.h"
|
||||
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "Windows/Time.h"
|
||||
@@ -25,10 +25,10 @@ namespace NFileHeader
|
||||
{
|
||||
namespace NMagic
|
||||
{
|
||||
extern const char *kMagic1 = "070701";
|
||||
extern const char *kMagic2 = "070702";
|
||||
extern const char *kMagic3 = "070707";
|
||||
extern const char *kEndName = "TRAILER!!!";
|
||||
const char *kMagic1 = "070701";
|
||||
const char *kMagic2 = "070702";
|
||||
const char *kMagic3 = "070707";
|
||||
const char *kEndName = "TRAILER!!!";
|
||||
|
||||
const Byte kMagicForRecord2[2] = { 0xC7, 0x71 };
|
||||
}
|
||||
|
||||
@@ -378,7 +378,7 @@ static const char *GetOS(Byte osId)
|
||||
if (g_OsPairs[i].Id == osId)
|
||||
return g_OsPairs[i].Name;
|
||||
return kUnknownOS;
|
||||
};
|
||||
}
|
||||
|
||||
static STATPROPSTG kProps[] =
|
||||
{
|
||||
@@ -400,7 +400,7 @@ public:
|
||||
static UInt16 Table[256];
|
||||
static void InitTable();
|
||||
|
||||
CCRC(): _value(0){};
|
||||
CCRC(): _value(0) {}
|
||||
void Init() { _value = 0; }
|
||||
void Update(const void *data, size_t size);
|
||||
UInt16 GetDigest() const { return _value; }
|
||||
@@ -460,7 +460,6 @@ public:
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
UInt32 GetCRC() const { return _crc.GetDigest(); }
|
||||
void InitCRC() { _crc.Init(); }
|
||||
|
||||
};
|
||||
|
||||
STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
|
||||
@@ -332,7 +332,7 @@ enum
|
||||
{
|
||||
kpidPrimary = kpidUserDefined,
|
||||
kpidBegChs,
|
||||
kpidEndChs,
|
||||
kpidEndChs
|
||||
};
|
||||
|
||||
STATPROPSTG kProps[] =
|
||||
|
||||
@@ -156,7 +156,7 @@ struct CMftRef
|
||||
#define ATNAME(n) ATTR_TYPE_ ## n
|
||||
#define DEF_ATTR_TYPE(v, n) ATNAME(n) = v
|
||||
|
||||
typedef enum
|
||||
enum
|
||||
{
|
||||
DEF_ATTR_TYPE(0x00, UNUSED),
|
||||
DEF_ATTR_TYPE(0x10, STANDARD_INFO),
|
||||
@@ -873,7 +873,7 @@ STDMETHODIMP CByteBufStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT DataParseExtents(int clusterSizeLog, const CObjectVector<CAttr> attrs,
|
||||
static HRESULT DataParseExtents(int clusterSizeLog, const CObjectVector<CAttr> &attrs,
|
||||
int attrIndex, int attrIndexLim, UInt64 numPhysClusters, CRecordVector<CExtent> &Extents)
|
||||
{
|
||||
CExtent e;
|
||||
@@ -969,6 +969,7 @@ struct CMftRec
|
||||
void ParseDataNames();
|
||||
HRESULT GetStream(IInStream *mainStream, int dataIndex,
|
||||
int clusterSizeLog, UInt64 numPhysClusters, IInStream **stream) const;
|
||||
int GetNumExtents(int dataIndex, int clusterSizeLog, UInt64 numPhysClusters) const;
|
||||
|
||||
UInt64 GetSize(int dataIndex) const { return DataAttrs[DataRefs[dataIndex].Start].GetSize(); }
|
||||
|
||||
@@ -1036,6 +1037,35 @@ HRESULT CMftRec::GetStream(IInStream *mainStream, int dataIndex,
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
int CMftRec::GetNumExtents(int dataIndex, int clusterSizeLog, UInt64 numPhysClusters) const
|
||||
{
|
||||
if (dataIndex < 0)
|
||||
return 0;
|
||||
{
|
||||
const CDataRef &ref = DataRefs[dataIndex];
|
||||
int numNonResident = 0;
|
||||
int i;
|
||||
for (i = ref.Start; i < ref.Start + ref.Num; i++)
|
||||
if (DataAttrs[i].NonResident)
|
||||
numNonResident++;
|
||||
|
||||
const CAttr &attr0 = DataAttrs[ref.Start];
|
||||
|
||||
if (numNonResident != 0 || ref.Num != 1)
|
||||
{
|
||||
if (numNonResident != ref.Num || !attr0.IsCompressionUnitSupported())
|
||||
return 0; // error;
|
||||
CRecordVector<CExtent> extents;
|
||||
if (DataParseExtents(clusterSizeLog, DataAttrs, ref.Start, ref.Start + ref.Num, numPhysClusters, extents) != S_OK)
|
||||
return 0; // error;
|
||||
return extents.Size() - 1;
|
||||
}
|
||||
// if (attr0.Data.GetCapacity() != 0)
|
||||
// return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool CMftRec::Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNumber,
|
||||
CObjectVector<CAttr> *attrs)
|
||||
{
|
||||
@@ -1425,7 +1455,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STATPROPSTG kProps[] =
|
||||
static const STATPROPSTG kProps[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidIsDir, VT_BOOL},
|
||||
@@ -1435,10 +1465,11 @@ STATPROPSTG kProps[] =
|
||||
{ NULL, kpidCTime, VT_FILETIME},
|
||||
{ NULL, kpidATime, VT_FILETIME},
|
||||
{ NULL, kpidAttrib, VT_UI4},
|
||||
{ NULL, kpidLinks, VT_UI4}
|
||||
{ NULL, kpidLinks, VT_UI4},
|
||||
{ NULL, kpidNumBlocks, VT_UI4}
|
||||
};
|
||||
|
||||
STATPROPSTG kArcProps[] =
|
||||
static const STATPROPSTG kArcProps[] =
|
||||
{
|
||||
{ NULL, kpidVolumeName, VT_BSTR},
|
||||
{ NULL, kpidFileSystem, VT_BSTR},
|
||||
@@ -1582,6 +1613,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
case kpidLinks: prop = rec.MyNumNameLinks; break;
|
||||
case kpidSize: if (data) prop = data->GetSize(); break;
|
||||
case kpidPackSize: if (data) prop = data->GetPackSize(); break;
|
||||
case kpidNumBlocks: if (data) prop = (UInt32)rec.GetNumExtents(item.DataIndex, Header.ClusterSizeLog, Header.NumClusters); break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
|
||||
@@ -98,7 +98,7 @@ void CDirLink::Parse(const Byte *p)
|
||||
{
|
||||
Va = Get32(p);
|
||||
Size = Get32(p + 4);
|
||||
};
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -991,7 +991,7 @@ bool CBitmapInfoHeader::Parse(const Byte *p, size_t size)
|
||||
Compression = Get32(p + 16);
|
||||
SizeImage = Get32(p + 20);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
static UInt32 GetImageSize(UInt32 xSize, UInt32 ySize, UInt32 bitCount)
|
||||
{
|
||||
|
||||
@@ -35,4 +35,3 @@ public:
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -202,7 +202,7 @@ enum EDescriptorType
|
||||
DESC_TYPE_UnallocatedSpace = 263,
|
||||
DESC_TYPE_SpaceBitmap = 264,
|
||||
DESC_TYPE_PartitionIntegrity = 265,
|
||||
DESC_TYPE_ExtendedFile = 266,
|
||||
DESC_TYPE_ExtendedFile = 266
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ static STATPROPSTG kArcProps[] =
|
||||
{ NULL, kpidCTime, VT_FILETIME},
|
||||
{ NULL, kpidMTime, VT_FILETIME},
|
||||
{ NULL, kpidComment, VT_BSTR},
|
||||
{ NULL, kpidUnpackVer, VT_BSTR},
|
||||
{ NULL, kpidIsVolume, VT_BOOL},
|
||||
{ NULL, kpidVolume, VT_UI4},
|
||||
{ NULL, kpidNumVolumes, VT_UI4}
|
||||
@@ -226,6 +227,28 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
}
|
||||
break;
|
||||
|
||||
case kpidUnpackVer:
|
||||
{
|
||||
UInt32 ver1 = _version >> 16;
|
||||
UInt32 ver2 = (_version >> 8) & 0xFF;
|
||||
UInt32 ver3 = (_version) & 0xFF;
|
||||
|
||||
char s[16];
|
||||
ConvertUInt32ToString(ver1, s);
|
||||
AString res = s;
|
||||
res += '.';
|
||||
ConvertUInt32ToString(ver2, s);
|
||||
res += s;
|
||||
if (ver3 != 0)
|
||||
{
|
||||
res += '.';
|
||||
ConvertUInt32ToString(ver3, s);
|
||||
res += s;
|
||||
}
|
||||
prop = res;
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidIsVolume:
|
||||
if (_xmls.Size() > 0)
|
||||
{
|
||||
@@ -303,8 +326,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
prop = _db.GetItemPath(realIndex);
|
||||
else
|
||||
{
|
||||
char sz[32];
|
||||
ConvertUInt64ToString(item.StreamIndex, sz);
|
||||
char sz[16];
|
||||
ConvertUInt32ToString(item.StreamIndex, sz);
|
||||
AString s = sz;
|
||||
while (s.Length() < _nameLenForStreams)
|
||||
s = '0' + s;
|
||||
@@ -342,8 +365,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
{
|
||||
case kpidPath:
|
||||
{
|
||||
char sz[32];
|
||||
ConvertUInt64ToString(_xmls[index].VolIndex, sz);
|
||||
char sz[16];
|
||||
ConvertUInt32ToString(_xmls[index].VolIndex, sz);
|
||||
prop = (AString)"[" + (AString)sz + "].xml";
|
||||
break;
|
||||
}
|
||||
@@ -379,8 +402,8 @@ public:
|
||||
|
||||
UString GetNextName(UInt32 index)
|
||||
{
|
||||
wchar_t s[32];
|
||||
ConvertUInt64ToString((index), s);
|
||||
wchar_t s[16];
|
||||
ConvertUInt32ToString(index, s);
|
||||
return _before + (UString)s + _after;
|
||||
}
|
||||
};
|
||||
@@ -426,6 +449,8 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
continue;
|
||||
return res;
|
||||
}
|
||||
_version = header.Version;
|
||||
_isOldVersion = header.IsOldVersion();
|
||||
if (firstVolumeIndex >= 0)
|
||||
if (!header.AreFromOnArchive(_volumes[firstVolumeIndex].Header))
|
||||
break;
|
||||
@@ -481,8 +506,8 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
_db.DetectPathMode();
|
||||
RINOK(_db.Sort(_db.SkipRoot));
|
||||
|
||||
wchar_t sz[32];
|
||||
ConvertUInt64ToString(_db.Streams.Size(), sz);
|
||||
wchar_t sz[16];
|
||||
ConvertUInt32ToString(_db.Streams.Size(), sz);
|
||||
_nameLenForStreams = MyStringLen(sz);
|
||||
|
||||
_xmlInComments = (_xmls.Size() == 1 && !_db.ShowImageNumber);
|
||||
|
||||
@@ -51,6 +51,8 @@ class CHandler:
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CDatabase _db;
|
||||
UInt32 _version;
|
||||
bool _isOldVersion;
|
||||
CObjectVector<CVolume> _volumes;
|
||||
CObjectVector<CXml> _xmls;
|
||||
int _nameLenForStreams;
|
||||
|
||||
@@ -264,9 +264,8 @@ static void GetStream(bool oldVersion, const Byte *p, CStreamInfo &s)
|
||||
if (oldVersion)
|
||||
{
|
||||
s.PartNumber = 1;
|
||||
s.RefCount = 1;
|
||||
// UInt32 id = Get32(p + 24);
|
||||
// UInt32 unknown = Get32(p + 28);
|
||||
s.Id = Get32(p + 24);
|
||||
s.RefCount = Get32(p + 28);
|
||||
memcpy(s.Hash, p + 32, kHashSize);
|
||||
}
|
||||
else
|
||||
@@ -384,31 +383,48 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
|
||||
DirProcessed += 8;
|
||||
return S_OK;
|
||||
}
|
||||
if ((len & 7) != 0 || len < 0x28 || rem < len)
|
||||
if ((len & 7) != 0 || rem < len)
|
||||
return S_FALSE;
|
||||
if (!IsOldVersion)
|
||||
if (len < 0x28)
|
||||
return S_FALSE;
|
||||
DirProcessed += (size_t)len;
|
||||
if (DirProcessed > DirSize)
|
||||
return S_FALSE;
|
||||
if (Get64(p + 8) == 0)
|
||||
int extraOffset = 0;
|
||||
if (IsOldVersion)
|
||||
{
|
||||
if (len < 0x40 || (/* Get32(p + 12) == 0 && */ Get32(p + 0x14) != 0))
|
||||
{
|
||||
extraOffset = 0x10;
|
||||
}
|
||||
}
|
||||
else if (Get64(p + 8) == 0)
|
||||
extraOffset = 0x24;
|
||||
if (extraOffset)
|
||||
{
|
||||
if (prevIndex == -1)
|
||||
return S_FALSE;
|
||||
|
||||
UInt32 fileNameLen = Get16(p + 0x24);
|
||||
UInt32 fileNameLen = Get16(p + extraOffset);
|
||||
if ((fileNameLen & 1) != 0)
|
||||
return S_FALSE;
|
||||
/* Probably different versions of ImageX can use different number of
|
||||
additional ZEROs. So we don't use exact check. */
|
||||
UInt32 fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2);
|
||||
if (((0x26 + fileNameLen2 + 6) & ~7) > len)
|
||||
if (((extraOffset + 2 + fileNameLen2 + 6) & ~7) > len)
|
||||
return S_FALSE;
|
||||
|
||||
UString name;
|
||||
RINOK(ReadName(p + 0x26, fileNameLen, name));
|
||||
RINOK(ReadName(p + extraOffset + 2, fileNameLen, name));
|
||||
|
||||
CItem &prevItem = Items[prevIndex];
|
||||
if (name.IsEmpty() && !prevItem.HasStream())
|
||||
memcpy(prevItem.Hash, p + 0x10, kHashSize);
|
||||
{
|
||||
if (IsOldVersion)
|
||||
prevItem.Id = Get32(p + 8);
|
||||
else
|
||||
memcpy(prevItem.Hash, p + 0x10, kHashSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
CItem item;
|
||||
@@ -416,7 +432,13 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
|
||||
item.CTime = prevItem.CTime;
|
||||
item.ATime = prevItem.ATime;
|
||||
item.MTime = prevItem.MTime;
|
||||
memcpy(item.Hash, p + 0x10, kHashSize);
|
||||
if (IsOldVersion)
|
||||
{
|
||||
item.Id = Get32(p + 8);
|
||||
memset(item.Hash, 0, kHashSize);
|
||||
}
|
||||
else
|
||||
memcpy(item.Hash, p + 0x10, kHashSize);
|
||||
item.Attrib = 0;
|
||||
item.Order = Order++;
|
||||
item.Parent = parent;
|
||||
@@ -425,30 +447,41 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
|
||||
pos += (size_t)len;
|
||||
continue;
|
||||
}
|
||||
if (len < kDirRecordSize)
|
||||
|
||||
UInt32 dirRecordSize = IsOldVersion ? kDirRecordSizeOld : kDirRecordSize;
|
||||
if (len < dirRecordSize)
|
||||
return S_FALSE;
|
||||
|
||||
CItem item;
|
||||
item.Attrib = Get32(p + 8);
|
||||
// item.SecurityId = Get32(p + 0xC);
|
||||
UInt64 subdirOffset = Get64(p + 0x10);
|
||||
GetFileTimeFromMem(p + 0x28, &item.CTime);
|
||||
GetFileTimeFromMem(p + 0x30, &item.ATime);
|
||||
GetFileTimeFromMem(p + 0x38, &item.MTime);
|
||||
memcpy(item.Hash, p + 0x40, kHashSize);
|
||||
UInt32 timeOffset = IsOldVersion ? 0x18: 0x28;
|
||||
GetFileTimeFromMem(p + timeOffset, &item.CTime);
|
||||
GetFileTimeFromMem(p + timeOffset + 8, &item.ATime);
|
||||
GetFileTimeFromMem(p + timeOffset + 16, &item.MTime);
|
||||
if (IsOldVersion)
|
||||
{
|
||||
item.Id = Get32(p + 0x10);
|
||||
memset(item.Hash, 0, kHashSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(item.Hash, p + 0x40, kHashSize);
|
||||
}
|
||||
// UInt32 numStreams = Get16(p + dirRecordSize - 6);
|
||||
UInt32 shortNameLen = Get16(p + dirRecordSize - 4);
|
||||
UInt32 fileNameLen = Get16(p + dirRecordSize - 2);
|
||||
|
||||
UInt32 shortNameLen = Get16(p + 98);
|
||||
UInt32 fileNameLen = Get16(p + 100);
|
||||
if ((shortNameLen & 1) != 0 || (fileNameLen & 1) != 0)
|
||||
return S_FALSE;
|
||||
|
||||
UInt32 shortNameLen2 = (shortNameLen == 0 ? shortNameLen : shortNameLen + 2);
|
||||
UInt32 fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2);
|
||||
|
||||
if (((kDirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7) > len)
|
||||
if (((dirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7) > len)
|
||||
return S_FALSE;
|
||||
|
||||
p += kDirRecordSize;
|
||||
p += dirRecordSize;
|
||||
|
||||
RINOK(ReadName(p, fileNameLen, item.Name));
|
||||
RINOK(ReadName(p + fileNameLen2, shortNameLen, item.ShortName));
|
||||
@@ -458,9 +491,9 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
|
||||
|
||||
/*
|
||||
// there are some extra data for some files.
|
||||
p -= kDirRecordSize;
|
||||
p += ((kDirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7);
|
||||
if (((kDirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7) != len)
|
||||
p -= dirRecordSize;
|
||||
p += ((dirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7);
|
||||
if (((dirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7) != len)
|
||||
p = p;
|
||||
*/
|
||||
|
||||
@@ -496,6 +529,29 @@ HRESULT CDatabase::ParseImageDirs(const CByteBuffer &buf, int parent)
|
||||
return S_FALSE;
|
||||
const Byte *p = DirData;
|
||||
UInt32 totalLength = Get32(p);
|
||||
if (IsOldVersion)
|
||||
{
|
||||
for (pos = 4;; pos += 8)
|
||||
{
|
||||
if (pos + 4 > DirSize)
|
||||
return S_FALSE;
|
||||
UInt32 n = Get32(p + pos);
|
||||
if (n == 0)
|
||||
break;
|
||||
if (pos + 8 > DirSize)
|
||||
return S_FALSE;
|
||||
totalLength += Get32(p + pos + 4);
|
||||
if (totalLength > DirSize)
|
||||
return S_FALSE;
|
||||
}
|
||||
pos += totalLength + 4;
|
||||
pos = (pos + 7) & ~(size_t)7;
|
||||
if (pos > DirSize)
|
||||
return S_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// UInt32 numEntries = Get32(p + 4);
|
||||
pos += 8;
|
||||
{
|
||||
@@ -511,7 +567,7 @@ HRESULT CDatabase::ParseImageDirs(const CByteBuffer &buf, int parent)
|
||||
sum += len;
|
||||
pos += 8;
|
||||
}
|
||||
pos += sum; // skip security descriptors
|
||||
pos += (size_t)sum; // skip security descriptors
|
||||
while ((pos & 7) != 0)
|
||||
pos++;
|
||||
if (pos != totalLength)
|
||||
@@ -524,6 +580,7 @@ HRESULT CDatabase::ParseImageDirs(const CByteBuffer &buf, int parent)
|
||||
else
|
||||
pos = totalLength;
|
||||
}
|
||||
}
|
||||
DirStartOffset = DirProcessed = pos;
|
||||
RINOK(ParseDirItem(pos, parent));
|
||||
if (DirProcessed == DirSize)
|
||||
@@ -580,8 +637,6 @@ HRESULT CHeader::Parse(const Byte *p)
|
||||
BootIndex = Get32(p + 0x48);
|
||||
IntegrityResource.Parse(p + offset + 0x4C);
|
||||
}
|
||||
if (IsOldVersion())
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -612,9 +667,18 @@ static HRESULT ReadStreams(bool oldVersion, IInStream *inStream, const CHeader &
|
||||
return (i == offsetBuf.GetCapacity()) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
static bool IsEmptySha(const Byte *data)
|
||||
{
|
||||
for (int i = 0; i < kHashSize; i++)
|
||||
if (data[i] != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
HRESULT CDatabase::Open(IInStream *inStream, const CHeader &h, CByteBuffer &xml, IArchiveOpenCallback *openCallback)
|
||||
{
|
||||
OpenCallback = openCallback;
|
||||
IsOldVersion = h.IsOldVersion();
|
||||
RINOK(UnpackData(inStream, h.XmlResource, h.IsLzxMode(), xml, NULL));
|
||||
RINOK(ReadStreams(h.IsOldVersion(), inStream, h, *this));
|
||||
bool needBootMetadata = !h.MetadataResource.IsEmpty();
|
||||
@@ -631,7 +695,8 @@ HRESULT CDatabase::Open(IInStream *inStream, const CHeader &h, CByteBuffer &xml,
|
||||
Byte hash[kHashSize];
|
||||
CByteBuffer metadata;
|
||||
RINOK(UnpackData(inStream, si.Resource, h.IsLzxMode(), metadata, hash));
|
||||
if (memcmp(hash, si.Hash, kHashSize) != 0)
|
||||
if (memcmp(hash, si.Hash, kHashSize) != 0 &&
|
||||
!(h.IsOldVersion() && IsEmptySha(si.Hash)))
|
||||
return S_FALSE;
|
||||
NumImages++;
|
||||
RINOK(ParseImageDirs(metadata, -(int)(++imageIndex)));
|
||||
@@ -660,12 +725,37 @@ static int CompareStreamsByPos(const CStreamInfo *p1, const CStreamInfo *p2, voi
|
||||
return MyCompare(p1->Resource.Offset, p2->Resource.Offset);
|
||||
}
|
||||
|
||||
static int CompareIDs(const int *p1, const int *p2, void *param)
|
||||
{
|
||||
const CRecordVector<CStreamInfo> &streams = *(const CRecordVector<CStreamInfo> *)param;
|
||||
return MyCompare(streams[*p1].Id, streams[*p2].Id);
|
||||
}
|
||||
|
||||
static int CompareHashRefs(const int *p1, const int *p2, void *param)
|
||||
{
|
||||
const CRecordVector<CStreamInfo> &streams = *(const CRecordVector<CStreamInfo> *)param;
|
||||
return memcmp(streams[*p1].Hash, streams[*p2].Hash, kHashSize);
|
||||
}
|
||||
|
||||
static int FindId(const CRecordVector<CStreamInfo> &streams,
|
||||
const CIntVector &sortedByHash, UInt32 id)
|
||||
{
|
||||
int left = 0, right = streams.Size();
|
||||
while (left != right)
|
||||
{
|
||||
int mid = (left + right) / 2;
|
||||
int streamIndex = sortedByHash[mid];
|
||||
UInt32 id2 = streams[streamIndex].Id;
|
||||
if (id == id2)
|
||||
return streamIndex;
|
||||
if (id < id2)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int FindHash(const CRecordVector<CStreamInfo> &streams,
|
||||
const CIntVector &sortedByHash, const Byte *hash)
|
||||
{
|
||||
@@ -712,7 +802,10 @@ HRESULT CDatabase::Sort(bool skipRootDir)
|
||||
{
|
||||
for (int i = 0; i < Streams.Size(); i++)
|
||||
sortedByHash.Add(i);
|
||||
sortedByHash.Sort(CompareHashRefs, &Streams);
|
||||
if (IsOldVersion)
|
||||
sortedByHash.Sort(CompareIDs, &Streams);
|
||||
else
|
||||
sortedByHash.Sort(CompareHashRefs, &Streams);
|
||||
}
|
||||
|
||||
for (int i = 0; i < Items.Size(); i++)
|
||||
@@ -720,7 +813,10 @@ HRESULT CDatabase::Sort(bool skipRootDir)
|
||||
CItem &item = Items[i];
|
||||
item.StreamIndex = -1;
|
||||
if (item.HasStream())
|
||||
item.StreamIndex = FindHash(Streams, sortedByHash, item.Hash);
|
||||
if (IsOldVersion)
|
||||
item.StreamIndex = FindId(Streams, sortedByHash, item.Id);
|
||||
else
|
||||
item.StreamIndex = FindHash(Streams, sortedByHash, item.Hash);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -155,8 +155,8 @@ struct CHeader
|
||||
bool IsSupported() const { return (!IsCompressed() || (Flags & NHeaderFlags::kLZX) != 0 || (Flags & NHeaderFlags::kXPRESS) != 0 ) ; }
|
||||
bool IsLzxMode() const { return (Flags & NHeaderFlags::kLZX) != 0; }
|
||||
bool IsSpanned() const { return (!IsCompressed() || (Flags & NHeaderFlags::kSpanned) != 0); }
|
||||
bool IsOldVersion() const { return (Version == 0x010A00); }
|
||||
bool IsNewVersion()const { return (Version > 0x010C00); }
|
||||
bool IsOldVersion() const { return (Version <= 0x010A00); }
|
||||
bool IsNewVersion() const { return (Version > 0x010C00); }
|
||||
|
||||
bool AreFromOnArchive(const CHeader &h)
|
||||
{
|
||||
@@ -172,11 +172,13 @@ struct CStreamInfo
|
||||
CResource Resource;
|
||||
UInt16 PartNumber;
|
||||
UInt32 RefCount;
|
||||
UInt32 Id;
|
||||
BYTE Hash[kHashSize];
|
||||
|
||||
void WriteTo(Byte *p) const;
|
||||
};
|
||||
|
||||
const UInt32 kDirRecordSizeOld = 62;
|
||||
const UInt32 kDirRecordSize = 102;
|
||||
|
||||
struct CItem
|
||||
@@ -186,25 +188,25 @@ struct CItem
|
||||
UInt32 Attrib;
|
||||
// UInt32 SecurityId;
|
||||
BYTE Hash[kHashSize];
|
||||
UInt32 Id;
|
||||
FILETIME CTime;
|
||||
FILETIME ATime;
|
||||
FILETIME MTime;
|
||||
// UInt32 ReparseTag;
|
||||
// UInt64 HardLink;
|
||||
// UInt16 NumStreams;
|
||||
// UInt16 ShortNameLen;
|
||||
int StreamIndex;
|
||||
int Parent;
|
||||
unsigned Order;
|
||||
bool HasMetadata;
|
||||
CItem(): HasMetadata(true), StreamIndex(-1) {}
|
||||
CItem(): HasMetadata(true), StreamIndex(-1), Id(0) {}
|
||||
bool IsDir() const { return HasMetadata && ((Attrib & 0x10) != 0); }
|
||||
bool HasStream() const
|
||||
{
|
||||
for (unsigned i = 0; i < kHashSize; i++)
|
||||
if (Hash[i] != 0)
|
||||
return true;
|
||||
return false;
|
||||
return Id != 0;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -228,6 +230,8 @@ public:
|
||||
bool SkipRoot;
|
||||
bool ShowImageNumber;
|
||||
|
||||
bool IsOldVersion;
|
||||
|
||||
UInt64 GetUnpackSize() const
|
||||
{
|
||||
UInt64 res = 0;
|
||||
@@ -253,6 +257,7 @@ public:
|
||||
|
||||
SkipRoot = true;
|
||||
ShowImageNumber = true;
|
||||
IsOldVersion = false;
|
||||
}
|
||||
|
||||
UString GetItemPath(int index) const;
|
||||
|
||||
@@ -146,6 +146,7 @@ HRESULT CAddCommon::Compress(
|
||||
opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default;
|
||||
if (inCrcStreamSpec != 0)
|
||||
RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
RINOK(outStream->SetSize(0));
|
||||
RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
if (_options.PasswordIsDefined)
|
||||
{
|
||||
@@ -218,7 +219,7 @@ HRESULT CAddCommon::Compress(
|
||||
_options.Algo,
|
||||
_options.DicSize,
|
||||
_options.NumFastBytes,
|
||||
(BSTR)(const wchar_t *)_options.MatchFinder,
|
||||
const_cast<BSTR>((const wchar_t *)_options.MatchFinder),
|
||||
_options.NumMatchFinderCycles
|
||||
};
|
||||
PROPID propIDs[] =
|
||||
@@ -373,7 +374,7 @@ HRESULT CAddCommon::Compress(
|
||||
RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize));
|
||||
}
|
||||
opRes.Method = method;
|
||||
return outStream->SetSize(opRes.PackSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -544,7 +544,17 @@ HRESULT CInArchive::FindCd(CCdInfo &cdInfo)
|
||||
UInt64 curPos = endPosition - bufSize + i;
|
||||
UInt64 cdEnd = cdInfo.Size + cdInfo.Offset;
|
||||
if (curPos != cdEnd)
|
||||
ArcInfo.Base = curPos - cdEnd;
|
||||
{
|
||||
/*
|
||||
if (cdInfo.Offset <= 16 && cdInfo.Size != 0)
|
||||
{
|
||||
// here we support some rare ZIP files with Central directory at the start
|
||||
ArcInfo.Base = 0;
|
||||
}
|
||||
else
|
||||
*/
|
||||
ArcInfo.Base = curPos - cdEnd;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/Alloc.h"
|
||||
|
||||
#include "Common/AutoPtr.h"
|
||||
#include "Common/Defs.h"
|
||||
#include "Common/StringConvert.h"
|
||||
@@ -16,6 +18,7 @@
|
||||
#ifndef _7ZIP_ST
|
||||
#include "../../Common/ProgressMt.h"
|
||||
#endif
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "../../Compress/CopyCoder.h"
|
||||
|
||||
@@ -798,6 +801,216 @@ static HRESULT Update2(
|
||||
#endif
|
||||
}
|
||||
|
||||
static const size_t kCacheBlockSize = (1 << 20);
|
||||
static const size_t kCacheSize = (kCacheBlockSize << 2);
|
||||
static const size_t kCacheMask = (kCacheSize - 1);
|
||||
|
||||
class CCacheOutStream:
|
||||
public IOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<IOutStream> _stream;
|
||||
Byte *_cache;
|
||||
UInt64 _virtPos;
|
||||
UInt64 _virtSize;
|
||||
UInt64 _phyPos;
|
||||
UInt64 _phySize; // <= _virtSize
|
||||
UInt64 _cachedPos; // (_cachedPos + _cachedSize) <= _virtSize
|
||||
size_t _cachedSize;
|
||||
|
||||
HRESULT MyWrite(size_t size);
|
||||
HRESULT MyWriteBlock()
|
||||
{
|
||||
return MyWrite(kCacheBlockSize - ((size_t)_cachedPos & (kCacheBlockSize - 1)));
|
||||
}
|
||||
HRESULT FlushCache();
|
||||
public:
|
||||
CCacheOutStream(): _cache(0) {}
|
||||
~CCacheOutStream();
|
||||
bool Allocate();
|
||||
HRESULT Init(IOutStream *stream);
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
STDMETHOD(SetSize)(UInt64 newSize);
|
||||
};
|
||||
|
||||
bool CCacheOutStream::Allocate()
|
||||
{
|
||||
if (!_cache)
|
||||
_cache = (Byte *)::MidAlloc(kCacheSize);
|
||||
return (_cache != NULL);
|
||||
}
|
||||
|
||||
HRESULT CCacheOutStream::Init(IOutStream *stream)
|
||||
{
|
||||
_virtPos = _phyPos = 0;
|
||||
_stream = stream;
|
||||
RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &_virtPos));
|
||||
RINOK(_stream->Seek(0, STREAM_SEEK_END, &_virtSize));
|
||||
RINOK(_stream->Seek(_virtPos, STREAM_SEEK_SET, &_virtPos));
|
||||
_phyPos = _virtPos;
|
||||
_phySize = _virtSize;
|
||||
_cachedPos = 0;
|
||||
_cachedSize = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CCacheOutStream::MyWrite(size_t size)
|
||||
{
|
||||
while (size != 0 && _cachedSize != 0)
|
||||
{
|
||||
if (_phyPos != _cachedPos)
|
||||
{
|
||||
RINOK(_stream->Seek(_cachedPos, STREAM_SEEK_SET, &_phyPos));
|
||||
}
|
||||
size_t pos = (size_t)_cachedPos & kCacheMask;
|
||||
size_t curSize = MyMin(kCacheSize - pos, _cachedSize);
|
||||
curSize = MyMin(curSize, size);
|
||||
RINOK(WriteStream(_stream, _cache + pos, curSize));
|
||||
_phyPos += curSize;
|
||||
if (_phySize < _phyPos)
|
||||
_phySize = _phyPos;
|
||||
_cachedPos += curSize;
|
||||
_cachedSize -= curSize;
|
||||
size -= curSize;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CCacheOutStream::FlushCache()
|
||||
{
|
||||
return MyWrite(_cachedSize);
|
||||
}
|
||||
|
||||
CCacheOutStream::~CCacheOutStream()
|
||||
{
|
||||
FlushCache();
|
||||
if (_virtSize != _phySize)
|
||||
_stream->SetSize(_virtSize);
|
||||
if (_virtPos != _phyPos)
|
||||
_stream->Seek(_virtPos, STREAM_SEEK_SET, NULL);
|
||||
::MidFree(_cache);
|
||||
}
|
||||
|
||||
STDMETHODIMP CCacheOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
|
||||
UInt64 zerosStart = _virtPos;
|
||||
if (_cachedSize != 0)
|
||||
{
|
||||
if (_virtPos < _cachedPos)
|
||||
{
|
||||
RINOK(FlushCache());
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt64 cachedEnd = _cachedPos + _cachedSize;
|
||||
if (cachedEnd < _virtPos)
|
||||
{
|
||||
if (cachedEnd < _phySize)
|
||||
{
|
||||
RINOK(FlushCache());
|
||||
}
|
||||
else
|
||||
zerosStart = cachedEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_cachedSize == 0 && _phySize < _virtPos)
|
||||
_cachedPos = zerosStart = _phySize;
|
||||
|
||||
if (zerosStart != _virtPos)
|
||||
{
|
||||
// write zeros to [cachedEnd ... _virtPos)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
UInt64 cachedEnd = _cachedPos + _cachedSize;
|
||||
size_t endPos = (size_t)cachedEnd & kCacheMask;
|
||||
size_t curSize = kCacheSize - endPos;
|
||||
if (curSize > _virtPos - cachedEnd)
|
||||
curSize = (size_t)(_virtPos - cachedEnd);
|
||||
if (curSize == 0)
|
||||
break;
|
||||
while (curSize > (kCacheSize - _cachedSize))
|
||||
{
|
||||
RINOK(MyWriteBlock());
|
||||
}
|
||||
memset(_cache + endPos, 0, curSize);
|
||||
_cachedSize += curSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (_cachedSize == 0)
|
||||
_cachedPos = _virtPos;
|
||||
|
||||
size_t pos = (size_t)_virtPos & kCacheMask;
|
||||
size = (UInt32)MyMin((size_t)size, kCacheSize - pos);
|
||||
UInt64 cachedEnd = _cachedPos + _cachedSize;
|
||||
if (_virtPos != cachedEnd) // _virtPos < cachedEnd
|
||||
size = (UInt32)MyMin((size_t)size, (size_t)(cachedEnd - _virtPos));
|
||||
else
|
||||
{
|
||||
// _virtPos == cachedEnd
|
||||
if (_cachedSize == kCacheSize)
|
||||
{
|
||||
RINOK(MyWriteBlock());
|
||||
}
|
||||
size_t startPos = (size_t)_cachedPos & kCacheMask;
|
||||
if (startPos > pos)
|
||||
size = (UInt32)MyMin((size_t)size, (size_t)(startPos - pos));
|
||||
_cachedSize += size;
|
||||
}
|
||||
memcpy(_cache + pos, data, size);
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
_virtPos += size;
|
||||
if (_virtSize < _virtPos)
|
||||
_virtSize = _virtPos;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCacheOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch(seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: _virtPos = offset; break;
|
||||
case STREAM_SEEK_CUR: _virtPos += offset; break;
|
||||
case STREAM_SEEK_END: _virtPos = _virtSize + offset; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (newPosition)
|
||||
*newPosition = _virtPos;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCacheOutStream::SetSize(UInt64 newSize)
|
||||
{
|
||||
_virtSize = newSize;
|
||||
if (newSize < _phySize)
|
||||
{
|
||||
RINOK(_stream->SetSize(newSize));
|
||||
_phySize = newSize;
|
||||
}
|
||||
if (newSize <= _cachedPos)
|
||||
{
|
||||
_cachedSize = 0;
|
||||
_cachedPos = newSize;
|
||||
}
|
||||
if (newSize < _cachedPos + _cachedSize)
|
||||
_cachedSize = (size_t)(newSize - _cachedPos);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT Update(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const CObjectVector<CItemEx> &inputItems,
|
||||
@@ -808,9 +1021,17 @@ HRESULT Update(
|
||||
IArchiveUpdateCallback *updateCallback)
|
||||
{
|
||||
CMyComPtr<IOutStream> outStream;
|
||||
RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream));
|
||||
if (!outStream)
|
||||
return E_NOTIMPL;
|
||||
{
|
||||
CMyComPtr<IOutStream> outStreamReal;
|
||||
seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStreamReal);
|
||||
if (!outStreamReal)
|
||||
return E_NOTIMPL;
|
||||
CCacheOutStream *cacheStream = new CCacheOutStream();
|
||||
outStream = cacheStream;
|
||||
if (!cacheStream->Allocate())
|
||||
return E_OUTOFMEMORY;
|
||||
RINOK(cacheStream->Init(outStreamReal));
|
||||
}
|
||||
|
||||
if (inArchive)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user