This commit is contained in:
Igor Pavlov
2018-01-11 22:16:32 +01:00
committed by Kornel
parent b5dc853b24
commit da28077952
44 changed files with 853 additions and 366 deletions

View File

@@ -1,7 +1,7 @@
#define MY_VER_MAJOR 17 #define MY_VER_MAJOR 18
#define MY_VER_MINOR 01 #define MY_VER_MINOR 00
#define MY_VER_BUILD 0 #define MY_VER_BUILD 0
#define MY_VERSION_NUMBERS "17.01 beta" #define MY_VERSION_NUMBERS "18.00 beta"
#define MY_VERSION MY_VERSION_NUMBERS #define MY_VERSION MY_VERSION_NUMBERS
#ifdef MY_CPU_NAME #ifdef MY_CPU_NAME
@@ -10,12 +10,12 @@
#define MY_VERSION_CPU MY_VERSION #define MY_VERSION_CPU MY_VERSION
#endif #endif
#define MY_DATE "2017-08-28" #define MY_DATE "2018-01-10"
#undef MY_COPYRIGHT #undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE #undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov" #define MY_AUTHOR_NAME "Igor Pavlov"
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain" #define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2017 Igor Pavlov" #define MY_COPYRIGHT_CR "Copyright (c) 1999-2018 Igor Pavlov"
#ifdef USE_COPYRIGHT_CR #ifdef USE_COPYRIGHT_CR
#define MY_COPYRIGHT MY_COPYRIGHT_CR #define MY_COPYRIGHT MY_COPYRIGHT_CR

View File

