diff options
Diffstat (limited to 'CPP')
135 files changed, 6140 insertions, 1944 deletions
diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp index d1a810cb..bfe1b24e 100644 --- a/CPP/7zip/Archive/7z/7zDecode.cpp +++ b/CPP/7zip/Archive/7z/7zDecode.cpp @@ -301,6 +301,12 @@ HRESULT CDecoder::Decode( { const CCoderInfo &coderInfo = folderInfo.Coders[i]; + #ifndef _SFX + // we don't support RAR codecs here + if ((coderInfo.MethodID >> 8) == 0x403) + return E_NOTIMPL; + #endif + CCreatedCoder cod; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h index 8a078e19..eb7791bc 100644 --- a/CPP/7zip/Archive/7z/7zHandler.h +++ b/CPP/7zip/Archive/7z/7zHandler.h @@ -44,6 +44,7 @@ public: UInt64 _numSolidBytes; bool _numSolidBytesDefined; bool _solidExtension; + bool _useTypeSorting; bool _compressHeaders; bool _encryptHeadersSpecified; diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp index 5cab6a82..7ece4c68 100644 --- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp +++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp @@ -508,14 +508,19 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (ui.NewData) { - NCOM::CPropVariant prop; - RINOK(updateCallback->GetProperty(i, kpidSize, &prop)); - if (prop.vt != VT_UI8) - return E_INVALIDARG; - ui.Size = (UInt64)prop.uhVal.QuadPart; - if (ui.Size != 0 && ui.IsAnti) - return E_INVALIDARG; + ui.Size = 0; + if (!ui.IsDir) + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(i, kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + ui.Size = (UInt64)prop.uhVal.QuadPart; + if (ui.Size != 0 && ui.IsAnti) + return E_INVALIDARG; + } } + updateItems.Add(ui); } @@ -613,6 +618,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt options.NumSolidFiles = _numSolidFiles; options.NumSolidBytes = _numSolidBytes; options.SolidExtension = _solidExtension; + options.UseTypeSorting = _useTypeSorting; + options.RemoveSfxBlock = _removeSfxBlock; // options.VolumeMode = _volumeMode; @@ -701,6 +708,7 @@ void COutHandler::InitProps() // _volumeMode = false; InitSolid(); + _useTypeSorting = false; } HRESULT COutHandler::SetSolidFromString(const UString &s) @@ -821,6 +829,8 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer); + if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting); + // if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode); } return CMultiMethodProps::SetProperty(name, value); diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp index e7c9ecc6..345cd627 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp @@ -554,11 +554,11 @@ static int CompareEmptyItems(const unsigned *p1, const unsigned *p2, void *param } static const char *g_Exts = - " lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar zoo" + " 7z xz lzma ace arc arj bz tbz bz2 tbz2 cab deb gz tgz ha lha lzh lzo lzx pak rar rpm sit zoo" " zip jar ear war msi" " 3gp avi mov mpeg mpg mpe wmv" " aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav" - " swf " + " swf" " chm hxi hxs" " gif jpeg jpg jp2 png tiff bmp ico psd psp" " awg ps eps cgm dxf svg vrml wmf emf ai md" @@ -569,9 +569,9 @@ static const char *g_Exts = " vmdk dsk nvram vmem vmsd vmsn vmss vmtm" " inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def" " f77 f f90 f95" - " asm sql manifest dep " - " mak clw csproj vcproj sln dsp dsw " - " class " + " asm sql manifest dep" + " mak clw csproj vcproj sln dsp dsw" + " class" " bat cmd" " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml" " awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs" @@ -580,7 +580,7 @@ static const char *g_Exts = " abw afp cwk lwp wpd wps wpt wrf wri" " abf afm bdf fon mgf otf pcf pfa snf ttf" " dbf mdb nsf ntf wdb db fdb gdb" - " exe dll ocx vbx sfx sys tlb awx com obj lib out o so " + " exe dll ocx vbx sfx sys tlb awx com obj lib out o so" " pdb pch idb ncb opt"; static unsigned GetExtIndex(const char *ext) @@ -2251,7 +2251,7 @@ HRESULT Update( continue; CRecordVector<CRefItem> refItems; refItems.ClearAndSetSize(numFiles); - bool sortByType = (numSolidFiles > 1); + bool sortByType = (options.UseTypeSorting && numSolidFiles > 1); for (i = 0; i < numFiles; i++) refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType); CSortParam sortParam; diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h index 3986af43..a7abf779 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.h +++ b/CPP/7zip/Archive/7z/7zUpdate.h @@ -97,6 +97,9 @@ struct CUpdateOptions UInt64 NumSolidFiles; UInt64 NumSolidBytes; bool SolidExtension; + + bool UseTypeSorting; + bool RemoveSfxBlock; bool MultiThreadMixer; @@ -109,6 +112,7 @@ struct CUpdateOptions NumSolidFiles((UInt64)(Int64)(-1)), NumSolidBytes((UInt64)(Int64)(-1)), SolidExtension(false), + UseTypeSorting(true), RemoveSfxBlock(false), MultiThreadMixer(true) {} diff --git a/CPP/7zip/Archive/7z/makefile b/CPP/7zip/Archive/7z/makefile index 19982112..49818371 100644 --- a/CPP/7zip/Archive/7z/makefile +++ b/CPP/7zip/Archive/7z/makefile @@ -1,5 +1,5 @@ PROG = 7z.dll -DEF_FILE = ../../Archive/Archive2.def +DEF_FILE = ../Archive.def CFLAGS = $(CFLAGS) \ -DEXTERNAL_CODECS \ @@ -60,9 +60,11 @@ WIN_OBJS = \ $O\StreamUtils.obj \ $O\VirtThread.obj \ +COMPRESS_OBJS = \ + $O\CopyCoder.obj \ + AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ - $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ @@ -76,4 +78,6 @@ C_OBJS = \ $O\CpuArch.obj \ $O\Threads.obj \ +!include "../../Crc.mak" + !include "../../7zip.mak" diff --git a/CPP/7zip/Archive/Common/CoderMixer.cpp b/CPP/7zip/Archive/Common/CoderMixer.cpp deleted file mode 100644 index a19f0457..00000000 --- a/CPP/7zip/Archive/Common/CoderMixer.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// CoderMixer.cpp - -#include "StdAfx.h" - -#include "CoderMixer.h" - -namespace NCoderMixer { - -void CCoderInfo::SetCoderInfo(const UInt64 *inSize, const UInt64 *outSize) -{ - InSizeAssigned = (inSize != 0); - if (InSizeAssigned) - InSizeValue = *inSize; - OutSizeAssigned = (outSize != 0); - if (OutSizeAssigned) - OutSizeValue = *outSize; -} - -} diff --git a/CPP/7zip/Archive/Common/CoderMixer.h b/CPP/7zip/Archive/Common/CoderMixer.h deleted file mode 100644 index 6379dd80..00000000 --- a/CPP/7zip/Archive/Common/CoderMixer.h +++ /dev/null @@ -1,32 +0,0 @@ -// CoderMixer.h - -#ifndef __CODER_MIXER_H -#define __CODER_MIXER_H - -#include "../../../Common/MyCom.h" -#include "../../ICoder.h" - -namespace NCoderMixer { - -struct CCoderInfo -{ - CMyComPtr<ICompressCoder> Coder; - CMyComPtr<ISequentialInStream> InStream; - CMyComPtr<ISequentialOutStream> OutStream; - CMyComPtr<ICompressProgressInfo> Progress; - - UInt64 InSizeValue; - UInt64 OutSizeValue; - bool InSizeAssigned; - bool OutSizeAssigned; - - void ReInit() - { - InSizeAssigned = OutSizeAssigned = false; - } - - void SetCoderInfo(const UInt64 *inSize, const UInt64 *outSize); -}; - -} -#endif diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp deleted file mode 100644 index c0139862..00000000 --- a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp +++ /dev/null @@ -1,254 +0,0 @@ -// CoderMixer2MT.cpp - -#include "StdAfx.h" - -#include "CoderMixer2MT.h" - -namespace NCoderMixer2 { - -void CCoderMT::Execute() { Code(NULL); } - -void CCoderMT::Code(ICompressProgressInfo *progress) -{ - unsigned numInStreams = EncodeMode ? 1 : NumStreams; - unsigned numOutStreams = EncodeMode ? NumStreams : 1; - - InStreamPointers.ClearAndReserve(numInStreams); - OutStreamPointers.ClearAndReserve(numOutStreams); - - unsigned i; - - for (i = 0; i < numInStreams; i++) - InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]); - - for (i = 0; i < numOutStreams; i++) - OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]); - - // we suppose that UnpackSizePointer and PackSizePointers contain correct pointers. - /* - if (UnpackSizePointer) - UnpackSizePointer = &UnpackSize; - for (i = 0; i < NumStreams; i++) - if (PackSizePointers[i]) - PackSizePointers[i] = &PackSizes[i]; - */ - - if (Coder) - Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], - EncodeMode ? UnpackSizePointer : PackSizePointers[0], - EncodeMode ? PackSizePointers[0] : UnpackSizePointer, - progress); - else - Result = Coder2->Code( - &InStreamPointers.Front(), EncodeMode ? &UnpackSizePointer : &PackSizePointers.Front(), numInStreams, - &OutStreamPointers.Front(), EncodeMode ? &PackSizePointers.Front(): &UnpackSizePointer, numOutStreams, - progress); - - InStreamPointers.Clear(); - OutStreamPointers.Clear(); - - for (i = 0; i < InStreams.Size(); i++) - InStreams[i].Release(); - for (i = 0; i < OutStreams.Size(); i++) - OutStreams[i].Release(); -} - -HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo) -{ - CMixer::SetBindInfo(bindInfo); - - _streamBinders.Clear(); - FOR_VECTOR (i, _bi.Bonds) - { - RINOK(_streamBinders.AddNew().CreateEvents()); - } - return S_OK; -} - -void CMixerMT::AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter) -{ - const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()]; - CCoderMT &c2 = _coders.AddNew(); - c2.NumStreams = c.NumStreams; - c2.EncodeMode = EncodeMode; - c2.Coder = coder; - c2.Coder2 = coder2; - IsFilter_Vector.Add(isFilter); -} - -CCoder &CMixerMT::GetCoder(unsigned index) -{ - return _coders[index]; -} - -void CMixerMT::ReInit() -{ - FOR_VECTOR (i, _streamBinders) - _streamBinders[i].ReInit(); -} - -void CMixerMT::SelectMainCoder(bool useFirst) -{ - unsigned ci = _bi.UnpackCoder; - - if (!useFirst) - for (;;) - { - if (_coders[ci].NumStreams != 1) - break; - if (!IsFilter_Vector[ci]) - break; - - UInt32 st = _bi.Coder_to_Stream[ci]; - if (_bi.IsStream_in_PackStreams(st)) - break; - int bond = _bi.FindBond_for_PackStream(st); - if (bond < 0) - throw 20150213; - ci = _bi.Bonds[bond].UnpackIndex; - } - - MainCoderIndex = ci; -} - -HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams) -{ - unsigned i; - - for (i = 0; i < _coders.Size(); i++) - { - CCoderMT &coderInfo = _coders[i]; - const CCoderStreamsInfo &csi = _bi.Coders[i]; - - UInt32 j; - - unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams; - unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1; - - coderInfo.InStreams.Clear(); - for (j = 0; j < numInStreams; j++) - coderInfo.InStreams.AddNew(); - - coderInfo.OutStreams.Clear(); - for (j = 0; j < numOutStreams; j++) - coderInfo.OutStreams.AddNew(); - } - - for (i = 0; i < _bi.Bonds.Size(); i++) - { - const CBond &bond = _bi.Bonds[i]; - - UInt32 inCoderIndex, inCoderStreamIndex; - UInt32 outCoderIndex, outCoderStreamIndex; - - { - UInt32 coderIndex, coderStreamIndex; - _bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex); - - inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex; - outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex; - - inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex; - outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0; - } - - _streamBinders[i].CreateStreams( - &_coders[inCoderIndex].InStreams[inCoderStreamIndex], - &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]); - - CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize; - _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize); - _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize); - if (inSetSize && outSetSize) - { - const UInt32 kBufSize = 1 << 19; - inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize); - outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize); - } - } - - { - CCoderMT &cod = _coders[_bi.UnpackCoder]; - if (EncodeMode) - cod.InStreams[0] = inStreams[0]; - else - cod.OutStreams[0] = outStreams[0]; - } - - for (i = 0; i < _bi.PackStreams.Size(); i++) - { - UInt32 coderIndex, coderStreamIndex; - _bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex); - CCoderMT &cod = _coders[coderIndex]; - if (EncodeMode) - cod.OutStreams[coderStreamIndex] = outStreams[i]; - else - cod.InStreams[coderStreamIndex] = inStreams[i]; - } - - return S_OK; -} - -HRESULT CMixerMT::ReturnIfError(HRESULT code) -{ - FOR_VECTOR (i, _coders) - if (_coders[i].Result == code) - return code; - return S_OK; -} - -HRESULT CMixerMT::Code( - ISequentialInStream * const *inStreams, - ISequentialOutStream * const *outStreams, - ICompressProgressInfo *progress) -{ - Init(inStreams, outStreams); - - unsigned i; - for (i = 0; i < _coders.Size(); i++) - if (i != MainCoderIndex) - { - RINOK(_coders[i].Create()); - } - - for (i = 0; i < _coders.Size(); i++) - if (i != MainCoderIndex) - _coders[i].Start(); - - _coders[MainCoderIndex].Code(progress); - - for (i = 0; i < _coders.Size(); i++) - if (i != MainCoderIndex) - _coders[i].WaitExecuteFinish(); - - RINOK(ReturnIfError(E_ABORT)); - RINOK(ReturnIfError(E_OUTOFMEMORY)); - - for (i = 0; i < _coders.Size(); i++) - { - HRESULT result = _coders[i].Result; - if (result != S_OK - && result != k_My_HRESULT_WritingWasCut - && result != S_FALSE - && result != E_FAIL) - return result; - } - - RINOK(ReturnIfError(S_FALSE)); - - for (i = 0; i < _coders.Size(); i++) - { - HRESULT result = _coders[i].Result; - if (result != S_OK && result != k_My_HRESULT_WritingWasCut) - return result; - } - - return S_OK; -} - -UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const -{ - return _streamBinders[bondIndex].ProcessedSize; -} - -} diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.h b/CPP/7zip/Archive/Common/CoderMixer2MT.h deleted file mode 100644 index 41bb3e1c..00000000 --- a/CPP/7zip/Archive/Common/CoderMixer2MT.h +++ /dev/null @@ -1,77 +0,0 @@ -// CoderMixer2MT.h - -#ifndef __CODER_MIXER2_MT_H -#define __CODER_MIXER2_MT_H - -#include "../../../Common/MyCom.h" - -#include "../../Common/StreamBinder.h" -#include "../../Common/VirtThread.h" - -#include "CoderMixer2.h" - -namespace NCoderMixer2 { - -class CCoderMT: public CCoder, public CVirtThread -{ - CLASS_NO_COPY(CCoderMT) - CRecordVector<ISequentialInStream*> InStreamPointers; - CRecordVector<ISequentialOutStream*> OutStreamPointers; - -private: - void Execute(); -public: - bool EncodeMode; - HRESULT Result; - CObjectVector< CMyComPtr<ISequentialInStream> > InStreams; - CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams; - - CCoderMT(): EncodeMode(false) {} - ~CCoderMT() { CVirtThread::WaitThreadFinish(); } - - void Code(ICompressProgressInfo *progress); -}; - - - -class CMixerMT: - public IUnknown, - public CMixer, - public CMyUnknownImp -{ - CObjectVector<CStreamBinder> _streamBinders; - - HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams); - HRESULT ReturnIfError(HRESULT code); - -public: - CObjectVector<CCoderMT> _coders; - - MY_UNKNOWN_IMP - - virtual HRESULT SetBindInfo(const CBindInfo &bindInfo); - - virtual void AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter); - - virtual CCoder &GetCoder(unsigned index); - - virtual void SelectMainCoder(bool useFirst); - - virtual void ReInit(); - - virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) - { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); } - - virtual HRESULT Code( - ISequentialInStream * const *inStreams, - ISequentialOutStream * const *outStreams, - ICompressProgressInfo *progress); - - virtual UInt64 GetBondStreamSize(unsigned bondIndex) const; - - CMixerMT(bool encodeMode): CMixer(encodeMode) {} -}; - -} - -#endif diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp deleted file mode 100644 index 127c1ed4..00000000 --- a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp +++ /dev/null @@ -1,562 +0,0 @@ -// CoderMixer2ST.cpp - -#include "StdAfx.h" - -#include "CoderMixer2ST.h" - -STDMETHODIMP CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize) -{ - UInt32 realProcessed = 0; - HRESULT result = S_OK; - if (_stream) - result = _stream->Read(data, size, &realProcessed); - _size += realProcessed; - if (size != 0 && realProcessed == 0) - _wasFinished = true; - if (processedSize) - *processedSize = realProcessed; - return result; -} - - - -STDMETHODIMP COutStreamCalcSize::Write(const void *data, UInt32 size, UInt32 *processedSize) -{ - HRESULT result = S_OK; - if (_stream) - result = _stream->Write(data, size, &size); - _size += size; - if (processedSize) - *processedSize = size; - return result; -} - -STDMETHODIMP COutStreamCalcSize::Flush() -{ - HRESULT result = S_OK; - if (_stream) - { - CMyComPtr<IOutStreamFlush> outStreamFlush; - _stream.QueryInterface(IID_IOutStreamFlush, &outStreamFlush); - if (outStreamFlush) - result = outStreamFlush->Flush();; - } - return result; -} - - - -namespace NCoderMixer2 { - -CMixerST::CMixerST(bool encodeMode): - CMixer(encodeMode) - {} - -CMixerST::~CMixerST() {} - -void CMixerST::AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter) -{ - IsFilter_Vector.Add(isFilter); - const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()]; - CCoderST &c2 = _coders.AddNew(); - c2.NumStreams = c.NumStreams; - c2.Coder = coder; - c2.Coder2 = coder2; - - /* - if (isFilter) - { - c2.CanRead = true; - c2.CanWrite = true; - } - else - */ - { - IUnknown *unk = (coder ? (IUnknown *)coder : (IUnknown *)coder2); - { - CMyComPtr<ISequentialInStream> s; - unk->QueryInterface(IID_ISequentialInStream, (void**)&s); - c2.CanRead = (s != NULL); - } - { - CMyComPtr<ISequentialOutStream> s; - unk->QueryInterface(IID_ISequentialOutStream, (void**)&s); - c2.CanWrite = (s != NULL); - } - } -} - -CCoder &CMixerST::GetCoder(unsigned index) -{ - return _coders[index]; -} - -void CMixerST::ReInit() {} - -HRESULT CMixerST::GetInStream2( - ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ - UInt32 outStreamIndex, ISequentialInStream **inStreamRes) -{ - UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0; - - if (EncodeMode) - { - _bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex); - if (coderStreamIndex != 0) - return E_NOTIMPL; - } - - const CCoder &coder = _coders[coderIndex]; - - CMyComPtr<ISequentialInStream> seqInStream; - coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream); - if (!seqInStream) - return E_NOTIMPL; - - UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams; - UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex]; - - bool isSet = false; - - if (numInStreams == 1) - { - CMyComPtr<ICompressSetInStream> setStream; - coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream); - if (setStream) - { - CMyComPtr<ISequentialInStream> seqInStream2; - RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2)); - RINOK(setStream->SetInStream(seqInStream2)); - isSet = true; - } - } - - if (!isSet && numInStreams != 0) - { - CMyComPtr<ICompressSetInStream2> setStream2; - coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2); - if (!setStream2) - return E_NOTIMPL; - - for (UInt32 i = 0; i < numInStreams; i++) - { - CMyComPtr<ISequentialInStream> seqInStream2; - RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2)); - RINOK(setStream2->SetInStream2(i, seqInStream2)); - } - } - - *inStreamRes = seqInStream.Detach(); - return S_OK; -} - - -HRESULT CMixerST::GetInStream( - ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ - UInt32 inStreamIndex, ISequentialInStream **inStreamRes) -{ - CMyComPtr<ISequentialInStream> seqInStream; - - { - int index = -1; - if (EncodeMode) - { - if (_bi.UnpackCoder == inStreamIndex) - index = 0; - } - else - index = _bi.FindStream_in_PackStreams(inStreamIndex); - - if (index >= 0) - { - seqInStream = inStreams[index]; - *inStreamRes = seqInStream.Detach(); - return S_OK; - } - } - - int bond = FindBond_for_Stream( - true, // forInputStream - inStreamIndex); - if (bond < 0) - return E_INVALIDARG; - - RINOK(GetInStream2(inStreams, /* inSizes, */ - _bi.Bonds[bond].Get_OutIndex(EncodeMode), &seqInStream)); - - while (_binderStreams.Size() <= (unsigned)bond) - _binderStreams.AddNew(); - CStBinderStream &bs = _binderStreams[bond]; - - if (bs.StreamRef || bs.InStreamSpec) - return E_NOTIMPL; - - CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize; - bs.StreamRef = spec; - bs.InStreamSpec = spec; - - spec->SetStream(seqInStream); - spec->Init(); - - seqInStream = bs.InStreamSpec; - - *inStreamRes = seqInStream.Detach(); - return S_OK; -} - - -HRESULT CMixerST::GetOutStream( - ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */ - UInt32 outStreamIndex, ISequentialOutStream **outStreamRes) -{ - CMyComPtr<ISequentialOutStream> seqOutStream; - - { - int index = -1; - if (!EncodeMode) - { - if (_bi.UnpackCoder == outStreamIndex) - index = 0; - } - else - index = _bi.FindStream_in_PackStreams(outStreamIndex); - - if (index >= 0) - { - seqOutStream = outStreams[index]; - *outStreamRes = seqOutStream.Detach(); - return S_OK; - } - } - - int bond = FindBond_for_Stream( - false, // forInputStream - outStreamIndex); - if (bond < 0) - return E_INVALIDARG; - - UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode); - - UInt32 coderIndex = inStreamIndex; - UInt32 coderStreamIndex = 0; - - if (!EncodeMode) - _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex); - - CCoder &coder = _coders[coderIndex]; - - /* - if (!coder.Coder) - return E_NOTIMPL; - */ - - coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream); - if (!seqOutStream) - return E_NOTIMPL; - - UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1; - UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex; - - bool isSet = false; - - if (numOutStreams == 1) - { - CMyComPtr<ICompressSetOutStream> setOutStream; - coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream); - if (setOutStream) - { - CMyComPtr<ISequentialOutStream> seqOutStream2; - RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2)); - RINOK(setOutStream->SetOutStream(seqOutStream2)); - isSet = true; - } - } - - if (!isSet && numOutStreams != 0) - { - // return E_NOTIMPL; - // /* - CMyComPtr<ICompressSetOutStream2> setStream2; - coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2); - if (!setStream2) - return E_NOTIMPL; - for (UInt32 i = 0; i < numOutStreams; i++) - { - CMyComPtr<ISequentialOutStream> seqOutStream2; - RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2)); - RINOK(setStream2->SetOutStream2(i, seqOutStream2)); - } - // */ - } - - while (_binderStreams.Size() <= (unsigned)bond) - _binderStreams.AddNew(); - CStBinderStream &bs = _binderStreams[bond]; - - if (bs.StreamRef || bs.OutStreamSpec) - return E_NOTIMPL; - - COutStreamCalcSize *spec = new COutStreamCalcSize; - bs.StreamRef = (ISequentialOutStream *)spec; - bs.OutStreamSpec = spec; - - spec->SetStream(seqOutStream); - spec->Init(); - - seqOutStream = bs.OutStreamSpec; - - *outStreamRes = seqOutStream.Detach(); - return S_OK; -} - - -static HRESULT GetError(HRESULT res, HRESULT res2) -{ - if (res == res2) - return res; - if (res == S_OK) - return res2; - if (res == k_My_HRESULT_WritingWasCut) - { - if (res2 != S_OK) - return res2; - } - return res; -} - - -HRESULT CMixerST::FlushStream(UInt32 streamIndex) -{ - { - int index = -1; - if (!EncodeMode) - { - if (_bi.UnpackCoder == streamIndex) - index = 0; - } - else - index = _bi.FindStream_in_PackStreams(streamIndex); - - if (index >= 0) - return S_OK; - } - - int bond = FindBond_for_Stream( - false, // forInputStream - streamIndex); - if (bond < 0) - return E_INVALIDARG; - - UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode); - - UInt32 coderIndex = inStreamIndex; - UInt32 coderStreamIndex = 0; - if (!EncodeMode) - _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex); - - CCoder &coder = _coders[coderIndex]; - CMyComPtr<IOutStreamFlush> flush; - coder.QueryInterface(IID_IOutStreamFlush, (void **)&flush); - HRESULT res = S_OK; - if (flush) - { - res = flush->Flush(); - } - return GetError(res, FlushCoder(coderIndex)); -} - - -HRESULT CMixerST::FlushCoder(UInt32 coderIndex) -{ - CCoder &coder = _coders[coderIndex]; - - UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1; - UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex; - - HRESULT res = S_OK; - for (unsigned i = 0; i < numOutStreams; i++) - res = GetError(res, FlushStream(startIndex + i)); - return res; -} - - -void CMixerST::SelectMainCoder(bool useFirst) -{ - unsigned ci = _bi.UnpackCoder; - - int firstNonFilter = -1; - int firstAllowed = ci; - - for (;;) - { - const CCoderST &coder = _coders[ci]; - // break; - - if (ci != _bi.UnpackCoder) - if (EncodeMode ? !coder.CanWrite : !coder.CanRead) - { - firstAllowed = ci; - firstNonFilter = -2; - } - - if (coder.NumStreams != 1) - break; - - UInt32 st = _bi.Coder_to_Stream[ci]; - if (_bi.IsStream_in_PackStreams(st)) - break; - int bond = _bi.FindBond_for_PackStream(st); - if (bond < 0) - throw 20150213; - - if (EncodeMode ? !coder.CanRead : !coder.CanWrite) - break; - - if (firstNonFilter == -1 && !IsFilter_Vector[ci]) - firstNonFilter = ci; - - ci = _bi.Bonds[bond].UnpackIndex; - } - - ci = firstNonFilter; - if (firstNonFilter < 0 || useFirst) - ci = firstAllowed; - MainCoderIndex = ci; -} - - -HRESULT CMixerST::Code( - ISequentialInStream * const *inStreams, - ISequentialOutStream * const *outStreams, - ICompressProgressInfo *progress) -{ - _binderStreams.Clear(); - unsigned ci = MainCoderIndex; - - const CCoder &mainCoder = _coders[MainCoderIndex]; - - CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams; - CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams; - - UInt32 numInStreams = EncodeMode ? 1 : mainCoder.NumStreams; - UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams; - - UInt32 startInIndex = EncodeMode ? ci : _bi.Coder_to_Stream[ci]; - UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci]; - - UInt32 i; - - for (i = 0; i < numInStreams; i++) - { - CMyComPtr<ISequentialInStream> seqInStream; - RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream)); - seqInStreams.Add(seqInStream); - } - - for (i = 0; i < numOutStreams; i++) - { - CMyComPtr<ISequentialOutStream> seqOutStream; - RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream)); - seqOutStreams.Add(seqOutStream); - } - - CRecordVector< ISequentialInStream * > seqInStreamsSpec; - CRecordVector< ISequentialOutStream * > seqOutStreamsSpec; - - for (i = 0; i < numInStreams; i++) - seqInStreamsSpec.Add(seqInStreams[i]); - for (i = 0; i < numOutStreams; i++) - seqOutStreamsSpec.Add(seqOutStreams[i]); - - for (i = 0; i < _coders.Size(); i++) - { - if (i == ci) - continue; - - CCoder &coder = _coders[i]; - - CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize; - coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize); - if (setOutStreamSize) - { - RINOK(setOutStreamSize->SetOutStreamSize( - EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer)); - } - } - - const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : &mainCoder.PackSizePointers.Front(); - const UInt64 * const *outSizes2 = EncodeMode ? &mainCoder.PackSizePointers.Front() : &mainCoder.UnpackSizePointer; - - HRESULT res; - if (mainCoder.Coder) - { - res = mainCoder.Coder->Code( - seqInStreamsSpec[0], seqOutStreamsSpec[0], - isSizes2[0], outSizes2[0], - progress); - } - else - { - res = mainCoder.Coder2->Code( - &seqInStreamsSpec.Front(), isSizes2, numInStreams, - &seqOutStreamsSpec.Front(), outSizes2, numOutStreams, - progress); - } - - if (res == k_My_HRESULT_WritingWasCut) - res = S_OK; - - if (res == S_OK || res == S_FALSE) - { - res = GetError(res, FlushCoder(ci)); - } - - for (i = 0; i < _binderStreams.Size(); i++) - { - const CStBinderStream &bs = _binderStreams[i]; - if (bs.InStreamSpec) - bs.InStreamSpec->ReleaseStream(); - else - bs.OutStreamSpec->ReleaseStream(); - } - - if (res == k_My_HRESULT_WritingWasCut) - res = S_OK; - return res; -} - - -HRESULT CMixerST::GetMainUnpackStream( - ISequentialInStream * const *inStreams, - ISequentialInStream **inStreamRes) -{ - CMyComPtr<ISequentialInStream> seqInStream; - - RINOK(GetInStream2(inStreams, /* inSizes, */ - _bi.UnpackCoder, &seqInStream)) - - FOR_VECTOR (i, _coders) - { - CCoder &coder = _coders[i]; - CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize; - coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize); - if (setOutStreamSize) - { - RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer)); - } - } - - *inStreamRes = seqInStream.Detach(); - return S_OK; -} - - -UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const -{ - const CStBinderStream &bs = _binderStreams[bondIndex]; - if (bs.InStreamSpec) - return bs.InStreamSpec->GetSize(); - return bs.OutStreamSpec->GetSize(); -} - -} diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.h b/CPP/7zip/Archive/Common/CoderMixer2ST.h deleted file mode 100644 index f2f7c4cb..00000000 --- a/CPP/7zip/Archive/Common/CoderMixer2ST.h +++ /dev/null @@ -1,129 +0,0 @@ -// CoderMixer2ST.h - -#ifndef __CODER_MIXER2_ST_H -#define __CODER_MIXER2_ST_H - -#include "../../../Common/MyCom.h" - -#include "../../ICoder.h" - -#include "CoderMixer2.h" - -class CSequentialInStreamCalcSize: - public ISequentialInStream, - public CMyUnknownImp -{ -public: - MY_UNKNOWN_IMP1(ISequentialInStream) - - STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); -private: - CMyComPtr<ISequentialInStream> _stream; - UInt64 _size; - bool _wasFinished; -public: - void SetStream(ISequentialInStream *stream) { _stream = stream; } - void Init() - { - _size = 0; - _wasFinished = false; - } - void ReleaseStream() { _stream.Release(); } - UInt64 GetSize() const { return _size; } - bool WasFinished() const { return _wasFinished; } -}; - - -class COutStreamCalcSize: - public ISequentialOutStream, - public IOutStreamFlush, - public CMyUnknownImp -{ - CMyComPtr<ISequentialOutStream> _stream; - UInt64 _size; -public: - MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFlush) - - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(Flush)(); - - void SetStream(ISequentialOutStream *stream) { _stream = stream; } - void ReleaseStream() { _stream.Release(); } - void Init() { _size = 0; } - UInt64 GetSize() const { return _size; } -}; - - - -namespace NCoderMixer2 { - -struct CCoderST: public CCoder -{ - bool CanRead; - bool CanWrite; - - CCoderST(): CanRead(false), CanWrite(false) {} -}; - - -struct CStBinderStream -{ - CSequentialInStreamCalcSize *InStreamSpec; - COutStreamCalcSize *OutStreamSpec; - CMyComPtr<IUnknown> StreamRef; - - CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {} -}; - - -class CMixerST: - public IUnknown, - public CMixer, - public CMyUnknownImp -{ - HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ - UInt32 outStreamIndex, ISequentialInStream **inStreamRes); - HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ - UInt32 inStreamIndex, ISequentialInStream **inStreamRes); - HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */ - UInt32 outStreamIndex, ISequentialOutStream **outStreamRes); - - HRESULT FlushStream(UInt32 streamIndex); - HRESULT FlushCoder(UInt32 coderIndex); - -public: - CObjectVector<CCoderST> _coders; - - CObjectVector<CStBinderStream> _binderStreams; - - MY_UNKNOWN_IMP - - CMixerST(bool encodeMode); - ~CMixerST(); - - virtual void AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter); - - virtual CCoder &GetCoder(unsigned index); - - virtual void SelectMainCoder(bool useFirst); - - virtual void ReInit(); - - virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) - { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); } - - virtual HRESULT Code( - ISequentialInStream * const *inStreams, - ISequentialOutStream * const *outStreams, - ICompressProgressInfo *progress); - - virtual UInt64 GetBondStreamSize(unsigned bondIndex) const; - - HRESULT GetMainUnpackStream( - ISequentialInStream * const *inStreams, - ISequentialInStream **inStreamRes); -}; - -} - -#endif diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.cpp b/CPP/7zip/Archive/Common/CoderMixerMT.cpp deleted file mode 100644 index 96ea76a3..00000000 --- a/CPP/7zip/Archive/Common/CoderMixerMT.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// CoderMixerMT.cpp - -#include "StdAfx.h" - -#include "CoderMixerMT.h" - -namespace NCoderMixer { - -void CCoder::Execute() { Code(NULL); } - -void CCoder::Code(ICompressProgressInfo *progress) -{ - Result = Coder->Code(InStream, OutStream, - InSizeAssigned ? &InSizeValue : NULL, - OutSizeAssigned ? &OutSizeValue : NULL, - progress); - InStream.Release(); - OutStream.Release(); -} - -void CCoderMixerMT::AddCoder(ICompressCoder *coder) -{ - _coders.Add(CCoder()); - _coders.Back().Coder = coder; -} - -void CCoderMixerMT::ReInit() -{ - for(int i = 0; i < _coders.Size(); i++) - _coders[i].ReInit(); -} - -HRESULT CCoderMixerMT::ReturnIfError(HRESULT code) -{ - for (int i = 0; i < _coders.Size(); i++) - if (_coders[i].Result == code) - return code; - return S_OK; -} - -STDMETHODIMP CCoderMixerMT::Code(ISequentialInStream *inStream, - ISequentialOutStream *outStream, - const UInt64 * /* inSize */, const UInt64 * /* outSize */, - ICompressProgressInfo *progress) -{ - _coders.Front().InStream = inStream; - int i; - _coders.Back().OutStream = outStream; - - for (i = 0; i < _coders.Size(); i++) - if (i != _progressCoderIndex) - { - RINOK(_coders[i].Create()); - } - - _streamBinders.Clear(); - for (i = 0; i + 1 < _coders.Size(); i++) - { - _streamBinders.Add(CStreamBinder()); - CStreamBinder &sb = _streamBinders[i]; - RINOK(sb.CreateEvents()); - sb.CreateStreams(&_coders[i + 1].InStream, &_coders[i].OutStream); - } - - for(i = 0; i < _streamBinders.Size(); i++) - _streamBinders[i].ReInit(); - - for (i = 0; i < _coders.Size(); i++) - if (i != _progressCoderIndex) - _coders[i].Start(); - - _coders[_progressCoderIndex].Code(progress); - - for (i = 0; i < _coders.Size(); i++) - if (i != _progressCoderIndex) - _coders[i].WaitExecuteFinish(); - - RINOK(ReturnIfError(E_ABORT)); - RINOK(ReturnIfError(E_OUTOFMEMORY)); - - for (i = 0; i < _coders.Size(); i++) - { - HRESULT result = _coders[i].Result; - if (result != S_OK && result != E_FAIL && result != S_FALSE) - return result; - } - - RINOK(ReturnIfError(S_FALSE)); - - for (i = 0; i < _coders.Size(); i++) - { - HRESULT result = _coders[i].Result; - if (result != S_OK) - return result; - } - return S_OK; -} - -} diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.h b/CPP/7zip/Archive/Common/CoderMixerMT.h deleted file mode 100644 index d2891b26..00000000 --- a/CPP/7zip/Archive/Common/CoderMixerMT.h +++ /dev/null @@ -1,70 +0,0 @@ -// CoderMixerMT.h - -#ifndef __CODER_MIXER_MT_H -#define __CODER_MIXER_MT_H - -#include "../../../Common/MyVector.h" -#include "../../../Common/MyCom.h" -#include "../../ICoder.h" -#include "../../Common/StreamBinder.h" -#include "../../Common/VirtThread.h" -#include "CoderMixer.h" - -namespace NCoderMixer { - -struct CCoder: public CCoderInfo, public CVirtThread -{ - HRESULT Result; - - virtual void Execute(); - void Code(ICompressProgressInfo *progress); - virtual ~CCoder() { CVirtThread::WaitThreadFinish(); } -}; - -/* - for each coder - AddCoder() - SetProgressIndex(UInt32 coderIndex); - - for each file - { - ReInit() - for each coder - SetCoderInfo - Code - } -*/ - - -class CCoderMixerMT: - public ICompressCoder, - public CMyUnknownImp -{ - CObjectVector<CStreamBinder> _streamBinders; - int _progressCoderIndex; - - HRESULT ReturnIfError(HRESULT code); -public: - CObjectVector<CCoder> _coders; - MY_UNKNOWN_IMP - - STDMETHOD(Code)(ISequentialInStream *inStream, - ISequentialOutStream *outStream, - const UInt64 *inSize, const UInt64 *outSize, - ICompressProgressInfo *progress); - - void AddCoder(ICompressCoder *coder); - void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; } - - void ReInit(); - void SetCoderInfo(UInt32 coderIndex, const UInt64 *inSize, const UInt64 *outSize) - { _coders[coderIndex].SetCoderInfo(inSize, outSize); } - - /* - UInt64 GetWriteProcessedSize(UInt32 binderIndex) const - { return _streamBinders[binderIndex].ProcessedSize; } - */ -}; - -} -#endif diff --git a/CPP/7zip/Archive/Common/FindSignature.cpp b/CPP/7zip/Archive/Common/FindSignature.cpp index e9a0f032..fc952fa8 100644 --- a/CPP/7zip/Archive/Common/FindSignature.cpp +++ b/CPP/7zip/Archive/Common/FindSignature.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include <string.h> + #include "../../../Common/MyBuffer.h" #include "../../Common/StreamUtils.h" diff --git a/CPP/7zip/Archive/Common/FindSignature.h b/CPP/7zip/Archive/Common/FindSignature.h index e15af573..c359b9ed 100644 --- a/CPP/7zip/Archive/Common/FindSignature.h +++ b/CPP/7zip/Archive/Common/FindSignature.h @@ -1,7 +1,7 @@ // FindSignature.h -#ifndef __FINDSIGNATURE_H -#define __FINDSIGNATURE_H +#ifndef __FIND_SIGNATURE_H +#define __FIND_SIGNATURE_H #include "../../IStream.h" diff --git a/CPP/7zip/Archive/DllExports2.cpp b/CPP/7zip/Archive/DllExports2.cpp index 2b196abe..979b4bf9 100644 --- a/CPP/7zip/Archive/DllExports2.cpp +++ b/CPP/7zip/Archive/DllExports2.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../Common/MyWindows.h" + #include "../../Common/MyInitGuid.h" #if defined(_7ZIP_LARGE_PAGES) diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h index 2bab5299..498784b8 100644 --- a/CPP/7zip/Archive/Nsis/NsisIn.h +++ b/CPP/7zip/Archive/Nsis/NsisIn.h @@ -16,7 +16,7 @@ /* If NSIS_SCRIPT is defined, it will decompile NSIS script to [NSIS].nsi file. The code is much larger in that case. */ -#define NSIS_SCRIPT +// #define NSIS_SCRIPT namespace NArchive { namespace NNsis { diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.cpp b/CPP/7zip/Archive/Rar/Rar5Handler.cpp new file mode 100644 index 00000000..72fe4f68 --- /dev/null +++ b/CPP/7zip/Archive/Rar/Rar5Handler.cpp @@ -0,0 +1,2683 @@ +// Rar5Handler.cpp + +#include "StdAfx.h" + +#include "../../../../C/7zCrc.h" +#include "../../../../C/CpuArch.h" + +#include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/UTFConvert.h" + +#include "../../../Windows/PropVariantUtils.h" +#include "../../../Windows/TimeUtils.h" + +#include "../../IPassword.h" + +#include "../../Common/FilterCoder.h" +#include "../../Common/LimitedStreams.h" +#include "../../Common/ProgressUtils.h" +#include "../../Common/RegisterArc.h" +#include "../../Common/StreamObjects.h" +#include "../../Common/StreamUtils.h" + +#include "../../Common/RegisterCodec.h" + +#include "../../Compress/CopyCoder.h" + +#include "../../Crypto/Rar5Aes.h" + +#include "../Common/FindSignature.h" +#include "../Common/ItemNameUtils.h" + +#include "RarVol.h" +#include "Rar5Handler.h" + +using namespace NWindows; + +#define Get32(p) GetUi32(p) + +namespace NArchive { + +namespace NRar { + +HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize); + +} + +namespace NRar5 { + +static const unsigned kMarkerSize = 8; + +#define SIGNATURE { 0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0 } + +static const Byte kMarker[kMarkerSize] = SIGNATURE; + +static const size_t kCommentSize_Max = (size_t)1 << 16; + +static const char * const kHostOS[] = +{ + "Windows" + , "Unix" +}; + +static const CUInt32PCharPair k_ArcFlags[] = +{ + { 0, "Volume" }, + { 1, "VolumeField" }, + { 2, "Solid" }, + { 3, "Recovery" }, + { 4, "Lock" } +}; + + + +template <unsigned alignMask> +struct CAlignedBuffer +{ + Byte *_buf; + Byte *_bufBase; + size_t _size; + + CAlignedBuffer(): _buf(NULL), _bufBase(NULL), _size(0) {} + ~CAlignedBuffer() { ::MyFree(_bufBase); } +public: + operator Byte *() { return _buf; } + operator const Byte *() const { return _buf; } + + void AllocAtLeast(size_t size) + { + if (_buf && _size >= size) + return; + ::MyFree(_bufBase); + _buf = NULL; + _size = 0; + _bufBase = (Byte *)::MyAlloc(size + alignMask); + + if (_bufBase) + { + _size = size; + // _buf = (Byte *)(((uintptr_t)_bufBase + alignMask) & ~(uintptr_t)alignMask); + _buf = (Byte *)(((ptrdiff_t)_bufBase + alignMask) & ~(ptrdiff_t)alignMask); + } + } +}; + +static unsigned ReadVarInt(const Byte *p, size_t maxSize, UInt64 *val) +{ + *val = 0; + + for (unsigned i = 0; i < maxSize;) + { + Byte b = p[i]; + if (i < 10) + *val |= (UInt64)(b & 0x7F) << (7 * i++); + if ((b & 0x80) == 0) + return i; + } + return 0; +} + + +int CItem::FindExtra(unsigned type, unsigned &recordDataSize) const +{ + recordDataSize = 0; + size_t offset = 0; + + for (;;) + { + size_t rem = Extra.Size() - offset; + if (rem == 0) + return -1; + + { + UInt64 size; + unsigned num = ReadVarInt(Extra + offset, rem, &size); + if (num == 0) + return -1; + offset += num; + rem -= num; + if (size > rem) + return -1; + rem = (size_t)size; + } + { + UInt64 type2; + unsigned num = ReadVarInt(Extra + offset, rem, &type2); + if (num == 0) + return -1; + offset += num; + rem -= num; + + // There was BUG in RAR 5.21- : it stored (size-1) instead of (size) + // for Subdata record in Service header. + // That record always was last in bad archives, so we can fix that case. + if (type2 == NExtraRecordType::kSubdata + && RecordType == NHeaderType::kService + && rem + 1 == Extra.Size() - offset) + rem++; + + if (type2 == type) + { + recordDataSize = (unsigned)rem; + return (int)offset; + } + + offset += rem; + } + } +} + + +bool CCryptoInfo::Parse(const Byte *p, size_t size) +{ + unsigned num = ReadVarInt(p, size, &Algo); + if (num == 0) return false; p += num; size -= num; + + num = ReadVarInt(p, size, &Flags); + if (num == 0) return false; p += num; size -= num; + + if (size != 1 + 16 + 16 + (unsigned)(IsThereCheck() ? 12 : 0)) + return false; + + Cnt = p[0]; + + return true; +} + + +bool CItem::FindExtra_Version(UInt64 &version) const +{ + unsigned size; + int offset = FindExtra(NExtraRecordType::kVersion, size); + if (offset < 0) + return false; + const Byte *p = Extra + (unsigned)offset; + + UInt64 Flags; + unsigned num = ReadVarInt(p, size, &Flags); + if (num == 0) return false; p += num; size -= num; + + num = ReadVarInt(p, size, &version); + if (num == 0) return false; p += num; size -= num; + + return size == 0; +} + +bool CItem::FindExtra_Link(CLinkInfo &link) const +{ + unsigned size; + int offset = FindExtra(NExtraRecordType::kLink, size); + if (offset < 0) + return false; + const Byte *p = Extra + (unsigned)offset; + + unsigned num = ReadVarInt(p, size, &link.Type); + if (num == 0) return false; p += num; size -= num; + + num = ReadVarInt(p, size, &link.Flags); + if (num == 0) return false; p += num; size -= num; + + UInt64 len; + num = ReadVarInt(p, size, &len); + if (num == 0) return false; p += num; size -= num; + + if (size != len) + return false; + + link.NameLen = (unsigned)len; + link.NameOffset = (unsigned)(p - Extra); + return true; +} + +bool CItem::Is_CopyLink() const +{ + CLinkInfo link; + return FindExtra_Link(link) && link.Type == NLinkType::kFileCopy; +} + +void CItem::Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) const +{ + CLinkInfo link; + if (!FindExtra_Link(link)) + return; + + if (link.Type != linkType) + { + if (linkType != NLinkType::kUnixSymLink) + return; + switch ((unsigned)link.Type) + { + case NLinkType::kUnixSymLink: + case NLinkType::kWinSymLink: + case NLinkType::kWinJunction: + break; + default: return; + } + } + + AString s; + s.SetFrom_CalcLen((const char *)(Extra + link.NameOffset), link.NameLen); + + UString unicode; + if (ConvertUTF8ToUnicode(s, unicode)) + prop = NItemName::GetOSName(unicode); +} + +bool CItem::GetAltStreamName(AString &name) const +{ + name.Empty(); + unsigned size; + int offset = FindExtra(NExtraRecordType::kSubdata, size); + if (offset < 0) + return false; + name.SetFrom_CalcLen((const char *)(Extra + (unsigned)offset), size); + return true; +} + + +class CHash +{ + bool _calcCRC; + UInt32 _crc; + int _blakeOffset; + CBlake2sp _blake; +public: + + void Init_NoCalc() + { + _calcCRC = false; + _crc = CRC_INIT_VAL; + _blakeOffset = -1; + } + + void Init(const CItem &item); + void Update(const void *data, size_t size); + UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } + + bool Check(const CItem &item, NCrypto::NRar5::CDecoder *cryptoDecoderSpec); +}; + +void CHash::Init(const CItem &item) +{ + _crc = CRC_INIT_VAL; + _calcCRC = item.Has_CRC(); + + _blakeOffset = item.FindExtra_Blake(); + if (_blakeOffset >= 0) + Blake2sp_Init(&_blake); +} + +void CHash::Update(const void *data, size_t size) +{ + if (_calcCRC) + _crc = CrcUpdate(_crc, data, size); + if (_blakeOffset >= 0) + Blake2sp_Update(&_blake, (const Byte *)data, size); +} + +bool CHash::Check(const CItem &item, NCrypto::NRar5::CDecoder *cryptoDecoderSpec) +{ + if (_calcCRC) + { + UInt32 crc = GetCRC(); + if (cryptoDecoderSpec) + crc = cryptoDecoderSpec->Hmac_Convert_Crc32(crc); + if (crc != item.CRC) + return false; + } + + if (_blakeOffset >= 0) + { + Byte digest[BLAKE2S_DIGEST_SIZE]; + Blake2sp_Final(&_blake, digest); + if (cryptoDecoderSpec) + cryptoDecoderSpec->Hmac_Convert_32Bytes(digest); + if (memcmp(digest, &item.Extra[(unsigned)_blakeOffset], BLAKE2S_DIGEST_SIZE) != 0) + return false; + } + + return true; +} + + +class COutStreamWithHash: + public ISequentialOutStream, + public CMyUnknownImp +{ + ISequentialOutStream *_stream; + UInt64 _pos; + UInt64 _size; + bool _size_Defined; + Byte *_destBuf; +public: + CHash _hash; + + COutStreamWithHash(): _destBuf(NULL) {} + + MY_UNKNOWN_IMP + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void Init(const CItem &item, Byte *destBuf) + { + _size_Defined = false; + _size = 0; + _destBuf = NULL; + if (!item.Is_UnknownSize()) + { + _size_Defined = true; + _size = item.Size; + _destBuf = destBuf; + } + _pos = 0; + _hash.Init(item); + } + UInt64 GetPos() const { return _pos; } +}; + + +STDMETHODIMP COutStreamWithHash::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + HRESULT result = S_OK; + if (_size_Defined) + { + UInt64 rem = _size - _pos; + if (size > rem) + size = (UInt32)rem; + } + if (_stream) + result = _stream->Write(data, size, &size); + if (_destBuf) + memcpy(_destBuf + (size_t)_pos, data, size); + _hash.Update(data, size); + _pos += size; + if (processedSize) + *processedSize = size; + return result; +} + + + + + +class CInArchive +{ + CAlignedBuffer<AES_BLOCK_SIZE - 1> _buf; + size_t _bufSize; + size_t _bufPos; + ISequentialInStream *_stream; + + NCrypto::NRar5::CDecoder *m_CryptoDecoderSpec; + CMyComPtr<ICompressFilter> m_CryptoDecoder; + + + + HRESULT ReadStream_Check(void *data, size_t size); + +public: + bool m_CryptoMode; + + bool WrongPassword; + bool IsArc; + bool UnexpectedEnd; + + UInt64 StreamStartPosition; + UInt64 Position; + + bool ReadVar(UInt64 &val); + + struct CHeader + { + UInt64 Type; + UInt64 Flags; + size_t ExtraSize; + UInt64 DataSize; + }; + + HRESULT ReadBlockHeader(CHeader &h); + bool ReadFileHeader(const CHeader &header, CItem &item); + void AddToSeekValue(UInt64 addValue) + { + Position += addValue; + } + + HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, ICryptoGetTextPassword *getTextPassword, + CInArcInfo &info); +}; + + +static HRESULT MySetPassword(ICryptoGetTextPassword *getTextPassword, NCrypto::NRar5::CDecoder *cryptoDecoderSpec) +{ + CMyComBSTR password; + RINOK(getTextPassword->CryptoGetTextPassword(&password)); + AString utf8; + const unsigned kPasswordLen_MAX = 127; + UString unicode = (LPCOLESTR)password; + if (unicode.Len() > kPasswordLen_MAX) + unicode.DeleteFrom(kPasswordLen_MAX); + ConvertUnicodeToUTF8(unicode, utf8); + cryptoDecoderSpec->SetPassword((const Byte *)(const char *)utf8, utf8.Len()); + return S_OK; +} + + +bool CInArchive::ReadVar(UInt64 &val) +{ + unsigned offset = ReadVarInt(_buf + _bufPos, _bufSize - _bufPos, &val); + _bufPos += offset; + return (offset != 0); +} + + +HRESULT CInArchive::ReadStream_Check(void *data, size_t size) +{ + size_t size2 = size; + RINOK(ReadStream(_stream, data, &size2)); + if (size2 == size) + return S_OK; + UnexpectedEnd = true; + return S_FALSE; +} + + +HRESULT CInArchive::ReadBlockHeader(CHeader &h) +{ + h.Type = 0; + h.Flags = 0; + h.ExtraSize = 0; + h.DataSize = 0; + + const unsigned kStartSize = 4 + 3; + const unsigned kBufSize = AES_BLOCK_SIZE + AES_BLOCK_SIZE; // must be >= kStartSize; + Byte buf[kBufSize]; + unsigned filled; + + if (m_CryptoMode) + { + RINOK(ReadStream_Check(buf, kBufSize)); + memcpy(m_CryptoDecoderSpec->_iv, buf, AES_BLOCK_SIZE); + RINOK(m_CryptoDecoderSpec->Init()); + + _buf.AllocAtLeast(1 << 12); + if (!(Byte *)_buf) + return E_OUTOFMEMORY; + + memcpy(_buf, buf + AES_BLOCK_SIZE, AES_BLOCK_SIZE); + if (m_CryptoDecoderSpec->Filter(_buf, AES_BLOCK_SIZE) != AES_BLOCK_SIZE) + return E_FAIL; + memcpy(buf, _buf, AES_BLOCK_SIZE); + filled = AES_BLOCK_SIZE; + } + else + { + RINOK(ReadStream_Check(buf, kStartSize)); + filled = kStartSize; + } + + UInt64 val; + unsigned offset = ReadVarInt(buf + 4, 3, &val); + if (offset == 0) + return S_FALSE; + { + size_t size = (size_t)val; + _bufPos = (4 + offset); + _bufSize = _bufPos + size; + if (size < 2) + return S_FALSE; + } + + size_t allocSize = _bufSize; + if (m_CryptoMode) + allocSize = (allocSize + AES_BLOCK_SIZE - 1) & ~(size_t)(AES_BLOCK_SIZE - 1); + _buf.AllocAtLeast(allocSize); + if (!(Byte *)_buf) + return E_OUTOFMEMORY; + + memcpy(_buf, buf, filled); + + size_t rem = allocSize - filled; + AddToSeekValue(allocSize + (m_CryptoMode ? AES_BLOCK_SIZE : 0)); + RINOK(ReadStream_Check(_buf + filled, rem)); + if (m_CryptoMode) + { + if (m_CryptoDecoderSpec->Filter(_buf + filled, (UInt32)rem) != rem) + return E_FAIL; + } + + if (CrcCalc(_buf + 4, _bufSize - 4) != Get32(buf)) + return S_FALSE; + + if (!ReadVar(h.Type)) return S_FALSE; + if (!ReadVar(h.Flags)) return S_FALSE; + + if (h.Flags & NHeaderFlags::kExtra) + { + UInt64 extraSize; + if (!ReadVar(extraSize)) + return S_FALSE; + if (extraSize > _bufSize) + return S_FALSE; + h.ExtraSize = (size_t)extraSize; + } + + if (h.Flags & NHeaderFlags::kData) + { + if (!ReadVar(h.DataSize)) + return S_FALSE; + } + + return S_OK; +} + + +/* +int CInArcInfo::FindExtra(unsigned type, unsigned &recordDataSize) const +{ + recordDataSize = 0; + size_t offset = 0; + + for (;;) + { + size_t rem = Extra.Size() - offset; + if (rem == 0) + return -1; + + { + UInt64 size; + unsigned num = ReadVarInt(Extra + offset, rem, &size); + if (num == 0) + return -1; + offset += num; + rem -= num; + if (size > rem) + return -1; + rem = (size_t)size; + } + { + UInt64 type2; + unsigned num = ReadVarInt(Extra + offset, rem, &type2); + if (num == 0) + return -1; + offset += num; + rem -= num; + + if (type2 == type) + { + recordDataSize = (unsigned)rem; + return (int)offset; + } + + offset += rem; + } + } +} + + +bool CInArcInfo::FindExtra_Locator(CLocator &locator) const +{ + locator.Flags = 0; + locator.QuickOpen = 0; + locator.Recovery = 0; + + unsigned size; + int offset = FindExtra(kArcExtraRecordType_Locator, size); + if (offset < 0) + return false; + const Byte *p = Extra + (unsigned)offset; + + unsigned num; + + num = ReadVarInt(p, size, &locator.Flags); + if (num == 0) return false; p += num; size -= num; + + if (locator.Is_QuickOpen()) + { + num = ReadVarInt(p, size, &locator.QuickOpen); + if (num == 0) return false; p += num; size -= num; + } + + if (locator.Is_Recovery()) + { + num = ReadVarInt(p, size, &locator.Recovery); + if (num == 0) return false; p += num; size -= num; + } + + return true; +} +*/ + + +HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit, ICryptoGetTextPassword *getTextPassword, + CInArcInfo &info) +{ + m_CryptoMode = false; + + WrongPassword = false; + IsArc = false; + UnexpectedEnd = false; + + Position = StreamStartPosition; + + UInt64 arcStartPos = StreamStartPosition; + { + Byte marker[kMarkerSize]; + RINOK(ReadStream_FALSE(stream, marker, kMarkerSize)); + if (memcmp(marker, kMarker, kMarkerSize) == 0) + Position += kMarkerSize; + else + { + if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0) + return S_FALSE; + RINOK(stream->Seek(StreamStartPosition, STREAM_SEEK_SET, NULL)); + RINOK(FindSignatureInStream(stream, kMarker, kMarkerSize, + searchHeaderSizeLimit, arcStartPos)); + arcStartPos += StreamStartPosition; + Position = arcStartPos + kMarkerSize; + RINOK(stream->Seek(Position, STREAM_SEEK_SET, NULL)); + } + } + + info.StartPos = arcStartPos; + _stream = stream; + + CHeader h; + RINOK(ReadBlockHeader(h)); + info.IsEncrypted = false; + + if (h.Type == NHeaderType::kArcEncrypt) + { + info.IsEncrypted = true; + IsArc = true; + if (!getTextPassword) + return E_NOTIMPL; + + m_CryptoMode = true; + + if (!m_CryptoDecoder) + { + m_CryptoDecoderSpec = new NCrypto::NRar5::CDecoder; + m_CryptoDecoder = m_CryptoDecoderSpec; + } + + RINOK(m_CryptoDecoderSpec->SetDecoderProps( + _buf + _bufPos, (unsigned)(_bufSize - _bufPos), false, false)); + + RINOK(MySetPassword(getTextPassword, m_CryptoDecoderSpec)); + + if (!m_CryptoDecoderSpec->CalcKey_and_CheckPassword()) + { + WrongPassword = True; + return S_FALSE; + } + + RINOK(ReadBlockHeader(h)); + } + + if (h.Type != NHeaderType::kArc) + return S_FALSE; + + IsArc = true; + info.VolNumber = 0; + + if (!ReadVar(info.Flags)) + return S_FALSE; + + if (info.Flags & NArcFlags::kVolNumber) + if (!ReadVar(info.VolNumber)) + return S_FALSE; + + if (h.ExtraSize != 0) + { + if (_bufSize - _bufPos < h.ExtraSize) + return S_FALSE; + /* + info.Extra.Alloc(h.ExtraSize); + memcpy(info.Extra, _buf + _bufPos, h.ExtraSize); + */ + _bufPos += h.ExtraSize; + + /* + CInArcInfo::CLocator locator; + if (info.FindExtra_Locator(locator)) + locator.Flags = locator.Flags; + */ + } + + if (_bufPos != _bufSize) + return S_FALSE; + + return S_OK; +} + + +bool CInArchive::ReadFileHeader(const CHeader &header, CItem &item) +{ + item.UnixMTime = 0; + item.CRC = 0; + item.Flags = 0; + + item.CommonFlags = (UInt32)header.Flags; + item.PackSize = header.DataSize; + + UInt64 flags64; + if (!ReadVar(flags64)) return false; + item.Flags = (UInt32)flags64; + + if (!ReadVar(item.Size)) return false; + + { + UInt64 attrib; + if (!ReadVar(attrib)) return false; + item.Attrib = (UInt32)attrib; + } + + if (item.Has_UnixMTime()) + { + if (_bufSize - _bufPos < 4) + return false; + item.UnixMTime = Get32(_buf + _bufPos); + _bufPos += 4; + } + + if (item.Has_CRC()) + { + if (_bufSize - _bufPos < 4) + return false; + item.CRC = Get32(_buf + _bufPos); + _bufPos += 4; + } + + { + UInt64 method; + if (!ReadVar(method)) return false; + item.Method = (UInt32)method; + } + + if (!ReadVar(item.HostOS)) return false; + + { + UInt64 len; + if (!ReadVar(len)) return false; + if (len > _bufSize - _bufPos) + return false; + item.Name.SetFrom_CalcLen((const char *)(_buf + _bufPos), (unsigned)len); + _bufPos += (unsigned)len; + } + + item.Extra.Free(); + size_t extraSize = header.ExtraSize; + if (extraSize != 0) + { + if (_bufSize - _bufPos < extraSize) + return false; + item.Extra.Alloc(extraSize); + memcpy(item.Extra, _buf + _bufPos, extraSize); + _bufPos += extraSize; + } + + + return (_bufPos == _bufSize); +} + + + +struct CLinkFile +{ + unsigned Index; + unsigned NumLinks; + CByteBuffer Data; + HRESULT Res; + bool crcOK; + + CLinkFile(): Index(0), NumLinks(0), Res(S_OK), crcOK(true) {} +}; + + +struct CUnpacker +{ + NCompress::CCopyCoder *copyCoderSpec; + CMyComPtr<ICompressCoder> copyCoder; + + CMyComPtr<ICompressCoder> LzCoders[2]; + bool NeedClearSolid[2]; + + CFilterCoder *filterStreamSpec; + CMyComPtr<ISequentialInStream> filterStream; + + NCrypto::NRar5::CDecoder *cryptoDecoderSpec; + CMyComPtr<ICompressFilter> cryptoDecoder; + + CMyComPtr<ICryptoGetTextPassword> getTextPassword; + + COutStreamWithHash *outStreamSpec; + CMyComPtr<ISequentialOutStream> outStream; + + CByteBuffer _tempBuf; + + CLinkFile *linkFile; + + CUnpacker(): linkFile(NULL) { NeedClearSolid[0] = NeedClearSolid[1] = true; } + + HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, bool isSolid, bool &wrongPassword); + + HRESULT Code(const CItem &item, const CItem &lastItem, UInt64 packSize, + ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress, + bool &isCrcOK); + + HRESULT DecodeToBuf(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, UInt64 packSize, ISequentialInStream *inStream, CByteBuffer &buffer); +}; + + +static const unsigned kLzMethodMax = 5; + +HRESULT CUnpacker::Create(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, bool isSolid, bool &wrongPassword) +{ + wrongPassword = false; + + if (item.GetAlgoVersion() != 0) + return E_NOTIMPL; + + if (!outStream) + { + outStreamSpec = new COutStreamWithHash; + outStream = outStreamSpec; + } + + unsigned method = item.GetMethod(); + + if (method == 0) + { + if (!copyCoder) + { + copyCoderSpec = new NCompress::CCopyCoder; + copyCoder = copyCoderSpec; + } + } + else + { + if (method > kLzMethodMax) + return E_NOTIMPL; + + /* + if (item.IsSplitBefore()) + return S_FALSE; + */ + + int lzIndex = item.IsService() ? 1 : 0; + CMyComPtr<ICompressCoder> &lzCoder = LzCoders[lzIndex]; + + if (!lzCoder) + { + const UInt32 methodID = 0x40305; + RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodID, false, lzCoder)); + if (!lzCoder) + return E_NOTIMPL; + } + + CMyComPtr<ICompressSetDecoderProperties2> csdp; + RINOK(lzCoder.QueryInterface(IID_ICompressSetDecoderProperties2, &csdp)); + + Byte props[2] = { (Byte)(item.GetDictSize()), (Byte)(isSolid ? 1 : 0) }; + RINOK(csdp->SetDecoderProperties2(props, 2)); + } + + unsigned cryptoSize = 0; + int cryptoOffset = item.FindExtra(NExtraRecordType::kCrypto, cryptoSize); + + if (cryptoOffset >= 0) + { + if (!filterStream) + { + filterStreamSpec = new CFilterCoder(false); + filterStream = filterStreamSpec; + } + + if (!cryptoDecoder) + { + cryptoDecoderSpec = new NCrypto::NRar5::CDecoder; + cryptoDecoder = cryptoDecoderSpec; + } + + RINOK(cryptoDecoderSpec->SetDecoderProps(item.Extra + (unsigned)cryptoOffset, cryptoSize, true, item.IsService())); + + if (!getTextPassword) + { + wrongPassword = True; + return E_NOTIMPL; + } + + RINOK(MySetPassword(getTextPassword, cryptoDecoderSpec)); + + if (!cryptoDecoderSpec->CalcKey_and_CheckPassword()) + wrongPassword = True; + } + + return S_OK; +} + + +HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSize, + ISequentialInStream *volsInStream, ISequentialOutStream *realOutStream, ICompressProgressInfo *progress, + bool &isCrcOK) +{ + isCrcOK = true; + + unsigned method = item.GetMethod(); + if (method > kLzMethodMax) + return E_NOTIMPL; + + if (linkFile && !lastItem.Is_UnknownSize()) + { + size_t dataSize = (size_t)lastItem.Size; + if (dataSize != lastItem.Size) + return E_NOTIMPL; + linkFile->Data.Alloc(dataSize); + } + + bool isCryptoMode = false; + ISequentialInStream *inStream; + + if (item.IsEncrypted()) + { + filterStreamSpec->Filter = cryptoDecoder; + filterStreamSpec->SetInStream(volsInStream); + filterStreamSpec->SetOutStreamSize(NULL); + inStream = filterStream; + isCryptoMode = true; + } + else + inStream = volsInStream; + + ICompressCoder *commonCoder = (method == 0) ? copyCoder : LzCoders[item.IsService() ? 1 : 0]; + + outStreamSpec->SetStream(realOutStream); + outStreamSpec->Init(lastItem, (linkFile ? (Byte *)linkFile->Data : NULL)); + + NeedClearSolid[item.IsService() ? 1 : 0] = false; + + HRESULT res = S_OK; + if (packSize != 0 || lastItem.Is_UnknownSize() || lastItem.Size != 0) + { + res = commonCoder->Code(inStream, outStream, &packSize, + lastItem.Is_UnknownSize() ? NULL : &lastItem.Size, progress); + } + else + { + res = res; + } + + if (isCryptoMode) + filterStreamSpec->ReleaseInStream(); + + UInt64 processedSize = outStreamSpec->GetPos(); + if (res == S_OK && !lastItem.Is_UnknownSize() && processedSize != lastItem.Size) + res = S_FALSE; + + // if (res == S_OK) + { + unsigned cryptoSize = 0; + int cryptoOffset = lastItem.FindExtra(NExtraRecordType::kCrypto, cryptoSize); + NCrypto::NRar5::CDecoder *crypto = NULL; + + if (cryptoOffset >= 0) + { + CCryptoInfo cryptoInfo; + if (cryptoInfo.Parse(lastItem.Extra + (unsigned)cryptoOffset, cryptoSize)) + if (cryptoInfo.UseMAC()) + crypto = cryptoDecoderSpec; + } + + isCrcOK = outStreamSpec->_hash.Check(lastItem, crypto); + } + + if (linkFile) + { + linkFile->Res = res; + linkFile->crcOK = isCrcOK; + if (!lastItem.Is_UnknownSize() && processedSize != lastItem.Size) + linkFile->Data.ChangeSize_KeepData((size_t)processedSize, (size_t)processedSize); + } + + return res; +} + + +HRESULT CUnpacker::DecodeToBuf(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, UInt64 packSize, ISequentialInStream *inStream, CByteBuffer &buffer) +{ + CBufPtrSeqOutStream *outSpec = new CBufPtrSeqOutStream; + CMyComPtr<ISequentialOutStream> out = outSpec; + _tempBuf.AllocAtLeast((size_t)item.Size); + outSpec->Init(_tempBuf, (size_t)item.Size); + + bool wrongPassword; + + if (item.IsSolid()) + return E_NOTIMPL; + + HRESULT res = Create(EXTERNAL_CODECS_LOC_VARS item, item.IsSolid(), wrongPassword); + + if (res == S_OK) + { + if (wrongPassword) + return S_FALSE; + + CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream; + CMyComPtr<ISequentialInStream> limitedStream(limitedStreamSpec); + limitedStreamSpec->SetStream(inStream); + limitedStreamSpec->Init(packSize); + + bool crcOK = true; + res = Code(item, item, packSize, limitedStream, out, NULL, crcOK); + if (res == S_OK) + { + if (!crcOK || outSpec->GetPos() != item.Size) + res = S_FALSE; + else + buffer.CopyFrom(_tempBuf, (size_t)item.Size); + } + } + + return res; +} + + +struct CTempBuf +{ + CByteBuffer _buf; + size_t _offset; + bool _isOK; + + void Clear() + { + _offset = 0; + _isOK = true; + } + + CTempBuf() { Clear(); } + + HRESULT Decode(DECL_EXTERNAL_CODECS_LOC_VARS + const CItem &item, + ISequentialInStream *inStream, CUnpacker &unpacker, CByteBuffer &destBuf); +}; + + +HRESULT CTempBuf::Decode(DECL_EXTERNAL_CODECS_LOC_VARS + const CItem &item, + ISequentialInStream *inStream, + CUnpacker &unpacker, + CByteBuffer &destBuf) +{ + const size_t kPackSize_Max = (1 << 24); + if (item.Size > (1 << 24) + || item.Size == 0 + || item.PackSize >= kPackSize_Max) + { + Clear(); + return S_OK; + } + + if (item.IsSplit() /* && _isOK */) + { + size_t packSize = (size_t)item.PackSize; + if (packSize > kPackSize_Max - _offset) + return S_OK; + size_t newSize = _offset + packSize; + if (newSize > _buf.Size()) + _buf.ChangeSize_KeepData(newSize, _offset); + + Byte *data = (Byte *)_buf + _offset; + RINOK(ReadStream_FALSE(inStream, data, packSize)); + + _offset += packSize; + + if (item.IsSplitAfter()) + { + CHash hash; + hash.Init(item); + hash.Update(data, packSize); + _isOK = hash.Check(item, NULL); // RAR5 doesn't use HMAC for packed part + } + } + + if (_isOK) + { + if (!item.IsSplitAfter()) + { + if (_offset == 0) + { + RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_LOC_VARS + item, item.PackSize, inStream, destBuf)); + } + else + { + CBufInStream *bufInStreamSpec = new CBufInStream; + CMyComPtr<ISequentialInStream> bufInStream = bufInStreamSpec; + bufInStreamSpec->Init(_buf, _offset); + RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_LOC_VARS + item, _offset, bufInStream, destBuf)); + } + } + } + + return S_OK; +} + + + +static const Byte kProps[] = +{ + kpidPath, + kpidIsDir, + kpidSize, + kpidPackSize, + kpidMTime, + kpidCTime, + kpidATime, + kpidAttrib, + + kpidIsAltStream, + kpidEncrypted, + kpidSolid, + kpidSplitBefore, + kpidSplitAfter, + kpidCRC, + kpidHostOS, + kpidMethod, + + kpidSymLink, + kpidHardLink, + kpidCopyLink, +}; + + +static const Byte kArcProps[] = +{ + kpidTotalPhySize, + kpidCharacts, + kpidSolid, + kpidNumBlocks, + kpidEncrypted, + kpidIsVolume, + kpidVolumeIndex, + kpidNumVolumes, + kpidComment +}; + + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + + +UInt64 CHandler::GetPackSize(unsigned refIndex) const +{ + UInt64 size = 0; + unsigned index = _refs[refIndex].Item; + for (;;) + { + const CItem &item = _items[index]; + size += item.PackSize; + if (item.NextItem < 0) + return size; + index = item.NextItem; + } +} + + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + + NCOM::CPropVariant prop; + + const CInArcInfo *arcInfo = NULL; + if (!_arcs.IsEmpty()) + arcInfo = &_arcs[0].Info; + + switch (propID) + { + case kpidVolumeIndex: if (arcInfo && arcInfo->IsVolume()) prop = arcInfo->GetVolIndex(); break; + case kpidSolid: if (arcInfo) prop = arcInfo->IsSolid(); break; + case kpidCharacts: + { + if (!_arcs.IsEmpty()) + { + FLAGS_TO_PROP(k_ArcFlags, (UInt32)arcInfo->Flags, prop); + } + break; + } + case kpidEncrypted: if (arcInfo) prop = arcInfo->IsEncrypted; break; // it's for encrypted names. + case kpidIsVolume: if (arcInfo) prop = arcInfo->IsVolume(); break; + case kpidNumVolumes: prop = (UInt32)_arcs.Size(); break; + case kpidOffset: if (arcInfo && arcInfo->StartPos != 0) prop = arcInfo->StartPos; break; + + case kpidTotalPhySize: + { + if (_arcs.Size() > 1) + { + UInt64 sum = 0; + FOR_VECTOR (v, _arcs) + sum += _arcs[v].Info.GetPhySize(); + prop = sum; + } + break; + } + + case kpidPhySize: + { + if (arcInfo) + prop = arcInfo->GetPhySize(); + break; + } + + case kpidComment: + { + // if (!_arcs.IsEmpty()) + { + // const CArc &arc = _arcs[0]; + const CByteBuffer &cmt = _comment; + if (cmt.Size() != 0 && cmt.Size() < (1 << 16)) + { + AString s; + s.SetFrom_CalcLen((const char *)(const Byte *)cmt, (unsigned)cmt.Size()); + UString unicode; + if (ConvertUTF8ToUnicode(s, unicode)) + prop = unicode; + } + } + break; + } + + case kpidNumBlocks: + { + UInt32 numBlocks = 0; + FOR_VECTOR (i, _refs) + if (!_items[_refs[i].Item].IsSolid()) + numBlocks++; + prop = (UInt32)numBlocks; + break; + } + + case kpidErrorFlags: + { + UInt32 v = _errorFlags; + if (!_isArc) + v |= kpv_ErrorFlags_IsNotArc; + prop = v; + break; + } + + /* + case kpidWarningFlags: + { + if (_warningFlags != 0) + prop = _warningFlags; + break; + } + */ + + case kpidExtension: + if (_arcs.Size() == 1) + { + if (arcInfo->IsVolume()) + { + char sz[32]; + ConvertUInt64ToString(arcInfo->GetVolIndex() + 1, sz); + unsigned len = MyStringLen(sz); + AString s = "part"; + for (; len < 2; len++) + s += '0'; + s += sz; + s += ".rar"; + prop = s; + } + } + break; + + case kpidIsAltStream: prop = true; break; + } + + prop.Detach(value); + return S_OK; + + COM_TRY_END +} + + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _refs.Size(); + return S_OK; +} + + +static const Byte kRawProps[] = +{ + kpidChecksum, + kpidNtSecure +}; + + +STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps) +{ + *numProps = ARRAY_SIZE(kRawProps); + return S_OK; +} + +STDMETHODIMP CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID) +{ + *propID = kRawProps[index]; + *name = 0; + return S_OK; +} + +STDMETHODIMP CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType) +{ + *parentType = NParentType::kDir; + *parent = (UInt32)(Int32)-1; + + if (index >= _refs.Size()) + return S_OK; + + const CRefItem &ref = _refs[index]; + const CItem &item = _items[ref.Item]; + + if (item.Is_STM() && ref.Parent >= 0) + { + *parent = (UInt32)ref.Parent; + *parentType = NParentType::kAltStream; + } + + return S_OK; +} + + +STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) +{ + *data = NULL; + *dataSize = 0; + *propType = 0; + + if (index >= _refs.Size()) + return E_INVALIDARG; + + const CItem &item = _items[_refs[index].Item]; + + if (propID == kpidNtSecure) + { + if (item.ACL >= 0) + { + const CByteBuffer &buf = _acls[item.ACL]; + *dataSize = (UInt32)buf.Size(); + *propType = NPropDataType::kRaw; + *data = (const Byte *)buf; + } + return S_OK; + } + + if (propID == kpidChecksum) + { + int hashRecOffset = item.FindExtra_Blake(); + if (hashRecOffset >= 0) + { + *dataSize = BLAKE2S_DIGEST_SIZE; + *propType = NPropDataType::kRaw; + *data = &item.Extra[hashRecOffset]; + } + return S_OK; + } + + return S_OK; +} + + +static void TimeRecordToProp(const CItem &item, unsigned stampIndex, NCOM::CPropVariant &prop) +{ + unsigned size; + int offset = item.FindExtra(NExtraRecordType::kTime, size); + if (offset < 0) + return; + + const Byte *p = item.Extra + (unsigned)offset; + UInt64 flags; + { + unsigned num = ReadVarInt(p, size, &flags); + if (num == 0) + return; + p += num; + size -= num; + } + + if ((flags & (NTimeRecord::NFlags::kMTime << stampIndex)) == 0) + return; + + unsigned numStamps = 0; + unsigned i; + for (i = 0; i < 3; i++) + if ((flags & (NTimeRecord::NFlags::kMTime << i)) != 0) + numStamps++; + unsigned stampSizeLog = ((flags & NTimeRecord::NFlags::kUnixTime) != 0) ? 2 : 3; + + if ((numStamps << stampSizeLog) != size) + return; + + numStamps = 0; + for (i = 0; i < stampIndex; i++) + if ((flags & (NTimeRecord::NFlags::kMTime << i)) != 0) + numStamps++; + + p += (numStamps << stampSizeLog); + + FILETIME ft; + if ((flags & NTimeRecord::NFlags::kUnixTime) != 0) + NWindows::NTime::UnixTimeToFileTime(Get32(p), ft); + else + { + ft.dwLowDateTime = Get32(p); + ft.dwHighDateTime = Get32(p + 4); + } + + prop = ft; +} + + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + + NCOM::CPropVariant prop; + const CRefItem &ref = _refs[index]; + const CItem &item = _items[ref.Item]; + const CItem &lastItem = _items[ref.Last]; + + switch (propID) + { + case kpidPath: + { + UString unicodeName; + + if (item.Is_STM()) + { + AString s; + if (ref.Parent >= 0) + { + CItem &mainItem = _items[_refs[ref.Parent].Item]; + s = mainItem.Name; + } + + AString name; + item.GetAltStreamName(name); + if (name[0] != ':') + s += ':'; + s += name; + if (!ConvertUTF8ToUnicode(s, unicodeName)) + break; + } + else + { + if (!ConvertUTF8ToUnicode(item.Name, unicodeName)) + break; + if (item.Version_Defined) + { + wchar_t temp[32]; + // temp[0] = ';'; + // ConvertUInt64ToString(item.Version, temp + 1); + // unicodeName += temp; + ConvertUInt64ToString(item.Version, temp); + UString s2 = L"[VER]" WSTRING_PATH_SEPARATOR; + s2 += temp; + s2.Add_PathSepar(); + unicodeName.Insert(0, s2); + } + } + + NItemName::ConvertToOSName2(unicodeName); + prop = unicodeName; + + break; + } + + case kpidIsDir: prop = item.IsDir(); break; + case kpidSize: if (!lastItem.Is_UnknownSize()) prop = lastItem.Size; break; + case kpidPackSize: prop = GetPackSize(index); break; + + case kpidMTime: + { + TimeRecordToProp(item, NTimeRecord::k_Index_MTime, prop); + if (prop.vt == VT_EMPTY && item.Has_UnixMTime()) + { + FILETIME ft; + NWindows::NTime::UnixTimeToFileTime(item.UnixMTime, ft); + prop = ft; + } + if (prop.vt == VT_EMPTY && ref.Parent >= 0) + { + const CItem &baseItem = _items[_refs[ref.Parent].Item]; + TimeRecordToProp(baseItem, NTimeRecord::k_Index_MTime, prop); + if (prop.vt == VT_EMPTY && baseItem.Has_UnixMTime()) + { + FILETIME ft; + NWindows::NTime::UnixTimeToFileTime(baseItem.UnixMTime, ft); + prop = ft; + } + } + break; + } + case kpidCTime: TimeRecordToProp(item, NTimeRecord::k_Index_CTime, prop); break; + case kpidATime: TimeRecordToProp(item, NTimeRecord::k_Index_ATime, prop); break; + + case kpidName: + { + if (item.Is_STM()) + { + AString name; + item.GetAltStreamName(name); + if (name[0] == ':') + { + name.DeleteFrontal(1); + UString unicodeName; + if (ConvertUTF8ToUnicode(name, unicodeName)) + prop = unicodeName; + } + } + break; + } + + case kpidIsAltStream: prop = item.Is_STM(); break; + + case kpidSymLink: item.Link_to_Prop(NLinkType::kUnixSymLink, prop); break; + case kpidHardLink: item.Link_to_Prop(NLinkType::kHardLink, prop); break; + case kpidCopyLink: item.Link_to_Prop(NLinkType::kFileCopy, prop); break; + + case kpidAttrib: prop = item.GetWinAttrib(); break; + case kpidEncrypted: prop = item.IsEncrypted(); break; + case kpidSolid: prop = item.IsSolid(); break; + + case kpidSplitBefore: prop = item.IsSplitBefore(); break; + case kpidSplitAfter: prop = lastItem.IsSplitAfter(); break; + case kpidCRC: + { + const CItem *item2 = (lastItem.IsSplitAfter() ? &item : &lastItem); + if (item2->Has_CRC()) + prop = item2->CRC; + break; + } + + case kpidMethod: + { + char temp[64]; + unsigned algo = item.GetAlgoVersion(); + char *s = temp; + if (algo != 0) + { + ConvertUInt32ToString(algo, s); + s += MyStringLen(s); + *s++ = ':'; + } + unsigned m = item.GetMethod(); + { + s[0] = 'm'; + s[1] = (char)(m + '0'); + s[2] = 0; + if (!item.IsDir()) + { + s[2] = ':'; + ConvertUInt32ToString(item.GetDictSize() + 17, s + 3); + } + } + + unsigned cryptoSize = 0; + int cryptoOffset = item.FindExtra(NExtraRecordType::kCrypto, cryptoSize); + if (cryptoOffset >= 0) + { + s = temp + strlen(temp); + *s++ = ' '; + strcpy(s, "AES:"); + CCryptoInfo cryptoInfo; + if (cryptoInfo.Parse(item.Extra + (unsigned)cryptoOffset, cryptoSize)) + { + s += strlen(s); + ConvertUInt32ToString(cryptoInfo.Cnt, s); + s += strlen(s); + *s++ = ':'; + ConvertUInt64ToString(cryptoInfo.Flags, s); + } + } + + prop = temp; + break; + } + + case kpidHostOS: + if (item.HostOS < ARRAY_SIZE(kHostOS)) + prop = kHostOS[(size_t)item.HostOS]; + else + prop = (UInt64)item.HostOS; + break; + } + + prop.Detach(value); + return S_OK; + + COM_TRY_END +} + + + +// ---------- Copy Links ---------- + +static int CompareItemsPaths(const CHandler &handler, unsigned p1, unsigned p2, const AString *name1) +{ + const CItem &item1 = handler._items[handler._refs[p1].Item]; + const CItem &item2 = handler._items[handler._refs[p2].Item]; + + if (item1.Version_Defined) + { + if (!item2.Version_Defined) + return -1; + int res = MyCompare(item1.Version, item2.Version); + if (res != 0) + return res; + } + else if (item2.Version_Defined) + return 1; + + if (!name1) + name1 = &item1.Name; + return strcmp(*name1, item2.Name); +} + +static int CompareItemsPaths2(const CHandler &handler, unsigned p1, unsigned p2, const AString *name1) +{ + int res = CompareItemsPaths(handler, p1, p2, name1); + if (res != 0) + return res; + return MyCompare(p1, p2); +} + +static int CompareItemsPaths_Sort(const unsigned *p1, const unsigned *p2, void *param) +{ + return CompareItemsPaths2(*(const CHandler *)param, *p1, *p2, NULL); +} + +static int FindLink(const CHandler &handler, const CUIntVector &sorted, + const AString &s, unsigned index) +{ + unsigned left = 0, right = sorted.Size(); + for (;;) + { + if (left == right) + { + if (left > 0) + { + unsigned refIndex = sorted[left - 1]; + if (CompareItemsPaths(handler, index, refIndex, &s) == 0) + return refIndex; + } + if (right < sorted.Size()) + { + unsigned refIndex = sorted[right]; + if (CompareItemsPaths(handler, index, refIndex, &s) == 0) + return refIndex; + } + return -1; + } + + unsigned mid = (left + right) / 2; + unsigned refIndex = sorted[mid]; + int compare = CompareItemsPaths2(handler, index, refIndex, &s); + if (compare == 0) + return refIndex; + if (compare < 0) + right = mid; + else + left = mid + 1; + } +} + +void CHandler::FillLinks() +{ + unsigned i; + + for (i = 0; i < _refs.Size(); i++) + { + const CItem &item = _items[_refs[i].Item]; + if (!item.IsDir() && !item.IsService() && item.NeedUse_as_CopyLink()) + break; + } + + if (i == _refs.Size()) + return; + + CUIntVector sorted; + for (i = 0; i < _refs.Size(); i++) + { + const CItem &item = _items[_refs[i].Item]; + if (!item.IsDir() && !item.IsService()) + sorted.Add(i); + } + + if (sorted.IsEmpty()) + return; + + sorted.Sort(CompareItemsPaths_Sort, (void *)this); + + AString link; + + for (i = 0; i < _refs.Size(); i++) + { + CRefItem &ref = _refs[i]; + const CItem &item = _items[ref.Item]; + if (item.IsDir() || item.IsService() || item.PackSize != 0) + continue; + CItem::CLinkInfo linkInfo; + if (!item.FindExtra_Link(linkInfo) || linkInfo.Type != NLinkType::kFileCopy) + continue; + link.SetFrom_CalcLen((const char *)(item.Extra + linkInfo.NameOffset), linkInfo.NameLen); + int linkIndex = FindLink(*this, sorted, link, i); + if (linkIndex < 0) + continue; + if ((unsigned)linkIndex >= i) + continue; // we don't support forward links that can lead to loops + const CRefItem &linkRef = _refs[linkIndex]; + const CItem &linkItem = _items[linkRef.Item]; + if (linkItem.Size == item.Size) + { + if (linkRef.Link >= 0) + ref.Link = linkRef.Link; + else if (!linkItem.NeedUse_as_CopyLink()) + ref.Link = linkIndex; + } + } +} + + + +HRESULT CHandler::Open2(IInStream *stream, + const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback *openCallback) +{ + CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; + CMyComPtr<ICryptoGetTextPassword> getTextPassword; + + NRar::CVolumeName seqName; + + UInt64 totalBytes = 0; + UInt64 curBytes = 0; + + if (openCallback) + { + openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback); + openCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword); + } + + CTempBuf tempBuf; + + CUnpacker unpacker; + unpacker.getTextPassword = getTextPassword; + + int prevSplitFile = -1; + int prevMainFile = -1; + + CInArchive arch; + + for (;;) + { + CMyComPtr<IInStream> inStream; + + if (_arcs.IsEmpty()) + inStream = stream; + else + { + if (!openVolumeCallback) + break; + + if (_arcs.Size() == 1) + { + UString baseName; + { + NCOM::CPropVariant prop; + RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); + if (prop.vt != VT_BSTR) + break; + baseName = prop.bstrVal; + } + if (!seqName.InitName(baseName)) + break; + } + + HRESULT result = openVolumeCallback->GetStream(seqName.GetNextName(), &inStream); + if (result == S_FALSE) + break; + if (result != S_OK) + return result; + if (!inStream) + break; + } + + UInt64 endPos = 0; + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &arch.StreamStartPosition)); + RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); + RINOK(inStream->Seek(arch.StreamStartPosition, STREAM_SEEK_SET, NULL)); + + if (openCallback) + { + totalBytes += endPos; + RINOK(openCallback->SetTotal(NULL, &totalBytes)); + } + + CInArcInfo arcInfoOpen; + HRESULT res = arch.Open(inStream, maxCheckStartPosition, getTextPassword, arcInfoOpen); + if (arch.IsArc && arch.UnexpectedEnd) + _errorFlags |= kpv_ErrorFlags_UnexpectedEnd; + if (_arcs.IsEmpty()) + { + _isArc = arch.IsArc; + } + + if (res != S_OK) + { + if (res != S_FALSE) + return res; + if (_arcs.IsEmpty()) + return res; + break; + } + + CArc &arc = _arcs.AddNew(); + CInArcInfo &arcInfo = arc.Info; + arcInfo = arcInfoOpen; + arc.Stream = inStream; + + CItem item; + + for (;;) + { + item.Clear(); + + arcInfo.EndPos = arch.Position; + + if (arch.Position > endPos) + { + _errorFlags |= kpv_ErrorFlags_UnexpectedEnd; + break; + } + + RINOK(inStream->Seek(arch.Position, STREAM_SEEK_SET, NULL)); + + { + CInArchive::CHeader h; + HRESULT res = arch.ReadBlockHeader(h); + if (res != S_OK) + { + if (res != S_FALSE) + return res; + if (arch.UnexpectedEnd) + { + _errorFlags |= kpv_ErrorFlags_UnexpectedEnd; + if (arcInfo.EndPos < arch.Position) + arcInfo.EndPos = arch.Position; + if (arcInfo.EndPos < endPos) + arcInfo.EndPos = endPos; + } + else + _errorFlags |= kpv_ErrorFlags_HeadersError; + break; + } + + if (h.Type == NHeaderType::kEndOfArc) + { + arcInfo.EndPos = arch.Position; + arcInfo.EndOfArchive_was_Read = true; + if (!arch.ReadVar(arcInfo.EndFlags)) + _errorFlags |= kpv_ErrorFlags_HeadersError; + if (arcInfo.IsVolume()) + { + // for multivolume archives RAR can add ZERO bytes at the end for alignment. + // We must skip these bytes to prevent phySize warning. + RINOK(inStream->Seek(arcInfo.EndPos, STREAM_SEEK_SET, NULL)); + bool areThereNonZeros; + UInt64 numZeros; + const UInt64 maxSize = 1 << 12; + RINOK(NRar::ReadZeroTail(inStream, areThereNonZeros, numZeros, maxSize)); + if (!areThereNonZeros && numZeros != 0 && numZeros <= maxSize) + arcInfo.EndPos += numZeros; + } + break; + } + + if (h.Type != NHeaderType::kFile && + h.Type != NHeaderType::kService) + { + _errorFlags |= kpv_ErrorFlags_UnsupportedFeature; + break; + } + + item.RecordType = (Byte)h.Type; + + if (!arch.ReadFileHeader(h, item)) + { + _errorFlags |= kpv_ErrorFlags_HeadersError; + break; + } + + // item.MainPartSize = (UInt32)(Position - item.Position); + item.DataPos = arch.Position; + } + + bool isOk_packSize = true; + { + arcInfo.EndPos = arch.Position; + if (arch.Position + item.PackSize < arch.Position) + { + isOk_packSize = false; + _errorFlags |= kpv_ErrorFlags_HeadersError; + if (arcInfo.EndPos < endPos) + arcInfo.EndPos = endPos; + } + else + { + arch.AddToSeekValue(item.PackSize); // Position points to next header; + arcInfo.EndPos = arch.Position; + } + } + + bool needAdd = true; + + { + if (_comment.Size() == 0 + && item.Is_CMT() + && item.PackSize < kCommentSize_Max + && item.PackSize == item.Size + && item.PackSize != 0 + && item.GetMethod() == 0 + && !item.IsSplit()) + { + RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_VARS item, item.PackSize, inStream, _comment)); + needAdd = false; + } + } + + if (needAdd) + { + CRefItem ref; + ref.Item = _items.Size(); + ref.Last = ref.Item; + ref.Parent = -1; + ref.Link = -1; + + if (item.IsService()) + { + if (item.Is_STM()) + { + if (prevMainFile >= 0) + ref.Parent = prevMainFile; + } + else + { + needAdd = false; + if (item.Is_ACL() && (!item.IsEncrypted() || arch.m_CryptoMode)) + { + if (prevMainFile >= 0 && item.Size < (1 << 24) && item.Size != 0) + { + CItem &mainItem = _items[_refs[prevMainFile].Item]; + + if (mainItem.ACL < 0) + { + CByteBuffer acl; + HRESULT res = tempBuf.Decode(EXTERNAL_CODECS_VARS item, inStream, unpacker, acl); + if (!item.IsSplitAfter()) + tempBuf.Clear(); + if (res != S_OK) + { + tempBuf.Clear(); + if (res != S_FALSE && res != E_NOTIMPL) + return res; + } + // RINOK(); + + if (res == S_OK && acl.Size() != 0) + { + if (_acls.IsEmpty() || acl != _acls.Back()) + _acls.Add(acl); + mainItem.ACL = _acls.Size() - 1; + } + } + } + } + } + } + + if (needAdd) + { + if (item.IsSplitBefore()) + { + if (prevSplitFile >= 0) + { + CRefItem &ref = _refs[prevSplitFile]; + CItem &prevItem = _items[ref.Last]; + if (item.IsNextForItem(prevItem)) + { + ref.Last = _items.Size(); + prevItem.NextItem = ref.Last; + needAdd = false; + } + } + } + } + + if (needAdd) + { + if (item.IsSplitAfter()) + prevSplitFile = _refs.Size(); + if (!item.IsService()) + prevMainFile = _refs.Size(); + _refs.Add(ref); + } + } + + { + UInt64 version; + if (item.FindExtra_Version(version)) + { + item.Version_Defined = true; + item.Version = version; + } + } + + item.VolIndex = _arcs.Size() - 1; + _items.Add(item); + + if (openCallback && (_items.Size() & 0xFF) == 0) + { + UInt64 numFiles = _items.Size(); + UInt64 numBytes = curBytes + item.DataPos; + RINOK(openCallback->SetCompleted(&numFiles, &numBytes)); + } + + if (!isOk_packSize) + break; + } + + curBytes += endPos; + if (!arcInfo.IsVolume()) + break; + if (arcInfo.EndOfArchive_was_Read + && !arcInfo.AreMoreVolumes()) + break; + } + + FillLinks(); + + return S_OK; +} + + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback *openCallback) +{ + COM_TRY_BEGIN + Close(); + return Open2(stream, maxCheckStartPosition, openCallback); + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + COM_TRY_BEGIN + _errorFlags = 0; + // _warningFlags = 0; + _isArc = false; + _refs.Clear(); + _items.Clear(); + _arcs.Clear(); + _acls.Clear(); + _comment.Free(); + return S_OK; + COM_TRY_END +} + + +class CVolsInStream: + public ISequentialInStream, + public CMyUnknownImp +{ + UInt64 _rem; + ISequentialInStream *_stream; + const CObjectVector<CArc> *_arcs; + const CObjectVector<CItem> *_items; + int _itemIndex; +public: + bool CrcIsOK; +private: + CHash _hash; +public: + MY_UNKNOWN_IMP + void Init(const CObjectVector<CArc> *arcs, + const CObjectVector<CItem> *items, + unsigned itemIndex) + { + _arcs = arcs; + _items = items; + _itemIndex = itemIndex; + _stream = NULL; + CrcIsOK = true; + } + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CVolsInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + UInt32 realProcessedSize = 0; + + while (size != 0) + { + if (!_stream) + { + if (_itemIndex < 0) + break; + const CItem &item = (*_items)[_itemIndex]; + IInStream *s = (*_arcs)[item.VolIndex].Stream; + RINOK(s->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL)); + _stream = s; + if (CrcIsOK && item.IsSplitAfter()) + _hash.Init(item); + else + _hash.Init_NoCalc(); + _rem = item.PackSize; + } + { + UInt32 cur = size; + if (cur > _rem) + cur = (UInt32)_rem; + UInt32 num = cur; + HRESULT res = _stream->Read(data, cur, &cur); + _hash.Update(data, cur); + realProcessedSize += cur; + if (processedSize) + *processedSize = realProcessedSize; + data = (Byte *)data + cur; + size -= cur; + _rem -= cur; + if (_rem == 0) + { + const CItem &item = (*_items)[_itemIndex]; + _itemIndex = item.NextItem; + if (!_hash.Check(item, NULL)) // RAR doesn't use MAC here + CrcIsOK = false; + _stream = NULL; + } + if (res != S_OK) + return res; + if (realProcessedSize != 0) + return S_OK; + if (cur == 0 && num != 0) + return S_OK; + } + } + + return S_OK; +} + + +static int FindLinkBuf(CObjectVector<CLinkFile> &linkFiles, unsigned index) +{ + unsigned left = 0, right = linkFiles.Size(); + for (;;) + { + if (left == right) + return -1; + unsigned mid = (left + right) / 2; + unsigned linkIndex = linkFiles[mid].Index; + if (index == linkIndex) + return mid; + if (index < linkIndex) + right = mid; + else + left = mid + 1; + } +} + + +static inline int DecoderRes_to_OpRes(HRESULT res, bool crcOK) +{ + if (res == E_NOTIMPL) + return NExtract::NOperationResult::kUnsupportedMethod; + // if (res == S_FALSE) + if (res != S_OK) + return NExtract::NOperationResult::kDataError; + return crcOK ? + NExtract::NOperationResult::kOK : + NExtract::NOperationResult::kCRCError; +} + + +static HRESULT CopyData_with_Progress(const Byte *data, size_t size, + ISequentialOutStream *outStream, ICompressProgressInfo *progress) +{ + size_t pos = 0; + + while (pos < size) + { + const UInt32 kStepSize = ((UInt32)1 << 24); + UInt32 cur32; + { + size_t cur = size - pos; + if (cur > kStepSize) + cur = kStepSize; + cur32 = (UInt32)cur; + } + RINOK(outStream->Write(data + pos, cur32, &cur32)); + if (cur32 == 0) + return E_FAIL; + pos += cur32; + if (progress) + { + UInt64 pos64 = pos; + RINOK(progress->SetRatioInfo(&pos64, &pos64)); + } + } + + return S_OK; +} + + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + + bool allFilesMode = (numItems == (UInt32)(Int32)-1); + if (allFilesMode) + numItems = _refs.Size(); + if (numItems == 0) + return S_OK; + + CByteArr extractStatuses(_refs.Size()); + memset(extractStatuses, 0, _refs.Size()); + + // we don't want to use temp buffer for big link files. + const size_t k_CopyLinkFile_MaxSize = (size_t)1 << (28 + sizeof(size_t) / 2); + + const Byte kStatus_Extract = 1 << 0; + const Byte kStatus_Skip = 1 << 1; + const Byte kStatus_Link = 1 << 2; + + CObjectVector<CLinkFile> linkFiles; + + { + UInt64 total = 0; + bool thereAreLinks = false; + + { + unsigned solidLimit = 0; + for (UInt32 t = 0; t < numItems; t++) + { + unsigned index = allFilesMode ? t : indices[t]; + const CRefItem &ref = _refs[index]; + const CItem &item = _items[ref.Item]; + + extractStatuses[index] |= kStatus_Extract; + total += item.Size; + + if (ref.Link >= 0) + { + if (!testMode) + { + if ((unsigned)ref.Link < index) + { + const CItem &linkItem = _items[_refs[(unsigned)ref.Link].Item]; + if (linkItem.IsSolid() && linkItem.Size <= k_CopyLinkFile_MaxSize) + { + if (extractStatuses[(unsigned)ref.Link] == 0) + total += linkItem.Size; + extractStatuses[(unsigned)ref.Link] |= kStatus_Link; + thereAreLinks = true; + } + } + } + continue; + } + + if (item.IsService()) + continue; + + if (item.IsSolid()) + { + unsigned j = index; + + while (j > solidLimit) + { + j--; + const CItem &item2 = _items[_refs[j].Item]; + if (!item2.IsService()) + { + if (extractStatuses[j] == 0) + total += item2.Size; + extractStatuses[j] |= kStatus_Skip; + if (!item2.IsSolid()) + break; + } + } + } + + solidLimit = index + 1; + } + } + + if (thereAreLinks) + { + unsigned solidLimit = 0; + + FOR_VECTOR(i, _refs) + { + if ((extractStatuses[i] & kStatus_Link) == 0) + continue; + const CItem &item = _items[_refs[i].Item]; + /* + if (item.IsService()) + continue; + */ + + CLinkFile &linkFile = linkFiles.AddNew(); + linkFile.Index = i; + + if (item.IsSolid()) + { + unsigned j = i; + + while (j > solidLimit) + { + j--; + const CItem &item2 = _items[_refs[j].Item]; + if (!item2.IsService()) + { + if (extractStatuses[j] != 0) + break; + extractStatuses[j] = kStatus_Skip; + total += item2.Size; + if (!item2.IsSolid()) + break; + } + } + } + + solidLimit = i + 1; + } + + for (UInt32 t = 0; t < numItems; t++) + { + unsigned index = allFilesMode ? t : indices[t]; + const CRefItem &ref = _refs[index]; + + int linkIndex = ref.Link; + if (linkIndex < 0 || (unsigned)linkIndex >= index) + continue; + const CItem &linkItem = _items[_refs[(unsigned)linkIndex].Item]; + if (!linkItem.IsSolid() || linkItem.Size > k_CopyLinkFile_MaxSize) + continue; + int bufIndex = FindLinkBuf(linkFiles, linkIndex); + if (bufIndex < 0) + return E_FAIL; + linkFiles[bufIndex].NumLinks++; + } + } + + RINOK(extractCallback->SetTotal(total)); + } + + + UInt64 totalUnpacked = 0; + UInt64 totalPacked = 0; + UInt64 curUnpackSize = 0; + UInt64 curPackSize = 0; + + CUnpacker unpacker; + + CVolsInStream *volsInStreamSpec = new CVolsInStream; + CMyComPtr<ISequentialInStream> volsInStream = volsInStreamSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + // bool needClearSolid = true; + + FOR_VECTOR(i, _refs) + { + if (extractStatuses[i] == 0) + continue; + + totalUnpacked += curUnpackSize; + totalPacked += curPackSize; + lps->InSize = totalPacked; + lps->OutSize = totalUnpacked; + RINOK(lps->SetCur()); + + CMyComPtr<ISequentialOutStream> realOutStream; + + Int32 askMode = + ((extractStatuses[i] & kStatus_Extract) != 0) ? (testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract) : + NExtract::NAskMode::kSkip; + + unpacker.linkFile = NULL; + + if (((extractStatuses[i] & kStatus_Link) != 0)) + { + int bufIndex = FindLinkBuf(linkFiles, i); + if (bufIndex < 0) + return E_FAIL; + unpacker.linkFile = &linkFiles[bufIndex]; + } + + UInt32 index = i; + + const CRefItem *ref = &_refs[index]; + const CItem *item = &_items[ref->Item]; + + curUnpackSize = item->Size; + curPackSize = GetPackSize(index); + + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + bool isSolid; + { + bool &needClearSolid = unpacker.NeedClearSolid[item->IsService() ? 1 : 0]; + isSolid = (item->IsSolid() && !needClearSolid); + if (item->IsService()) + isSolid = false; + needClearSolid = !item->IsSolid(); + } + + if (item->IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + + int index2 = ref->Link; + + int bufIndex = -1; + + if (index2 >= 0) + { + const CRefItem &ref2 = _refs[index2]; + const CItem &item2 = _items[ref2.Item]; + if (!item2.IsSolid()) + { + item = &item2; + ref = &ref2; + curUnpackSize = item->Size; + curPackSize = GetPackSize(index2); + } + else if ((unsigned)index2 < index) + bufIndex = FindLinkBuf(linkFiles, index2); + } + + if (!realOutStream) + { + if (testMode) + { + if (item->Is_CopyLink() && item->PackSize == 0) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + } + else + { + if (item->IsService()) + continue; + + bool needDecode = false; + + for (unsigned n = i + 1; n < _refs.Size(); n++) + { + const CItem &nextItem = _items[_refs[n].Item]; + if (nextItem.IsService()) + continue; + if (!nextItem.IsSolid()) + break; + if (extractStatuses[i] != 0) + { + needDecode = true; + break; + } + } + + if (!needDecode) + continue; + + askMode = NExtract::NAskMode::kSkip; + } + } + + RINOK(extractCallback->PrepareOperation(askMode)); + + if (bufIndex >= 0) + { + CLinkFile &linkFile = linkFiles[bufIndex]; + if (linkFile.NumLinks == 0) + return E_FAIL; + if (realOutStream) + { + RINOK(CopyData_with_Progress(linkFile.Data, linkFile.Data.Size(), realOutStream, progress)); + } + if (--linkFile.NumLinks == 0) + linkFile.Data.Free(); + RINOK(extractCallback->SetOperationResult(DecoderRes_to_OpRes(linkFile.Res, linkFile.crcOK))); + continue; + } + + if (item->Is_CopyLink() && item->PackSize == 0) + { + RINOK(extractCallback->SetOperationResult( + realOutStream ? + NExtract::NOperationResult::kUnsupportedMethod: + NExtract::NOperationResult::kOK)); + continue; + } + + volsInStreamSpec->Init(&_arcs, &_items, ref->Item); + + UInt64 packSize = curPackSize; + + if (item->IsEncrypted()) + if (!unpacker.getTextPassword) + extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&unpacker.getTextPassword); + + bool wrongPassword; + HRESULT result = unpacker.Create(EXTERNAL_CODECS_VARS *item, isSolid, wrongPassword); + + if (wrongPassword) + { + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kWrongPassword)); + continue; + } + + bool crcOK = true; + if (result == S_OK) + result = unpacker.Code(*item, _items[ref->Last], packSize, volsInStream, realOutStream, progress, crcOK); + realOutStream.Release(); + if (!volsInStreamSpec->CrcIsOK) + crcOK = false; + + int opRes = crcOK ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kCRCError; + + if (result != S_OK) + { + if (result == S_FALSE) + opRes = NExtract::NOperationResult::kDataError; + else if (result == E_NOTIMPL) + opRes = NExtract::NOperationResult::kUnsupportedMethod; + else + return result; + } + + RINOK(extractCallback->SetOperationResult(opRes)); + } + + { + FOR_VECTOR(i, linkFiles) + if (linkFiles[i].NumLinks != 0) + return E_FAIL; + } + + return S_OK; + + COM_TRY_END +} + + +IMPL_ISetCompressCodecsInfo + +REGISTER_ARC_I( + "Rar5", "rar r00", 0, 0xCC, + kMarker, + 0, + NArcInfoFlags::kFindSignature, + NULL) + +}} + + +class CBlake2spHasher: + public IHasher, + public CMyUnknownImp +{ + CBlake2sp _blake; + Byte mtDummy[1 << 7]; + +public: + CBlake2spHasher() { Init(); } + + MY_UNKNOWN_IMP + INTERFACE_IHasher(;) +}; + +STDMETHODIMP_(void) CBlake2spHasher::Init() throw() +{ + Blake2sp_Init(&_blake); +} + +STDMETHODIMP_(void) CBlake2spHasher::Update(const void *data, UInt32 size) throw() +{ + Blake2sp_Update(&_blake, (const Byte *)data, size); +} + +STDMETHODIMP_(void) CBlake2spHasher::Final(Byte *digest) throw() +{ + Blake2sp_Final(&_blake, digest); +} + +REGISTER_HASHER(CBlake2spHasher, 0x202, "BLAKE2sp", BLAKE2S_DIGEST_SIZE) diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.h b/CPP/7zip/Archive/Rar/Rar5Handler.h new file mode 100644 index 00000000..5eaf0075 --- /dev/null +++ b/CPP/7zip/Archive/Rar/Rar5Handler.h @@ -0,0 +1,410 @@ +// Rar5Handler.h + +#ifndef __RAR5_HANDLER_H +#define __RAR5_HANDLER_H + +#include "../../../../C/Blake2.h" + +#include "../../../Common/MyBuffer.h" + +#include "../../../Windows/PropVariant.h" + +#include "../../Common/CreateCoder.h" + +#include "../IArchive.h" + +namespace NArchive { +namespace NRar5 { + +namespace NHeaderFlags +{ + const unsigned kExtra = 1 << 0; + const unsigned kData = 1 << 1; + // const unsigned kUnknown = 1 << 2; + const unsigned kPrevVol = 1 << 3; + const unsigned kNextVol = 1 << 4; + // const unsigned kIsChild = 1 << 5; + // const unsigned kPreserveChild = 1 << 6; +} + +namespace NHeaderType +{ + enum + { + kArc = 1, + kFile, + kService, + kArcEncrypt, + kEndOfArc + }; +} + +namespace NArcFlags +{ + const unsigned kVol = 1 << 0; + const unsigned kVolNumber = 1 << 1; + const unsigned kSolid = 1 << 2; + // const unsigned kRecovery = 1 << 3; + // const unsigned kLocked = 1 << 4; +} + +const unsigned kArcExtraRecordType_Locator = 1; + +namespace NLocatorFlags +{ + const unsigned kQuickOpen = 1 << 0; + const unsigned kRecovery = 1 << 1; +} + +namespace NFileFlags +{ + const unsigned kIsDir = 1 << 0; + const unsigned kUnixTime = 1 << 1; + const unsigned kCrc32 = 1 << 2; + const unsigned kUnknownSize = 1 << 3; +} + +namespace NMethodFlags +{ + // const unsigned kVersionMask = 0x3F; + const unsigned kSolid = 1 << 6; +} + +namespace NArcEndFlags +{ + const unsigned kMoreVols = 1 << 0; +} + +enum EHostOS +{ + kHost_Windows = 0, + kHost_Unix +}; + + + +// ---------- Extra ---------- + +namespace NExtraRecordType +{ + enum + { + kCrypto = 1, + kHash, + kTime, + kVersion, + kLink, + kUnixOwner, + kSubdata + }; +} + +// const unsigned kCryptoAlgo_AES = 0; + +namespace NCryptoFlags +{ + const unsigned kPswCheck = 1 << 0; + const unsigned kUseMAC = 1 << 1; +} + +struct CCryptoInfo +{ + UInt64 Algo; + UInt64 Flags; + Byte Cnt; + + bool UseMAC() const { return (Flags & NCryptoFlags::kUseMAC) != 0; } + bool IsThereCheck() const { return (Flags & NCryptoFlags::kPswCheck) != 0; } + bool Parse(const Byte *p, size_t size); +}; + +const unsigned kHashID_Blake2sp = 0; + +namespace NTimeRecord +{ + enum + { + k_Index_MTime = 0, + k_Index_CTime, + k_Index_ATime + }; + + namespace NFlags + { + const unsigned kUnixTime = 1 << 0; + const unsigned kMTime = 1 << 1; + // const unsigned kCTime = 1 << 2; + // const unsigned kATime = 1 << 3; + } +} + +namespace NLinkType +{ + enum + { + kUnixSymLink = 1, + kWinSymLink, + kWinJunction, + kHardLink, + kFileCopy + }; +} + +namespace NLinkFlags +{ + const unsigned kTargetIsDir = 1 << 0; +} + + +struct CItem +{ + UInt32 CommonFlags; + UInt32 Flags; + + Byte RecordType; + bool Version_Defined; + + int ACL; + + AString Name; + + int VolIndex; + int NextItem; + + UInt32 UnixMTime; + UInt32 CRC; + UInt32 Attrib; + UInt32 Method; + + CByteBuffer Extra; + + UInt64 Size; + UInt64 PackSize; + UInt64 HostOS; + + UInt64 DataPos; + UInt64 Version; + + CItem() { Clear(); } + + void Clear() + { + CommonFlags = 0; + Flags = 0; + + VolIndex = 0; + NextItem = -1; + + Version_Defined = false; + Version = 0; + + Name.Empty(); + Extra.Free(); + ACL = -1; + } + + bool IsSplitBefore() const { return (CommonFlags & NHeaderFlags::kPrevVol) != 0; } + bool IsSplitAfter() const { return (CommonFlags & NHeaderFlags::kNextVol) != 0; } + bool IsSplit() const { return (CommonFlags & (NHeaderFlags::kPrevVol | NHeaderFlags::kNextVol)) != 0; } + + bool IsDir() const { return (Flags & NFileFlags::kIsDir) != 0; } + bool Has_UnixMTime() const { return (Flags & NFileFlags::kUnixTime) != 0; } + bool Has_CRC() const { return (Flags & NFileFlags::kCrc32) != 0; } + bool Is_UnknownSize() const { return (Flags & NFileFlags::kUnknownSize) != 0; } + + bool IsNextForItem(const CItem &prev) const + { + return !IsDir() && !prev.IsDir() && IsSplitBefore() && prev.IsSplitAfter() && (Name == prev.Name); + // && false; + } + + bool IsSolid() const { return ((UInt32)Method & NMethodFlags::kSolid) != 0; } + unsigned GetAlgoVersion() const { return (unsigned)Method & 0x3F; } + unsigned GetMethod() const { return ((unsigned)Method >> 7) & 0x7; } + UInt32 GetDictSize() const { return (((UInt32)Method >> 10) & 0xF); } + + bool IsService() const { return RecordType == NHeaderType::kService; } + + bool Is_STM() const { return IsService() && Name == "STM"; } + bool Is_CMT() const { return IsService() && Name == "CMT"; } + bool Is_ACL() const { return IsService() && Name == "ACL"; } + // bool Is_QO() const { return IsService() && Name == "QO"; } + + int FindExtra(unsigned type, unsigned &recordDataSize) const; + + bool IsEncrypted() const + { + unsigned size; + return FindExtra(NExtraRecordType::kCrypto, size) >= 0; + } + + int FindExtra_Blake() const + { + unsigned size = 0; + int offset = FindExtra(NExtraRecordType::kHash, size); + if (offset >= 0 + && size == BLAKE2S_DIGEST_SIZE + 1 + && Extra[(unsigned)offset] == kHashID_Blake2sp) + return offset + 1; + return -1; + } + + bool FindExtra_Version(UInt64 &version) const; + + struct CLinkInfo + { + UInt64 Type; + UInt64 Flags; + unsigned NameOffset; + unsigned NameLen; + }; + + bool FindExtra_Link(CLinkInfo &link) const; + void Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) const; + bool Is_CopyLink() const; + + bool NeedUse_as_CopyLink() const { return PackSize == 0 && Is_CopyLink(); } + + bool GetAltStreamName(AString &name) const; + + UInt32 GetWinAttrib() const + { + UInt32 a; + switch (HostOS) + { + case kHost_Windows: a = Attrib; break; + case kHost_Unix: a = (Attrib << 16); break; + default: a = 0; + } + // if (IsDir()) a |= FILE_ATTRIBUTE_DIRECTORY; + return a; + } + + UInt64 GetDataPosition() const { return DataPos; } +}; + + +struct CInArcInfo +{ + UInt64 Flags; + UInt64 VolNumber; + UInt64 StartPos; + UInt64 EndPos; + + UInt64 EndFlags; + bool EndOfArchive_was_Read; + + bool IsEncrypted; + + // CByteBuffer Extra; + + /* + struct CLocator + { + UInt64 Flags; + UInt64 QuickOpen; + UInt64 Recovery; + + bool Is_QuickOpen() const { return (Flags & NLocatorFlags::kQuickOpen) != 0; } + bool Is_Recovery() const { return (Flags & NLocatorFlags::kRecovery) != 0; } + }; + + int FindExtra(unsigned type, unsigned &recordDataSize) const; + bool FindExtra_Locator(CLocator &locator) const; + */ + + CInArcInfo(): + Flags(0), + VolNumber(0), + StartPos(0), + EndPos(0), + EndFlags(0), + EndOfArchive_was_Read(false), + IsEncrypted(false) + {} + + /* + void Clear() + { + Flags = 0; + VolNumber = 0; + StartPos = 0; + EndPos = 0; + EndFlags = 0; + EndOfArchive_was_Read = false; + Extra.Free(); + } + */ + + UInt64 GetPhySize() const { return EndPos - StartPos; } + + bool AreMoreVolumes() const { return (EndFlags & NArcEndFlags::kMoreVols) != 0; } + + bool IsVolume() const { return (Flags & NArcFlags::kVol) != 0; } + bool IsSolid() const { return (Flags & NArcFlags::kSolid) != 0; } + bool Is_VolNumber_Defined() const { return (Flags & NArcFlags::kVolNumber) != 0; } + + UInt64 GetVolIndex() const { return Is_VolNumber_Defined() ? VolNumber : 0; } +}; + + +struct CRefItem +{ + unsigned Item; + unsigned Last; + int Parent; + int Link; +}; + + +struct CArc +{ + CMyComPtr<IInStream> Stream; + CInArcInfo Info; +}; + + +class CHandler: + public IInArchive, + public IArchiveGetRawProps, + PUBLIC_ISetCompressCodecsInfo + public CMyUnknownImp +{ +public: + CRecordVector<CRefItem> _refs; + CObjectVector<CItem> _items; +private: + CObjectVector<CArc> _arcs; + CObjectVector<CByteBuffer> _acls; + + UInt32 _errorFlags; + // UInt32 _warningFlags; + bool _isArc; + CByteBuffer _comment; + + DECL_EXTERNAL_CODECS_VARS + + UInt64 GetPackSize(unsigned refIndex) const; + + void FillLinks(); + + HRESULT Open2(IInStream *stream, + const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback *openCallback); + +public: + MY_QUERYINTERFACE_BEGIN2(IInArchive) + MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps) + QUERY_ENTRY_ISetCompressCodecsInfo + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + INTERFACE_IInArchive(;) + INTERFACE_IArchiveGetRawProps(;) + + DECL_ISetCompressCodecsInfo +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp index 516e5d7f..d6d894f4 100644 --- a/CPP/7zip/Archive/Rar/RarHandler.cpp +++ b/CPP/7zip/Archive/Rar/RarHandler.cpp @@ -30,6 +30,7 @@ #include "../Common/ItemNameUtils.h" #include "../Common/OutStreamWithCRC.h" +#include "RarVol.h" #include "RarHandler.h" using namespace NWindows; @@ -44,6 +45,8 @@ namespace NRar { static const Byte kMarker[NHeader::kMarkerSize] = SIGNATURE; +const unsigned kPasswordLen_MAX = 127; + bool CItem::IgnoreItem() const { switch (HostOS) @@ -131,7 +134,7 @@ class CInArchive CByteBuffer _comment; CByteBuffer m_FileHeaderData; NHeader::NBlock::CBlock m_BlockHeader; - NCrypto::NRar29::CDecoder *m_RarAESSpec; + NCrypto::NRar3::CDecoder *m_RarAESSpec; CMyComPtr<ICompressFilter> m_RarAES; CBuffer<Byte> m_DecryptedData; Byte *m_DecryptedDataAligned; @@ -362,6 +365,7 @@ static int ReadTime(const Byte *p, unsigned size, Byte mask, CRarTime &rarTime) _ttt_ .DosTime = Get32(p); p += 4; size -= 4; \ READ_TIME(_mask_, _ttt_); } \ + bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item) { const Byte *pStart = p; @@ -500,7 +504,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass } if (!m_RarAES) { - m_RarAESSpec = new NCrypto::NRar29::CDecoder; + m_RarAESSpec = new NCrypto::NRar3::CDecoder; m_RarAES = m_RarAESSpec; } m_RarAESSpec->SetRar350Mode(ArcInfo.IsEncryptOld()); @@ -518,7 +522,10 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass unsigned len = 0; if (password) len = MyStringLen(password); - CByteBuffer buffer(len * 2); + if (len > kPasswordLen_MAX) + len = kPasswordLen_MAX; + + CByteArr buffer(len * 2); for (unsigned i = 0; i < len; i++) { wchar_t c = password[i]; @@ -526,7 +533,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } - RINOK(m_RarAESSpec->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size())); + m_RarAESSpec->SetPassword((const Byte *)buffer, len * 2); const UInt32 kDecryptedBufferSize = (1 << 12); if (m_DecryptedData.Size() == 0) @@ -990,121 +997,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val COM_TRY_END } -static bool IsDigit(wchar_t c) -{ - return c >= L'0' && c <= L'9'; -} -class CVolumeName -{ - bool _first; - bool _newStyle; - UString _unchangedPart; - UString _changedPart; - UString _afterPart; -public: - CVolumeName(): _newStyle(true) {}; - - bool InitName(const UString &name, bool newStyle) - { - _first = true; - _newStyle = newStyle; - int dotPos = name.ReverseFind_Dot(); - UString basePart = name; - - if (dotPos >= 0) - { - UString ext = name.Ptr(dotPos + 1); - if (ext.IsEqualTo_Ascii_NoCase("rar")) - { - _afterPart = name.Ptr(dotPos); - basePart = name.Left(dotPos); - } - else if (ext.IsEqualTo_Ascii_NoCase("exe")) - { - _afterPart.SetFromAscii(".rar"); - basePart = name.Left(dotPos); - } - else if (!_newStyle) - { - if (ext.IsEqualTo_Ascii_NoCase("000") || - ext.IsEqualTo_Ascii_NoCase("001") || - ext.IsEqualTo_Ascii_NoCase("r00") || - ext.IsEqualTo_Ascii_NoCase("r01")) - { - _afterPart.Empty(); - _first = false; - _changedPart = ext; - _unchangedPart = name.Left(dotPos + 1); - return true; - } - } - } - - if (!_newStyle) - { - _afterPart.Empty(); - _unchangedPart = basePart; - _unchangedPart += L'.'; - _changedPart.SetFromAscii("r00"); - return true; - } - - if (basePart.IsEmpty()) - return false; - unsigned i = basePart.Len(); - - do - if (!IsDigit(basePart[i - 1])) - break; - while (--i); - - _unchangedPart = basePart.Left(i); - _changedPart = basePart.Ptr(i); - return true; - } - - /* - void MakeBeforeFirstName() - { - unsigned len = _changedPart.Len(); - _changedPart.Empty(); - for (unsigned i = 0; i < len; i++) - _changedPart += L'0'; - } - */ - - UString GetNextName() - { - if (_newStyle || !_first) - { - unsigned i = _changedPart.Len(); - for (;;) - { - wchar_t c = _changedPart[--i]; - if (c == L'9') - { - c = L'0'; - _changedPart.ReplaceOneCharAtPos(i, c); - if (i == 0) - { - _changedPart.InsertAtFront(L'1'); - break; - } - continue; - } - c++; - _changedPart.ReplaceOneCharAtPos(i, c); - break; - } - } - - _first = false; - return _unchangedPart + _changedPart + _afterPart; - } -}; - -static HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize) +HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize) { areThereNonZeros = false; numZeros = 0; @@ -1136,7 +1030,6 @@ HRESULT CHandler::Open2(IInStream *stream, { CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; CMyComPtr<ICryptoGetTextPassword> getTextPassword; - CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openCallback; CVolumeName seqName; @@ -1145,8 +1038,8 @@ HRESULT CHandler::Open2(IInStream *stream, if (openCallback) { - openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback); - openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); + openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback); + openCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword); } CInArchive archive; @@ -1363,108 +1256,91 @@ struct CMethodItem }; -class CFolderInStream: +class CVolsInStream: public ISequentialInStream, public CMyUnknownImp { -public: - MY_UNKNOWN_IMP - - STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - -private: - const CObjectVector<CArc> *_archives; + UInt64 _rem; + ISequentialInStream *_stream; + const CObjectVector<CArc> *_arcs; const CObjectVector<CItem> *_items; CRefItem _refItem; unsigned _curIndex; UInt32 _crc; - bool _fileIsOpen; - CMyComPtr<ISequentialInStream> _stream; + bool _calcCrc; - HRESULT OpenStream(); - HRESULT CloseStream(); public: - void Init(const CObjectVector<CArc> *archives, - const CObjectVector<CItem> *items, - const CRefItem &refItem); - - CRecordVector<UInt32> CRCs; -}; - - -ISequentialInStream* CArc::CreateLimitedStream(UInt64 offset, UInt64 size) const -{ - CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; - CMyComPtr<ISequentialInStream> inStream(streamSpec); - Stream->Seek(offset, STREAM_SEEK_SET, NULL); - streamSpec->SetStream(Stream); - streamSpec->Init(size); - return inStream.Detach(); -} - -void CFolderInStream::Init( - const CObjectVector<CArc> *archives, - const CObjectVector<CItem> *items, - const CRefItem &refItem) -{ - _archives = archives; - _items = items; - _refItem = refItem; - _curIndex = 0; - CRCs.Clear(); - _fileIsOpen = false; -} + MY_UNKNOWN_IMP -HRESULT CFolderInStream::OpenStream() -{ - while (_curIndex < _refItem.NumItems) + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + + void Init(const CObjectVector<CArc> *arcs, + const CObjectVector<CItem> *items, + const CRefItem &refItem) { - const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex]; - _stream.Attach((*_archives)[_refItem.VolumeIndex + _curIndex]. - CreateLimitedStream(item.GetDataPosition(), item.PackSize)); - _curIndex++; - _fileIsOpen = true; - _crc = CRC_INIT_VAL; - return S_OK; + _arcs = arcs; + _items = items; + _refItem = refItem; + _curIndex = 0; + _stream = NULL; + CrcIsOK = true; } - return S_OK; -} -HRESULT CFolderInStream::CloseStream() -{ - CRCs.Add(CRC_GET_DIGEST(_crc)); - _stream.Release(); - _fileIsOpen = false; - return S_OK; -} + bool CrcIsOK; +}; -STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) + +STDMETHODIMP CVolsInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { + if (processedSize) + *processedSize = 0; UInt32 realProcessedSize = 0; - while ((_curIndex < _refItem.NumItems || _fileIsOpen) && size > 0) + + while (size != 0) { - if (_fileIsOpen) + if (!_stream) { - UInt32 localProcessedSize; - RINOK(_stream->Read( - ((Byte *)data) + realProcessedSize, size, &localProcessedSize)); - _crc = CrcUpdate(_crc, ((Byte *)data) + realProcessedSize, localProcessedSize); - if (localProcessedSize == 0) - { - RINOK(CloseStream()); - continue; - } - realProcessedSize += localProcessedSize; - size -= localProcessedSize; - break; + if (_curIndex >= _refItem.NumItems) + break; + const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex]; + IInStream *s = (*_arcs)[_refItem.VolumeIndex + _curIndex].Stream; + RINOK(s->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL)); + _stream = s; + _calcCrc = (CrcIsOK && item.IsSplitAfter()); + _crc = CRC_INIT_VAL; + _rem = item.PackSize; } - else { - RINOK(OpenStream()); + UInt32 cur = size; + if (cur > _rem) + cur = (UInt32)_rem; + UInt32 num = cur; + HRESULT res = _stream->Read(data, cur, &cur); + if (_calcCrc) + _crc = CrcUpdate(_crc, data, cur); + realProcessedSize += cur; + if (processedSize) + *processedSize = realProcessedSize; + data = (Byte *)data + cur; + size -= cur; + _rem -= cur; + if (_rem == 0) + { + const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex]; + _curIndex++; + if (_calcCrc && CRC_GET_DIGEST(_crc) != item.FileCRC) + CrcIsOK = false; + _stream = NULL; + } + if (res != S_OK) + return res; + if (realProcessedSize != 0) + return S_OK; + if (cur == 0 && num != 0) + return S_OK; } } - if (processedSize != 0) - *processedSize = realProcessedSize; + return S_OK; } @@ -1526,13 +1402,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CFilterCoder *filterStreamSpec = new CFilterCoder(false); CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec; - NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL; + NCrypto::NRar2::CDecoder *rar20CryptoDecoderSpec = NULL; CMyComPtr<ICompressFilter> rar20CryptoDecoder; - NCrypto::NRar29::CDecoder *rar29CryptoDecoderSpec = NULL; - CMyComPtr<ICompressFilter> rar29CryptoDecoder; + NCrypto::NRar3::CDecoder *rar3CryptoDecoderSpec = NULL; + CMyComPtr<ICompressFilter> rar3CryptoDecoder; - CFolderInStream *folderInStreamSpec = NULL; - CMyComPtr<ISequentialInStream> folderInStream; + CVolsInStream *volsInStreamSpec = NULL; + CMyComPtr<ISequentialInStream> volsInStream; CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; @@ -1602,26 +1478,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, outStreamSpec->Init(); realOutStream.Release(); - /* - for (unsigned partIndex = 0; partIndex < 1; partIndex++) - { - CMyComPtr<ISequentialInStream> inStream; - - // item redefinition - const CItem &item = _items[refItem.ItemIndex + partIndex]; - - CInArchive &archive = _arcs[refItem.VolumeIndex + partIndex]; - - inStream.Attach(archive.CreateLimitedStream(item.GetDataPosition(), - item.PackSize)); - */ - if (!folderInStream) + if (!volsInStream) { - folderInStreamSpec = new CFolderInStream; - folderInStream = folderInStreamSpec; + volsInStreamSpec = new CVolsInStream; + volsInStream = volsInStreamSpec; } - folderInStreamSpec->Init(&_arcs, &_items, refItem); + volsInStreamSpec->Init(&_arcs, &_items, refItem); UInt64 packSize = currentPackSize; @@ -1632,29 +1495,29 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (item.IsEncrypted()) { - CMyComPtr<ICryptoSetPassword> cryptoSetPassword; + // CMyComPtr<ICryptoSetPassword> cryptoSetPassword; if (item.UnPackVersion >= 29) { - if (!rar29CryptoDecoder) + if (!rar3CryptoDecoder) { - rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder; - rar29CryptoDecoder = rar29CryptoDecoderSpec; + rar3CryptoDecoderSpec = new NCrypto::NRar3::CDecoder; + rar3CryptoDecoder = rar3CryptoDecoderSpec; } - rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36); + rar3CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36); /* CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties; - RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, + RINOK(rar3CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &cryptoProperties)); */ - RINOK(rar29CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0)); - filterStreamSpec->Filter = rar29CryptoDecoder; + RINOK(rar3CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0)); + filterStreamSpec->Filter = rar3CryptoDecoder; } else if (item.UnPackVersion >= 20) { if (!rar20CryptoDecoder) { - rar20CryptoDecoderSpec = new NCrypto::NRar20::CDecoder; + rar20CryptoDecoderSpec = new NCrypto::NRar2::CDecoder; rar20CryptoDecoder = rar20CryptoDecoderSpec; } filterStreamSpec->Filter = rar20CryptoDecoder; @@ -1666,49 +1529,66 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, continue; } - RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword)); + // RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword)); if (!getTextPassword) extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword); - if (getTextPassword) + + if (!getTextPassword) + { + outStream.Release(); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod)); + continue; + } + + // if (getTextPassword) { CMyComBSTR password; RINOK(getTextPassword->CryptoGetTextPassword(&password)); + if (item.UnPackVersion >= 29) { - UString unicodePassword; unsigned len = 0; if (password) len = MyStringLen(password); - CByteBuffer buffer(len * 2); + if (len > kPasswordLen_MAX) + len = kPasswordLen_MAX; + CByteArr buffer(len * 2); for (unsigned i = 0; i < len; i++) { wchar_t c = password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } - RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size())); + rar3CryptoDecoderSpec->SetPassword((const Byte *)buffer, len * 2); } else { AString oemPassword; if (password) - oemPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP); - RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)(const char *)oemPassword, oemPassword.Len())); + { + UString unicode = (LPCOLESTR)password; + if (unicode.Len() > kPasswordLen_MAX) + unicode.DeleteFrom(kPasswordLen_MAX); + oemPassword = UnicodeStringToMultiByte(unicode, CP_OEMCP); + } + rar20CryptoDecoderSpec->SetPassword((const Byte *)(const char *)oemPassword, oemPassword.Len()); } } + /* else { - RINOK(cryptoSetPassword->CryptoSetPassword(0, 0)); + RINOK(cryptoSetPassword->CryptoSetPassword(NULL, 0)); } + */ - filterStreamSpec->SetInStream(folderInStream); + filterStreamSpec->SetInStream(volsInStream); filterStreamSpec->SetOutStreamSize(NULL); inStream = filterStream; } else { - inStream = folderInStream; + inStream = volsInStream; } CMyComPtr<ICompressCoder> commonCoder; @@ -1766,7 +1646,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Byte isSolid = (Byte)((IsSolid(index) || item.IsSplitBefore()) ? 1: 0); if (solidStart) { - isSolid = false; + isSolid = 0; solidStart = false; } @@ -1786,46 +1666,25 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (item.IsEncrypted()) filterStreamSpec->ReleaseInStream(); - if (result == S_FALSE) - { - outStream.Release(); - RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError)); - continue; - } - if (result != S_OK) - return result; + + const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1]; + int opRes = (volsInStreamSpec->CrcIsOK && outStreamSpec->GetCRC() == lastItem.FileCRC) ? + NExtract::NOperationResult::kOK: + NExtract::NOperationResult::kCRCError; + outStream.Release(); - /* - if (refItem.NumItems == 1 && - !item.IsSplitBefore() && !item.IsSplitAfter()) - */ - { - const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1]; - bool crcOK = outStreamSpec->GetCRC() == lastItem.FileCRC; - outStream.Release(); - RINOK(extractCallback->SetOperationResult(crcOK ? - NExtract::NOperationResult::kOK: - NExtract::NOperationResult::kCRCError)); - } - /* - else + if (result != S_OK) { - bool crcOK = true; - for (unsigned partIndex = 0; partIndex < refItem.NumItems; partIndex++) - { - const CItem &item = _items[refItem.ItemIndex + partIndex]; - if (item.FileCRC != folderInStreamSpec->CRCs[partIndex]) - { - crcOK = false; - break; - } - } - RINOK(extractCallback->SetOperationResult(crcOK ? - NExtract::NOperationResult::kOK: - NExtract::NOperationResult::kCRCError)); + if (result == S_FALSE) + opRes = NExtract::NOperationResult::kDataError; + else if (result == E_NOTIMPL) + opRes = NExtract::NOperationResult::kUnsupportedMethod; + else + return result; } - */ + RINOK(extractCallback->SetOperationResult(opRes)); } + return S_OK; COM_TRY_END } diff --git a/CPP/7zip/Archive/Rar/RarVol.h b/CPP/7zip/Archive/Rar/RarVol.h new file mode 100644 index 00000000..d0f91de6 --- /dev/null +++ b/CPP/7zip/Archive/Rar/RarVol.h @@ -0,0 +1,129 @@ +// RarVol.h + +#ifndef __ARCHIVE_RAR_VOL_H +#define __ARCHIVE_RAR_VOL_H + +#include "../../../Common/StringConvert.h" + +#include "RarHeader.h" + +namespace NArchive { +namespace NRar { + +inline bool IsDigit(wchar_t c) +{ + return c >= L'0' && c <= L'9'; +} + +class CVolumeName +{ + bool _first; + bool _newStyle; + UString _unchangedPart; + UString _changedPart; + UString _afterPart; +public: + CVolumeName(): _newStyle(true) {}; + + bool InitName(const UString &name, bool newStyle = true) + { + _first = true; + _newStyle = newStyle; + int dotPos = name.ReverseFind_Dot(); + UString basePart = name; + + if (dotPos >= 0) + { + UString ext = name.Ptr(dotPos + 1); + if (ext.IsEqualTo_Ascii_NoCase("rar")) + { + _afterPart = name.Ptr(dotPos); + basePart = name.Left(dotPos); + } + else if (ext.IsEqualTo_Ascii_NoCase("exe")) + { + _afterPart.SetFromAscii(".rar"); + basePart = name.Left(dotPos); + } + else if (!_newStyle) + { + if (ext.IsEqualTo_Ascii_NoCase("000") || + ext.IsEqualTo_Ascii_NoCase("001") || + ext.IsEqualTo_Ascii_NoCase("r00") || + ext.IsEqualTo_Ascii_NoCase("r01")) + { + _afterPart.Empty(); + _first = false; + _changedPart = ext; + _unchangedPart = name.Left(dotPos + 1); + return true; + } + } + } + + if (!_newStyle) + { + _afterPart.Empty(); + _unchangedPart = basePart; + _unchangedPart += L'.'; + _changedPart.SetFromAscii("r00"); + return true; + } + + if (basePart.IsEmpty()) + return false; + unsigned i = basePart.Len(); + + do + if (!IsDigit(basePart[i - 1])) + break; + while (--i); + + _unchangedPart = basePart.Left(i); + _changedPart = basePart.Ptr(i); + return true; + } + + /* + void MakeBeforeFirstName() + { + unsigned len = _changedPart.Len(); + _changedPart.Empty(); + for (unsigned i = 0; i < len; i++) + _changedPart += L'0'; + } + */ + + UString GetNextName() + { + if (_newStyle || !_first) + { + unsigned i = _changedPart.Len(); + for (;;) + { + wchar_t c = _changedPart[--i]; + if (c == L'9') + { + c = L'0'; + _changedPart.ReplaceOneCharAtPos(i, c); + if (i == 0) + { + _changedPart.InsertAtFront(L'1'); + break; + } + continue; + } + c++; + _changedPart.ReplaceOneCharAtPos(i, c); + break; + } + } + + _first = false; + return _unchangedPart + _changedPart + _afterPart; + } +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp index ae005ac5..8dd99869 100644 --- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp +++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp @@ -29,11 +29,13 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro { NCOM::CPropVariant prop; RINOK(callback->GetProperty(index, propId, &prop)); + if (prop.vt == VT_BSTR) { UString s = prop.bstrVal; if (convertSlash) s = NItemName::MakeLegalName(s); + if (codePage == CP_UTF8) { ConvertUnicodeToUTF8(s, res); @@ -44,9 +46,11 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro } else if (prop.vt != VT_EMPTY) return E_INVALIDARG; + return S_OK; } + // sort old files with original order. static int CompareUpdateItems(void *const *p1, void *const *p2, void *) @@ -57,33 +61,39 @@ static int CompareUpdateItems(void *const *p1, void *const *p2, void *) { if (u2.NewProps) return -1; - return MyCompare(u1.IndexInArchive, u2.IndexInArchive); + return MyCompare(u1.IndexInArc, u2.IndexInArc); } if (!u2.NewProps) return 1; return MyCompare(u1.IndexInClient, u2.IndexInClient); } + STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *callback) { COM_TRY_BEGIN + if ((_stream && (_error != k_ErrorType_OK /* || _isSparse */)) || _seqStream) return E_NOTIMPL; CObjectVector<CUpdateItem> updateItems; UINT codePage = (_forceCodePage ? _specifiedCodePage : _openCodePage); + for (UInt32 i = 0; i < numItems; i++) { CUpdateItem ui; Int32 newData; Int32 newProps; - UInt32 indexInArchive; + UInt32 indexInArc; + if (!callback) return E_FAIL; - RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive)); + + RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArc)); + ui.NewProps = IntToBool(newProps); ui.NewData = IntToBool(newData); - ui.IndexInArchive = indexInArchive; + ui.IndexInArc = indexInArc; ui.IndexInClient = i; if (IntToBool(newProps)) @@ -109,6 +119,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt else ui.Mode = prop.ulVal; } + { NCOM::CPropVariant prop; RINOK(callback->GetProperty(i, kpidMTime, &prop)); @@ -119,6 +130,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt else ui.MTime = NTime::FileTimeToUnixTime64(prop.filetime); } + RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, true)); if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/') ui.Name += '/'; @@ -139,14 +151,18 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt return E_INVALIDARG; */ } + updateItems.Add(ui); } + if (_thereIsPaxExtendedHeader) { // we restore original order of files, if there is pax header block updateItems.Sort(CompareUpdateItems, NULL); } + return UpdateArchive(_stream, outStream, _items, updateItems, codePage, callback); + COM_TRY_END } diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp index 3adbdee9..0cdb30d1 100644 --- a/CPP/7zip/Archive/Tar/TarUpdate.cpp +++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp @@ -43,7 +43,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, if (ui.NewData) complexity += ui.Size; else - complexity += inputItems[ui.IndexInArchive].GetFullSize(); + complexity += inputItems[ui.IndexInArc].GetFullSize(); } RINOK(updateCallback->SetTotal(complexity)); @@ -68,12 +68,14 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, const CUpdateItem &ui = updateItems[i]; CItem item; + if (ui.NewProps) { item.Mode = ui.Mode; item.Name = ui.Name; item.User = ui.User; item.Group = ui.Group; + if (ui.IsDir) { item.LinkFlag = NFileHeader::NLinkFlag::kDirectory; @@ -84,6 +86,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, item.LinkFlag = NFileHeader::NLinkFlag::kNormal; item.PackSize = ui.Size; } + item.MTime = ui.MTime; item.DeviceMajorDefined = false; item.DeviceMinorDefined = false; @@ -92,7 +95,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, memcpy(item.Magic, NFileHeader::NMagic::kUsTar_00, 8); } else - item = inputItems[ui.IndexInArchive]; + item = inputItems[ui.IndexInArc]; AString symLink; if (ui.NewData || ui.NewProps) @@ -116,6 +119,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, CMyComPtr<ISequentialInStream> fileInStream; bool needWrite = true; + if (!symLink.IsEmpty()) { item.PackSize = 0; @@ -124,6 +128,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, else { HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream); + if (res == S_FALSE) needWrite = false; else @@ -141,10 +146,17 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, if (getProps->GetProps(&size2, NULL, NULL, &mTime, NULL) == S_OK) { item.PackSize = size2; + item.Size = size2; item.MTime = NWindows::NTime::FileTimeToUnixTime64(mTime);; } } } + else + { + item.PackSize = 0; + item.Size = 0; + } + { AString hardLink; RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidHardLink, hardLink, codePage, true)); @@ -183,13 +195,15 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, RINOK(outArchive.FillDataResidual(item.PackSize)); } } + complexity += item.PackSize; RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); } else { - const CItemEx &existItem = inputItems[ui.IndexInArchive]; + const CItemEx &existItem = inputItems[ui.IndexInArc]; UInt64 size; + if (ui.NewProps) { // memcpy(item.Magic, NFileHeader::NMagic::kEmpty, 8); @@ -225,12 +239,13 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, RINOK(inStream->Seek(existItem.HeaderPos, STREAM_SEEK_SET, NULL)); size = existItem.GetFullSize(); } + streamSpec->Init(size); if (opCallback) { RINOK(opCallback->ReportOperation( - NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArchive, + NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArc, NUpdateNotifyOp::kReplicate)) } @@ -242,6 +257,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, complexity += size; } } + lps->InSize = lps->OutSize = complexity; RINOK(lps->SetCur()); return outArchive.WriteFinishHeader(); diff --git a/CPP/7zip/Archive/Tar/TarUpdate.h b/CPP/7zip/Archive/Tar/TarUpdate.h index c2393416..b758635f 100644 --- a/CPP/7zip/Archive/Tar/TarUpdate.h +++ b/CPP/7zip/Archive/Tar/TarUpdate.h @@ -4,6 +4,7 @@ #define __TAR_UPDATE_H #include "../IArchive.h" + #include "TarItem.h" namespace NArchive { @@ -11,10 +12,10 @@ namespace NTar { struct CUpdateItem { - int IndexInArchive; + int IndexInArc; int IndexInClient; - Int64 MTime; UInt64 Size; + Int64 MTime; UInt32 Mode; bool NewData; bool NewProps; @@ -22,6 +23,8 @@ struct CUpdateItem AString Name; AString User; AString Group; + + CUpdateItem(): Size(0), IsDir(false) {} }; HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, diff --git a/CPP/7zip/Archive/XarHandler.cpp b/CPP/7zip/Archive/XarHandler.cpp index 7e89bf48..5ef3bdf9 100644 --- a/CPP/7zip/Archive/XarHandler.cpp +++ b/CPP/7zip/Archive/XarHandler.cpp @@ -358,15 +358,24 @@ HRESULT CHandler::Open2(IInStream *stream) return S_FALSE; UInt64 totalPackSize = 0; + unsigned numMainFiles = 0; + FOR_VECTOR(i, _files) { const CFile &file = _files[i]; file.UpdateTotalPackSize(totalPackSize); if (file.Name == "Payload") + { _mainSubfile = i; + numMainFiles++; + } if (file.Name == "PackageInfo") _is_pkg = true; } + + if (numMainFiles > 1) + _mainSubfile = -1; + _phySize = _dataStartPos + totalPackSize; return S_OK; diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp index f1c8b227..aa06c4f8 100644 --- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp @@ -207,7 +207,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt } if (IntToBool(newData)) { - UInt64 size; + UInt64 size = 0; + if (!ui.IsDir) { NCOM::CPropVariant prop; RINOK(callback->GetProperty(i, kpidSize, &prop)); @@ -219,6 +220,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt largestSizeDefined = true; } ui.Size = size; + // ui.Size -= ui.Size / 2; } updateItems.Add(ui); diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index 6f495305..3c466424 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -591,6 +591,29 @@ static bool FlagsAreSame(const CItem &i1, const CItem &i2) return ((i1.Flags & mask) == (i2.Flags & mask)); } +// #ifdef _WIN32 +static bool AreEqualPaths_IgnoreSlashes(const char *s1, const char *s2) +{ + for (;;) + { + char c1 = *s1++; + char c2 = *s2++; + if (c1 == c2) + { + if (c1 == 0) + return true; + } + else + { + if (c1 == '\\') c1 = '/'; + if (c2 == '\\') c2 = '/'; + if (c1 != c2) + return false; + } + } +} +// #endif + static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem) { if (!FlagsAreSame(cdItem, localItem)) @@ -611,7 +634,30 @@ static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem) return false; */ if (cdItem.Name != localItem.Name) - return false; + { + // #ifdef _WIN32 + // some xap files use backslash in central dir items. + // we can ignore such errors in windows, where all slashes are converted to backslashes + unsigned hostOs = cdItem.GetHostOS(); + + if (hostOs == NFileHeader::NHostOS::kFAT || + hostOs == NFileHeader::NHostOS::kNTFS) + { + if (!AreEqualPaths_IgnoreSlashes(cdItem.Name, localItem.Name)) + { + // pkzip 2.50 uses DOS encoding in central dir and WIN encoding in local header. + // so we ignore that error + if (hostOs != NFileHeader::NHostOS::kFAT + || cdItem.MadeByVersion.Version != 25) + return false; + } + } + /* + else + #endif + return false; + */ + } return true; } diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp index 9a9526cc..7d03056c 100644 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -103,7 +103,8 @@ static void SetFileHeader( item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir; item.Method = kMethodForDirectory; item.PackSize = 0; - item.Crc = 0; // test it + item.Size = 0; + item.Crc = 0; } } diff --git a/CPP/7zip/Bundles/Fm/FM.dsp b/CPP/7zip/Bundles/Fm/FM.dsp index dfb0bb47..057da977 100644 --- a/CPP/7zip/Bundles/Fm/FM.dsp +++ b/CPP/7zip/Bundles/Fm/FM.dsp @@ -332,14 +332,6 @@ SOURCE=..\..\Archive\7z\7zUpdate.h # PROP Default_Filter "" # Begin Source File -SOURCE=..\..\Archive\Common\CoderMixer.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Common\CoderMixer.h -# End Source File -# Begin Source File - SOURCE=..\..\Archive\Common\CoderMixer2.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/Bundles/Format7zF/Arc.mak b/CPP/7zip/Bundles/Format7zF/Arc.mak index c2f415cf..a1221c61 100644 --- a/CPP/7zip/Bundles/Format7zF/Arc.mak +++ b/CPP/7zip/Bundles/Format7zF/Arc.mak @@ -141,6 +141,7 @@ NSIS_OBJS = \ RAR_OBJS = \ $O\RarHandler.obj \ + $O\Rar5Handler.obj \ TAR_OBJS = \ $O\TarHandler.obj \ @@ -212,6 +213,7 @@ COMPRESS_OBJS = \ $O\Rar2Decoder.obj \ $O\Rar3Decoder.obj \ $O\Rar3Vm.obj \ + $O\Rar5Decoder.obj \ $O\RarCodecsRegister.obj \ $O\ShrinkDecoder.obj \ $O\ZlibDecoder.obj \ @@ -222,11 +224,13 @@ CRYPTO_OBJS = \ $O\7zAes.obj \ $O\7zAesRegister.obj \ $O\HmacSha1.obj \ + $O\HmacSha256.obj \ $O\MyAes.obj \ $O\MyAesReg.obj \ $O\Pbkdf2HmacSha1.obj \ $O\RandGen.obj \ $O\Rar20Crypto.obj \ + $O\Rar5Aes.obj \ $O\RarAes.obj \ $O\WzAes.obj \ $O\ZipCrypto.obj \ @@ -239,6 +243,7 @@ C_OBJS = \ $O\Alloc.obj \ $O\Bcj2.obj \ $O\Bcj2Enc.obj \ + $O\Blake2s.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp index 82df284c..169d9f0e 100644 --- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp +++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp @@ -243,6 +243,10 @@ SOURCE=..\..\..\Common\CrcReg.cpp # End Source File # Begin Source File +SOURCE=..\..\..\Common\Defs.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\DynamicBuffer.h # End Source File # Begin Source File @@ -452,6 +456,24 @@ SOURCE=..\..\Compress\Rar3Vm.h # End Source File # Begin Source File +SOURCE=..\..\Compress\Rar5Decoder.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Rar5Decoder.h +# End Source File +# Begin Source File + SOURCE=..\..\Compress\RarCodecsRegister.cpp # End Source File # End Group @@ -821,6 +843,14 @@ SOURCE=..\..\Crypto\HmacSha1.h # End Source File # Begin Source File +SOURCE=..\..\Crypto\HmacSha256.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\HmacSha256.h +# End Source File +# Begin Source File + SOURCE=..\..\Crypto\MyAes.cpp # End Source File # Begin Source File @@ -887,6 +917,14 @@ SOURCE=..\..\Crypto\Rar20Crypto.h # End Source File # Begin Source File +SOURCE=..\..\Crypto\Rar5Aes.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Rar5Aes.h +# End Source File +# Begin Source File + SOURCE=..\..\Crypto\RarAes.cpp # End Source File # Begin Source File @@ -1319,6 +1357,26 @@ SOURCE=..\..\..\..\C\Bcj2Enc.c # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Blake2.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Blake2s.c + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Bra.c !IF "$(CFG)" == "7z - Win32 Release" @@ -1874,6 +1932,14 @@ SOURCE=..\..\Archive\7z\7zUpdateItem.h # PROP Default_Filter "" # Begin Source File +SOURCE=..\..\Archive\Rar\Rar5Handler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Rar\Rar5Handler.h +# End Source File +# Begin Source File + SOURCE=..\..\Archive\Rar\RarHandler.cpp # End Source File # Begin Source File @@ -1888,6 +1954,10 @@ SOURCE=..\..\Archive\Rar\RarHeader.h SOURCE=..\..\Archive\Rar\RarItem.h # End Source File +# Begin Source File + +SOURCE=..\..\Archive\Rar\RarVol.h +# End Source File # End Group # Begin Group "Cab" diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp index 5b64b524..0e8586e9 100644 --- a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp +++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp @@ -12,7 +12,7 @@ #define MY_SET_BINARY_MODE(file) #endif -// #include "../../../Common/MyWindows.h" +#include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" #include "../../../../C/7zVersion.h" diff --git a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp index 01089c5e..781f810c 100644 --- a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp +++ b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../Common/MyWindows.h" + #include "../../../Common/MyInitGuid.h" #include "../../../Common/CommandLineParser.h" diff --git a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp index 611ef651..cd2584fd 100644 --- a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp +++ b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../Common/MyWindows.h" + #include "../../../Common/MyInitGuid.h" #include "../../../Common/CommandLineParser.h" diff --git a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp index ee57d445..c301ecf8 100644 --- a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp +++ b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../Common/MyWindows.h" + #include <Shlwapi.h> #include "../../../Common/MyInitGuid.h" diff --git a/CPP/7zip/Common/FilterCoder.h b/CPP/7zip/Common/FilterCoder.h index cde33c88..224ff2ca 100644 --- a/CPP/7zip/Common/FilterCoder.h +++ b/CPP/7zip/Common/FilterCoder.h @@ -19,7 +19,7 @@ struct CAlignedMidBuffer { - #ifndef _WIN32 + #ifdef _WIN32 Byte *_buf; diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp index 2ea718e7..77665ae1 100644 --- a/CPP/7zip/Common/LimitedStreams.cpp +++ b/CPP/7zip/Common/LimitedStreams.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include <string.h> + #include "LimitedStreams.h" #include "../../Common/Defs.h" diff --git a/CPP/7zip/Common/PropId.cpp b/CPP/7zip/Common/PropId.cpp index 2ce6fd85..11d20d55 100644 --- a/CPP/7zip/Common/PropId.cpp +++ b/CPP/7zip/Common/PropId.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../Common/MyWindows.h" + #include "../PropID.h" // VARTYPE @@ -101,5 +103,6 @@ const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] = VT_UI8, VT_UI8, VT_BOOL, - VT_BSTR // kpidOutName + VT_BSTR, + VT_BSTR }; diff --git a/CPP/7zip/Common/UniqBlocks.cpp b/CPP/7zip/Common/UniqBlocks.cpp index a2cacdde..8f754e17 100644 --- a/CPP/7zip/Common/UniqBlocks.cpp +++ b/CPP/7zip/Common/UniqBlocks.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include <string.h> + #include "UniqBlocks.h" unsigned CUniqBlocks::AddUniq(const Byte *data, size_t size) diff --git a/CPP/7zip/Compress/Codec.def b/CPP/7zip/Compress/Codec.def index ebf73a3b..f55b2d57 100644 --- a/CPP/7zip/Compress/Codec.def +++ b/CPP/7zip/Compress/Codec.def @@ -2,3 +2,5 @@ EXPORTS CreateObject PRIVATE GetNumberOfMethods PRIVATE GetMethodProperty PRIVATE + CreateDecoder PRIVATE + CreateEncoder PRIVATE diff --git a/CPP/7zip/Compress/DeflateEncoder.cpp b/CPP/7zip/Compress/DeflateEncoder.cpp index eb012e8d..94d0092b 100644 --- a/CPP/7zip/Compress/DeflateEncoder.cpp +++ b/CPP/7zip/Compress/DeflateEncoder.cpp @@ -130,14 +130,14 @@ CCoder::CCoder(bool deflate64Mode): m_Values(0), m_Tables(0) { - { - CEncProps props; - SetProps(&props); - } m_MatchMaxLen = deflate64Mode ? kMatchMaxLen64 : kMatchMaxLen32; m_NumLenCombinations = deflate64Mode ? kNumLenSymbols64 : kNumLenSymbols32; m_LenStart = deflate64Mode ? kLenStart64 : kLenStart32; m_LenDirectBits = deflate64Mode ? kLenDirectBits64 : kLenDirectBits32; + { + CEncProps props; + SetProps(&props); + } MatchFinder_Construct(&_lzInWindow); } diff --git a/CPP/7zip/Compress/HuffmanDecoder.h b/CPP/7zip/Compress/HuffmanDecoder.h index 6faf8005..65e0f93c 100644 --- a/CPP/7zip/Compress/HuffmanDecoder.h +++ b/CPP/7zip/Compress/HuffmanDecoder.h @@ -22,11 +22,13 @@ public: bool SetCodeLengths(const Byte *lens) { - unsigned lenCounts[kNumBitsMax + 1]; + UInt32 lenCounts[kNumBitsMax + 1]; UInt32 tmpPositions[kNumBitsMax + 1]; + unsigned i; for (i = 1; i <= kNumBitsMax; i++) lenCounts[i] = 0; + UInt32 symbol; for (symbol = 0; symbol < m_NumSymbols; symbol++) @@ -42,7 +44,7 @@ public: m_Positions[0] = m_Limits[0] = 0; UInt32 startPos = 0; UInt32 index = 0; - const UInt32 kMaxValue = (1 << kNumBitsMax); + const UInt32 kMaxValue = (UInt32)1 << kNumBitsMax; for (i = 1; i <= kNumBitsMax; i++) { @@ -74,14 +76,15 @@ public: UInt32 DecodeSymbol(TBitDecoder *bitStream) { unsigned numBits; - UInt32 value = bitStream->GetValue(kNumBitsMax); - if (value < m_Limits[kNumTableBits]) - numBits = m_Lengths[value >> (kNumBitsMax - kNumTableBits)]; + UInt32 val = bitStream->GetValue(kNumBitsMax); + + if (val < m_Limits[kNumTableBits]) + numBits = m_Lengths[val >> (kNumBitsMax - kNumTableBits)]; else - for (numBits = kNumTableBits + 1; value >= m_Limits[numBits]; numBits++); + for (numBits = kNumTableBits + 1; val >= m_Limits[numBits]; numBits++); + bitStream->MovePos(numBits); - UInt32 index = m_Positions[numBits] + - ((value - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits)); + UInt32 index = m_Positions[numBits] + ((val - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits)); if (index >= m_NumSymbols) // throw CDecoderException(); // test it return 0xFFFFFFFF; diff --git a/CPP/7zip/Compress/Rar1Decoder.cpp b/CPP/7zip/Compress/Rar1Decoder.cpp index 12de7e19..1aaedcc1 100644 --- a/CPP/7zip/Compress/Rar1Decoder.cpp +++ b/CPP/7zip/Compress/Rar1Decoder.cpp @@ -486,7 +486,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) { if (size < 1) return E_INVALIDARG; - m_IsSolid = (data[0] != 0); + m_IsSolid = ((data[0] & 1) != 0); return S_OK; } diff --git a/CPP/7zip/Compress/Rar2Decoder.cpp b/CPP/7zip/Compress/Rar2Decoder.cpp index 6f42d2e6..5082ded3 100644 --- a/CPP/7zip/Compress/Rar2Decoder.cpp +++ b/CPP/7zip/Compress/Rar2Decoder.cpp @@ -394,7 +394,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) { if (size < 1) return E_INVALIDARG; - m_IsSolid = (data[0] != 0); + m_IsSolid = ((data[0] & 1) != 0); return S_OK; } diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp index f0553c85..81eb8285 100644 --- a/CPP/7zip/Compress/Rar3Decoder.cpp +++ b/CPP/7zip/Compress/Rar3Decoder.cpp @@ -140,6 +140,8 @@ void CDecoder::ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef) NVm::SetValue32(&tempFilter->GlobalData[0x24], (UInt32)_writtenFileSize); NVm::SetValue32(&tempFilter->GlobalData[0x28], (UInt32)(_writtenFileSize >> 32)); CFilter *filter = _filters[tempFilter->FilterIndex]; + if (!filter->IsSupported) + _unsupportedFilter = true; _vm.Execute(filter, tempFilter, outBlockRef, filter->GlobalData); delete tempFilter; _tempFilters[tempFilterIndex] = 0; @@ -226,12 +228,15 @@ void CDecoder::InitFilters() _filters.Clear(); } +static const unsigned MAX_UNPACK_FILTERS = 8192; + bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize) { CMemBitDecoder inp; inp.Init(_vmData, codeSize); UInt32 filterIndex; + if (firstByte & 0x80) { filterIndex = inp.ReadEncodedUInt32(); @@ -242,6 +247,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize) } else filterIndex = _lastFilter; + if (filterIndex > (UInt32)_filters.Size()) return false; _lastFilter = filterIndex; @@ -251,7 +257,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize) if (newFilter) { // check if too many filters - if (filterIndex > 1024) + if (filterIndex > MAX_UNPACK_FILTERS) return false; filter = new CFilter; _filters.Add(filter); @@ -301,6 +307,8 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize) if (initMask & (1 << i)) tempFilter->InitR[i] = inp.ReadEncodedUInt32(); } + + bool isOK = true; if (newFilter) { UInt32 vmCodeSize = inp.ReadEncodedUInt32(); @@ -308,7 +316,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize) return false; for (UInt32 i = 0; i < vmCodeSize; i++) _vmCode[i] = (Byte)inp.ReadBits(8); - filter->PrepareProgram(_vmCode, vmCodeSize); + isOK = filter->PrepareProgram(_vmCode, vmCodeSize); } Byte *globalData = &tempFilter->GlobalData[0]; @@ -331,7 +339,8 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize) for (UInt32 i = 0; i < dataSize; i++) dest[i] = (Byte)inp.ReadBits(8); } - return true; + + return isOK; } bool CDecoder::ReadVmCodeLZ() @@ -796,6 +805,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) { _writtenFileSize = 0; + _unsupportedFilter = false; if (!m_IsSolid) { _lzSize = 0; @@ -843,6 +853,10 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize)); if (_writtenFileSize < _unpackSize) return S_FALSE; + + if (_unsupportedFilter) + return E_NOTIMPL; + return S_OK; } @@ -892,7 +906,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) { if (size < 1) return E_INVALIDARG; - m_IsSolid = (data[0] != 0); + m_IsSolid = ((data[0] & 1) != 0); return S_OK; } diff --git a/CPP/7zip/Compress/Rar3Decoder.h b/CPP/7zip/Compress/Rar3Decoder.h index 77379858..d8dfd11a 100644 --- a/CPP/7zip/Compress/Rar3Decoder.h +++ b/CPP/7zip/Compress/Rar3Decoder.h @@ -194,6 +194,7 @@ class CDecoder: bool m_IsSolid; bool _lzMode; + bool _unsupportedFilter; UInt32 PrevAlignBits; UInt32 PrevAlignCount; diff --git a/CPP/7zip/Compress/Rar3Vm.cpp b/CPP/7zip/Compress/Rar3Vm.cpp index 3cbfb0e1..5dca9eab 100644 --- a/CPP/7zip/Compress/Rar3Vm.cpp +++ b/CPP/7zip/Compress/Rar3Vm.cpp @@ -12,6 +12,8 @@ Note: #include "StdAfx.h" +#include <stdlib.h> + #include "../../../C/7zCrc.h" #include "../../../C/Alloc.h" @@ -55,6 +57,8 @@ namespace NVm { static const UInt32 kStackRegIndex = kNumRegs - 1; +#ifdef RARVM_VM_ENABLE + static const UInt32 FLAG_C = 1; static const UInt32 FLAG_Z = 2; static const UInt32 FLAG_S = 0x80000000; @@ -113,11 +117,14 @@ static const Byte kCmdFlags[]= /* CMD_PRINT */ CF_OP0 }; +#endif + + CVm::CVm(): Mem(NULL) {} bool CVm::Create() { - if (Mem == NULL) + if (!Mem) Mem = (Byte *)::MyAlloc(kSpaceSize + 4); return (Mem != NULL); } @@ -145,12 +152,14 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState, memcpy(Mem + kGlobalOffset + globalSize, &prg->StaticData[0], staticSize); bool res = true; + #ifdef RARVM_STANDARD_FILTERS if (prg->StandardFilterIndex >= 0) ExecuteStandardFilter(prg->StandardFilterIndex); else #endif { + #ifdef RARVM_VM_ENABLE res = ExecuteCode(prg); if (!res) { @@ -158,7 +167,11 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState, prg->Commands.Add(CCommand()); prg->Commands.Back().OpCode = CMD_RET; } + #else + res = false; + #endif } + UInt32 newBlockPos = GetFixedGlobalValue32(NGlobalOffset::kBlockPos) & kSpaceMask; UInt32 newBlockSize = GetFixedGlobalValue32(NGlobalOffset::kBlockSize) & kSpaceMask; if (newBlockPos + newBlockSize >= kSpaceSize) @@ -175,9 +188,11 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState, outGlobalData.ClearAndSetSize(dataSize); memcpy(&outGlobalData[0], Mem + kGlobalOffset, dataSize); } + return res; } +#ifdef RARVM_VM_ENABLE #define SET_IP(IP) \ if ((IP) >= numCommands) return true; \ @@ -191,7 +206,7 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState, UInt32 CVm::GetOperand32(const COperand *op) const { - switch(op->Type) + switch (op->Type) { case OP_TYPE_REG: return R[op->Data]; case OP_TYPE_REGMEM: return GetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask]); @@ -201,7 +216,7 @@ UInt32 CVm::GetOperand32(const COperand *op) const void CVm::SetOperand32(const COperand *op, UInt32 val) { - switch(op->Type) + switch (op->Type) { case OP_TYPE_REG: R[op->Data] = val; return; case OP_TYPE_REGMEM: SetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask], val); return; @@ -210,7 +225,7 @@ void CVm::SetOperand32(const COperand *op, UInt32 val) Byte CVm::GetOperand8(const COperand *op) const { - switch(op->Type) + switch (op->Type) { case OP_TYPE_REG: return (Byte)R[op->Data]; case OP_TYPE_REGMEM: return Mem[(op->Base + R[op->Data]) & kSpaceMask];; @@ -220,7 +235,7 @@ Byte CVm::GetOperand8(const COperand *op) const void CVm::SetOperand8(const COperand *op, Byte val) { - switch(op->Type) + switch (op->Type) { case OP_TYPE_REG: R[op->Data] = (R[op->Data] & 0xFFFFFF00) | val; return; case OP_TYPE_REGMEM: Mem[(op->Base + R[op->Data]) & kSpaceMask] = val; return; @@ -253,10 +268,8 @@ bool CVm::ExecuteCode(const CProgram *prg) for (;;) { - switch(cmd->OpCode) + switch (cmd->OpCode) { - #ifndef RARVM_NO_VM - case CMD_MOV: SetOperand32(&cmd->Op1, GetOperand32(&cmd->Op2)); break; @@ -619,8 +632,6 @@ bool CVm::ExecuteCode(const CProgram *prg) } break; - #endif - case CMD_RET: { if (R[kStackRegIndex] >= kSpaceSize) @@ -638,7 +649,6 @@ bool CVm::ExecuteCode(const CProgram *prg) } } - ////////////////////////////////////////////////////// // Read program @@ -682,25 +692,31 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize) inp.Init(code, codeSize); StaticData.Clear(); + if (inp.ReadBit()) { UInt32 dataSize = inp.ReadEncodedUInt32() + 1; for (UInt32 i = 0; inp.Avail() && i < dataSize; i++) StaticData.Add((Byte)inp.ReadBits(8)); } + while (inp.Avail()) { Commands.Add(CCommand()); CCommand *cmd = &Commands.Back(); + if (inp.ReadBit() == 0) cmd->OpCode = (ECommand)inp.ReadBits(3); else cmd->OpCode = (ECommand)(8 + inp.ReadBits(5)); + if (kCmdFlags[(unsigned)cmd->OpCode] & CF_BYTEMODE) cmd->ByteMode = (inp.ReadBit()) ? true : false; else cmd->ByteMode = 0; + int opNum = (kCmdFlags[(unsigned)cmd->OpCode] & CF_OPMASK); + if (opNum > 0) { DecodeArg(inp, cmd->Op1, cmd->ByteMode); @@ -727,6 +743,7 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize) } } } + if (cmd->ByteMode) { switch (cmd->OpCode) @@ -751,6 +768,9 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize) } } +#endif + + #ifdef RARVM_STANDARD_FILTERS enum EStandardFilter @@ -760,8 +780,8 @@ enum EStandardFilter SF_ITANIUM, SF_RGB, SF_AUDIO, - SF_DELTA, - SF_UPCASE + SF_DELTA + // SF_UPCASE }; static const struct CStandardFilterSignature @@ -777,8 +797,8 @@ kStdFilters[]= { 120, 0x3769893f, SF_ITANIUM }, { 29, 0x0e06077d, SF_DELTA }, { 149, 0x1c2c5dc8, SF_RGB }, - { 216, 0xbc85e701, SF_AUDIO }, - { 40, 0x46b9c560, SF_UPCASE } + { 216, 0xbc85e701, SF_AUDIO } + // { 40, 0x46b9c560, SF_UPCASE } }; static int FindStandardFilter(const Byte *code, UInt32 codeSize) @@ -795,28 +815,48 @@ static int FindStandardFilter(const Byte *code, UInt32 codeSize) #endif -void CProgram::PrepareProgram(const Byte *code, UInt32 codeSize) + +bool CProgram::PrepareProgram(const Byte *code, UInt32 codeSize) { - Byte xorSum = 0; - for (UInt32 i = 1; i < codeSize; i++) - xorSum ^= code[i]; + IsSupported = false; + #ifdef RARVM_VM_ENABLE Commands.Clear(); + #endif + #ifdef RARVM_STANDARD_FILTERS StandardFilterIndex = -1; #endif - if (xorSum == code[0] && codeSize > 0) + bool isOK = false; + + Byte xorSum = 0; + for (UInt32 i = 0; i < codeSize; i++) + xorSum ^= code[i]; + + if (xorSum == 0 && codeSize != 0) { + IsSupported = true; + isOK = true; #ifdef RARVM_STANDARD_FILTERS StandardFilterIndex = FindStandardFilter(code, codeSize); if (StandardFilterIndex >= 0) - return; + return true; #endif + + #ifdef RARVM_VM_ENABLE ReadProgram(code + 1, codeSize - 1); + #else + IsSupported = false; + #endif } + + #ifdef RARVM_VM_ENABLE Commands.Add(CCommand()); Commands.Back().OpCode = CMD_RET; + #endif + + return isOK; } void CVm::SetMemory(UInt32 pos, const Byte *data, UInt32 dataSize) @@ -833,12 +873,11 @@ static void E8E9Decode(Byte *data, UInt32 dataSize, UInt32 fileOffset, bool e9) return; dataSize -= 4; const UInt32 kFileSize = 0x1000000; - Byte cmpByte2 = (Byte)(e9 ? 0xE9 : 0xE8); + Byte cmpMask = (Byte)(e9 ? 0xFE : 0xFF); for (UInt32 curPos = 0; curPos < dataSize;) { - Byte curByte = *(data++); curPos++; - if (curByte == 0xE8 || curByte == cmpByte2) + if (((*data++) & cmpMask) == 0xE8) { UInt32 offset = curPos + fileOffset; UInt32 addr = (Int32)GetValue32(data); @@ -852,9 +891,9 @@ static void E8E9Decode(Byte *data, UInt32 dataSize, UInt32 fileOffset, bool e9) } } -static inline UInt32 ItaniumGetOpType(const Byte *data, int bitPos) +static inline UInt32 ItaniumGetOpType(const Byte *data, unsigned bitPos) { - return (data[(unsigned int)bitPos >> 3] >> (bitPos & 7)) & 0xF; + return (data[bitPos >> 3] >> (bitPos & 7)) & 0xF; } static const Byte kCmdMasks[16] = {4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0}; @@ -870,20 +909,20 @@ static void ItaniumDecode(Byte *data, UInt32 dataSize, UInt32 fileOffset) { Byte cmdMask = kCmdMasks[b]; if (cmdMask != 0) - for (int i = 0; i < 3; i++) + for (unsigned i = 0; i < 3; i++) if (cmdMask & (1 << i)) { - int startPos = i * 41 + 18; + unsigned startPos = i * 41 + 18; if (ItaniumGetOpType(data, startPos + 24) == 5) { const UInt32 kMask = 0xFFFFF; - Byte *p = data + ((unsigned int)startPos >> 3); + Byte *p = data + (startPos >> 3); UInt32 bitField = ((UInt32)p[0]) | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16); - int inBit = (startPos & 7); + unsigned inBit = (startPos & 7); UInt32 offset = (bitField >> inBit) & kMask; UInt32 andMask = ~(kMask << inBit); bitField = ((offset - fileOffset) & kMask) << inBit; - for (int j = 0; j < 3; j++) + for (unsigned j = 0; j < 3; j++) { p[j] &= andMask; p[j] |= bitField; @@ -1016,6 +1055,7 @@ static void AudioDecode(Byte *srcData, UInt32 dataSize, UInt32 numChannels) } } +/* static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize) { UInt32 srcPos = 0, destPos = dataSize; @@ -1028,6 +1068,7 @@ static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize) } return destPos - dataSize; } +*/ void CVm::ExecuteStandardFilter(unsigned filterIndex) { @@ -1068,6 +1109,7 @@ void CVm::ExecuteStandardFilter(unsigned filterIndex) SetBlockPos(dataSize); AudioDecode(Mem, dataSize, R[0]); break; + /* case SF_UPCASE: if (dataSize >= kGlobalOffset / 2) break; @@ -1075,6 +1117,7 @@ void CVm::ExecuteStandardFilter(unsigned filterIndex) SetBlockSize(destSize); SetBlockPos(dataSize); break; + */ } } diff --git a/CPP/7zip/Compress/Rar3Vm.h b/CPP/7zip/Compress/Rar3Vm.h index 23f4abab..4272c93e 100644 --- a/CPP/7zip/Compress/Rar3Vm.h +++ b/CPP/7zip/Compress/Rar3Vm.h @@ -7,10 +7,10 @@ #include "../../../C/CpuArch.h" -#include "../../Common/MyTypes.h" #include "../../Common/MyVector.h" #define RARVM_STANDARD_FILTERS +// #define RARVM_VM_ENABLE namespace NCompress { namespace NRar3 { @@ -39,12 +39,12 @@ namespace NVm { inline UInt32 GetValue32(const void *addr) { return GetUi32(addr); } inline void SetValue32(void *addr, UInt32 value) { SetUi32(addr, value); } -const int kNumRegBits = 3; +const unsigned kNumRegBits = 3; const UInt32 kNumRegs = 1 << kNumRegBits; const UInt32 kNumGpRegs = kNumRegs - 1; const UInt32 kSpaceSize = 0x40000; -const UInt32 kSpaceMask = kSpaceSize -1; +const UInt32 kSpaceMask = kSpaceSize - 1; const UInt32 kGlobalOffset = 0x3C000; const UInt32 kGlobalSize = 0x2000; const UInt32 kFixedGlobalSize = 64; @@ -57,6 +57,9 @@ namespace NGlobalOffset const UInt32 kGlobalMemOutSize = 0x30; } + +#ifdef RARVM_VM_ENABLE + enum ECommand { CMD_MOV, CMD_CMP, CMD_ADD, CMD_SUB, CMD_JZ, CMD_JNZ, CMD_INC, CMD_DEC, @@ -89,27 +92,36 @@ struct CCommand COperand Op1, Op2; }; +#endif + + struct CBlockRef { UInt32 Offset; UInt32 Size; }; + class CProgram { + #ifdef RARVM_VM_ENABLE + void ReadProgram(const Byte *code, UInt32 codeSize); public: CRecordVector<CCommand> Commands; + #endif + +public: #ifdef RARVM_STANDARD_FILTERS int StandardFilterIndex; #endif + + bool IsSupported; CRecordVector<Byte> StaticData; -private: - void ReadProgram(const Byte *code, UInt32 codeSize); -public: - void PrepareProgram(const Byte *code, UInt32 codeSize); + bool PrepareProgram(const Byte *code, UInt32 codeSize); }; + struct CProgramInitState { UInt32 InitR[kNumGpRegs]; @@ -122,6 +134,7 @@ struct CProgramInitState } }; + class CVm { static UInt32 GetValue(bool byteMode, const void *addr) @@ -146,15 +159,18 @@ class CVm void SetBlockPos(UInt32 v) { SetValue(&Mem[kGlobalOffset + NGlobalOffset::kBlockPos], v); } public: static void SetValue(void *addr, UInt32 value) { SetValue(false, addr, value); } + private: + + #ifdef RARVM_VM_ENABLE UInt32 GetOperand32(const COperand *op) const; void SetOperand32(const COperand *op, UInt32 val); Byte GetOperand8(const COperand *op) const; void SetOperand8(const COperand *op, Byte val); UInt32 GetOperand(bool byteMode, const COperand *op) const; void SetOperand(bool byteMode, const COperand *op, UInt32 val); - bool ExecuteCode(const CProgram *prg); + #endif #ifdef RARVM_STANDARD_FILTERS void ExecuteStandardFilter(unsigned filterIndex); @@ -163,6 +179,7 @@ private: Byte *Mem; UInt32 R[kNumRegs + 1]; // R[kNumRegs] = 0 always (speed optimization) UInt32 Flags; + public: CVm(); ~CVm(); @@ -171,7 +188,6 @@ public: bool Execute(CProgram *prg, const CProgramInitState *initState, CBlockRef &outBlockRef, CRecordVector<Byte> &outGlobalData); const Byte *GetDataPointer(UInt32 offset) const { return Mem + offset; } - }; #endif diff --git a/CPP/7zip/Compress/Rar5Decoder.cpp b/CPP/7zip/Compress/Rar5Decoder.cpp new file mode 100644 index 00000000..9e3ff3e4 --- /dev/null +++ b/CPP/7zip/Compress/Rar5Decoder.cpp @@ -0,0 +1,960 @@ +// Rar5Decoder.cpp +// According to unRAR license, this code may not be used to develop +// a program that creates RAR archives + +#include "StdAfx.h" + +// #include <stdio.h> + +#include "../Common/StreamUtils.h" + +#include "Rar5Decoder.h" + +namespace NCompress { +namespace NRar5 { + +static const size_t kInputBufSize = 1 << 20; + +void CBitDecoder::Prepare2() throw() +{ + const unsigned kSize = 16; + if (_buf > _bufLim) + return; + + size_t rem = _bufLim - _buf; + if (rem != 0) + memcpy(_bufBase, _buf, rem); + + _bufLim = _bufBase + rem; + _processedSize += (_buf - _bufBase); + _buf = _bufBase; + + if (!_wasFinished) + { + UInt32 processed = (UInt32)(kInputBufSize - rem); + _hres = _stream->Read(_bufLim, (UInt32)processed, &processed); + _bufLim += processed; + _wasFinished = (processed == 0); + if (_hres != S_OK) + { + _wasFinished = true; + // throw CInBufferException(result); + } + } + + rem = _bufLim - _buf; + _bufCheck = _buf; + if (rem < kSize) + memset(_bufLim, 0xFF, kSize - rem); + else + _bufCheck = _bufLim - kSize; + + SetCheck2(); +} + + +enum FilterType +{ + FILTER_DELTA = 0, + FILTER_E8, + FILTER_E8E9, + FILTER_ARM +}; + +static const size_t kWriteStep = (size_t)1 << 22; + +CDecoder::CDecoder(): + _window(NULL), + _winPos(0), + _winSizeAllocated(0), + _lzSize(0), + _lzEnd(0), + _writtenFileSize(0), + _dictSizeLog(0), + _isSolid(false), + _wasInit(false), + _inputBuf(NULL) +{ +} + +CDecoder::~CDecoder() +{ + ::MidFree(_window); + ::MidFree(_inputBuf); +} + +HRESULT CDecoder::WriteData(const Byte *data, size_t size) +{ + HRESULT res = S_OK; + if (!_unpackSize_Defined || _writtenFileSize < _unpackSize) + { + size_t cur = size; + if (_unpackSize_Defined) + { + UInt64 rem = _unpackSize - _writtenFileSize; + if (cur > rem) + cur = (size_t)rem; + } + res = WriteStream(_outStream, data, cur); + if (res != S_OK) + _writeError = true; + } + _writtenFileSize += size; + return res; +} + +HRESULT CDecoder::ExecuteFilter(const CFilter &f) +{ + bool useDest = false; + + Byte *data = _filterSrc; + UInt32 dataSize = f.Size; + + // printf("\nType = %d offset = %9d size = %5d", f.Type, (unsigned)(f.Start - _lzFileStart), dataSize); + + switch (f.Type) + { + case FILTER_E8: + case FILTER_E8E9: + { + // printf(" FILTER_E8"); + if (dataSize > 4) + { + dataSize -= 4; + UInt32 fileOffset = (UInt32)(f.Start - _lzFileStart); + + const UInt32 kFileSize = (UInt32)1 << 24; + Byte cmpMask = (Byte)(f.Type == FILTER_E8 ? 0xFF : 0xFE); + + for (UInt32 curPos = 0; curPos < dataSize;) + { + curPos++; + if (((*data++) & cmpMask) == 0xE8) + { + UInt32 offset = (curPos + fileOffset) & (kFileSize - 1); + UInt32 addr = GetUi32(data); + + if (addr < kFileSize) + { + SetUi32(data, addr - offset); + } + else if (addr > ((UInt32)0xFFFFFFFF - offset)) // (addr > ~(offset)) + { + SetUi32(data, addr + kFileSize); + } + + data += 4; + curPos += 4; + } + } + } + break; + } + + case FILTER_ARM: + { + if (dataSize >= 4) + { + dataSize -= 4; + UInt32 fileOffset = (UInt32)(f.Start - _lzFileStart); + + for (UInt32 curPos = 0; curPos <= dataSize; curPos += 4) + { + Byte *d = data + curPos; + if (d[3] == 0xEB) + { + UInt32 offset = d[0] | ((UInt32)d[1] << 8) | ((UInt32)d[2] << 16); + offset -= (fileOffset + curPos) >> 2; + d[0] = (Byte)offset; + d[1] = (Byte)(offset >> 8); + d[2] = (Byte)(offset >> 16); + } + } + } + break; + } + + case FILTER_DELTA: + { + // printf(" channels = %d", f.Channels); + _filterDst.AllocAtLeast(dataSize); + if (!_filterDst.IsAllocated()) + return E_OUTOFMEMORY; + + Byte *dest = _filterDst; + UInt32 numChannels = f.Channels; + + for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++) + { + Byte prevByte = 0; + for (UInt32 destPos = curChannel; destPos < dataSize; destPos += numChannels) + dest[destPos] = (prevByte = (Byte)(prevByte - *data++)); + } + useDest = true; + break; + } + + default: + _unsupportedFilter = true; + } + + return WriteData(useDest ? + (const Byte *)_filterDst : + (const Byte *)_filterSrc, + f.Size); +} + + +HRESULT CDecoder::WriteBuf() +{ + DeleteUnusedFilters(); + + for (unsigned i = 0; i < _filters.Size();) + { + const CFilter &f = _filters[i]; + + UInt64 blockStart = f.Start; + + size_t lzAvail = (size_t)(_lzSize - _lzWritten); + if (lzAvail == 0) + break; + + if (blockStart > _lzWritten) + { + UInt64 rem = blockStart - _lzWritten; + size_t size = lzAvail; + if (size > rem) + size = (size_t)rem; + if (size != 0) + { + RINOK(WriteData(_window + _winPos - lzAvail, size)); + _lzWritten += size; + } + continue; + } + + UInt32 blockSize = f.Size; + size_t offset = (size_t)(_lzWritten - blockStart); + if (offset == 0) + { + _filterSrc.AllocAtLeast(blockSize); + if (!_filterSrc.IsAllocated()) + return E_OUTOFMEMORY; + } + + size_t blockRem = (size_t)blockSize - offset; + size_t size = lzAvail; + if (size > blockRem) + size = blockRem; + memcpy(_filterSrc + offset, _window + _winPos - lzAvail, size); + _lzWritten += size; + offset += size; + if (offset != blockSize) + return S_OK; + + _numUnusedFilters = ++i; + RINOK(ExecuteFilter(f)); + } + + DeleteUnusedFilters(); + + if (!_filters.IsEmpty()) + return S_OK; + + size_t lzAvail = (size_t)(_lzSize - _lzWritten); + RINOK(WriteData(_window + _winPos - lzAvail, lzAvail)); + _lzWritten += lzAvail; + return S_OK; +} + + +static UInt32 ReadUInt32(CBitDecoder &bi) +{ + unsigned numBytes = bi.ReadBits9fix(2) + 1; + UInt32 v = 0; + for (unsigned i = 0; i < numBytes; i++) + v += ((UInt32)bi.ReadBits9fix(8) << (i * 8)); + return v; +} + + +static const unsigned MAX_UNPACK_FILTERS = 8192; + +HRESULT CDecoder::AddFilter(CBitDecoder &_bitStream) +{ + DeleteUnusedFilters(); + + if (_filters.Size() >= MAX_UNPACK_FILTERS) + { + RINOK(WriteBuf()); + DeleteUnusedFilters(); + if (_filters.Size() >= MAX_UNPACK_FILTERS) + { + _unsupportedFilter = true; + InitFilters(); + } + } + + _bitStream.Prepare(); + + CFilter f; + UInt32 blockStart = ReadUInt32(_bitStream); + f.Size = ReadUInt32(_bitStream); + + // if (f.Size > ((UInt32)1 << 16)) _unsupportedFilter = true; + + f.Type = (Byte)_bitStream.ReadBits9fix(3); + if (f.Type == FILTER_DELTA) + f.Channels = (Byte)(_bitStream.ReadBits9fix(5) + 1); + f.Start = _lzSize + blockStart; + + if (f.Start < _filterEnd) + _unsupportedFilter = true; + else + { + _filterEnd = f.Start + f.Size; + if (f.Size != 0) + _filters.Add(f); + } + + return S_OK; +} + + +#define RIF(x) { if (!(x)) return S_FALSE; } + +HRESULT CDecoder::ReadTables(CBitDecoder &_bitStream) +{ + if (_progress) + { + UInt64 packSize = _bitStream.GetProcessedSize(); + RINOK(_progress->SetRatioInfo(&packSize, &_writtenFileSize)); + } + + _bitStream.AlignToByte(); + _bitStream.Prepare(); + + unsigned flags = _bitStream.ReadByteInAligned(); + unsigned checkSum = _bitStream.ReadByteInAligned(); + checkSum ^= flags; + + UInt32 blockSize; + { + unsigned num = (flags >> 3) & 3; + if (num == 3) + return S_FALSE; + blockSize = _bitStream.ReadByteInAligned(); + if (num > 0) + { + blockSize += (UInt32)_bitStream.ReadByteInAligned() << 8; + if (num > 1) + blockSize += (UInt32)_bitStream.ReadByteInAligned() << 16; + } + } + + checkSum ^= blockSize ^ (blockSize >> 8) ^ (blockSize >> 16); + if ((Byte)checkSum != 0x5A) + return S_FALSE; + + unsigned blockSizeBits7 = (flags & 7) + 1; + + if (blockSize == 0 && blockSizeBits7 != 8) + return S_FALSE; + + blockSize += (blockSizeBits7 >> 3); + blockSize--; + + _bitStream._blockEndBits7 = (Byte)(blockSizeBits7 & 7); + _bitStream._blockEnd = _bitStream.GetProcessedSize_Round() + blockSize; + + _bitStream.SetCheck2(); + + _isLastBlock = ((flags & 0x40) != 0); + + if ((flags & 0x80) == 0) + { + if (!_tableWasFilled && blockSize != 0) + return S_FALSE; + return S_OK; + } + + _tableWasFilled = false; + + { + Byte lens2[kLevelTableSize]; + + for (unsigned i = 0; i < kLevelTableSize;) + { + _bitStream.Prepare(); + unsigned len = (unsigned)_bitStream.ReadBits9fix(4); + if (len == 15) + { + unsigned num = (unsigned)_bitStream.ReadBits9fix(4); + if (num != 0) + { + num += 2; + num += i; + if (num > kLevelTableSize) + num = kLevelTableSize; + do + lens2[i++] = 0; + while (i < num); + continue; + } + } + lens2[i++] = (Byte)len; + } + + if (_bitStream.IsBlockOverRead()) + return S_FALSE; + + RIF(m_LevelDecoder.SetCodeLengths(lens2)); + } + + Byte lens[kTablesSizesSum]; + unsigned i = 0; + + while (i < kTablesSizesSum) + { + if (_bitStream._buf >= _bitStream._bufCheck2) + { + if (_bitStream._buf >= _bitStream._bufCheck) + _bitStream.Prepare(); + if (_bitStream.IsBlockOverRead()) + return S_FALSE; + } + + UInt32 sym = m_LevelDecoder.DecodeSymbol(&_bitStream); + + if (sym < 16) + lens[i++] = (Byte)sym; + else if (sym > kLevelTableSize) + return S_FALSE; + else + { + sym -= 16; + unsigned sh = ((sym & 1) << 2); + unsigned num = (unsigned)_bitStream.ReadBits9(3 + sh) + 3 + (sh << 1); + + num += i; + if (num > kTablesSizesSum) + num = kTablesSizesSum; + + if (sym < 2) + { + if (i == 0) + { + // return S_FALSE; + continue; // original unRAR + } + Byte v = lens[i - 1]; + do + lens[i++] = v; + while (i < num); + } + else + { + do + lens[i++] = 0; + while (i < num); + } + } + } + + if (_bitStream.IsBlockOverRead()) + return S_FALSE; + if (_bitStream.InputEofError()) + return S_FALSE; + + RIF(m_MainDecoder.SetCodeLengths(&lens[0])); + RIF(m_DistDecoder.SetCodeLengths(&lens[kMainTableSize])); + RIF(m_AlignDecoder.SetCodeLengths(&lens[kMainTableSize + kDistTableSize])); + RIF(m_LenDecoder.SetCodeLengths(&lens[kMainTableSize + kDistTableSize + kAlignTableSize])); + + _useAlignBits = false; + // _useAlignBits = true; + for (i = 0; i < kAlignTableSize; i++) + if (lens[kMainTableSize + kDistTableSize + i] != kNumAlignBits) + { + _useAlignBits = true; + break; + } + + _tableWasFilled = true; + return S_OK; +} + + +static inline unsigned SlotToLen(CBitDecoder &_bitStream, unsigned slot) +{ + if (slot < 8) + return slot + 2; + unsigned numBits = (slot >> 2) - 1; + return 2 + ((4 | (slot & 3)) << numBits) + _bitStream.ReadBits9(numBits); +} + + +static const UInt32 kSymbolRep = 258; +// static const unsigned kMaxMatchLen = 0x1001 + 3; + +HRESULT CDecoder::DecodeLZ() +{ + CBitDecoder _bitStream; + _bitStream._stream = _inStream; + _bitStream._bufBase = _inputBuf; + _bitStream.Init(); + + UInt32 rep0 = _reps[0]; + + UInt32 remLen = 0; + + size_t limit; + { + size_t rem = _winSize - _winPos; + if (rem > kWriteStep) + rem = kWriteStep; + limit = _winPos + rem; + } + + for (;;) + { + if (_winPos >= limit) + { + RINOK(WriteBuf()); + if (_unpackSize_Defined && _writtenFileSize > _unpackSize) + break; // return S_FALSE; + + { + size_t rem = _winSize - _winPos; + + if (rem == 0) + { + _winPos = 0; + rem = _winSize; + } + if (rem > kWriteStep) + rem = kWriteStep; + limit = _winPos + rem; + } + + if (remLen != 0) + { + size_t winPos = _winPos; + size_t winMask = _winMask; + size_t pos = (winPos - (size_t)rep0 - 1) & winMask; + + Byte *win = _window; + do + { + if (winPos >= limit) + break; + win[winPos] = win[pos]; + winPos++; + pos = (pos + 1) & winMask; + } + while (--remLen != 0); + + _lzSize += winPos - _winPos; + _winPos = winPos; + continue; + } + } + + if (_bitStream._buf >= _bitStream._bufCheck2) + { + if (_bitStream.InputEofError()) + break; // return S_FALSE; + if (_bitStream._buf >= _bitStream._bufCheck) + _bitStream.Prepare2(); + + UInt64 processed = _bitStream.GetProcessedSize_Round(); + if (processed >= _bitStream._blockEnd) + { + if (processed > _bitStream._blockEnd) + break; // return S_FALSE; + { + unsigned bits7 = _bitStream.GetProcessedBits7(); + if (bits7 > _bitStream._blockEndBits7) + break; // return S_FALSE; + if (bits7 == _bitStream._blockEndBits7) + { + if (_isLastBlock) + { + _reps[0] = rep0; + + if (_bitStream.InputEofError()) + break; + + /* + // packSize can be 15 bytes larger for encrypted archive + if (_packSize_Defined && _packSize < _bitStream.GetProcessedSize()) + break; + */ + + return _bitStream._hres; + // break; + } + RINOK(ReadTables(_bitStream)); + continue; + } + } + } + } + + UInt32 sym = m_MainDecoder.DecodeSymbol(&_bitStream); + + if (sym < 256) + { + size_t winPos = _winPos; + _window[winPos] = (Byte)sym; + _winPos = winPos + 1; + _lzSize++; + continue; + } + + UInt32 len; + + if (sym < kSymbolRep + kNumReps) + { + if (sym >= kSymbolRep) + { + if (sym != kSymbolRep) + { + UInt32 dist; + if (sym == kSymbolRep + 1) + dist = _reps[1]; + else + { + if (sym == kSymbolRep + 2) + dist = _reps[2]; + else + { + dist = _reps[3]; + _reps[3] = _reps[2]; + } + _reps[2] = _reps[1]; + } + _reps[1] = rep0; + rep0 = dist; + } + + UInt32 sym = m_LenDecoder.DecodeSymbol(&_bitStream); + if (sym >= kLenTableSize) + break; // return S_FALSE; + len = SlotToLen(_bitStream, sym); + } + else + { + if (sym == 256) + { + RINOK(AddFilter(_bitStream)); + continue; + } + else // if (sym == 257) + { + len = _lastLen; + // if (len = 0), we ignore that symbol, like original unRAR code, but it can mean error in stream. + // if (len == 0) return S_FALSE; + if (len == 0) + continue; + } + } + } + else if (sym >= kMainTableSize) + break; // return S_FALSE; + else + { + _reps[3] = _reps[2]; + _reps[2] = _reps[1]; + _reps[1] = rep0; + len = SlotToLen(_bitStream, sym - (kSymbolRep + kNumReps)); + + rep0 = m_DistDecoder.DecodeSymbol(&_bitStream); + + if (rep0 >= 4) + { + if (rep0 >= _numCorrectDistSymbols) + break; // return S_FALSE; + unsigned numBits = (rep0 >> 1) - 1; + rep0 = (2 | (rep0 & 1)) << numBits; + + if (numBits < kNumAlignBits) + rep0 += _bitStream.ReadBits9(numBits); + else + { + len += (numBits >= 7); + len += (numBits >= 12); + len += (numBits >= 17); + + if (_useAlignBits) + { + // if (numBits > kNumAlignBits) + rep0 += (_bitStream.ReadBits32(numBits - kNumAlignBits) << kNumAlignBits); + UInt32 a = m_AlignDecoder.DecodeSymbol(&_bitStream); + if (a >= kAlignTableSize) + break; // return S_FALSE; + rep0 += a; + } + else + rep0 += _bitStream.ReadBits32(numBits); + } + } + } + + _lastLen = len; + + if (rep0 >= _lzSize) + _lzError = true; + + { + UInt32 lenCur = len; + size_t winPos = _winPos; + size_t pos = (winPos - (size_t)rep0 - 1) & _winMask; + { + size_t rem = limit - winPos; + // size_t rem = _winSize - winPos; + + if (lenCur > rem) + { + lenCur = (UInt32)rem; + remLen = len - lenCur; + } + } + + Byte *win = _window; + _lzSize += lenCur; + _winPos = winPos + lenCur; + if (_winSize - pos >= lenCur) + { + const Byte *src = win + pos; + Byte *dest = win + winPos; + do + *dest++ = *src++; + while (--lenCur != 0); + } + else + { + do + { + win[winPos] = win[pos]; + winPos++; + pos = (pos + 1) & _winMask; + } + while (--lenCur != 0); + } + } + } + + if (_bitStream._hres != S_OK) + return _bitStream._hres; + + return S_FALSE; +} + + +HRESULT CDecoder::CodeReal() +{ + _unsupportedFilter = false; + _lzError = false; + _writeError = false; + + if (!_isSolid || !_wasInit) + { + size_t clearSize = _winSize; + if (_lzSize < _winSize) + clearSize = (size_t)_lzSize; + memset(_window, 0, clearSize); + + _wasInit = true; + _lzSize = 0; + _lzWritten = 0; + _winPos = 0; + + for (unsigned i = 0; i < kNumReps; i++) + _reps[i] = (UInt32)0 - 1; + + _lastLen = 0; + _tableWasFilled = false; + } + + _isLastBlock = false; + + InitFilters(); + + _filterEnd = 0; + _writtenFileSize = 0; + + _lzFileStart = _lzSize; + _lzWritten = _lzSize; + + HRESULT res = DecodeLZ(); + + HRESULT res2 = S_OK; + if (!_writeError && res != E_OUTOFMEMORY) + res2 = WriteBuf(); + + /* + if (res == S_OK) + if (InputEofError()) + res = S_FALSE; + */ + + if (res == S_OK) + res = res2; + + if (res == S_OK && _unpackSize_Defined && _writtenFileSize != _unpackSize) + return S_FALSE; + return res; +} + + +// Original unRAR claims that maximum possible filter block size is (1 << 16) now, +// and (1 << 17) is minimum win size required to support filter. +// Original unRAR uses (1 << 18) for "extra safety and possible filter area size expansion" +// We can use any win size. + +static const unsigned kWinSize_Log_Min = 17; + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + try + { + if (_dictSizeLog >= sizeof(size_t) * 8) + return E_NOTIMPL; + + if (!_isSolid) + _lzEnd = 0; + else + { + if (_lzSize < _lzEnd) + { + if (_window) + { + UInt64 rem = _lzEnd - _lzSize; + if (rem >= _winSize) + memset(_window, 0, _winSize); + else + { + size_t pos = (size_t)_lzSize & _winSize; + size_t rem2 = _winSize - pos; + if (rem2 > rem) + rem2 = (size_t)rem; + memset(_window + pos, 0, rem2); + rem -= rem2; + memset(_window, 0, (size_t)rem); + } + } + _lzEnd &= ((((UInt64)1) << 33) - 1); + _lzSize = _lzEnd; + _winPos = (size_t)(_lzSize & _winSize); + } + _lzEnd = _lzSize; + } + + size_t newSize; + { + unsigned newSizeLog = _dictSizeLog; + if (newSizeLog < kWinSize_Log_Min) + newSizeLog = kWinSize_Log_Min; + newSize = (size_t)1 << newSizeLog; + _numCorrectDistSymbols = newSizeLog * 2; + } + + if (!_window || _winSize != newSize) + { + if (!_isSolid && newSize > _winSizeAllocated) + { + ::MidFree(_window); + _window = NULL; + _winSizeAllocated = 0; + } + + Byte *win = _window; + if (!_window || newSize > _winSizeAllocated) + { + win = (Byte *)::MidAlloc(newSize); + if (!win) + return E_OUTOFMEMORY; + _winSizeAllocated = newSize; + memset(win, 0, newSize); + } + + if (_isSolid && _window) + { + // original unRAR claims: + // "Archiving code guarantees that win size does not grow in the same solid stream", + // but the original unRAR decoder still supports such grow case. + + Byte *winOld = _window; + size_t oldSize = _winSize; + size_t newMask = newSize - 1; + size_t oldMask = _winSize - 1; + size_t winPos = _winPos; + for (size_t i = 1; i < oldSize; i++) // i < oldSize) ? + win[(winPos - i) & newMask] = winOld[(winPos - i) & oldMask]; + ::MidFree(_window); + } + + _window = win; + _winSize = newSize; + } + + _winMask = _winSize - 1; + + if (!_inputBuf) + { + _inputBuf = (Byte *)::MidAlloc(kInputBufSize); + if (!_inputBuf) + return E_OUTOFMEMORY; + } + + _inStream = inStream; + _outStream = outStream; + + /* + _packSize = 0; + _packSize_Defined = (inSize != NULL); + if (_packSize_Defined) + _packSize = *inSize; + */ + + _unpackSize = 0; + _unpackSize_Defined = (outSize != NULL); + if (_unpackSize_Defined) + _unpackSize = *outSize; + + if ((Int64)_unpackSize >= 0) + _lzEnd += _unpackSize; + else + _lzEnd = 0; + + _progress = progress; + + HRESULT res = CodeReal(); + + if (res != S_OK) + return res; + if (_lzError) + return S_FALSE; + if (_unsupportedFilter) + return E_NOTIMPL; + return S_OK; + } + // catch(const CInBufferException &e) { return e.ErrorCode; } + // catch(...) { return S_FALSE; } + catch(...) { return E_OUTOFMEMORY; } + // CNewException is possible here. But probably CNewException is caused + // by error in data stream. +} + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) +{ + if (size != 2) + return E_NOTIMPL; + _dictSizeLog = (Byte)((data[0] & 0xF) + 17); + _isSolid = ((data[1] & 1) != 0); + return S_OK; +} + +}} diff --git a/CPP/7zip/Compress/Rar5Decoder.h b/CPP/7zip/Compress/Rar5Decoder.h new file mode 100644 index 00000000..b0a4dd12 --- /dev/null +++ b/CPP/7zip/Compress/Rar5Decoder.h @@ -0,0 +1,335 @@ +// Rar5Decoder.h +// According to unRAR license, this code may not be used to develop +// a program that creates RAR archives + +#ifndef __COMPRESS_RAR5_DECODER_H +#define __COMPRESS_RAR5_DECODER_H + +#include "../../../C/Alloc.h" +#include "../../../C/CpuArch.h" + +#include "../../Common/MyBuffer.h" +#include "../../Common/MyCom.h" +#include "../../Common/MyException.h" +#include "../../Common/MyVector.h" + +#include "../ICoder.h" + +#include "HuffmanDecoder.h" + +namespace NCompress { +namespace NRar5 { + +class CMidBuffer +{ + Byte *_data; + size_t _size; + + CLASS_NO_COPY(CMidBuffer) + +public: + CMidBuffer(): _data(NULL), _size(0) {}; + ~CMidBuffer() { ::MidFree(_data); } + + bool IsAllocated() const { return _data != NULL; } + operator Byte *() { return _data; } + operator const Byte *() const { return _data; } + size_t Size() const { return _size; } + + void AllocAtLeast(size_t size) + { + if (size > _size) + { + const size_t kMinSize = (1 << 16); + if (size < kMinSize) + size = kMinSize; + ::MidFree(_data); + _data = (Byte *)::MidAlloc(size); + _size = size; + } + } +}; + +/* +struct CInBufferException: public CSystemException +{ + CInBufferException(HRESULT errorCode): CSystemException(errorCode) {} +}; +*/ + +class CBitDecoder +{ +public: + const Byte *_buf; + unsigned _bitPos; + bool _wasFinished; + Byte _blockEndBits7; + const Byte *_bufCheck2; + const Byte *_bufCheck; + Byte *_bufLim; + Byte *_bufBase; + + UInt64 _processedSize; + UInt64 _blockEnd; + + ISequentialInStream *_stream; + HRESULT _hres; + + void SetCheck2() + { + _bufCheck2 = _bufCheck; + if (_bufCheck > _buf) + { + UInt64 processed = GetProcessedSize_Round(); + if (_blockEnd < processed) + _bufCheck2 = _buf; + else + { + UInt64 delta = _blockEnd - processed; + if ((size_t)(_bufCheck - _buf) > delta) + _bufCheck2 = _buf + (size_t)delta; + } + } + } + + bool IsBlockOverRead() const + { + UInt64 v = GetProcessedSize_Round(); + if (v < _blockEnd) + return false; + if (v > _blockEnd) + return true; + return _bitPos > _blockEndBits7; + } + + /* + CBitDecoder() throw(): + _buf(0), + _bufLim(0), + _bufBase(0), + _stream(0), + _processedSize(0), + _wasFinished(false) + {} + */ + + void Init() throw() + { + _blockEnd = 0; + _blockEndBits7 = 0; + + _bitPos = 0; + _processedSize = 0; + _buf = _bufBase; + _bufLim = _bufBase; + _bufCheck = _buf; + _bufCheck2 = _buf; + _wasFinished = false; + } + + void Prepare2() throw(); + + void Prepare() throw() + { + if (_buf >= _bufCheck) + Prepare2(); + } + + bool ExtraBitsWereRead() const + { + return _buf >= _bufLim && (_buf > _bufLim || _bitPos != 0); + } + + bool InputEofError() const { return ExtraBitsWereRead(); } + + unsigned GetProcessedBits7() const { return _bitPos; } + UInt64 GetProcessedSize_Round() const { return _processedSize + (_buf - _bufBase); } + UInt64 GetProcessedSize() const { return _processedSize + (_buf - _bufBase) + ((_bitPos + 7) >> 3); } + + void AlignToByte() + { + _buf += (_bitPos + 7) >> 3; + _bitPos = 0; + } + + Byte ReadByteInAligned() + { + return *_buf++; + } + + UInt32 GetValue(unsigned numBits) + { + UInt32 v = ((UInt32)_buf[0] << 16) | ((UInt32)_buf[1] << 8) | (UInt32)_buf[2]; + v >>= (24 - numBits - _bitPos); + return v & ((1 << numBits) - 1); + } + + void MovePos(unsigned numBits) + { + _bitPos += numBits; + _buf += (_bitPos >> 3); + _bitPos &= 7; + } + + UInt32 ReadBits9(unsigned numBits) + { + const Byte *buf = _buf; + UInt32 v = ((UInt32)buf[0] << 8) | (UInt32)buf[1]; + v &= ((UInt32)0xFFFF >> _bitPos); + numBits += _bitPos; + v >>= (16 - numBits); + _buf = buf + (numBits >> 3); + _bitPos = numBits & 7; + return v; + } + + UInt32 ReadBits9fix(unsigned numBits) + { + const Byte *buf = _buf; + UInt32 v = ((UInt32)buf[0] << 8) | (UInt32)buf[1]; + UInt32 mask = ((1 << numBits) - 1); + numBits += _bitPos; + v >>= (16 - numBits); + _buf = buf + (numBits >> 3); + _bitPos = numBits & 7; + return v & mask; + } + + UInt32 ReadBits32(unsigned numBits) + { + UInt32 mask = ((1 << numBits) - 1); + numBits += _bitPos; + const Byte *buf = _buf; + UInt32 v = GetBe32(buf); + if (numBits > 32) + { + v <<= (numBits - 32); + v |= (UInt32)buf[4] >> (40 - numBits); + } + else + v >>= (32 - numBits); + _buf = buf + (numBits >> 3); + _bitPos = numBits & 7; + return v & mask; + } +}; + + +struct CFilter +{ + Byte Type; + Byte Channels; + UInt32 Size; + UInt64 Start; +}; + + +const unsigned kNumReps = 4; +const unsigned kLenTableSize = 11 * 4; +const unsigned kMainTableSize = 256 + 1 + 1 + kNumReps + kLenTableSize; +const unsigned kDistTableSize = 64; +const unsigned kNumAlignBits = 4; +const unsigned kAlignTableSize = (1 << kNumAlignBits); +const unsigned kLevelTableSize = 20; +const unsigned kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize + kLenTableSize; + +const unsigned kNumHuffmanBits = 15; + +class CDecoder: + public ICompressCoder, + public ICompressSetDecoderProperties2, + public CMyUnknownImp +{ + bool _useAlignBits; + bool _isLastBlock; + bool _unpackSize_Defined; + // bool _packSize_Defined; + + bool _unsupportedFilter; + bool _lzError; + bool _writeError; + + // CBitDecoder _bitStream; + Byte *_window; + size_t _winPos; + size_t _winSize; + size_t _winMask; + + UInt64 _lzSize; + + unsigned _numCorrectDistSymbols; + unsigned _numUnusedFilters; + + UInt64 _lzWritten; + UInt64 _lzFileStart; + UInt64 _unpackSize; + // UInt64 _packSize; + UInt64 _lzEnd; + UInt64 _writtenFileSize; + size_t _winSizeAllocated; + + Byte _dictSizeLog; + bool _tableWasFilled; + bool _isSolid; + bool _wasInit; + + UInt32 _reps[kNumReps]; + UInt32 _lastLen; + + UInt64 _filterEnd; + CMidBuffer _filterSrc; + CMidBuffer _filterDst; + + CRecordVector<CFilter> _filters; + + ISequentialInStream *_inStream; + ISequentialOutStream *_outStream; + ICompressProgressInfo *_progress; + Byte *_inputBuf; + + NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder; + NHuffman::CDecoder<kNumHuffmanBits, kDistTableSize> m_DistDecoder; + NHuffman::CDecoder<kNumHuffmanBits, kAlignTableSize> m_AlignDecoder; + NHuffman::CDecoder<kNumHuffmanBits, kLenTableSize> m_LenDecoder; + NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder; + + + void InitFilters() + { + _numUnusedFilters = 0; + _filters.Clear(); + } + + void DeleteUnusedFilters() + { + if (_numUnusedFilters != 0) + { + _filters.DeleteFrontal(_numUnusedFilters); + _numUnusedFilters = 0; + } + } + + HRESULT WriteData(const Byte *data, size_t size); + HRESULT ExecuteFilter(const CFilter &f); + HRESULT WriteBuf(); + HRESULT AddFilter(CBitDecoder &_bitStream); + + HRESULT ReadTables(CBitDecoder &_bitStream); + HRESULT DecodeLZ(); + HRESULT CodeReal(); + +public: + CDecoder(); + ~CDecoder(); + + MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/RarCodecsRegister.cpp b/CPP/7zip/Compress/RarCodecsRegister.cpp index 66fcc9a9..2f3a1138 100644 --- a/CPP/7zip/Compress/RarCodecsRegister.cpp +++ b/CPP/7zip/Compress/RarCodecsRegister.cpp @@ -7,12 +7,14 @@ #include "Rar1Decoder.h" #include "Rar2Decoder.h" #include "Rar3Decoder.h" +#include "Rar5Decoder.h" #define CREATE_CODEC(x) REGISTER_CODEC_CREATE(CreateCodec ## x, NCompress::NRar ## x::CDecoder()) CREATE_CODEC(1) CREATE_CODEC(2) CREATE_CODEC(3) +CREATE_CODEC(5) #define RAR_CODEC(x, name) { CreateCodec ## x, NULL, 0x40300 + x, "Rar" name, 1, false } @@ -21,6 +23,7 @@ REGISTER_CODECS_VAR RAR_CODEC(1, "1"), RAR_CODEC(2, "2"), RAR_CODEC(3, "3"), + RAR_CODEC(5, "5"), }; REGISTER_CODECS(Rar) diff --git a/CPP/7zip/Crypto/HmacSha256.cpp b/CPP/7zip/Crypto/HmacSha256.cpp new file mode 100644 index 00000000..2e1efb48 --- /dev/null +++ b/CPP/7zip/Crypto/HmacSha256.cpp @@ -0,0 +1,62 @@ +// HmacSha256.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "HmacSha256.h" + +namespace NCrypto { +namespace NSha256 { + +static const unsigned kBlockSize = 64; + +void CHmac::SetKey(const Byte *key, size_t keySize) +{ + Byte temp[kBlockSize]; + size_t i; + + for (i = 0; i < kBlockSize; i++) + temp[i] = 0; + + if (keySize > kBlockSize) + { + Sha256_Init(&_sha); + Sha256_Update(&_sha, key, keySize); + Sha256_Final(&_sha, temp); + } + else + for (i = 0; i < keySize; i++) + temp[i] = key[i]; + + for (i = 0; i < kBlockSize; i++) + temp[i] ^= 0x36; + + Sha256_Init(&_sha); + Sha256_Update(&_sha, temp, kBlockSize); + + for (i = 0; i < kBlockSize; i++) + temp[i] ^= 0x36 ^ 0x5C; + + Sha256_Init(&_sha2); + Sha256_Update(&_sha2, temp, kBlockSize); +} + +void CHmac::Final(Byte *mac) +{ + Sha256_Final(&_sha, mac); + Sha256_Update(&_sha2, mac, SHA256_DIGEST_SIZE); + Sha256_Final(&_sha2, mac); +} + +/* +void CHmac::Final(Byte *mac, size_t macSize) +{ + Byte digest[SHA256_DIGEST_SIZE]; + Final(digest); + for (size_t i = 0; i < macSize; i++) + mac[i] = digest[i]; +} +*/ + +}} diff --git a/CPP/7zip/Crypto/HmacSha256.h b/CPP/7zip/Crypto/HmacSha256.h new file mode 100644 index 00000000..233424a0 --- /dev/null +++ b/CPP/7zip/Crypto/HmacSha256.h @@ -0,0 +1,27 @@ +// HmacSha256.h +// Implements HMAC-SHA-256 (RFC2104, FIPS-198) + +#ifndef __CRYPTO_HMAC_SHA256_H +#define __CRYPTO_HMAC_SHA256_H + +#include "../../../C/Sha256.h" + +namespace NCrypto { +namespace NSha256 { + +const unsigned kDigestSize = SHA256_DIGEST_SIZE; + +class CHmac +{ + CSha256 _sha; + CSha256 _sha2; +public: + void SetKey(const Byte *key, size_t keySize); + void Update(const Byte *data, size_t dataSize) { Sha256_Update(&_sha, data, dataSize); } + void Final(Byte *mac); + // void Final(Byte *mac, size_t macSize); +}; + +}} + +#endif diff --git a/CPP/7zip/Crypto/Rar20Crypto.cpp b/CPP/7zip/Crypto/Rar20Crypto.cpp index 1523151d..346d969e 100644 --- a/CPP/7zip/Crypto/Rar20Crypto.cpp +++ b/CPP/7zip/Crypto/Rar20Crypto.cpp @@ -9,7 +9,7 @@ #include "Rar20Crypto.h" namespace NCrypto { -namespace NRar20 { +namespace NRar2 { static const unsigned kNumRounds = 32; @@ -39,44 +39,48 @@ void CData::UpdateKeys(const Byte *data) Keys[j] ^= g_CrcTable[data[i + j]]; } -static void Swap(Byte *b1, Byte *b2) +static inline void Swap(Byte &b1, Byte &b2) { - Byte b = *b1; - *b1 = *b2; - *b2 = b; + Byte b = b1; + b1 = b2; + b2 = b; } -void CData::SetPassword(const Byte *data, UInt32 size) +void CData::SetPassword(const Byte *data, unsigned size) { Keys[0] = 0xD3A3B879L; Keys[1] = 0x3F6D12F7L; Keys[2] = 0x7515A235L; Keys[3] = 0xA4E7F123L; - Byte psw[256]; - if (size >= sizeof(psw)) - size = sizeof(psw) - 1; + Byte psw[128]; memset(psw, 0, sizeof(psw)); if (size != 0) + { + if (size >= sizeof(psw)) + size = sizeof(psw) - 1; memcpy(psw, data, size); + } + memcpy(SubstTable, g_InitSubstTable, sizeof(SubstTable)); - for (UInt32 j = 0; j < 256; j++) - for (UInt32 i = 0; i < size; i += 2) + for (unsigned j = 0; j < 256; j++) + for (unsigned i = 0; i < size; i += 2) { - UInt32 n2 = (Byte)g_CrcTable[(psw[i + 1] + j) & 0xFF]; - UInt32 n1 = (Byte)g_CrcTable[(psw[i] - j) & 0xFF]; - for (UInt32 k = 1; (n1 & 0xFF) != n2; n1++, k++) - Swap(&SubstTable[n1 & 0xFF], &SubstTable[(n1 + i + k) & 0xFF]); + unsigned n1 = (Byte)g_CrcTable[(psw[i] - j) & 0xFF]; + unsigned n2 = (Byte)g_CrcTable[(psw[i + 1] + j) & 0xFF]; + for (unsigned k = 1; (n1 & 0xFF) != n2; n1++, k++) + Swap(SubstTable[n1 & 0xFF], SubstTable[(n1 + i + k) & 0xFF]); } - for (UInt32 i = 0; i < size; i += 16) - EncryptBlock(&psw[i]); + + for (unsigned i = 0; i < size; i += 16) + EncryptBlock(psw + i); } void CData::CryptBlock(Byte *buf, bool encrypt) { Byte inBuf[16]; - UInt32 A, B, C, D, T, TA, TB; + UInt32 A, B, C, D; A = GetUi32(buf + 0) ^ Keys[0]; B = GetUi32(buf + 4) ^ Keys[1]; @@ -89,14 +93,10 @@ void CData::CryptBlock(Byte *buf, bool encrypt) for (unsigned i = 0; i < kNumRounds; i++) { UInt32 key = Keys[(encrypt ? i : (kNumRounds - 1 - i)) & 3]; - T = ((C + rotlFixed(D, 11)) ^ key); - TA = A ^ SubstLong(T); - T = ((D ^ rotlFixed(C, 17)) + key); - TB = B ^ SubstLong(T); - A = C; - B = D; - C = TA; - D = TB; + UInt32 TA = A ^ SubstLong((C + rotlFixed(D, 11)) ^ key); + UInt32 TB = B ^ SubstLong((D ^ rotlFixed(C, 17)) + key); + A = C; C = TA; + B = D; D = TB; } SetUi32(buf + 0, C ^ Keys[0]); @@ -107,12 +107,6 @@ void CData::CryptBlock(Byte *buf, bool encrypt) UpdateKeys(encrypt ? buf : inBuf); } -STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size) -{ - _cipher.SetPassword(data, size); - return S_OK; -} - STDMETHODIMP CDecoder::Init() { return S_OK; @@ -126,10 +120,10 @@ STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size) return 0; if (size < kBlockSize) return kBlockSize; - UInt32 i; size -= kBlockSize; + UInt32 i; for (i = 0; i <= size; i += kBlockSize) - _cipher.DecryptBlock(data + i); + DecryptBlock(data + i); return i; } diff --git a/CPP/7zip/Crypto/Rar20Crypto.h b/CPP/7zip/Crypto/Rar20Crypto.h index b0445932..b3033700 100644 --- a/CPP/7zip/Crypto/Rar20Crypto.h +++ b/CPP/7zip/Crypto/Rar20Crypto.h @@ -6,13 +6,12 @@ #include "../../Common/MyCom.h" #include "../ICoder.h" -#include "../IPassword.h" namespace NCrypto { -namespace NRar20 { +namespace NRar2 { /* ICompressFilter::Init() does nothing for this filter. - Call CryptoSetPassword() to initialize filter. */ + Call SetPassword() to initialize filter. */ class CData { @@ -31,22 +30,17 @@ class CData public: void EncryptBlock(Byte *buf) { CryptBlock(buf, true); } void DecryptBlock(Byte *buf) { CryptBlock(buf, false); } - void SetPassword(const Byte *password, UInt32 passwordLen); + void SetPassword(const Byte *password, unsigned passwordLen); }; class CDecoder: public ICompressFilter, - public ICryptoSetPassword, public CMyUnknownImp, public CData { - CData _cipher; public: - MY_UNKNOWN_IMP1(ICryptoSetPassword) - - STDMETHOD(Init)(); - STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); - STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); + MY_UNKNOWN_IMP + INTERFACE_ICompressFilter(;) }; }} diff --git a/CPP/7zip/Crypto/Rar5Aes.cpp b/CPP/7zip/Crypto/Rar5Aes.cpp new file mode 100644 index 00000000..648a3d4d --- /dev/null +++ b/CPP/7zip/Crypto/Rar5Aes.cpp @@ -0,0 +1,257 @@ +// Crypto/Rar5Aes.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#ifndef _7ZIP_ST +#include "../../Windows/Synchronization.h" +#endif + +#include "Rar5Aes.h" + +namespace NCrypto { +namespace NRar5 { + +static const unsigned kNumIterationsLog_Max = 24; + +static const unsigned kPswCheckCsumSize = 4; +static const unsigned kCheckSize = kPswCheckSize + kPswCheckCsumSize; + +CKey::CKey(): + _needCalc(true), + _numIterationsLog(0) +{ + for (unsigned i = 0; i < sizeof(_salt); i++) + _salt[i] = 0; +} + +CDecoder::CDecoder(): CAesCbcDecoder(kAesKeySize) {} + +static unsigned ReadVarInt(const Byte *p, unsigned maxSize, UInt64 *val) +{ + unsigned i; + *val = 0; + + for (i = 0; i < maxSize;) + { + Byte b = p[i]; + if (i < 10) + *val |= (UInt64)(b & 0x7F) << (7 * i++); + if ((b & 0x80) == 0) + return i; + } + return 0; +} + +HRESULT CDecoder::SetDecoderProps(const Byte *p, unsigned size, bool includeIV, bool isService) +{ + UInt64 Version; + + unsigned num = ReadVarInt(p, size, &Version); + if (num == 0) + return E_NOTIMPL; + p += num; + size -= num; + + if (Version != 0) + return E_NOTIMPL; + + num = ReadVarInt(p, size, &Flags); + if (num == 0) + return E_NOTIMPL; + p += num; + size -= num; + + bool isCheck = IsThereCheck(); + if (size != 1 + kSaltSize + (includeIV ? AES_BLOCK_SIZE : 0) + (unsigned)(isCheck ? kCheckSize : 0)) + return E_NOTIMPL; + + if (_numIterationsLog != p[0]) + { + _numIterationsLog = p[0]; + _needCalc = true; + } + + p++; + + if (memcmp(_salt, p, kSaltSize) != 0) + { + memcpy(_salt, p, kSaltSize); + _needCalc = true; + } + + p += kSaltSize; + + if (includeIV) + { + memcpy(_iv, p, AES_BLOCK_SIZE); + p += AES_BLOCK_SIZE; + } + + _canCheck = true; + + if (isCheck) + { + memcpy(_check, p, kPswCheckSize); + CSha256 sha; + Byte digest[SHA256_DIGEST_SIZE]; + Sha256_Init(&sha); + Sha256_Update(&sha, _check, kPswCheckSize); + Sha256_Final(&sha, digest); + _canCheck = (memcmp(digest, p + kPswCheckSize, kPswCheckCsumSize) == 0); + if (_canCheck && isService) + { + // There was bug in RAR 5.21- : PswCheck field in service records ("QO") contained zeros. + // so we disable password checking for such bad records. + _canCheck = false; + for (unsigned i = 0; i < kPswCheckSize; i++) + if (p[i] != 0) + { + _canCheck = true; + break; + } + } + } + + return (_numIterationsLog <= kNumIterationsLog_Max ? S_OK : E_NOTIMPL); +} + + +void CDecoder::SetPassword(const Byte *data, size_t size) +{ + if (size != _password.Size() || memcmp(data, _password, size) != 0) + { + _needCalc = true; + _password.CopyFrom(data, size); + } +} + + +STDMETHODIMP CDecoder::Init() +{ + CalcKey_and_CheckPassword(); + RINOK(SetKey(_key, kAesKeySize)); + RINOK(SetInitVector(_iv, AES_BLOCK_SIZE)); + return CAesCbcCoder::Init(); +} + + +UInt32 CDecoder::Hmac_Convert_Crc32(UInt32 crc) const +{ + NSha256::CHmac ctx; + ctx.SetKey(_hashKey, NSha256::kDigestSize); + Byte v[4]; + SetUi32(v, crc); + ctx.Update(v, 4); + Byte h[NSha256::kDigestSize]; + ctx.Final(h); + crc = 0; + for (unsigned i = 0; i < NSha256::kDigestSize; i++) + crc ^= (UInt32)h[i] << ((i & 3) * 8); + return crc; +}; + + +void CDecoder::Hmac_Convert_32Bytes(Byte *data) const +{ + NSha256::CHmac ctx; + ctx.SetKey(_hashKey, NSha256::kDigestSize); + ctx.Update(data, NSha256::kDigestSize); + ctx.Final(data); +}; + + +#ifndef _7ZIP_ST + static CKey g_Key; + static NWindows::NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection; + #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection); +#else + #define MT_LOCK +#endif + +bool CDecoder::CalcKey_and_CheckPassword() +{ + if (_needCalc) + { + { + MT_LOCK + if (!g_Key._needCalc && IsKeyEqualTo(g_Key)) + { + CopyCalcedKeysFrom(g_Key); + _needCalc = false; + } + } + + if (_needCalc) + { + Byte pswCheck[SHA256_DIGEST_SIZE]; + + { + // Pbkdf HMAC-SHA-256 + + NSha256::CHmac baseCtx; + baseCtx.SetKey(_password, _password.Size()); + + NSha256::CHmac ctx = baseCtx; + ctx.Update(_salt, sizeof(_salt)); + + Byte u[NSha256::kDigestSize]; + Byte key[NSha256::kDigestSize]; + + u[0] = 0; + u[1] = 0; + u[2] = 0; + u[3] = 1; + + ctx.Update(u, 4); + ctx.Final(u); + + memcpy(key, u, NSha256::kDigestSize); + + UInt32 numIterations = ((UInt32)1 << _numIterationsLog) - 1; + + for (unsigned i = 0; i < 3; i++) + { + UInt32 j = numIterations; + + for (; j != 0; j--) + { + ctx = baseCtx; + ctx.Update(u, NSha256::kDigestSize); + ctx.Final(u); + for (unsigned s = 0; s < NSha256::kDigestSize; s++) + key[s] ^= u[s]; + } + + // RAR uses additional iterations for additional keys + memcpy((i == 0 ? _key : (i == 1 ? _hashKey : pswCheck)), key, NSha256::kDigestSize); + numIterations = 16; + } + } + + { + unsigned i; + + for (i = 0; i < kPswCheckSize; i++) + _check_Calced[i] = pswCheck[i]; + + for (i = kPswCheckSize; i < SHA256_DIGEST_SIZE; i++) + _check_Calced[i & (kPswCheckSize - 1)] ^= pswCheck[i]; + } + + _needCalc = false; + + { + MT_LOCK + g_Key = *this; + } + } + } + + if (IsThereCheck() && _canCheck) + return (memcmp(_check_Calced, _check, kPswCheckSize) == 0); + return true; +} + +}} diff --git a/CPP/7zip/Crypto/Rar5Aes.h b/CPP/7zip/Crypto/Rar5Aes.h new file mode 100644 index 00000000..c69b24e4 --- /dev/null +++ b/CPP/7zip/Crypto/Rar5Aes.h @@ -0,0 +1,84 @@ +// Crypto/Rar5Aes.h + +#ifndef __CRYPTO_RAR5_AES_H +#define __CRYPTO_RAR5_AES_H + +#include "../../../C/Aes.h" + +#include "../../Common/MyBuffer.h" + +#include "HmacSha256.h" +#include "MyAes.h" + +namespace NCrypto { +namespace NRar5 { + +const unsigned kSaltSize = 16; +const unsigned kPswCheckSize = 8; +const unsigned kAesKeySize = 32; + +namespace NCryptoFlags +{ + const unsigned kPswCheck = 1 << 0; + const unsigned kUseMAC = 1 << 1; +} + +struct CKey +{ + bool _needCalc; + + unsigned _numIterationsLog; + Byte _salt[kSaltSize]; + CByteBuffer _password; + + Byte _key[kAesKeySize]; + Byte _check_Calced[kPswCheckSize]; + Byte _hashKey[SHA256_DIGEST_SIZE]; + + void CopyCalcedKeysFrom(const CKey &k) + { + memcpy(_key, k._key, sizeof(_key)); + memcpy(_check_Calced, k._check_Calced, sizeof(_check_Calced)); + memcpy(_hashKey, k._hashKey, sizeof(_hashKey)); + } + + bool IsKeyEqualTo(const CKey &key) + { + return (_numIterationsLog == key._numIterationsLog + && memcmp(_salt, key._salt, sizeof(_salt)) == 0 + && _password == key._password); + } + + CKey(); +}; + + +class CDecoder: + public CAesCbcDecoder, + public CKey +{ + Byte _check[kPswCheckSize]; + bool _canCheck; + UInt64 Flags; + + bool IsThereCheck() const { return ((Flags & NCryptoFlags::kPswCheck) != 0); } +public: + Byte _iv[AES_BLOCK_SIZE]; + + CDecoder(); + + STDMETHOD(Init)(); + + void SetPassword(const Byte *data, size_t size); + HRESULT SetDecoderProps(const Byte *data, unsigned size, bool includeIV, bool isService); + + bool CalcKey_and_CheckPassword(); + + bool UseMAC() const { return (Flags & NCryptoFlags::kUseMAC) != 0; } + UInt32 Hmac_Convert_Crc32(UInt32 crc) const; + void Hmac_Convert_32Bytes(Byte *data) const; +}; + +}} + +#endif diff --git a/CPP/7zip/Crypto/RarAes.cpp b/CPP/7zip/Crypto/RarAes.cpp index f562023a..5bae8529 100644 --- a/CPP/7zip/Crypto/RarAes.cpp +++ b/CPP/7zip/Crypto/RarAes.cpp @@ -1,5 +1,4 @@ // Crypto/RarAes.cpp -// Note: you must include MyAes.cpp to project to initialize AES tables #include "StdAfx.h" @@ -7,10 +6,10 @@ #include "Sha1Cls.h" namespace NCrypto { -namespace NRar29 { +namespace NRar3 { CDecoder::CDecoder(): - CAesCbcDecoder(kRarAesKeySize), + CAesCbcDecoder(kAesKeySize), _thereIsSalt(false), _needCalc(true), _rar350Mode(false) @@ -19,7 +18,7 @@ CDecoder::CDecoder(): _salt[i] = 0; } -STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) +HRESULT CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) { bool prev = _thereIsSalt; _thereIsSalt = false; @@ -53,12 +52,12 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) return S_OK; } -static const unsigned kPasswordLen_MAX = 127 * 2; +static const unsigned kPasswordLen_Bytes_MAX = 127 * 2; -STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size) +void CDecoder::SetPassword(const Byte *data, unsigned size) { - if (size > kPasswordLen_MAX) - size = kPasswordLen_MAX; + if (size > kPasswordLen_Bytes_MAX) + size = kPasswordLen_Bytes_MAX; bool same = false; if (size == _password.Size()) { @@ -73,13 +72,12 @@ STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size) if (!_needCalc && !same) _needCalc = true; _password.CopyFrom(data, (size_t)size); - return S_OK; } STDMETHODIMP CDecoder::Init() { CalcKey(); - RINOK(SetKey(_key, kRarAesKeySize)); + RINOK(SetKey(_key, kAesKeySize)); RINOK(SetInitVector(_iv, AES_BLOCK_SIZE)); return CAesCbcCoder::Init(); } @@ -91,7 +89,7 @@ void CDecoder::CalcKey() const unsigned kSaltSize = 8; - Byte buf[kPasswordLen_MAX + kSaltSize]; + Byte buf[kPasswordLen_Bytes_MAX + kSaltSize]; if (_password.Size() != 0) memcpy(buf, _password, _password.Size()); @@ -109,7 +107,7 @@ void CDecoder::CalcKey() Byte digest[NSha1::kDigestSize]; // rar reverts hash for sha. - const UInt32 kNumRounds = (1 << 18); + const UInt32 kNumRounds = ((UInt32)1 << 18); UInt32 i; for (i = 0; i < kNumRounds; i++) { diff --git a/CPP/7zip/Crypto/RarAes.h b/CPP/7zip/Crypto/RarAes.h index 197a0b2d..083b4104 100644 --- a/CPP/7zip/Crypto/RarAes.h +++ b/CPP/7zip/Crypto/RarAes.h @@ -12,14 +12,14 @@ #include "MyAes.h" namespace NCrypto { -namespace NRar29 { +namespace NRar3 { -const UInt32 kRarAesKeySize = 16; +const unsigned kAesKeySize = 16; class CDecoder: - public CAesCbcDecoder, + public CAesCbcDecoder // public ICompressSetDecoderProperties2, - public ICryptoSetPassword + // public ICryptoSetPassword { Byte _salt[8]; bool _thereIsSalt; @@ -28,17 +28,20 @@ class CDecoder: CByteBuffer _password; - Byte _key[kRarAesKeySize]; + Byte _key[kAesKeySize]; Byte _iv[AES_BLOCK_SIZE]; void CalcKey(); public: + /* MY_UNKNOWN_IMP1( - ICryptoSetPassword) + ICryptoSetPassword // ICompressSetDecoderProperties2 + */ STDMETHOD(Init)(); - STDMETHOD(CryptoSetPassword)(const Byte *aData, UInt32 aSize); - STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + + void SetPassword(const Byte *data, unsigned size); + HRESULT SetDecoderProperties2(const Byte *data, UInt32 size); CDecoder(); void SetRar350Mode(bool rar350Mode) { _rar350Mode = rar350Mode; } diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt index 64214e80..1ab1b7a2 100644 --- a/CPP/7zip/Guid.txt +++ b/CPP/7zip/Guid.txt @@ -163,6 +163,7 @@ Handler GUIDs: 0C xz 0D ppmd + CC Rar5 CD IHex CE Hxs CF TE diff --git a/CPP/7zip/IProgress.h b/CPP/7zip/IProgress.h index 59c55aea..fac951ec 100644 --- a/CPP/7zip/IProgress.h +++ b/CPP/7zip/IProgress.h @@ -4,7 +4,6 @@ #define __IPROGRESS_H #include "../Common/MyTypes.h" -#include "../Common/MyUnknown.h" #include "IDecl.h" diff --git a/CPP/7zip/IStream.h b/CPP/7zip/IStream.h index 70cb3620..9a0bcbf3 100644 --- a/CPP/7zip/IStream.h +++ b/CPP/7zip/IStream.h @@ -4,7 +4,7 @@ #define __ISTREAM_H #include "../Common/MyTypes.h" -#include "../Common/MyUnknown.h" +#include "../Common/MyWindows.h" #include "IDecl.h" diff --git a/CPP/7zip/PropID.h b/CPP/7zip/PropID.h index 3f3acb2d..1822f402 100644 --- a/CPP/7zip/PropID.h +++ b/CPP/7zip/PropID.h @@ -102,6 +102,7 @@ enum kpidStreamId, kpidReadOnly, kpidOutName, + kpidCopyLink, kpid_NUM_DEFINED, diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp index 3fed8cba..0468fdd1 100644 --- a/CPP/7zip/UI/Agent/AgentOut.cpp +++ b/CPP/7zip/UI/Agent/AgentOut.cpp @@ -380,6 +380,21 @@ STDMETHODIMP CAgent::DoOperation( HRESULT res = outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(), updateCallback); if (res == S_OK && processedPaths) { + { + /* OutHandler for 7z archives doesn't report compression operation for empty files. + So we must include these files manually */ + FOR_VECTOR(i, updatePairs2) + { + const CUpdatePair2 &up = updatePairs2[i]; + if (up.DirIndex >= 0 && up.NewData) + { + const CDirItem &di = dirItems.Items[up.DirIndex]; + if (!di.IsDir() && di.Size == 0) + processedItems[up.DirIndex] = 1; + } + } + } + FOR_VECTOR (i, dirItems.Items) if (processedItems[i] != 0) processedPaths->Add(dirItems.GetPhyPath(i)); diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp index 4df4b199..4d85754d 100644 --- a/CPP/7zip/UI/Client7z/Client7z.cpp +++ b/CPP/7zip/UI/Client7z/Client7z.cpp @@ -4,6 +4,8 @@ #include <stdio.h> +#include "../../../Common/MyWindows.h" + #include "../../../Common/Defs.h" #include "../../../Common/MyInitGuid.h" diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp index 8410756a..8e4936a9 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp @@ -5,6 +5,8 @@ #undef sprintf #undef printf +#include "../../../../C/Alloc.h" + #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" @@ -23,6 +25,7 @@ #endif #include "../../Common/FilePathAutoRename.h" +// #include "../../Common/StreamUtils.h" #include "../Common/ExtractingFilePath.h" #include "../Common/PropIDUtils.h" @@ -541,11 +544,54 @@ static FString MakePath_from_2_Parts(const FString &prefix, const FString &path) return s; } + +/* +#ifdef SUPPORT_LINKS + +struct CTempMidBuffer +{ + void *Buf; + + CTempMidBuffer(size_t size): Buf(NULL) { Buf = ::MidAlloc(size); } + ~CTempMidBuffer() { ::MidFree(Buf); } +}; + +HRESULT CArchiveExtractCallback::MyCopyFile(ISequentialOutStream *outStream) +{ + const size_t kBufSize = 1 << 16; + CTempMidBuffer buf(kBufSize); + if (!buf.Buf) + return E_OUTOFMEMORY; + + NIO::CInFile inFile; + NIO::COutFile outFile; + + if (!inFile.Open(_CopyFile_Path)) + return SendMessageError_with_LastError("Open error", _CopyFile_Path); + + for (;;) + { + UInt32 num; + + if (!inFile.Read(buf.Buf, kBufSize, num)) + return SendMessageError_with_LastError("Read error", _CopyFile_Path); + + if (num == 0) + return S_OK; + + + RINOK(WriteStream(outStream, buf.Buf, num)); + } +} + +#endif +*/ + STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { COM_TRY_BEGIN - *outStream = 0; + *outStream = NULL; #ifndef _SFX if (_hashStream) @@ -563,6 +609,11 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre _curSizeDefined = false; _index = index; + #ifdef SUPPORT_LINKS + // _CopyFile_Path.Empty(); + linkPath.Empty(); + #endif + IInArchive *archive = _arc->Archive; #ifndef _SFX @@ -596,46 +647,56 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre #ifdef SUPPORT_LINKS + // bool isCopyLink = false; bool isHardLink = false; bool isJunction = false; bool isRelative = false; - UString linkPath; - // RINOK(Archive_GetItemBoolProp(archive, index, kpidIsHardLink, isHardLink)); - // if (isHardLink) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidHardLink, &prop)); if (prop.vt == VT_BSTR) { isHardLink = true; + // isCopyLink = false; + isRelative = false; // RAR5, TAR: hard links are from root folder of archive linkPath.SetFromBstr(prop.bstrVal); - isRelative = false; // TAR: hard links are from root folder of archive } - else if (prop.vt == VT_EMPTY) + else if (prop.vt != VT_EMPTY) + return E_FAIL; + } + + /* + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidCopyLink, &prop)); + if (prop.vt == VT_BSTR) { - // linkPath.Empty(); + isHardLink = false; + isCopyLink = true; + isRelative = false; // RAR5: copy links are from root folder of archive + linkPath.SetFromBstr(prop.bstrVal); } - else + else if (prop.vt != VT_EMPTY) return E_FAIL; } + */ + { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidSymLink, &prop)); if (prop.vt == VT_BSTR) { isHardLink = false; + // isCopyLink = false; + isRelative = true; // RAR5, TAR: symbolic links can be relative linkPath.SetFromBstr(prop.bstrVal); - isRelative = true; // TAR: symbolic links are relative } - else if (prop.vt == VT_EMPTY) - { - // linkPath.Empty(); - } - else + else if (prop.vt != VT_EMPTY) return E_FAIL; } + bool isOkReparse = false; if (linkPath.IsEmpty() && _arc->GetRawProps) @@ -643,7 +704,9 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre const void *data; UInt32 dataSize; UInt32 propType; + _arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType); + if (dataSize != 0) { if (propType != NPropDataType::kRaw) @@ -654,6 +717,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre if (isOkReparse) { isHardLink = false; + // isCopyLink = false; linkPath = reparse.GetPath(); isJunction = reparse.IsMountPoint(); isRelative = reparse.IsRelative(); @@ -669,6 +733,13 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre #ifdef _WIN32 linkPath.Replace(L'/', WCHAR_PATH_SEPARATOR); #endif + + // rar5 uses "\??\" prefix for absolute links + if (linkPath.IsPrefixedBy(WSTRING_PATH_SEPARATOR L"??" WSTRING_PATH_SEPARATOR)) + { + isRelative = false; + linkPath.DeleteFrontal(4); + } for (;;) // while (NName::IsAbsolutePath(linkPath)) @@ -1108,7 +1179,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) else { FString existPath; - if (isHardLink || !isRelative) + if (isHardLink /* || isCopyLink */ || !isRelative) { if (!NName::GetFullPath(_dirPathPrefix_Full, us2fs(relatPath), existPath)) { @@ -1122,13 +1193,37 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) if (!existPath.IsEmpty()) { - if (isHardLink) + if (isHardLink /* || isCopyLink */) { - if (!MyCreateHardLink(fullProcessedPath, existPath)) + // if (isHardLink) { - RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, existPath)); - // return S_OK; + if (!MyCreateHardLink(fullProcessedPath, existPath)) + { + RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, existPath)); + // return S_OK; + } } + /* + else + { + NFind::CFileInfo fi; + if (!fi.Find(existPath)) + { + RINOK(SendMessageError2("Can not find the file for copying", existPath, fullProcessedPath)); + } + else + { + if (_curSizeDefined && _curSize == fi.Size) + _CopyFile_Path = existPath; + else + { + RINOK(SendMessageError2("File size collision for file copying", existPath, fullProcessedPath)); + } + + // RINOK(MyCopyFile(existPath, fullProcessedPath)); + } + } + */ } else if (_ntOptions.SymLinks.Val) { @@ -1161,7 +1256,8 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) #endif } - else + + if (linkPath.IsEmpty() /* || !_CopyFile_Path.IsEmpty() */) #endif // SUPPORT_LINKS { bool needWriteFile = true; @@ -1225,6 +1321,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) { RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL)); } + _outFileStream = outStreamLoc; } } @@ -1250,12 +1347,34 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) #endif + if (outStreamLoc) + { + /* + #ifdef SUPPORT_LINKS + + if (!_CopyFile_Path.IsEmpty()) + { + RINOK(PrepareOperation(askExtractMode)); + RINOK(MyCopyFile(outStreamLoc)); + return SetOperationResult(NArchive::NExtract::NOperationResult::kOK); + } + + if (isCopyLink && _testMode) + return S_OK; + + #endif + */ + *outStream = outStreamLoc.Detach(); + } + return S_OK; + COM_TRY_END } + STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { COM_TRY_BEGIN @@ -1266,6 +1385,7 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) #endif _extractMode = false; + switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: @@ -1282,6 +1402,7 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) COM_TRY_END } + STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes) { COM_TRY_BEGIN @@ -1346,6 +1467,7 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes) if (!_curSizeDefined) GetUnpackSize(); + if (_curSizeDefined) { #ifdef SUPPORT_ALT_STREAMS @@ -1367,8 +1489,11 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes) if (_extractMode && _fi.AttribDefined) SetFileAttrib(_diskFilePath, _fi.Attrib); + RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted))); + return S_OK; + COM_TRY_END } diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h index 561a6e42..7d4155fe 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h @@ -299,14 +299,23 @@ public: const UStringVector &removePathParts, bool removePartsForAltStreams, UInt64 packSize); + #ifdef SUPPORT_LINKS + private: CHardLinks _hardLinks; + UString linkPath; + + // FString _CopyFile_Path; + // HRESULT MyCopyFile(ISequentialOutStream *outStream); + public: // call PrepareHardLinks() after Init() HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items + #endif + #ifdef SUPPORT_ALT_STREAMS CObjectVector<CIndexToPathPair> _renamedFiles; #endif diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/CPP/7zip/UI/Common/ArchiveOpenCallback.h index afa03766..e9575f56 100644 --- a/CPP/7zip/UI/Common/ArchiveOpenCallback.h +++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.h @@ -48,18 +48,13 @@ class COpenCallbackImp: public CMyUnknownImp { public: + MY_QUERYINTERFACE_BEGIN2(IArchiveOpenVolumeCallback) + MY_QUERYINTERFACE_ENTRY(IArchiveOpenSetSubArchiveName) #ifndef _NO_CRYPTO - MY_UNKNOWN_IMP3( - IArchiveOpenVolumeCallback, - ICryptoGetTextPassword, - IArchiveOpenSetSubArchiveName - ) - #else - MY_UNKNOWN_IMP2( - IArchiveOpenVolumeCallback, - IArchiveOpenSetSubArchiveName - ) + MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword) #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE INTERFACE_IArchiveOpenCallback(;) INTERFACE_IArchiveOpenVolumeCallback(;) @@ -93,7 +88,8 @@ public: CMyComPtr<IArchiveOpenCallback> ReOpenCallback; // UInt64 TotalSize; - COpenCallbackImp(): Callback(NULL) {} + COpenCallbackImp(): Callback(NULL), _subArchiveMode(false) {} + void Init(const FString &folderPrefix, const FString &fileName) { _folderPrefix = folderPrefix; @@ -106,6 +102,7 @@ public: // TotalSize = 0; PasswordWasAsked = false; } + bool SetSecondFileInfo(CFSTR newName) { return _fileInfo.Find(newName) && !_fileInfo.IsDir(); diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp index c38b132c..5f6373f4 100644 --- a/CPP/7zip/UI/Common/Bench.cpp +++ b/CPP/7zip/UI/Common/Bench.cpp @@ -1566,7 +1566,8 @@ static const CBenchHash g_Hash[] = { 10, 339, 0x8F8FEDAB, "CRC32:8" }, { 10, 512, 0xDF1C17CC, "CRC64" }, { 10, 5100, 0x2D79FF2E, "SHA256" }, - { 10, 2340, 0x4C25132B, "SHA1" } + { 10, 2340, 0x4C25132B, "SHA1" }, + { 2, 5500, 0xE084E913, "BLAKE2sp" } }; struct CTotalBenchRes diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp index 696b6749..5435499b 100644 --- a/CPP/7zip/UI/Common/LoadCodecs.cpp +++ b/CPP/7zip/UI/Common/LoadCodecs.cpp @@ -865,7 +865,7 @@ STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder) { const CCodecLib &lib = Libs[ci.LibIndex]; if (lib.CreateDecoder) - return lib.CreateDecoder(index - NUM_EXPORT_CODECS, iid, (void **)coder); + return lib.CreateDecoder(ci.CodecIndex, iid, (void **)coder); return lib.CreateObject(&ci.Decoder, iid, (void **)coder); } return S_OK; @@ -887,7 +887,7 @@ STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder) { const CCodecLib &lib = Libs[ci.LibIndex]; if (lib.CreateEncoder) - return lib.CreateEncoder(index - NUM_EXPORT_CODECS, iid, (void **)coder); + return lib.CreateEncoder(ci.CodecIndex, iid, (void **)coder); return lib.CreateObject(&ci.Encoder, iid, (void **)coder); } return S_OK; diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp index acc10876..a7488044 100644 --- a/CPP/7zip/UI/Common/OpenArchive.cpp +++ b/CPP/7zip/UI/Common/OpenArchive.cpp @@ -1083,6 +1083,7 @@ static bool IsNewStyleSignature(const CArcInfoEx &ai) class CArchiveOpenCallback_Offset: public IArchiveOpenCallback, + public IArchiveOpenVolumeCallback, #ifndef _NO_CRYPTO public ICryptoGetTextPassword, #endif @@ -1090,19 +1091,24 @@ class CArchiveOpenCallback_Offset: { public: CMyComPtr<IArchiveOpenCallback> Callback; + CMyComPtr<IArchiveOpenVolumeCallback> OpenVolumeCallback; UInt64 Files; UInt64 Offset; #ifndef _NO_CRYPTO CMyComPtr<ICryptoGetTextPassword> GetTextPassword; - MY_UNKNOWN_IMP2( - IArchiveOpenCallback, - ICryptoGetTextPassword) - #else - MY_UNKNOWN_IMP1(IArchiveOpenCallback) #endif - STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes); - STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes); + + MY_QUERYINTERFACE_BEGIN2(IArchiveOpenCallback) + MY_QUERYINTERFACE_ENTRY(IArchiveOpenVolumeCallback) + #ifndef _NO_CRYPTO + MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + INTERFACE_IArchiveOpenCallback(;) + INTERFACE_IArchiveOpenVolumeCallback(;) #ifndef _NO_CRYPTO STDMETHOD(CryptoGetTextPassword)(BSTR *password); #endif @@ -1119,12 +1125,12 @@ STDMETHODIMP CArchiveOpenCallback_Offset::CryptoGetTextPassword(BSTR *password) } #endif -STDMETHODIMP CArchiveOpenCallback_Offset::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */) +STDMETHODIMP CArchiveOpenCallback_Offset::SetTotal(const UInt64 *, const UInt64 *) { return S_OK; } -STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 * /* files */, const UInt64 *bytes) +STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 *, const UInt64 *bytes) { if (!Callback) return S_OK; @@ -1134,8 +1140,25 @@ STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 * /* files * return Callback->SetCompleted(&Files, &value); } +STDMETHODIMP CArchiveOpenCallback_Offset::GetProperty(PROPID propID, PROPVARIANT *value) +{ + if (OpenVolumeCallback) + return OpenVolumeCallback->GetProperty(propID, value); + NCOM::PropVariant_Clear(value); + return S_OK; + // return E_NOTIMPL; +} + +STDMETHODIMP CArchiveOpenCallback_Offset::GetStream(const wchar_t *name, IInStream **inStream) +{ + if (OpenVolumeCallback) + return OpenVolumeCallback->GetStream(name, inStream); + return S_FALSE; +} + #endif + UInt32 GetOpenArcErrorFlags(const NCOM::CPropVariant &prop, bool *isDefinedProp) { if (isDefinedProp != NULL) @@ -2208,9 +2231,6 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) } { - CArchiveOpenCallback_Offset *openCallback_Offset_Spec = new CArchiveOpenCallback_Offset; - CMyComPtr<IArchiveOpenCallback> openCallback_Offset = openCallback_Offset_Spec; - const size_t kBeforeSize = 1 << 16; const size_t kAfterSize = 1 << 20; const size_t kBufSize = 1 << 22; // it must be more than kBeforeSize + kAfterSize @@ -2288,14 +2308,18 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) CMyComPtr<IInStream> limitedStream = limitedStreamSpec; limitedStreamSpec->SetStream(op.stream); - openCallback_Offset_Spec->Callback = op.callback; - - #ifndef _NO_CRYPTO + CArchiveOpenCallback_Offset *openCallback_Offset_Spec = NULL; + CMyComPtr<IArchiveOpenCallback> openCallback_Offset; if (op.callback) { + openCallback_Offset_Spec = new CArchiveOpenCallback_Offset; + openCallback_Offset = openCallback_Offset_Spec; + openCallback_Offset_Spec->Callback = op.callback; + openCallback_Offset_Spec->Callback.QueryInterface(IID_IArchiveOpenVolumeCallback, &openCallback_Offset_Spec->OpenVolumeCallback); + #ifndef _NO_CRYPTO openCallback_Offset_Spec->Callback.QueryInterface(IID_ICryptoGetTextPassword, &openCallback_Offset_Spec->GetTextPassword); + #endif } - #endif if (op.callback) RINOK(op.callback->SetTotal(NULL, &fileSize)); @@ -2382,12 +2406,19 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) } } - if (pos >= callbackPrev + (1 << 23)) + bool useOffsetCallback = false; + if (openCallback_Offset) { openCallback_Offset_Spec->Files = handlerSpec->_items.Size(); openCallback_Offset_Spec->Offset = pos; - RINOK(openCallback_Offset->SetCompleted(NULL, NULL)); - callbackPrev = pos; + + useOffsetCallback = (!op.openType.CanReturnArc || handlerSpec->_items.Size() > 1); + + if (pos >= callbackPrev + (1 << 23)) + { + RINOK(openCallback_Offset_Spec->SetCompleted(NULL, NULL)); + callbackPrev = pos; + } } { @@ -2557,14 +2588,21 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) } UInt64 maxCheckStartPosition = 0; - openCallback_Offset_Spec->Files = handlerSpec->_items.Size(); - openCallback_Offset_Spec->Offset = startArcPos; + + if (openCallback_Offset) + { + openCallback_Offset_Spec->Files = handlerSpec->_items.Size(); + openCallback_Offset_Spec->Offset = startArcPos; + } + // HRESULT result = archive->Open(limitedStream, &maxCheckStartPosition, openCallback_Offset); extractCallback_To_OpenCallback_Spec->Files = 0; extractCallback_To_OpenCallback_Spec->Offset = startArcPos; - HRESULT result = OpenArchiveSpec(archive, true, limitedStream, &maxCheckStartPosition, openCallback_Offset, extractCallback_To_OpenCallback); - + HRESULT result = OpenArchiveSpec(archive, true, limitedStream, &maxCheckStartPosition, + useOffsetCallback ? (IArchiveOpenCallback *)openCallback_Offset : (IArchiveOpenCallback *)op.callback, + extractCallback_To_OpenCallback); + RINOK(ReadBasicProps(archive, ai.Flags_UseGlobalOffset() ? 0 : startArcPos, result)); bool isOpen = false; diff --git a/CPP/7zip/UI/Common/UpdateAction.h b/CPP/7zip/UI/Common/UpdateAction.h index 28dd28c3..bc53fcdb 100644 --- a/CPP/7zip/UI/Common/UpdateAction.h +++ b/CPP/7zip/UI/Common/UpdateAction.h @@ -35,7 +35,7 @@ namespace NUpdateArchive { { NPairAction::EEnum StateActions[NPairState::kNumValues]; - const bool IsEqualTo(const CActionSet &a) const + bool IsEqualTo(const CActionSet &a) const { for (unsigned i = 0; i < NPairState::kNumValues; i++) if (StateActions[i] != a.StateActions[i]) diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp index 993ab266..058e9153 100644 --- a/CPP/7zip/UI/Common/UpdateCallback.cpp +++ b/CPP/7zip/UI/Common/UpdateCallback.cpp @@ -413,7 +413,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR { case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break; case kpidIsDir: prop = di.IsDir(); break; - case kpidSize: prop = di.Size; break; + case kpidSize: prop = di.IsDir() ? (UInt64)0 : di.Size; break; case kpidAttrib: prop = di.Attrib; break; case kpidCTime: prop = di.CTime; break; case kpidATime: prop = di.ATime; break; diff --git a/CPP/7zip/UI/Console/ConsoleClose.cpp b/CPP/7zip/UI/Console/ConsoleClose.cpp index 75bd9e51..6bf2531d 100644 --- a/CPP/7zip/UI/Console/ConsoleClose.cpp +++ b/CPP/7zip/UI/Console/ConsoleClose.cpp @@ -4,6 +4,10 @@ #include "ConsoleClose.h" +#if !defined(UNDER_CE) && defined(_WIN32) +#include "../../../Common/MyWindows.h" +#endif + namespace NConsoleClose { unsigned g_BreakCounter = 0; diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp index 64abb1fb..e70f1b67 100644 --- a/CPP/7zip/UI/Console/List.cpp +++ b/CPP/7zip/UI/Console/List.cpp @@ -123,6 +123,7 @@ static const char * const kPropIdToName[] = , "Stream ID" , "Read-only" , "Out Name" + , "Copy Link" }; static const char kEmptyAttribChar = '.'; diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp index 83e6ef5b..b9cb4eb9 100644 --- a/CPP/7zip/UI/Console/Main.cpp +++ b/CPP/7zip/UI/Console/Main.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../Common/MyWindows.h" + #include <Psapi.h> #include "../../../../C/CpuArch.h" @@ -230,42 +232,51 @@ static void PrintWarningsPaths(const CErrorPathCodes &pc, CStdOutStream &so) } static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback, - const CUpdateErrorInfo &errorInfo, CStdOutStream &so, bool showHeaders) + const CUpdateErrorInfo &errorInfo, + CStdOutStream *so, + CStdOutStream *se, + bool showHeaders) { int exitCode = NExitCode::kSuccess; if (callback.ScanErrors.Paths.Size() != 0) { - so << endl; - so << "Scan WARNINGS for files and folders:" << endl << endl; - PrintWarningsPaths(callback.ScanErrors, so); - so << "Scan WARNINGS: " << callback.ScanErrors.Paths.Size(); - so << endl; + if (se) + { + *se << endl; + *se << "Scan WARNINGS for files and folders:" << endl << endl; + PrintWarningsPaths(callback.ScanErrors, *se); + *se << "Scan WARNINGS: " << callback.ScanErrors.Paths.Size(); + *se << endl; + } exitCode = NExitCode::kWarning; } if (result != S_OK || errorInfo.ThereIsError()) { - UString message; - if (!errorInfo.Message.IsEmpty()) - { - message.AddAscii(errorInfo.Message); - message.Add_LF(); - } + if (se) { - FOR_VECTOR(i, errorInfo.FileNames) + UString message; + if (!errorInfo.Message.IsEmpty()) { - message += fs2us(errorInfo.FileNames[i]); + message.AddAscii(errorInfo.Message); message.Add_LF(); } + { + FOR_VECTOR(i, errorInfo.FileNames) + { + message += fs2us(errorInfo.FileNames[i]); + message.Add_LF(); + } + } + if (errorInfo.SystemError != 0) + { + message += NError::MyFormatMessage(errorInfo.SystemError); + message.Add_LF(); + } + if (!message.IsEmpty()) + *se << L"\nError:\n" << message; } - if (errorInfo.SystemError != 0) - { - message += NError::MyFormatMessage(errorInfo.SystemError); - message.Add_LF(); - } - if (!message.IsEmpty()) - so << L"\nError:\n" << message; // we will work with (result) later // throw CSystemException(result); @@ -277,17 +288,25 @@ static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback, { if (showHeaders) if (callback.ScanErrors.Paths.Size() == 0) - so << kEverythingIsOk << endl; + if (so) + { + if (se) + se->Flush(); + *so << kEverythingIsOk << endl; + } } else { - so << endl; - so << "WARNINGS for files:" << endl << endl; - PrintWarningsPaths(callback.FailedFiles, so); - so << "WARNING: Cannot open " << numErrors << " file"; - if (numErrors > 1) - so << 's'; - so << endl; + if (se) + { + *se << endl; + *se << "WARNINGS for files:" << endl << endl; + PrintWarningsPaths(callback.FailedFiles, *se); + *se << "WARNING: Cannot open " << numErrors << " file"; + if (numErrors > 1) + *se << 's'; + *se << endl; + } exitCode = NExitCode::kWarning; } @@ -473,10 +492,7 @@ int Main2( CStdOutStream *percentsStream = NULL; if (options.Number_for_Percents != k_OutStream_disabled) percentsStream = (options.Number_for_Percents == k_OutStream_stderr) ? &g_StdErr : &g_StdOut;; - - CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut); - if (options.HelpMode) { ShowCopyrightAndHelp(g_StdStream, true); @@ -589,6 +605,7 @@ int Main2( if (options.Command.CommandType == NCommandType::kInfo) { + CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut); unsigned i; #ifdef EXTERNAL_CODECS @@ -754,6 +771,7 @@ int Main2( } else if (options.Command.CommandType == NCommandType::kBenchmark) { + CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut); hresultMain = BenchCon(EXTERNAL_CODECS_VARS_L options.Properties, options.NumIterations, (FILE *)so); if (hresultMain == S_FALSE) @@ -890,73 +908,91 @@ int Main2( hresultMain = E_FAIL; } - so << endl; + CStdOutStream *so = g_StdStream; + + bool isError = false; - if (ecs->NumTryArcs > 1) + if (so) { - so << "Archives: " << ecs->NumTryArcs << endl; - so << "OK archives: " << ecs->NumOkArcs << endl; + *so << endl; + + if (ecs->NumTryArcs > 1) + { + *so << "Archives: " << ecs->NumTryArcs << endl; + *so << "OK archives: " << ecs->NumOkArcs << endl; + } } - bool isError = false; + if (ecs->NumCantOpenArcs != 0) { isError = true; - so << "Can't open as archive: " << ecs->NumCantOpenArcs << endl; + if (so) + *so << "Can't open as archive: " << ecs->NumCantOpenArcs << endl; } + if (ecs->NumArcsWithError != 0) { isError = true; - so << "Archives with Errors: " << ecs->NumArcsWithError << endl; + if (so) + *so << "Archives with Errors: " << ecs->NumArcsWithError << endl; } - if (ecs->NumArcsWithWarnings != 0) - so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl; - if (ecs->NumOpenArcWarnings != 0) + if (so) { - so << endl; + if (ecs->NumArcsWithWarnings != 0) + *so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl; + if (ecs->NumOpenArcWarnings != 0) - so << "Warnings: " << ecs->NumOpenArcWarnings << endl; + { + *so << endl; + if (ecs->NumOpenArcWarnings != 0) + *so << "Warnings: " << ecs->NumOpenArcWarnings << endl; + } } if (ecs->NumOpenArcErrors != 0) { isError = true; - so << endl; - if (ecs->NumOpenArcErrors != 0) - so << "Open Errors: " << ecs->NumOpenArcErrors << endl; + if (so) + { + *so << endl; + if (ecs->NumOpenArcErrors != 0) + *so << "Open Errors: " << ecs->NumOpenArcErrors << endl; + } } if (isError) retCode = NExitCode::kFatalError; + if (so) if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0) { // if (ecs->NumArchives > 1) { - so << endl; + *so << endl; if (ecs->NumFileErrors != 0) - so << "Sub items Errors: " << ecs->NumFileErrors << endl; + *so << "Sub items Errors: " << ecs->NumFileErrors << endl; } } else if (hresultMain == S_OK) { if (stat.NumFolders != 0) - so << "Folders: " << stat.NumFolders << endl; + *so << "Folders: " << stat.NumFolders << endl; if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0) - so << "Files: " << stat.NumFiles << endl; + *so << "Files: " << stat.NumFiles << endl; if (stat.NumAltStreams != 0) { - so << "Alternate Streams: " << stat.NumAltStreams << endl; - so << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl; + *so << "Alternate Streams: " << stat.NumAltStreams << endl; + *so << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl; } - so + *so << "Size: " << stat.UnpackSize << endl << "Compressed: " << stat.PackSize << endl; if (hashCalc) { - so << endl; - PrintHashStat(so, hb); + *so << endl; + PrintHashStat(*so, hb); } } } @@ -1047,9 +1083,14 @@ int Main2( callback.ClosePercents2(); - retCode = WarningsCheck(hresultMain, callback, errorInfo, so, - // options.EnableHeaders - true); + CStdOutStream *se = g_StdStream; + if (!se) + se = g_ErrStream; + + retCode = WarningsCheck(hresultMain, callback, errorInfo, + g_StdStream, se, + true // options.EnableHeaders + ); } else if (options.Command.CommandType == NCommandType::kHash) { @@ -1068,7 +1109,10 @@ int Main2( errorInfoString, &callback); CUpdateErrorInfo errorInfo; errorInfo.Message = errorInfoString; - retCode = WarningsCheck(hresultMain, callback, errorInfo, so, options.EnableHeaders); + CStdOutStream *se = g_StdStream; + if (!se) + se = g_ErrStream; + retCode = WarningsCheck(hresultMain, callback, errorInfo, g_StdStream, se, options.EnableHeaders); } else ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError); diff --git a/CPP/7zip/UI/Explorer/ContextMenu.h b/CPP/7zip/UI/Explorer/ContextMenu.h index a3b1174b..90ca0e64 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.h +++ b/CPP/7zip/UI/Explorer/ContextMenu.h @@ -3,6 +3,10 @@ #ifndef __CONTEXT_MENU_H #define __CONTEXT_MENU_H +#include "../../../Common/MyWindows.h" + +#include <ShlObj.h> + #include "../../../Common/MyString.h" #include "../FileManager/MyCom2.h" diff --git a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp index d620cb70..3b04e7be 100644 --- a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp +++ b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp @@ -8,11 +8,13 @@ #include "StdAfx.h" -#include "../../../Common/MyInitGuid.h" +#include "../../../Common/MyWindows.h" #include <ShlGuid.h> #include <OleCtl.h> +#include "../../../Common/MyInitGuid.h" + #include "../../../Common/ComTry.h" #include "../../../Common/StringConvert.h" diff --git a/CPP/7zip/UI/Far/Far.cpp b/CPP/7zip/UI/Far/Far.cpp index 3ae5bba2..d5656e29 100644 --- a/CPP/7zip/UI/Far/Far.cpp +++ b/CPP/7zip/UI/Far/Far.cpp @@ -3,6 +3,8 @@ #include "StdAfx.h" +#include "../../../Common/MyWindows.h" + #include "../../../Common/MyInitGuid.h" #include "../../../Common/StringConvert.h" @@ -96,6 +98,7 @@ EXTERN_C void WINAPI SetStartupInfo(const PluginStartupInfo *info) class COpenArchiveCallback: public IArchiveOpenCallback, public IArchiveOpenVolumeCallback, + public IArchiveOpenSetSubArchiveName, public IProgress, public ICryptoGetTextPassword, public CMyUnknownImp @@ -109,6 +112,8 @@ class COpenArchiveCallback: bool _numBytesTotalDefined; NFind::CFileInfo _fileInfo; + bool _subArchiveMode; + UString _subArchiveName; public: bool PasswordIsDefined; UString Password; @@ -116,8 +121,9 @@ public: FString _folderPrefix; public: - MY_UNKNOWN_IMP3( + MY_UNKNOWN_IMP4( IArchiveOpenVolumeCallback, + IArchiveOpenSetSubArchiveName, IProgress, ICryptoGetTextPassword ) @@ -134,13 +140,24 @@ public: STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value); STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream); + STDMETHOD(SetSubArchiveName(const wchar_t *name)) + { + _subArchiveMode = true; + _subArchiveName = name; + return S_OK; + } + // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *password); + COpenArchiveCallback(): _subArchiveMode(false) {} + void Init() { PasswordIsDefined = false; + _subArchiveMode = false; + _numFilesTotalDefined = false; _numBytesTotalDefined = false; @@ -220,6 +237,8 @@ STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **in { if (WasEscPressed()) return E_ABORT; + if (_subArchiveMode) + return S_FALSE; *inStream = NULL; FString fullPath = _folderPrefix + us2fs(name); if (!_fileInfo.Find(fullPath)) @@ -238,6 +257,14 @@ STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **in STDMETHODIMP COpenArchiveCallback::GetProperty(PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; + if (_subArchiveMode) + { + switch(propID) + { + case kpidName: prop = _subArchiveName; break; + } + } + else switch(propID) { case kpidName: prop = GetUnicodeString(_fileInfo.Name, CP_OEMCP); break; diff --git a/CPP/7zip/UI/Far/Messages.h b/CPP/7zip/UI/Far/Messages.h index e6972392..0697a163 100644 --- a/CPP/7zip/UI/Far/Messages.h +++ b/CPP/7zip/UI/Far/Messages.h @@ -7,7 +7,7 @@ namespace NMessageID { -const UINT k_Last_PropId_supported_by_plugin = kpidStreamId; +const unsigned k_Last_PropId_supported_by_plugin = kpidStreamId; enum EEnum { diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp index 89a6b45a..8b605d0f 100644 --- a/CPP/7zip/UI/FileManager/BrowseDialog.cpp +++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp @@ -2,6 +2,10 @@ #include "StdAfx.h" +#include "../../../Common/MyWindows.h" + +#include <commctrl.h> + #ifndef UNDER_CE #include "../../../Windows/CommonDialog.h" #include "../../../Windows/Shell.h" @@ -106,7 +110,7 @@ class CBrowseDialog: public NControl::CModalDialog virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); virtual void OnOK(); - void Post_RefreshPathEdit() { PostMessage(k_Message_RefreshPathEdit); } + void Post_RefreshPathEdit() { PostMsg(k_Message_RefreshPathEdit); } bool GetParentPath(const UString &path, UString &parentPrefix, UString &name); // Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter @@ -295,7 +299,7 @@ bool CBrowseDialog::OnInit() #ifndef UNDER_CE /* If we clear UISF_HIDEFOCUS, the focus rectangle in ListView will be visible, even if we use mouse for pressing the button to open this dialog. */ - PostMessage(MY__WM_UPDATEUISTATE, MAKEWPARAM(MY__UIS_CLEAR, MY__UISF_HIDEFOCUS)); + PostMsg(MY__WM_UPDATEUISTATE, MAKEWPARAM(MY__UIS_CLEAR, MY__UISF_HIDEFOCUS)); #endif return CModalDialog::OnInit(); diff --git a/CPP/7zip/UI/FileManager/ClassDefs.cpp b/CPP/7zip/UI/FileManager/ClassDefs.cpp index b092a9ed..33197fc3 100644 --- a/CPP/7zip/UI/FileManager/ClassDefs.cpp +++ b/CPP/7zip/UI/FileManager/ClassDefs.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../Common/MyWindows.h" + #include "../../../Common/MyInitGuid.h" #include "../Agent/Agent.h" diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp index 00b152c8..1a7ed060 100644 --- a/CPP/7zip/UI/FileManager/FM.cpp +++ b/CPP/7zip/UI/FileManager/FM.cpp @@ -2,6 +2,10 @@ #include "StdAfx.h" +#include "../../../Common/MyWindows.h" + +#include <shlwapi.h> + #include "../../../../C/Alloc.h" #include "../../../Common/IntToString.h" diff --git a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp index 54dabc57..af0cd8cc 100644 --- a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp +++ b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../Common/MyWindows.h" + #include <Winbase.h> #include "../../../Common/Defs.h" @@ -585,7 +587,6 @@ STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num CCopyState state; state.ProgressInfo.TotalSize = stat.Size; - state.ProgressInfo.TotalSize = stat.Size; state.ProgressInfo.StartPos = 0; state.ProgressInfo.Progress = callback; state.ProgressInfo.Init(); @@ -593,7 +594,6 @@ STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num state.MoveMode = IntToBool(moveMode); state.UseReadWriteMode = isAltDest; state.Prepare(); - state.TotalSize = stat.Size; for (UInt32 i = 0; i < numItems; i++) { diff --git a/CPP/7zip/UI/FileManager/LinkDialog.cpp b/CPP/7zip/UI/FileManager/LinkDialog.cpp index bc482e4b..07f046e1 100644 --- a/CPP/7zip/UI/FileManager/LinkDialog.cpp +++ b/CPP/7zip/UI/FileManager/LinkDialog.cpp @@ -42,7 +42,7 @@ static const UInt32 kLangIDs[] = static bool GetSymLink(CFSTR path, CReparseAttr &attr) { - NFile::NIO::CInFile file; + NIO::CInFile file; if (!file.Open(path, FILE_SHARE_READ, OPEN_EXISTING, @@ -88,12 +88,13 @@ bool CLinkDialog::OnInit() LangSetWindowText(*this, IDD_LINK); LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); #endif + _pathFromCombo.Attach(GetItem(IDC_LINK_PATH_FROM)); _pathToCombo.Attach(GetItem(IDC_LINK_PATH_TO)); if (!FilePath.IsEmpty()) { - NFile::NFind::CFileInfo fi; + NFind::CFileInfo fi; int linkType = 0; if (!fi.Find(us2fs(FilePath))) linkType = IDR_LINK_TYPE_SYM_FILE; @@ -219,7 +220,7 @@ void CLinkDialog::OnButton_SetPath(bool to) UString resultPath; if (!MyBrowseForFolder(*this, title, currentPath, resultPath)) return; - NFile::NName::NormalizeDirPathPrefix(resultPath); + NName::NormalizeDirPathPrefix(resultPath); combo.SetCurSel(-1); combo.SetText(resultPath); } @@ -239,16 +240,23 @@ void CLinkDialog::OnButton_Link() UString from, to; _pathFromCombo.GetText(from); _pathToCombo.GetText(to); - int i; - for (i = 0; i < ARRAY_SIZE(k_LinkType_Buttons); i++) - if (IsButtonCheckedBool(k_LinkType_Buttons[i])) - break; - if (i >= ARRAY_SIZE(k_LinkType_Buttons)) + + if (from.IsEmpty()) return; + if (!NName::IsAbsolutePath(from)) + from.Insert(0, CurDirPrefix); - int idb = k_LinkType_Buttons[i]; + int idb = -1; + for (unsigned i = 0;; i++) + { + if (i >= ARRAY_SIZE(k_LinkType_Buttons)) + return; + idb = k_LinkType_Buttons[i]; + if (IsButtonCheckedBool(idb)) + break; + } - NFile::NFind::CFileInfo info1, info2; + NFind::CFileInfo info1, info2; bool finded1 = info1.Find(us2fs(from)); bool finded2 = info2.Find(us2fs(to)); @@ -259,14 +267,13 @@ void CLinkDialog::OnButton_Link() if (finded1 && info1.IsDir() != isDirLink || finded2 && info2.IsDir() != isDirLink) { - ShowError(L"Incorrect linkType"); + ShowError(L"Incorrect link type"); return; } if (idb == IDR_LINK_TYPE_HARD) { - bool res = NFile::NDir::MyCreateHardLink(us2fs(from), us2fs(to)); - if (!res) + if (!NDir::MyCreateHardLink(us2fs(from), us2fs(to))) { ShowLastErrorMessage(); return; @@ -291,9 +298,10 @@ void CLinkDialog::OnButton_Link() } - if (!NFile::NIO::SetReparseData(us2fs(from), isDirLink, data, (DWORD)data.Size())) + if (!NIO::SetReparseData(us2fs(from), isDirLink, data, (DWORD)data.Size())) { ShowLastErrorMessage(); + return; } } @@ -321,7 +329,8 @@ void CApp::Link() int index = indices[0]; const UString itemName = srcPanel.GetItemName(index); - UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index); + const UString fsPrefix = srcPanel.GetFsPath(); + const UString srcPath = fsPrefix + srcPanel.GetItemPrefix(index); UString path = srcPath; { int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); @@ -332,6 +341,7 @@ void CApp::Link() } CLinkDialog dlg; + dlg.CurDirPrefix = fsPrefix; dlg.FilePath = srcPath + itemName; dlg.AnotherPath = path; diff --git a/CPP/7zip/UI/FileManager/LinkDialog.h b/CPP/7zip/UI/FileManager/LinkDialog.h index 8417fac8..56deec9d 100644 --- a/CPP/7zip/UI/FileManager/LinkDialog.h +++ b/CPP/7zip/UI/FileManager/LinkDialog.h @@ -23,6 +23,7 @@ class CLinkDialog: public NWindows::NControl::CModalDialog void ShowError(const wchar_t *s); void Set_LinkType_Radio(int idb); public: + UString CurDirPrefix; UString FilePath; UString AnotherPath; diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp index a7416a4c..96a34af8 100644 --- a/CPP/7zip/UI/FileManager/Panel.cpp +++ b/CPP/7zip/UI/FileManager/Panel.cpp @@ -795,7 +795,7 @@ void CPanel::Change_ShowNtfsStrems_Mode() void CPanel::Post_Refresh_StatusBar() { if (_processStatusBar) - PostMessage(kRefresh_StatusBar); + PostMsg(kRefresh_StatusBar); } void CPanel::AddToArchive() diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h index 39915a27..5d03f6da 100644 --- a/CPP/7zip/UI/FileManager/Panel.h +++ b/CPP/7zip/UI/FileManager/Panel.h @@ -3,6 +3,10 @@ #ifndef __PANEL_H #define __PANEL_H +#include "../../../Common/MyWindows.h" + +#include <ShlObj.h> + #include "../../../../C/Alloc.h" #include "../../../Common/Defs.h" diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp index cd70c727..4d9ce51f 100644 --- a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp +++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp @@ -359,7 +359,7 @@ LRESULT CPanel::OnNotifyComboBoxEnter(const UString &s) { if (BindToPathAndRefresh(GetUnicodeString(s)) == S_OK) { - PostMessage(kSetFocusToListView); + PostMsg(kSetFocusToListView); return TRUE; } return FALSE; @@ -370,7 +370,7 @@ bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDITW info, LRESULT &result) if (info->iWhy == CBENF_ESCAPE) { _headerComboBox.SetText(_currentFolderPrefix); - PostMessage(kSetFocusToListView); + PostMsg(kSetFocusToListView); result = FALSE; return true; } @@ -401,7 +401,7 @@ bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info, LRESULT &result) if (info->iWhy == CBENF_ESCAPE) { _headerComboBox.SetText(_currentFolderPrefix); - PostMessage(kSetFocusToListView); + PostMsg(kSetFocusToListView); result = FALSE; return true; } @@ -528,9 +528,9 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result) // _headerComboBox.SetText(pass); // it's fix for seclecting by mouse. if (BindToPathAndRefresh(pass) == S_OK) { - PostMessage(kSetFocusToListView); + PostMsg(kSetFocusToListView); #ifdef UNDER_CE - PostMessage(kRefresh_HeaderComboBox); + PostMsg(kRefresh_HeaderComboBox); #endif return true; } diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp index a485522f..b47a30a3 100644 --- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp +++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../Common/MyWindows.h" + #include <tlhelp32.h> #include "../../../Common/AutoPtr.h" diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp index 62a08e13..0afbc07b 100644 --- a/CPP/7zip/UI/FileManager/PanelOperations.cpp +++ b/CPP/7zip/UI/FileManager/PanelOperations.cpp @@ -354,7 +354,7 @@ BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh) _dontShowMode = true; - PostMessage(kReLoadMessage); + PostMsg(kReLoadMessage); return TRUE; } diff --git a/CPP/7zip/UI/FileManager/PanelSelect.cpp b/CPP/7zip/UI/FileManager/PanelSelect.cpp index 7b53eb00..de9cf4b5 100644 --- a/CPP/7zip/UI/FileManager/PanelSelect.cpp +++ b/CPP/7zip/UI/FileManager/PanelSelect.cpp @@ -70,7 +70,7 @@ void CPanel::OnArrowWithShift() } _prevFocusedItem = focusedItem; - PostMessage(kShiftSelectMessage); + PostMsg(kShiftSelectMessage); _listView.RedrawItem(focusedItem); } diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.cpp b/CPP/7zip/UI/FileManager/ProgressDialog.cpp index b4195c18..4b20f1a9 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog.cpp +++ b/CPP/7zip/UI/FileManager/ProgressDialog.cpp @@ -184,7 +184,7 @@ void CProgressDialog::CheckNeedClose() { if (_needClose) { - PostMessage(kCloseMessage); + PostMsg(kCloseMessage); _needClose = false; } } diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.h b/CPP/7zip/UI/FileManager/ProgressDialog.h index 175db017..0f41b57a 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog.h +++ b/CPP/7zip/UI/FileManager/ProgressDialog.h @@ -152,7 +152,7 @@ public: { WaitCreating(); if (_wasCreated) - PostMessage(kCloseMessage); + PostMsg(kCloseMessage); else _needClose = true; }; diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp index 231d0ace..dc828e72 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp @@ -1229,7 +1229,7 @@ void CProgressDialog::CheckNeedClose() { if (_needClose) { - PostMessage(kCloseMessage); + PostMsg(kCloseMessage); _needClose = false; } } @@ -1241,7 +1241,7 @@ void CProgressDialog::ProcessWasFinished() WaitCreating(); if (_wasCreated) - PostMessage(kCloseMessage); + PostMsg(kCloseMessage); else _needClose = true; } diff --git a/CPP/7zip/UI/FileManager/PropertyName.rc b/CPP/7zip/UI/FileManager/PropertyName.rc index 8b8c7899..5de5aeec 100644 --- a/CPP/7zip/UI/FileManager/PropertyName.rc +++ b/CPP/7zip/UI/FileManager/PropertyName.rc @@ -96,4 +96,5 @@ BEGIN IDS_PROP_STREAM_ID "Stream ID" IDS_PROP_READ_ONLY "Read-only" IDS_PROP_OUT_NAME "Out Name" + IDS_PROP_COPY_LINK "Copy Link" END diff --git a/CPP/7zip/UI/FileManager/PropertyNameRes.h b/CPP/7zip/UI/FileManager/PropertyNameRes.h index 3696ed2e..67f33902 100644 --- a/CPP/7zip/UI/FileManager/PropertyNameRes.h +++ b/CPP/7zip/UI/FileManager/PropertyNameRes.h @@ -92,3 +92,4 @@ #define IDS_PROP_STREAM_ID 1092 #define IDS_PROP_READ_ONLY 1093 #define IDS_PROP_OUT_NAME 1094 +#define IDS_PROP_COPY_LINK 1095 diff --git a/CPP/7zip/UI/FileManager/RootFolder.cpp b/CPP/7zip/UI/FileManager/RootFolder.cpp index c5b57821..2a5d513a 100644 --- a/CPP/7zip/UI/FileManager/RootFolder.cpp +++ b/CPP/7zip/UI/FileManager/RootFolder.cpp @@ -2,6 +2,10 @@ #include "StdAfx.h" +#include "../../../Common/MyWindows.h" + +#include <ShlObj.h> + #include "../../../Common/StringConvert.h" #include "../../../Windows/DLL.h" diff --git a/CPP/7zip/UI/FileManager/StdAfx.h b/CPP/7zip/UI/FileManager/StdAfx.h index 85389112..e6d96041 100644 --- a/CPP/7zip/UI/FileManager/StdAfx.h +++ b/CPP/7zip/UI/FileManager/StdAfx.h @@ -12,8 +12,10 @@ #include "../../../Common/Common.h" -#include <commctrl.h> -#include <ShlObj.h> -#include <shlwapi.h> +// #include "../../../Common/MyWindows.h" + +// #include <commctrl.h> +// #include <ShlObj.h> +// #include <shlwapi.h> #endif diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.cpp b/CPP/7zip/UI/FileManager/SysIconUtils.cpp index 2c35c191..c400bc29 100644 --- a/CPP/7zip/UI/FileManager/SysIconUtils.cpp +++ b/CPP/7zip/UI/FileManager/SysIconUtils.cpp @@ -10,6 +10,8 @@ #include "SysIconUtils.h" +#include <ShlObj.h> + #ifndef _UNICODE extern bool g_IsNT; #endif diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.h b/CPP/7zip/UI/FileManager/SysIconUtils.h index 20199acb..f1b27fa1 100644 --- a/CPP/7zip/UI/FileManager/SysIconUtils.h +++ b/CPP/7zip/UI/FileManager/SysIconUtils.h @@ -3,6 +3,10 @@ #ifndef __SYS_ICON_UTILS_H #define __SYS_ICON_UTILS_H +#include "../../../Common/MyWindows.h" + +#include <commctrl.h> + #include "../../../Common/MyString.h" struct CExtIconPair diff --git a/CPP/7zip/UI/FileManager/SystemPage.cpp b/CPP/7zip/UI/FileManager/SystemPage.cpp index a7f0c3fb..d60d7b4f 100644 --- a/CPP/7zip/UI/FileManager/SystemPage.cpp +++ b/CPP/7zip/UI/FileManager/SystemPage.cpp @@ -2,6 +2,10 @@ #include "StdAfx.h" +#include "../../../Common/MyWindows.h" + +#include <ShlObj.h> + #include "../../../Common/StringConvert.h" #include "../../../Common/Defs.h" diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp index 2f118846..db4b1378 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp @@ -114,7 +114,7 @@ bool CBenchmarkDialog::OnInit() // f.lfFaceName[0] = 0; _font.Create(&f); if (_font._font) - _consoleEdit.SendMessage(WM_SETFONT, (WPARAM)_font._font, TRUE); + _consoleEdit.SendMsg(WM_SETFONT, (WPARAM)_font._font, TRUE); } { diff --git a/CPP/7zip/UI/GUI/GUI.cpp b/CPP/7zip/UI/GUI/GUI.cpp index 134ac021..0f3cde94 100644 --- a/CPP/7zip/UI/GUI/GUI.cpp +++ b/CPP/7zip/UI/GUI/GUI.cpp @@ -2,6 +2,10 @@ #include "StdAfx.h" +#include "../../../Common/MyWindows.h" + +#include <shlwapi.h> + #include "../../../../C/Alloc.h" #include "../../../Common/MyInitGuid.h" diff --git a/CPP/7zip/UI/GUI/StdAfx.h b/CPP/7zip/UI/GUI/StdAfx.h index 9e322f96..64290769 100644 --- a/CPP/7zip/UI/GUI/StdAfx.h +++ b/CPP/7zip/UI/GUI/StdAfx.h @@ -9,9 +9,11 @@ #include "../../../Common/Common.h" +// #include "../../../Common/MyWindows.h" + // #include <commctrl.h> -#include <ShlObj.h> -#include <shlwapi.h> +// #include <ShlObj.h> +// #include <shlwapi.h> // #define printf(x) NO_PRINTF_(x) // #define sprintf(x) NO_SPRINTF_(x) diff --git a/CPP/Common/Defs.h b/CPP/Common/Defs.h index dad3ae8f..1fbd78bd 100644 --- a/CPP/Common/Defs.h +++ b/CPP/Common/Defs.h @@ -3,18 +3,13 @@ #ifndef __COMMON_DEFS_H #define __COMMON_DEFS_H -template <class T> inline T MyMin(T a, T b) - { return a < b ? a : b; } -template <class T> inline T MyMax(T a, T b) - { return a > b ? a : b; } +template <class T> inline T MyMin(T a, T b) { return a < b ? a : b; } +template <class T> inline T MyMax(T a, T b) { return a > b ? a : b; } template <class T> inline int MyCompare(T a, T b) - { return a < b ? -1 : (a == b ? 0 : 1); } + { return a == b ? 0 : (a < b ? -1 : 1); } -inline int BoolToInt(bool value) - { return (value ? 1: 0); } - -inline bool IntToBool(int value) - { return (value != 0); } +inline int BoolToInt(bool v) { return (v ? 1 : 0); } +inline bool IntToBool(int v) { return (v != 0); } #endif diff --git a/CPP/Common/MyBuffer.h b/CPP/Common/MyBuffer.h index 58caa2ff..379e0d2c 100644 --- a/CPP/Common/MyBuffer.h +++ b/CPP/Common/MyBuffer.h @@ -78,8 +78,10 @@ public: if (newSize != 0) { newBuffer = new T[newSize]; - if (_size != 0) - memcpy(newBuffer, _items, MyMin(MyMin(_size, keepSize), newSize) * sizeof(T)); + if (keepSize > _size) + keepSize = _size; + if (keepSize != 0) + memcpy(newBuffer, _items, MyMin(keepSize, newSize) * sizeof(T)); } delete []_items; _items = newBuffer; @@ -109,8 +111,8 @@ template <class T> bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2) { size_t size1 = b1.Size(); - if (size1 == b2.Size()) - return false; + if (size1 != b2.Size()) + return true; if (size1 == 0) return false; return memcmp(b1, b2, size1 * sizeof(T)) != 0; @@ -118,7 +120,7 @@ bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2) typedef CBuffer<char> CCharBuffer; -typedef CBuffer<wchar_t> CWCharBuffer; +// typedef CBuffer<wchar_t> CWCharBuffer; typedef CBuffer<unsigned char> CByteBuffer; @@ -155,11 +157,9 @@ typedef CObjArray<unsigned char> CByteArr; typedef CObjArray<bool> CBoolArr; typedef CObjArray<int> CIntArr; -// #define CRecArray CObjArray template <class T> class CObjArray2 { -// protected: T *_items; unsigned _size; diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp index f35ed71e..a2d4cc4e 100644 --- a/CPP/Common/MyString.cpp +++ b/CPP/Common/MyString.cpp @@ -3,7 +3,6 @@ #include "StdAfx.h" #ifdef _WIN32 -#include <windows.h> #include <wchar.h> #else #include <ctype.h> diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h index a0e88df5..2430230b 100644 --- a/CPP/Common/MyString.h +++ b/CPP/Common/MyString.h @@ -10,6 +10,7 @@ #include <wchar.h> #endif +#include "MyWindows.h" #include "MyTypes.h" #include "MyVector.h" diff --git a/CPP/Common/MyUnknown.h b/CPP/Common/MyUnknown.h index e9e8666b..ff025cb5 100644 --- a/CPP/Common/MyUnknown.h +++ b/CPP/Common/MyUnknown.h @@ -3,11 +3,15 @@ #ifndef __MY_UNKNOWN_H #define __MY_UNKNOWN_H +#include "MyWindows.h" + +/* #ifdef _WIN32 #include <basetyps.h> #include <unknwn.h> #else #include "MyWindows.h" #endif +*/ #endif diff --git a/CPP/Common/MyVector.h b/CPP/Common/MyVector.h index 28b26d68..14f7b11a 100644 --- a/CPP/Common/MyVector.h +++ b/CPP/Common/MyVector.h @@ -3,6 +3,8 @@ #ifndef __COMMON_MY_VECTOR_H #define __COMMON_MY_VECTOR_H +#include <string.h> + template <class T> class CRecordVector { diff --git a/CPP/Common/NewHandler.h b/CPP/Common/NewHandler.h index e3e7422c..dcad5688 100644 --- a/CPP/Common/NewHandler.h +++ b/CPP/Common/NewHandler.h @@ -21,6 +21,7 @@ problem for your code. Also we declare delete(void *p) throw() that creates smaller code. */ +#include <stddef.h> class CNewException {}; diff --git a/CPP/Common/Random.cpp b/CPP/Common/Random.cpp index 4bd3fcf9..fbdb8c97 100644 --- a/CPP/Common/Random.cpp +++ b/CPP/Common/Random.cpp @@ -6,6 +6,8 @@ #ifndef _WIN32 #include <time.h> +#else +#include "MyWindows.h" #endif #include "Random.h" diff --git a/CPP/Windows/CommonDialog.cpp b/CPP/Windows/CommonDialog.cpp index 52ad77bc..8f4f56d3 100644 --- a/CPP/Windows/CommonDialog.cpp +++ b/CPP/Windows/CommonDialog.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../Common/MyWindows.h" + #ifdef UNDER_CE #include <commdlg.h> #endif diff --git a/CPP/Windows/Control/ComboBox.cpp b/CPP/Windows/Control/ComboBox.cpp index 3c08309b..c6d5a8d6 100644 --- a/CPP/Windows/Control/ComboBox.cpp +++ b/CPP/Windows/Control/ComboBox.cpp @@ -34,7 +34,7 @@ LRESULT CComboBox::GetLBText(int index, CSysString &s) LRESULT CComboBox::AddString(LPCWSTR s) { if (g_IsNT) - return SendMessageW(CB_ADDSTRING, 0, (LPARAM)s); + return SendMsgW(CB_ADDSTRING, 0, (LPARAM)s); return AddString(GetSystemString(s)); } @@ -43,10 +43,10 @@ LRESULT CComboBox::GetLBText(int index, UString &s) s.Empty(); if (g_IsNT) { - LRESULT len = SendMessageW(CB_GETLBTEXTLEN, index, 0); + LRESULT len = SendMsgW(CB_GETLBTEXTLEN, index, 0); if (len == CB_ERR) return len; - LRESULT len2 = SendMessageW(CB_GETLBTEXT, index, (LPARAM)s.GetBuf((unsigned)len)); + LRESULT len2 = SendMsgW(CB_GETLBTEXT, index, (LPARAM)s.GetBuf((unsigned)len)); if (len2 == CB_ERR) return len; if (len > len2) diff --git a/CPP/Windows/Control/ComboBox.h b/CPP/Windows/Control/ComboBox.h index 8c6fd381..1d5a4821 100644 --- a/CPP/Windows/Control/ComboBox.h +++ b/CPP/Windows/Control/ComboBox.h @@ -3,6 +3,8 @@ #ifndef __WINDOWS_CONTROL_COMBOBOX_H #define __WINDOWS_CONTROL_COMBOBOX_H +#include "../../Common/MyWindows.h" + #include <commctrl.h> #include "../Window.h" @@ -13,28 +15,28 @@ namespace NControl { class CComboBox: public CWindow { public: - void ResetContent() { SendMessage(CB_RESETCONTENT, 0, 0); } - LRESULT AddString(LPCTSTR s) { return SendMessage(CB_ADDSTRING, 0, (LPARAM)s); } + void ResetContent() { SendMsg(CB_RESETCONTENT, 0, 0); } + LRESULT AddString(LPCTSTR s) { return SendMsg(CB_ADDSTRING, 0, (LPARAM)s); } #ifndef _UNICODE LRESULT AddString(LPCWSTR s); #endif - LRESULT SetCurSel(int index) { return SendMessage(CB_SETCURSEL, index, 0); } - int GetCurSel() { return (int)SendMessage(CB_GETCURSEL, 0, 0); } - int GetCount() { return (int)SendMessage(CB_GETCOUNT, 0, 0); } + LRESULT SetCurSel(int index) { return SendMsg(CB_SETCURSEL, index, 0); } + int GetCurSel() { return (int)SendMsg(CB_GETCURSEL, 0, 0); } + int GetCount() { return (int)SendMsg(CB_GETCOUNT, 0, 0); } - LRESULT GetLBTextLen(int index) { return SendMessage(CB_GETLBTEXTLEN, index, 0); } - LRESULT GetLBText(int index, LPTSTR s) { return SendMessage(CB_GETLBTEXT, index, (LPARAM)s); } + LRESULT GetLBTextLen(int index) { return SendMsg(CB_GETLBTEXTLEN, index, 0); } + LRESULT GetLBText(int index, LPTSTR s) { return SendMsg(CB_GETLBTEXT, index, (LPARAM)s); } LRESULT GetLBText(int index, CSysString &s); #ifndef _UNICODE LRESULT GetLBText(int index, UString &s); #endif - LRESULT SetItemData(int index, LPARAM lParam) { return SendMessage(CB_SETITEMDATA, index, lParam); } - LRESULT GetItemData(int index) { return SendMessage(CB_GETITEMDATA, index, 0); } + LRESULT SetItemData(int index, LPARAM lParam) { return SendMsg(CB_SETITEMDATA, index, lParam); } + LRESULT GetItemData(int index) { return SendMsg(CB_GETITEMDATA, index, 0); } LRESULT GetItemData_of_CurSel() { return GetItemData(GetCurSel()); } - void ShowDropDown(bool show = true) { SendMessage(CB_SHOWDROPDOWN, show ? TRUE : FALSE, 0); } + void ShowDropDown(bool show = true) { SendMsg(CB_SHOWDROPDOWN, show ? TRUE : FALSE, 0); } }; #ifndef UNDER_CE @@ -42,18 +44,18 @@ public: class CComboBoxEx: public CComboBox { public: - bool SetUnicodeFormat(bool fUnicode) { return LRESULTToBool(SendMessage(CBEM_SETUNICODEFORMAT, BOOLToBool(fUnicode), 0)); } + bool SetUnicodeFormat(bool fUnicode) { return LRESULTToBool(SendMsg(CBEM_SETUNICODEFORMAT, BOOLToBool(fUnicode), 0)); } - LRESULT DeleteItem(int index) { return SendMessage(CBEM_DELETEITEM, index, 0); } - LRESULT InsertItem(COMBOBOXEXITEM *item) { return SendMessage(CBEM_INSERTITEM, 0, (LPARAM)item); } + LRESULT DeleteItem(int index) { return SendMsg(CBEM_DELETEITEM, index, 0); } + LRESULT InsertItem(COMBOBOXEXITEM *item) { return SendMsg(CBEM_INSERTITEM, 0, (LPARAM)item); } #ifndef _UNICODE - LRESULT InsertItem(COMBOBOXEXITEMW *item) { return SendMessage(CBEM_INSERTITEMW, 0, (LPARAM)item); } + LRESULT InsertItem(COMBOBOXEXITEMW *item) { return SendMsg(CBEM_INSERTITEMW, 0, (LPARAM)item); } #endif - LRESULT SetItem(COMBOBOXEXITEM *item) { return SendMessage(CBEM_SETITEM, 0, (LPARAM)item); } - DWORD SetExtendedStyle(DWORD exMask, DWORD exStyle) { return (DWORD)SendMessage(CBEM_SETEXTENDEDSTYLE, exMask, exStyle); } - HWND GetEditControl() { return (HWND)SendMessage(CBEM_GETEDITCONTROL, 0, 0); } - HIMAGELIST SetImageList(HIMAGELIST imageList) { return (HIMAGELIST)SendMessage(CBEM_SETIMAGELIST, 0, (LPARAM)imageList); } + LRESULT SetItem(COMBOBOXEXITEM *item) { return SendMsg(CBEM_SETITEM, 0, (LPARAM)item); } + DWORD SetExtendedStyle(DWORD exMask, DWORD exStyle) { return (DWORD)SendMsg(CBEM_SETEXTENDEDSTYLE, exMask, exStyle); } + HWND GetEditControl() { return (HWND)SendMsg(CBEM_GETEDITCONTROL, 0, 0); } + HIMAGELIST SetImageList(HIMAGELIST imageList) { return (HIMAGELIST)SendMsg(CBEM_SETIMAGELIST, 0, (LPARAM)imageList); } }; #endif diff --git a/CPP/Windows/Control/CommandBar.h b/CPP/Windows/Control/CommandBar.h index 780211ec..a6197447 100644 --- a/CPP/Windows/Control/CommandBar.h +++ b/CPP/Windows/Control/CommandBar.h @@ -5,6 +5,10 @@ #ifdef UNDER_CE +#include "../../Common/MyWindows.h" + +#include <commctrl.h> + #include "../Window.h" namespace NWindows { @@ -21,10 +25,10 @@ public: // Macros // void Destroy() { CommandBar_Destroy(_window); } - // bool AddButtons(UINT numButtons, LPTBBUTTON buttons) { return BOOLToBool(SendMessage(TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)buttons)); } - bool InsertButton(int iButton, LPTBBUTTON button) { return BOOLToBool(SendMessage(TB_INSERTBUTTON, (WPARAM)iButton, (LPARAM)button)); } - BOOL AddToolTips(UINT numToolTips, LPTSTR toolTips) { return BOOLToBool(SendMessage(TB_SETTOOLTIPS, (WPARAM)numToolTips, (LPARAM)toolTips)); } - void AutoSize() { SendMessage(TB_AUTOSIZE, 0, 0); } + // bool AddButtons(UINT numButtons, LPTBBUTTON buttons) { return BOOLToBool(SendMsg(TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)buttons)); } + bool InsertButton(int iButton, LPTBBUTTON button) { return BOOLToBool(SendMsg(TB_INSERTBUTTON, (WPARAM)iButton, (LPARAM)button)); } + BOOL AddToolTips(UINT numToolTips, LPTSTR toolTips) { return BOOLToBool(SendMsg(TB_SETTOOLTIPS, (WPARAM)numToolTips, (LPARAM)toolTips)); } + void AutoSize() { SendMsg(TB_AUTOSIZE, 0, 0); } bool AddAdornments(DWORD dwFlags) { return BOOLToBool(::CommandBar_AddAdornments(_window, dwFlags, 0)); } int AddBitmap(HINSTANCE hInst, int idBitmap, int iNumImages, int iImageWidth, int iImageHeight) { return ::CommandBar_AddBitmap(_window, hInst, idBitmap, iNumImages, iImageWidth, iImageHeight); } diff --git a/CPP/Windows/Control/Edit.h b/CPP/Windows/Control/Edit.h index 17ac9f13..51a22c53 100644 --- a/CPP/Windows/Control/Edit.h +++ b/CPP/Windows/Control/Edit.h @@ -11,7 +11,7 @@ namespace NControl { class CEdit: public CWindow { public: - void SetPasswordChar(WPARAM c) { SendMessage(EM_SETPASSWORDCHAR, c); } + void SetPasswordChar(WPARAM c) { SendMsg(EM_SETPASSWORDCHAR, c); } }; }} diff --git a/CPP/Windows/Control/ListView.h b/CPP/Windows/Control/ListView.h index ceb297f8..eeae041c 100644 --- a/CPP/Windows/Control/ListView.h +++ b/CPP/Windows/Control/ListView.h @@ -3,10 +3,12 @@ #ifndef __WINDOWS_CONTROL_LISTVIEW_H #define __WINDOWS_CONTROL_LISTVIEW_H -#include "../Window.h" +#include "../../Common/MyWindows.h" #include <commctrl.h> +#include "../Window.h" + namespace NWindows { namespace NControl { @@ -37,11 +39,11 @@ public: #ifndef _UNICODE - int InsertColumn(int columnIndex, const LVCOLUMNW *columnInfo) { return (int)SendMessage(LVM_INSERTCOLUMNW, (WPARAM)columnIndex, (LPARAM)columnInfo); } + int InsertColumn(int columnIndex, const LVCOLUMNW *columnInfo) { return (int)SendMsg(LVM_INSERTCOLUMNW, (WPARAM)columnIndex, (LPARAM)columnInfo); } int InsertColumn(int columnIndex, LPCWSTR text, int width); - int InsertItem(const LV_ITEMW* item) { return (int)SendMessage(LVM_INSERTITEMW, 0, (LPARAM)item); } + int InsertItem(const LV_ITEMW* item) { return (int)SendMsg(LVM_INSERTITEMW, 0, (LPARAM)item); } int InsertItem(int index, LPCWSTR text); - bool SetItem(const LV_ITEMW* item) { return BOOLToBool((BOOL)SendMessage(LVM_SETITEMW, 0, (LPARAM)item)); } + bool SetItem(const LV_ITEMW* item) { return BOOLToBool((BOOL)SendMsg(LVM_SETITEMW, 0, (LPARAM)item)); } int SetSubItem(int index, int subIndex, LPCWSTR text); #endif diff --git a/CPP/Windows/Control/ProgressBar.h b/CPP/Windows/Control/ProgressBar.h index 4591880a..38ebcb61 100644 --- a/CPP/Windows/Control/ProgressBar.h +++ b/CPP/Windows/Control/ProgressBar.h @@ -3,6 +3,10 @@ #ifndef __WINDOWS_CONTROL_PROGRESSBAR_H #define __WINDOWS_CONTROL_PROGRESSBAR_H +#include "../../Common/MyWindows.h" + +#include <commctrl.h> + #include "../Window.h" namespace NWindows { @@ -11,18 +15,18 @@ namespace NControl { class CProgressBar: public CWindow { public: - LRESULT SetPos(int pos) { return SendMessage(PBM_SETPOS, pos, 0); } - LRESULT DeltaPos(int increment) { return SendMessage(PBM_DELTAPOS, increment, 0); } - UINT GetPos() { return (UINT)SendMessage(PBM_GETPOS, 0, 0); } - LRESULT SetRange(unsigned short minValue, unsigned short maxValue) { return SendMessage(PBM_SETRANGE, 0, MAKELPARAM(minValue, maxValue)); } - DWORD SetRange32(int minValue, int maxValue) { return (DWORD)SendMessage(PBM_SETRANGE32, minValue, maxValue); } - int SetStep(int step) { return (int)SendMessage(PBM_SETSTEP, step, 0); } - LRESULT StepIt() { return SendMessage(PBM_STEPIT, 0, 0); } - INT GetRange(bool minValue, PPBRANGE range) { return (INT)SendMessage(PBM_GETRANGE, BoolToBOOL(minValue), (LPARAM)range); } + LRESULT SetPos(int pos) { return SendMsg(PBM_SETPOS, pos, 0); } + LRESULT DeltaPos(int increment) { return SendMsg(PBM_DELTAPOS, increment, 0); } + UINT GetPos() { return (UINT)SendMsg(PBM_GETPOS, 0, 0); } + LRESULT SetRange(unsigned short minValue, unsigned short maxValue) { return SendMsg(PBM_SETRANGE, 0, MAKELPARAM(minValue, maxValue)); } + DWORD SetRange32(int minValue, int maxValue) { return (DWORD)SendMsg(PBM_SETRANGE32, minValue, maxValue); } + int SetStep(int step) { return (int)SendMsg(PBM_SETSTEP, step, 0); } + LRESULT StepIt() { return SendMsg(PBM_STEPIT, 0, 0); } + INT GetRange(bool minValue, PPBRANGE range) { return (INT)SendMsg(PBM_GETRANGE, BoolToBOOL(minValue), (LPARAM)range); } #ifndef UNDER_CE - COLORREF SetBarColor(COLORREF color) { return (COLORREF)SendMessage(PBM_SETBARCOLOR, 0, color); } - COLORREF SetBackgroundColor(COLORREF color) { return (COLORREF)SendMessage(PBM_SETBKCOLOR, 0, color); } + COLORREF SetBarColor(COLORREF color) { return (COLORREF)SendMsg(PBM_SETBARCOLOR, 0, color); } + COLORREF SetBackgroundColor(COLORREF color) { return (COLORREF)SendMsg(PBM_SETBKCOLOR, 0, color); } #endif }; diff --git a/CPP/Windows/Control/PropertyPage.h b/CPP/Windows/Control/PropertyPage.h index 7df8645e..4c4ddad9 100644 --- a/CPP/Windows/Control/PropertyPage.h +++ b/CPP/Windows/Control/PropertyPage.h @@ -3,6 +3,8 @@ #ifndef __WINDOWS_CONTROL_PROPERTYPAGE_H #define __WINDOWS_CONTROL_PROPERTYPAGE_H +#include "../../Common/MyWindows.h" + #include <prsht.h> #include "Dialog.h" diff --git a/CPP/Windows/Control/ReBar.h b/CPP/Windows/Control/ReBar.h index bd475b10..c2d58dbe 100644 --- a/CPP/Windows/Control/ReBar.h +++ b/CPP/Windows/Control/ReBar.h @@ -12,21 +12,21 @@ class CReBar: public NWindows::CWindow { public: bool SetBarInfo(LPREBARINFO barInfo) - { return LRESULTToBool(SendMessage(RB_SETBARINFO, 0, (LPARAM)barInfo)); } + { return LRESULTToBool(SendMsg(RB_SETBARINFO, 0, (LPARAM)barInfo)); } bool InsertBand(int index, LPREBARBANDINFO bandInfo) - { return LRESULTToBool(SendMessage(RB_INSERTBAND, index, (LPARAM)bandInfo)); } + { return LRESULTToBool(SendMsg(RB_INSERTBAND, index, (LPARAM)bandInfo)); } bool SetBandInfo(unsigned index, LPREBARBANDINFO bandInfo) - { return LRESULTToBool(SendMessage(RB_SETBANDINFO, index, (LPARAM)bandInfo)); } + { return LRESULTToBool(SendMsg(RB_SETBANDINFO, index, (LPARAM)bandInfo)); } void MaximizeBand(unsigned index, bool ideal) - { SendMessage(RB_MAXIMIZEBAND, index, BoolToBOOL(ideal)); } + { SendMsg(RB_MAXIMIZEBAND, index, BoolToBOOL(ideal)); } bool SizeToRect(LPRECT rect) - { return LRESULTToBool(SendMessage(RB_SIZETORECT, 0, (LPARAM)rect)); } + { return LRESULTToBool(SendMsg(RB_SIZETORECT, 0, (LPARAM)rect)); } UINT GetHeight() - { return (UINT)SendMessage(RB_GETBARHEIGHT); } + { return (UINT)SendMsg(RB_GETBARHEIGHT); } UINT GetBandCount() - { return (UINT)SendMessage(RB_GETBANDCOUNT); } + { return (UINT)SendMsg(RB_GETBANDCOUNT); } bool DeleteBand(UINT index) - { return LRESULTToBool(SendMessage(RB_DELETEBAND, index)); } + { return LRESULTToBool(SendMsg(RB_DELETEBAND, index)); } }; }} diff --git a/CPP/Windows/Control/Static.h b/CPP/Windows/Control/Static.h index cb3126dd..5523b2e6 100644 --- a/CPP/Windows/Control/Static.h +++ b/CPP/Windows/Control/Static.h @@ -11,15 +11,15 @@ namespace NControl { class CStatic: public CWindow { public: - HANDLE SetImage(WPARAM imageType, HANDLE handle) { return (HANDLE)SendMessage(STM_SETIMAGE, imageType, (LPARAM)handle); } - HANDLE GetImage(WPARAM imageType) { return (HANDLE)SendMessage(STM_GETIMAGE, imageType, 0); } + HANDLE SetImage(WPARAM imageType, HANDLE handle) { return (HANDLE)SendMsg(STM_SETIMAGE, imageType, (LPARAM)handle); } + HANDLE GetImage(WPARAM imageType) { return (HANDLE)SendMsg(STM_GETIMAGE, imageType, 0); } #ifdef UNDER_CE HICON SetIcon(HICON icon) { return (HICON)SetImage(IMAGE_ICON, icon); } HICON GetIcon() { return (HICON)GetImage(IMAGE_ICON); } #else - HICON SetIcon(HICON icon) { return (HICON)SendMessage(STM_SETICON, (WPARAM)icon, 0); } - HICON GetIcon() { return (HICON)SendMessage(STM_GETICON, 0, 0); } + HICON SetIcon(HICON icon) { return (HICON)SendMsg(STM_SETICON, (WPARAM)icon, 0); } + HICON GetIcon() { return (HICON)SendMsg(STM_GETICON, 0, 0); } #endif }; diff --git a/CPP/Windows/Control/StatusBar.h b/CPP/Windows/Control/StatusBar.h index f3e0d3ef..988b8470 100644 --- a/CPP/Windows/Control/StatusBar.h +++ b/CPP/Windows/Control/StatusBar.h @@ -16,7 +16,7 @@ public: bool SetText(LPCTSTR text) { return CWindow::SetText(text); } bool SetText(unsigned index, LPCTSTR text, UINT type) - { return LRESULTToBool(SendMessage(SB_SETTEXT, index | type, (LPARAM)text)); } + { return LRESULTToBool(SendMsg(SB_SETTEXT, index | type, (LPARAM)text)); } bool SetText(unsigned index, LPCTSTR text) { return SetText(index, text, 0); } @@ -26,15 +26,15 @@ public: bool SetText(LPCWSTR text) { return CWindow::SetText(text); } bool SetText(unsigned index, LPCWSTR text, UINT type) - { return LRESULTToBool(SendMessage(SB_SETTEXTW, index | type, (LPARAM)text)); } + { return LRESULTToBool(SendMsg(SB_SETTEXTW, index | type, (LPARAM)text)); } bool SetText(unsigned index, LPCWSTR text) { return SetText(index, text, 0); } #endif bool SetParts(unsigned numParts, const int *edgePostions) - { return LRESULTToBool(SendMessage(SB_SETPARTS, numParts, (LPARAM)edgePostions)); } + { return LRESULTToBool(SendMsg(SB_SETPARTS, numParts, (LPARAM)edgePostions)); } void Simple(bool simple) - { SendMessage(SB_SIMPLE, BoolToBOOL(simple), 0); } + { SendMsg(SB_SIMPLE, BoolToBOOL(simple), 0); } }; }} diff --git a/CPP/Windows/Control/ToolBar.h b/CPP/Windows/Control/ToolBar.h index d579ab7d..7bc93a24 100644 --- a/CPP/Windows/Control/ToolBar.h +++ b/CPP/Windows/Control/ToolBar.h @@ -11,8 +11,8 @@ namespace NControl { class CToolBar: public NWindows::CWindow { public: - void AutoSize() { SendMessage(TB_AUTOSIZE, 0, 0); } - DWORD GetButtonSize() { return (DWORD)SendMessage(TB_GETBUTTONSIZE, 0, 0); } + void AutoSize() { SendMsg(TB_AUTOSIZE, 0, 0); } + DWORD GetButtonSize() { return (DWORD)SendMsg(TB_GETBUTTONSIZE, 0, 0); } bool GetMaxSize(LPSIZE size) #ifdef UNDER_CE @@ -25,16 +25,16 @@ public: } #else { - return LRESULTToBool(SendMessage(TB_GETMAXSIZE, 0, (LPARAM)size)); + return LRESULTToBool(SendMsg(TB_GETMAXSIZE, 0, (LPARAM)size)); } #endif - bool EnableButton(UINT buttonID, bool enable) { return LRESULTToBool(SendMessage(TB_ENABLEBUTTON, buttonID, MAKELONG(BoolToBOOL(enable), 0))); } - void ButtonStructSize() { SendMessage(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON)); } - HIMAGELIST SetImageList(UINT listIndex, HIMAGELIST imageList) { return HIMAGELIST(SendMessage(TB_SETIMAGELIST, listIndex, (LPARAM)imageList)); } - bool AddButton(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMessage(TB_ADDBUTTONS, numButtons, (LPARAM)buttons)); } + bool EnableButton(UINT buttonID, bool enable) { return LRESULTToBool(SendMsg(TB_ENABLEBUTTON, buttonID, MAKELONG(BoolToBOOL(enable), 0))); } + void ButtonStructSize() { SendMsg(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON)); } + HIMAGELIST SetImageList(UINT listIndex, HIMAGELIST imageList) { return HIMAGELIST(SendMsg(TB_SETIMAGELIST, listIndex, (LPARAM)imageList)); } + bool AddButton(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMsg(TB_ADDBUTTONS, numButtons, (LPARAM)buttons)); } #ifndef _UNICODE - bool AddButtonW(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMessage(TB_ADDBUTTONSW, numButtons, (LPARAM)buttons)); } + bool AddButtonW(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMsg(TB_ADDBUTTONSW, numButtons, (LPARAM)buttons)); } #endif }; diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp index fdf77831..94486977 100644 --- a/CPP/Windows/FileFind.cpp +++ b/CPP/Windows/FileFind.cpp @@ -130,9 +130,11 @@ WinXP-64 FindFirstFile(): \\Server\ - ERROR_INVALID_NAME \\Server\Share - ERROR_BAD_NETPATH + \\Server\Share - ERROR_BAD_NET_NAME (Win7) \\Server\Share\ - ERROR_FILE_NOT_FOUND \\?\UNC\Server\Share - ERROR_INVALID_NAME + \\?\UNC\Server\Share - ERROR_BAD_PATHNAME (Win7) \\?\UNC\Server\Share\ - ERROR_FILE_NOT_FOUND \\Server\Share_RootDrive - ERROR_INVALID_NAME @@ -512,9 +514,11 @@ bool CFileInfo::Find(CFSTR path) #if defined(_WIN32) && !defined(UNDER_CE) { DWORD lastError = GetLastError(); - if (lastError == ERROR_BAD_NETPATH || - lastError == ERROR_FILE_NOT_FOUND || - lastError == ERROR_INVALID_NAME // for "\\SERVER\shared" paths that are translated to "\\?\UNC\SERVER\shared" + if (lastError == ERROR_FILE_NOT_FOUND + || lastError == ERROR_BAD_NETPATH // XP64: "\\Server\Share" + || lastError == ERROR_BAD_NET_NAME // Win7: "\\Server\Share" + || lastError == ERROR_INVALID_NAME // XP64: "\\?\UNC\Server\Share" + || lastError == ERROR_BAD_PATHNAME // Win7: "\\?\UNC\Server\Share" ) { unsigned rootSize = 0; diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h index 4c8e694c..32c285fb 100644 --- a/CPP/Windows/FileIO.h +++ b/CPP/Windows/FileIO.h @@ -3,6 +3,8 @@ #ifndef __WINDOWS_FILE_IO_H #define __WINDOWS_FILE_IO_H +#include "../Common/MyWindows.h" + #if defined(_WIN32) && !defined(UNDER_CE) #include <winioctl.h> #endif diff --git a/CPP/Windows/MemoryGlobal.h b/CPP/Windows/MemoryGlobal.h index 94e5f508..c217510e 100644 --- a/CPP/Windows/MemoryGlobal.h +++ b/CPP/Windows/MemoryGlobal.h @@ -3,6 +3,8 @@ #ifndef __WINDOWS_MEMORY_GLOBAL_H #define __WINDOWS_MEMORY_GLOBAL_H +#include "../Common/MyWindows.h" + namespace NWindows { namespace NMemory { diff --git a/CPP/Windows/MemoryLock.cpp b/CPP/Windows/MemoryLock.cpp index 674af007..b628a03e 100644 --- a/CPP/Windows/MemoryLock.cpp +++ b/CPP/Windows/MemoryLock.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "MemoryLock.h" + namespace NWindows { namespace NSecurity { diff --git a/CPP/Windows/MemoryLock.h b/CPP/Windows/MemoryLock.h index f08e5179..4a5dafcf 100644 --- a/CPP/Windows/MemoryLock.h +++ b/CPP/Windows/MemoryLock.h @@ -3,12 +3,14 @@ #ifndef __WINDOWS_MEMORY_LOCK_H #define __WINDOWS_MEMORY_LOCK_H +#include "../Common/MyWindows.h" + namespace NWindows { namespace NSecurity { #ifndef UNDER_CE - bool EnablePrivilege(LPCTSTR privilegeName, bool enable = true); +bool EnablePrivilege(LPCTSTR privilegeName, bool enable = true); inline bool EnablePrivilege_LockMemory(bool enable = true) { diff --git a/CPP/Windows/NtCheck.h b/CPP/Windows/NtCheck.h index e56318f0..a1b89ef2 100644 --- a/CPP/Windows/NtCheck.h +++ b/CPP/Windows/NtCheck.h @@ -5,6 +5,8 @@ #ifdef _WIN32 +#include "../Common/MyWindows.h" + #if !defined(_WIN64) && !defined(UNDER_CE) static inline bool IsItWindowsNT() { diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp index 4bc8d2a3..67551b6d 100644 --- a/CPP/Windows/System.cpp +++ b/CPP/Windows/System.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../Common/MyWindows.h" + #include "../Common/Defs.h" #include "System.h" diff --git a/CPP/Windows/TimeUtils.h b/CPP/Windows/TimeUtils.h index 2967214e..d3033ede 100644 --- a/CPP/Windows/TimeUtils.h +++ b/CPP/Windows/TimeUtils.h @@ -4,6 +4,7 @@ #define __WINDOWS_TIME_UTILS_H #include "../Common/MyTypes.h" +#include "../Common/MyWindows.h" namespace NWindows { namespace NTime { diff --git a/CPP/Windows/Window.h b/CPP/Windows/Window.h index 1b12d991..3bda6795 100644 --- a/CPP/Windows/Window.h +++ b/CPP/Windows/Window.h @@ -3,6 +3,7 @@ #ifndef __WINDOWS_WINDOW_H #define __WINDOWS_WINDOW_H +#include "../Common/MyWindows.h" #include "../Common/MyString.h" #include "Defs.h" @@ -170,7 +171,7 @@ public: bool Update() { return BOOLToBool(::UpdateWindow(_window)); } bool InvalidateRect(LPCRECT rect, bool backgroundErase = true) { return BOOLToBool(::InvalidateRect(_window, rect, BoolToBOOL(backgroundErase))); } - void SetRedraw(bool redraw = true) { SendMessage(WM_SETREDRAW, BoolToBOOL(redraw), 0); } + void SetRedraw(bool redraw = true) { SendMsg(WM_SETREDRAW, BoolToBOOL(redraw), 0); } LONG_PTR SetStyle(LONG_PTR style) { return SetLongPtr(GWL_STYLE, style); } LONG_PTR GetStyle() const { return GetLongPtr(GWL_STYLE); } @@ -222,18 +223,18 @@ public: HWND SetFocus() { return ::SetFocus(_window); } - LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) - { return ::SendMessage(_window, message, wParam, lParam) ;} + LRESULT SendMsg(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { return ::SendMessage(_window, message, wParam, lParam); } #ifndef _UNICODE - LRESULT SendMessageW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) - { return ::SendMessageW(_window, message, wParam, lParam) ;} + LRESULT SendMsgW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { return ::SendMessageW(_window, message, wParam, lParam); } #endif - bool PostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) - { return BOOLToBool(::PostMessage(_window, message, wParam, lParam)) ;} + bool PostMsg(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { return BOOLToBool(::PostMessage(_window, message, wParam, lParam)); } #ifndef _UNICODE - LRESULT PostMessageW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) - { return ::PostMessageW(_window, message, wParam, lParam) ;} + bool PostMsgW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { return BOOLToBool(::PostMessageW(_window, message, wParam, lParam)); } #endif bool SetText(LPCTSTR s) { return BOOLToBool(::SetWindowText(_window, s)); } @@ -270,7 +271,7 @@ public: bool KillTimer(UINT_PTR idEvent) {return BOOLToBool(::KillTimer(_window, idEvent)); } - HICON SetIcon(WPARAM sizeType, HICON icon) { return (HICON)SendMessage(WM_SETICON, sizeType, (LPARAM)icon); } + HICON SetIcon(WPARAM sizeType, HICON icon) { return (HICON)SendMsg(WM_SETICON, sizeType, (LPARAM)icon); } }; #define RECT_SIZE_X(r) ((r).right - (r).left) |