mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 21:14:58 -06:00
17.01
This commit is contained in:
@@ -370,6 +370,17 @@ HRESULT CEncoder::Encode(
|
||||
resetInitVector->ResetInitVector();
|
||||
}
|
||||
|
||||
{
|
||||
CMyComPtr<ICompressSetCoderPropertiesOpt> optProps;
|
||||
coder->QueryInterface(IID_ICompressSetCoderPropertiesOpt, (void **)&optProps);
|
||||
if (optProps)
|
||||
{
|
||||
PROPID propID = NCoderPropID::kExpectedDataSize;
|
||||
NWindows::NCOM::CPropVariant prop = (UInt64)unpackSize;
|
||||
RINOK(optProps->SetCoderPropertiesOpt(&propID, &prop, 1));
|
||||
}
|
||||
}
|
||||
|
||||
CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
|
||||
coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
|
||||
|
||||
@@ -380,7 +391,7 @@ HRESULT CEncoder::Encode(
|
||||
CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;
|
||||
CMyComPtr<ISequentialOutStream> dynOutStream(outStreamSpec);
|
||||
outStreamSpec->Init();
|
||||
writeCoderProperties->WriteCoderProperties(dynOutStream);
|
||||
RINOK(writeCoderProperties->WriteCoderProperties(dynOutStream));
|
||||
outStreamSpec->CopyToBuffer(props);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -80,14 +80,17 @@ STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSiz
|
||||
{
|
||||
if (_stream)
|
||||
{
|
||||
UInt32 processed2;
|
||||
RINOK(_stream->Read(data, size, &processed2));
|
||||
if (processed2 != 0)
|
||||
UInt32 cur = size;
|
||||
const UInt32 kMax = (UInt32)1 << 20;
|
||||
if (cur > kMax)
|
||||
cur = kMax;
|
||||
RINOK(_stream->Read(data, cur, &cur));
|
||||
if (cur != 0)
|
||||
{
|
||||
_crc = CrcUpdate(_crc, data, processed2);
|
||||
_pos += processed2;
|
||||
_crc = CrcUpdate(_crc, data, cur);
|
||||
_pos += cur;
|
||||
if (processedSize)
|
||||
*processedSize = processed2;
|
||||
*processedSize = cur;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -515,7 +515,7 @@ HRESULT COutArchive::EncodeStream(
|
||||
outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size()));
|
||||
// outFolders.NumUnpackStreamsVector.Add(1);
|
||||
UInt64 dataSize64 = data.Size();
|
||||
UInt64 unpackSize;
|
||||
UInt64 unpackSize = data.Size();
|
||||
RINOK(encoder.Encode(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
stream,
|
||||
|
||||
@@ -2171,6 +2171,7 @@ HRESULT Update(
|
||||
#endif
|
||||
}
|
||||
|
||||
curUnpackSize = sizeToEncode;
|
||||
|
||||
HRESULT encodeRes = encoder.Encode(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
@@ -2358,7 +2359,9 @@ HRESULT Update(
|
||||
inStreamSpec->Init(updateCallback, &indices[i], numSubFiles);
|
||||
|
||||
unsigned startPackIndex = newDatabase.PackSizes.Size();
|
||||
UInt64 curFolderUnpackSize;
|
||||
UInt64 curFolderUnpackSize = totalSize;
|
||||
// curFolderUnpackSize = (UInt64)(Int64)-1;
|
||||
|
||||
RINOK(encoder.Encode(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
solidInStream,
|
||||
|
||||
@@ -461,8 +461,8 @@ bool CHeader::Parse(const Byte *p)
|
||||
|
||||
if (Is64Bit())
|
||||
{
|
||||
HI_32(150, NumBlocks);
|
||||
// HI_32(154, NumBlocksSuper);
|
||||
HI_32(0x150, NumBlocks);
|
||||
// HI_32(0x154, NumBlocksSuper);
|
||||
HI_32(0x158, NumFreeBlocks);
|
||||
}
|
||||
|
||||
|
||||
@@ -2489,7 +2489,7 @@ void CInArchive::DetectNsisType(const CBlockHeader &bh, const Byte *p)
|
||||
if (c2 == NS_3_CODE_VAR)
|
||||
// if (c2 <= NS_3_CODE_SKIP && c2 != NS_3_CODE_SHELL && c2 != 1)
|
||||
{
|
||||
if ((strData[i+ 2] & 0x80) != 0)
|
||||
if ((strData[i + 2] & 0x80) != 0)
|
||||
{
|
||||
// const char *p2 = (const char *)(strData + i + 1);
|
||||
// p2 = p2;
|
||||
@@ -5048,6 +5048,12 @@ HRESULT CInArchive::Parse()
|
||||
DetectNsisType(bhEntries, _data + bhEntries.Offset);
|
||||
|
||||
Decoder.IsNsisDeflate = (NsisType != k_NsisType_Nsis3);
|
||||
|
||||
// some NSIS files (that are not detected as k_NsisType_Nsis3)
|
||||
// use original (non-NSIS) Deflate
|
||||
// How to detect these cases?
|
||||
|
||||
// Decoder.IsNsisDeflate = false;
|
||||
|
||||
|
||||
#ifdef NSIS_SCRIPT
|
||||
|
||||
@@ -341,15 +341,19 @@ bool CVolInfo::Parse(const Byte *p, unsigned size)
|
||||
struct CAttr
|
||||
{
|
||||
UInt32 Type;
|
||||
|
||||
Byte NonResident;
|
||||
|
||||
// Non-Resident
|
||||
Byte CompressionUnit;
|
||||
|
||||
// UInt32 Len;
|
||||
UString2 Name;
|
||||
// UInt16 Flags;
|
||||
// UInt16 Instance;
|
||||
CByteBuffer Data;
|
||||
Byte NonResident;
|
||||
|
||||
// Non-Resident
|
||||
Byte CompressionUnit;
|
||||
UInt64 LowVcn;
|
||||
UInt64 HighVcn;
|
||||
UInt64 AllocatedSize;
|
||||
@@ -408,15 +412,16 @@ UInt32 CAttr::Parse(const Byte *p, unsigned size)
|
||||
return 8; // required size is 4, but attributes are 8 bytes aligned. So we return 8
|
||||
if (size < 0x18)
|
||||
return 0;
|
||||
|
||||
PRF(printf(" T=%2X", Type));
|
||||
|
||||
UInt32 len = Get32(p + 0x04);
|
||||
UInt32 len = Get32(p + 4);
|
||||
PRF(printf(" L=%3d", len));
|
||||
if (len > size)
|
||||
return 0;
|
||||
if ((len & 7) != 0)
|
||||
return 0;
|
||||
NonResident = p[0x08];
|
||||
NonResident = p[8];
|
||||
{
|
||||
unsigned nameLen = p[9];
|
||||
UInt32 nameOffset = Get16(p + 0x0A);
|
||||
@@ -437,6 +442,7 @@ UInt32 CAttr::Parse(const Byte *p, unsigned size)
|
||||
|
||||
UInt32 dataSize;
|
||||
UInt32 offs;
|
||||
|
||||
if (NonResident)
|
||||
{
|
||||
if (len < 0x40)
|
||||
@@ -472,16 +478,19 @@ UInt32 CAttr::Parse(const Byte *p, unsigned size)
|
||||
{
|
||||
if (len < 0x18)
|
||||
return 0;
|
||||
PRF(printf(" RES"));
|
||||
dataSize = Get32(p + 0x10);
|
||||
PRF(printf(" dataSize=%3d", dataSize));
|
||||
offs = Get16(p + 0x14);
|
||||
G32(p + 0x10, dataSize);
|
||||
G16(p + 0x14, offs);
|
||||
// G16(p + 0x16, ResidentFlags);
|
||||
PRF(printf(" RES"));
|
||||
PRF(printf(" dataSize=%3d", dataSize));
|
||||
// PRF(printf(" ResFlags=%4X", ResidentFlags));
|
||||
}
|
||||
|
||||
if (offs > len || dataSize > len || len - dataSize < offs)
|
||||
return 0;
|
||||
|
||||
Data.CopyFrom(p + offs, dataSize);
|
||||
|
||||
#ifdef SHOW_DEBUG_INFO
|
||||
PRF(printf(" : "));
|
||||
for (unsigned i = 0; i < Data.Size(); i++)
|
||||
@@ -489,16 +498,19 @@ UInt32 CAttr::Parse(const Byte *p, unsigned size)
|
||||
PRF(printf(" %02X", (unsigned)Data[i]));
|
||||
}
|
||||
#endif
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
bool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax, unsigned compressionUnit) const
|
||||
{
|
||||
const Byte *p = Data;
|
||||
unsigned size = (unsigned)Data.Size();
|
||||
UInt64 vcn = LowVcn;
|
||||
UInt64 lcn = 0;
|
||||
UInt64 highVcn1 = HighVcn + 1;
|
||||
const UInt64 highVcn1 = HighVcn + 1;
|
||||
|
||||
if (LowVcn != extents.Back().Virt || highVcn1 > (UInt64)1 << 63)
|
||||
return false;
|
||||
|
||||
@@ -528,15 +540,30 @@ bool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax,
|
||||
if ((highVcn1 - vcn) < vSize)
|
||||
return false;
|
||||
|
||||
CExtent e;
|
||||
e.Virt = vcn;
|
||||
vcn += vSize;
|
||||
|
||||
num = (b >> 4) & 0xF;
|
||||
if (num > 8 || num > size)
|
||||
return false;
|
||||
CExtent e;
|
||||
e.Virt = vcn;
|
||||
|
||||
if (num == 0)
|
||||
{
|
||||
// Sparse
|
||||
|
||||
/* if Unit is compressed, it can have many Elements for each compressed Unit:
|
||||
and last Element for unit MUST be without LCN.
|
||||
Element 0: numCompressedClusters2, LCN_0
|
||||
Element 1: numCompressedClusters2, LCN_1
|
||||
...
|
||||
Last Element : (16 - total_clusters_in_previous_elements), no LCN
|
||||
*/
|
||||
|
||||
// sparse is not allowed for (compressionUnit == 0) ? Why ?
|
||||
if (compressionUnit == 0)
|
||||
return false;
|
||||
|
||||
e.Phy = kEmptyExtent;
|
||||
}
|
||||
else
|
||||
@@ -553,9 +580,10 @@ bool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax,
|
||||
return false;
|
||||
e.Phy = lcn;
|
||||
}
|
||||
|
||||
extents.Add(e);
|
||||
vcn += vSize;
|
||||
}
|
||||
|
||||
CExtent e;
|
||||
e.Phy = kEmptyExtent;
|
||||
e.Virt = vcn;
|
||||
@@ -563,10 +591,11 @@ bool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax,
|
||||
return (highVcn1 == vcn);
|
||||
}
|
||||
|
||||
|
||||
static const UInt64 kEmptyTag = (UInt64)(Int64)-1;
|
||||
|
||||
static const unsigned kNumCacheChunksLog = 1;
|
||||
static const size_t kNumCacheChunks = (1 << kNumCacheChunksLog);
|
||||
static const size_t kNumCacheChunks = (size_t)1 << kNumCacheChunksLog;
|
||||
|
||||
class CInStream:
|
||||
public IInStream,
|
||||
@@ -734,24 +763,27 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
|
||||
while (_curRem == 0)
|
||||
{
|
||||
UInt64 cacheTag = _virtPos >> _chunkSizeLog;
|
||||
UInt32 cacheIndex = (UInt32)cacheTag & (kNumCacheChunks - 1);
|
||||
const UInt64 cacheTag = _virtPos >> _chunkSizeLog;
|
||||
const size_t cacheIndex = (size_t)cacheTag & (kNumCacheChunks - 1);
|
||||
|
||||
if (_tags[cacheIndex] == cacheTag)
|
||||
{
|
||||
UInt32 chunkSize = (UInt32)1 << _chunkSizeLog;
|
||||
UInt32 offset = (UInt32)_virtPos & (chunkSize - 1);
|
||||
UInt32 cur = MyMin(chunkSize - offset, size);
|
||||
const size_t chunkSize = (size_t)1 << _chunkSizeLog;
|
||||
const size_t offset = (size_t)_virtPos & (chunkSize - 1);
|
||||
size_t cur = chunkSize - offset;
|
||||
if (cur > size)
|
||||
cur = size;
|
||||
memcpy(data, _outBuf + (cacheIndex << _chunkSizeLog) + offset, cur);
|
||||
*processedSize = cur;
|
||||
*processedSize = (UInt32)cur;
|
||||
_virtPos += cur;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
PRF2(printf("\nVirtPos = %6d", _virtPos));
|
||||
|
||||
UInt32 comprUnitSize = (UInt32)1 << CompressionUnit;
|
||||
UInt64 virtBlock = _virtPos >> BlockSizeLog;
|
||||
UInt64 virtBlock2 = virtBlock & ~((UInt64)comprUnitSize - 1);
|
||||
const UInt32 comprUnitSize = (UInt32)1 << CompressionUnit;
|
||||
const UInt64 virtBlock = _virtPos >> BlockSizeLog;
|
||||
const UInt64 virtBlock2 = virtBlock & ~((UInt64)comprUnitSize - 1);
|
||||
|
||||
unsigned left = 0, right = Extents.Size();
|
||||
for (;;)
|
||||
@@ -766,7 +798,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
}
|
||||
|
||||
bool isCompressed = false;
|
||||
UInt64 virtBlock2End = virtBlock2 + comprUnitSize;
|
||||
const UInt64 virtBlock2End = virtBlock2 + comprUnitSize;
|
||||
if (CompressionUnit != 0)
|
||||
for (unsigned i = left; i < Extents.Size(); i++)
|
||||
{
|
||||
@@ -802,7 +834,9 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
_curRem = next - _virtPos;
|
||||
break;
|
||||
}
|
||||
|
||||
bool thereArePhy = false;
|
||||
|
||||
for (unsigned i2 = left; i2 < Extents.Size(); i2++)
|
||||
{
|
||||
const CExtent &e = Extents[i2];
|
||||
@@ -814,6 +848,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!thereArePhy)
|
||||
{
|
||||
_curRem = (Extents[i + 1].Virt << BlockSizeLog) - _virtPos;
|
||||
@@ -823,6 +858,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
|
||||
size_t offs = 0;
|
||||
UInt64 curVirt = virtBlock2;
|
||||
|
||||
for (i = left; i < Extents.Size(); i++)
|
||||
{
|
||||
const CExtent &e = Extents[i];
|
||||
@@ -845,6 +881,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
_physPos += compressed;
|
||||
offs += compressed;
|
||||
}
|
||||
|
||||
size_t destLenMax = GetCuSize();
|
||||
size_t destLen = destLenMax;
|
||||
const UInt64 rem = Size - (virtBlock2 << BlockSizeLog);
|
||||
@@ -863,6 +900,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (size > _curRem)
|
||||
size = (UInt32)_curRem;
|
||||
HRESULT res = S_OK;
|
||||
@@ -913,6 +951,12 @@ static HRESULT DataParseExtents(unsigned clusterSizeLog, const CObjectVector<CAt
|
||||
|
||||
const CAttr &attr0 = attrs[attrIndex];
|
||||
|
||||
/*
|
||||
if (attrs[attrIndexLim - 1].HighVcn + 1 != (attr0.AllocatedSize >> clusterSizeLog))
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
if (attr0.AllocatedSize < attr0.Size ||
|
||||
(attrs[attrIndexLim - 1].HighVcn + 1) != (attr0.AllocatedSize >> clusterSizeLog) ||
|
||||
(attr0.AllocatedSize & ((1 << clusterSizeLog) - 1)) != 0)
|
||||
|
||||
@@ -1363,7 +1363,7 @@ static const Byte kProps[] =
|
||||
kpidCharacts,
|
||||
kpidSymLink,
|
||||
kpidHardLink,
|
||||
kpidCopyLink,
|
||||
kpidCopyLink
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ UInt64 Get64b(const Byte *p, bool be) { return be ? GetBe64(p) : GetUi64(p); }
|
||||
static const UInt32 kSignature32_LE = 0x73717368;
|
||||
static const UInt32 kSignature32_BE = 0x68737173;
|
||||
static const UInt32 kSignature32_LZ = 0x71736873;
|
||||
static const UInt32 kSignature32_B2 = 0x73687371;
|
||||
|
||||
#define kMethod_ZLIB 1
|
||||
#define kMethod_LZMA 2
|
||||
@@ -225,6 +226,7 @@ struct CHeader
|
||||
case kSignature32_LE: break;
|
||||
case kSignature32_BE: be = true; break;
|
||||
case kSignature32_LZ: SeveralMethods = true; break;
|
||||
case kSignature32_B2: SeveralMethods = true; be = true; break;
|
||||
default: return false;
|
||||
}
|
||||
GET_32 (4, NumInodes);
|
||||
@@ -2258,7 +2260,8 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
static const Byte k_Signature[] = {
|
||||
4, 'h', 's', 'q', 's',
|
||||
4, 's', 'q', 's', 'h',
|
||||
4, 's', 'h', 's', 'q' };
|
||||
4, 's', 'h', 's', 'q',
|
||||
4, 'q', 's', 'h', 's' };
|
||||
|
||||
REGISTER_ARC_I(
|
||||
"SquashFS", "squashfs", 0, 0xD2,
|
||||
|
||||
@@ -26,24 +26,25 @@ static void MyStrNCpy(char *dest, const char *src, unsigned size)
|
||||
}
|
||||
}
|
||||
|
||||
static bool OctalToNumber(const char *srcString, unsigned size, UInt64 &res)
|
||||
static bool OctalToNumber(const char *srcString, unsigned size, UInt64 &res, bool allowEmpty = false)
|
||||
{
|
||||
res = 0;
|
||||
char sz[32];
|
||||
MyStrNCpy(sz, srcString, size);
|
||||
sz[size] = 0;
|
||||
const char *end;
|
||||
unsigned i;
|
||||
for (i = 0; sz[i] == ' '; i++);
|
||||
if (sz[i] == 0)
|
||||
return allowEmpty;
|
||||
res = ConvertOctStringToUInt64(sz + i, &end);
|
||||
if (end == sz + i)
|
||||
return false;
|
||||
return (*end == ' ' || *end == 0);
|
||||
}
|
||||
|
||||
static bool OctalToNumber32(const char *srcString, unsigned size, UInt32 &res)
|
||||
static bool OctalToNumber32(const char *srcString, unsigned size, UInt32 &res, bool allowEmpty = false)
|
||||
{
|
||||
UInt64 res64;
|
||||
if (!OctalToNumber(srcString, size, res64))
|
||||
if (!OctalToNumber(srcString, size, res64, allowEmpty))
|
||||
return false;
|
||||
res = (UInt32)res64;
|
||||
return (res64 <= 0xFFFFFFFF);
|
||||
@@ -123,7 +124,8 @@ API_FUNC_IsArc IsArc_Tar(const Byte *p2, size_t size)
|
||||
p += NFileHeader::kNameSize;
|
||||
|
||||
UInt32 mode;
|
||||
CHECK(OctalToNumber32(p, 8, mode)); p += 8;
|
||||
// we allow empty Mode value for LongName prefix items
|
||||
CHECK(OctalToNumber32(p, 8, mode, true)); p += 8;
|
||||
|
||||
// if (!OctalToNumber32(p, 8, item.UID)) item.UID = 0;
|
||||
p += 8;
|
||||
@@ -194,7 +196,8 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
|
||||
(item.Name.Len() == NFileHeader::kNameSize ||
|
||||
item.Name.Len() == NFileHeader::kNameSize - 1);
|
||||
|
||||
RIF(OctalToNumber32(p, 8, item.Mode)); p += 8;
|
||||
// we allow empty Mode value for LongName prefix items
|
||||
RIF(OctalToNumber32(p, 8, item.Mode, true)); p += 8;
|
||||
|
||||
if (!OctalToNumber32(p, 8, item.UID)) item.UID = 0; p += 8;
|
||||
if (!OctalToNumber32(p, 8, item.GID)) item.GID = 0; p += 8;
|
||||
|
||||
@@ -7,8 +7,11 @@
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/Defs.h"
|
||||
#include "../../Common/IntToString.h"
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/StringToInt.h"
|
||||
|
||||
#include "../../Windows/PropVariant.h"
|
||||
#include "../../Windows/System.h"
|
||||
|
||||
#include "../Common/CWrappers.h"
|
||||
#include "../Common/ProgressUtils.h"
|
||||
@@ -33,9 +36,19 @@ namespace NXz {
|
||||
#define k_LZMA2_Name "LZMA2"
|
||||
|
||||
|
||||
struct CBlockInfo
|
||||
{
|
||||
unsigned StreamFlags;
|
||||
UInt64 PackPos;
|
||||
UInt64 PackSize; // pure value from Index record, it doesn't include pad zeros
|
||||
UInt64 UnpackPos;
|
||||
};
|
||||
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
public IArchiveOpenSeq,
|
||||
public IInArchiveGetStream,
|
||||
#ifndef EXTRACT_ONLY
|
||||
public IOutArchive,
|
||||
public ISetProperties,
|
||||
@@ -48,9 +61,7 @@ class CHandler:
|
||||
bool _isArc;
|
||||
bool _needSeekToStart;
|
||||
bool _phySize_Defined;
|
||||
|
||||
CMyComPtr<IInStream> _stream;
|
||||
CMyComPtr<ISequentialInStream> _seqStream;
|
||||
bool _firstBlockWasRead;
|
||||
|
||||
AString _methodsString;
|
||||
|
||||
@@ -58,8 +69,20 @@ class CHandler:
|
||||
|
||||
UInt32 _filterId;
|
||||
|
||||
UInt64 _numSolidBytes;
|
||||
|
||||
HRESULT SetSolidFromString(const UString &s);
|
||||
HRESULT SetSolidFromPROPVARIANT(const PROPVARIANT &value);
|
||||
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
|
||||
|
||||
void InitSolid()
|
||||
{
|
||||
_numSolidBytes = XZ_PROPS__BLOCK_SIZE__AUTO;
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
InitSolid();
|
||||
_filterId = 0;
|
||||
CMultiMethodProps::Init();
|
||||
}
|
||||
@@ -83,6 +106,7 @@ class CHandler:
|
||||
public:
|
||||
MY_QUERYINTERFACE_BEGIN2(IInArchive)
|
||||
MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq)
|
||||
MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream)
|
||||
#ifndef EXTRACT_ONLY
|
||||
MY_QUERYINTERFACE_ENTRY(IOutArchive)
|
||||
MY_QUERYINTERFACE_ENTRY(ISetProperties)
|
||||
@@ -92,22 +116,45 @@ public:
|
||||
|
||||
INTERFACE_IInArchive(;)
|
||||
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
INTERFACE_IOutArchive(;)
|
||||
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
|
||||
#endif
|
||||
|
||||
size_t _blocksArraySize;
|
||||
CBlockInfo *_blocks;
|
||||
UInt64 _maxBlocksSize;
|
||||
CMyComPtr<IInStream> _stream;
|
||||
CMyComPtr<ISequentialInStream> _seqStream;
|
||||
|
||||
CXzBlock _firstBlock;
|
||||
|
||||
CHandler();
|
||||
~CHandler();
|
||||
|
||||
HRESULT SeekToPackPos(UInt64 pos)
|
||||
{
|
||||
return _stream->Seek(pos, STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
};
|
||||
|
||||
CHandler::CHandler()
|
||||
|
||||
CHandler::CHandler():
|
||||
_blocks(NULL),
|
||||
_blocksArraySize(0)
|
||||
{
|
||||
#ifndef EXTRACT_ONLY
|
||||
Init();
|
||||
#endif
|
||||
}
|
||||
|
||||
CHandler::~CHandler()
|
||||
{
|
||||
MyFree(_blocks);
|
||||
}
|
||||
|
||||
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
@@ -120,7 +167,9 @@ static const Byte kArcProps[] =
|
||||
{
|
||||
kpidMethod,
|
||||
kpidNumStreams,
|
||||
kpidNumBlocks
|
||||
kpidNumBlocks,
|
||||
kpidClusterSize,
|
||||
kpidCharacts
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
@@ -177,7 +226,7 @@ static const CMethodNamePair g_NamePairs[] =
|
||||
{ XZ_ID_LZMA2, "LZMA2" }
|
||||
};
|
||||
|
||||
static AString GetMethodString(const CXzFilter &f)
|
||||
static void AddMethodString(AString &s, const CXzFilter &f)
|
||||
{
|
||||
const char *p = NULL;
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(g_NamePairs); i++)
|
||||
@@ -193,7 +242,7 @@ static AString GetMethodString(const CXzFilter &f)
|
||||
p = temp;
|
||||
}
|
||||
|
||||
AString s (p);
|
||||
s += p;
|
||||
|
||||
if (f.propsSize > 0)
|
||||
{
|
||||
@@ -210,13 +259,6 @@ static AString GetMethodString(const CXzFilter &f)
|
||||
s += ']';
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static void AddString(AString &dest, const AString &src)
|
||||
{
|
||||
dest.Add_Space_if_NotEmpty();
|
||||
dest += src;
|
||||
}
|
||||
|
||||
static const char * const kChecks[] =
|
||||
@@ -239,27 +281,24 @@ static const char * const kChecks[] =
|
||||
, NULL
|
||||
};
|
||||
|
||||
static AString GetCheckString(const CXzs &xzs)
|
||||
static void AddCheckString(AString &s, const CXzs &xzs)
|
||||
{
|
||||
size_t i;
|
||||
UInt32 mask = 0;
|
||||
for (i = 0; i < xzs.num; i++)
|
||||
mask |= ((UInt32)1 << XzFlags_GetCheckType(xzs.streams[i].flags));
|
||||
AString s;
|
||||
for (i = 0; i <= XZ_CHECK_MASK; i++)
|
||||
if (((mask >> i) & 1) != 0)
|
||||
{
|
||||
AString s2;
|
||||
s.Add_Space_if_NotEmpty();
|
||||
if (kChecks[i])
|
||||
s2 = kChecks[i];
|
||||
s += kChecks[i];
|
||||
else
|
||||
{
|
||||
s2 = "Check-";
|
||||
s2.Add_UInt32((UInt32)i);
|
||||
s += "Check-";
|
||||
s.Add_UInt32((UInt32)i);
|
||||
}
|
||||
AddString(s, s2);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
@@ -272,11 +311,26 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
case kpidNumStreams: if (_stat.NumStreams_Defined) prop = _stat.NumStreams; break;
|
||||
case kpidNumBlocks: if (_stat.NumBlocks_Defined) prop = _stat.NumBlocks; break;
|
||||
case kpidUnpackSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break;
|
||||
case kpidClusterSize: if (_stat.NumBlocks_Defined && _stat.NumBlocks > 1) prop = _maxBlocksSize; break;
|
||||
case kpidCharacts:
|
||||
if (_firstBlockWasRead)
|
||||
{
|
||||
AString s;
|
||||
if (XzBlock_HasPackSize(&_firstBlock))
|
||||
s.Add_OptSpaced("BlockPackSize");
|
||||
if (XzBlock_HasUnpackSize(&_firstBlock))
|
||||
s.Add_OptSpaced("BlockUnpackSize");
|
||||
if (!s.IsEmpty())
|
||||
prop = s;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;;
|
||||
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
|
||||
if (_stat.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;
|
||||
if (_stat.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;
|
||||
if (_stat.HeadersError) v |= kpv_ErrorFlags_HeadersError;
|
||||
@@ -284,6 +338,13 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
if (_stat.DataError) v |= kpv_ErrorFlags_DataError;
|
||||
if (_stat.CrcError) v |= kpv_ErrorFlags_CrcError;
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidMainSubfile:
|
||||
{
|
||||
// if (_blocks) prop = (UInt32)0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
@@ -409,9 +470,15 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal
|
||||
SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.vt, &isIndex, &headerSizeRes);
|
||||
if (res2 == SZ_OK && !isIndex)
|
||||
{
|
||||
_firstBlockWasRead = true;
|
||||
_firstBlock = block;
|
||||
|
||||
unsigned numFilters = XzBlock_GetNumFilters(&block);
|
||||
for (unsigned i = 0; i < numFilters; i++)
|
||||
AddString(_methodsString, GetMethodString(block.filters[i]));
|
||||
{
|
||||
_methodsString.Add_Space_if_NotEmpty();
|
||||
AddMethodString(_methodsString, block.filters[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -422,7 +489,7 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal
|
||||
RINOK(callback->SetTotal(NULL, &_stat.PhySize));
|
||||
}
|
||||
|
||||
CSeekInStreamWrap inStreamImp;;
|
||||
CSeekInStreamWrap inStreamImp;
|
||||
|
||||
inStreamImp.Init(inStream);
|
||||
|
||||
@@ -460,7 +527,64 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal
|
||||
_stat.NumBlocks = Xzs_GetNumBlocks(&xzs.p);
|
||||
_stat.NumBlocks_Defined = true;
|
||||
|
||||
AddString(_methodsString, GetCheckString(xzs.p));
|
||||
AddCheckString(_methodsString, xzs.p);
|
||||
|
||||
const size_t numBlocks = (size_t)_stat.NumBlocks + 1;
|
||||
const size_t bytesAlloc = numBlocks * sizeof(CBlockInfo);
|
||||
|
||||
if (bytesAlloc / sizeof(CBlockInfo) == _stat.NumBlocks + 1)
|
||||
{
|
||||
_blocks = (CBlockInfo *)MyAlloc(bytesAlloc);
|
||||
if (_blocks)
|
||||
{
|
||||
unsigned blockIndex = 0;
|
||||
UInt64 unpackPos = 0;
|
||||
|
||||
for (size_t si = xzs.p.num; si != 0;)
|
||||
{
|
||||
si--;
|
||||
const CXzStream &str = xzs.p.streams[si];
|
||||
UInt64 packPos = str.startOffset + XZ_STREAM_HEADER_SIZE;
|
||||
|
||||
for (size_t bi = 0; bi < str.numBlocks; bi++)
|
||||
{
|
||||
const CXzBlockSizes &bs = str.blocks[bi];
|
||||
const UInt64 packSizeAligned = bs.totalSize + ((0 - (unsigned)bs.totalSize) & 3);
|
||||
|
||||
if (bs.unpackSize != 0)
|
||||
{
|
||||
if (blockIndex >= _stat.NumBlocks)
|
||||
return E_FAIL;
|
||||
|
||||
CBlockInfo &block = _blocks[blockIndex++];
|
||||
block.StreamFlags = str.flags;
|
||||
block.PackSize = bs.totalSize; // packSizeAligned;
|
||||
block.PackPos = packPos;
|
||||
block.UnpackPos = unpackPos;
|
||||
}
|
||||
packPos += packSizeAligned;
|
||||
unpackPos += bs.unpackSize;
|
||||
if (_maxBlocksSize < bs.unpackSize)
|
||||
_maxBlocksSize = bs.unpackSize;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (blockIndex != _stat.NumBlocks)
|
||||
{
|
||||
// there are Empty blocks;
|
||||
}
|
||||
*/
|
||||
if (_stat.OutSize != unpackPos)
|
||||
return E_FAIL;
|
||||
CBlockInfo &block = _blocks[blockIndex++];
|
||||
block.StreamFlags = 0;
|
||||
block.PackSize = 0;
|
||||
block.PackPos = 0;
|
||||
block.UnpackPos = unpackPos;
|
||||
_blocksArraySize = blockIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -474,6 +598,8 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
@@ -499,39 +625,297 @@ STDMETHODIMP CHandler::Close()
|
||||
|
||||
_isArc = false;
|
||||
_needSeekToStart = false;
|
||||
|
||||
_phySize_Defined = false;
|
||||
_firstBlockWasRead = false;
|
||||
|
||||
_methodsString.Empty();
|
||||
_stream.Release();
|
||||
_seqStream.Release();
|
||||
|
||||
MyFree(_blocks);
|
||||
_blocks = NULL;
|
||||
_blocksArraySize = 0;
|
||||
_maxBlocksSize = 0;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
struct CXzUnpackerCPP2
|
||||
{
|
||||
Byte *InBuf;
|
||||
// Byte *OutBuf;
|
||||
CXzUnpacker p;
|
||||
|
||||
CXzUnpackerCPP2();
|
||||
~CXzUnpackerCPP2();
|
||||
};
|
||||
|
||||
CXzUnpackerCPP2::CXzUnpackerCPP2(): InBuf(NULL)
|
||||
// , OutBuf(NULL)
|
||||
{
|
||||
XzUnpacker_Construct(&p, &g_Alloc);
|
||||
}
|
||||
|
||||
CXzUnpackerCPP2::~CXzUnpackerCPP2()
|
||||
{
|
||||
XzUnpacker_Free(&p);
|
||||
MidFree(InBuf);
|
||||
// MidFree(OutBuf);
|
||||
}
|
||||
|
||||
|
||||
class CInStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
UInt64 _virtPos;
|
||||
UInt64 Size;
|
||||
UInt64 _cacheStartPos;
|
||||
size_t _cacheSize;
|
||||
CByteBuffer _cache;
|
||||
// UInt64 _startPos;
|
||||
CXzUnpackerCPP2 xz;
|
||||
|
||||
void InitAndSeek()
|
||||
{
|
||||
_virtPos = 0;
|
||||
_cacheStartPos = 0;
|
||||
_cacheSize = 0;
|
||||
// _startPos = startPos;
|
||||
}
|
||||
|
||||
CHandler *_handlerSpec;
|
||||
CMyComPtr<IUnknown> _handler;
|
||||
|
||||
MY_UNKNOWN_IMP1(IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
|
||||
~CInStream();
|
||||
};
|
||||
|
||||
|
||||
CInStream::~CInStream()
|
||||
{
|
||||
// _cache.Free();
|
||||
}
|
||||
|
||||
|
||||
size_t FindBlock(const CBlockInfo *blocks, size_t numBlocks, UInt64 pos)
|
||||
{
|
||||
size_t left = 0, right = numBlocks;
|
||||
for (;;)
|
||||
{
|
||||
size_t mid = (left + right) / 2;
|
||||
if (mid == left)
|
||||
return left;
|
||||
if (pos < blocks[mid].UnpackPos)
|
||||
right = mid;
|
||||
else
|
||||
left = mid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static HRESULT DecodeBlock(CXzUnpackerCPP2 &xzu,
|
||||
ISequentialInStream *seqInStream,
|
||||
unsigned streamFlags,
|
||||
UInt64 packSize, // pure size from Index record, it doesn't include pad zeros
|
||||
size_t unpackSize, Byte *dest
|
||||
// , ICompressProgressInfo *progress
|
||||
)
|
||||
{
|
||||
const size_t kInBufSize = (size_t)1 << 16;
|
||||
|
||||
XzUnpacker_Init(&xzu.p);
|
||||
|
||||
if (!xzu.InBuf)
|
||||
{
|
||||
xzu.InBuf = (Byte *)MidAlloc(kInBufSize);
|
||||
if (!xzu.InBuf)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
xzu.p.streamFlags = (UInt16)streamFlags;
|
||||
XzUnpacker_PrepareToRandomBlockDecoding(&xzu.p);
|
||||
|
||||
const UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);
|
||||
UInt64 packRem = packSizeAligned;
|
||||
|
||||
UInt32 inSize = 0;
|
||||
SizeT inPos = 0;
|
||||
SizeT outPos = 0;
|
||||
|
||||
HRESULT readRes = S_OK;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (inPos == inSize && readRes == S_OK)
|
||||
{
|
||||
inPos = 0;
|
||||
inSize = 0;
|
||||
UInt32 rem = kInBufSize;
|
||||
if (rem > packRem)
|
||||
rem = (UInt32)packRem;
|
||||
if (rem != 0)
|
||||
readRes = seqInStream->Read(xzu.InBuf, rem, &inSize);
|
||||
}
|
||||
|
||||
SizeT inLen = inSize - inPos;
|
||||
SizeT outLen = unpackSize - outPos;
|
||||
|
||||
ECoderStatus status;
|
||||
|
||||
SRes res = XzUnpacker_Code(&xzu.p,
|
||||
dest + outPos, &outLen,
|
||||
xzu.InBuf + inPos, &inLen,
|
||||
CODER_FINISH_END, &status);
|
||||
|
||||
// return E_OUTOFMEMORY;
|
||||
// res = SZ_ERROR_CRC;
|
||||
|
||||
if (res != SZ_OK)
|
||||
{
|
||||
if (res == SZ_ERROR_CRC)
|
||||
return S_FALSE;
|
||||
return SResToHRESULT(res);
|
||||
}
|
||||
|
||||
inPos += inLen;
|
||||
outPos += outLen;
|
||||
|
||||
packRem -= inLen;
|
||||
|
||||
Bool blockFinished = XzUnpacker_IsBlockFinished(&xzu.p);
|
||||
|
||||
if ((inLen == 0 && outLen == 0) || blockFinished)
|
||||
{
|
||||
if (packRem != 0 || !blockFinished || unpackSize != outPos)
|
||||
return S_FALSE;
|
||||
if (XzUnpacker_GetPackSizeForIndex(&xzu.p) != packSize)
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
|
||||
{
|
||||
if (_virtPos >= Size)
|
||||
return S_OK; // (Size == _virtPos) ? S_OK: E_FAIL;
|
||||
{
|
||||
UInt64 rem = Size - _virtPos;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
|
||||
if (_virtPos < _cacheStartPos || _virtPos >= _cacheStartPos + _cacheSize)
|
||||
{
|
||||
size_t bi = FindBlock(_handlerSpec->_blocks, _handlerSpec->_blocksArraySize, _virtPos);
|
||||
const CBlockInfo &block = _handlerSpec->_blocks[bi];
|
||||
const UInt64 unpackSize = _handlerSpec->_blocks[bi + 1].UnpackPos - block.UnpackPos;
|
||||
if (_cache.Size() < unpackSize)
|
||||
return E_FAIL;
|
||||
|
||||
_cacheSize = 0;
|
||||
|
||||
RINOK(_handlerSpec->SeekToPackPos(block.PackPos));
|
||||
RINOK(DecodeBlock(xz, _handlerSpec->_seqStream, block.StreamFlags, block.PackSize,
|
||||
(size_t)unpackSize, _cache));
|
||||
_cacheStartPos = block.UnpackPos;
|
||||
_cacheSize = (size_t)unpackSize;
|
||||
}
|
||||
|
||||
{
|
||||
size_t offset = (size_t)(_virtPos - _cacheStartPos);
|
||||
size_t rem = _cacheSize - offset;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
memcpy(data, _cache + offset, size);
|
||||
_virtPos += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _virtPos; break;
|
||||
case STREAM_SEEK_END: offset += Size; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_virtPos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = offset;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class CSeekToSeqStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
CMyComPtr<ISequentialInStream> Stream;
|
||||
MY_UNKNOWN_IMP1(IInStream)
|
||||
static const UInt64 kMaxBlockSize_for_GetStream = (UInt64)1 << 40;
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
};
|
||||
|
||||
STDMETHODIMP CSeekToSeqStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
{
|
||||
return Stream->Read(data, size, processedSize);
|
||||
COM_TRY_BEGIN
|
||||
|
||||
*stream = NULL;
|
||||
|
||||
if (index != 0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (!_stat.UnpackSize_Defined
|
||||
|| _maxBlocksSize > kMaxBlockSize_for_GetStream
|
||||
|| _maxBlocksSize != (size_t)_maxBlocksSize)
|
||||
return S_FALSE;
|
||||
|
||||
UInt64 physSize = (UInt64)(sizeof(size_t)) << 29;
|
||||
bool ramSize_Defined = NSystem::GetRamSize(physSize);
|
||||
if (ramSize_Defined)
|
||||
{
|
||||
if (_maxBlocksSize > physSize / 4)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
CInStream *spec = new CInStream;
|
||||
CMyComPtr<ISequentialInStream> specStream = spec;
|
||||
spec->_cache.Alloc((size_t)_maxBlocksSize);
|
||||
spec->_handlerSpec = this;
|
||||
spec->_handler = (IInArchive *)this;
|
||||
spec->Size = _stat.OutSize;
|
||||
spec->InitAndSeek();
|
||||
|
||||
*stream = specStream.Detach();
|
||||
return S_OK;
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CSeekToSeqStream::Seek(Int64, UInt32, UInt64 *) { return E_NOTIMPL; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -584,6 +968,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
|
||||
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
|
||||
@@ -592,16 +978,15 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
|
||||
IArchiveUpdateCallback *updateCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
|
||||
if (numItems == 0)
|
||||
{
|
||||
CSeqOutStreamWrap seqOutStream;
|
||||
|
||||
seqOutStream.Init(outStream);
|
||||
SRes res = Xz_EncodeEmpty(&seqOutStream.vt);
|
||||
return SResToHRESULT(res);
|
||||
@@ -641,82 +1026,76 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
|
||||
NCompress::NXz::CEncoder *encoderSpec = new NCompress::NXz::CEncoder;
|
||||
CMyComPtr<ICompressCoder> encoder = encoderSpec;
|
||||
CLzma2EncProps &lzma2Props = encoderSpec->_lzma2Props;
|
||||
|
||||
CXzProps &xzProps = encoderSpec->xzProps;
|
||||
CLzma2EncProps &lzma2Props = xzProps.lzma2Props;
|
||||
|
||||
lzma2Props.lzmaProps.level = GetLevel();
|
||||
|
||||
CMyComPtr<ISequentialInStream> fileInStream;
|
||||
RINOK(updateCallback->GetStream(0, &fileInStream));
|
||||
|
||||
xzProps.reduceSize = size;
|
||||
/*
|
||||
{
|
||||
NCOM::CPropVariant prop = (UInt64)size;
|
||||
RINOK(encoderSpec->SetCoderProp(NCoderPropID::kReduceSize, prop));
|
||||
}
|
||||
*/
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
xzProps.numTotalThreads = _numThreads;
|
||||
#endif
|
||||
|
||||
xzProps.blockSize = _numSolidBytes;
|
||||
if (_numSolidBytes == XZ_PROPS__BLOCK_SIZE__SOLID)
|
||||
{
|
||||
xzProps.lzma2Props.blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID;
|
||||
}
|
||||
|
||||
RINOK(encoderSpec->SetCheckSize(_crcSize));
|
||||
|
||||
{
|
||||
CXzFilterProps &filter = xzProps.filterProps;
|
||||
|
||||
if (_filterId == XZ_ID_Delta)
|
||||
{
|
||||
bool deltaDefined = false;
|
||||
FOR_VECTOR (j, _filterMethod.Props)
|
||||
{
|
||||
const CProp &prop = _filterMethod.Props[j];
|
||||
if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4)
|
||||
{
|
||||
UInt32 delta = (UInt32)prop.Value.ulVal;
|
||||
if (delta < 1 || delta > 256)
|
||||
return E_INVALIDARG;
|
||||
filter.delta = delta;
|
||||
deltaDefined = true;
|
||||
}
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
if (!deltaDefined)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
filter.id = _filterId;
|
||||
}
|
||||
|
||||
FOR_VECTOR (i, _methods)
|
||||
{
|
||||
COneMethodInfo &m = _methods[i];
|
||||
|
||||
/*
|
||||
SetGlobalLevelTo(m);
|
||||
#ifndef _7ZIP_ST
|
||||
CMultiMethodProps::SetMethodThreads(m, _numThreads);
|
||||
#endif
|
||||
*/
|
||||
|
||||
FOR_VECTOR (j, m.Props)
|
||||
{
|
||||
FOR_VECTOR (j, m.Props)
|
||||
{
|
||||
const CProp &prop = m.Props[j];
|
||||
RINOK(encoderSpec->SetCoderProp(prop.Id, prop.Value));
|
||||
}
|
||||
const CProp &prop = m.Props[j];
|
||||
RINOK(encoderSpec->SetCoderProp(prop.Id, prop.Value));
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
lzma2Props.numTotalThreads = _numThreads;
|
||||
#endif
|
||||
CMyComPtr<ISequentialInStream> fileInStream;
|
||||
RINOK(updateCallback->GetStream(0, &fileInStream));
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(updateCallback, true);
|
||||
|
||||
CXzProps &xzProps = encoderSpec->xzProps;
|
||||
CXzFilterProps &filter = encoderSpec->filter;
|
||||
|
||||
XzProps_Init(&xzProps);
|
||||
XzFilterProps_Init(&filter);
|
||||
|
||||
xzProps.lzma2Props = &lzma2Props;
|
||||
xzProps.filterProps = (_filterId != 0 ? &filter : NULL);
|
||||
switch (_crcSize)
|
||||
{
|
||||
case 0: xzProps.checkId = XZ_CHECK_NO; break;
|
||||
case 4: xzProps.checkId = XZ_CHECK_CRC32; break;
|
||||
case 8: xzProps.checkId = XZ_CHECK_CRC64; break;
|
||||
case 32: xzProps.checkId = XZ_CHECK_SHA256; break;
|
||||
default: return E_INVALIDARG;
|
||||
}
|
||||
filter.id = _filterId;
|
||||
if (_filterId == XZ_ID_Delta)
|
||||
{
|
||||
bool deltaDefined = false;
|
||||
FOR_VECTOR (j, _filterMethod.Props)
|
||||
{
|
||||
const CProp &prop = _filterMethod.Props[j];
|
||||
if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4)
|
||||
{
|
||||
UInt32 delta = (UInt32)prop.Value.ulVal;
|
||||
if (delta < 1 || delta > 256)
|
||||
return E_INVALIDARG;
|
||||
filter.delta = delta;
|
||||
deltaDefined = true;
|
||||
}
|
||||
}
|
||||
if (!deltaDefined)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
return encoderSpec->Code(fileInStream, outStream, NULL, NULL, progress);
|
||||
}
|
||||
|
||||
@@ -747,11 +1126,83 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
}
|
||||
|
||||
|
||||
HRESULT CHandler::SetSolidFromString(const UString &s)
|
||||
{
|
||||
UString s2 = s;
|
||||
s2.MakeLower_Ascii();
|
||||
|
||||
{
|
||||
const wchar_t *start = ((const wchar_t *)s2);
|
||||
const wchar_t *end;
|
||||
UInt64 v = ConvertStringToUInt64(start, &end);
|
||||
if (start == end)
|
||||
return E_INVALIDARG;
|
||||
if ((unsigned)(end - start) + 1 != s2.Len())
|
||||
return E_INVALIDARG;
|
||||
wchar_t c = *end;
|
||||
{
|
||||
unsigned numBits;
|
||||
switch (c)
|
||||
{
|
||||
case 'b': numBits = 0; break;
|
||||
case 'k': numBits = 10; break;
|
||||
case 'm': numBits = 20; break;
|
||||
case 'g': numBits = 30; break;
|
||||
case 't': numBits = 40; break;
|
||||
default: return E_INVALIDARG;
|
||||
}
|
||||
_numSolidBytes = (v << numBits);
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CHandler::SetSolidFromPROPVARIANT(const PROPVARIANT &value)
|
||||
{
|
||||
bool isSolid;
|
||||
switch (value.vt)
|
||||
{
|
||||
case VT_EMPTY: isSolid = true; break;
|
||||
case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break;
|
||||
case VT_BSTR:
|
||||
if (StringToBool(value.bstrVal, isSolid))
|
||||
break;
|
||||
return SetSolidFromString(value.bstrVal);
|
||||
default: return E_INVALIDARG;
|
||||
}
|
||||
_numSolidBytes = (isSolid ? XZ_PROPS__BLOCK_SIZE__SOLID : XZ_PROPS__BLOCK_SIZE__AUTO);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
|
||||
{
|
||||
UString name = nameSpec;
|
||||
name.MakeLower_Ascii();
|
||||
if (name.IsEmpty())
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (name[0] == L's')
|
||||
{
|
||||
name.Delete(0);
|
||||
if (name.IsEmpty())
|
||||
return SetSolidFromPROPVARIANT(value);
|
||||
if (value.vt != VT_EMPTY)
|
||||
return E_INVALIDARG;
|
||||
return SetSolidFromString(name);
|
||||
}
|
||||
|
||||
return CMultiMethodProps::SetProperty(name, value);
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
Init();
|
||||
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
RINOK(SetProperty(names[i], values[i]));
|
||||
@@ -781,7 +1232,9 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
|
||||
AString &methodName = _methods[0].MethodName;
|
||||
if (methodName.IsEmpty())
|
||||
methodName = k_LZMA2_Name;
|
||||
else if (!methodName.IsEqualTo_Ascii_NoCase(k_LZMA2_Name))
|
||||
else if (
|
||||
!methodName.IsEqualTo_Ascii_NoCase(k_LZMA2_Name)
|
||||
&& !methodName.IsEqualTo_Ascii_NoCase("xz"))
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ static const UInt32 kLzmaHeaderSize = 4 + kLzmaPropsSize;
|
||||
class CLzmaEncoder:
|
||||
public ICompressCoder,
|
||||
public ICompressSetCoderProperties,
|
||||
public ICompressSetCoderPropertiesOpt,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
@@ -46,8 +47,11 @@ public:
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
|
||||
STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
|
||||
|
||||
MY_UNKNOWN_IMP1(ICompressSetCoderProperties)
|
||||
MY_UNKNOWN_IMP2(
|
||||
ICompressSetCoderProperties,
|
||||
ICompressSetCoderPropertiesOpt)
|
||||
};
|
||||
|
||||
STDMETHODIMP CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
|
||||
@@ -71,6 +75,11 @@ STDMETHODIMP CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPV
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CLzmaEncoder::SetCoderPropertiesOpt(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
|
||||
{
|
||||
return EncoderSpec->SetCoderPropertiesOpt(propIDs, props, numProps);
|
||||
}
|
||||
|
||||
STDMETHODIMP CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
@@ -118,7 +127,8 @@ HRESULT CAddCommon::CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultC
|
||||
}
|
||||
|
||||
|
||||
HRESULT CAddCommon::Set_Pre_CompressionResult(bool seqMode, UInt64 unpackSize, CCompressingResult &opRes) const
|
||||
HRESULT CAddCommon::Set_Pre_CompressionResult(bool inSeqMode, bool outSeqMode, UInt64 unpackSize,
|
||||
CCompressingResult &opRes) const
|
||||
{
|
||||
// We use Zip64, if unPackSize size is larger than 0xF8000000 to support
|
||||
// cases when compressed size can be about 3% larger than uncompressed size
|
||||
@@ -144,7 +154,7 @@ HRESULT CAddCommon::Set_Pre_CompressionResult(bool seqMode, UInt64 unpackSize, C
|
||||
opRes.LzmaEos = false;
|
||||
|
||||
opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default;
|
||||
opRes.FileTimeWasUsed = false;
|
||||
opRes.DescriptorMode = outSeqMode;
|
||||
|
||||
if (_options.PasswordIsDefined)
|
||||
{
|
||||
@@ -153,8 +163,8 @@ HRESULT CAddCommon::Set_Pre_CompressionResult(bool seqMode, UInt64 unpackSize, C
|
||||
opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Aes;
|
||||
else
|
||||
{
|
||||
if (seqMode)
|
||||
opRes.FileTimeWasUsed = true;
|
||||
if (inSeqMode)
|
||||
opRes.DescriptorMode = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +197,8 @@ HRESULT CAddCommon::Set_Pre_CompressionResult(bool seqMode, UInt64 unpackSize, C
|
||||
HRESULT CAddCommon::Compress(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
ISequentialInStream *inStream, IOutStream *outStream,
|
||||
bool seqMode, UInt32 fileTime,
|
||||
bool inSeqMode, bool outSeqMode,
|
||||
UInt32 fileTime, UInt64 expectedDataSize,
|
||||
ICompressProgressInfo *progress, CCompressingResult &opRes)
|
||||
{
|
||||
opRes.LzmaEos = false;
|
||||
@@ -202,16 +213,31 @@ HRESULT CAddCommon::Compress(
|
||||
CMyComPtr<ISequentialInStream> inCrcStream = inSecCrcStreamSpec;
|
||||
|
||||
CMyComPtr<IInStream> inStream2;
|
||||
if (!seqMode)
|
||||
if (!inSeqMode)
|
||||
{
|
||||
inStream->QueryInterface(IID_IInStream, (void **)&inStream2);
|
||||
if (!inStream2)
|
||||
{
|
||||
// inSeqMode = true;
|
||||
// inSeqMode must be correct before
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
inSecCrcStreamSpec->SetStream(inStream);
|
||||
inSecCrcStreamSpec->Init();
|
||||
|
||||
unsigned numTestMethods = _options.MethodSequence.Size();
|
||||
|
||||
if (seqMode || (numTestMethods > 1 && !inStream2))
|
||||
numTestMethods = 1;
|
||||
|
||||
bool descriptorMode = outSeqMode;
|
||||
if (!outSeqMode)
|
||||
if (inSeqMode && _options.PasswordIsDefined && !_options.IsAesMode)
|
||||
descriptorMode = true;
|
||||
opRes.DescriptorMode = descriptorMode;
|
||||
|
||||
if (numTestMethods > 1)
|
||||
if (inSeqMode || outSeqMode || !inStream2)
|
||||
numTestMethods = 1;
|
||||
|
||||
UInt32 crc = 0;
|
||||
bool crc_IsCalculated = false;
|
||||
@@ -219,19 +245,23 @@ HRESULT CAddCommon::Compress(
|
||||
Byte method = 0;
|
||||
CFilterCoder::C_OutStream_Releaser outStreamReleaser;
|
||||
opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default;
|
||||
opRes.FileTimeWasUsed = false;
|
||||
|
||||
for (unsigned i = 0; i < numTestMethods; i++)
|
||||
{
|
||||
opRes.LzmaEos = false;
|
||||
opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default;
|
||||
if (inStream2 && i != 0)
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
inSecCrcStreamSpec->Init();
|
||||
RINOK(inStream2->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
if (inStream2)
|
||||
{
|
||||
inSecCrcStreamSpec->Init();
|
||||
RINOK(inStream2->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
|
||||
RINOK(outStream->SetSize(0));
|
||||
RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
RINOK(outStream->SetSize(0));
|
||||
RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
|
||||
if (_options.PasswordIsDefined)
|
||||
{
|
||||
@@ -264,7 +294,12 @@ HRESULT CAddCommon::Compress(
|
||||
|
||||
UInt32 check;
|
||||
|
||||
if (inStream2)
|
||||
if (descriptorMode)
|
||||
{
|
||||
// it's Info-ZIP modification for stream_mode descriptor_mode (bit 3 of the general purpose bit flag is set)
|
||||
check = (fileTime & 0xFFFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!crc_IsCalculated)
|
||||
{
|
||||
@@ -275,11 +310,6 @@ HRESULT CAddCommon::Compress(
|
||||
}
|
||||
check = (crc >> 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
opRes.FileTimeWasUsed = true;
|
||||
check = (fileTime & 0xFFFF);
|
||||
}
|
||||
|
||||
RINOK(_filterSpec->WriteHeader_Check16(outStream, (UInt16)check));
|
||||
}
|
||||
@@ -295,7 +325,13 @@ HRESULT CAddCommon::Compress(
|
||||
{
|
||||
case NCompressionMethod::kStore:
|
||||
{
|
||||
if (_copyCoderSpec == NULL)
|
||||
if (descriptorMode)
|
||||
{
|
||||
// we still can create descriptor_mode archives with "Store" method, but they are not good for 100%
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
if (!_copyCoderSpec)
|
||||
{
|
||||
_copyCoderSpec = new NCompress::CCopyCoder;
|
||||
_copyCoder = _copyCoderSpec;
|
||||
@@ -390,6 +426,18 @@ HRESULT CAddCommon::Compress(
|
||||
outStreamNew = outStream;
|
||||
if (_compressExtractVersion > opRes.ExtractVersion)
|
||||
opRes.ExtractVersion = _compressExtractVersion;
|
||||
|
||||
{
|
||||
CMyComPtr<ICompressSetCoderPropertiesOpt> optProps;
|
||||
_compressEncoder->QueryInterface(IID_ICompressSetCoderPropertiesOpt, (void **)&optProps);
|
||||
if (optProps)
|
||||
{
|
||||
PROPID propID = NCoderPropID::kExpectedDataSize;
|
||||
NWindows::NCOM::CPropVariant prop = (UInt64)expectedDataSize;
|
||||
RINOK(optProps->SetCoderPropertiesOpt(&propID, &prop, 1));
|
||||
}
|
||||
}
|
||||
|
||||
RINOK(_compressEncoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ struct CCompressingResult
|
||||
UInt32 CRC;
|
||||
UInt16 Method;
|
||||
Byte ExtractVersion;
|
||||
bool FileTimeWasUsed;
|
||||
bool DescriptorMode;
|
||||
bool LzmaEos;
|
||||
};
|
||||
|
||||
@@ -53,12 +53,14 @@ public:
|
||||
CAddCommon(const CCompressionMethodMode &options);
|
||||
~CAddCommon();
|
||||
|
||||
HRESULT Set_Pre_CompressionResult(bool seqMode, UInt64 unpackSize, CCompressingResult &opRes) const;
|
||||
HRESULT Set_Pre_CompressionResult(bool inSeqMode, bool outSeqMode, UInt64 unpackSize,
|
||||
CCompressingResult &opRes) const;
|
||||
|
||||
HRESULT Compress(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
ISequentialInStream *inStream, IOutStream *outStream,
|
||||
bool seqMode, UInt32 fileTime,
|
||||
bool inSeqMode, bool outSeqMode,
|
||||
UInt32 fileTime, UInt64 expectedDataSize,
|
||||
ICompressProgressInfo *progress, CCompressingResult &opRes);
|
||||
};
|
||||
|
||||
|
||||
@@ -564,7 +564,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
AString s2 = FlagsToString(g_HeaderCharacts, ARRAY_SIZE(g_HeaderCharacts), flags);
|
||||
if (!s2.IsEmpty())
|
||||
{
|
||||
s.Add_OptSpaced(":");
|
||||
if (!s.IsEmpty())
|
||||
s.Add_OptSpaced(":");
|
||||
s.Add_OptSpaced(s2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -459,7 +459,16 @@ API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size)
|
||||
extraSize -= 4;
|
||||
p += 4;
|
||||
if (dataSize > extraSize)
|
||||
return k_IsArc_Res_NO;
|
||||
{
|
||||
// It can be error on header.
|
||||
// We want to support such rare case bad archives.
|
||||
// We use additional checks to reduce false-positive probability.
|
||||
if (nameSize == 0
|
||||
|| nameSize > (1 << 9)
|
||||
|| extraSize > (1 << 9))
|
||||
return k_IsArc_Res_NO;
|
||||
return k_IsArc_Res_YES;
|
||||
}
|
||||
if (dataSize > size)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
size -= dataSize;
|
||||
|
||||
@@ -269,7 +269,25 @@ UInt32 CItem::GetWinAttrib() const
|
||||
case NHostOS::kUnix:
|
||||
// do we need to clear 16 low bits in this case?
|
||||
if (FromCentral)
|
||||
{
|
||||
/*
|
||||
Some programs write posix attributes in high 16 bits of ExternalAttrib
|
||||
Also some programs can write additional marker flag:
|
||||
0x8000 - p7zip
|
||||
0x4000 - Zip in MacOS
|
||||
no marker - Info-Zip
|
||||
|
||||
Client code has two options to detect posix field:
|
||||
1) check 0x8000 marker. In that case we must add 0x8000 marker here.
|
||||
2) check that high 4 bits (file type bits in posix field) of attributes are not zero.
|
||||
*/
|
||||
|
||||
winAttrib = ExternalAttrib & 0xFFFF0000;
|
||||
|
||||
// #ifndef _WIN32
|
||||
winAttrib |= 0x8000; // add posix mode marker
|
||||
// #endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (IsDir()) // test it;
|
||||
|
||||
@@ -174,6 +174,9 @@ void COutArchive::WriteLocalHeader_Replace(CItemOut &item)
|
||||
{
|
||||
WriteDescriptor(item);
|
||||
m_OutBuffer.FlushWithCheck();
|
||||
return;
|
||||
// we don't replace local header, if we write Descriptor.
|
||||
// so local header with Descriptor flag must be written to local header before.
|
||||
}
|
||||
|
||||
const UInt64 nextPos = m_CurPos;
|
||||
|
||||
@@ -62,7 +62,7 @@ static void AddAesExtra(CItem &item, Byte aesKeyMode, UInt16 method)
|
||||
static void SetFileHeader(
|
||||
const CCompressionMethodMode &options,
|
||||
const CUpdateItem &ui,
|
||||
// bool isSeqMode,
|
||||
bool useDescriptor,
|
||||
CItemOut &item)
|
||||
{
|
||||
item.Size = ui.Size;
|
||||
@@ -94,7 +94,7 @@ static void SetFileHeader(
|
||||
|
||||
item.InternalAttrib = 0; // test it
|
||||
item.SetEncrypted(!isDir && options.PasswordIsDefined);
|
||||
// item.SetDescriptorMode(isSeqMode);
|
||||
item.SetDescriptorMode(useDescriptor);
|
||||
|
||||
if (isDir)
|
||||
{
|
||||
@@ -166,18 +166,22 @@ struct CThreadInfo
|
||||
HRESULT Result;
|
||||
CCompressingResult CompressingResult;
|
||||
|
||||
bool SeqMode;
|
||||
bool InSeqMode;
|
||||
bool OutSeqMode;
|
||||
bool IsFree;
|
||||
UInt32 UpdateIndex;
|
||||
UInt32 FileTime;
|
||||
UInt64 ExpectedDataSize;
|
||||
|
||||
CThreadInfo(const CCompressionMethodMode &options):
|
||||
ExitThread(false),
|
||||
ProgressSpec(0),
|
||||
OutStreamSpec(0),
|
||||
Coder(options),
|
||||
SeqMode(false),
|
||||
FileTime(0)
|
||||
InSeqMode(false),
|
||||
OutSeqMode(false),
|
||||
FileTime(0),
|
||||
ExpectedDataSize((UInt64)(Int64)-1)
|
||||
{}
|
||||
|
||||
HRESULT CreateEvents()
|
||||
@@ -210,7 +214,9 @@ void CThreadInfo::WaitAndCode()
|
||||
|
||||
Result = Coder.Compress(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
InStream, OutStream, SeqMode, FileTime, Progress, CompressingResult);
|
||||
InStream, OutStream,
|
||||
InSeqMode, OutSeqMode, FileTime, ExpectedDataSize,
|
||||
Progress, CompressingResult);
|
||||
|
||||
if (Result == S_OK && Progress)
|
||||
Result = Progress->SetRatioInfo(&CompressingResult.UnpackSize, &CompressingResult.PackSize);
|
||||
@@ -237,10 +243,13 @@ public:
|
||||
|
||||
struct CMemBlocks2: public CMemLockBlocks
|
||||
{
|
||||
CCompressingResult CompressingResult;
|
||||
bool Defined;
|
||||
bool Skip;
|
||||
CMemBlocks2(): Defined(false), Skip(false) {}
|
||||
bool InSeqMode;
|
||||
bool PreDescriptorMode;
|
||||
bool Finished;
|
||||
CCompressingResult CompressingResult;
|
||||
|
||||
CMemBlocks2(): Skip(false), InSeqMode(false), PreDescriptorMode(false), Finished(false) {}
|
||||
};
|
||||
|
||||
class CMemRefs
|
||||
@@ -412,7 +421,7 @@ static HRESULT UpdateItemOldData(
|
||||
static void WriteDirHeader(COutArchive &archive, const CCompressionMethodMode *options,
|
||||
const CUpdateItem &ui, CItemOut &item)
|
||||
{
|
||||
SetFileHeader(*options, ui, item);
|
||||
SetFileHeader(*options, ui, false, item);
|
||||
archive.WriteLocalHeader(item);
|
||||
}
|
||||
|
||||
@@ -471,7 +480,7 @@ static HRESULT Update2St(
|
||||
CInArchive *inArchive,
|
||||
const CObjectVector<CItemEx> &inputItems,
|
||||
CObjectVector<CUpdateItem> &updateItems,
|
||||
const CCompressionMethodMode *options,
|
||||
const CCompressionMethodMode *options, bool outSeqMode,
|
||||
const CByteBuffer *comment,
|
||||
IArchiveUpdateCallback *updateCallback,
|
||||
UInt64 &totalComplexity,
|
||||
@@ -527,28 +536,28 @@ static HRESULT Update2St(
|
||||
if (!fileInStream)
|
||||
return E_INVALIDARG;
|
||||
|
||||
bool seqMode;
|
||||
bool inSeqMode = false;
|
||||
if (!inSeqMode)
|
||||
{
|
||||
CMyComPtr<IInStream> inStream2;
|
||||
fileInStream->QueryInterface(IID_IInStream, (void **)&inStream2);
|
||||
seqMode = (inStream2 == NULL);
|
||||
inSeqMode = (inStream2 == NULL);
|
||||
}
|
||||
// seqMode = true; // to test seqMode
|
||||
|
||||
UpdatePropsFromStream(ui, fileInStream, updateCallback, totalComplexity);
|
||||
SetFileHeader(*options, ui, item);
|
||||
|
||||
item.SetDescriptorMode(seqMode);
|
||||
|
||||
// file Size can be 64-bit !!!
|
||||
|
||||
CCompressingResult compressingResult;
|
||||
|
||||
RINOK(compressor.Set_Pre_CompressionResult(
|
||||
seqMode,
|
||||
inSeqMode, outSeqMode,
|
||||
ui.Size,
|
||||
compressingResult));
|
||||
|
||||
SetFileHeader(*options, ui, compressingResult.DescriptorMode, item);
|
||||
|
||||
// file Size can be 64-bit !!!
|
||||
|
||||
SetItemInfoFromCompressingResult(compressingResult, options->IsRealAesMode(), options->AesKeyMode, item);
|
||||
|
||||
archive.WriteLocalHeader(item);
|
||||
@@ -559,17 +568,12 @@ static HRESULT Update2St(
|
||||
RINOK(compressor.Compress(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
fileInStream, outStream,
|
||||
seqMode, ui.Time,
|
||||
inSeqMode, outSeqMode,
|
||||
ui.Time, ui.Size,
|
||||
progress, compressingResult));
|
||||
|
||||
if (compressingResult.FileTimeWasUsed)
|
||||
{
|
||||
/*
|
||||
if (!item.HasDescriptor())
|
||||
return E_FAIL;
|
||||
*/
|
||||
item.SetDescriptorMode(true);
|
||||
}
|
||||
if (item.HasDescriptor() != compressingResult.DescriptorMode)
|
||||
return E_FAIL;
|
||||
|
||||
SetItemInfoFromCompressingResult(compressingResult, options->IsRealAesMode(), options->AesKeyMode, item);
|
||||
|
||||
@@ -609,7 +613,7 @@ static HRESULT Update2(
|
||||
CInArchive *inArchive,
|
||||
const CObjectVector<CItemEx> &inputItems,
|
||||
CObjectVector<CUpdateItem> &updateItems,
|
||||
const CCompressionMethodMode &options,
|
||||
const CCompressionMethodMode &options, bool outSeqMode,
|
||||
const CByteBuffer *comment,
|
||||
IArchiveUpdateCallback *updateCallback)
|
||||
{
|
||||
@@ -743,32 +747,38 @@ static HRESULT Update2(
|
||||
const UInt64 averageSize = numBytesToCompress / numFilesToCompress;
|
||||
const UInt32 blockSize = oneMethodMain->Get_BZip2_BlockSize();
|
||||
const UInt64 averageNumberOfBlocks = averageSize / blockSize + 1;
|
||||
numBZip2Threads = 32;
|
||||
numBZip2Threads = 64;
|
||||
if (numBZip2Threads > averageNumberOfBlocks)
|
||||
numBZip2Threads = (UInt32)averageNumberOfBlocks;
|
||||
if (numBZip2Threads > numThreads)
|
||||
numBZip2Threads = numThreads;
|
||||
oneMethodMain->AddProp_NumThreads(numBZip2Threads);
|
||||
}
|
||||
numThreads /= numBZip2Threads;
|
||||
}
|
||||
|
||||
if (method == NFileHeader::NCompressionMethod::kXz)
|
||||
else if (method == NFileHeader::NCompressionMethod::kXz)
|
||||
{
|
||||
bool fixedNumber;
|
||||
UInt32 numLzma2Threads = oneMethodMain->Get_Lzma2_NumThreads(fixedNumber);
|
||||
if (!fixedNumber)
|
||||
UInt32 numLzmaThreads = 1;
|
||||
int numXzThreads = oneMethodMain->Get_Xz_NumThreads(numLzmaThreads);
|
||||
if (numXzThreads < 0)
|
||||
{
|
||||
const UInt64 averageSize = numBytesToCompress / numFilesToCompress;
|
||||
const UInt64 blockSize = oneMethodMain->Get_Lzma2_BlockSize();
|
||||
const UInt64 averageNumberOfBlocks = averageSize / blockSize + 1;
|
||||
numLzma2Threads = 2;
|
||||
if (numLzma2Threads > averageNumberOfBlocks)
|
||||
numLzma2Threads = (UInt32)averageNumberOfBlocks;
|
||||
oneMethodMain->AddProp_NumThreads(numLzma2Threads);
|
||||
const UInt64 blockSize = oneMethodMain->Get_Xz_BlockSize();
|
||||
UInt64 averageNumberOfBlocks = 1;
|
||||
if (blockSize != (UInt64)(Int64)-1)
|
||||
averageNumberOfBlocks = averageSize / blockSize + 1;
|
||||
UInt32 t = 256;
|
||||
if (t > averageNumberOfBlocks)
|
||||
t = (UInt32)averageNumberOfBlocks;
|
||||
t *= numLzmaThreads;
|
||||
if (t > numThreads)
|
||||
t = numThreads;
|
||||
oneMethodMain->AddProp_NumThreads(t);
|
||||
numXzThreads = t;
|
||||
}
|
||||
numThreads /= numLzma2Threads;
|
||||
numThreads /= (unsigned)numXzThreads;
|
||||
}
|
||||
|
||||
if (method == NFileHeader::NCompressionMethod::kLZMA)
|
||||
else if (method == NFileHeader::NCompressionMethod::kLZMA)
|
||||
{
|
||||
// we suppose that default LZMA is 2 thread. So we don't change it
|
||||
UInt32 numLZMAThreads = oneMethodMain->Get_Lzma_NumThreads();
|
||||
@@ -782,12 +792,14 @@ static HRESULT Update2(
|
||||
mtMode = false;
|
||||
}
|
||||
|
||||
// mtMode = true; // to test mtMode for seqMode
|
||||
|
||||
if (!mtMode)
|
||||
#endif
|
||||
return Update2St(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
archive, inArchive,
|
||||
inputItems, updateItems, &options2, comment, updateCallback, totalComplexity, opCallback);
|
||||
inputItems, updateItems, &options2, outSeqMode, comment, updateCallback, totalComplexity, opCallback);
|
||||
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
@@ -830,8 +842,10 @@ static HRESULT Update2(
|
||||
threadInfo.ProgressSpec = new CMtCompressProgress();
|
||||
threadInfo.Progress = threadInfo.ProgressSpec;
|
||||
threadInfo.ProgressSpec->Init(&mtCompressProgressMixer, (int)i);
|
||||
threadInfo.SeqMode = false; // fix it !
|
||||
threadInfo.FileTime = 0; // fix it !
|
||||
threadInfo.InSeqMode = false;
|
||||
threadInfo.OutSeqMode = false;
|
||||
threadInfo.FileTime = 0;
|
||||
threadInfo.ExpectedDataSize = (UInt64)(Int64)-1;
|
||||
RINOK(threadInfo.CreateThread());
|
||||
}
|
||||
}
|
||||
@@ -840,10 +854,15 @@ static HRESULT Update2(
|
||||
unsigned itemIndex = 0;
|
||||
int lastRealStreamItemIndex = -1;
|
||||
|
||||
|
||||
while (itemIndex < updateItems.Size())
|
||||
{
|
||||
if (threadIndices.Size() < numThreads && mtItemIndex < updateItems.Size())
|
||||
{
|
||||
// we start ahead the threads for compressing
|
||||
// also we set refs.Refs[itemIndex].SeqMode that is used later
|
||||
// don't move that code block
|
||||
|
||||
CUpdateItem &ui = updateItems[mtItemIndex++];
|
||||
if (!ui.NewData)
|
||||
continue;
|
||||
@@ -869,6 +888,8 @@ static HRESULT Update2(
|
||||
|
||||
CMyComPtr<ISequentialInStream> fileInStream;
|
||||
|
||||
CMemBlocks2 &memRef2 = refs.Refs[mtItemIndex - 1];
|
||||
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(mtProgressMixerSpec->Mixer2->CriticalSection);
|
||||
HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream);
|
||||
@@ -878,7 +899,7 @@ static HRESULT Update2(
|
||||
complexity += kLocalHeaderSize;
|
||||
mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity);
|
||||
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
refs.Refs[mtItemIndex - 1].Skip = true;
|
||||
memRef2.Skip = true;
|
||||
continue;
|
||||
}
|
||||
RINOK(res);
|
||||
@@ -888,26 +909,46 @@ static HRESULT Update2(
|
||||
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
}
|
||||
|
||||
for (UInt32 k = 0; k < numThreads; k++)
|
||||
UInt32 k;
|
||||
for (k = 0; k < numThreads; k++)
|
||||
if (threads.Threads[k].IsFree)
|
||||
break;
|
||||
|
||||
if (k == numThreads)
|
||||
return E_FAIL;
|
||||
{
|
||||
CThreadInfo &threadInfo = threads.Threads[k];
|
||||
if (threadInfo.IsFree)
|
||||
{
|
||||
CThreadInfo &threadInfo = threads.Threads[k];
|
||||
threadInfo.IsFree = false;
|
||||
threadInfo.InStream = fileInStream;
|
||||
|
||||
bool inSeqMode = false;
|
||||
|
||||
if (!inSeqMode)
|
||||
{
|
||||
CMyComPtr<IInStream> inStream2;
|
||||
fileInStream->QueryInterface(IID_IInStream, (void **)&inStream2);
|
||||
inSeqMode = (inStream2 == NULL);
|
||||
}
|
||||
memRef2.InSeqMode = inSeqMode;
|
||||
|
||||
// !!!!! we must release ref before sending event
|
||||
// BUG was here in v4.43 and v4.44. It could change ref counter in two threads in same time
|
||||
fileInStream.Release();
|
||||
|
||||
threadInfo.OutStreamSpec->Init();
|
||||
threadInfo.ProgressSpec->Reinit();
|
||||
threadInfo.CompressEvent.Set();
|
||||
|
||||
threadInfo.UpdateIndex = mtItemIndex - 1;
|
||||
|
||||
threadInfo.InSeqMode = inSeqMode;
|
||||
threadInfo.OutSeqMode = outSeqMode;
|
||||
threadInfo.FileTime = ui.Time; // FileTime is used for ZipCrypto only in seqMode
|
||||
threadInfo.ExpectedDataSize = ui.Size;
|
||||
|
||||
threadInfo.CompressEvent.Set();
|
||||
|
||||
compressingCompletedEvents.Add(threadInfo.CompressionCompletedEvent);
|
||||
threadIndices.Add(k);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -946,15 +987,17 @@ static HRESULT Update2(
|
||||
{
|
||||
CMemBlocks2 &memRef = refs.Refs[itemIndex];
|
||||
|
||||
if (memRef.Defined)
|
||||
if (memRef.Finished)
|
||||
{
|
||||
if (lastRealStreamItemIndex < (int)itemIndex)
|
||||
lastRealStreamItemIndex = itemIndex;
|
||||
|
||||
SetFileHeader(options, ui, item);
|
||||
SetFileHeader(options, ui, memRef.CompressingResult.DescriptorMode, item);
|
||||
|
||||
// the BUG was fixed in 9.26:
|
||||
// SetItemInfoFromCompressingResult must be after SetFileHeader
|
||||
// to write correct Size.
|
||||
|
||||
SetItemInfoFromCompressingResult(memRef.CompressingResult,
|
||||
options.IsRealAesMode(), options.AesKeyMode, item);
|
||||
archive.WriteLocalHeader(item);
|
||||
@@ -967,16 +1010,25 @@ static HRESULT Update2(
|
||||
}
|
||||
else
|
||||
{
|
||||
// current file was not finished
|
||||
|
||||
if (lastRealStreamItemIndex < (int)itemIndex)
|
||||
{
|
||||
// LocalHeader was not written for current itemIndex still
|
||||
|
||||
lastRealStreamItemIndex = itemIndex;
|
||||
SetFileHeader(options, ui, item);
|
||||
|
||||
// thread was started before for that item already, and memRef.SeqMode was set
|
||||
|
||||
CCompressingResult compressingResult;
|
||||
RINOK(compressor.Set_Pre_CompressionResult(
|
||||
false, // seqMode
|
||||
memRef.InSeqMode, outSeqMode,
|
||||
ui.Size,
|
||||
compressingResult));
|
||||
|
||||
memRef.PreDescriptorMode = compressingResult.DescriptorMode;
|
||||
SetFileHeader(options, ui, compressingResult.DescriptorMode, item);
|
||||
|
||||
SetItemInfoFromCompressingResult(compressingResult, options.IsRealAesMode(), options.AesKeyMode, item);
|
||||
|
||||
// file Size can be 64-bit !!!
|
||||
@@ -1015,19 +1067,29 @@ static HRESULT Update2(
|
||||
|
||||
if (t == 0)
|
||||
{
|
||||
// if thread for current file was finished.
|
||||
if (threadInfo.UpdateIndex != itemIndex)
|
||||
return E_FAIL;
|
||||
|
||||
if (memRef.PreDescriptorMode != threadInfo.CompressingResult.DescriptorMode)
|
||||
return E_FAIL;
|
||||
|
||||
RINOK(threadInfo.OutStreamSpec->WriteToRealStream());
|
||||
threadInfo.OutStreamSpec->ReleaseOutStream();
|
||||
SetFileHeader(options, ui, item);
|
||||
SetFileHeader(options, ui, threadInfo.CompressingResult.DescriptorMode, item);
|
||||
SetItemInfoFromCompressingResult(threadInfo.CompressingResult,
|
||||
options.IsRealAesMode(), options.AesKeyMode, item);
|
||||
|
||||
archive.WriteLocalHeader_Replace(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's not current file. So we must store information in array
|
||||
CMemBlocks2 &memRef2 = refs.Refs[threadInfo.UpdateIndex];
|
||||
threadInfo.OutStreamSpec->DetachData(memRef2);
|
||||
memRef2.CompressingResult = threadInfo.CompressingResult;
|
||||
memRef2.Defined = true;
|
||||
// memRef2.SeqMode = threadInfo.SeqMode; // it was set before
|
||||
memRef2.Finished = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1060,6 +1122,7 @@ class CCacheOutStream:
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<IOutStream> _stream;
|
||||
CMyComPtr<ISequentialOutStream> _seqStream;
|
||||
Byte *_cache;
|
||||
UInt64 _virtPos;
|
||||
UInt64 _virtSize;
|
||||
@@ -1075,10 +1138,10 @@ class CCacheOutStream:
|
||||
}
|
||||
HRESULT FlushCache();
|
||||
public:
|
||||
CCacheOutStream(): _cache(0) {}
|
||||
CCacheOutStream(): _cache(NULL) {}
|
||||
~CCacheOutStream();
|
||||
bool Allocate();
|
||||
HRESULT Init(IOutStream *stream);
|
||||
HRESULT Init(ISequentialOutStream *seqStream, IOutStream *stream);
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
@@ -1094,13 +1157,19 @@ bool CCacheOutStream::Allocate()
|
||||
return (_cache != NULL);
|
||||
}
|
||||
|
||||
HRESULT CCacheOutStream::Init(IOutStream *stream)
|
||||
HRESULT CCacheOutStream::Init(ISequentialOutStream *seqStream, IOutStream *stream)
|
||||
{
|
||||
_virtPos = _phyPos = 0;
|
||||
_virtPos = 0;
|
||||
_phyPos = 0;
|
||||
_virtSize = 0;
|
||||
_seqStream = seqStream;
|
||||
_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));
|
||||
if (_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;
|
||||
@@ -1114,12 +1183,14 @@ HRESULT CCacheOutStream::MyWrite(size_t size)
|
||||
{
|
||||
if (_phyPos != _cachedPos)
|
||||
{
|
||||
if (!_stream)
|
||||
return E_FAIL;
|
||||
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));
|
||||
RINOK(WriteStream(_seqStream, _cache + pos, curSize));
|
||||
_phyPos += curSize;
|
||||
if (_phySize < _phyPos)
|
||||
_phySize = _phyPos;
|
||||
@@ -1138,10 +1209,13 @@ HRESULT CCacheOutStream::FlushCache()
|
||||
CCacheOutStream::~CCacheOutStream()
|
||||
{
|
||||
FlushCache();
|
||||
if (_virtSize != _phySize)
|
||||
_stream->SetSize(_virtSize);
|
||||
if (_virtPos != _phyPos)
|
||||
_stream->Seek(_virtPos, STREAM_SEEK_SET, NULL);
|
||||
if (_stream)
|
||||
{
|
||||
if (_virtSize != _phySize)
|
||||
_stream->SetSize(_virtSize);
|
||||
if (_virtPos != _phyPos)
|
||||
_stream->Seek(_virtPos, STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
::MidFree(_cache);
|
||||
}
|
||||
|
||||
@@ -1250,6 +1324,8 @@ STDMETHODIMP CCacheOutStream::SetSize(UInt64 newSize)
|
||||
_virtSize = newSize;
|
||||
if (newSize < _phySize)
|
||||
{
|
||||
if (!_stream)
|
||||
return E_NOTIMPL;
|
||||
RINOK(_stream->SetSize(newSize));
|
||||
_phySize = newSize;
|
||||
}
|
||||
@@ -1281,11 +1357,14 @@ HRESULT Update(
|
||||
|
||||
|
||||
CMyComPtr<IOutStream> outStream;
|
||||
bool outSeqMode;
|
||||
{
|
||||
CMyComPtr<IOutStream> outStreamReal;
|
||||
seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStreamReal);
|
||||
if (!outStreamReal)
|
||||
return E_NOTIMPL;
|
||||
{
|
||||
// return E_NOTIMPL;
|
||||
}
|
||||
|
||||
if (inArchive)
|
||||
{
|
||||
@@ -1293,7 +1372,7 @@ HRESULT Update(
|
||||
{
|
||||
IInStream *baseStream = inArchive->GetBaseStream();
|
||||
RINOK(baseStream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
RINOK(NCompress::CopyStream_ExactSize(baseStream, outStreamReal, inArchive->ArcInfo.Base, NULL));
|
||||
RINOK(NCompress::CopyStream_ExactSize(baseStream, seqOutStream, inArchive->ArcInfo.Base, NULL));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1301,7 +1380,8 @@ HRESULT Update(
|
||||
outStream = cacheStream;
|
||||
if (!cacheStream->Allocate())
|
||||
return E_OUTOFMEMORY;
|
||||
RINOK(cacheStream->Init(outStreamReal));
|
||||
RINOK(cacheStream->Init(seqOutStream, outStreamReal));
|
||||
outSeqMode = (outStreamReal == NULL);
|
||||
}
|
||||
|
||||
COutArchive outArchive;
|
||||
@@ -1323,7 +1403,7 @@ HRESULT Update(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
outArchive, inArchive,
|
||||
inputItems, updateItems,
|
||||
compressionMethodMode,
|
||||
compressionMethodMode, outSeqMode,
|
||||
inArchive ? &inArchive->ArcInfo.Comment : NULL,
|
||||
updateCallback);
|
||||
}
|
||||
|
||||
@@ -28,13 +28,17 @@ HRESULT SResToHRESULT(SRes res) throw()
|
||||
switch (res)
|
||||
{
|
||||
case SZ_OK: return S_OK;
|
||||
case SZ_ERROR_DATA: return S_FALSE;
|
||||
case SZ_ERROR_CRC: return S_FALSE;
|
||||
case SZ_ERROR_MEM: return E_OUTOFMEMORY;
|
||||
case SZ_ERROR_PARAM: return E_INVALIDARG;
|
||||
case SZ_ERROR_PROGRESS: return E_ABORT;
|
||||
case SZ_ERROR_DATA: return S_FALSE;
|
||||
case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;
|
||||
// case SZ_ERROR_READ: return E_NOTIMPL;
|
||||
// case SZ_ERROR_THREAD: return E_FAIL;
|
||||
// case SZ_ERROR_READ: return E_FAIL;
|
||||
}
|
||||
if (res < 0)
|
||||
return res;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,14 @@ unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number)
|
||||
return (unsigned)(end - start);
|
||||
}
|
||||
|
||||
static unsigned ParseStringToUInt64(const UString &srcString, UInt64 &number)
|
||||
{
|
||||
const wchar_t *start = srcString;
|
||||
const wchar_t *end;
|
||||
number = ConvertStringToUInt64(start, &end);
|
||||
return (unsigned)(end - start);
|
||||
}
|
||||
|
||||
HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
|
||||
{
|
||||
// =VT_UI4
|
||||
@@ -263,7 +271,11 @@ static const CNameToPropID g_NameToPropID[] =
|
||||
{ VT_UI4, "mt" },
|
||||
{ VT_BOOL, "eos" },
|
||||
{ VT_UI4, "x" },
|
||||
{ VT_UI4, "reduceSize" }
|
||||
{ VT_UI8, "reduce" },
|
||||
{ VT_UI8, "expect" },
|
||||
{ VT_UI4, "b" },
|
||||
{ VT_UI4, "check" },
|
||||
{ VT_BSTR, "filter" }
|
||||
};
|
||||
|
||||
static int FindPropIdExact(const UString &name)
|
||||
@@ -345,7 +357,8 @@ static bool IsLogSizeProp(PROPID propid)
|
||||
case NCoderPropID::kDictionarySize:
|
||||
case NCoderPropID::kUsedMemorySize:
|
||||
case NCoderPropID::kBlockSize:
|
||||
case NCoderPropID::kReduceSize:
|
||||
case NCoderPropID::kBlockSize2:
|
||||
// case NCoderPropID::kReduceSize:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -378,9 +391,22 @@ HRESULT CMethodProps::SetParam(const UString &name, const UString &value)
|
||||
}
|
||||
else if (!value.IsEmpty())
|
||||
{
|
||||
UInt32 number;
|
||||
if (ParseStringToUInt32(value, number) == value.Len())
|
||||
propValue = number;
|
||||
if (nameToPropID.VarType == VT_UI4)
|
||||
{
|
||||
UInt32 number;
|
||||
if (ParseStringToUInt32(value, number) == value.Len())
|
||||
propValue = number;
|
||||
else
|
||||
propValue = value;
|
||||
}
|
||||
else if (nameToPropID.VarType == VT_UI8)
|
||||
{
|
||||
UInt64 number;
|
||||
if (ParseStringToUInt64(value, number) == value.Len())
|
||||
propValue = number;
|
||||
else
|
||||
propValue = value;
|
||||
}
|
||||
else
|
||||
propValue = value;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#define __7Z_METHOD_PROPS_H
|
||||
|
||||
#include "../../Common/MyString.h"
|
||||
#include "../../Common/Defs.h"
|
||||
|
||||
#include "../../Windows/Defs.h"
|
||||
|
||||
@@ -133,38 +134,50 @@ public:
|
||||
return 2;
|
||||
}
|
||||
|
||||
UInt32 Get_Lzma2_NumThreads(bool &fixedNumber) const
|
||||
int Get_Xz_NumThreads(UInt32 &lzmaThreads) const
|
||||
{
|
||||
fixedNumber = false;
|
||||
lzmaThreads = 1;
|
||||
int numThreads = Get_NumThreads();
|
||||
if (numThreads >= 0)
|
||||
{
|
||||
fixedNumber = true;
|
||||
if (numThreads < 1) return 1;
|
||||
const unsigned kNumLzma2ThreadsMax = 32;
|
||||
if (numThreads > kNumLzma2ThreadsMax) return kNumLzma2ThreadsMax;
|
||||
return numThreads;
|
||||
}
|
||||
return 1;
|
||||
if (numThreads >= 0 && numThreads <= 1)
|
||||
return 1;
|
||||
if (Get_Lzma_Algo() != 0)
|
||||
lzmaThreads = 2;
|
||||
return numThreads;
|
||||
}
|
||||
|
||||
UInt64 Get_Lzma2_BlockSize() const
|
||||
UInt64 GetProp_BlockSize(PROPID id) const
|
||||
{
|
||||
int i = FindProp(NCoderPropID::kBlockSize);
|
||||
int i = FindProp(id);
|
||||
if (i >= 0)
|
||||
{
|
||||
const NWindows::NCOM::CPropVariant &val = Props[i].Value;
|
||||
if (val.vt == VT_UI4) return val.ulVal;
|
||||
if (val.vt == VT_UI8) return val.uhVal.QuadPart;
|
||||
if (val.vt == VT_UI4) { return val.ulVal; }
|
||||
if (val.vt == VT_UI8) { return val.uhVal.QuadPart; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UInt32 dictSize = Get_Lzma_DicSize();
|
||||
UInt64 blockSize = (UInt64)dictSize << 2;
|
||||
UInt64 Get_Xz_BlockSize() const
|
||||
{
|
||||
{
|
||||
UInt64 blockSize1 = GetProp_BlockSize(NCoderPropID::kBlockSize);
|
||||
UInt64 blockSize2 = GetProp_BlockSize(NCoderPropID::kBlockSize2);
|
||||
UInt64 minSize = MyMin(blockSize1, blockSize2);
|
||||
if (minSize != 0)
|
||||
return minSize;
|
||||
UInt64 maxSize = MyMax(blockSize1, blockSize2);
|
||||
if (maxSize != 0)
|
||||
return maxSize;
|
||||
}
|
||||
const UInt32 kMinSize = (UInt32)1 << 20;
|
||||
const UInt32 kMaxSize = (UInt32)1 << 28;
|
||||
UInt32 dictSize = Get_Lzma_DicSize();
|
||||
UInt64 blockSize = (UInt64)dictSize << 2;
|
||||
if (blockSize < kMinSize) blockSize = kMinSize;
|
||||
if (blockSize > kMaxSize) blockSize = kMaxSize;
|
||||
if (blockSize < dictSize) blockSize = dictSize;
|
||||
blockSize += (kMinSize - 1);
|
||||
blockSize &= ~(UInt64)(kMinSize - 1);
|
||||
return blockSize;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,18 +21,19 @@ namespace NLzma2 {
|
||||
|
||||
CEncoder::CEncoder()
|
||||
{
|
||||
_encoder = 0;
|
||||
_encoder = NULL;
|
||||
_encoder = Lzma2Enc_Create(&g_Alloc, &g_BigAlloc);
|
||||
if (_encoder == 0)
|
||||
if (!_encoder)
|
||||
throw 1;
|
||||
}
|
||||
|
||||
CEncoder::~CEncoder()
|
||||
{
|
||||
if (_encoder != 0)
|
||||
if (_encoder)
|
||||
Lzma2Enc_Destroy(_encoder);
|
||||
}
|
||||
|
||||
|
||||
HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props)
|
||||
{
|
||||
switch (propID)
|
||||
@@ -42,12 +43,7 @@ HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzm
|
||||
if (prop.vt == VT_UI4)
|
||||
lzma2Props.blockSize = prop.ulVal;
|
||||
else if (prop.vt == VT_UI8)
|
||||
{
|
||||
size_t v = (size_t)prop.uhVal.QuadPart;
|
||||
if (v != prop.uhVal.QuadPart)
|
||||
return E_INVALIDARG;
|
||||
lzma2Props.blockSize = v;
|
||||
}
|
||||
lzma2Props.blockSize = prop.uhVal.QuadPart;
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
break;
|
||||
@@ -60,6 +56,7 @@ HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzm
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
|
||||
const PROPVARIANT *coderProps, UInt32 numProps)
|
||||
{
|
||||
@@ -73,30 +70,52 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
|
||||
return SResToHRESULT(Lzma2Enc_SetProps(_encoder, &lzma2Props));
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs,
|
||||
const PROPVARIANT *coderProps, UInt32 numProps)
|
||||
{
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
const PROPVARIANT &prop = coderProps[i];
|
||||
PROPID propID = propIDs[i];
|
||||
if (propID == NCoderPropID::kExpectedDataSize)
|
||||
if (prop.vt == VT_UI8)
|
||||
Lzma2Enc_SetDataSize(_encoder, prop.uhVal.QuadPart);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
|
||||
{
|
||||
Byte prop = Lzma2Enc_WriteProperties(_encoder);
|
||||
return WriteStream(outStream, &prop, 1);
|
||||
}
|
||||
|
||||
|
||||
#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
|
||||
if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
|
||||
|
||||
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
|
||||
{
|
||||
CSeqInStreamWrap inWrap;
|
||||
CSeqOutStreamWrap outWrap;
|
||||
CCompressProgressWrap progressWrap;
|
||||
|
||||
|
||||
inWrap.Init(inStream);
|
||||
outWrap.Init(outStream);
|
||||
progressWrap.Init(progress);
|
||||
|
||||
SRes res = Lzma2Enc_Encode(_encoder, &outWrap.vt, &inWrap.vt, progress ? &progressWrap.vt : NULL);
|
||||
if (res == SZ_ERROR_READ && inWrap.Res != S_OK)
|
||||
return inWrap.Res;
|
||||
if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK)
|
||||
return outWrap.Res;
|
||||
if (res == SZ_ERROR_PROGRESS && progressWrap.Res != S_OK)
|
||||
return progressWrap.Res;
|
||||
SRes res = Lzma2Enc_Encode2(_encoder,
|
||||
&outWrap.vt, NULL, NULL,
|
||||
&inWrap.vt, NULL, 0,
|
||||
progress ? &progressWrap.vt : NULL);
|
||||
|
||||
RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ)
|
||||
RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
|
||||
RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
|
||||
|
||||
return SResToHRESULT(res);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,16 +16,22 @@ class CEncoder:
|
||||
public ICompressCoder,
|
||||
public ICompressSetCoderProperties,
|
||||
public ICompressWriteCoderProperties,
|
||||
public ICompressSetCoderPropertiesOpt,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CLzma2EncHandle _encoder;
|
||||
public:
|
||||
MY_UNKNOWN_IMP3(ICompressCoder, ICompressSetCoderProperties, ICompressWriteCoderProperties)
|
||||
MY_UNKNOWN_IMP4(
|
||||
ICompressCoder,
|
||||
ICompressSetCoderProperties,
|
||||
ICompressWriteCoderProperties,
|
||||
ICompressSetCoderPropertiesOpt)
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
|
||||
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
|
||||
STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
|
||||
|
||||
CEncoder();
|
||||
virtual ~CEncoder();
|
||||
|
||||
@@ -74,14 +74,19 @@ HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep)
|
||||
return E_INVALIDARG;
|
||||
return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (propID > NCoderPropID::kReduceSize)
|
||||
return S_OK;
|
||||
|
||||
if (propID == NCoderPropID::kReduceSize)
|
||||
{
|
||||
if (prop.vt == VT_UI8)
|
||||
ep.reduceSize = prop.uhVal.QuadPart;
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
UInt32 v = prop.ulVal;
|
||||
@@ -123,6 +128,22 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
|
||||
return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props));
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs,
|
||||
const PROPVARIANT *coderProps, UInt32 numProps)
|
||||
{
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
const PROPVARIANT &prop = coderProps[i];
|
||||
PROPID propID = propIDs[i];
|
||||
if (propID == NCoderPropID::kExpectedDataSize)
|
||||
if (prop.vt == VT_UI8)
|
||||
LzmaEnc_SetDataSize(_encoder, prop.uhVal.QuadPart);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
|
||||
{
|
||||
Byte props[LZMA_PROPS_SIZE];
|
||||
@@ -131,6 +152,10 @@ STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
|
||||
return WriteStream(outStream, props, size);
|
||||
}
|
||||
|
||||
|
||||
#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
|
||||
if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
|
||||
|
||||
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
|
||||
{
|
||||
@@ -142,15 +167,15 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream
|
||||
outWrap.Init(outStream);
|
||||
progressWrap.Init(progress);
|
||||
|
||||
SRes res = LzmaEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt, progress ? &progressWrap.vt : NULL, &g_Alloc, &g_BigAlloc);
|
||||
SRes res = LzmaEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt,
|
||||
progress ? &progressWrap.vt : NULL, &g_Alloc, &g_BigAlloc);
|
||||
|
||||
_inputProcessed = inWrap.Processed;
|
||||
if (res == SZ_ERROR_READ && inWrap.Res != S_OK)
|
||||
return inWrap.Res;
|
||||
if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK)
|
||||
return outWrap.Res;
|
||||
if (res == SZ_ERROR_PROGRESS && progressWrap.Res != S_OK)
|
||||
return progressWrap.Res;
|
||||
|
||||
RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ)
|
||||
RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
|
||||
RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
|
||||
|
||||
return SResToHRESULT(res);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,17 +16,23 @@ class CEncoder:
|
||||
public ICompressCoder,
|
||||
public ICompressSetCoderProperties,
|
||||
public ICompressWriteCoderProperties,
|
||||
public ICompressSetCoderPropertiesOpt,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CLzmaEncHandle _encoder;
|
||||
UInt64 _inputProcessed;
|
||||
public:
|
||||
MY_UNKNOWN_IMP3(ICompressCoder, ICompressSetCoderProperties, ICompressWriteCoderProperties)
|
||||
MY_UNKNOWN_IMP4(
|
||||
ICompressCoder,
|
||||
ICompressSetCoderProperties,
|
||||
ICompressWriteCoderProperties,
|
||||
ICompressSetCoderPropertiesOpt)
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
|
||||
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
|
||||
STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
|
||||
|
||||
CEncoder();
|
||||
virtual ~CEncoder();
|
||||
|
||||
@@ -144,7 +144,8 @@ void CDecoder::ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef)
|
||||
CFilter *filter = _filters[tempFilter->FilterIndex];
|
||||
if (!filter->IsSupported)
|
||||
_unsupportedFilter = true;
|
||||
_vm.Execute(filter, tempFilter, outBlockRef, filter->GlobalData);
|
||||
if (!_vm.Execute(filter, tempFilter, outBlockRef, filter->GlobalData))
|
||||
_unsupportedFilter = true;
|
||||
delete tempFilter;
|
||||
_tempFilters[tempFilterIndex] = 0;
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
|
||||
|
||||
#ifdef RARVM_STANDARD_FILTERS
|
||||
if (prg->StandardFilterIndex >= 0)
|
||||
ExecuteStandardFilter(prg->StandardFilterIndex);
|
||||
res = ExecuteStandardFilter(prg->StandardFilterIndex);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
@@ -880,10 +880,10 @@ static void E8E9Decode(Byte *data, UInt32 dataSize, UInt32 fileOffset, bool e9)
|
||||
if (((*data++) & cmpMask) == 0xE8)
|
||||
{
|
||||
UInt32 offset = curPos + fileOffset;
|
||||
UInt32 addr = (Int32)GetValue32(data);
|
||||
UInt32 addr = GetValue32(data);
|
||||
if (addr < kFileSize)
|
||||
SetValue32(data, addr - offset);
|
||||
else if ((Int32)addr < 0 && (Int32)(addr + offset) >= 0)
|
||||
else if ((addr & 0x80000000) != 0 && ((addr + offset) & 0x80000000) == 0)
|
||||
SetValue32(data, addr + kFileSize);
|
||||
data += 4;
|
||||
curPos += 4;
|
||||
@@ -935,7 +935,7 @@ static void ItaniumDecode(Byte *data, UInt32 dataSize, UInt32 fileOffset)
|
||||
static void DeltaDecode(Byte *data, UInt32 dataSize, UInt32 numChannels)
|
||||
{
|
||||
UInt32 srcPos = 0;
|
||||
UInt32 border = dataSize * 2;
|
||||
const UInt32 border = dataSize * 2;
|
||||
for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++)
|
||||
{
|
||||
Byte prevByte = 0;
|
||||
@@ -947,12 +947,13 @@ static void DeltaDecode(Byte *data, UInt32 dataSize, UInt32 numChannels)
|
||||
static void RgbDecode(Byte *srcData, UInt32 dataSize, UInt32 width, UInt32 posR)
|
||||
{
|
||||
Byte *destData = srcData + dataSize;
|
||||
const UInt32 numChannels = 3;
|
||||
for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++)
|
||||
const UInt32 kNumChannels = 3;
|
||||
|
||||
for (UInt32 curChannel = 0; curChannel < kNumChannels; curChannel++)
|
||||
{
|
||||
Byte prevByte = 0;
|
||||
|
||||
for (UInt32 i = curChannel; i < dataSize; i+= numChannels)
|
||||
for (UInt32 i = curChannel; i < dataSize; i += kNumChannels)
|
||||
{
|
||||
unsigned int predicted;
|
||||
if (i < width)
|
||||
@@ -978,7 +979,8 @@ static void RgbDecode(Byte *srcData, UInt32 dataSize, UInt32 width, UInt32 posR)
|
||||
}
|
||||
if (dataSize < 3)
|
||||
return;
|
||||
for (UInt32 i = posR, border = dataSize - 2; i < border; i += 3)
|
||||
const UInt32 border = dataSize - 2;
|
||||
for (UInt32 i = posR; i < border; i += 3)
|
||||
{
|
||||
Byte g = destData[i + 1];
|
||||
destData[i ] = (Byte)(destData[i ] + g);
|
||||
@@ -1064,11 +1066,11 @@ static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize)
|
||||
}
|
||||
*/
|
||||
|
||||
void CVm::ExecuteStandardFilter(unsigned filterIndex)
|
||||
bool CVm::ExecuteStandardFilter(unsigned filterIndex)
|
||||
{
|
||||
UInt32 dataSize = R[4];
|
||||
if (dataSize >= kGlobalOffset)
|
||||
return;
|
||||
return false;
|
||||
EStandardFilter filterType = kStdFilters[filterIndex].Type;
|
||||
|
||||
switch (filterType)
|
||||
@@ -1077,42 +1079,59 @@ void CVm::ExecuteStandardFilter(unsigned filterIndex)
|
||||
case SF_E8E9:
|
||||
E8E9Decode(Mem, dataSize, R[6], (filterType == SF_E8E9));
|
||||
break;
|
||||
|
||||
case SF_ITANIUM:
|
||||
ItaniumDecode(Mem, dataSize, R[6]);
|
||||
break;
|
||||
|
||||
case SF_DELTA:
|
||||
{
|
||||
if (dataSize >= kGlobalOffset / 2)
|
||||
break;
|
||||
return false;
|
||||
UInt32 numChannels = R[0];
|
||||
if (numChannels == 0 || numChannels > 1024) // unrar 5.5.5
|
||||
return false;
|
||||
SetBlockPos(dataSize);
|
||||
DeltaDecode(Mem, dataSize, R[0]);
|
||||
DeltaDecode(Mem, dataSize, numChannels);
|
||||
break;
|
||||
}
|
||||
|
||||
case SF_RGB:
|
||||
if (dataSize >= kGlobalOffset / 2)
|
||||
break;
|
||||
{
|
||||
UInt32 width = R[0];
|
||||
if (width <= 3)
|
||||
break;
|
||||
SetBlockPos(dataSize);
|
||||
RgbDecode(Mem, dataSize, width, R[1]);
|
||||
}
|
||||
break;
|
||||
case SF_AUDIO:
|
||||
if (dataSize >= kGlobalOffset / 2)
|
||||
break;
|
||||
{
|
||||
if (dataSize >= kGlobalOffset / 2 || dataSize < 3) // unrar 5.5.5
|
||||
return false;
|
||||
UInt32 width = R[0];
|
||||
UInt32 posR = R[1];
|
||||
if (width < 3 || width - 3 > dataSize || posR > 2) // unrar 5.5.5
|
||||
return false;
|
||||
SetBlockPos(dataSize);
|
||||
AudioDecode(Mem, dataSize, R[0]);
|
||||
RgbDecode(Mem, dataSize, width, posR);
|
||||
break;
|
||||
}
|
||||
|
||||
case SF_AUDIO:
|
||||
{
|
||||
if (dataSize >= kGlobalOffset / 2)
|
||||
return false;
|
||||
UInt32 numChannels = R[0];
|
||||
if (numChannels == 0 || numChannels > 128) // unrar 5.5.5
|
||||
return false;
|
||||
SetBlockPos(dataSize);
|
||||
AudioDecode(Mem, dataSize, numChannels);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
case SF_UPCASE:
|
||||
if (dataSize >= kGlobalOffset / 2)
|
||||
break;
|
||||
return false;
|
||||
UInt32 destSize = UpCaseDecode(Mem, dataSize);
|
||||
SetBlockSize(destSize);
|
||||
SetBlockPos(dataSize);
|
||||
break;
|
||||
*/
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -173,7 +173,7 @@ private:
|
||||
#endif
|
||||
|
||||
#ifdef RARVM_STANDARD_FILTERS
|
||||
void ExecuteStandardFilter(unsigned filterIndex);
|
||||
bool ExecuteStandardFilter(unsigned filterIndex);
|
||||
#endif
|
||||
|
||||
Byte *Mem;
|
||||
|
||||
@@ -196,6 +196,8 @@ HRESULT CDecoder::ExecuteFilter(const CFilter &f)
|
||||
|
||||
default:
|
||||
_unsupportedFilter = true;
|
||||
memset(_filterSrc, 0, f.Size);
|
||||
// return S_OK; // unrar
|
||||
}
|
||||
|
||||
return WriteData(useDest ?
|
||||
@@ -301,7 +303,11 @@ HRESULT CDecoder::AddFilter(CBitDecoder &_bitStream)
|
||||
UInt32 blockStart = ReadUInt32(_bitStream);
|
||||
f.Size = ReadUInt32(_bitStream);
|
||||
|
||||
// if (f.Size > ((UInt32)1 << 16)) _unsupportedFilter = true;
|
||||
if (f.Size > ((UInt32)1 << 22))
|
||||
{
|
||||
_unsupportedFilter = true;
|
||||
f.Size = 0; // unrar 5.5.5
|
||||
}
|
||||
|
||||
f.Type = (Byte)_bitStream.ReadBits9fix(3);
|
||||
f.Channels = 0;
|
||||
|
||||
@@ -16,6 +16,19 @@ namespace NCompress {
|
||||
namespace NXz {
|
||||
|
||||
|
||||
CXzUnpackerCPP::CXzUnpackerCPP(): InBuf(NULL), OutBuf(NULL)
|
||||
{
|
||||
XzUnpacker_Construct(&p, &g_Alloc);
|
||||
}
|
||||
|
||||
CXzUnpackerCPP::~CXzUnpackerCPP()
|
||||
{
|
||||
XzUnpacker_Free(&p);
|
||||
MidFree(InBuf);
|
||||
MidFree(OutBuf);
|
||||
}
|
||||
|
||||
|
||||
void CStatInfo::Clear()
|
||||
{
|
||||
InSize = 0;
|
||||
@@ -40,20 +53,6 @@ void CStatInfo::Clear()
|
||||
}
|
||||
|
||||
|
||||
CXzUnpackerCPP::CXzUnpackerCPP(): InBuf(0), OutBuf(0)
|
||||
{
|
||||
XzUnpacker_Construct(&p, &g_Alloc);
|
||||
}
|
||||
|
||||
CXzUnpackerCPP::~CXzUnpackerCPP()
|
||||
{
|
||||
XzUnpacker_Free(&p);
|
||||
MidFree(InBuf);
|
||||
MidFree(OutBuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *progress)
|
||||
{
|
||||
@@ -95,8 +94,12 @@ HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream
|
||||
SizeT inLen = inSize - inPos;
|
||||
SizeT outLen = kOutBufSize - outPos;
|
||||
ECoderFinishMode finishMode = CODER_FINISH_ANY;
|
||||
|
||||
/*
|
||||
// 17.01 : the code was disabled:
|
||||
if (inSize == 0)
|
||||
finishMode = CODER_FINISH_END;
|
||||
*/
|
||||
|
||||
if (outSizeLimit)
|
||||
{
|
||||
|
||||
@@ -3,13 +3,11 @@
|
||||
#ifndef __XZ_DECODER_H
|
||||
#define __XZ_DECODER_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../ICoder.h"
|
||||
|
||||
#include "../../../C/Xz.h"
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
// #include "../../Archive/XzHandler.h"
|
||||
#include "../ICoder.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NXz {
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "../../Common/MyString.h"
|
||||
#include "../../Common/StringToInt.h"
|
||||
|
||||
#include "../Common/CWrappers.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
@@ -19,172 +22,224 @@ HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzm
|
||||
|
||||
namespace NXz {
|
||||
|
||||
extern "C" {
|
||||
|
||||
static void *SzBigAlloc(ISzAllocPtr, size_t size) { return BigAlloc(size); }
|
||||
static void SzBigFree(ISzAllocPtr, void *address) { BigFree(address); }
|
||||
static const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
|
||||
|
||||
static void *SzAlloc(ISzAllocPtr, size_t size) { return MyAlloc(size); }
|
||||
static void SzFree(ISzAllocPtr, void *address) { MyFree(address); }
|
||||
static const ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
|
||||
}
|
||||
|
||||
void CEncoder::InitCoderProps()
|
||||
{
|
||||
Lzma2EncProps_Init(&_lzma2Props);
|
||||
XzProps_Init(&xzProps);
|
||||
XzFilterProps_Init(&filter);
|
||||
|
||||
xzProps.lzma2Props = &_lzma2Props;
|
||||
// xzProps.filterProps = (_filterId != 0 ? &filter : NULL);
|
||||
xzProps.filterProps = NULL;
|
||||
}
|
||||
|
||||
CEncoder::CEncoder()
|
||||
{
|
||||
InitCoderProps();
|
||||
XzProps_Init(&xzProps);
|
||||
_encoder = NULL;
|
||||
_encoder = XzEnc_Create(&g_Alloc, &g_BigAlloc);
|
||||
if (!_encoder)
|
||||
throw 1;
|
||||
}
|
||||
|
||||
CEncoder::~CEncoder()
|
||||
{
|
||||
if (_encoder)
|
||||
XzEnc_Destroy(_encoder);
|
||||
}
|
||||
|
||||
|
||||
struct CMethodNamePair
|
||||
{
|
||||
UInt32 Id;
|
||||
const char *Name;
|
||||
};
|
||||
|
||||
static const CMethodNamePair g_NamePairs[] =
|
||||
{
|
||||
{ XZ_ID_Delta, "Delta" },
|
||||
{ XZ_ID_X86, "BCJ" },
|
||||
{ XZ_ID_PPC, "PPC" },
|
||||
{ XZ_ID_IA64, "IA64" },
|
||||
{ XZ_ID_ARM, "ARM" },
|
||||
{ XZ_ID_ARMT, "ARMT" },
|
||||
{ XZ_ID_SPARC, "SPARC" }
|
||||
// { XZ_ID_LZMA2, "LZMA2" }
|
||||
};
|
||||
|
||||
static int FilterIdFromName(const wchar_t *name)
|
||||
{
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(g_NamePairs); i++)
|
||||
{
|
||||
const CMethodNamePair &pair = g_NamePairs[i];
|
||||
if (StringsAreEqualNoCase_Ascii(name, pair.Name))
|
||||
return (int)pair.Id;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CEncoder::SetCheckSize(UInt32 checkSizeInBytes)
|
||||
{
|
||||
unsigned id;
|
||||
switch (checkSizeInBytes)
|
||||
{
|
||||
case 0: id = XZ_CHECK_NO; break;
|
||||
case 4: id = XZ_CHECK_CRC32; break;
|
||||
case 8: id = XZ_CHECK_CRC64; break;
|
||||
case 32: id = XZ_CHECK_SHA256; break;
|
||||
default: return E_INVALIDARG;
|
||||
}
|
||||
xzProps.checkId = id;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CEncoder::SetCoderProp(PROPID propID, const PROPVARIANT &prop)
|
||||
{
|
||||
return NLzma2::SetLzma2Prop(propID, prop, _lzma2Props);
|
||||
if (propID == NCoderPropID::kNumThreads)
|
||||
{
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
xzProps.numTotalThreads = (int)(prop.ulVal);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (propID == NCoderPropID::kCheckSize)
|
||||
{
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
return SetCheckSize(prop.ulVal);
|
||||
}
|
||||
|
||||
if (propID == NCoderPropID::kBlockSize2)
|
||||
{
|
||||
if (prop.vt == VT_UI4)
|
||||
xzProps.blockSize = prop.ulVal;
|
||||
else if (prop.vt == VT_UI8)
|
||||
xzProps.blockSize = prop.uhVal.QuadPart;
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (propID == NCoderPropID::kReduceSize)
|
||||
{
|
||||
if (prop.vt == VT_UI8)
|
||||
xzProps.reduceSize = prop.uhVal.QuadPart;
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (propID == NCoderPropID::kFilter)
|
||||
{
|
||||
if (prop.vt == VT_UI4)
|
||||
{
|
||||
UInt32 id32 = prop.ulVal;
|
||||
if (id32 == XZ_ID_Delta)
|
||||
return E_INVALIDARG;
|
||||
xzProps.filterProps.id = prop.ulVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prop.vt != VT_BSTR)
|
||||
return E_INVALIDARG;
|
||||
|
||||
const wchar_t *name = prop.bstrVal;
|
||||
const wchar_t *end;
|
||||
|
||||
UInt32 id32 = ConvertStringToUInt32(name, &end);
|
||||
|
||||
if (end != name)
|
||||
name = end;
|
||||
else
|
||||
{
|
||||
if (IsString1PrefixedByString2_NoCase_Ascii(name, "Delta"))
|
||||
{
|
||||
name += 5; // strlen("Delta");
|
||||
id32 = XZ_ID_Delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
int filterId = FilterIdFromName(prop.bstrVal);
|
||||
if (filterId < 0 /* || filterId == XZ_ID_LZMA2 */)
|
||||
return E_INVALIDARG;
|
||||
id32 = filterId;
|
||||
}
|
||||
}
|
||||
|
||||
if (id32 == XZ_ID_Delta)
|
||||
{
|
||||
wchar_t c = *name;
|
||||
if (c != '-' && c != ':')
|
||||
return E_INVALIDARG;
|
||||
name++;
|
||||
UInt32 delta = ConvertStringToUInt32(name, &end);
|
||||
if (end == name || *end != 0 || delta == 0 || delta > 256)
|
||||
return E_INVALIDARG;
|
||||
xzProps.filterProps.delta = delta;
|
||||
}
|
||||
|
||||
xzProps.filterProps.id = id32;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return NLzma2::SetLzma2Prop(propID, prop, xzProps.lzma2Props);
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
|
||||
const PROPVARIANT *coderProps, UInt32 numProps)
|
||||
{
|
||||
Lzma2EncProps_Init(&_lzma2Props);
|
||||
XzProps_Init(&xzProps);
|
||||
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
RINOK(SetCoderProp(propIDs[i], coderProps[i]));
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
// return SResToHRESULT(Lzma2Enc_SetProps(_encoder, &lzma2Props));
|
||||
// return SResToHRESULT(XzEnc_SetProps(_encoder, &xzProps));
|
||||
}
|
||||
|
||||
|
||||
|
||||
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */,
|
||||
ICompressProgressInfo *progress)
|
||||
STDMETHODIMP CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs,
|
||||
const PROPVARIANT *coderProps, UInt32 numProps)
|
||||
{
|
||||
CSeqOutStreamWrap seqOutStream;
|
||||
|
||||
seqOutStream.Init(outStream);
|
||||
|
||||
// if (IntToBool(newData))
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
/*
|
||||
UInt64 size;
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(0, kpidSize, &prop));
|
||||
if (prop.vt != VT_UI8)
|
||||
return E_INVALIDARG;
|
||||
size = prop.uhVal.QuadPart;
|
||||
RINOK(updateCallback->SetTotal(size));
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
CLzma2EncProps lzma2Props;
|
||||
Lzma2EncProps_Init(&lzma2Props);
|
||||
|
||||
lzma2Props.lzmaProps.level = GetLevel();
|
||||
*/
|
||||
|
||||
CSeqInStreamWrap seqInStream;
|
||||
|
||||
seqInStream.Init(inStream);
|
||||
|
||||
|
||||
/*
|
||||
{
|
||||
NCOM::CPropVariant prop = (UInt64)size;
|
||||
RINOK(NCompress::NLzma2::SetLzma2Prop(NCoderPropID::kReduceSize, prop, lzma2Props));
|
||||
}
|
||||
|
||||
FOR_VECTOR (i, _methods)
|
||||
{
|
||||
COneMethodInfo &m = _methods[i];
|
||||
SetGlobalLevelAndThreads(m
|
||||
#ifndef _7ZIP_ST
|
||||
, _numThreads
|
||||
#endif
|
||||
);
|
||||
{
|
||||
FOR_VECTOR (j, m.Props)
|
||||
{
|
||||
const CProp &prop = m.Props[j];
|
||||
RINOK(NCompress::NLzma2::SetLzma2Prop(prop.Id, prop.Value, lzma2Props));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
lzma2Props.numTotalThreads = _numThreads;
|
||||
#endif
|
||||
|
||||
*/
|
||||
|
||||
CCompressProgressWrap progressWrap;
|
||||
|
||||
progressWrap.Init(progress);
|
||||
|
||||
xzProps.checkId = XZ_CHECK_CRC32;
|
||||
// xzProps.checkId = XZ_CHECK_CRC64;
|
||||
/*
|
||||
CXzProps xzProps;
|
||||
CXzFilterProps filter;
|
||||
XzProps_Init(&xzProps);
|
||||
XzFilterProps_Init(&filter);
|
||||
xzProps.lzma2Props = &_lzma2Props;
|
||||
*/
|
||||
/*
|
||||
xzProps.filterProps = (_filterId != 0 ? &filter : NULL);
|
||||
switch (_crcSize)
|
||||
{
|
||||
case 0: xzProps.checkId = XZ_CHECK_NO; break;
|
||||
case 4: xzProps.checkId = XZ_CHECK_CRC32; break;
|
||||
case 8: xzProps.checkId = XZ_CHECK_CRC64; break;
|
||||
case 32: xzProps.checkId = XZ_CHECK_SHA256; break;
|
||||
default: return E_INVALIDARG;
|
||||
}
|
||||
filter.id = _filterId;
|
||||
if (_filterId == XZ_ID_Delta)
|
||||
{
|
||||
bool deltaDefined = false;
|
||||
FOR_VECTOR (j, _filterMethod.Props)
|
||||
{
|
||||
const CProp &prop = _filterMethod.Props[j];
|
||||
if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4)
|
||||
{
|
||||
UInt32 delta = (UInt32)prop.Value.ulVal;
|
||||
if (delta < 1 || delta > 256)
|
||||
return E_INVALIDARG;
|
||||
filter.delta = delta;
|
||||
deltaDefined = true;
|
||||
}
|
||||
}
|
||||
if (!deltaDefined)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*/
|
||||
SRes res = Xz_Encode(&seqOutStream.vt, &seqInStream.vt, &xzProps, progress ? &progressWrap.vt : NULL);
|
||||
/*
|
||||
if (res == SZ_OK)
|
||||
return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
|
||||
*/
|
||||
return SResToHRESULT(res);
|
||||
const PROPVARIANT &prop = coderProps[i];
|
||||
PROPID propID = propIDs[i];
|
||||
if (propID == NCoderPropID::kExpectedDataSize)
|
||||
if (prop.vt == VT_UI8)
|
||||
XzEnc_SetDataSize(_encoder, prop.uhVal.QuadPart);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
|
||||
if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
|
||||
|
||||
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
|
||||
{
|
||||
CSeqInStreamWrap inWrap;
|
||||
CSeqOutStreamWrap outWrap;
|
||||
CCompressProgressWrap progressWrap;
|
||||
|
||||
inWrap.Init(inStream);
|
||||
outWrap.Init(outStream);
|
||||
progressWrap.Init(progress);
|
||||
|
||||
SRes res = XzEnc_SetProps(_encoder, &xzProps);
|
||||
if (res == SZ_OK)
|
||||
res = XzEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt, progress ? &progressWrap.vt : NULL);
|
||||
|
||||
// SRes res = Xz_Encode(&outWrap.vt, &inWrap.vt, &xzProps, progress ? &progressWrap.vt : NULL);
|
||||
|
||||
RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ)
|
||||
RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
|
||||
RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
|
||||
|
||||
return SResToHRESULT(res);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -16,24 +16,26 @@ namespace NXz {
|
||||
class CEncoder:
|
||||
public ICompressCoder,
|
||||
public ICompressSetCoderProperties,
|
||||
public ICompressSetCoderPropertiesOpt,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
// CXzEncHandle _encoder;
|
||||
CXzEncHandle _encoder;
|
||||
public:
|
||||
CLzma2EncProps _lzma2Props;
|
||||
|
||||
CXzProps xzProps;
|
||||
CXzFilterProps filter;
|
||||
|
||||
MY_UNKNOWN_IMP2(ICompressCoder, ICompressSetCoderProperties)
|
||||
MY_UNKNOWN_IMP3(
|
||||
ICompressCoder,
|
||||
ICompressSetCoderProperties,
|
||||
ICompressSetCoderPropertiesOpt)
|
||||
|
||||
void InitCoderProps();
|
||||
|
||||
HRESULT SetCheckSize(UInt32 checkSizeInBytes);
|
||||
HRESULT SetCoderProp(PROPID propID, const PROPVARIANT &prop);
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
|
||||
STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
|
||||
|
||||
CEncoder();
|
||||
virtual ~CEncoder();
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
04 ICompressProgressInfo
|
||||
05 ICompressCoder
|
||||
18 ICompressCoder2
|
||||
1F ICompressSetCoderPropertiesOpt
|
||||
20 ICompressSetCoderProperties
|
||||
21 ICompressSetDecoderProperties //
|
||||
22 ICompressSetDecoderProperties2
|
||||
|
||||
@@ -104,25 +104,40 @@ namespace NCoderPropID
|
||||
enum EEnum
|
||||
{
|
||||
kDefaultProp = 0,
|
||||
kDictionarySize,
|
||||
kUsedMemorySize,
|
||||
kOrder,
|
||||
kBlockSize,
|
||||
kPosStateBits,
|
||||
kLitContextBits,
|
||||
kLitPosBits,
|
||||
kNumFastBytes,
|
||||
kMatchFinder,
|
||||
kMatchFinderCycles,
|
||||
kNumPasses,
|
||||
kAlgorithm,
|
||||
kNumThreads,
|
||||
kEndMarker,
|
||||
kLevel,
|
||||
kReduceSize // estimated size of data that will be compressed. Encoder can use this value to reduce dictionary size.
|
||||
kDictionarySize, // VT_UI4
|
||||
kUsedMemorySize, // VT_UI4
|
||||
kOrder, // VT_UI4
|
||||
kBlockSize, // VT_UI4 or VT_UI8
|
||||
kPosStateBits, // VT_UI4
|
||||
kLitContextBits, // VT_UI4
|
||||
kLitPosBits, // VT_UI4
|
||||
kNumFastBytes, // VT_UI4
|
||||
kMatchFinder, // VT_BSTR
|
||||
kMatchFinderCycles, // VT_UI4
|
||||
kNumPasses, // VT_UI4
|
||||
kAlgorithm, // VT_UI4
|
||||
kNumThreads, // VT_UI4
|
||||
kEndMarker, // VT_BOOL
|
||||
kLevel, // VT_UI4
|
||||
kReduceSize, // VT_UI8 : it's estimated size of largest data stream that will be compressed
|
||||
// encoder can use this value to reduce dictionary size and allocate data buffers
|
||||
|
||||
kExpectedDataSize, // VT_UI8 : for ICompressSetCoderPropertiesOpt :
|
||||
// it's estimated size of current data stream
|
||||
// real data size can differ from that size
|
||||
// encoder can use this value to optimize encoder initialization
|
||||
|
||||
kBlockSize2, // VT_UI4 or VT_UI8
|
||||
kCheckSize, // VT_UI4 : size of digest in bytes
|
||||
kFilter // VT_BSTR
|
||||
};
|
||||
}
|
||||
|
||||
CODER_INTERFACE(ICompressSetCoderPropertiesOpt, 0x1F)
|
||||
{
|
||||
STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) PURE;
|
||||
};
|
||||
|
||||
CODER_INTERFACE(ICompressSetCoderProperties, 0x20)
|
||||
{
|
||||
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) PURE;
|
||||
|
||||
@@ -1453,7 +1453,12 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices,
|
||||
pathMode = NExtract::NPathMode::kNoPathnames;
|
||||
*/
|
||||
|
||||
extractCallbackSpec->InitForMulti(false, pathMode, overwriteMode);
|
||||
extractCallbackSpec->InitForMulti(
|
||||
false, // multiArchives
|
||||
pathMode,
|
||||
overwriteMode,
|
||||
true // keepEmptyDirPrefixes
|
||||
);
|
||||
|
||||
if (extractCallback2)
|
||||
extractCallback2->SetTotal(_agentSpec->GetArc().GetEstmatedPhySize());
|
||||
@@ -1717,7 +1722,12 @@ STDMETHODIMP CAgent::Extract(
|
||||
COM_TRY_BEGIN
|
||||
CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
|
||||
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
|
||||
extractCallbackSpec->InitForMulti(false, pathMode, overwriteMode);
|
||||
extractCallbackSpec->InitForMulti(
|
||||
false, // multiArchives
|
||||
pathMode,
|
||||
overwriteMode,
|
||||
true // keepEmptyDirPrefixes
|
||||
);
|
||||
|
||||
CExtractNtOptions extractNtOptions;
|
||||
extractNtOptions.AltStreams.Val = true; // change it!!!
|
||||
|
||||
@@ -479,7 +479,7 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
|
||||
}
|
||||
_outFileStream.Release();
|
||||
if (_extractMode && _processedFileInfo.AttribDefined)
|
||||
SetFileAttrib(_diskFilePath, _processedFileInfo.Attrib);
|
||||
SetFileAttrib_PosixHighDetect(_diskFilePath, _processedFileInfo.Attrib);
|
||||
PrintNewLine();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -988,7 +988,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
|
||||
|| !pathParts.IsEmpty()
|
||||
|| !(_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt))
|
||||
#endif
|
||||
Correct_FsPath(_pathMode == NExtract::NPathMode::kAbsPaths, pathParts, _item.MainIsDir);
|
||||
Correct_FsPath(_pathMode == NExtract::NPathMode::kAbsPaths, _keepAndReplaceEmptyDirPrefixes, pathParts, _item.MainIsDir);
|
||||
|
||||
#ifdef SUPPORT_ALT_STREAMS
|
||||
|
||||
@@ -1542,7 +1542,7 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
|
||||
NumFiles++;
|
||||
|
||||
if (!_stdOutMode && _extractMode && _fi.AttribDefined)
|
||||
SetFileAttrib(_diskFilePath, _fi.Attrib);
|
||||
SetFileAttrib_PosixHighDetect(_diskFilePath, _fi.Attrib);
|
||||
|
||||
RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted)));
|
||||
|
||||
|
||||
@@ -172,6 +172,7 @@ class CArchiveExtractCallback:
|
||||
FString _dirPathPrefix_Full;
|
||||
NExtract::NPathMode::EEnum _pathMode;
|
||||
NExtract::NOverwriteMode::EEnum _overwriteMode;
|
||||
bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_";
|
||||
|
||||
#ifndef _SFX
|
||||
|
||||
@@ -278,11 +279,13 @@ public:
|
||||
|
||||
void InitForMulti(bool multiArchives,
|
||||
NExtract::NPathMode::EEnum pathMode,
|
||||
NExtract::NOverwriteMode::EEnum overwriteMode)
|
||||
NExtract::NOverwriteMode::EEnum overwriteMode,
|
||||
bool keepAndReplaceEmptyDirPrefixes)
|
||||
{
|
||||
_multiArchives = multiArchives;
|
||||
_pathMode = pathMode;
|
||||
_overwriteMode = overwriteMode;
|
||||
_keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes;
|
||||
NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -2376,15 +2376,7 @@ static UInt32 GetNumThreadsNext(unsigned i, UInt32 numThreads)
|
||||
|
||||
static bool AreSameMethodNames(const char *fullName, const char *shortName)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
char c2 = *shortName++;
|
||||
if (c2 == 0)
|
||||
return true;
|
||||
char c1 = *fullName++;
|
||||
if (MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
|
||||
return false;
|
||||
}
|
||||
return StringsAreEqualNoCase_Ascii(fullName, shortName);
|
||||
}
|
||||
|
||||
|
||||
@@ -2545,27 +2537,24 @@ static const char * const k_PF[] =
|
||||
#endif
|
||||
|
||||
|
||||
static void PrintSize(AString &s, UInt64 ptr)
|
||||
static void PrintSize(AString &s, UInt64 v)
|
||||
{
|
||||
UInt64 v = ptr;
|
||||
UInt64 t = v >> 40;
|
||||
UInt64 g = v >> 30;
|
||||
UInt64 m = v >> 20;
|
||||
UInt64 k = v >> 10;
|
||||
UInt32 d = (UInt32)v;
|
||||
char c = 0;
|
||||
if (t >= 1000) { d = (UInt32)t; c = 'T'; }
|
||||
else if (g >= 1000) { d = (UInt32)g; c = 'G'; }
|
||||
else if (m >= 1000) { d = (UInt32)m; c = 'M'; }
|
||||
else if (k >= 10) { d = (UInt32)k; c = 'K'; }
|
||||
|
||||
s.Add_UInt32(d);
|
||||
// s += ' ';
|
||||
if ((v & 0x3FF) == 0) { v >>= 10; c = 'K';
|
||||
if ((v & 0x3FF) == 0) { v >>= 10; c = 'M';
|
||||
if ((v & 0x3FF) == 0) { v >>= 10; c = 'G';
|
||||
if ((v & 0x3FF) == 0) { v >>= 10; c = 'T';
|
||||
}}}}
|
||||
else
|
||||
{
|
||||
PrintHex(s, v);
|
||||
return;
|
||||
}
|
||||
char temp[32];
|
||||
ConvertUInt64ToString(v, temp);
|
||||
s += temp;
|
||||
if (c)
|
||||
s += c;
|
||||
|
||||
|
||||
// PrintHex(s, (DWORD_PTR)v);
|
||||
}
|
||||
|
||||
|
||||
@@ -2631,12 +2620,19 @@ static void SysInfo_To_String(AString &s, const SYSTEM_INFO &si)
|
||||
s += " ";
|
||||
|
||||
DWORD_PTR minAdd = (DWORD_PTR)si.lpMinimumApplicationAddress;
|
||||
if (minAdd != (1 << 16))
|
||||
UInt64 maxSize = (UInt64)(DWORD_PTR)si.lpMaximumApplicationAddress + 1;
|
||||
const UInt32 kReserveSize = ((UInt32)1 << 16);
|
||||
if (minAdd != kReserveSize)
|
||||
{
|
||||
PrintSize(s, minAdd);
|
||||
s += "-";
|
||||
}
|
||||
PrintSize(s, (UInt64)(DWORD_PTR)si.lpMaximumApplicationAddress + 1);
|
||||
else
|
||||
{
|
||||
if ((maxSize & (kReserveSize - 1)) == 0)
|
||||
maxSize += kReserveSize;
|
||||
}
|
||||
PrintSize(s, maxSize);
|
||||
}
|
||||
|
||||
#ifndef _WIN64
|
||||
@@ -3006,26 +3002,34 @@ HRESULT Bench(
|
||||
UInt32 complexity = 10000;
|
||||
const UInt32 *checkSum = NULL;
|
||||
{
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(g_Hash); i++)
|
||||
unsigned i;
|
||||
for (i = 0; i < ARRAY_SIZE(g_Hash); i++)
|
||||
{
|
||||
const CBenchHash &h = g_Hash[i];
|
||||
AString s (h.Name);
|
||||
AString hProp;
|
||||
int propPos = s.Find(':');
|
||||
AString benchMethod (h.Name);
|
||||
AString benchProps;
|
||||
int propPos = benchMethod.Find(':');
|
||||
if (propPos >= 0)
|
||||
{
|
||||
hProp = s.Ptr(propPos + 1);
|
||||
s.DeleteFrom(propPos);
|
||||
benchProps = benchMethod.Ptr(propPos + 1);
|
||||
benchMethod.DeleteFrom(propPos);
|
||||
}
|
||||
|
||||
if (AreSameMethodNames(s, methodName))
|
||||
if (AreSameMethodNames(benchMethod, methodName))
|
||||
{
|
||||
complexity = h.Complex;
|
||||
checkSum = &h.CheckSum;
|
||||
if (method.PropsString.IsEqualTo_Ascii_NoCase(hProp))
|
||||
break;
|
||||
if (benchProps.IsEmpty()
|
||||
|| benchMethod.IsEqualTo_Ascii_NoCase("crc32") && benchProps == "8" && method.PropsString.IsEmpty()
|
||||
|| method.PropsString.IsPrefixedBy_Ascii_NoCase(benchProps))
|
||||
{
|
||||
complexity = h.Complex;
|
||||
checkSum = &h.CheckSum;
|
||||
if (method.PropsString.IsEqualTo_Ascii_NoCase(benchProps))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i == ARRAY_SIZE(g_Hash))
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
f.NewLine();
|
||||
@@ -3316,18 +3320,35 @@ HRESULT Bench(
|
||||
bool needSetComplexity = true;
|
||||
if (!methodName.IsEqualTo_Ascii_NoCase("LZMA"))
|
||||
{
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(g_Bench); i++)
|
||||
unsigned i;
|
||||
for (i = 0; i < ARRAY_SIZE(g_Bench); i++)
|
||||
{
|
||||
const CBenchMethod &h = g_Bench[i];
|
||||
if (AreSameMethodNames(h.Name, methodName))
|
||||
AString benchMethod (h.Name);
|
||||
AString benchProps;
|
||||
int propPos = benchMethod.Find(':');
|
||||
if (propPos >= 0)
|
||||
{
|
||||
callback.BenchProps.EncComplex = h.EncComplex;
|
||||
callback.BenchProps.DecComplexCompr = h.DecComplexCompr;
|
||||
callback.BenchProps.DecComplexUnc = h.DecComplexUnc;;
|
||||
needSetComplexity = false;
|
||||
break;
|
||||
benchProps = benchMethod.Ptr(propPos + 1);
|
||||
benchMethod.DeleteFrom(propPos);
|
||||
}
|
||||
|
||||
if (AreSameMethodNames(benchMethod, methodName))
|
||||
{
|
||||
if (benchProps.IsEmpty()
|
||||
|| benchProps == "x5" && method.PropsString.IsEmpty()
|
||||
|| method.PropsString.IsPrefixedBy_Ascii_NoCase(benchProps))
|
||||
{
|
||||
callback.BenchProps.EncComplex = h.EncComplex;
|
||||
callback.BenchProps.DecComplexCompr = h.DecComplexCompr;
|
||||
callback.BenchProps.DecComplexUnc = h.DecComplexUnc;;
|
||||
needSetComplexity = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i == ARRAY_SIZE(g_Bench))
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
if (needSetComplexity)
|
||||
callback.BenchProps.SetLzmaCompexity();
|
||||
|
||||
@@ -39,7 +39,6 @@ using namespace NWindows;
|
||||
#define kArcIncludeSwitches " -an -ai"
|
||||
#define kHashIncludeSwitches " -i"
|
||||
#define kStopSwitchParsing " --"
|
||||
#define kLargePagesDisable " -slp-"
|
||||
|
||||
extern HWND g_HWND;
|
||||
|
||||
@@ -94,8 +93,8 @@ static HRESULT Call7zGui(const UString ¶ms,
|
||||
|
||||
static void AddLagePagesSwitch(UString ¶ms)
|
||||
{
|
||||
if (!ReadLockMemoryEnable())
|
||||
params += kLargePagesDisable;
|
||||
if (ReadLockMemoryEnable())
|
||||
params += " -slp";
|
||||
}
|
||||
|
||||
class CRandNameGenerator
|
||||
@@ -289,6 +288,7 @@ void Benchmark(bool totalMode)
|
||||
UString params ('b');
|
||||
if (totalMode)
|
||||
params += " -mm=*";
|
||||
AddLagePagesSwitch(params);
|
||||
HRESULT result = Call7zGui(params, false, NULL);
|
||||
if (result != S_OK)
|
||||
ErrorMessageHRESULT(result);
|
||||
|
||||
@@ -21,7 +21,7 @@ struct CDirItemsStat
|
||||
|
||||
UInt64 NumErrors;
|
||||
|
||||
UInt64 Get_NumItems() const { return NumDirs + NumFiles + NumAltStreams; }
|
||||
// UInt64 Get_NumItems() const { return NumDirs + NumFiles + NumAltStreams; }
|
||||
UInt64 Get_NumDataItems() const { return NumFiles + NumAltStreams; }
|
||||
UInt64 GetTotalBytes() const { return FilesSize + AltStreamsSize; }
|
||||
|
||||
@@ -43,6 +43,30 @@ struct CDirItemsStat
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
struct CDirItemsStat2: public CDirItemsStat
|
||||
{
|
||||
UInt64 Anti_NumDirs;
|
||||
UInt64 Anti_NumFiles;
|
||||
UInt64 Anti_NumAltStreams;
|
||||
|
||||
// UInt64 Get_NumItems() const { return Anti_NumDirs + Anti_NumFiles + Anti_NumAltStreams + CDirItemsStat::Get_NumItems(); }
|
||||
UInt64 Get_NumDataItems2() const { return Anti_NumFiles + Anti_NumAltStreams + CDirItemsStat::Get_NumDataItems(); }
|
||||
|
||||
bool IsEmpty() const { return CDirItemsStat::IsEmpty()
|
||||
&& 0 == Anti_NumDirs
|
||||
&& 0 == Anti_NumFiles
|
||||
&& 0 == Anti_NumAltStreams; }
|
||||
|
||||
CDirItemsStat2():
|
||||
Anti_NumDirs(0),
|
||||
Anti_NumFiles(0),
|
||||
Anti_NumAltStreams(0)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define INTERFACE_IDirItemsCallback(x) \
|
||||
virtual HRESULT ScanError(const FString &path, DWORD systemError) x; \
|
||||
virtual HRESULT ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) x; \
|
||||
|
||||
@@ -343,6 +343,7 @@ static HRESULT EnumerateAltStreams(
|
||||
const NWildcard::CCensorNode &curNode,
|
||||
int phyParent, int logParent, const FString &fullPath,
|
||||
const UStringVector &addArchivePrefix, // prefix from curNode
|
||||
bool addAllItems,
|
||||
CDirItems &dirItems)
|
||||
{
|
||||
NFind::CStreamEnumerator enumerator(fullPath);
|
||||
@@ -363,6 +364,10 @@ static HRESULT EnumerateAltStreams(
|
||||
addArchivePrefixNew.Back() += reducedName;
|
||||
if (curNode.CheckPathToRoot(false, addArchivePrefixNew, true))
|
||||
continue;
|
||||
if (!addAllItems)
|
||||
if (!curNode.CheckPathToRoot(true, addArchivePrefixNew, true))
|
||||
continue;
|
||||
|
||||
NFind::CFileInfo fi2 = fi;
|
||||
fi2.Name += us2fs(reducedName);
|
||||
fi2.Size = si.Size;
|
||||
@@ -413,6 +418,8 @@ static HRESULT EnumerateForItem(
|
||||
}
|
||||
int dirItemIndex = -1;
|
||||
|
||||
bool addAllSubStreams = false;
|
||||
|
||||
if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir()))
|
||||
{
|
||||
int secureIndex = -1;
|
||||
@@ -427,6 +434,8 @@ static HRESULT EnumerateForItem(
|
||||
dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi);
|
||||
if (fi.IsDir())
|
||||
enterToSubFolders2 = true;
|
||||
|
||||
addAllSubStreams = true;
|
||||
}
|
||||
|
||||
#ifndef UNDER_CE
|
||||
@@ -434,7 +443,9 @@ static HRESULT EnumerateForItem(
|
||||
{
|
||||
RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent,
|
||||
phyPrefix + fi.Name,
|
||||
addArchivePrefixNew, dirItems));
|
||||
addArchivePrefixNew,
|
||||
addAllSubStreams,
|
||||
dirItems));
|
||||
}
|
||||
|
||||
if (dirItemIndex >= 0)
|
||||
@@ -643,7 +654,9 @@ static HRESULT EnumerateDirItems(
|
||||
UStringVector pathParts;
|
||||
pathParts.Add(fs2us(fi.Name));
|
||||
RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent,
|
||||
fullPath, pathParts, dirItems));
|
||||
fullPath, pathParts,
|
||||
true, /* addAllSubStreams */
|
||||
dirItems));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -279,7 +279,9 @@ HRESULT Extract(
|
||||
CArchiveExtractCallback *ecs = new CArchiveExtractCallback;
|
||||
CMyComPtr<IArchiveExtractCallback> ec(ecs);
|
||||
bool multi = (numArcs > 1);
|
||||
ecs->InitForMulti(multi, options.PathMode, options.OverwriteMode);
|
||||
ecs->InitForMulti(multi, options.PathMode, options.OverwriteMode,
|
||||
false // keepEmptyDirParts
|
||||
);
|
||||
#ifndef _SFX
|
||||
ecs->SetHashMethods(hash);
|
||||
#endif
|
||||
|
||||
@@ -146,6 +146,9 @@ static void CorrectUnsupportedName(UString &name)
|
||||
static void Correct_PathPart(UString &s)
|
||||
{
|
||||
// "." and ".."
|
||||
if (s.IsEmpty())
|
||||
return;
|
||||
|
||||
if (s[0] == '.' && (s[1] == 0 || s[1] == '.' && s[2] == 0))
|
||||
s.Empty();
|
||||
#ifdef _WIN32
|
||||
@@ -172,7 +175,7 @@ UString Get_Correct_FsFile_Name(const UString &name)
|
||||
}
|
||||
|
||||
|
||||
void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir)
|
||||
void Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir)
|
||||
{
|
||||
unsigned i = 0;
|
||||
|
||||
@@ -181,6 +184,7 @@ void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir)
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
bool isDrive = false;
|
||||
#endif
|
||||
|
||||
if (parts[0].IsEmpty())
|
||||
{
|
||||
i = 1;
|
||||
@@ -191,7 +195,7 @@ void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir)
|
||||
if (parts.Size() > 2 && parts[2] == L"?")
|
||||
{
|
||||
i = 3;
|
||||
if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3]))
|
||||
if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3]))
|
||||
{
|
||||
isDrive = true;
|
||||
i = 4;
|
||||
@@ -220,6 +224,9 @@ void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (i != 0)
|
||||
keepAndReplaceEmptyPrefixes = false;
|
||||
|
||||
for (; i < parts.Size();)
|
||||
{
|
||||
UString &s = parts[i];
|
||||
@@ -228,15 +235,17 @@ void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir)
|
||||
|
||||
if (s.IsEmpty())
|
||||
{
|
||||
if (isDir || i != parts.Size() - 1)
|
||||
{
|
||||
parts.Delete(i);
|
||||
continue;
|
||||
}
|
||||
if (!keepAndReplaceEmptyPrefixes)
|
||||
if (isDir || i != parts.Size() - 1)
|
||||
{
|
||||
parts.Delete(i);
|
||||
continue;
|
||||
}
|
||||
s = k_EmptyReplaceName;
|
||||
}
|
||||
else
|
||||
{
|
||||
keepAndReplaceEmptyPrefixes = false;
|
||||
#ifdef _WIN32
|
||||
CorrectUnsupportedName(s);
|
||||
#endif
|
||||
|
||||
@@ -12,7 +12,19 @@ void Correct_AltStream_Name(UString &s);
|
||||
// replaces unsuported characters, and replaces "." , ".." and "" to "[]"
|
||||
UString Get_Correct_FsFile_Name(const UString &name);
|
||||
|
||||
void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir);
|
||||
/*
|
||||
Correct_FsPath() corrects path parts to prepare it for File System operations.
|
||||
It also corrects empty path parts like "\\\\":
|
||||
- frontal empty path parts : it removes them or changes them to "_"
|
||||
- another empty path parts : it removes them
|
||||
if (absIsAllowed && path is absolute) : it removes empty path parts after start absolute path prefix marker
|
||||
else
|
||||
{
|
||||
if (!keepAndReplaceEmptyPrefixes) : it removes empty path parts
|
||||
if ( keepAndReplaceEmptyPrefixes) : it changes each empty frontal path part to "_"
|
||||
}
|
||||
*/
|
||||
void Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir);
|
||||
|
||||
UString MakePathFromParts(const UStringVector &parts);
|
||||
|
||||
|
||||
@@ -19,12 +19,16 @@
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
static const char g_WinAttribChars[16 + 1] = "RHS8DAdNTsLCOnE_";
|
||||
static const unsigned kNumWinAtrribFlags = 21;
|
||||
static const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEV.X.PU";
|
||||
|
||||
/*
|
||||
FILE_ATTRIBUTE_
|
||||
|
||||
0 READONLY
|
||||
1 HIDDEN
|
||||
2 SYSTEM
|
||||
|
||||
3 (Volume label - obsolete)
|
||||
4 DIRECTORY
|
||||
5 ARCHIVE
|
||||
6 DEVICE
|
||||
@@ -34,12 +38,19 @@ static const char g_WinAttribChars[16 + 1] = "RHS8DAdNTsLCOnE_";
|
||||
10 REPARSE_POINT
|
||||
11 COMPRESSED
|
||||
12 OFFLINE
|
||||
13 NOT_CONTENT_INDEXED
|
||||
13 NOT_CONTENT_INDEXED (I - Win10 attrib/Explorer)
|
||||
14 ENCRYPTED
|
||||
|
||||
16 VIRTUAL
|
||||
15 INTEGRITY_STREAM (V - ReFS Win8/Win2012)
|
||||
16 VIRTUAL (reserved)
|
||||
17 NO_SCRUB_DATA (X - ReFS Win8/Win2012 attrib)
|
||||
18 RECALL_ON_OPEN or EA
|
||||
19 PINNED
|
||||
20 UNPINNED
|
||||
21 STRICTLY_SEQUENTIAL
|
||||
22 RECALL_ON_DATA_ACCESS
|
||||
*/
|
||||
|
||||
|
||||
static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' };
|
||||
#define MY_ATTR_CHAR(a, n, c) ((a) & (1 << (n))) ? c : '-';
|
||||
|
||||
@@ -65,24 +76,57 @@ static void ConvertPosixAttribToString(char *s, UInt32 a) throw()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ConvertWinAttribToString(char *s, UInt32 wa) throw()
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
if ((wa & (1 << i)) && i != 7)
|
||||
*s++ = g_WinAttribChars[i];
|
||||
*s = 0;
|
||||
|
||||
// we support p7zip trick that stores posix attributes in high 16 bits, and 0x8000 flag
|
||||
// we also support ZIP archives created in Unix, that store posix attributes in high 16 bits without 0x8000 flag
|
||||
/*
|
||||
some programs store posix attributes in high 16 bits.
|
||||
p7zip - stores additional 0x8000 flag marker.
|
||||
macos - stores additional 0x4000 flag marker.
|
||||
info-zip - no additional marker.
|
||||
*/
|
||||
|
||||
// if (wa & 0x8000)
|
||||
if ((wa >> 16) != 0)
|
||||
bool isPosix = ((wa & 0xF0000000) != 0);
|
||||
|
||||
UInt32 posix = 0;
|
||||
if (isPosix)
|
||||
{
|
||||
posix = wa >> 16;
|
||||
wa &= (UInt32)0x3FFF;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < kNumWinAtrribFlags; i++)
|
||||
{
|
||||
UInt32 flag = (1 << i);
|
||||
if ((wa & flag) != 0)
|
||||
{
|
||||
char c = g_WinAttribChars[i];
|
||||
if (c != '.')
|
||||
{
|
||||
wa &= ~flag;
|
||||
// if (i != 7) // we can disable N (NORMAL) printing
|
||||
*s++ = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wa != 0)
|
||||
{
|
||||
*s++ = ' ';
|
||||
ConvertPosixAttribToString(s, wa >> 16);
|
||||
ConvertUInt32ToHex8Digits(wa, s);
|
||||
s += strlen(s);
|
||||
}
|
||||
|
||||
*s = 0;
|
||||
|
||||
if (isPosix)
|
||||
{
|
||||
*s++ = ' ';
|
||||
ConvertPosixAttribToString(s, posix);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &prop, PROPID propID, int level) throw()
|
||||
{
|
||||
*dest = 0;
|
||||
|
||||
@@ -657,38 +657,74 @@ static HRESULT Compress(
|
||||
FOR_VECTOR (i, updatePairs2)
|
||||
{
|
||||
const CUpdatePair2 &up = updatePairs2[i];
|
||||
if (up.NewData)
|
||||
|
||||
// 17.01: anti-item is (up.NewData && (p.UseArcProps in most cases))
|
||||
|
||||
if (up.NewData && !up.UseArcProps)
|
||||
{
|
||||
CDirItemsStat &stat = stat2.NewData;
|
||||
const CDirItem &di = dirItems.Items[up.DirIndex];
|
||||
if (di.IsDir())
|
||||
stat.NumDirs++;
|
||||
else if (di.IsAltStream)
|
||||
if (up.ExistOnDisk())
|
||||
{
|
||||
stat.NumAltStreams++;
|
||||
stat.AltStreamsSize += di.Size;
|
||||
}
|
||||
else
|
||||
{
|
||||
stat.NumFiles++;
|
||||
stat.FilesSize += di.Size;
|
||||
CDirItemsStat2 &stat = stat2.NewData;
|
||||
const CDirItem &di = dirItems.Items[up.DirIndex];
|
||||
if (di.IsDir())
|
||||
{
|
||||
if (up.IsAnti)
|
||||
stat.Anti_NumDirs++;
|
||||
else
|
||||
stat.NumDirs++;
|
||||
}
|
||||
else if (di.IsAltStream)
|
||||
{
|
||||
if (up.IsAnti)
|
||||
stat.Anti_NumAltStreams++;
|
||||
else
|
||||
{
|
||||
stat.NumAltStreams++;
|
||||
stat.AltStreamsSize += di.Size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (up.IsAnti)
|
||||
stat.Anti_NumFiles++;
|
||||
else
|
||||
{
|
||||
stat.NumFiles++;
|
||||
stat.FilesSize += di.Size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (up.ArcIndex >= 0)
|
||||
{
|
||||
CDirItemsStat &stat = stat2.OldData;
|
||||
CDirItemsStat2 &stat = *(up.NewData ? &stat2.NewData : &stat2.OldData);
|
||||
const CArcItem &ai = arcItems[up.ArcIndex];
|
||||
if (ai.IsDir)
|
||||
stat.NumDirs++;
|
||||
{
|
||||
if (up.IsAnti)
|
||||
stat.Anti_NumDirs++;
|
||||
else
|
||||
stat.NumDirs++;
|
||||
}
|
||||
else if (ai.IsAltStream)
|
||||
{
|
||||
stat.NumAltStreams++;
|
||||
stat.AltStreamsSize += ai.Size;
|
||||
if (up.IsAnti)
|
||||
stat.Anti_NumAltStreams++;
|
||||
else
|
||||
{
|
||||
stat.NumAltStreams++;
|
||||
stat.AltStreamsSize += ai.Size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stat.NumFiles++;
|
||||
stat.FilesSize += ai.Size;
|
||||
if (up.IsAnti)
|
||||
stat.Anti_NumFiles++;
|
||||
else
|
||||
{
|
||||
stat.NumFiles++;
|
||||
stat.FilesSize += ai.Size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1592,8 +1628,18 @@ HRESULT UpdateArchive(
|
||||
{
|
||||
if (processedItems[i] != 0 || dirItem.Size == 0)
|
||||
{
|
||||
RINOK(callback->DeletingAfterArchiving(phyPath, false));
|
||||
DeleteFileAlways(phyPath);
|
||||
NFind::CFileInfo fileInfo;
|
||||
if (fileInfo.Find(phyPath))
|
||||
{
|
||||
// maybe we must exclude also files with archive name: "a a.7z * -sdel"
|
||||
if (fileInfo.Size == dirItem.Size
|
||||
&& CompareFileTime(&fileInfo.MTime, &dirItem.MTime) == 0
|
||||
&& CompareFileTime(&fileInfo.CTime, &dirItem.CTime) == 0)
|
||||
{
|
||||
RINOK(callback->DeletingAfterArchiving(phyPath, false));
|
||||
DeleteFileAlways(phyPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
|
||||
struct CArcToDoStat
|
||||
{
|
||||
CDirItemsStat NewData;
|
||||
CDirItemsStat OldData;
|
||||
CDirItemsStat DeleteData;
|
||||
CDirItemsStat2 NewData;
|
||||
CDirItemsStat2 OldData;
|
||||
CDirItemsStat2 DeleteData;
|
||||
|
||||
UInt64 Get_NumDataItems_Total() const
|
||||
{
|
||||
return NewData.Get_NumDataItems() + OldData.Get_NumDataItems();
|
||||
return NewData.Get_NumDataItems2() + OldData.Get_NumDataItems2();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -48,9 +48,14 @@ namespace NCompression
|
||||
UString Options;
|
||||
UString EncryptionMethod;
|
||||
|
||||
void Reset_BlockLogSize()
|
||||
{
|
||||
BlockLogSize = (UInt32)(Int32)-1;
|
||||
}
|
||||
|
||||
void ResetForLevelChange()
|
||||
{
|
||||
BlockLogSize = NumThreads = Level = Dictionary = Order = UInt32(-1);
|
||||
BlockLogSize = NumThreads = Level = Dictionary = Order = (UInt32)(Int32)-1;
|
||||
Method.Empty();
|
||||
// Options.Empty();
|
||||
// EncryptionMethod.Empty();
|
||||
|
||||
@@ -114,6 +114,39 @@ void Print_DirItemsStat(AString &s, const CDirItemsStat &st)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st)
|
||||
{
|
||||
Print_DirItemsStat(s, (CDirItemsStat &)st);
|
||||
bool needLF = true;
|
||||
if (st.Anti_NumDirs != 0)
|
||||
{
|
||||
if (needLF)
|
||||
s.Add_LF();
|
||||
needLF = false;
|
||||
Print_UInt64_and_String(s, st.Anti_NumDirs, st.Anti_NumDirs == 1 ? "anti-folder" : "anti-folders");
|
||||
}
|
||||
if (st.Anti_NumFiles != 0)
|
||||
{
|
||||
if (needLF)
|
||||
s.Add_LF();
|
||||
else
|
||||
s += ", ";
|
||||
needLF = false;
|
||||
Print_UInt64_and_String(s, st.Anti_NumFiles, st.Anti_NumFiles == 1 ? "anti-file" : "anti-files");
|
||||
}
|
||||
if (st.Anti_NumAltStreams != 0)
|
||||
{
|
||||
if (needLF)
|
||||
s.Add_LF();
|
||||
else
|
||||
s += ", ";
|
||||
needLF = false;
|
||||
Print_UInt64_and_String(s, st.Anti_NumAltStreams, "anti-alternate-streams");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CExtractScanConsole::PrintStat(const CDirItemsStat &st)
|
||||
{
|
||||
if (_so)
|
||||
|
||||
@@ -97,7 +97,6 @@ static const char * const kHelpString =
|
||||
#endif
|
||||
#endif
|
||||
" <command> [<switches>...] <archive_name> [<file_names>...]\n"
|
||||
" [<@listfiles...>]\n"
|
||||
"\n"
|
||||
"<Commands>\n"
|
||||
" a : Add files to archive\n"
|
||||
@@ -114,6 +113,7 @@ static const char * const kHelpString =
|
||||
"\n"
|
||||
"<Switches>\n"
|
||||
" -- : Stop switches parsing\n"
|
||||
" @listfile : set path to listfile that contains file names\n"
|
||||
" -ai[r[-|0]]{@listfile|!wildcard} : Include archives\n"
|
||||
" -ax[r[-|0]]{@listfile|!wildcard} : eXclude archives\n"
|
||||
" -ao{a|s|t|u} : set Overwrite mode\n"
|
||||
@@ -548,6 +548,7 @@ int Main2(
|
||||
if (options.LargePages)
|
||||
{
|
||||
SetLargePageSize();
|
||||
// note: this process also can inherit that Privilege from parent process
|
||||
g_LargePagesMode =
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
NSecurity::EnablePrivilege_LockMemory();
|
||||
|
||||
@@ -241,6 +241,7 @@ static void PrintPropPair(AString &s, const char *name, UInt64 val)
|
||||
|
||||
void PrintSize_bytes_Smart(AString &s, UInt64 val);
|
||||
void Print_DirItemsStat(AString &s, const CDirItemsStat &st);
|
||||
void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st);
|
||||
|
||||
HRESULT CUpdateCallbackConsole::FinishScanning(const CDirItemsStat &st)
|
||||
{
|
||||
@@ -399,10 +400,10 @@ HRESULT CUpdateCallbackConsole::Finalize()
|
||||
*/
|
||||
|
||||
|
||||
void static PrintToDoStat(CStdOutStream *_so, const CDirItemsStat &stat, const char *name)
|
||||
void static PrintToDoStat(CStdOutStream *_so, const CDirItemsStat2 &stat, const char *name)
|
||||
{
|
||||
AString s;
|
||||
Print_DirItemsStat(s, stat);
|
||||
Print_DirItemsStat2(s, stat);
|
||||
*_so << name << ": " << s << endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
namespace NMessageID {
|
||||
|
||||
const unsigned k_Last_PropId_supported_by_plugin = kpidStreamId;
|
||||
const unsigned k_Last_PropId_supported_by_plugin = kpidCopyLink;
|
||||
|
||||
enum EEnum
|
||||
{
|
||||
|
||||
@@ -574,7 +574,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
|
||||
}
|
||||
else if (!srcPanel.DoesItSupportOperations())
|
||||
{
|
||||
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
srcPanel.MessageBox_Error_UnsupportOperation();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -608,6 +608,8 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
|
||||
UStringVector copyFolders;
|
||||
ReadCopyHistory(copyFolders);
|
||||
|
||||
bool useFullItemPaths = srcPanel.Is_IO_FS_Folder(); // maybe we need flat also here ??
|
||||
|
||||
{
|
||||
CCopyDialog copyDialog;
|
||||
|
||||
@@ -626,14 +628,14 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
|
||||
{
|
||||
if (destPath.IsEmpty())
|
||||
{
|
||||
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
srcPanel.MessageBox_Error_UnsupportOperation();
|
||||
return;
|
||||
}
|
||||
|
||||
UString correctName;
|
||||
if (!srcPanel.CorrectFsPath(destPath, correctName))
|
||||
{
|
||||
srcPanel.MessageBoxError(E_INVALIDARG);
|
||||
srcPanel.MessageBox_Error_HRESULT(E_INVALIDARG);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -647,7 +649,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
|
||||
if (destPath.Len() > 0 && destPath[0] == '\\')
|
||||
if (destPath.Len() == 1 || destPath[1] != '\\')
|
||||
{
|
||||
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
srcPanel.MessageBox_Error_UnsupportOperation();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -658,7 +660,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
|
||||
{
|
||||
if (NumPanels == 1 || CompareFileNames(destPath, srcPanel.GetFsPath()) == 0)
|
||||
{
|
||||
srcPanel.MessageBoxMyError(L"Can not copy files onto itself");
|
||||
srcPanel.MessageBox_Error(L"Can not copy files onto itself");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -674,7 +676,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
|
||||
destIsFsPath = true;
|
||||
else if (destPanel.IsFSDrivesFolder() || destPanel.IsRootFolder())
|
||||
{
|
||||
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
srcPanel.MessageBox_Error_UnsupportOperation();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -683,7 +685,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
|
||||
if (IsAltPathPrefix(us2fs(destPath)))
|
||||
{
|
||||
// we allow alt streams dest only to alt stream folder in second panel
|
||||
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
srcPanel.MessageBox_Error_UnsupportOperation();
|
||||
return;
|
||||
/*
|
||||
FString basePath = us2fs(destPath);
|
||||
@@ -704,7 +706,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
|
||||
int pos = destPath.ReverseFind_PathSepar();
|
||||
if (pos < 0)
|
||||
{
|
||||
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
srcPanel.MessageBox_Error_UnsupportOperation();
|
||||
return;
|
||||
}
|
||||
{
|
||||
@@ -713,7 +715,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
|
||||
UString name = destPath.Ptr(pos + 1);
|
||||
if (name.Find(L':') >= 0)
|
||||
{
|
||||
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
srcPanel.MessageBox_Error_UnsupportOperation();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -721,7 +723,8 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
|
||||
UString prefix = destPath.Left(pos + 1);
|
||||
if (!CreateComplexDir(us2fs(prefix)))
|
||||
{
|
||||
srcPanel.MessageBoxError2Lines(prefix, GetLastError());
|
||||
DWORD lastError = ::GetLastError();
|
||||
srcPanel.MessageBox_Error_2Lines_Message_HRESULT(prefix, lastError);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -732,7 +735,8 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
|
||||
NName::NormalizeDirPathPrefix(destPath);
|
||||
if (!CreateComplexDir(us2fs(destPath)))
|
||||
{
|
||||
srcPanel.MessageBoxError2Lines(destPath, GetLastError());
|
||||
DWORD lastError = ::GetLastError();
|
||||
srcPanel.MessageBox_Error_2Lines_Message_HRESULT(destPath, lastError);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -754,7 +758,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
|
||||
bool useTemp = useSrcPanel && useDestPanel;
|
||||
if (useTemp && NumPanels == 1)
|
||||
{
|
||||
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
srcPanel.MessageBox_Error_UnsupportOperation();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -793,13 +797,25 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
|
||||
{
|
||||
UStringVector filePaths;
|
||||
UString folderPrefix;
|
||||
|
||||
if (useTemp)
|
||||
folderPrefix = fs2us(tempDirPrefix);
|
||||
else
|
||||
folderPrefix = srcPanel.GetFsPath();
|
||||
|
||||
filePaths.ClearAndReserve(indices.Size());
|
||||
|
||||
FOR_VECTOR (i, indices)
|
||||
filePaths.AddInReserved(srcPanel.GetItemRelPath2(indices[i]));
|
||||
{
|
||||
UInt32 index = indices[i];
|
||||
UString s;
|
||||
if (useFullItemPaths)
|
||||
s = srcPanel.GetItemRelPath2(index);
|
||||
else
|
||||
s = srcPanel.GetItemName_for_Copy(index);
|
||||
filePaths.AddInReserved(s);
|
||||
}
|
||||
|
||||
result = destPanel.CopyFrom(move, folderPrefix, filePaths, true, 0);
|
||||
}
|
||||
|
||||
@@ -812,7 +828,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
|
||||
// srcPanel.InvalidateList(NULL, true);
|
||||
|
||||
if (result != E_ABORT)
|
||||
srcPanel.MessageBoxError(result);
|
||||
srcPanel.MessageBox_Error_HRESULT(result);
|
||||
// return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1025,7 +1025,7 @@ HRESULT CVirtFileSystem::FlushToDisk(bool closeLast)
|
||||
_numFlushed++;
|
||||
_fileIsOpen = false;
|
||||
if (file.AttribDefined)
|
||||
NDir::SetFileAttrib(path, file.Attrib);
|
||||
NDir::SetFileAttrib_PosixHighDetect(path, file.Attrib);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -383,7 +383,10 @@ static void SetMemoryLock()
|
||||
NSecurity::AddLockMemoryPrivilege();
|
||||
|
||||
if (ReadLockMemoryEnable())
|
||||
{
|
||||
// note: child processes can inherit that Privilege
|
||||
g_LargePagesMode = NSecurity::EnablePrivilege_LockMemory();
|
||||
}
|
||||
}
|
||||
|
||||
bool g_SymLink_Supported = false;
|
||||
|
||||
@@ -205,7 +205,7 @@ struct CCopyStateIO
|
||||
|
||||
CCopyStateIO(): DeleteSrcFile(false), TotalSize(0), StartPos(0) {}
|
||||
|
||||
HRESULT MyCopyFile(CFSTR inPath, CFSTR outPath);
|
||||
HRESULT MyCopyFile(CFSTR inPath, CFSTR outPath, DWORD attrib = INVALID_FILE_ATTRIBUTES);
|
||||
};
|
||||
|
||||
HRESULT SendLastErrorMessage(IFolderOperationsExtractCallback *callback, const FString &fileName);
|
||||
|
||||
@@ -31,7 +31,7 @@ extern bool g_IsNT;
|
||||
|
||||
namespace NFsFolder {
|
||||
|
||||
HRESULT CCopyStateIO::MyCopyFile(CFSTR inPath, CFSTR outPath)
|
||||
HRESULT CCopyStateIO::MyCopyFile(CFSTR inPath, CFSTR outPath, DWORD attrib)
|
||||
{
|
||||
ErrorFileIndex = -1;
|
||||
ErrorMessage.Empty();
|
||||
@@ -87,6 +87,9 @@ HRESULT CCopyStateIO::MyCopyFile(CFSTR inPath, CFSTR outPath)
|
||||
}
|
||||
}
|
||||
|
||||
if (attrib != INVALID_FILE_ATTRIBUTES)
|
||||
SetFileAttrib(outPath, attrib);
|
||||
|
||||
if (DeleteSrcFile)
|
||||
{
|
||||
if (!DeleteFileAlways(inPath))
|
||||
@@ -424,7 +427,9 @@ static HRESULT CopyFile_Ask(
|
||||
state2.DeleteSrcFile = state.MoveMode;
|
||||
state2.TotalSize = state.ProgressInfo.TotalSize;
|
||||
state2.StartPos = state.ProgressInfo.StartPos;
|
||||
RINOK(state2.MyCopyFile(srcPath, destPathNew));
|
||||
|
||||
RINOK(state2.MyCopyFile(srcPath, destPathNew, srcFileInfo.Attrib));
|
||||
|
||||
if (state2.ErrorFileIndex >= 0)
|
||||
{
|
||||
if (state2.ErrorMessage.IsEmpty())
|
||||
|
||||
@@ -314,7 +314,7 @@ void CApp::Link()
|
||||
CPanel &srcPanel = Panels[srcPanelIndex];
|
||||
if (!srcPanel.IsFSFolder())
|
||||
{
|
||||
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
srcPanel.MessageBox_Error_UnsupportOperation();
|
||||
return;
|
||||
}
|
||||
CRecordVector<UInt32> indices;
|
||||
@@ -323,7 +323,7 @@ void CApp::Link()
|
||||
return;
|
||||
if (indices.Size() != 1)
|
||||
{
|
||||
srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE);
|
||||
srcPanel.MessageBox_Error_LangID(IDS_SELECT_ONE_FILE);
|
||||
return;
|
||||
}
|
||||
int index = indices[0];
|
||||
|
||||
@@ -697,43 +697,57 @@ bool CPanel::OnCommand(int code, int itemID, LPARAM lParam, LRESULT &result)
|
||||
return CWindow2::OnCommand(code, itemID, lParam, result);
|
||||
}
|
||||
|
||||
void CPanel::MessageBoxInfo(LPCWSTR message, LPCWSTR caption)
|
||||
|
||||
|
||||
/*
|
||||
void CPanel::MessageBox_Info(LPCWSTR message, LPCWSTR caption) const
|
||||
{ ::MessageBoxW((HWND)*this, message, caption, MB_OK); }
|
||||
void CPanel::MessageBox(LPCWSTR message, LPCWSTR caption)
|
||||
void CPanel::MessageBox_Warning(LPCWSTR message) const
|
||||
{ ::MessageBoxW((HWND)*this, message, L"7-Zip", MB_OK | MB_ICONWARNING); }
|
||||
*/
|
||||
|
||||
void CPanel::MessageBox_Error_Caption(LPCWSTR message, LPCWSTR caption) const
|
||||
{ ::MessageBoxW((HWND)*this, message, caption, MB_OK | MB_ICONSTOP); }
|
||||
void CPanel::MessageBox(LPCWSTR message)
|
||||
{ MessageBox(message, L"7-Zip"); }
|
||||
void CPanel::MessageBoxWarning(LPCWSTR message)
|
||||
{ ::MessageBoxW(NULL, message, L"7-Zip", MB_OK | MB_ICONWARNING); }
|
||||
void CPanel::MessageBoxMyError(LPCWSTR message)
|
||||
{ MessageBox(message, L"7-Zip"); }
|
||||
|
||||
void CPanel::MessageBox_Error(LPCWSTR message) const
|
||||
{ MessageBox_Error_Caption(message, L"7-Zip"); }
|
||||
|
||||
void CPanel::MessageBoxError(HRESULT errorCode, LPCWSTR caption)
|
||||
static UString ErrorHResult_To_Message(HRESULT errorCode)
|
||||
{
|
||||
MessageBox(HResultToMessage(errorCode), caption);
|
||||
if (errorCode == 0)
|
||||
errorCode = E_FAIL;
|
||||
return HResultToMessage(errorCode);
|
||||
}
|
||||
|
||||
void CPanel::MessageBoxError2Lines(LPCWSTR message, HRESULT errorCode)
|
||||
void CPanel::MessageBox_Error_HRESULT_Caption(HRESULT errorCode, LPCWSTR caption) const
|
||||
{
|
||||
MessageBox_Error_Caption(ErrorHResult_To_Message(errorCode), caption);
|
||||
}
|
||||
|
||||
void CPanel::MessageBox_Error_HRESULT(HRESULT errorCode) const
|
||||
{ MessageBox_Error_HRESULT_Caption(errorCode, L"7-Zip"); }
|
||||
|
||||
void CPanel::MessageBox_Error_2Lines_Message_HRESULT(LPCWSTR message, HRESULT errorCode) const
|
||||
{
|
||||
UString m = message;
|
||||
if (errorCode != 0)
|
||||
{
|
||||
m.Add_LF();
|
||||
m += HResultToMessage(errorCode);
|
||||
}
|
||||
MessageBoxMyError(m);
|
||||
m.Add_LF();
|
||||
m += ErrorHResult_To_Message(errorCode);
|
||||
MessageBox_Error(m);
|
||||
}
|
||||
|
||||
void CPanel::MessageBoxError(HRESULT errorCode)
|
||||
{ MessageBoxError(errorCode, L"7-Zip"); }
|
||||
void CPanel::MessageBoxLastError(LPCWSTR caption)
|
||||
{ MessageBoxError(::GetLastError(), caption); }
|
||||
void CPanel::MessageBoxLastError()
|
||||
{ MessageBoxLastError(L"7-Zip"); }
|
||||
void CPanel::MessageBox_LastError(LPCWSTR caption) const
|
||||
{ MessageBox_Error_HRESULT_Caption(::GetLastError(), caption); }
|
||||
|
||||
void CPanel::MessageBox_LastError() const
|
||||
{ MessageBox_LastError(L"7-Zip"); }
|
||||
|
||||
void CPanel::MessageBox_Error_LangID(UINT resourceID) const
|
||||
{ MessageBox_Error(LangString(resourceID)); }
|
||||
|
||||
void CPanel::MessageBox_Error_UnsupportOperation() const
|
||||
{ MessageBox_Error_LangID(IDS_OPERATION_IS_NOT_SUPPORTED); }
|
||||
|
||||
|
||||
void CPanel::MessageBoxErrorLang(UINT resourceID)
|
||||
{ MessageBox(LangString(resourceID)); }
|
||||
|
||||
|
||||
void CPanel::SetFocusToList()
|
||||
@@ -821,7 +835,7 @@ void CPanel::ChangeFlatMode()
|
||||
_flatModeForArc = _flatMode;
|
||||
else
|
||||
_flatModeForDisk = _flatMode;
|
||||
RefreshListCtrlSaveFocused();
|
||||
RefreshListCtrl_SaveFocused();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -848,12 +862,12 @@ void CPanel::AddToArchive()
|
||||
GetOperatedItemIndices(indices);
|
||||
if (!Is_IO_FS_Folder())
|
||||
{
|
||||
MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
MessageBox_Error_UnsupportOperation();
|
||||
return;
|
||||
}
|
||||
if (indices.Size() == 0)
|
||||
{
|
||||
MessageBoxErrorLang(IDS_SELECT_FILES);
|
||||
MessageBox_Error_LangID(IDS_SELECT_FILES);
|
||||
return;
|
||||
}
|
||||
UStringVector names;
|
||||
@@ -873,7 +887,7 @@ void CPanel::AddToArchive()
|
||||
if (res != S_OK)
|
||||
{
|
||||
if (destCurDirPrefix.Len() >= MAX_PATH)
|
||||
MessageBoxErrorLang(IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER);
|
||||
MessageBox_Error_LangID(IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER);
|
||||
}
|
||||
// KillSelection();
|
||||
}
|
||||
@@ -910,7 +924,7 @@ void CPanel::GetFilePaths(const CRecordVector<UInt32> &indices, UStringVector &p
|
||||
}
|
||||
if (paths.Size() == 0)
|
||||
{
|
||||
MessageBoxErrorLang(IDS_SELECT_FILES);
|
||||
MessageBox_Error_LangID(IDS_SELECT_FILES);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1026,7 +1040,7 @@ void CPanel::TestArchives()
|
||||
if (res != S_OK)
|
||||
{
|
||||
if (res != E_ABORT)
|
||||
MessageBoxError(res);
|
||||
MessageBox_Error_HRESULT(res);
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -1071,7 +1085,7 @@ void CPanel::TestArchives()
|
||||
|
||||
if (!IsFSFolder())
|
||||
{
|
||||
MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
MessageBox_Error_UnsupportOperation();
|
||||
return;
|
||||
}
|
||||
UStringVector paths;
|
||||
|
||||
@@ -220,11 +220,12 @@ public:
|
||||
struct CSelectedState
|
||||
{
|
||||
int FocusedItem;
|
||||
UString FocusedName;
|
||||
bool SelectFocused;
|
||||
bool FocusedName_Defined;
|
||||
UString FocusedName;
|
||||
UStringVector SelectedNames;
|
||||
|
||||
CSelectedState(): FocusedItem(-1), SelectFocused(false) {}
|
||||
CSelectedState(): FocusedItem(-1), FocusedName_Defined(false), SelectFocused(true) {}
|
||||
};
|
||||
|
||||
#ifdef UNDER_CE
|
||||
@@ -326,9 +327,7 @@ private:
|
||||
void AddColumn(const CPropColumn &prop);
|
||||
|
||||
void SetFocusedSelectedItem(int index, bool select);
|
||||
HRESULT RefreshListCtrl(const UString &focusedName, int focusedPos, bool selectFocused,
|
||||
const UStringVector &selectedNames);
|
||||
|
||||
|
||||
void OnShiftSelectMessage();
|
||||
void OnArrowWithShift();
|
||||
|
||||
@@ -463,7 +462,7 @@ public:
|
||||
void GetSelectedNames(UStringVector &selectedNames);
|
||||
void SaveSelectedState(CSelectedState &s);
|
||||
HRESULT RefreshListCtrl(const CSelectedState &s);
|
||||
HRESULT RefreshListCtrlSaveFocused();
|
||||
HRESULT RefreshListCtrl_SaveFocused();
|
||||
|
||||
bool GetItem_BoolProp(UInt32 itemIndex, PROPID propID) const;
|
||||
bool IsItem_Deleted(int itemIndex) const;
|
||||
@@ -745,20 +744,20 @@ public:
|
||||
|
||||
HRESULT RefreshListCtrl();
|
||||
|
||||
void MessageBoxInfo(LPCWSTR message, LPCWSTR caption);
|
||||
void MessageBox(LPCWSTR message);
|
||||
void MessageBoxWarning(LPCWSTR message);
|
||||
void MessageBox(LPCWSTR message, LPCWSTR caption);
|
||||
void MessageBoxMyError(LPCWSTR message);
|
||||
void MessageBoxError(HRESULT errorCode, LPCWSTR caption);
|
||||
void MessageBoxError(HRESULT errorCode);
|
||||
void MessageBoxError2Lines(LPCWSTR message, HRESULT errorCode);
|
||||
void MessageBoxLastError(LPCWSTR caption);
|
||||
void MessageBoxLastError();
|
||||
|
||||
|
||||
// void MessageBox_Info(LPCWSTR message, LPCWSTR caption) const;
|
||||
// void MessageBox_Warning(LPCWSTR message) const;
|
||||
void MessageBox_Error_Caption(LPCWSTR message, LPCWSTR caption) const;
|
||||
void MessageBox_Error(LPCWSTR message) const;
|
||||
void MessageBox_Error_HRESULT_Caption(HRESULT errorCode, LPCWSTR caption) const;
|
||||
void MessageBox_Error_HRESULT(HRESULT errorCode) const;
|
||||
void MessageBox_Error_2Lines_Message_HRESULT(LPCWSTR message, HRESULT errorCode) const;
|
||||
void MessageBox_LastError(LPCWSTR caption) const;
|
||||
void MessageBox_LastError() const;
|
||||
void MessageBox_Error_LangID(UINT resourceID) const;
|
||||
void MessageBox_Error_UnsupportOperation() const;
|
||||
// void MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID);
|
||||
|
||||
void MessageBoxErrorLang(UINT resourceID);
|
||||
|
||||
void OpenAltStreams();
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind
|
||||
{
|
||||
UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
if (options.showErrorMessages)
|
||||
MessageBox(errorMessage);
|
||||
MessageBox_Error(errorMessage);
|
||||
else if (messages != 0)
|
||||
messages->Add(errorMessage);
|
||||
return E_FAIL;
|
||||
@@ -307,7 +307,7 @@ HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStri
|
||||
{
|
||||
UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
if (showErrorMessages)
|
||||
MessageBox(errorMessage);
|
||||
MessageBox_Error(errorMessage);
|
||||
else if (messages != 0)
|
||||
messages->Add(errorMessage);
|
||||
return E_ABORT;
|
||||
@@ -334,7 +334,7 @@ void CPanel::CopyFromNoAsk(const UStringVector &filePaths)
|
||||
// For Password:
|
||||
SetFocusToList();
|
||||
if (result != E_ABORT)
|
||||
MessageBoxError(result);
|
||||
MessageBox_Error_HRESULT(result);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -382,6 +382,6 @@ void CApp::CalculateCrc(const char *methodName)
|
||||
{
|
||||
unsigned srcPanelIndex = GetFocusedPanelIndex();
|
||||
CPanel &srcPanel = Panels[srcPanelIndex];
|
||||
srcPanel.MessageBoxError(res);
|
||||
srcPanel.MessageBox_Error_HRESULT(res);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,6 +327,7 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */)
|
||||
// CSelectedState selState;
|
||||
// SaveSelectedState(selState);
|
||||
|
||||
// FString dirPrefix2;
|
||||
FString dirPrefix;
|
||||
CTempDir tempDirectory;
|
||||
|
||||
@@ -337,6 +338,7 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */)
|
||||
{
|
||||
tempDirectory.Create(kTempDirPrefix);
|
||||
dirPrefix = tempDirectory.GetPath();
|
||||
// dirPrefix2 = dirPrefix;
|
||||
NFile::NName::NormalizeDirPathPrefix(dirPrefix);
|
||||
}
|
||||
|
||||
@@ -345,6 +347,10 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */)
|
||||
|
||||
{
|
||||
UStringVector names;
|
||||
|
||||
// names variable is USED for drag and drop from 7-zip to Explorer or to 7-zip archive folder.
|
||||
// names variable is NOT USED for drag and drop from 7-zip to 7-zip File System folder.
|
||||
|
||||
FOR_VECTOR (i, indices)
|
||||
{
|
||||
UInt32 index = indices[i];
|
||||
@@ -354,6 +360,23 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */)
|
||||
else
|
||||
{
|
||||
s = GetItemName(index);
|
||||
/*
|
||||
// We use (keepAndReplaceEmptyPrefixes = true) in CAgentFolder::Extract
|
||||
// So the following code is not required.
|
||||
// Maybe we also can change IFolder interface and send some flag also.
|
||||
|
||||
if (s.IsEmpty())
|
||||
{
|
||||
// Correct_FsFile_Name("") returns "_".
|
||||
// If extracting code removes empty folder prefixes from path (as it was in old version),
|
||||
// Explorer can't find "_" folder in temp folder.
|
||||
// We can ask Explorer to copy parent temp folder "7zE" instead.
|
||||
|
||||
names.Clear();
|
||||
names.Add(dirPrefix2);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
s = Get_Correct_FsFile_Name(s);
|
||||
}
|
||||
names.Add(fs2us(dirPrefix) + s);
|
||||
@@ -408,7 +431,7 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */)
|
||||
// we ignore E_UNEXPECTED that is returned if we drag file to printer
|
||||
if (res != DRAGDROP_S_CANCEL && res != S_OK
|
||||
&& res != E_UNEXPECTED)
|
||||
MessageBoxError(res);
|
||||
MessageBox_Error_HRESULT(res);
|
||||
|
||||
res = dropSourceSpec->Result;
|
||||
}
|
||||
@@ -422,10 +445,10 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */)
|
||||
|
||||
if (res != S_OK && res != E_ABORT)
|
||||
{
|
||||
// we restore Notify before MessageBoxError. So we will se files selection
|
||||
// we restore Notify before MessageBox_Error_HRESULT. So we will se files selection
|
||||
disableNotify.Restore();
|
||||
// SetFocusToList();
|
||||
MessageBoxError(res);
|
||||
MessageBox_Error_HRESULT(res);
|
||||
}
|
||||
if (res == S_OK && dropSourceSpec->Messages.IsEmpty() && !canceled)
|
||||
KillSelection();
|
||||
|
||||
@@ -298,7 +298,7 @@ HRESULT CPanel::BindToPathAndRefresh(const UString &path)
|
||||
#endif
|
||||
|
||||
HRESULT res = BindToPath(s, UString(), archiveIsOpened, encrypted);
|
||||
RefreshListCtrl(UString(), -1, true, UStringVector());
|
||||
RefreshListCtrl();
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -740,17 +740,20 @@ void CPanel::OpenParentFolder()
|
||||
}
|
||||
}
|
||||
|
||||
UStringVector selectedItems;
|
||||
CSelectedState state;
|
||||
state.FocusedName = focusedName;
|
||||
state.FocusedName_Defined = true;
|
||||
/*
|
||||
if (!focusedName.IsEmpty())
|
||||
selectedItems.Add(focusedName);
|
||||
state.SelectedNames.Add(focusedName);
|
||||
*/
|
||||
LoadFullPath();
|
||||
// ::SetCurrentDirectory(::_currentFolderPrefix);
|
||||
RefreshListCtrl(focusedName, -1, true, selectedItems);
|
||||
RefreshListCtrl(state);
|
||||
// _listView.EnsureVisible(_listView.GetFocusedItem(), false);
|
||||
}
|
||||
|
||||
|
||||
void CPanel::CloseOneLevel()
|
||||
{
|
||||
ReleaseFolder();
|
||||
@@ -783,7 +786,7 @@ void CPanel::OpenRootFolder()
|
||||
CDisableNotify disableNotify(*this);
|
||||
_parentFolders.Clear();
|
||||
SetToRootFolder();
|
||||
RefreshListCtrl(UString(), -1, true, UStringVector());
|
||||
RefreshListCtrl();
|
||||
// ::SetCurrentDirectory(::_currentFolderPrefix);
|
||||
/*
|
||||
BeforeChangeFolder();
|
||||
@@ -847,7 +850,7 @@ void CPanel::OpenAltStreams()
|
||||
CDisableTimerProcessing disableTimerProcessing(*this);
|
||||
CDisableNotify disableNotify(*this);
|
||||
SetNewFolder(newFolder);
|
||||
RefreshListCtrl(UString(), -1, true, UStringVector());
|
||||
RefreshListCtrl();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -559,11 +559,11 @@ HRESULT CPanel::OpenAsArc(IInStream *inStream,
|
||||
*/
|
||||
/*
|
||||
if (!s.IsEmpty())
|
||||
MessageBoxWarning(s);
|
||||
MessageBox_Warning(s);
|
||||
else
|
||||
*/
|
||||
// after MessageBoxWarning it throws exception in nested archives in Debug Mode. why ?.
|
||||
// MessageBoxWarning(L"test error");
|
||||
// after MessageBox_Warning it throws exception in nested archives in Debug Mode. why ?.
|
||||
// MessageBox_Warning(L"test error");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -585,9 +585,10 @@ HRESULT CPanel::OpenAsArc_Msg(IInStream *inStream,
|
||||
if (res == E_ABORT)
|
||||
return res;
|
||||
|
||||
if (showErrorMessage && encrypted)
|
||||
if (showErrorMessage)
|
||||
if (encrypted || res != S_FALSE) // 17.01 : we show message also for (res != S_FALSE)
|
||||
{
|
||||
UString message("Error");
|
||||
UString message;
|
||||
if (res == S_FALSE)
|
||||
{
|
||||
message = MyFormatNew(
|
||||
@@ -598,7 +599,7 @@ HRESULT CPanel::OpenAsArc_Msg(IInStream *inStream,
|
||||
}
|
||||
else
|
||||
message = HResultToMessage(res);
|
||||
MessageBoxMyError(message);
|
||||
MessageBox_Error(message);
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -799,6 +800,12 @@ void CApp::DiffFiles()
|
||||
{
|
||||
const CPanel &panel = GetFocusedPanel();
|
||||
|
||||
if (!panel.Is_IO_FS_Folder())
|
||||
{
|
||||
panel.MessageBox_Error_UnsupportOperation();
|
||||
return;
|
||||
}
|
||||
|
||||
CRecordVector<UInt32> indices;
|
||||
panel.GetSelectedItemsIndices(indices);
|
||||
|
||||
@@ -811,6 +818,13 @@ void CApp::DiffFiles()
|
||||
else if (indices.Size() == 1 && NumPanels >= 2)
|
||||
{
|
||||
const CPanel &destPanel = Panels[1 - LastFocusedPanel];
|
||||
|
||||
if (!destPanel.Is_IO_FS_Folder())
|
||||
{
|
||||
panel.MessageBox_Error_UnsupportOperation();
|
||||
return;
|
||||
}
|
||||
|
||||
path1 = panel.GetItemFullPath(indices[0]);
|
||||
CRecordVector<UInt32> indices2;
|
||||
destPanel.GetSelectedItemsIndices(indices2);
|
||||
@@ -1061,7 +1075,7 @@ bool CPanel::IsVirus_Message(const UString &name)
|
||||
s.Add_LF(); s += name2;
|
||||
s.Add_LF(); s += name3;
|
||||
|
||||
MessageBoxMyError(s);
|
||||
MessageBox_Error(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1095,7 +1109,7 @@ void CPanel::OpenItem(int index, bool tryInternal, bool tryExternal, const wchar
|
||||
return;
|
||||
if (res != S_FALSE)
|
||||
{
|
||||
MessageBoxError(res);
|
||||
MessageBox_Error_HRESULT(res);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1130,7 +1144,7 @@ HRESULT CPanel::OnOpenItemChanged(UInt32 index, const wchar_t *fullFilePath,
|
||||
{
|
||||
if (!_folderOperations)
|
||||
{
|
||||
MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
MessageBox_Error_UnsupportOperation();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
@@ -1589,7 +1603,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo
|
||||
|
||||
if (!_folderOperations)
|
||||
{
|
||||
MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
MessageBox_Error_UnsupportOperation();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1600,7 +1614,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo
|
||||
CTempDir tempDirectory;
|
||||
if (!tempDirectory.Create(kTempDirPrefix))
|
||||
{
|
||||
MessageBoxLastError();
|
||||
MessageBox_LastError();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1729,7 +1743,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo
|
||||
if (result != S_OK)
|
||||
{
|
||||
if (result != E_ABORT)
|
||||
MessageBoxError(result);
|
||||
MessageBox_Error_HRESULT(result);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include "../../PropID.h"
|
||||
|
||||
#include "../Common/ExtractingFilePath.h"
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
#include "LangUtils.h"
|
||||
@@ -317,7 +319,8 @@ void CPanel::AddColumn(const CPropColumn &prop)
|
||||
|
||||
HRESULT CPanel::RefreshListCtrl()
|
||||
{
|
||||
return RefreshListCtrl(UString(), -1, true, UStringVector());
|
||||
CSelectedState state;
|
||||
return RefreshListCtrl(state);
|
||||
}
|
||||
|
||||
int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData);
|
||||
@@ -356,7 +359,9 @@ void CPanel::GetSelectedNames(UStringVector &selectedNames)
|
||||
|
||||
void CPanel::SaveSelectedState(CSelectedState &s)
|
||||
{
|
||||
s.FocusedName_Defined = false;
|
||||
s.FocusedName.Empty();
|
||||
s.SelectFocused = true; // false;
|
||||
s.SelectedNames.Clear();
|
||||
s.FocusedItem = _listView.GetFocusedItem();
|
||||
{
|
||||
@@ -364,7 +369,12 @@ void CPanel::SaveSelectedState(CSelectedState &s)
|
||||
{
|
||||
int realIndex = GetRealItemIndex(s.FocusedItem);
|
||||
if (realIndex != kParentIndex)
|
||||
{
|
||||
s.FocusedName = GetItemRelPath(realIndex);
|
||||
s.FocusedName_Defined = true;
|
||||
|
||||
s.SelectFocused = _listView.IsItemSelected(s.FocusedItem);
|
||||
|
||||
/*
|
||||
const int kSize = 1024;
|
||||
WCHAR name[kSize + 1];
|
||||
@@ -376,21 +386,26 @@ void CPanel::SaveSelectedState(CSelectedState &s)
|
||||
item.mask = LVIF_TEXT;
|
||||
if (_listView.GetItem(&item))
|
||||
focusedName = item.pszText;
|
||||
*/
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
GetSelectedNames(s.SelectedNames);
|
||||
}
|
||||
|
||||
/*
|
||||
HRESULT CPanel::RefreshListCtrl(const CSelectedState &s)
|
||||
{
|
||||
bool selectFocused = s.SelectFocused;
|
||||
if (_mySelectMode)
|
||||
selectFocused = true;
|
||||
return RefreshListCtrl(s.FocusedName, s.FocusedItem, selectFocused, s.SelectedNames);
|
||||
return RefreshListCtrl2(
|
||||
s.FocusedItem >= 0, // allowEmptyFocusedName
|
||||
s.FocusedName, s.FocusedItem, selectFocused, s.SelectedNames);
|
||||
}
|
||||
*/
|
||||
|
||||
HRESULT CPanel::RefreshListCtrlSaveFocused()
|
||||
HRESULT CPanel::RefreshListCtrl_SaveFocused()
|
||||
{
|
||||
CSelectedState state;
|
||||
SaveSelectedState(state);
|
||||
@@ -420,8 +435,7 @@ void CPanel::SetFocusedSelectedItem(int index, bool select)
|
||||
#endif
|
||||
|
||||
|
||||
HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool selectFocused,
|
||||
const UStringVector &selectedNames)
|
||||
HRESULT CPanel::RefreshListCtrl(const CSelectedState &state)
|
||||
{
|
||||
if (!_folder)
|
||||
return S_OK;
|
||||
@@ -433,6 +447,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
|
||||
CDisableTimerProcessing timerProcessing(*this);
|
||||
CDisableNotify disableNotify(*this);
|
||||
|
||||
int focusedPos = state.FocusedItem;
|
||||
if (focusedPos < 0)
|
||||
focusedPos = 0;
|
||||
|
||||
@@ -534,8 +549,8 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
|
||||
{
|
||||
UString itemName ("..");
|
||||
item.iItem = listViewItemCount;
|
||||
if (itemName == focusedName)
|
||||
cursorIndex = item.iItem;
|
||||
if (itemName == state.FocusedName)
|
||||
cursorIndex = listViewItemCount;
|
||||
item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
|
||||
int subItem = 0;
|
||||
item.iSubItem = subItem++;
|
||||
@@ -573,7 +588,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
|
||||
|
||||
bool selected = false;
|
||||
|
||||
if (!focusedName.IsEmpty() || !selectedNames.IsEmpty())
|
||||
if (state.FocusedName_Defined || !state.SelectedNames.IsEmpty())
|
||||
{
|
||||
relPath.Empty();
|
||||
|
||||
@@ -599,9 +614,9 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
|
||||
}
|
||||
}
|
||||
relPath += name;
|
||||
if (relPath == focusedName)
|
||||
if (relPath == state.FocusedName)
|
||||
cursorIndex = listViewItemCount;
|
||||
if (selectedNames.FindInSorted(relPath) >= 0)
|
||||
if (state.SelectedNames.FindInSorted(relPath) >= 0)
|
||||
selected = true;
|
||||
}
|
||||
|
||||
@@ -724,7 +739,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
|
||||
disableNotify.Restore();
|
||||
|
||||
if (_listView.GetItemCount() > 0 && cursorIndex >= 0)
|
||||
SetFocusedSelectedItem(cursorIndex, selectFocused);
|
||||
SetFocusedSelectedItem(cursorIndex, state.SelectFocused);
|
||||
|
||||
Print_OnNotify("after SetFocusedSelectedItem");
|
||||
|
||||
@@ -738,7 +753,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
|
||||
if (focusedPos >= _listView.GetItemCount())
|
||||
focusedPos = _listView.GetItemCount() - 1;
|
||||
// we select item only in showDots mode.
|
||||
SetFocusedSelectedItem(focusedPos, showDots);
|
||||
SetFocusedSelectedItem(focusedPos, showDots && (focusedPos == 0));
|
||||
}
|
||||
|
||||
// m_RedrawEnabled = true;
|
||||
@@ -789,6 +804,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
void CPanel::GetSelectedItemsIndices(CRecordVector<UInt32> &indices) const
|
||||
{
|
||||
indices.Clear();
|
||||
@@ -800,13 +816,16 @@ void CPanel::GetSelectedItemsIndices(CRecordVector<UInt32> &indices) const
|
||||
if (_listView.GetItemParam(itemIndex, param))
|
||||
indices.Add(param);
|
||||
}
|
||||
HeapSort(&indices.Front(), indices.Size());
|
||||
*/
|
||||
FOR_VECTOR (i, _selectedStatusVector)
|
||||
if (_selectedStatusVector[i])
|
||||
const bool *v = &_selectedStatusVector.Front();
|
||||
unsigned size = _selectedStatusVector.Size();
|
||||
for (unsigned i = 0; i < size; i++)
|
||||
if (v[i])
|
||||
indices.Add(i);
|
||||
// HeapSort(&indices.Front(), indices.Size());
|
||||
}
|
||||
|
||||
|
||||
void CPanel::GetOperatedItemIndices(CRecordVector<UInt32> &indices) const
|
||||
{
|
||||
GetSelectedItemsIndices(indices);
|
||||
@@ -922,7 +941,7 @@ void CPanel::OpenSelectedItems(bool tryInternal)
|
||||
GetOperatedItemIndices(indices);
|
||||
if (indices.Size() > 20)
|
||||
{
|
||||
MessageBoxErrorLang(IDS_TOO_MANY_ITEMS);
|
||||
MessageBox_Error_LangID(IDS_TOO_MANY_ITEMS);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -974,17 +993,20 @@ UString CPanel::GetItemName_for_Copy(int itemIndex) const
|
||||
{
|
||||
if (itemIndex == kParentIndex)
|
||||
return L"..";
|
||||
UString s;
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
if (_folder->GetProperty(itemIndex, kpidOutName, &prop) == S_OK)
|
||||
{
|
||||
if (prop.vt == VT_BSTR)
|
||||
return prop.bstrVal;
|
||||
if (prop.vt != VT_EMPTY)
|
||||
s = prop.bstrVal;
|
||||
else if (prop.vt != VT_EMPTY)
|
||||
throw 2723401;
|
||||
}
|
||||
if (s.IsEmpty())
|
||||
s = GetItemName(itemIndex);
|
||||
}
|
||||
return GetItemName(itemIndex);
|
||||
return Get_Correct_FsFile_Name(s);
|
||||
}
|
||||
|
||||
void CPanel::GetItemName(int itemIndex, UString &s) const
|
||||
@@ -1224,9 +1246,9 @@ void CPanel::ShowColumnsContextMenu(int x, int y)
|
||||
|
||||
void CPanel::OnReload()
|
||||
{
|
||||
HRESULT res = RefreshListCtrlSaveFocused();
|
||||
HRESULT res = RefreshListCtrl_SaveFocused();
|
||||
if (res != S_OK)
|
||||
MessageBoxError(res);
|
||||
MessageBox_Error_HRESULT(res);
|
||||
}
|
||||
|
||||
void CPanel::OnTimer()
|
||||
|
||||
@@ -661,7 +661,7 @@ bool CPanel::CheckBeforeUpdate(UINT resourceID)
|
||||
{
|
||||
if (!_folderOperations)
|
||||
{
|
||||
MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
MessageBox_Error_UnsupportOperation();
|
||||
// resourceID = resourceID;
|
||||
// MessageBoxErrorForUpdate(E_NOINTERFACE, resourceID);
|
||||
return false;
|
||||
@@ -689,7 +689,7 @@ bool CPanel::CheckBeforeUpdate(UINT resourceID)
|
||||
s += _parentFolders[i - 1].VirtualPath;
|
||||
s.Add_LF();
|
||||
AddLangString(s, IDS_PROP_READ_ONLY);
|
||||
MessageBoxMyError(s);
|
||||
MessageBox_Error(s);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -111,9 +111,9 @@ typedef int (WINAPI * SHFileOperationWP)(LPSHFILEOPSTRUCTW lpFileOp);
|
||||
void CPanel::MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID)
|
||||
{
|
||||
if (errorCode == E_NOINTERFACE)
|
||||
MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
MessageBox_Error_UnsupportOperation();
|
||||
else
|
||||
MessageBoxError(errorCode, LangString(resourceID));
|
||||
MessageBox_Error_HRESULT_Caption(errorCode, LangString(resourceID));
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -178,7 +178,7 @@ void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin))
|
||||
{
|
||||
if (toRecycleBin)
|
||||
{
|
||||
MessageBoxErrorLang(IDS_ERROR_LONG_PATH_TO_RECYCLE);
|
||||
MessageBox_Error_LangID(IDS_ERROR_LONG_PATH_TO_RECYCLE);
|
||||
return;
|
||||
}
|
||||
useInternalDelete = true;
|
||||
@@ -210,7 +210,7 @@ void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin))
|
||||
}
|
||||
/*
|
||||
if (fo.fAnyOperationsAborted)
|
||||
MessageBoxError(result, LangString(IDS_ERROR_DELETING, 0x03020217));
|
||||
MessageBox_Error_HRESULT_Caption(result, LangString(IDS_ERROR_DELETING));
|
||||
*/
|
||||
if (!useInternalDelete)
|
||||
{
|
||||
@@ -301,7 +301,7 @@ BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh)
|
||||
UString newName = lpnmh->item.pszText;
|
||||
if (!IsCorrectFsName(newName))
|
||||
{
|
||||
MessageBoxError(E_INVALIDARG);
|
||||
MessageBox_Error_HRESULT(E_INVALIDARG);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -310,7 +310,7 @@ BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh)
|
||||
UString correctName;
|
||||
if (!CorrectFsPath(newName, correctName))
|
||||
{
|
||||
MessageBoxError(E_INVALIDARG);
|
||||
MessageBox_Error_HRESULT(E_INVALIDARG);
|
||||
return FALSE;
|
||||
}
|
||||
newName = correctName;
|
||||
@@ -344,6 +344,7 @@ BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh)
|
||||
// Can't use RefreshListCtrl here.
|
||||
// RefreshListCtrlSaveFocused();
|
||||
_selectedState.FocusedName = prefix + newName;
|
||||
_selectedState.FocusedName_Defined = true;
|
||||
_selectedState.SelectFocused = true;
|
||||
|
||||
// We need clear all items to disable GetText before Reload:
|
||||
@@ -375,7 +376,7 @@ void CPanel::CreateFolder()
|
||||
|
||||
if (!IsCorrectFsName(newName))
|
||||
{
|
||||
MessageBoxError(E_INVALIDARG);
|
||||
MessageBox_Error_HRESULT(E_INVALIDARG);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -384,7 +385,7 @@ void CPanel::CreateFolder()
|
||||
UString correctName;
|
||||
if (!CorrectFsPath(newName, correctName))
|
||||
{
|
||||
MessageBoxError(E_INVALIDARG);
|
||||
MessageBox_Error_HRESULT(E_INVALIDARG);
|
||||
return;
|
||||
}
|
||||
newName = correctName;
|
||||
@@ -413,6 +414,7 @@ void CPanel::CreateFolder()
|
||||
if (!_mySelectMode)
|
||||
state.SelectedNames.Clear();
|
||||
state.FocusedName = newName;
|
||||
state.FocusedName_Defined = true;
|
||||
state.SelectFocused = true;
|
||||
}
|
||||
RefreshTitleAlways();
|
||||
@@ -444,7 +446,7 @@ void CPanel::CreateFile()
|
||||
UString correctName;
|
||||
if (!CorrectFsPath(newName, correctName))
|
||||
{
|
||||
MessageBoxError(E_INVALIDARG);
|
||||
MessageBox_Error_HRESULT(E_INVALIDARG);
|
||||
return;
|
||||
}
|
||||
newName = correctName;
|
||||
@@ -453,7 +455,7 @@ void CPanel::CreateFile()
|
||||
HRESULT result = _folderOperations->CreateFile(newName, 0);
|
||||
if (result != S_OK)
|
||||
{
|
||||
MessageBoxError(result, LangString(IDS_CREATE_FILE_ERROR));
|
||||
MessageBox_Error_HRESULT_Caption(result, LangString(IDS_CREATE_FILE_ERROR));
|
||||
// MessageBoxErrorForUpdate(result, IDS_CREATE_FILE_ERROR);
|
||||
return;
|
||||
}
|
||||
@@ -463,6 +465,7 @@ void CPanel::CreateFile()
|
||||
if (!_mySelectMode)
|
||||
state.SelectedNames.Clear();
|
||||
state.FocusedName = newName;
|
||||
state.FocusedName_Defined = true;
|
||||
state.SelectFocused = true;
|
||||
RefreshListCtrl(state);
|
||||
}
|
||||
@@ -515,9 +518,9 @@ void CPanel::ChangeComment()
|
||||
if (result != S_OK)
|
||||
{
|
||||
if (result == E_NOINTERFACE)
|
||||
MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
MessageBox_Error_UnsupportOperation();
|
||||
else
|
||||
MessageBoxError(result, L"Set Comment Error");
|
||||
MessageBox_Error_HRESULT_Caption(result, L"Set Comment Error");
|
||||
}
|
||||
RefreshListCtrl(state);
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ void CApp::Split()
|
||||
CPanel &srcPanel = Panels[srcPanelIndex];
|
||||
if (!srcPanel.Is_IO_FS_Folder())
|
||||
{
|
||||
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
srcPanel.MessageBox_Error_UnsupportOperation();
|
||||
return;
|
||||
}
|
||||
CRecordVector<UInt32> indices;
|
||||
@@ -176,13 +176,13 @@ void CApp::Split()
|
||||
return;
|
||||
if (indices.Size() != 1)
|
||||
{
|
||||
srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE);
|
||||
srcPanel.MessageBox_Error_LangID(IDS_SELECT_ONE_FILE);
|
||||
return;
|
||||
}
|
||||
int index = indices[0];
|
||||
if (srcPanel.IsItem_Folder(index))
|
||||
{
|
||||
srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE);
|
||||
srcPanel.MessageBox_Error_LangID(IDS_SELECT_ONE_FILE);
|
||||
return;
|
||||
}
|
||||
const UString itemName = srcPanel.GetItemName(index);
|
||||
@@ -203,12 +203,12 @@ void CApp::Split()
|
||||
NFind::CFileInfo fileInfo;
|
||||
if (!fileInfo.Find(us2fs(srcPath + itemName)))
|
||||
{
|
||||
srcPanel.MessageBoxMyError(L"Can not find file");
|
||||
srcPanel.MessageBox_Error(L"Can not find file");
|
||||
return;
|
||||
}
|
||||
if (fileInfo.Size <= splitDialog.VolumeSizes.Front())
|
||||
{
|
||||
srcPanel.MessageBoxErrorLang(IDS_SPLIT_VOL_MUST_BE_SMALLER);
|
||||
srcPanel.MessageBox_Error_LangID(IDS_SPLIT_VOL_MUST_BE_SMALLER);
|
||||
return;
|
||||
}
|
||||
const UInt64 numVolumes = GetNumberOfVolumes(fileInfo.Size, splitDialog.VolumeSizes);
|
||||
@@ -226,7 +226,8 @@ void CApp::Split()
|
||||
NName::NormalizeDirPathPrefix(path);
|
||||
if (!CreateComplexDir(us2fs(path)))
|
||||
{
|
||||
srcPanel.MessageBoxError2Lines(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, path), ::GetLastError());
|
||||
DWORD lastError = ::GetLastError();
|
||||
srcPanel.MessageBox_Error_2Lines_Message_HRESULT(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, path), lastError);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -350,7 +351,7 @@ void CApp::Combine()
|
||||
CPanel &srcPanel = Panels[srcPanelIndex];
|
||||
if (!srcPanel.IsFSFolder())
|
||||
{
|
||||
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
srcPanel.MessageBox_Error_LangID(IDS_OPERATION_IS_NOT_SUPPORTED);
|
||||
return;
|
||||
}
|
||||
CRecordVector<UInt32> indices;
|
||||
@@ -360,7 +361,7 @@ void CApp::Combine()
|
||||
int index = indices[0];
|
||||
if (indices.Size() != 1 || srcPanel.IsItem_Folder(index))
|
||||
{
|
||||
srcPanel.MessageBoxErrorLang(IDS_COMBINE_SELECT_ONE_FILE);
|
||||
srcPanel.MessageBox_Error_LangID(IDS_COMBINE_SELECT_ONE_FILE);
|
||||
return;
|
||||
}
|
||||
const UString itemName = srcPanel.GetItemName(index);
|
||||
@@ -376,7 +377,7 @@ void CApp::Combine()
|
||||
CVolSeqName volSeqName;
|
||||
if (!volSeqName.ParseName(itemName))
|
||||
{
|
||||
srcPanel.MessageBoxErrorLang(IDS_COMBINE_CANT_DETECT_SPLIT_FILE);
|
||||
srcPanel.MessageBox_Error_LangID(IDS_COMBINE_CANT_DETECT_SPLIT_FILE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -396,13 +397,13 @@ void CApp::Combine()
|
||||
}
|
||||
if (combiner.Names.Size() == 1)
|
||||
{
|
||||
srcPanel.MessageBoxErrorLang(IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART);
|
||||
srcPanel.MessageBox_Error_LangID(IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART);
|
||||
return;
|
||||
}
|
||||
|
||||
if (combiner.TotalSize == 0)
|
||||
{
|
||||
srcPanel.MessageBoxMyError(L"No data");
|
||||
srcPanel.MessageBox_Error(L"No data");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -438,7 +439,8 @@ void CApp::Combine()
|
||||
NName::NormalizeDirPathPrefix(path);
|
||||
if (!CreateComplexDir(us2fs(path)))
|
||||
{
|
||||
srcPanel.MessageBoxError2Lines(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, path), ::GetLastError());
|
||||
DWORD lastError = ::GetLastError();
|
||||
srcPanel.MessageBox_Error_2Lines_Message_HRESULT(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, path), lastError);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -457,7 +459,7 @@ void CApp::Combine()
|
||||
combiner.OutputPath = us2fs(destFilePath);
|
||||
if (fileInfo.Find(combiner.OutputPath))
|
||||
{
|
||||
srcPanel.MessageBoxMyError(MyFormatNew(IDS_FILE_EXIST, destFilePath));
|
||||
srcPanel.MessageBox_Error(MyFormatNew(IDS_FILE_EXIST, destFilePath));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,9 @@ using namespace NDir;
|
||||
|
||||
static const unsigned kHistorySize = 20;
|
||||
|
||||
static const UInt32 kNoSolidBlockSize = 0;
|
||||
static const UInt32 kSolidBlockSize = 64;
|
||||
|
||||
static LPCSTR const kExeExt = ".exe";
|
||||
|
||||
#define k7zFormat "7z"
|
||||
@@ -221,7 +224,7 @@ static const CFormatInfo g_Formats[] =
|
||||
"xz",
|
||||
(1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
|
||||
METHODS_PAIR(g_XzMethods),
|
||||
false, false, true, false, false, false
|
||||
false, true, true, false, false, false
|
||||
},
|
||||
{
|
||||
"Swfc",
|
||||
@@ -737,10 +740,17 @@ void CCompressDialog::OnOK()
|
||||
Info.OrderMode = GetOrderMode();
|
||||
Info.NumThreads = GetNumThreadsSpec();
|
||||
|
||||
UInt32 solidLogSize = GetBlockSizeSpec();
|
||||
Info.SolidBlockSize = 0;
|
||||
if (solidLogSize > 0 && solidLogSize != (UInt32)(Int32)-1)
|
||||
Info.SolidBlockSize = (solidLogSize >= 64) ? (UInt64)(Int64)-1 : ((UInt64)1 << solidLogSize);
|
||||
{
|
||||
// Info.SolidIsSpecified = g_Formats[GetStaticFormatIndex()].Solid;
|
||||
UInt32 solidLogSize = GetBlockSizeSpec();
|
||||
Info.SolidBlockSize = 0;
|
||||
if (solidLogSize == (UInt32)(Int32)-1)
|
||||
Info.SolidIsSpecified = false;
|
||||
else if (solidLogSize > 0)
|
||||
Info.SolidBlockSize = (solidLogSize >= 64) ?
|
||||
(UInt64)(Int64)-1 :
|
||||
((UInt64)1 << solidLogSize);
|
||||
}
|
||||
|
||||
Info.Method = GetMethodSpec();
|
||||
Info.EncryptionMethod = GetEncryptionMethodSpec();
|
||||
@@ -846,6 +856,7 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam)
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
case IDC_COMPRESS_FORMAT:
|
||||
{
|
||||
bool isSFX = IsSFX();
|
||||
@@ -860,12 +871,16 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam)
|
||||
SetMemoryUsage();
|
||||
return true;
|
||||
}
|
||||
|
||||
case IDC_COMPRESS_LEVEL:
|
||||
{
|
||||
const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
|
||||
int index = FindRegistryFormatAlways(ai.Name);
|
||||
NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
|
||||
fo.ResetForLevelChange();
|
||||
{
|
||||
const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
|
||||
int index = FindRegistryFormatAlways(ai.Name);
|
||||
NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
|
||||
fo.ResetForLevelChange();
|
||||
}
|
||||
|
||||
SetMethod();
|
||||
SetSolidBlockSize();
|
||||
SetNumThreads();
|
||||
@@ -873,6 +888,7 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam)
|
||||
SetMemoryUsage();
|
||||
return true;
|
||||
}
|
||||
|
||||
case IDC_COMPRESS_METHOD:
|
||||
{
|
||||
SetDictionary();
|
||||
@@ -883,13 +899,34 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam)
|
||||
SetMemoryUsage();
|
||||
return true;
|
||||
}
|
||||
|
||||
case IDC_COMPRESS_DICTIONARY:
|
||||
case IDC_COMPRESS_ORDER:
|
||||
{
|
||||
SetSolidBlockSize();
|
||||
UInt32 blockSizeLog = GetBlockSizeSpec();
|
||||
if (blockSizeLog != (UInt32)(Int32)-1
|
||||
&& blockSizeLog != kNoSolidBlockSize
|
||||
&& blockSizeLog != kSolidBlockSize)
|
||||
{
|
||||
const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
|
||||
int index = FindRegistryFormatAlways(ai.Name);
|
||||
NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
|
||||
fo.Reset_BlockLogSize();
|
||||
SetSolidBlockSize(true);
|
||||
}
|
||||
|
||||
SetMemoryUsage();
|
||||
return true;
|
||||
}
|
||||
|
||||
case IDC_COMPRESS_ORDER:
|
||||
return true;
|
||||
|
||||
case IDC_COMPRESS_SOLID:
|
||||
{
|
||||
SetMemoryUsage();
|
||||
return true;
|
||||
}
|
||||
|
||||
case IDC_COMPRESS_THREADS:
|
||||
{
|
||||
SetMemoryUsage();
|
||||
@@ -1022,6 +1059,8 @@ void CCompressDialog::SetLevel()
|
||||
const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
|
||||
if (fo.Level <= 9)
|
||||
level = fo.Level;
|
||||
else if (fo.Level == (UInt32)(Int32)-1)
|
||||
level = 5;
|
||||
else
|
||||
level = 9;
|
||||
}
|
||||
@@ -1101,6 +1140,12 @@ bool CCompressDialog::IsZipFormat()
|
||||
return ai.Name.IsEqualTo_Ascii_NoCase("zip");
|
||||
}
|
||||
|
||||
bool CCompressDialog::IsXzFormat()
|
||||
{
|
||||
const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
|
||||
return ai.Name.IsEqualTo_Ascii_NoCase("xz");
|
||||
}
|
||||
|
||||
void CCompressDialog::SetEncryptionMethod()
|
||||
{
|
||||
_encryptionMethod.ResetContent();
|
||||
@@ -1465,10 +1510,8 @@ bool CCompressDialog::GetOrderMode()
|
||||
return false;
|
||||
}
|
||||
|
||||
static const UInt32 kNoSolidBlockSize = 0;
|
||||
static const UInt32 kSolidBlockSize = 64;
|
||||
|
||||
void CCompressDialog::SetSolidBlockSize()
|
||||
void CCompressDialog::SetSolidBlockSize(bool useDictionary)
|
||||
{
|
||||
m_Solid.ResetContent();
|
||||
const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
|
||||
@@ -1486,6 +1529,10 @@ void CCompressDialog::SetSolidBlockSize()
|
||||
UInt32 defaultBlockSize = (UInt32)(Int32)-1;
|
||||
|
||||
const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
|
||||
|
||||
if (useDictionary)
|
||||
defaultBlockSize = GetBlockSizeSpec();
|
||||
else
|
||||
{
|
||||
int index = FindRegistryFormat(ai.Name);
|
||||
if (index >= 0)
|
||||
@@ -1496,23 +1543,54 @@ void CCompressDialog::SetSolidBlockSize()
|
||||
}
|
||||
}
|
||||
|
||||
bool is7z = ai.Name.IsEqualTo_Ascii_NoCase("7z");
|
||||
|
||||
{
|
||||
int index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_NON_SOLID));
|
||||
UString s ('-');
|
||||
if (is7z)
|
||||
LangString(IDS_COMPRESS_NON_SOLID, s);
|
||||
int index = (int)m_Solid.AddString(s);
|
||||
m_Solid.SetItemData(index, (UInt32)kNoSolidBlockSize);
|
||||
m_Solid.SetCurSel(0);
|
||||
if (defaultBlockSize == kNoSolidBlockSize)
|
||||
m_Solid.SetCurSel(0);
|
||||
}
|
||||
|
||||
bool needSet = (defaultBlockSize == (UInt32)(Int32)-1);
|
||||
UInt64 blockSize;
|
||||
|
||||
if (is7z)
|
||||
{
|
||||
blockSize = (UInt64)dict << 7;
|
||||
const UInt32 kMinSize = (UInt32)1 << 24;
|
||||
const UInt64 kMaxSize = (UInt64)1 << 32;
|
||||
if (blockSize < kMinSize) blockSize = kMinSize;
|
||||
if (blockSize > kMaxSize) blockSize = kMaxSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
blockSize = (UInt64)dict << 2;
|
||||
const UInt32 kMinSize = (UInt32)1 << 20;
|
||||
const UInt32 kMaxSize = (UInt32)1 << 28;
|
||||
if (blockSize < kMinSize) blockSize = kMinSize;
|
||||
if (blockSize > kMaxSize) blockSize = kMaxSize;
|
||||
if (blockSize < dict) blockSize = dict;
|
||||
}
|
||||
|
||||
for (unsigned i = 20; i <= 36; i++)
|
||||
{
|
||||
if (needSet && dict >= (((UInt64)1 << (i - 7))) && i <= 32)
|
||||
if (defaultBlockSize == (UInt32)(Int32)-1 && ((UInt64)1 << i) >= blockSize)
|
||||
defaultBlockSize = i;
|
||||
|
||||
TCHAR s[40];
|
||||
char post;
|
||||
ConvertUInt32ToString(1 << (i % 10), s);
|
||||
if (i < 30) lstrcat(s, TEXT(" M"));
|
||||
else lstrcat(s, TEXT(" G"));
|
||||
lstrcat(s, TEXT("B"));
|
||||
if (i < 20) post = 'K';
|
||||
else if (i < 30) post = 'M';
|
||||
else post = 'G';
|
||||
unsigned pos = (unsigned)lstrlen(s);
|
||||
s[pos++] = ' ';
|
||||
s[pos++] = post;
|
||||
s[pos++] = 'B';
|
||||
s[pos] = 0;
|
||||
int index = (int)m_Solid.AddString(s);
|
||||
m_Solid.SetItemData(index, (UInt32)i);
|
||||
}
|
||||
@@ -1628,17 +1706,39 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dict, UInt64 &decompressMemory)
|
||||
|
||||
UInt32 numBlockThreads = numThreads / numThreads1;
|
||||
|
||||
if (methidId == kLZMA || numBlockThreads == 1)
|
||||
size1 += (UInt64)dict * 3 / 2;
|
||||
else
|
||||
UInt64 chunkSize = 0;
|
||||
|
||||
if (methidId != kLZMA && numBlockThreads != 1)
|
||||
{
|
||||
UInt64 chunkSize = (UInt64)dict << 2;
|
||||
chunkSize = (UInt64)dict << 2;
|
||||
chunkSize = MyMax(chunkSize, (UInt64)(1 << 20));
|
||||
chunkSize = MyMin(chunkSize, (UInt64)(1 << 28));
|
||||
chunkSize = MyMax(chunkSize, (UInt64)dict);
|
||||
size1 += chunkSize * 2;
|
||||
|
||||
if (IsXzFormat())
|
||||
{
|
||||
UInt32 blockSizeLog = GetBlockSizeSpec();
|
||||
if (blockSizeLog != (UInt32)(Int32)-1)
|
||||
{
|
||||
if (blockSizeLog == kSolidBlockSize)
|
||||
{
|
||||
numBlockThreads = 1;
|
||||
chunkSize = 0;
|
||||
}
|
||||
else if (blockSizeLog != kNoSolidBlockSize)
|
||||
chunkSize = (UInt64)1 << blockSizeLog;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (chunkSize == 0)
|
||||
size += numBlockThreads * (size1 + (UInt64)dict * 3 / 2);
|
||||
else
|
||||
{
|
||||
size += numBlockThreads * (size1 + chunkSize);
|
||||
UInt64 numPackChunks = numBlockThreads + (numBlockThreads / 4) + 2;
|
||||
size += numPackChunks * chunkSize;
|
||||
}
|
||||
size += size1 * numBlockThreads;
|
||||
|
||||
decompressMemory = dict + (2 << 20);
|
||||
return size;
|
||||
@@ -1653,9 +1753,11 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dict, UInt64 &decompressMemory)
|
||||
case kDeflate:
|
||||
case kDeflate64:
|
||||
{
|
||||
/*
|
||||
UInt32 order = GetOrder();
|
||||
if (order == (UInt32)(Int32)-1)
|
||||
order = 32;
|
||||
*/
|
||||
if (level >= 7)
|
||||
size += (1 << 20);
|
||||
size += 3 << 20;
|
||||
|
||||
@@ -137,6 +137,7 @@ class CCompressDialog: public NWindows::NControl::CModalDialog
|
||||
UString GetEncryptionMethodSpec();
|
||||
|
||||
bool IsZipFormat();
|
||||
bool IsXzFormat();
|
||||
|
||||
void SetEncryptionMethod();
|
||||
|
||||
@@ -161,7 +162,7 @@ class CCompressDialog: public NWindows::NControl::CModalDialog
|
||||
void SetOrder();
|
||||
bool GetOrderMode();
|
||||
|
||||
void SetSolidBlockSize();
|
||||
void SetSolidBlockSize(bool useDictionary = false);
|
||||
void SetNumThreads();
|
||||
|
||||
UInt64 GetMemoryUsage(UInt32 dict, UInt64 &decompressMemory);
|
||||
|
||||
@@ -128,14 +128,21 @@ static int Main2()
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
NSecurity::EnablePrivilege_SymLink();
|
||||
#endif
|
||||
|
||||
#ifdef _7ZIP_LARGE_PAGES
|
||||
if (options.LargePages)
|
||||
{
|
||||
SetLargePageSize();
|
||||
g_LargePagesMode = NSecurity::EnablePrivilege_LockMemory();
|
||||
// note: this process also can inherit that Privilege from parent process
|
||||
g_LargePagesMode =
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
NSecurity::EnablePrivilege_LockMemory();
|
||||
#else
|
||||
true;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
CREATE_CODECS_OBJECT
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ RSC=rc.exe
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||
# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /FAcs /Yu"stdafx.h" /FD /c
|
||||
# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /D "_7ZIP_LARGE_PAGES" /FAcs /Yu"stdafx.h" /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x419 /d "NDEBUG"
|
||||
@@ -72,7 +72,7 @@ LINK32=link.exe
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||
# ADD CPP /nologo /Gr /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /GZ /c
|
||||
# ADD CPP /nologo /Gr /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /D "_7ZIP_LARGE_PAGES" /Yu"stdafx.h" /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x419 /d "_DEBUG"
|
||||
@@ -99,7 +99,7 @@ LINK32=link.exe
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||
# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /c
|
||||
# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /D "_7ZIP_LARGE_PAGES" /Yu"stdafx.h" /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x419 /d "NDEBUG"
|
||||
@@ -127,7 +127,7 @@ LINK32=link.exe
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||
# ADD CPP /nologo /Gr /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /GZ /c
|
||||
# ADD CPP /nologo /Gr /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /D "_7ZIP_LARGE_PAGES" /Yu"stdafx.h" /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x419 /d "_DEBUG"
|
||||
|
||||
@@ -32,7 +32,9 @@ LFLAGS = $(LFLAGS) /ENTRY:mainACRTStartup
|
||||
!IFNDEF NEW_COMPILER
|
||||
LFLAGS = $(LFLAGS) -OPT:NOWIN98
|
||||
!ENDIF
|
||||
# !IF "$(CPU)" != "ARM"
|
||||
CFLAGS = $(CFLAGS) -Gr
|
||||
# !ENDIF
|
||||
LIBS = $(LIBS) user32.lib advapi32.lib shell32.lib
|
||||
!ENDIF
|
||||
|
||||
@@ -80,7 +82,9 @@ LFLAGS = $(LFLAGS) /LARGEADDRESSAWARE
|
||||
!IFDEF DEF_FILE
|
||||
LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE)
|
||||
!ELSE
|
||||
# !IF "$(CPU)" != "ARM"
|
||||
LFLAGS = $(LFLAGS) /FIXED
|
||||
# !ENDIF
|
||||
# /BASE:0x400000
|
||||
!ENDIF
|
||||
|
||||
|
||||
@@ -128,6 +128,15 @@ bool SetFileAttrib(CFSTR path, DWORD attrib)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib)
|
||||
{
|
||||
if ((attrib & 0xF0000000) != 0)
|
||||
attrib &= 0x3FFF;
|
||||
return SetFileAttrib(path, attrib);
|
||||
}
|
||||
|
||||
|
||||
bool RemoveDir(CFSTR path)
|
||||
{
|
||||
#ifndef _UNICODE
|
||||
|
||||
@@ -15,7 +15,20 @@ bool GetWindowsDir(FString &path);
|
||||
bool GetSystemDir(FString &path);
|
||||
|
||||
bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime);
|
||||
|
||||
|
||||
bool SetFileAttrib(CFSTR path, DWORD attrib);
|
||||
|
||||
/*
|
||||
Some programs store posix attributes in high 16 bits of windows attributes field.
|
||||
Also some programs use additional flag markers: 0x8000 or 0x4000.
|
||||
SetFileAttrib_PosixHighDetect() tries to detect posix field, and it extracts only attribute
|
||||
bits that are related to current system only.
|
||||
*/
|
||||
|
||||
bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib);
|
||||
|
||||
|
||||
bool MyMoveFile(CFSTR existFileName, CFSTR newFileName);
|
||||
|
||||
#ifndef UNDER_CE
|
||||
|
||||
Reference in New Issue
Block a user