@@ -377,11 +377,17 @@ static SRes SeqInFilter_Read(const ISeqInStream *pp, void *data, size_t *size)
static void SeqInFilter_Construct(CSeqInFilter *p) static void SeqInFilter_Construct(CSeqInFilter *p)
{ {
p->buf = NULL; p->buf = NULL;
p->StateCoder.p = NULL;
p->p.Read = SeqInFilter_Read; p->p.Read = SeqInFilter_Read;
} }
static void SeqInFilter_Free(CSeqInFilter *p, ISzAllocPtr alloc) static void SeqInFilter_Free(CSeqInFilter *p, ISzAllocPtr alloc)
{ {
if (p->StateCoder.p)
{
p->StateCoder.Free(p->StateCoder.p, alloc);
p->StateCoder.p = NULL;
}
if (p->buf) if (p->buf)
{ {
ISzAlloc_Free(alloc, p->buf); ISzAlloc_Free(alloc, p->buf);

View File

@@ -180,7 +180,7 @@ UInt32 CInArchive::ReadDigits(int numDigits)
Byte b = ReadByte(); Byte b = ReadByte();
if (b < '0' || b > '9') if (b < '0' || b > '9')
{ {
if (b == 0) // it's bug in some CD's if (b == 0 || b == ' ') // it's bug in some CD's
b = '0'; b = '0';
else else
throw CHeaderErrorException(); throw CHeaderErrorException();

View File

@@ -109,7 +109,8 @@ void CVersion::ToProp(NCOM::CPropVariant &prop)
prop = sz; prop = sz;
} }
static const unsigned kHeaderSize = 4 + 20; static const unsigned kCoffHeaderSize = 20;
static const unsigned kPeHeaderSize = 4 + kCoffHeaderSize;
static const unsigned k_OptHeader32_Size_MIN = 96; static const unsigned k_OptHeader32_Size_MIN = 96;
static const unsigned k_OptHeader64_Size_MIN = 112; static const unsigned k_OptHeader64_Size_MIN = 112;
@@ -125,15 +126,14 @@ struct CHeader
UInt16 OptHeaderSize; UInt16 OptHeaderSize;
UInt16 Flags; UInt16 Flags;
bool Parse(const Byte *p); void ParseBase(const Byte *p);
bool ParseCoff(const Byte *p);
bool ParsePe(const Byte *p);
bool IsDll() const { return (Flags & PE_IMAGE_FILE_DLL) != 0; } bool IsDll() const { return (Flags & PE_IMAGE_FILE_DLL) != 0; }
}; };
bool CHeader::Parse(const Byte *p) void CHeader::ParseBase(const Byte *p)
{ {
if (Get32(p) != k_Signature32)
return false;
p += 4;
G16( 0, Machine); G16( 0, Machine);
G16( 2, NumSections); G16( 2, NumSections);
G32( 4, Time); G32( 4, Time);
@@ -141,6 +141,13 @@ bool CHeader::Parse(const Byte *p)
G32(12, NumSymbols); G32(12, NumSymbols);
G16(16, OptHeaderSize); G16(16, OptHeaderSize);
G16(18, Flags); G16(18, Flags);
}
bool CHeader::ParsePe(const Byte *p)
{
if (Get32(p) != k_Signature32)
return false;
ParseBase(p + 4);
return OptHeaderSize >= k_OptHeader32_Size_MIN; return OptHeaderSize >= k_OptHeader32_Size_MIN;
} }
@@ -399,39 +406,67 @@ static const CUInt32PCharPair g_HeaderCharacts[] =
{ 15, "Big-Endian" } { 15, "Big-Endian" }
}; };
static const CUInt32PCharPair g_DllCharacts[] =
// IMAGE_DLLCHARACTERISTICS_* constants
static const char * const g_DllCharacts[] =
{ {
{ 5, "HighEntropyVA" }, NULL
{ 6, "Relocated" }, , NULL
{ 7, "Integrity" }, , NULL
{ 8, "NX-Compatible" }, , NULL
{ 9, "NoIsolation" }, , NULL
{ 10, "NoSEH" }, , "HighEntropyVA"
{ 11, "NoBind" }, , "Relocated"
{ 12, "AppContainer" }, , "Integrity"
{ 13, "WDM" }, , "NX-Compatible"
{ 14, "GuardCF" }, , "NoIsolation"
{ 15, "TerminalServerAware" } , "NoSEH"
, "NoBind"
, "AppContainer"
, "WDM"
, "GuardCF"
, "TerminalServerAware"
}; };
static const CUInt32PCharPair g_SectFlags[] =
// IMAGE_SCN_* constants:
static const char * const g_SectFlags[] =
{ {
{ 3, "NoPad" }, NULL
{ 5, "Code" }, , NULL
{ 6, "InitializedData" }, , NULL
{ 7, "UninitializedData" }, , "NoPad"
{ 9, "Comments" }, , NULL
{ 11, "Remove" }, , "Code"
{ 12, "COMDAT" }, , "InitializedData"
{ 15, "GP" }, , "UninitializedData"
{ 24, "ExtendedRelocations" }, , "Other"
{ 25, "Discardable" }, , "Comments"
{ 26, "NotCached" }, , NULL // OVER
{ 27, "NotPaged" }, , "Remove"
{ 28, "Shared" }, , "COMDAT"
{ 29, "Execute" }, , NULL
{ 30, "Read" }, , "NO_DEFER_SPEC_EXC"
{ 31, "Write" } , "GP" // MEM_FARDATA
, NULL // SYSHEAP
, "PURGEABLE" // 16BIT
, "LOCKED"
, "PRELOAD"
, NULL
, NULL
, NULL
, NULL
, "ExtendedRelocations"
, "Discardable"
, "NotCached"
, "NotPaged"
, "Shared"
, "Execute"
, "Read"
, "Write"
}; };
static const CUInt32PCharPair g_MachinePairs[] = static const CUInt32PCharPair g_MachinePairs[] =
@@ -699,7 +734,6 @@ class CHandler:
{ {
CMyComPtr<IInStream> _stream; CMyComPtr<IInStream> _stream;
CObjectVector<CSection> _sections; CObjectVector<CSection> _sections;
UInt32 _peOffset;
CHeader _header; CHeader _header;
UInt32 _totalSize; UInt32 _totalSize;
Int32 _mainSubfile; Int32 _mainSubfile;
@@ -720,9 +754,12 @@ class CHandler:
bool _parseResources; bool _parseResources;
bool _checksumError; bool _checksumError;
bool IsOpt() const { return _header.OptHeaderSize != 0; }
COptHeader _optHeader; COptHeader _optHeader;
bool _allowTail; bool _allowTail;
bool _coffMode;
HRESULT LoadDebugSections(IInStream *stream, bool &thereIsSection); HRESULT LoadDebugSections(IInStream *stream, bool &thereIsSection);
HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
@@ -742,7 +779,10 @@ class CHandler:
} }
public: public:
CHandler(): _allowTail(false) {} CHandler(bool coffMode = false):
_coffMode(coffMode),
_allowTail(coffMode)
{}
MY_UNKNOWN_IMP3(IInArchive, IInArchiveGetStream, IArchiveAllowTail) MY_UNKNOWN_IMP3(IInArchive, IInArchiveGetStream, IArchiveAllowTail)
INTERFACE_IInArchive(;) INTERFACE_IInArchive(;)
@@ -841,6 +881,34 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
NCOM::CPropVariant prop; NCOM::CPropVariant prop;
switch (propID) switch (propID)
{ {
case kpidPhySize: prop = _totalSize; break;
case kpidComment: if (!_versionFullString.IsEmpty()) prop = _versionFullString; break;
case kpidShortComment:
if (!_versionShortString.IsEmpty())
prop = _versionShortString;
else
{
PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop);
}
break;
case kpidName: if (!_originalFilename.IsEmpty()) prop = _originalFilename; break;
// case kpidIsSelfExe: prop = !_header.IsDll(); break;
// case kpidError:
case kpidWarning: if (_checksumError) prop = "Checksum error"; break;
case kpidCpu: PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop); break;
case kpidMTime:
case kpidCTime: TimeToProp(_header.Time, prop); break;
case kpidCharacts: FLAGS_TO_PROP(g_HeaderCharacts, _header.Flags, prop); break;
case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
default:
if (IsOpt())
switch (propID)
{
case kpidSectAlign: prop = _optHeader.SectAlign; break; case kpidSectAlign: prop = _optHeader.SectAlign; break;
case kpidFileAlign: prop = _optHeader.FileAlign; break; case kpidFileAlign: prop = _optHeader.FileAlign; break;
case kpidLinkerVer: case kpidLinkerVer:
@@ -857,37 +925,17 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidInitDataSize: prop = _optHeader.InitDataSize; break; case kpidInitDataSize: prop = _optHeader.InitDataSize; break;
case kpidUnInitDataSize: prop = _optHeader.UninitDataSize; break; case kpidUnInitDataSize: prop = _optHeader.UninitDataSize; break;
case kpidImageSize: prop = _optHeader.ImageSize; break; case kpidImageSize: prop = _optHeader.ImageSize; break;
case kpidPhySize: prop = _totalSize; break;
case kpidHeadersSize: prop = _optHeader.HeadersSize; break; case kpidHeadersSize: prop = _optHeader.HeadersSize; break;
case kpidChecksum: prop = _optHeader.CheckSum; break; case kpidChecksum: prop = _optHeader.CheckSum; break;
case kpidComment: if (!_versionFullString.IsEmpty()) prop = _versionFullString; break;
case kpidShortComment:
if (!_versionShortString.IsEmpty())
prop = _versionShortString;
else
{
PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop);
}
break;
case kpidName: if (!_originalFilename.IsEmpty()) prop = _originalFilename; break;
case kpidExtension: case kpidExtension:
if (_header.IsDll()) if (_header.IsDll())
prop = _optHeader.IsSybSystem_EFI() ? "efi" : "dll"; prop = _optHeader.IsSybSystem_EFI() ? "efi" : "dll";
break; break;
// case kpidIsSelfExe: prop = !_header.IsDll(); break;
// case kpidError:
case kpidWarning: if (_checksumError) prop = "Checksum error"; break;
case kpidCpu: PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop); break;
case kpidBit64: if (_optHeader.Is64Bit()) prop = true; break; case kpidBit64: if (_optHeader.Is64Bit()) prop = true; break;
case kpidSubSystem: TYPE_TO_PROP(g_SubSystems, _optHeader.SubSystem, prop); break; case kpidSubSystem: TYPE_TO_PROP(g_SubSystems, _optHeader.SubSystem, prop); break;
case kpidMTime:
case kpidCTime: TimeToProp(_header.Time, prop); break;
case kpidCharacts: FLAGS_TO_PROP(g_HeaderCharacts, _header.Flags, prop); break;
case kpidDllCharacts: FLAGS_TO_PROP(g_DllCharacts, _optHeader.DllCharacts, prop); break; case kpidDllCharacts: FLAGS_TO_PROP(g_DllCharacts, _optHeader.DllCharacts, prop); break;
case kpidStackReserve: prop = _optHeader.StackReserve; break; case kpidStackReserve: prop = _optHeader.StackReserve; break;
case kpidStackCommit: prop = _optHeader.StackCommit; break; case kpidStackCommit: prop = _optHeader.StackCommit; break;
@@ -898,8 +946,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
// case kpidAddressOfEntryPoint: prop = _optHeader.AddressOfEntryPoint; break; // case kpidAddressOfEntryPoint: prop = _optHeader.AddressOfEntryPoint; break;
// case kpidBaseOfCode: prop = _optHeader.BaseOfCode; break; // case kpidBaseOfCode: prop = _optHeader.BaseOfCode; break;
// case kpidBaseOfData32: if (!_optHeader.Is64Bit()) prop = _optHeader.BaseOfData32; break; // case kpidBaseOfData32: if (!_optHeader.Is64Bit()) prop = _optHeader.BaseOfData32; break;
}
case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
} }
prop.Detach(value); prop.Detach(value);
return S_OK; return S_OK;
@@ -1056,7 +1103,24 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidMTime: case kpidMTime:
case kpidCTime: case kpidCTime:
TimeToProp(item.IsDebug ? item.Time : _header.Time, prop); break; TimeToProp(item.IsDebug ? item.Time : _header.Time, prop); break;
case kpidCharacts: if (item.IsRealSect) FLAGS_TO_PROP(g_SectFlags, item.Flags, prop); break; case kpidCharacts:
if (item.IsRealSect)
{
UInt32 flags = item.Flags;
const UInt32 MY__IMAGE_SCN_ALIGN_MASK = 0x00F00000;
AString s = FlagsToString(g_SectFlags, ARRAY_SIZE(g_SectFlags), item.Flags & ~MY__IMAGE_SCN_ALIGN_MASK);
const UInt32 align = ((flags >> 20) & 0xF);
if (align != 0)
{
char sz[32];
ConvertUInt32ToString(1 << (align - 1), sz);
s.Add_Space();
s += "align_";
s += sz;
}
prop = s;
}
break;
case kpidZerosTailIsAllowed: if (!item.IsRealSect) prop = true; break; case kpidZerosTailIsAllowed: if (!item.IsRealSect) prop = true; break;
} }
} }
@@ -2114,6 +2178,23 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi
return S_OK; return S_OK;
} }
bool CHeader::ParseCoff(const Byte *p)
{
ParseBase(p);
if (PointerToSymbolTable < kCoffHeaderSize)
return false;
if (NumSymbols >= (1 << 24))
return false;
if (OptHeaderSize != 0 && OptHeaderSize < k_OptHeader32_Size_MIN)
return false;
for (unsigned i = 0; i < ARRAY_SIZE(g_MachinePairs); i++)
if (Machine == g_MachinePairs[i].Value)
return true;
return false;
}
static inline bool CheckPeOffset(UInt32 pe) static inline bool CheckPeOffset(UInt32 pe)
{ {
// ((pe & 7) == 0) is for most PE files. But there is unusual EFI-PE file that uses unaligned pe value. // ((pe & 7) == 0) is for most PE files. But there is unusual EFI-PE file that uses unaligned pe value.
@@ -2133,10 +2214,10 @@ API_FUNC_static_IsArc IsArc_Pe(const Byte *p, size_t size)
UInt32 pe = Get32(p + 0x3C); UInt32 pe = Get32(p + 0x3C);
if (!CheckPeOffset(pe)) if (!CheckPeOffset(pe))
return k_IsArc_Res_NO; return k_IsArc_Res_NO;
if (pe + kHeaderSize > size) if (pe + kPeHeaderSize > size)
return k_IsArc_Res_NEED_MORE; return k_IsArc_Res_NEED_MORE;
CHeader header; CHeader header;
if (!header.Parse(p + pe)) if (!header.ParsePe(p + pe))
return k_IsArc_Res_NO; return k_IsArc_Res_NO;
return k_IsArc_Res_YES; return k_IsArc_Res_YES;
} }
@@ -2144,32 +2225,47 @@ API_FUNC_static_IsArc IsArc_Pe(const Byte *p, size_t size)
HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
{ {
UInt32 coffOffset = 0;
if (_coffMode)
{ {
Byte h[kStartSize]; Byte h[kCoffHeaderSize];
_mainSubfile = -1; RINOK(ReadStream_FALSE(stream, h, kCoffHeaderSize));
RINOK(ReadStream_FALSE(stream, h, kStartSize)); if (!_header.ParseCoff(h))
if (h[0] != 'M' || h[1] != 'Z')
return S_FALSE;
/* most of PE files contain 0x0090 at offset 2.
But some rare PE files contain another values. So we don't use that check.
if (Get16(h + 2) != 0x90) return false; */
_peOffset = Get32(h + 0x3C);
if (!CheckPeOffset(_peOffset))
return S_FALSE; return S_FALSE;
} }
else
{ {
Byte h[kHeaderSize]; UInt32 _peOffset;
RINOK(stream->Seek(_peOffset, STREAM_SEEK_SET, NULL)); {
RINOK(ReadStream_FALSE(stream, h, kHeaderSize)); Byte h[kStartSize];
if (!_header.Parse(h)) RINOK(ReadStream_FALSE(stream, h, kStartSize));
return S_FALSE; if (h[0] != 'M' || h[1] != 'Z')
return S_FALSE;
/* most of PE files contain 0x0090 at offset 2.
But some rare PE files contain another values. So we don't use that check.
if (Get16(h + 2) != 0x90) return false; */
_peOffset = Get32(h + 0x3C);
if (!CheckPeOffset(_peOffset))
return S_FALSE;
coffOffset = _peOffset + 4;
}
{
Byte h[kPeHeaderSize];
RINOK(stream->Seek(_peOffset, STREAM_SEEK_SET, NULL));
RINOK(ReadStream_FALSE(stream, h, kPeHeaderSize));
if (!_header.ParsePe(h))
return S_FALSE;
}
} }
UInt32 bufSize = _header.OptHeaderSize + (UInt32)_header.NumSections * kSectionSize; const UInt32 optStart = coffOffset + kCoffHeaderSize;
_totalSize = _peOffset + kHeaderSize + bufSize; const UInt32 bufSize = _header.OptHeaderSize + (UInt32)_header.NumSections * kSectionSize;
_totalSize = optStart + bufSize;
CByteBuffer buffer(bufSize); CByteBuffer buffer(bufSize);
RINOK(ReadStream_FALSE(stream, buffer, bufSize)); RINOK(ReadStream_FALSE(stream, buffer, bufSize));
if (_header.OptHeaderSize != 0)
if (!_optHeader.Parse(buffer, _header.OptHeaderSize)) if (!_optHeader.Parse(buffer, _header.OptHeaderSize))
return S_FALSE; return S_FALSE;
@@ -2207,7 +2303,9 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
for (i = 0; i < _sections.Size(); i++) for (i = 0; i < _sections.Size(); i++)
_sections[i].UpdateTotalSize(_totalSize); _sections[i].UpdateTotalSize(_totalSize);
bool thereISDebug; bool thereISDebug = false;
if (IsOpt())
{
RINOK(LoadDebugSections(stream, thereISDebug)); RINOK(LoadDebugSections(stream, thereISDebug));
const CDirLink &certLink = _optHeader.DirItems[kDirLink_Certificate]; const CDirLink &certLink = _optHeader.DirItems[kDirLink_Certificate];
@@ -2256,8 +2354,9 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
_totalSize += (UInt32)k; _totalSize += (UInt32)k;
} }
} }
}
if (_header.NumSymbols > 0 && _header.PointerToSymbolTable >= 512) if (_header.NumSymbols > 0 && _header.PointerToSymbolTable >= optStart)
{ {
if (_header.NumSymbols >= (1 << 24)) if (_header.NumSymbols >= (1 << 24))
return S_FALSE; return S_FALSE;
@@ -2306,11 +2405,12 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
} }
if (IsOpt())
if (_optHeader.CheckSum != 0) if (_optHeader.CheckSum != 0)
{ {
RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
UInt32 checkSum = 0; UInt32 checkSum = 0;
RINOK(CalcCheckSum(stream, _totalSize, _peOffset + kHeaderSize + k_CheckSum_Field_Offset, checkSum)); RINOK(CalcCheckSum(stream, _totalSize, optStart + k_CheckSum_Field_Offset, checkSum));
_checksumError = (checkSum != _optHeader.CheckSum); _checksumError = (checkSum != _optHeader.CheckSum);
} }
@@ -2333,6 +2433,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
const CSection &sect = _sections[i]; const CSection &sect = _sections[i];
CMixItem mixItem; CMixItem mixItem;
mixItem.SectionIndex = i; mixItem.SectionIndex = i;
if (IsOpt())
if (_parseResources && sect.Name == ".rsrc" && _items.IsEmpty()) if (_parseResources && sect.Name == ".rsrc" && _items.IsEmpty())
{ {
const unsigned numMixItems = _mixItems.Size(); const unsigned numMixItems = _mixItems.Size();
@@ -2480,6 +2581,8 @@ STDMETHODIMP CHandler::Close()
{ {
_totalSize = 0; _totalSize = 0;
_checksumError = false; _checksumError = false;
_mainSubfile = -1;
_stream.Release(); _stream.Release();
_sections.Clear(); _sections.Clear();
_mixItems.Clear(); _mixItems.Clear();
@@ -2675,10 +2778,41 @@ REGISTER_ARC_I(
0, 0,
NArcInfoFlags::kPreArc, NArcInfoFlags::kPreArc,
IsArc_Pe) IsArc_Pe)
} }
namespace NCoff {
API_FUNC_static_IsArc IsArc_Coff(const Byte *p, size_t size)
{
if (size < NPe::kCoffHeaderSize)
return k_IsArc_Res_NEED_MORE;
NPe::CHeader header;
if (!header.ParseCoff(p))
return k_IsArc_Res_NO;
return k_IsArc_Res_YES;
}
}
/*
static const Byte k_Signature[] =
{
2, 0x4C, 0x01, // x86
2, 0x64, 0x86, // x64
2, 0x64, 0xAA // ARM64
};
REGISTER_ARC_I_CLS(
*/
REGISTER_ARC_I_CLS_NO_SIG(
NPe::CHandler(true),
"COFF", "obj", 0, 0xC6,
// k_Signature,
0,
// NArcInfoFlags::kMultiSignature |
NArcInfoFlags::kStartOpen,
IsArc_Coff)
}
namespace NTe { namespace NTe {

View File

@@ -28,14 +28,23 @@ HRESULT SResToHRESULT(SRes res) throw()
switch (res) switch (res)
{ {
case SZ_OK: return S_OK; case SZ_OK: return S_OK;
case SZ_ERROR_DATA: return S_FALSE;
case SZ_ERROR_CRC: return S_FALSE; case SZ_ERROR_DATA:
case SZ_ERROR_CRC:
case SZ_ERROR_INPUT_EOF:
return S_FALSE;
case SZ_ERROR_MEM: return E_OUTOFMEMORY; case SZ_ERROR_MEM: return E_OUTOFMEMORY;
case SZ_ERROR_PARAM: return E_INVALIDARG; case SZ_ERROR_PARAM: return E_INVALIDARG;
case SZ_ERROR_PROGRESS: return E_ABORT; case SZ_ERROR_PROGRESS: return E_ABORT;
case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;
// case SZ_ERROR_THREAD: return E_FAIL; // case SZ_ERROR_OUTPUT_EOF:
// case SZ_ERROR_READ: return E_FAIL; // case SZ_ERROR_READ:
// case SZ_ERROR_WRITE:
// case SZ_ERROR_THREAD:
// case SZ_ERROR_ARCHIVE:
// case SZ_ERROR_NO_ARCHIVE:
// return E_FAIL;
} }
if (res < 0) if (res < 0)
return res; return res;

View File

@@ -50,6 +50,17 @@ const UInt32 kNumSelectorsMax = (2 + (kBlockSizeMax / kGroupSize));
const unsigned kRleModeRepSize = 4; const unsigned kRleModeRepSize = 4;
/*
The number of selectors stored in bzip2 block:
(numSelectors <= 18001) - must work with any decoder.
(numSelectors == 18002) - works with bzip2 1.0.6 decoder and all derived decoders.
(numSelectors > 18002)
7-Zip decoder doesn't support it.
bzip2 1.0.6 decoder can overflow selector[18002] arrays. But there are another
arrays after selector arrays. So the compiled code works.
lbzip2 2.5 encoder can write up to (18001 + 7) selectors.
*/
}} }}
#endif #endif

