mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-09 04:07:08 -06:00
9.11
This commit is contained in:
committed by
Kornel Lesiński
parent
db5eb6d638
commit
993daef9cb
@@ -44,6 +44,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break;
|
||||
case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break;
|
||||
case kpidMainSubfile: if (_db.MainSubfile >= 0) prop = (UInt32)_db.MainSubfile; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
|
||||
@@ -174,8 +174,9 @@ bool CompoundMsiNameToFileName(const UString &name, UString &resultName)
|
||||
return true;
|
||||
}
|
||||
|
||||
static UString ConvertName(const Byte *p)
|
||||
static UString ConvertName(const Byte *p, bool &isMsi)
|
||||
{
|
||||
isMsi = false;
|
||||
UString s;
|
||||
for (int i = 0; i < kNameSizeMax; i += 2)
|
||||
{
|
||||
@@ -186,10 +187,19 @@ static UString ConvertName(const Byte *p)
|
||||
}
|
||||
UString msiName;
|
||||
if (CompoundMsiNameToFileName(s, msiName))
|
||||
{
|
||||
isMsi = true;
|
||||
return msiName;
|
||||
}
|
||||
return CompoundNameToFileName(s);
|
||||
}
|
||||
|
||||
static UString ConvertName(const Byte *p)
|
||||
{
|
||||
bool isMsi;
|
||||
return ConvertName(p, isMsi);
|
||||
}
|
||||
|
||||
UString CDatabase::GetItemPath(UInt32 index) const
|
||||
{
|
||||
UString s;
|
||||
@@ -207,6 +217,7 @@ UString CDatabase::GetItemPath(UInt32 index) const
|
||||
|
||||
HRESULT CDatabase::Open(IInStream *inStream)
|
||||
{
|
||||
MainSubfile = -1;
|
||||
static const UInt32 kHeaderSize = 512;
|
||||
Byte p[kHeaderSize];
|
||||
RINOK(ReadStream_FALSE(inStream, p, kHeaderSize));
|
||||
@@ -353,7 +364,26 @@ HRESULT CDatabase::Open(IInStream *inStream)
|
||||
}
|
||||
}
|
||||
|
||||
return AddNode(-1, root.SonDid);
|
||||
RINOK(AddNode(-1, root.SonDid));
|
||||
|
||||
unsigned numCabs = 0;
|
||||
for (int i = 0; i < Refs.Size(); i++)
|
||||
{
|
||||
const CItem &item = Items[Refs[i].Did];
|
||||
if (item.IsDir() || numCabs > 1)
|
||||
continue;
|
||||
bool isMsiName;
|
||||
UString msiName = ConvertName(item.Name, isMsiName);
|
||||
if (isMsiName && msiName.Right(4).CompareNoCase(L".cab") == 0)
|
||||
{
|
||||
numCabs++;
|
||||
MainSubfile = i;
|
||||
}
|
||||
}
|
||||
if (numCabs > 1)
|
||||
MainSubfile = -1;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -88,6 +88,8 @@ public:
|
||||
int SectorSizeBits;
|
||||
int MiniSectorSizeBits;
|
||||
|
||||
Int32 MainSubfile;
|
||||
|
||||
void Clear();
|
||||
bool IsLargeStream(UInt64 size) const { return size >= LongStreamMinSize; }
|
||||
UString GetItemPath(UInt32 index) const;
|
||||
|
||||
@@ -68,10 +68,10 @@ struct CItem
|
||||
class CInArchive
|
||||
{
|
||||
CMyComPtr<IInStream> m_Stream;
|
||||
UInt64 m_Position;
|
||||
|
||||
HRESULT GetNextItemReal(bool &filled, CItem &itemInfo);
|
||||
public:
|
||||
UInt64 m_Position;
|
||||
HRESULT Open(IInStream *inStream);
|
||||
HRESULT GetNextItem(bool &filled, CItem &itemInfo);
|
||||
HRESULT SkipData(UInt64 dataSize);
|
||||
@@ -155,9 +155,9 @@ HRESULT CInArchive::GetNextItemReal(bool &filled, CItem &item)
|
||||
size_t processedSize = sizeof(header);
|
||||
item.HeaderPos = m_Position;
|
||||
RINOK(ReadStream(m_Stream, header, &processedSize));
|
||||
m_Position += processedSize;
|
||||
if (processedSize != sizeof(header))
|
||||
return S_OK;
|
||||
m_Position += processedSize;
|
||||
|
||||
char tempString[NHeader::kNameSize + 1];
|
||||
MyStrNCpy(tempString, cur, NHeader::kNameSize);
|
||||
@@ -212,14 +212,20 @@ class CHandler:
|
||||
{
|
||||
CObjectVector<CItem> _items;
|
||||
CMyComPtr<IInStream> _stream;
|
||||
Int32 _mainSubfile;
|
||||
UInt64 _phySize;
|
||||
public:
|
||||
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
|
||||
INTERFACE_IInArchive(;)
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
|
||||
};
|
||||
|
||||
static STATPROPSTG kArcProps[] =
|
||||
{
|
||||
{ NULL, kpidPhySize, VT_UI8}
|
||||
};
|
||||
|
||||
STATPROPSTG kProps[] =
|
||||
static STATPROPSTG kProps[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidSize, VT_UI8},
|
||||
@@ -227,7 +233,7 @@ STATPROPSTG kProps[] =
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps_NO
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
@@ -235,6 +241,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
{
|
||||
_mainSubfile = -1;
|
||||
CInArchive archive;
|
||||
if (archive.Open(stream) != S_OK)
|
||||
return S_FALSE;
|
||||
@@ -258,6 +265,8 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
return S_FALSE;
|
||||
if (!filled)
|
||||
break;
|
||||
if (item.Name.Left(5) == "data.")
|
||||
_mainSubfile = _items.Size();
|
||||
_items.Add(item);
|
||||
archive.SkipData(item.Size);
|
||||
if (openArchiveCallback != NULL)
|
||||
@@ -267,6 +276,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
}
|
||||
}
|
||||
_stream = stream;
|
||||
_phySize = archive.m_Position;
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
@@ -285,6 +295,18 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
switch(propID)
|
||||
{
|
||||
case kpidPhySize: prop = _phySize; break;
|
||||
case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
@@ -259,8 +259,9 @@ struct CSection
|
||||
// UInt16 NumRelocs;
|
||||
bool IsDebug;
|
||||
bool IsRealSect;
|
||||
bool IsAdditionalSection;
|
||||
|
||||
CSection(): IsRealSect(false), IsDebug(false) {}
|
||||
CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {}
|
||||
UInt64 GetPackSize() const { return PSize; }
|
||||
|
||||
void UpdateTotalSize(UInt32 &totalSize)
|
||||
@@ -448,6 +449,7 @@ struct CResItem
|
||||
bool IsBmp() const { return Type == 2; }
|
||||
bool IsIcon() const { return Type == 3; }
|
||||
bool IsString() const { return Type == 6; }
|
||||
bool IsRcData() const { return Type == 10; }
|
||||
};
|
||||
|
||||
struct CStringItem
|
||||
@@ -530,6 +532,7 @@ class CHandler:
|
||||
COptHeader _optHeader;
|
||||
UInt32 _totalSize;
|
||||
UInt32 _totalSizeLimited;
|
||||
Int32 _mainSubfile;
|
||||
|
||||
CRecordVector<CResItem> _items;
|
||||
CObjectVector<CStringItem> _strings;
|
||||
@@ -648,7 +651,7 @@ STATPROPSTG kArcProps[] =
|
||||
{ L"Stack Commit", kpidStackCommit, VT_UI8},
|
||||
{ L"Heap Reserve", kpidHeapReserve, VT_UI8},
|
||||
{ L"Heap Commit", kpidHeapCommit, VT_UI8},
|
||||
};
|
||||
};
|
||||
|
||||
STATPROPSTG kProps[] =
|
||||
{
|
||||
@@ -689,7 +692,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
case kpidLinkerVer:
|
||||
{
|
||||
CVersion v = { _optHeader.LinkerVerMajor, _optHeader.LinkerVerMinor };
|
||||
VerToProp(v, prop); break;
|
||||
VerToProp(v, prop);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -716,6 +719,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
case kpidStackCommit: prop = _optHeader.StackCommit; break;
|
||||
case kpidHeapReserve: prop = _optHeader.HeapReserve; break;
|
||||
case kpidHeapCommit: prop = _optHeader.HeapCommit; break;
|
||||
case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
@@ -1240,16 +1244,26 @@ HRESULT CHandler::OpenResources(int sectionIndex, IInStream *stream, IArchiveOpe
|
||||
{
|
||||
UInt32 mask = (1 << numBits) - 1;
|
||||
size_t end = ((maxOffset + mask) & ~mask);
|
||||
if (end < sect.VSize)
|
||||
if (end < sect.VSize && end <= sect.PSize)
|
||||
{
|
||||
CSection sect2;
|
||||
sect2.Flags = 0;
|
||||
|
||||
// we skip Zeros to start of aligned block
|
||||
size_t i;
|
||||
for (i = maxOffset; i < end; i++)
|
||||
if (_buf[i] != 0)
|
||||
break;
|
||||
if (i == end)
|
||||
maxOffset = end;
|
||||
|
||||
sect2.Pa = sect.Pa + (UInt32)maxOffset;
|
||||
sect2.Va = sect.Va + (UInt32)maxOffset;
|
||||
sect2.PSize = sect.VSize - (UInt32)maxOffset;
|
||||
sect2.VSize = sect2.PSize;
|
||||
sect2.Name = ".rsrc_1";
|
||||
sect2.Time = 0;
|
||||
sect2.IsAdditionalSection = true;
|
||||
_sections.Add(sect2);
|
||||
}
|
||||
}
|
||||
@@ -1262,6 +1276,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
const UInt32 kBufSize = 1 << 18;
|
||||
const UInt32 kSigSize = 2;
|
||||
|
||||
_mainSubfile = -1;
|
||||
|
||||
CByteBuffer buffer;
|
||||
buffer.SetCapacity(kBufSize);
|
||||
Byte *buf = buffer;
|
||||
@@ -1358,6 +1374,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
CSection s2;
|
||||
s2.Pa = s2.Va = limit;
|
||||
s2.PSize = s2.VSize = s.Pa - limit;
|
||||
s2.IsAdditionalSection = true;
|
||||
s2.Name = '[';
|
||||
s2.Name += GetDecString(num++);
|
||||
s2.Name += ']';
|
||||
@@ -1374,6 +1391,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
|
||||
_parseResources = true;
|
||||
|
||||
UInt64 mainSize = 0, mainSize2 = 0;
|
||||
for (int i = 0; i < _sections.Size(); i++)
|
||||
{
|
||||
const CSection § = _sections[i];
|
||||
@@ -1386,12 +1404,26 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
{
|
||||
_resourceFileName = GetUnicodeString(sect.Name);
|
||||
for (int j = 0; j < _items.Size(); j++)
|
||||
if (_items[j].Enabled)
|
||||
{
|
||||
const CResItem &item = _items[j];
|
||||
if (item.Enabled)
|
||||
{
|
||||
mixItem.ResourceIndex = j;
|
||||
mixItem.StringIndex = -1;
|
||||
if (item.IsRcData())
|
||||
{
|
||||
if (item.Size >= mainSize)
|
||||
{
|
||||
mainSize2 = mainSize;
|
||||
mainSize = item.Size;
|
||||
_mainSubfile = _mixItems.Size();
|
||||
}
|
||||
else if (item.Size >= mainSize2)
|
||||
mainSize2 = item.Size;
|
||||
}
|
||||
_mixItems.Add(mixItem);
|
||||
}
|
||||
}
|
||||
if (sect.PSize > sect.VSize)
|
||||
{
|
||||
int numBits = _optHeader.GetNumFileAlignBits();
|
||||
@@ -1410,6 +1442,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
sect2.VSize = sect2.PSize;
|
||||
sect2.Name = ".rsrc_2";
|
||||
sect2.Time = 0;
|
||||
sect2.IsAdditionalSection = true;
|
||||
_sections.Add(sect2);
|
||||
}
|
||||
}
|
||||
@@ -1422,8 +1455,21 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
}
|
||||
mixItem.StringIndex = -1;
|
||||
mixItem.ResourceIndex = -1;
|
||||
if (sect.IsAdditionalSection)
|
||||
{
|
||||
if (sect.PSize >= mainSize)
|
||||
{
|
||||
mainSize2 = mainSize;
|
||||
mainSize = sect.PSize;
|
||||
_mainSubfile = _mixItems.Size();
|
||||
}
|
||||
else
|
||||
mainSize2 = sect.PSize;
|
||||
}
|
||||
_mixItems.Add(mixItem);
|
||||
}
|
||||
if (mainSize2 >= (1 << 20) && mainSize < mainSize2 * 2)
|
||||
_mainSubfile = -1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
456
CPP/7zip/Archive/PpmdHandler.cpp
Executable file
456
CPP/7zip/Archive/PpmdHandler.cpp
Executable file
@@ -0,0 +1,456 @@
|
||||
/* PpmdHandler.c -- PPMd format handler
|
||||
2010-03-10 : Igor Pavlov : Public domain
|
||||
This code is based on:
|
||||
PPMd var.H (2001) / var.I (2002): Dmitry Shkarin : Public domain
|
||||
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
#include "../../../C/Alloc.h"
|
||||
#include "../../../C/Ppmd7.h"
|
||||
#include "../../../C/Ppmd8.h"
|
||||
|
||||
#include "Common/ComTry.h"
|
||||
#include "Common/IntToString.h"
|
||||
#include "Common/StringConvert.h"
|
||||
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "Windows/Time.h"
|
||||
|
||||
#include "../Common/CWrappers.h"
|
||||
#include "../Common/ProgressUtils.h"
|
||||
#include "../Common/RegisterArc.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
namespace NArchive {
|
||||
namespace NPpmd {
|
||||
|
||||
static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
|
||||
static void SzBigFree(void *, void *address) { BigFree(address); }
|
||||
static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
|
||||
|
||||
static const UInt32 kBufSize = (1 << 20);
|
||||
|
||||
struct CBuf
|
||||
{
|
||||
Byte *Buf;
|
||||
|
||||
CBuf(): Buf(0) {}
|
||||
~CBuf() { ::MidFree(Buf); }
|
||||
bool Alloc()
|
||||
{
|
||||
if (!Buf)
|
||||
Buf = (Byte *)::MidAlloc(kBufSize);
|
||||
return (Buf != 0);
|
||||
}
|
||||
};
|
||||
|
||||
static const UInt32 kHeaderSize = 16;
|
||||
static const UInt32 kSignature = 0x84ACAF8F;
|
||||
static const unsigned kNewHeaderVer = 8;
|
||||
|
||||
struct CItem
|
||||
{
|
||||
UInt32 Attrib;
|
||||
UInt32 Time;
|
||||
AString Name;
|
||||
|
||||
unsigned Order;
|
||||
unsigned MemInMB;
|
||||
unsigned Ver;
|
||||
unsigned Restor;
|
||||
|
||||
HRESULT ReadHeader(ISequentialInStream *s, UInt32 &headerSize);
|
||||
bool IsSupported() const { return Ver == 7 || (Ver == 8 && Restor <= 1); }
|
||||
};
|
||||
|
||||
HRESULT CItem::ReadHeader(ISequentialInStream *s, UInt32 &headerSize)
|
||||
{
|
||||
Byte h[kHeaderSize];
|
||||
RINOK(ReadStream_FALSE(s, h, kHeaderSize));
|
||||
if (GetUi32(h) != kSignature)
|
||||
return S_FALSE;
|
||||
Attrib = GetUi32(h + 4);
|
||||
Time = GetUi32(h + 12);
|
||||
|
||||
unsigned info = GetUi16(h + 8);
|
||||
Order = (info & 0xF) + 1;
|
||||
MemInMB = ((info >> 4) & 0xFF) + 1;
|
||||
Ver = info >> 12;
|
||||
|
||||
UInt32 nameLen = GetUi16(h + 10);
|
||||
Restor = nameLen >> 14;
|
||||
if (Restor > 2)
|
||||
return S_FALSE;
|
||||
if (Ver >= kNewHeaderVer)
|
||||
nameLen &= 0x3FFF;
|
||||
if (nameLen > (1 << 9))
|
||||
return S_FALSE;
|
||||
char *name = Name.GetBuffer(nameLen + 1);
|
||||
HRESULT res = ReadStream_FALSE(s, name, nameLen);
|
||||
name[nameLen] = 0;
|
||||
headerSize = kHeaderSize + nameLen;
|
||||
Name.ReleaseBuffer();
|
||||
return res;
|
||||
}
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
public IArchiveOpenSeq,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CItem _item;
|
||||
UInt32 _headerSize;
|
||||
UInt64 _packSize;
|
||||
bool _packSizeDefined;
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
|
||||
public:
|
||||
MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq)
|
||||
INTERFACE_IInArchive(;)
|
||||
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
|
||||
};
|
||||
|
||||
STATPROPSTG kProps[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidMTime, VT_FILETIME},
|
||||
{ NULL, kpidAttrib, VT_UI4},
|
||||
{ NULL, kpidMethod, VT_BSTR}
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps_NO_Table
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
switch(propID)
|
||||
{
|
||||
case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
{
|
||||
*numItems = 1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void UIntToString(AString &s, const char *prefix, unsigned value)
|
||||
{
|
||||
s += prefix;
|
||||
char temp[16];
|
||||
::ConvertUInt32ToString((UInt32)value, temp);
|
||||
s += temp;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch(propID)
|
||||
{
|
||||
case kpidPath: prop = MultiByteToUnicodeString(_item.Name, CP_ACP); break;
|
||||
case kpidMTime:
|
||||
{
|
||||
FILETIME utc;
|
||||
if (NTime::DosTimeToFileTime(_item.Time, utc))
|
||||
prop = utc;
|
||||
break;
|
||||
}
|
||||
case kpidAttrib: prop = _item.Attrib; break;
|
||||
case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;
|
||||
case kpidMethod:
|
||||
{
|
||||
AString s = "PPMd";
|
||||
s += (char)('A' + _item.Ver);
|
||||
UIntToString(s, ":o", _item.Order);
|
||||
UIntToString(s, ":mem", _item.MemInMB);
|
||||
s += 'm';
|
||||
if (_item.Ver >= kNewHeaderVer && _item.Restor != 0)
|
||||
UIntToString(s, ":r", _item.Restor);
|
||||
prop = s;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *)
|
||||
{
|
||||
return OpenSeq(stream);
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
HRESULT res;
|
||||
try
|
||||
{
|
||||
Close();
|
||||
res = _item.ReadHeader(stream, _headerSize);
|
||||
}
|
||||
catch(...) { res = S_FALSE; }
|
||||
if (res == S_OK)
|
||||
_stream = stream;
|
||||
else
|
||||
Close();
|
||||
return res;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_packSizeDefined = false;
|
||||
_stream.Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const UInt32 kTopValue = (1 << 24);
|
||||
static const UInt32 kBot = (1 << 15);
|
||||
|
||||
struct CRangeDecoder
|
||||
{
|
||||
IPpmd7_RangeDec s;
|
||||
UInt32 Range;
|
||||
UInt32 Code;
|
||||
UInt32 Low;
|
||||
CByteInBufWrap *Stream;
|
||||
|
||||
public:
|
||||
bool Init()
|
||||
{
|
||||
Code = 0;
|
||||
Low = 0;
|
||||
Range = 0xFFFFFFFF;
|
||||
for (int i = 0; i < 4; i++)
|
||||
Code = (Code << 8) | Stream->ReadByte();
|
||||
return Code < 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
void Normalize()
|
||||
{
|
||||
while ((Low ^ (Low + Range)) < kTopValue ||
|
||||
Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1))
|
||||
{
|
||||
Code = (Code << 8) | Stream->ReadByte();
|
||||
Range <<= 8;
|
||||
Low <<= 8;
|
||||
}
|
||||
}
|
||||
|
||||
CRangeDecoder();
|
||||
};
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
static UInt32 Range_GetThreshold(void *pp, UInt32 total)
|
||||
{
|
||||
CRangeDecoder *p = (CRangeDecoder *)pp;
|
||||
return p->Code / (p->Range /= total);
|
||||
}
|
||||
|
||||
static void Range_Decode(void *pp, UInt32 start, UInt32 size)
|
||||
{
|
||||
CRangeDecoder *p = (CRangeDecoder *)pp;
|
||||
start *= p->Range;
|
||||
p->Low += start;
|
||||
p->Code -= start;
|
||||
p->Range *= size;
|
||||
p->Normalize();
|
||||
}
|
||||
|
||||
static UInt32 Range_DecodeBit(void *pp, UInt32 size0)
|
||||
{
|
||||
CRangeDecoder *p = (CRangeDecoder *)pp;
|
||||
if (p->Code / (p->Range >>= 14) < size0)
|
||||
{
|
||||
Range_Decode(p, 0, size0);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Range_Decode(p, size0, (1 << 14) - size0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CRangeDecoder::CRangeDecoder()
|
||||
{
|
||||
s.GetThreshold = Range_GetThreshold;
|
||||
s.Decode = Range_Decode;
|
||||
s.DecodeBit = Range_DecodeBit;
|
||||
}
|
||||
|
||||
struct CPpmdCpp
|
||||
{
|
||||
unsigned Ver;
|
||||
CRangeDecoder _rc;
|
||||
CPpmd7 _ppmd7;
|
||||
CPpmd8 _ppmd8;
|
||||
|
||||
CPpmdCpp(unsigned version)
|
||||
{
|
||||
Ver = version;
|
||||
Ppmd7_Construct(&_ppmd7);
|
||||
Ppmd8_Construct(&_ppmd8);
|
||||
}
|
||||
|
||||
~CPpmdCpp()
|
||||
{
|
||||
Ppmd7_Free(&_ppmd7, &g_BigAlloc);
|
||||
Ppmd8_Free(&_ppmd8, &g_BigAlloc);
|
||||
}
|
||||
|
||||
bool Alloc(UInt32 memInMB)
|
||||
{
|
||||
memInMB <<= 20;
|
||||
if (Ver == 7)
|
||||
return Ppmd7_Alloc(&_ppmd7, memInMB, &g_BigAlloc) != 0;
|
||||
return Ppmd8_Alloc(&_ppmd8, memInMB, &g_BigAlloc) != 0;
|
||||
}
|
||||
|
||||
void Init(unsigned order, unsigned restor)
|
||||
{
|
||||
if (Ver == 7)
|
||||
Ppmd7_Init(&_ppmd7, order);
|
||||
else
|
||||
Ppmd8_Init(&_ppmd8, order, restor);;
|
||||
}
|
||||
|
||||
bool InitRc(CByteInBufWrap *inStream)
|
||||
{
|
||||
if (Ver == 7)
|
||||
{
|
||||
_rc.Stream = inStream;
|
||||
return _rc.Init();
|
||||
}
|
||||
else
|
||||
{
|
||||
_ppmd8.Stream.In = &inStream->p;
|
||||
return Ppmd8_RangeDec_Init(&_ppmd8) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsFinishedOK()
|
||||
{
|
||||
if (Ver == 7)
|
||||
return Ppmd7z_RangeDec_IsFinishedOK(&_rc);
|
||||
return Ppmd8_RangeDec_IsFinishedOK(&_ppmd8);
|
||||
}
|
||||
};
|
||||
|
||||
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback)
|
||||
{
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
|
||||
return E_INVALIDARG;
|
||||
|
||||
// extractCallback->SetTotal(_packSize);
|
||||
UInt64 currentTotalPacked = 0;
|
||||
RINOK(extractCallback->SetCompleted(¤tTotalPacked));
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
|
||||
if (!testMode && !realOutStream)
|
||||
return S_OK;
|
||||
|
||||
extractCallback->PrepareOperation(askMode);
|
||||
|
||||
CByteInBufWrap inBuf;
|
||||
if (!inBuf.Alloc(1 << 20))
|
||||
return E_OUTOFMEMORY;
|
||||
inBuf.Stream = _stream;
|
||||
|
||||
CBuf outBuf;
|
||||
if (!outBuf.Alloc())
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(extractCallback, true);
|
||||
|
||||
CPpmdCpp ppmd(_item.Ver);
|
||||
if (!ppmd.Alloc(_item.MemInMB))
|
||||
return E_OUTOFMEMORY;
|
||||
Int32 opRes = NExtract::NOperationResult::kUnSupportedMethod;
|
||||
if (_item.IsSupported())
|
||||
{
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
ppmd.Init(_item.Order, _item.Restor);
|
||||
inBuf.Init();
|
||||
UInt64 outSize = 0;
|
||||
if (ppmd.InitRc(&inBuf) && !inBuf.Extra && inBuf.Res == S_OK)
|
||||
for (;;)
|
||||
{
|
||||
lps->InSize = _packSize = inBuf.GetProcessed();
|
||||
lps->OutSize = outSize;
|
||||
RINOK(lps->SetCur());
|
||||
|
||||
size_t i;
|
||||
int sym = 0;
|
||||
|
||||
if (ppmd.Ver == 7)
|
||||
{
|
||||
for (i = 0; i < kBufSize; i++)
|
||||
{
|
||||
sym = Ppmd7_DecodeSymbol(&ppmd._ppmd7, &ppmd._rc.s);
|
||||
if (inBuf.Extra || sym < 0)
|
||||
break;
|
||||
outBuf.Buf[i] = (Byte)sym;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < kBufSize; i++)
|
||||
{
|
||||
sym = Ppmd8_DecodeSymbol(&ppmd._ppmd8);
|
||||
if (inBuf.Extra || sym < 0)
|
||||
break;
|
||||
outBuf.Buf[i] = (Byte)sym;
|
||||
}
|
||||
}
|
||||
|
||||
outSize += i;
|
||||
_packSize = _headerSize + inBuf.GetProcessed();
|
||||
_packSizeDefined = true;
|
||||
if (realOutStream)
|
||||
{
|
||||
RINOK(WriteStream(realOutStream, outBuf.Buf, i));
|
||||
}
|
||||
if (sym < 0)
|
||||
{
|
||||
if (sym == -1 && ppmd.IsFinishedOK())
|
||||
opRes = NExtract::NOperationResult::kOK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
RINOK(inBuf.Res);
|
||||
}
|
||||
realOutStream.Release();
|
||||
return extractCallback->SetOperationResult(opRes);
|
||||
}
|
||||
|
||||
static IInArchive *CreateArc() { return new CHandler; }
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ L"Ppmd", L"pmd", 0, 0xD, { 0x8F, 0xAF, 0xAC, 0x84 }, 4, false, CreateArc, 0 };
|
||||
|
||||
REGISTER_ARC(Ppmd)
|
||||
|
||||
}}
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "../../Compress/LzmaEncoder.h"
|
||||
#include "../../Compress/PpmdZip.h"
|
||||
|
||||
#include "../Common/InStreamWithCRC.h"
|
||||
|
||||
@@ -169,13 +170,14 @@ HRESULT CAddCommon::Compress(
|
||||
else
|
||||
{
|
||||
if (!_cryptoStreamSpec->Filter)
|
||||
{
|
||||
_cryptoStreamSpec->Filter = _filterSpec = new NCrypto::NZip::CEncoder;
|
||||
RINOK(_filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Length()));
|
||||
_filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Length());
|
||||
}
|
||||
UInt32 crc = 0;
|
||||
RINOK(GetStreamCRC(inStream, crc));
|
||||
RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
RINOK(_filterSpec->CryptoSetCRC(crc));
|
||||
RINOK(_filterSpec->WriteHeader(outStream));
|
||||
RINOK(_filterSpec->WriteHeader(outStream, crc));
|
||||
}
|
||||
RINOK(_cryptoStreamSpec->SetOutStream(outStream));
|
||||
outStreamReleaser.FilterCoder = _cryptoStreamSpec;
|
||||
@@ -235,6 +237,26 @@ HRESULT CAddCommon::Compress(
|
||||
numProps--;
|
||||
RINOK(_lzmaEncoder->SetCoderProperties(propIDs, props, numProps));
|
||||
}
|
||||
else if (method == NFileHeader::NCompressionMethod::kPPMd)
|
||||
{
|
||||
_compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_PPMd;
|
||||
NCompress::NPpmdZip::CEncoder *encoder = new NCompress::NPpmdZip::CEncoder();
|
||||
_compressEncoder = encoder;
|
||||
NWindows::NCOM::CPropVariant props[] =
|
||||
{
|
||||
// _options.Algo,
|
||||
_options.MemSize,
|
||||
_options.Order
|
||||
|
||||
};
|
||||
PROPID propIDs[] =
|
||||
{
|
||||
// NCoderPropID::kAlgorithm,
|
||||
NCoderPropID::kUsedMemorySize,
|
||||
NCoderPropID::kOrder
|
||||
};
|
||||
RINOK(encoder->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0])));
|
||||
}
|
||||
else
|
||||
{
|
||||
CMethodId methodId;
|
||||
|
||||
@@ -18,6 +18,9 @@ struct CCompressionMethodMode
|
||||
bool NumMatchFinderCyclesDefined;
|
||||
UInt32 NumMatchFinderCycles;
|
||||
UInt32 DicSize;
|
||||
UInt32 MemSize;
|
||||
UInt32 Order;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
UInt32 NumThreads;
|
||||
#endif
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "../../Compress/CopyCoder.h"
|
||||
#include "../../Compress/LzmaDecoder.h"
|
||||
#include "../../Compress/ImplodeDecoder.h"
|
||||
#include "../../Compress/PpmdZip.h"
|
||||
#include "../../Compress/ShrinkDecoder.h"
|
||||
|
||||
#include "../../Crypto/WzAes.h"
|
||||
@@ -595,6 +596,8 @@ HRESULT CZipDecoder::Decode(
|
||||
mi.Coder = new NCompress::NImplode::NDecoder::CCoder;
|
||||
else if (methodId == NFileHeader::NCompressionMethod::kLZMA)
|
||||
mi.Coder = new CLzmaDecoder;
|
||||
else if (methodId == NFileHeader::NCompressionMethod::kPPMd)
|
||||
mi.Coder = new NCompress::NPpmdZip::CDecoder(true);
|
||||
else
|
||||
{
|
||||
CMethodId szMethodID;
|
||||
|
||||
@@ -53,6 +53,9 @@ private:
|
||||
UInt32 m_NumPasses;
|
||||
UInt32 m_NumFastBytes;
|
||||
UInt32 m_NumMatchFinderCycles;
|
||||
UInt32 m_MemSize;
|
||||
UInt32 m_Order;
|
||||
|
||||
bool m_NumMatchFinderCyclesDefined;
|
||||
|
||||
bool m_ForceAesMode;
|
||||
@@ -77,6 +80,8 @@ private:
|
||||
m_DicSize =
|
||||
m_NumPasses =
|
||||
m_NumFastBytes =
|
||||
m_Order =
|
||||
m_MemSize =
|
||||
m_NumMatchFinderCycles = 0xFFFFFFFF;
|
||||
m_NumMatchFinderCyclesDefined = false;
|
||||
m_ForceAesMode = false;
|
||||
|
||||
@@ -51,6 +51,18 @@ static const UInt32 kLzmaDicSizeX5 = 1 << 24;
|
||||
static const UInt32 kLzmaDicSizeX7 = 1 << 25;
|
||||
static const UInt32 kLzmaDicSizeX9 = 1 << 26;
|
||||
|
||||
static const UInt32 kPpmdMemSizeX1 = (1 << 20);
|
||||
static const UInt32 kPpmdMemSizeX3 = (1 << 22);
|
||||
static const UInt32 kPpmdMemSizeX5 = (1 << 24);
|
||||
static const UInt32 kPpmdMemSizeX7 = (1 << 26);
|
||||
static const UInt32 kPpmdMemSizeX9 = (1 << 27);
|
||||
|
||||
static const UInt32 kPpmdOrderX1 = 4;
|
||||
static const UInt32 kPpmdOrderX3 = 6;
|
||||
static const UInt32 kPpmdOrderX5 = 8;
|
||||
static const UInt32 kPpmdOrderX7 = 10;
|
||||
static const UInt32 kPpmdOrderX9 = 16;
|
||||
|
||||
static const UInt32 kBZip2NumPassesX1 = 1;
|
||||
static const UInt32 kBZip2NumPassesX7 = 2;
|
||||
static const UInt32 kBZip2NumPassesX9 = 7;
|
||||
@@ -290,13 +302,14 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
(mainMethod == NFileHeader::NCompressionMethod::kDeflated64);
|
||||
bool isLZMA = (mainMethod == NFileHeader::NCompressionMethod::kLZMA);
|
||||
bool isLz = (isLZMA || isDeflate);
|
||||
bool isBZip2 = (mainMethod == NFileHeader::NCompressionMethod::kBZip2);
|
||||
options.NumPasses = m_NumPasses;
|
||||
options.DicSize = m_DicSize;
|
||||
options.NumFastBytes = m_NumFastBytes;
|
||||
options.NumMatchFinderCycles = m_NumMatchFinderCycles;
|
||||
options.NumMatchFinderCyclesDefined = m_NumMatchFinderCyclesDefined;
|
||||
options.Algo = m_Algo;
|
||||
options.MemSize = m_MemSize;
|
||||
options.Order = m_Order;
|
||||
#ifndef _7ZIP_ST
|
||||
options.NumThreads = _numThreads;
|
||||
#endif
|
||||
@@ -336,7 +349,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
options.Algo = (level >= 5 ? kLzAlgoX5 :
|
||||
kLzAlgoX1);
|
||||
}
|
||||
if (isBZip2)
|
||||
if (mainMethod == NFileHeader::NCompressionMethod::kBZip2)
|
||||
{
|
||||
if (options.NumPasses == 0xFFFFFFFF)
|
||||
options.NumPasses = (level >= 9 ? kBZip2NumPassesX9 :
|
||||
@@ -347,6 +360,26 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
(level >= 3 ? kBZip2DicSizeX3 :
|
||||
kBZip2DicSizeX1));
|
||||
}
|
||||
if (mainMethod == NFileHeader::NCompressionMethod::kPPMd)
|
||||
{
|
||||
if (options.MemSize == 0xFFFFFFFF)
|
||||
options.MemSize =
|
||||
(level >= 9 ? kPpmdMemSizeX9 :
|
||||
(level >= 7 ? kPpmdMemSizeX7 :
|
||||
(level >= 5 ? kPpmdMemSizeX5 :
|
||||
(level >= 3 ? kPpmdMemSizeX3 :
|
||||
kPpmdMemSizeX1))));
|
||||
|
||||
if (options.Order == 0xFFFFFFFF)
|
||||
options.Order =
|
||||
(level >= 9 ? kPpmdOrderX9 :
|
||||
(level >= 7 ? kPpmdOrderX7 :
|
||||
(level >= 5 ? kPpmdOrderX5 :
|
||||
(level >= 3 ? kPpmdOrderX3 :
|
||||
kPpmdOrderX1))));
|
||||
|
||||
options.Algo = 0;
|
||||
}
|
||||
|
||||
return Update(
|
||||
EXTERNAL_CODECS_VARS
|
||||
@@ -389,6 +422,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
|
||||
else if (m == L"DEFLATE64") m_MainMethod = NFileHeader::NCompressionMethod::kDeflated64;
|
||||
else if (m == L"BZIP2") m_MainMethod = NFileHeader::NCompressionMethod::kBZip2;
|
||||
else if (m == L"LZMA") m_MainMethod = NFileHeader::NCompressionMethod::kLZMA;
|
||||
else if (m == L"PPMD") m_MainMethod = NFileHeader::NCompressionMethod::kPPMd;
|
||||
else return E_INVALIDARG;
|
||||
}
|
||||
else if (prop.vt == VT_UI4)
|
||||
@@ -446,6 +480,18 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
|
||||
RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize));
|
||||
m_DicSize = dicSize;
|
||||
}
|
||||
else if (name.Left(3) == L"MEM")
|
||||
{
|
||||
UInt32 memSize = kPpmdMemSizeX5;
|
||||
RINOK(ParsePropDictionaryValue(name.Mid(3), prop, memSize));
|
||||
m_MemSize = memSize;
|
||||
}
|
||||
else if (name[0] == L'O')
|
||||
{
|
||||
UInt32 order = kPpmdOrderX5;
|
||||
RINOK(ParsePropValue(name.Mid(1), prop, order));
|
||||
m_Order = order;
|
||||
}
|
||||
else if (name.Left(4) == L"PASS")
|
||||
{
|
||||
UInt32 num = kDeflateNumPassesX9;
|
||||
|
||||
@@ -89,6 +89,7 @@ namespace NFileHeader
|
||||
const Byte kExtractVersion_BZip2 = 46;
|
||||
const Byte kExtractVersion_Aes = 51;
|
||||
const Byte kExtractVersion_LZMA = 63;
|
||||
const Byte kExtractVersion_PPMd = 63;
|
||||
|
||||
// const Byte kSupportedVersion = 20;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user