View File

@@ -411,9 +411,13 @@ SRes CBase::ReadBlock2()
lens[state4] = (Byte)state3; lens[state4] = (Byte)state3;
state5 = 0; state5 = 0;
} }
// lbzip2 2.5 can produce dummy tree, where lens[i] = kMaxHuffmanLen
// BuildFull() returns error for such tree
/* /*
for (unsigned i = state4; i < kMaxAlphaSize; i++) for (unsigned i = state4; i < kMaxAlphaSize; i++)
lens[i] = 0; lens[i] = 0;
if (!huffs[state2].Build(lens))
*/ */
if (!huffs[state2].BuildFull(lens, state4)) if (!huffs[state2].BuildFull(lens, state4))
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
@@ -474,7 +478,7 @@ SRes CBase::ReadBlock2()
for (len = kNumTableBits + 1; val >= huff->_limits[len]; len++); for (len = kNumTableBits + 1; val >= huff->_limits[len]; len++);
/* /*
if (len > kNumBitsMax) if (len > kNumBitsMax)
return SZ_ERROR_DATA; return SZ_ERROR_DATA; // that check is required, if NHuffman::Build() was used instead of BuildFull()
*/ */
if (_numBits < len) if (_numBits < len)
{ {

View File

@@ -29,7 +29,7 @@ public:
}; };
*/ */
CDecoder::CDecoder(): m_IsSolid(false) { } CDecoder::CDecoder(): m_IsSolid(false), _errorMode(false) { }
void CDecoder::InitStructures() void CDecoder::InitStructures()
{ {
@@ -406,9 +406,14 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
InitData(); InitData();
if (!m_IsSolid) if (!m_IsSolid)
{ {
_errorMode = false;
InitStructures(); InitStructures();
InitHuff(); InitHuff();
} }
if (_errorMode)
return S_FALSE;
if (m_UnpackSize > 0) if (m_UnpackSize > 0)
{ {
GetFlagsBuf(); GetFlagsBuf();
@@ -477,9 +482,9 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
{ {
try { return CodeReal(inStream, outStream, inSize, outSize, progress); } try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
catch(const CInBufferException &e) { return e.ErrorCode; } catch(const CInBufferException &e) { _errorMode = true; return e.ErrorCode; }
catch(const CLzOutWindowException &e) { return e.ErrorCode; } catch(const CLzOutWindowException &e) { _errorMode = true; return e.ErrorCode; }
catch(...) { return S_FALSE; } catch(...) { _errorMode = true; return S_FALSE; }
} }
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)

View File

@@ -39,6 +39,7 @@ public:
Int64 m_UnpackSize; Int64 m_UnpackSize;
bool m_IsSolid; bool m_IsSolid;
bool _errorMode;
UInt32 ReadBits(int numBits); UInt32 ReadBits(int numBits);
HRESULT CopyBlock(UInt32 distance, UInt32 len); HRESULT CopyBlock(UInt32 distance, UInt32 len);

View File

@@ -130,7 +130,7 @@ bool CDecoder::ReadTables(void)
i = 0; i = 0;
while (i < numLevels) do
{ {
UInt32 sym = m_LevelDecoder.Decode(&m_InBitStream); UInt32 sym = m_LevelDecoder.Decode(&m_InBitStream);
if (sym < kTableDirectLevels) if (sym < kTableDirectLevels)
@@ -144,10 +144,7 @@ bool CDecoder::ReadTables(void)
{ {
unsigned num = ReadBits(2) + 3; unsigned num = ReadBits(2) + 3;
if (i == 0) if (i == 0)
{ return false;
// return false;
continue; // original unRAR
}
num += i; num += i;
if (num > numLevels) if (num > numLevels)
{ {
@@ -180,6 +177,10 @@ bool CDecoder::ReadTables(void)
} }
} }
} }
while (i < numLevels);
if (m_InBitStream.ExtraBitsWereRead())
return false;
if (m_AudioMode) if (m_AudioMode)
for (i = 0; i < m_NumChannels; i++) for (i = 0; i < m_NumChannels; i++)
@@ -244,6 +245,8 @@ bool CDecoder::DecodeMm(UInt32 pos)
while (pos-- != 0) while (pos-- != 0)
{ {
UInt32 symbol = m_MMDecoders[m_MmFilter.CurrentChannel].Decode(&m_InBitStream); UInt32 symbol = m_MMDecoders[m_MmFilter.CurrentChannel].Decode(&m_InBitStream);
if (m_InBitStream.ExtraBitsWereRead())
return false;
if (symbol >= 256) if (symbol >= 256)
return symbol == 256; return symbol == 256;
/* /*
@@ -264,6 +267,8 @@ bool CDecoder::DecodeLz(Int32 pos)
while (pos > 0) while (pos > 0)
{ {
UInt32 sym = m_MainDecoder.Decode(&m_InBitStream); UInt32 sym = m_MainDecoder.Decode(&m_InBitStream);
if (m_InBitStream.ExtraBitsWereRead())
return false;
UInt32 length, distance; UInt32 length, distance;
if (sym < 256) if (sym < 256)
{ {
@@ -389,15 +394,19 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
if (!DecodeLz((Int32)blockSize)) if (!DecodeLz((Int32)blockSize))
return S_FALSE; return S_FALSE;
} }
if (m_InBitStream.ExtraBitsWereRead())
return S_FALSE;
UInt64 globalPos = m_OutWindowStream.GetProcessedSize(); UInt64 globalPos = m_OutWindowStream.GetProcessedSize();
pos = globalPos - blockStartPos; pos = globalPos - blockStartPos;
if (pos < blockSize) if (pos < blockSize)
if (!ReadTables()) if (!ReadTables())
return S_FALSE; return S_FALSE;
pos = globalPos - startPos; pos = globalPos - startPos;
if (progress != 0) if (progress)
{ {
UInt64 packSize = m_InBitStream.GetProcessedSize(); const UInt64 packSize = m_InBitStream.GetProcessedSize();
RINOK(progress->SetRatioInfo(&packSize, &pos)); RINOK(progress->SetRatioInfo(&packSize, &pos));
} }
} }

View File

@@ -94,7 +94,8 @@ CDecoder::CDecoder():
_writtenFileSize(0), _writtenFileSize(0),
_vmData(0), _vmData(0),
_vmCode(0), _vmCode(0),
m_IsSolid(false) m_IsSolid(false),
_errorMode(false)
{ {
Ppmd7_Construct(&_ppmd); Ppmd7_Construct(&_ppmd);
} }
@@ -135,7 +136,7 @@ HRESULT CDecoder::WriteArea(UInt32 startPtr, UInt32 endPtr)
return WriteData(_window, endPtr); return WriteData(_window, endPtr);
} }
void CDecoder::ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef) void CDecoder::ExecuteFilter(unsigned tempFilterIndex, NVm::CBlockRef &outBlockRef)
{ {
CTempFilter *tempFilter = _tempFilters[tempFilterIndex]; CTempFilter *tempFilter = _tempFilters[tempFilterIndex];
tempFilter->InitR[6] = (UInt32)_writtenFileSize; tempFilter->InitR[6] = (UInt32)_writtenFileSize;
@@ -405,7 +406,7 @@ bool CDecoder::ReadVmCodePPM()
#define RIF(x) { if (!(x)) return S_FALSE; } #define RIF(x) { if (!(x)) return S_FALSE; }
UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.BitDecoder.ReadBits(numBits); } UInt32 CDecoder::ReadBits(unsigned numBits) { return m_InBitStream.BitDecoder.ReadBits(numBits); }
// ---------- PPM ---------- // ---------- PPM ----------
@@ -414,7 +415,7 @@ HRESULT CDecoder::InitPPM()
unsigned maxOrder = (unsigned)ReadBits(7); unsigned maxOrder = (unsigned)ReadBits(7);
bool reset = ((maxOrder & 0x20) != 0); bool reset = ((maxOrder & 0x20) != 0);
int maxMB = 0; UInt32 maxMB = 0;
if (reset) if (reset)
maxMB = (Byte)ReadBits(8); maxMB = (Byte)ReadBits(8);
else else
@@ -556,12 +557,13 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing)
PrevAlignCount = 0; PrevAlignCount = 0;
Byte levelLevels[kLevelTableSize]; Byte levelLevels[kLevelTableSize];
Byte newLevels[kTablesSizesSum]; Byte lens[kTablesSizesSum];
if (ReadBits(1) == 0) if (ReadBits(1) == 0)
memset(m_LastLevels, 0, kTablesSizesSum); memset(m_LastLevels, 0, kTablesSizesSum);
int i; unsigned i;
for (i = 0; i < kLevelTableSize; i++) for (i = 0; i < kLevelTableSize; i++)
{ {
UInt32 length = ReadBits(4); UInt32 length = ReadBits(4);
@@ -579,39 +581,44 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing)
} }
levelLevels[i] = (Byte)length; levelLevels[i] = (Byte)length;
} }
RIF(m_LevelDecoder.Build(levelLevels)); RIF(m_LevelDecoder.Build(levelLevels));
i = 0; i = 0;
while (i < kTablesSizesSum)
do
{ {
UInt32 sym = m_LevelDecoder.Decode(&m_InBitStream.BitDecoder); UInt32 sym = m_LevelDecoder.Decode(&m_InBitStream.BitDecoder);
if (sym < 16) if (sym < 16)
{ {
newLevels[i] = Byte((sym + m_LastLevels[i]) & 15); lens[i] = Byte((sym + m_LastLevels[i]) & 15);
i++; i++;
} }
else if (sym > kLevelTableSize) else if (sym > kLevelTableSize)
return S_FALSE; return S_FALSE;
else else
{ {
int num; unsigned num = ((sym - 16) & 1) * 4;
if (((sym - 16) & 1) == 0) num += num + 3 + (unsigned)ReadBits(num + 3);
num = ReadBits(3) + 3; num += i;
else if (num > kTablesSizesSum)
num = ReadBits(7) + 11; num = kTablesSizesSum;
if (sym < 18) Byte v = 0;
if (sym < 16 + 2)
{ {
if (i == 0) if (i == 0)
return S_FALSE; return S_FALSE;
for (; num > 0 && i < kTablesSizesSum; num--, i++) v = lens[(size_t)i - 1];
newLevels[i] = newLevels[(size_t)i - 1];
}
else
{
for (; num > 0 && i < kTablesSizesSum; num--)
newLevels[i++] = 0;
} }
do
lens[i++] = v;
while (i < num);
} }
} }
while (i < kTablesSizesSum);
if (InputEofError())
return S_FALSE;
TablesRead = true; TablesRead = true;
@@ -624,12 +631,12 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing)
} }
*/ */
RIF(m_MainDecoder.Build(&newLevels[0])); RIF(m_MainDecoder.Build(&lens[0]));
RIF(m_DistDecoder.Build(&newLevels[kMainTableSize])); RIF(m_DistDecoder.Build(&lens[kMainTableSize]));
RIF(m_AlignDecoder.Build(&newLevels[kMainTableSize + kDistTableSize])); RIF(m_AlignDecoder.Build(&lens[kMainTableSize + kDistTableSize]));
RIF(m_LenDecoder.Build(&newLevels[kMainTableSize + kDistTableSize + kAlignTableSize])); RIF(m_LenDecoder.Build(&lens[kMainTableSize + kDistTableSize + kAlignTableSize]));
memcpy(m_LastLevels, newLevels, kTablesSizesSum); memcpy(m_LastLevels, lens, kTablesSizesSum);
TablesOK = true; TablesOK = true;
@@ -769,7 +776,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
if (sym2 >= kDistTableSize) if (sym2 >= kDistTableSize)
return S_FALSE; return S_FALSE;
rep0 = kDistStart[sym2]; rep0 = kDistStart[sym2];
int numBits = kDistDirectBits[sym2]; unsigned numBits = kDistDirectBits[sym2];
if (sym2 >= (kNumAlignBits * 2) + 2) if (sym2 >= (kNumAlignBits * 2) + 2)
{ {
if (numBits > kNumAlignBits) if (numBits > kNumAlignBits)
@@ -835,8 +842,12 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
PpmEscChar = 2; PpmEscChar = 2;
PpmError = true; PpmError = true;
InitFilters(); InitFilters();
_errorMode = false;
} }
if (_errorMode)
return S_FALSE;
if (!m_IsSolid || !TablesRead) if (!m_IsSolid || !TablesRead)
{ {
bool keepDecompressing; bool keepDecompressing;
@@ -915,8 +926,8 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream
_unpackSize = outSize ? *outSize : (UInt64)(Int64)-1; _unpackSize = outSize ? *outSize : (UInt64)(Int64)-1;
return CodeReal(progress); return CodeReal(progress);
} }
catch(const CInBufferException &e) { return e.ErrorCode; } catch(const CInBufferException &e) { _errorMode = true; return e.ErrorCode; }
catch(...) { return S_FALSE; } catch(...) { _errorMode = true; return S_FALSE; }
// CNewException is possible here. But probably CNewException is caused // CNewException is possible here. But probably CNewException is caused
// by error in data stream. // by error in data stream.
} }

View File

@@ -31,7 +31,7 @@ const UInt32 kLenTableSize = 28;
const UInt32 kMainTableSize = 256 + 1 + 1 + 1 + kNumReps + kNumLen2Symbols + kLenTableSize; const UInt32 kMainTableSize = 256 + 1 + 1 + 1 + kNumReps + kNumLen2Symbols + kLenTableSize;
const UInt32 kDistTableSize = 60; const UInt32 kDistTableSize = 60;
const int kNumAlignBits = 4; const unsigned kNumAlignBits = 4;
const UInt32 kAlignTableSize = (1 << kNumAlignBits) + 1; const UInt32 kAlignTableSize = (1 << kNumAlignBits) + 1;
const UInt32 kLevelTableSize = 20; const UInt32 kLevelTableSize = 20;
@@ -158,7 +158,7 @@ struct CTempFilter: public NVm::CProgramInitState
} }
}; };
const int kNumHuffmanBits = 15; const unsigned kNumHuffmanBits = 15;
class CDecoder: class CDecoder:
public ICompressCoder, public ICompressCoder,
@@ -192,6 +192,7 @@ class CDecoder:
UInt32 _lastFilter; UInt32 _lastFilter;
bool m_IsSolid; bool m_IsSolid;
bool _errorMode;
bool _lzMode; bool _lzMode;
bool _unsupportedFilter; bool _unsupportedFilter;
@@ -209,7 +210,7 @@ class CDecoder:
HRESULT WriteDataToStream(const Byte *data, UInt32 size); HRESULT WriteDataToStream(const Byte *data, UInt32 size);
HRESULT WriteData(const Byte *data, UInt32 size); HRESULT WriteData(const Byte *data, UInt32 size);
HRESULT WriteArea(UInt32 startPtr, UInt32 endPtr); HRESULT WriteArea(UInt32 startPtr, UInt32 endPtr);
void ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef); void ExecuteFilter(unsigned tempFilterIndex, NVm::CBlockRef &outBlockRef);
HRESULT WriteBuf(); HRESULT WriteBuf();
void InitFilters(); void InitFilters();
@@ -217,7 +218,7 @@ class CDecoder:
bool ReadVmCodeLZ(); bool ReadVmCodeLZ();
bool ReadVmCodePPM(); bool ReadVmCodePPM();
UInt32 ReadBits(int numBits); UInt32 ReadBits(unsigned numBits);
HRESULT InitPPM(); HRESULT InitPPM();
int DecodePpmSymbol(); int DecodePpmSymbol();

View File

@@ -421,7 +421,7 @@ HRESULT CDecoder::ReadTables(CBitDecoder &_bitStream)
Byte lens[kTablesSizesSum]; Byte lens[kTablesSizesSum];
unsigned i = 0; unsigned i = 0;
while (i < kTablesSizesSum) do
{ {
if (_bitStream._buf >= _bitStream._bufCheck2) if (_bitStream._buf >= _bitStream._bufCheck2)
{ {
@@ -439,34 +439,24 @@ HRESULT CDecoder::ReadTables(CBitDecoder &_bitStream)
return S_FALSE; return S_FALSE;
else else
{ {
sym -= 16; unsigned num = ((sym - 16) & 1) * 4;
unsigned sh = ((sym & 1) << 2); num += num + 3 + (unsigned)_bitStream.ReadBits9(num + 3);
unsigned num = (unsigned)_bitStream.ReadBits9(3 + sh) + 3 + (sh << 1);
num += i; num += i;
if (num > kTablesSizesSum) if (num > kTablesSizesSum)
num = kTablesSizesSum; num = kTablesSizesSum;
Byte v = 0;
if (sym < 2) if (sym < 16 + 2)
{ {
if (i == 0) if (i == 0)
{ return S_FALSE;
// return S_FALSE; v = lens[(size_t)i - 1];
continue; // original unRAR
}
Byte v = lens[(size_t)i - 1];
do
lens[i++] = v;
while (i < num);
}
else
{
do
lens[i++] = 0;
while (i < num);
} }
do
lens[i++] = v;
while (i < num);
} }
} }
while (i < kTablesSizesSum);
if (_bitStream.IsBlockOverRead()) if (_bitStream.IsBlockOverRead())
return S_FALSE; return S_FALSE;

View File

@@ -13,6 +13,7 @@
namespace NCompress { namespace NCompress {
namespace NShrink { namespace NShrink {
static const UInt32 kEmpty = 256; // kNumItems;
static const UInt32 kBufferSize = (1 << 18); static const UInt32 kBufferSize = (1 << 18);
static const unsigned kNumMinBits = 9; static const unsigned kNumMinBits = 9;
@@ -34,20 +35,15 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
outBuffer.Init(); outBuffer.Init();
{ {
unsigned i; for (unsigned i = 0; i < kNumItems; i++)
for (i = 0; i < 257; i++) _parents[i] = kEmpty;
_parents[i] = (UInt16)i;
for (; i < kNumItems; i++)
_parents[i] = kNumItems;
for (i = 0; i < kNumItems; i++)
_suffixes[i] = 0;
} }
UInt64 prevPos = 0, inPrev = 0; UInt64 outPrev = 0, inPrev = 0;
unsigned numBits = kNumMinBits; unsigned numBits = kNumMinBits;
unsigned head = 257; unsigned head = 257;
int lastSym = -1; int lastSym = -1;
Byte lastChar2 = 0; Byte lastChar = 0;
bool moreOut = false; bool moreOut = false;
HRESULT res = S_FALSE; HRESULT res = S_FALSE;
@@ -67,18 +63,22 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
break; break;
} }
eofCheck = true; eofCheck = true;
// Is specSym(=256) allowed after end of stream // Is specSym(=256) allowed after end of stream ?
// Do we need to read it here // Do we need to read it here ?
} }
if (progress) if (progress)
{ {
if (nowPos - prevPos >= (1 << 18) if (nowPos - outPrev >= (1 << 20) || _inProcessed - inPrev >= (1 << 20))
|| _inProcessed - inPrev >= (1 << 20))
{ {
prevPos = nowPos; outPrev = nowPos;
inPrev = _inProcessed; inPrev = _inProcessed;
RINOK(progress->SetRatioInfo(&_inProcessed, &nowPos)); res = progress->SetRatioInfo(&_inProcessed, &nowPos);
if (res != SZ_OK)
{
// break;
return res;
}
} }
} }
@@ -105,23 +105,30 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
continue; continue;
} }
if (sym != 2) if (sym != 2)
break;
{ {
break;
// continue; // info-zip just ignores such code
}
{
/*
---------- Free leaf nodes ----------
Note : that code can mark _parents[lastSym] as free, and next
inserted node will be Orphan in that case.
*/
unsigned i; unsigned i;
for (i = 257; i < kNumItems; i++) for (i = 256; i < kNumItems; i++)
_stack[i] = 0; _stack[i] = 0;
for (i = 257; i < kNumItems; i++) for (i = 257; i < kNumItems; i++)
{ {
unsigned par = _parents[i]; unsigned par = _parents[i];
if (par != kNumItems) if (par != kEmpty)
_stack[par] = 1; _stack[par] = 1;
} }
for (i = 257; i < kNumItems; i++) for (i = 257; i < kNumItems; i++)
if (_stack[i] == 0) if (_stack[i] == 0)
_parents[i] = kNumItems; _parents[i] = kEmpty;
head = 257; head = 257;
continue; continue;
} }
} }
@@ -137,27 +144,22 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
bool needPrev = false; bool needPrev = false;
if (head < kNumItems && lastSym >= 0) if (head < kNumItems && lastSym >= 0)
{ {
while (head < kNumItems && _parents[head] != kNumItems) while (head < kNumItems && _parents[head] != kEmpty)
head++; head++;
if (head < kNumItems) if (head < kNumItems)
{ {
if (head == (unsigned)lastSym) /*
{ if (head == lastSym), it updates Orphan to self-linked Orphan and creates two problems:
// we need to fix the code for that case 1) we must check _stack[i++] overflow in code that walks tree nodes.
// _parents[head] is not allowed to link to itself 2) self-linked node can not be removed. So such self-linked nodes can occupy all _parents items.
res = E_NOTIMPL; */
break;
}
needPrev = true; needPrev = true;
_parents[head] = (UInt16)lastSym; _parents[head] = (UInt16)lastSym;
_suffixes[head] = (Byte)lastChar2; _suffixes[head] = (Byte)lastChar;
head++; head++;
} }
} }
if (_parents[sym] == kNumItems)
break;
lastSym = sym; lastSym = sym;
unsigned cur = sym; unsigned cur = sym;
unsigned i = 0; unsigned i = 0;
@@ -166,10 +168,17 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
{ {
_stack[i++] = _suffixes[cur]; _stack[i++] = _suffixes[cur];
cur = _parents[cur]; cur = _parents[cur];
// don't change that code:
// Orphan Check and self-linked Orphan check (_stack overflow check);
if (cur == kEmpty || i >= kNumItems)
break;
} }
if (cur == kEmpty || i >= kNumItems)
break;
_stack[i++] = (Byte)cur; _stack[i++] = (Byte)cur;
lastChar2 = (Byte)cur; lastChar = (Byte)cur;
if (needPrev) if (needPrev)
_suffixes[(size_t)head - 1] = (Byte)cur; _suffixes[(size_t)head - 1] = (Byte)cur;

View File

@@ -19,8 +19,8 @@ class CDecoder :
public ICompressGetInStreamProcessedSize, public ICompressGetInStreamProcessedSize,
public CMyUnknownImp public CMyUnknownImp
{ {
UInt64 _inProcessed;
bool _fullStreamMode; bool _fullStreamMode;
UInt64 _inProcessed;
UInt16 _parents[kNumItems]; UInt16 _parents[kNumItems];
Byte _suffixes[kNumItems]; Byte _suffixes[kNumItems];

View File

@@ -162,8 +162,9 @@ void CDecoder::Hmac_Convert_32Bytes(Byte *data) const
}; };
static CKey g_Key;
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
static CKey g_Key;
static NWindows::NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection; static NWindows::NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection;
#define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection); #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection);
#else #else

View File

@@ -1507,11 +1507,18 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices,
#endif #endif
HRESULT result = _agentSpec->GetArchive()->Extract(&realIndices.Front(), {
realIndices.Size(), testMode, extractCallback); CArchiveExtractCallback_Closer ecsCloser(extractCallbackSpec);
if (result == S_OK)
result = extractCallbackSpec->SetDirsTimes(); HRESULT res = _agentSpec->GetArchive()->Extract(&realIndices.Front(),
return result; realIndices.Size(), testMode, extractCallback);
HRESULT res2 = ecsCloser.Close();
if (res == S_OK)
res = res2;
return res;
}
COM_TRY_END COM_TRY_END
} }

View File

@@ -124,6 +124,7 @@ enum Enum
kTechMode, kTechMode,
kShareForWrite, kShareForWrite,
kStopAfterOpenError,
kCaseSensitive, kCaseSensitive,
kArcNameMode, kArcNameMode,
@@ -245,6 +246,7 @@ static const CSwitchForm kSwitchForms[] =
{ "slt" }, { "slt" },
{ "ssw" }, { "ssw" },
{ "sse" },
{ "ssc", NSwitchType::kMinus }, { "ssc", NSwitchType::kMinus },
{ "sa", NSwitchType::kChar, false, 1, k_ArcNameMode_PostCharSet }, { "sa", NSwitchType::kChar, false, 1, k_ArcNameMode_PostCharSet },
@@ -1299,6 +1301,8 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
if (parser[NKey::kShareForWrite].ThereIs) if (parser[NKey::kShareForWrite].ThereIs)
updateOptions.OpenShareForWrite = true; updateOptions.OpenShareForWrite = true;
if (parser[NKey::kStopAfterOpenError].ThereIs)
updateOptions.StopAfterOpenError = true;
updateOptions.PathMode = censorPathMode; updateOptions.PathMode = censorPathMode;

View File

@@ -182,6 +182,7 @@ HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *r
#endif #endif
CArchiveExtractCallback::CArchiveExtractCallback(): CArchiveExtractCallback::CArchiveExtractCallback():
_arc(NULL),
WriteCTime(true), WriteCTime(true),
WriteATime(true), WriteATime(true),
WriteMTime(true), WriteMTime(true),
@@ -205,8 +206,8 @@ void CArchiveExtractCallback::Init(
const UStringVector &removePathParts, bool removePartsForAltStreams, const UStringVector &removePathParts, bool removePartsForAltStreams,
UInt64 packSize) UInt64 packSize)
{ {
_extractedFolderPaths.Clear(); ClearExtractedDirsInfo();
_extractedFolderIndices.Clear(); _outFileStream.Release();
#ifdef SUPPORT_LINKS #ifdef SUPPORT_LINKS
_hardLinks.Clear(); _hardLinks.Clear();
@@ -368,7 +369,7 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat
} }
} }
HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined) HRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined)
{ {
filetimeIsDefined = false; filetimeIsDefined = false;
NCOM::CPropVariant prop; NCOM::CPropVariant prop;
@@ -734,7 +735,8 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
return E_FAIL; return E_FAIL;
UString s; UString s;
CReparseAttr reparse; CReparseAttr reparse;
isOkReparse = reparse.Parse((const Byte *)data, dataSize); DWORD errorCode = 0;
isOkReparse = reparse.Parse((const Byte *)data, dataSize, errorCode);
if (isOkReparse) if (isOkReparse)
{ {
isHardLink = false; isHardLink = false;
@@ -1270,7 +1272,8 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
if (FillLinkData(data, fs2us(existPath), !isJunction)) if (FillLinkData(data, fs2us(existPath), !isJunction))
{ {
CReparseAttr attr; CReparseAttr attr;
if (!attr.Parse(data, data.Size())) DWORD errorCode = 0;
if (!attr.Parse(data, data.Size(), errorCode))
{ {
RINOK(SendMessageError("Internal error for symbolic link file", us2fs(_item.Path))); RINOK(SendMessageError("Internal error for symbolic link file", us2fs(_item.Path)));
// return E_FAIL; // return E_FAIL;
@@ -1447,6 +1450,33 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
} }
HRESULT CArchiveExtractCallback::CloseFile()
{
if (!_outFileStream)
return S_OK;
HRESULT hres = S_OK;
_outFileStreamSpec->SetTime(
(WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,
(WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,
(WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
const UInt64 processedSize = _outFileStreamSpec->ProcessedSize;
if (_fileLengthWasSet && _curSize > processedSize)
{
bool res = _outFileStreamSpec->File.SetLength(processedSize);
_fileLengthWasSet = res;
if (!res)
hres = SendMessageError_with_LastError(kCantSetFileLen, us2fs(_item.Path));
}
_curSize = processedSize;
_curSizeDefined = true;
RINOK(_outFileStreamSpec->Close());
_outFileStream.Release();
return hres;
}
STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes) STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
@@ -1475,27 +1505,7 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
#endif #endif
if (_outFileStream) RINOK(CloseFile());
{
HRESULT hres = S_OK;
_outFileStreamSpec->SetTime(
(WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,
(WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,
(WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
const UInt64 processedSize = _outFileStreamSpec->ProcessedSize;
if (_fileLengthWasSet && _curSize > processedSize)
{
bool res = _outFileStreamSpec->File.SetLength(processedSize);
_fileLengthWasSet = res;
if (!res)
hres = SendMessageError_with_LastError(kCantSetFileLen, us2fs(_item.Path));
}
_curSize = processedSize;
_curSizeDefined = true;
RINOK(_outFileStreamSpec->Close());
_outFileStream.Release();
RINOK(hres);
}
#ifdef _USE_SECURITY_CODE #ifdef _USE_SECURITY_CODE
if (!_stdOutMode && _extractMode && _ntOptions.NtSecurity.Val && _arc->GetRawProps) if (!_stdOutMode && _extractMode && _ntOptions.NtSecurity.Val && _arc->GetRawProps)
@@ -1620,8 +1630,12 @@ static unsigned GetNumSlashes(const FChar *s)
} }
} }
HRESULT CArchiveExtractCallback::SetDirsTimes() HRESULT CArchiveExtractCallback::SetDirsTimes()
{ {
if (!_arc)
return S_OK;
CRecordVector<CExtrRefSortPair> pairs; CRecordVector<CExtrRefSortPair> pairs;
pairs.ClearAndSetSize(_extractedFolderPaths.Size()); pairs.ClearAndSetSize(_extractedFolderPaths.Size());
unsigned i; unsigned i;
@@ -1637,8 +1651,8 @@ HRESULT CArchiveExtractCallback::SetDirsTimes()
for (i = 0; i < pairs.Size(); i++) for (i = 0; i < pairs.Size(); i++)
{ {
int pairIndex = pairs[i].Index; unsigned pairIndex = pairs[i].Index;
int index = _extractedFolderIndices[pairIndex]; UInt32 index = _extractedFolderIndices[pairIndex];
FILETIME CTime; FILETIME CTime;
FILETIME ATime; FILETIME ATime;
@@ -1658,5 +1672,18 @@ HRESULT CArchiveExtractCallback::SetDirsTimes()
(WriteATime && ATimeDefined) ? &ATime : NULL, (WriteATime && ATimeDefined) ? &ATime : NULL,
(WriteMTime && MTimeDefined) ? &MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL)); (WriteMTime && MTimeDefined) ? &MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
} }
ClearExtractedDirsInfo();
return S_OK; return S_OK;
} }
HRESULT CArchiveExtractCallback::CloseArc()
{
HRESULT res = CloseFile();
HRESULT res2 = SetDirsTimes();
if (res == S_OK)
res = res2;
_arc = NULL;
return res;
}

View File

@@ -249,7 +249,7 @@ class CArchiveExtractCallback:
#endif #endif
void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath); void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath);
HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); HRESULT GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);
HRESULT GetUnpackSize(); HRESULT GetUnpackSize();
HRESULT SendMessageError(const char *message, const FString &path); HRESULT SendMessageError(const char *message, const FString &path);
@@ -343,9 +343,44 @@ public:
} }
#endif #endif
HRESULT CloseArc();
private:
void ClearExtractedDirsInfo()
{
_extractedFolderPaths.Clear();
_extractedFolderIndices.Clear();
}
HRESULT CloseFile();
HRESULT SetDirsTimes(); HRESULT SetDirsTimes();
}; };
struct CArchiveExtractCallback_Closer
{
CArchiveExtractCallback *_ref;
CArchiveExtractCallback_Closer(CArchiveExtractCallback *ref): _ref(ref) {}
HRESULT Close()
{
HRESULT res = S_OK;
if (_ref)
{
res = _ref->CloseArc();
_ref = NULL;
}
return res;
}
~CArchiveExtractCallback_Closer()
{
Close();
}
};
bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item); bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);
#endif #endif

View File

@@ -386,15 +386,27 @@ HRESULT CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi,
return S_OK; return S_OK;
const FString path = phyPrefix + fi.Name; const FString path = phyPrefix + fi.Name;
CByteBuffer &buf = dirItem.ReparseData; CByteBuffer &buf = dirItem.ReparseData;
DWORD res = 0;
if (NIO::GetReparseData(path, buf)) if (NIO::GetReparseData(path, buf))
{ {
CReparseAttr attr; CReparseAttr attr;
if (attr.Parse(buf, buf.Size())) if (attr.Parse(buf, buf.Size(), res))
return S_OK; return S_OK;
// we ignore unknown reparse points
if (res != ERROR_INVALID_REPARSE_DATA)
res = 0;
} }
DWORD res = ::GetLastError(); else
{
res = ::GetLastError();
if (res == 0)
res = ERROR_INVALID_FUNCTION;
}
buf.Free(); buf.Free();
return AddError(path , res); if (res == 0)
return S_OK;
return AddError(path, res);
} }
#endif #endif
@@ -865,7 +877,8 @@ void CDirItems::FillFixedReparse()
continue; continue;
CReparseAttr attr; CReparseAttr attr;
if (!attr.Parse(item.ReparseData, item.ReparseData.Size())) DWORD errorCode = 0;
if (!attr.Parse(item.ReparseData, item.ReparseData.Size(), errorCode))
continue; continue;
if (attr.IsRelative()) if (attr.IsRelative())
continue; continue;

View File

@@ -197,6 +197,9 @@ static HRESULT DecompressArchive(
HRESULT result; HRESULT result;
Int32 testMode = (options.TestMode && !calcCrc) ? 1: 0; Int32 testMode = (options.TestMode && !calcCrc) ? 1: 0;
CArchiveExtractCallback_Closer ecsCloser(ecs);
if (options.StdInMode) if (options.StdInMode)
{ {
result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, ecs); result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, ecs);
@@ -206,8 +209,11 @@ static HRESULT DecompressArchive(
} }
else else
result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, ecs); result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, ecs);
if (result == S_OK && !options.StdInMode)
result = ecs->SetDirsTimes(); HRESULT res2 = ecsCloser.Close();
if (result == S_OK)
result = res2;
return callback->ExtractResult(result); return callback->ExtractResult(result);
} }

View File

@@ -224,7 +224,6 @@ static inline void AddHexToString(AString &res, unsigned v)
{ {
res += (char)GetHex(v >> 4); res += (char)GetHex(v >> 4);
res += (char)GetHex(v & 0xF); res += (char)GetHex(v & 0xF);
res += ' ';
} }
/* /*
@@ -269,6 +268,14 @@ struct CSecID2Name
const char *sz; const char *sz;
}; };
static int FindPairIndex(const CSecID2Name * pairs, unsigned num, UInt32 id)
{
for (unsigned i = 0; i < num; i++)
if (pairs[i].n == id)
return i;
return -1;
}
static const CSecID2Name sid_32_Names[] = static const CSecID2Name sid_32_Names[] =
{ {
{ 544, "Administrators" }, { 544, "Administrators" },
@@ -359,22 +366,22 @@ static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize)
if (v0 == 32 && num == 2) if (v0 == 32 && num == 2)
{ {
UInt32 v1 = Get32(p + 12); UInt32 v1 = Get32(p + 12);
for (unsigned i = 0; i < ARRAY_SIZE(sid_32_Names); i++) int index = FindPairIndex(sid_32_Names, ARRAY_SIZE(sid_32_Names), v1);
if (sid_32_Names[i].n == v1) if (index >= 0)
{ {
s += sid_32_Names[i].sz; s += sid_32_Names[index].sz;
return; return;
} }
} }
if (v0 == 21 && num == 5) if (v0 == 21 && num == 5)
{ {
UInt32 v4 = Get32(p + 8 + 4 * 4); UInt32 v4 = Get32(p + 8 + 4 * 4);
for (unsigned i = 0; i < ARRAY_SIZE(sid_21_Names); i++) int index = FindPairIndex(sid_21_Names, ARRAY_SIZE(sid_21_Names), v4);
if (sid_21_Names[i].n == v4) if (index >= 0)
{ {
s += sid_21_Names[i].sz; s += sid_21_Names[index].sz;
return; return;
} }
} }
if (v0 == 80 && num == 6) if (v0 == 80 && num == 6)
{ {
@@ -419,20 +426,13 @@ static void ParseOwner(AString &s, const Byte *p, UInt32 size, UInt32 pos)
ParseSid(s, p + pos, size - pos, sidSize); ParseSid(s, p + pos, size - pos, sidSize);
} }
static void AddUInt32ToString(AString &s, UInt32 val)
{
char sz[16];
ConvertUInt32ToString(val, sz);
s += sz;
}
static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName, UInt32 flags, UInt32 offset) static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName, UInt32 flags, UInt32 offset)
{ {
UInt32 control = Get16(p + 2); UInt32 control = Get16(p + 2);
if ((flags & control) == 0) if ((flags & control) == 0)
return; return;
UInt32 pos = Get32(p + offset); UInt32 pos = Get32(p + offset);
s += ' '; s.Add_Space();
s += strName; s += strName;
if (pos >= size) if (pos >= size)
return; return;
@@ -443,7 +443,7 @@ static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName
if (Get16(p) != 2) // revision if (Get16(p) != 2) // revision
return; return;
UInt32 num = Get32(p + 4); UInt32 num = Get32(p + 4);
AddUInt32ToString(s, num); s.Add_UInt32(num);
/* /*
UInt32 aclSize = Get16(p + 2); UInt32 aclSize = Get16(p + 2);
@@ -466,7 +466,7 @@ static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName
size -= 8; size -= 8;
UInt32 sidSize = 0; UInt32 sidSize = 0;
s += ' '; s.Add_Space();
ParseSid(s, p, size, sidSize); ParseSid(s, p, size, sidSize);
if (sidSize == 0) if (sidSize == 0)
return; return;
@@ -508,12 +508,12 @@ void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s)
return; return;
} }
ParseOwner(s, data, size, Get32(data + 4)); ParseOwner(s, data, size, Get32(data + 4));
s += ' '; s.Add_Space();
ParseOwner(s, data, size, Get32(data + 8)); ParseOwner(s, data, size, Get32(data + 8));
ParseAcl(s, data, size, "s:", MY_SE_SACL_PRESENT, 12); ParseAcl(s, data, size, "s:", MY_SE_SACL_PRESENT, 12);
ParseAcl(s, data, size, "d:", MY_SE_DACL_PRESENT, 16); ParseAcl(s, data, size, "d:", MY_SE_DACL_PRESENT, 16);
s += ' '; s.Add_Space();
AddUInt32ToString(s, size); s.Add_UInt32(size);
// s += '\n'; // s += '\n';
// s += Data_To_Hex(data, size); // s += Data_To_Hex(data, size);
} }
@@ -567,11 +567,38 @@ bool CheckNtSecure(const Byte *data, UInt32 size) throw()
#endif #endif
// IO_REPARSE_TAG_*
static const CSecID2Name k_ReparseTags[] =
{
{ 0xA0000003, "MOUNT_POINT" },
{ 0xC0000004, "HSM" },
{ 0x80000005, "DRIVE_EXTENDER" },
{ 0x80000006, "HSM2" },
{ 0x80000007, "SIS" },
{ 0x80000008, "WIM" },
{ 0x80000009, "CSV" },
{ 0x8000000A, "DFS" },
{ 0x8000000B, "FILTER_MANAGER" },
{ 0xA000000C, "SYMLINK" },
{ 0xA0000010, "IIS_CACHE" },
{ 0x80000012, "DFSR" },
{ 0x80000013, "DEDUP" },
{ 0xC0000014, "APPXSTRM" },
{ 0x80000014, "NFS" },
{ 0x80000015, "FILE_PLACEHOLDER" },
{ 0x80000016, "DFM" },
{ 0x80000017, "WOF" }
};
bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s) bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s)
{ {
s.Empty(); s.Empty();
NFile::CReparseAttr attr; NFile::CReparseAttr attr;
if (attr.Parse(data, size)) DWORD errorCode = 0;
if (attr.Parse(data, size, errorCode))
{ {
if (!attr.IsSymLink()) if (!attr.IsSymLink())
s += "Junction: "; s += "Junction: ";
@@ -593,19 +620,48 @@ bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s)
if (Get16(data + 6) != 0) // padding if (Get16(data + 6) != 0) // padding
return false; return false;
char hex[16]; /*
ConvertUInt32ToHex8Digits(tag, hex); #define _my_IO_REPARSE_TAG_DEDUP (0x80000013L)
s += hex; if (tag == _my_IO_REPARSE_TAG_DEDUP)
s.Add_Space();
data += 8;
for (UInt32 i = 0; i < len; i++)
{ {
unsigned b = ((const Byte *)data)[i];
s += (char)GetHex((b >> 4) & 0xF);
s += (char)GetHex(b & 0xF);
} }
*/
{
int index = FindPairIndex(k_ReparseTags, ARRAY_SIZE(k_ReparseTags), tag);
if (index >= 0)
s += k_ReparseTags[index].sz;
else
{
s += "REPARSE:";
char hex[16];
ConvertUInt32ToHex8Digits(tag, hex);
s += hex;
}
}
s += ":";
s.Add_UInt32(len);
if (len != 0)
{
s.Add_Space();
data += 8;
for (UInt32 i = 0; i < len; i++)
{
if (i >= 8)
{
s += "...";
break;
}
unsigned b = data[i];
s += (char)GetHex((b >> 4) & 0xF);
s += (char)GetHex(b & 0xF);
}
}
return true; return true;
} }

View File

@@ -735,6 +735,7 @@ static HRESULT Compress(
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec); CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
updateCallbackSpec->ShareForWrite = options.OpenShareForWrite; updateCallbackSpec->ShareForWrite = options.OpenShareForWrite;
updateCallbackSpec->StopAfterOpenError = options.StopAfterOpenError;
updateCallbackSpec->StdInMode = options.StdInMode; updateCallbackSpec->StdInMode = options.StdInMode;
updateCallbackSpec->Callback = callback; updateCallbackSpec->Callback = callback;

View File

@@ -92,6 +92,7 @@ struct CUpdateOptions
FString SfxModule; FString SfxModule;
bool OpenShareForWrite; bool OpenShareForWrite;
bool StopAfterOpenError;
bool StdInMode; bool StdInMode;
UString StdInFileName; UString StdInFileName;
@@ -127,6 +128,7 @@ struct CUpdateOptions
EMailMode(false), EMailMode(false),
EMailRemoveAfter(false), EMailRemoveAfter(false),
OpenShareForWrite(false), OpenShareForWrite(false),
StopAfterOpenError(false),
ArcNameMode(k_ArcNameMode_Smart), ArcNameMode(k_ArcNameMode_Smart),
PathMode(NWildcard::k_RelatPath), PathMode(NWildcard::k_RelatPath),

View File

@@ -55,6 +55,7 @@ CArchiveUpdateCallback::CArchiveUpdateCallback():
Comment(NULL), Comment(NULL),
ShareForWrite(false), ShareForWrite(false),
StopAfterOpenError(false),
StdInMode(false), StdInMode(false),
KeepOriginalItemNames(false), KeepOriginalItemNames(false),
@@ -346,7 +347,8 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
// if (di.IsDir()) // if (di.IsDir())
{ {
CReparseAttr attr; CReparseAttr attr;
if (attr.Parse(di.ReparseData, di.ReparseData.Size())) DWORD errorCode = 0;
if (attr.Parse(di.ReparseData, di.ReparseData.Size(), errorCode))
{ {
UString simpleName = attr.GetPath(); UString simpleName = attr.GetPath();
if (attr.IsRelative()) if (attr.IsRelative())
@@ -512,7 +514,12 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStrea
#endif #endif
if (!inStreamSpec->OpenShared(path, ShareForWrite)) if (!inStreamSpec->OpenShared(path, ShareForWrite))
{ {
return Callback->OpenFileError(path, ::GetLastError()); DWORD error = ::GetLastError();
HRESULT hres = Callback->OpenFileError(path, error);
if (StopAfterOpenError)
if (hres == S_OK || hres == S_FALSE)
return HRESULT_FROM_WIN32(error);
return hres;
} }
if (StoreHardLinks) if (StoreHardLinks)

View File

@@ -136,6 +136,7 @@ public:
const UString *Comment; const UString *Comment;
bool ShareForWrite; bool ShareForWrite;
bool StopAfterOpenError;
bool StdInMode; bool StdInMode;
bool KeepOriginalItemNames; bool KeepOriginalItemNames;

View File

@@ -95,6 +95,16 @@ void PrintSize_bytes_Smart(AString &s, UInt64 val)
s += ')'; s += ')';
} }
void PrintSize_bytes_Smart_comma(AString &s, UInt64 val)
{
if (val == (UInt64)(Int64)-1)
return;
s += ", ";
PrintSize_bytes_Smart(s, val);
}
void Print_DirItemsStat(AString &s, const CDirItemsStat &st) void Print_DirItemsStat(AString &s, const CDirItemsStat &st)
{ {
if (st.NumDirs != 0) if (st.NumDirs != 0)
@@ -103,14 +113,12 @@ void Print_DirItemsStat(AString &s, const CDirItemsStat &st)
s += ", "; s += ", ";
} }
Print_UInt64_and_String(s, st.NumFiles, st.NumFiles == 1 ? "file" : "files"); Print_UInt64_and_String(s, st.NumFiles, st.NumFiles == 1 ? "file" : "files");
s += ", "; PrintSize_bytes_Smart_comma(s, st.FilesSize);
PrintSize_bytes_Smart(s, st.FilesSize);
if (st.NumAltStreams != 0) if (st.NumAltStreams != 0)
{ {
s.Add_LF(); s.Add_LF();
Print_UInt64_and_String(s, st.NumAltStreams, "alternate streams"); Print_UInt64_and_String(s, st.NumAltStreams, "alternate streams");
s += ", "; PrintSize_bytes_Smart_comma(s, st.AltStreamsSize);
PrintSize_bytes_Smart(s, st.AltStreamsSize);
} }
} }
@@ -244,7 +252,7 @@ static const char * const kTab = " ";
static void PrintFileInfo(CStdOutStream *_so, const wchar_t *path, const FILETIME *ft, const UInt64 *size) static void PrintFileInfo(CStdOutStream *_so, const wchar_t *path, const FILETIME *ft, const UInt64 *size)
{ {
*_so << kTab << "Path: " << path << endl; *_so << kTab << "Path: " << path << endl;
if (size) if (size && *size != (UInt64)(Int64)-1)
{ {
AString s; AString s;
PrintSize_bytes_Smart(s, *size); PrintSize_bytes_Smart(s, *size);

View File

@@ -150,6 +150,7 @@ static const char * const kHelpString =
" -spe : eliminate duplication of root folder for extract command\n" " -spe : eliminate duplication of root folder for extract command\n"
" -spf : use fully qualified file paths\n" " -spf : use fully qualified file paths\n"
" -ssc[-] : set sensitive case mode\n" " -ssc[-] : set sensitive case mode\n"
" -sse : stop archive creating, if it can't open some input file\n"
" -ssw : compress shared files\n" " -ssw : compress shared files\n"
" -stl : set archive timestamp from the most recently modified file\n" " -stl : set archive timestamp from the most recently modified file\n"
" -stm{HexMask} : set CPU thread affinity mask (hexadecimal number)\n" " -stm{HexMask} : set CPU thread affinity mask (hexadecimal number)\n"

View File

@@ -55,7 +55,8 @@ static bool GetSymLink(CFSTR path, CReparseAttr &attr)
if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize)) if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize))
return false; return false;
if (!attr.Parse(buf, returnedSize)) DWORD errorCode = 0;
if (!attr.Parse(buf, returnedSize, errorCode))
return false; return false;
CByteBuffer data2; CByteBuffer data2;
@@ -291,7 +292,8 @@ void CLinkDialog::OnButton_Link()
} }
CReparseAttr attr; CReparseAttr attr;
if (!attr.Parse(data, data.Size())) DWORD errorCode = 0;
if (!attr.Parse(data, data.Size(), errorCode))
{ {
ShowError(L"Internal conversion error"); ShowError(L"Internal conversion error");
return; return;

View File

@@ -827,7 +827,8 @@ void CPanel::OpenFolder(int index)
SetNewFolder(newFolder); SetNewFolder(newFolder);
LoadFullPath(); LoadFullPath();
RefreshListCtrl(); RefreshListCtrl();
_listView.SetItemState_Selected(_listView.GetFocusedItem()); // 17.02: fixed : now we don't select first item
// _listView.SetItemState_Selected(_listView.GetFocusedItem());
_listView.EnsureVisible(_listView.GetFocusedItem(), false); _listView.EnsureVisible(_listView.GetFocusedItem(), false);
} }

View File

@@ -702,6 +702,8 @@ void CPanel::Refresh_StatusBar()
wchar_t temp[32]; wchar_t temp[32];
ConvertUInt32ToString(indices.Size(), temp); ConvertUInt32ToString(indices.Size(), temp);
wcscat(temp, L" / ");
ConvertUInt32ToString(_selectedStatusVector.Size(), temp + wcslen(temp));
// UString s1 = MyFormatNew(g_App.LangString_N_SELECTED_ITEMS, NumberToString(indices.Size())); // UString s1 = MyFormatNew(g_App.LangString_N_SELECTED_ITEMS, NumberToString(indices.Size()));
// UString s1 = MyFormatNew(IDS_N_SELECTED_ITEMS, NumberToString(indices.Size())); // UString s1 = MyFormatNew(IDS_N_SELECTED_ITEMS, NumberToString(indices.Size()));

View File

@@ -403,82 +403,117 @@ void CPanel::EditPaste()
// InvokeSystemCommand("paste"); // InvokeSystemCommand("paste");
} }
struct CFolderPidls
{
LPITEMIDLIST parent;
CRecordVector<LPITEMIDLIST> items;
CFolderPidls(): parent(NULL) {}
~CFolderPidls()
{
FOR_VECTOR (i, items)
CoTaskMemFree(items[i]);
CoTaskMemFree(parent);
}
};
HRESULT CPanel::CreateShellContextMenu( HRESULT CPanel::CreateShellContextMenu(
const CRecordVector<UInt32> &operatedIndices, const CRecordVector<UInt32> &operatedIndices,
CMyComPtr<IContextMenu> &systemContextMenu) CMyComPtr<IContextMenu> &systemContextMenu)
{ {
systemContextMenu.Release(); systemContextMenu.Release();
UString folderPath = GetFsPath(); const UString folderPath = GetFsPath();
CMyComPtr<IShellFolder> desktopFolder; CMyComPtr<IShellFolder> desktopFolder;
RINOK(::SHGetDesktopFolder(&desktopFolder)); RINOK(::SHGetDesktopFolder(&desktopFolder));
if (!desktopFolder) if (!desktopFolder)
{ {
// ShowMessage("Failed to get Desktop folder."); // ShowMessage("Failed to get Desktop folder");
return E_FAIL; return E_FAIL;
} }
// Separate the file from the folder. CFolderPidls pidls;
// Get a pidl for the folder the file
// is located in.
LPITEMIDLIST parentPidl;
DWORD eaten; DWORD eaten;
// if (folderPath.IsEmpty()), then ParseDisplayName returns pidls of "My Computer"
RINOK(desktopFolder->ParseDisplayName( RINOK(desktopFolder->ParseDisplayName(
GetParent(), 0, (wchar_t *)(const wchar_t *)folderPath, GetParent(), NULL, (wchar_t *)(const wchar_t *)folderPath,
&eaten, &parentPidl, 0)); &eaten, &pidls.parent, NULL));
/*
STRRET pName;
res = desktopFolder->GetDisplayNameOf(pidls.parent, SHGDN_NORMAL, &pName);
WCHAR dir[MAX_PATH];
if (!SHGetPathFromIDListW(pidls.parent, dir))
dir[0] = 0;
*/
if (!pidls.parent)
return E_FAIL;
if (operatedIndices.IsEmpty())
{
// how to get IContextMenu, if there are no selected files?
return E_FAIL;
/*
xp64 :
1) we can't use GetUIObjectOf() with (numItems == 0), it throws exception
2) we can't use desktopFolder->GetUIObjectOf() with absolute pidls of folder
context menu items are different in that case:
"Open / Explorer" for folder
"Delete" for "My Computer" icon
"Preperties" for "System"
*/
/*
parentFolder = desktopFolder;
pidls.items.AddInReserved(pidls.parent);
pidls.parent = NULL;
*/
// CreateViewObject() doesn't show all context menu items
/*
HRESULT res = parentFolder->CreateViewObject(
GetParent(), IID_IContextMenu, (void**)&systemContextMenu);
*/
}
// Get an IShellFolder for the folder
// the file is located in.
CMyComPtr<IShellFolder> parentFolder; CMyComPtr<IShellFolder> parentFolder;
RINOK(desktopFolder->BindToObject(parentPidl, RINOK(desktopFolder->BindToObject(pidls.parent,
0, IID_IShellFolder, (void**)&parentFolder)); NULL, IID_IShellFolder, (void**)&parentFolder));
if (!parentFolder) if (!parentFolder)
{ {
// ShowMessage("Invalid file name."); // ShowMessage("Invalid file name");
return E_FAIL; return E_FAIL;
} }
// Get a pidl for the file itself. pidls.items.ClearAndReserve(operatedIndices.Size());
CRecordVector<LPITEMIDLIST> pidls;
pidls.ClearAndReserve(operatedIndices.Size());
FOR_VECTOR (i, operatedIndices) FOR_VECTOR (i, operatedIndices)
{ {
LPITEMIDLIST pidl; LPITEMIDLIST pidl;
UString fileName = GetItemRelPath2(operatedIndices[i]); const UString fileName = GetItemRelPath2(operatedIndices[i]);
RINOK(parentFolder->ParseDisplayName(GetParent(), 0, RINOK(parentFolder->ParseDisplayName(GetParent(), 0,
(wchar_t *)(const wchar_t *)fileName, &eaten, &pidl, 0)); (wchar_t *)(const wchar_t *)fileName, &eaten, &pidl, 0));
pidls.AddInReserved(pidl); pidls.items.AddInReserved(pidl);
} }
// Get IContextMenu for items
ITEMIDLIST temp; RINOK(parentFolder->GetUIObjectOf(GetParent(), pidls.items.Size(),
if (pidls.Size() == 0) (LPCITEMIDLIST *)&pidls.items.Front(), IID_IContextMenu, 0, (void**)&systemContextMenu));
if (!systemContextMenu)
{ {
temp.mkid.cb = 0; // ShowMessage("Unable to get context menu interface");
/*
LPITEMIDLIST pidl;
HRESULT result = parentFolder->ParseDisplayName(GetParent(), 0,
L"." WSTRING_PATH_SEPARATOR, &eaten, &pidl, 0);
if (result != NOERROR)
return;
*/
pidls.Add(&temp);
}
// Get the IContextMenu for the file.
CMyComPtr<IContextMenu> cm;
RINOK( parentFolder->GetUIObjectOf(GetParent(), pidls.Size(),
(LPCITEMIDLIST *)&pidls.Front(), IID_IContextMenu, 0, (void**)&cm));
if (!cm)
{
// ShowMessage("Unable to get context menu interface.");
return E_FAIL; return E_FAIL;
} }
systemContextMenu = cm;
return S_OK; return S_OK;
} }
void CPanel::CreateSystemMenu(HMENU menuSpec, void CPanel::CreateSystemMenu(HMENU menuSpec,
const CRecordVector<UInt32> &operatedIndices, const CRecordVector<UInt32> &operatedIndices,
CMyComPtr<IContextMenu> &systemContextMenu) CMyComPtr<IContextMenu> &systemContextMenu)

View File

@@ -218,6 +218,8 @@ void CPanel::InvertSelection()
FOR_VECTOR (i, _selectedStatusVector) FOR_VECTOR (i, _selectedStatusVector)
if (_selectedStatusVector[i]) if (_selectedStatusVector[i])
numSelected++; numSelected++;
// 17.02: fixed : now we invert item even, if single item is selected
/*
if (numSelected == 1) if (numSelected == 1)
{ {
int focused = _listView.GetFocusedItem(); int focused = _listView.GetFocusedItem();
@@ -229,6 +231,7 @@ void CPanel::InvertSelection()
_selectedStatusVector[realIndex] = false; _selectedStatusVector[realIndex] = false;
} }
} }
*/
} }
FOR_VECTOR (i, _selectedStatusVector) FOR_VECTOR (i, _selectedStatusVector)
_selectedStatusVector[i] = !_selectedStatusVector[i]; _selectedStatusVector[i] = !_selectedStatusVector[i];

View File

@@ -77,8 +77,6 @@ UString CVolSeqName::GetNextName()
return UnchangedPart + ChangedPart; return UnchangedPart + ChangedPart;
} }
static const UInt32 kBufSize = (1 << 20);
class CThreadSplit: public CProgressThreadVirt class CThreadSplit: public CProgressThreadVirt
{ {
HRESULT ProcessVirt(); HRESULT ProcessVirt();
@@ -89,30 +87,84 @@ public:
CRecordVector<UInt64> VolumeSizes; CRecordVector<UInt64> VolumeSizes;
}; };
class CPreAllocOutFile
{
UInt64 _preAllocSize;
public:
NIO::COutFile File;
UInt64 Written;
CPreAllocOutFile(): _preAllocSize(0), Written(0) {}
~CPreAllocOutFile()
{
SetCorrectFileLength();
}
void PreAlloc(UInt64 preAllocSize)
{
_preAllocSize = 0;
if (File.SetLength(preAllocSize))
_preAllocSize = preAllocSize;
File.SeekToBegin();
}
bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw()
{
bool res = File.Write(data, size, processedSize);
Written += processedSize;
return res;
}
void Close()
{
SetCorrectFileLength();
Written = 0;
_preAllocSize = 0;
File.Close();
}
void SetCorrectFileLength()
{
if (Written < _preAllocSize)
{
File.SetLength(Written);
_preAllocSize = 0;
}
}
};
static const UInt32 kBufSize = (1 << 20);
HRESULT CThreadSplit::ProcessVirt() HRESULT CThreadSplit::ProcessVirt()
{ {
NIO::CInFile inFile; NIO::CInFile inFile;
if (!inFile.Open(FilePath)) if (!inFile.Open(FilePath))
return GetLastError(); return GetLastError();
NIO::COutFile outFile;
CMyBuffer bufferObject; CPreAllocOutFile outFile;
if (!bufferObject.Allocate(kBufSize))
CMyBuffer buffer;
if (!buffer.Allocate(kBufSize))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
Byte *buffer = (Byte *)(void *)bufferObject;
UInt64 curVolSize = 0;
CVolSeqName seqName; CVolSeqName seqName;
seqName.SetNumDigits(NumVolumes); seqName.SetNumDigits(NumVolumes);
UInt64 length; UInt64 length;
if (!inFile.GetLength(length)) if (!inFile.GetLength(length))
return GetLastError(); return GetLastError();
CProgressSync &sync = ProgressDialog.Sync; CProgressSync &sync = ProgressDialog.Sync;
sync.Set_NumBytesTotal(length); sync.Set_NumBytesTotal(length);
UInt64 pos = 0;
UInt64 pos = 0;
UInt64 prev = 0;
UInt64 numFiles = 0; UInt64 numFiles = 0;
unsigned volIndex = 0; unsigned volIndex = 0;
for (;;) for (;;)
{ {
UInt64 volSize; UInt64 volSize;
@@ -121,46 +173,65 @@ HRESULT CThreadSplit::ProcessVirt()
else else
volSize = VolumeSizes.Back(); volSize = VolumeSizes.Back();
UInt32 needSize = (UInt32)(MyMin((UInt64)kBufSize, volSize - curVolSize)); UInt32 needSize = kBufSize;
{
const UInt64 rem = volSize - outFile.Written;
if (needSize > rem)
needSize = (UInt32)rem;
}
UInt32 processedSize; UInt32 processedSize;
if (!inFile.Read(buffer, needSize, processedSize)) if (!inFile.Read(buffer, needSize, processedSize))
return GetLastError(); return GetLastError();
if (processedSize == 0) if (processedSize == 0)
break; return S_OK;
needSize = processedSize; needSize = processedSize;
if (curVolSize == 0)
if (outFile.Written == 0)
{ {
FString name = VolBasePath; FString name = VolBasePath;
name += '.'; name += '.';
name += us2fs(seqName.GetNextName()); name += us2fs(seqName.GetNextName());
sync.Set_FilePath(fs2us(name)); sync.Set_FilePath(fs2us(name));
sync.Set_NumFilesCur(numFiles++); if (!outFile.File.Create(name, false))
if (!outFile.Create(name, false))
{ {
HRESULT res = GetLastError(); HRESULT res = GetLastError();
AddErrorPath(name); AddErrorPath(name);
return res; return res;
} }
UInt64 expectSize = volSize;
if (pos < length)
{
const UInt64 rem = length - pos;
if (expectSize > rem)
expectSize = rem;
}
outFile.PreAlloc(expectSize);
} }
if (!outFile.Write(buffer, needSize, processedSize)) if (!outFile.Write(buffer, needSize, processedSize))
return GetLastError(); return GetLastError();
if (needSize != processedSize) if (needSize != processedSize)
throw g_Message_FileWriteError; throw g_Message_FileWriteError;
curVolSize += processedSize;
if (curVolSize == volSize) pos += processedSize;
if (outFile.Written == volSize)
{ {
outFile.Close(); outFile.Close();
sync.Set_NumFilesCur(++numFiles);
if (volIndex < VolumeSizes.Size()) if (volIndex < VolumeSizes.Size())
volIndex++; volIndex++;
curVolSize = 0;
} }
pos += processedSize;
RINOK(sync.Set_NumBytesCur(pos)); if (pos - prev >= ((UInt32)1 << 22) || outFile.Written == 0)
{
RINOK(sync.Set_NumBytesCur(pos));
prev = pos;
}
} }
sync.Set_NumFilesCur(numFiles);
return S_OK;
} }
void CApp::Split() void CApp::Split()
{ {
int srcPanelIndex = GetFocusedPanelIndex(); int srcPanelIndex = GetFocusedPanelIndex();

View File

@@ -861,6 +861,7 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam)
{ {
bool isSFX = IsSFX(); bool isSFX = IsSFX();
SaveOptionsInMem(); SaveOptionsInMem();
m_Solid.ResetContent();
SetLevel(); SetLevel();
SetSolidBlockSize(); SetSolidBlockSize();
SetNumThreads(); SetNumThreads();

View File

@@ -15,11 +15,11 @@ O=O
!ENDIF !ENDIF
!IF "$(CPU)" == "AMD64" !IF "$(CPU)" == "AMD64"
MY_ML = ml64 -Dx64 MY_ML = ml64 -Dx64 -WX
!ELSEIF "$(CPU)" == "ARM" !ELSEIF "$(CPU)" == "ARM"
MY_ML = armasm MY_ML = armasm -WX
!ELSE !ELSE
MY_ML = ml MY_ML = ml -WX
!ENDIF !ENDIF
@@ -32,9 +32,9 @@ LFLAGS = $(LFLAGS) /ENTRY:mainACRTStartup
!IFNDEF NEW_COMPILER !IFNDEF NEW_COMPILER
LFLAGS = $(LFLAGS) -OPT:NOWIN98 LFLAGS = $(LFLAGS) -OPT:NOWIN98
!ENDIF !ENDIF
# !IF "$(CPU)" != "ARM" !IF "$(CPU)" != "ARM" && "$(CPU)" != "ARM64"
CFLAGS = $(CFLAGS) -Gr CFLAGS = $(CFLAGS) -Gr
# !ENDIF !ENDIF
LIBS = $(LIBS) user32.lib advapi32.lib shell32.lib LIBS = $(LIBS) user32.lib advapi32.lib shell32.lib
!ENDIF !ENDIF
@@ -82,9 +82,9 @@ LFLAGS = $(LFLAGS) /LARGEADDRESSAWARE
!IFDEF DEF_FILE !IFDEF DEF_FILE
LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE) LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE)
!ELSE !ELSE
# !IF "$(CPU)" != "ARM" !IF "$(CPU)" != "ARM" && "$(CPU)" != "ARM64"
LFLAGS = $(LFLAGS) /FIXED LFLAGS = $(LFLAGS) /FIXED
# !ENDIF !ENDIF
# /BASE:0x400000 # /BASE:0x400000
!ENDIF !ENDIF

View File

@@ -45,7 +45,11 @@ struct CReparseAttr
UString PrintName; UString PrintName;
CReparseAttr(): Tag(0), Flags(0) {} CReparseAttr(): Tag(0), Flags(0) {}
bool Parse(const Byte *p, size_t size);
// Parse()
// returns true and (errorCode = 0), if (correct MOUNT_POINT or SYMLINK)
// returns false and (errorCode = ERROR_REPARSE_TAG_MISMATCH), if not (MOUNT_POINT or SYMLINK)
bool Parse(const Byte *p, size_t size, DWORD &errorCode);
bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction
bool IsSymLink() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; } bool IsSymLink() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; }
@@ -171,7 +175,12 @@ public:
bool OpenReparse(CFSTR fileName) bool OpenReparse(CFSTR fileName)
{ {
return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, // 17.02 fix: to support Windows XP compatibility junctions:
// we use Create() with (desiredAccess = 0) instead of Open() with GENERIC_READ
return
Create(fileName, 0,
// Open(fileName,
FILE_SHARE_READ, OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS); FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS);
} }

View File

@@ -194,8 +194,9 @@ static void GetString(const Byte *p, unsigned len, UString &res)
res.ReleaseBuf_SetLen(i); res.ReleaseBuf_SetLen(i);
} }
bool CReparseAttr::Parse(const Byte *p, size_t size) bool CReparseAttr::Parse(const Byte *p, size_t size, DWORD &errorCode)
{ {
errorCode = ERROR_INVALID_REPARSE_DATA;
if (size < 8) if (size < 8)
return false; return false;
Tag = Get32(p); Tag = Get32(p);
@@ -209,8 +210,10 @@ bool CReparseAttr::Parse(const Byte *p, size_t size)
*/ */
if (Tag != _my_IO_REPARSE_TAG_MOUNT_POINT && if (Tag != _my_IO_REPARSE_TAG_MOUNT_POINT &&
Tag != _my_IO_REPARSE_TAG_SYMLINK) Tag != _my_IO_REPARSE_TAG_SYMLINK)
// return true; {
errorCode = ERROR_REPARSE_TAG_MISMATCH; // ERROR_REPARSE_TAG_INVALID
return false; return false;
}
if (Get16(p + 6) != 0) // padding if (Get16(p + 6) != 0) // padding
return false; return false;
@@ -247,6 +250,7 @@ bool CReparseAttr::Parse(const Byte *p, size_t size)
GetString(p + subOffs, subLen >> 1, SubsName); GetString(p + subOffs, subLen >> 1, SubsName);
GetString(p + printOffs, printLen >> 1, PrintName); GetString(p + printOffs, printLen >> 1, PrintName);
errorCode = 0;
return true; return true;
} }

View File

@@ -10,8 +10,8 @@ AppName = "7-Zip"
InstallDir = %CE1%\%AppName% InstallDir = %CE1%\%AppName%
[Strings] [Strings]
AppVer = "17.01" AppVer = "18.00"
AppDate = "2017-08-28" AppDate = "2018-01-10"
[CEDevice] [CEDevice]
; ProcessorType = 2577 ; ARM ; ProcessorType = 2577 ; ARM

View File

@@ -1,8 +1,8 @@
;-------------------------------- ;--------------------------------
;Defines ;Defines
!define VERSION_MAJOR 17 !define VERSION_MAJOR 18
!define VERSION_MINOR 01 !define VERSION_MINOR 00
!define VERSION_POSTFIX_FULL " beta" !define VERSION_POSTFIX_FULL " beta"
!ifdef WIN64 !ifdef WIN64
!ifdef IA64 !ifdef IA64

View File

@@ -1,7 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<?define VerMajor = "17" ?> <?define VerMajor = "18" ?>
<?define VerMinor = "01" ?> <?define VerMinor = "00" ?>
<?define VerBuild = "00" ?> <?define VerBuild = "00" ?>
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?> <?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
<?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?> <?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?>

View File

@@ -3,7 +3,7 @@
License for use and distribution License for use and distribution
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7-Zip Copyright (C) 1999-2017 Igor Pavlov. 7-Zip Copyright (C) 1999-2018 Igor Pavlov.
Licenses for files are: Licenses for files are:

View File

@@ -1,9 +1,9 @@
7-Zip 17.00 beta Sources 7-Zip 18.00 beta Sources
------------------------ ------------------------
7-Zip is a file archiver for Windows. 7-Zip is a file archiver for Windows.
7-Zip Copyright (C) 1999-2017 Igor Pavlov. 7-Zip Copyright (C) 1999-2018 Igor Pavlov.
License Info License Info