diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2015-06-15 03:00:00 +0300 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:16:54 +0300 |
commit | 54490d51d5c6b0d794dcbad2d634d4c95fc25b6c (patch) | |
tree | c3c413656432c0ef87b2841c80e42b55ad17d4e8 /CPP/7zip | |
parent | 0713a3ab803e57401f18432148b4139e5fe6e5dd (diff) |
15.0515.05
Diffstat (limited to 'CPP/7zip')
458 files changed, 26014 insertions, 14013 deletions
diff --git a/CPP/7zip/Archive/7z/7z.dsp b/CPP/7zip/Archive/7z/7z.dsp index 53913f77..7fd1ccdc 100644 --- a/CPP/7zip/Archive/7z/7z.dsp +++ b/CPP/7zip/Archive/7z/7z.dsp @@ -350,14 +350,6 @@ SOURCE=..\Common\CoderMixer2.h # End Source File # Begin Source File -SOURCE=..\Common\CoderMixer2MT.cpp -# End Source File -# Begin Source File - -SOURCE=..\Common\CoderMixer2MT.h -# End Source File -# Begin Source File - SOURCE=..\Common\CrossThreadProgress.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h index 5cde97c3..8105ff04 100644 --- a/CPP/7zip/Archive/7z/7zCompressionMode.h +++ b/CPP/7zip/Archive/7z/7zCompressionMode.h @@ -9,37 +9,62 @@ namespace NArchive { namespace N7z { -struct CMethodFull: public CProps +struct CMethodFull: public CMethodProps { CMethodId Id; - UInt32 NumInStreams; - UInt32 NumOutStreams; + UInt32 NumStreams; - bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } + bool IsSimpleCoder() const { return NumStreams == 1; } }; -struct CBind +struct CBond2 { - UInt32 InCoder; - UInt32 InStream; UInt32 OutCoder; UInt32 OutStream; + UInt32 InCoder; }; struct CCompressionMethodMode { + /* + if (Bonds.Empty()), then default bonds must be created + if (Filter_was_Inserted) + { + Methods[0] is filter method + Bonds don't contain bonds for filter (these bonds must be created) + } + */ + CObjectVector<CMethodFull> Methods; - CRecordVector<CBind> Binds; + CRecordVector<CBond2> Bonds; + + bool IsThereBond_to_Coder(unsigned coderIndex) const + { + FOR_VECTOR(i, Bonds) + if (Bonds[i].InCoder == coderIndex) + return true; + return false; + } + + bool DefaultMethod_was_Inserted; + bool Filter_was_Inserted; + #ifndef _7ZIP_ST UInt32 NumThreads; + bool MultiThreadMixer; #endif + bool PasswordIsDefined; UString Password; bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } - CCompressionMethodMode(): PasswordIsDefined(false) + CCompressionMethodMode(): + DefaultMethod_was_Inserted(false), + Filter_was_Inserted(false), + PasswordIsDefined(false) #ifndef _7ZIP_ST , NumThreads(1) + , MultiThreadMixer(true) #endif {} }; diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp index 7f0e45d1..d1a810cb 100644 --- a/CPP/7zip/Archive/7z/7zDecode.cpp +++ b/CPP/7zip/Archive/7z/7zDecode.cpp @@ -3,7 +3,6 @@ #include "StdAfx.h" #include "../../Common/LimitedStreams.h" -#include "../../Common/LockedStream.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamObjects.h" @@ -12,50 +11,70 @@ namespace NArchive { namespace N7z { -static void ConvertFolderItemInfoToBindInfo(const CFolder &folder, - CBindInfoEx &bindInfo) +class CDecProgress: + public ICompressProgressInfo, + public CMyUnknownImp { - bindInfo.Clear(); - bindInfo.BindPairs.ClearAndSetSize(folder.BindPairs.Size()); + CMyComPtr<ICompressProgressInfo> _progress; +public: + CDecProgress(ICompressProgressInfo *progress): _progress(progress) {} + + MY_UNKNOWN_IMP1(ICompressProgressInfo) + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + +STDMETHODIMP CDecProgress::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 *outSize) +{ + return _progress->SetRatioInfo(NULL, outSize); +} + +static void Convert_FolderInfo_to_BindInfo(const CFolderEx &folder, CBindInfoEx &bi) +{ + bi.Clear(); + + bi.Bonds.ClearAndSetSize(folder.Bonds.Size()); unsigned i; - for (i = 0; i < folder.BindPairs.Size(); i++) + for (i = 0; i < folder.Bonds.Size(); i++) { - NCoderMixer::CBindPair &bindPair = bindInfo.BindPairs[i]; - bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex; - bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex; + NCoderMixer2::CBond &bond = bi.Bonds[i]; + const N7z::CBond &folderBond = folder.Bonds[i]; + bond.PackIndex = folderBond.PackIndex; + bond.UnpackIndex = folderBond.UnpackIndex; } - bindInfo.Coders.ClearAndSetSize(folder.Coders.Size()); - bindInfo.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size()); - - UInt32 outStreamIndex = 0; + bi.Coders.ClearAndSetSize(folder.Coders.Size()); + bi.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size()); for (i = 0; i < folder.Coders.Size(); i++) { - NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i]; const CCoderInfo &coderInfo = folder.Coders[i]; - coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams; - coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams; - bindInfo.CoderMethodIDs[i] = coderInfo.MethodID; - for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++) - if (folder.FindBindPairForOutStream(outStreamIndex) < 0) - bindInfo.OutStreams.Add(outStreamIndex); + bi.Coders[i].NumStreams = coderInfo.NumStreams; + bi.CoderMethodIDs[i] = coderInfo.MethodID; } - bindInfo.InStreams.ClearAndSetSize(folder.PackStreams.Size()); + + /* + if (!bi.SetUnpackCoder()) + throw 1112; + */ + bi.UnpackCoder = folder.UnpackCoder; + bi.PackStreams.ClearAndSetSize(folder.PackStreams.Size()); for (i = 0; i < folder.PackStreams.Size(); i++) - bindInfo.InStreams[i] = (UInt32)folder.PackStreams[i]; + bi.PackStreams[i] = folder.PackStreams[i]; } -static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1, - const NCoderMixer::CCoderStreamsInfo &a2) +static inline bool AreCodersEqual( + const NCoderMixer2::CCoderStreamsInfo &a1, + const NCoderMixer2::CCoderStreamsInfo &a2) { - return (a1.NumInStreams == a2.NumInStreams) && - (a1.NumOutStreams == a2.NumOutStreams); + return (a1.NumStreams == a2.NumStreams); } -static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2) +static inline bool AreBondsEqual( + const NCoderMixer2::CBond &a1, + const NCoderMixer2::CBond &a2) { - return (a1.InIndex == a2.InIndex) && - (a1.OutIndex == a2.OutIndex); + return + (a1.PackIndex == a2.PackIndex) && + (a1.UnpackIndex == a2.UnpackIndex); } static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2) @@ -66,186 +85,284 @@ static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2) for (i = 0; i < a1.Coders.Size(); i++) if (!AreCodersEqual(a1.Coders[i], a2.Coders[i])) return false; - if (a1.BindPairs.Size() != a2.BindPairs.Size()) + + if (a1.Bonds.Size() != a2.Bonds.Size()) return false; - for (i = 0; i < a1.BindPairs.Size(); i++) - if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i])) + for (i = 0; i < a1.Bonds.Size(); i++) + if (!AreBondsEqual(a1.Bonds[i], a2.Bonds[i])) return false; + for (i = 0; i < a1.CoderMethodIDs.Size(); i++) if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i]) return false; - if (a1.InStreams.Size() != a2.InStreams.Size()) + + if (a1.PackStreams.Size() != a2.PackStreams.Size()) return false; - if (a1.OutStreams.Size() != a2.OutStreams.Size()) + for (i = 0; i < a1.PackStreams.Size(); i++) + if (a1.PackStreams[i] != a2.PackStreams[i]) + return false; + + /* + if (a1.UnpackCoder != a2.UnpackCoder) return false; + */ return true; } -CDecoder::CDecoder(bool multiThread) +CDecoder::CDecoder(bool useMixerMT): + _bindInfoPrev_Defined(false), + _useMixerMT(useMixerMT) +{} + + +struct CLockedInStream: + public IUnknown, + public CMyUnknownImp { - #ifndef _ST_MODE - multiThread = true; + CMyComPtr<IInStream> Stream; + UInt64 Pos; + + MY_UNKNOWN_IMP + + #ifdef USE_MIXER_MT + NWindows::NSynchronization::CCriticalSection CriticalSection; #endif - _multiThread = multiThread; - _bindInfoExPrevIsDefined = false; +}; + + +#ifdef USE_MIXER_MT + +class CLockedSequentialInStreamMT: + public ISequentialInStream, + public CMyUnknownImp +{ + CLockedInStream *_glob; + UInt64 _pos; + CMyComPtr<IUnknown> _globRef; +public: + void Init(CLockedInStream *lockedInStream, UInt64 startPos) + { + _globRef = lockedInStream; + _glob = lockedInStream; + _pos = startPos; + } + + MY_UNKNOWN_IMP1(ISequentialInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + NWindows::NSynchronization::CCriticalSectionLock lock(_glob->CriticalSection); + + if (_pos != _glob->Pos) + { + RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL)); + _glob->Pos = _pos; + } + + UInt32 realProcessedSize = 0; + HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize); + _pos += realProcessedSize; + _glob->Pos = _pos; + if (processedSize) + *processedSize = realProcessedSize; + return res; +} + +#endif + + +#ifdef USE_MIXER_ST + +class CLockedSequentialInStreamST: + public ISequentialInStream, + public CMyUnknownImp +{ + CLockedInStream *_glob; + UInt64 _pos; + CMyComPtr<IUnknown> _globRef; +public: + void Init(CLockedInStream *lockedInStream, UInt64 startPos) + { + _globRef = lockedInStream; + _glob = lockedInStream; + _pos = startPos; + } + + MY_UNKNOWN_IMP1(ISequentialInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (_pos != _glob->Pos) + { + RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL)); + _glob->Pos = _pos; + } + + UInt32 realProcessedSize = 0; + HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize); + _pos += realProcessedSize; + _glob->Pos = _pos; + if (processedSize) + *processedSize = realProcessedSize; + return res; } +#endif + + + HRESULT CDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, - const CFolders &folders, int folderIndex, - ISequentialOutStream *outStream, - ICompressProgressInfo *compressProgress + const CFolders &folders, unsigned folderIndex, + const UInt64 *unpackSize + + , ISequentialOutStream *outStream + , ICompressProgressInfo *compressProgress + , ISequentialInStream ** + + #ifdef USE_MIXER_ST + inStreamMainRes + #endif + _7Z_DECODER_CRYPRO_VARS_DECL + #if !defined(_7ZIP_ST) && !defined(_SFX) , bool mtMode, UInt32 numThreads #endif ) { const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]]; - CFolder folderInfo; - folders.ParseFolderInfo(folderIndex, folderInfo); + CFolderEx folderInfo; + folders.ParseFolderEx(folderIndex, folderInfo); - if (!folderInfo.CheckStructure(folders.GetNumFolderUnpackSizes(folderIndex))) + if (!folderInfo.IsDecodingSupported()) + return E_NOTIMPL; + + CBindInfoEx bindInfo; + Convert_FolderInfo_to_BindInfo(folderInfo, bindInfo); + if (!bindInfo.CalcMapsAndCheck()) return E_NOTIMPL; + UInt64 folderUnpackSize = folders.GetFolderUnpackSize(folderIndex); + bool fullUnpack = true; + if (unpackSize) + { + if (*unpackSize > folderUnpackSize) + return E_FAIL; + fullUnpack = (*unpackSize == folderUnpackSize); + } + /* We don't need to init isEncrypted and passwordIsDefined We must upgrade them only + #ifndef _NO_CRYPTO isEncrypted = false; passwordIsDefined = false; #endif */ - - CObjectVector< CMyComPtr<ISequentialInStream> > inStreams; - CLockedInStream lockedInStream; - lockedInStream.Init(inStream); - - for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++) + if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev)) { - CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp; - CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec; - lockedStreamImpSpec->Init(&lockedInStream, startPos + packPositions[j]); - CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; - CMyComPtr<ISequentialInStream> inStream = streamSpec; - streamSpec->SetStream(lockedStreamImp); - streamSpec->Init(packPositions[j + 1] - packPositions[j]); - inStreams.Add(inStream); - } - - unsigned numCoders = folderInfo.Coders.Size(); - - CBindInfoEx bindInfo; - ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo); - bool createNewCoders; - if (!_bindInfoExPrevIsDefined) - createNewCoders = true; - else - createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev); - if (createNewCoders) - { - unsigned i; - _decoders.Clear(); - // _decoders2.Clear(); - - _mixerCoder.Release(); + _mixerRef.Release(); - if (_multiThread) + #ifdef USE_MIXER_MT + #ifdef USE_MIXER_ST + if (_useMixerMT) + #endif { - _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT; - _mixerCoder = _mixerCoderMTSpec; - _mixerCoderCommon = _mixerCoderMTSpec; + _mixerMT = new NCoderMixer2::CMixerMT(false); + _mixerRef = _mixerMT; + _mixer = _mixerMT; } + #ifdef USE_MIXER_ST else + #endif + #endif { - #ifdef _ST_MODE - _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST; - _mixerCoder = _mixerCoderSTSpec; - _mixerCoderCommon = _mixerCoderSTSpec; + #ifdef USE_MIXER_ST + _mixerST = new NCoderMixer2::CMixerST(false); + _mixerRef = _mixerST; + _mixer = _mixerST; #endif } - RINOK(_mixerCoderCommon->SetBindInfo(bindInfo)); - for (i = 0; i < numCoders; i++) + RINOK(_mixer->SetBindInfo(bindInfo)); + + FOR_VECTOR(i, folderInfo.Coders) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; - - CMyComPtr<ICompressCoder> decoder; - CMyComPtr<ICompressCoder2> decoder2; + CCreatedCoder cod; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS - coderInfo.MethodID, decoder, decoder2, false)); - CMyComPtr<IUnknown> decoderUnknown; + coderInfo.MethodID, false, cod)); + if (coderInfo.IsSimpleCoder()) { - if (decoder == 0) + if (!cod.Coder) return E_NOTIMPL; - - decoderUnknown = (IUnknown *)decoder; - - if (_multiThread) - _mixerCoderMTSpec->AddCoder(decoder); - #ifdef _ST_MODE - else - _mixerCoderSTSpec->AddCoder(decoder, false); - #endif + // CMethodId m = coderInfo.MethodID; + // isFilter = (IsFilterMethod(m) || m == k_AES); } else { - if (decoder2 == 0) + if (!cod.Coder2 || cod.NumStreams != coderInfo.NumStreams) return E_NOTIMPL; - decoderUnknown = (IUnknown *)decoder2; - if (_multiThread) - _mixerCoderMTSpec->AddCoder2(decoder2); - #ifdef _ST_MODE - else - _mixerCoderSTSpec->AddCoder2(decoder2, false); - #endif } - _decoders.Add(decoderUnknown); + _mixer->AddCoder(cod); + + // now there is no codec that uses another external codec + /* #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { + // we must use g_ExternalCodecs also RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs)); } #endif + */ } - _bindInfoExPrev = bindInfo; - _bindInfoExPrevIsDefined = true; + + _bindInfoPrev = bindInfo; + _bindInfoPrev_Defined = true; } - unsigned i; - _mixerCoderCommon->ReInit(); + + _mixer->ReInit(); UInt32 packStreamIndex = 0; UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex]; - UInt32 unpackStreamIndex = unpackStreamIndexStart; - UInt32 coderIndex = 0; - // UInt32 coder2Index = 0; - - for (i = 0; i < numCoders; i++) + + unsigned i; + + for (i = 0; i < folderInfo.Coders.Size(); i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; - CMyComPtr<IUnknown> &decoder = _decoders[coderIndex]; - + IUnknown *decoder = _mixer->GetCoder(i).GetUnknown(); + { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; - decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); + decoder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties); if (setDecoderProperties) { const CByteBuffer &props = coderInfo.Props; size_t size = props.Size(); if (size > 0xFFFFFFFF) return E_NOTIMPL; - // if (size > 0) - { - RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size)); - } + HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size); + if (res == E_INVALIDARG) + res = E_NOTIMPL; + RINOK(res); } } @@ -253,7 +370,7 @@ HRESULT CDecoder::Decode( if (mtMode) { CMyComPtr<ICompressSetCoderMt> setCoderMt; - decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); + decoder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(numThreads)); @@ -264,7 +381,7 @@ HRESULT CDecoder::Decode( #ifndef _NO_CRYPTO { CMyComPtr<ICryptoSetPassword> cryptoSetPassword; - decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); + decoder->QueryInterface(IID_ICryptoSetPassword, (void **)&cryptoSetPassword); if (cryptoSetPassword) { isEncrypted = true; @@ -273,9 +390,13 @@ HRESULT CDecoder::Decode( CMyComBSTR passwordBSTR; RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR)); passwordIsDefined = true; + password.Empty(); size_t len = 0; if (passwordBSTR) - len = MyStringLen((BSTR)passwordBSTR); + { + password = passwordBSTR; + len = password.Len(); + } CByteBuffer buffer(len * 2); for (size_t i = 0; i < len; i++) { @@ -288,56 +409,129 @@ HRESULT CDecoder::Decode( } #endif - coderIndex++; + { + CMyComPtr<ICompressSetFinishMode> setFinishMode; + decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode); + if (setFinishMode) + { + RINOK(setFinishMode->SetFinishMode(BoolToInt(fullUnpack))); + } + } - UInt32 numInStreams = (UInt32)coderInfo.NumInStreams; - UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams; - CObjArray<UInt64> packSizes(numInStreams); - CObjArray<const UInt64 *> packSizesPointers(numInStreams); - CObjArray<const UInt64 *> unpackSizesPointers(numOutStreams); - UInt32 j; - - for (j = 0; j < numOutStreams; j++, unpackStreamIndex++) - unpackSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndex]; + UInt32 numStreams = (UInt32)coderInfo.NumStreams; - for (j = 0; j < numInStreams; j++, packStreamIndex++) + CObjArray<UInt64> packSizes(numStreams); + CObjArray<const UInt64 *> packSizesPointers(numStreams); + + for (UInt32 j = 0; j < numStreams; j++, packStreamIndex++) { - int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex); - if (bindPairIndex >= 0) - packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + (UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]; + int bond = folderInfo.FindBond_for_PackStream(packStreamIndex); + + if (bond >= 0) + packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + folderInfo.Bonds[(unsigned)bond].UnpackIndex]; else { - int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex); + int index = folderInfo.Find_in_PackStreams(packStreamIndex); if (index < 0) - return S_FALSE; // check it - packSizes[j] = packPositions[index + 1] - packPositions[index]; + return E_NOTIMPL; + packSizes[j] = packPositions[(unsigned)index + 1] - packPositions[(unsigned)index]; packSizesPointers[j] = &packSizes[j]; } } + + const UInt64 *unpackSizesPointer = + (unpackSize && i == bindInfo.UnpackCoder) ? + unpackSize : + &folders.CoderUnpackSizes[unpackStreamIndexStart + i]; - _mixerCoderCommon->SetCoderInfo(i, packSizesPointers, unpackSizesPointers); + _mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers); } - UInt32 mainCoder, temp; - bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp); - if (_multiThread) - _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder); - /* - else - _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);; - */ + if (outStream) + { + _mixer->SelectMainCoder(!fullUnpack); + } + + CObjectVector< CMyComPtr<ISequentialInStream> > inStreams; + + CLockedInStream *lockedInStreamSpec = new CLockedInStream; + CMyComPtr<IUnknown> lockedInStream = lockedInStreamSpec; + + bool needMtLock = false; + + if (folderInfo.PackStreams.Size() > 1) + { + // lockedInStream.Pos = (UInt64)(Int64)-1; + // RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &lockedInStream.Pos)); + RINOK(inStream->Seek(startPos + packPositions[0], STREAM_SEEK_SET, &lockedInStreamSpec->Pos)); + lockedInStreamSpec->Stream = inStream; + + #ifdef USE_MIXER_ST + if (_mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex)) + #endif + needMtLock = true; + } + + for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++) + { + CMyComPtr<ISequentialInStream> packStream; + UInt64 packPos = startPos + packPositions[j]; + + if (folderInfo.PackStreams.Size() == 1) + { + RINOK(inStream->Seek(packPos, STREAM_SEEK_SET, NULL)); + packStream = inStream; + } + else + { + #ifdef USE_MIXER_MT + #ifdef USE_MIXER_ST + if (_useMixerMT || needMtLock) + #endif + { + CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT; + packStream = lockedStreamImpSpec; + lockedStreamImpSpec->Init(lockedInStreamSpec, packPos); + } + #ifdef USE_MIXER_ST + else + #endif + #endif + { + #ifdef USE_MIXER_ST + CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST; + packStream = lockedStreamImpSpec; + lockedStreamImpSpec->Init(lockedInStreamSpec, packPos); + #endif + } + } + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + inStreams.AddNew() = streamSpec; + streamSpec->SetStream(packStream); + streamSpec->Init(packPositions[j + 1] - packPositions[j]); + } - if (numCoders == 0) - return 0; unsigned num = inStreams.Size(); CObjArray<ISequentialInStream *> inStreamPointers(num); for (i = 0; i < num; i++) inStreamPointers[i] = inStreams[i]; - ISequentialOutStream *outStreamPointer = outStream; - return _mixerCoder->Code( - inStreamPointers, NULL, num, - &outStreamPointer, NULL, 1, - compressProgress); + + if (outStream) + { + CMyComPtr<ICompressProgressInfo> progress2; + if (compressProgress && !_mixer->Is_PackSize_Correct_for_Coder(_mixer->MainCoderIndex)) + progress2 = new CDecProgress(compressProgress); + + ISequentialOutStream *outStreamPointer = outStream; + return _mixer->Code(inStreamPointers, &outStreamPointer, progress2 ? (ICompressProgressInfo *)progress2 : compressProgress); + } + + #ifdef USE_MIXER_ST + return _mixerST->GetMainUnpackStream(inStreamPointers, inStreamMainRes); + #else + return E_FAIL; + #endif } }} diff --git a/CPP/7zip/Archive/7z/7zDecode.h b/CPP/7zip/Archive/7z/7zDecode.h index 1361772c..5b729f6c 100644 --- a/CPP/7zip/Archive/7z/7zDecode.h +++ b/CPP/7zip/Archive/7z/7zDecode.h @@ -3,25 +3,17 @@ #ifndef __7Z_DECODE_H #define __7Z_DECODE_H -#include "../../IStream.h" -#include "../../IPassword.h" - #include "../Common/CoderMixer2.h" -#include "../Common/CoderMixer2MT.h" -#ifdef _ST_MODE -#include "../Common/CoderMixer2ST.h" -#endif - -#include "../../Common/CreateCoder.h" #include "7zIn.h" namespace NArchive { namespace N7z { -struct CBindInfoEx: public NCoderMixer::CBindInfo +struct CBindInfoEx: public NCoderMixer2::CBindInfo { CRecordVector<CMethodId> CoderMethodIDs; + void Clear() { CBindInfo::Clear(); @@ -31,29 +23,40 @@ struct CBindInfoEx: public NCoderMixer::CBindInfo class CDecoder { - bool _bindInfoExPrevIsDefined; - CBindInfoEx _bindInfoExPrev; + bool _bindInfoPrev_Defined; + CBindInfoEx _bindInfoPrev; + + bool _useMixerMT; - bool _multiThread; - #ifdef _ST_MODE - NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec; + #ifdef USE_MIXER_ST + NCoderMixer2::CMixerST *_mixerST; #endif - NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec; - NCoderMixer::CCoderMixer2 *_mixerCoderCommon; - CMyComPtr<ICompressCoder2> _mixerCoder; - CObjectVector<CMyComPtr<IUnknown> > _decoders; - // CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2; + #ifdef USE_MIXER_MT + NCoderMixer2::CMixerMT *_mixerMT; + #endif + + NCoderMixer2::CMixer *_mixer; + CMyComPtr<IUnknown> _mixerRef; + public: - CDecoder(bool multiThread); + + CDecoder(bool useMixerMT); + HRESULT Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, - const CFolders &folders, int folderIndex, - ISequentialOutStream *outStream, - ICompressProgressInfo *compressProgress + const CFolders &folders, unsigned folderIndex, + const UInt64 *unpackSize // if (!unpackSize), then full folder is required + // if (unpackSize), then only *unpackSize bytes from folder are required + + , ISequentialOutStream *outStream + , ICompressProgressInfo *compressProgress + , ISequentialInStream **inStreamMainRes + _7Z_DECODER_CRYPRO_VARS_DECL + #if !defined(_7ZIP_ST) && !defined(_SFX) , bool mtMode, UInt32 numThreads #endif diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp index 36ff5177..ab251711 100644 --- a/CPP/7zip/Archive/7z/7zEncode.cpp +++ b/CPP/7zip/Archive/7z/7zEncode.cpp @@ -12,43 +12,80 @@ #include "7zEncode.h" #include "7zSpecStream.h" -static const UInt64 k_Delta = 0x03; -static const UInt64 k_BCJ = 0x03030103; -static const UInt64 k_BCJ2 = 0x0303011B; - namespace NArchive { namespace N7z { -static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo, - const CRecordVector<CMethodId> decompressionMethods, - CFolder &folder) +void CEncoder::InitBindConv() +{ + unsigned numIn = _bindInfo.Coders.Size(); + + _SrcIn_to_DestOut.ClearAndSetSize(numIn); + _DestOut_to_SrcIn.ClearAndSetSize(numIn); + + unsigned numOut = _bindInfo.GetNum_Bonds_and_PackStreams(); + _SrcOut_to_DestIn.ClearAndSetSize(numOut); + // _DestIn_to_SrcOut.ClearAndSetSize(numOut); + + UInt32 destIn = 0; + UInt32 destOut = 0; + + for (unsigned i = _bindInfo.Coders.Size(); i != 0;) + { + i--; + + const NCoderMixer2::CCoderStreamsInfo &coder = _bindInfo.Coders[i]; + + numIn--; + numOut -= coder.NumStreams; + + _SrcIn_to_DestOut[numIn] = destOut; + _DestOut_to_SrcIn[destOut] = numIn; + + destOut++; + + for (UInt32 j = 0; j < coder.NumStreams; j++, destIn++) + { + UInt32 index = numOut + j; + _SrcOut_to_DestIn[index] = destIn; + // _DestIn_to_SrcOut[destIn] = index; + } + } +} + +void CEncoder::SetFolder(CFolder &folder) { - // bindInfo.CoderMethodIDs.Clear(); - // folder.OutStreams.Clear(); - folder.BindPairs.SetSize(bindInfo.BindPairs.Size()); + folder.Bonds.SetSize(_bindInfo.Bonds.Size()); + unsigned i; - for (i = 0; i < bindInfo.BindPairs.Size(); i++) + + for (i = 0; i < _bindInfo.Bonds.Size(); i++) { - CBindPair &bp = folder.BindPairs[i]; - const NCoderMixer::CBindPair &mixerBp = bindInfo.BindPairs[i]; - bp.InIndex = mixerBp.InIndex; - bp.OutIndex = mixerBp.OutIndex; + CBond &fb = folder.Bonds[i]; + const NCoderMixer2::CBond &mixerBond = _bindInfo.Bonds[_bindInfo.Bonds.Size() - 1 - i]; + fb.PackIndex = _SrcOut_to_DestIn[mixerBond.PackIndex]; + fb.UnpackIndex = _SrcIn_to_DestOut[mixerBond.UnpackIndex]; } - folder.Coders.SetSize(bindInfo.Coders.Size()); - for (i = 0; i < bindInfo.Coders.Size(); i++) + + folder.Coders.SetSize(_bindInfo.Coders.Size()); + + for (i = 0; i < _bindInfo.Coders.Size(); i++) { CCoderInfo &coderInfo = folder.Coders[i]; - const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i]; - coderInfo.NumInStreams = coderStreamsInfo.NumInStreams; - coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams; - coderInfo.MethodID = decompressionMethods[i]; - // coderInfo.Props can be nonFree; + const NCoderMixer2::CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[_bindInfo.Coders.Size() - 1 - i]; + + coderInfo.NumStreams = coderStreamsInfo.NumStreams; + coderInfo.MethodID = _decompressionMethods[i]; + // we don't free coderInfo.Props here. So coderInfo.Props can be non-empty. } - folder.PackStreams.SetSize(bindInfo.InStreams.Size()); - for (i = 0; i < bindInfo.InStreams.Size(); i++) - folder.PackStreams[i] = bindInfo.InStreams[i]; + + folder.PackStreams.SetSize(_bindInfo.PackStreams.Size()); + + for (i = 0; i < _bindInfo.PackStreams.Size(); i++) + folder.PackStreams[i] = _SrcOut_to_DestIn[_bindInfo.PackStreams[i]]; } + + static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder) { CMyComPtr<ICompressSetCoderProperties> setCoderProperties; @@ -58,30 +95,75 @@ static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK; } + + +void CMtEncMultiProgress::Init(ICompressProgressInfo *progress) +{ + _progress = progress; + OutSize = 0; +} + +STDMETHODIMP CMtEncMultiProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */) +{ + UInt64 outSize2; + { + #ifndef _7ZIP_ST + NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); + #endif + outSize2 = OutSize; + } + + if (_progress) + return _progress->SetRatioInfo(inSize, &outSize2); + + return S_OK; +} + + + HRESULT CEncoder::CreateMixerCoder( DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce) { - _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT; - _mixerCoder = _mixerCoderSpec; - RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo)); + #ifdef USE_MIXER_MT + #ifdef USE_MIXER_ST + if (_options.MultiThreadMixer) + #endif + { + _mixerMT = new NCoderMixer2::CMixerMT(true); + _mixerRef = _mixerMT; + _mixer = _mixerMT; + } + #ifdef USE_MIXER_ST + else + #endif + #endif + { + #ifdef USE_MIXER_ST + _mixerST = new NCoderMixer2::CMixerST(true); + _mixerRef = _mixerST; + _mixer = _mixerST; + #endif + } + + RINOK(_mixer->SetBindInfo(_bindInfo)); + FOR_VECTOR (i, _options.Methods) { const CMethodFull &methodFull = _options.Methods[i]; - CCoderInfo &encodingInfo = _codersInfo.AddNew(); - encodingInfo.MethodID = methodFull.Id; - CMyComPtr<ICompressCoder> encoder; - CMyComPtr<ICompressCoder2> encoder2; - + CCreatedCoder cod; + RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS - methodFull.Id, encoder, encoder2, true)); + methodFull.Id, true, cod)); - if (!encoder && !encoder2) + if (cod.NumStreams != methodFull.NumStreams) + return E_FAIL; + if (!cod.Coder && !cod.Coder2) return E_FAIL; - CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2; + CMyComPtr<IUnknown> encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2; #ifndef _7ZIP_ST { @@ -105,21 +187,25 @@ HRESULT CEncoder::CreateMixerCoder( } */ + // now there is no codec that uses another external codec + /* #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { + // we must use g_ExternalCodecs also RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs)); } #endif + */ CMyComPtr<ICryptoSetPassword> cryptoSetPassword; encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { - const UInt32 sizeInBytes = _options.Password.Len() * 2; + const unsigned sizeInBytes = _options.Password.Len() * 2; CByteBuffer buffer(sizeInBytes); for (unsigned i = 0; i < _options.Password.Len(); i++) { @@ -127,21 +213,79 @@ HRESULT CEncoder::CreateMixerCoder( ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } - RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); + RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)sizeInBytes)); } - if (encoder) - _mixerCoderSpec->AddCoder(encoder); - else - _mixerCoderSpec->AddCoder2(encoder2); + _mixer->AddCoder(cod); } return S_OK; } + + +class CSequentialOutTempBufferImp2: + public ISequentialOutStream, + public CMyUnknownImp +{ + CInOutTempBuffer *_buf; +public: + CMtEncMultiProgress *_mtProgresSpec; + + CSequentialOutTempBufferImp2(): _buf(0), _mtProgresSpec(NULL) {} + void Init(CInOutTempBuffer *buffer) { _buf = buffer; } + MY_UNKNOWN_IMP1(ISequentialOutStream) + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed) +{ + if (!_buf->Write(data, size)) + { + if (processed) + *processed = 0; + return E_FAIL; + } + if (processed) + *processed = size; + if (_mtProgresSpec) + _mtProgresSpec->AddOutSize(size); + return S_OK; +} + + +class CSequentialOutMtNotify: + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + CMyComPtr<ISequentialOutStream> _stream; + CMtEncMultiProgress *_mtProgresSpec; + + CSequentialOutMtNotify(): _mtProgresSpec(NULL) {} + MY_UNKNOWN_IMP1(ISequentialOutStream) + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CSequentialOutMtNotify::Write(const void *data, UInt32 size, UInt32 *processed) +{ + UInt32 realProcessed = 0; + HRESULT res = _stream->Write(data, size, &realProcessed); + if (processed) + *processed = realProcessed; + if (_mtProgresSpec) + _mtProgresSpec->AddOutSize(size); + return res; +} + + + HRESULT CEncoder::Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, - const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, + // const UInt64 *inStreamSize, + const UInt64 *inSizeForReduce, CFolder &folderItem, CRecordVector<UInt64> &coderUnpackSizes, UInt64 &unpackSize, @@ -151,27 +295,37 @@ HRESULT CEncoder::Encode( { RINOK(EncoderConstr()); - if (!_mixerCoderSpec) + if (!_mixerRef) { RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); } - _mixerCoderSpec->ReInit(); - // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress); + + _mixer->ReInit(); + + CMtEncMultiProgress *mtProgressSpec = NULL; + CMyComPtr<ICompressProgressInfo> mtProgress; + + CSequentialOutMtNotify *mtOutStreamNotifySpec = NULL; + CMyComPtr<ISequentialOutStream> mtOutStreamNotify; CObjectVector<CInOutTempBuffer> inOutTempBuffers; - CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs; + CObjectVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs; CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers; + unsigned numMethods = _bindInfo.Coders.Size(); + unsigned i; - for (i = 1; i < _bindInfo.OutStreams.Size(); i++) + + for (i = 1; i < _bindInfo.PackStreams.Size(); i++) { CInOutTempBuffer &iotb = inOutTempBuffers.AddNew(); iotb.Create(); iotb.InitWriting(); } - for (i = 1; i < _bindInfo.OutStreams.Size(); i++) + + for (i = 1; i < _bindInfo.PackStreams.Size(); i++) { - CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp; + CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2; CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec; tempBufferSpec->Init(&inOutTempBuffers[i - 1]); tempBuffers.Add(tempBuffer); @@ -179,94 +333,111 @@ HRESULT CEncoder::Encode( } for (i = 0; i < numMethods; i++) - _mixerCoderSpec->SetCoderInfo(i, NULL, NULL); + _mixer->SetCoderInfo(i, NULL, NULL); - if (_bindInfo.InStreams.IsEmpty()) - return E_FAIL; - UInt32 mainCoderIndex, mainStreamIndex; - _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex); - + + /* inStreamSize can be used by BCJ2 to set optimal range of conversion. + But current BCJ2 encoder uses also another way to check exact size of current file. + So inStreamSize is not required. */ + + /* if (inStreamSize) - { - CRecordVector<const UInt64 *> sizePointers; - for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++) - if (i == mainStreamIndex) - sizePointers.Add(inStreamSize); - else - sizePointers.Add(NULL); - _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL); - } + _mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL); + */ - // UInt64 outStreamStartPos; - // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos)); - CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec; + CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL; CMyComPtr<ISequentialOutStream> outStreamSizeCount; inStreamSizeCountSpec->Init(inStream); - CRecordVector<ISequentialInStream *> inStreamPointers; + ISequentialInStream *inStreamPointer = inStreamSizeCount; CRecordVector<ISequentialOutStream *> outStreamPointers; - inStreamPointers.Add(inStreamSizeCount); - if (_bindInfo.OutStreams.Size() != 0) - { - outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; - outStreamSizeCount = outStreamSizeCountSpec; - outStreamSizeCountSpec->SetStream(outStream); - outStreamSizeCountSpec->Init(); - outStreamPointers.Add(outStreamSizeCount); - } + SetFolder(folderItem); - for (i = 1; i < _bindInfo.OutStreams.Size(); i++) - outStreamPointers.Add(tempBuffers[i - 1]); - - for (i = 0; i < _codersInfo.Size(); i++) + for (i = 0; i < numMethods; i++) { - CCoderInfo &encodingInfo = _codersInfo[i]; - + IUnknown *coder = _mixer->GetCoder(i).GetUnknown(); + CMyComPtr<ICryptoResetInitVector> resetInitVector; - _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); + coder->QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); if (resetInitVector) { resetInitVector->ResetInitVector(); } CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; - _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); + coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); + + CByteBuffer &props = folderItem.Coders[numMethods - 1 - i].Props; + if (writeCoderProperties) { CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream; - CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); + CMyComPtr<ISequentialOutStream> dynOutStream(outStreamSpec); outStreamSpec->Init(); - writeCoderProperties->WriteCoderProperties(outStream); - outStreamSpec->CopyToBuffer(encodingInfo.Props); + writeCoderProperties->WriteCoderProperties(dynOutStream); + outStreamSpec->CopyToBuffer(props); } + else + props.Free(); } - UInt32 progressIndex = mainCoderIndex; + _mixer->SelectMainCoder(false); + UInt32 mainCoder = _mixer->MainCoderIndex; - for (i = 0; i + 1 < _codersInfo.Size(); i++) + bool useMtProgress = false; + if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder)) { - UInt64 m = _codersInfo[i].MethodID; - if (m == k_Delta || m == k_BCJ || m == k_BCJ2) - progressIndex = i + 1; + #ifdef _7ZIP_ST + if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder)) + #endif + useMtProgress = true; } - _mixerCoderSpec->SetProgressCoderIndex(progressIndex); + if (useMtProgress) + { + mtProgressSpec = new CMtEncMultiProgress; + mtProgress = mtProgressSpec; + mtProgressSpec->Init(compressProgress); + + mtOutStreamNotifySpec = new CSequentialOutMtNotify; + mtOutStreamNotify = mtOutStreamNotifySpec; + mtOutStreamNotifySpec->_stream = outStream; + mtOutStreamNotifySpec->_mtProgresSpec = mtProgressSpec; + + FOR_VECTOR(i, tempBufferSpecs) + { + tempBufferSpecs[i]->_mtProgresSpec = mtProgressSpec; + } + } - RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1, - &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress)); - ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem); + if (_bindInfo.PackStreams.Size() != 0) + { + outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; + outStreamSizeCount = outStreamSizeCountSpec; + outStreamSizeCountSpec->SetStream(mtOutStreamNotify ? (ISequentialOutStream *)mtOutStreamNotify : outStream); + outStreamSizeCountSpec->Init(); + outStreamPointers.Add(outStreamSizeCount); + } + + for (i = 1; i < _bindInfo.PackStreams.Size(); i++) + outStreamPointers.Add(tempBuffers[i - 1]); + + RINOK(_mixer->Code( + &inStreamPointer, + &outStreamPointers.Front(), + mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress)); - if (_bindInfo.OutStreams.Size() != 0) + if (_bindInfo.PackStreams.Size() != 0) packSizes.Add(outStreamSizeCountSpec->GetSize()); - for (i = 1; i < _bindInfo.OutStreams.Size(); i++) + for (i = 1; i < _bindInfo.PackStreams.Size(); i++) { CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1]; RINOK(inOutTempBuffer.WriteToStream(outStream)); @@ -274,37 +445,45 @@ HRESULT CEncoder::Encode( } unpackSize = 0; - for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++) + + for (i = 0; i < _bindInfo.Coders.Size(); i++) { - int binder = _bindInfo.FindBinderForInStream( - _bindReverseConverter->DestOutToSrcInMap[i]); + int bond = _bindInfo.FindBond_for_UnpackStream(_DestOut_to_SrcIn[i]); UInt64 streamSize; - if (binder < 0) + if (bond < 0) { streamSize = inStreamSizeCountSpec->GetSize(); unpackSize = streamSize; } else - streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder); + streamSize = _mixer->GetBondStreamSize(bond); coderUnpackSizes.Add(streamSize); } - for (i = 0; i < numMethods; i++) - folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props; + return S_OK; } CEncoder::CEncoder(const CCompressionMethodMode &options): - _bindReverseConverter(0), - _constructed(false) + _constructed(false) { if (options.IsEmpty()) throw 1; _options = options; - _mixerCoderSpec = NULL; + + #ifdef USE_MIXER_ST + _mixerST = NULL; + #endif + + #ifdef USE_MIXER_MT + _mixerMT = NULL; + #endif + + _mixer = NULL; } + HRESULT CEncoder::EncoderConstr() { if (_constructed) @@ -314,112 +493,125 @@ HRESULT CEncoder::EncoderConstr() // it has only password method; if (!_options.PasswordIsDefined) throw 1; - if (!_options.Binds.IsEmpty()) + if (!_options.Bonds.IsEmpty()) throw 1; - NCoderMixer::CCoderStreamsInfo coderStreamsInfo; + CMethodFull method; - - method.NumInStreams = 1; - method.NumOutStreams = 1; - coderStreamsInfo.NumInStreams = 1; - coderStreamsInfo.NumOutStreams = 1; method.Id = k_AES; - + method.NumStreams = 1; _options.Methods.Add(method); + + NCoderMixer2::CCoderStreamsInfo coderStreamsInfo; + coderStreamsInfo.NumStreams = 1; _bindInfo.Coders.Add(coderStreamsInfo); - _bindInfo.InStreams.Add(0); - _bindInfo.OutStreams.Add(0); + _bindInfo.PackStreams.Add(0); + _bindInfo.UnpackCoder = 0; } else { - UInt32 numInStreams = 0, numOutStreams = 0; + UInt32 numOutStreams = 0; unsigned i; + for (i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; - NCoderMixer::CCoderStreamsInfo coderStreamsInfo; - coderStreamsInfo.NumInStreams = methodFull.NumOutStreams; - coderStreamsInfo.NumOutStreams = methodFull.NumInStreams; - if (_options.Binds.IsEmpty()) + NCoderMixer2::CCoderStreamsInfo cod; + + cod.NumStreams = methodFull.NumStreams; + + if (_options.Bonds.IsEmpty()) { - if (i < _options.Methods.Size() - 1) + // if there are no bonds in options, we create bonds via first streams of coders + if (i != _options.Methods.Size() - 1) { - NCoderMixer::CBindPair bindPair; - bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams; - bindPair.OutIndex = numOutStreams; - _bindInfo.BindPairs.Add(bindPair); + NCoderMixer2::CBond bond; + bond.PackIndex = numOutStreams; + bond.UnpackIndex = i + 1; // it's next coder + _bindInfo.Bonds.Add(bond); } - else if (coderStreamsInfo.NumOutStreams != 0) - _bindInfo.OutStreams.Insert(0, numOutStreams); - for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++) - _bindInfo.OutStreams.Add(numOutStreams + j); + else if (cod.NumStreams != 0) + _bindInfo.PackStreams.Insert(0, numOutStreams); + + for (UInt32 j = 1; j < cod.NumStreams; j++) + _bindInfo.PackStreams.Add(numOutStreams + j); } - numInStreams += coderStreamsInfo.NumInStreams; - numOutStreams += coderStreamsInfo.NumOutStreams; + numOutStreams += cod.NumStreams; - _bindInfo.Coders.Add(coderStreamsInfo); + _bindInfo.Coders.Add(cod); } - if (!_options.Binds.IsEmpty()) + if (!_options.Bonds.IsEmpty()) { - for (i = 0; i < _options.Binds.Size(); i++) + for (i = 0; i < _options.Bonds.Size(); i++) { - NCoderMixer::CBindPair bindPair; - const CBind &bind = _options.Binds[i]; - bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream; - bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream; - _bindInfo.BindPairs.Add(bindPair); + NCoderMixer2::CBond mixerBond; + const CBond2 &bond = _options.Bonds[i]; + if (bond.InCoder >= _bindInfo.Coders.Size() + || bond.OutCoder >= _bindInfo.Coders.Size() + || bond.OutStream >= _bindInfo.Coders[bond.OutCoder].NumStreams) + return E_INVALIDARG; + mixerBond.PackIndex = _bindInfo.GetStream_for_Coder(bond.OutCoder) + bond.OutStream; + mixerBond.UnpackIndex = bond.InCoder; + _bindInfo.Bonds.Add(mixerBond); } - for (i = 0; i < (int)numOutStreams; i++) - if (_bindInfo.FindBinderForOutStream(i) == -1) - _bindInfo.OutStreams.Add(i); + + for (i = 0; i < numOutStreams; i++) + if (_bindInfo.FindBond_for_PackStream(i) == -1) + _bindInfo.PackStreams.Add(i); } - for (i = 0; i < (int)numInStreams; i++) - if (_bindInfo.FindBinderForInStream(i) == -1) - _bindInfo.InStreams.Add(i); + if (!_bindInfo.SetUnpackCoder()) + return E_INVALIDARG; - if (_bindInfo.InStreams.IsEmpty()) - throw 1; // this is error + if (!_bindInfo.CalcMapsAndCheck()) + return E_INVALIDARG; - // Make main stream first in list - int inIndex = _bindInfo.InStreams[0]; - for (;;) + if (_bindInfo.PackStreams.Size() != 1) { - UInt32 coderIndex, coderStreamIndex; - _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex); - UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex); - int binder = _bindInfo.FindBinderForOutStream(outIndex); - if (binder >= 0) + /* main_PackStream is pack stream of main path of coders tree. + We find main_PackStream, and place to start of list of out streams. + It allows to use more optimal memory usage for temp buffers, + if main_PackStream is largest stream. */ + + UInt32 ci = _bindInfo.UnpackCoder; + + for (;;) { - inIndex = _bindInfo.BindPairs[binder].InIndex; - continue; - } - for (i = 0; i < _bindInfo.OutStreams.Size(); i++) - if (_bindInfo.OutStreams[i] == outIndex) - { - _bindInfo.OutStreams.Delete(i); - _bindInfo.OutStreams.Insert(0, outIndex); + if (_bindInfo.Coders[ci].NumStreams == 0) break; + + UInt32 outIndex = _bindInfo.Coder_to_Stream[ci]; + int bond = _bindInfo.FindBond_for_PackStream(outIndex); + if (bond >= 0) + { + ci = _bindInfo.Bonds[bond].UnpackIndex; + continue; } - break; + + int i = _bindInfo.FindStream_in_PackStreams(outIndex); + if (i >= 0) + _bindInfo.PackStreams.MoveToFront(i); + break; + } } if (_options.PasswordIsDefined) { - unsigned numCryptoStreams = _bindInfo.OutStreams.Size(); + unsigned numCryptoStreams = _bindInfo.PackStreams.Size(); + unsigned numInStreams = _bindInfo.Coders.Size(); + for (i = 0; i < numCryptoStreams; i++) { - NCoderMixer::CBindPair bindPair; - bindPair.InIndex = numInStreams + i; - bindPair.OutIndex = _bindInfo.OutStreams[i]; - _bindInfo.BindPairs.Add(bindPair); + NCoderMixer2::CBond bond; + bond.UnpackIndex = numInStreams + i; + bond.PackIndex = _bindInfo.PackStreams[i]; + _bindInfo.Bonds.Add(bond); } - _bindInfo.OutStreams.Clear(); + _bindInfo.PackStreams.Clear(); /* if (numCryptoStreams == 0) @@ -428,37 +620,37 @@ HRESULT CEncoder::EncoderConstr() for (i = 0; i < numCryptoStreams; i++) { - NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; - method.NumInStreams = 1; - method.NumOutStreams = 1; - coderStreamsInfo.NumInStreams = method.NumOutStreams; - coderStreamsInfo.NumOutStreams = method.NumInStreams; + method.NumStreams = 1; method.Id = k_AES; - _options.Methods.Add(method); - _bindInfo.Coders.Add(coderStreamsInfo); - _bindInfo.OutStreams.Add(numOutStreams + i); + + NCoderMixer2::CCoderStreamsInfo cod; + cod.NumStreams = 1; + _bindInfo.Coders.Add(cod); + + _bindInfo.PackStreams.Add(numOutStreams++); } } } - for (int i = _options.Methods.Size() - 1; i >= 0; i--) - { - const CMethodFull &methodFull = _options.Methods[i]; - _decompressionMethods.Add(methodFull.Id); - } + for (unsigned i = _options.Methods.Size(); i != 0;) + _decompressionMethods.Add(_options.Methods[--i].Id); - _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo); - _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo); + if (_bindInfo.Coders.Size() > 16) + return E_INVALIDARG; + if (_bindInfo.GetNum_Bonds_and_PackStreams() > 16) + return E_INVALIDARG; + + if (!_bindInfo.CalcMapsAndCheck()) + return E_INVALIDARG; + + InitBindConv(); _constructed = true; return S_OK; } -CEncoder::~CEncoder() -{ - delete _bindReverseConverter; -} +CEncoder::~CEncoder() {} }} diff --git a/CPP/7zip/Archive/7z/7zEncode.h b/CPP/7zip/Archive/7z/7zEncode.h index 8e20bdb5..f1a9b5ad 100644 --- a/CPP/7zip/Archive/7z/7zEncode.h +++ b/CPP/7zip/Archive/7z/7zEncode.h @@ -3,47 +3,82 @@ #ifndef __7Z_ENCODE_H #define __7Z_ENCODE_H -// #include "../../Common/StreamObjects.h" - #include "7zCompressionMode.h" #include "../Common/CoderMixer2.h" -#include "../Common/CoderMixer2MT.h" -#ifdef _ST_MODE -#include "../Common/CoderMixer2ST.h" -#endif -#include "7zItem.h" -#include "../../Common/CreateCoder.h" +#include "7zItem.h" namespace NArchive { namespace N7z { -class CEncoder +class CMtEncMultiProgress: + public ICompressProgressInfo, + public CMyUnknownImp { - NCoderMixer::CCoderMixer2MT *_mixerCoderSpec; - CMyComPtr<ICompressCoder2> _mixerCoder; + CMyComPtr<ICompressProgressInfo> _progress; + #ifndef _7ZIP_ST + NWindows::NSynchronization::CCriticalSection CriticalSection; + #endif + +public: + UInt64 OutSize; + + CMtEncMultiProgress(): OutSize(0) {} + + void Init(ICompressProgressInfo *progress); - CObjectVector<CCoderInfo> _codersInfo; + void AddOutSize(UInt64 addOutSize) + { + #ifndef _7ZIP_ST + NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); + #endif + OutSize += addOutSize; + } + + MY_UNKNOWN_IMP1(ICompressProgressInfo) + + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + +class CEncoder +{ + #ifdef USE_MIXER_ST + NCoderMixer2::CMixerST *_mixerST; + #endif + #ifdef USE_MIXER_MT + NCoderMixer2::CMixerMT *_mixerMT; + #endif + + NCoderMixer2::CMixer *_mixer; + CMyComPtr<IUnknown> _mixerRef; CCompressionMethodMode _options; - NCoderMixer::CBindInfo _bindInfo; - NCoderMixer::CBindInfo _decompressBindInfo; - NCoderMixer::CBindReverseConverter *_bindReverseConverter; + NCoderMixer2::CBindInfo _bindInfo; CRecordVector<CMethodId> _decompressionMethods; + CRecordVector<UInt32> _SrcIn_to_DestOut; + CRecordVector<UInt32> _SrcOut_to_DestIn; + // CRecordVector<UInt32> _DestIn_to_SrcOut; + CRecordVector<UInt32> _DestOut_to_SrcIn; + + void InitBindConv(); + void SetFolder(CFolder &folder); + HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce); bool _constructed; public: + CEncoder(const CCompressionMethodMode &options); ~CEncoder(); HRESULT EncoderConstr(); HRESULT Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, - const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, + // const UInt64 *inStreamSize, + const UInt64 *inSizeForReduce, CFolder &folderItem, CRecordVector<UInt64> &coderUnpackSizes, UInt64 &unpackSize, diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp index 6d2c5b06..d21bafdb 100644 --- a/CPP/7zip/Archive/7z/7zExtract.cpp +++ b/CPP/7zip/Archive/7z/7zExtract.cpp @@ -2,205 +2,327 @@ #include "StdAfx.h" +#include "../../../../C/7zCrc.h" + #include "../../../Common/ComTry.h" #include "../../Common/ProgressUtils.h" #include "7zDecode.h" -// #include "7z1Decode.h" -#include "7zFolderOutStream.h" #include "7zHandler.h" +// EXTERN_g_ExternalCodecs + namespace NArchive { namespace N7z { -struct CExtractFolderInfo +class CFolderOutStream: + public ISequentialOutStream, + public CMyUnknownImp { - #ifdef _7Z_VOL - int VolumeIndex; - #endif - CNum FileIndex; - CNum FolderIndex; - CBoolVector ExtractStatuses; - UInt64 UnpackSize; - CExtractFolderInfo( - #ifdef _7Z_VOL - int volumeIndex, - #endif - CNum fileIndex, CNum folderIndex): - #ifdef _7Z_VOL - VolumeIndex(volumeIndex), - #endif - FileIndex(fileIndex), - FolderIndex(folderIndex), - UnpackSize(0) + CMyComPtr<ISequentialOutStream> _stream; +public: + bool TestMode; + bool CheckCrc; +private: + bool _fileIsOpen; + bool _calcCrc; + UInt32 _crc; + UInt64 _rem; + + const UInt32 *_indexes; + unsigned _numFiles; + unsigned _fileIndex; + + HRESULT OpenFile(bool isCorrupted = false); + HRESULT CloseFile_and_SetResult(Int32 res); + HRESULT CloseFile(); + HRESULT ProcessEmptyFiles(); + +public: + MY_UNKNOWN_IMP1(ISequentialOutStream) + + const CDbEx *_db; + CMyComPtr<IArchiveExtractCallback> ExtractCallback; + + bool ExtraWriteWasCut; + + CFolderOutStream(): + TestMode(false), + CheckCrc(true) + {} + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + + HRESULT Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles); + HRESULT FlushCorrupted(Int32 callbackOperationResult); + + bool WasWritingFinished() const { return _numFiles == 0; } +}; + + +HRESULT CFolderOutStream::Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles) +{ + _fileIndex = startIndex; + _indexes = indexes; + _numFiles = numFiles; + + _fileIsOpen = false; + ExtraWriteWasCut = false; + + return ProcessEmptyFiles(); +} + +HRESULT CFolderOutStream::OpenFile(bool isCorrupted) +{ + const CFileItem &fi = _db->Files[_fileIndex]; + UInt32 nextFileIndex = (_indexes ? *_indexes : _fileIndex); + Int32 askMode = (_fileIndex == nextFileIndex) ? + (TestMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract) : + NExtract::NAskMode::kSkip; + + if (isCorrupted + && askMode == NExtract::NAskMode::kExtract + && !_db->IsItemAnti(_fileIndex) + && !fi.IsDir) + askMode = NExtract::NAskMode::kTest; + + CMyComPtr<ISequentialOutStream> realOutStream; + RINOK(ExtractCallback->GetStream(_fileIndex, &realOutStream, askMode)); + + _stream = realOutStream; + _crc = CRC_INIT_VAL; + _calcCrc = (CheckCrc && fi.CrcDefined && !fi.IsDir); + + _fileIsOpen = true; + _rem = fi.Size; + + if (askMode == NExtract::NAskMode::kExtract + && !realOutStream + && !_db->IsItemAnti(_fileIndex) + && !fi.IsDir) + askMode = NExtract::NAskMode::kSkip; + return ExtractCallback->PrepareOperation(askMode); +} + +HRESULT CFolderOutStream::CloseFile_and_SetResult(Int32 res) +{ + _stream.Release(); + _fileIsOpen = false; + + if (!_indexes) + _numFiles--; + else if (*_indexes == _fileIndex) + { + _indexes++; + _numFiles--; + } + + _fileIndex++; + return ExtractCallback->SetOperationResult(res); +} + +HRESULT CFolderOutStream::CloseFile() +{ + const CFileItem &fi = _db->Files[_fileIndex]; + return CloseFile_and_SetResult((!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc)) ? + NExtract::NOperationResult::kOK : + NExtract::NOperationResult::kCRCError); +} + +HRESULT CFolderOutStream::ProcessEmptyFiles() +{ + while (_numFiles != 0 && _db->Files[_fileIndex].Size == 0) { - if (fileIndex != kNumNoIndex) + RINOK(OpenFile()); + RINOK(CloseFile()); + } + return S_OK; +} + +STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + + while (size != 0) + { + if (_fileIsOpen) { - ExtractStatuses.ClearAndSetSize(1); - ExtractStatuses[0] = true; + UInt32 cur = (size < _rem ? size : (UInt32)_rem); + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, cur, &cur); + if (_calcCrc) + _crc = CrcUpdate(_crc, data, cur); + if (processedSize) + *processedSize += cur; + data = (const Byte *)data + cur; + size -= cur; + _rem -= cur; + if (_rem == 0) + { + RINOK(CloseFile()); + RINOK(ProcessEmptyFiles()); + } + RINOK(result); + if (cur == 0) + break; + continue; } - }; -}; + + RINOK(ProcessEmptyFiles()); + if (_numFiles == 0) + { + // we support partial extracting + /* + if (processedSize) + *processedSize += size; + break; + */ + ExtraWriteWasCut = true; + // return S_FALSE; + return k_My_HRESULT_WritingWasCut; + } + RINOK(OpenFile()); + } + + return S_OK; +} + +HRESULT CFolderOutStream::FlushCorrupted(Int32 callbackOperationResult) +{ + while (_numFiles != 0) + { + if (_fileIsOpen) + { + RINOK(CloseFile_and_SetResult(callbackOperationResult)); + } + else + { + RINOK(OpenFile(true)); + } + } + return S_OK; +} STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec) { COM_TRY_BEGIN - bool testMode = (testModeSpec != 0); + CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; + UInt64 importantTotalUnpacked = 0; + // numItems = (UInt32)(Int32)-1; + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) - numItems = - #ifdef _7Z_VOL - _refs.Size(); - #else - _db.Files.Size(); - #endif + numItems = _db.Files.Size(); - if(numItems == 0) + if (numItems == 0) return S_OK; - /* - if(_volumes.Size() != 1) - return E_FAIL; - const CVolume &volume = _volumes.Front(); - const CDbEx &_db = volume.Database; - IInStream *_inStream = volume.Stream; - */ - - CObjectVector<CExtractFolderInfo> extractFolderInfoVector; - for (UInt32 ii = 0; ii < numItems; ii++) { - // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex]; - UInt32 ref2Index = allFilesMode ? ii : indices[ii]; - // const CRef2 &ref2 = _refs[ref2Index]; - - // for (UInt32 ri = 0; ri < ref2.Refs.Size(); ri++) + CNum prevFolder = kNumNoIndex; + UInt32 nextFile = 0; + + UInt32 i; + + for (i = 0; i < numItems; i++) { - #ifdef _7Z_VOL - // const CRef &ref = ref2.Refs[ri]; - const CRef &ref = _refs[ref2Index]; - - int volumeIndex = ref.VolumeIndex; - const CVolume &volume = _volumes[volumeIndex]; - const CDbEx &db = volume.Database; - UInt32 fileIndex = ref.ItemIndex; - #else - const CDbEx &db = _db; - UInt32 fileIndex = ref2Index; - #endif - - CNum folderIndex = db.FileIndexToFolderIndexMap[fileIndex]; + UInt32 fileIndex = allFilesMode ? i : indices[i]; + CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex]; if (folderIndex == kNumNoIndex) - { - extractFolderInfoVector.Add(CExtractFolderInfo( - #ifdef _7Z_VOL - volumeIndex, - #endif - fileIndex, kNumNoIndex)); continue; - } - if (extractFolderInfoVector.IsEmpty() || - folderIndex != extractFolderInfoVector.Back().FolderIndex - #ifdef _7Z_VOL - || volumeIndex != extractFolderInfoVector.Back().VolumeIndex - #endif - ) - { - extractFolderInfoVector.Add(CExtractFolderInfo( - #ifdef _7Z_VOL - volumeIndex, - #endif - kNumNoIndex, folderIndex)); - UInt64 unpackSize = db.GetFolderUnpackSize(folderIndex); - importantTotalUnpacked += unpackSize; - extractFolderInfoVector.Back().UnpackSize = unpackSize; - } - - CExtractFolderInfo &efi = extractFolderInfoVector.Back(); - - // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex]; - CNum startIndex = db.FolderStartFileIndex[folderIndex]; - for (CNum index = efi.ExtractStatuses.Size(); - index <= fileIndex - startIndex; index++) - { - // UInt64 unpackSize = _db.Files[startIndex + index].UnpackSize; - // Count partial_folder_size - // efi.UnpackSize += unpackSize; - // importantTotalUnpacked += unpackSize; - efi.ExtractStatuses.Add(index == fileIndex - startIndex); - } + if (folderIndex != prevFolder || fileIndex < nextFile) + nextFile = _db.FolderStartFileIndex[folderIndex]; + for (CNum index = nextFile; index <= fileIndex; index++) + importantTotalUnpacked += _db.Files[index].Size; + nextFile = fileIndex + 1; + prevFolder = folderIndex; } } RINOK(extractCallback->SetTotal(importantTotalUnpacked)); + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + CDecoder decoder( - #ifdef _ST_MODE - false + #ifndef USE_MIXER_ST + false #else - true + _useMultiThreadMixer #endif ); - // CDecoder1 decoder; - UInt64 totalPacked = 0; - UInt64 totalUnpacked = 0; UInt64 curPacked, curUnpacked; - CLocalProgress *lps = new CLocalProgress; - CMyComPtr<ICompressProgressInfo> progress = lps; - lps->Init(extractCallback, false); + CMyComPtr<IArchiveExtractCallbackMessage> callbackMessage; + extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage, &callbackMessage); + + CFolderOutStream *folderOutStream = new CFolderOutStream; + CMyComPtr<ISequentialOutStream> outStream(folderOutStream); - for (unsigned i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked) + folderOutStream->_db = &_db; + folderOutStream->ExtractCallback = extractCallback; + folderOutStream->TestMode = (testModeSpec != 0); + folderOutStream->CheckCrc = (_crcSize != 0); + + for (UInt32 i = 0;; lps->OutSize += curUnpacked, lps->InSize += curPacked) { - lps->OutSize = totalUnpacked; - lps->InSize = totalPacked; RINOK(lps->SetCur()); - if (i >= extractFolderInfoVector.Size()) + if (i >= numItems) break; - - const CExtractFolderInfo &efi = extractFolderInfoVector[i]; - curUnpacked = efi.UnpackSize; + + curUnpacked = 0; curPacked = 0; - CFolderOutStream *folderOutStream = new CFolderOutStream; - CMyComPtr<ISequentialOutStream> outStream(folderOutStream); + UInt32 fileIndex = allFilesMode ? i : indices[i]; + CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex]; - #ifdef _7Z_VOL - const CVolume &volume = _volumes[efi.VolumeIndex]; - const CDbEx &db = volume.Database; - #else - const CDbEx &db = _db; - #endif + UInt32 numSolidFiles = 1; - CNum startIndex; - if (efi.FileIndex != kNumNoIndex) - startIndex = efi.FileIndex; - else - startIndex = db.FolderStartFileIndex[efi.FolderIndex]; + if (folderIndex != kNumNoIndex) + { + curPacked = _db.GetFolderFullPackSize(folderIndex); + UInt32 nextFile = fileIndex + 1; + fileIndex = _db.FolderStartFileIndex[folderIndex]; + UInt32 k; + + for (k = i + 1; k < numItems; k++) + { + UInt32 fileIndex2 = allFilesMode ? k : indices[k]; + if (_db.FileIndexToFolderIndexMap[fileIndex2] != folderIndex + || fileIndex2 < nextFile) + break; + nextFile = fileIndex2 + 1; + } + + numSolidFiles = k - i; + + for (k = fileIndex; k < nextFile; k++) + curUnpacked += _db.Files[k].Size; + } + + HRESULT result = folderOutStream->Init(fileIndex, + allFilesMode ? NULL : indices + i, + numSolidFiles); - HRESULT result = folderOutStream->Init(&db, - #ifdef _7Z_VOL - volume.StartRef2Index, - #else - 0, - #endif - startIndex, - &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0); + i += numSolidFiles; RINOK(result); - if (efi.FileIndex != kNumNoIndex) + // to test solid block with zero unpacked size we disable that code + if (folderOutStream->WasWritingFinished()) continue; - CNum folderIndex = efi.FolderIndex; - curPacked = _db.GetFolderFullPackSize(folderIndex); - #ifndef _NO_CRYPTO CMyComPtr<ICryptoGetTextPassword> getTextPassword; if (extractCallback) @@ -212,50 +334,64 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, #ifndef _NO_CRYPTO bool isEncrypted = false; bool passwordIsDefined = false; + UString password; #endif + HRESULT result = decoder.Decode( EXTERNAL_CODECS_VARS - #ifdef _7Z_VOL - volume.Stream, - #else - _inStream, - #endif - db.ArcInfo.DataStartPosition, - db, folderIndex, + _inStream, + _db.ArcInfo.DataStartPosition, + _db, folderIndex, + &curUnpacked, + outStream, - progress + progress, + NULL // *inStreamMainRes + _7Z_DECODER_CRYPRO_VARS #if !defined(_7ZIP_ST) && !defined(_SFX) , true, _numThreads #endif ); - if (result == S_FALSE) + if (result == S_FALSE || result == E_NOTIMPL) { - RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)); - continue; - } - if (result == E_NOTIMPL) - { - RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnsupportedMethod)); + bool wasFinished = folderOutStream->WasWritingFinished(); + + int resOp = (result == S_FALSE ? + NExtract::NOperationResult::kDataError : + NExtract::NOperationResult::kUnsupportedMethod); + + RINOK(folderOutStream->FlushCorrupted(resOp)); + + if (wasFinished) + { + // we don't show error, if it's after required files + if (/* !folderOutStream->ExtraWriteWasCut && */ callbackMessage) + { + RINOK(callbackMessage->ReportExtractResult(NEventIndexType::kBlockIndex, folderIndex, resOp)); + } + } continue; } + if (result != S_OK) return result; - if (folderOutStream->WasWritingFinished() != S_OK) - { - RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)); - continue; - } + + RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)); + continue; } catch(...) { RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)); - continue; + // continue; + return E_FAIL; } } + return S_OK; + COM_TRY_END } diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/CPP/7zip/Archive/7z/7zFolderInStream.cpp index 3f420a51..14cdc436 100644 --- a/CPP/7zip/Archive/7z/7zFolderInStream.cpp +++ b/CPP/7zip/Archive/7z/7zFolderInStream.cpp @@ -7,96 +7,103 @@ namespace NArchive { namespace N7z { -CFolderInStream::CFolderInStream() -{ - _inStreamWithHashSpec = new CSequentialInStreamWithCRC; - _inStreamWithHash = _inStreamWithHashSpec; -} - void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, - const UInt32 *fileIndices, UInt32 numFiles) + const UInt32 *indexes, unsigned numFiles) { _updateCallback = updateCallback; + _indexes = indexes; _numFiles = numFiles; - _fileIndex = 0; - _fileIndices = fileIndices; - Processed.Clear(); - CRCs.Clear(); - Sizes.Clear(); - _fileIsOpen = false; - _currentSizeIsDefined = false; + _index = 0; + + Processed.ClearAndReserve(numFiles); + CRCs.ClearAndReserve(numFiles); + Sizes.ClearAndReserve(numFiles); + + _pos = 0; + _crc = CRC_INIT_VAL; + _size_Defined = false; + _size = 0; + + _stream.Release(); } HRESULT CFolderInStream::OpenStream() { - _filePos = 0; - while (_fileIndex < _numFiles) + _pos = 0; + _crc = CRC_INIT_VAL; + _size_Defined = false; + _size = 0; + + while (_index < _numFiles) { CMyComPtr<ISequentialInStream> stream; - HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream); - if (result != S_OK && result != S_FALSE) - return result; - _fileIndex++; - _inStreamWithHashSpec->SetStream(stream); - _inStreamWithHashSpec->Init(); + HRESULT result = _updateCallback->GetStream(_indexes[_index], &stream); + if (result != S_OK) + { + if (result != S_FALSE) + return result; + } + + _stream = stream; + if (stream) { - _fileIsOpen = true; CMyComPtr<IStreamGetSize> streamGetSize; stream.QueryInterface(IID_IStreamGetSize, &streamGetSize); if (streamGetSize) { - RINOK(streamGetSize->GetSize(&_currentSize)); - _currentSizeIsDefined = true; + if (streamGetSize->GetSize(&_size) == S_OK) + _size_Defined = true; } return S_OK; } + + _index++; RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); - Sizes.Add(0); - Processed.Add(result == S_OK); - AddDigest(); + AddFileInfo(result == S_OK); } return S_OK; } -void CFolderInStream::AddDigest() +void CFolderInStream::AddFileInfo(bool isProcessed) { - CRCs.Add(_inStreamWithHashSpec->GetCRC()); -} - -HRESULT CFolderInStream::CloseStream() -{ - RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); - _inStreamWithHashSpec->ReleaseStream(); - _fileIsOpen = false; - _currentSizeIsDefined = false; - Processed.Add(true); - Sizes.Add(_filePos); - AddDigest(); - return S_OK; + Processed.Add(isProcessed); + Sizes.Add(_pos); + CRCs.Add(CRC_GET_DIGEST(_crc)); } STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { - if (processedSize != 0) + if (processedSize) *processedSize = 0; - while (size > 0) + while (size != 0) { - if (_fileIsOpen) + if (_stream) { UInt32 processed2; - RINOK(_inStreamWithHash->Read(data, size, &processed2)); - if (processed2 == 0) + RINOK(_stream->Read(data, size, &processed2)); + if (processed2 != 0) { - RINOK(CloseStream()); - continue; + _crc = CrcUpdate(_crc, data, processed2); + _pos += processed2; + if (processedSize) + *processedSize = processed2; + return S_OK; } - if (processedSize != 0) - *processedSize = processed2; - _filePos += processed2; - break; + + _stream.Release(); + _index++; + AddFileInfo(true); + + _pos = 0; + _crc = CRC_INIT_VAL; + _size_Defined = false; + _size = 0; + + RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); } - if (_fileIndex >= _numFiles) + + if (_index >= _numFiles) break; RINOK(OpenStream()); } @@ -106,17 +113,23 @@ STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSiz STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) { *value = 0; - unsigned index2 = (unsigned)subStream; if (subStream > Sizes.Size()) - return E_FAIL; - if (index2 < Sizes.Size()) + return S_FALSE; // E_FAIL; + + unsigned index = (unsigned)subStream; + if (index < Sizes.Size()) { - *value = Sizes[index2]; + *value = Sizes[index]; return S_OK; } - if (!_currentSizeIsDefined) + + if (!_size_Defined) + { + *value = _pos; return S_FALSE; - *value = _currentSize; + } + + *value = (_pos > _size ? _pos : _size); return S_OK; } diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.h b/CPP/7zip/Archive/7z/7zFolderInStream.h index 4ed4b2dd..805db54e 100644 --- a/CPP/7zip/Archive/7z/7zFolderInStream.h +++ b/CPP/7zip/Archive/7z/7zFolderInStream.h @@ -3,11 +3,13 @@ #ifndef __7Z_FOLDER_IN_STREAM_H #define __7Z_FOLDER_IN_STREAM_H +#include "../../../../C/7zCrc.h" + +#include "../../../Common/MyCom.h" +#include "../../../Common/MyVector.h" + #include "../../ICoder.h" #include "../IArchive.h" -#include "../Common/InStreamWithCRC.h" - -#include "7zItem.h" namespace NArchive { namespace N7z { @@ -17,33 +19,34 @@ class CFolderInStream: public ICompressGetSubStreamSize, public CMyUnknownImp { - CSequentialInStreamWithCRC *_inStreamWithHashSpec; - CMyComPtr<ISequentialInStream> _inStreamWithHash; - CMyComPtr<IArchiveUpdateCallback> _updateCallback; + CMyComPtr<ISequentialInStream> _stream; + UInt64 _pos; + UInt32 _crc; + bool _size_Defined; + UInt64 _size; - bool _currentSizeIsDefined; - bool _fileIsOpen; - UInt64 _currentSize; - UInt64 _filePos; - const UInt32 *_fileIndices; - UInt32 _numFiles; - UInt32 _fileIndex; + const UInt32 *_indexes; + unsigned _numFiles; + unsigned _index; + + CMyComPtr<IArchiveUpdateCallback> _updateCallback; HRESULT OpenStream(); - HRESULT CloseStream(); - void AddDigest(); + void AddFileInfo(bool isProcessed); public: CRecordVector<bool> Processed; CRecordVector<UInt32> CRCs; CRecordVector<UInt64> Sizes; - MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) + MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); - CFolderInStream(); - void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles); + void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles); + + bool WasFinished() const { return _index == _numFiles; } + UInt64 GetFullSize() const { UInt64 size = 0; diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp index 847f65bf..e63ee925 100644 --- a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp +++ b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp @@ -1,149 +1,3 @@ // 7zFolderOutStream.cpp #include "StdAfx.h" - -#include "7zFolderOutStream.h" - -namespace NArchive { -namespace N7z { - -CFolderOutStream::CFolderOutStream() -{ - _crcStreamSpec = new COutStreamWithCRC; - _crcStream = _crcStreamSpec; -} - -HRESULT CFolderOutStream::Init( - const CDbEx *db, - UInt32 ref2Offset, UInt32 startIndex, - const CBoolVector *extractStatuses, - IArchiveExtractCallback *extractCallback, - bool testMode, bool checkCrc) -{ - _db = db; - _ref2Offset = ref2Offset; - _startIndex = startIndex; - - _extractStatuses = extractStatuses; - _extractCallback = extractCallback; - _testMode = testMode; - _checkCrc = checkCrc; - - _currentIndex = 0; - _fileIsOpen = false; - return ProcessEmptyFiles(); -} - -HRESULT CFolderOutStream::OpenFile() -{ - Int32 askMode = ((*_extractStatuses)[_currentIndex]) ? (_testMode ? - NExtract::NAskMode::kTest : - NExtract::NAskMode::kExtract) : - NExtract::NAskMode::kSkip; - CMyComPtr<ISequentialOutStream> realOutStream; - UInt32 index = _startIndex + _currentIndex; - RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode)); - _crcStreamSpec->SetStream(realOutStream); - _crcStreamSpec->Init(_checkCrc); - _fileIsOpen = true; - const CFileItem &fi = _db->Files[index]; - _rem = fi.Size; - if (askMode == NExtract::NAskMode::kExtract && !realOutStream && - !_db->IsItemAnti(index) && !fi.IsDir) - askMode = NExtract::NAskMode::kSkip; - return _extractCallback->PrepareOperation(askMode); -} - -HRESULT CFolderOutStream::CloseFileAndSetResult(Int32 res) -{ - _crcStreamSpec->ReleaseStream(); - _fileIsOpen = false; - _currentIndex++; - return _extractCallback->SetOperationResult(res); -} - -HRESULT CFolderOutStream::CloseFileAndSetResult() -{ - const CFileItem &fi = _db->Files[_startIndex + _currentIndex]; - return CloseFileAndSetResult( - (fi.IsDir || !fi.CrcDefined || !_checkCrc || fi.Crc == _crcStreamSpec->GetCRC()) ? - NExtract::NOperationResult::kOK : - NExtract::NOperationResult::kCRCError); -} - -HRESULT CFolderOutStream::ProcessEmptyFiles() -{ - while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0) - { - RINOK(OpenFile()); - RINOK(CloseFileAndSetResult()); - } - return S_OK; -} - -STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) -{ - if (processedSize != NULL) - *processedSize = 0; - while (size != 0) - { - if (_fileIsOpen) - { - UInt32 cur = size < _rem ? size : (UInt32)_rem; - RINOK(_crcStream->Write(data, cur, &cur)); - if (cur == 0) - break; - data = (const Byte *)data + cur; - size -= cur; - _rem -= cur; - if (processedSize != NULL) - *processedSize += cur; - if (_rem == 0) - { - RINOK(CloseFileAndSetResult()); - RINOK(ProcessEmptyFiles()); - continue; - } - } - else - { - RINOK(ProcessEmptyFiles()); - if (_currentIndex == _extractStatuses->Size()) - { - // we support partial extracting - if (processedSize != NULL) - *processedSize += size; - break; - } - RINOK(OpenFile()); - } - } - return S_OK; -} - -STDMETHODIMP CFolderOutStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) -{ - *value = 0; - if ((int)subStream >= _extractStatuses->Size()) - return S_FALSE; - *value = _db->Files[_startIndex + (int)subStream].Size; - return S_OK; -} - -HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult) -{ - while (_currentIndex < _extractStatuses->Size()) - { - if (_fileIsOpen) - { - RINOK(CloseFileAndSetResult(resultEOperationResult)); - } - else - { - RINOK(OpenFile()); - } - } - return S_OK; -} - -}} diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.h b/CPP/7zip/Archive/7z/7zFolderOutStream.h index cc2d7734..a32b22e0 100644 --- a/CPP/7zip/Archive/7z/7zFolderOutStream.h +++ b/CPP/7zip/Archive/7z/7zFolderOutStream.h @@ -3,56 +3,4 @@ #ifndef __7Z_FOLDER_OUT_STREAM_H #define __7Z_FOLDER_OUT_STREAM_H -#include "../../IStream.h" -#include "../IArchive.h" -#include "../Common/OutStreamWithCRC.h" - -#include "7zIn.h" - -namespace NArchive { -namespace N7z { - -class CFolderOutStream: - public ISequentialOutStream, - public ICompressGetSubStreamSize, - public CMyUnknownImp -{ - COutStreamWithCRC *_crcStreamSpec; - CMyComPtr<ISequentialOutStream> _crcStream; - const CDbEx *_db; - const CBoolVector *_extractStatuses; - CMyComPtr<IArchiveExtractCallback> _extractCallback; - UInt32 _ref2Offset; - UInt32 _startIndex; - unsigned _currentIndex; - bool _testMode; - bool _checkCrc; - bool _fileIsOpen; - UInt64 _rem; - - HRESULT OpenFile(); - HRESULT CloseFileAndSetResult(Int32 res); - HRESULT CloseFileAndSetResult(); - HRESULT ProcessEmptyFiles(); -public: - MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) - - CFolderOutStream(); - - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); - - HRESULT Init( - const CDbEx *db, - UInt32 ref2Offset, UInt32 startIndex, - const CBoolVector *extractStatuses, - IArchiveExtractCallback *extractCallback, - bool testMode, bool checkCrc); - HRESULT FlushCorrupted(Int32 resultEOperationResult); - HRESULT WasWritingFinished() const - { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; } -}; - -}} - #endif diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp index 2b86ed22..d397e818 100644 --- a/CPP/7zip/Archive/7z/7zHandler.cpp +++ b/CPP/7zip/Archive/7z/7zHandler.cpp @@ -150,22 +150,12 @@ static char *AddProp32(char *s, const char *name, UInt32 v) void CHandler::AddMethodName(AString &s, UInt64 id) { - UString methodName; - FindMethod(EXTERNAL_CODECS_VARS id, methodName); - if (methodName.IsEmpty()) - { - for (unsigned i = 0; i < methodName.Len(); i++) - if (methodName[i] >= 0x80) - { - methodName.Empty(); - break; - } - } - if (methodName.IsEmpty()) + AString name; + FindMethod(EXTERNAL_CODECS_VARS id, name); + if (name.IsEmpty()) ConvertMethodIdToString(s, id); else - for (unsigned i = 0; i < methodName.Len(); i++) - s += (char)methodName[i]; + s += name; } #endif @@ -186,8 +176,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) FOR_VECTOR (i, pm.IDs) { UInt64 id = pm.IDs[i]; - if (!s.IsEmpty()) - s += ' '; + s.Add_Space_if_NotEmpty(); char temp[16]; if (id == k_LZMA2) { @@ -376,6 +365,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const // numCoders == 0 ??? CNum numCoders = inByte.ReadNum(); bool needSpace = false; + for (; numCoders != 0; numCoders--, needSpace = true) { if (pos < 32) // max size of property @@ -500,17 +490,8 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const } else { - UString methodName; + AString methodName; FindMethod(EXTERNAL_CODECS_VARS id64, methodName); - if (methodName.IsEmpty()) - { - for (unsigned j = 0; j < methodName.Len(); j++) - if (methodName[j] >= 0x80) - { - methodName.Empty(); - break; - } - } if (needSpace) temp[--pos] = ' '; if (methodName.IsEmpty()) @@ -522,10 +503,11 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const break; pos -= len; for (unsigned i = 0; i < len; i++) - temp[pos + i] = (char)methodName[i]; + temp[pos + i] = methodName[i]; } } } + if (numCoders != 0 && pos >= 4) { temp[--pos] = ' '; @@ -533,6 +515,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const temp[--pos] = '.'; temp[--pos] = '.'; } + return PropVarEm_Set_Str(prop, temp + pos); // } } @@ -555,7 +538,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val const CFileItem &item = _db.Files[index]; UInt32 index2 = index; - switch(propID) + switch (propID) { case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break; case kpidSize: @@ -608,7 +591,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val */ case kpidPath: return _db.GetPath_Prop(index, value); + #ifndef _SFX + case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value); case kpidBlock: { @@ -617,30 +602,29 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val PropVarEm_Set_UInt32(value, (UInt32)folderIndex); } break; + /* case kpidPackedSize0: case kpidPackedSize1: case kpidPackedSize2: case kpidPackedSize3: case kpidPackedSize4: { - /* CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { - const CFolder &folderInfo = _db.Folders[folderIndex]; if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 && - folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0)) + _db.FoStartPackStreamIndex[folderIndex + 1] - + _db.FoStartPackStreamIndex[folderIndex] > (propID - kpidPackedSize0)) { - prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0); + PropVarEm_Set_UInt64(value, _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0)); } - else - prop = (UInt64)0; } else - prop = (UInt64)0; - */ + PropVarEm_Set_UInt64(value, 0); } break; + */ + #endif } // prop.Detach(value); @@ -668,7 +652,13 @@ STDMETHODIMP CHandler::Open(IInStream *stream, openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); #endif - CInArchive archive; + CInArchive archive( + #ifdef __7Z_SET_PROPERTIES + _useMultiThreadMixer + #else + true + #endif + ); _db.IsArc = false; RINOK(archive.Open(stream, maxCheckStartPosition)); _db.IsArc = true; @@ -677,7 +667,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, EXTERNAL_CODECS_VARS _db #ifndef _NO_CRYPTO - , getTextPassword, _isEncrypted, _passwordIsDefined + , getTextPassword, _isEncrypted, _passwordIsDefined, _password #endif ); RINOK(result); @@ -688,8 +678,9 @@ STDMETHODIMP CHandler::Open(IInStream *stream, { Close(); // return E_INVALIDARG; + // return S_FALSE; // we must return out_of_memory here - return S_FALSE; + return E_OUTOFMEMORY; } // _inStream = stream; #ifndef _SFX @@ -707,6 +698,7 @@ STDMETHODIMP CHandler::Close() #ifndef _NO_CRYPTO _isEncrypted = false; _passwordIsDefined = false; + _password.Empty(); #endif return S_OK; COM_TRY_END @@ -715,11 +707,12 @@ STDMETHODIMP CHandler::Close() #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) +STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) { COM_TRY_BEGIN const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); _numThreads = numProcessors; + _useMultiThreadMixer = true; for (UInt32 i = 0; i < numProps; i++) { @@ -732,7 +725,8 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v int index = ParseStringToUInt32(name, number); if (index == 0) { - if (name.IsPrefixedBy(L"mt")) + if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer); + if (name.IsPrefixedBy_Ascii_NoCase("mt")) { RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads)); continue; diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h index c33617c4..8a078e19 100644 --- a/CPP/7zip/Archive/7z/7zHandler.h +++ b/CPP/7zip/Archive/7z/7zHandler.h @@ -18,16 +18,6 @@ namespace NArchive { namespace N7z { -const UInt32 k_Copy = 0x0; -const UInt32 k_Delta = 3; -const UInt32 k_LZMA2 = 0x21; -const UInt32 k_LZMA = 0x030101; -const UInt32 k_PPMD = 0x030401; -const UInt32 k_BCJ = 0x03030103; -const UInt32 k_BCJ2 = 0x0303011B; -const UInt32 k_Deflate = 0x040108; -const UInt32 k_BZip2 = 0x040202; - #ifndef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY @@ -64,7 +54,9 @@ public: CBoolPair Write_ATime; CBoolPair Write_MTime; - bool _volumeMode; + bool _useMultiThreadMixer; + + // bool _volumeMode; void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } @@ -117,7 +109,7 @@ public: INTERFACE_IArchiveGetRawProps(;) #ifdef __7Z_SET_PROPERTIES - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); + STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); #endif #ifndef EXTRACT_ONLY @@ -131,28 +123,29 @@ public: private: CMyComPtr<IInStream> _inStream; NArchive::N7z::CDbEx _db; + #ifndef _NO_CRYPTO bool _isEncrypted; bool _passwordIsDefined; + UString _password; #endif #ifdef EXTRACT_ONLY #ifdef __7Z_SET_PROPERTIES UInt32 _numThreads; + bool _useMultiThreadMixer; #endif UInt32 _crcSize; #else - CRecordVector<CBind> _binds; + CRecordVector<CBond2> _bonds; HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m); HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod); - void AddDefaultMethod(); - HRESULT SetMainMethod(CCompressionMethodMode &method, - CObjectVector<COneMethodInfo> &methodsInfo + HRESULT SetMainMethod(CCompressionMethodMode &method #ifndef _7ZIP_ST , UInt32 numThreads #endif diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp index 5e113207..5cab6a82 100644 --- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp +++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp @@ -18,11 +18,11 @@ using namespace NWindows; namespace NArchive { namespace N7z { -static const wchar_t *k_LZMA_Name = L"LZMA"; -static const wchar_t *kDefaultMethodName = L"LZMA2"; -static const wchar_t *k_Copy_Name = L"Copy"; +static const char *k_LZMA_Name = "LZMA"; +static const char *kDefaultMethodName = "LZMA2"; +static const char *k_Copy_Name = "Copy"; -static const wchar_t *k_MatchFinder_ForHeaders = L"BT2"; +static const char *k_MatchFinder_ForHeaders = "BT2"; static const UInt32 k_NumFastBytes_ForHeaders = 273; static const UInt32 k_Level_ForHeaders = 5; static const UInt32 k_Dictionary_ForHeaders = @@ -42,7 +42,7 @@ HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodI { if (!FindMethod( EXTERNAL_CODECS_VARS - m.MethodName, dest.Id, dest.NumInStreams, dest.NumOutStreams)) + m.MethodName, dest.Id, dest.NumStreams)) return E_INVALIDARG; (CProps &)dest = (CProps &)m; return S_OK; @@ -54,48 +54,62 @@ HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod) return S_OK; COneMethodInfo m; m.MethodName = k_LZMA_Name; - m.AddPropString(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders); - m.AddProp32(NCoderPropID::kLevel, k_Level_ForHeaders); + m.AddProp_Ascii(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders); + m.AddProp_Level(k_Level_ForHeaders); m.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders); m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders); - m.AddNumThreadsProp(1); + m.AddProp_NumThreads(1); - CMethodFull methodFull; - RINOK(PropsMethod_To_FullMethod(methodFull, m)); - headerMethod.Methods.Add(methodFull); - return S_OK; -} - -void CHandler::AddDefaultMethod() -{ - FOR_VECTOR (i, _methods) - { - UString &methodName = _methods[i].MethodName; - if (methodName.IsEmpty()) - methodName = kDefaultMethodName; - } - if (_methods.IsEmpty()) - { - COneMethodInfo m; - m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName); - _methods.Add(m); - } + CMethodFull &methodFull = headerMethod.Methods.AddNew(); + return PropsMethod_To_FullMethod(methodFull, m); } HRESULT CHandler::SetMainMethod( - CCompressionMethodMode &methodMode, - CObjectVector<COneMethodInfo> &methods + CCompressionMethodMode &methodMode #ifndef _7ZIP_ST , UInt32 numThreads #endif ) { - AddDefaultMethod(); + methodMode.Bonds = _bonds; + + CObjectVector<COneMethodInfo> methods = _methods; + + { + FOR_VECTOR (i, methods) + { + AString &methodName = methods[i].MethodName; + if (methodName.IsEmpty()) + methodName = kDefaultMethodName; + } + if (methods.IsEmpty()) + { + COneMethodInfo &m = methods.AddNew(); + m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName); + methodMode.DefaultMethod_was_Inserted = true; + } + } + + if (!_filterMethod.MethodName.IsEmpty()) + { + // if (methodMode.Bonds.IsEmpty()) + { + FOR_VECTOR (k, methodMode.Bonds) + { + CBond2 &bond = methodMode.Bonds[k]; + bond.InCoder++; + bond.OutCoder++; + } + methods.Insert(0, _filterMethod); + methodMode.Filter_was_Inserted = true; + } + } const UInt64 kSolidBytes_Min = (1 << 24); const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1; bool needSolid = false; + FOR_VECTOR (i, methods) { COneMethodInfo &oneMethodInfo = methods[i]; @@ -105,9 +119,8 @@ HRESULT CHandler::SetMainMethod( #endif ); - CMethodFull methodFull; + CMethodFull &methodFull = methodMode.Methods.AddNew(); RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo)); - methodMode.Methods.Add(methodFull); if (methodFull.Id != k_Copy) needSolid = true; @@ -125,6 +138,7 @@ HRESULT CHandler::SetMainMethod( case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break; default: continue; } + _numSolidBytes = (UInt64)dicSize << 7; if (_numSolidBytes < kSolidBytes_Min) _numSolidBytes = kSolidBytes_Min; if (_numSolidBytes > kSolidBytes_Max) _numSolidBytes = kSolidBytes_Max; @@ -517,18 +531,20 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt CCompressionMethodMode methodMode, headerMethod; - HRESULT res = SetMainMethod(methodMode, _methods + HRESULT res = SetMainMethod(methodMode #ifndef _7ZIP_ST , _numThreads #endif ); RINOK(res); - methodMode.Binds = _binds; RINOK(SetHeaderMethod(headerMethod)); + #ifndef _7ZIP_ST methodMode.NumThreads = _numThreads; + methodMode.MultiThreadMixer = _useMultiThreadMixer; headerMethod.NumThreads = 1; + headerMethod.MultiThreadMixer = _useMultiThreadMixer; #endif CMyComPtr<ICryptoGetTextPassword2> getPassword2; @@ -542,7 +558,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt Int32 passwordIsDefined; RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password)); methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); - if (methodMode.PasswordIsDefined && (BSTR)password) + if (methodMode.PasswordIsDefined && password) methodMode.Password = password; } @@ -550,6 +566,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt bool encryptHeaders = false; + #ifndef _NO_CRYPTO + if (!methodMode.PasswordIsDefined && _passwordIsDefined) + { + // if header is compressed, we use that password for updated archive + methodMode.PasswordIsDefined = true; + methodMode.Password = _password; + } + #endif + if (methodMode.PasswordIsDefined) { if (_encryptHeadersSpecified) @@ -569,12 +594,14 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (numItems < 2) compressMainHeader = false; + int level = GetLevel(); + CUpdateOptions options; options.Method = &methodMode; - options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0; - int level = GetLevel(); - options.UseFilters = level != 0 && _autoFilter; - options.MaxFilter = level >= 8; + options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : NULL; + options.UseFilters = (level != 0 && _autoFilter && !methodMode.Filter_was_Inserted); + options.MaxFilter = (level >= 8); + options.AnalysisLevel = GetAnalysisLevel(); options.HeaderOptions.CompressMainHeader = compressMainHeader; /* @@ -587,7 +614,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt options.NumSolidBytes = _numSolidBytes; options.SolidExtension = _solidExtension; options.RemoveSfxBlock = _removeSfxBlock; - options.VolumeMode = _volumeMode; + // options.VolumeMode = _volumeMode; + + options.MultiThreadMixer = _useMultiThreadMixer; COutArchive archive; CArchiveDatabaseOut newDatabase; @@ -635,20 +664,20 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt COM_TRY_END } -static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream) +static HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream) { stream = 0; int index = ParseStringToUInt32(srcString, coder); if (index == 0) return E_INVALIDARG; - srcString.Delete(0, index); + srcString.DeleteFrontal(index); if (srcString[0] == 's') { srcString.Delete(0); int index = ParseStringToUInt32(srcString, stream); if (index == 0) return E_INVALIDARG; - srcString.Delete(0, index); + srcString.DeleteFrontal(index); } return S_OK; } @@ -667,7 +696,10 @@ void COutHandler::InitProps() Write_ATime.Init(); Write_MTime.Init(); - _volumeMode = false; + _useMultiThreadMixer = true; + + // _volumeMode = false; + InitSolid(); } @@ -762,7 +794,7 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val UInt32 number; int index = ParseStringToUInt32(name, number); - UString realName = name.Ptr(index); + // UString realName = name.Ptr(index); if (index == 0) { if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock); @@ -787,15 +819,17 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val if (name.IsEqualTo("ta")) return PROPVARIANT_to_BoolPair(value, Write_ATime); if (name.IsEqualTo("tm")) return PROPVARIANT_to_BoolPair(value, Write_MTime); - if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode); + if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer); + + // if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode); } return CMultiMethodProps::SetProperty(name, value); } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) +STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) { COM_TRY_BEGIN - _binds.Clear(); + _bonds.Clear(); InitProps(); for (UInt32 i = 0; i < numProps; i++) @@ -812,15 +846,19 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v if (value.vt != VT_EMPTY) return E_INVALIDARG; name.Delete(0); - CBind bind; - RINOK(GetBindInfoPart(name, bind.OutCoder, bind.OutStream)); + + CBond2 bond; + RINOK(ParseBond(name, bond.OutCoder, bond.OutStream)); if (name[0] != ':') return E_INVALIDARG; name.Delete(0); - RINOK(GetBindInfoPart(name, bind.InCoder, bind.InStream)); + UInt32 inStream = 0; + RINOK(ParseBond(name, bond.InCoder, inStream)); + if (inStream != 0) + return E_INVALIDARG; if (!name.IsEmpty()) return E_INVALIDARG; - _binds.Add(bind); + _bonds.Add(bond); continue; } @@ -831,40 +869,27 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v if (numEmptyMethods > 0) { unsigned k; - for (k = 0; k < _binds.Size(); k++) + for (k = 0; k < _bonds.Size(); k++) { - const CBind &bind = _binds[k]; - if (bind.InCoder < (UInt32)numEmptyMethods || - bind.OutCoder < (UInt32)numEmptyMethods) + const CBond2 &bond = _bonds[k]; + if (bond.InCoder < (UInt32)numEmptyMethods || + bond.OutCoder < (UInt32)numEmptyMethods) return E_INVALIDARG; } - for (k = 0; k < _binds.Size(); k++) + for (k = 0; k < _bonds.Size(); k++) { - CBind &bind = _binds[k]; - bind.InCoder -= (UInt32)numEmptyMethods; - bind.OutCoder -= (UInt32)numEmptyMethods; + CBond2 &bond = _bonds[k]; + bond.InCoder -= (UInt32)numEmptyMethods; + bond.OutCoder -= (UInt32)numEmptyMethods; } _methods.DeleteFrontal(numEmptyMethods); } - AddDefaultMethod(); - - if (!_filterMethod.MethodName.IsEmpty()) - { - FOR_VECTOR (k, _binds) - { - CBind &bind = _binds[k]; - bind.InCoder++; - bind.OutCoder++; - } - _methods.Insert(0, _filterMethod); - } - - FOR_VECTOR (k, _binds) + FOR_VECTOR (k, _bonds) { - const CBind &bind = _binds[k]; - if (bind.InCoder >= (UInt32)_methods.Size() || - bind.OutCoder >= (UInt32)_methods.Size()) + const CBond2 &bond = _bonds[k]; + if (bond.InCoder >= (UInt32)_methods.Size() || + bond.OutCoder >= (UInt32)_methods.Size()) return E_INVALIDARG; } diff --git a/CPP/7zip/Archive/7z/7zHeader.h b/CPP/7zip/Archive/7z/7zHeader.h index d72fdefa..d7f0ae36 100644 --- a/CPP/7zip/Archive/7z/7zHeader.h +++ b/CPP/7zip/Archive/7z/7zHeader.h @@ -96,6 +96,53 @@ namespace NID }; } + +const UInt32 k_Copy = 0; +const UInt32 k_Delta = 3; + +const UInt32 k_LZMA2 = 0x21; + +const UInt32 k_SWAP2 = 0x20302; +const UInt32 k_SWAP4 = 0x20304; + +const UInt32 k_LZMA = 0x30101; +const UInt32 k_PPMD = 0x30401; + +const UInt32 k_Deflate = 0x40108; +const UInt32 k_BZip2 = 0x40202; + +const UInt32 k_BCJ = 0x3030103; +const UInt32 k_BCJ2 = 0x303011B; +const UInt32 k_PPC = 0x3030205; +const UInt32 k_IA64 = 0x3030401; +const UInt32 k_ARM = 0x3030501; +const UInt32 k_ARMT = 0x3030701; +const UInt32 k_SPARC = 0x3030805; + +const UInt32 k_AES = 0x6F10701; + + +static inline bool IsFilterMethod(UInt64 m) +{ + if (m > (UInt64)0xFFFFFFFF) + return false; + switch ((UInt32)m) + { + case k_Delta: + case k_BCJ: + case k_BCJ2: + case k_PPC: + case k_IA64: + case k_ARM: + case k_ARMT: + case k_SPARC: + case k_SWAP2: + case k_SWAP4: + return true; + } + return false; +} + }} #endif diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp index 4f04aa83..bd6c4d95 100644 --- a/CPP/7zip/Archive/7z/7zIn.cpp +++ b/CPP/7zip/Archive/7z/7zIn.cpp @@ -32,9 +32,6 @@ using namespace NCOM; namespace NArchive { namespace N7z { -static const UInt32 k_LZMA2 = 0x21; -static const UInt32 k_LZMA = 0x030101; - static void BoolVector_Fill_False(CBoolVector &v, unsigned size) { v.ClearAndSetSize(size); @@ -43,78 +40,6 @@ static void BoolVector_Fill_False(CBoolVector &v, unsigned size) p[i] = false; } -static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index) -{ - if (index >= (UInt32)v.Size()) - return true; - bool res = v[index]; - v[index] = true; - return res; -} - -bool CFolder::CheckStructure(unsigned numUnpackSizes) const -{ - const unsigned kNumCodersMax = sizeof(UInt32) * 8; // don't change it - const unsigned kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax - const unsigned kNumBindsMax = 32; - - if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax) - return false; - - { - CBoolVector v; - BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size()); - - unsigned i; - for (i = 0; i < BindPairs.Size(); i++) - if (BoolVector_GetAndSet(v, BindPairs[i].InIndex)) - return false; - for (i = 0; i < PackStreams.Size(); i++) - if (BoolVector_GetAndSet(v, PackStreams[i])) - return false; - - BoolVector_Fill_False(v, numUnpackSizes); - for (i = 0; i < BindPairs.Size(); i++) - if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex)) - return false; - } - - UInt32 mask[kMaskSize]; - unsigned i; - for (i = 0; i < kMaskSize; i++) - mask[i] = 0; - - { - CUIntVector inStreamToCoder, outStreamToCoder; - for (i = 0; i < Coders.Size(); i++) - { - CNum j; - const CCoderInfo &coder = Coders[i]; - for (j = 0; j < coder.NumInStreams; j++) - inStreamToCoder.Add(i); - for (j = 0; j < coder.NumOutStreams; j++) - outStreamToCoder.Add(i); - } - - for (i = 0; i < BindPairs.Size(); i++) - { - const CBindPair &bp = BindPairs[i]; - mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]); - } - } - - for (i = 0; i < kMaskSize; i++) - for (unsigned j = 0; j < kMaskSize; j++) - if (((1 << j) & mask[i]) != 0) - mask[i] |= mask[j]; - - for (i = 0; i < kMaskSize; i++) - if (((1 << i) & mask[i]) != 0) - return false; - - return true; -} - class CInArchiveException {}; class CUnsupportedFeatureException: public CInArchiveException {}; @@ -193,6 +118,8 @@ Byte CInByte2::ReadByte() void CInByte2::ReadBytes(Byte *data, size_t size) { + if (size == 0) + return; if (size > _size - _pos) ThrowEndOfData(); memcpy(data, _buffer + _pos, size); @@ -218,41 +145,48 @@ static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed) processed = 0; return 0; } - Byte firstByte = *p++; + + unsigned b = *p++; size--; - if ((firstByte & 0x80) == 0) + + if ((b & 0x80) == 0) { processed = 1; - return firstByte; + return b; } - Byte mask = 0x40; + if (size == 0) { processed = 0; return 0; } + UInt64 value = (UInt64)*p; p++; size--; + for (unsigned i = 1; i < 8; i++) { - if ((firstByte & mask) == 0) + unsigned mask = (unsigned)0x80 >> i; + if ((b & mask) == 0) { - UInt64 highPart = firstByte & (mask - 1); - value += (highPart << (i * 8)); + UInt64 high = b & (mask - 1); + value |= (high << (i * 8)); processed = i + 1; return value; } + if (size == 0) { processed = 0; return 0; } + value |= ((UInt64)*p << (i * 8)); p++; size--; - mask >>= 1; } + processed = 9; return value; } @@ -344,6 +278,7 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search for (;;) { UInt32 readSize = kBufSize - kHeaderSize; + if (searchHeaderSizeLimit) { UInt64 rem = *searchHeaderSizeLimit - offset; if (readSize > rem) @@ -351,10 +286,12 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search if (readSize == 0) return S_FALSE; } + UInt32 processed = 0; RINOK(stream->Read(buf + kHeaderSize, readSize, &processed)); if (processed == 0) return S_FALSE; + for (UInt32 pos = 0;;) { const Byte *p = buf + pos + 1; @@ -376,6 +313,7 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL); } } + offset += processed; memmove(buf, buf + processed, kHeaderSize); } @@ -415,13 +353,15 @@ void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) void CInByte2::ParseFolder(CFolder &folder) { - CNum numCoders = ReadNum(); + UInt32 numCoders = ReadNum(); + + if (numCoders == 0) + ThrowUnsupported(); folder.Coders.SetSize(numCoders); - CNum numInStreams = 0; - CNum numOutStreams = 0; - CNum i; + UInt32 numInStreams = 0; + UInt32 i; for (i = 0; i < numCoders; i++) { CCoderInfo &coder = folder.Coders[i]; @@ -441,14 +381,14 @@ void CInByte2::ParseFolder(CFolder &folder) if ((mainByte & 0x10) != 0) { - coder.NumInStreams = ReadNum(); - coder.NumOutStreams = ReadNum(); + coder.NumStreams = ReadNum(); + /* numOutStreams = */ ReadNum(); } else { - coder.NumInStreams = 1; - coder.NumOutStreams = 1; + coder.NumStreams = 1; } + if ((mainByte & 0x20) != 0) { CNum propsSize = ReadNum(); @@ -458,27 +398,27 @@ void CInByte2::ParseFolder(CFolder &folder) else coder.Props.Free(); } - numInStreams += coder.NumInStreams; - numOutStreams += coder.NumOutStreams; + numInStreams += coder.NumStreams; } - CNum numBindPairs = numOutStreams - 1; - folder.BindPairs.SetSize(numBindPairs); - for (i = 0; i < numBindPairs; i++) + UInt32 numBonds = numCoders - 1; + folder.Bonds.SetSize(numBonds); + for (i = 0; i < numBonds; i++) { - CBindPair &bp = folder.BindPairs[i]; - bp.InIndex = ReadNum(); - bp.OutIndex = ReadNum(); + CBond &bp = folder.Bonds[i]; + bp.PackIndex = ReadNum(); + bp.UnpackIndex = ReadNum(); } - if (numInStreams < numBindPairs) + if (numInStreams < numBonds) ThrowUnsupported(); - CNum numPackStreams = numInStreams - numBindPairs; + UInt32 numPackStreams = numInStreams - numBonds; folder.PackStreams.SetSize(numPackStreams); + if (numPackStreams == 1) { for (i = 0; i < numInStreams; i++) - if (folder.FindBindPairForInStream(i) < 0) + if (folder.FindBond_for_PackStream(i) < 0) { folder.PackStreams[0] = i; break; @@ -509,12 +449,12 @@ void CDatabase::GetPath(unsigned index, UString &path) const return; size_t offset = NameOffsets[index]; - size_t size = NameOffsets[index + 1] - offset - 1; + size_t size = NameOffsets[index + 1] - offset; - if (size >= (1 << 20)) + if (size >= (1 << 28)) return; - wchar_t *s = path.GetBuffer((unsigned)size); + wchar_t *s = path.GetBuf((unsigned)size - 1); const Byte *p = ((const Byte *)NamesBuf + offset * 2); @@ -533,7 +473,7 @@ void CDatabase::GetPath(unsigned index, UString &path) const #endif - path.ReleaseBuffer((unsigned)size); + path.ReleaseBuf_SetLen((unsigned)size - 1); } HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw() @@ -592,7 +532,7 @@ HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw() { unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1); const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2; - do + for (; len != 0; len--) { p -= 2; --s; @@ -601,7 +541,7 @@ HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw() c = WCHAR_PATH_SEPARATOR; *s = c; } - while (--len); + const CFileItem &file = Files[cur]; cur = file.Parent; if (cur < 0) @@ -639,6 +579,9 @@ void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs) } } +#define k_Scan_NumCoders_MAX 64 +#define k_Scan_NumCodersStreams_in_Folder_MAX 64 + void CInArchive::ReadPackInfo(CFolders &f) { CNum numPackStreams = ReadNum(); @@ -692,27 +635,31 @@ void CInArchive::ReadUnpackInfo( folders.FoCodersDataOffset.Alloc(numFolders + 1); folders.FoToCoderUnpackSizes.Alloc(numFolders + 1); - CRecordVector<bool> InStreamUsed; - CRecordVector<bool> OutStreamUsed; + CBoolVector StreamUsed; + CBoolVector CoderUsed; CNum packStreamIndex = 0; CNum fo; CInByte2 *inByte = _inByteBack; + for (fo = 0; fo < numFolders; fo++) { - UInt32 numOutStreams = 0; UInt32 indexOfMainStream = 0; UInt32 numPackStreams = 0; folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr; - numOutStreams = 0; CNum numInStreams = 0; CNum numCoders = inByte->ReadNum(); + + if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX) + ThrowUnsupported(); + for (CNum ci = 0; ci < numCoders; ci++) { Byte mainByte = inByte->ReadByte(); if ((mainByte & 0xC0) != 0) ThrowUnsupported(); + unsigned idSize = (mainByte & 0xF); if (idSize > 8) ThrowUnsupported(); @@ -725,19 +672,21 @@ void CInArchive::ReadUnpackInfo( inByte->SkipDataNoCheck(idSize); if (folders.ParsedMethods.IDs.Size() < 128) folders.ParsedMethods.IDs.AddToUniqueSorted(id); + CNum coderInStreams = 1; - CNum coderOutStreams = 1; if ((mainByte & 0x10) != 0) { coderInStreams = inByte->ReadNum(); - coderOutStreams = inByte->ReadNum(); + if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX) + ThrowUnsupported(); + if (inByte->ReadNum() != 1) + ThrowUnsupported(); } + numInStreams += coderInStreams; - if (numInStreams < coderInStreams) - ThrowUnsupported(); - numOutStreams += coderOutStreams; - if (numOutStreams < coderOutStreams) + if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX) ThrowUnsupported(); + if ((mainByte & 0x20) != 0) { CNum propsSize = inByte->ReadNum(); @@ -759,7 +708,7 @@ void CInArchive::ReadUnpackInfo( } } - if (numOutStreams == 1 && numInStreams == 1) + if (numCoders == 1 && numInStreams == 1) { indexOfMainStream = 0; numPackStreams = 1; @@ -767,55 +716,55 @@ void CInArchive::ReadUnpackInfo( else { UInt32 i; - if (numOutStreams == 0) - ThrowUnsupported(); - CNum numBindPairs = numOutStreams - 1; - if (numInStreams < numBindPairs) - ThrowUnsupported(); - if (numInStreams >= 256 || numOutStreams >= 256) + CNum numBonds = numCoders - 1; + if (numInStreams < numBonds) ThrowUnsupported(); - InStreamUsed.ClearAndSetSize(numInStreams); - for (i = 0; i < numInStreams; i++) - InStreamUsed[i] = false; + BoolVector_Fill_False(StreamUsed, numInStreams); + BoolVector_Fill_False(CoderUsed, numCoders); - OutStreamUsed.ClearAndSetSize(numOutStreams); - for (i = 0; i < numOutStreams; i++) - OutStreamUsed[i] = false; - - for (i = 0; i < numBindPairs; i++) + for (i = 0; i < numBonds; i++) { CNum index = ReadNum(); - if (index >= numInStreams || InStreamUsed[index]) + if (index >= numInStreams || StreamUsed[index]) ThrowUnsupported(); - InStreamUsed[index] = true; + StreamUsed[index] = true; + index = ReadNum(); - if (index >= numOutStreams || OutStreamUsed[index]) + if (index >= numCoders || CoderUsed[index]) ThrowUnsupported(); - OutStreamUsed[index] = true; + CoderUsed[index] = true; } - numPackStreams = numInStreams - numBindPairs; + numPackStreams = numInStreams - numBonds; if (numPackStreams != 1) for (i = 0; i < numPackStreams; i++) - inByte->ReadNum(); // PackStreams + { + CNum index = inByte->ReadNum(); // PackStreams + if (index >= numInStreams || StreamUsed[index]) + ThrowUnsupported(); + StreamUsed[index] = true; + } - for (i = 0; i < numOutStreams; i++) - if (!OutStreamUsed[i]) + for (i = 0; i < numCoders; i++) + if (!CoderUsed[i]) { indexOfMainStream = i; break; } - if (i == numOutStreams) + + if (i == numCoders) ThrowUnsupported(); } + folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; - numCodersOutStreams += numOutStreams; + numCodersOutStreams += numCoders; folders.FoStartPackStreamIndex[fo] = packStreamIndex; packStreamIndex += numPackStreams; folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream; } + size_t dataSize = _inByteBack->GetPtr() - startBufPtr; folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; folders.FoStartPackStreamIndex[fo] = packStreamIndex; @@ -1105,13 +1054,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( unpackSizes, digests); - CDecoder decoder( - #ifdef _ST_MODE - false - #else - true - #endif - ); + CDecoder decoder(_useMixerMT); for (CNum i = 0; i < folders.NumFolders; i++) { @@ -1127,14 +1070,20 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( outStreamSpec->Init(data, unpackSize); HRESULT result = decoder.Decode( - EXTERNAL_CODECS_LOC_VARS - _stream, baseOffset + dataOffset, - folders, i, - outStream, NULL - _7Z_DECODER_CRYPRO_VARS - #if !defined(_7ZIP_ST) && !defined(_SFX) - , false, 1 - #endif + EXTERNAL_CODECS_LOC_VARS + _stream, baseOffset + dataOffset, + folders, i, + NULL, // *unpackSize + + outStream, + NULL, // *compressProgress + NULL // **inStreamMainRes + + _7Z_DECODER_CRYPRO_VARS + #if !defined(_7ZIP_ST) && !defined(_SFX) + , false // mtMode + , 1 // numThreads + #endif ); RINOK(result); @@ -1208,7 +1157,7 @@ HRESULT CInArchive::ReadHeader( db.ArcInfo.FileInfoPopIDs.Add(NID::kSize); // if (!db.PackSizes.IsEmpty()) db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo); - if (numFiles > 0 && !digests.Defs.IsEmpty()) + if (numFiles > 0 && !digests.Defs.IsEmpty()) db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC); CBoolVector emptyStreamVector; @@ -1396,6 +1345,9 @@ HRESULT CInArchive::ReadHeader( type = ReadID(); // Read (NID::kEnd) end of headers + if (numFiles - numEmptyStreams != unpackSizes.Size()) + ThrowUnsupported(); + CNum emptyFileIndex = 0; CNum sizeIndex = 0; @@ -1403,7 +1355,7 @@ HRESULT CInArchive::ReadHeader( for (i = 0; i < numEmptyStreams; i++) if (antiFileVector[i]) numAntiItems++; - + for (i = 0; i < numFiles; i++) { CFileItem &file = db.Files[i]; @@ -1444,13 +1396,13 @@ HRESULT CInArchive::ReadHeader( void CDbEx::FillLinks() { - FolderStartFileIndex.ClearAndSetSize(NumFolders); - - FileIndexToFolderIndexMap.ClearAndSetSize(Files.Size()); + FolderStartFileIndex.Alloc(NumFolders); + FileIndexToFolderIndexMap.Alloc(Files.Size()); CNum folderIndex = 0; CNum indexInFolder = 0; unsigned i; + for (i = 0; i < Files.Size(); i++) { bool emptyStream = !Files[i].HasStream; @@ -1489,6 +1441,7 @@ void CDbEx::FillLinks() if (indexInFolder != 0) ThrowIncorrect(); */ + for (;;) { if (folderIndex >= NumFolders) diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h index 373000f7..ad8ceba5 100644 --- a/CPP/7zip/Archive/7z/7zIn.h +++ b/CPP/7zip/Archive/7z/7zIn.h @@ -26,8 +26,8 @@ namespace N7z { #define _7Z_DECODER_CRYPRO_VARS_DECL #define _7Z_DECODER_CRYPRO_VARS #else -#define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined -#define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined +#define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined, UString &password +#define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined, password #endif struct CParsedMethods @@ -39,6 +39,11 @@ struct CParsedMethods CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {} }; +struct CFolderEx: public CFolder +{ + unsigned UnpackCoder; +}; + struct CFolders { CNum NumPackStreams; @@ -47,10 +52,10 @@ struct CFolders CObjArray<UInt64> PackPositions; // NumPackStreams + 1 // CUInt32DefVector PackCRCs; // we don't use PackCRCs now - CUInt32DefVector FolderCRCs; // NumFolders + CUInt32DefVector FolderCRCs; // NumFolders CObjArray<CNum> NumUnpackStreamsVector; // NumFolders - CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bind coders + CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders CObjArray<CNum> FoToCoderUnpackSizes; // NumFolders + 1 CObjArray<CNum> FoStartPackStreamIndex; // NumFolders + 1 CObjArray<Byte> FoToMainUnpackSizeIndex; // NumFolders @@ -61,10 +66,15 @@ struct CFolders CParsedMethods ParsedMethods; void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const; + void ParseFolderEx(unsigned folderIndex, CFolderEx &folder) const + { + ParseFolderInfo(folderIndex, folder); + folder.UnpackCoder = FoToMainUnpackSizeIndex[folderIndex]; + } unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const { - return FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]; + return (unsigned)(FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]); } UInt64 GetFolderUnpackSize(unsigned folderIndex) const @@ -103,9 +113,9 @@ struct CDatabase: public CFolders CUInt64DefVector ATime; CUInt64DefVector MTime; CUInt64DefVector StartPos; - CRecordVector<bool> IsAnti; + CBoolVector IsAnti; /* - CRecordVector<bool> IsAux; + CBoolVector IsAux; CByteBuffer SecureBuf; CRecordVector<UInt32> SecureIDs; */ @@ -148,13 +158,14 @@ struct CDatabase: public CFolders bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); } // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); } - const void * GetName(unsigned index) const + /* + const void* GetName(unsigned index) const { if (!NameOffsets || !NamesBuf) return NULL; - return (const void *)((const Byte *)NamesBuf + NameOffsets[index] * 2); + return (void *)((const Byte *)NamesBuf + NameOffsets[index] * 2); }; - + */ void GetPath(unsigned index, UString &path) const; HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw(); }; @@ -181,8 +192,9 @@ struct CInArchiveInfo struct CDbEx: public CDatabase { CInArchiveInfo ArcInfo; - CRecordVector<CNum> FolderStartFileIndex; - CRecordVector<CNum> FileIndexToFolderIndexMap; + + CObjArray<CNum> FolderStartFileIndex; + CObjArray<CNum> FileIndexToFolderIndexMap; UInt64 HeadersSize; UInt64 PhySize; @@ -234,8 +246,8 @@ struct CDbEx: public CDatabase // SecureOffsets.Clear(); ArcInfo.Clear(); - FolderStartFileIndex.Clear(); - FileIndexToFolderIndexMap.Clear(); + FolderStartFileIndex.Free(); + FileIndexToFolderIndexMap.Free(); HeadersSize = 0; PhySize = 0; @@ -243,22 +255,22 @@ struct CDbEx: public CDatabase void FillLinks(); - UInt64 GetFolderStreamPos(unsigned folderIndex, unsigned indexInFolder) const + UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const { return ArcInfo.DataStartPosition + PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder]; } - UInt64 GetFolderFullPackSize(unsigned folderIndex) const + UInt64 GetFolderFullPackSize(CNum folderIndex) const { return PackPositions[FoStartPackStreamIndex[folderIndex + 1]] - PackPositions[FoStartPackStreamIndex[folderIndex]]; } - UInt64 GetFolderPackStreamSize(unsigned folderIndex, unsigned streamIndex) const + UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const { - unsigned i = FoStartPackStreamIndex[folderIndex] + streamIndex; + size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex; return PackPositions[i + 1] - PackPositions[i]; } @@ -327,6 +339,8 @@ class CInArchive UInt64 HeadersSize; + bool _useMixerMT; + void AddByteStream(const Byte *buffer, size_t size); void DeleteByteStream(bool needUpdatePos) @@ -340,7 +354,6 @@ class CInArchive } } -private: HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } @@ -396,7 +409,11 @@ private: _7Z_DECODER_CRYPRO_VARS_DECL ); public: - CInArchive(): _numInByteBufs(0) { } + CInArchive(bool useMixerMT): + _numInByteBufs(0), + _useMixerMT(useMixerMT) + {} + HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive void Close(); diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h index 02a86196..5e2b58f2 100644 --- a/CPP/7zip/Archive/7z/7zItem.h +++ b/CPP/7zip/Archive/7z/7zItem.h @@ -13,8 +13,6 @@ namespace NArchive { namespace N7z { -const UInt64 k_AES = 0x06F10701; - typedef UInt32 CNum; const CNum kNumMax = 0x7FFFFFFF; const CNum kNumNoIndex = 0xFFFFFFFF; @@ -23,71 +21,70 @@ struct CCoderInfo { CMethodId MethodID; CByteBuffer Props; - CNum NumInStreams; - CNum NumOutStreams; + UInt32 NumStreams; - bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } + bool IsSimpleCoder() const { return NumStreams == 1; } }; -struct CBindPair +struct CBond { - CNum InIndex; - CNum OutIndex; + UInt32 PackIndex; + UInt32 UnpackIndex; }; struct CFolder { + CLASS_NO_COPY(CFolder) +public: CObjArray2<CCoderInfo> Coders; - CObjArray2<CBindPair> BindPairs; - CObjArray2<CNum> PackStreams; + CObjArray2<CBond> Bonds; + CObjArray2<UInt32> PackStreams; - CNum GetNumOutStreams() const - { - CNum result = 0; - FOR_VECTOR(i, Coders) - result += Coders[i].NumOutStreams; - return result; - } + CFolder() {} - int FindBindPairForInStream(CNum inStreamIndex) const + bool IsDecodingSupported() const { return Coders.Size() <= 32; } + + int Find_in_PackStreams(UInt32 packStream) const { - FOR_VECTOR(i, BindPairs) - if (BindPairs[i].InIndex == inStreamIndex) + FOR_VECTOR(i, PackStreams) + if (PackStreams[i] == packStream) return i; return -1; } - int FindBindPairForOutStream(CNum outStreamIndex) const + + int FindBond_for_PackStream(UInt32 packStream) const { - FOR_VECTOR(i, BindPairs) - if (BindPairs[i].OutIndex == outStreamIndex) + FOR_VECTOR(i, Bonds) + if (Bonds[i].PackIndex == packStream) return i; return -1; } - int FindPackStreamArrayIndex(CNum inStreamIndex) const + + /* + int FindBond_for_UnpackStream(UInt32 unpackStream) const { - FOR_VECTOR(i, PackStreams) - if (PackStreams[i] == inStreamIndex) + FOR_VECTOR(i, Bonds) + if (Bonds[i].UnpackIndex == unpackStream) return i; return -1; } - int GetIndexOfMainOutStream() const + int FindOutCoder() const { - for (int i = (int)GetNumOutStreams() - 1; i >= 0; i--) - if (FindBindPairForOutStream(i) < 0) + for (int i = (int)Coders.Size() - 1; i >= 0; i--) + if (FindBond_for_UnpackStream(i) < 0) return i; - throw 1; + return -1; } + */ bool IsEncrypted() const { - for (int i = Coders.Size() - 1; i >= 0; i--) + FOR_VECTOR(i, Coders) if (Coders[i].MethodID == k_AES) return true; return false; } - - bool CheckStructure(unsigned numUnpackSizes) const; }; struct CUInt32DefVector diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp index 9ff97595..2f906588 100644 --- a/CPP/7zip/Archive/7z/7zOut.cpp +++ b/CPP/7zip/Archive/7z/7zOut.cpp @@ -199,7 +199,7 @@ void COutArchive::WriteNumber(UInt64 value) mask >>= 1; } WriteByte(firstByte); - for (;i > 0; i--) + for (; i > 0; i--) { WriteByte((Byte)value); value >>= 8; @@ -254,31 +254,33 @@ void COutArchive::WriteFolder(const CFolder &folder) { WriteNumber(folder.Coders.Size()); unsigned i; + for (i = 0; i < folder.Coders.Size(); i++) { const CCoderInfo &coder = folder.Coders[i]; { - size_t propsSize = coder.Props.Size(); - UInt64 id = coder.MethodID; - int idSize; + unsigned idSize; for (idSize = 1; idSize < sizeof(id); idSize++) if ((id >> (8 * idSize)) == 0) break; - Byte longID[15]; - for (int t = idSize - 1; t >= 0 ; t--, id >>= 8) - longID[t] = (Byte)(id & 0xFF); - Byte b; - b = (Byte)(idSize & 0xF); + idSize &= 0xF; + Byte temp[16]; + for (unsigned t = idSize; t != 0; t--, id >>= 8) + temp[t] = (Byte)(id & 0xFF); + + Byte b = (Byte)(idSize); bool isComplex = !coder.IsSimpleCoder(); b |= (isComplex ? 0x10 : 0); - b |= ((propsSize != 0) ? 0x20 : 0 ); - WriteByte(b); - WriteBytes(longID, idSize); + + size_t propsSize = coder.Props.Size(); + b |= ((propsSize != 0) ? 0x20 : 0); + temp[0] = b; + WriteBytes(temp, idSize + 1); if (isComplex) { - WriteNumber(coder.NumInStreams); - WriteNumber(coder.NumOutStreams); + WriteNumber(coder.NumStreams); + WriteNumber(1); // NumOutStreams; } if (propsSize == 0) continue; @@ -286,17 +288,17 @@ void COutArchive::WriteFolder(const CFolder &folder) WriteBytes(coder.Props, propsSize); } } - for (i = 0; i < folder.BindPairs.Size(); i++) + + for (i = 0; i < folder.Bonds.Size(); i++) { - const CBindPair &bindPair = folder.BindPairs[i]; - WriteNumber(bindPair.InIndex); - WriteNumber(bindPair.OutIndex); + const CBond &bond = folder.Bonds[i]; + WriteNumber(bond.PackIndex); + WriteNumber(bond.UnpackIndex); } + if (folder.PackStreams.Size() > 1) for (i = 0; i < folder.PackStreams.Size(); i++) - { WriteNumber(folder.PackStreams[i]); - } } void COutArchive::WriteBoolVector(const CBoolVector &boolVector) @@ -521,7 +523,10 @@ HRESULT COutArchive::EncodeStream( UInt64 unpackSize; RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS - stream, NULL, &dataSize64, folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL)) + stream, + // NULL, + &dataSize64, + folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL)) return S_OK; } diff --git a/CPP/7zip/Archive/7z/7zOut.h b/CPP/7zip/Archive/7z/7zOut.h index cead4bce..6c902668 100644 --- a/CPP/7zip/Archive/7z/7zOut.h +++ b/CPP/7zip/Archive/7z/7zOut.h @@ -29,6 +29,8 @@ public: } void WriteBytes(const void *data, size_t size) { + if (size == 0) + return; if (size > _size - _pos) throw 1; memcpy(_data + _pos, data, size); @@ -92,7 +94,7 @@ struct COutFolders CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only. CRecordVector<CNum> NumUnpackStreamsVector; - CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bind coders + CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders void OutFoldersClear() { diff --git a/CPP/7zip/Archive/7z/7zProperties.cpp b/CPP/7zip/Archive/7z/7zProperties.cpp index 5ed36947..a2c9bf31 100644 --- a/CPP/7zip/Archive/7z/7zProperties.cpp +++ b/CPP/7zip/Archive/7z/7zProperties.cpp @@ -13,7 +13,7 @@ namespace N7z { struct CPropMap { - UInt64 FilePropID; + UInt32 FilePropID; STATPROPSTG StatPROPSTG; }; @@ -35,7 +35,7 @@ static const CPropMap kPropMap[] = { NID::kMTime, { NULL, kpidMTime, VT_FILETIME } }, { NID::kATime, { NULL, kpidATime, VT_FILETIME } }, { NID::kWinAttrib, { NULL, kpidAttrib, VT_UI4 } }, - { NID::kStartPos, { NULL, kpidPosition, VT_UI4 } }, + { NID::kStartPos, { NULL, kpidPosition, VT_UI8 } }, { NID::kCRC, { NULL, kpidCRC, VT_UI4 } }, @@ -44,20 +44,12 @@ static const CPropMap kPropMap[] = #ifndef _SFX , - { 97, { NULL,kpidEncrypted, VT_BOOL } }, - { 98, { NULL,kpidMethod, VT_BSTR } }, - { 99, { NULL,kpidBlock, VT_UI4 } } + { 97, { NULL, kpidEncrypted, VT_BOOL } }, + { 98, { NULL, kpidMethod, VT_BSTR } }, + { 99, { NULL, kpidBlock, VT_UI4 } } #endif }; -static int FindPropInMap(UInt64 filePropID) -{ - for (int i = 0; i < ARRAY_SIZE(kPropMap); i++) - if (kPropMap[i].FilePropID == filePropID) - return i; - return -1; -} - static void CopyOneItem(CRecordVector<UInt64> &src, CRecordVector<UInt64> &dest, UInt32 item) { @@ -131,6 +123,7 @@ void CHandler::FillPopIDs() _fileInfoPopIDs.Add(98); _fileInfoPopIDs.Add(99); #endif + #ifdef _MULTI_PACK _fileInfoPopIDs.Add(100); _fileInfoPopIDs.Add(101); @@ -155,16 +148,27 @@ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) { - if ((int)index >= _fileInfoPopIDs.Size()) + if (index >= _fileInfoPopIDs.Size()) return E_INVALIDARG; - int indexInMap = FindPropInMap(_fileInfoPopIDs[index]); - if (indexInMap == -1) - return E_INVALIDARG; - const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG; - *propID = srcItem.propid; - *varType = srcItem.vt; - *name = 0; - return S_OK; + UInt64 id = _fileInfoPopIDs[index]; + for (unsigned i = 0; i < ARRAY_SIZE(kPropMap); i++) + { + const CPropMap &pr = kPropMap[i]; + if (pr.FilePropID == id) + { + const STATPROPSTG &st = pr.StatPROPSTG; + *propID = st.propid; + *varType = st.vt; + /* + if (st.lpwstrName) + *name = ::SysAllocString(st.lpwstrName); + else + */ + *name = NULL; + return S_OK; + } + } + return E_INVALIDARG; } }} diff --git a/CPP/7zip/Archive/7z/7zRegister.cpp b/CPP/7zip/Archive/7z/7zRegister.cpp index 37ea29d3..389b5407 100644 --- a/CPP/7zip/Archive/7z/7zRegister.cpp +++ b/CPP/7zip/Archive/7z/7zRegister.cpp @@ -9,17 +9,13 @@ namespace NArchive { namespace N7z { -IMP_CreateArcIn -IMP_CreateArcOut +static Byte k_Signature_Dec[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C}; -static CArcInfo g_ArcInfo = - { "7z", "7z", 0, 7, - 6, {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C}, +REGISTER_ARC_IO_DECREMENT_SIG( + "7z", "7z", NULL, 7, + k_Signature_Dec, 0, NArcInfoFlags::kFindSignature, - REF_CreateArc_Pair }; - -REGISTER_ARC_DEC_SIG(7z) -// REGISTER_ARC(7z) + NULL); }} diff --git a/CPP/7zip/Archive/7z/7zSpecStream.h b/CPP/7zip/Archive/7z/7zSpecStream.h index 2e26efd5..21155069 100644 --- a/CPP/7zip/Archive/7z/7zSpecStream.h +++ b/CPP/7zip/Archive/7z/7zSpecStream.h @@ -3,10 +3,10 @@ #ifndef __7Z_SPEC_STREAM_H #define __7Z_SPEC_STREAM_H -#include "../../IStream.h" -#include "../../ICoder.h" #include "../../../Common/MyCom.h" +#include "../../ICoder.h" + class CSequentialInStreamSizeCount2: public ISequentialInStream, public ICompressGetSubStreamSize, @@ -18,14 +18,14 @@ class CSequentialInStreamSizeCount2: public: void Init(ISequentialInStream *stream) { + _size = 0; + _getSubStreamSize.Release(); _stream = stream; - _getSubStreamSize = 0; _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize); - _size = 0; } UInt64 GetSize() const { return _size; } - MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) + MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp index 7875ed5b..e7c9ecc6 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp @@ -13,7 +13,6 @@ #include "../../Compress/CopyCoder.h" #include "../Common/ItemNameUtils.h" -#include "../Common/OutStreamWithCRC.h" #include "7zDecode.h" #include "7zEncode.h" @@ -25,9 +24,392 @@ namespace NArchive { namespace N7z { -#ifdef MY_CPU_X86_OR_AMD64 -#define USE_86_FILTER -#endif + +#define k_X86 k_BCJ + +struct CFilterMode +{ + UInt32 Id; + UInt32 Delta; + + CFilterMode(): Id(0), Delta(0) {} + + void SetDelta() + { + if (Id == k_IA64) + Delta = 16; + else if (Id == k_ARM || Id == k_PPC || Id == k_PPC) + Delta = 4; + else if (Id == k_ARMT) + Delta = 2; + else + Delta = 0; + } +}; + + +/* ---------- PE ---------- */ + +#define MZ_SIG 0x5A4D + +#define PE_SIG 0x00004550 +#define PE_OptHeader_Magic_32 0x10B +#define PE_OptHeader_Magic_64 0x20B +#define PE_SectHeaderSize 40 +#define PE_SECT_EXECUTE 0x20000000 + +static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode) +{ + if (size < 512 || GetUi16(buf) != MZ_SIG) + return 0; + + const Byte *p; + UInt32 peOffset, optHeaderSize, filterId; + + peOffset = GetUi32(buf + 0x3C); + if (peOffset >= 0x1000 || peOffset + 512 > size || (peOffset & 7) != 0) + return 0; + p = buf + peOffset; + if (GetUi32(p) != PE_SIG) + return 0; + p += 4; + + switch (GetUi16(p)) + { + case 0x014C: + case 0x8664: filterId = k_X86; break; + + /* + IMAGE_FILE_MACHINE_ARM 0x01C0 // ARM LE + IMAGE_FILE_MACHINE_THUMB 0x01C2 // ARM Thumb / Thumb-2 LE + IMAGE_FILE_MACHINE_ARMNT 0x01C4 // ARM Thumb-2, LE + Note: We use ARM filter for 0x01C2. (WinCE 5 - 0x01C2) files mostly contain ARM code (not Thumb/Thumb-2). + */ + + case 0x01C0: // WinCE old + case 0x01C2: filterId = k_ARM; break; // WinCE new + case 0x01C4: filterId = k_ARMT; break; // WinRT + + case 0x0200: filterId = k_IA64; break; + default: return 0; + } + + optHeaderSize = GetUi16(p + 16); + if (optHeaderSize > (1 << 10)) + return 0; + + p += 20; /* headerSize */ + + switch (GetUi16(p)) + { + case PE_OptHeader_Magic_32: + case PE_OptHeader_Magic_64: + break; + default: + return 0; + } + + filterMode->Id = filterId; + return 1; +} + + +/* ---------- ELF ---------- */ + +#define ELF_SIG 0x464C457F + +#define ELF_CLASS_32 1 +#define ELF_CLASS_64 2 + +#define ELF_DATA_2LSB 1 +#define ELF_DATA_2MSB 2 + +static UInt16 Get16(const Byte *p, Bool be) { if (be) return (UInt16)GetBe16(p); return (UInt16)GetUi16(p); } +static UInt32 Get32(const Byte *p, Bool be) { if (be) return GetBe32(p); return GetUi32(p); } +// static UInt64 Get64(const Byte *p, Bool be) { if (be) return GetBe64(p); return GetUi64(p); } + +static int Parse_ELF(const Byte *buf, size_t size, CFilterMode *filterMode) +{ + Bool /* is32, */ be; + UInt32 filterId; + + if (size < 512 || buf[6] != 1) /* ver */ + return 0; + + if (GetUi32(buf) != ELF_SIG) + return 0; + + switch (buf[4]) + { + case ELF_CLASS_32: /* is32 = True; */ break; + case ELF_CLASS_64: /* is32 = False; */ break; + default: return 0; + } + + switch (buf[5]) + { + case ELF_DATA_2LSB: be = False; break; + case ELF_DATA_2MSB: be = True; break; + default: return 0; + } + + switch (Get16(buf + 0x12, be)) + { + case 3: + case 6: + case 62: filterId = k_X86; break; + case 2: + case 18: + case 43: filterId = k_SPARC; break; + case 20: + case 21: if (!be) return 0; filterId = k_PPC; break; + case 40: if ( be) return 0; filterId = k_ARM; break; + + /* Some IA-64 ELF exacutable have size that is not aligned for 16 bytes. + So we don't use IA-64 filter for IA-64 ELF */ + // case 50: if ( be) return 0; filterId = k_IA64; break; + + default: return 0; + } + + filterMode->Id = filterId; + return 1; +} + + + +/* ---------- Mach-O ---------- */ + +#define MACH_SIG_BE_32 0xCEFAEDFE +#define MACH_SIG_BE_64 0xCFFAEDFE +#define MACH_SIG_LE_32 0xFEEDFACE +#define MACH_SIG_LE_64 0xFEEDFACF + +#define MACH_ARCH_ABI64 (1 << 24) +#define MACH_MACHINE_386 7 +#define MACH_MACHINE_ARM 12 +#define MACH_MACHINE_SPARC 14 +#define MACH_MACHINE_PPC 18 +#define MACH_MACHINE_PPC64 (MACH_ARCH_ABI64 | MACH_MACHINE_PPC) +#define MACH_MACHINE_AMD64 (MACH_ARCH_ABI64 | MACH_MACHINE_386) + +static unsigned Parse_MACH(const Byte *buf, size_t size, CFilterMode *filterMode) +{ + UInt32 filterId, numCommands, commandsSize; + + if (size < 512) + return 0; + + Bool /* mode64, */ be; + switch (GetUi32(buf)) + { + case MACH_SIG_BE_32: /* mode64 = False; */ be = True; break; + case MACH_SIG_BE_64: /* mode64 = True; */ be = True; break; + case MACH_SIG_LE_32: /* mode64 = False; */ be = False; break; + case MACH_SIG_LE_64: /* mode64 = True; */ be = False; break; + default: return 0; + } + + switch (Get32(buf + 4, be)) + { + case MACH_MACHINE_386: + case MACH_MACHINE_AMD64: filterId = k_X86; break; + case MACH_MACHINE_ARM: if ( be) return 0; filterId = k_ARM; break; + case MACH_MACHINE_SPARC: if (!be) return 0; filterId = k_SPARC; break; + case MACH_MACHINE_PPC: + case MACH_MACHINE_PPC64: if (!be) return 0; filterId = k_PPC; break; + default: return 0; + } + + numCommands = Get32(buf + 0x10, be); + commandsSize = Get32(buf + 0x14, be); + + if (commandsSize > (1 << 24) || numCommands > (1 << 18)) + return 0; + + filterMode->Id = filterId; + return 1; +} + + +/* ---------- WAV ---------- */ + +#define WAV_SUBCHUNK_fmt 0x20746D66 +#define WAV_SUBCHUNK_data 0x61746164 + +#define RIFF_SIG 0x46464952 + +static Bool Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode) +{ + UInt32 subChunkSize, pos; + if (size < 0x2C) + return False; + + if (GetUi32(buf + 0) != RIFF_SIG || + GetUi32(buf + 8) != 0x45564157 || // WAVE + GetUi32(buf + 0xC) != WAV_SUBCHUNK_fmt) + return False; + subChunkSize = GetUi32(buf + 0x10); + /* [0x14 = format] = 1 (PCM) */ + if (subChunkSize < 0x10 || subChunkSize > 0x12 || GetUi16(buf + 0x14) != 1) + return False; + + unsigned numChannels = GetUi16(buf + 0x16); + unsigned bitsPerSample = GetUi16(buf + 0x22); + + if ((bitsPerSample & 0x7) != 0 || bitsPerSample >= 256 || numChannels >= 256) + return False; + + pos = 0x14 + subChunkSize; + + const int kNumSubChunksTests = 10; + // Do we need to scan more than 3 sub-chunks? + for (int i = 0; i < kNumSubChunksTests; i++) + { + if (pos + 8 > size) + return False; + subChunkSize = GetUi32(buf + pos + 4); + if (GetUi32(buf + pos) == WAV_SUBCHUNK_data) + { + unsigned delta = numChannels * (bitsPerSample >> 3); + if (delta >= 256) + return False; + filterMode->Id = k_Delta; + filterMode->Delta = delta; + return True; + } + if (subChunkSize > (1 << 16)) + return False; + pos += subChunkSize + 8; + } + return False; +} + +static Bool ParseFile(const Byte *buf, size_t size, CFilterMode *filterMode) +{ + filterMode->Id = 0; + filterMode->Delta = 0; + + if (Parse_EXE(buf, size, filterMode)) return True; + if (Parse_ELF(buf, size, filterMode)) return True; + if (Parse_MACH(buf, size, filterMode)) return True; + return Parse_WAV(buf, size, filterMode); +} + + + + +struct CFilterMode2: public CFilterMode +{ + bool Encrypted; + unsigned GroupIndex; + + CFilterMode2(): Encrypted(false) {} + + int Compare(const CFilterMode2 &m) const + { + if (!Encrypted) + { + if (m.Encrypted) + return -1; + } + else if (!m.Encrypted) + return 1; + + if (Id < m.Id) return -1; + if (Id > m.Id) return 1; + + if (Delta < m.Delta) return -1; + if (Delta > m.Delta) return 1; + + return 0; + } + + bool operator ==(const CFilterMode2 &m) const + { + return Id == m.Id && Delta == m.Delta && Encrypted == m.Encrypted; + } +}; + +static unsigned GetGroup(CRecordVector<CFilterMode2> &filters, const CFilterMode2 &m) +{ + unsigned i; + for (i = 0; i < filters.Size(); i++) + { + const CFilterMode2 &m2 = filters[i]; + if (m == m2) + return i; + /* + if (m.Encrypted != m2.Encrypted) + { + if (!m.Encrypted) + break; + continue; + } + + if (m.Id < m2.Id) break; + if (m.Id != m2.Id) continue; + + if (m.Delta < m2.Delta) break; + if (m.Delta != m2.Delta) continue; + */ + } + // filters.Insert(i, m); + // return i; + return filters.Add(m); +} + +static inline bool Is86Filter(CMethodId m) +{ + return (m == k_BCJ || m == k_BCJ2); +} + +static inline bool IsExeFilter(CMethodId m) +{ + switch (m) + { + case k_BCJ: + case k_BCJ2: + case k_ARM: + case k_ARMT: + case k_PPC: + case k_SPARC: + case k_IA64: + return true; + } + return false; +} + +static unsigned Get_FilterGroup_for_Folder(CRecordVector<CFilterMode2> &filters, const CFolderEx &f) +{ + CFilterMode2 m; + m.Id = 0; + m.Delta = 0; + m.Encrypted = f.IsEncrypted(); + + const CCoderInfo &coder = f.Coders[f.UnpackCoder]; + + if (coder.MethodID == k_Delta) + { + if (coder.Props.Size() == 1) + { + m.Delta = (unsigned)coder.Props[0] + 1; + m.Id = k_Delta; + } + } + else if (IsExeFilter(coder.MethodID)) + { + m.Id = (UInt32)coder.MethodID; + if (m.Id == k_BCJ2) + m.Id = k_BCJ; + m.SetDelta(); + } + + return GetGroup(filters, m); +} + + + static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, UInt64 position, UInt64 size, ICompressProgressInfo *progress) @@ -44,21 +426,12 @@ static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL); } -static int GetReverseSlashPos(const UString &name) -{ - int slashPos = name.ReverseFind(L'/'); - #ifdef _WIN32 - int slash1Pos = name.ReverseFind(L'\\'); - slashPos = MyMax(slashPos, slash1Pos); - #endif - return slashPos; -} - -int CUpdateItem::GetExtensionPos() const +/* +unsigned CUpdateItem::GetExtensionPos() const { - int slashPos = GetReverseSlashPos(Name); - int dotPos = Name.ReverseFind(L'.'); - if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) + int slashPos = Name.ReverseFind_PathSepar(); + int dotPos = Name.ReverseFind_Dot(); + if (dotPos <= slashPos) return Name.Len(); return dotPos + 1; } @@ -67,6 +440,7 @@ UString CUpdateItem::GetExtension() const { return Name.Ptr(GetExtensionPos()); } +*/ #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } @@ -91,7 +465,7 @@ static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2) return CompareBuffers(c1.Props, c2.Props); } -static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2) +static int CompareBonds(const CBond &b1, const CBond &b2) { RINOZ_COMP(b1.InIndex, b2.InIndex); return MyCompare(b1.OutIndex, b2.OutIndex); @@ -105,11 +479,11 @@ static int CompareFolders(const CFolder &f1, const CFolder &f2) int i; for (i = 0; i < s1; i++) RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i])); - s1 = f1.BindPairs.Size(); - s2 = f2.BindPairs.Size(); + s1 = f1.Bonds.Size(); + s2 = f2.Bonds.Size(); RINOZ_COMP(s1, s2); for (i = 0; i < s1; i++) - RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i])); + RINOZ(CompareBonds(f1.Bonds[i], f2.Bonds[i])); return 0; } */ @@ -123,36 +497,34 @@ static int CompareFiles(const CFileItem &f1, const CFileItem &f2) struct CFolderRepack { - int FolderIndex; - int Group; + unsigned FolderIndex; CNum NumCopyFiles; }; -static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void * /* param */) +/* +static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *) { - RINOZ_COMP(p1->Group, p2->Group); int i1 = p1->FolderIndex; int i2 = p2->FolderIndex; - /* // In that version we don't want to parse folders here, so we don't compare folders // probably it must be improved in future - const CDbEx &db = *(const CDbEx *)param; - RINOZ(CompareFolders( - db.Folders[i1], - db.Folders[i2])); - */ + // const CDbEx &db = *(const CDbEx *)param; + // RINOZ(CompareFolders( + // db.Folders[i1], + // db.Folders[i2])); + return MyCompare(i1, i2); - /* - RINOZ_COMP( - db.NumUnpackStreamsVector[i1], - db.NumUnpackStreamsVector[i2]); - if (db.NumUnpackStreamsVector[i1] == 0) - return 0; - return CompareFiles( - db.Files[db.FolderStartFileIndex[i1]], - db.Files[db.FolderStartFileIndex[i2]]); - */ + + // RINOZ_COMP( + // db.NumUnpackStreamsVector[i1], + // db.NumUnpackStreamsVector[i2]); + // if (db.NumUnpackStreamsVector[i1] == 0) + // return 0; + // return CompareFiles( + // db.Files[db.FolderStartFileIndex[i1]], + // db.Files[db.FolderStartFileIndex[i2]]); } +*/ /* we sort empty files and dirs in such order: @@ -162,7 +534,7 @@ static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2 - Dir.Anti (reverse name sorted) */ -static int CompareEmptyItems(const int *p1, const int *p2, void *param) +static int CompareEmptyItems(const unsigned *p1, const unsigned *p2, void *param) { const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param; const CUpdateItem &u1 = updateItems[*p1]; @@ -211,9 +583,9 @@ static const char *g_Exts = " exe dll ocx vbx sfx sys tlb awx com obj lib out o so " " pdb pch idb ncb opt"; -static int GetExtIndex(const char *ext) +static unsigned GetExtIndex(const char *ext) { - int extIndex = 1; + unsigned extIndex = 1; const char *p = g_Exts; for (;;) { @@ -222,7 +594,7 @@ static int GetExtIndex(const char *ext) return extIndex; if (c == ' ') continue; - int pos = 0; + unsigned pos = 0; for (;;) { char c2 = ext[pos++]; @@ -248,8 +620,8 @@ struct CRefItem { const CUpdateItem *UpdateItem; UInt32 Index; - UInt32 ExtensionPos; - UInt32 NamePos; + unsigned ExtensionPos; + unsigned NamePos; unsigned ExtensionIndex; CRefItem() {}; @@ -262,10 +634,10 @@ struct CRefItem { if (sortByType) { - int slashPos = GetReverseSlashPos(ui.Name); + int slashPos = ui.Name.ReverseFind_PathSepar(); NamePos = slashPos + 1; - int dotPos = ui.Name.ReverseFind(L'.'); - if (dotPos < 0 || dotPos < slashPos) + int dotPos = ui.Name.ReverseFind_Dot(); + if (dotPos <= slashPos) ExtensionPos = ui.Name.Len(); else { @@ -396,35 +768,193 @@ static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *para struct CSolidGroup { CRecordVector<UInt32> Indices; + + CRecordVector<CFolderRepack> folderRefs; }; -static const wchar_t *g_ExeExts[] = +static const char *g_ExeExts[] = { - L"dll" - , L"exe" - , L"ocx" - , L"sfx" - , L"sys" + "dll" + , "exe" + , "ocx" + , "sfx" + , "sys" }; static bool IsExeExt(const wchar_t *ext) { - for (int i = 0; i < ARRAY_SIZE(g_ExeExts); i++) - if (MyStringCompareNoCase(ext, g_ExeExts[i]) == 0) + for (unsigned i = 0; i < ARRAY_SIZE(g_ExeExts); i++) + if (StringsAreEqualNoCase_Ascii(ext, g_ExeExts[i])) return true; return false; } +struct CAnalysis +{ + CMyComPtr<IArchiveUpdateCallbackFile> Callback; + CByteBuffer Buffer; + + bool ParseWav; + bool ParseExe; + bool ParseAll; -static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &m) + CAnalysis(): + ParseWav(true), + ParseExe(false), + ParseAll(false) + {} + + HRESULT GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode); +}; + +static const size_t kAnalysisBufSize = 1 << 14; + +HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode) +{ + filterMode.Id = 0; + filterMode.Delta = 0; + + CFilterMode filterModeTemp = filterMode; + + int slashPos = ui.Name.ReverseFind_PathSepar(); + int dotPos = ui.Name.ReverseFind_Dot(); + + // if (dotPos > slashPos) + { + bool needReadFile = ParseAll; + + bool probablyIsSameIsa = false; + + if (!needReadFile || !Callback) + { + const wchar_t *ext; + if (dotPos > slashPos) + ext = ui.Name.Ptr(dotPos + 1); + else + ext = ui.Name.RightPtr(0); + + // p7zip uses the trick to store posix attributes in high 16 bits + if (ui.Attrib & 0x8000) + { + unsigned st_mode = ui.Attrib >> 16; + // st_mode = 00111; + if ((st_mode & 00111) && (ui.Size >= 2048)) + { + #ifndef _WIN32 + probablyIsSameIsa = true; + #endif + needReadFile = true; + } + } + + if (IsExeExt(ext)) + { + needReadFile = true; + #ifdef _WIN32 + probablyIsSameIsa = true; + needReadFile = ParseExe; + #endif + } + else if (StringsAreEqualNoCase_Ascii(ext, "wav")) + { + needReadFile = ParseWav; + } + /* + else if (!needReadFile && ParseUnixExt) + { + if (StringsAreEqualNoCase_Ascii(ext, "so") + || StringsAreEqualNoCase_Ascii(ext, "")) + + needReadFile = true; + } + */ + } + + if (needReadFile && Callback) + { + if (Buffer.Size() != kAnalysisBufSize) + { + Buffer.Alloc(kAnalysisBufSize); + } + { + CMyComPtr<ISequentialInStream> stream; + HRESULT result = Callback->GetStream2(index, &stream, NUpdateNotifyOp::kAnalyze); + if (result == S_OK && stream) + { + size_t size = kAnalysisBufSize; + result = ReadStream(stream, Buffer, &size); + stream.Release(); + // RINOK(Callback->SetOperationResult2(index, NUpdate::NOperationResult::kOK)); + if (result == S_OK) + { + Bool parseRes = ParseFile(Buffer, size, &filterModeTemp); + if (parseRes && filterModeTemp.Delta == 0) + { + filterModeTemp.SetDelta(); + if (filterModeTemp.Delta != 0 && filterModeTemp.Id != k_Delta) + { + if (ui.Size % filterModeTemp.Delta != 0) + { + parseRes = false; + } + } + } + if (!parseRes) + { + filterModeTemp.Id = 0; + filterModeTemp.Delta = 0; + } + } + } + } + } + else if ((needReadFile && !Callback) || probablyIsSameIsa) + { + #ifdef MY_CPU_X86_OR_AMD64 + if (probablyIsSameIsa) + filterModeTemp.Id = k_X86; + #endif + } + } + + filterMode = filterModeTemp; + return S_OK; +} + +static inline void GetMethodFull(UInt64 methodID, UInt32 numStreams, CMethodFull &m) { m.Id = methodID; - m.NumInStreams = numInStreams; - m.NumOutStreams = 1; + m.NumStreams = numStreams; +} + +static HRESULT AddBondForFilter(CCompressionMethodMode &mode) +{ + for (unsigned c = 1; c < mode.Methods.Size(); c++) + { + if (!mode.IsThereBond_to_Coder(c)) + { + CBond2 bond; + bond.OutCoder = 0; + bond.OutStream = 0; + bond.InCoder = c; + mode.Bonds.Add(bond); + return S_OK; + } + } + return E_INVALIDARG; } -static void AddBcj2Methods(CCompressionMethodMode &mode) +static HRESULT AddFilterBond(CCompressionMethodMode &mode) { + if (!mode.Bonds.IsEmpty()) + return AddBondForFilter(mode); + return S_OK; +} + +static HRESULT AddBcj2Methods(CCompressionMethodMode &mode) +{ + // mode.Methods[0] must be k_BCJ2 method ! + CMethodFull m; GetMethodFull(k_LZMA, 1, m); @@ -433,54 +963,121 @@ static void AddBcj2Methods(CCompressionMethodMode &mode) m.AddProp32(NCoderPropID::kNumThreads, 1); m.AddProp32(NCoderPropID::kLitPosBits, 2); m.AddProp32(NCoderPropID::kLitContextBits, 0); - // m.AddPropString(NCoderPropID::kMatchFinder, L"BT2"); + // m.AddProp_Ascii(NCoderPropID::kMatchFinder, "BT2"); + + unsigned methodIndex = mode.Methods.Size(); + + if (mode.Bonds.IsEmpty()) + { + for (unsigned i = 1; i + 1 < mode.Methods.Size(); i++) + { + CBond2 bond; + bond.OutCoder = i; + bond.OutStream = 0; + bond.InCoder = i + 1; + mode.Bonds.Add(bond); + } + } mode.Methods.Add(m); mode.Methods.Add(m); - CBind bind; - bind.OutCoder = 0; - bind.InStream = 0; - bind.InCoder = 1; bind.OutStream = 0; mode.Binds.Add(bind); - bind.InCoder = 2; bind.OutStream = 1; mode.Binds.Add(bind); - bind.InCoder = 3; bind.OutStream = 2; mode.Binds.Add(bind); + RINOK(AddBondForFilter(mode)); + CBond2 bond; + bond.OutCoder = 0; + bond.InCoder = methodIndex; bond.OutStream = 1; mode.Bonds.Add(bond); + bond.InCoder = methodIndex + 1; bond.OutStream = 2; mode.Bonds.Add(bond); + return S_OK; } -static void MakeExeMethod(CCompressionMethodMode &mode, - bool useFilters, bool addFilter, bool bcj2Filter) +static HRESULT MakeExeMethod(CCompressionMethodMode &mode, + const CFilterMode &filterMode, /* bool addFilter, */ bool bcj2Filter) { - if (!mode.Binds.IsEmpty() || !useFilters || mode.Methods.Size() > 2) - return; - if (mode.Methods.Size() == 2) + if (mode.Filter_was_Inserted) { - if (mode.Methods[0].Id == k_BCJ2) - AddBcj2Methods(mode); - return; + const CMethodFull &m = mode.Methods[0]; + CMethodId id = m.Id; + if (id == k_BCJ2) + return AddBcj2Methods(mode); + if (!m.IsSimpleCoder()) + return E_NOTIMPL; + // if (Bonds.IsEmpty()) we can create bonds later + return AddFilterBond(mode); + } + + if (filterMode.Id == 0) + return S_OK; + + CMethodFull &m = mode.Methods.InsertNew(0); + + { + FOR_VECTOR(k, mode.Bonds) + { + CBond2 &bond = mode.Bonds[k]; + bond.InCoder++; + bond.OutCoder++; + } } - if (!addFilter) - return; - bcj2Filter = bcj2Filter; - #ifdef USE_86_FILTER - if (bcj2Filter) + + HRESULT res; + + if (bcj2Filter && Is86Filter(filterMode.Id)) { - CMethodFull m; GetMethodFull(k_BCJ2, 4, m); - mode.Methods.Insert(0, m); - AddBcj2Methods(mode); + res = AddBcj2Methods(mode); } else { - CMethodFull m; - GetMethodFull(k_BCJ, 1, m); - mode.Methods.Insert(0, m); - CBind bind; - bind.OutCoder = 0; - bind.InStream = 0; - bind.InCoder = 1; - bind.OutStream = 0; - mode.Binds.Add(bind); + GetMethodFull(filterMode.Id, 1, m); + if (filterMode.Id == k_Delta) + m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta); + res = AddFilterBond(mode); + + int alignBits = -1; + if (filterMode.Id == k_Delta || filterMode.Delta != 0) + { + if (filterMode.Delta == 1) alignBits = 0; + else if (filterMode.Delta == 2) alignBits = 1; + else if (filterMode.Delta == 4) alignBits = 2; + else if (filterMode.Delta == 8) alignBits = 3; + else if (filterMode.Delta == 16) alignBits = 4; + } + else + { + // alignBits = GetAlignForFilterMethod(filterMode.Id); + } + + if (res == S_OK && alignBits >= 0) + { + unsigned nextCoder = 1; + if (!mode.Bonds.IsEmpty()) + { + nextCoder = mode.Bonds.Back().InCoder; + } + if (nextCoder < mode.Methods.Size()) + { + CMethodFull &nextMethod = mode.Methods[nextCoder]; + if (nextMethod.Id == k_LZMA || nextMethod.Id == k_LZMA2) + { + if (!nextMethod.Are_Lzma_Model_Props_Defined()) + { + if (alignBits != 0) + { + if (alignBits > 2 || filterMode.Id == k_Delta) + nextMethod.AddProp32(NCoderPropID::kPosStateBits, alignBits); + unsigned lc = 0; + if (alignBits < 3) + lc = 3 - alignBits; + nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc); + nextMethod.AddProp32(NCoderPropID::kLitPosBits, alignBits); + } + } + } + } + } } - #endif + + return res; } @@ -503,133 +1100,336 @@ static void FromUpdateItemToFileItem(const CUpdateItem &ui, // file.IsAltStream = ui.IsAltStream; } -class CFolderOutStream2: - public ISequentialOutStream, +class CRepackInStreamWithSizes: + public ISequentialInStream, + public ICompressGetSubStreamSize, public CMyUnknownImp { - COutStreamWithCRC *_crcStreamSpec; - CMyComPtr<ISequentialOutStream> _crcStream; - const CDbEx *_db; + CMyComPtr<ISequentialInStream> _stream; + // UInt64 _size; const CBoolVector *_extractStatuses; - CMyComPtr<ISequentialOutStream> _outStream; UInt32 _startIndex; - unsigned _currentIndex; +public: + const CDbEx *_db; + + void Init(ISequentialInStream *stream, UInt32 startIndex, const CBoolVector *extractStatuses) + { + _startIndex = startIndex; + _extractStatuses = extractStatuses; + // _size = 0; + _stream = stream; + } + // UInt64 GetSize() const { return _size; } + + MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + + STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); +}; + +STDMETHODIMP CRepackInStreamWithSizes::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + return _stream->Read(data, size, processedSize); + /* + UInt32 realProcessedSize; + HRESULT result = _stream->Read(data, size, &realProcessedSize); + _size += realProcessedSize; + if (processedSize) + *processedSize = realProcessedSize; + return result; + */ +} + +STDMETHODIMP CRepackInStreamWithSizes::GetSubStreamSize(UInt64 subStream, UInt64 *value) +{ + *value = 0; + if (subStream >= _extractStatuses->Size()) + return S_FALSE; // E_FAIL; + unsigned index = (unsigned)subStream; + if ((*_extractStatuses)[index]) + { + const CFileItem &fi = _db->Files[_startIndex + index]; + if (fi.HasStream) + *value = fi.Size; + } + return S_OK; +} + + +class CRepackStreamBase +{ +protected: + bool _needWrite; bool _fileIsOpen; + bool _calcCrc; + UInt32 _crc; UInt64 _rem; - void OpenFile(); - void CloseFile(); - HRESULT CloseFileAndSetResult(); + const CBoolVector *_extractStatuses; + UInt32 _startIndex; + unsigned _currentIndex; + + HRESULT OpenFile(); + HRESULT CloseFile(); HRESULT ProcessEmptyFiles(); + public: - MY_UNKNOWN_IMP - - CFolderOutStream2() - { - _crcStreamSpec = new COutStreamWithCRC; - _crcStream = _crcStreamSpec; - } + const CDbEx *_db; + CMyComPtr<IArchiveUpdateCallbackFile> _opCallback; + CMyComPtr<IArchiveExtractCallbackMessage> _extractCallback; - HRESULT Init(const CDbEx *db, UInt32 startIndex, - const CBoolVector *extractStatuses, ISequentialOutStream *outStream); - void ReleaseOutStream(); + HRESULT Init(UInt32 startIndex, const CBoolVector *extractStatuses); HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; } - - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; -HRESULT CFolderOutStream2::Init(const CDbEx *db, UInt32 startIndex, - const CBoolVector *extractStatuses, ISequentialOutStream *outStream) +HRESULT CRepackStreamBase::Init(UInt32 startIndex, const CBoolVector *extractStatuses) { - _db = db; _startIndex = startIndex; _extractStatuses = extractStatuses; - _outStream = outStream; _currentIndex = 0; _fileIsOpen = false; + return ProcessEmptyFiles(); } -void CFolderOutStream2::ReleaseOutStream() +HRESULT CRepackStreamBase::OpenFile() { - _outStream.Release(); - _crcStreamSpec->ReleaseStream(); -} + UInt32 arcIndex = _startIndex + _currentIndex; + const CFileItem &fi = _db->Files[arcIndex]; + + _needWrite = (*_extractStatuses)[_currentIndex]; + if (_opCallback) + { + RINOK(_opCallback->ReportOperation( + NEventIndexType::kInArcIndex, arcIndex, + _needWrite ? + NUpdateNotifyOp::kRepack : + NUpdateNotifyOp::kSkip)); + } + + _crc = CRC_INIT_VAL; + _calcCrc = (fi.CrcDefined && !fi.IsDir); -void CFolderOutStream2::OpenFile() -{ - _crcStreamSpec->SetStream((*_extractStatuses)[_currentIndex] ? _outStream : NULL); - _crcStreamSpec->Init(true); _fileIsOpen = true; - _rem = _db->Files[_startIndex + _currentIndex].Size; + _rem = fi.Size; + return S_OK; } -void CFolderOutStream2::CloseFile() +const HRESULT k_My_HRESULT_CRC_ERROR = 0x20000002; + +HRESULT CRepackStreamBase::CloseFile() { - _crcStreamSpec->ReleaseStream(); + UInt32 arcIndex = _startIndex + _currentIndex; + const CFileItem &fi = _db->Files[arcIndex]; _fileIsOpen = false; _currentIndex++; -} + if (!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc)) + return S_OK; -HRESULT CFolderOutStream2::CloseFileAndSetResult() -{ - const CFileItem &file = _db->Files[_startIndex + _currentIndex]; - CloseFile(); - return (file.IsDir || !file.CrcDefined || file.Crc == _crcStreamSpec->GetCRC()) ? S_OK: S_FALSE; + if (_extractCallback) + { + RINOK(_extractCallback->ReportExtractResult( + NEventIndexType::kInArcIndex, arcIndex, + NExtract::NOperationResult::kCRCError)); + } + // return S_FALSE; + return k_My_HRESULT_CRC_ERROR; } -HRESULT CFolderOutStream2::ProcessEmptyFiles() +HRESULT CRepackStreamBase::ProcessEmptyFiles() { while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0) { - OpenFile(); - RINOK(CloseFileAndSetResult()); + RINOK(OpenFile()); + RINOK(CloseFile()); } return S_OK; } + + + +#ifndef _7ZIP_ST + +class CFolderOutStream2: + public CRepackStreamBase, + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + CMyComPtr<ISequentialOutStream> _stream; + + MY_UNKNOWN_IMP + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; STDMETHODIMP CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *processedSize) { - if (processedSize != NULL) + if (processedSize) *processedSize = 0; + while (size != 0) { if (_fileIsOpen) { - UInt32 cur = size < _rem ? size : (UInt32)_rem; - RINOK(_crcStream->Write(data, cur, &cur)); - if (cur == 0) - break; + UInt32 cur = (size < _rem ? size : (UInt32)_rem); + HRESULT result = S_OK; + if (_needWrite) + result = _stream->Write(data, cur, &cur); + if (_calcCrc) + _crc = CrcUpdate(_crc, data, cur); + if (processedSize) + *processedSize += cur; data = (const Byte *)data + cur; size -= cur; _rem -= cur; - if (processedSize != NULL) - *processedSize += cur; if (_rem == 0) { - RINOK(CloseFileAndSetResult()); + RINOK(CloseFile()); RINOK(ProcessEmptyFiles()); - continue; } + RINOK(result); + if (cur == 0) + break; + continue; } - else + + RINOK(ProcessEmptyFiles()); + if (_currentIndex == _extractStatuses->Size()) { - RINOK(ProcessEmptyFiles()); - if (_currentIndex == _extractStatuses->Size()) + // we don't support write cut here + return E_FAIL; + } + RINOK(OpenFile()); + } + + return S_OK; +} + +#endif + + + +static const UInt32 kTempBufSize = 1 << 16; + +class CFolderInStream2: + public CRepackStreamBase, + public ISequentialInStream, + public CMyUnknownImp +{ + Byte *_buf; +public: + CMyComPtr<ISequentialInStream> _inStream; + HRESULT Result; + + MY_UNKNOWN_IMP + + CFolderInStream2(): + Result(S_OK) + { + _buf = new Byte[kTempBufSize]; + } + + ~CFolderInStream2() + { + delete []_buf; + } + + void Init() { Result = S_OK; } + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CFolderInStream2::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + + while (size != 0) + { + if (_fileIsOpen) + { + UInt32 cur = (size < _rem ? size : (UInt32)_rem); + + void *buf; + if (_needWrite) + buf = data; + else { - // we don't support partial extracting - return E_FAIL; + buf = _buf; + if (cur > kTempBufSize) + cur = kTempBufSize; } - OpenFile(); + + HRESULT result = _inStream->Read(buf, cur, &cur); + _crc = CrcUpdate(_crc, buf, cur); + _rem -= cur; + + if (_needWrite) + { + data = (Byte *)data + cur; + size -= cur; + if (processedSize) + *processedSize += cur; + } + + if (result != S_OK) + Result = result; + + if (_rem == 0) + { + RINOK(CloseFile()); + RINOK(ProcessEmptyFiles()); + } + + RINOK(result); + + if (cur == 0) + return E_FAIL; + + continue; } + + RINOK(ProcessEmptyFiles()); + if (_currentIndex == _extractStatuses->Size()) + { + return S_OK; + } + RINOK(OpenFile()); } + return S_OK; } -class CThreadDecoder: public CVirtThread + +class CThreadDecoder + #ifndef _7ZIP_ST + : public CVirtThread + #endif { public: + CDecoder Decoder; + + CThreadDecoder(bool multiThreadMixer): + Decoder(multiThreadMixer) + { + #ifndef _7ZIP_ST + if (multiThreadMixer) + { + MtMode = false; + NumThreads = 1; + FosSpec = new CFolderOutStream2; + Fos = FosSpec; + Result = E_FAIL; + } + #endif + // UnpackSize = 0; + // send_UnpackSize = false; + } + + #ifndef _7ZIP_ST + HRESULT Result; CMyComPtr<IInStream> InStream; @@ -639,33 +1439,30 @@ public: UInt64 StartPos; const CFolders *Folders; int FolderIndex; + + // bool send_UnpackSize; + // UInt64 UnpackSize; + #ifndef _NO_CRYPTO CMyComPtr<ICryptoGetTextPassword> getTextPassword; #endif DECL_EXTERNAL_CODECS_LOC_VARS2; - CDecoder Decoder; #ifndef _7ZIP_ST bool MtMode; UInt32 NumThreads; #endif - CThreadDecoder(): - Decoder(true) - { - #ifndef _7ZIP_ST - MtMode = false; - NumThreads = 1; - #endif - FosSpec = new CFolderOutStream2; - Fos = FosSpec; - Result = E_FAIL; - } + ~CThreadDecoder() { CVirtThread::WaitThreadFinish(); } virtual void Execute(); + + #endif }; +#ifndef _7ZIP_ST + void CThreadDecoder::Execute() { try @@ -673,6 +1470,7 @@ void CThreadDecoder::Execute() #ifndef _NO_CRYPTO bool isEncrypted = false; bool passwordIsDefined = false; + UString password; #endif Result = Decoder.Decode( @@ -680,8 +1478,14 @@ void CThreadDecoder::Execute() InStream, StartPos, *Folders, FolderIndex, + + // send_UnpackSize ? &UnpackSize : NULL, + NULL, // unpackSize : FULL unpack + Fos, - NULL + NULL, // compressProgress + NULL // *inStreamMainRes + _7Z_DECODER_CRYPRO_VARS #ifndef _7ZIP_ST , MtMode, NumThreads @@ -692,21 +1496,15 @@ void CThreadDecoder::Execute() { Result = E_FAIL; } + + /* if (Result == S_OK) Result = FosSpec->CheckFinishedState(); - FosSpec->ReleaseOutStream(); + */ + FosSpec->_stream.Release(); } -bool static Is86FilteredFolder(const CFolder &f) -{ - FOR_VECTOR(i, f.Coders) - { - CMethodId m = f.Coders[i].MethodID; - if (m == k_BCJ || m == k_BCJ2) - return true; - } - return false; -} +#endif #ifndef _NO_CRYPTO @@ -728,14 +1526,8 @@ STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password) #endif -static const int kNumGroupsMax = 4; - -static bool Is86Group(int group) { return (group & 1) != 0; } -static bool IsEncryptedGroup(int group) { return (group & 2) != 0; } -static int GetGroupIndex(bool encrypted, int bcjFiltered) - { return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); } -static void GetFile(const CDatabase &inDb, int index, CFileItem &file, CFileItem2 &file2) +static void GetFile(const CDatabase &inDb, unsigned index, CFileItem &file, CFileItem2 &file2) { file = inDb.Files[index]; file2.CTimeDefined = inDb.CTime.GetItem(index, file2.CTime); @@ -767,6 +1559,12 @@ HRESULT Update( if (numSolidFiles == 0) numSolidFiles = 1; + CMyComPtr<IArchiveUpdateCallbackFile> opCallback; + updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback); + + CMyComPtr<IArchiveExtractCallbackMessage> extractCallback; + updateCallback->QueryInterface(IID_IArchiveExtractCallbackMessage, (void **)&extractCallback); + // size_t totalSecureDataSize = (size_t)secureBlocks.GetTotalSizeInBytes(); /* @@ -783,14 +1581,19 @@ HRESULT Update( } CIntArr fileIndexToUpdateIndexMap; - CRecordVector<CFolderRepack> folderRefs; UInt64 complexity = 0; UInt64 inSizeForReduce2 = 0; bool needEncryptedRepack = false; + + CRecordVector<CFilterMode2> filters; + CObjectVector<CSolidGroup> groups; + bool thereAreRepacks = false; + if (db != 0) { fileIndexToUpdateIndexMap.Alloc(db->Files.Size()); unsigned i; + for (i = 0; i < db->Files.Size(); i++) fileIndexToUpdateIndexMap[i] = -1; @@ -798,15 +1601,16 @@ HRESULT Update( { int index = updateItems[i].IndexInArchive; if (index != -1) - fileIndexToUpdateIndexMap[index] = i; + fileIndexToUpdateIndexMap[(unsigned)index] = i; } - for (i = 0; i < (int)db->NumFolders; i++) + for (i = 0; i < db->NumFolders; i++) { CNum indexInFolder = 0; CNum numCopyItems = 0; CNum numUnpackStreams = db->NumUnpackStreamsVector[i]; UInt64 repackSize = 0; + for (CNum fi = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fi++) { const CFileItem &file = db->Files[fi]; @@ -828,23 +1632,30 @@ HRESULT Update( CFolderRepack rep; rep.FolderIndex = i; rep.NumCopyFiles = numCopyItems; - CFolder f; - db->ParseFolderInfo(i, f); + CFolderEx f; + db->ParseFolderEx(i, f); + bool isEncrypted = f.IsEncrypted(); - rep.Group = GetGroupIndex(isEncrypted, Is86FilteredFolder(f)); - folderRefs.Add(rep); + + unsigned groupIndex = Get_FilterGroup_for_Folder(filters, f); + + while (groupIndex >= groups.Size()) + groups.AddNew(); + + groups[groupIndex].folderRefs.Add(rep); + if (numCopyItems == numUnpackStreams) complexity += db->GetFolderFullPackSize(i); else { + thereAreRepacks = true; complexity += repackSize; - if (repackSize > inSizeForReduce2) + if (inSizeForReduce2 < repackSize) inSizeForReduce2 = repackSize; if (isEncrypted) needEncryptedRepack = true; } } - folderRefs.Sort(CompareFolderRepacks, (void *)db); } UInt64 inSizeForReduce = 0; @@ -857,12 +1668,12 @@ HRESULT Update( complexity += ui.Size; if (numSolidFiles != 1) inSizeForReduce += ui.Size; - else if (ui.Size > inSizeForReduce) + else if (inSizeForReduce < ui.Size) inSizeForReduce = ui.Size; } } - if (inSizeForReduce2 > inSizeForReduce) + if (inSizeForReduce < inSizeForReduce2) inSizeForReduce = inSizeForReduce2; RINOK(updateCallback->SetTotal(complexity)); @@ -871,52 +1682,102 @@ HRESULT Update( CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); + #ifndef _7ZIP_ST + CStreamBinder sb; - RINOK(sb.CreateEvents()); + if (options.MultiThreadMixer) + { + RINOK(sb.CreateEvents()); + } + + #endif - CThreadDecoder threadDecoder; - if (!folderRefs.IsEmpty()) + CThreadDecoder threadDecoder(options.MultiThreadMixer); + + #ifndef _7ZIP_ST + if (options.MultiThreadMixer && thereAreRepacks) { #ifdef EXTERNAL_CODECS threadDecoder.__externalCodecs = __externalCodecs; #endif RINOK(threadDecoder.Create()); } - - CObjectVector<CSolidGroup> groups; - for (i = 0; i < kNumGroupsMax; i++) - groups.AddNew(); + #endif { + CAnalysis analysis; + if (options.AnalysisLevel == 0) + { + analysis.ParseWav = false; + analysis.ParseExe = false; + analysis.ParseAll = false; + } + else + { + analysis.Callback = opCallback; + if (options.AnalysisLevel > 0) + { + analysis.ParseWav = true; + if (options.AnalysisLevel >= 7) + { + analysis.ParseExe = true; + if (options.AnalysisLevel >= 9) + analysis.ParseAll = true; + } + } + } + // ---------- Split files to groups ---------- bool useFilters = options.UseFilters; const CCompressionMethodMode &method = *options.Method; - if (method.Methods.Size() != 1 || method.Binds.Size() != 0) + + if (useFilters) + for (i = 0; i < method.Methods.Size(); i++) + if (IsFilterMethod(method.Methods[i].Id)) + { + useFilters = false; + break; + } + + /* + if (!method.Bonds.IsEmpty()) useFilters = false; + */ + for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (!ui.NewData || !ui.HasStream()) continue; - bool filteredGroup = false; + + CFilterMode2 fm; if (useFilters) { - int dotPos = ui.Name.ReverseFind(L'.'); - if (dotPos >= 0) - filteredGroup = IsExeExt(ui.Name.Ptr(dotPos + 1)); + RINOK(analysis.GetFilterGroup(i, ui, fm)); } - groups[GetGroupIndex(method.PasswordIsDefined, filteredGroup)].Indices.Add(i); + fm.Encrypted = method.PasswordIsDefined; + + unsigned groupIndex = GetGroup(filters, fm); + while (groupIndex >= groups.Size()) + groups.AddNew(); + groups[groupIndex].Indices.Add(i); } } + #ifndef _NO_CRYPTO CCryptoGetTextPassword *getPasswordSpec = NULL; + CMyComPtr<ICryptoGetTextPassword> getTextPassword; if (needEncryptedRepack) { getPasswordSpec = new CCryptoGetTextPassword; + getTextPassword = getPasswordSpec; + + #ifndef _7ZIP_ST threadDecoder.getTextPassword = getPasswordSpec; + #endif if (options.Method->PasswordIsDefined) getPasswordSpec->Password = options.Method->Password; @@ -926,7 +1787,7 @@ HRESULT Update( return E_NOTIMPL; CMyComBSTR password; RINOK(getDecoderPassword->CryptoGetTextPassword(&password)); - if ((BSTR)password) + if (password) getPasswordSpec->Password = password; } } @@ -986,7 +1847,8 @@ HRESULT Update( { /* ---------- Write non-AUX dirs and Empty files ---------- */ - CRecordVector<int> emptyRefs; + CUIntVector emptyRefs; + for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; @@ -1003,7 +1865,9 @@ HRESULT Update( */ emptyRefs.Add(i); } + emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems); + for (i = 0; i < emptyRefs.Size(); i++) { const CUpdateItem &ui = updateItems[emptyRefs[i]]; @@ -1030,17 +1894,34 @@ HRESULT Update( } } - unsigned folderRefIndex = 0; lps->ProgressOffset = 0; - for (int groupIndex = 0; groupIndex < kNumGroupsMax; groupIndex++) { - const CSolidGroup &group = groups[groupIndex]; + // ---------- Sort Filters ---------- + + FOR_VECTOR (i, filters) + { + filters[i].GroupIndex = i; + } + filters.Sort2(); + } + + for (unsigned groupIndex = 0; groupIndex < filters.Size(); groupIndex++) + { + const CFilterMode2 &filterMode = filters[groupIndex]; CCompressionMethodMode method = *options.Method; - MakeExeMethod(method, options.UseFilters, Is86Group(groupIndex), options.MaxFilter); + HRESULT res = MakeExeMethod(method, filterMode, + #ifdef _7ZIP_ST + false + #else + options.MaxFilter && options.MultiThreadMixer + #endif + ); + + RINOK(res); - if (IsEncryptedGroup(groupIndex)) + if (filterMode.Encrypted) { if (!method.PasswordIsDefined) { @@ -1059,83 +1940,260 @@ HRESULT Update( CEncoder encoder(method); - for (; folderRefIndex < folderRefs.Size(); folderRefIndex++) + // ---------- Repack and copy old solid blocks ---------- + + const CSolidGroup &group = groups[filterMode.GroupIndex]; + + FOR_VECTOR(folderRefIndex, group.folderRefs) { - const CFolderRepack &rep = folderRefs[folderRefIndex]; - if (rep.Group != groupIndex) - break; - int folderIndex = rep.FolderIndex; + const CFolderRepack &rep = group.folderRefs[folderRefIndex]; + + unsigned folderIndex = rep.FolderIndex; - if (rep.NumCopyFiles == db->NumUnpackStreamsVector[folderIndex]) + CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; + + if (rep.NumCopyFiles == numUnpackStreams) { + if (opCallback) + { + RINOK(opCallback->ReportOperation( + NEventIndexType::kBlockIndex, (UInt32)folderIndex, + NUpdateNotifyOp::kReplicate)); + + // ---------- Copy old solid block ---------- + { + CNum indexInFolder = 0; + for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) + { + if (db->Files[fi].HasStream) + { + indexInFolder++; + RINOK(opCallback->ReportOperation( + NEventIndexType::kInArcIndex, (UInt32)fi, + NUpdateNotifyOp::kReplicate)); + } + } + } + } + UInt64 packSize = db->GetFolderFullPackSize(folderIndex); RINOK(WriteRange(inStream, archive.SeqStream, - db->GetFolderStreamPos(folderIndex, 0), packSize, progress)); + db->GetFolderStreamPos(folderIndex, 0), packSize, progress)); lps->ProgressOffset += packSize; CFolder &folder = newDatabase.Folders.AddNew(); db->ParseFolderInfo(folderIndex, folder); CNum startIndex = db->FoStartPackStreamIndex[folderIndex]; - for (unsigned j = 0; j < folder.PackStreams.Size(); j++) + FOR_VECTOR(j, folder.PackStreams) { newDatabase.PackSizes.Add(db->GetStreamPackSize(startIndex + j)); // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]); // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]); } - UInt32 indexStart = db->FoToCoderUnpackSizes[folderIndex]; - UInt32 indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1]; + size_t indexStart = db->FoToCoderUnpackSizes[folderIndex]; + size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1]; for (; indexStart < indexEnd; indexStart++) newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes[indexStart]); } else { + // ---------- Repack old solid block ---------- + CBoolVector extractStatuses; - CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; CNum indexInFolder = 0; - + + if (opCallback) + { + RINOK(opCallback->ReportOperation( + NEventIndexType::kBlockIndex, (UInt32)folderIndex, + NUpdateNotifyOp::kRepack)) + } + + /* We could reduce data size of decoded folder, if we don't need to repack + last files in folder. But the gain in speed is small in most cases. + So we unpack full folder. */ + + UInt64 sizeToEncode = 0; + + /* + UInt64 importantUnpackSize = 0; + unsigned numImportantFiles = 0; + UInt64 decodeSize = 0; + */ + for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) { bool needExtract = false; - if (db->Files[fi].HasStream) + const CFileItem &file = db->Files[fi]; + + if (file.HasStream) { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fi]; if (updateIndex >= 0 && !updateItems[updateIndex].NewData) needExtract = true; + // decodeSize += file.Size; } + extractStatuses.Add(needExtract); + if (needExtract) + { + sizeToEncode += file.Size; + /* + numImportantFiles = extractStatuses.Size(); + importantUnpackSize = decodeSize; + */ + } } + // extractStatuses.DeleteFrom(numImportantFiles); + unsigned startPackIndex = newDatabase.PackSizes.Size(); UInt64 curUnpackSize; { + CMyComPtr<ISequentialInStream> sbInStream; + CRepackStreamBase *repackBase; + CFolderInStream2 *FosSpec2 = NULL; + + CRepackInStreamWithSizes *inStreamSizeCountSpec = new CRepackInStreamWithSizes; + CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec; { - CMyComPtr<ISequentialOutStream> sbOutStream; - sb.CreateStreams(&sbInStream, &sbOutStream); - sb.ReInit(); - RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream)); - } - - threadDecoder.InStream = inStream; - threadDecoder.Folders = (const CFolders *)db; - threadDecoder.FolderIndex = folderIndex; - threadDecoder.StartPos = db->ArcInfo.DataStartPosition; // db->GetFolderStreamPos(folderIndex, 0); - - threadDecoder.Start(); + #ifndef _7ZIP_ST + if (options.MultiThreadMixer) + { + repackBase = threadDecoder.FosSpec; + CMyComPtr<ISequentialOutStream> sbOutStream; + sb.CreateStreams(&sbInStream, &sbOutStream); + sb.ReInit(); + + threadDecoder.FosSpec->_stream = sbOutStream; + + threadDecoder.InStream = inStream; + threadDecoder.StartPos = db->ArcInfo.DataStartPosition; // db->GetFolderStreamPos(folderIndex, 0); + threadDecoder.Folders = (const CFolders *)db; + threadDecoder.FolderIndex = folderIndex; + + // threadDecoder.UnpackSize = importantUnpackSize; + // threadDecoder.send_UnpackSize = true; + } + else + #endif + { + FosSpec2 = new CFolderInStream2; + FosSpec2->Init(); + sbInStream = FosSpec2; + repackBase = FosSpec2; + + #ifndef _NO_CRYPTO + bool isEncrypted = false; + bool passwordIsDefined = false; + UString password; + #endif + + CMyComPtr<ISequentialInStream> decodedStream; + HRESULT res = threadDecoder.Decoder.Decode( + EXTERNAL_CODECS_LOC_VARS + inStream, + db->ArcInfo.DataStartPosition, // db->GetFolderStreamPos(folderIndex, 0);, + *db, folderIndex, + // &importantUnpackSize, // *unpackSize + NULL, // *unpackSize : FULL unpack + + NULL, // *outStream + NULL, // *compressProgress + &decodedStream + + _7Z_DECODER_CRYPRO_VARS + #ifndef _7ZIP_ST + , false // mtMode + , 1 // numThreads + #endif + ); - RINOK(encoder.Encode( + RINOK(res); + if (!decodedStream) + return E_FAIL; + + FosSpec2->_inStream = decodedStream; + } + + repackBase->_db = db; + repackBase->_opCallback = opCallback; + repackBase->_extractCallback = extractCallback; + + UInt32 startIndex = db->FolderStartFileIndex[folderIndex]; + RINOK(repackBase->Init(startIndex, &extractStatuses)); + + inStreamSizeCountSpec->_db = db; + inStreamSizeCountSpec->Init(sbInStream, startIndex, &extractStatuses); + + #ifndef _7ZIP_ST + if (options.MultiThreadMixer) + { + threadDecoder.Start(); + } + #endif + } + + + HRESULT encodeRes = encoder.Encode( EXTERNAL_CODECS_LOC_VARS - sbInStream, NULL, &inSizeForReduce, + inStreamSizeCount, + // NULL, + &inSizeForReduce, newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curUnpackSize, - archive.SeqStream, newDatabase.PackSizes, progress)); - - threadDecoder.WaitExecuteFinish(); - } + archive.SeqStream, newDatabase.PackSizes, progress); - RINOK(threadDecoder.Result); + if (encodeRes == k_My_HRESULT_CRC_ERROR) + return E_FAIL; + + #ifndef _7ZIP_ST + if (options.MultiThreadMixer) + { + threadDecoder.WaitExecuteFinish(); + HRESULT decodeRes = threadDecoder.Result; + // if (res == k_My_HRESULT_CRC_ERROR) + if (decodeRes == S_FALSE) + { + if (extractCallback) + { + RINOK(extractCallback->ReportExtractResult( + NEventIndexType::kInArcIndex, db->FolderStartFileIndex[folderIndex], + // NEventIndexType::kBlockIndex, (UInt32)folderIndex, + NExtract::NOperationResult::kDataError)); + } + return E_FAIL; + } + RINOK(decodeRes); + if (encodeRes == S_OK) + if (sb.ProcessedSize != sizeToEncode) + encodeRes = E_FAIL; + } + else + #endif + { + if (FosSpec2->Result == S_FALSE) + { + if (extractCallback) + { + RINOK(extractCallback->ReportExtractResult( + NEventIndexType::kBlockIndex, (UInt32)folderIndex, + NExtract::NOperationResult::kDataError)); + } + return E_FAIL; + } + RINOK(FosSpec2->Result); + } + + RINOK(encodeRes); + RINOK(repackBase->CheckFinishedState()); + + if (curUnpackSize != sizeToEncode) + return E_FAIL; + } for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) lps->OutSize += newDatabase.PackSizes[startPackIndex]; @@ -1144,8 +2202,6 @@ HRESULT Update( newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles); - CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; - CNum indexInFolder = 0; for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) { @@ -1187,6 +2243,9 @@ HRESULT Update( } } + + // ---------- Compress files to new solid blocks ---------- + unsigned numFiles = group.Indices.Size(); if (numFiles == 0) continue; @@ -1222,10 +2281,11 @@ HRESULT Update( for (i = 0; i < numFiles;) { UInt64 totalSize = 0; - int numSubFiles; - UString prevExtension; - for (numSubFiles = 0; i + numSubFiles < numFiles && - numSubFiles < numSolidFiles; numSubFiles++) + unsigned numSubFiles; + + const wchar_t *prevExtension = NULL; + + for (numSubFiles = 0; i + numSubFiles < numFiles && numSubFiles < numSolidFiles; numSubFiles++) { const CUpdateItem &ui = updateItems[indices[i + numSubFiles]]; totalSize += ui.Size; @@ -1233,17 +2293,21 @@ HRESULT Update( break; if (options.SolidExtension) { - UString ext = ui.GetExtension(); + int slashPos = ui.Name.ReverseFind_PathSepar(); + int dotPos = ui.Name.ReverseFind_Dot(); + const wchar_t *ext = ui.Name.Ptr(dotPos <= slashPos ? ui.Name.Len() : dotPos + 1); if (numSubFiles == 0) prevExtension = ext; - else - if (!ext.IsEqualToNoCase(prevExtension)) - break; + else if (!StringsAreEqualNoCase(ext, prevExtension)) + break; } } + if (numSubFiles < 1) numSubFiles = 1; + RINOK(lps->SetCur()); + CFolderInStream *inStreamSpec = new CFolderInStream; CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec); inStreamSpec->Init(updateCallback, &indices[i], numSubFiles); @@ -1252,10 +2316,15 @@ HRESULT Update( UInt64 curFolderUnpackSize; RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS - solidInStream, NULL, &inSizeForReduce, + solidInStream, + // NULL, + &inSizeForReduce, newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curFolderUnpackSize, archive.SeqStream, newDatabase.PackSizes, progress)); + if (!inStreamSpec->WasFinished()) + return E_FAIL; + for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) lps->OutSize += newDatabase.PackSizes[startPackIndex]; @@ -1263,9 +2332,11 @@ HRESULT Update( // for () // newDatabase.PackCRCsDefined.Add(false); // newDatabase.PackCRCs.Add(0); - + CNum numUnpackStreams = 0; - for (int subIndex = 0; subIndex < numSubFiles; subIndex++) + UInt64 skippedSize = 0; + + for (unsigned subIndex = 0; subIndex < numSubFiles; subIndex++) { const CUpdateItem &ui = updateItems[indices[i + subIndex]]; CFileItem file; @@ -1290,12 +2361,15 @@ HRESULT Update( */ if (!inStreamSpec->Processed[subIndex]) { + skippedSize += ui.Size; continue; - // file.Name += L".locked"; + // file.Name.AddAscii(".locked"); } file.Crc = inStreamSpec->CRCs[subIndex]; file.Size = inStreamSpec->Sizes[subIndex]; + + // if (file.Size >= 0) // test purposes if (file.Size != 0) { file.CrcDefined = true; @@ -1307,6 +2381,7 @@ HRESULT Update( file.CrcDefined = false; file.HasStream = false; } + /* file.Parent = ui.ParentFolderIndex; if (ui.TreeFolderIndex >= 0) @@ -1316,20 +2391,23 @@ HRESULT Update( */ newDatabase.AddFile(file, file2, name); } + // numUnpackStreams = 0 is very bad case for locked files // v3.13 doesn't understand it. newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams); i += numSubFiles; + + if (skippedSize != 0 && complexity >= skippedSize) + { + complexity -= skippedSize; + RINOK(updateCallback->SetTotal(complexity)); + } } } - if (folderRefIndex != folderRefs.Size()) - return E_FAIL; - RINOK(lps->SetCur()); /* - folderRefs.ClearAndFree(); fileIndexToUpdateIndexMap.ClearAndFree(); groups.ClearAndFree(); */ @@ -1350,13 +2428,18 @@ HRESULT Update( { const CByteBuffer &buf = secureBlocks.Bufs[secureBlocks.Sorted[i]]; size_t size = buf.GetCapacity(); - memcpy(newDatabase.SecureBuf + pos, buf, size); + if (size != 0) + memcpy(newDatabase.SecureBuf + pos, buf, size); newDatabase.SecureSizes.Add((UInt32)size); pos += size; } } */ newDatabase.ReserveDown(); + + if (opCallback) + RINOK(opCallback->ReportOperation(NEventIndexType::kNoIndex, (UInt32)(Int32)-1, NUpdateNotifyOp::kHeader)); + return S_OK; } diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h index d00276e0..3986af43 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.h +++ b/CPP/7zip/Archive/7z/7zUpdate.h @@ -65,6 +65,7 @@ struct CUpdateItem // int SecureIndex; // 0 means (no_security) bool HasStream() const { return !IsDir && !IsAnti && Size != 0; } + // bool HasStream() const { return !IsDir && !IsAnti /* && Size != 0 */; } // for test purposes CUpdateItem(): // ParentSortIndex(-1), @@ -77,18 +78,19 @@ struct CUpdateItem MTimeDefined(false) // SecureIndex(0) {} - void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); }; + void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); } - int GetExtensionPos() const; - UString GetExtension() const; + // unsigned GetExtensionPos() const; + // UString GetExtension() const; }; struct CUpdateOptions { const CCompressionMethodMode *Method; const CCompressionMethodMode *HeaderMethod; - bool UseFilters; - bool MaxFilter; + bool UseFilters; // use additional filters for some files + bool MaxFilter; // use BCJ2 filter instead of BCJ + int AnalysisLevel; CHeaderOptions HeaderOptions; @@ -96,7 +98,20 @@ struct CUpdateOptions UInt64 NumSolidBytes; bool SolidExtension; bool RemoveSfxBlock; - bool VolumeMode; + bool MultiThreadMixer; + + CUpdateOptions(): + Method(NULL), + HeaderMethod(NULL), + UseFilters(false), + MaxFilter(false), + AnalysisLevel(-1), + NumSolidFiles((UInt64)(Int64)(-1)), + NumSolidBytes((UInt64)(Int64)(-1)), + SolidExtension(false), + RemoveSfxBlock(false), + MultiThreadMixer(true) + {} }; HRESULT Update( diff --git a/CPP/7zip/Archive/ApmHandler.cpp b/CPP/7zip/Archive/ApmHandler.cpp index 96656733..d5a111e9 100644 --- a/CPP/7zip/Archive/ApmHandler.cpp +++ b/CPP/7zip/Archive/ApmHandler.cpp @@ -376,15 +376,13 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -IMP_CreateArcIn +static const Byte k_Signature[] = { kSig0, kSig1 }; -static CArcInfo g_ArcInfo = - { "APM", "apm", 0, 0xD4, - 2, { kSig0, kSig1 }, +REGISTER_ARC_I( + "APM", "apm", 0, 0xD4, + k_Signature, 0, 0, - CreateArc, NULL, IsArc_Apm }; - -REGISTER_ARC(Apm) + IsArc_Apm) }} diff --git a/CPP/7zip/Archive/ArHandler.cpp b/CPP/7zip/Archive/ArHandler.cpp index b7dcda85..1eec728f 100644 --- a/CPP/7zip/Archive/ArHandler.cpp +++ b/CPP/7zip/Archive/ArHandler.cpp @@ -77,7 +77,7 @@ enum EType kType_Lib }; -static const char *k_TypeExtionsions[] = +static const char * const k_TypeExtionsions[] = { "ar" , "a" @@ -121,7 +121,7 @@ struct CItem int SameNameIndex; CItem(): TextFileIndex(-1), SameNameIndex(-1) {} - UInt64 GetDataPos() const { return HeaderPos + HeaderSize; }; + UInt64 GetDataPos() const { return HeaderPos + HeaderSize; } }; class CInArchive @@ -257,10 +257,9 @@ HRESULT CInArchive::GetNextItem(CItem &item, bool &filled) { SubType = kSubType_BSD; size_t processedSize = longNameLen; - char *s = item.Name.GetBuffer(longNameLen); + char *s = item.Name.GetBuf(longNameLen); HRESULT res = ReadStream(m_Stream, s, &processedSize); - s[longNameLen] = 0; - item.Name.ReleaseBuffer(); + item.Name.ReleaseBuf_CalcLen(longNameLen); RINOK(res); if (processedSize != longNameLen) return S_OK; @@ -683,11 +682,11 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { case kpidPhySize: prop = _phySize; break; case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break; - case kpidExtension: prop = k_TypeExtionsions[_type]; break; + case kpidExtension: prop = k_TypeExtionsions[(unsigned)_type]; break; case kpidShortComment: case kpidSubType: { - AString s = k_TypeExtionsions[_type]; + AString s = k_TypeExtionsions[(unsigned)_type]; if (_subType == kSubType_BSD) s += ":BSD"; prop = s; @@ -724,7 +723,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidSize: case kpidPackSize: if (item.TextFileIndex >= 0) - prop = (UInt64)_libFiles[item.TextFileIndex].Len(); + prop = (UInt64)_libFiles[(unsigned)item.TextFileIndex].Len(); else prop = item.Size; break; @@ -766,7 +765,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, const CItem &item = _items[allFilesMode ? i : indices[i]]; totalSize += (item.TextFileIndex >= 0) ? - (UInt64)_libFiles[item.TextFileIndex].Len() : item.Size; + (UInt64)_libFiles[(unsigned)item.TextFileIndex].Len() : item.Size; } extractCallback->SetTotal(totalSize); @@ -795,7 +794,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, const CItem &item = _items[index]; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); currentTotalSize += (item.TextFileIndex >= 0) ? - (UInt64)_libFiles[item.TextFileIndex].Len() : item.Size; + (UInt64)_libFiles[(unsigned)item.TextFileIndex].Len() : item.Size; if (!testMode && !realOutStream) continue; @@ -808,7 +807,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, bool isOk = true; if (item.TextFileIndex >= 0) { - const AString &f = _libFiles[item.TextFileIndex]; + const AString &f = _libFiles[(unsigned)item.TextFileIndex]; if (realOutStream) RINOK(WriteStream(realOutStream, f, f.Len())); } @@ -834,8 +833,8 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) const CItem &item = _items[index]; if (item.TextFileIndex >= 0) { - const AString &f = _libFiles[item.TextFileIndex]; - Create_BufInStream_WithNewBuf((const void *)(const char *)f, f.Len(), stream); + const AString &f = _libFiles[(unsigned)item.TextFileIndex]; + Create_BufInStream_WithNewBuffer((const void *)(const char *)f, f.Len(), stream); return S_OK; } else @@ -843,15 +842,11 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -IMP_CreateArcIn - -static CArcInfo g_ArcInfo = - { "Ar", "ar a deb lib", 0, 0xEC, - kSignatureLen, SIGNATURE, +REGISTER_ARC_I( + "Ar", "ar a deb lib", 0, 0xEC, + kSignature, 0, 0, - CreateArc }; - -REGISTER_ARC(Ar) + NULL) }} diff --git a/CPP/7zip/Archive/Archive.def b/CPP/7zip/Archive/Archive.def index 55b530b2..145516d7 100644 --- a/CPP/7zip/Archive/Archive.def +++ b/CPP/7zip/Archive/Archive.def @@ -1,6 +1,12 @@ EXPORTS CreateObject PRIVATE + GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE - CreateObject PRIVATE + GetIsArc PRIVATE + + SetCodecs PRIVATE + + SetLargePageMode PRIVATE + SetCaseSensitive PRIVATE diff --git a/CPP/7zip/Archive/Archive2.def b/CPP/7zip/Archive/Archive2.def index 66feb41d..c7582742 100644 --- a/CPP/7zip/Archive/Archive2.def +++ b/CPP/7zip/Archive/Archive2.def @@ -1,11 +1,19 @@ EXPORTS CreateObject PRIVATE + GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE + GetIsArc PRIVATE + GetNumberOfMethods PRIVATE GetMethodProperty PRIVATE + CreateDecoder PRIVATE + CreateEncoder PRIVATE + GetHashers PRIVATE + + SetCodecs PRIVATE + SetLargePageMode PRIVATE SetCaseSensitive PRIVATE - GetIsArc PRIVATE
\ No newline at end of file diff --git a/CPP/7zip/Archive/ArchiveExports.cpp b/CPP/7zip/Archive/ArchiveExports.cpp index 0a520413..28e9946d 100644 --- a/CPP/7zip/Archive/ArchiveExports.cpp +++ b/CPP/7zip/Archive/ArchiveExports.cpp @@ -22,17 +22,19 @@ void RegisterArc(const CArcInfo *arcInfo) throw() const char *p = arcInfo->Name; if (p[0] == '7' && p[1] == 'z' && p[2] == 0) g_DefaultArcIndex = g_NumArcs; - g_Arcs[g_NumArcs] = arcInfo; - g_NumArcs++; + g_Arcs[g_NumArcs++] = arcInfo; } } DEFINE_GUID(CLSID_CArchiveHandler, -0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); + k_7zip_GUID_Data1, + k_7zip_GUID_Data2, + k_7zip_GUID_Data3_Common, + 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); #define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5]) -static inline HRESULT SetPropString(const char *s, unsigned size, PROPVARIANT *value) +static inline HRESULT SetPropStrFromBin(const char *s, unsigned size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; @@ -41,18 +43,18 @@ static inline HRESULT SetPropString(const char *s, unsigned size, PROPVARIANT *v static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { - return SetPropString((const char *)&guid, sizeof(GUID), value); + return SetPropStrFromBin((const char *)&guid, sizeof(guid), value); } -int FindFormatCalssId(const GUID *clsID) +int FindFormatCalssId(const GUID *clsid) { - GUID cls = *clsID; + GUID cls = *clsid; CLS_ARC_ID_ITEM(cls) = 0; if (cls != CLSID_CArchiveHandler) return -1; - Byte id = CLS_ARC_ID_ITEM(*clsID); + Byte id = CLS_ARC_ID_ITEM(*clsid); for (unsigned i = 0; i < g_NumArcs; i++) - if (g_Arcs[i]->ClassId == id) + if (g_Arcs[i]->Id == id) return (int)i; return -1; } @@ -101,7 +103,7 @@ STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value case NArchive::NHandlerPropID::kClassID: { GUID clsId = CLSID_CArchiveHandler; - CLS_ARC_ID_ITEM(clsId) = arc.ClassId; + CLS_ARC_ID_ITEM(clsId) = arc.Id; return SetPropGUID(clsId, value); } case NArchive::NHandlerPropID::kExtension: if (arc.Ext) prop = arc.Ext; break; @@ -115,12 +117,12 @@ STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value // case NArchive::NHandlerPropID::kVersion: prop = (UInt32)MY_VER_MIX; break; case NArchive::NHandlerPropID::kSignature: - if (!arc.IsMultiSignature()) - return SetPropString((const char *)arc.Signature, arc.SignatureSize, value); + if (arc.SignatureSize != 0 && !arc.IsMultiSignature()) + return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value); break; case NArchive::NHandlerPropID::kMultiSignature: - if (arc.IsMultiSignature()) - return SetPropString((const char *)arc.Signature, arc.SignatureSize, value); + if (arc.SignatureSize != 0 && arc.IsMultiSignature()) + return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value); break; } prop.Detach(value); diff --git a/CPP/7zip/Archive/ArjHandler.cpp b/CPP/7zip/Archive/ArjHandler.cpp index 737b8fc9..90819753 100644 --- a/CPP/7zip/Archive/ArjHandler.cpp +++ b/CPP/7zip/Archive/ArjHandler.cpp @@ -17,13 +17,180 @@ #include "../Common/StreamObjects.h" #include "../Common/StreamUtils.h" -#include "../Compress/ArjDecoder1.h" -#include "../Compress/ArjDecoder2.h" #include "../Compress/CopyCoder.h" +#include "../Compress/LzhDecoder.h" #include "Common/ItemNameUtils.h" #include "Common/OutStreamWithCRC.h" +namespace NCompress { +namespace NArj { +namespace NDecoder { + +static const unsigned kMatchMinLen = 3; + +static const UInt32 kWindowSize = 1 << 15; // must be >= (1 << 14) + +class CCoder: + public ICompressCoder, + public CMyUnknownImp +{ + CLzOutWindow _outWindow; + NBitm::CDecoder<CInBuffer> _inBitStream; + + class CCoderReleaser + { + CCoder *_coder; + public: + CCoderReleaser(CCoder *coder): _coder(coder) {} + void Disable() { _coder = NULL; } + ~CCoderReleaser() { if (_coder) _coder->_outWindow.Flush(); } + }; + friend class CCoderReleaser; + + HRESULT CodeReal(UInt64 outSize, ICompressProgressInfo *progress); +public: + MY_UNKNOWN_IMP + + bool FinishMode; + CCoder(): FinishMode(false) {} + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + UInt64 GetInputProcessedSize() const { return _inBitStream.GetProcessedSize(); } +}; + +HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress) +{ + const UInt32 kStep = 1 << 20; + UInt64 next = 0; + if (rem > kStep && progress) + next = rem - kStep; + + while (rem != 0) + { + if (rem <= next) + { + if (_inBitStream.ExtraBitsWereRead()) + return S_FALSE; + + UInt64 packSize = _inBitStream.GetProcessedSize(); + UInt64 pos = _outWindow.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&packSize, &pos)); + next = 0; + if (rem > kStep) + next = rem - kStep; + } + + UInt32 len; + + { + const unsigned kNumBits = 7 + 7; + UInt32 val = _inBitStream.GetValue(kNumBits); + + if ((val & (1 << (kNumBits - 1))) == 0) + { + _outWindow.PutByte((Byte)(val >> 5)); + _inBitStream.MovePos(1 + 8); + rem--; + continue; + } + + UInt32 mask = 1 << (kNumBits - 2); + unsigned w; + + for (w = 1; w < 7; w++, mask >>= 1) + if ((val & mask) == 0) + break; + + unsigned readBits = (w != 7 ? 1 : 0); + readBits += w + w; + len = (1 << w) - 1 + kMatchMinLen - 1 + + (((val >> (kNumBits - readBits)) & ((1 << w) - 1))); + _inBitStream.MovePos(readBits); + } + + { + const unsigned kNumBits = 4 + 13; + UInt32 val = _inBitStream.GetValue(kNumBits); + + unsigned readBits = 1; + unsigned w; + + if ((val & ((UInt32)1 << 16)) == 0) w = 9; + else if ((val & ((UInt32)1 << 15)) == 0) w = 10; + else if ((val & ((UInt32)1 << 14)) == 0) w = 11; + else if ((val & ((UInt32)1 << 13)) == 0) w = 12; + else { w = 13; readBits = 0; } + + readBits += w + w - 9; + + UInt32 dist = ((UInt32)1 << w) - (1 << 9) + + (((val >> (kNumBits - readBits)) & ((1 << w) - 1))); + _inBitStream.MovePos(readBits); + + if (len > rem) + len = (UInt32)rem; + + if (!_outWindow.CopyBlock(dist, len)) + return S_FALSE; + rem -= len; + } + } + + if (FinishMode) + { + if (_inBitStream.ReadAlignBits() != 0) + return S_FALSE; + } + + if (_inBitStream.ExtraBitsWereRead()) + return S_FALSE; + + return S_OK; +} + + + +STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + try + { + if (!outSize) + return E_INVALIDARG; + + if (!_outWindow.Create(kWindowSize)) + return E_OUTOFMEMORY; + if (!_inBitStream.Create(1 << 17)) + return E_OUTOFMEMORY; + + _outWindow.SetStream(outStream); + _outWindow.Init(false); + _inBitStream.SetStream(inStream); + _inBitStream.Init(); + + CCoderReleaser coderReleaser(this); + HRESULT res; + { + res = CodeReal(*outSize, progress); + if (res != S_OK) + return res; + } + + coderReleaser.Disable(); + return _outWindow.Flush(); + } + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(const CLzOutWindowException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +}}} + + + + using namespace NWindows; #define Get16(p) GetUi16(p) @@ -95,7 +262,7 @@ namespace NHostOS }; } -static const char *kHostOS[] = +static const char * const kHostOS[] = { "MSDOS" , "PRIMOS" @@ -164,10 +331,10 @@ API_FUNC_static_IsArc IsArc_Arj(const Byte *p, size_t size) static HRESULT ReadString(const Byte *p, unsigned &size, AString &res) { - for (unsigned i = 0; i < size;) + unsigned num = size; + for (unsigned i = 0; i < num;) { - char c = (char)p[i++]; - if (c == 0) + if (p[i++] == 0) { size = i; res = (const char *)p; @@ -656,15 +823,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { const CItem &item = _items[allFilesMode ? i : indices[i]]; totalUnpacked += item.Size; - totalPacked += item.PackSize; + // totalPacked += item.PackSize; } extractCallback->SetTotal(totalUnpacked); totalUnpacked = totalPacked = 0; UInt64 curUnpacked, curPacked; - CMyComPtr<ICompressCoder> arj1Decoder; - CMyComPtr<ICompressCoder> arj2Decoder; + NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = NULL; + CMyComPtr<ICompressCoder> lzhDecoder; + + NCompress::NArj::NDecoder::CCoder *arjDecoderSpec = NULL; + CMyComPtr<ICompressCoder> arjDecoder; + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; @@ -741,22 +912,37 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, case NCompressionMethod::kCompressed1b: case NCompressionMethod::kCompressed1c: { - if (!arj1Decoder) - arj1Decoder = new NCompress::NArj::NDecoder1::CCoder; - result = arj1Decoder->Code(inStream, outStream, NULL, &curUnpacked, progress); + if (!lzhDecoder) + { + lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder; + lzhDecoder = lzhDecoderSpec; + } + lzhDecoderSpec->FinishMode = true; + const UInt32 kHistorySize = 26624; + lzhDecoderSpec->SetDictSize(kHistorySize); + result = lzhDecoder->Code(inStream, outStream, NULL, &curUnpacked, progress); + if (result == S_OK && lzhDecoderSpec->GetInputProcessedSize() != item.PackSize) + result = S_FALSE; break; } case NCompressionMethod::kCompressed2: { - if (!arj2Decoder) - arj2Decoder = new NCompress::NArj::NDecoder2::CCoder; - result = arj2Decoder->Code(inStream, outStream, NULL, &curUnpacked, progress); + if (!arjDecoder) + { + arjDecoderSpec = new NCompress::NArj::NDecoder::CCoder; + arjDecoder = arjDecoderSpec; + } + arjDecoderSpec->FinishMode = true; + result = arjDecoder->Code(inStream, outStream, NULL, &curUnpacked, progress); + if (result == S_OK && arjDecoderSpec->GetInputProcessedSize() != item.PackSize) + result = S_FALSE; break; } default: opRes = NExtract::NOperationResult::kUnsupportedMethod; } } + if (opRes == NExtract::NOperationResult::kOK) { if (result == S_FALSE) @@ -769,23 +955,23 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, NExtract::NOperationResult::kCRCError; } } + outStream.Release(); RINOK(extractCallback->SetOperationResult(opRes)); } } + return S_OK; COM_TRY_END } -IMP_CreateArcIn +static const Byte k_Signature[] = { kSig0, kSig1 }; -static CArcInfo g_ArcInfo = - { "Arj", "arj", 0, 4, - 2, { kSig0, kSig1 }, +REGISTER_ARC_I( + "Arj", "arj", 0, 4, + k_Signature, 0, 0, - CreateArc, NULL, IsArc_Arj }; - -REGISTER_ARC(Arj) + IsArc_Arj) }} diff --git a/CPP/7zip/Archive/Bz2Handler.cpp b/CPP/7zip/Archive/Bz2Handler.cpp index a49e8293..d1d5f727 100644 --- a/CPP/7zip/Archive/Bz2Handler.cpp +++ b/CPP/7zip/Archive/Bz2Handler.cpp @@ -56,7 +56,7 @@ public: INTERFACE_IInArchive(;) INTERFACE_IOutArchive(;) STDMETHOD(OpenSeq)(ISequentialInStream *stream); - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); + STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); CHandler() { } }; @@ -367,6 +367,8 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { + COM_TRY_BEGIN + if (numItems != 1) return E_INVALIDARG; @@ -381,13 +383,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop)); - if (prop.vt == VT_BOOL) - { - if (prop.boolVal != VARIANT_FALSE) + if (prop.vt != VT_EMPTY) + if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE) return E_INVALIDARG; - } - else if (prop.vt != VT_EMPTY) - return E_INVALIDARG; } } @@ -403,28 +401,43 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt } return UpdateArchive(size, outStream, _props, updateCallback); } + if (indexInArchive != 0) return E_INVALIDARG; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(updateCallback, true); + + CMyComPtr<IArchiveUpdateCallbackFile> opCallback; + updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback); + if (opCallback) + { + RINOK(opCallback->ReportOperation( + NEventIndexType::kInArcIndex, 0, + NUpdateNotifyOp::kReplicate)) + } + if (_stream) RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); - return NCompress::CopyStream(_stream, outStream, NULL); + + return NCompress::CopyStream(_stream, outStream, progress); + + COM_TRY_END } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) +STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) { return _props.SetProperties(names, values, numProps); } -IMP_CreateArcIn -IMP_CreateArcOut +static const Byte k_Signature[] = { 'B', 'Z', 'h' }; -static CArcInfo g_ArcInfo = - { "bzip2", "bz2 bzip2 tbz2 tbz", "* * .tar .tar", 2, - 3, { 'B', 'Z', 'h' }, +REGISTER_ARC_IO( + "bzip2", "bz2 bzip2 tbz2 tbz", "* * .tar .tar", 2, + k_Signature, 0, NArcInfoFlags::kKeepName, - REF_CreateArc_Pair, IsArc_BZip2 }; - -REGISTER_ARC(BZip2) + IsArc_BZip2) }} diff --git a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp index cebec610..625276f3 100644 --- a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp +++ b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp @@ -75,11 +75,14 @@ HRESULT CCabBlockInStream::PreRead(ISequentialInStream *stream, UInt32 &packSize STDMETHODIMP CCabBlockInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { - UInt32 rem = _size - _pos; - if (size > rem) - size = rem; - memcpy(data, _buf + _pos, size); - _pos += size; + if (size != 0) + { + UInt32 rem = _size - _pos; + if (size > rem) + size = rem; + memcpy(data, _buf + _pos, size); + _pos += size; + } if (processedSize) *processedSize = size; return S_OK; diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp index 22bc93a0..4235ec34 100644 --- a/CPP/7zip/Archive/Cab/CabHandler.cpp +++ b/CPP/7zip/Archive/Cab/CabHandler.cpp @@ -71,7 +71,7 @@ static const Byte kArcProps[] = IMP_IInArchive_Props IMP_IInArchive_ArcProps -static const char *kMethods[] = +static const char * const kMethods[] = { "None" , "MSZip" @@ -124,17 +124,19 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) } } } + AString s; + for (unsigned i = 0; i < kNumMethodsMax; i++) { if ((mask & (1 << i)) == 0) continue; - if (!s.IsEmpty()) - s += ' '; + s.Add_Space_if_NotEmpty(); char temp[kMethodNameBufSize]; SetMethodName(temp, i, params[i == NHeader::NMethod::kQuantum ? 0 : 1]); s += temp; } + prop = s; break; } @@ -466,8 +468,8 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, return result; if (!_errorMessage.IsEmpty()) - _errorMessage += L"\n"; - _errorMessage += L"Can't open volume: "; + _errorMessage.Add_LF(); + _errorMessage.AddAscii("Can't open volume: "); _errorMessage += fullName; if (prevChecked) @@ -528,7 +530,7 @@ private: Byte *TempBuf; UInt32 TempBufSize; - int NumIdenticalFiles; + unsigned NumIdenticalFiles; bool TempBufMode; UInt32 m_BufStartFolderOffset; @@ -619,8 +621,9 @@ HRESULT CFolderOutStream::OpenFile() { const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex]; const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; - int numExtractItems = 0; + unsigned numExtractItems = 0; unsigned curIndex; + for (curIndex = m_CurrentIndex; curIndex < m_ExtractStatuses->Size(); curIndex++) { const CMvItem &mvItem2 = m_Database->Items[m_StartIndex + curIndex]; @@ -632,10 +635,12 @@ HRESULT CFolderOutStream::OpenFile() if (!m_TestMode && (*m_ExtractStatuses)[curIndex]) numExtractItems++; } + NumIdenticalFiles = (curIndex - m_CurrentIndex); if (NumIdenticalFiles == 0) NumIdenticalFiles = 1; TempBufMode = false; + if (numExtractItems > 1) { if (!TempBuf || item.Size > TempBufSize) @@ -699,7 +704,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe { COM_TRY_BEGIN UInt32 realProcessed = 0; - if (processedSize != NULL) + if (processedSize) *processedSize = 0; while (size != 0) { @@ -707,7 +712,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe { UInt32 numBytesToWrite = MyMin(m_RemainFileSize, size); HRESULT res = S_OK; - if (numBytesToWrite > 0) + if (numBytesToWrite != 0) { if (!isOK) m_IsOk = false; @@ -721,7 +726,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe memcpy(TempBuf + (m_PosInFolder - m_BufStartFolderOffset), data, numBytesToWrite); } realProcessed += numBytesToWrite; - if (processedSize != NULL) + if (processedSize) *processedSize = realProcessed; data = (const void *)((const Byte *)data + numBytesToWrite); size -= numBytesToWrite; @@ -773,7 +778,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe { UInt32 numBytesToWrite = MyMin(fileOffset - (UInt32)m_PosInFolder, size); realProcessed += numBytesToWrite; - if (processedSize != NULL) + if (processedSize) *processedSize = realProcessed; data = (const void *)((const Byte *)data + numBytesToWrite); size -= numBytesToWrite; @@ -799,24 +804,24 @@ STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *proc HRESULT CFolderOutStream::FlushCorrupted() { - const UInt32 kBufferSize = (1 << 10); - Byte buffer[kBufferSize]; - for (int i = 0; i < kBufferSize; i++) - buffer[i] = 0; + const unsigned kBufSize = (1 << 10); + Byte buf[kBufSize]; + for (unsigned i = 0; i < kBufSize; i++) + buf[i] = 0; for (;;) { UInt64 remain = GetRemain(); if (remain == 0) return S_OK; - UInt32 size = (UInt32)MyMin(remain, (UInt64)kBufferSize); + UInt32 size = (remain < kBufSize ? (UInt32)remain : (UInt32)kBufSize); UInt32 processedSizeLocal = 0; - RINOK(Write2(buffer, size, &processedSizeLocal, false)); + RINOK(Write2(buf, size, &processedSizeLocal, false)); } } HRESULT CFolderOutStream::Unsupported() { - while(m_CurrentIndex < m_ExtractStatuses->Size()) + while (m_CurrentIndex < m_ExtractStatuses->Size()) { HRESULT result = OpenFile(); if (result != S_FALSE && result != S_OK) @@ -844,9 +849,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UInt32 i; int lastFolder = -2; UInt64 lastFolderSize = 0; - for(i = 0; i < numItems; i++) + + for (i = 0; i < numItems; i++) { - int index = allFilesMode ? i : indices[i]; + unsigned index = allFilesMode ? i : indices[i]; const CMvItem &mvItem = m_Database.Items[index]; const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; if (item.IsDir()) @@ -857,6 +863,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, lastFolder = folderIndex; lastFolderSize = item.GetEndOffset(); } + totalUnPacked += lastFolderSize; extractCallback->SetTotal(totalUnPacked); @@ -887,9 +894,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, return E_OUTOFMEMORY; CRecordVector<bool> extractStatuses; - for(i = 0; i < numItems;) + + for (i = 0; i < numItems;) { - int index = allFilesMode ? i : indices[i]; + unsigned index = allFilesMode ? i : indices[i]; const CMvItem &mvItem = m_Database.Items[index]; const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex]; @@ -909,7 +917,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); continue; } + int folderIndex = m_Database.GetFolderIndex(&mvItem); + if (folderIndex < 0) { // If we need previous archive @@ -923,17 +933,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError)); continue; } - int startIndex2 = m_Database.FolderStartFileIndex[folderIndex]; - int startIndex = startIndex2; + + unsigned startIndex2 = m_Database.FolderStartFileIndex[folderIndex]; + unsigned startIndex = startIndex2; extractStatuses.Clear(); for (; startIndex < index; startIndex++) extractStatuses.Add(false); extractStatuses.Add(true); startIndex++; UInt64 curUnpack = item.GetEndOffset(); + for (; i < numItems; i++) { - int indexNext = allFilesMode ? i : indices[i]; + unsigned indexNext = allFilesMode ? i : indices[i]; const CMvItem &mvItem = m_Database.Items[indexNext]; const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; if (item.IsDir()) @@ -963,6 +975,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, cabBlockInStreamSpec->MsZip = false; HRESULT res = S_OK; + switch (folder.GetMethod()) { case NHeader::NMethod::kNone: @@ -1009,7 +1022,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, int locFolderIndex = item.GetFolderIndex(db.Folders.Size()); bool keepHistory = false; bool keepInputBuffer = false; - for (UInt32 f = 0; cabFolderOutStream->GetRemain() != 0;) + + for (UInt32 bl = 0; cabFolderOutStream->GetRemain() != 0;) { if (volIndex >= m_Database.Volumes.Size()) { @@ -1019,19 +1033,32 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, const CDatabaseEx &db = m_Database.Volumes[volIndex]; const CFolder &folder = db.Folders[locFolderIndex]; - if (f == 0) + + if (bl == 0) { cabBlockInStreamSpec->ReservedSize = db.ArcInfo.GetDataBlockReserveSize(); RINOK(db.Stream->Seek(db.StartPosition + folder.DataStart, STREAM_SEEK_SET, NULL)); } - if (f == folder.NumDataBlocks) + + if (bl == folder.NumDataBlocks) { - volIndex++; - locFolderIndex = 0; - f = 0; - continue; + /* + CFolder::NumDataBlocks (CFFOLDER::cCFData in CAB specification) is 16-bit. + But there are some big CAB archives from MS that contain more + than (0xFFFF) CFDATA blocks in folder. + Old cab extracting software can show error (or ask next volume) + but cab extracting library in new Windows ignores this error. + 15.00 : We also try to ignore such error, if archive is not multi-volume. + */ + if (m_Database.Volumes.Size() > 1) + { + volIndex++; + locFolderIndex = 0; + bl = 0; + continue; + } } - f++; + bl++; if (!keepInputBuffer) cabBlockInStreamSpec->InitForNewBlock(); @@ -1059,7 +1086,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, unpackRemain = kBlockSizeMax; if (unpackRemain > unpackSize) unpackRemain = unpackSize; - + switch (folder.GetMethod()) { case NHeader::NMethod::kNone: @@ -1092,14 +1119,17 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, res = quantumDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL); break; } + if (res != S_OK) { if (res != S_FALSE) RINOK(res); break; } + keepHistory = true; } + if (res == S_OK) { RINOK(cabFolderOutStream->WriteEmptyFiles()); @@ -1111,6 +1141,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } totalUnPacked += curUnpack; } + return S_OK; COM_TRY_END } diff --git a/CPP/7zip/Archive/Cab/CabHeader.cpp b/CPP/7zip/Archive/Cab/CabHeader.cpp index 0cba1b0b..370a2f1e 100644 --- a/CPP/7zip/Archive/Cab/CabHeader.cpp +++ b/CPP/7zip/Archive/Cab/CabHeader.cpp @@ -8,8 +8,8 @@ namespace NArchive { namespace NCab { namespace NHeader { -Byte kMarker[kMarkerSize] = {'M', 'S', 'C', 'F', 0, 0, 0, 0 }; +const Byte kMarker[kMarkerSize] = {'M', 'S', 'C', 'F', 0, 0, 0, 0 }; -// struct CSignatureInitializer { CSignatureInitializer() { kMarker[0]--; }; } g_SignatureInitializer; +// struct CSignatureInitializer { CSignatureInitializer() { kMarker[0]--; } } g_SignatureInitializer; }}} diff --git a/CPP/7zip/Archive/Cab/CabHeader.h b/CPP/7zip/Archive/Cab/CabHeader.h index 9ec0760a..2f2bd109 100644 --- a/CPP/7zip/Archive/Cab/CabHeader.h +++ b/CPP/7zip/Archive/Cab/CabHeader.h @@ -1,4 +1,4 @@ -// Archive/Cab/Header.h +// Archive/CabHeader.h #ifndef __ARCHIVE_CAB_HEADER_H #define __ARCHIVE_CAB_HEADER_H @@ -10,7 +10,7 @@ namespace NCab { namespace NHeader { const unsigned kMarkerSize = 8; -extern Byte kMarker[kMarkerSize]; +extern const Byte kMarker[kMarkerSize]; namespace NArcFlags { diff --git a/CPP/7zip/Archive/Cab/CabIn.cpp b/CPP/7zip/Archive/Cab/CabIn.cpp index c499f05f..a72e05f7 100644 --- a/CPP/7zip/Archive/Cab/CabIn.cpp +++ b/CPP/7zip/Archive/Cab/CabIn.cpp @@ -40,8 +40,7 @@ void CInArchive::ReadName(AString &s) throw CUnexpectedEndException(); if (b == 0) { - memcpy(s.GetBuffer((unsigned)i), _tempBuf, i); - s.ReleaseBuffer((unsigned)i); + s.SetFrom((const char *)(const Byte *)_tempBuf, (unsigned)i); return; } if (_tempBuf.Size() == i) diff --git a/CPP/7zip/Archive/Cab/CabIn.h b/CPP/7zip/Archive/Cab/CabIn.h index 4fdab77b..baeeb7b2 100644 --- a/CPP/7zip/Archive/Cab/CabIn.h +++ b/CPP/7zip/Archive/Cab/CabIn.h @@ -17,6 +17,12 @@ struct COtherArc { AString FileName; AString DiskName; + + void Clear() + { + FileName.Empty(); + DiskName.Empty(); + } }; struct CArchInfo @@ -43,7 +49,9 @@ struct CArchInfo CArchInfo() { - Clear(); + PerCabinet_AreaSize = 0; + PerFolder_AreaSize = 0; + PerDataBlock_AreaSize = 0; } void Clear() @@ -51,6 +59,9 @@ struct CArchInfo PerCabinet_AreaSize = 0; PerFolder_AreaSize = 0; PerDataBlock_AreaSize = 0; + + PrevArc.Clear(); + NextArc.Clear(); } }; diff --git a/CPP/7zip/Archive/Cab/CabItem.h b/CPP/7zip/Archive/Cab/CabItem.h index eda62bda..9b513202 100644 --- a/CPP/7zip/Archive/Cab/CabItem.h +++ b/CPP/7zip/Archive/Cab/CabItem.h @@ -51,7 +51,7 @@ struct CItem FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext; } - int GetFolderIndex(int numFolders) const + int GetFolderIndex(unsigned numFolders) const { if (ContinuedFromPrev()) return 0; diff --git a/CPP/7zip/Archive/Cab/CabRegister.cpp b/CPP/7zip/Archive/Cab/CabRegister.cpp index acad4c4a..0b5cc93a 100644 --- a/CPP/7zip/Archive/Cab/CabRegister.cpp +++ b/CPP/7zip/Archive/Cab/CabRegister.cpp @@ -9,15 +9,11 @@ namespace NArchive { namespace NCab { -IMP_CreateArcIn - -static CArcInfo g_ArcInfo = - { "Cab", "cab", 0, 8, - 8, { 'M', 'S', 'C', 'F', 0, 0, 0, 0 }, +REGISTER_ARC_I( + "Cab", "cab", 0, 8, + NHeader::kMarker, 0, NArcInfoFlags::kFindSignature, - CreateArc }; - -REGISTER_ARC(Cab) + NULL) }} diff --git a/CPP/7zip/Archive/Chm/ChmHandler.cpp b/CPP/7zip/Archive/Chm/ChmHandler.cpp index c67ded28..3035ef9e 100644 --- a/CPP/7zip/Archive/Chm/ChmHandler.cpp +++ b/CPP/7zip/Archive/Chm/ChmHandler.cpp @@ -123,15 +123,16 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidPath: { UString us; - if (ConvertUTF8ToUnicode(item.Name, us)) + // if ( + ConvertUTF8ToUnicode(item.Name, us); { if (!m_Database.LowLevel) { - if (us.Len() > 1) - if (us[0] == L'/') - us.Delete(0); + if (us.Len() > 1 && us[0] == L'/') + us.Delete(0); } - prop = NItemName::GetOSName2(us); + NItemName::ConvertToOSName2(us); + prop = us; } break; } @@ -141,7 +142,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { if (!item.IsDir()) if (item.Section == 0) - prop = L"Copy"; + prop = "Copy"; else if (item.Section < m_Database.Sections.Size()) prop = m_Database.Sections[(int)item.Section].GetMethodName(); break; @@ -734,30 +735,30 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) namespace NChm { -IMP_CreateArcIn_2(CHandler(false)) +static const Byte k_Signature[] = { 'I', 'T', 'S', 'F', 3, 0, 0, 0, 0x60, 0, 0, 0 }; -static CArcInfo g_ArcInfo = - { "Chm", "chm chi chq chw", 0, 0xE9, - 12, { 'I', 'T', 'S', 'F', 3, 0, 0, 0, 0x60, 0, 0, 0 }, +REGISTER_ARC_I_CLS( + CHandler(false), + "Chm", "chm chi chq chw", 0, 0xE9, + k_Signature, 0, 0, - CreateArc }; + NULL) -REGISTER_ARC(Chm) } namespace NHxs { -IMP_CreateArcIn_2(CHandler(true)) +static const Byte k_Signature[] = { 'I', 'T', 'O', 'L', 'I', 'T', 'L', 'S', 1, 0, 0, 0, 0x28, 0, 0, 0 }; -static CArcInfo g_ArcInfo = - { "Hxs", "hxs hxi hxr hxq hxw lit", 0, 0xCE, - 16, { 'I', 'T', 'O', 'L', 'I', 'T', 'L', 'S', 1, 0, 0, 0, 0x28, 0, 0, 0 }, +REGISTER_ARC_I_CLS( + CHandler(true), + "Hxs", "hxs hxi hxr hxq hxw lit", 0, 0xCE, + k_Signature, 0, NArcInfoFlags::kFindSignature, - CreateArc }; + NULL) -REGISTER_ARC(Hxs) } }} diff --git a/CPP/7zip/Archive/Chm/ChmIn.cpp b/CPP/7zip/Archive/Chm/ChmIn.cpp index 9b0bb199..e8da227d 100644 --- a/CPP/7zip/Archive/Chm/ChmIn.cpp +++ b/CPP/7zip/Archive/Chm/ChmIn.cpp @@ -107,10 +107,10 @@ UString CMethodInfo::GetName() const UString s; if (IsLzx()) { - s = L"LZX:"; - wchar_t temp[16]; + s.SetFromAscii("LZX:"); + char temp[16]; ConvertUInt32ToString(LzxInfo.GetNumDictBits(), temp); - s += temp; + s.AddAscii(temp); } else { @@ -147,12 +147,12 @@ UString CSectionInfo::GetMethodName() const UString temp; if (ConvertUTF8ToUnicode(Name, temp)) s += temp; - s += L": "; + s.AddAscii(": "); } FOR_VECTOR (i, Methods) { if (i != 0) - s += L' '; + s.Add_Space(); s += Methods[i].GetName(); } return s; @@ -584,9 +584,9 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database) AString s; ConvertUnicodeToUTF8(name, s); Byte b = ReadByte(); - s += ' '; + s.Add_Space(); PrintByte(b, s); - s += ' '; + s.Add_Space(); UInt64 len = ReadEncInt(); // then number of items ? // then length ? @@ -641,7 +641,10 @@ static const char *kTransformList = "List"; static AString GetSectionPrefix(const AString &name) { - return AString(kStorage) + name + AString("/"); + AString s = kStorage; + s += name; + s += '/'; + return s; } #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } @@ -721,8 +724,8 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database) ReadUString(nameLen, name); if (ReadUInt16() != 0) return S_FALSE; - if (!ConvertUnicodeToUTF8(name, section.Name)) - return S_FALSE; + ConvertUnicodeToUTF8(name, section.Name); + // if (!ConvertUnicodeToUTF8(name, section.Name)) return S_FALSE; database.Sections.Add(section); } } diff --git a/CPP/7zip/Archive/Chm/ChmIn.h b/CPP/7zip/Archive/Chm/ChmIn.h index 70764ab9..c4ce83ed 100644 --- a/CPP/7zip/Archive/Chm/ChmIn.h +++ b/CPP/7zip/Archive/Chm/ChmIn.h @@ -120,10 +120,10 @@ struct CLzxInfo return 0; } - UInt64 GetFolderSize() const { return ResetTable.BlockSize * ResetInterval; }; - UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); }; - UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); }; - UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex * ResetInterval; }; + UInt64 GetFolderSize() const { return ResetTable.BlockSize * ResetInterval; } + UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); } + UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); } + UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex * ResetInterval; } bool GetOffsetOfFolder(UInt64 folderIndex, UInt64 &offset) const { UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex); diff --git a/CPP/7zip/Archive/ComHandler.cpp b/CPP/7zip/Archive/ComHandler.cpp index fc686b94..9cfd40cc 100644 --- a/CPP/7zip/Archive/ComHandler.cpp +++ b/CPP/7zip/Archive/ComHandler.cpp @@ -27,8 +27,7 @@ namespace NArchive { namespace NCom { #define SIGNATURE { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 } -static const UInt32 kSignatureSize = 8; -static const Byte kSignature[kSignatureSize] = SIGNATURE; +static const Byte kSignature[] = SIGNATURE; enum EType { @@ -40,7 +39,7 @@ enum EType k_Type_Xls, }; -static const char *kExtensions[] = +static const char * const kExtensions[] = { "compound" , "msi" @@ -240,8 +239,8 @@ HRESULT CDatabase::AddNode(int parent, UInt32 did) return S_OK; } -static const char kCharOpenBracket = '['; -static const char kCharCloseBracket = ']'; +static const wchar_t kCharOpenBracket = L'['; +static const wchar_t kCharCloseBracket = L']'; static UString CompoundNameToFileName(const UString &s) { @@ -263,23 +262,25 @@ static UString CompoundNameToFileName(const UString &s) return res; } -static char g_MsiChars[] = +static const char k_Msi_Chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._"; -static const wchar_t *kMsi_ID = L""; // L"{msi}"; +// static const char *k_Msi_ID = ""; // "{msi}"; +static const wchar_t k_Msi_SpecChar = L'!'; + +static const unsigned k_Msi_NumBits = 6; +static const unsigned k_Msi_NumChars = 1 << k_Msi_NumBits; +static const unsigned k_Msi_CharMask = k_Msi_NumChars - 1; +static const unsigned k_Msi_StartUnicodeChar = 0x3800; +static const unsigned k_Msi_UnicodeRange = k_Msi_NumChars * (k_Msi_NumChars + 1); -static const unsigned kMsiNumBits = 6; -static const UInt32 kMsiNumChars = 1 << kMsiNumBits; -static const UInt32 kMsiCharMask = kMsiNumChars - 1; -static const UInt32 kMsiStartUnicodeChar = 0x3800; -static const UInt32 kMsiUnicodeRange = kMsiNumChars * (kMsiNumChars + 1); static bool IsMsiName(const Byte *p) { UInt32 c = Get16(p); return - c >= kMsiStartUnicodeChar && - c <= kMsiStartUnicodeChar + kMsiUnicodeRange; + c >= k_Msi_StartUnicodeChar && + c <= k_Msi_StartUnicodeChar + k_Msi_UnicodeRange; } static bool AreEqualNames(const Byte *rawName, const char *asciiName) @@ -296,30 +297,32 @@ static bool AreEqualNames(const Byte *rawName, const char *asciiName) return false; } -static bool CompoundMsiNameToFileName(const UString &name, UString &resultName) +static bool CompoundMsiNameToFileName(const UString &name, UString &res) { - resultName.Empty(); + res.Empty(); for (unsigned i = 0; i < name.Len(); i++) { wchar_t c = name[i]; - if (c < kMsiStartUnicodeChar || c > kMsiStartUnicodeChar + kMsiUnicodeRange) + if (c < k_Msi_StartUnicodeChar || c > k_Msi_StartUnicodeChar + k_Msi_UnicodeRange) return false; + /* if (i == 0) - resultName += kMsi_ID; - c -= kMsiStartUnicodeChar; + res += k_Msi_ID; + */ + c -= k_Msi_StartUnicodeChar; - UInt32 c0 = c & kMsiCharMask; - UInt32 c1 = c >> kMsiNumBits; + unsigned c0 = (unsigned)c & k_Msi_CharMask; + unsigned c1 = (unsigned)c >> k_Msi_NumBits; - if (c1 <= kMsiNumChars) + if (c1 <= k_Msi_NumChars) { - resultName += (wchar_t)g_MsiChars[c0]; - if (c1 == kMsiNumChars) + res += (wchar_t)(Byte)k_Msi_Chars[c0]; + if (c1 == k_Msi_NumChars) break; - resultName += (wchar_t)g_MsiChars[c1]; + res += (wchar_t)(Byte)k_Msi_Chars[c1]; } else - resultName += L'!'; + res += k_Msi_SpecChar; } return true; } @@ -328,6 +331,7 @@ static UString ConvertName(const Byte *p, bool &isMsi) { isMsi = false; UString s; + for (unsigned i = 0; i < kNameSizeMax; i += 2) { wchar_t c = Get16(p + i); @@ -335,6 +339,7 @@ static UString ConvertName(const Byte *p, bool &isMsi) break; s += c; } + UString msiName; if (CompoundMsiNameToFileName(s, msiName)) { @@ -416,7 +421,7 @@ HRESULT CDatabase::Open(IInStream *inStream) Byte p[kHeaderSize]; PhySize = kHeaderSize; RINOK(ReadStream_FALSE(inStream, p, kHeaderSize)); - if (memcmp(p, kSignature, kSignatureSize) != 0) + if (memcmp(p, kSignature, ARRAY_SIZE(kSignature)) != 0) return S_FALSE; if (Get16(p + 0x1A) > 4) // majorVer return S_FALSE; @@ -573,11 +578,14 @@ HRESULT CDatabase::Open(IInStream *inStream) continue; bool isMsiName; UString msiName = ConvertName(item.Name, isMsiName); - if (isMsiName && msiName.Len() >= 4 && - MyStringCompareNoCase(msiName.RightPtr(4), L".cab") == 0) + if (isMsiName) { - numCabs++; - MainSubfile = i; + if (msiName.Len() >= 4 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(4), ".cab") + || msiName.Len() >= 3 && msiName[0] != k_Msi_SpecChar && StringsAreEqualNoCase_Ascii(msiName.RightPtr(3), "exe")) + { + numCabs++; + MainSubfile = i; + } } } if (numCabs > 1) @@ -663,7 +671,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) NWindows::NCOM::CPropVariant prop; switch (propID) { - case kpidExtension: prop = kExtensions[_db.Type]; break; + case kpidExtension: prop = kExtensions[(unsigned)_db.Type]; break; case kpidPhySize: prop = _db.PhySize; break; case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break; case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break; @@ -861,15 +869,11 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -IMP_CreateArcIn - -static CArcInfo g_ArcInfo = - { "Compound", "msi msp doc xls ppt", 0, 0xE5, - kSignatureSize, SIGNATURE, +REGISTER_ARC_I( + "Compound", "msi msp doc xls ppt", 0, 0xE5, + kSignature, 0, 0, - CreateArc }; - -REGISTER_ARC(Com) + NULL) }} diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp index 13019d1f..41b5805c 100644 --- a/CPP/7zip/Archive/Common/CoderMixer2.cpp +++ b/CPP/7zip/Archive/Common/CoderMixer2.cpp @@ -4,116 +4,1041 @@ #include "CoderMixer2.h" -namespace NCoderMixer { +#ifdef USE_MIXER_ST -CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo): - _srcBindInfo(srcBindInfo) +STDMETHODIMP CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize) { - srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams); + 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; +} + - UInt32 j; - _srcInToDestOutMap.ClearAndSetSize(NumSrcInStreams); - DestOutToSrcInMap.ClearAndSetSize(NumSrcInStreams); +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; +} - for (j = 0; j < NumSrcInStreams; j++) +STDMETHODIMP COutStreamCalcSize::OutStreamFinish() +{ + HRESULT result = S_OK; + if (_stream) { - _srcInToDestOutMap[j] = 0; - DestOutToSrcInMap[j] = 0; + CMyComPtr<IOutStreamFinish> outStreamFinish; + _stream.QueryInterface(IID_IOutStreamFinish, &outStreamFinish); + if (outStreamFinish) + result = outStreamFinish->OutStreamFinish(); } + return result; +} - _srcOutToDestInMap.ClearAndSetSize(_numSrcOutStreams); - _destInToSrcOutMap.ClearAndSetSize(_numSrcOutStreams); +#endif - for (j = 0; j < _numSrcOutStreams; j++) + + + +namespace NCoderMixer2 { + +static void BoolVector_Fill_False(CBoolVector &v, unsigned size) +{ + v.ClearAndSetSize(size); + bool *p = &v[0]; + for (unsigned i = 0; i < size; i++) + p[i] = false; +} + +class CBondsChecks +{ + CBoolVector _coderUsed; + + bool Init(); + bool CheckCoder(unsigned coderIndex); +public: + const CBindInfo *BindInfo; + + bool Check(); +}; + +bool CBondsChecks::CheckCoder(unsigned coderIndex) +{ + const CCoderStreamsInfo &coder = BindInfo->Coders[coderIndex]; + + if (coderIndex >= _coderUsed.Size() || _coderUsed[coderIndex]) + return false; + _coderUsed[coderIndex] = true; + + UInt32 start = BindInfo->Coder_to_Stream[coderIndex]; + + for (unsigned i = 0; i < coder.NumStreams; i++) { - _srcOutToDestInMap[j] = 0; - _destInToSrcOutMap[j] = 0; + UInt32 ind = start + i; + + if (BindInfo->IsStream_in_PackStreams(ind)) + continue; + + int bond = BindInfo->FindBond_for_PackStream(ind); + if (bond < 0) + return false; + if (!CheckCoder(BindInfo->Bonds[bond].UnpackIndex)) + return false; } + + return true; +} + +bool CBondsChecks::Check() +{ + BoolVector_Fill_False(_coderUsed, BindInfo->Coders.Size()); + + if (!CheckCoder(BindInfo->UnpackCoder)) + return false; + + FOR_VECTOR(i, _coderUsed) + if (!_coderUsed[i]) + return false; + + return true; +} + +void CBindInfo::ClearMaps() +{ + Coder_to_Stream.Clear(); + Stream_to_Coder.Clear(); +} - UInt32 destInOffset = 0; - UInt32 destOutOffset = 0; - UInt32 srcInOffset = NumSrcInStreams; - UInt32 srcOutOffset = _numSrcOutStreams; +bool CBindInfo::CalcMapsAndCheck() +{ + ClearMaps(); + + UInt32 numStreams = 0; + + if (Coders.Size() == 0) + return false; + if (Coders.Size() - 1 != Bonds.Size()) + return false; - for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--) + FOR_VECTOR(i, Coders) { - const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i]; + Coder_to_Stream.Add(numStreams); + + const CCoderStreamsInfo &c = Coders[i]; + + for (unsigned j = 0; j < c.NumStreams; j++) + Stream_to_Coder.Add(i); + + numStreams += c.NumStreams; + } + + if (numStreams != GetNum_Bonds_and_PackStreams()) + return false; + + CBondsChecks bc; + bc.BindInfo = this; + return bc.Check(); +} + + +void CCoder::SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes) +{ + if (unpackSize) + { + UnpackSize = *unpackSize; + UnpackSizePointer = &UnpackSize; + } + else + { + UnpackSize = 0; + UnpackSizePointer = NULL; + } + + PackSizes.ClearAndSetSize((unsigned)NumStreams); + PackSizePointers.ClearAndSetSize((unsigned)NumStreams); + + for (unsigned i = 0; i < NumStreams; i++) + { + if (packSizes && packSizes[i]) + { + PackSizes[i] = *(packSizes[i]); + PackSizePointers[i] = &PackSizes[i]; + } + else + { + PackSizes[i] = 0; + PackSizePointers[i] = NULL; + } + } +} + +bool CMixer::Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex) +{ + if (coderIndex == _bi.UnpackCoder) + return true; + + int bond = _bi.FindBond_for_UnpackStream(coderIndex); + if (bond < 0) + throw 20150213; + + /* + UInt32 coderIndex, coderStreamIndex; + _bi.GetCoder_for_Stream(_bi.Bonds[bond].PackIndex, coderIndex, coderStreamIndex); + */ + UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[bond].PackIndex]; + + if (!IsFilter_Vector[nextCoder]) + return false; + + return Is_UnpackSize_Correct_for_Coder(nextCoder); +} + +bool CMixer::Is_PackSize_Correct_for_Stream(UInt32 streamIndex) +{ + if (_bi.IsStream_in_PackStreams(streamIndex)) + return true; + + int bond = _bi.FindBond_for_PackStream(streamIndex); + if (bond < 0) + throw 20150213; + + UInt32 nextCoder = _bi.Bonds[bond].UnpackIndex; + + if (!IsFilter_Vector[nextCoder]) + return false; + + return Is_PackSize_Correct_for_Coder(nextCoder); +} + +bool CMixer::Is_PackSize_Correct_for_Coder(UInt32 coderIndex) +{ + UInt32 startIndex = _bi.Coder_to_Stream[coderIndex]; + UInt32 numStreams = _bi.Coders[coderIndex].NumStreams; + for (UInt32 i = 0; i < numStreams; i++) + if (!Is_PackSize_Correct_for_Stream(startIndex + i)) + return false; + return true; +} + +bool CMixer::IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex) +{ + if (IsExternal_Vector[coderIndex]) + return true; + UInt32 startIndex = _bi.Coder_to_Stream[coderIndex]; + UInt32 numStreams = _bi.Coders[coderIndex].NumStreams; + for (UInt32 i = 0; i < numStreams; i++) + { + UInt32 si = startIndex + i; + if (_bi.IsStream_in_PackStreams(si)) + continue; + + int bond = _bi.FindBond_for_PackStream(si); + if (bond < 0) + throw 20150213; + + if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[bond].UnpackIndex)) + return true; + } + return false; +} + + + + +#ifdef USE_MIXER_ST + +CMixerST::CMixerST(bool encodeMode): + CMixer(encodeMode) + {} + +CMixerST::~CMixerST() {} + +void CMixerST::AddCoder(const CCreatedCoder &cod) +{ + IsFilter_Vector.Add(cod.IsFilter); + IsExternal_Vector.Add(cod.IsExternal); + // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()]; + CCoderST &c2 = _coders.AddNew(); + c2.NumStreams = cod.NumStreams; + c2.Coder = cod.Coder; + c2.Coder2 = cod.Coder2; - srcInOffset -= srcCoderInfo.NumInStreams; - srcOutOffset -= srcCoderInfo.NumOutStreams; + /* + if (isFilter) + { + c2.CanRead = true; + c2.CanWrite = true; + } + else + */ + { + IUnknown *unk = (cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.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; - UInt32 j; - for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++) + 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[(unsigned)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[(unsigned)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::FinishStream(UInt32 streamIndex) +{ + { + int index = -1; + if (!EncodeMode) { - UInt32 index = srcInOffset + j; - _srcInToDestOutMap[index] = destOutOffset; - DestOutToSrcInMap[destOutOffset] = index; + if (_bi.UnpackCoder == streamIndex) + index = 0; } - for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++) + 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<IOutStreamFinish> finish; + coder.QueryInterface(IID_IOutStreamFinish, (void **)&finish); + HRESULT res = S_OK; + if (finish) + { + res = finish->OutStreamFinish(); + } + return GetError(res, FinishCoder(coderIndex)); +} + + +HRESULT CMixerST::FinishCoder(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, FinishStream(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; + } + + if (useFirst) + ci = firstAllowed; + else if (firstNonFilter >= 0) + ci = firstNonFilter; + + 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]; + + if (EncodeMode) + { + CMyComPtr<ICompressInitEncoder> initEncoder; + coder.QueryInterface(IID_ICompressInitEncoder, (void **)&initEncoder); + if (initEncoder) + RINOK(initEncoder->InitEncoder()); + } + else + { + 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, FinishCoder(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) { - UInt32 index = srcOutOffset + j; - _srcOutToDestInMap[index] = destInOffset; - _destInToSrcOutMap[destInOffset] = index; + RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer)); } } + + *inStreamRes = seqInStream.Detach(); + return S_OK; } -void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo) + +UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const { - destBindInfo.Coders.ClearAndReserve(_srcBindInfo.Coders.Size()); - destBindInfo.BindPairs.ClearAndReserve(_srcBindInfo.BindPairs.Size()); - destBindInfo.InStreams.ClearAndReserve(_srcBindInfo.OutStreams.Size()); - destBindInfo.OutStreams.ClearAndReserve(_srcBindInfo.InStreams.Size()); + const CStBinderStream &bs = _binderStreams[bondIndex]; + if (bs.InStreamSpec) + return bs.InStreamSpec->GetSize(); + return bs.OutStreamSpec->GetSize(); +} + +#endif + + + + + + +#ifdef USE_MIXER_MT + + +void CCoderMT::Execute() +{ + try + { + Code(NULL); + } + catch(...) + { + Result = E_FAIL; + } +} + +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 = _srcBindInfo.Coders.Size(); i != 0;) + + 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]; + */ + + CReleaser releaser(*this); + + 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); +} + +HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo) +{ + CMixer::SetBindInfo(bindInfo); + + _streamBinders.Clear(); + FOR_VECTOR (i, _bi.Bonds) { - i--; - const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i]; - CCoderStreamsInfo destCoderInfo; - destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams; - destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams; - destBindInfo.Coders.AddInReserved(destCoderInfo); + RINOK(_streamBinders.AddNew().CreateEvents()); } - for (i = _srcBindInfo.BindPairs.Size(); i != 0;) + return S_OK; +} + +void CMixerMT::AddCoder(const CCreatedCoder &cod) +{ + IsFilter_Vector.Add(cod.IsFilter); + IsExternal_Vector.Add(cod.IsExternal); + // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()]; + CCoderMT &c2 = _coders.AddNew(); + c2.NumStreams = cod.NumStreams; + c2.Coder = cod.Coder; + c2.Coder2 = cod.Coder2; + c2.EncodeMode = EncodeMode; +} + +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 (;;) { - i--; - const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i]; - CBindPair destBindPair; - destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex]; - destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex]; - destBindInfo.BindPairs.AddInReserved(destBindPair); + 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; } - for (i = 0; i < _srcBindInfo.InStreams.Size(); i++) - destBindInfo.OutStreams.AddInReserved(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]); - for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++) - destBindInfo.InStreams.AddInReserved(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]); + + MainCoderIndex = ci; } -void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, - CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) +HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams) { - sizes.ClearAndSetSize(numItems); - sizePointers.ClearAndSetSize(numItems); - for(UInt32 i = 0; i < numItems; i++) + 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++) { - if (!srcSizes || !srcSizes[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) { - sizes[i] = 0; - sizePointers[i] = NULL; + 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) { - sizes[i] = *(srcSizes[i]); - sizePointers[i] = &sizes[i]; + 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; } -void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) +UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const { - SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); - SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); + return _streamBinders[bondIndex].ProcessedSize; } +#endif + } diff --git a/CPP/7zip/Archive/Common/CoderMixer2.h b/CPP/7zip/Archive/Common/CoderMixer2.h index 50e7077a..e63f2ff0 100644 --- a/CPP/7zip/Archive/Common/CoderMixer2.h +++ b/CPP/7zip/Archive/Common/CoderMixer2.h @@ -8,172 +8,430 @@ #include "../../ICoder.h" -namespace NCoderMixer { +#include "../../Common/CreateCoder.h" -struct CBindPair +#ifdef _7ZIP_ST + #define USE_MIXER_ST +#else + #define USE_MIXER_MT + #ifndef _SFX + #define USE_MIXER_ST + #endif +#endif + +#ifdef USE_MIXER_MT +#include "../../Common/StreamBinder.h" +#include "../../Common/VirtThread.h" +#endif + + + +#ifdef USE_MIXER_ST + +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 IOutStreamFinish, + public CMyUnknownImp +{ + CMyComPtr<ISequentialOutStream> _stream; + UInt64 _size; +public: + MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFinish) + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(OutStreamFinish)(); + + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void ReleaseStream() { _stream.Release(); } + void Init() { _size = 0; } + UInt64 GetSize() const { return _size; } +}; + +#endif + + + +namespace NCoderMixer2 { + +struct CBond { - UInt32 InIndex; - UInt32 OutIndex; + UInt32 PackIndex; + UInt32 UnpackIndex; + + UInt32 Get_InIndex(bool encodeMode) const { return encodeMode ? UnpackIndex : PackIndex; } + UInt32 Get_OutIndex(bool encodeMode) const { return encodeMode ? PackIndex : UnpackIndex; } }; + struct CCoderStreamsInfo { - UInt32 NumInStreams; - UInt32 NumOutStreams; + UInt32 NumStreams; }; + struct CBindInfo { CRecordVector<CCoderStreamsInfo> Coders; - CRecordVector<CBindPair> BindPairs; - CRecordVector<UInt32> InStreams; - CRecordVector<UInt32> OutStreams; + CRecordVector<CBond> Bonds; + CRecordVector<UInt32> PackStreams; + unsigned UnpackCoder; - void Clear() + unsigned GetNum_Bonds_and_PackStreams() const { return Bonds.Size() + PackStreams.Size(); } + + int FindBond_for_PackStream(UInt32 packStream) const { - Coders.Clear(); - BindPairs.Clear(); - InStreams.Clear(); - OutStreams.Clear(); + FOR_VECTOR (i, Bonds) + if (Bonds[i].PackIndex == packStream) + return i; + return -1; } - /* - UInt32 GetCoderStartOutStream(UInt32 coderIndex) const + int FindBond_for_UnpackStream(UInt32 unpackStream) const { - UInt32 numOutStreams = 0; - for (UInt32 i = 0; i < coderIndex; i++) - numOutStreams += Coders[i].NumOutStreams; - return numOutStreams; + FOR_VECTOR (i, Bonds) + if (Bonds[i].UnpackIndex == unpackStream) + return i; + return -1; } - */ - - void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const + bool SetUnpackCoder() { - numInStreams = 0; - numOutStreams = 0; - FOR_VECTOR (i, Coders) + bool isOk = false; + FOR_VECTOR(i, Coders) { - const CCoderStreamsInfo &coderStreamsInfo = Coders[i]; - numInStreams += coderStreamsInfo.NumInStreams; - numOutStreams += coderStreamsInfo.NumOutStreams; + if (FindBond_for_UnpackStream(i) < 0) + { + if (isOk) + return false; + UnpackCoder = i; + isOk = true; + } } + return isOk; } - - int FindBinderForInStream(UInt32 inStream) const + + bool IsStream_in_PackStreams(UInt32 streamIndex) const { - FOR_VECTOR (i, BindPairs) - if (BindPairs[i].InIndex == inStream) - return i; - return -1; + return FindStream_in_PackStreams(streamIndex) >= 0; } - int FindBinderForOutStream(UInt32 outStream) const + + int FindStream_in_PackStreams(UInt32 streamIndex) const { - FOR_VECTOR (i, BindPairs) - if (BindPairs[i].OutIndex == outStream) + FOR_VECTOR(i, PackStreams) + if (PackStreams[i] == streamIndex) return i; return -1; } - UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const + + // that function is used before Maps is calculated + + UInt32 GetStream_for_Coder(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) - streamIndex += Coders[i].NumInStreams; + streamIndex += Coders[i].NumStreams; return streamIndex; } + + // ---------- Maps Section ---------- + + CRecordVector<UInt32> Coder_to_Stream; + CRecordVector<UInt32> Stream_to_Coder; + + void ClearMaps(); + bool CalcMapsAndCheck(); + + // ---------- End of Maps Section ---------- - UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const + void Clear() { - UInt32 streamIndex = 0; - for (UInt32 i = 0; i < coderIndex; i++) - streamIndex += Coders[i].NumOutStreams; - return streamIndex; + Coders.Clear(); + Bonds.Clear(); + PackStreams.Clear(); + + ClearMaps(); } + + void GetCoder_for_Stream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const + { + coderIndex = Stream_to_Coder[streamIndex]; + coderStreamIndex = streamIndex - Coder_to_Stream[coderIndex]; + } +}; - void FindInStream(UInt32 streamIndex, UInt32 &coderIndex, - UInt32 &coderStreamIndex) const + +class CCoder +{ + CLASS_NO_COPY(CCoder); +public: + CMyComPtr<ICompressCoder> Coder; + CMyComPtr<ICompressCoder2> Coder2; + UInt32 NumStreams; + + UInt64 UnpackSize; + const UInt64 *UnpackSizePointer; + + CRecordVector<UInt64> PackSizes; + CRecordVector<const UInt64 *> PackSizePointers; + + CCoder() {} + + void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes); + + IUnknown *GetUnknown() const { - for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) - { - UInt32 curSize = Coders[coderIndex].NumInStreams; - if (streamIndex < curSize) - { - coderStreamIndex = streamIndex; - return; - } - streamIndex -= curSize; - } - throw 1; + return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; } - void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex, - UInt32 &coderStreamIndex) const + + HRESULT QueryInterface(REFGUID iid, void** pp) const { - for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) - { - UInt32 curSize = Coders[coderIndex].NumOutStreams; - if (streamIndex < curSize) + return GetUnknown()->QueryInterface(iid, pp); + } +}; + + + +class CMixer +{ + bool Is_PackSize_Correct_for_Stream(UInt32 streamIndex); + +protected: + CBindInfo _bi; + + int FindBond_for_Stream(bool forInputStream, UInt32 streamIndex) const + { + if (EncodeMode == forInputStream) + return _bi.FindBond_for_UnpackStream(streamIndex); + else + return _bi.FindBond_for_PackStream(streamIndex); + } + + CBoolVector IsFilter_Vector; + CBoolVector IsExternal_Vector; + bool EncodeMode; +public: + unsigned MainCoderIndex; + + CMixer(bool encodeMode): + EncodeMode(encodeMode), + MainCoderIndex(0) + {} + + /* + Sequence of calling: + + SetBindInfo(); + for each coder + AddCoder(); + SelectMainCoder(); + + for each file { - coderStreamIndex = streamIndex; - return; + ReInit() + for each coder + SetCoderInfo(); + Code(); } - streamIndex -= curSize; - } - throw 1; + */ + + virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) + { + _bi = bindInfo; + IsFilter_Vector.Clear(); + MainCoderIndex = 0; + return S_OK; } + + virtual void AddCoder(const CCreatedCoder &cod) = 0; + virtual CCoder &GetCoder(unsigned index) = 0; + virtual void SelectMainCoder(bool useFirst) = 0; + virtual void ReInit() = 0; + virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) = 0; + virtual HRESULT Code( + ISequentialInStream * const *inStreams, + ISequentialOutStream * const *outStreams, + ICompressProgressInfo *progress) = 0; + virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0; + + bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex); + bool Is_PackSize_Correct_for_Coder(UInt32 coderIndex); + bool IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex); }; -class CBindReverseConverter + + + +#ifdef USE_MIXER_ST + +struct CCoderST: public CCoder { - UInt32 _numSrcOutStreams; - NCoderMixer::CBindInfo _srcBindInfo; - CRecordVector<UInt32> _srcInToDestOutMap; - CRecordVector<UInt32> _srcOutToDestInMap; - CRecordVector<UInt32> _destInToSrcOutMap; -public: - UInt32 NumSrcInStreams; - CRecordVector<UInt32> DestOutToSrcInMap; + bool CanRead; + bool CanWrite; + + CCoderST(): CanRead(false), CanWrite(false) {} +}; - CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo); - void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo); + +struct CStBinderStream +{ + CSequentialInStreamCalcSize *InStreamSpec; + COutStreamCalcSize *OutStreamSpec; + CMyComPtr<IUnknown> StreamRef; + + CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {} }; -void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, - CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems); -struct CCoderInfo2 +class CMixerST: + public IUnknown, + public CMixer, + public CMyUnknownImp { - CMyComPtr<ICompressCoder> Coder; - CMyComPtr<ICompressCoder2> Coder2; - UInt32 NumInStreams; - UInt32 NumOutStreams; + 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); - CRecordVector<UInt64> InSizes; - CRecordVector<UInt64> OutSizes; - CRecordVector<const UInt64 *> InSizePointers; - CRecordVector<const UInt64 *> OutSizePointers; + HRESULT FinishStream(UInt32 streamIndex); + HRESULT FinishCoder(UInt32 coderIndex); - CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams): - NumInStreams(numInStreams), - NumOutStreams(numOutStreams) {} - void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); +public: + CObjectVector<CCoderST> _coders; + + CObjectVector<CStBinderStream> _binderStreams; - HRESULT QueryInterface(REFGUID iid, void** pp) const + MY_UNKNOWN_IMP + + CMixerST(bool encodeMode); + ~CMixerST(); + + virtual void AddCoder(const CCreatedCoder &cod); + 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 + + + + +#ifdef USE_MIXER_MT + +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; + + void Release() { - IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; - return p->QueryInterface(iid, pp); + InStreamPointers.Clear(); + OutStreamPointers.Clear(); + unsigned i; + for (i = 0; i < InStreams.Size(); i++) + InStreams[i].Release(); + for (i = 0; i < OutStreams.Size(); i++) + OutStreams[i].Release(); } + + class CReleaser + { + CLASS_NO_COPY(CReleaser) + CCoderMT &_c; + public: + CReleaser(CCoderMT &c): _c(c) {} + ~CReleaser() { _c.Release(); } + }; + + CCoderMT(): EncodeMode(false) {} + ~CCoderMT() { CVirtThread::WaitThreadFinish(); } + + void Code(ICompressProgressInfo *progress); }; -class CCoderMixer2 + +class CMixerMT: + public IUnknown, + public CMixer, + public CMyUnknownImp { + CObjectVector<CStreamBinder> _streamBinders; + + HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams); + HRESULT ReturnIfError(HRESULT code); + public: - virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0; - virtual void ReInit() = 0; - virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0; + CObjectVector<CCoderMT> _coders; + + MY_UNKNOWN_IMP + + virtual HRESULT SetBindInfo(const CBindInfo &bindInfo); + virtual void AddCoder(const CCreatedCoder &cod); + 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 + } #endif diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp index 5288fbc1..c0139862 100644 --- a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp +++ b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp @@ -4,125 +4,153 @@ #include "CoderMixer2MT.h" -namespace NCoderMixer { +namespace NCoderMixer2 { -CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams): - CCoderInfo2(numInStreams, numOutStreams) +void CCoderMT::Execute() { Code(NULL); } + +void CCoderMT::Code(ICompressProgressInfo *progress) { - InStreams.ClearAndReserve(NumInStreams); - OutStreams.ClearAndReserve(NumOutStreams); -} + unsigned numInStreams = EncodeMode ? 1 : NumStreams; + unsigned numOutStreams = EncodeMode ? NumStreams : 1; -void CCoder2::Execute() { Code(NULL); } + InStreamPointers.ClearAndReserve(numInStreams); + OutStreamPointers.ClearAndReserve(numOutStreams); -void CCoder2::Code(ICompressProgressInfo *progress) -{ - InStreamPointers.ClearAndReserve(NumInStreams); - OutStreamPointers.ClearAndReserve(NumOutStreams); - UInt32 i; - for (i = 0; i < NumInStreams; i++) - { - if (InSizePointers[i]) - InSizePointers[i] = &InSizes[i]; + unsigned i; + + for (i = 0; i < numInStreams; i++) InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]); - } - for (i = 0; i < NumOutStreams; i++) - { - if (OutSizePointers[i]) - OutSizePointers[i] = &OutSizes[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], - InSizePointers[0], OutSizePointers[0], progress); + EncodeMode ? UnpackSizePointer : PackSizePointers[0], + EncodeMode ? PackSizePointers[0] : UnpackSizePointer, + progress); else - Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams, - &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress); - { - unsigned i; - for (i = 0; i < InStreams.Size(); i++) - InStreams[i].Release(); - for (i = 0; i < OutStreams.Size(); i++) - OutStreams[i].Release(); - } -} + Result = Coder2->Code( + &InStreamPointers.Front(), EncodeMode ? &UnpackSizePointer : &PackSizePointers.Front(), numInStreams, + &OutStreamPointers.Front(), EncodeMode ? &PackSizePointers.Front(): &UnpackSizePointer, numOutStreams, + progress); + + InStreamPointers.Clear(); + OutStreamPointers.Clear(); -/* -void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) -{ - SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); - SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); + for (i = 0; i < InStreams.Size(); i++) + InStreams[i].Release(); + for (i = 0; i < OutStreams.Size(); i++) + OutStreams[i].Release(); } -*/ - -////////////////////////////////////// -// CCoderMixer2MT -HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo) +HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo) { - _bindInfo = bindInfo; + CMixer::SetBindInfo(bindInfo); + _streamBinders.Clear(); - FOR_VECTOR (i, _bindInfo.BindPairs) + FOR_VECTOR (i, _bi.Bonds) { RINOK(_streamBinders.AddNew().CreateEvents()); } return S_OK; } -void CCoderMixer2MT::AddCoderCommon() -{ - const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()]; - CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams); - _coders.Add(threadCoderInfo); -} - -void CCoderMixer2MT::AddCoder(ICompressCoder *coder) +void CMixerMT::AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter) { - AddCoderCommon(); - _coders.Back().Coder = coder; + 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); } -void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder) +CCoder &CMixerMT::GetCoder(unsigned index) { - AddCoderCommon(); - _coders.Back().Coder2 = coder; + return _coders[index]; } - -void CCoderMixer2MT::ReInit() +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 CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams) +HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams) { - /* - if (_coders.Size() != _bindInfo.Coders.Size()) - throw 0; - */ unsigned i; + for (i = 0; i < _coders.Size(); i++) { - CCoder2 &coderInfo = _coders[i]; - const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i]; - coderInfo.InStreams.Clear(); + CCoderMT &coderInfo = _coders[i]; + const CCoderStreamsInfo &csi = _bi.Coders[i]; + UInt32 j; - for (j = 0; j < coderStreamsInfo.NumInStreams; j++) - coderInfo.InStreams.Add(NULL); + + 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 < coderStreamsInfo.NumOutStreams; j++) - coderInfo.OutStreams.Add(NULL); + for (j = 0; j < numOutStreams; j++) + coderInfo.OutStreams.AddNew(); } - for (i = 0; i < _bindInfo.BindPairs.Size(); i++) + for (i = 0; i < _bi.Bonds.Size(); i++) { - const CBindPair &bindPair = _bindInfo.BindPairs[i]; + const CBond &bond = _bi.Bonds[i]; + UInt32 inCoderIndex, inCoderStreamIndex; UInt32 outCoderIndex, outCoderStreamIndex; - _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex); - _bindInfo.FindOutStream(bindPair.OutIndex, 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], @@ -139,23 +167,29 @@ HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStre } } - for (i = 0; i < _bindInfo.InStreams.Size(); i++) { - UInt32 inCoderIndex, inCoderStreamIndex; - _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex); - _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i]; + CCoderMT &cod = _coders[_bi.UnpackCoder]; + if (EncodeMode) + cod.InStreams[0] = inStreams[0]; + else + cod.OutStreams[0] = outStreams[0]; } - - for (i = 0; i < _bindInfo.OutStreams.Size(); i++) + + for (i = 0; i < _bi.PackStreams.Size(); i++) { - UInt32 outCoderIndex, outCoderStreamIndex; - _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex); - _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[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 CCoderMixer2MT::ReturnIfError(HRESULT code) +HRESULT CMixerMT::ReturnIfError(HRESULT code) { FOR_VECTOR (i, _coders) if (_coders[i].Result == code) @@ -163,35 +197,28 @@ HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code) return S_OK; } -STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, - const UInt64 ** /* inSizes */, - UInt32 numInStreams, - ISequentialOutStream **outStreams, - const UInt64 ** /* outSizes */, - UInt32 numOutStreams, - ICompressProgressInfo *progress) +HRESULT CMixerMT::Code( + ISequentialInStream * const *inStreams, + ISequentialOutStream * const *outStreams, + ICompressProgressInfo *progress) { - if (numInStreams != (UInt32)_bindInfo.InStreams.Size() || - numOutStreams != (UInt32)_bindInfo.OutStreams.Size()) - return E_INVALIDARG; - Init(inStreams, outStreams); unsigned i; for (i = 0; i < _coders.Size(); i++) - if (i != _progressCoderIndex) + if (i != MainCoderIndex) { RINOK(_coders[i].Create()); } for (i = 0; i < _coders.Size(); i++) - if (i != _progressCoderIndex) + if (i != MainCoderIndex) _coders[i].Start(); - _coders[_progressCoderIndex].Code(progress); + _coders[MainCoderIndex].Code(progress); for (i = 0; i < _coders.Size(); i++) - if (i != _progressCoderIndex) + if (i != MainCoderIndex) _coders[i].WaitExecuteFinish(); RINOK(ReturnIfError(E_ABORT)); @@ -200,7 +227,10 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; - if (result != S_OK && result != E_FAIL && result != S_FALSE) + if (result != S_OK + && result != k_My_HRESULT_WritingWasCut + && result != S_FALSE + && result != E_FAIL) return result; } @@ -209,10 +239,16 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; - if (result != S_OK) + 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 index ba475cec..41bb3e1c 100644 --- a/CPP/7zip/Archive/Common/CoderMixer2MT.h +++ b/CPP/7zip/Archive/Common/CoderMixer2MT.h @@ -3,81 +3,75 @@ #ifndef __CODER_MIXER2_MT_H #define __CODER_MIXER2_MT_H -#include "CoderMixer2.h" #include "../../../Common/MyCom.h" + #include "../../Common/StreamBinder.h" #include "../../Common/VirtThread.h" -namespace NCoderMixer { +#include "CoderMixer2.h" + +namespace NCoderMixer2 { -struct CCoder2: public CCoderInfo2, public CVirtThread +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; - CCoder2(UInt32 numInStreams, UInt32 numOutStreams); - ~CCoder2() { CVirtThread::WaitThreadFinish(); } - // void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); - virtual void Execute(); + CCoderMT(): EncodeMode(false) {} + ~CCoderMT() { CVirtThread::WaitThreadFinish(); } + void Code(ICompressProgressInfo *progress); }; -/* - SetBindInfo() - for each coder - AddCoder[2]() - SetProgressIndex(UInt32 coderIndex); - - for each file - { - ReInit() - for each coder - SetCoderInfo - Code - } -*/ - -class CCoderMixer2MT: - public ICompressCoder2, - public CCoderMixer2, + +class CMixerMT: + public IUnknown, + public CMixer, public CMyUnknownImp { - CBindInfo _bindInfo; CObjectVector<CStreamBinder> _streamBinders; - unsigned _progressCoderIndex; - void AddCoderCommon(); - HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams); + HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams); HRESULT ReturnIfError(HRESULT code); + public: - CObjectVector<CCoder2> _coders; + CObjectVector<CCoderMT> _coders; + MY_UNKNOWN_IMP - STDMETHOD(Code)(ISequentialInStream **inStreams, - const UInt64 **inSizes, - UInt32 numInStreams, - ISequentialOutStream **outStreams, - const UInt64 **outSizes, - UInt32 numOutStreams, + 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); - HRESULT SetBindInfo(const CBindInfo &bindInfo); - void AddCoder(ICompressCoder *coder); - void AddCoder2(ICompressCoder2 *coder); - void SetProgressCoderIndex(unsigned coderIndex) { _progressCoderIndex = coderIndex; } + virtual UInt64 GetBondStreamSize(unsigned bondIndex) const; - void ReInit(); - void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) - { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); } - UInt64 GetWriteProcessedSize(UInt32 binderIndex) const - { return _streamBinders[binderIndex].ProcessedSize; } + CMixerMT(bool encodeMode): CMixer(encodeMode) {} }; } + #endif diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp index a94ba115..127c1ed4 100644 --- a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp +++ b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp @@ -4,236 +4,559 @@ #include "CoderMixer2ST.h" -namespace NCoderMixer { +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; +} -CCoderMixer2ST::CCoderMixer2ST() {} -CCoderMixer2ST::~CCoderMixer2ST(){ } -HRESULT CCoderMixer2ST::SetBindInfo(const CBindInfo &bindInfo) +STDMETHODIMP COutStreamCalcSize::Write(const void *data, UInt32 size, UInt32 *processedSize) { - _bindInfo = bindInfo; - return S_OK; + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, size, &size); + _size += size; + if (processedSize) + *processedSize = size; + return result; } -void CCoderMixer2ST::AddCoderCommon(bool isMain) +STDMETHODIMP COutStreamCalcSize::Flush() { - const CCoderStreamsInfo &csi = _bindInfo.Coders[_coders.Size()]; - _coders.Add(CSTCoderInfo(csi.NumInStreams, csi.NumOutStreams, isMain)); + HRESULT result = S_OK; + if (_stream) + { + CMyComPtr<IOutStreamFlush> outStreamFlush; + _stream.QueryInterface(IID_IOutStreamFlush, &outStreamFlush); + if (outStreamFlush) + result = outStreamFlush->Flush();; + } + return result; } -void CCoderMixer2ST::AddCoder(ICompressCoder *coder, bool isMain) + + +namespace NCoderMixer2 { + +CMixerST::CMixerST(bool encodeMode): + CMixer(encodeMode) + {} + +CMixerST::~CMixerST() {} + +void CMixerST::AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter) { - AddCoderCommon(isMain); - _coders.Back().Coder = coder; + 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); + } + } } -void CCoderMixer2ST::AddCoder2(ICompressCoder2 *coder, bool isMain) +CCoder &CMixerST::GetCoder(unsigned index) { - AddCoderCommon(isMain); - _coders.Back().Coder2 = coder; + 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; } -void CCoderMixer2ST::ReInit() { } -HRESULT CCoderMixer2ST::GetInStream( - ISequentialInStream **inStreams, const UInt64 **inSizes, - UInt32 streamIndex, ISequentialInStream **inStreamRes) +HRESULT CMixerST::GetInStream( + ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ + UInt32 inStreamIndex, ISequentialInStream **inStreamRes) { CMyComPtr<ISequentialInStream> seqInStream; - int i; - for (i = 0; i < _bindInfo.InStreams.Size(); i++) - if (_bindInfo.InStreams[i] == streamIndex) + + { + int index = -1; + if (EncodeMode) + { + if (_bi.UnpackCoder == inStreamIndex) + index = 0; + } + else + index = _bi.FindStream_in_PackStreams(inStreamIndex); + + if (index >= 0) { - seqInStream = inStreams[i]; + seqInStream = inStreams[index]; *inStreamRes = seqInStream.Detach(); return S_OK; } - int binderIndex = _bindInfo.FindBinderForInStream(streamIndex); - if (binderIndex < 0) + } + + int bond = FindBond_for_Stream( + true, // forInputStream + inStreamIndex); + if (bond < 0) return E_INVALIDARG; - UInt32 coderIndex, coderStreamIndex; - _bindInfo.FindOutStream(_bindInfo.BindPairs[binderIndex].OutIndex, - coderIndex, coderStreamIndex); - - CCoderInfo2 &coder = _coders[coderIndex]; - if (!coder.Coder) - return E_NOTIMPL; - coder.Coder.QueryInterface(IID_ISequentialInStream, &seqInStream); - if (!seqInStream) - return E_NOTIMPL; + RINOK(GetInStream2(inStreams, /* inSizes, */ + _bi.Bonds[bond].Get_OutIndex(EncodeMode), &seqInStream)); - UInt32 startIndex = _bindInfo.GetCoderInStreamIndex(coderIndex); + while (_binderStreams.Size() <= (unsigned)bond) + _binderStreams.AddNew(); + CStBinderStream &bs = _binderStreams[bond]; - CMyComPtr<ICompressSetInStream> setInStream; - if (!coder.Coder) - return E_NOTIMPL; - coder.Coder.QueryInterface(IID_ICompressSetInStream, &setInStream); - if (!setInStream) + 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; - if (coder.NumInStreams > 1) - return E_NOTIMPL; - for (i = 0; i < (int)coder.NumInStreams; i++) - { - CMyComPtr<ISequentialInStream> seqInStream2; - RINOK(GetInStream(inStreams, inSizes, startIndex + i, &seqInStream2)); - RINOK(setInStream->SetInStream(seqInStream2)); - } *inStreamRes = seqInStream.Detach(); return S_OK; } -HRESULT CCoderMixer2ST::GetOutStream( - ISequentialOutStream **outStreams, const UInt64 **outSizes, - UInt32 streamIndex, ISequentialOutStream **outStreamRes) + +HRESULT CMixerST::GetOutStream( + ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */ + UInt32 outStreamIndex, ISequentialOutStream **outStreamRes) { CMyComPtr<ISequentialOutStream> seqOutStream; - int i; - for (i = 0; i < _bindInfo.OutStreams.Size(); i++) - if (_bindInfo.OutStreams[i] == streamIndex) + + { + int index = -1; + if (!EncodeMode) + { + if (_bi.UnpackCoder == outStreamIndex) + index = 0; + } + else + index = _bi.FindStream_in_PackStreams(outStreamIndex); + + if (index >= 0) { - seqOutStream = outStreams[i]; + seqOutStream = outStreams[index]; *outStreamRes = seqOutStream.Detach(); return S_OK; } - int binderIndex = _bindInfo.FindBinderForOutStream(streamIndex); - if (binderIndex < 0) + } + + int bond = FindBond_for_Stream( + false, // forInputStream + outStreamIndex); + if (bond < 0) return E_INVALIDARG; - UInt32 coderIndex, coderStreamIndex; - _bindInfo.FindInStream(_bindInfo.BindPairs[binderIndex].InIndex, - coderIndex, coderStreamIndex); + 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]; - CCoderInfo2 &coder = _coders[coderIndex]; + /* if (!coder.Coder) return E_NOTIMPL; - coder.Coder.QueryInterface(IID_ISequentialOutStream, &seqOutStream); + */ + + coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream); if (!seqOutStream) return E_NOTIMPL; - UInt32 startIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex); + UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1; + UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex; - CMyComPtr<ICompressSetOutStream> setOutStream; - if (!coder.Coder) - return E_NOTIMPL; - coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream); - if (!setOutStream) - return E_NOTIMPL; + bool isSet = false; - if (coder.NumOutStreams > 1) - return E_NOTIMPL; - for (i = 0; i < (int)coder.NumOutStreams; i++) + if (numOutStreams == 1) { - CMyComPtr<ISequentialOutStream> seqOutStream2; - RINOK(GetOutStream(outStreams, outSizes, startIndex + i, &seqOutStream2)); - RINOK(setOutStream->SetOutStream(seqOutStream2)); + 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; } - -STDMETHODIMP CCoderMixer2ST::Code(ISequentialInStream **inStreams, - const UInt64 **inSizes, - UInt32 numInStreams, - ISequentialOutStream **outStreams, - const UInt64 **outSizes, - UInt32 numOutStreams, - ICompressProgressInfo *progress) + +static HRESULT GetError(HRESULT res, HRESULT res2) { - if (numInStreams != (UInt32)_bindInfo.InStreams.Size() || - numOutStreams != (UInt32)_bindInfo.OutStreams.Size()) - return E_INVALIDARG; + 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; +} - // Find main coder - int _mainCoderIndex = -1; - int i; - for (i = 0; i < _coders.Size(); i++) - if (_coders[i].IsMain) - { - _mainCoderIndex = i; - break; - } - if (_mainCoderIndex < 0) - for (i = 0; i < _coders.Size(); i++) - if (_coders[i].NumInStreams > 1) + +HRESULT CMixerST::FlushStream(UInt32 streamIndex) +{ + { + int index = -1; + if (!EncodeMode) { - if (_mainCoderIndex >= 0) - return E_NOTIMPL; - _mainCoderIndex = i; + if (_bi.UnpackCoder == streamIndex) + index = 0; } - if (_mainCoderIndex < 0) - _mainCoderIndex = 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; - // _mainCoderIndex = 0; - // _mainCoderIndex = _coders.Size() - 1; - CCoderInfo2 &mainCoder = _coders[_mainCoderIndex]; + const CCoder &mainCoder = _coders[MainCoderIndex]; CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams; CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams; - UInt32 startInIndex = _bindInfo.GetCoderInStreamIndex(_mainCoderIndex); - UInt32 startOutIndex = _bindInfo.GetCoderOutStreamIndex(_mainCoderIndex); - for (i = 0; i < (int)mainCoder.NumInStreams; i++) + + 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)); + RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream)); seqInStreams.Add(seqInStream); } - for (i = 0; i < (int)mainCoder.NumOutStreams; i++) + + for (i = 0; i < numOutStreams; i++) { CMyComPtr<ISequentialOutStream> seqOutStream; - RINOK(GetOutStream(outStreams, outSizes, startOutIndex + i, &seqOutStream)); + RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream)); seqOutStreams.Add(seqOutStream); } + CRecordVector< ISequentialInStream * > seqInStreamsSpec; CRecordVector< ISequentialOutStream * > seqOutStreamsSpec; - for (i = 0; i < (int)mainCoder.NumInStreams; i++) + + for (i = 0; i < numInStreams; i++) seqInStreamsSpec.Add(seqInStreams[i]); - for (i = 0; i < (int)mainCoder.NumOutStreams; i++) + for (i = 0; i < numOutStreams; i++) seqOutStreamsSpec.Add(seqOutStreams[i]); for (i = 0; i < _coders.Size(); i++) { - if (i == _mainCoderIndex) + if (i == ci) continue; - CCoderInfo2 &coder = _coders[i]; + + CCoder &coder = _coders[i]; + CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize; - coder.Coder.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize); + coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize); if (setOutStreamSize) { - RINOK(setOutStreamSize->SetOutStreamSize(coder.OutSizePointers[0])); + 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) { - RINOK(mainCoder.Coder->Code( + res = mainCoder.Coder->Code( seqInStreamsSpec[0], seqOutStreamsSpec[0], - mainCoder.InSizePointers[0], mainCoder.OutSizePointers[0], - progress)); + isSizes2[0], outSizes2[0], + progress); } else { - RINOK(mainCoder.Coder2->Code( - &seqInStreamsSpec.Front(), - &mainCoder.InSizePointers.Front(), mainCoder.NumInStreams, - &seqOutStreamsSpec.Front(), - &mainCoder.OutSizePointers.Front(), mainCoder.NumOutStreams, - progress)); + res = mainCoder.Coder2->Code( + &seqInStreamsSpec.Front(), isSizes2, numInStreams, + &seqOutStreamsSpec.Front(), outSizes2, numOutStreams, + progress); } - CMyComPtr<IOutStreamFlush> flush; - seqOutStreams.Front().QueryInterface(IID_IOutStreamFlush, &flush); - if (flush) - return flush->Flush(); + + 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 CCoderMixer2ST::GetWriteProcessedSize(UInt32 binderIndex) const + +UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const { - return _streamBinders[binderIndex].ProcessedSize; + 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 index d35655ba..f2f7c4cb 100644 --- a/CPP/7zip/Archive/Common/CoderMixer2ST.h +++ b/CPP/7zip/Archive/Common/CoderMixer2ST.h @@ -3,84 +3,125 @@ #ifndef __CODER_MIXER2_ST_H #define __CODER_MIXER2_ST_H -#include "CoderMixer2.h" #include "../../../Common/MyCom.h" + #include "../../ICoder.h" -namespace NCoderMixer { - -// SetBindInfo() -// for each coder -// { -// AddCoder[2]() -// } -// -// for each file -// { -// ReInit() -// for each coder -// { -// SetCoderInfo -// } -// SetProgressIndex(UInt32 coderIndex); -// Code -// } - -struct CSTCoderInfo: public CCoderInfo2 +#include "CoderMixer2.h" + +class CSequentialInStreamCalcSize: + public ISequentialInStream, + public CMyUnknownImp { - bool IsMain; - CSTCoderInfo(UInt32 numInStreams, UInt32 numOutStreams, bool isMain): - CCoderInfo2(numInStreams, numOutStreams), IsMain(isMain) {} +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 CCoderMixer2ST: - public ICompressCoder2, - public CCoderMixer2, + +class COutStreamCalcSize: + public ISequentialOutStream, + public IOutStreamFlush, public CMyUnknownImp { - MY_UNKNOWN_IMP - - HRESULT GetInStream( - ISequentialInStream **inStreams, const UInt64 **inSizes, - UInt32 streamIndex, ISequentialInStream **inStreamRes); - HRESULT GetOutStream( - ISequentialOutStream **outStreams, const UInt64 **outSizes, - UInt32 streamIndex, ISequentialOutStream **outStreamRes); + CMyComPtr<ISequentialOutStream> _stream; + UInt64 _size; public: - STDMETHOD(Code)(ISequentialInStream **inStreams, - const UInt64 **inSizes, - UInt32 numInStreams, - ISequentialOutStream **outStreams, - const UInt64 **outSizes, - UInt32 numOutStreams, - ICompressProgressInfo *progress); + 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; } +}; - CCoderMixer2ST(); - ~CCoderMixer2ST(); - void AddCoderCommon(bool isMain); - void AddCoder(ICompressCoder *coder, bool isMain); - void AddCoder2(ICompressCoder2 *coder, bool isMain); - void ReInit(); - void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) - { - { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); } - } - void SetProgressCoderIndex(UInt32 /*coderIndex*/) - { - // _progressCoderIndex = coderIndex; - } +namespace NCoderMixer2 { - // UInt64 GetWriteProcessedSize(UInt32 binderIndex) const; +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); -private: - CBindInfo _bindInfo; - CObjectVector<CSTCoderInfo> _coders; - int _mainCoderIndex; public: - HRESULT SetBindInfo(const CBindInfo &bindInfo); + 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); }; } diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.h b/CPP/7zip/Archive/Common/CoderMixerMT.h index 9491a965..d2891b26 100644 --- a/CPP/7zip/Archive/Common/CoderMixerMT.h +++ b/CPP/7zip/Archive/Common/CoderMixerMT.h @@ -18,7 +18,7 @@ struct CCoder: public CCoderInfo, public CVirtThread virtual void Execute(); void Code(ICompressProgressInfo *progress); - ~CCoder() { CVirtThread::WaitThreadFinish(); } + virtual ~CCoder() { CVirtThread::WaitThreadFinish(); } }; /* diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp index 18ad5580..9c11b31d 100644 --- a/CPP/7zip/Archive/Common/HandlerOut.cpp +++ b/CPP/7zip/Archive/Common/HandlerOut.cpp @@ -29,6 +29,7 @@ void CMultiMethodProps::SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo UInt32 level = _level; if (level != (UInt32)(Int32)-1) SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level); + #ifndef _7ZIP_ST SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif @@ -41,6 +42,8 @@ void CMultiMethodProps::Init() #endif _level = (UInt32)(Int32)-1; + _analysisLevel = -1; + _autoFilter = true; _crcSize = 4; _filterMethod.Clear(); @@ -60,8 +63,17 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN _level = 9; return ParsePropToUInt32(name, value, _level); } + + if (name.IsPrefixedBy_Ascii_NoCase("yx")) + { + name.Delete(0, 2); + UInt32 v = 9; + RINOK(ParsePropToUInt32(name, value, v)); + _analysisLevel = (int)v; + return S_OK; + } - if (name == L"crc") + if (name.IsEqualTo("crc")) { name.Delete(0, 3); _crcSize = 4; @@ -73,11 +85,12 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN UString realName = name.Ptr(index); if (index == 0) { - if (name.IsPrefixedBy(L"mt")) + if (name.IsPrefixedBy_Ascii_NoCase("mt")) { #ifndef _7ZIP_ST RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads)); #endif + return S_OK; } if (name.IsEqualTo("f")) @@ -87,7 +100,7 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN return res; if (value.vt != VT_BSTR) return E_INVALIDARG; - return _filterMethod.ParseMethodFromPROPVARIANT(L"", value); + return _filterMethod.ParseMethodFromPROPVARIANT(UString(), value); } number = 0; } @@ -101,14 +114,15 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN void CSingleMethodProps::Init() { Clear(); + _level = (UInt32)(Int32)-1; + #ifndef _7ZIP_ST _numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors(); - AddNumThreadsProp(_numThreads); + AddProp_NumThreads(_numThreads); #endif - _level = (UInt32)(Int32)-1; } -HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) +HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) { Init(); for (UInt32 i = 0; i < numProps; i++) @@ -123,13 +137,13 @@ HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIA UInt32 a = 9; RINOK(ParsePropToUInt32(name.Ptr(1), value, a)); _level = a; - AddLevelProp(a); + AddProp_Level(a); } - else if (name.IsPrefixedBy(L"mt")) + else if (name.IsPrefixedBy_Ascii_NoCase("mt")) { #ifndef _7ZIP_ST RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads)); - AddNumThreadsProp(_numThreads); + AddProp_NumThreads(_numThreads); #endif } else diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h index 40a4a698..5a18d980 100644 --- a/CPP/7zip/Archive/Common/HandlerOut.h +++ b/CPP/7zip/Archive/Common/HandlerOut.h @@ -10,6 +10,7 @@ namespace NArchive { class CMultiMethodProps { UInt32 _level; + int _analysisLevel; public: #ifndef _7ZIP_ST UInt32 _numThreads; @@ -37,6 +38,7 @@ public: } int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; } + int GetAnalysisLevel() const { return _analysisLevel; } void Init(); @@ -57,7 +59,7 @@ public: void Init(); CSingleMethodProps() { Init(); } int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; } - HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); + HRESULT SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); }; } diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp index 0526c1b1..77252938 100644 --- a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp +++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp @@ -10,9 +10,9 @@ STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *pr if (_stream) result = _stream->Write(data, size, &size); if (_calculate) - _sha.Update((const Byte *)data, size); + Sha1_Update(&_sha, (const Byte *)data, size); _size += size; - if (processedSize != NULL) + if (processedSize) *processedSize = size; return result; } diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.h b/CPP/7zip/Archive/Common/OutStreamWithSha1.h index 3bbfbbe1..41a84cd6 100644 --- a/CPP/7zip/Archive/Common/OutStreamWithSha1.h +++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.h @@ -3,7 +3,7 @@ #ifndef __OUT_STREAM_WITH_SHA1_H #define __OUT_STREAM_WITH_SHA1_H -#include "../../Crypto/Sha1.h" +#include "../../../../C/Sha1.h" #include "../../../Common/MyCom.h" @@ -15,7 +15,7 @@ class COutStreamWithSha1: { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; - NCrypto::NSha1::CContext _sha; + CSha1 _sha; bool _calculate; public: MY_UNKNOWN_IMP @@ -26,11 +26,11 @@ public: { _size = 0; _calculate = calculate; - _sha.Init(); + Sha1_Init(&_sha); } - void InitSha1() { _sha.Init(); } + void InitSha1() { Sha1_Init(&_sha); } UInt64 GetSize() const { return _size; } - void Final(Byte *digest) { _sha.Final(digest); } + void Final(Byte *digest) { Sha1_Final(&_sha, digest); } }; #endif diff --git a/CPP/7zip/Archive/CpioHandler.cpp b/CPP/7zip/Archive/CpioHandler.cpp index 431d315d..2436fb5e 100644 --- a/CPP/7zip/Archive/CpioHandler.cpp +++ b/CPP/7zip/Archive/CpioHandler.cpp @@ -87,7 +87,7 @@ enum EType k_Type_HexCrc }; -static const char *k_Types[] = +static const char * const k_Types[] = { "Binary LE" , "Binary BE" @@ -396,11 +396,10 @@ HRESULT CInArchive::GetNextItem(CItem &item, EErrorType &errorType) return S_FALSE; if (nameSize == 0 || nameSize >= kNameSizeMax) return S_OK; - char *s = item.Name.GetBuffer(nameSize); + char *s = item.Name.GetBuf(nameSize); size_t processedSize = nameSize; RINOK(Read(s, &processedSize)); - s[nameSize] = 0; - item.Name.ReleaseBuffer(); + item.Name.ReleaseBuf_CalcLen(nameSize); if (processedSize != nameSize) { errorType = k_ErrorType_UnexpectedEnd; @@ -451,7 +450,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) NCOM::CPropVariant prop; switch (propID) { - case kpidSubType: prop = k_Types[_Type]; break; + case kpidSubType: prop = k_Types[(unsigned)_Type]; break; case kpidPhySize: prop = _phySize; break; case kpidErrorFlags: { @@ -780,20 +779,16 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -IMP_CreateArcIn - -static CArcInfo g_ArcInfo = - { "Cpio", "cpio", 0, 0xED, - 3 + 5 + 2 + 2, - { +static const Byte k_Signature[] = { 5, '0', '7', '0', '7', '0', 2, kMagicBin0, kMagicBin1, - 2, kMagicBin1, kMagicBin0, - }, + 2, kMagicBin1, kMagicBin0 }; + +REGISTER_ARC_I( + "Cpio", "cpio", 0, 0xED, + k_Signature, 0, NArcInfoFlags::kMultiSignature, - CreateArc, NULL, IsArc_Cpio }; - -REGISTER_ARC(Cpio) + IsArc_Cpio) }} diff --git a/CPP/7zip/Archive/CramfsHandler.cpp b/CPP/7zip/Archive/CramfsHandler.cpp index 3764f1af..e776b3c7 100644 --- a/CPP/7zip/Archive/CramfsHandler.cpp +++ b/CPP/7zip/Archive/CramfsHandler.cpp @@ -26,8 +26,7 @@ namespace NCramfs { #define SIGNATURE { 'C','o','m','p','r','e','s','s','e','d',' ','R','O','M','F','S' } -static const UInt32 kSignatureSize = 16; -static const char kSignature[kSignatureSize] = SIGNATURE; +static const Byte kSignature[] = SIGNATURE; static const UInt32 kArcSizeMax = (256 + 16) << 20; static const UInt32 kNumFilesMax = (1 << 19); @@ -55,7 +54,7 @@ static const unsigned k_Flags_Method_Mask = 3; #define k_Flags_Method_ZLIB 1 #define k_Flags_Method_LZMA 2 -static const char *k_Methods[] = +static const char * const k_Methods[] = { "Copy" , "ZLIB" @@ -145,7 +144,7 @@ struct CHeader bool Parse(const Byte *p) { - if (memcmp(p + 16, kSignature, kSignatureSize) != 0) + if (memcmp(p + 16, kSignature, ARRAY_SIZE(kSignature)) != 0) return false; switch(GetUi32(p)) { @@ -408,7 +407,7 @@ AString CHandler::GetPath(int index) const len--; AString path; - char *dest = path.GetBuffer(len) + len; + char *dest = path.GetBuf_SetEnd(len) + len; index = indexMem; for (;;) { @@ -425,7 +424,6 @@ AString CHandler::GetPath(int index) const break; *(--dest) = CHAR_PATH_SEPARATOR; } - path.ReleaseBuffer(len); return path; } @@ -565,10 +563,6 @@ HRESULT CCramfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSi return Handler->ReadBlock(blockIndex, dest, blockSize); } -static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } -static void SzFree(void *p, void *address) { p = p; MyFree(address); } -static ISzAlloc g_Alloc = { SzAlloc, SzFree }; - HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) { if (_method == k_Flags_Method_ZLIB) @@ -789,15 +783,11 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -IMP_CreateArcIn - -static CArcInfo g_ArcInfo = - { "CramFS", "cramfs", 0, 0xD3, - kSignatureSize, SIGNATURE, +REGISTER_ARC_I( + "CramFS", "cramfs", 0, 0xD3, + kSignature, 16, 0, - CreateArc }; - -REGISTER_ARC(Cramfs) + NULL) }} diff --git a/CPP/7zip/Archive/DllExports.cpp b/CPP/7zip/Archive/DllExports.cpp index 37f53cd7..7aee235e 100644 --- a/CPP/7zip/Archive/DllExports.cpp +++ b/CPP/7zip/Archive/DllExports.cpp @@ -13,10 +13,13 @@ #include "../../Windows/NtCheck.h" #include "../../Windows/PropVariant.h" -#include "IArchive.h" #include "../ICoder.h" #include "../IPassword.h" +#include "../Common/CreateCoder.h" + +#include "IArchive.h" + HINSTANCE g_hInstance; #define NT_CHECK_FAIL_ACTION return FALSE; @@ -33,7 +36,10 @@ BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) } DEFINE_GUID(CLSID_CArchiveHandler, -0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); + k_7zip_GUID_Data1, + k_7zip_GUID_Data2, + k_7zip_GUID_Data3_Common, + 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject); @@ -49,3 +55,40 @@ STDAPI SetLargePageMode() #endif return S_OK; } + +extern bool g_CaseSensitive; + +STDAPI SetCaseSensitive(Int32 caseSensitive) +{ + g_CaseSensitive = (caseSensitive != 0); + return S_OK; +} + +#ifdef EXTERNAL_CODECS + +CExternalCodecs g_ExternalCodecs; + +STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo) +{ + COM_TRY_BEGIN + + // OutputDebugStringA(compressCodecsInfo ? "SetCodecs" : "SetCodecs NULL"); + if (compressCodecsInfo) + { + g_ExternalCodecs.GetCodecs = compressCodecsInfo; + return g_ExternalCodecs.Load(); + } + g_ExternalCodecs.ClearAndRelease(); + return S_OK; + + COM_TRY_END +} + +#else + +STDAPI SetCodecs(ICompressCodecsInfo *) +{ + return S_OK; +} + +#endif diff --git a/CPP/7zip/Archive/DllExports2.cpp b/CPP/7zip/Archive/DllExports2.cpp index aa023524..2b196abe 100644 --- a/CPP/7zip/Archive/DllExports2.cpp +++ b/CPP/7zip/Archive/DllExports2.cpp @@ -16,6 +16,8 @@ #include "../ICoder.h" #include "../IPassword.h" +#include "../Common/CreateCoder.h" + #include "IArchive.h" HINSTANCE g_hInstance; @@ -33,23 +35,28 @@ BOOL WINAPI DllMain( { if (dwReason == DLL_PROCESS_ATTACH) { + // OutputDebugStringA("7z.dll DLL_PROCESS_ATTACH"); g_hInstance = (HINSTANCE)hInstance; NT_CHECK; } + /* + if (dwReason == DLL_PROCESS_DETACH) + { + OutputDebugStringA("7z.dll DLL_PROCESS_DETACH"); + } + */ return TRUE; } DEFINE_GUID(CLSID_CArchiveHandler, -0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); - -static const UInt16 kDecodeId = 0x2790; - -DEFINE_GUID(CLSID_CCodec, -0x23170F69, 0x40C1, kDecodeId, 0, 0, 0, 0, 0, 0, 0, 0); + k_7zip_GUID_Data1, + k_7zip_GUID_Data2, + k_7zip_GUID_Data3_Common, + 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateHasher(const GUID *clsid, IHasher **hasher); -STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject); +STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) { @@ -80,3 +87,32 @@ STDAPI SetCaseSensitive(Int32 caseSensitive) g_CaseSensitive = (caseSensitive != 0); return S_OK; } + +#ifdef EXTERNAL_CODECS + +CExternalCodecs g_ExternalCodecs; + +STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo) +{ + COM_TRY_BEGIN + + // OutputDebugStringA(compressCodecsInfo ? "SetCodecs" : "SetCodecs NULL"); + if (compressCodecsInfo) + { + g_ExternalCodecs.GetCodecs = compressCodecsInfo; + return g_ExternalCodecs.Load(); + } + g_ExternalCodecs.ClearAndRelease(); + return S_OK; + + COM_TRY_END +} + +#else + +STDAPI SetCodecs(ICompressCodecsInfo *) +{ + return S_OK; +} + +#endif diff --git a/CPP/7zip/Archive/DmgHandler.cpp b/CPP/7zip/Archive/DmgHandler.cpp index 7166f2ce..208f2a82 100644 --- a/CPP/7zip/Archive/DmgHandler.cpp +++ b/CPP/7zip/Archive/DmgHandler.cpp @@ -48,6 +48,7 @@ static Byte *Base64ToBin(Byte *dest, const char *src) { UInt32 val = 1; UInt32 c = k_Base64Table[(Byte)(*src++)]; + for (;;) { /* @@ -88,12 +89,14 @@ static Byte *Base64ToBin(Byte *dest, const char *src) break; c = k_Base64Table[(Byte)(*src++)]; } + if (val >= ((UInt32)1 << 12)) { if (val >= ((UInt32)1 << 18)) *dest++ = (Byte)(val >> 16); *dest++ = (Byte)(val); } + return dest; } @@ -195,7 +198,8 @@ public: STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; -const UInt32 kXmlSizeMax = ((UInt32)1 << 31) - (1 << 14); +// that limit can be increased, if there are such dmg files +static const size_t kXmlSizeMax = 0xFFFF0000; // 4 GB - 64 KB; struct CMethods { @@ -216,7 +220,9 @@ void CMethods::Update(const CFile &file) void CMethods::GetString(AString &res) const { res.Empty(); + unsigned i; + for (i = 0; i < Types.Size(); i++) { UInt32 type = Types[i]; @@ -234,10 +240,10 @@ void CMethods::GetString(AString &res) const case METHOD_BZIP2: s = "BZip2"; break; default: ConvertUInt32ToString(type, buf); s = buf; } - if (!res.IsEmpty()) - res += ' '; + res.Add_Space_if_NotEmpty(); res += s; } + for (i = 0; i < ChecksumTypes.Size(); i++) { UInt32 type = ChecksumTypes[i]; @@ -250,8 +256,7 @@ void CMethods::GetString(AString &res) const ConvertUInt32ToString(type, MyStpCpy(buf, "Check")); s = buf; } - if (!res.IsEmpty()) - res += ' '; + res.Add_Space_if_NotEmpty(); res += s; } } @@ -325,8 +330,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidMainSubfile: { int mainIndex = -1; - int numFS = 0; - int numUnknown = 0; + unsigned numFS = 0; + unsigned numUnknown = 0; FOR_VECTOR (i, _files) { const AString &name = _files[i].Name; @@ -334,7 +339,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) for (n = 0; n < kNumAppleNames; n++) { const CAppleName &appleName = k_Names[n]; - if (name.Find(appleName.AppleName) >= 0) + // if (name.Find(appleName.AppleName) >= 0) + if (strstr(name, appleName.AppleName)) { if (appleName.IsFs) { @@ -404,6 +410,7 @@ HRESULT CFile::Parse(const Byte *p, UInt32 size) p += kHeadSize; UInt32 i; + for (i = 0; i < numBlocks; i++, p += kRecordSize) { CBlock b; @@ -426,6 +433,7 @@ HRESULT CFile::Parse(const Byte *p, UInt32 size) if (b.Type == METHOD_END) break; PackSize += b.PackSize; + if (b.UnpSize != 0) { if (b.Type == METHOD_ZERO_2) @@ -433,12 +441,14 @@ HRESULT CFile::Parse(const Byte *p, UInt32 size) Blocks.AddInReserved(b); } } + if (i != numBlocks - 1) return S_FALSE; if (!Blocks.IsEmpty()) Size = Blocks.Back().GetNextUnpPos(); if (Size != (numSectors << 9)) return S_FALSE; + return S_OK; } @@ -463,8 +473,12 @@ static const AString *GetStringFromKeyPair(const CXmlItem &item, const AString & static const unsigned HEADER_SIZE = 0x200; -static bool IsKoly(const Byte *p) +static const Byte k_Signature[] = { 'k','o','l','y', 0, 0, 0, 4, 0, 0, 2, 0 }; + +static inline bool IsKoly(const Byte *p) { + return memcmp(p, k_Signature, ARRAY_SIZE(k_Signature)) == 0; + /* if (Get32(p) != 0x6B6F6C79) // "koly" signature return false; if (Get32(p + 4) != 4) // version @@ -472,6 +486,7 @@ static bool IsKoly(const Byte *p) if (Get32(p + 8) != HEADER_SIZE) return false; return true; + */ } HRESULT CHandler::Open2(IInStream *stream) @@ -510,6 +525,14 @@ HRESULT CHandler::Open2(IInStream *stream) UInt64 xmlOffset = Get64(buf + 0xD8); UInt64 xmlLen = Get64(buf + 0xE0); + if ( headerPos < dataForkOffset + || headerPos - dataForkOffset < dataForkLen + || headerPos < rsrcOffset + || headerPos - rsrcOffset < rsrcLen + || headerPos < xmlOffset + || headerPos - xmlOffset < xmlLen) + return S_FALSE; + UInt64 totalLen = dataForkLen + rsrcLen + xmlLen; if (totalLen > headerPos) return S_FALSE; @@ -517,14 +540,6 @@ HRESULT CHandler::Open2(IInStream *stream) _phySize = totalLen + HEADER_SIZE; headerPos = totalLen; - if (headerPos < dataForkOffset || - headerPos < dataForkOffset + dataForkLen || - headerPos < rsrcOffset || - headerPos < rsrcOffset + rsrcLen || - headerPos < xmlOffset || - headerPos < xmlOffset + xmlLen) - return S_FALSE; - // Byte reserved[0x78] CChecksum masterChecksum; @@ -620,9 +635,7 @@ HRESULT CHandler::Open2(IInStream *stream) ConvertUInt32ToString(_files.Size(), extraName); extra.Name = extraName; } - CByteBuffer &rawBuf = extra.Data; - rawBuf.SetCapacity(blockSize); - memcpy(rawBuf, pBlock + 4, blockSize); + extra.Data.CopyFrom(pBlock + 4, blockSize); } #endif @@ -638,10 +651,10 @@ HRESULT CHandler::Open2(IInStream *stream) return S_FALSE; for (UInt32 r = 1; r <= nameLen; r++) { - char c = namePtr[r]; + Byte c = namePtr[r]; if (c < 0x20 || c >= 0x80) break; - file.Name += c; + file.Name += (char)c; } } RINOK(file.Parse(pBlock + 4, blockSize)); @@ -652,36 +665,28 @@ HRESULT CHandler::Open2(IInStream *stream) { if (xmlLen >= kXmlSizeMax || xmlLen == 0) return S_FALSE; - RINOK(stream->Seek(_startPos + dataForkLen, STREAM_SEEK_SET, NULL)); size_t size = (size_t)xmlLen; + if (size != xmlLen) + return S_FALSE; + + RINOK(stream->Seek(_startPos + dataForkLen, STREAM_SEEK_SET, NULL)); CXml xml; { - AString xmlStr; - char *ss = xmlStr.GetBuffer((int)size + 1); - RINOK(ReadStream_FALSE(stream, ss, size)); - ss[size] = 0; - { - const char *p = ss; - for (;;) - { - if (*p == 0) break; p++; - if (*p == 0) break; p++; - if (*p == 0) break; p++; - if (*p == 0) break; p++; - } - xmlStr.ReleaseBuffer((int)(p - ss)); - } + CObjArray<char> xmlStr(size + 1); + RINOK(ReadStream_FALSE(stream, xmlStr, size)); + xmlStr[size] = 0; + // if (strlen(xmlStr) != size) return S_FALSE; if (!xml.Parse(xmlStr)) return S_FALSE; #ifdef DMG_SHOW_RAW CExtraFile &extra = _extras.AddNew(); extra.Name = "a.xml"; - extra.Data.SetCapacity(size); - memcpy(extra.Data, ss, size); + extra.Data.CopyFrom((const Byte *)(const char *)xmlStr, size); #endif } + if (xml.Root.Name != "plist") return S_FALSE; @@ -708,14 +713,14 @@ HRESULT CHandler::Open2(IInStream *stream) continue; CByteBuffer rawBuf; - int destLen = 0; + unsigned destLen = 0; { const AString *dataString = GetStringFromKeyPair(item, "Data", "data"); if (!dataString) return S_FALSE; destLen = dataString->Len() / 4 * 3 + 4; rawBuf.Alloc(destLen); - destLen = (int)(Base64ToBin(rawBuf, *dataString) - rawBuf); + destLen = (unsigned)(Base64ToBin(rawBuf, *dataString) - rawBuf); #ifdef DMG_SHOW_RAW CExtraFile &extra = _extras.AddNew(); { @@ -723,8 +728,7 @@ HRESULT CHandler::Open2(IInStream *stream) ConvertUInt32ToString(_files.Size(), extraName); extra.Name = extraName; } - extra.Data.SetCapacity(destLen); - memcpy(extra.Data, rawBuf, destLen); + extra.Data.CopyFrom(rawBuf, destLen); #endif } CFile &file = _files.AddNew(); @@ -805,7 +809,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val NWindows::NCOM::CPropVariant prop; #ifdef DMG_SHOW_RAW - if ((int)index >= _files.Size()) + if (index >= _files.Size()) { const CExtraFile &extra = _extras[index - _files.Size()]; switch (propID) @@ -897,7 +901,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val UString name2; ConvertUTF8ToUnicode(item.Name, name2); if (!name2.IsEmpty()) - name += L" - "; + name.AddAscii(" - "); name += name2; } prop = name; @@ -1060,9 +1064,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, return S_OK; UInt64 totalSize = 0; UInt32 i; + for (i = 0; i < numItems; i++) { - int index = (int)(allFilesMode ? i : indices[i]); + UInt32 index = (allFilesMode ? i : indices[i]); #ifdef DMG_SHOW_RAW if (index >= _files.Size()) totalSize += _extras[index - _files.Size()].Data.Size(); @@ -1112,7 +1117,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 askMode = testMode ? NExtract::NAskMode::kTest : NExtract::NAskMode::kExtract; - Int32 index = allFilesMode ? i : indices[i]; + UInt32 index = allFilesMode ? i : indices[i]; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); if (!testMode && !realOutStream) @@ -1225,6 +1230,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, opRes = NExtract::NOperationResult::kUnsupportedMethod; break; } + if (res != S_OK) { if (res != S_FALSE) @@ -1232,7 +1238,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (opRes == NExtract::NOperationResult::kOK) opRes = NExtract::NOperationResult::kDataError; } + unpPos += block.UnpSize; + if (!outStreamSpec->IsFinishedOK()) { if (realMethod && opRes == NExtract::NOperationResult::kOK) @@ -1247,6 +1255,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } } } + if (needCrc && opRes == NExtract::NOperationResult::kOK) { if (outCrcStreamSpec->GetCRC() != item.Checksum.GetCrc32()) @@ -1256,6 +1265,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, outStream.Release(); RINOK(extractCallback->SetOperationResult(opRes)); } + return S_OK; COM_TRY_END } @@ -1322,12 +1332,12 @@ public: }; -int FindBlock(const CRecordVector<CBlock> &blocks, UInt64 pos) +unsigned FindBlock(const CRecordVector<CBlock> &blocks, UInt64 pos) { - int left = 0, right = blocks.Size(); + unsigned left = 0, right = blocks.Size(); for (;;) { - int mid = (left + right) / 2; + unsigned mid = (left + right) / 2; if (mid == left) return left; if (pos < blocks[mid].UnpPos) @@ -1359,23 +1369,27 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) if (_virtPos < block.UnpPos || (_virtPos - block.UnpPos) >= block.UnpSize) _latestBlock = -1; } + if (_latestBlock < 0) { _latestChunk = -1; - int blockIndex = FindBlock(File->Blocks, _virtPos); + unsigned blockIndex = FindBlock(File->Blocks, _virtPos); const CBlock &block = File->Blocks[blockIndex]; + if (!block.IsZeroMethod() && block.Type != METHOD_COPY) { unsigned i; for (i = 0; i < _chunks.Size(); i++) - if (_chunks[i].BlockIndex == blockIndex) + if (_chunks[i].BlockIndex == (int)blockIndex) break; + if (i != _chunks.Size()) _latestChunk = i; else { - const int kNumChunksMax = 128; - int chunkIndex; + const unsigned kNumChunksMax = 128; + unsigned chunkIndex; + if (_chunks.Size() != kNumChunksMax) chunkIndex = _chunks.Add(CChunk()); else @@ -1385,9 +1399,11 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) if (_chunks[i].AccessMark < _chunks[chunkIndex].AccessMark) chunkIndex = i; } + CChunk &chunk = _chunks[chunkIndex]; chunk.BlockIndex = -1; chunk.AccessMark = 0; + if (chunk.Buf.Size() < block.UnpSize) { chunk.Buf.Free(); @@ -1395,12 +1411,14 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) return E_FAIL; chunk.Buf.Alloc((size_t)block.UnpSize); } + outStreamSpec->Init(chunk.Buf, (size_t)block.UnpSize); RINOK(Stream->Seek(_startPos + File->StartPos + block.PackPos, STREAM_SEEK_SET, NULL)); limitedStreamSpec->Init(block.PackSize); HRESULT res = S_OK; + switch (block.Type) { case METHOD_COPY: @@ -1443,6 +1461,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) default: return E_FAIL; } + if (res != S_OK) return res; if (block.Type != METHOD_COPY && outStreamSpec->GetPos() != block.UnpSize) @@ -1450,8 +1469,10 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) chunk.BlockIndex = blockIndex; _latestChunk = chunkIndex; } + _chunks[_latestChunk].AccessMark = _accessMark++; } + _latestBlock = blockIndex; } @@ -1462,6 +1483,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) size = (UInt32)rem; HRESULT res = S_OK; + if (block.Type == METHOD_COPY) { RINOK(Stream->Seek(_startPos + File->StartPos + block.PackPos + offset, STREAM_SEEK_SET, NULL)); @@ -1469,11 +1491,13 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) } else if (block.IsZeroMethod()) memset(data, 0, size); - else + else if (size != 0) memcpy(data, _chunks[_latestChunk].Buf + offset, size); + _virtPos += size; if (processedSize) *processedSize = size; + return res; COM_TRY_END } @@ -1498,14 +1522,17 @@ STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPositio STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { COM_TRY_BEGIN + #ifdef DMG_SHOW_RAW if (index >= (UInt32)_files.Size()) return S_FALSE; #endif + CInStream *spec = new CInStream; CMyComPtr<ISequentialInStream> specStream = spec; spec->File = &_files[index]; const CFile &file = *spec->File; + FOR_VECTOR (i, file.Blocks) { const CBlock &block = file.Blocks[i]; @@ -1523,24 +1550,22 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) return S_FALSE; } } + spec->Stream = _inStream; spec->Size = spec->File->Size; RINOK(spec->InitAndSeek(_startPos)); *stream = specStream.Detach(); return S_OK; + COM_TRY_END } -IMP_CreateArcIn - -static CArcInfo g_ArcInfo = - { "Dmg", "dmg", 0, 0xE4, - 12, { 'k','o','l','y', 0, 0, 0, 4, 0, 0, 2, 0 }, +REGISTER_ARC_I( + "Dmg", "dmg", 0, 0xE4, + k_Signature, 0, NArcInfoFlags::kBackwardOpen | NArcInfoFlags::kUseGlobalOffset, - CreateArc }; - -REGISTER_ARC(Dmg) + NULL) }} diff --git a/CPP/7zip/Archive/ElfHandler.cpp b/CPP/7zip/Archive/ElfHandler.cpp index 5e378ba8..089d1023 100644 --- a/CPP/7zip/Archive/ElfHandler.cpp +++ b/CPP/7zip/Archive/ElfHandler.cpp @@ -963,15 +963,13 @@ STDMETHODIMP CHandler::AllowTail(Int32 allowTail) return S_OK; } -IMP_CreateArcIn +static const Byte k_Signature[] = { 0x7F, 'E', 'L', 'F' }; -static CArcInfo g_ArcInfo = - { "ELF", "elf", 0, 0xDE, - 4, { 0x7F, 'E', 'L', 'F' }, +REGISTER_ARC_I( + "ELF", "elf", 0, 0xDE, + k_Signature, 0, NArcInfoFlags::kPreArc, - CreateArc }; - -REGISTER_ARC(Elf) + NULL) }} diff --git a/CPP/7zip/Archive/FatHandler.cpp b/CPP/7zip/Archive/FatHandler.cpp index 970330cc..649d54bd 100644 --- a/CPP/7zip/Archive/FatHandler.cpp +++ b/CPP/7zip/Archive/FatHandler.cpp @@ -272,19 +272,27 @@ struct CItem UString GetVolName() const; }; -static int CopyAndTrim(char *dest, const char *src, int size, bool toLower) +static unsigned CopyAndTrim(char *dest, const char *src, unsigned size, bool toLower) { - int i; memcpy(dest, src, size); if (toLower) - for (i = 0; i < size; i++) + { + for (unsigned i = 0; i < size; i++) { char c = dest[i]; if (c >= 'A' && c <= 'Z') dest[i] = (char)(c + 0x20); } - for (i = size - 1; i >= 0 && dest[i] == ' '; i--); - return i + 1; + } + + for (unsigned i = size;;) + { + if (i == 0) + return 0; + if (dest[i - 1] != ' ') + return i; + i--; + } } static UString FatStringToUnicode(const char *s) @@ -295,11 +303,11 @@ static UString FatStringToUnicode(const char *s) UString CItem::GetShortName() const { char s[16]; - int i = CopyAndTrim(s, DosName, 8, NameIsLow()); + unsigned i = CopyAndTrim(s, DosName, 8, NameIsLow()); s[i++] = '.'; - int j = CopyAndTrim(s + i, DosName + 8, 3, ExtIsLow()); + unsigned j = CopyAndTrim(s + i, DosName + 8, 3, ExtIsLow()); if (j == 0) - j--; + i--; s[i + j] = 0; return FatStringToUnicode(s); } @@ -316,7 +324,7 @@ UString CItem::GetVolName() const if (!UName.IsEmpty()) return UName; char s[12]; - int i = CopyAndTrim(s, DosName, 11, false); + unsigned i = CopyAndTrim(s, DosName, 11, false); s[i] = 0; return FatStringToUnicode(s); } @@ -348,7 +356,7 @@ struct CDatabase UString GetItemPath(Int32 index) const; HRESULT Open(); - HRESULT ReadDir(Int32 parent, UInt32 cluster, int level); + HRESULT ReadDir(Int32 parent, UInt32 cluster, unsigned level); UInt64 GetHeadersSize() const { @@ -420,9 +428,9 @@ UString CDatabase::GetItemPath(Int32 index) const } } -static wchar_t *AddSubStringToName(wchar_t *dest, const Byte *p, int numChars) +static wchar_t *AddSubStringToName(wchar_t *dest, const Byte *p, unsigned numChars) { - for (int i = 0; i < numChars; i++) + for (unsigned i = 0; i < numChars; i++) { wchar_t c = Get16(p + i * 2); if (c != 0 && c != 0xFFFF) @@ -432,9 +440,9 @@ static wchar_t *AddSubStringToName(wchar_t *dest, const Byte *p, int numChars) return dest; } -HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level) +HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, unsigned level) { - int startIndex = Items.Size(); + unsigned startIndex = Items.Size(); if (startIndex >= (1 << 30) || level > 256) return S_FALSE; @@ -451,6 +459,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level) UString curName; int checkSum = -1; int numLongRecords = -1; + for (UInt32 pos = blockSize;; pos += 32) { if (pos == blockSize) @@ -483,7 +492,9 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level) RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize)); } + const Byte *p = ByteBuf + pos; + if (p[0] == 0) { /* @@ -493,6 +504,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level) */ break; } + if (p[0] == 0xE5) { if (numLongRecords > 0) @@ -545,7 +557,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level) if (checkSum >= 0) { Byte sum = 0; - for (int i = 0; i < 11; i++) + for (unsigned i = 0; i < 11; i++) sum = (Byte)(((sum & 1) ? 0x80 : 0) + (sum >> 1) + (Byte)item.DosName[i]); if (sum == checkSum) item.UName = curName; @@ -590,8 +602,8 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level) } } - int finishIndex = Items.Size(); - for (int i = startIndex; i < finishIndex; i++) + unsigned finishIndex = Items.Size(); + for (unsigned i = startIndex; i < finishIndex; i++) { const CItem &item = Items[i]; if (item.IsDir()) @@ -831,7 +843,7 @@ static void FatTimeToProp(UInt32 dosTime, UInt32 ms10, NWindows::NCOM::CPropVari } /* -static void StringToProp(const Byte *src, int size, NWindows::NCOM::CPropVariant &prop) +static void StringToProp(const Byte *src, unsigned size, NWindows::NCOM::CPropVariant &prop) { char dest[32]; memcpy(dest, src, size); @@ -1021,15 +1033,13 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } -IMP_CreateArcIn +static const Byte k_Signature[] = { 0x55, 0xAA }; -static CArcInfo g_ArcInfo = - { "FAT", "fat img", 0, 0xDA, - 2, { 0x55, 0xAA }, +REGISTER_ARC_I( + "FAT", "fat img", 0, 0xDA, + k_Signature, 0x1FE, 0, - CreateArc, NULL, IsArc_Fat }; - -REGISTER_ARC(Fat) + IsArc_Fat) }} diff --git a/CPP/7zip/Archive/FlvHandler.cpp b/CPP/7zip/Archive/FlvHandler.cpp index 577224b2..dafb250b 100644 --- a/CPP/7zip/Archive/FlvHandler.cpp +++ b/CPP/7zip/Archive/FlvHandler.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +// #include <stdio.h> + #include "../../../C/CpuArch.h" #include "../../Common/ComTry.h" @@ -69,12 +71,12 @@ class CHandler: { CMyComPtr<IInStream> _stream; CObjectVector<CItem2> _items2; - // CByteBuffer _metadata; + CByteBuffer _metadata; bool _isRaw; UInt64 _phySize; HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); - AString GetComment(); + // AString GetComment(); public: MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) @@ -195,10 +197,7 @@ AString CHandler::GetComment() break; { AString temp; - char *sz = temp.GetBuffer(len); - memcpy(sz, p, len); - sz[len] = 0; - temp.ReleaseBuffer(); + temp.SetFrom_CalcLen((const char *)p, len); if (!res.IsEmpty()) res += '\n'; res += temp; @@ -251,7 +250,6 @@ AString CHandler::GetComment() } return res; } - */ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) @@ -413,8 +411,11 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) src += kTagHeaderSize + 1; size -= (kTagHeaderSize + 4 + 1); } - memcpy(item2.BufSpec->Buf + item2.Size, src, size); - item2.Size += size; + if (size != 0) + { + memcpy(item2.BufSpec->Buf + item2.Size, src, size); + item2.Size += size; + } } return S_OK; } @@ -513,15 +514,13 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -IMP_CreateArcIn +static const Byte k_Signature[] = { 'F', 'L', 'V', 1, }; -static CArcInfo g_ArcInfo = - { "FLV", "flv", 0, 0xD6, - 4, { 'F', 'L', 'V', 1, }, +REGISTER_ARC_I( + "FLV", "flv", 0, 0xD6, + k_Signature, 0, 0, - CreateArc }; - -REGISTER_ARC(Flv) + NULL) }} diff --git a/CPP/7zip/Archive/GzHandler.cpp b/CPP/7zip/Archive/GzHandler.cpp index 766cefbf..d8979ada 100644 --- a/CPP/7zip/Archive/GzHandler.cpp +++ b/CPP/7zip/Archive/GzHandler.cpp @@ -44,10 +44,10 @@ namespace NGz { namespace NFlags { - const Byte kIsText = 1 << 0; - const Byte kCrc = 1 << 1; - const Byte kExtra = 1 << 2; - const Byte kName = 1 << 3; + const Byte kIsText = 1 << 0; + const Byte kCrc = 1 << 1; + const Byte kExtra = 1 << 2; + const Byte kName = 1 << 3; const Byte kComment = 1 << 4; const Byte kReserved = 0xE0; } @@ -85,7 +85,7 @@ namespace NGz { }; } -static const char *kHostOSes[] = +static const char * const kHostOSes[] = { "FAT" , "AMIGA" @@ -126,19 +126,44 @@ public: AString Comment; // CByteBuffer Extra; - // bool IsText() const { return TestFlag(NFlags::kIsText); } - bool HeaderCrcIsPresent() const { return TestFlag(NFlags::kCrc); } - bool ExtraFieldIsPresent() const { return TestFlag(NFlags::kExtra); } - bool NameIsPresent() const { return TestFlag(NFlags::kName); } - bool CommentIsPresent() const { return TestFlag(NFlags::kComment); } - bool IsSupported() const { return (Flags & NFlags::kReserved) == 0; } + CItem(): + Flags(0), + ExtraFlags(0), + HostOS(0), + Time(0), + Crc(0), + Size32(0) {} void Clear() { Name.Empty(); Comment.Empty(); - // Extra.SetCapacity(0); + // Extra.Free(); + } + + void CopyMetaPropsFrom(const CItem &a) + { + Flags = a.Flags; + HostOS = a.HostOS; + Time = a.Time; + Name = a.Name; + Comment = a.Comment; + // Extra = a.Extra; + } + + void CopyDataPropsFrom(const CItem &a) + { + ExtraFlags = a.ExtraFlags; + Crc = a.Crc; + Size32 = a.Size32; } + + // bool IsText() const { return TestFlag(NFlags::kIsText); } + bool HeaderCrcIsPresent() const { return TestFlag(NFlags::kCrc); } + bool ExtraFieldIsPresent() const { return TestFlag(NFlags::kExtra); } + bool NameIsPresent() const { return TestFlag(NFlags::kName); } + bool CommentIsPresent() const { return TestFlag(NFlags::kComment); } + bool IsSupported() const { return (Flags & NFlags::kReserved) == 0; } HRESULT ReadHeader(NDecoder::CCOMCoder *stream); HRESULT ReadFooter1(NDecoder::CCOMCoder *stream); @@ -459,7 +484,7 @@ public: INTERFACE_IInArchive(;) INTERFACE_IOutArchive(;) STDMETHOD(OpenSeq)(ISequentialInStream *stream); - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); + STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); CHandler() { @@ -510,7 +535,11 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) } case kpidName: if (_item.NameIsPresent()) - prop = MultiByteToUnicodeString(_item.Name, CP_ACP) + L".gz"; + { + UString s = MultiByteToUnicodeString(_item.Name, CP_ACP); + s.AddAscii(".gz"); + prop = s; + } break; } prop.Detach(value); @@ -656,7 +685,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; - // if (_stream) extractCallback->SetTotal(_packSize); + if (_packSize_Defined) + extractCallback->SetTotal(_packSize); // UInt64 currentTotalPacked = 0; // RINOK(extractCallback->SetCompleted(¤tTotalPacked)); CMyComPtr<ISequentialOutStream> realOutStream; @@ -794,6 +824,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, result = S_FALSE; break; } + + // break; // we can use break, if we need only first stream } } catch(const CInBufferException &e) { return e.ErrorCode; } @@ -844,7 +876,7 @@ static const Byte kHostOS = static HRESULT UpdateArchive( ISequentialOutStream *outStream, UInt64 unpackSize, - const CItem &newItem, + CItem &item, const CSingleMethodProps &props, IArchiveUpdateCallback *updateCallback) { @@ -865,7 +897,6 @@ static HRESULT UpdateArchive( CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); - CItem item = newItem; item.ExtraFlags = props.GetLevel() >= 7 ? NExtraFlags::kMaximum : NExtraFlags::kFastest; @@ -894,6 +925,8 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { + COM_TRY_BEGIN + if (numItems != 1) return E_INVALIDARG; @@ -903,11 +936,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt return E_FAIL; RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive)); - CItem newItem = _item; - newItem.ExtraFlags = 0; - newItem.Flags = 0; - if (IntToBool(newProps)) + CItem newItem; + + if (!IntToBool(newProps)) + { + newItem.CopyMetaPropsFrom(_item); + } + else { + newItem.HostOS = kHostOS; { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(0, kpidMTime, &prop)); @@ -924,9 +961,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (prop.vt == VT_BSTR) { UString name = prop.bstrVal; - int dirDelimiterPos = name.ReverseFind(WCHAR_PATH_SEPARATOR); - if (dirDelimiterPos >= 0) - name = name.Ptr(dirDelimiterPos + 1); + int slashPos = name.ReverseFind_PathSepar(); + if (slashPos >= 0) + name.DeleteFrontal(slashPos + 1); newItem.Name = UnicodeStringToMultiByte(name, CP_ACP); if (!newItem.Name.IsEmpty()) newItem.Flags |= NFlags::kName; @@ -937,13 +974,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop)); - if (prop.vt == VT_BOOL) - { - if (prop.boolVal != VARIANT_FALSE) + if (prop.vt != VT_EMPTY) + if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE) return E_INVALIDARG; - } - else if (prop.vt != VT_EMPTY) - return E_INVALIDARG; } } @@ -959,13 +992,28 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt } return UpdateArchive(outStream, size, newItem, _props, updateCallback); } - + if (indexInArchive != 0) return E_INVALIDARG; if (!_stream) return E_NOTIMPL; + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(updateCallback, true); + + CMyComPtr<IArchiveUpdateCallbackFile> opCallback; + updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback); + if (opCallback) + { + RINOK(opCallback->ReportOperation( + NEventIndexType::kInArcIndex, 0, + NUpdateNotifyOp::kReplicate)) + } + + newItem.CopyDataPropsFrom(_item); + UInt64 offset = 0; if (IntToBool(newProps)) { @@ -973,24 +1021,24 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt offset += _headerSize; } RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); - return NCompress::CopyStream(_stream, outStream, NULL); + + return NCompress::CopyStream(_stream, outStream, progress); + + COM_TRY_END } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) +STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) { return _props.SetProperties(names, values, numProps); } -IMP_CreateArcIn -IMP_CreateArcOut +static const Byte k_Signature[] = { kSignature_0, kSignature_1, kSignature_2 }; -static CArcInfo g_ArcInfo = - { "gzip", "gz gzip tgz tpz", "* * .tar .tar", 0xEF, - 3, { kSignature_0, kSignature_1, kSignature_2 }, +REGISTER_ARC_IO( + "gzip", "gz gzip tgz tpz", "* * .tar .tar", 0xEF, + k_Signature, 0, NArcInfoFlags::kKeepName, - REF_CreateArc_Pair, IsArc_Gz }; - -REGISTER_ARC(GZip) + IsArc_Gz) }} diff --git a/CPP/7zip/Archive/HfsHandler.cpp b/CPP/7zip/Archive/HfsHandler.cpp index ca1370d8..8459280d 100644 --- a/CPP/7zip/Archive/HfsHandler.cpp +++ b/CPP/7zip/Archive/HfsHandler.cpp @@ -28,7 +28,7 @@ namespace NArchive { namespace NHfs { -static const wchar_t *kResFileName = L"rsrc"; // L"com.apple.ResourceFork"; +static const char *kResFileName = "rsrc"; // "com.apple.ResourceFork"; struct CExtent { @@ -655,12 +655,17 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec static void LoadName(const Byte *data, unsigned len, UString &dest) { - wchar_t *p = dest.GetBuffer(len); + wchar_t *p = dest.GetBuf(len); unsigned i; for (i = 0; i < len; i++) - p[i] = Get16(data + i * 2); + { + wchar_t c = Get16(data + i * 2); + if (c == 0) + break; + p[i] = c; + } p[i] = 0; - dest.ReleaseBuffer(); + dest.ReleaseBuf_SetLen(i); } static bool IsNameEqualTo(const Byte *data, const char *name) @@ -805,7 +810,7 @@ static const UInt32 kMethod_Resource = 4; // data stored in resource fork bool CDatabase::Parse_decmpgfs(const CAttr &attr, CItem &item, bool &skip) { skip = false; - if (attr.Name != L"com.apple.decmpfs") + if (!attr.Name.IsEqualTo("com.apple.decmpfs")) return true; if (item.UseAttr || !item.DataFork.IsEmpty()) return false; @@ -961,13 +966,13 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents IsNameEqualTo(name + 8, "HFS+ Private Data")) { // it's folder for "Hard Links" files - item.Name = L"[HFS+ Private Data]"; + item.Name.SetFromAscii("[HFS+ Private Data]"); } } // Some dmg files have ' ' folder item. if (item.Name.IsEmpty() || item.Name[0] == L' ') - item.Name = L"[]"; + item.Name.SetFromAscii("[]"); } } @@ -1221,7 +1226,7 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress) return S_FALSE; */ - ResFileName = kResFileName; + ResFileName.SetFromAscii(kResFileName); CFork extentsFork, catalogFork, attrFork; // allocationFork.Parse(p + 0x70 + 0x50 * 0); @@ -1856,19 +1861,15 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) return GetForkStream(item.GetFork(ref.IsResource), stream); } -IMP_CreateArcIn - -static CArcInfo g_ArcInfo = - { "HFS", "hfs hfsx", 0, 0xE3, - 2 * (4 + 1), - { +static const Byte k_Signature[] = { 4, 'H', '+', 0, 4, - 4, 'H', 'X', 0, 5, - }, + 4, 'H', 'X', 0, 5 }; + +REGISTER_ARC_I( + "HFS", "hfs hfsx", 0, 0xE3, + k_Signature, kHeaderPadSize, NArcInfoFlags::kMultiSignature, - CreateArc }; - -REGISTER_ARC(Hfs) + NULL) }} diff --git a/CPP/7zip/Archive/IArchive.h b/CPP/7zip/Archive/IArchive.h index a57a9b8f..84a4cc4b 100644 --- a/CPP/7zip/Archive/IArchive.h +++ b/CPP/7zip/Archive/IArchive.h @@ -82,10 +82,22 @@ namespace NArchive kUnexpectedEnd, kDataAfterEnd, kIsNotArc, - kHeadersError + kHeadersError, + kWrongPassword }; } } + + namespace NEventIndexType + { + enum + { + kNoIndex = 0, + kInArcIndex, + kBlockIndex, + kOutArcIndex + }; + } namespace NUpdate { @@ -110,17 +122,59 @@ ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10) }; /* -IArchiveExtractCallback::GetStream - Result: +IArchiveExtractCallback:: + +7-Zip doesn't call IArchiveExtractCallback functions + GetStream() + PrepareOperation() + SetOperationResult() +from different threads simultaneously. +But 7-Zip can call functions for IProgress or ICompressProgressInfo functions +from another threads simultaneously with calls for IArchiveExtractCallback interface. + +IArchiveExtractCallback::GetStream() + UInt32 index - index of item in Archive + Int32 askExtractMode (Extract::NAskMode) + if (askMode != NExtract::NAskMode::kExtract) + { + then the callee can not real stream: (*inStream == NULL) + } + + Out: (*inStream == NULL) - for directories (*inStream == NULL) - if link (hard link or symbolic link) was created + if (*inStream == NULL && askMode == NExtract::NAskMode::kExtract) + { + then the caller must skip extracting of that file. + } + + returns: + S_OK : OK + S_FALSE : data error (for decoders) + +if (IProgress::SetTotal() was called) +{ + IProgress::SetCompleted(completeValue) uses + packSize - for some stream formats (xz, gz, bz2, lzma, z, ppmd). + unpackSize - for another formats. +} +else +{ + IProgress::SetCompleted(completeValue) uses packSize. +} + +SetOperationResult() + 7-Zip calls SetOperationResult at the end of extracting, + so the callee can close the file, set attributes, timestamps and security information. + + Int32 opRes (NExtract::NOperationResult) */ #define INTERFACE_IArchiveExtractCallback(x) \ INTERFACE_IProgress(x) \ STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \ STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \ - STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \ + STDMETHOD(SetOperationResult)(Int32 opRes) x; \ ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20) { @@ -128,6 +182,25 @@ ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20) }; + +/* +IArchiveExtractCallbackMessage can be requested from IArchiveExtractCallback object + by Extract() or UpdateItems() functions to report about extracting errors +ReportExtractResult() + UInt32 indexType (NEventIndexType) + UInt32 index + Int32 opRes (NExtract::NOperationResult) +*/ + +#define INTERFACE_IArchiveExtractCallbackMessage(x) \ + STDMETHOD(ReportExtractResult)(UInt32 indexType, UInt32 index, Int32 opRes) x; \ + +ARCHIVE_INTERFACE_SUB(IArchiveExtractCallbackMessage, IProgress, 0x21) +{ + INTERFACE_IArchiveExtractCallbackMessage(PURE) +}; + + #define INTERFACE_IArchiveOpenVolumeCallback(x) \ STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \ @@ -183,9 +256,6 @@ Notes: Some IInArchive handlers will work incorrectly in that case. */ -/* MSVC allows the code where there is throw() in declaration of function, - but there is no throw() in definition of function. */ - #ifdef _MSC_VER #define MY_NO_THROW_DECL_ONLY throw() #else @@ -202,7 +272,7 @@ Notes: STDMETHOD(GetNumberOfProperties)(UInt32 *numProps) MY_NO_THROW_DECL_ONLY x; \ STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x; \ STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProps) MY_NO_THROW_DECL_ONLY x; \ - STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x; + STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x; \ ARCHIVE_INTERFACE(IInArchive, 0x60) { @@ -324,6 +394,8 @@ The order of calling for hard links: - GetStream() - GetProperty(kpidHardLink) +SetOperationResult() + Int32 opRes (NExtract::NOperationResult::kOK) */ #define INTERFACE_IArchiveUpdateCallback(x) \ @@ -348,6 +420,40 @@ ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82) INTERFACE_IArchiveUpdateCallback2(PURE); }; +namespace NUpdateNotifyOp +{ + enum + { + kAdd = 0, + kUpdate, + kAnalyze, + kReplicate, + kRepack, + kSkip, + kDelete, + kHeader + + // kNumDefined + }; +}; + +/* +IArchiveUpdateCallbackFile::ReportOperation + UInt32 indexType (NEventIndexType) + UInt32 index + UInt32 notifyOp (NUpdateNotifyOp) +*/ + +#define INTERFACE_IArchiveUpdateCallbackFile(x) \ + STDMETHOD(GetStream2)(UInt32 index, ISequentialInStream **inStream, UInt32 notifyOp) x; \ + STDMETHOD(ReportOperation)(UInt32 indexType, UInt32 index, UInt32 notifyOp) x; \ + +ARCHIVE_INTERFACE(IArchiveUpdateCallbackFile, 0x83) +{ + INTERFACE_IArchiveUpdateCallbackFile(PURE); +}; + + /* UpdateItems() ------------- @@ -382,7 +488,7 @@ ARCHIVE_INTERFACE(IOutArchive, 0xA0) ARCHIVE_INTERFACE(ISetProperties, 0x03) { - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) PURE; + STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) PURE; }; ARCHIVE_INTERFACE(IArchiveKeepModeForNextOpen, 0x04) diff --git a/CPP/7zip/Archive/IhexHandler.cpp b/CPP/7zip/Archive/IhexHandler.cpp index 00816f0c..00ff80a7 100644 --- a/CPP/7zip/Archive/IhexHandler.cpp +++ b/CPP/7zip/Archive/IhexHandler.cpp @@ -85,7 +85,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val const CBlock &block = _blocks[index]; switch (propID) { - case kpidSize: prop = block.Data.GetPos(); break; + case kpidSize: prop = (UInt64)block.Data.GetPos(); break; case kpidVa: prop = block.Offset; break; case kpidPath: { @@ -103,7 +103,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val COM_TRY_END } -static inline int HexToByte(char c) +static inline int HexToByte(unsigned c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'A' && c <= 'F') return c - 'A' + 10; @@ -138,9 +138,9 @@ API_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size) p++; size--; - const int kNumLinesToCheck = 3; // 1 line is OK also, but we don't want false detection + const unsigned kNumLinesToCheck = 3; // 1 line is OK also, but we don't want false detection - for (int j = 0; j < kNumLinesToCheck; j++) + for (unsigned j = 0; j < kNumLinesToCheck; j++) { if (size < 4 * 2) return k_IsArc_Res_NEED_MORE; @@ -279,7 +279,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb } { - size_t numPairs = (num + 4); + size_t numPairs = ((unsigned)num + 4); size_t numBytes = numPairs * 2; if (s.ReadBytes(temp, numBytes) != numBytes) { @@ -287,7 +287,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb return S_FALSE; } - int sum = num; + unsigned sum = num; for (size_t i = 0; i < numPairs; i++) { int a = Parse(temp + i * 2); @@ -339,7 +339,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb block = &_blocks.AddNew(); block->Offset = offs; } - memcpy(block->Data.GetCurPtrAndGrow(num), temp + 3, num); + block->Data.AddData(temp + 3, (unsigned)num); } } else if (type == kType_Eof) @@ -486,16 +486,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } -IMP_CreateArcIn +// k_Signature: { ':', '1' } -static CArcInfo g_ArcInfo = - { "IHex", "ihex", 0, 0xCD, - 0, { 0 }, - // 2, { ':', '1' }, +REGISTER_ARC_I_NO_SIG( + "IHex", "ihex", 0, 0xCD, 0, NArcInfoFlags::kStartOpen, - CreateArc, NULL, IsArc_Ihex }; - -REGISTER_ARC(Z) + IsArc_Ihex) }} diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp index aef920b0..713764d9 100644 --- a/CPP/7zip/Archive/Iso/IsoHandler.cpp +++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp @@ -79,8 +79,7 @@ static void AddString(AString &s, const char *name, const Byte *p, unsigned size if (i != 0) { AString d; - memcpy(d.GetBuffer(i), p, i); - d.ReleaseBuffer(i); + d.SetFrom((const char *)p, i); s += '\n'; s += name; s += ": "; @@ -170,11 +169,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { case kpidPath: { - // char name[16]; - // ConvertUInt32ToString(index + 1, name); AString s = "[BOOT]" STRING_PATH_SEPARATOR; - // s += name; - // s += '-'; + if (_archive.BootEntries.Size() != 1) + { + char temp[16]; + ConvertUInt32ToString(index + 1, temp); + s += temp; + s += '-'; + } s += be.GetName(); prop = s; break; @@ -197,18 +199,18 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { UString s; if (_archive.IsJoliet()) - s = item.GetPathU(); + item.GetPathU(s); else s = MultiByteToUnicodeString(item.GetPath(_archive.IsSusp, _archive.SuspSkipSize), CP_OEMCP); - int pos = s.ReverseFind(L';'); - if (pos >= 0 && pos == (int)s.Len() - 2) - if (s.Back() == L'1') - s.DeleteFrom(pos); - if (!s.IsEmpty()) - if (s.Back() == L'.') - s.DeleteBack(); - prop = (const wchar_t *)NItemName::GetOSName2(s); + if (s.Len() >= 2 && s[s.Len() - 2] == ';' && s.Back() == '1') + s.DeleteFrom(s.Len() - 2); + + if (!s.IsEmpty() && s.Back() == L'.') + s.DeleteBack(); + + NItemName::ConvertToOSName2(s); + prop = s; } break; case kpidIsDir: prop = item.IsDir(); break; @@ -319,8 +321,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UInt64 offset = 0; for (UInt32 e = 0; e < ref.NumExtents; e++) { - if (e != 0) - lps->InSize = lps->OutSize = currentTotalSize + offset; + lps->InSize = lps->OutSize = currentTotalSize + offset; const CDir &item2 = ref.Dir->_subItems[ref.Index + e]; RINOK(_stream->Seek((UInt64)item2.ExtentLocation * _archive.BlockSize, STREAM_SEEK_SET, NULL)); streamSpec->Init(item2.Size); @@ -356,6 +357,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) *stream = 0; UInt64 blockIndex; UInt64 currentItemSize; + if (index < (UInt32)_archive.Refs.Size()) { const CRef &ref = _archive.Refs[index]; @@ -402,6 +404,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) currentItemSize = _archive.GetBootItemSize(bootIndex); blockIndex = be.LoadRBA; } + return CreateLimitedInStream(_stream, blockIndex * _archive.BlockSize, currentItemSize, stream); COM_TRY_END } diff --git a/CPP/7zip/Archive/Iso/IsoHeader.cpp b/CPP/7zip/Archive/Iso/IsoHeader.cpp index 1cd2516c..59c283c1 100644 --- a/CPP/7zip/Archive/Iso/IsoHeader.cpp +++ b/CPP/7zip/Archive/Iso/IsoHeader.cpp @@ -9,13 +9,4 @@ namespace NIso { const char *kElToritoSpec = "EL TORITO SPECIFICATION\0\0\0\0\0\0\0\0\0"; -const char *kMediaTypes[5] = -{ - "NoEmulation" - , "1.2M" - , "1.44M" - , "2.88M" - , "HardDisk" -}; - }} diff --git a/CPP/7zip/Archive/Iso/IsoHeader.h b/CPP/7zip/Archive/Iso/IsoHeader.h index ce21b0ff..db0b1df9 100644 --- a/CPP/7zip/Archive/Iso/IsoHeader.h +++ b/CPP/7zip/Archive/Iso/IsoHeader.h @@ -34,6 +34,11 @@ namespace NBootEntryId const Byte kValidationEntry = 1; const Byte kInitialEntryNotBootable = 0; const Byte kInitialEntryBootable = 0x88; + + const Byte kMoreHeaders = 0x90; + const Byte kFinalHeader = 0x91; + + const Byte kExtensionIndicator = 0x44; } namespace NBootPlatformId @@ -54,9 +59,6 @@ namespace NBootMediaType const Byte kHardDisk = 4; } -const unsigned kNumBootMediaTypes = 5; -extern const char *kMediaTypes[]; - }} #endif diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp index ba12acae..b72e8687 100644 --- a/CPP/7zip/Archive/Iso/IsoIn.cpp +++ b/CPP/7zip/Archive/Iso/IsoIn.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../../C/CpuArch.h" + #include "../../../Common/MyException.h" #include "../../Common/StreamUtils.h" @@ -10,11 +12,78 @@ namespace NArchive { namespace NIso { - + struct CUnexpectedEndException {}; struct CHeaderErrorException {}; struct CEndianErrorException {}; +static const char * const kMediaTypes[] = +{ + "NoEmul" + , "1.2M" + , "1.44M" + , "2.88M" + , "HardDisk" +}; + +bool CBootInitialEntry::Parse(const Byte *p) +{ + Bootable = (p[0] == NBootEntryId::kInitialEntryBootable); + BootMediaType = p[1]; + LoadSegment = GetUi16(p + 2); + SystemType = p[4]; + SectorCount = GetUi16(p + 6); + LoadRBA = GetUi32(p + 8); + memcpy(VendorSpec, p + 12, 20); + if (p[5] != 0) + return false; + if (p[0] != NBootEntryId::kInitialEntryBootable + && p[0] != NBootEntryId::kInitialEntryNotBootable) + return false; + return true; +} + +AString CBootInitialEntry::GetName() const +{ + AString s = (Bootable ? "Boot" : "NotBoot"); + s += '-'; + + if (BootMediaType < ARRAY_SIZE(kMediaTypes)) + s += kMediaTypes[BootMediaType]; + else + { + char name[16]; + ConvertUInt32ToString(BootMediaType, name); + s += name; + } + + if (VendorSpec[0] == 1) + { + // "Language and Version Information (IBM)" + + unsigned i; + for (i = 1; i < sizeof(VendorSpec); i++) + if (VendorSpec[i] > 0x7F) + break; + if (i == sizeof(VendorSpec)) + { + s += '-'; + for (i = 1; i < sizeof(VendorSpec); i++) + { + char c = VendorSpec[i]; + if (c == 0) + break; + if (c == '\\' || c == '/') + c = '_'; + s += c; + } + } + } + + s += ".img"; + return s; +} + Byte CInArchive::ReadByte() { if (m_BufferPos >= BlockSize) @@ -58,15 +127,6 @@ void CInArchive::SkipZeros(size_t size) } } -UInt16 CInArchive::ReadUInt16Spec() -{ - UInt16 val = 0; - for (int i = 0; i < 2; i++) - val |= ((UInt16)(ReadByte()) << (8 * i)); - return val; -} - - UInt16 CInArchive::ReadUInt16() { Byte b[4]; @@ -179,15 +239,15 @@ void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len) Byte idLen = ReadByte(); r.FileId.Alloc(idLen); ReadBytes((Byte *)r.FileId, idLen); - int padSize = 1 - (idLen & 1); + unsigned padSize = 1 - (idLen & 1); - // SkipZeros(1 - (idLen & 1)); - Skip(1 - (idLen & 1)); // it's bug in some cd's. Must be zeros + // SkipZeros(padSize); + Skip(padSize); // it's bug in some cd's. Must be zeros - int curPos = 33 + idLen + padSize; + unsigned curPos = 33 + idLen + padSize; if (curPos > len) throw CHeaderErrorException(); - int rem = len - curPos; + unsigned rem = len - curPos; r.SystemUse.Alloc(rem); ReadBytes((Byte *)r.SystemUse, rem); } @@ -349,45 +409,94 @@ void CInArchive::ReadBootInfo() { if (!_bootIsDefined) return; + HeadersError = true; + if (memcmp(_bootDesc.BootSystemId, kElToritoSpec, sizeof(_bootDesc.BootSystemId)) != 0) return; - const Byte *p = (const Byte *)_bootDesc.BootSystemUse; - UInt32 blockIndex = p[0] | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16) | ((UInt32)p[3] << 24); + UInt32 blockIndex = GetUi32(_bootDesc.BootSystemUse); SeekToBlock(blockIndex); - Byte b = ReadByte(); - if (b != NBootEntryId::kValidationEntry) + + Byte buf[32]; + ReadBytes(buf, 32); + + if (buf[0] != NBootEntryId::kValidationEntry + || buf[2] != 0 + || buf[3] != 0 + || buf[30] != 0x55 + || buf[31] != 0xAA) return; + { + UInt32 sum = 0; + for (unsigned i = 0; i < 32; i += 2) + sum += GetUi16(buf + i); + if ((sum & 0xFFFF) != 0) + return; + /* CBootValidationEntry e; - e.PlatformId = ReadByte(); - if (ReadUInt16Spec() != 0) - throw CHeaderErrorException(); - ReadBytes(e.Id, sizeof(e.Id)); - /* UInt16 checkSum = */ ReadUInt16Spec(); - if (ReadByte() != 0x55) - throw CHeaderErrorException(); - if (ReadByte() != 0xAA) - throw CHeaderErrorException(); + e.PlatformId = buf[1]; + memcpy(e.Id, buf + 4, sizeof(e.Id)); + // UInt16 checkSum = GetUi16(p + 28); + */ } - b = ReadByte(); - if (b == NBootEntryId::kInitialEntryBootable || b == NBootEntryId::kInitialEntryNotBootable) + + ReadBytes(buf, 32); { CBootInitialEntry e; - e.Bootable = (b == NBootEntryId::kInitialEntryBootable); - e.BootMediaType = ReadByte(); - e.LoadSegment = ReadUInt16Spec(); - e.SystemType = ReadByte(); - if (ReadByte() != 0) - throw CHeaderErrorException(); - e.SectorCount = ReadUInt16Spec(); - e.LoadRBA = ReadUInt32Le(); - if (ReadByte() != 0) - throw CHeaderErrorException(); + if (!e.Parse(buf)) + return; BootEntries.Add(e); } - else - return; + + bool error = false; + + for (;;) + { + ReadBytes(buf, 32); + Byte headerIndicator = buf[0]; + if (headerIndicator != NBootEntryId::kMoreHeaders + && headerIndicator != NBootEntryId::kFinalHeader) + break; + + // Section Header + // Byte platform = p[1]; + unsigned numEntries = GetUi16(buf + 2); + // id[28] + + for (unsigned i = 0; i < numEntries; i++) + { + ReadBytes(buf, 32); + CBootInitialEntry e; + if (!e.Parse(buf)) + { + error = true; + break; + } + if (e.BootMediaType & (1 << 5)) + { + // Section entry extension + for (unsigned j = 0;; j++) + { + ReadBytes(buf, 32); + if (j > 32 || buf[0] != NBootEntryId::kExtensionIndicator) + { + error = true; + break; + } + if ((buf[1] & (1 << 5)) == 0) + break; + // info += (buf + 2, 30) + } + } + BootEntries.Add(e); + } + + if (headerIndicator != NBootEntryId::kMoreHeaders) + break; + } + + HeadersError = error; } HRESULT CInArchive::Open2() diff --git a/CPP/7zip/Archive/Iso/IsoIn.h b/CPP/7zip/Archive/Iso/IsoIn.h index 614b3744..c2007bce 100644 --- a/CPP/7zip/Archive/Iso/IsoIn.h +++ b/CPP/7zip/Archive/Iso/IsoIn.h @@ -25,77 +25,92 @@ struct CDir: public CDirRecord _subItems.Clear(); } - unsigned GetLen(bool checkSusp, unsigned skipSize) const - { - unsigned len = GetLenCur(checkSusp, skipSize); - if (Parent != 0) - if (Parent->Parent != 0) - len += 1 + Parent->GetLen(checkSusp, skipSize); - return len; - } - - unsigned GetLenU() const - { - unsigned len = (unsigned)(FileId.Size() / 2); - if (Parent != 0) - if (Parent->Parent != 0) - len += 1 + Parent->GetLenU(); - return len; - } - AString GetPath(bool checkSusp, unsigned skipSize) const { AString s; - unsigned len = GetLen(checkSusp, skipSize); - char *p = s.GetBuffer(len); - p += len; - *p = 0; + + unsigned len = 0; const CDir *cur = this; + for (;;) { - unsigned curLen = cur->GetLenCur(checkSusp, skipSize); - p -= curLen; - memcpy(p, (const char *)(const Byte *)cur->GetNameCur(checkSusp, skipSize), curLen); + unsigned curLen; + cur->GetNameCur(checkSusp, skipSize, curLen); + len += curLen; cur = cur->Parent; - if (cur == 0) + if (!cur || !cur->Parent) break; - if (cur->Parent == 0) + len++; + } + + char *p = s.GetBuf_SetEnd(len) + len; + + cur = this; + + for (;;) + { + unsigned curLen; + const Byte *name = cur->GetNameCur(checkSusp, skipSize, curLen); + p -= curLen; + if (curLen != 0) + memcpy(p, name, curLen); + cur = cur->Parent; + if (!cur || !cur->Parent) break; p--; *p = CHAR_PATH_SEPARATOR; } - s.ReleaseBuffer(); + return s; } - UString GetPathU() const + void GetPathU(UString &s) const { - UString s; - unsigned len = GetLenU(); - wchar_t *p = s.GetBuffer(len); - p += len; - *p = 0; + s.Empty(); + + unsigned len = 0; const CDir *cur = this; + for (;;) { unsigned curLen = (unsigned)(cur->FileId.Size() / 2); - p -= curLen; - for (unsigned i = 0; i < curLen; i++) - { - Byte b0 = ((const Byte *)cur->FileId)[i * 2]; - Byte b1 = ((const Byte *)cur->FileId)[i * 2 + 1]; - p[i] = (wchar_t)(((wchar_t)b0 << 8) | b1); - } + const Byte *fid = cur->FileId; + + unsigned i; + for (i = 0; i < curLen; i++) + if (fid[i * 2] == 0 && fid[i * 2 + 1] == 0) + break; + len += i; cur = cur->Parent; - if (cur == 0) + if (!cur || !cur->Parent) break; - if (cur->Parent == 0) + len++; + } + + wchar_t *p = s.GetBuf_SetEnd(len) + len; + + cur = this; + + for (;;) + { + unsigned curLen = (unsigned)(cur->FileId.Size() / 2); + const Byte *fid = cur->FileId; + + unsigned i; + for (i = 0; i < curLen; i++) + if (fid[i * 2] == 0 && fid[i * 2 + 1] == 0) + break; + curLen = i; + + p -= curLen; + for (i = 0; i < curLen; i++) + p[i] = (wchar_t)(((wchar_t)fid[i * 2] << 8) | fid[i * 2 + 1]); + cur = cur->Parent; + if (!cur || !cur->Parent) break; p--; *p = WCHAR_PATH_SEPARATOR; } - s.ReleaseBuffer(); - return s; } }; @@ -109,6 +124,7 @@ struct CDateTime Byte Second; Byte Hundredths; signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded. + bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 && Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; } @@ -118,7 +134,7 @@ struct CDateTime bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, value); if (res) { - value -= (UInt64)((Int64)GmtOffset * 15 * 60); + value -= (Int64)((Int32)GmtOffset * 15 * 60); value *= 10000000; } ft.dwLowDateTime = (DWORD)value; @@ -157,27 +173,16 @@ struct CBootInitialEntry UInt32 LoadRBA; // This is the start address of the virtual disk. CDs use // Relative/Logical block addressing. - UInt64 GetSize() const + Byte VendorSpec[20]; + + UInt32 GetSize() const { // if (BootMediaType == NBootMediaType::k1d44Floppy) (1440 << 10); - return SectorCount * 512; + return (UInt32)SectorCount * 512; } - AString GetName() const - { - AString s = (Bootable ? "Bootable" : "NotBootable"); - s += '_'; - if (BootMediaType < kNumBootMediaTypes) - s += kMediaTypes[BootMediaType]; - else - { - char name[16]; - ConvertUInt32ToString(BootMediaType, name); - s += name; - } - s += ".img"; - return s; - } + bool Parse(const Byte *p); + AString GetName() const; }; struct CVolumeDescriptor @@ -247,7 +252,6 @@ class CInArchive void SkipZeros(size_t size); Byte ReadByte(); void ReadBytes(Byte *data, UInt32 size); - UInt16 ReadUInt16Spec(); UInt16 ReadUInt16(); UInt32 ReadUInt32Le(); UInt32 ReadUInt32Be(); diff --git a/CPP/7zip/Archive/Iso/IsoItem.h b/CPP/7zip/Archive/Iso/IsoItem.h index b6ae21b7..2603afdb 100644 --- a/CPP/7zip/Archive/Iso/IsoItem.h +++ b/CPP/7zip/Archive/Iso/IsoItem.h @@ -29,7 +29,7 @@ struct CRecordingDateTime bool res = NWindows::NTime::GetSecondsSince1601(Year + 1900, Month, Day, Hour, Minute, Second, value); if (res) { - value -= (UInt64)((Int64)GmtOffset * 15 * 60); + value -= (Int64)((Int32)GmtOffset * 15 * 60); value *= 10000000; } ft.dwLowDateTime = (DWORD)value; @@ -94,28 +94,23 @@ struct CDirRecord return 0; } - unsigned GetLenCur(bool checkSusp, int skipSize) const + const Byte* GetNameCur(bool checkSusp, int skipSize, unsigned &nameLenRes) const { + const Byte *res = NULL; + unsigned len = 0; if (checkSusp) + res = FindSuspName(skipSize, len); + if (!res) { - unsigned len; - const Byte *res = FindSuspName(skipSize, len); - if (res != 0) - return len; + res = (const Byte *)FileId; + len = (unsigned)FileId.Size(); } - return (unsigned)FileId.Size(); - } - - const Byte* GetNameCur(bool checkSusp, int skipSize) const - { - if (checkSusp) - { - unsigned len; - const Byte *res = FindSuspName(skipSize, len); - if (res != 0) - return res; - } - return (const Byte *)FileId; + unsigned i; + for (i = 0; i < len; i++) + if (res[i] == 0) + break; + nameLenRes = i; + return res; } diff --git a/CPP/7zip/Archive/Iso/IsoRegister.cpp b/CPP/7zip/Archive/Iso/IsoRegister.cpp index c6f4a521..0205238d 100644 --- a/CPP/7zip/Archive/Iso/IsoRegister.cpp +++ b/CPP/7zip/Archive/Iso/IsoRegister.cpp @@ -9,15 +9,13 @@ namespace NArchive { namespace NIso { -IMP_CreateArcIn +static const Byte k_Signature[] = { 'C', 'D', '0', '0', '1' }; -static CArcInfo g_ArcInfo = - { "Iso", "iso img", 0, 0xE7, - 5, { 'C', 'D', '0', '0', '1' }, +REGISTER_ARC_I( + "Iso", "iso img", 0, 0xE7, + k_Signature, NArchive::NIso::kStartPos + 1, 0, - CreateArc }; - -REGISTER_ARC(Iso) + NULL) }} diff --git a/CPP/7zip/Archive/LzhHandler.cpp b/CPP/7zip/Archive/LzhHandler.cpp index ef4b4196..c8d3ff6d 100644 --- a/CPP/7zip/Archive/LzhHandler.cpp +++ b/CPP/7zip/Archive/LzhHandler.cpp @@ -660,8 +660,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = 0; CMyComPtr<ICompressCoder> lzhDecoder; - CMyComPtr<ICompressCoder> lzh1Decoder; - CMyComPtr<ICompressCoder> arj2Decoder; + // CMyComPtr<ICompressCoder> lzh1Decoder; + // CMyComPtr<ICompressCoder> arj2Decoder; NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; @@ -736,8 +736,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder; lzhDecoder = lzhDecoderSpec; } - lzhDecoderSpec->SetDictionary(item.GetNumDictBits()); + lzhDecoderSpec->FinishMode = true; + lzhDecoderSpec->SetDictSize(1 << item.GetNumDictBits()); result = lzhDecoder->Code(inStream, outStream, NULL, ¤tItemUnPacked, progress); + if (result == S_OK && lzhDecoderSpec->GetInputProcessedSize() != item.PackSize) + result = S_FALSE; } /* else if (item.IsLh1GroupMethod()) @@ -773,15 +776,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } -IMP_CreateArcIn +static const Byte k_Signature[] = { '-', 'l', 'h' }; -static CArcInfo g_ArcInfo = - { "Lzh", "lzh lha", 0, 6, - 3, { '-', 'l', 'h' }, +REGISTER_ARC_I( + "Lzh", "lzh lha", 0, 6, + k_Signature, 2, 0, - CreateArc, NULL, IsArc_Lzh }; - -REGISTER_ARC(Lzh) + IsArc_Lzh) }} diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp index 04aa4685..e4ac2a42 100644 --- a/CPP/7zip/Archive/LzmaHandler.cpp +++ b/CPP/7zip/Archive/LzmaHandler.cpp @@ -9,11 +9,12 @@ #include "../../Windows/PropVariant.h" -#include "../Common/CreateCoder.h" +#include "../Common/FilterCoder.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" #include "../Common/StreamUtils.h" +#include "../Compress/BcjCoder.h" #include "../Compress/LzmaDecoder.h" #include "Common/DummyOutStream.h" @@ -75,14 +76,14 @@ bool CHeader::Parse(const Byte *buf, bool isThereFilter) class CDecoder { - CMyComPtr<ICompressCoder> _lzmaDecoder; CMyComPtr<ISequentialOutStream> _bcjStream; + CFilterCoder *_filterCoder; + CMyComPtr<ICompressCoder> _lzmaDecoder; public: NCompress::NLzma::CDecoder *_lzmaDecoderSpec; ~CDecoder(); - HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS - bool filtered, ISequentialInStream *inStream); + HRESULT Create(bool filtered, ISequentialInStream *inStream); HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress); @@ -94,11 +95,7 @@ public: { return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); } }; -static const UInt32 k_BCJ = 0x03030103; - -HRESULT CDecoder::Create( - DECL_EXTERNAL_CODECS_LOC_VARS - bool filteredMode, ISequentialInStream *inStream) +HRESULT CDecoder::Create(bool filteredMode, ISequentialInStream *inStream) { if (!_lzmaDecoder) { @@ -111,13 +108,10 @@ HRESULT CDecoder::Create( { if (!_bcjStream) { - CMyComPtr<ICompressCoder> coder; - RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false)); - if (!coder) - return E_NOTIMPL; - coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream); - if (!_bcjStream) - return E_NOTIMPL; + _filterCoder = new CFilterCoder(false); + CMyComPtr<ICompressCoder> coder = _filterCoder; + _filterCoder->Filter = new CBcjCoder(false); + _bcjStream = _filterCoder; } } @@ -143,17 +137,13 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream, RINOK(setDecoderProperties->SetDecoderProperties2(header.LzmaProps, 5)); } - CMyComPtr<ICompressSetOutStream> setOutStream; - bool filteredMode = (header.FilterID == 1); if (filteredMode) { - _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream); - if (!setOutStream) - return E_NOTIMPL; - RINOK(setOutStream->SetOutStream(outStream)); + RINOK(_filterCoder->SetOutStream(outStream)); outStream = _bcjStream; + RINOK(_filterCoder->SetOutStreamSize(NULL)); } const UInt64 *Size = header.HasSize() ? &header.Size : NULL; @@ -161,18 +151,16 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream, if (filteredMode) { - CMyComPtr<IOutStreamFlush> flush; - _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush); - if (flush) { - HRESULT res2 = flush->Flush(); + HRESULT res2 = _filterCoder->OutStreamFinish(); if (res == S_OK) res = res2; } - HRESULT res2 = setOutStream->ReleaseOutStream(); + HRESULT res2 = _filterCoder->ReleaseOutStream(); if (res == S_OK) res = res2; } + RINOK(res); if (header.HasSize()) @@ -186,7 +174,6 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream, class CHandler: public IInArchive, public IArchiveOpenSeq, - PUBLIC_ISetCompressCodecsInfo public CMyUnknownImp { CHeader _header; @@ -210,15 +197,8 @@ class CHandler: UInt64 _unpackSize; UInt64 _numStreams; - DECL_EXTERNAL_CODECS_VARS - DECL_ISetCompressCodecsInfo - public: - MY_QUERYINTERFACE_BEGIN2(IInArchive) - MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq) - QUERY_ENTRY_ISetCompressCodecsInfo - MY_QUERYINTERFACE_END - MY_ADDREF_RELEASE + MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq) INTERFACE_IInArchive(;) STDMETHOD(OpenSeq)(ISequentialInStream *stream); @@ -427,6 +407,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN + if (numItems == 0) return S_OK; if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) @@ -466,9 +447,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, _needSeekToStart = true; CDecoder decoder; - HRESULT result = decoder.Create( - EXTERNAL_CODECS_VARS - _lzma86, _seqStream); + HRESULT result = decoder.Create(_lzma86, _seqStream); RINOK(result); bool firstItem = true; @@ -562,43 +541,33 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, outStream.Release(); return extractCallback->SetOperationResult(opResult); + COM_TRY_END } -IMPL_ISetCompressCodecsInfo - namespace NLzmaAr { -IMP_CreateArcIn_2(CHandler(false)) +// 2, { 0x5D, 0x00 }, -static CArcInfo g_ArcInfo = - { "lzma", "lzma", 0, 0xA, - 0, { 0 }, - // 2, { 0x5D, 0x00 }, +REGISTER_ARC_I_CLS_NO_SIG( + CHandler(false), + "lzma", "lzma", 0, 0xA, 0, NArcInfoFlags::kStartOpen | NArcInfoFlags::kKeepName, - CreateArc, NULL, - IsArc_Lzma }; - -REGISTER_ARC(Lzma) - + IsArc_Lzma) + } namespace NLzma86Ar { -IMP_CreateArcIn_2(CHandler(true)) - -static CArcInfo g_ArcInfo = - { "lzma86", "lzma86", 0, 0xB, - 0, { 0 }, +REGISTER_ARC_I_CLS_NO_SIG( + CHandler(true), + "lzma86", "lzma86", 0, 0xB, 0, NArcInfoFlags::kKeepName, - CreateArc, NULL, - IsArc_Lzma86 }; - -REGISTER_ARC(Lzma86) - + IsArc_Lzma86) + } }} diff --git a/CPP/7zip/Archive/MachoHandler.cpp b/CPP/7zip/Archive/MachoHandler.cpp index 11ff9703..00dc571b 100644 --- a/CPP/7zip/Archive/MachoHandler.cpp +++ b/CPP/7zip/Archive/MachoHandler.cpp @@ -42,7 +42,7 @@ namespace NMacho { #define CPU_SUBTYPE_POWERPC_970 100 -static const char *k_PowerPc_SubTypes[] = +static const char * const k_PowerPc_SubTypes[] = { NULL , "601" @@ -297,7 +297,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) ConvertUInt32ToString(t, temp); n = temp; } - s += ' '; + s.Add_Space(); s += n; } prop = s; @@ -310,7 +310,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) AString s = FlagsToString(g_ArcFlags, ARRAY_SIZE(g_ArcFlags), _flags); if (!s.IsEmpty()) { - res += ' '; + res.Add_Space(); res += s; } prop = res; @@ -354,7 +354,7 @@ static AString SectFlagsToString(UInt32 flags) AString s = FlagsToString(g_Flags, ARRAY_SIZE(g_Flags), flags & SECT_ATTR_MASK); if (!s.IsEmpty()) { - res += ' '; + res.Add_Space(); res += s; } return res; @@ -643,22 +643,18 @@ STDMETHODIMP CHandler::AllowTail(Int32 allowTail) return S_OK; } -IMP_CreateArcIn +static const Byte k_Signature[] = { + 4, 0xCE, 0xFA, 0xED, 0xFE, + 4, 0xCF, 0xFA, 0xED, 0xFE, + 4, 0xFE, 0xED, 0xFA, 0xCE, + 4, 0xFE, 0xED, 0xFA, 0xCF }; -#define k_Signature { \ - 4, 0xCE, 0xFA, 0xED, 0xFE, \ - 4, 0xCF, 0xFA, 0xED, 0xFE, \ - 4, 0xFE, 0xED, 0xFA, 0xCE, \ - 4, 0xFE, 0xED, 0xFA, 0xCF } - -static CArcInfo g_ArcInfo = - { "MachO", "macho", 0, 0xDF, - 4 * 5, k_Signature, +REGISTER_ARC_I( + "MachO", "macho", 0, 0xDF, + k_Signature, 0, NArcInfoFlags::kMultiSignature | NArcInfoFlags::kPreArc, - CreateArc }; - -REGISTER_ARC(Macho) + NULL) }} diff --git a/CPP/7zip/Archive/MbrHandler.cpp b/CPP/7zip/Archive/MbrHandler.cpp index abc981f3..c4e4cc60 100644 --- a/CPP/7zip/Archive/MbrHandler.cpp +++ b/CPP/7zip/Archive/MbrHandler.cpp @@ -169,7 +169,7 @@ static const CPartType kPartTypes[] = static int FindPartType(UInt32 type) { - for (int i = 0; i < ARRAY_SIZE(kPartTypes); i++) + for (unsigned i = 0; i < ARRAY_SIZE(kPartTypes); i++) if (kPartTypes[i].Id == type) return i; return -1; @@ -193,19 +193,19 @@ class CHandler: UInt64 _totalSize; CByteBuffer _buffer; - HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int level); + HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level); public: MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; -HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int level) +HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level) { if (level >= 128 || _items.Size() >= 128) return S_FALSE; - const int kNumHeaderParts = 4; + const unsigned kNumHeaderParts = 4; CPartition parts[kNumHeaderParts]; { @@ -221,7 +221,7 @@ HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA) return S_FALSE; - for (int i = 0; i < kNumHeaderParts; i++) + for (unsigned i = 0; i < kNumHeaderParts; i++) if (!parts[i].Parse(buf + 0x1BE + 16 * i)) return S_FALSE; } @@ -232,13 +232,13 @@ HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int if (limLba == 0) return S_FALSE; - for (int i = 0; i < kNumHeaderParts; i++) + for (unsigned i = 0; i < kNumHeaderParts; i++) { CPartition &part = parts[i]; if (part.IsEmpty()) continue; - PRF(printf("\n %2d ", (int)level)); + PRF(printf("\n %2d ", (unsigned)level)); #ifdef SHOW_DEBUG_INFO part.Print(); #endif @@ -402,8 +402,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val int typeIndex = FindPartType(part.Type); s += '.'; const char *ext = "img"; - if (typeIndex >= 0 && kPartTypes[typeIndex].Ext != 0) - ext = kPartTypes[typeIndex].Ext; + if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Ext) + ext = kPartTypes[(unsigned)typeIndex].Ext; s += ext; } prop = s; @@ -416,8 +416,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val ConvertUInt32ToString(part.Type, s); const char *res = s; int typeIndex = FindPartType(part.Type); - if (typeIndex >= 0 && kPartTypes[typeIndex].Name) - res = kPartTypes[typeIndex].Name; + if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Name) + res = kPartTypes[(unsigned)typeIndex].Name; prop = res; } break; @@ -499,17 +499,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -IMP_CreateArcIn -static CArcInfo g_ArcInfo = - { "MBR", "mbr", 0, 0xDB, // 3, { 1, 1, 0 }, // 2, { 0x55, 0x1FF }, - 0, { 0 }, + +REGISTER_ARC_I_NO_SIG( + "MBR", "mbr", 0, 0xDB, 0, NArcInfoFlags::kPureStartOpen, - CreateArc }; - -REGISTER_ARC(Mbr) + NULL) }} diff --git a/CPP/7zip/Archive/MslzHandler.cpp b/CPP/7zip/Archive/MslzHandler.cpp index cb124c40..ec375733 100644 --- a/CPP/7zip/Archive/MslzHandler.cpp +++ b/CPP/7zip/Archive/MslzHandler.cpp @@ -111,11 +111,13 @@ static const unsigned kHeaderSize = kSignatureSize + 1 + 4; static const Byte kSignature[kSignatureSize] = MSLZ_SIGNATURE; // we support only 3 chars strings here -static const char *g_Exts[] = +static const char * const g_Exts[] = { - "dll" + "bin" + , "dll" , "exe" , "kmd" + , "pdf" , "sys" }; @@ -147,14 +149,15 @@ void CHandler::ParseName(Byte replaceByte, IArchiveOpenCallback *callback) for (unsigned i = 0; i < ARRAY_SIZE(g_Exts); i++) { const char *ext = g_Exts[i]; - if (s[s.Len() - 2] == ext[0] && - s[s.Len() - 1] == ext[1]) + if (s[s.Len() - 2] == (Byte)ext[0] && + s[s.Len() - 1] == (Byte)ext[1]) { replaceByte = ext[2]; break; } } } + if (replaceByte >= 0x20 && replaceByte < 0x80) _name += (wchar_t)replaceByte; } @@ -225,6 +228,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn Byte buf[kBufSize]; UInt32 dest = 0; memset(buf, ' ', kBufSize); + while (dest < unpackSize) { Byte b; @@ -233,6 +237,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn needMoreData = true; return S_FALSE; } + for (unsigned mask = (unsigned)b | 0x100; mask > 1 && dest < unpackSize; mask >>= 1) { if (!inStream.ReadByte(b)) @@ -240,6 +245,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn needMoreData = true; return S_FALSE; } + if (mask & 1) { buf[dest++ & kMask] = b; @@ -258,6 +264,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn unsigned len = (b1 & 0xF) + 3; if (len > kMaxLen || dest + len > unpackSize) return S_FALSE; + do { buf[dest++ & kMask] = buf[src++ & kMask]; @@ -267,6 +274,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn } } } + if (outStream) RINOK(WriteStream(outStream, buf, dest & kMask)); return S_OK; @@ -379,15 +387,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } -IMP_CreateArcIn - -static CArcInfo g_ArcInfo = - { "MsLZ", "mslz", 0, 0xD5, - kSignatureSize, MSLZ_SIGNATURE, +REGISTER_ARC_I( + "MsLZ", "mslz", 0, 0xD5, + kSignature, 0, 0, - CreateArc }; - -REGISTER_ARC(Mslz) + NULL) }} diff --git a/CPP/7zip/Archive/MubHandler.cpp b/CPP/7zip/Archive/MubHandler.cpp index 39f8de27..a84c3120 100644 --- a/CPP/7zip/Archive/MubHandler.cpp +++ b/CPP/7zip/Archive/MubHandler.cpp @@ -292,22 +292,18 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -IMP_CreateArcIn - namespace NBe { -static CArcInfo g_ArcInfo = - { "Mub", "mub", 0, 0xE2, - 2 + 7 + 4, - { +static const Byte k_Signature[] = { 7, 0xCA, 0xFE, 0xBA, 0xBE, 0, 0, 0, - 4, 0xB9, 0xFA, 0xF1, 0x0E - }, + 4, 0xB9, 0xFA, 0xF1, 0x0E }; + +REGISTER_ARC_I( + "Mub", "mub", 0, 0xE2, + k_Signature, 0, NArcInfoFlags::kMultiSignature, - CreateArc }; - -REGISTER_ARC(Mub) + NULL) } diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.cpp b/CPP/7zip/Archive/Nsis/NsisDecode.cpp index bb73d273..68243129 100644 --- a/CPP/7zip/Archive/Nsis/NsisDecode.cpp +++ b/CPP/7zip/Archive/Nsis/NsisDecode.cpp @@ -7,7 +7,6 @@ #include "NsisDecode.h" #include "../../Common/CreateCoder.h" -#include "../../Common/FilterCoder.h" #include "../../Common/LimitedStreams.h" #include "../../Common/MethodId.h" @@ -58,18 +57,11 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter) { if (!_filterInStream) { - CFilterCoder *coderSpec = new CFilterCoder; - CMyComPtr<ICompressCoder> coder = coderSpec; - coderSpec->Filter = new CBCJ_x86_Decoder(); - coder.QueryInterface(IID_ISequentialInStream, &_filterInStream); - if (!_filterInStream) - return E_NOTIMPL; + _filter = new CFilterCoder(false); + _filterInStream = _filter; + _filter->Filter = new CBcjCoder(false); } - CMyComPtr<ICompressSetInStream> setInStream; - _filterInStream.QueryInterface(IID_ICompressSetInStream, &setInStream); - if (!setInStream) - return E_NOTIMPL; - RINOK(setInStream->SetInStream(_codecInStream)); + RINOK(_filter->SetInStream(_codecInStream)); _decoderInStream = _filterInStream; } @@ -99,13 +91,7 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter) if (useFilter) { - /* - CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize; - _filterInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize); - if (!setOutStreamSize) - return E_NOTIMPL; - RINOK(setOutStreamSize->SetOutStreamSize(NULL)); - */ + RINOK(_filter->SetOutStreamSize(NULL)); } return S_OK; diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.h b/CPP/7zip/Archive/Nsis/NsisDecode.h index 0b95d4b2..7b22181e 100644 --- a/CPP/7zip/Archive/Nsis/NsisDecode.h +++ b/CPP/7zip/Archive/Nsis/NsisDecode.h @@ -5,6 +5,7 @@ #include "../../../Common/MyBuffer.h" +#include "../../Common/FilterCoder.h" #include "../../Common/StreamUtils.h" #include "../../Compress/LzmaDecoder.h" @@ -31,6 +32,7 @@ class CDecoder { NMethodType::EEnum _curMethod; // method of created decoder + CFilterCoder *_filter; CMyComPtr<ISequentialInStream> _filterInStream; CMyComPtr<ISequentialInStream> _codecInStream; CMyComPtr<ISequentialInStream> _decoderInStream; diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.cpp b/CPP/7zip/Archive/Nsis/NsisHandler.cpp index 233edd52..971c8464 100644 --- a/CPP/7zip/Archive/Nsis/NsisHandler.cpp +++ b/CPP/7zip/Archive/Nsis/NsisHandler.cpp @@ -26,7 +26,7 @@ namespace NNsis { static const char *kBcjMethod = "BCJ"; static const char *kUnknownMethod = "Unknown"; -static const char *kMethods[] = +static const char * const kMethods[] = { "Copy" , "Deflate" @@ -84,9 +84,9 @@ static AString GetMethod(bool useFilter, NMethodType::EEnum method, UInt32 dict) if (useFilter) { s += kBcjMethod; - s += ' '; + s.Add_Space(); } - s += (method < ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod; + s += ((unsigned)method < ARRAY_SIZE(kMethods)) ? kMethods[(unsigned)method] : kUnknownMethod; if (method == NMethodType::kLZMA) { s += ':'; @@ -102,7 +102,7 @@ AString CHandler::GetMethod(NMethodType::EEnum method, bool useItemFilter, UInt3 if (_archive.IsSolid && _archive.UseFilter || !_archive.IsSolid && useItemFilter) { s += kBcjMethod; - s += ' '; + s.Add_Space(); } s += (method < ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod; if (method == NMethodType::kLZMA) @@ -126,8 +126,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) AString s = _archive.GetFormatDescription(); if (!_archive.IsInstaller) { - if (!s.IsEmpty()) - s += ' '; + s.Add_Space_if_NotEmpty(); s += "(Uninstall)"; } if (!s.IsEmpty()) @@ -138,8 +137,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidMethod: prop = _methodString; break; case kpidSolid: prop = _archive.IsSolid; break; case kpidOffset: prop = _archive.StartOffset; break; - case kpidPhySize: prop = _archive.ExeStub.Size() + _archive.FirstHeader.ArcSize; break; - case kpidEmbeddedStubSize: prop = _archive.ExeStub.Size(); break; + case kpidPhySize: prop = (UInt64)((UInt64)_archive.ExeStub.Size() + _archive.FirstHeader.ArcSize); break; + case kpidEmbeddedStubSize: prop = (UInt64)_archive.ExeStub.Size(); break; case kpidHeadersSize: prop = _archive.FirstHeader.HeaderSize; break; case kpidErrorFlags: @@ -611,7 +610,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, HRESULT res = _archive.Decoder.Decode( writeToTemp1 ? &tempBuf : NULL, item.IsUninstaller, item.PatchSize, - item.IsUninstaller ? NULL : realOutStream, + item.IsUninstaller ? NULL : (ISequentialOutStream *)realOutStream, progress, curPacked, curUnpacked32); curUnpacked = curUnpacked32; diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp index dc570ec2..6ca87df4 100644 --- a/CPP/7zip/Archive/Nsis/NsisIn.cpp +++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp @@ -20,7 +20,7 @@ namespace NNsis { static const size_t kInputBufSize = 1 << 20; -static const Byte kSignature[kSignatureSize] = NSIS_SIGNATURE; +const Byte kSignature[kSignatureSize] = NSIS_SIGNATURE; static const UInt32 kMask_IsCompressed = (UInt32)1 << 31; static const unsigned kNumCommandParams = 6; @@ -30,7 +30,7 @@ static const unsigned kCmdSize = 4 + kNumCommandParams * 4; #define CR_LF "\x0D\x0A" #endif -static const char *kErrorStr = "$_ERROR_STR_"; +static const char * const kErrorStr = "$_ERROR_STR_"; #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } @@ -244,7 +244,7 @@ static const CCommandInfo k_Commands[kNumCmds] = #ifdef NSIS_SCRIPT -static const char *k_CommandNames[kNumCmds] = +static const char * const k_CommandNames[kNumCmds] = { "Invalid" , NULL // Return @@ -331,7 +331,7 @@ static const char *k_CommandNames[kNumCmds] = Some NSIS shell names are not identical to WIN32 CSIDL_* names. NSIS doesn't use some CSIDL_* values. But we add name for all CSIDL_ (marked with '+'). */ -static const char *kShellStrings[] = +static const char * const kShellStrings[] = { "DESKTOP" // + , "INTERNET" // + @@ -526,7 +526,7 @@ void CInArchive::AddLicense(UInt32 param, Int32 langID) #define kVar_Spec_OUTDIR 31 // NSIS 2.26+ -static const char *kVarStrings[] = +static const char * const kVarStrings[] = { "CMDLINE" , "INSTDIR" @@ -963,8 +963,7 @@ void CInArchive::GetNsisString_Unicode_Raw(const Byte *p) else // if (c == PARK_CODE_LANG) Add_LangStr(Raw_AString, n); } - for (const Byte *s = (const Byte *)(const char *)Raw_AString; *s != 0; s++) - Raw_UString += *s; + Raw_UString.AddAscii(Raw_AString); continue; } c = n; @@ -1010,8 +1009,7 @@ void CInArchive::GetNsisString_Unicode_Raw(const Byte *p) else // if (c == NS_3_CODE_LANG) Add_LangStr(Raw_AString, n); } - for (const Byte *s = (const Byte *)(const char *)Raw_AString; *s != 0; s++) - Raw_UString += (wchar_t)*s; + Raw_UString.AddAscii(Raw_AString); } } @@ -1147,8 +1145,7 @@ void CInArchive::ReadString2_Raw(UInt32 pos) GetNsisString_Raw(_data + _stringsPos + pos); return; } - for (const char *s = (const char *)Raw_AString; *s != 0; s++) - Raw_UString += *s; + Raw_UString.SetFromAscii(Raw_AString); } bool CInArchive::IsGoodString(UInt32 param) const @@ -1417,7 +1414,7 @@ static const char *g_WinAttrib[] = #define FLAGS_DELIMITER '|' -static void FlagsToString2(CDynLimBuf &s, const char **table, unsigned num, UInt32 flags) +static void FlagsToString2(CDynLimBuf &s, const char * const *table, unsigned num, UInt32 flags) { bool filled = false; for (unsigned i = 0; i < num; i++) @@ -1536,7 +1533,7 @@ inline bool IsProbablyEndOfFunc(UInt32 flag) return (flag != 0 && flag != CMD_REF_Goto); } -static const char *kOnFunc[] = +static const char * const kOnFunc[] = { "Init" , "InstSuccess" @@ -1622,12 +1619,12 @@ static bool NoLabels(const UInt32 *labels, UInt32 num) return true; } -static const char *k_REBOOTOK = " /REBOOTOK"; +static const char * const k_REBOOTOK = " /REBOOTOK"; #define MY__MB_ABORTRETRYIGNORE 2 #define MY__MB_RETRYCANCEL 5 -static const char *k_MB_Buttons[] = +static const char * const k_MB_Buttons[] = { "OK" , "OKCANCEL" @@ -1640,7 +1637,7 @@ static const char *k_MB_Buttons[] = #define MY__MB_ICONSTOP (1 << 4) -static const char *k_MB_Icons[] = +static const char * const k_MB_Icons[] = { NULL , "ICONSTOP" @@ -1649,7 +1646,7 @@ static const char *k_MB_Icons[] = , "ICONINFORMATION" }; -static const char *k_MB_Flags[] = +static const char * const k_MB_Flags[] = { "HELP" , "NOFOCUS" @@ -1664,7 +1661,7 @@ static const char *k_MB_Flags[] = #define MY__IDCANCEL 2 #define MY__IDIGNORE 5 -static const char *k_Button_IDs[] = +static const char * const k_Button_IDs[] = { "0" , "IDOK" @@ -1702,31 +1699,6 @@ bool CInArchive::IsDirectString_Equal(UInt32 offset, const char *s) const return strcmp((const char *)(const Byte *)_data + _stringsPos + offset, s) == 0; } -static UInt32 ConvertHexStringToUInt32(const char *s, const char **end) -{ - UInt32 result = 0; - for (int i = 0; i < 8; i++) - { - char c = *s; - UInt32 v; - if (c >= '0' && c <= '9') v = (c - '0'); - else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); - else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); - else - { - if (end != NULL) - *end = s; - return result; - } - result <<= 4; - result |= v; - s++; - } - if (end != NULL) - *end = s; - return 0; -} - static bool StringToUInt32(const char *s, UInt32 &res) { const char *end; @@ -1816,7 +1788,7 @@ void CInArchive::Add_Color(UInt32 v) #define MY__SW_SHOWMINNOACTIVE 7 #define MY__SW_SHOWNA 8 -static const char *kShowWindow_Commands[] = +static const char * const kShowWindow_Commands[] = { "HIDE" , "SHOWNORMAL" // "NORMAL" @@ -1854,7 +1826,7 @@ void CInArchive::Add_ShowWindow_Cmd(UInt32 cmd) Add_UInt(cmd); } -void CInArchive::Add_TypeFromList(const char **table, unsigned tableSize, UInt32 type) +void CInArchive::Add_TypeFromList(const char * const *table, unsigned tableSize, UInt32 type) { if (type < tableSize) Script += table[type]; @@ -1886,7 +1858,7 @@ enum }; // Names for NSIS exec_flags_t structure vars -static const char *kExecFlags_VarsNames[] = +static const char * const kExecFlags_VarsNames[] = { "AutoClose" // autoclose; , "ShellVarContext" // all_user_var; @@ -1940,7 +1912,7 @@ enum PWP_CUSTOM }; -static const char *kPageTypes[] = +static const char * const kPageTypes[] = { "license" , "components" @@ -2062,7 +2034,7 @@ void CInArchive::AddStringLF(const char *s) // ---------- Section ---------- -static const char *kSection_VarsNames[] = +static const char * const kSection_VarsNames[] = { "Text" , "InstTypes" @@ -2240,7 +2212,7 @@ void CInArchive::NewLine() static const UInt32 kPageSize = 16 * 4; -static const char *k_SetOverwrite_Modes[] = +static const char * const k_SetOverwrite_Modes[] = { "on" , "off" @@ -2294,7 +2266,7 @@ void CInArchive::MessageBox_MB_Part(UInt32 param) else if (modal == 2) Script += "|MB_TASKMODAL"; else if (modal == 3) Script += "|0x3000"; UInt32 flags = (param >> 14); - for (int i = 0; i < ARRAY_SIZE(k_MB_Flags); i++) + for (unsigned i = 0; i < ARRAY_SIZE(k_MB_Flags); i++) if ((flags & (1 << i)) != 0) { Script += "|MB_"; @@ -2327,8 +2299,7 @@ static const UInt32 kSectionSize_16bit_Big = kSectionSize_base + 8196 * 2; static void AddString(AString &dest, const char *src) { - if (!dest.IsEmpty()) - dest += ' '; + dest.Add_Space_if_NotEmpty(); dest += src; } @@ -3133,7 +3104,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) } default: continue; } - for (int i = 0; mask != 0; i++, mask >>= 1) + for (unsigned i = 0; mask != 0; i++, mask >>= 1) if (mask & 1) { UInt32 param = Get32(p + 4 + 4 * i); @@ -3535,17 +3506,11 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) pars[i] = Get32(p2 + i * 4 + 4); if (pars[0] == 10 + 4 && pars[2] == 0 && pars[3] == 0) // 10 + 4 means $R4 { - ReadString2_Raw(pars[1]); - if (IsUnicode) - { - if (!Raw_UString.IsEmpty()) - item.NameU = Raw_UString; - } - else - { - if (!Raw_AString.IsEmpty()) - item.NameA = Raw_AString; - } + item.Prefix = -1; + item.NameA.Empty(); + item.NameU.Empty(); + SetItemName(item, pars[1]); + // maybe here we can restore original item name, if new name is empty } } } @@ -5011,7 +4976,7 @@ HRESULT CInArchive::SortItems() #define CH_FLAGS_COMP_ONLY_ON_CUSTOM 256 #define CH_FLAGS_NO_CUSTOM 512 -static const char *k_PostStrings[] = +static const char * const k_PostStrings[] = { "install_directory_auto_append" , "uninstchild" // NSIS 2.25+, used by uninstaller: @@ -5242,7 +5207,7 @@ HRESULT CInArchive::Parse() AddRegRoot(rootKey); AddParam(subKey); AddParam(value); - NewLine(); + AddLF(); } } @@ -5296,6 +5261,9 @@ HRESULT CInArchive::Parse() UInt32 langtable_size = Get32(p2 + 32); if (bhLangTables.Num > 0) { + if (langtable_size == (UInt32)(Int32)-1) + return E_NOTIMPL; // maybe it's old NSIS archive() + UInt32 numStrings = (langtable_size - 10) / 4; _numLangStrings = numStrings; AddLF(); @@ -5310,7 +5278,7 @@ HRESULT CInArchive::Parse() { const Byte *p = _data + bhLangTables.Offset + langtable_size * i; LANGID langID = Get16(p); - UInt32 val = Get32(p + 10 + licenseLangIndex * 4); + UInt32 val = Get32(p + 10 + (UInt32)licenseLangIndex * 4); if (val != 0) { Script += "LicenseLangString "; @@ -5902,6 +5870,7 @@ void CInArchive::Clear2() Script.Empty(); LicenseFiles.Clear(); _numRootLicenses = 0; + _numLangStrings = 0; langStrIDs.Clear(); LangComment.Empty(); noParseStringIndexes.Clear(); diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h index 3acd9ee5..2bab5299 100644 --- a/CPP/7zip/Archive/Nsis/NsisIn.h +++ b/CPP/7zip/Archive/Nsis/NsisIn.h @@ -24,6 +24,7 @@ namespace NNsis { const size_t kScriptSizeLimit = 1 << 27; const unsigned kSignatureSize = 16; +extern const Byte kSignature[kSignatureSize]; #define NSIS_SIGNATURE { 0xEF, 0xBE, 0xAD, 0xDE, 'N', 'u', 'l', 'l', 's', 'o', 'f', 't', 'I', 'n', 's', 't' } const UInt32 kFlagsMask = 0xF; @@ -261,7 +262,7 @@ private: void Add_ButtonID(UInt32 buttonID); void Add_ShowWindow_Cmd(UInt32 cmd); - void Add_TypeFromList(const char **table, unsigned tableSize, UInt32 type); + void Add_TypeFromList(const char * const *table, unsigned tableSize, UInt32 type); void Add_ExecFlags(UInt32 flagsType); void Add_SectOp(UInt32 opType); diff --git a/CPP/7zip/Archive/Nsis/NsisRegister.cpp b/CPP/7zip/Archive/Nsis/NsisRegister.cpp index b363bdec..7230c3c2 100644 --- a/CPP/7zip/Archive/Nsis/NsisRegister.cpp +++ b/CPP/7zip/Archive/Nsis/NsisRegister.cpp @@ -9,16 +9,12 @@ namespace NArchive { namespace NNsis { -IMP_CreateArcIn - -static CArcInfo g_ArcInfo = - { "Nsis", "nsis", 0, 0x9, - NArchive::NNsis::kSignatureSize, NSIS_SIGNATURE, +REGISTER_ARC_I( + "Nsis", "nsis", 0, 0x9, + kSignature, 4, NArcInfoFlags::kFindSignature | NArcInfoFlags::kUseGlobalOffset, - CreateArc }; - -REGISTER_ARC(Nsis) + NULL) }} diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp index 6661492f..ee630a66 100644 --- a/CPP/7zip/Archive/NtfsHandler.cpp +++ b/CPP/7zip/Archive/NtfsHandler.cpp @@ -22,6 +22,7 @@ #include "../Common/MethodProps.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" +#include "../Common/StreamObjects.h" #include "../Common/StreamUtils.h" #include "../Compress/CopyCoder.h" @@ -62,6 +63,7 @@ static const wchar_t *kVirtualFolder_Lost_Deleted = L"[UNKNOWN]"; static const unsigned kNumSysRecs = 16; static const unsigned kRecIndex_Volume = 3; +static const unsigned kRecIndex_RootDir = 5; static const unsigned kRecIndex_BadClus = 8; static const unsigned kRecIndex_Security = 9; @@ -198,10 +200,18 @@ enum DEF_ATTR_TYPE(0x1000, FIRST_USER_DEFINED_ATTRIBUTE) }; -static const Byte kFileNameType_Posix = 0; -static const Byte kFileNameType_Win32 = 1; -static const Byte kFileNameType_Dos = 2; -static const Byte kFileNameType_Win32Dos = 3; + +/* WinXP-64: + Probably only one short name (dos name) per record is allowed. + There are no short names for hard links. + The pair (Win32,Dos) can be in any order. + Posix name can be after or before Win32 name +*/ + +static const Byte kFileNameType_Posix = 0; // for hard links +static const Byte kFileNameType_Win32 = 1; // after Dos name +static const Byte kFileNameType_Dos = 2; // short name +static const Byte kFileNameType_Win32Dos = 3; // short and full name are same struct CFileNameAttr { @@ -215,21 +225,31 @@ struct CFileNameAttr // UInt64 AllocatedSize; // UInt64 DataSize; // UInt16 PackedEaSize; - UString Name; + UString2 Name; UInt32 Attrib; Byte NameType; bool IsDos() const { return NameType == kFileNameType_Dos; } + bool IsWin32() const { return (NameType == kFileNameType_Win32); } + bool Parse(const Byte *p, unsigned size); }; -static void GetString(const Byte *p, unsigned len, UString &res) +static void GetString(const Byte *p, unsigned len, UString2 &res) { - wchar_t *s = res.GetBuffer(len); - for (unsigned i = 0; i < len; i++) - s[i] = Get16(p + i * 2); - s[len] = 0; - res.ReleaseBuffer(); + if (len == 0 && res.IsEmpty()) + return; + wchar_t *s = res.GetBuf(len); + unsigned i; + for (i = 0; i < len; i++) + { + wchar_t c = Get16(p + i * 2); + if (c == 0) + break; + s[i] = c; + } + s[i] = 0; + res.ReleaseBuf_SetLen(i); } bool CFileNameAttr::Parse(const Byte *p, unsigned size) @@ -249,7 +269,8 @@ bool CFileNameAttr::Parse(const Byte *p, unsigned size) unsigned len = p[0x40]; if (0x42 + len > size) return false; - GetString(p + 0x42, len, Name); + if (len != 0) + GetString(p + 0x42, len, Name); return true; } @@ -321,7 +342,7 @@ struct CAttr { UInt32 Type; // UInt32 Len; - UString Name; + UString2 Name; // UInt16 Flags; // UInt16 Instance; CByteBuffer Data; @@ -364,7 +385,17 @@ static int CompareAttr(void *const *elem1, void *const *elem2, void *) const CAttr &a1 = *(*((const CAttr **)elem1)); const CAttr &a2 = *(*((const CAttr **)elem2)); RINOZ(MyCompare(a1.Type, a2.Type)); - RINOZ(wcscmp(a1.Name, a2.Name)); + if (a1.Name.IsEmpty()) + { + if (!a2.Name.IsEmpty()) + return -1; + } + else if (a2.Name.IsEmpty()) + return 1; + else + { + RINOZ(wcscmp(a1.Name.GetRawPtr(), a2.Name.GetRawPtr())); + } return MyCompare(a1.LowVcn, a2.LowVcn); } @@ -387,13 +418,13 @@ UInt32 CAttr::Parse(const Byte *p, unsigned size) return 0; NonResident = p[0x08]; { - unsigned nameLength = p[9]; + unsigned nameLen = p[9]; UInt32 nameOffset = Get16(p + 0x0A); - if (nameLength != 0) + if (nameLen != 0) { - if (nameOffset + nameLength * 2 > len) + if (nameOffset + nameLen * 2 > len) return 0; - GetString(p + nameOffset, nameLength, Name); + GetString(p + nameOffset, nameLen, Name); PRF(printf(" N=")); PRF_UTF16(Name); } @@ -485,10 +516,11 @@ bool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax, if (num == 0 || num > 8 || num > size) return false; - int i; - UInt64 vSize = p[num - 1]; - for (i = (int)num - 2; i >= 0; i--) - vSize = (vSize << 8) | p[i]; + UInt64 vSize = 0; + { + unsigned i = num; + do vSize = (vSize << 8) | p[--i]; while(i); + } if (vSize == 0) return false; p += num; @@ -510,8 +542,10 @@ bool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax, else { Int64 v = (signed char)p[num - 1]; - for (i = (int)num - 2; i >= 0; i--) - v = (v << 8) | p[i]; + { + for (unsigned i = num - 1; i != 0;) + v = (v << 8) | p[--i]; + } p += num; size -= num; lcn += v; @@ -617,7 +651,7 @@ static size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte { if (destSize + (1 << 12) > outBufLim || (src[0] & 1) != 0) return 0; - int numDistBits = 4; + unsigned numDistBits = 4; UInt32 sbOffset = 0; UInt32 pos = 0; @@ -669,7 +703,7 @@ static size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { - if (processedSize != NULL) + if (processedSize) *processedSize = 0; if (_virtPos >= Size) return (Size == _virtPos) ? S_OK: E_FAIL; @@ -830,7 +864,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) res = Stream->Read(data, size, &size); _physPos += size; } - if (processedSize != NULL) + if (processedSize) *processedSize = size; _virtPos += size; _curRem -= size; @@ -858,54 +892,6 @@ STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPositio return S_OK; } -class CByteBufStream: - public IInStream, - public CMyUnknownImp -{ - UInt64 _virtPos; -public: - CByteBuffer Buf; - void Init() { _virtPos = 0; } - - MY_UNKNOWN_IMP1(IInStream) - - STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); -}; - -STDMETHODIMP CByteBufStream::Read(void *data, UInt32 size, UInt32 *processedSize) -{ - if (processedSize != NULL) - *processedSize = 0; - if (_virtPos >= Buf.Size()) - return (_virtPos == Buf.Size()) ? S_OK: E_FAIL; - UInt64 rem = Buf.Size() - _virtPos; - if (rem < size) - size = (UInt32)rem; - memcpy(data, Buf + (size_t)_virtPos, size); - if (processedSize != NULL) - *processedSize = size; - _virtPos += size; - return S_OK; -} - -STDMETHODIMP CByteBufStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) -{ - switch (seekOrigin) - { - case STREAM_SEEK_SET: break; - case STREAM_SEEK_CUR: offset += _virtPos; break; - case STREAM_SEEK_END: offset += Buf.Size(); break; - default: return STG_E_INVALIDFUNCTION; - } - if (offset < 0) - return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _virtPos = offset; - if (newPosition) - *newPosition = offset; - return S_OK; -} - static HRESULT DataParseExtents(unsigned clusterSizeLog, const CObjectVector<CAttr> &attrs, unsigned attrIndex, unsigned attrIndexLim, UInt64 numPhysClusters, CRecordVector<CExtent> &Extents) { @@ -966,7 +952,9 @@ struct CMftRec // UInt16 NextAttrInstance; CMftRef BaseMftRef; // UInt32 ThisRecNumber; + UInt32 MyNumNameLinks; + int MyItemIndex; // index in Items[] of main item for that record, or -1 if there is no item for that record CObjectVector<CAttr> DataAttrs; CObjectVector<CFileNameAttr> FileNames; @@ -977,12 +965,40 @@ struct CMftRec CByteBuffer ReparseData; + int FindWin32Name_for_DosName(unsigned dosNameIndex) const + { + const CFileNameAttr &cur = FileNames[dosNameIndex]; + if (cur.IsDos()) + for (unsigned i = 0; i < FileNames.Size(); i++) + { + const CFileNameAttr &next = FileNames[i]; + if (next.IsWin32() && cur.ParentDirRef.Val == next.ParentDirRef.Val) + return i; + } + return -1; + } + + int FindDosName(unsigned nameIndex) const + { + const CFileNameAttr &cur = FileNames[nameIndex]; + if (cur.IsWin32()) + for (unsigned i = 0; i < FileNames.Size(); i++) + { + const CFileNameAttr &next = FileNames[i]; + if (next.IsDos() && cur.ParentDirRef.Val == next.ParentDirRef.Val) + return i; + } + return -1; + } + + /* bool IsAltStream(int dataIndex) const { return dataIndex >= 0 && ( (IsDir() || !DataAttrs[DataRefs[dataIndex].Start].Name.IsEmpty())); } + */ void MoveAttrsFrom(CMftRec &src) { @@ -1016,7 +1032,7 @@ struct CMftRec UInt64 GetSize(unsigned dataIndex) const { return DataAttrs[DataRefs[dataIndex].Start].GetSize(); } - CMftRec(): MyNumNameLinks(0) {} + CMftRec(): MyNumNameLinks(0), MyItemIndex(-1) {} }; void CMftRec::ParseDataNames() @@ -1040,12 +1056,10 @@ HRESULT CMftRec::GetStream(IInStream *mainStream, int dataIndex, unsigned clusterSizeLog, UInt64 numPhysClusters, IInStream **destStream) const { *destStream = 0; - CByteBufStream *streamSpec = new CByteBufStream; + CBufferInStream *streamSpec = new CBufferInStream; CMyComPtr<IInStream> streamTemp = streamSpec; - if (dataIndex < 0) - return E_FAIL; - + if (dataIndex >= 0) if ((unsigned)dataIndex < DataRefs.Size()) { const CDataRef &ref = DataRefs[dataIndex]; @@ -1231,26 +1245,42 @@ bool CMftRec::Parse(Byte *p, unsigned sectorSizeLog, UInt32 numSectors, UInt32 r return true; } +/* + NTFS probably creates empty DATA_ATTRIBUTE for empty file, + But it doesn't do it for + $Secure (:$SDS), + $Extend\$Quota + $Extend\$ObjId + $Extend\$Reparse +*/ + +static const int k_Item_DataIndex_IsEmptyFile = -1; // file without unnamed data stream +static const int k_Item_DataIndex_IsDir = -2; + +// static const int k_ParentFolderIndex_Root = -1; +static const int k_ParentFolderIndex_Lost = -2; +static const int k_ParentFolderIndex_Deleted = -3; + struct CItem { unsigned RecIndex; // index in Recs array unsigned NameIndex; // index in CMftRec::FileNames int DataIndex; /* index in CMftRec::DataRefs - -1: for folders - -1: for files that have no DATA_ATRIBUTE */ + -1: file without unnamed data stream + -2: for directories */ int ParentFolder; /* index in Items array -1: for root items -2: [LOST] folder -3: [UNKNOWN] folder (deleted lost) */ int ParentHost; /* index in Items array, if it's AltStream - -1: if it's not AltStream - -1: if there is no Host item */ + -1: if it's not AltStream */ - CItem(): DataIndex(-1), ParentFolder(-1), ParentHost(-1) {} + CItem(): DataIndex(k_Item_DataIndex_IsDir), ParentFolder(-1), ParentHost(-1) {} - bool IsDir() const { return DataIndex < 0; } + bool IsAltStream() const { return ParentHost != -1; } + bool IsDir() const { return DataIndex == k_Item_DataIndex_IsDir; } // check it !!! // probably NTFS for empty file still creates empty DATA_ATTRIBUTE // But it doesn't do it for $Secure:$SDS @@ -1276,7 +1306,9 @@ struct CDatabase bool _showSystemFiles; bool _showDeletedFiles; - UStringVector VirtFolderNames; + CObjectVector<UString2> VirtFolderNames; + UString EmptyString; + int _systemFolderIndex; int _lostFolderIndex_Normal; int _lostFolderIndex_Deleted; @@ -1311,6 +1343,8 @@ struct CDatabase const CMftRec &rec = Recs[(unsigned)recIndex]; if (!rec.IsDir()) return -1; + return rec.MyItemIndex; + /* unsigned left = 0, right = Items.Size(); while (left != right) { @@ -1319,9 +1353,9 @@ struct CDatabase UInt64 midValue = item.RecIndex; if (recIndex == midValue) { - // if (!item.IsAltStream) - // if (!rec.IsAltStream(item.DataIndex)) - if (item.DataIndex < 0) + // if item is not dir (file or alt stream we don't return it) + // if (item.DataIndex < 0) + if (item.IsDir()) return mid; right = mid; } @@ -1331,6 +1365,7 @@ struct CDatabase left = mid + 1; } return -1; + */ } bool FindSecurityDescritor(UInt32 id, UInt64 &offset, UInt32 &size) const; @@ -1374,8 +1409,6 @@ void CDatabase::ClearAndClose() InStream.Release(); } -#define MY_DIR_PREFIX(x) L"[" x L"]" WSTRING_PATH_SEPARATOR - void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const { const CItem *item = &Items[index]; @@ -1383,22 +1416,24 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const const CMftRec &rec = Recs[item->RecIndex]; size += rec.FileNames[item->NameIndex].Name.Len(); - bool isAltStream = rec.IsAltStream(item->DataIndex); + bool isAltStream = item->IsAltStream(); + if (isAltStream) { const CAttr &data = rec.DataAttrs[rec.DataRefs[item->DataIndex].Start]; + if (item->RecIndex == kRecIndex_RootDir) + { + wchar_t *s = path.AllocBstr(data.Name.Len() + 1); + s[0] = L':'; + if (!data.Name.IsEmpty()) + MyStringCopy(s + 1, data.Name.GetRawPtr()); + return; + } + size += data.Name.Len(); size++; } - /* - if (item->ParentHost >= 0) - { - item = &Items[item->ParentHost]; - size += item->Name.Len() + 1; - } - */ - for (unsigned i = 0;; i++) { if (i > 256) @@ -1407,7 +1442,8 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const return; } const wchar_t *servName; - if (item->RecIndex < kNumSysRecs) + if (item->RecIndex < kNumSysRecs + /* && item->RecIndex != kRecIndex_RootDir */) servName = kVirtualFolder_System; else { @@ -1420,7 +1456,7 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const } if (index2 == -1) break; - servName = (index2 == -2) ? + servName = (index2 == k_ParentFolderIndex_Lost) ? kVirtualFolder_Lost_Normal : kVirtualFolder_Lost_Deleted; } @@ -1435,47 +1471,31 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const bool needColon = false; if (isAltStream) { - const UString &name = rec.DataAttrs[rec.DataRefs[item->DataIndex].Start].Name; - size -= name.Len(); - MyStringCopy(s + size, (const wchar_t *)name); + const UString2 &name = rec.DataAttrs[rec.DataRefs[item->DataIndex].Start].Name; + if (!name.IsEmpty()) + { + size -= name.Len(); + MyStringCopy(s + size, name.GetRawPtr()); + } s[--size] = ':'; needColon = true; } { - const UString &name = rec.FileNames[item->NameIndex].Name; + const UString2 &name = rec.FileNames[item->NameIndex].Name; unsigned len = name.Len(); - MyStringCopy(s + size - len, (const wchar_t *)name); + if (len != 0) + MyStringCopy(s + size - len, name.GetRawPtr()); if (needColon) s[size] = ':'; size -= len; } - /* - { - unsigned len = item->Name.Len(); - size -= len; - MyStringCopy(s + size, (const wchar_t *)item->Name); - } - */ - - - /* - if (item->ParentHost >= 0) - { - item = &Items[item->ParentHost]; - unsigned len = item->Name.Len(); - size--; - size -= len; - MyStringCopy(s + size, (const wchar_t *)item->Name); - s[size + len] = ':'; - } - */ - for (;;) { const wchar_t *servName; - if (item->RecIndex < kNumSysRecs) + if (item->RecIndex < kNumSysRecs + /* && && item->RecIndex != kRecIndex_RootDir */) servName = kVirtualFolder_System; else { @@ -1483,17 +1503,20 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const if (index2 >= 0) { item = &Items[index2]; - const UString &name = Recs[item->RecIndex].FileNames[item->NameIndex].Name; + const UString2 &name = Recs[item->RecIndex].FileNames[item->NameIndex].Name; unsigned len = name.Len(); size--; - size -= len; - MyStringCopy(s + size, (const wchar_t *)name); + if (len != 0) + { + size -= len; + MyStringCopy(s + size, name.GetRawPtr()); + } s[size + len] = WCHAR_PATH_SEPARATOR; continue; } if (index2 == -1) break; - servName = (index2 == -2) ? + servName = (index2 == k_ParentFolderIndex_Lost) ? kVirtualFolder_Lost_Normal : kVirtualFolder_Lost_Deleted; } @@ -1800,120 +1823,110 @@ HRESULT CDatabase::Open() if (!rec.InUse() && !_showDeletedFiles) continue; - unsigned numNames = 0; + rec.MyNumNameLinks = rec.FileNames.Size(); + // printf("\n%4d: ", i); - FOR_VECTOR (t, rec.FileNames) - { - const CFileNameAttr &fna = rec.FileNames[t]; - // PRF(printf("%4d ", (int)fna.NameType)); - // PRF_UTF16(fna.Name) - // PRF(printf(" | ")); - if (fna.IsDos()) - continue; - unsigned numDatas = rec.DataRefs.Size(); - - /* - // we can use that code to reduce the number of alt streams - // For hard linked files we show alt streams only for first Name. - if (numDatas > 1 && numNames > 0) - numDatas = 1; - */ + + /* Actually DataAttrs / DataRefs are sorted by name. + It can not be more than one unnamed stream in DataRefs + And indexOfUnnamedStream <= 0. + */ - numNames++; + int indexOfUnnamedStream = -1; + if (!rec.IsDir()) + { + FOR_VECTOR(di, rec.DataRefs) + if (rec.DataAttrs[rec.DataRefs[di].Start].Name.IsEmpty()) + { + indexOfUnnamedStream = di; + break; + } + } - // here we suppose that first stream is main stream (unnamed stream). - // IS IT SO ???? - int hostIndex = -1; - if (rec.IsDir()) + if (rec.FileNames.IsEmpty()) + { + bool needShow = true; + if (i < kNumSysRecs) { - CItem item; - item.NameIndex = t; - item.RecIndex = i; - // item.ParentRef = fna.ParentDirRef; - // item.Attrib = rec.SiAttr.Attrib | 0x10; - // item.Attrib = fna.Attrib; - hostIndex = Items.Add(item); + needShow = false; + FOR_VECTOR(di, rec.DataRefs) + if (rec.GetSize(di) != 0) + { + needShow = true; + break; + } } - else + if (needShow) { - - // probably NTFS for empty file still creates empty DATA_ATTRIBUTE - // But it doesn't do it for $Secure:$SDS - if (rec.DataRefs.IsEmpty() || - !rec.DataAttrs[rec.DataRefs[0].Start].Name.IsEmpty()) - { - CItem item; - item.NameIndex = t; - item.RecIndex = i; - // item.ParentRef = fna.ParentDirRef; - // item.Attrib = rec.SiAttr.Attrib; - hostIndex = Items.Add(item); - } + CFileNameAttr &fna = rec.FileNames.AddNew(); + // we set incorrect ParentDirRef, that will place item to [LOST] folder + fna.ParentDirRef.Val = (UInt64)(Int64)-1; + char s[16 + 16]; + ConvertUInt32ToString(i, MyStpCpy(s, "[NONAME]-")); + fna.Name.SetFromAscii(s); + fna.NameType = kFileNameType_Win32Dos; + fna.Attrib = 0; } + } + + // bool isMainName = true; + + FOR_VECTOR (t, rec.FileNames) + { + #ifdef SHOW_DEBUG_INFO + const CFileNameAttr &fna = rec.FileNames[t]; + #endif + PRF(printf("\n %4d ", (int)fna.NameType)); + PRF_UTF16(fna.Name); + // PRF(printf(" | ")); + if (rec.FindWin32Name_for_DosName(t) >= 0) { - bool isThereUnNamedStream = false; - for (unsigned di = 0; di < numDatas; di++) - { - const UString &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name; - if (subName.IsEmpty()) - isThereUnNamedStream = true; - } - if (!rec.IsDir() && !isThereUnNamedStream) - { - // return S_FALSE; - } + rec.MyNumNameLinks--; + continue; } + + CItem item; + item.NameIndex = t; + item.RecIndex = i; + item.DataIndex = rec.IsDir() ? + k_Item_DataIndex_IsDir : + (indexOfUnnamedStream < 0 ? + k_Item_DataIndex_IsEmptyFile : + indexOfUnnamedStream); + + if (rec.MyItemIndex < 0) + rec.MyItemIndex = Items.Size(); + item.ParentHost = Items.Add(item); + + /* we can use that code to reduce the number of alt streams: + it will not show how alt streams for hard links. */ + // if (!isMainName) continue; isMainName = false; + + unsigned numAltStreams = 0; - for (unsigned di = 0; di < numDatas; di++) + FOR_VECTOR(di, rec.DataRefs) { - CItem item; - item.NameIndex = t; - // item.FileNameAttr = fna; - // item.Name = fna.Name; - // item.Attrib = rec.SiAttr.Attrib; - const UString &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name; - if (subName.IsEmpty()) - { - if (hostIndex >= 0) - continue; - hostIndex = Items.Size(); - } - else + if (!rec.IsDir() && (int)di == indexOfUnnamedStream) + continue; + + const UString2 &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name; + + PRF(printf("\n alt stream: ")); + PRF_UTF16(subName); + { // $BadClus:$Bad is sparse file for all clusters. So we skip it. if (i == kRecIndex_BadClus && subName == L"$Bad") continue; - if (hostIndex >= 0) - { - // item.Name = subName; - } - else - { - // there is no host file for some streams - // return E_FAIL; - // item.Name += L":"; - // item.Name += subName; - } - // item.Attrib = fna.Attrib; - item.ParentHost = hostIndex; - // item.IsAltStream = true; - ThereAreAltStreams = true; } - - PRF(printf("\n%3d", i)); - PRF(printf(" attrib=%2x ", rec.SiAttr.Attrib)); - // PRF_UTF16(item.Name); - - item.RecIndex = i; - item.DataIndex = di; - // item.ParentRef = fna.ParentDirRef; + numAltStreams++; + ThereAreAltStreams = true; + item.DataIndex = di; Items.Add(item); - rec.MyNumNameLinks++; } } - // rec.FileNames.ClearAndFree(); } if (Recs.Size() > kRecIndex_Security) @@ -1959,7 +1972,7 @@ HRESULT CDatabase::Open() const CFileNameAttr &fn = rec.FileNames[item.NameIndex]; const CMftRef &parentDirRef = fn.ParentDirRef; UInt64 refIndex = parentDirRef.GetIndex(); - if (refIndex == 5) + if (refIndex == kRecIndex_RootDir) item.ParentFolder = -1; else { @@ -1970,12 +1983,12 @@ HRESULT CDatabase::Open() if (Recs[item.RecIndex].InUse()) { thereAreUnknownFolders_Normal = true; - index = -2; + index = k_ParentFolderIndex_Lost; } else { thereAreUnknownFolders_Deleted = true; - index = -3; + index = k_ParentFolderIndex_Deleted; } } item.ParentFolder = index; @@ -2019,7 +2032,7 @@ public: INTERFACE_IInArchive(;) INTERFACE_IArchiveGetRawProps(;) STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); + STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); }; STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps) @@ -2038,29 +2051,30 @@ STDMETHODIMP CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID) STDMETHODIMP CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType) { *parentType = NParentType::kDir; - *parent = (UInt32)(Int32)-1; + int par = -1; - if (index >= Items.Size()) - return S_OK; - const CItem &item = Items[index]; - - if (item.ParentHost >= 0) - { - *parentType = NParentType::kAltStream; - *parent = (UInt32)(Int32)item.ParentHost; - return S_OK; - } - if (item.RecIndex < kNumSysRecs) + if (index < Items.Size()) { - if (_showSystemFiles) - *parent = _systemFolderIndex; - } - else if (item.ParentFolder >= 0) - *parent = item.ParentFolder; - else if (item.ParentFolder == -2) - *parent = _lostFolderIndex_Normal; - else if (item.ParentFolder == -3) - *parent = _lostFolderIndex_Deleted; + const CItem &item = Items[index]; + + if (item.ParentHost >= 0) + { + *parentType = NParentType::kAltStream; + par = (item.RecIndex == kRecIndex_RootDir ? -1 : item.ParentHost); + } + else if (item.RecIndex < kNumSysRecs) + { + if (_showSystemFiles) + par = _systemFolderIndex; + } + else if (item.ParentFolder >= 0) + par = item.ParentFolder; + else if (item.ParentFolder == k_ParentFolderIndex_Lost) + par = _lostFolderIndex_Normal; + else if (item.ParentFolder == k_ParentFolderIndex_Deleted) + par = _lostFolderIndex_Deleted; + } + *parent = (UInt32)(Int32)par; return S_OK; } @@ -2073,30 +2087,22 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data if (propID == kpidName) { #ifdef MY_CPU_LE - const UString *s; + const UString2 *s; if (index >= Items.Size()) s = &VirtFolderNames[index - Items.Size()]; else { const CItem &item = Items[index]; const CMftRec &rec = Recs[item.RecIndex]; - - // fix it for no HOST case !! - // if (item.IsAltStream && item.DataIndex >= 0) - if (rec.IsAltStream(item.DataIndex)) - { - if (item.ParentHost < 0) - return S_OK; - const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start]; - s = &data.Name; - } + if (item.IsAltStream()) + s = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start].Name; else - { s = &rec.FileNames[item.NameIndex].Name; - } - // s = &item.Name; } - *data = (const wchar_t *)*s; + if (s->IsEmpty()) + *data = (const wchar_t *)EmptyString; + else + *data = s->GetRawPtr(); *dataSize = (s->Len() + 1) * sizeof(wchar_t); *propType = PROP_DATA_TYPE_wchar_t_PTR_Z_LE; #endif @@ -2209,6 +2215,9 @@ static const Byte kProps[] = kpidLinks, kpidINode, kpidNumBlocks, + kpidNumAltStreams, + kpidIsAltStream, + kpidShortName, kpidIsDeleted }; @@ -2293,9 +2302,10 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) const CAttr &attr = VolAttrs[i]; if (attr.Type == ATTR_TYPE_VOLUME_NAME) { - UString name; + UString2 name; GetString(attr.Data, (unsigned)attr.Data.Size() / 2, name); - prop = name; + if (!name.IsEmpty()) + prop = name.GetRawPtr(); break; } } @@ -2312,7 +2322,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) CVolInfo vi; if (attr.ParseVolInfo(vi)) { - s += ' '; + s.Add_Space(); char temp[16]; ConvertUInt32ToString(vi.MajorVer, temp); s += temp; @@ -2339,6 +2349,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidWarning: if (_lostFolderIndex_Normal >= 0) prop = "There are lost files"; + break; /* case kpidWarningFlags: @@ -2372,7 +2383,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { case kpidName: case kpidPath: - prop = VirtFolderNames[index - Items.Size()]; + prop = VirtFolderNames[index - Items.Size()].GetRawPtr(); break; case kpidIsDir: prop = true; break; case kpidIsAux: prop = true; break; @@ -2433,35 +2444,46 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val prop = item.RecIndex; break; } + case kpidStreamId: + { + if (item.DataIndex >= 0) + prop = ((UInt64)item.RecIndex << 32) | (unsigned)item.DataIndex; + break; + } case kpidName: { - // prop = item.Name; - const UString *s; - if (rec.IsAltStream(item.DataIndex)) + const UString2 *s; + if (item.IsAltStream()) + s = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start].Name; + else + s = &rec.FileNames[item.NameIndex].Name; + if (s->IsEmpty()) + prop = (const wchar_t *)EmptyString; + else + prop = s->GetRawPtr(); + break; + } + + case kpidShortName: + { + if (!item.IsAltStream()) { - const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start]; - s = &data.Name; - if (item.ParentHost < 0) + int dosNameIndex = rec.FindDosName(item.NameIndex); + if (dosNameIndex >= 0) { - UString s2 = rec.FileNames[item.NameIndex].Name; - s2 += L':'; - s2 += *s; - prop = s2; - break; + const UString2 &s = rec.FileNames[dosNameIndex].Name; + if (s.IsEmpty()) + prop = (const wchar_t *)EmptyString; + else + prop = s.GetRawPtr(); } } - else - { - s = &rec.FileNames[item.NameIndex].Name; - } - prop = *s; - break; } case kpidIsDir: prop = item.IsDir(); break; - case kpidIsAltStream: prop = rec.IsAltStream(item.DataIndex); break; + case kpidIsAltStream: prop = item.IsAltStream(); break; case kpidIsDeleted: prop = !rec.InUse(); break; case kpidIsAux: prop = false; break; @@ -2491,12 +2513,35 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val if (item.IsDir()) attrib |= FILE_ATTRIBUTE_DIRECTORY; + /* some system entries can contain extra flags (Index View). + // 0x10000000 (Directory) + // 0x20000000 FILE_ATTR_VIEW_INDEX_PRESENT MFT_RECORD_IS_VIEW_INDEX (Index View) + But we don't need them */ + attrib &= 0xFFFF; + prop = attrib; break; } - case kpidLinks: prop = rec.MyNumNameLinks; break; - case kpidSize: if (data) prop = data->GetSize(); break; - case kpidPackSize: if (data) prop = data->GetPackSize(); break; + case kpidLinks: if (rec.MyNumNameLinks != 1) prop = rec.MyNumNameLinks; break; + + case kpidNumAltStreams: + { + if (!item.IsAltStream()) + { + unsigned num = rec.DataRefs.Size(); + if (num > 0) + { + if (!rec.IsDir() && rec.DataAttrs[rec.DataRefs[0].Start].Name.IsEmpty()) + num--; + if (num > 0) + prop = num; + } + } + break; + } + + case kpidSize: if (data) prop = data->GetSize(); else if (!item.IsDir()) prop = (UInt64)0; break; + case kpidPackSize: if (data) prop = data->GetPackSize(); else if (!item.IsDir()) prop = (UInt64)0; break; case kpidNumBlocks: if (data) prop = (UInt32)rec.GetNumExtents(item.DataIndex, Header.ClusterSizeLog, Header.NumClusters); break; } prop.Detach(value); @@ -2603,7 +2648,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, outStreamSpec->Init(); const CMftRec &rec = Recs[item.RecIndex]; - const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start]; int res = NExtract::NOperationResult::kDataError; { @@ -2626,8 +2670,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } } } - totalPackSize += data.GetPackSize(); - totalSize += data.GetSize(); + if (item.DataIndex >= 0) + { + const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start]; + totalPackSize += data.GetPackSize(); + totalSize += data.GetSize(); + } outStreamSpec->ReleaseStream(); RINOK(extractCallback->SetOperationResult(res)); } @@ -2641,7 +2689,7 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) +STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) { InitProps(); @@ -2668,15 +2716,13 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v return S_OK; } -IMP_CreateArcIn +static const Byte k_Signature[] = { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 }; -static CArcInfo g_ArcInfo = - { "NTFS", "ntfs img", 0, 0xD9, - 9, { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 }, +REGISTER_ARC_I( + "NTFS", "ntfs img", 0, 0xD9, + k_Signature, 3, 0, - CreateArc }; - -REGISTER_ARC(Ntfs) + NULL) }} diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp index ae7553df..43450e80 100644 --- a/CPP/7zip/Archive/PeHandler.cpp +++ b/CPP/7zip/Archive/PeHandler.cpp @@ -37,7 +37,7 @@ using namespace NWindows; namespace NArchive { namespace NPe { -static const UInt32 k_Signature = 0x00004550; +static const UInt32 k_Signature32 = 0x00004550; static HRESULT CalcCheckSum(ISequentialInStream *stream, UInt32 size, UInt32 excludePos, UInt32 &res) { @@ -137,7 +137,7 @@ struct CHeader bool CHeader::Parse(const Byte *p) { - if (Get32(p) != k_Signature) + if (Get32(p) != k_Signature32) return false; p += 4; G16( 0, Machine); @@ -364,19 +364,14 @@ struct CSection static const unsigned kNameSize = 8; -static AString GetName(const Byte *name) +static void GetName(const Byte *name, AString &res) { - AString res; - char *p = res.GetBuffer(kNameSize); - memcpy(p, name, kNameSize); - p[kNameSize] = 0; - res.ReleaseBuffer(); - return res; + res.SetFrom_CalcLen((const char *)name, kNameSize); } void CSection::Parse(const Byte *p) { - Name = GetName(p); + GetName(p, Name); G32( 8, VSize); G32(12, Va); G32(16, PSize); @@ -484,33 +479,33 @@ static const CUInt32PCharPair g_SubSystems[] = { 14, "XBOX" } }; -static const wchar_t *g_ResTypes[] = +static const char * const g_ResTypes[] = { NULL - , L"CURSOR" - , L"BITMAP" - , L"ICON" - , L"MENU" - , L"DIALOG" - , L"STRING" - , L"FONTDIR" - , L"FONT" - , L"ACCELERATOR" - , L"RCDATA" - , L"MESSAGETABLE" - , L"GROUP_CURSOR" + , "CURSOR" + , "BITMAP" + , "ICON" + , "MENU" + , "DIALOG" + , "STRING" + , "FONTDIR" + , "FONT" + , "ACCELERATOR" + , "RCDATA" + , "MESSAGETABLE" + , "GROUP_CURSOR" , NULL - , L"GROUP_ICON" + , "GROUP_ICON" , NULL - , L"VERSION" - , L"DLGINCLUDE" + , "VERSION" + , "DLGINCLUDE" , NULL - , L"PLUGPLAY" - , L"VXD" - , L"ANICURSOR" - , L"ANIICON" - , L"HTML" - , L"MANIFEST" + , "PLUGPLAY" + , "VXD" + , "ANICURSOR" + , "ANIICON" + , "HTML" + , "MANIFEST" }; static const UInt32 kFlag = (UInt32)1 << 31; @@ -561,7 +556,10 @@ struct CTextFile void NewLine(); void AddString(const char *s); void AddSpaces(int num); - void AddBytes(const Byte *p, size_t len); + void AddBytes(const Byte *p, size_t size) + { + Buf.AddData(p, size); + } void OpenBlock(int num) { @@ -623,12 +621,6 @@ void CTextFile::AddSpaces(int num) AddChar(' '); } -void CTextFile::AddBytes(const Byte *data, size_t size) -{ - Byte *p = Buf.GetCurPtrAndGrow(size); - memcpy(p, data, size); -} - struct CStringItem: public CTextFile { UInt32 Lang; @@ -648,7 +640,7 @@ struct CMixItem int VersionIndex; CMixItem(): SectionIndex(-1), ResourceIndex(-1), StringIndex(-1), VersionIndex(-1) {} - bool IsSectionItem() const { return ResourceIndex < 0 && StringIndex < 0 && VersionIndex < 0; }; + bool IsSectionItem() const { return ResourceIndex < 0 && StringIndex < 0 && VersionIndex < 0; } }; struct CUsedBitmap @@ -802,6 +794,7 @@ static const STATPROPSTG kArcProps[] = { (LPOLESTR)L"Heap Commit", kpidHeapCommit, VT_UI8}, { (LPOLESTR)L"Image Base", kpidImageBase, VT_UI8}, { NULL, kpidComment, VT_BSTR}, + // { (LPOLESTR)L"Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8}, // { (LPOLESTR)L"Base Of Code", kpidBaseOfCode, VT_UI8}, // { (LPOLESTR)L"Base Of Data", kpidBaseOfData32, VT_UI8}, @@ -913,7 +906,7 @@ HRESULT CHandler::ReadString(UInt32 offset, UString &dest) const if ((rem - 2) / 2 < len) return S_FALSE; dest.Empty(); - wchar_t *destBuf = dest.GetBuffer(len); + wchar_t *destBuf = dest.GetBuf(len); offset += 2; const Byte *src = _buf + offset; unsigned i; @@ -924,7 +917,8 @@ HRESULT CHandler::ReadString(UInt32 offset, UString &dest) const break; destBuf[i] = c; } - dest.ReleaseBuffer(i); + destBuf[i] = 0; + dest.ReleaseBuf_SetLen(i); return S_OK; } @@ -960,7 +954,7 @@ void CHandler::AddLangPrefix(UString &s, UInt32 lang) const if (!_oneLang) { AddResNameToString(s, lang); - s += WCHAR_PATH_SEPARATOR; + s.Add_PathSepar(); } } @@ -978,7 +972,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { UString s = _resourcesPrefix; AddLangPrefix(s, item.Lang); - s += L"string.txt"; + s.AddAscii("string.txt"); prop = s; break; } @@ -996,7 +990,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { UString s = _resourcesPrefix; AddLangPrefix(s, item.Lang); - s += L"version.txt"; + s.AddAscii("version.txt"); prop = s; break; } @@ -1015,22 +1009,22 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val UString s = _resourcesPrefix; AddLangPrefix(s, item.Lang); { - const wchar_t *p = NULL; + const char *p = NULL; if (item.Type < ARRAY_SIZE(g_ResTypes)) p = g_ResTypes[item.Type]; if (p) - s += p; + s.AddAscii(p); else AddResNameToString(s, item.Type); } - s += WCHAR_PATH_SEPARATOR; + s.Add_PathSepar(); AddResNameToString(s, item.ID); if (item.HeaderSize != 0) { if (item.IsBmp()) - s += L".bmp"; + s.AddAscii(".bmp"); else if (item.IsIcon()) - s += L".ico"; + s.AddAscii(".ico"); } prop = s; break; @@ -1199,11 +1193,14 @@ static UInt32 SetBitmapHeader(Byte *dest, const Byte *src, UInt32 size) return 0; if (h.YSize < 0) h.YSize = -h.YSize; - if (h.XSize > (1 << 26) || h.YSize > (1 << 26) || h.Planes != 1 || h.BitCount > 32 || - h.Compression != 0) // BI_RGB + if (h.XSize > (1 << 26) || h.YSize > (1 << 26) || h.Planes != 1 || h.BitCount > 32) return 0; if (h.SizeImage == 0) + { + if (h.Compression != 0) // BI_RGB + return 0; h.SizeImage = GetImageSize(h.XSize, h.YSize, h.BitCount); + } UInt32 totalSize = kBmpHeaderSize + size; UInt32 offBits = totalSize - h.SizeImage; // BITMAPFILEHEADER @@ -1413,7 +1410,7 @@ static void PrintVersion(UString &s, UInt32 ms, UInt32 ls) PrintUInt32(s, LOWORD(ls)); } -static const char *k_VS_FileFlags[] = +static const char * const k_VS_FileFlags[] = { "DEBUG" , "PRERELEASE" @@ -1432,7 +1429,7 @@ static const CUInt32PCharPair k_VS_FileOS[] = { 0x40004, "VOS_NT_WINDOWS32" } }; -static const char *k_VS_FileOS_High[] = +static const char * const k_VS_FileOS_High[] = { "VOS_UNKNOWN" , "VOS_DOS" @@ -1445,7 +1442,7 @@ static const char *k_VS_FileOS_High[] = static const UInt32 kMY_VFT_DRV = 3; static const UInt32 kMY_VFT_FONT = 4; -static const char *k_VS_FileOS_Low[] = +static const char * const k_VS_FileOS_Low[] = { "VOS__BASE" , "VOS__WINDOWS16" @@ -1454,7 +1451,7 @@ static const char *k_VS_FileOS_Low[] = , "VOS__WINDOWS32" }; -static const char *k_VS_FileType[] = +static const char * const k_VS_FileType[] = { "VFT_UNKNOWN" , "VFT_APP" @@ -1467,7 +1464,7 @@ static const char *k_VS_FileType[] = }; // Subtype for VFT_DRV Type -static const char *k_VS_FileSubType_DRV[] = +static const char * const k_VS_FileSubType_DRV[] = { "0" , "PRINTER" @@ -1485,7 +1482,7 @@ static const char *k_VS_FileSubType_DRV[] = }; // Subtype for VFT_FONT Type -static const char *k_VS_FileSubType_FONT[] = +static const char * const k_VS_FileSubType_FONT[] = { "0" , "VFT2_FONT_RASTER" @@ -1493,10 +1490,10 @@ static const char *k_VS_FileSubType_FONT[] = , "VFT2_FONT_TRUETYPE" }; -static int FindKey(CObjectVector<CStringKeyValue> &v, const UString &key) +static int FindKey(CObjectVector<CStringKeyValue> &v, const char *key) { FOR_VECTOR (i, v) - if (v[i].Key == key) + if (v[i].Key.IsEqualTo(key)) return i; return -1; } @@ -1665,7 +1662,7 @@ struct CVersionBlock UInt32 TotalLen; UInt32 ValueLen; bool IsTextValue; - int StrSize; + unsigned StrSize; bool Parse(const Byte *p, UInt32 size); }; @@ -1691,7 +1688,7 @@ bool CVersionBlock::Parse(const Byte *p, UInt32 size) return false; TotalLen = Get16(p); ValueLen = Get16(p + 2); - if (TotalLen > size) + if (TotalLen == 0 || TotalLen > size) return false; switch (Get16(p + 4)) { @@ -1699,8 +1696,12 @@ bool CVersionBlock::Parse(const Byte *p, UInt32 size) case 1: IsTextValue = true; break; default: return false; } - StrSize = Get_Utf16Str_Len_InBytes(p + k_ResoureBlockHeader_Size, TotalLen - k_ResoureBlockHeader_Size); - return StrSize >= 0; + StrSize = 0; + int t = Get_Utf16Str_Len_InBytes(p + k_ResoureBlockHeader_Size, TotalLen - k_ResoureBlockHeader_Size); + if (t < 0) + return false; + StrSize = t; + return true; } static void AddParamString(CTextFile &f, const Byte *p, size_t sLen) @@ -1868,7 +1869,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector int sLen = Get_Utf16Str_Len_InBytes(p + pos, endPos3 - pos); if (sLen < 0) return false; - AddParamString(f, p + pos, sLen); + AddParamString(f, p + pos, (unsigned)sLen); CopyToUString(p + pos, value); pos += sLen + 2; } @@ -2276,6 +2277,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) // _parseResources = false; UInt64 mainSize = 0, mainSize2 = 0; + for (i = 0; i < _sections.Size(); i++) { const CSection § = _sections[i]; @@ -2287,7 +2289,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) if (res == S_OK) { _resourcesPrefix.SetFromAscii(sect.Name); - _resourcesPrefix += WCHAR_PATH_SEPARATOR; + _resourcesPrefix.Add_PathSepar(); FOR_VECTOR (j, _items) { const CResItem &item = _items[j]; @@ -2348,7 +2350,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) mainSize = sect.PSize; _mainSubfile = _mixItems.Size(); } - else + else if (sect.PSize >= mainSize2) mainSize2 = sect.PSize; } _mixItems.Add(mixItem); @@ -2370,7 +2372,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) for (i = 0; i < _versionKeys.Size(); i++) { if (i != 0) - _versionFullString += L'\n'; + _versionFullString.Add_LF(); const CStringKeyValue &k = _versionKeys[i]; _versionFullString += k.Key; _versionFullString += L": "; @@ -2378,20 +2380,20 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) } { - int keyIndex = FindKey(_versionKeys, L"OriginalFilename"); + int keyIndex = FindKey(_versionKeys, "OriginalFilename"); if (keyIndex >= 0) _originalFilename = _versionKeys[keyIndex].Value; } { - int keyIndex = FindKey(_versionKeys, L"FileDescription"); + int keyIndex = FindKey(_versionKeys, "FileDescription"); if (keyIndex >= 0) _versionShortString = _versionKeys[keyIndex].Value; } { - int keyIndex = FindKey(_versionKeys, L"FileVersion"); + int keyIndex = FindKey(_versionKeys, "FileVersion"); if (keyIndex >= 0) { - _versionShortString += L' '; + _versionShortString.Add_Space(); _versionShortString += _versionKeys[keyIndex].Value; } } @@ -2597,7 +2599,8 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) } referenceBuf->Buf.Alloc(item.HeaderSize + item.Size); memcpy(referenceBuf->Buf, item.Header, item.HeaderSize); - memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size); + if (item.Size != 0) + memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size); } inStreamSpec->Init(referenceBuf); @@ -2612,17 +2615,15 @@ STDMETHODIMP CHandler::AllowTail(Int32 allowTail) return S_OK; } -IMP_CreateArcIn +static const Byte k_Signature[] = { 'M', 'Z' }; -static CArcInfo g_ArcInfo = - { "PE", "exe dll sys", 0, 0xDD, - 2, { 'M', 'Z' }, +REGISTER_ARC_I( + "PE", "exe dll sys", 0, 0xDD, + k_Signature, 0, NArcInfoFlags::kPreArc, - CreateArc, NULL, IsArc_Pe }; - -REGISTER_ARC(Pe) - + IsArc_Pe) + } @@ -2836,7 +2837,13 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val const CSection &item = _items[index]; switch (propID) { - case kpidPath: prop = MultiByteToUnicodeString(NPe::GetName(item.Name)); break; + case kpidPath: + { + AString name; + NPe::GetName(item.Name, name); + prop = MultiByteToUnicodeString(name); + break; + } case kpidSize: case kpidPackSize: prop = (UInt64)item.PSize; break; case kpidVirtualSize: prop = (UInt64)item.VSize; break; @@ -2995,16 +3002,14 @@ STDMETHODIMP CHandler::AllowTail(Int32 allowTail) return S_OK; } -IMP_CreateArcIn +static const Byte k_Signature[] = { 'V', 'Z' }; -static CArcInfo g_ArcInfo = - { "TE", "te", 0, 0xCF, - 2, { 'V', 'Z' }, +REGISTER_ARC_I( + "TE", "te", 0, 0xCF, + k_Signature, 0, NArcInfoFlags::kPreArc, - CreateArc, NULL, IsArc_Te }; - -REGISTER_ARC(TE) + IsArc_Te) } } diff --git a/CPP/7zip/Archive/PpmdHandler.cpp b/CPP/7zip/Archive/PpmdHandler.cpp index 70e9ffac..86927f8f 100644 --- a/CPP/7zip/Archive/PpmdHandler.cpp +++ b/CPP/7zip/Archive/PpmdHandler.cpp @@ -28,10 +28,6 @@ using namespace NWindows; namespace NArchive { namespace NPpmd { -static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } -static void SzBigFree(void *, void *address) { BigFree(address); } -static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; - static const UInt32 kBufSize = (1 << 20); struct CBuf @@ -90,11 +86,10 @@ HRESULT CItem::ReadHeader(ISequentialInStream *s, UInt32 &headerSize) nameLen &= 0x3FFF; if (nameLen > (1 << 9)) return S_FALSE; - char *name = Name.GetBuffer(nameLen + 1); + char *name = Name.GetBuf(nameLen); HRESULT res = ReadStream_FALSE(s, name, nameLen); - name[nameLen] = 0; + Name.ReleaseBuf_CalcLen(nameLen); headerSize = kHeaderSize + nameLen; - Name.ReleaseBuffer(); return res; } @@ -449,15 +444,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, return extractCallback->SetOperationResult(opRes); } -IMP_CreateArcIn +static const Byte k_Signature[] = { 0x8F, 0xAF, 0xAC, 0x84 }; -static CArcInfo g_ArcInfo = - { "Ppmd", "pmd", 0, 0xD, - 4, { 0x8F, 0xAF, 0xAC, 0x84 }, +REGISTER_ARC_I( + "Ppmd", "pmd", 0, 0xD, + k_Signature, 0, 0, - CreateArc }; - -REGISTER_ARC(Ppmd) + NULL) }} diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp index c26d72f9..516e5d7f 100644 --- a/CPP/7zip/Archive/Rar/RarHandler.cpp +++ b/CPP/7zip/Archive/Rar/RarHandler.cpp @@ -89,7 +89,7 @@ UInt32 CItem::GetWinAttrib() const return a; } -static const char *kHostOS[] = +static const char * const kHostOS[] = { "MS DOS" , "OS/2" @@ -354,7 +354,7 @@ static int ReadTime(const Byte *p, unsigned size, Byte mask, CRarTime &rarTime) } #define READ_TIME(_mask_, _ttt_) \ - { int size2 = ReadTime(p, size, _mask_, _ttt_); if (size2 < 0) return false; p += size2, size -= size2; } + { int size2 = ReadTime(p, size, _mask_, _ttt_); if (size2 < 0) return false; p += (unsigned)size2, size -= (unsigned)size2; } #define READ_TIME_2(_mask_, _def_, _ttt_) \ _def_ = ((_mask_ & 8) != 0); if (_def_) \ @@ -421,7 +421,7 @@ bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item) { item.IsAltStream = true; item.Name.Empty(); - item.UnicodeName = L".ACL"; + item.UnicodeName.SetFromAscii(".ACL"); } else if (item.Name == "STM" && size != 0 && (size & 1) == 0) { @@ -517,7 +517,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass RINOK(getTextPassword->CryptoGetTextPassword(&password)) unsigned len = 0; if (password) - len = MyStringLen((BSTR)password); + len = MyStringLen(password); CByteBuffer buffer(len * 2); for (unsigned i = 0; i < len; i++) { @@ -645,6 +645,8 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass error = k_ErrorType_Corrupted; ArcInfo.VolNumber = (UInt32)Get16(m_FileHeaderData + offset); } + + ArcInfo.EndOfArchive_was_Read = true; } m_Position += processed; FinishCryptoBlock(); @@ -668,7 +670,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass bool okItem = ReadHeaderReal(m_FileHeaderData + 7, m_BlockHeader.HeadSize - 7, item); if (okItem) { - if (!CheckHeaderCrc(m_FileHeaderData, m_BlockHeader.HeadSize - item.CommentSize)) + if (!CheckHeaderCrc(m_FileHeaderData, (unsigned)m_BlockHeader.HeadSize - item.CommentSize)) { error = k_ErrorType_Corrupted; // ThrowExceptionWithCode(CInArchiveException::kFileHeaderCRCError); return S_OK; @@ -802,8 +804,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) // FLAGS_TO_PROP(k_Flags, _arcInfo.Flags, prop); if (_arcInfo.Is_DataCRC_Defined()) { - if (!s.IsEmpty()) - s += ' '; + s.Add_Space_if_NotEmpty(); s += "VolCRC"; } prop = s; @@ -1008,27 +1009,28 @@ public: { _first = true; _newStyle = newStyle; - int dotPos = name.ReverseFind('.'); + int dotPos = name.ReverseFind_Dot(); UString basePart = name; + if (dotPos >= 0) { UString ext = name.Ptr(dotPos + 1); - if (ext.IsEqualToNoCase(L"rar")) + if (ext.IsEqualTo_Ascii_NoCase("rar")) { _afterPart = name.Ptr(dotPos); basePart = name.Left(dotPos); } - else if (ext.IsEqualToNoCase(L"exe")) + else if (ext.IsEqualTo_Ascii_NoCase("exe")) { - _afterPart = L".rar"; + _afterPart.SetFromAscii(".rar"); basePart = name.Left(dotPos); } else if (!_newStyle) { - if (ext.IsEqualToNoCase(L"000") || - ext.IsEqualToNoCase(L"001") || - ext.IsEqualToNoCase(L"r00") || - ext.IsEqualToNoCase(L"r01")) + 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; @@ -1042,18 +1044,21 @@ public: if (!_newStyle) { _afterPart.Empty(); - _unchangedPart = basePart + UString(L"."); - _changedPart = L"r00"; + _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; @@ -1071,34 +1076,59 @@ public: UString GetNextName() { - UString newName; if (_newStyle || !_first) { - for (int i = (int)_changedPart.Len() - 1; i >= 0; i--) + unsigned i = _changedPart.Len(); + for (;;) { - wchar_t c = _changedPart[i]; + wchar_t c = _changedPart[--i]; if (c == L'9') { c = L'0'; - newName.InsertAtFront(c); + _changedPart.ReplaceOneCharAtPos(i, c); if (i == 0) - newName.InsertAtFront(L'1'); + { + _changedPart.InsertAtFront(L'1'); + break; + } continue; } c++; - newName = UString(c) + newName; - i--; - for (; i >= 0; i--) - newName.InsertAtFront(_changedPart[i]); + _changedPart.ReplaceOneCharAtPos(i, c); break; } - _changedPart = newName; } + _first = false; return _unchangedPart + _changedPart + _afterPart; } }; +static HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize) +{ + areThereNonZeros = false; + numZeros = 0; + const size_t kBufSize = 1 << 9; + Byte buf[kBufSize]; + for (;;) + { + UInt32 size = 0; + HRESULT(stream->Read(buf, kBufSize, &size)); + if (size == 0) + return S_OK; + for (UInt32 i = 0; i < size; i++) + if (buf[i] != 0) + { + areThereNonZeros = true; + numZeros += i; + return S_OK; + } + numZeros += size; + if (numZeros > maxSize) + return S_OK; + } +} + HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback) @@ -1174,6 +1204,7 @@ HRESULT CHandler::Open2(IInStream *stream, RINOK(archive.Open(inStream, maxCheckStartPosition)); _isArc = true; CItem item; + for (;;) { if (archive.m_Position > endPos) @@ -1181,11 +1212,13 @@ HRESULT CHandler::Open2(IInStream *stream, _errorFlags |= kpv_ErrorFlags_UnexpectedEnd; break; } + EErrorType error; // bool decryptionError; // AString errorMessageLoc; bool filled; HRESULT result = archive.GetNextItem(item, getTextPassword, filled, error); + if (error != k_ErrorType_OK) { if (error == k_ErrorType_UnexpectedEnd) @@ -1198,16 +1231,33 @@ HRESULT CHandler::Open2(IInStream *stream, // AddErrorMessage(errorMessageLoc); } RINOK(result); + if (!filled) { if (error == k_ErrorType_DecryptionError && _items.IsEmpty()) return S_FALSE; + + if (archive.ArcInfo.ExtraZeroTail_is_Possible()) + { + /* if there is recovery record for multivolume archive, + RAR adds 18 bytes (ZERO bytes) at the end for alignment. + We must skip these bytes to prevent phySize warning. */ + RINOK(inStream->Seek(archive.ArcInfo.EndPos, STREAM_SEEK_SET, NULL)); + bool areThereNonZeros; + UInt64 numZeros; + const UInt64 maxSize = 1 << 12; + RINOK(ReadZeroTail(inStream, areThereNonZeros, numZeros, maxSize)); + if (!areThereNonZeros && numZeros != 0 && numZeros <= maxSize) + archive.ArcInfo.EndPos += numZeros; + } break; } + if (item.IgnoreItem()) continue; bool needAdd = true; + if (item.IsSplitBefore()) { if (!_refItems.IsEmpty()) @@ -1217,6 +1267,7 @@ HRESULT CHandler::Open2(IInStream *stream, needAdd = false; } } + if (needAdd) { CRefItem refItem; @@ -1225,7 +1276,9 @@ HRESULT CHandler::Open2(IInStream *stream, refItem.VolumeIndex = _arcs.Size(); _refItems.Add(refItem); } + _items.Add(item); + if (openCallback && _items.Size() % 100 == 0) { UInt64 numFiles = _items.Size(); @@ -1256,7 +1309,7 @@ HRESULT CHandler::Open2(IInStream *stream, /* int baseFileIndex = -1; - for (int i = 0; i < _refItems.Size(); i++) + for (unsigned i = 0; i < _refItems.Size(); i++) { CItem &item = _items[_refItems[i].ItemIndex]; if (item.IsAltStream) @@ -1430,7 +1483,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (numItems == 0) return S_OK; unsigned lastIndex = 0; - CRecordVector<int> importantIndexes; + CRecordVector<unsigned> importantIndexes; CRecordVector<bool> extractStatuses; for (UInt32 t = 0; t < numItems; t++) @@ -1470,7 +1523,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; - CFilterCoder *filterStreamSpec = new CFilterCoder; + CFilterCoder *filterStreamSpec = new CFilterCoder(false); CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec; NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL; @@ -1576,22 +1629,25 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, // unpackedPos += 0; CMyComPtr<ISequentialInStream> inStream; + if (item.IsEncrypted()) { CMyComPtr<ICryptoSetPassword> cryptoSetPassword; + if (item.UnPackVersion >= 29) { if (!rar29CryptoDecoder) { rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder; rar29CryptoDecoder = rar29CryptoDecoderSpec; - // RINOK(rar29CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar29Decoder)); } rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36); + /* CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties; RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &cryptoProperties)); - RINOK(cryptoProperties->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0)); + */ + RINOK(rar29CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0)); filterStreamSpec->Filter = rar29CryptoDecoder; } else if (item.UnPackVersion >= 20) @@ -1600,7 +1656,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { rar20CryptoDecoderSpec = new NCrypto::NRar20::CDecoder; rar20CryptoDecoder = rar20CryptoDecoderSpec; - // RINOK(rar20CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar20Decoder)); } filterStreamSpec->Filter = rar20CryptoDecoder; } @@ -1610,8 +1665,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod)); continue; } - RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, - &cryptoSetPassword)); + + RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword)); if (!getTextPassword) extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword); @@ -1624,7 +1679,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UString unicodePassword; unsigned len = 0; if (password) - len = MyStringLen((BSTR)password); + len = MyStringLen(password); CByteBuffer buffer(len * 2); for (unsigned i = 0; i < len; i++) { @@ -1646,14 +1701,18 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { RINOK(cryptoSetPassword->CryptoSetPassword(0, 0)); } + filterStreamSpec->SetInStream(folderInStream); + filterStreamSpec->SetOutStreamSize(NULL); inStream = filterStream; } else { inStream = folderInStream; } + CMyComPtr<ICompressCoder> commonCoder; + switch(item.Method) { case '0': @@ -1679,14 +1738,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, mi.Coder.Release(); if (item.UnPackVersion <= 40) { - UInt32 methodID = 0x040300; + UInt32 methodID = 0x40300; if (item.UnPackVersion < 20) methodID += 1; else if (item.UnPackVersion < 29) methodID += 2; else methodID += 3; - RINOK(CreateCoder(EXTERNAL_CODECS_VARS methodID, mi.Coder, false)); + RINOK(CreateCoder(EXTERNAL_CODECS_VARS methodID, false, mi.Coder)); } if (mi.Coder == 0) @@ -1722,7 +1781,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod)); continue; } + HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &item.Size, progress); + if (item.IsEncrypted()) filterStreamSpec->ReleaseInStream(); if (result == S_FALSE) @@ -1771,15 +1832,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, IMPL_ISetCompressCodecsInfo -IMP_CreateArcIn - -static CArcInfo g_ArcInfo = - { "Rar", "rar r00", 0, 3, - NHeader::kMarkerSize, SIGNATURE, +REGISTER_ARC_I( + "Rar", "rar r00", 0, 3, + kMarker, 0, NArcInfoFlags::kFindSignature, - CreateArc }; - -REGISTER_ARC(Rar) + NULL) }} diff --git a/CPP/7zip/Archive/Rar/RarHandler.h b/CPP/7zip/Archive/Rar/RarHandler.h index 81191be9..dd3daa5d 100644 --- a/CPP/7zip/Archive/Rar/RarHandler.h +++ b/CPP/7zip/Archive/Rar/RarHandler.h @@ -1,4 +1,4 @@ -// Rar/Handler.h +// RarHandler.h #ifndef __RAR_HANDLER_H #define __RAR_HANDLER_H @@ -24,18 +24,25 @@ struct CInArcInfo UInt32 EndFlags; UInt32 VolNumber; UInt32 DataCRC; + bool EndOfArchive_was_Read; - CInArcInfo(): EndFlags(0) {} + CInArcInfo(): EndFlags(0), EndOfArchive_was_Read(false) {} UInt64 GetPhySize() const { return EndPos - StartPos; } - bool IsSolid() const { return (Flags & NHeader::NArchive::kSolid) != 0; } - bool IsCommented() const { return (Flags & NHeader::NArchive::kComment) != 0; } + bool ExtraZeroTail_is_Possible() const { return IsVolume() && IsRecovery() && EndOfArchive_was_Read; } + bool IsVolume() const { return (Flags & NHeader::NArchive::kVolume) != 0; } + bool IsCommented() const { return (Flags & NHeader::NArchive::kComment) != 0; } + // kLock + bool IsSolid() const { return (Flags & NHeader::NArchive::kSolid) != 0; } bool HaveNewVolumeName() const { return (Flags & NHeader::NArchive::kNewVolName) != 0; } - bool IsFirstVolume() const { return (Flags & NHeader::NArchive::kFirstVolume) != 0; } + // kAuthenticity + bool IsRecovery() const { return (Flags & NHeader::NArchive::kRecovery) != 0; } bool IsEncrypted() const { return (Flags & NHeader::NArchive::kBlockEncryption) != 0; } + bool IsFirstVolume() const { return (Flags & NHeader::NArchive::kFirstVolume) != 0; } bool IsThereEncryptVer() const { return (Flags & NHeader::NArchive::kEncryptVer) != 0; } + bool IsEncryptOld() const { return (!IsThereEncryptVer() || EncryptVersion < 36); } bool Is_VolNumber_Defined() const { return (EndFlags & NHeader::NArchive::kEndOfArc_Flags_VolNumber) != 0; } diff --git a/CPP/7zip/Archive/Rar/RarItem.h b/CPP/7zip/Archive/Rar/RarItem.h index 56d25f2c..13daa1cb 100644 --- a/CPP/7zip/Archive/Rar/RarItem.h +++ b/CPP/7zip/Archive/Rar/RarItem.h @@ -84,10 +84,10 @@ struct CItem CItem() { Clear(); } - UInt64 GetFullSize() const { return MainPartSize + CommentSize + AlignSize + PackSize; }; - // DWORD GetHeaderWithCommentSize() const { return MainPartSize + CommentSize; }; - UInt64 GetCommentPosition() const { return Position + MainPartSize; }; - UInt64 GetDataPosition() const { return GetCommentPosition() + CommentSize + AlignSize; }; + UInt64 GetFullSize() const { return MainPartSize + CommentSize + AlignSize + PackSize; } + // DWORD GetHeaderWithCommentSize() const { return MainPartSize + CommentSize; } + UInt64 GetCommentPosition() const { return Position + MainPartSize; } + UInt64 GetDataPosition() const { return GetCommentPosition() + CommentSize + AlignSize; } }; }} diff --git a/CPP/7zip/Archive/RpmHandler.cpp b/CPP/7zip/Archive/RpmHandler.cpp index 220bc650..268e0837 100644 --- a/CPP/7zip/Archive/RpmHandler.cpp +++ b/CPP/7zip/Archive/RpmHandler.cpp @@ -77,7 +77,7 @@ enum k_EntryType_I18NSTRING }; -static const char *k_CPUs[] = +static const char * const k_CPUs[] = { "noarch" , "i386" @@ -101,7 +101,7 @@ static const char *k_CPUs[] = , "aarch64" // 19 }; -static const char *k_OS[] = +static const char * const k_OS[] = { "0" , "Linux" @@ -299,12 +299,7 @@ AString CHandler::GetBaseName() const } } else - { - char *p = s.GetBuffer(kNameSize); - memcpy(p, _lead.Name, kNameSize); - p[kNameSize] = 0; - s.ReleaseBuffer(); - } + s.SetFrom_CalcLen(_lead.Name, kNameSize); s += '.'; if (_lead.Type == kRpmType_Src) @@ -553,7 +548,7 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader) for (UInt32 t = 0; t < entry.Count; t++) { if (t != 0) - _metadata += ' '; + _metadata.Add_Space(); char temp[16]; ConvertUInt32ToString(Get32(p + t * 4), temp); _metadata += temp; @@ -592,7 +587,7 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader) for (UInt32 t = 0; t < entry.Count; t++) { if (t != 0) - _metadata += ' '; + _metadata.Add_Space(); char temp[16]; ConvertUInt32ToString(Get16(p + t * 2), temp); _metadata += temp; @@ -777,15 +772,13 @@ STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea COM_TRY_END } -IMP_CreateArcIn +static const Byte k_Signature[] = { 0xED, 0xAB, 0xEE, 0xDB}; -static CArcInfo g_ArcInfo = - { "Rpm", "rpm", 0, 0xEB, - 4, { 0xED, 0xAB, 0xEE, 0xDB}, +REGISTER_ARC_I( + "Rpm", "rpm", 0, 0xEB, + k_Signature, 0, 0, - CreateArc }; - -REGISTER_ARC(Rpm) + NULL) }} diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp index 19dc1b47..23187064 100644 --- a/CPP/7zip/Archive/SplitHandler.cpp +++ b/CPP/7zip/Archive/SplitHandler.cpp @@ -71,68 +71,53 @@ struct CSeqName UString _changedPart; bool _splitStyle; - UString GetNextName() + bool GetNextName(UString &s) { - UString newName; - if (_splitStyle) { - int i; - int numLetters = _changedPart.Len(); - for (i = numLetters - 1; i >= 0; i--) + unsigned i = _changedPart.Len(); + for (;;) { - wchar_t c = _changedPart[i]; - if (c == 'z') + wchar_t c = _changedPart[--i]; + + if (_splitStyle) { - newName.InsertAtFront('a'); - continue; + if (c == 'z') + { + _changedPart.ReplaceOneCharAtPos(i, L'a'); + if (i == 0) + return false; + continue; + } + else if (c == 'Z') + { + _changedPart.ReplaceOneCharAtPos(i, L'A'); + if (i == 0) + return false; + continue; + } } - else if (c == 'Z') + else { - newName.InsertAtFront('A'); - continue; - } - c++; - if ((c == 'z' || c == 'Z') && i == 0) - { - _unchangedPart += c; - wchar_t newChar = (c == 'z') ? L'a' : L'A'; - newName.Empty(); - numLetters++; - for (int k = 0; k < numLetters; k++) - newName += newChar; - break; - } - newName.InsertAtFront(c); - i--; - for (; i >= 0; i--) - newName.InsertAtFront(_changedPart[i]); - break; - } - } - else - { - int i; - int numLetters = _changedPart.Len(); - for (i = numLetters - 1; i >= 0; i--) - { - wchar_t c = _changedPart[i]; - if (c == '9') - { - newName.InsertAtFront('0'); - if (i == 0) - newName.InsertAtFront('1'); - continue; + if (c == '9') + { + _changedPart.ReplaceOneCharAtPos(i, L'0'); + if (i == 0) + { + _changedPart.InsertAtFront(L'1'); + break; + } + continue; + } } + c++; - newName.InsertAtFront(c); - i--; - for (; i >= 0; i--) - newName.InsertAtFront(_changedPart[i]); + _changedPart.ReplaceOneCharAtPos(i, c); break; } } - _changedPart = newName; - return _unchangedPart + _changedPart; + + s = _unchangedPart + _changedPart; + return true; } }; @@ -156,7 +141,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) name = prop.bstrVal; } - int dotPos = name.ReverseFind('.'); + int dotPos = name.ReverseFind_Dot(); const UString prefix = name.Left(dotPos + 1); const UString ext = name.Ptr(dotPos + 1); UString ext2 = ext; @@ -196,7 +181,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) seqName._splitStyle = splitStyle; if (prefix.Len() < 1) - _subName = L"file"; + _subName.SetFromAscii("file"); else _subName.SetFrom(prefix, prefix.Len() - 1); @@ -220,7 +205,9 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) for (;;) { - const UString fullName = seqName.GetNextName(); + UString fullName; + if (!seqName.GetNextName(fullName)) + break; CMyComPtr<IInStream> nextStream; HRESULT result = volumeCallback->GetStream(fullName, &nextStream); if (result == S_FALSE) @@ -355,15 +342,10 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -IMP_CreateArcIn - -static CArcInfo g_ArcInfo = - { "Split", "001", 0, 0xEA, - 0, { 0 }, +REGISTER_ARC_I_NO_SIG( + "Split", "001", 0, 0xEA, 0, 0, - CreateArc }; - -REGISTER_ARC(Split) + NULL) }} diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp index 1f70bb8e..c65067af 100644 --- a/CPP/7zip/Archive/SquashfsHandler.cpp +++ b/CPP/7zip/Archive/SquashfsHandler.cpp @@ -28,10 +28,6 @@ namespace NArchive { namespace NSquashfs { -static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } -static void SzFree(void *p, void *address) { p = p; MyFree(address); } -static ISzAlloc g_Alloc = { SzAlloc, SzFree }; - static const UInt32 kNumFilesMax = (1 << 28); static const unsigned kNumDirLevelsMax = (1 << 10); @@ -68,7 +64,7 @@ static const UInt32 kSignature32_LZ = 0x71736873; #define kMethod_LZO 3 #define kMethod_XZ 4 -static const char *k_Methods[] = +static const char * const k_Methods[] = { "Unknown" , "ZLIB" @@ -1652,13 +1648,12 @@ AString CHandler::GetPath(int index) const len--; AString path; - char *dest = path.GetBuffer(len) + len; + char *dest = path.GetBuf_SetEnd(len) + len; index = indexMem; for (;;) { const CItem &item = _items[index]; index = item.Parent; - const Byte *p = _dirs.Data + item.Ptr; unsigned size = (_h.IsOldVersion() ? (unsigned)p[2] : (unsigned)Get16(p + 6)) + 1; p += _h.GetFileNameOffset(); @@ -1670,7 +1665,6 @@ AString CHandler::GetPath(int index) const break; *(--dest) = CHAR_PATH_SEPARATOR; } - path.ReleaseBuffer(len); return path; } @@ -1846,7 +1840,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) AString res = "SquashFS"; if (_h.SeveralMethods) res += "-LZMA"; - res += ' '; + res.Add_Space(); char s[16]; ConvertUInt32ToString(_h.Major, s); res += s; @@ -2049,7 +2043,8 @@ HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) } if (offsetInBlock + blockSize > _cachedUnpackBlockSize) return S_FALSE; - memcpy(dest, _cachedBlock + offsetInBlock, blockSize); + if (blockSize != 0) + memcpy(dest, _cachedBlock + offsetInBlock, blockSize); return S_OK; } @@ -2208,20 +2203,16 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -IMP_CreateArcIn - -static CArcInfo g_ArcInfo = - { "SquashFS", "squashfs", 0, 0xD2, - 3 * (1 + 4), - { +static const Byte k_Signature[] = { 4, 'h', 's', 'q', 's', 4, 's', 'q', 's', 'h', - 4, 's', 'h', 's', 'q', - }, + 4, 's', 'h', 's', 'q' }; + +REGISTER_ARC_I( + "SquashFS", "squashfs", 0, 0xD2, + k_Signature, 0, NArcInfoFlags::kMultiSignature, - CreateArc }; - -REGISTER_ARC(Cramfs) + NULL) }} diff --git a/CPP/7zip/Archive/SwfHandler.cpp b/CPP/7zip/Archive/SwfHandler.cpp index 85c61fe2..77d2ad7d 100644 --- a/CPP/7zip/Archive/SwfHandler.cpp +++ b/CPP/7zip/Archive/SwfHandler.cpp @@ -170,7 +170,7 @@ public: INTERFACE_IInArchive(;) INTERFACE_IOutArchive(;) STDMETHOD(OpenSeq)(ISequentialInStream *stream); - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); + STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); }; static const Byte kProps[] = @@ -218,7 +218,7 @@ static void DicSizeToString(char *s, UInt32 val) else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; } } ::ConvertUInt32ToString(val, s); - int pos = MyStringLen(s); + unsigned pos = MyStringLen(s); s[pos++] = c; s[pos] = 0; } @@ -558,11 +558,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt return NCompress::CopyStream(_seqStream, outStream, NULL); } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) +STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) { _lzmaMode = false; RINOK(_props.SetProperties(names, values, numProps)); - UString m = _props.MethodName; + AString m = _props.MethodName; m.MakeLower_Ascii(); if (m.IsEqualTo("lzma")) { @@ -576,21 +576,16 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v return S_OK; } -IMP_CreateArcIn -IMP_CreateArcOut - -static CArcInfo g_ArcInfo = - { "SWFc", "swf", "~.swf", 0xD8, - 2 + 3 + 3, - { +static const Byte k_Signature[] = { 3, 'C', 'W', 'S', - 3, 'Z', 'W', 'S', - }, + 3, 'Z', 'W', 'S' }; + +REGISTER_ARC_IO( + "SWFc", "swf", "~.swf", 0xD8, + k_Signature, 0, NArcInfoFlags::kMultiSignature, - REF_CreateArc_Pair, IsArc_Swfc }; - -REGISTER_ARC(Swfc) + IsArc_Swfc) } @@ -978,15 +973,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } -IMP_CreateArcIn +static const Byte k_Signature[] = { 'F', 'W', 'S' }; -static CArcInfo g_ArcInfo = - { "SWF", "swf", 0, 0xD7, - 3, { 'F', 'W', 'S' }, +REGISTER_ARC_I( + "SWF", "swf", 0, 0xD7, + k_Signature, 0, NArcInfoFlags::kKeepName, - CreateArc, NULL, NSwfc::IsArc_Swf }; - -REGISTER_ARC(Swf) + NSwfc::IsArc_Swf) }} diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp index 5b587529..d1eec144 100644 --- a/CPP/7zip/Archive/Tar/TarHandler.cpp +++ b/CPP/7zip/Archive/Tar/TarHandler.cpp @@ -143,10 +143,10 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) if (!_forceCodePage) { - if (utf8_OK) utf8_OK = CheckUTF8(item.Name); + if (utf8_OK) utf8_OK = CheckUTF8(item.Name, item.NameCouldBeReduced); + if (utf8_OK) utf8_OK = CheckUTF8(item.LinkName, item.LinkNameCouldBeReduced); if (utf8_OK) utf8_OK = CheckUTF8(item.User); if (utf8_OK) utf8_OK = CheckUTF8(item.Group); - if (utf8_OK) utf8_OK = CheckUTF8(item.LinkName); } RINOK(stream->Seek(item.GetPackSizeAligned(), STREAM_SEEK_CUR, &_phySize)); @@ -298,19 +298,12 @@ void CHandler::TarStringToUnicode(const AString &s, NWindows::NCOM::CPropVariant { UString dest; if (_curCodePage == CP_UTF8) - { - if (!ConvertUTF8ToUnicode(s, dest)) - { - prop = "[ERROR-NAME]"; - return; - } - } + ConvertUTF8ToUnicode(s, dest); else - dest = MultiByteToUnicodeString(s, _curCodePage); + MultiByteToUnicodeString2(dest, s, _curCodePage); if (toOs) - prop = NItemName::GetOSName2(dest); - else - prop = dest; + NItemName::ConvertToOSName2(dest); + prop = dest; } STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) @@ -632,10 +625,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) if (item.IsSymLink()) { - CBufInStream *streamSpec = new CBufInStream; - CMyComPtr<IInStream> streamTemp = streamSpec; - streamSpec->Init((const Byte *)(const char *)item.LinkName, item.LinkName.Len(), (IInArchive *)this); - *stream = streamTemp.Detach(); + Create_BufInStream_WithReference((const Byte *)(const char *)item.LinkName, item.LinkName.Len(), (IInArchive *)this, stream); return S_OK; } @@ -651,7 +641,7 @@ void CHandler::Init() _curCodePage = _specifiedCodePage = CP_UTF8; // CP_OEMCP; } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) +STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) { Init(); diff --git a/CPP/7zip/Archive/Tar/TarHandler.h b/CPP/7zip/Archive/Tar/TarHandler.h index 23854767..42d57d45 100644 --- a/CPP/7zip/Archive/Tar/TarHandler.h +++ b/CPP/7zip/Archive/Tar/TarHandler.h @@ -67,7 +67,7 @@ public: INTERFACE_IOutArchive(;) STDMETHOD(OpenSeq)(ISequentialInStream *stream); STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); + STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); void Init(); CHandler(); diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp index b909e96c..ae005ac5 100644 --- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp +++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp @@ -36,8 +36,8 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro s = NItemName::MakeLegalName(s); if (codePage == CP_UTF8) { - if (!ConvertUnicodeToUTF8(s, res)) - return E_INVALIDARG; + ConvertUnicodeToUTF8(s, res); + // if (!ConvertUnicodeToUTF8(s, res)) // return E_INVALIDARG; } else UnicodeStringToMultiByte2(res, s, codePage); diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp index 1584a520..80200c3b 100644 --- a/CPP/7zip/Archive/Tar/TarIn.cpp +++ b/CPP/7zip/Archive/Tar/TarIn.cpp @@ -180,6 +180,9 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE error = k_ErrorType_Corrupted; ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize; + item.NameCouldBeReduced = + (item.Name.Len() == NFileHeader::kNameSize || + item.Name.Len() == NFileHeader::kNameSize - 1); RIF(OctalToNumber32(p, 8, item.Mode)); p += 8; @@ -198,6 +201,9 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE item.LinkFlag = *p++; ReadString(p, NFileHeader::kNameSize, item.LinkName); p += NFileHeader::kNameSize; + item.LinkNameCouldBeReduced = + (item.LinkName.Len() == NFileHeader::kNameSize || + item.LinkName.Len() == NFileHeader::kNameSize - 1); memcpy(item.Magic, p, 8); p += 8; @@ -207,12 +213,17 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE item.DeviceMajorDefined = (p[0] != 0); if (item.DeviceMajorDefined) { RIF(OctalToNumber32(p, 8, item.DeviceMajor)); } p += 8; item.DeviceMinorDefined = (p[0] != 0); if (item.DeviceMinorDefined) { RIF(OctalToNumber32(p, 8, item.DeviceMinor)); } p += 8; - AString prefix; - ReadString(p, NFileHeader::kPrefixSize, prefix); + if (p[0] != 0) + { + AString prefix; + ReadString(p, NFileHeader::kPrefixSize, prefix); + if (!prefix.IsEmpty() + && item.IsUstarMagic() + && (item.LinkFlag != 'L' /* || prefix != "00000000000" */ )) + item.Name = prefix + '/' + item.Name; + } + p += NFileHeader::kPrefixSize; - if (!prefix.IsEmpty() && item.IsUstarMagic() && - (item.LinkFlag != 'L' /* || prefix != "00000000000" */ )) - item.Name = prefix + AString('/') + item.Name; if (item.LinkFlag == NFileHeader::NLinkFlag::kHardLink) { @@ -353,12 +364,11 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErro if (item.PackSize > (1 << 14)) return S_OK; unsigned packSize = (unsigned)item.GetPackSizeAligned(); - char *buf = name->GetBuffer(packSize); + char *buf = name->GetBuf(packSize); size_t processedSize = packSize; HRESULT res = ReadStream(stream, buf, &processedSize); item.HeaderSize += (unsigned)processedSize; - buf[(size_t)item.PackSize] = 0; - name->ReleaseBuffer(); + name->ReleaseBuf_CalcLen((unsigned)item.PackSize); RINOK(res); if (processedSize != packSize) { @@ -392,8 +402,18 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErro return S_OK; } - if (flagL) item.Name = nameL; - if (flagK) item.LinkName = nameK; + if (flagL) + { + item.Name = nameL; + item.NameCouldBeReduced = false; + } + + if (flagK) + { + item.LinkName = nameK; + item.LinkNameCouldBeReduced = false; + } + error = k_ErrorType_OK; return S_OK; } diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h index 805a2e7c..5245aaa4 100644 --- a/CPP/7zip/Archive/Tar/TarItem.h +++ b/CPP/7zip/Archive/Tar/TarItem.h @@ -86,6 +86,8 @@ struct CItemEx: public CItem { UInt64 HeaderPos; unsigned HeaderSize; + bool NameCouldBeReduced; + bool LinkNameCouldBeReduced; UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; } UInt64 GetFullSize() const { return HeaderSize + PackSize; } diff --git a/CPP/7zip/Archive/Tar/TarRegister.cpp b/CPP/7zip/Archive/Tar/TarRegister.cpp index 9e0f6f21..f7b256df 100644 --- a/CPP/7zip/Archive/Tar/TarRegister.cpp +++ b/CPP/7zip/Archive/Tar/TarRegister.cpp @@ -9,18 +9,15 @@ namespace NArchive { namespace NTar { -IMP_CreateArcIn -IMP_CreateArcOut +static const Byte k_Signature[] = { 'u', 's', 't', 'a', 'r' }; -static CArcInfo g_ArcInfo = - { "tar", "tar", 0, 0xEE, - 5, { 'u', 's', 't', 'a', 'r' }, +REGISTER_ARC_IO( + "tar", "tar", 0, 0xEE, + k_Signature, NFileHeader::kUstarMagic_Offset, NArcInfoFlags::kStartOpen | NArcInfoFlags::kSymLinks | NArcInfoFlags::kHardLinks, - REF_CreateArc_Pair, IsArc_Tar }; - -REGISTER_ARC(Tar) - + IsArc_Tar) + }} diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp index fdbce395..3adbdee9 100644 --- a/CPP/7zip/Archive/Tar/TarUpdate.cpp +++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp @@ -31,6 +31,9 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, CMyComPtr<IOutStream> outSeekStream; outStream->QueryInterface(IID_IOutStream, (void **)&outSeekStream); + CMyComPtr<IArchiveUpdateCallbackFile> opCallback; + updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback); + UInt64 complexity = 0; unsigned i; @@ -224,6 +227,13 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, } streamSpec->Init(size); + if (opCallback) + { + RINOK(opCallback->ReportOperation( + NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArchive, + NUpdateNotifyOp::kReplicate)) + } + RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); if (copyCoderSpec->TotalSize != size) return E_FAIL; diff --git a/CPP/7zip/Archive/Udf/UdfHandler.cpp b/CPP/7zip/Archive/Udf/UdfHandler.cpp index 6aa53ea9..d35db9fb 100644 --- a/CPP/7zip/Archive/Udf/UdfHandler.cpp +++ b/CPP/7zip/Archive/Udf/UdfHandler.cpp @@ -26,7 +26,7 @@ static void UdfTimeToFileTime(const CTime &t, NWindows::NCOM::CPropVariant &prop if (!NWindows::NTime::GetSecondsSince1601(t.GetYear(), d[4], d[5], d[6], d[7], d[8], numSecs)) return; if (t.IsLocal()) - numSecs -= t.GetMinutesOffset() * 60; + numSecs -= (Int64)((Int32)t.GetMinutesOffset() * 60); FILETIME ft; UInt64 v = (((numSecs * 100 + d[9]) * 100 + d[10]) * 100 + d[11]) * 10; ft.dwLowDateTime = (UInt32)v; @@ -227,13 +227,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) if (item.IsInline) { - CBufInStream *inStreamSpec = new CBufInStream; - CMyComPtr<ISequentialInStream> inStream = inStreamSpec; - CReferenceBuf *referenceBuf = new CReferenceBuf; - CMyComPtr<IUnknown> ref = referenceBuf; - referenceBuf->Buf = item.InlineData; - inStreamSpec->Init(referenceBuf); - *stream = inStream.Detach(); + Create_BufInStream_WithNewBuffer(item.InlineData, stream); return S_OK; } @@ -366,18 +360,16 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } -IMP_CreateArcIn - static const UInt32 kIsoStartPos = 0x8000; -static CArcInfo g_ArcInfo = - { "Udf", "udf iso img", 0, 0xE0, - // 5, { 0, 'N', 'S', 'R', '0' }, - 6, { 1, 'C', 'D', '0', '0', '1' }, +// 5, { 0, 'N', 'S', 'R', '0' }, +static const Byte k_Signature[] = { 1, 'C', 'D', '0', '0', '1' }; + +REGISTER_ARC_I( + "Udf", "udf iso img", 0, 0xE0, + k_Signature, kIsoStartPos, NArcInfoFlags::kStartOpen, - CreateArc, NULL, IsArc_Udf }; - -REGISTER_ARC(Udf) + IsArc_Udf) }} diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp index 3053a0c1..62df64dc 100644 --- a/CPP/7zip/Archive/Udf/UdfIn.cpp +++ b/CPP/7zip/Archive/Udf/UdfIn.cpp @@ -82,13 +82,13 @@ void CDString::Parse(const Byte *p, unsigned size) static UString ParseDString(const Byte *data, unsigned size) { UString res; - wchar_t *p; if (size > 0) { + wchar_t *p; Byte type = data[0]; if (type == 8) { - p = res.GetBuffer(size); + p = res.GetBuf(size); for (unsigned i = 1; i < size; i++) { wchar_t c = data[i]; @@ -99,7 +99,7 @@ static UString ParseDString(const Byte *data, unsigned size) } else if (type == 16) { - p = res.GetBuffer(size / 2); + p = res.GetBuf(size / 2); for (unsigned i = 1; i + 2 <= size; i += 2) { wchar_t c = GetBe16(data + i); @@ -110,8 +110,8 @@ static UString ParseDString(const Byte *data, unsigned size) } else return L"[unknow]"; - *p++ = 0; - res.ReleaseBuffer(); + *p = 0; + res.ReleaseBuf_SetLen((unsigned)(p - (const wchar_t *)res)); } return res; } @@ -432,6 +432,8 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la CTag tag; const Byte *p = buf; RINOK(tag.Parse(p, size)); + if (size < 176) + return S_FALSE; if (tag.Id != DESC_TYPE_File) return S_FALSE; @@ -449,7 +451,7 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la if ((extendedAttrLen & 3) != 0) return S_FALSE; - int pos = 176; + size_t pos = 176; if (extendedAttrLen > size - pos) return S_FALSE; /* @@ -595,7 +597,7 @@ API_FUNC_IsArc IsArc_Udf(const Byte *p, size_t size) if (SecLogSize < 8) return res; UInt32 offset = (UInt32)256 << SecLogSize; - size_t bufSize = 1 << SecLogSize; + size_t bufSize = (UInt32)1 << SecLogSize; if (offset + bufSize > size) res = k_IsArc_Res_NEED_MORE; else @@ -652,7 +654,7 @@ HRESULT CInArchive::Open2() if (offset >= fileSize) continue; RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); - size_t bufSize = 1 << SecLogSize; + size_t bufSize = (UInt32)1 << SecLogSize; size_t readSize = bufSize; RINOK(ReadStream(_stream, buf, &readSize)); if (readSize == bufSize) @@ -677,7 +679,7 @@ HRESULT CInArchive::Open2() for (UInt32 location = 0; ; location++) { - size_t bufSize = 1 << SecLogSize; + size_t bufSize = (UInt32)1 << SecLogSize; size_t pos = 0; if (((UInt64)(location + 1) << SecLogSize) > extentVDS.Len) return S_FALSE; @@ -950,7 +952,7 @@ HRESULT CInArchive::Open2() if (PhySize < fileSize) { RINOK(_stream->Seek(PhySize, STREAM_SEEK_SET, NULL)); - size_t bufSize = 1 << SecLogSize; + size_t bufSize = (UInt32)1 << SecLogSize; size_t readSize = bufSize; RINOK(ReadStream(_stream, buf, &readSize)); if (readSize == bufSize) @@ -1018,8 +1020,8 @@ UString CInArchive::GetComment() const UString res; FOR_VECTOR (i, LogVols) { - if (i > 0) - res += L" "; + if (i != 0) + res.Add_Space(); res += LogVols[i].GetName(); } return res; diff --git a/CPP/7zip/Archive/Udf/UdfRegister.cpp b/CPP/7zip/Archive/Udf/UdfRegister.cpp deleted file mode 100644 index ed32f12e..00000000 --- a/CPP/7zip/Archive/Udf/UdfRegister.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// UdfRegister.cpp - -#include "StdAfx.h" - -#include "../../Common/RegisterArc.h" - -#include "UdfHandler.h" diff --git a/CPP/7zip/Archive/UefiHandler.cpp b/CPP/7zip/Archive/UefiHandler.cpp index a6760b36..3de6351a 100644 --- a/CPP/7zip/Archive/UefiHandler.cpp +++ b/CPP/7zip/Archive/UefiHandler.cpp @@ -26,6 +26,7 @@ #include "../Common/StreamUtils.h" #include "../Compress/CopyCoder.h" +#include "../Compress/LzhDecoder.h" #ifdef SHOW_DEBUG_INFO #define PRF(x) x @@ -41,22 +42,18 @@ namespace NArchive { namespace NUefi { -static const UInt32 kBufTotalSizeMax = (1 << 29); -static const UInt32 kNumFilesMax = (1 << 18); -static const int kLevelMax = 64; +static const size_t kBufTotalSizeMax = (1 << 29); +static const unsigned kNumFilesMax = (1 << 18); +static const unsigned kLevelMax = 64; -static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } -static void SzFree(void *p, void *address) { p = p; MyFree(address); } -static ISzAlloc g_Alloc = { SzAlloc, SzFree }; +static const unsigned kFvHeaderSize = 0x38; -static const UInt32 kFvHeaderSize = 0x38; -static const UInt32 kGuidSize = 16; -static const UInt32 kCapsuleSigSize = kGuidSize; +static const unsigned kGuidSize = 16; #define CAPSULE_SIGNATURE \ { 0xBD,0x86,0x66,0x3B,0x76,0x0D,0x30,0x40,0xB7,0x0E,0xB5,0x51,0x9E,0x2F,0xC5,0xA0 } -static const Byte kCapsuleSig[kCapsuleSigSize] = CAPSULE_SIGNATURE; +static const Byte kCapsuleSig[kGuidSize] = CAPSULE_SIGNATURE; -static const UInt32 kFfsGuidOffset = 16; +static const unsigned kFfsGuidOffset = 16; #define FFS_SIGNATURE \ { 0xD9,0x54,0x93,0x7A,0x68,0x04,0x4A,0x44,0x81,0xCE,0x0B,0xF6,0x17,0xD8,0x90,0xDF } static const Byte k_FFS_Guid[kGuidSize] = FFS_SIGNATURE; @@ -84,7 +81,7 @@ static const Byte kGuids[][kGuidSize] = }; -static const char *kGuidNames[] = +static const char * const kGuidNames[] = { "CRC" , "VolumeTopFile" @@ -175,7 +172,7 @@ static bool AreGuidsEq(const Byte *p1, const Byte *p2) static int FindGuid(const Byte *p) { - for (int i = 0; i < ARRAY_SIZE(kGuids); i++) + for (unsigned i = 0; i < ARRAY_SIZE(kGuids); i++) if (AreGuidsEq(p, kGuids[i])) return i; return -1; @@ -325,7 +322,7 @@ static const CUInt32PCharPair g_SECTION_TYPE[] = #define COMPRESSION_TYPE_LZH 1 #define COMPRESSION_TYPE_LZMA 2 -static const char *g_Methods[] = +static const char * const g_Methods[] = { "COPY" , "LZH" @@ -367,7 +364,7 @@ static AString GuidToString(const Byte *p, bool full) return s; } -static const char *kExpressionCommands[] = +static const char * const kExpressionCommands[] = { "BEFORE", "AFTER", "PUSH", "AND", "OR", "NOT", "TRUE", "FALSE", "END", "SOR" }; @@ -385,7 +382,7 @@ static bool ParseDepedencyExpression(const Byte *p, UInt32 size, AString &res) { if (i + kGuidSize > size) return false; - res += " "; + res.Add_Space(); res += GuidToString(p + i, false); i += kGuidSize; } @@ -427,9 +424,11 @@ static const UInt32 kFileHeaderSize = 24; static void AddSpaceAndString(AString &res, const AString &newString) { - if (!res.IsEmpty() && !newString.IsEmpty()) - res += ' '; - res += newString; + if (!newString.IsEmpty()) + { + res.Add_Space_if_NotEmpty(); + res += newString; + } } class CFfsFileHeader @@ -604,7 +603,7 @@ void CItem::SetGuid(const Byte *guidName, bool full) ThereIsUniqueName = true; int index = FindGuid(guidName); if (index >= 0) - Name = kGuidNames[index]; + Name = kGuidNames[(unsigned)index]; else Name = GuidToString(guidName, full); } @@ -617,9 +616,9 @@ AString CItem::GetName(int numChildsInParent) const char sz2[32]; ConvertUInt32ToString(NameIndex, sz); ConvertUInt32ToString(numChildsInParent - 1, sz2); - int numZeros = (int)strlen(sz2) - (int)strlen(sz); + unsigned numZeros = (unsigned)strlen(sz2) - (unsigned)strlen(sz); AString res; - for (int i = 0; i < numZeros; i++) + for (unsigned i = 0; i < numZeros; i++) res += '0'; return res + (AString)sz + '.' + Name; } @@ -646,7 +645,7 @@ class CHandler: UInt32 _methodsMask; bool _capsuleMode; - UInt32 _totalBufsSize; + size_t _totalBufsSize; CCapsuleHeader _h; UInt64 _phySize; @@ -654,9 +653,9 @@ class CHandler: int AddItem(const CItem &item); int AddFileItemWithIndex(CItem &item); int AddDirItem(CItem &item); - int AddBuf(UInt32 size); + unsigned AddBuf(size_t size); - HRESULT ParseSections(int bufIndex, UInt32 pos, UInt32 size, int parent, int method, int level); + HRESULT ParseSections(int bufIndex, UInt32 pos, UInt32 size, int parent, int method, unsigned level); HRESULT ParseVolume(int bufIndex, UInt32 posBase, UInt32 exactSize, UInt32 limitSize, int parent, int method, int level); @@ -711,7 +710,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val break; } case kpidIsDir: prop = item.IsDir; break; - case kpidMethod: if (item.Method >= 0) prop = g_Methods[item.Method]; break; + case kpidMethod: if (item.Method >= 0) prop = g_Methods[(unsigned)item.Method]; break; case kpidCharacts: if (!item2.Characts.IsEmpty()) prop = item2.Characts; break; case kpidSize: if (!item.IsDir) prop = (UInt64)item.Size; break; } @@ -739,15 +738,15 @@ void CHandler::AddCommentString(const wchar_t *name, UInt32 pos) c = Get16(buf + i); if (c == 0) break; - s += L'\n'; + s.Add_LF(); } s += c; } if (s.IsEmpty()) return; - _comment += L'\n'; + _comment.Add_LF(); _comment += name; - _comment += L": "; + _comment.AddAscii(": "); _comment += s; } @@ -760,7 +759,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidMethod: { AString s; - for (int i = 0; i < 32; i++) + for (unsigned i = 0; i < 32; i++) if ((_methodsMask & ((UInt32)1 << i)) != 0) AddSpaceAndString(s, g_Methods[i]); if (!s.IsEmpty()) @@ -792,341 +791,7 @@ static void MyPrint(UInt32 posBase, UInt32 size, int level, const char *name) #define MyPrint(posBase, size, level, name) #endif -static const unsigned kNumBigValueBits = 8 * 4; -static const unsigned kNumValueBytes = 3; -static const unsigned kNumValueBits = 8 * kNumValueBytes; -static const UInt32 kMask = (1 << kNumValueBits) - 1; - -class CBitmMemDecoder -{ - unsigned _bitPos; - UInt32 _value; - const Byte *_buf; - size_t _pos; - size_t _size; - size_t _extra; -public: - void Init(const Byte *buf, size_t size) - { - _buf = buf; - _size = size; - _pos = 0; - _extra = 0; - _bitPos = kNumBigValueBits; - Normalize(); - } - - bool IsFullFinished() const { return (_extra * 8) == (kNumBigValueBits - _bitPos); } - - void Normalize() - { - for (; _bitPos >= 8; _bitPos -= 8) - { - Byte b; - if (_pos < _size) - b = _buf[_pos++]; - else - { - b = 0; - _extra++; - } - _value = (_value << 8) | b; - } - } - - UInt32 GetValue(unsigned numBits) const - { - return ((_value >> (8 - _bitPos)) & kMask) >> (kNumValueBits - numBits); - } - - void MovePos(unsigned numBits) - { - _bitPos += numBits; - Normalize(); - } - - UInt32 ReadBitsFast(unsigned numBits) - { - UInt32 res = GetValue(numBits); - MovePos(numBits); - return res; - } - - UInt32 ReadBits(unsigned numBits); - UInt32 ReadAlignBits() { return ReadBits((32 - _bitPos) & 7); } -}; - -UInt32 CBitmMemDecoder::ReadBits(unsigned numBits) -{ - UInt32 res = GetValue(numBits); - MovePos(numBits); - return res; -} - -namespace NHuffman { - -static const int kNumTableBits = 9; -static const int kNumBitsMax = 16; - -class CDecoder -{ - UInt32 m_Limits[kNumBitsMax + 1]; - UInt32 m_Positions[kNumBitsMax + 1]; - Byte m_Lengths[1 << kNumTableBits]; - Int32 m_MainSymbol; - -public: - UInt32 *m_Symbols; - UInt32 m_NumSymbols; - - void SetSingleSymbolMode(UInt32 symbol) { m_MainSymbol = symbol; } - bool SetCodeLengths(const Byte *codeLengths); - UInt32 DecodeSymbol(CBitmMemDecoder *bitStream) - { - if (m_MainSymbol != -1) - return (UInt32)m_MainSymbol; - int numBits; - UInt32 value = bitStream->GetValue(kNumBitsMax); - if (value < m_Limits[kNumTableBits]) - numBits = m_Lengths[value >> (kNumBitsMax - kNumTableBits)]; - else - for (numBits = kNumTableBits + 1; value >= m_Limits[numBits]; numBits++); - bitStream->MovePos(numBits); - return m_Symbols[m_Positions[numBits] + ((value - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits))]; - } -}; - -bool CDecoder::SetCodeLengths(const Byte *codeLengths) -{ - m_MainSymbol = -1; - int lenCounts[kNumBitsMax + 1]; - UInt32 tmpPositions[kNumBitsMax + 1]; - int i; - for (i = 1; i <= kNumBitsMax; i++) - lenCounts[i] = 0; - UInt32 symbol; - for (symbol = 0; symbol < m_NumSymbols; symbol++) - { - int len = codeLengths[symbol]; - if (len > kNumBitsMax) - return false; - lenCounts[len]++; - m_Symbols[symbol] = 0xFFFFFFFF; - } - lenCounts[0] = 0; - m_Positions[0] = m_Limits[0] = 0; - UInt32 startPos = 0; - UInt32 index = 0; - const UInt32 kMaxValue = (1 << kNumBitsMax); - for (i = 1; i <= kNumBitsMax; i++) - { - startPos += lenCounts[i] << (kNumBitsMax - i); - if (startPos > kMaxValue) - return false; - m_Limits[i] = (i == kNumBitsMax) ? kMaxValue : startPos; - m_Positions[i] = m_Positions[i - 1] + lenCounts[i - 1]; - tmpPositions[i] = m_Positions[i]; - if (i <= kNumTableBits) - { - UInt32 limit = (m_Limits[i] >> (kNumBitsMax - kNumTableBits)); - for (; index < limit; index++) - m_Lengths[index] = (Byte)i; - } - } - if (startPos != kMaxValue) - return false; - for (symbol = 0; symbol < m_NumSymbols; symbol++) - { - int len = codeLengths[symbol]; - if (len != 0) - m_Symbols[tmpPositions[len]++] = symbol; - } - return true; -} - -} - -static const int kMaxHuffmanLen = 16; -static const int kExtraSize = kMaxHuffmanLen + 3; -static const int kMinMatchLen = 3; -static const int kMaxMatchLen = 256; -static const int kNumAlphaSymsMax = 256 + kMaxMatchLen - kMinMatchLen + 1; -static const int kNumDistSymsMax = 24 + 2; // it's limited by bit decoder. - -#define HUFF_START_CODE(huff, numSymsMax, numSymBits) \ - UInt32 numSyms = bitDec.ReadBits(numSymBits); \ - Byte lens[numSymsMax]; memset(lens, 0, sizeof(lens)); \ - if (numSyms > (numSymsMax)) return S_FALSE; \ - huff.m_NumSymbols = numSyms; \ - if (numSyms == 0) { \ - numSyms = bitDec.ReadBits(numSymBits); \ - if (numSyms >= (numSymsMax)) return S_FALSE; \ - huff.SetSingleSymbolMode(numSyms); } \ - -static HRESULT LzhDecode(Byte *dest, UInt32 destSize, const Byte *src, UInt32 srcSize) -{ - if (srcSize < 8) - return S_FALSE; - { - UInt32 packSize = Get32(src); - UInt32 unpackSize = Get32(src + 4); - src += 8; - srcSize -= 8; - if (destSize != unpackSize || srcSize != packSize) - return S_FALSE; - } - - CBitmMemDecoder bitDec; - bitDec.Init(src, srcSize); - UInt32 pos = 0; - for (;;) - { - UInt32 blockSize = bitDec.ReadBits(16); - UInt32 symbols[kExtraSize + kNumAlphaSymsMax + kNumDistSymsMax]; - - NHuffman::CDecoder extraHuff; - extraHuff.m_Symbols = symbols; - { - HUFF_START_CODE(extraHuff, kExtraSize, 5) - else - { - for (UInt32 i = 0; i < numSyms; i++) - { - if (i == 3) - { - UInt32 numZeros = bitDec.ReadBits(2); - if (i + numZeros > numSyms) - return S_FALSE; - for (UInt32 j = 0; j < numZeros; j++, i++) - lens[i] = (Byte)0; - if (i == numSyms) - break; - } - - UInt32 len = bitDec.ReadBits(3); - if (len == 7) - { - for(;; len++) - { - if (len > kMaxHuffmanLen) - return S_FALSE; - if (bitDec.ReadBits(1) == 0) - break; - } - } - lens[i] = (Byte)len; - } - if (!extraHuff.SetCodeLengths(lens)) - return S_FALSE; - } - } - - NHuffman::CDecoder symHuff; - symHuff.m_Symbols = symbols + kExtraSize; - { - HUFF_START_CODE(symHuff, kNumAlphaSymsMax, 9) - else - { - for (UInt32 i = 0; i < numSyms;) - { - UInt32 c = extraHuff.DecodeSymbol(&bitDec); - if (c > 2) - lens[i++] = (Byte)(c - 2); - else - { - UInt32 numZeros; - if (c == 0) - numZeros = 1; - else if (c == 1) - numZeros = bitDec.ReadBits(4) + 3; - else - numZeros = bitDec.ReadBits(9) + 20; - if (i + numZeros > numSyms) - return S_FALSE; - for (UInt32 j = 0; j < numZeros; j++, i++) - lens[i] = (Byte)0; - } - } - if (!symHuff.SetCodeLengths(lens)) - return S_FALSE; - } - } - - NHuffman::CDecoder distHuff; - distHuff.m_Symbols = symbols + kExtraSize + kNumAlphaSymsMax; - { - const UInt32 version = 1; - const UInt32 numDistBits = version + 4; - HUFF_START_CODE(distHuff, kNumDistSymsMax, numDistBits) - else - { - for (UInt32 i = 0; i < numSyms; i++) - { - UInt32 len = bitDec.ReadBits(3); - if (len == 7) - { - for(;; len++) - { - if (len > kMaxHuffmanLen) - return S_FALSE; - if (bitDec.ReadBits(1) == 0) - break; - } - } - lens[i] = (Byte)len; - } - if (!distHuff.SetCodeLengths(lens)) - return S_FALSE; - } - } - - while (blockSize) - { - blockSize--; - UInt32 c = symHuff.DecodeSymbol(&bitDec); - if (c < 256) - { - if (destSize == 0) - return S_FALSE; - *dest++ = (Byte)c; - destSize--; - pos++; - continue; - } - c = c - 256 + kMinMatchLen; - if (destSize < c) - return S_FALSE; - UInt32 dist = distHuff.DecodeSymbol(&bitDec); - if (dist > 1) - dist = ((UInt32)1 << (dist - 1)) + bitDec.ReadBits(dist - 1); - dist++; - if (dist > pos) - return S_FALSE; - pos += c; - destSize -= c; - do - { - *dest = dest[0 - (Int32)dist]; - dest++; - } - while (--c); - } - - // PRF(printf("\ndestSize = %6d", destSize)); - if (destSize == 0) - { - if (bitDec.ReadAlignBits() != 0) - return S_FALSE; - if (bitDec.ReadBits(8) != 0) - return S_FALSE; - if (!bitDec.IsFullFinished()) - return S_FALSE; - break; - } - } - return S_OK; -} int CHandler::AddItem(const CItem &item) { @@ -1153,17 +818,17 @@ int CHandler::AddDirItem(CItem &item) return AddItem(item); } -int CHandler::AddBuf(UInt32 size) +unsigned CHandler::AddBuf(size_t size) { if (size > kBufTotalSizeMax - _totalBufsSize) throw 1; _totalBufsSize += size; - int index = _bufs.Size(); + unsigned index = _bufs.Size(); _bufs.AddNew().Alloc(size); return index; } -HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int parent, int method, int level) +HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int parent, int method, unsigned level) { if (level > kLevelMax) return S_FALSE; @@ -1229,9 +894,55 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p } else if (compressionType == COMPRESSION_TYPE_LZH) { - int newBufIndex = AddBuf(uncompressedSize); + unsigned newBufIndex = AddBuf(uncompressedSize); CByteBuffer &buf = _bufs[newBufIndex]; - RINOK(LzhDecode(buf, uncompressedSize, pStart, newSectSize)); + + NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = 0; + CMyComPtr<ICompressCoder> lzhDecoder; + + lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder; + lzhDecoder = lzhDecoderSpec; + + { + const Byte *src = pStart; + if (newSectSize < 8) + return S_FALSE; + UInt32 packSize = Get32(src); + UInt32 unpackSize = Get32(src + 4); + if (uncompressedSize != unpackSize || newSectSize - 8 != packSize) + return S_FALSE; + if (packSize < 1) + return S_FALSE; + packSize--; + src += 8; + if (src[packSize] != 0) + return S_FALSE; + + CBufInStream *inStreamSpec = new CBufInStream; + CMyComPtr<IInStream> inStream = inStreamSpec; + inStreamSpec->Init(src, packSize); + + CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream; + CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; + outStreamSpec->Init(buf, uncompressedSize); + + UInt64 uncompressedSize64 = uncompressedSize; + lzhDecoderSpec->FinishMode = true; + /* + EFI 1.1 probably used small dictionary and (pbit = 4) in LZH. We don't support such archives. + New version of compression code (named Tiano) uses LZH with (1 << 19) dictionary. + But maybe LZH decoder in UEFI decoder supports larger than (1 << 19) dictionary. + */ + lzhDecoderSpec->SetDictSize(1 << 19); + + HRESULT res = lzhDecoder->Code(inStream, outStream, NULL, &uncompressedSize64, NULL); + if (res != S_OK) + return res; + + if (lzhDecoderSpec->GetInputProcessedSize() != packSize) + return S_FALSE; + } + RINOK(ParseSections(newBufIndex, 0, uncompressedSize, parent, compressionType, level)); } else @@ -1258,7 +969,7 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p if (lzmaUncompressedSize < uncompressedSize) return S_FALSE; SizeT destLen = (SizeT)lzmaUncompressedSize; - int newBufIndex = AddBuf((UInt32)lzmaUncompressedSize); + unsigned newBufIndex = AddBuf((size_t)lzmaUncompressedSize); CByteBuffer &buf = _bufs[newBufIndex]; ELzmaStatus status; SizeT srcLen = newSectSize - (addSize + 5 + 8); @@ -1278,7 +989,7 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p } else if (type == SECTION_GUID_DEFINED) { - const UInt32 kHeaderSize = 4 + kGuidSize + 4; + const unsigned kHeaderSize = 4 + kGuidSize + 4; if (sectSize < kHeaderSize) return S_FALSE; item.SetGuid(p + 4); @@ -1373,7 +1084,8 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p { item.BufIndex = AddBuf(s.Len()); CByteBuffer &buf0 = _bufs[item.BufIndex]; - memcpy(buf0, s, s.Len()); + if (s.Len() != 0) + memcpy(buf0, s, s.Len()); item.Offset = 0; item.Size = s.Len(); } @@ -1389,7 +1101,7 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p { AString s2 = "ver:"; s2 += UInt32ToString(Get16(p + 4)); - s2 += ' '; + s2.Add_Space(); s2 += s; AddSpaceAndString(_items[item.Parent].Characts, s2); needAdd = false; @@ -1617,7 +1329,7 @@ HRESULT CHandler::ParseVolume( HRESULT CHandler::OpenCapsule(IInStream *stream) { - const UInt32 kHeaderSize = 80; + const unsigned kHeaderSize = 80; Byte buf[kHeaderSize]; RINOK(ReadStream_FALSE(stream, buf, kHeaderSize)); _h.Parse(buf); @@ -1632,7 +1344,7 @@ HRESULT CHandler::OpenCapsule(IInStream *stream) _h.OffsetToSplitInformation != 0 ) return E_NOTIMPL; - int bufIndex = AddBuf(_h.CapsuleImageSize); + unsigned bufIndex = AddBuf(_h.CapsuleImageSize); CByteBuffer &buf0 = _bufs[bufIndex]; memcpy(buf0, buf, kHeaderSize); ReadStream_FALSE(stream, buf0 + kHeaderSize, _h.CapsuleImageSize - kHeaderSize); @@ -1662,7 +1374,7 @@ HRESULT CHandler::OpenFv(IInStream *stream, const UInt64 * /* maxCheckStartPosit _phySize = ffsHeader.VolSize; RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); UInt32 fvSize32 = (UInt32)ffsHeader.VolSize; - int bufIndex = AddBuf(fvSize32); + unsigned bufIndex = AddBuf(fvSize32); RINOK(ReadStream_FALSE(stream, _bufs[bufIndex], fvSize32)); return ParseVolume(bufIndex, 0, fvSize32, fvSize32, -1, -1, 0); } @@ -1680,14 +1392,17 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, unsigned num = _items.Size(); CIntArr numChilds(num); + unsigned i; + for (i = 0; i < num; i++) numChilds[i] = 0; + for (i = 0; i < num; i++) { int parent = _items[i].Parent; if (parent >= 0) - numChilds[parent]++; + numChilds[(unsigned)parent]++; } for (i = 0; i < num; i++) @@ -1696,14 +1411,15 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, int parent = item.Parent; if (parent >= 0) { - CItem &parentItem = _items[parent]; - if (numChilds[parent] == 1) + CItem &parentItem = _items[(unsigned)parent]; + if (numChilds[(unsigned)parent] == 1) if (!item.ThereIsUniqueName || !parentItem.ThereIsUniqueName || !parentItem.ThereAreSubDirs) parentItem.Skip = true; } } CUIntVector mainToReduced; + for (i = 0; i < _items.Size(); i++) { mainToReduced.Add(_items2.Size()); @@ -1714,14 +1430,15 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, int numItems = -1; int parent = item.Parent; if (parent >= 0) - numItems = numChilds[parent]; + numItems = numChilds[(unsigned)parent]; AString name2 = item.GetName(numItems); AString characts2 = item.Characts; if (item.KeepName) name = name2; + while (parent >= 0) { - const CItem &item3 = _items[parent]; + const CItem &item3 = _items[(unsigned)parent]; if (!item3.Skip) break; if (item3.KeepName) @@ -1735,6 +1452,7 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, AddSpaceAndString(characts2, item3.Characts); parent = item3.Parent; } + if (name.IsEmpty()) name = name2; @@ -1743,7 +1461,7 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, item2.Name = name; item2.Characts = characts2; if (parent >= 0) - item2.Parent = mainToReduced[parent]; + item2.Parent = mainToReduced[(unsigned)parent]; _items2.Add(item2); /* CItem2 item2; @@ -1753,6 +1471,7 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, _items2.Add(item2); */ } + return S_OK; } @@ -1873,30 +1592,26 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) namespace UEFIc { -IMP_CreateArcIn_2(CHandler(true)) - -static CArcInfo g_ArcInfo = - { "UEFIc", "scap", 0, 0xD0, - kCapsuleSigSize, CAPSULE_SIGNATURE, +REGISTER_ARC_I_CLS( + CHandler(true), + "UEFIc", "scap", 0, 0xD0, + kCapsuleSig, 0, NArcInfoFlags::kFindSignature, - CreateArc }; + NULL) -REGISTER_ARC(UEFIc) } namespace UEFIf { -IMP_CreateArcIn_2(CHandler(false)) - -static CArcInfo g_ArcInfo = - { "UEFIf", "uefif", 0, 0xD1, - kGuidSize, FFS_SIGNATURE, +REGISTER_ARC_I_CLS( + CHandler(false), + "UEFIf", "uefif", 0, 0xD1, + k_FFS_Guid, kFfsGuidOffset, NArcInfoFlags::kFindSignature, - CreateArc }; - -REGISTER_ARC(UEFIf) + NULL) + } }} diff --git a/CPP/7zip/Archive/VhdHandler.cpp b/CPP/7zip/Archive/VhdHandler.cpp index a2126811..7508adfa 100644 --- a/CPP/7zip/Archive/VhdHandler.cpp +++ b/CPP/7zip/Archive/VhdHandler.cpp @@ -6,8 +6,6 @@ #include "../../Common/ComTry.h" #include "../../Common/IntToString.h" -#include "../../Common/MyBuffer.h" -#include "../../Common/MyString.h" #include "../../Windows/PropVariant.h" @@ -41,7 +39,7 @@ static const UInt32 kDiskType_Fixed = 2; static const UInt32 kDiskType_Dynamic = 3; static const UInt32 kDiskType_Diff = 4; -static const char *kDiskTypes[] = +static const char * const kDiskTypes[] = { "0" , "1" @@ -201,11 +199,17 @@ bool CDynHeader::Parse(const Byte *p) memcpy(ParentId, p + 0x28, 16); { const unsigned kNameLen = 256; - wchar_t *s = ParentName.GetBuffer(kNameLen); - for (unsigned i = 0; i < kNameLen; i++) - s[i] = Get16(p + 0x40 + i * 2); - s[kNameLen] = 0; - ParentName.ReleaseBuffer(); + wchar_t *s = ParentName.GetBuf(kNameLen); + unsigned i; + for (i = 0; i < kNameLen; i++) + { + wchar_t c = Get16(p + 0x40 + i * 2); + if (c == 0) + break; + s[i] = c; + } + s[i] = 0; + ParentName.ReleaseBuf_SetLen(i); } for (unsigned i = 0; i < 8; i++) if (!ParentLocators[i].Parse(p + 0x240 + i * 24)) @@ -240,7 +244,7 @@ class CHandler: void AddErrorMessage(const wchar_t *s) { if (!_errorMessage.IsEmpty()) - _errorMessage += L'\n'; + _errorMessage.Add_LF(); _errorMessage += s; } void UpdatePhySize(UInt64 value) @@ -265,7 +269,7 @@ class CHandler: while (p && p->NeedParent()) { if (!res.IsEmpty()) - res += L" -> "; + res.AddAscii(" -> "); UString mainName; UString anotherName; if (Dyn.RelativeNameWasUsed) @@ -281,7 +285,7 @@ class CHandler: res += mainName; if (mainName != anotherName && !anotherName.IsEmpty()) { - res += L' '; + res.Add_Space(); res += L'('; res += anotherName; res += L')'; @@ -425,12 +429,20 @@ HRESULT CHandler::Open3() Byte nameBuf[kNameBufSizeMax]; UString tempString; unsigned len = (locator.DataLen >> 1); - wchar_t *s = tempString.GetBuffer(len); - RINOK(ReadPhy(locator.DataOffset, nameBuf, locator.DataLen)); - for (unsigned j = 0; j < len; j++) - s[j] = GetUi16(nameBuf + j * 2); - s[len] = 0; - tempString.ReleaseBuffer(); + { + wchar_t *s = tempString.GetBuf(len); + RINOK(ReadPhy(locator.DataOffset, nameBuf, locator.DataLen)); + unsigned j; + for (j = 0; j < len; j++) + { + wchar_t c = GetUi16(nameBuf + j * 2); + if (c == 0) + break; + s[j] = c; + } + s[j] = 0; + tempString.ReleaseBuf_SetLen(j); + } if (tempString[0] == L'.' && tempString[1] == L'\\') tempString.DeleteFrontal(2); Dyn.RelativeParentNameFromLocator = tempString; @@ -518,10 +530,10 @@ HRESULT CHandler::Open3() STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) { - if (processedSize != NULL) + if (processedSize) *processedSize = 0; if (_virtPos >= Footer.CurrentSize) - return (Footer.CurrentSize == _virtPos) ? S_OK: E_FAIL; + return S_OK; UInt64 rem = Footer.CurrentSize - _virtPos; if (size > rem) size = (UInt32)rem; @@ -576,7 +588,7 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) cur += rem; } } - if (processedSize != NULL) + if (processedSize) *processedSize = size; _virtPos += size; return res; @@ -705,7 +717,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) AString res = s; res.Trim(); ConvertUInt32ToString(Footer.CreatorVersion >> 16, s); - res += ' '; + res.Add_Space(); res += s; res += '.'; ConvertUInt32ToString(Footer.CreatorVersion & 0xFFFF, s); @@ -971,15 +983,11 @@ STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea COM_TRY_END } -IMP_CreateArcIn - -static CArcInfo g_ArcInfo = - { "VHD", "vhd", ".mbr", 0xDC, - kSignatureSize, SIGNATURE, +REGISTER_ARC_I( + "VHD", "vhd", ".mbr", 0xDC, + kSignature, 0, NArcInfoFlags::kUseGlobalOffset, - CreateArc }; - -REGISTER_ARC(Vhd) + NULL) }} diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp index 886d8d77..bca551a6 100644 --- a/CPP/7zip/Archive/Wim/WimHandler.cpp +++ b/CPP/7zip/Archive/Wim/WimHandler.cpp @@ -37,7 +37,9 @@ static const Byte kProps[] = kpidMethod, kpidShortName, kpidINode, - kpidLinks + kpidLinks, + kpidIsAltStream, + kpidNumAltStreams, #ifdef WIM_DETAILS , kpidVolume @@ -269,14 +271,12 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) res = kMethodLZX; if (xpress) { - if (!res.IsEmpty()) - res += ' '; + res.Add_Space_if_NotEmpty(); res += kMethodXpress; } if (copy) { - if (!res.IsEmpty()) - res += ' '; + res.Add_Space_if_NotEmpty(); res += kMethodCopy; } prop = res; @@ -308,6 +308,26 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) AddErrorMessage(s, "Some files have incorrect reference count"); if (!s.IsEmpty()) prop = s; + break; + } + + case kpidReadOnly: + { + bool readOnly = false; + if (ThereIsError()) + readOnly = true; + else if (_volumes.Size() != 0) + { + if (_version != kWimVersion + || _volumes.Size() != 2 + || _volumes[0].Stream + // || _db.Images.Size() > kNumImagesMax + ) + readOnly = true; + } + if (readOnly) + prop = readOnly; + break; } } prop.Detach(value); @@ -397,6 +417,22 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidSize: prop = (UInt64)(si ? si->Resource.UnpackSize : 0); break; case kpidIsDir: prop = item.IsDir; break; case kpidIsAltStream: prop = item.IsAltStream; break; + case kpidNumAltStreams: + { + if (!item.IsAltStream && mainItem->HasMetadata()) + { + UInt32 dirRecordSize = _db.IsOldVersion ? kDirRecordSizeOld : kDirRecordSize; + UInt32 numAltStreams = Get16(metadata + dirRecordSize - 6); + if (numAltStreams != 0) + { + if (!item.IsDir) + numAltStreams--; + prop = numAltStreams; + } + } + break; + } + case kpidAttrib: if (!item.IsAltStream && mainItem->ImageIndex >= 0) { @@ -481,7 +517,7 @@ STDMETHODIMP CHandler::GetRootProp(PROPID propID, PROPVARIANT *value) { // COM_TRY_BEGIN NCOM::CPropVariant prop; - if (_db.Images.Size() != 0 && _db.NumExludededItems != 0) + if (_db.Images.Size() != 0 && _db.NumExcludededItems != 0) { const CImage &image = _db.Images[_db.IndexOfUserImage]; const CItem &item = _db.Items[image.StartItem]; @@ -532,7 +568,7 @@ STDMETHODIMP CHandler::GetRootRawProp(PROPID propID, const void **data, UInt32 * *data = 0; *dataSize = 0; *propType = 0; - if (propID == kpidNtSecure && _db.Images.Size() != 0 && _db.NumExludededItems != 0) + if (propID == kpidNtSecure && _db.Images.Size() != 0 && _db.NumExcludededItems != 0) { const CImage &image = _db.Images[_db.IndexOfUserImage]; const CItem &item = _db.Items[image.StartItem]; @@ -705,7 +741,7 @@ class CVolumeName public: void InitName(const UString &name) { - int dotPos = name.ReverseFind('.'); + int dotPos = name.ReverseFind_Dot(); if (dotPos < 0) dotPos = name.Len(); _before = name.Left(dotPos); @@ -798,11 +834,11 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCal if (_xmls.IsEmpty() || xml.Data != _xmls[0].Data) { - wchar_t sz[16]; + char sz[16]; ConvertUInt32ToString(xml.VolIndex, sz); xml.FileName = L'['; - xml.FileName += sz; - xml.FileName += L"].xml"; + xml.FileName.AddAscii(sz); + xml.FileName.AddAscii("].xml"); _xmls.Add(xml); } @@ -957,11 +993,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, int streamIndex = item.StreamIndex; if (streamIndex < 0) { - if (!testMode && !realOutStream) - continue; + if (!item.IsDir) + if (!testMode && !realOutStream) + continue; RINOK(extractCallback->PrepareOperation(askMode)); realOutStream.Release(); - RINOK(extractCallback->SetOperationResult(_db.ItemHasStream(item) ? + RINOK(extractCallback->SetOperationResult(!item.IsDir && _db.ItemHasStream(item) ? NExtract::NOperationResult::kDataError : NExtract::NOperationResult::kOK)); continue; @@ -1016,7 +1053,7 @@ CHandler::CHandler() _xmlError = false; } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) +STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) { InitDefaults(); diff --git a/CPP/7zip/Archive/Wim/WimHandler.h b/CPP/7zip/Archive/Wim/WimHandler.h index 416e11ca..00de1b87 100644 --- a/CPP/7zip/Archive/Wim/WimHandler.h +++ b/CPP/7zip/Archive/Wim/WimHandler.h @@ -70,7 +70,7 @@ public: INTERFACE_IInArchive(;) INTERFACE_IArchiveGetRawProps(;) INTERFACE_IArchiveGetRootProps(;) - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); + STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); STDMETHOD(KeepModeForNextOpen)(); INTERFACE_IOutArchive(;) }; diff --git a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp index 149989d1..145ede42 100644 --- a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp +++ b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp @@ -21,7 +21,7 @@ #include "../../Common/UniqBlocks.h" #include "../../Crypto/RandGen.h" -#include "../../Crypto/Sha1.h" +#include "../../Crypto/Sha1Cls.h" #include "WimHandler.h" @@ -676,6 +676,8 @@ static void AddTrees(CObjectVector<CDir> &trees, CObjectVector<CMetaItem> &metaI trees.AddNew().Dirs.AddNew().MetaIndex = metaItems.Add(ri); } +#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z') + STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 numItems, IArchiveUpdateCallback *callback) { COM_TRY_BEGIN @@ -789,7 +791,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu unsigned imageIndex = (unsigned)val - 1; if (imageIndex < _db.Images.Size()) isChangedImage[imageIndex] = true; - if (_defaultImageNumber > 0 && val != _defaultImageNumber) + if (_defaultImageNumber > 0 && val != (unsigned)_defaultImageNumber) return E_INVALIDARG; } } @@ -1065,9 +1067,16 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu int colonPos = fileName.Find(L':'); if (colonPos < 0) return E_INVALIDARG; + + // we want to support cases of c::substream, where c: is drive name + if (colonPos == 1 && fileName[2] == L':' && IS_LETTER_CHAR(fileName[0])) + colonPos = 2; const UString mainName = fileName.Left(colonPos); unsigned indexOfDir; - if (curItem->FindDir(db.MetaItems, mainName, indexOfDir)) + + if (mainName.IsEmpty()) + ui.MetaIndex = curItem->MetaIndex; + else if (curItem->FindDir(db.MetaItems, mainName, indexOfDir)) ui.MetaIndex = curItem->Dirs[indexOfDir].MetaIndex; else { @@ -1082,6 +1091,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu } } } + if (ui.MetaIndex >= 0) { CAltStream ss; @@ -1126,7 +1136,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu NCOM::CPropVariant prop; RINOK(GetOutProperty(callback, i, arcIndex, kpidShortName, &prop)); if (prop.vt == VT_BSTR) - mi.ShortName = prop.bstrVal; + mi.ShortName.SetFromBstr(prop.bstrVal); else if (prop.vt != VT_EMPTY) return E_INVALIDARG; } @@ -1235,7 +1245,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu { const CItem &item = _db.Items[k]; if (item.StreamIndex >= 0) - streamsRefs[item.StreamIndex]++; + streamsRefs[(unsigned)item.StreamIndex]++; } } @@ -1250,7 +1260,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu continue; const CItem &item = _db.Items[_db.SortedItems[ui.InArcIndex]]; if (item.StreamIndex >= 0) - streamsRefs[item.StreamIndex]++; + streamsRefs[(unsigned)item.StreamIndex]++; } else { @@ -1614,7 +1624,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu db.DefaultDirItem = ri; pos += db.WriteTree_Dummy(tree); - CByteBuffer meta(pos); + CByteArr meta(pos); Set32((Byte *)meta + 4, secBufs.Size()); // num security entries pos = kSecuritySize; @@ -1637,8 +1647,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu { const CByteBuffer &buf = secBufs[i]; size_t size = buf.Size(); - memcpy(meta + pos, buf, size); - pos += size; + if (size != 0) + { + memcpy(meta + pos, buf, size); + pos += size; + } } while ((pos & 7) != 0) meta[pos++] = 0; @@ -1740,15 +1753,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu size_t xmlSize; { - UString utf16String; - if (!ConvertUTF8ToUnicode(xml, utf16String)) + UString utf16; + if (!ConvertUTF8ToUnicode(xml, utf16)) return S_FALSE; - xmlSize = (utf16String.Len() + 1) * 2; + xmlSize = (utf16.Len() + 1) * 2; - CByteBuffer xmlBuf(xmlSize); + CByteArr xmlBuf(xmlSize); Set16((Byte *)xmlBuf, 0xFEFF); - for (i = 0; i < (unsigned)utf16String.Len(); i++) - Set16((Byte *)xmlBuf + 2 + i * 2, utf16String[i]); + for (i = 0; i < (unsigned)utf16.Len(); i++) + Set16((Byte *)xmlBuf + 2 + i * 2, utf16[i]); RINOK(WriteStream(outStream, (const Byte *)xmlBuf, xmlSize)); } diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp index cec037cc..12b8525c 100644 --- a/CPP/7zip/Archive/Wim/WimIn.cpp +++ b/CPP/7zip/Archive/Wim/WimIn.cpp @@ -325,10 +325,13 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO { unsigned size = 0; int index = index1; - unsigned newLevel; int imageIndex = Items[index].ImageIndex; const CImage &image = Images[imageIndex]; - for (newLevel = 0;;) + + unsigned newLevel = 0; + bool needColon = false; + + for (;;) { const CItem &item = Items[index]; index = item.Parent; @@ -338,10 +341,11 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO meta += item.IsAltStream ? (IsOldVersion ? 0x10 : 0x24) : (IsOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2); + needColon = item.IsAltStream; size += Get16(meta) / 2; size += newLevel; newLevel = 1; - if ((UInt32)size >= ((UInt32)1 << 15)) + if (size >= ((UInt32)1 << 15)) { path = kLongPath; return; @@ -356,7 +360,9 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO size += image.RootName.Len(); size += newLevel; } - + else if (needColon) + size++; + wchar_t *s = path.AllocBstr(size); s[size] = 0; @@ -364,28 +370,31 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO { MyStringCopy(s, (const wchar_t *)image.RootName); if (newLevel) - s[image.RootName.Len()] = WCHAR_PATH_SEPARATOR; + s[image.RootName.Len()] = (wchar_t)(needColon ? L':' : WCHAR_PATH_SEPARATOR); } + else if (needColon) + s[0] = L':'; index = index1; wchar_t separator = 0; + for (;;) { const CItem &item = Items[index]; index = item.Parent; if (index >= 0 || image.NumEmptyRootItems == 0) { - if (separator) + if (separator != 0) s[--size] = separator; const Byte *meta = image.Meta + item.Offset; meta += (item.IsAltStream) ? (IsOldVersion ? 0x10: 0x24) : (IsOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2); - UInt32 len = Get16(meta) / 2; + unsigned len = Get16(meta) / 2; size -= len; wchar_t *dest = s + size; meta += 2; - for (UInt32 i = 0; i < len; i++) + for (unsigned i = 0; i < len; i++) dest[i] = Get16(meta + i * 2); } if (index < 0) @@ -394,6 +403,14 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO } } +static bool IsEmptySha(const Byte *data) +{ + for (unsigned i = 0; i < kHashSize; i++) + if (data[i] != 0) + return false; + return true; +} + // Root folders in OLD archives (ver = 1.10) conatin real items. // Root folders in NEW archives (ver > 1.11) contain only one folder with empty name. @@ -472,6 +489,8 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent) pos += (size_t)len; + unsigned numItems2 = Items.Size(); + for (UInt32 i = 0; i < numAltStreams; i++) { size_t rem = DirSize - pos; @@ -522,7 +541,13 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent) return S_FALSE; } - if (fileNameLen == 0) + + /* wim uses alt sreams list, if there is at least one alt stream. + And alt stream without name is main stream. */ + + if (fileNameLen == 0 && + (attrib & FILE_ATTRIBUTE_REPARSE_POINT + || !item.IsDir /* && (IsOldVersion || IsEmptySha(prevMeta + 0x40)) */ )) { Byte *prevMeta = DirData + item.Offset; if (IsOldVersion) @@ -546,7 +571,7 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent) if (parent < 0 && numItems == 0 && shortNameLen == 0 && fileNameLen == 0 && item.IsDir) { CImage &image = Images.Back(); - image.NumEmptyRootItems = Items.Size() - image.StartItem; + image.NumEmptyRootItems = numItems2 - image.StartItem; // Items.Size() } if (item.IsDir && subdirOffset != 0) @@ -732,14 +757,6 @@ static HRESULT ReadStreams(IInStream *inStream, const CHeader &h, CDatabase &db) return (i == offsetBuf.Size()) ? S_OK : S_FALSE; } -static bool IsEmptySha(const Byte *data) -{ - for (unsigned i = 0; i < kHashSize; i++) - if (data[i] != 0) - return false; - return true; -} - HRESULT CDatabase::OpenXml(IInStream *inStream, const CHeader &h, CByteBuffer &xml) { return UnpackData(inStream, h.XmlResource, h.IsLzxMode(), xml, NULL); @@ -1046,7 +1063,7 @@ HRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber) SortedItems.Clear(); VirtualRoots.Clear(); IndexOfUserImage = imageIndex; - NumExludededItems = 0; + NumExcludededItems = 0; ExludedItem = -1; if (Images.Size() != 1 && imageIndex < 0) @@ -1054,6 +1071,7 @@ HRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber) unsigned startItem = 0; unsigned endItem = 0; + if (imageIndex < 0) { endItem = Items.Size(); @@ -1062,7 +1080,7 @@ HRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber) IndexOfUserImage = 0; const CImage &image = Images[0]; if (!showImageNumber) - NumExludededItems = image.NumEmptyRootItems; + NumExcludededItems = image.NumEmptyRootItems; } } else if ((unsigned)imageIndex < Images.Size()) @@ -1071,12 +1089,13 @@ HRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber) startItem = image.StartItem; endItem = startItem + image.NumItems; if (!showImageNumber) - NumExludededItems = image.NumEmptyRootItems; + NumExcludededItems = image.NumEmptyRootItems; } - if (NumExludededItems != 0) + + if (NumExcludededItems != 0) { ExludedItem = startItem; - startItem += NumExludededItems; + startItem += NumExcludededItems; } unsigned num = endItem - startItem; @@ -1205,7 +1224,8 @@ HRESULT CDatabase::ExtractReparseStreams(const CObjectVector<CVolume> &volumes, Byte *dest = (Byte *)reparse; SetUi32(dest, tag); SetUi32(dest + 4, (UInt32)buf.Size()); - memcpy(dest + 8, buf, buf.Size()); + if (buf.Size() != 0) + memcpy(dest + 8, buf, buf.Size()); ItemToReparse[i] = ReparseItems.Size() - 1; } @@ -1278,20 +1298,28 @@ void CWimXml::ToUnicode(UString &s) const Byte *p = Data; if (Get16(p) != 0xFEFF) return; - wchar_t *chars = s.GetBuffer((unsigned)size / 2); + wchar_t *chars = s.GetBuf((unsigned)(size / 2)); for (size_t i = 2; i < size; i += 2) - *chars++ = (wchar_t)Get16(p + i); + { + wchar_t c = Get16(p + i); + if (c == 0) + break; + *chars++ = c; + } *chars = 0; - s.ReleaseBuffer(); + s.ReleaseBuf_SetLen((unsigned)(chars - (const wchar_t *)s)); } bool CWimXml::Parse() { - UString s; - ToUnicode(s); AString utf; - if (!ConvertUnicodeToUTF8(s, utf)) - return false; + { + UString s; + ToUnicode(s); + // if (!ConvertUnicodeToUTF8(s, utf)) return false; + ConvertUnicodeToUTF8(s, utf); + } + if (!Xml.Parse(utf)) return false; if (Xml.Root.Name != "WIM") diff --git a/CPP/7zip/Archive/Wim/WimIn.h b/CPP/7zip/Archive/Wim/WimIn.h index 4b7c6d95..c3b93a8d 100644 --- a/CPP/7zip/Archive/Wim/WimIn.h +++ b/CPP/7zip/Archive/Wim/WimIn.h @@ -406,7 +406,7 @@ public: CUIntVector SortedItems; int IndexOfUserImage; // -1 : if more than one images was filled to Sorted Items - unsigned NumExludededItems; + unsigned NumExcludededItems; int ExludedItem; // -1 : if there are no exclude items CUIntVector VirtualRoots; // we use them for old 1.10 WIM archives @@ -418,7 +418,7 @@ public: return 0; if (imageIndex >= Images.Size()) return 0; - return Images[imageIndex].NumItems - NumExludededItems; + return Images[imageIndex].NumItems - NumExcludededItems; } bool ItemHasStream(const CItem &item) const; diff --git a/CPP/7zip/Archive/Wim/WimRegister.cpp b/CPP/7zip/Archive/Wim/WimRegister.cpp index 35d78314..3063dec4 100644 --- a/CPP/7zip/Archive/Wim/WimRegister.cpp +++ b/CPP/7zip/Archive/Wim/WimRegister.cpp @@ -9,19 +9,14 @@ namespace NArchive { namespace NWim { -IMP_CreateArcIn -IMP_CreateArcOut - -static CArcInfo g_ArcInfo = - { "wim", "wim swm", 0, 0xE6, - 8, { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 }, +REGISTER_ARC_IO( + "wim", "wim swm", 0, 0xE6, + kSignature, 0, NArcInfoFlags::kAltStreams | NArcInfoFlags::kNtSecure | NArcInfoFlags::kSymLinks | NArcInfoFlags::kHardLinks - , REF_CreateArc_Pair }; - -REGISTER_ARC(Wim) + , NULL) }} diff --git a/CPP/7zip/Archive/XarHandler.cpp b/CPP/7zip/Archive/XarHandler.cpp index 918ef736..7e89bf48 100644 --- a/CPP/7zip/Archive/XarHandler.cpp +++ b/CPP/7zip/Archive/XarHandler.cpp @@ -35,15 +35,15 @@ using namespace NWindows; namespace NArchive { namespace NXar { -static const UInt32 kXmlSizeMax = ((UInt32)1 << 30) - (1 << 14); -static const UInt32 kXmlPackSizeMax = kXmlSizeMax; +static const size_t kXmlSizeMax = ((size_t )1 << 30) - (1 << 14); +static const size_t kXmlPackSizeMax = kXmlSizeMax; /* #define XAR_CKSUM_NONE 0 #define XAR_CKSUM_SHA1 1 #define XAR_CKSUM_MD5 2 -static const char *k_ChecksumAlgos[] = +static const char * const k_ChecksumAlgos[] = { "None" , "SHA-1" @@ -76,8 +76,8 @@ struct CFile bool Sha1IsDefined; // bool packSha1IsDefined; - Byte Sha1[NCrypto::NSha1::kDigestSize]; - // Byte packSha1[NCrypto::NSha1::kDigestSize]; + Byte Sha1[SHA1_DIGEST_SIZE]; + // Byte packSha1[SHA1_DIGEST_SIZE]; int Parent; @@ -107,7 +107,8 @@ class CHandler: { UInt64 _dataStartPos; CMyComPtr<IInStream> _inStream; - AString _xml; + CByteArr _xml; + size_t _xmlLen; CObjectVector<CFile> _files; // UInt32 _checkSumAlgo; UInt64 _phySize; @@ -182,7 +183,7 @@ static UInt64 ParseTime(const CXmlItem &item, const char *name) return numSecs * 10000000; } -static int HexToByte(char c) +static int HexToByte(unsigned char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'A' && c <= 'F') return c - 'A' + 10; @@ -200,7 +201,7 @@ static bool ParseSha1(const CXmlItem &item, const char *name, Byte *digest) if (style == "SHA1") { const AString s = checkItem.GetSubString(); - if (s.Len() != NCrypto::NSha1::kDigestSize * 2) + if (s.Len() != SHA1_DIGEST_SIZE * 2) return false; for (unsigned i = 0; i < s.Len(); i += 2) { @@ -321,8 +322,9 @@ HRESULT CHandler::Open2(IInStream *stream) _dataStartPos = kHeaderSize + packSize; _phySize = _dataStartPos; - char *ss = _xml.GetBuffer((unsigned)unpackSize); - + _xml.Alloc((size_t)unpackSize + 1); + _xmlLen = (size_t)unpackSize; + NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder(); CMyComPtr<ICompressCoder> zlibCoder = zlibCoderSpec; @@ -333,18 +335,18 @@ HRESULT CHandler::Open2(IInStream *stream) CBufPtrSeqOutStream *outStreamLimSpec = new CBufPtrSeqOutStream; CMyComPtr<ISequentialOutStream> outStreamLim(outStreamLimSpec); - outStreamLimSpec->Init((Byte *)ss, (size_t)unpackSize); + outStreamLimSpec->Init(_xml, (size_t)unpackSize); RINOK(zlibCoder->Code(inStreamLim, outStreamLim, NULL, NULL, NULL)); if (outStreamLimSpec->GetPos() != (size_t)unpackSize) return S_FALSE; - ss[(size_t)unpackSize] = 0; - _xml.ReleaseBuffer(); + _xml[(size_t)unpackSize] = 0; + if (strlen((const char *)(const Byte *)_xml) != unpackSize) return S_FALSE; CXml xml; - if (!xml.Parse(_xml)) + if (!xml.Parse((const char *)(const Byte *)_xml)) return S_FALSE; if (!xml.Root.IsTagged("xar") || xml.Root.SubItems.Size() != 1) @@ -390,7 +392,8 @@ STDMETHODIMP CHandler::Close() _phySize = 0; _inStream.Release(); _files.Clear(); - _xml.Empty(); + _xmlLen = 0; + _xml.Free(); _mainSubfile = -1; _is_pkg = false; return S_OK; @@ -456,7 +459,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { case kpidPath: prop = "[TOC].xml"; break; case kpidSize: - case kpidPackSize: prop = (UInt64)_xml.Len(); break; + case kpidPackSize: prop = (UInt64)_xmlLen; break; } } else @@ -531,7 +534,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UInt32 index = (allFilesMode ? i : indices[i]); #ifdef XAR_SHOW_RAW if (index == _files.Size()) - totalSize += _xml.Len(); + totalSize += _xmlLen; else #endif totalSize += _files[index].Size; @@ -614,9 +617,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (index == _files.Size()) { outStreamSha1Spec->Init(false); - outStreamLimSpec->Init(_xml.Len()); - RINOK(WriteStream(outStream, (const char *)_xml, _xml.Len())); - currentPackSize = currentUnpSize = _xml.Len(); + outStreamLimSpec->Init(_xmlLen); + RINOK(WriteStream(outStream, _xml, _xmlLen)); + currentPackSize = currentUnpSize = _xmlLen; } else #endif @@ -670,9 +673,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } else if (item.Sha1IsDefined) { - Byte digest[NCrypto::NSha1::kDigestSize]; + Byte digest[SHA1_DIGEST_SIZE]; outStreamSha1Spec->Final(digest); - if (memcmp(digest, item.Sha1, NCrypto::NSha1::kDigestSize) != 0) + if (memcmp(digest, item.Sha1, SHA1_DIGEST_SIZE) != 0) opRes = NExtract::NOperationResult::kCRCError; } } @@ -695,7 +698,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) #ifdef XAR_SHOW_RAW if (index == _files.Size()) { - Create_BufInStream_WithNewBuf((const void *)(const char *)_xml, _xml.Len(), stream); + Create_BufInStream_WithNewBuffer(_xml, _xmlLen, stream); return S_OK; } else @@ -709,15 +712,13 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) COM_TRY_END } -IMP_CreateArcIn +static const Byte k_Signature[] = { 'x', 'a', 'r', '!', 0, 0x1C }; -static CArcInfo g_ArcInfo = - { "Xar", "xar pkg", 0, 0xE1, - 6, { 'x', 'a', 'r', '!', 0, 0x1C }, +REGISTER_ARC_I( + "Xar", "xar pkg", 0, 0xE1, + k_Signature, 0, 0, - CreateArc }; - -REGISTER_ARC(Xar) + NULL) }} diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp index 0de58a44..ada14fbf 100644 --- a/CPP/7zip/Archive/XzHandler.cpp +++ b/CPP/7zip/Archive/XzHandler.cpp @@ -23,6 +23,8 @@ #include "Common/HandlerOut.h" +#include "XzHandler.h" + using namespace NWindows; namespace NCompress { @@ -32,92 +34,36 @@ HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzm }} -static void *SzAlloc(void *, size_t size) { return MyAlloc(size); } -static void SzFree(void *, void *address) { MyFree(address); } -static ISzAlloc g_Alloc = { SzAlloc, SzFree }; - namespace NArchive { namespace NXz { struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit; -static const wchar_t *k_LZMA2_Name = L"LZMA2"; +static const char *k_LZMA2_Name = "LZMA2"; -struct CStatInfo +void CStatInfo::Clear() { - UInt64 InSize; - UInt64 OutSize; - UInt64 PhySize; - - UInt64 NumStreams; - UInt64 NumBlocks; - - bool UnpackSize_Defined; - - bool NumStreams_Defined; - bool NumBlocks_Defined; - - bool IsArc; - bool UnexpectedEnd; - bool DataAfterEnd; - bool Unsupported; - bool HeadersError; - bool DataError; - bool CrcError; - - CStatInfo() { Clear(); } - - void Clear() - { - InSize = 0; - OutSize = 0; - PhySize = 0; - - NumStreams = 0; - NumBlocks = 0; - - UnpackSize_Defined = false; + InSize = 0; + OutSize = 0; + PhySize = 0; - NumStreams_Defined = false; - NumBlocks_Defined = false; - - UnexpectedEnd = false; - DataAfterEnd = false; - Unsupported = false; - HeadersError = false; - DataError = false; - CrcError = false; - IsArc = false; - } - -}; - -struct IDecodeState: public CStatInfo -{ - SRes DecodeRes; - - IDecodeState(): DecodeRes(SZ_OK) {} - virtual HRESULT Progress() = 0; - - HRESULT Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream); -}; - -struct CVirtProgress_To_LocalProgress: public IDecodeState -{ - CLocalProgress *lps; - CMyComPtr<ICompressProgressInfo> progress; - - HRESULT Progress(); -}; - -HRESULT CVirtProgress_To_LocalProgress::Progress() -{ - lps->InSize = InSize; - lps->OutSize = OutSize; - return lps->SetCur(); + NumStreams = 0; + NumBlocks = 0; + + UnpackSize_Defined = false; + + NumStreams_Defined = false; + NumBlocks_Defined = false; + + IsArc = false; + UnexpectedEnd = false; + DataAfterEnd = false; + Unsupported = false; + HeadersError = false; + DataError = false; + CrcError = false; } - class CHandler: public IInArchive, public IArchiveOpenSeq, @@ -148,10 +94,11 @@ class CHandler: HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback); - HRESULT Decode2(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, IDecodeState &progress) + HRESULT Decode2(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, + CDecoder &decoder, ICompressProgressInfo *progress) { - RINOK(progress.Decode(seqInStream, outStream)); - _stat = progress; + RINOK(decoder.Decode(seqInStream, outStream, progress)); + _stat = decoder; _phySize_Defined = true; return S_OK; } @@ -171,7 +118,7 @@ public: #ifndef EXTRACT_ONLY INTERFACE_IOutArchive(;) - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); + STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); #endif CHandler(); @@ -295,12 +242,11 @@ static AString GetMethodString(const CXzFilter &f) static void AddString(AString &dest, const AString &src) { - if (!dest.IsEmpty()) - dest += ' '; + dest.Add_Space_if_NotEmpty(); dest += src; } -static const char *kChecks[] = +static const char * const kChecks[] = { "NoCheck" , "CRC32" @@ -423,26 +369,6 @@ struct CXzsCPP ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); } }; - -struct CVirtProgress_To_OpenProgress: public IDecodeState -{ - IArchiveOpenCallback *Callback; - UInt64 Offset; - - HRESULT Progress(); -}; - -HRESULT CVirtProgress_To_OpenProgress::Progress() -{ - if (Callback) - { - UInt64 files = 0; - UInt64 value = Offset + InSize; - return Callback->SetCompleted(&files, &value); - } - return S_OK; -} - static HRESULT SRes_to_Open_HRESULT(SRes res) { switch (res) @@ -527,6 +453,7 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal { res = SZ_OK; } + RINOK(SRes_to_Open_HRESULT(res)); _stream = inStream; _seqStream = inStream; @@ -587,38 +514,32 @@ STDMETHODIMP CSeekToSeqStream::Read(void *data, UInt32 size, UInt32 *processedSi STDMETHODIMP CSeekToSeqStream::Seek(Int64, UInt32, UInt64 *) { return E_NOTIMPL; } -struct CXzUnpackerCPP +CXzUnpackerCPP::CXzUnpackerCPP(): InBuf(0), OutBuf(0) { - Byte *InBuf; - Byte *OutBuf; - CXzUnpacker p; - - CXzUnpackerCPP(): InBuf(0), OutBuf(0) - { - XzUnpacker_Construct(&p, &g_Alloc); - } - ~CXzUnpackerCPP() - { - XzUnpacker_Free(&p); - MyFree(InBuf); - MyFree(OutBuf); - } -}; + XzUnpacker_Construct(&p, &g_Alloc); +} + +CXzUnpackerCPP::~CXzUnpackerCPP() +{ + XzUnpacker_Free(&p); + MyFree(InBuf); + MyFree(OutBuf); +} -HRESULT IDecodeState::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream) +HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) { const size_t kInBufSize = 1 << 15; const size_t kOutBufSize = 1 << 21; + Clear(); DecodeRes = SZ_OK; - CXzUnpackerCPP xzu; XzUnpacker_Init(&xzu.p); - xzu.InBuf = (Byte *)MyAlloc(kInBufSize); - xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize); - if (!xzu.InBuf || !xzu.OutBuf) - return E_OUTOFMEMORY; - + if (!xzu.InBuf) + xzu.InBuf = (Byte *)MyAlloc(kInBufSize); + if (!xzu.OutBuf) + xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize); + UInt32 inSize = 0; SizeT inPos = 0; SizeT outPos = 0; @@ -664,7 +585,10 @@ HRESULT IDecodeState::Decode(ISequentialInStream *seqInStream, ISequentialOutStr else outPos = 0; - RINOK(Progress()); + if (progress) + { + RINOK(progress->SetRatioInfo(&InSize, &OutSize)); + } if (finished) { @@ -730,6 +654,30 @@ HRESULT IDecodeState::Decode(ISequentialInStream *seqInStream, ISequentialOutStr return S_OK; } +Int32 CDecoder::Get_Extract_OperationResult() const +{ + Int32 opRes; + if (!IsArc) + opRes = NExtract::NOperationResult::kIsNotArc; + else if (UnexpectedEnd) + opRes = NExtract::NOperationResult::kUnexpectedEnd; + else if (DataAfterEnd) + opRes = NExtract::NOperationResult::kDataAfterEnd; + else if (CrcError) + opRes = NExtract::NOperationResult::kCRCError; + else if (Unsupported) + opRes = NExtract::NOperationResult::kUnsupportedMethod; + else if (HeadersError) + opRes = NExtract::NOperationResult::kDataError; + else if (DataError) + opRes = NExtract::NOperationResult::kDataError; + else if (DecodeRes != SZ_OK) + opRes = NExtract::NOperationResult::kDataError; + else + opRes = NExtract::NOperationResult::kOK; + return opRes; +} + STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { @@ -739,7 +687,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; - extractCallback->SetTotal(_stat.PhySize); + if (_phySize_Defined) + extractCallback->SetTotal(_stat.PhySize); + UInt64 currentTotalPacked = 0; RINOK(extractCallback->SetCompleted(¤tTotalPacked)); CMyComPtr<ISequentialOutStream> realOutStream; @@ -754,11 +704,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, extractCallback->PrepareOperation(askMode); - CVirtProgress_To_LocalProgress vp; - vp.lps = new CLocalProgress; - vp.progress = vp.lps; - vp.lps->Init(extractCallback, true); - + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> lpsRef = lps; + lps->Init(extractCallback, true); if (_needSeekToStart) { @@ -769,28 +717,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, else _needSeekToStart = true; - RINOK(Decode2(_seqStream, realOutStream, vp)); - - Int32 opRes; - - if (!vp.IsArc) - opRes = NExtract::NOperationResult::kIsNotArc; - else if (vp.UnexpectedEnd) - opRes = NExtract::NOperationResult::kUnexpectedEnd; - else if (vp.DataAfterEnd) - opRes = NExtract::NOperationResult::kDataAfterEnd; - else if (vp.CrcError) - opRes = NExtract::NOperationResult::kCRCError; - else if (vp.Unsupported) - opRes = NExtract::NOperationResult::kUnsupportedMethod; - else if (vp.HeadersError) - opRes = NExtract::NOperationResult::kDataError; - else if (vp.DataError) - opRes = NExtract::NOperationResult::kDataError; - else if (vp.DecodeRes != SZ_OK) - opRes = NExtract::NOperationResult::kDataError; - else - opRes = NExtract::NOperationResult::kOK; + CDecoder decoder; + RINOK(Decode2(_seqStream, realOutStream, decoder, lpsRef)); + Int32 opRes = decoder.Get_Extract_OperationResult(); realOutStream.Release(); return extractCallback->SetOperationResult(opRes); @@ -808,6 +737,8 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { + COM_TRY_BEGIN + CSeqOutStreamWrap seqOutStream(outStream); if (numItems == 0) @@ -927,16 +858,37 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); return SResToHRESULT(res); } + if (indexInArchive != 0) return E_INVALIDARG; + + CMyComPtr<IArchiveUpdateCallbackFile> opCallback; + updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback); + if (opCallback) + { + RINOK(opCallback->ReportOperation(NEventIndexType::kInArcIndex, 0, NUpdateNotifyOp::kReplicate)) + } + if (_stream) + { + if (_phySize_Defined) + RINOK(updateCallback->SetTotal(_stat.PhySize)); RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); - return NCompress::CopyStream(_stream, outStream, NULL); + } + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(updateCallback, true); + + return NCompress::CopyStream(_stream, outStream, progress); + + COM_TRY_END } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) +STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) { COM_TRY_BEGIN + Init(); for (UInt32 i = 0; i < numProps; i++) { @@ -964,28 +916,25 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v return E_INVALIDARG; if (_methods.Size() == 1) { - UString &methodName = _methods[0].MethodName; + AString &methodName = _methods[0].MethodName; if (methodName.IsEmpty()) methodName = k_LZMA2_Name; - else if (!methodName.IsEqualToNoCase(k_LZMA2_Name)) + else if (!methodName.IsEqualTo_Ascii_NoCase(k_LZMA2_Name)) return E_INVALIDARG; } + return S_OK; + COM_TRY_END } #endif -IMP_CreateArcIn -IMP_CreateArcOut - -static CArcInfo g_ArcInfo = - { "xz", "xz txz", "* .tar", 0xC, - 6, { 0xFD, '7' , 'z', 'X', 'Z', 0 }, +REGISTER_ARC_IO( + "xz", "xz txz", "* .tar", 0xC, + XZ_SIG, 0, NArcInfoFlags::kKeepName, - REF_CreateArc_Pair }; - -REGISTER_ARC(xz) + NULL) }} diff --git a/CPP/7zip/Archive/XzHandler.h b/CPP/7zip/Archive/XzHandler.h new file mode 100644 index 00000000..4a59e356 --- /dev/null +++ b/CPP/7zip/Archive/XzHandler.h @@ -0,0 +1,65 @@ +// XzHandler.h + +#ifndef __XZ_HANDLER_H +#define __XZ_HANDLER_H + +#include "../../../C/Xz.h" + +#include "../ICoder.h" + +namespace NArchive { +namespace NXz { + +struct CXzUnpackerCPP +{ + Byte *InBuf; + Byte *OutBuf; + CXzUnpacker p; + + CXzUnpackerCPP(); + ~CXzUnpackerCPP(); +}; + +struct CStatInfo +{ + UInt64 InSize; + UInt64 OutSize; + UInt64 PhySize; + + UInt64 NumStreams; + UInt64 NumBlocks; + + bool UnpackSize_Defined; + + bool NumStreams_Defined; + bool NumBlocks_Defined; + + bool IsArc; + bool UnexpectedEnd; + bool DataAfterEnd; + bool Unsupported; + bool HeadersError; + bool DataError; + bool CrcError; + + CStatInfo() { Clear(); } + + void Clear(); +}; + +struct CDecoder: public CStatInfo +{ + CXzUnpackerCPP xzu; + SRes DecodeRes; // it's not HRESULT + + CDecoder(): DecodeRes(SZ_OK) {} + + /* Decode() can return ERROR code only if there is progress or stream error. + Decode() returns S_OK in case of xz decoding error, but DecodeRes and CStatInfo contain error information */ + HRESULT Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress); + Int32 Get_Extract_OperationResult() const; +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/ZHandler.cpp b/CPP/7zip/Archive/ZHandler.cpp index 7635f22d..29934367 100644 --- a/CPP/7zip/Archive/ZHandler.cpp +++ b/CPP/7zip/Archive/ZHandler.cpp @@ -224,15 +224,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } -IMP_CreateArcIn +static const Byte k_Signature[] = { 0x1F, 0x9D }; -static CArcInfo g_ArcInfo = - { "Z", "z taz", "* .tar", 5, - 2, { 0x1F, 0x9D }, +REGISTER_ARC_I( + "Z", "z taz", "* .tar", 5, + k_Signature, 0, 0, - CreateArc, NULL, IsArc_Z }; - -REGISTER_ARC(Z) + IsArc_Z) }} diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp index 9a0d7515..c9c290aa 100644 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp @@ -3,6 +3,7 @@ #include "StdAfx.h" #include "../../../../C/7zCrc.h" +#include "../../../../C/Alloc.h" #include "../../../Windows/PropVariant.h" @@ -77,32 +78,46 @@ STDMETHODIMP CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStr CAddCommon::CAddCommon(const CCompressionMethodMode &options): - _options(options), - _copyCoderSpec(NULL), - _cryptoStreamSpec(0) - {} + _options(options), + _copyCoderSpec(NULL), + _cryptoStreamSpec(NULL), + _buf(NULL) + {} -static HRESULT GetStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC) +CAddCommon::~CAddCommon() { + MidFree(_buf); +} + +static const UInt32 kBufSize = ((UInt32)1 << 16); + +HRESULT CAddCommon::CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC) +{ + if (!_buf) + { + _buf = (Byte *)MidAlloc(kBufSize); + if (!_buf) + return E_OUTOFMEMORY; + } + UInt32 crc = CRC_INIT_VAL; - const UInt32 kBufSize = (1 << 14); - Byte buf[kBufSize]; for (;;) { UInt32 processed; - RINOK(inStream->Read(buf, kBufSize, &processed)); + RINOK(inStream->Read(_buf, kBufSize, &processed)); if (processed == 0) { resultCRC = CRC_GET_DIGEST(crc); return S_OK; } - crc = CrcUpdate(crc, buf, (size_t)processed); + crc = CrcUpdate(crc, _buf, (size_t)processed); } } HRESULT CAddCommon::Compress( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, IOutStream *outStream, + UInt32 /* fileTime */, ICompressProgressInfo *progress, CCompressingResult &opRes) { if (!inStream) @@ -111,13 +126,14 @@ HRESULT CAddCommon::Compress( return E_INVALIDARG; } - CSequentialInStreamWithCRC *inSecCrcStreamSpec = NULL; + // CSequentialInStreamWithCRC *inSecCrcStreamSpec = NULL; CInStreamWithCRC *inCrcStreamSpec = NULL; CMyComPtr<ISequentialInStream> inCrcStream; { CMyComPtr<IInStream> inStream2; - // we don't support stdin, since stream from stdin can require 64-bit size header - RINOK(inStream->QueryInterface(IID_IInStream, (void **)&inStream2)); + + inStream->QueryInterface(IID_IInStream, (void **)&inStream2); + if (inStream2) { inCrcStreamSpec = new CInStreamWithCRC; @@ -127,28 +143,29 @@ HRESULT CAddCommon::Compress( } else { + // we don't support stdin, since stream from stdin can require 64-bit size header + return E_NOTIMPL; + /* inSecCrcStreamSpec = new CSequentialInStreamWithCRC; inCrcStream = inSecCrcStreamSpec; inSecCrcStreamSpec->SetStream(inStream); inSecCrcStreamSpec->Init(); + */ } } unsigned numTestMethods = _options.MethodSequence.Size(); - if (numTestMethods > 1 || _options.PasswordIsDefined) - { - if (!inCrcStreamSpec) - { - if (_options.PasswordIsDefined) - return E_NOTIMPL; - numTestMethods = 1; - } - } + if (numTestMethods > 1 && !inCrcStreamSpec) + numTestMethods = 1; + + UInt32 crc = 0; + bool crc_IsCalculated = false; Byte method = 0; - COutStreamReleaser outStreamReleaser; + CFilterCoder::C_OutStream_Releaser outStreamReleaser; opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default; + opRes.FileTimeWasUsed = false; for (unsigned i = 0; i < numTestMethods; i++) { @@ -164,7 +181,7 @@ HRESULT CAddCommon::Compress( if (!_cryptoStream) { - _cryptoStreamSpec = new CFilterCoder; + _cryptoStreamSpec = new CFilterCoder(true); _cryptoStream = _cryptoStreamSpec; } @@ -186,13 +203,32 @@ HRESULT CAddCommon::Compress( _cryptoStreamSpec->Filter = _filterSpec = new NCrypto::NZip::CEncoder; _filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len()); } - UInt32 crc = 0; - RINOK(GetStreamCRC(inStream, crc)); - RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL)); - RINOK(_filterSpec->WriteHeader(outStream, crc)); + + UInt32 check; + + // if (inCrcStreamSpec) + { + if (!crc_IsCalculated) + { + RINOK(CalcStreamCRC(inStream, crc)); + crc_IsCalculated = true; + RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL)); + } + check = (crc >> 16); + } + /* + else + { + opRes.FileTimeWasUsed = true; + check = (fileTime & 0xFFFF); + } + */ + + RINOK(_filterSpec->WriteHeader_Check16(outStream, (UInt16)check)); } RINOK(_cryptoStreamSpec->SetOutStream(outStream)); + RINOK(_cryptoStreamSpec->InitEncoder()); outStreamReleaser.FilterCoder = _cryptoStreamSpec; } @@ -250,7 +286,7 @@ HRESULT CAddCommon::Compress( } RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS - methodId, _compressEncoder, true)); + methodId, true, _compressEncoder)); if (!_compressEncoder) return E_NOTIMPL; @@ -284,34 +320,42 @@ HRESULT CAddCommon::Compress( } } + if (_options.PasswordIsDefined) + { + RINOK(_cryptoStreamSpec->OutStreamFinish()); + + if (_options.IsAesMode) + { + RINOK(_filterAesSpec->WriteFooter(outStream)); + } + } + RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize)); - if (inCrcStreamSpec) + // if (inCrcStreamSpec) { opRes.CRC = inCrcStreamSpec->GetCRC(); opRes.UnpackSize = inCrcStreamSpec->GetSize(); } + /* else { opRes.CRC = inSecCrcStreamSpec->GetCRC(); opRes.UnpackSize = inSecCrcStreamSpec->GetSize(); } + */ if (_options.PasswordIsDefined) { if (opRes.PackSize < opRes.UnpackSize + - (_options.IsAesMode ? _filterAesSpec->GetHeaderSize() : NCrypto::NZip::kHeaderSize)) + (_options.IsAesMode ? _filterAesSpec->GetAddPackSize() : NCrypto::NZip::kHeaderSize)) break; } else if (opRes.PackSize < opRes.UnpackSize) break; } - - if (_options.PasswordIsDefined && _options.IsAesMode) - { - RINOK(_filterAesSpec->WriteFooter(outStream)); - RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize)); - } + + opRes.Method = method; return S_OK; } diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.h b/CPP/7zip/Archive/Zip/ZipAddCommon.h index e4c02db3..1e0c3bfa 100644 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.h +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.h @@ -26,6 +26,7 @@ struct CCompressingResult UInt32 CRC; UInt16 Method; Byte ExtractVersion; + bool FileTimeWasUsed; }; class CAddCommon @@ -43,11 +44,16 @@ class CAddCommon NCrypto::NZip::CEncoder *_filterSpec; NCrypto::NWzAes::CEncoder *_filterAesSpec; + Byte *_buf; + + HRESULT CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC); public: CAddCommon(const CCompressionMethodMode &options); + ~CAddCommon(); HRESULT Compress( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, IOutStream *outStream, + UInt32 fileTime, ICompressProgressInfo *progress, CCompressingResult &operationResult); }; diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp index f556068c..3e29a880 100644 --- a/CPP/7zip/Archive/Zip/ZipHandler.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp @@ -28,6 +28,8 @@ #include "../Common/ItemNameUtils.h" #include "../Common/OutStreamWithCRC.h" +#include "../XzHandler.h" + #include "ZipHandler.h" using namespace NWindows; @@ -38,7 +40,7 @@ namespace NZip { static const CMethodId kMethodId_ZipBase = 0x040100; static const CMethodId kMethodId_BZip2 = 0x040202; -static const char *kHostOS[] = +static const char * const kHostOS[] = { "FAT" , "AMIGA" @@ -62,7 +64,7 @@ static const char *kHostOS[] = , "OS/X" }; -static const char *kMethods[] = +static const char * const kMethods[] = { "Store" , "Shrink" @@ -91,6 +93,7 @@ static const CIdToNamePair k_MethodIdNamePairs[] = { { NFileHeader::NCompressionMethod::kBZip2, "BZip2" }, { NFileHeader::NCompressionMethod::kLZMA, "LZMA" }, + { NFileHeader::NCompressionMethod::kXz, "xz" }, { NFileHeader::NCompressionMethod::kJpeg, "Jpeg" }, { NFileHeader::NCompressionMethod::kWavPack, "WavPack" }, { NFileHeader::NCompressionMethod::kPPMd, "PPMd" } @@ -156,14 +159,7 @@ CHandler::CHandler() static AString BytesToString(const CByteBuffer &data) { AString s; - unsigned size = (unsigned)data.Size(); - if (size > 0) - { - char *p = s.GetBuffer(size); - memcpy(p, (const Byte *)data, size); - p[size] = 0; - s.ReleaseBuffer(); - } + s.SetFrom_CalcLen((const char *)(const Byte *)data, (unsigned)data.Size()); return s; } @@ -220,6 +216,14 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) prop = v; break; } + + case kpidReadOnly: + { + if (m_Archive.IsOpen()) + if (!m_Archive.CanUpdate()) + prop = true; + break; + } } prop.Detach(value); COM_TRY_END @@ -334,12 +338,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidMethod: { - UInt16 methodId = item.Method; + unsigned id = item.Method; AString m; if (item.IsEncrypted()) { - if (methodId == NFileHeader::NCompressionMethod::kWzAES) + if (id == NFileHeader::NCompressionMethod::kWzAES) { m += kMethod_AES; CWzAesExtra aesField; @@ -349,7 +353,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val s[0] = '-'; ConvertUInt32ToString(((unsigned)aesField.Strength + 1) * 64 , s + 1); m += s; - methodId = aesField.Method; + id = aesField.Method; } } else if (item.IsStrongEncrypted()) @@ -381,19 +385,19 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { char temp[16]; const char *s = NULL; - if (methodId < ARRAY_SIZE(kMethods)) - s = kMethods[methodId]; + if (id < ARRAY_SIZE(kMethods)) + s = kMethods[id]; else { - s = FindNameForId(k_MethodIdNamePairs, ARRAY_SIZE(k_MethodIdNamePairs), methodId); + s = FindNameForId(k_MethodIdNamePairs, ARRAY_SIZE(k_MethodIdNamePairs), id); if (!s) { - ConvertUInt32ToString(methodId, temp); + ConvertUInt32ToString(id, temp); s = temp; } } m += s; - if (methodId == NFileHeader::NCompressionMethod::kLZMA && item.IsLzmaEOS()) + if (id == NFileHeader::NCompressionMethod::kLZMA && item.IsLzmaEOS()) m += ":EOS"; } @@ -507,9 +511,36 @@ HRESULT CLzmaDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream * return Decoder->Code(inStream, outStream, NULL, outSize, progress); } + +class CXzDecoder: + public ICompressCoder, + public CMyUnknownImp +{ + NArchive::NXz::CDecoder _decoder; +public: + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + MY_UNKNOWN_IMP +}; + +HRESULT CXzDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) +{ + RINOK(_decoder.Decode(inStream, outStream, progress)); + Int32 opRes = _decoder.Get_Extract_OperationResult(); + if (opRes == NExtract::NOperationResult::kUnsupportedMethod) + return E_NOTIMPL; + if (opRes != NExtract::NOperationResult::kOK) + return S_FALSE; + return S_OK; +} + + struct CMethodItem { - UInt16 ZipMethod; + unsigned ZipMethod; CMyComPtr<ICompressCoder> Coder; }; @@ -559,12 +590,13 @@ HRESULT CZipDecoder::Decode( Int32 &res) { res = NExtract::NOperationResult::kDataError; - CInStreamReleaser inStreamReleaser; + CFilterCoder::C_InStream_Releaser inStreamReleaser; bool needCRC = true; bool wzAesMode = false; bool pkAesMode = false; - UInt16 methodId = item.Method; + unsigned id = item.Method; + if (item.IsEncrypted()) { if (item.IsStrongEncrypted()) @@ -580,7 +612,7 @@ HRESULT CZipDecoder::Decode( return S_OK; } } - if (!pkAesMode && methodId == NFileHeader::NCompressionMethod::kWzAES) + if (!pkAesMode && id == NFileHeader::NCompressionMethod::kWzAES) { CWzAesExtra aesField; if (item.CentralExtra.GetWzAes(aesField)) @@ -613,6 +645,7 @@ HRESULT CZipDecoder::Decode( } CMyComPtr<ICompressFilter> cryptoFilter; + if (item.IsEncrypted()) { if (wzAesMode) @@ -620,15 +653,18 @@ HRESULT CZipDecoder::Decode( CWzAesExtra aesField; if (!item.CentralExtra.GetWzAes(aesField)) return S_OK; - methodId = aesField.Method; + id = aesField.Method; if (!_wzAesDecoder) { _wzAesDecoderSpec = new NCrypto::NWzAes::CDecoder; _wzAesDecoder = _wzAesDecoderSpec; } cryptoFilter = _wzAesDecoder; - Byte properties = aesField.Strength; - RINOK(_wzAesDecoderSpec->SetDecoderProperties2(&properties, 1)); + if (!_wzAesDecoderSpec->SetKeyMode(aesField.Strength)) + { + res = NExtract::NOperationResult::kUnsupportedMethod; + return S_OK; + } } else if (pkAesMode) { @@ -648,6 +684,7 @@ HRESULT CZipDecoder::Decode( } cryptoFilter = _zipCryptoDecoder; } + CMyComPtr<ICryptoSetPassword> cryptoSetPassword; RINOK(cryptoFilter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword)); @@ -699,39 +736,41 @@ HRESULT CZipDecoder::Decode( unsigned m; for (m = 0; m < methodItems.Size(); m++) - if (methodItems[m].ZipMethod == methodId) + if (methodItems[m].ZipMethod == id) break; if (m == methodItems.Size()) { CMethodItem mi; - mi.ZipMethod = methodId; - if (methodId == NFileHeader::NCompressionMethod::kStored) + mi.ZipMethod = id; + if (id == NFileHeader::NCompressionMethod::kStored) mi.Coder = new NCompress::CCopyCoder; - else if (methodId == NFileHeader::NCompressionMethod::kShrunk) + else if (id == NFileHeader::NCompressionMethod::kShrunk) mi.Coder = new NCompress::NShrink::CDecoder; - else if (methodId == NFileHeader::NCompressionMethod::kImploded) + else if (id == NFileHeader::NCompressionMethod::kImploded) mi.Coder = new NCompress::NImplode::NDecoder::CCoder; - else if (methodId == NFileHeader::NCompressionMethod::kLZMA) + else if (id == NFileHeader::NCompressionMethod::kLZMA) mi.Coder = new CLzmaDecoder; - else if (methodId == NFileHeader::NCompressionMethod::kPPMd) + else if (id == NFileHeader::NCompressionMethod::kXz) + mi.Coder = new CXzDecoder; + else if (id == NFileHeader::NCompressionMethod::kPPMd) mi.Coder = new NCompress::NPpmdZip::CDecoder(true); else { CMethodId szMethodID; - if (methodId == NFileHeader::NCompressionMethod::kBZip2) + if (id == NFileHeader::NCompressionMethod::kBZip2) szMethodID = kMethodId_BZip2; else { - if (methodId > 0xFF) + if (id > 0xFF) { res = NExtract::NOperationResult::kUnsupportedMethod; return S_OK; } - szMethodID = kMethodId_ZipBase + (Byte)methodId; + szMethodID = kMethodId_ZipBase + (Byte)id; } - RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS szMethodID, mi.Coder, false)); + RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS szMethodID, false, mi.Coder)); if (mi.Coder == 0) { @@ -741,6 +780,7 @@ HRESULT CZipDecoder::Decode( } m = methodItems.Add(mi); } + ICompressCoder *coder = methodItems[m].Coder; { @@ -771,13 +811,23 @@ HRESULT CZipDecoder::Decode( { if (!filterStream) { - filterStreamSpec = new CFilterCoder; + filterStreamSpec = new CFilterCoder(false); filterStream = filterStreamSpec; } + filterStreamSpec->Filter = cryptoFilter; + if (wzAesMode) { result = _wzAesDecoderSpec->ReadHeader(inStream); + if (result == S_OK) + { + if (!_wzAesDecoderSpec->Init_and_CheckPassword()) + { + res = NExtract::NOperationResult::kWrongPassword; + return S_OK; + } + } } else if (pkAesMode) { @@ -785,43 +835,64 @@ HRESULT CZipDecoder::Decode( if (result == S_OK) { bool passwOK; - result = _pkAesDecoderSpec->CheckPassword(passwOK); + result = _pkAesDecoderSpec->Init_and_CheckPassword(passwOK); if (result == S_OK && !passwOK) - result = S_FALSE; + { + res = NExtract::NOperationResult::kWrongPassword; + return S_OK; + } } } else { result = _zipCryptoDecoderSpec->ReadHeader(inStream); + if (result == S_OK) + { + _zipCryptoDecoderSpec->Init_BeforeDecode(); + + /* Info-ZIP modification to ZipCrypto format: + if bit 3 of the general purpose bit flag is set, + it uses high byte of 16-bit File Time. + Info-ZIP code probably writes 2 bytes of File Time. + We check only 1 byte. */ + + // UInt32 v1 = GetUi16(_zipCryptoDecoderSpec->_header + NCrypto::NZip::kHeaderSize - 2); + // UInt32 v2 = (item.HasDescriptor() ? (item.Time & 0xFFFF) : (item.Crc >> 16)); + + Byte v1 = _zipCryptoDecoderSpec->_header[NCrypto::NZip::kHeaderSize - 1]; + Byte v2 = (Byte)(item.HasDescriptor() ? (item.Time >> 8) : (item.Crc >> 24)); + + if (v1 != v2) + { + res = NExtract::NOperationResult::kWrongPassword; + return S_OK; + } + } } if (result == S_OK) { - if (pkAesMode) - { - /* 9.31: The BUG in 9.24-9.30 was fixed. pkAes archives didn't work. - We don't need to call CAesCbcCoder::Init() to reset IV for data. */ - filterStreamSpec->SetInStream_NoSubFilterInit(inStream); - } - else - { - RINOK(filterStreamSpec->SetInStream(inStream)); - } inStreamReleaser.FilterCoder = filterStreamSpec; + RINOK(filterStreamSpec->SetInStream(inStream)); + + /* IFilter::Init() does nothing in all zip crypto filters. + So we can call any Initialize function in CFilterCoder. */ + + RINOK(filterStreamSpec->Init_NoSubFilterInit()); + // RINOK(filterStreamSpec->SetOutStreamSize(NULL)); + inStreamNew = filterStream; - if (wzAesMode) - { - if (!_wzAesDecoderSpec->CheckPasswordVerifyCode()) - result = S_FALSE; - } } } else inStreamNew = inStream; + if (result == S_OK) result = coder->Code(inStreamNew, outStream, NULL, &item.Size, compressProgress); + if (result == S_FALSE) return S_OK; + if (result == E_NOTIMPL) { res = NExtract::NOperationResult::kUnsupportedMethod; @@ -830,6 +901,7 @@ HRESULT CZipDecoder::Decode( RINOK(result); } + bool crcOK = true; bool authOk = true; if (needCRC) diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h index 7f1d2eba..c2a362a7 100644 --- a/CPP/7zip/Archive/Zip/ZipHandler.h +++ b/CPP/7zip/Archive/Zip/ZipHandler.h @@ -33,7 +33,7 @@ public: INTERFACE_IInArchive(;) INTERFACE_IOutArchive(;) - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); + STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); DECL_ISetCompressCodecsInfo diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp index ae58cbe2..f1c8b227 100644 --- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp @@ -34,15 +34,16 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) return S_OK; } -static bool IsAsciiString(const UString &s) +static bool IsSimpleAsciiString(const wchar_t *s) { - for (unsigned i = 0; i < s.Len(); i++) + for (;;) { - wchar_t c = s[i]; + wchar_t c = *s++; + if (c == 0) + return true; if (c < 0x20 || c > 0x7F) return false; } - return true; } #define COM_TRY_BEGIN2 try { @@ -180,11 +181,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (tryUtf8) { - unsigned i; - for (i = 0; i < name.Len() && (unsigned)name[i] < 0x80; i++); - ui.IsUtf8 = (i != name.Len()); - if (!ConvertUnicodeToUTF8(name, ui.Name)) - return E_INVALIDARG; + ui.IsUtf8 = !name.IsAscii(); + ConvertUnicodeToUTF8(name, ui.Name); } if (ui.Name.Len() >= (1 << 16)) @@ -249,10 +247,10 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (!m_ForceAesMode) options.IsAesMode = thereAreAesUpdates; - if (!IsAsciiString((BSTR)password)) + if (!IsSimpleAsciiString(password)) return E_INVALIDARG; if (password) - options.Password = UnicodeStringToMultiByte((BSTR)password, CP_OEMCP); + options.Password = UnicodeStringToMultiByte((LPCOLESTR)password, CP_OEMCP); if (options.IsAesMode) { if (options.Password.Len() > NCrypto::NWzAes::kPasswordSizeMax) @@ -297,7 +295,7 @@ static const CMethodIndexToName k_SupportedMethods[] = { NFileHeader::NCompressionMethod::kPPMd, "ppmd" } }; -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) +STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) { InitMethodProps(); #ifndef _7ZIP_ST @@ -318,7 +316,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v UInt32 level = 9; RINOK(ParsePropToUInt32(name.Ptr(1), prop, level)); _props.Level = level; - _props.MethodInfo.AddLevelProp(level); + _props.MethodInfo.AddProp_Level(level); } else if (name == L"m") { diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h index 1391cdf4..c109992c 100644 --- a/CPP/7zip/Archive/Zip/ZipHeader.h +++ b/CPP/7zip/Archive/Zip/ZipHeader.h @@ -54,6 +54,8 @@ namespace NFileHeader kLZMA = 14, kTerse = 18, kLz77 = 19, + + kXz = 0x5F, kJpeg = 0x60, kWavPack = 0x61, kPPMd = 0x62, diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index 345fbf56..6f495305 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -348,7 +348,7 @@ HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchLim return S_FALSE; } -HRESULT CInArchive::IncreaseRealPosition(UInt64 addValue) +HRESULT CInArchive::IncreaseRealPosition(Int64 addValue) { return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position); } @@ -439,10 +439,9 @@ void CInArchive::ReadFileName(unsigned size, AString &s) s.Empty(); return; } - char *p = s.GetBuffer(size); + char *p = s.GetBuf(size); SafeReadBytes(p, size); - p[size] = 0; - s.ReleaseBuffer(); + s.ReleaseBuf_CalcLen(size); } bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extraBlock, @@ -556,7 +555,12 @@ bool CInArchive::ReadLocalItem(CItemEx &item) UInt32 diskStartNumber = 0; if (!ReadExtra(extraSize, item.LocalExtra, item.Size, item.PackSize, localHeaderOffset, diskStartNumber)) - return false; + { + /* Most of archives are OK for Extra. But there are some rare cases + that have error. And if error in first item, it can't open archive. + So we ignore that error */ + // return false; + } } if (!CheckDosTime(item.Time)) { @@ -650,6 +654,7 @@ HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item) numBytesInBuffer += processedSize; if (numBytesInBuffer < kDataDescriptorSize) return S_FALSE; + UInt32 i; for (i = 0; i <= numBytesInBuffer - kDataDescriptorSize; i++) { @@ -666,10 +671,11 @@ HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item) item.Crc = Get32(buf + i + 4); item.PackSize = descriptorPackSize; item.Size = Get32(buf + i + 12); - return IncreaseRealPosition(Int64(Int32(0 - (numBytesInBuffer - i - kDataDescriptorSize)))); + return IncreaseRealPosition((Int64)(Int32)(0 - (numBytesInBuffer - i - kDataDescriptorSize))); } } } + packedSize += i; unsigned j; for (j = 0; i < numBytesInBuffer; i++, j++) @@ -1262,7 +1268,10 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p (UInt32)ecd64.cdSize != (UInt32)cdSize || ((UInt32)(ecd64.cdStartOffset) != (UInt32)cdRelatOffset && (!items.IsEmpty()))) - return S_FALSE; + { + // return S_FALSE; + HeadersError = true; + } // printf("\nOpen OK"); return S_OK; diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h index f6b349b1..734d3bcb 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.h +++ b/CPP/7zip/Archive/Zip/ZipIn.h @@ -25,7 +25,7 @@ public: UInt64 GetLocalFullSize() const { return LocalFullHeaderSize + PackSize + (HasDescriptor() ? kDataDescriptorSize : 0); } UInt64 GetDataPosition() const - { return LocalHeaderPos + LocalFullHeaderSize; }; + { return LocalHeaderPos + LocalFullHeaderSize; } }; struct CInArchiveInfo @@ -107,7 +107,7 @@ class CInArchive HRESULT Seek(UInt64 offset); HRESULT FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit); - HRESULT IncreaseRealPosition(UInt64 addValue); + HRESULT IncreaseRealPosition(Int64 addValue); HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize); void SafeReadBytes(void *data, unsigned size); diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp index ae88944d..f2ccc814 100644 --- a/CPP/7zip/Archive/Zip/ZipItem.cpp +++ b/CPP/7zip/Archive/Zip/ZipItem.cpp @@ -114,7 +114,7 @@ bool CItem::IsDir() const case NHostOS::kMVS: return false; // change it throw kUnknownAttributes; case NHostOS::kUnix: - return (highAttrib & NUnixAttrib::kIFDIR) != 0; + return ((highAttrib & NUnixAttrib::kIFMT) == NUnixAttrib::kIFDIR); default: return false; } @@ -130,6 +130,11 @@ UInt32 CItem::GetWinAttrib() const if (FromCentral) winAttrib = ExternalAttrib; break; + case NHostOS::kUnix: + // do we need to clear 16 low bits in this case? + if (FromCentral) + winAttrib = ExternalAttrib & 0xFFFF0000; + break; } if (IsDir()) // test it; winAttrib |= FILE_ATTRIBUTE_DIRECTORY; diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h index d50c3ae9..98afdf1d 100644 --- a/CPP/7zip/Archive/Zip/ZipItem.h +++ b/CPP/7zip/Archive/Zip/ZipItem.h @@ -179,9 +179,12 @@ struct CExtraBlock void RemoveUnknownSubBlocks() { - for (int i = SubBlocks.Size() - 1; i >= 0; i--) + for (unsigned i = SubBlocks.Size(); i != 0;) + { + i--; if (SubBlocks[i].ID != NFileHeader::NExtraID::kWzAES) SubBlocks.Delete(i); + } } }; @@ -204,8 +207,8 @@ public: bool IsUtf8() const { return (Flags & NFileHeader::NFlags::kUtf8) != 0; } bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kEncrypted) != 0; } - bool IsStrongEncrypted() const { return IsEncrypted() && (Flags & NFileHeader::NFlags::kStrongEncrypted) != 0; }; - bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || Method == NFileHeader::NCompressionMethod::kWzAES); }; + bool IsStrongEncrypted() const { return IsEncrypted() && (Flags & NFileHeader::NFlags::kStrongEncrypted) != 0; } + bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || Method == NFileHeader::NCompressionMethod::kWzAES); } bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; } bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; } @@ -237,6 +240,7 @@ public: void ClearFlags() { Flags = 0; } void SetEncrypted(bool encrypted) { SetFlag(NFileHeader::NFlags::kEncrypted, encrypted); } void SetUtf8(bool isUtf8) { SetFlag(NFileHeader::NFlags::kUtf8, isUtf8); } + void SetDescriptorMode(bool useDescriptor) { SetFlag(NFileHeader::NFlags::kDescriptorUsedMask, useDescriptor); } UINT GetCodePage() const { return CP_OEMCP; } }; @@ -277,6 +281,7 @@ public: void GetUnicodeString(const AString &s, UString &res, bool useSpecifiedCodePage, UINT codePage) const { bool isUtf8 = IsUtf8(); + bool ignore_Utf8_Errors = true; #ifdef _WIN32 if (!isUtf8) @@ -287,14 +292,15 @@ public: { /* Some ZIP archives in Unix use UTF-8 encoding without Utf8 flag in header. We try to get name as UTF-8. - Do we need to do it in POSIX version also? */ + Do we need to do it in POSIX version also? */ isUtf8 = true; + ignore_Utf8_Errors = false; } } #endif if (isUtf8) - if (ConvertUTF8ToUnicode(s, res)) + if (ConvertUTF8ToUnicode(s, res) || ignore_Utf8_Errors) return; MultiByteToUnicodeString2(res, s, useSpecifiedCodePage ? codePage : GetCodePage()); } diff --git a/CPP/7zip/Archive/Zip/ZipOut.h b/CPP/7zip/Archive/Zip/ZipOut.h index eaaa0320..056d0d09 100644 --- a/CPP/7zip/Archive/Zip/ZipOut.h +++ b/CPP/7zip/Archive/Zip/ZipOut.h @@ -63,7 +63,7 @@ public: HRESULT Create(IOutStream *outStream); void MoveCurPos(UInt64 distanceToMove); - UInt64 GetCurPos() const { return m_CurPos; }; + UInt64 GetCurPos() const { return m_CurPos; } void SeekToCurPos(); diff --git a/CPP/7zip/Archive/Zip/ZipRegister.cpp b/CPP/7zip/Archive/Zip/ZipRegister.cpp index 545e76c6..2be783e6 100644 --- a/CPP/7zip/Archive/Zip/ZipRegister.cpp +++ b/CPP/7zip/Archive/Zip/ZipRegister.cpp @@ -9,23 +9,18 @@ namespace NArchive { namespace NZip { -IMP_CreateArcIn -IMP_CreateArcOut - -static CArcInfo g_ArcInfo = - { "zip", "zip zipx jar xpi odt ods docx xlsx epub", 0, 1, - 3 + 4 + 4 + 6, - { +static const Byte k_Signature[] = { 4, 0x50, 0x4B, 0x03, 0x04, 4, 0x50, 0x4B, 0x05, 0x06, - 6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B, - }, + 6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B }; + +REGISTER_ARC_IO( + "zip", "zip zipx jar xpi odt ods docx xlsx epub", 0, 1, + k_Signature, 0, NArcInfoFlags::kFindSignature | NArcInfoFlags::kMultiSignature | NArcInfoFlags::kUseGlobalOffset, - REF_CreateArc_Pair, IsArc_Zip }; - -REGISTER_ARC(Zip) - + IsArc_Zip) + }} diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp index 97cce5ac..9a9526cc 100644 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -65,6 +65,7 @@ static void SetFileHeader( COutArchive &archive, const CCompressionMethodMode &options, const CUpdateItem &ui, + // bool isSeqMode, CItemOut &item) { item.Size = ui.Size; @@ -95,6 +96,8 @@ static void SetFileHeader( item.InternalAttrib = 0; // test it item.SetEncrypted(!isDir && options.PasswordIsDefined); + // item.SetDescriptorMode(isSeqMode); + if (isDir) { item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir; @@ -156,12 +159,14 @@ struct CThreadInfo bool IsFree; UInt32 UpdateIndex; + UInt32 FileTime; CThreadInfo(const CCompressionMethodMode &options): ExitThread(false), ProgressSpec(0), OutStreamSpec(0), - Coder(options) + Coder(options), + FileTime(0) {} HRESULT CreateEvents() @@ -192,9 +197,11 @@ void CThreadInfo::WaitAndCode() CompressEvent.Lock(); if (ExitThread) return; + Result = Coder.Compress( EXTERNAL_CODECS_LOC_VARS - InStream, OutStream, Progress, CompressingResult); + InStream, OutStream, FileTime, Progress, CompressingResult); + if (Result == S_OK && Progress) Result = Progress->SetRatioInfo(&CompressingResult.UnpackSize, &CompressingResult.PackSize); CompressionCompletedEvent.Set(); @@ -254,7 +261,7 @@ public: MY_UNKNOWN_IMP void Create(IProgress *progress, bool inSizeIsMain); void SetProgressOffset(UInt64 progressOffset); - HRESULT SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize); + HRESULT SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize); STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; @@ -274,16 +281,16 @@ void CMtProgressMixer2::SetProgressOffset(UInt64 progressOffset) CriticalSection.Leave(); } -HRESULT CMtProgressMixer2::SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize) +HRESULT CMtProgressMixer2::SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize) { NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); if (index == 0 && RatioProgress) { RINOK(RatioProgress->SetRatioInfo(inSize, outSize)); } - if (inSize != 0) + if (inSize) InSizes[index] = *inSize; - if (outSize != 0) + if (outSize) OutSizes[index] = *outSize; UInt64 v = ProgressOffset + (_inSizeIsMain ? (InSizes[0] + InSizes[1]) : @@ -332,8 +339,16 @@ static HRESULT UpdateItemOldData( CItemOut &item, /* bool izZip64, */ ICompressProgressInfo *progress, + IArchiveUpdateCallbackFile *opCallback, UInt64 &complexity) { + if (opCallback) + { + RINOK(opCallback->ReportOperation( + NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArc, + NUpdateNotifyOp::kReplicate)) + } + if (ui.NewProps) { if (item.HasDescriptor()) @@ -396,7 +411,8 @@ static HRESULT Update2St( const CObjectVector<CUpdateItem> &updateItems, const CCompressionMethodMode *options, const CByteBuffer *comment, - IArchiveUpdateCallback *updateCallback) + IArchiveUpdateCallback *updateCallback, + IArchiveUpdateCallbackFile *opCallback) { CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; @@ -445,15 +461,37 @@ static HRESULT Update2St( if (!fileInStream) return E_INVALIDARG; + // bool isSeqMode = false; + /* + { + CMyComPtr<IInStream> inStream2; + fileInStream->QueryInterface(IID_IInStream, (void **)&inStream2); + isSeqMode = (inStream2 == NULL); + } + */ + // file Size can be 64-bit !!! SetFileHeader(archive, *options, ui, item); archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size, options->IsRealAesMode()); CCompressingResult compressingResult; CMyComPtr<IOutStream> outStream; archive.CreateStreamForCompressing(&outStream); + RINOK(compressor.Compress( EXTERNAL_CODECS_LOC_VARS - fileInStream, outStream, progress, compressingResult)); + fileInStream, outStream, + ui.Time, + progress, compressingResult)); + + if (compressingResult.FileTimeWasUsed) + { + /* + if (!item.HasDescriptor()) + return E_FAIL; + */ + item.SetDescriptorMode(true); + } + SetItemInfoFromCompressingResult(compressingResult, options->IsRealAesMode(), options->AesKeyMode, item); archive.WriteLocalHeader_And_SeekToNextFile(item); RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); @@ -465,13 +503,14 @@ static HRESULT Update2St( { UInt64 complexity = 0; lps->SendRatio = false; - RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, complexity)); + RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, opCallback, complexity)); lps->SendRatio = true; lps->ProgressOffset += complexity; } items.Add(item); lps->ProgressOffset += kLocalHeaderSize; } + lps->InSize = unpackSizeTotal; lps->OutSize = packSizeTotal; RINOK(lps->SetCur()); @@ -489,6 +528,9 @@ static HRESULT Update2( const CByteBuffer *comment, IArchiveUpdateCallback *updateCallback) { + CMyComPtr<IArchiveUpdateCallbackFile> opCallback; + updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback); + UInt64 complexity = 0; UInt64 numFilesToCompress = 0; UInt64 numBytesToCompress = 0; @@ -542,6 +584,7 @@ static HRESULT Update2( numThreads = MAXIMUM_WAIT_OBJECTS; if (numThreads < 1) numThreads = 1; + const size_t kMemPerThread = (1 << 25); const size_t kBlockSize = 1 << 16; @@ -558,7 +601,7 @@ static HRESULT Update2( { // fixed for 9.31. bzip2 default is just one thread. if (options2.NumThreadsWasChanged || method == NFileHeader::NCompressionMethod::kBZip2) - options2.MethodInfo.AddNumThreadsProp(numThreads); + options2.MethodInfo.AddProp_NumThreads(numThreads); } } else @@ -577,7 +620,7 @@ static HRESULT Update2( numBZip2Threads = 32; if (averageNumberOfBlocks < numBZip2Threads) numBZip2Threads = (UInt32)averageNumberOfBlocks; - options2.MethodInfo.AddNumThreadsProp(numBZip2Threads); + options2.MethodInfo.AddProp_NumThreads(numBZip2Threads); } numThreads /= numBZip2Threads; } @@ -599,7 +642,7 @@ static HRESULT Update2( return Update2St( EXTERNAL_CODECS_LOC_VARS archive, inArchive, - inputItems, updateItems, &options2, comment, updateCallback); + inputItems, updateItems, &options2, comment, updateCallback, opCallback); #ifndef _7ZIP_ST @@ -643,6 +686,7 @@ static HRESULT Update2( threadInfo.ProgressSpec = new CMtCompressProgress(); threadInfo.Progress = threadInfo.ProgressSpec; threadInfo.ProgressSpec->Init(&mtCompressProgressMixer, (int)i); + threadInfo.FileTime = 0; // fix it ! RINOK(threadInfo.CreateThread()); } } @@ -784,7 +828,15 @@ static HRESULT Update2( DWORD result = ::WaitForMultipleObjects(compressingCompletedEvents.Size(), &compressingCompletedEvents.Front(), FALSE, INFINITE); - int t = (int)(result - WAIT_OBJECT_0); + if (result == WAIT_FAILED) + { + DWORD lastError = GetLastError(); + return lastError != 0 ? lastError : E_FAIL; + } + unsigned t = (unsigned)(result - WAIT_OBJECT_0); + if (t >= compressingCompletedEvents.Size()) + return E_FAIL; + CThreadInfo &threadInfo = threads.Threads[threadIndices[t]]; threadInfo.InStream.Release(); threadInfo.IsFree = true; @@ -813,7 +865,7 @@ static HRESULT Update2( } else { - RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, complexity)); + RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, opCallback, complexity)); } items.Add(item); complexity += kLocalHeaderSize; diff --git a/CPP/7zip/Bundles/Alone/Alone.dsp b/CPP/7zip/Bundles/Alone/Alone.dsp index 40f87879..cd7341c1 100644 --- a/CPP/7zip/Bundles/Alone/Alone.dsp +++ b/CPP/7zip/Bundles/Alone/Alone.dsp @@ -350,6 +350,10 @@ SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\Sha1Reg.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\Sha256Reg.cpp # End Source File # Begin Source File @@ -1214,14 +1218,6 @@ SOURCE=..\..\Compress\BitmEncoder.h # End Source File # Begin Source File -SOURCE=..\..\Compress\BranchCoder.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Compress\BranchCoder.h -# End Source File -# Begin Source File - SOURCE=..\..\Compress\BranchMisc.cpp # End Source File # Begin Source File @@ -1517,14 +1513,6 @@ SOURCE=..\..\Archive\Common\CoderMixer2.h # End Source File # Begin Source File -SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Common\CoderMixer2MT.h -# End Source File -# Begin Source File - SOURCE=..\..\Archive\Common\DummyOutStream.cpp # End Source File # Begin Source File @@ -1650,6 +1638,10 @@ SOURCE=..\..\Archive\GzHandler.cpp # End Source File # Begin Source File +SOURCE=..\..\Archive\IArchive.h +# End Source File +# Begin Source File + SOURCE=..\..\Archive\LzmaHandler.cpp # End Source File # Begin Source File @@ -1944,32 +1936,6 @@ SOURCE=..\..\Crypto\RandGen.h # End Source File # Begin Source File -SOURCE=..\..\Crypto\Sha1.cpp - -!IF "$(CFG)" == "Alone - Win32 Release" - -# ADD CPP /O2 -# SUBTRACT CPP /YX /Yc /Yu - -!ELSEIF "$(CFG)" == "Alone - Win32 Debug" - -!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" - -!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=..\..\Crypto\Sha1.h -# End Source File -# Begin Source File - -SOURCE=..\..\Crypto\Sha1Reg.cpp -# End Source File -# Begin Source File - SOURCE=..\..\Crypto\WzAes.cpp # End Source File # Begin Source File @@ -2385,6 +2351,30 @@ SOURCE=..\..\..\..\C\Bcj2.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Bcj2Enc.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Bra.c !IF "$(CFG)" == "Alone - Win32 Release" @@ -2918,6 +2908,34 @@ SOURCE=..\..\..\..\C\RotateDefs.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Sha1.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sha1.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Sha256.c !IF "$(CFG)" == "Alone - Win32 Release" diff --git a/CPP/7zip/Bundles/Alone/makefile b/CPP/7zip/Bundles/Alone/makefile index 15139714..02a51398 100644 --- a/CPP/7zip/Bundles/Alone/makefile +++ b/CPP/7zip/Bundles/Alone/makefile @@ -23,6 +23,7 @@ COMMON_OBJS = \ $O\MyVector.obj \ $O\Wildcard.obj \ $O\XzCrc64Reg.obj \ + $O\Sha1Reg.obj \ $O\Sha256Reg.obj \ WIN_OBJS = \ @@ -50,7 +51,6 @@ WIN_OBJS = \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\LimitedStreams.obj \ - $O\LockedStream.obj \ $O\MemBlocks.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ @@ -77,7 +77,6 @@ AR_OBJS = \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ - $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\DummyOutStream.obj \ $O\FindSignature.obj \ @@ -139,7 +138,6 @@ COMPRESS_OBJS = \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BitlDecoder.obj \ - $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ @@ -181,8 +179,6 @@ CRYPTO_OBJS = \ $O\MyAesReg.obj \ $O\Pbkdf2HmacSha1.obj \ $O\RandGen.obj \ - $O\Sha1.obj \ - $O\Sha1Reg.obj \ $O\WzAes.obj \ $O\ZipCrypto.obj \ $O\ZipStrong.obj \ @@ -190,6 +186,8 @@ CRYPTO_OBJS = \ C_OBJS = \ $O\7zStream.obj \ $O\Alloc.obj \ + $O\Bcj2.obj \ + $O\Bcj2Enc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ @@ -210,6 +208,7 @@ C_OBJS = \ $O\Ppmd8.obj \ $O\Ppmd8Dec.obj \ $O\Ppmd8Enc.obj \ + $O\Sha1.obj \ $O\Sha256.obj \ $O\Sort.obj \ $O\Threads.obj \ diff --git a/CPP/7zip/Bundles/Alone7z/Alone.dsp b/CPP/7zip/Bundles/Alone7z/Alone.dsp index 2800ff88..089e4020 100644 --- a/CPP/7zip/Bundles/Alone7z/Alone.dsp +++ b/CPP/7zip/Bundles/Alone7z/Alone.dsp @@ -44,7 +44,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gr /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /FAc /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe @@ -69,7 +69,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gr /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe @@ -94,7 +94,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /Yu"StdAfx.h" /FD /c -# ADD CPP /nologo /Gz /MD /W4 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gr /MD /W4 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe @@ -121,7 +121,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gr /MDd /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe @@ -738,14 +738,6 @@ SOURCE=..\..\Compress\BcjRegister.cpp # End Source File # Begin Source File -SOURCE=..\..\Compress\BranchCoder.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Compress\BranchCoder.h -# End Source File -# Begin Source File - SOURCE=..\..\Compress\BranchMisc.cpp # End Source File # Begin Source File @@ -961,14 +953,6 @@ SOURCE=..\..\Archive\Common\CoderMixer2.h # End Source File # Begin Source File -SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Common\CoderMixer2MT.h -# End Source File -# Begin Source File - SOURCE=..\..\Archive\Common\DummyOutStream.cpp # End Source File # Begin Source File @@ -1026,6 +1010,10 @@ SOURCE=..\..\Archive\Common\ParseProperties.h # End Group # Begin Source File +SOURCE=..\..\Archive\IArchive.h +# End Source File +# Begin Source File + SOURCE=..\..\Archive\LzmaHandler.cpp # End Source File # Begin Source File @@ -1526,6 +1514,58 @@ SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Bcj2.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bcj2.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bcj2Enc.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Bra.c # SUBTRACT CPP /YX /Yc /Yu # End Source File diff --git a/CPP/7zip/Bundles/Alone7z/makefile b/CPP/7zip/Bundles/Alone7z/makefile index 84b235eb..7589bc30 100644 --- a/CPP/7zip/Bundles/Alone7z/makefile +++ b/CPP/7zip/Bundles/Alone7z/makefile @@ -48,7 +48,6 @@ WIN_OBJS = \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ - $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OffsetStream.obj \ @@ -68,7 +67,6 @@ AR_OBJS = \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ - $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\DummyOutStream.obj \ $O\HandlerOut.obj \ @@ -101,7 +99,6 @@ COMPRESS_OBJS = \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ - $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ @@ -125,6 +122,8 @@ CRYPTO_OBJS = \ C_OBJS = \ $O\7zStream.obj \ $O\Alloc.obj \ + $O\Bcj2.obj \ + $O\Bcj2Enc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ diff --git a/CPP/7zip/Bundles/Fm/FM.dsp b/CPP/7zip/Bundles/Fm/FM.dsp index 1f214b33..dfb0bb47 100644 --- a/CPP/7zip/Bundles/Fm/FM.dsp +++ b/CPP/7zip/Bundles/Fm/FM.dsp @@ -45,7 +45,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS_2" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -72,7 +72,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS_2" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -99,7 +99,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /c -# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS_2" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -127,7 +127,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS_2" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -211,9 +211,188 @@ SOURCE=..\..\UI\FileManager\Test.bmp # Begin Group "Archive" # PROP Default_Filter "" +# Begin Group "7z" + +# PROP Default_Filter "" # Begin Source File -SOURCE=..\..\Archive\IArchive.h +SOURCE=..\..\Archive\7z\7zCompressionMode.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zCompressionMode.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zDecode.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zDecode.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zEncode.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zEncode.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zExtract.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zFolderInStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zFolderInStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zFolderOutStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandlerOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHeader.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHeader.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zItem.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zOut.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zProperties.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zProperties.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zSpecStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zSpecStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zUpdate.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zUpdate.h +# End Source File +# End Group +# Begin Group "Archive Common" + +# 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 + +SOURCE=..\..\Archive\Common\CoderMixer2.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\DummyOutStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\DummyOutStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\FindSignature.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\FindSignature.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\HandlerOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\HandlerOut.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\InStreamWithCRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\InStreamWithCRC.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\ItemNameUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\ItemNameUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\MultiStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\MultiStream.h # End Source File # Begin Source File @@ -223,12 +402,33 @@ SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp SOURCE=..\..\Archive\Common\OutStreamWithCRC.h # End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\ParseProperties.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\ParseProperties.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\Archive\IArchive.h +# End Source File # End Group # Begin Group "Folders" # PROP Default_Filter "" # Begin Source File +SOURCE=..\..\UI\FileManager\AltStreamsFolder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\AltStreamsFolder.h +# End Source File +# Begin Source File + SOURCE=..\..\UI\FileManager\FSDrives.cpp # End Source File # Begin Source File @@ -605,6 +805,22 @@ SOURCE=..\..\UI\FileManager\UpdateCallback100.h # PROP Default_Filter "" # Begin Source File +SOURCE=..\..\Common\CreateCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CreateCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CWrappers.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CWrappers.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\FilePathAutoRename.cpp # End Source File # Begin Source File @@ -621,6 +837,14 @@ SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File +SOURCE=..\..\Common\InOutTempBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\InOutTempBuffer.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\MethodProps.cpp # End Source File # Begin Source File @@ -629,6 +853,14 @@ SOURCE=..\..\Common\MethodProps.h # End Source File # Begin Source File +SOURCE=..\..\Common\OutBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File @@ -641,6 +873,14 @@ SOURCE=..\..\Common\PropId.cpp # End Source File # Begin Source File +SOURCE=..\..\Common\StreamBinder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamBinder.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\StreamObjects.cpp # End Source File # Begin Source File @@ -663,6 +903,14 @@ SOURCE=..\..\Common\UniqBlocks.cpp SOURCE=..\..\Common\UniqBlocks.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\VirtThread.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\VirtThread.h +# End Source File # End Group # Begin Group "C" @@ -745,6 +993,42 @@ SOURCE=..\..\..\..\C\CpuArch.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\LzFind.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFind.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFindMt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFindMt.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaDec.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaEnc.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaEnc.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Sha256.c !IF "$(CFG)" == "FM - Win32 Release" @@ -1302,14 +1586,6 @@ SOURCE=..\..\UI\Common\CompressCall2.cpp # End Source File # Begin Source File -SOURCE=..\..\Common\CreateCoder.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Common\CreateCoder.h -# End Source File -# Begin Source File - SOURCE=..\..\UI\Common\DefaultName.cpp # End Source File # Begin Source File @@ -1618,6 +1894,14 @@ SOURCE=..\..\UI\GUI\UpdateCallbackGUI.h # End Source File # Begin Source File +SOURCE=..\..\UI\GUI\UpdateCallbackGUI2.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\GUI\UpdateCallbackGUI2.h +# End Source File +# Begin Source File + SOURCE=..\..\UI\GUI\UpdateGUI.cpp # End Source File # Begin Source File @@ -1637,37 +1921,49 @@ SOURCE=..\..\Compress\CopyCoder.cpp SOURCE=..\..\Compress\CopyCoder.h # End Source File -# End Group -# Begin Group "Interface" +# Begin Source File -# PROP Default_Filter "" +SOURCE=..\..\Compress\CopyRegister.cpp +# End Source File # Begin Source File -SOURCE=..\..\ICoder.h +SOURCE=..\..\Compress\LzmaDecoder.cpp # End Source File # Begin Source File -SOURCE=..\..\IDecl.h +SOURCE=..\..\Compress\LzmaDecoder.h # End Source File # Begin Source File -SOURCE=..\..\IPassword.h +SOURCE=..\..\Compress\LzmaEncoder.cpp # End Source File # Begin Source File -SOURCE=..\..\IProgress.h +SOURCE=..\..\Compress\LzmaEncoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzmaRegister.cpp # End Source File # End Group -# Begin Group "Crypto" +# Begin Group "Interface" # PROP Default_Filter "" # Begin Source File -SOURCE=..\..\Crypto\Sha1.cpp +SOURCE=..\..\ICoder.h # End Source File # Begin Source File -SOURCE=..\..\Crypto\Sha1.h +SOURCE=..\..\IDecl.h +# End Source File +# Begin Source File + +SOURCE=..\..\IPassword.h +# End Source File +# Begin Source File + +SOURCE=..\..\IProgress.h # End Source File # End Group # Begin Source File diff --git a/CPP/7zip/Bundles/Fm/makefile b/CPP/7zip/Bundles/Fm/makefile index fd211a1d..8ae5f4f6 100644 --- a/CPP/7zip/Bundles/Fm/makefile +++ b/CPP/7zip/Bundles/Fm/makefile @@ -2,7 +2,6 @@ PROG = 7zFM.exe CFLAGS = $(CFLAGS) \ -DLANG \ -DNEW_FOLDER_INTERFACE \ - -DEXTERNAL_CODECS \ !IFDEF UNDER_CE LIBS = $(LIBS) ceshell.lib Commctrl.lib @@ -86,6 +85,7 @@ GUI_OBJS = \ $O\ExtractGUI.obj \ $O\HashGUI.obj \ $O\UpdateCallbackGUI.obj \ + $O\UpdateCallbackGUI2.obj \ $O\UpdateGUI.obj \ diff --git a/CPP/7zip/Bundles/Format7z/makefile b/CPP/7zip/Bundles/Format7z/makefile index 01e63e67..992fc714 100644 --- a/CPP/7zip/Bundles/Format7z/makefile +++ b/CPP/7zip/Bundles/Format7z/makefile @@ -32,7 +32,6 @@ WIN_OBJS = \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ - $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ @@ -50,7 +49,6 @@ AR_OBJS = \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ - $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ @@ -84,7 +82,6 @@ COMPRESS_OBJS = \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BitlDecoder.obj \ - $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ @@ -116,6 +113,8 @@ CRYPTO_OBJS = \ C_OBJS = \ $O\Alloc.obj \ + $O\Bcj2.obj \ + $O\Bcj2Enc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ diff --git a/CPP/7zip/Bundles/Format7zExtract/makefile b/CPP/7zip/Bundles/Format7zExtract/makefile index 86a76e3d..93240c80 100644 --- a/CPP/7zip/Bundles/Format7zExtract/makefile +++ b/CPP/7zip/Bundles/Format7zExtract/makefile @@ -26,7 +26,6 @@ WIN_OBJS = \ $O\InBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ - $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ @@ -43,7 +42,6 @@ AR_OBJS = \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ - $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ @@ -68,7 +66,6 @@ COMPRESS_OBJS = \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BitlDecoder.obj \ - $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ @@ -96,6 +93,7 @@ CRYPTO_OBJS = \ C_OBJS = \ $O\Alloc.obj \ + $O\Bcj2.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ diff --git a/CPP/7zip/Bundles/Format7zExtractR/makefile b/CPP/7zip/Bundles/Format7zExtractR/makefile index 7241b37c..3d49c46f 100644 --- a/CPP/7zip/Bundles/Format7zExtractR/makefile +++ b/CPP/7zip/Bundles/Format7zExtractR/makefile @@ -26,7 +26,6 @@ WIN_OBJS = \ $O\InBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ - $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ @@ -43,7 +42,6 @@ AR_OBJS = \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ - $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\ItemNameUtils.obj \ @@ -69,7 +67,6 @@ COMPRESS_OBJS = \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ - $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ @@ -83,6 +80,7 @@ COMPRESS_OBJS = \ C_OBJS = \ $O\Alloc.obj \ + $O\Bcj2.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ diff --git a/CPP/7zip/Bundles/Format7zF/Arc.mak b/CPP/7zip/Bundles/Format7zF/Arc.mak index c26a6d67..c2f415cf 100644 --- a/CPP/7zip/Bundles/Format7zF/Arc.mak +++ b/CPP/7zip/Bundles/Format7zF/Arc.mak @@ -8,6 +8,7 @@ COMMON_OBJS = \ $O\MyVector.obj \ $O\MyXml.obj \ $O\NewHandler.obj \ + $O\Sha1Reg.obj \ $O\Sha256Reg.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ @@ -86,7 +87,6 @@ AR_OBJS = \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ - $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\DummyOutStream.obj \ $O\FindSignature.obj \ @@ -172,14 +172,11 @@ ZIP_OBJS = \ $O\ZipRegister.obj \ COMPRESS_OBJS = \ - $O\ArjDecoder1.obj \ - $O\ArjDecoder2.obj \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BitlDecoder.obj \ - $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ @@ -231,8 +228,6 @@ CRYPTO_OBJS = \ $O\RandGen.obj \ $O\Rar20Crypto.obj \ $O\RarAes.obj \ - $O\Sha1.obj \ - $O\Sha1Reg.obj \ $O\WzAes.obj \ $O\ZipCrypto.obj \ $O\ZipStrong.obj \ @@ -242,6 +237,8 @@ C_OBJS = \ $O\7zBuf2.obj \ $O\7zStream.obj \ $O\Alloc.obj \ + $O\Bcj2.obj \ + $O\Bcj2Enc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ @@ -262,6 +259,7 @@ C_OBJS = \ $O\Ppmd8.obj \ $O\Ppmd8Dec.obj \ $O\Ppmd8Enc.obj \ + $O\Sha1.obj \ $O\Sha256.obj \ $O\Sort.obj \ $O\Threads.obj \ diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp index 40f45455..82df284c 100644 --- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp +++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp @@ -43,7 +43,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /YX /FD /c -# ADD CPP /nologo /Gr /MT /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "NO_REGISTRY" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /FAs /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gr /MT /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "NO_REGISTRY" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "_7ZIP_ST_9" /FAcs /Yu"StdAfx.h" /FD /GF /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -70,7 +70,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /Gr /MTd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\..\SDK" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "NO_REGISTRY" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gr /MTd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\..\SDK" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "NO_REGISTRY" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "_7ZIP_ST_9" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -80,7 +80,8 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-Zip\7z.dll" /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-Zip\7z.dll" /pdbtype:sept /ignore:4033 +# SUBTRACT LINK32 /pdb:none !ENDIF @@ -334,6 +335,10 @@ SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\Sha1Reg.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\Sha256Reg.cpp # End Source File # Begin Source File @@ -376,58 +381,6 @@ SOURCE=..\..\..\Common\XzCrc64Reg.cpp # Begin Group "Compress" # PROP Default_Filter "" -# Begin Group "PPMD" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\..\Compress\PpmdDecoder.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\PpmdDecoder.h -# End Source File -# Begin Source File - -SOURCE=..\..\Compress\PpmdEncoder.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\PpmdEncoder.h -# End Source File -# Begin Source File - -SOURCE=..\..\Compress\PpmdRegister.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Compress\PpmdSubAlloc.h -# End Source File -# Begin Source File - -SOURCE=..\..\Compress\PpmdType.h -# End Source File -# End Group # Begin Group "Bit Coder" # PROP Default_Filter "" @@ -628,6 +581,16 @@ SOURCE=..\..\Compress\ZlibEncoder.h # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.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 @@ -651,14 +614,6 @@ SOURCE=..\..\Compress\BcjRegister.cpp # End Source File # Begin Source File -SOURCE=..\..\Compress\BranchCoder.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Compress\BranchCoder.h -# End Source File -# Begin Source File - SOURCE=..\..\Compress\BranchMisc.cpp # End Source File # Begin Source File @@ -687,6 +642,10 @@ SOURCE=..\..\Compress\CopyRegister.cpp # End Source File # Begin Source File +SOURCE=..\..\Compress\DeltaFilter.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Compress\Lzma2Decoder.cpp # End Source File # Begin Source File @@ -727,65 +686,77 @@ SOURCE=..\..\Compress\LzmaRegister.cpp # End Source File # Begin Source File -SOURCE=..\..\Compress\RangeCoder.h -# End Source File -# Begin Source File +SOURCE=..\..\Compress\PpmdDecoder.cpp -SOURCE=..\..\Compress\RangeCoderBit.h -# End Source File -# End Group -# Begin Group "Cab Compress" +!IF "$(CFG)" == "7z - Win32 Release" -# PROP Default_Filter "" -# Begin Source File +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF -SOURCE=..\..\Compress\Lzx.h # End Source File # Begin Source File -SOURCE=..\..\Compress\Lzx86Converter.cpp +SOURCE=..\..\Compress\PpmdDecoder.h # End Source File # Begin Source File -SOURCE=..\..\Compress\Lzx86Converter.h +SOURCE=..\..\Compress\PpmdEncoder.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\LzxDecoder.cpp +SOURCE=..\..\Compress\PpmdEncoder.h # End Source File # Begin Source File -SOURCE=..\..\Compress\LzxDecoder.h +SOURCE=..\..\Compress\PpmdRegister.cpp # End Source File +# End Group +# Begin Group "Cab Compress" + +# PROP Default_Filter "" # Begin Source File -SOURCE=..\..\Compress\QuantumDecoder.cpp +SOURCE=..\..\Compress\Lzx.h # End Source File # Begin Source File -SOURCE=..\..\Compress\QuantumDecoder.h +SOURCE=..\..\Compress\Lzx86Converter.cpp # End Source File -# End Group # Begin Source File -SOURCE=..\..\Compress\ArjDecoder1.cpp +SOURCE=..\..\Compress\Lzx86Converter.h # End Source File # Begin Source File -SOURCE=..\..\Compress\ArjDecoder1.h +SOURCE=..\..\Compress\LzxDecoder.cpp # End Source File # Begin Source File -SOURCE=..\..\Compress\ArjDecoder2.cpp +SOURCE=..\..\Compress\LzxDecoder.h # End Source File # Begin Source File -SOURCE=..\..\Compress\ArjDecoder2.h +SOURCE=..\..\Compress\QuantumDecoder.cpp # End Source File # Begin Source File -SOURCE=..\..\Compress\DeltaFilter.cpp +SOURCE=..\..\Compress\QuantumDecoder.h # End Source File +# End Group # Begin Source File SOURCE=..\..\Compress\HuffmanDecoder.h @@ -924,25 +895,7 @@ SOURCE=..\..\Crypto\RarAes.h # End Source File # Begin Source File -SOURCE=..\..\Crypto\Sha1.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=..\..\Crypto\Sha1.h -# End Source File -# Begin Source File - -SOURCE=..\..\Crypto\Sha1Reg.cpp +SOURCE=..\..\Crypto\Sha1Cls.h # End Source File # Begin Source File @@ -1042,14 +995,6 @@ SOURCE=..\..\Common\LimitedStreams.h # End Source File # Begin Source File -SOURCE=..\..\Common\LockedStream.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Common\LockedStream.h -# End Source File -# Begin Source File - SOURCE=..\..\Common\MemBlocks.cpp # End Source File # Begin Source File @@ -1338,6 +1283,42 @@ SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Bcj2.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\Bcj2.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bcj2Enc.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" @@ -1701,6 +1682,26 @@ SOURCE=..\..\..\..\C\RotateDefs.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Sha1.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\Sha1.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Sha256.c !IF "$(CFG)" == "7z - Win32 Release" @@ -1797,14 +1798,6 @@ SOURCE=..\..\Archive\7z\7zFolderInStream.h # End Source File # Begin Source File -SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\7z\7zFolderOutStream.h -# End Source File -# Begin Source File - SOURCE=..\..\Archive\7z\7zHandler.cpp # End Source File # Begin Source File @@ -1973,14 +1966,6 @@ SOURCE=..\..\Archive\Common\CoderMixer2.h # End Source File # Begin Source File -SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Common\CoderMixer2MT.h -# End Source File -# Begin Source File - SOURCE=..\..\Archive\Common\DummyOutStream.cpp # End Source File # Begin Source File @@ -2440,6 +2425,10 @@ SOURCE=..\..\Archive\XzHandler.cpp # End Source File # Begin Source File +SOURCE=..\..\Archive\XzHandler.h +# End Source File +# Begin Source File + SOURCE=..\..\Archive\ZHandler.cpp # End Source File # End Group diff --git a/CPP/7zip/Bundles/Format7zR/makefile b/CPP/7zip/Bundles/Format7zR/makefile index 555654bc..8d41ce89 100644 --- a/CPP/7zip/Bundles/Format7zR/makefile +++ b/CPP/7zip/Bundles/Format7zR/makefile @@ -30,7 +30,6 @@ WIN_OBJS = \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ - $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ @@ -48,7 +47,6 @@ AR_OBJS = \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ - $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ @@ -81,7 +79,6 @@ COMPRESS_OBJS = \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ - $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ @@ -97,6 +94,8 @@ COMPRESS_OBJS = \ C_OBJS = \ $O\Alloc.obj \ + $O\Bcj2.obj \ + $O\Bcj2Enc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp index d321e454..5b64b524 100644 --- a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp +++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp @@ -25,6 +25,7 @@ #include "../../../Windows/System.h" #endif +#include "../../../Common/IntToString.h" #include "../../../Common/CommandLineParser.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" @@ -36,14 +37,41 @@ #include "../../Compress/LzmaEncoder.h" #include "../../UI/Console/BenchCon.h" - +#include "../../UI/Console/ConsoleClose.h" using namespace NCommandLineParser; +static const unsigned kDictSizeLog = 24; + +static const char *kCopyrightString = "\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n\n"; + +static const char *kHelpString = + "Usage: LZMA <command> [inputFile] [outputFile] [<switches>...]\n" + "\n" + "<command>\n" + " e : Encode file\n" + " d : Decode file\n" + " b : Benchmark\n" + "<switches>\n" + " -a{N} : set compression mode : [0, 1] : default = 1 (max)\n" + " -d{N} : set dictionary size : [12, 30] : default = 24 (16 MiB)\n" + " -fb{N} : set number of fast bytes : [5, 273] : default = 128\n" + " -mc{N} : set number of cycles for match finder\n" + " -lc{N} : set number of literal context bits : [0, 8] : default = 3\n" + " -lp{N} : set number of literal pos bits : [0, 4] : default = 0\n" + " -pb{N} : set number of pos bits : [0, 4] : default = 2\n" + " -mf{M} : set match finder: [hc4, bt2, bt3, bt4] : default = bt4\n" + " -mt{N} : set number of CPU threads\n" + " -eos : write end of stream marker\n" + " -si : read data from stdin\n" + " -so : write data to stdout\n"; + + static const char *kCantAllocate = "Can not allocate memory"; static const char *kReadError = "Read error"; static const char *kWriteError = "Write error"; + namespace NKey { enum Enum { @@ -88,75 +116,195 @@ static const CSwitchForm kSwitchForms[] = { "F86", NSwitchType::kChar, false, 0, "+" } }; -static void PrintMessage(const char *s) + +static void PrintErr(const char *s) { fputs(s, stderr); } +static void PrintErr_LF(const char *s) +{ + PrintErr(s); + fputc('\n', stderr); +} + + +static void PrintError(const char *s) +{ + PrintErr("\nERROR: "); + PrintErr_LF(s); +} + +static void PrintError2(const char *s1, const wchar_t *s2) +{ + PrintError(s1); + PrintErr_LF(GetOemString(s2)); +} + +static void PrintError_int(const char *s, int code) +{ + PrintError(s); + char temp[32]; + ConvertInt64ToString(code, temp); + PrintErr("Error code = "); + PrintErr_LF(temp); +} + + + +static void Print(const char *s) +{ + fputs(s, stdout); +} + +static void Print_UInt64(UInt64 v) +{ + char temp[32]; + ConvertUInt64ToString(v, temp); + Print(temp); +} + +static void Print_MB(UInt64 v) +{ + Print_UInt64(v); + Print(" MiB"); +} + +static void Print_Size(const char *s, UInt64 v) +{ + Print(s); + Print_UInt64(v); + Print(" ("); + Print_MB(v >> 20); + Print(")\n"); +} + +static void PrintTitle() +{ + Print(kCopyrightString); +} + static void PrintHelp() { - PrintMessage("\nUsage: LZMA <e|d> inputFile outputFile [<switches>...]\n" - " e: encode file\n" - " d: decode file\n" - " b: Benchmark\n" - "<Switches>\n" - " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" - " -d{N}: set dictionary size - [12, 30], default: 23 (8MB)\n" - " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" - " -mc{N}: set number of cycles for match finder\n" - " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" - " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" - " -pb{N}: set number of pos bits - [0, 4], default: 2\n" - " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n" - " -mt{N}: set number of CPU threads\n" - " -eos: write End Of Stream marker\n" - " -si: read data from stdin\n" - " -so: write data to stdout\n" - ); + PrintTitle(); + Print(kHelpString); } -static void PrintHelpAndExit(const char *s) +class CProgressPrint: + public ICompressProgressInfo, + public CMyUnknownImp +{ + UInt64 _size1; + UInt64 _size2; +public: + CProgressPrint(): _size1(0), _size2(0) {} + + void ClosePrint(); + + MY_UNKNOWN_IMP1(ICompressProgressInfo) + + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + +#define BACK_STR \ +"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" +static const char *kBackSpaces = +BACK_STR +" " +BACK_STR; + + +void CProgressPrint::ClosePrint() { - fprintf(stderr, "\nError: %s\n\n", s); - PrintHelp(); - throw -1; + Print(kBackSpaces); } -static void IncorrectCommand() +STDMETHODIMP CProgressPrint::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { - PrintHelpAndExit("Incorrect command"); + if (NConsoleClose::TestBreakSignal()) + return E_ABORT; + if (inSize) + { + UInt64 v1 = *inSize >> 20; + UInt64 v2 = _size2; + if (outSize) + v2 = *outSize >> 20; + if (v1 != _size1 || v2 != _size2) + { + _size1 = v1; + _size2 = v2; + ClosePrint(); + Print_MB(_size1); + Print(" -> "); + Print_MB(_size2); + } + } + return S_OK; } -static void WriteArgumentsToStringList(int numArgs, const char *args[], UStringVector &strings) + +static void IncorrectCommand() { - for (int i = 1; i < numArgs; i++) - strings.Add(MultiByteToUnicodeString(args[i])); + throw "Incorrect command"; } -static bool GetNumber(const wchar_t *s, UInt32 &value) +static UInt32 GetNumber(const wchar_t *s) { - value = 0; - if (*s == 0) - return false; const wchar_t *end; - value = ConvertStringToUInt32(s, &end); - return *end == 0; + UInt32 v = ConvertStringToUInt32(s, &end); + if (*end != 0) + IncorrectCommand(); + return v; } static void ParseUInt32(const CParser &parser, unsigned index, UInt32 &res) { if (parser[index].ThereIs) - if (!GetNumber(parser[index].PostStrings[0], res)) - IncorrectCommand(); + res = GetNumber(parser[index].PostStrings[0]); } -#define NT_CHECK_FAIL_ACTION PrintMessage("Unsupported Windows version"); return 1; -int main2(int numArgs, const char *args[]) +static int Error_HRESULT(const char *s, HRESULT res) { - NT_CHECK + if (res == E_ABORT) + { + Print("\n\nBreak signaled\n"); + return 255; + } - PrintMessage("\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n"); + PrintError(s); + + if (res == E_OUTOFMEMORY) + { + PrintErr_LF(kCantAllocate); + return 8; + } + if (res == E_INVALIDARG) + { + PrintErr_LF("Ununsupported parameter"); + } + else + { + char temp[32]; + ConvertUInt32ToHex(res, temp); + PrintErr("Error code = 0x"); + PrintErr_LF(temp); + } + return 1; +} + +#define NT_CHECK_FAIL_ACTION PrintError("Unsupported Windows version"); return 1; + +static void AddProp(CObjectVector<CProperty> &props2, const char *name, const wchar_t *val) +{ + CProperty &prop = props2.AddNew(); + prop.Name.SetFromAscii(name); + prop.Value = val; +} + +static int main2(int numArgs, const char *args[]) +{ + NT_CHECK if (numArgs == 1) { @@ -164,20 +312,24 @@ int main2(int numArgs, const char *args[]) return 0; } - bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4); + /* + bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 8); if (unsupportedTypes) - { - PrintMessage("Unsupported base types. Edit Common/Types.h and recompile"); - return 1; - } + throw "Unsupported base types. Edit Common/Types.h and recompile"; + */ UStringVector commandStrings; - WriteArgumentsToStringList(numArgs, args, commandStrings); + for (int i = 1; i < numArgs; i++) + commandStrings.Add(MultiByteToUnicodeString(args[i])); CParser parser(ARRAY_SIZE(kSwitchForms)); try { - parser.ParseStrings(kSwitchForms, commandStrings); + if (!parser.ParseStrings(kSwitchForms, commandStrings)) + { + PrintError2(parser.ErrorMessage, parser.ErrorLine); + return 1; + } } catch(...) { @@ -189,40 +341,41 @@ int main2(int numArgs, const char *args[]) PrintHelp(); return 0; } - const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; + + bool stdInMode = parser[NKey::kStdIn].ThereIs; + bool stdOutMode = parser[NKey::kStdOut].ThereIs; + + if (!stdOutMode) + PrintTitle(); + + const UStringVector ¶ms = parser.NonSwitchStrings; unsigned paramIndex = 0; - if (paramIndex >= nonSwitchStrings.Size()) + if (paramIndex >= params.Size()) IncorrectCommand(); - const UString &command = nonSwitchStrings[paramIndex++]; + const UString &command = params[paramIndex++]; - CObjectVector<CProperty> props; + CObjectVector<CProperty> props2; bool dictDefined = false; UInt32 dict = (UInt32)(Int32)-1; + if (parser[NKey::kDict].ThereIs) { - UInt32 dicLog; + UInt32 dictLog; const UString &s = parser[NKey::kDict].PostStrings[0]; - if (!GetNumber(s, dicLog)) - IncorrectCommand(); - dict = 1 << dicLog; + dictLog = GetNumber(s); + dict = 1 << dictLog; dictDefined = true; - CProperty prop; - prop.Name = L"d"; - prop.Value = s; - props.Add(prop); + AddProp(props2, "d", s); } + if (parser[NKey::kLevel].ThereIs) { - UInt32 level = 5; const UString &s = parser[NKey::kLevel].PostStrings[0]; - if (!GetNumber(s, level)) - IncorrectCommand(); - CProperty prop; - prop.Name = L"x"; - prop.Value = s; - props.Add(prop); + /* UInt32 level = */ GetNumber(s); + AddProp(props2, "x", s); } + UString mf = L"BT4"; if (parser[NKey::kMatchFinder].ThereIs) mf = parser[NKey::kMatchFinder].PostStrings[0]; @@ -230,70 +383,64 @@ int main2(int numArgs, const char *args[]) UInt32 numThreads = (UInt32)(Int32)-1; #ifndef _7ZIP_ST + if (parser[NKey::kMultiThread].ThereIs) { - UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); const UString &s = parser[NKey::kMultiThread].PostStrings[0]; if (s.IsEmpty()) - numThreads = numCPUs; + numThreads = NWindows::NSystem::GetNumberOfProcessors(); else - if (!GetNumber(s, numThreads)) - IncorrectCommand(); - CProperty prop; - prop.Name = L"mt"; - prop.Value = s; - props.Add(prop); + numThreads = GetNumber(s); + AddProp(props2, "mt", s); } + #endif + if (parser[NKey::kMethod].ThereIs) { - UString s = parser[NKey::kMethod].PostStrings[0]; + const UString &s = parser[NKey::kMethod].PostStrings[0]; if (s.IsEmpty() || s[0] != '=') IncorrectCommand(); - CProperty prop; - prop.Name = L"m"; - prop.Value = s.Ptr(1); - props.Add(prop); + AddProp(props2, "m", s.Ptr(1)); } - if (MyStringCompareNoCase(command, L"b") == 0) + if (StringsAreEqualNoCase_Ascii(command, "b")) { - const UInt32 kNumDefaultItereations = 1; - UInt32 numIterations = kNumDefaultItereations; - { - if (paramIndex < nonSwitchStrings.Size()) - if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations)) - numIterations = kNumDefaultItereations; - } - HRESULT res = BenchCon(props, numIterations, stderr); - if (res != S_OK) - { - if (res != E_ABORT) - { - PrintMessage("Benchmark Error"); - return 1; - } - } - return 0; + UInt32 numIterations = 1; + if (paramIndex < params.Size()) + numIterations = GetNumber(params[paramIndex++]); + if (params.Size() != paramIndex) + IncorrectCommand(); + + HRESULT res = BenchCon(props2, numIterations, stdout); + + if (res == S_OK) + return 0; + return Error_HRESULT("Benchmark error", res); + } + + { + UInt32 needParams = 3; + if (stdInMode) needParams--; + if (stdOutMode) needParams--; + if (needParams != params.Size()) + IncorrectCommand(); } if (numThreads == (UInt32)(Int32)-1) numThreads = 1; bool encodeMode = false; - if (MyStringCompareNoCase(command, L"e") == 0) + + if (StringsAreEqualNoCase_Ascii(command, "e")) encodeMode = true; - else if (MyStringCompareNoCase(command, L"d") == 0) - encodeMode = false; - else + else if (!StringsAreEqualNoCase_Ascii(command, "d")) IncorrectCommand(); - bool stdInMode = parser[NKey::kStdIn].ThereIs; - bool stdOutMode = parser[NKey::kStdOut].ThereIs; - CMyComPtr<ISequentialInStream> inStream; - CInFileStream *inStreamSpec = 0; + CInFileStream *inStreamSpec = NULL; + if (stdInMode) { inStream = new CStdInFileStream; @@ -301,21 +448,19 @@ int main2(int numArgs, const char *args[]) } else { - if (paramIndex >= nonSwitchStrings.Size()) - IncorrectCommand(); - const UString &inputName = nonSwitchStrings[paramIndex++]; + const UString &inputName = params[paramIndex++]; inStreamSpec = new CInFileStream; inStream = inStreamSpec; if (!inStreamSpec->Open(us2fs(inputName))) { - fprintf(stderr, "\nError: can not open input file %s\n", - (const char *)GetOemString(inputName)); + PrintError2("can not open input file", inputName); return 1; } } CMyComPtr<ISequentialOutStream> outStream; COutFileStream *outStreamSpec = NULL; + if (stdOutMode) { outStream = new CStdOutFileStream; @@ -323,42 +468,70 @@ int main2(int numArgs, const char *args[]) } else { - if (paramIndex >= nonSwitchStrings.Size()) - IncorrectCommand(); - const UString &outputName = nonSwitchStrings[paramIndex++]; + const UString &outputName = params[paramIndex++]; outStreamSpec = new COutFileStream; outStream = outStreamSpec; if (!outStreamSpec->Create(us2fs(outputName), true)) { - fprintf(stderr, "\nError: can not open output file %s\n", - (const char *)GetOemString(outputName)); + PrintError2("can not open output file", outputName); return 1; } } + bool fileSizeDefined = false; + UInt64 fileSize = 0; + + if (inStreamSpec) + { + if (!inStreamSpec->File.GetLength(fileSize)) + throw "Can not get file length"; + fileSizeDefined = true; + if (!stdOutMode) + Print_Size("Input size: ", fileSize); + } + + if (encodeMode && !dictDefined) + { + dict = 1 << kDictSizeLog; + if (fileSizeDefined) + { + unsigned i; + for (i = 16; i < kDictSizeLog; i++) + if ((UInt32)((UInt32)1 << i) >= fileSize) + break; + dict = (UInt32)1 << i; + } + } + if (parser[NKey::kFilter86].ThereIs) { - // -f86 switch is for x86 filtered mode: BCJ + LZMA. + /* -f86 switch is for x86 filtered mode: BCJ + LZMA. + It uses modified header format. + It's not recommended to use -f86 mode now. + You can use xz format instead, if you want to use filters */ + if (parser[NKey::kEOS].ThereIs || stdInMode) throw "Can not use stdin in this mode"; - UInt64 fileSize; - inStreamSpec->File.GetLength(fileSize); + if (fileSize > 0xF0000000) throw "File is too big"; + size_t inSize = (size_t)fileSize; - Byte *inBuffer = 0; + Byte *inBuffer = NULL; + if (inSize != 0) { inBuffer = (Byte *)MyAlloc((size_t)inSize); - if (inBuffer == 0) + if (!inBuffer) throw kCantAllocate; } if (ReadStream_FAIL(inStream, inBuffer, inSize) != S_OK) throw "Can not read"; - Byte *outBuffer = 0; + Byte *outBuffer = NULL; size_t outSize; + if (encodeMode) { // we allocate 105% of original size for output buffer @@ -366,56 +539,70 @@ int main2(int numArgs, const char *args[]) if (outSize != 0) { outBuffer = (Byte *)MyAlloc((size_t)outSize); - if (outBuffer == 0) + if (!outBuffer) throw kCantAllocate; } - if (!dictDefined) - dict = 1 << 23; + int res = Lzma86_Encode(outBuffer, &outSize, inBuffer, inSize, 5, dict, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO); + if (res != 0) { - fprintf(stderr, "\nEncoder error = %d\n", (int)res); + PrintError_int("Encode error", (int)res); return 1; } } else { UInt64 outSize64; + if (Lzma86_GetUnpackSize(inBuffer, inSize, &outSize64) != 0) throw "data error"; + outSize = (size_t)outSize64; if (outSize != outSize64) throw "too big"; if (outSize != 0) { outBuffer = (Byte *)MyAlloc(outSize); - if (outBuffer == 0) + if (!outBuffer) throw kCantAllocate; } + int res = Lzma86_Decode(outBuffer, &outSize, inBuffer, &inSize); + if (inSize != (size_t)fileSize) throw "incorrect processed size"; if (res != 0) - throw "LzmaDecoder error"; + { + PrintError_int("Decode error", (int)res); + return 1; + } } + if (WriteStream(outStream, outBuffer, outSize) != S_OK) throw kWriteError; + MyFree(outBuffer); MyFree(inBuffer); - return 0; } + else + { + + CProgressPrint *progressSpec = NULL; + CMyComPtr<ICompressProgressInfo> progress; + if (!stdOutMode) + { + progressSpec = new CProgressPrint; + progress = progressSpec; + } - UInt64 fileSize; if (encodeMode) { NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder; CMyComPtr<ICompressCoder> encoder = encoderSpec; - if (!dictDefined) - dict = 1 << 23; - UInt32 pb = 2; UInt32 lc = 3; // = 0; for 32-bit data UInt32 lp = 0; // = 2; for 32-bit data @@ -434,8 +621,7 @@ int main2(int numArgs, const char *args[]) mcDefined = parser[NKey::kMc].ThereIs; if (mcDefined) - if (!GetNumber(parser[NKey::kMc].PostStrings[0], mc)) - IncorrectCommand(); + mc = GetNumber(parser[NKey::kMc].PostStrings[0]); const PROPID propIDs[] = { @@ -450,6 +636,7 @@ int main2(int numArgs, const char *args[]) NCoderPropID::kNumThreads, NCoderPropID::kMatchFinderCycles, }; + const unsigned kNumPropsMax = ARRAY_SIZE(propIDs); PROPVARIANT props[kNumPropsMax]; @@ -480,92 +667,106 @@ int main2(int numArgs, const char *args[]) if (!mcDefined) numProps--; - if (encoderSpec->SetCoderProperties(propIDs, props, numProps) != S_OK) - IncorrectCommand(); - encoderSpec->WriteCoderProperties(outStream); + HRESULT res = encoderSpec->SetCoderProperties(propIDs, props, numProps); + if (res != S_OK) + return Error_HRESULT("incorrect encoder properties", res); - if (eos || stdInMode) - fileSize = (UInt64)(Int64)-1; - else - inStreamSpec->File.GetLength(fileSize); + if (encoderSpec->WriteCoderProperties(outStream) != S_OK) + throw kWriteError; - for (int i = 0; i < 8; i++) - { - Byte b = Byte(fileSize >> (8 * i)); - if (outStream->Write(&b, 1, 0) != S_OK) - { - PrintMessage(kWriteError); - return 1; - } - } - HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); - if (result == E_OUTOFMEMORY) + bool fileSizeWasUsed = true; + if (eos || stdInMode) { - PrintMessage("\nError: Can not allocate memory\n"); - return 1; + fileSize = (UInt64)(Int64)-1; + fileSizeWasUsed = false; } - else if (result != S_OK) + { - fprintf(stderr, "\nEncoder error = %X\n", (unsigned)result); - return 1; + Byte temp[8]; + for (int i = 0; i < 8; i++) + temp[i]= (Byte)(fileSize >> (8 * i)); + if (WriteStream(outStream, temp, 8) != S_OK) + throw kWriteError; } + + res = encoder->Code(inStream, outStream, NULL, NULL, progress); + if (progressSpec) + progressSpec->ClosePrint(); + + if (res != S_OK) + return Error_HRESULT("Encoding error", res); + + UInt64 processedSize = encoderSpec->GetInputProcessedSize(); + + if (fileSizeWasUsed && processedSize != fileSize) + throw "Incorrect size of processed data"; } else { NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder; CMyComPtr<ICompressCoder> decoder = decoderSpec; + decoderSpec->FinishStream = true; - const UInt32 kPropertiesSize = 5; + + const unsigned kPropertiesSize = 5; Byte header[kPropertiesSize + 8]; + if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK) - { - PrintMessage(kReadError); - return 1; - } + throw kReadError; + if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK) - { - PrintMessage("SetDecoderProperties error"); - return 1; - } - fileSize = 0; + throw "SetDecoderProperties error"; + + UInt64 unpackSize = 0; for (int i = 0; i < 8; i++) - fileSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i); + unpackSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i); + + bool unpackSizeDefined = (unpackSize != (UInt64)(Int64)-1); + + HRESULT res = decoder->Code(inStream, outStream, NULL, unpackSizeDefined ? &unpackSize : NULL, progress); + if (progressSpec) + progressSpec->ClosePrint(); - bool isSizeDefined = (fileSize != (UInt64)(Int64)-1); - HRESULT res = decoder->Code(inStream, outStream, 0, isSizeDefined ? &fileSize : NULL, 0) != S_OK; if (res != S_OK) { - PrintMessage("Decoder error"); - return 1; - } - if (isSizeDefined && decoderSpec->GetOutputProcessedSize() != fileSize) - { - PrintMessage("Error: incorrect uncompressed size in header"); - return 1; + if (res == S_FALSE) + { + PrintError("Decoding error"); + return 1; + } + return Error_HRESULT("Decoding error", res); } + + if (unpackSizeDefined && unpackSize != decoderSpec->GetOutputProcessedSize()) + throw "incorrect uncompressed size in header"; + } } - if (outStreamSpec != NULL) + + if (!stdOutMode) + Print_Size("Output size: ", outStreamSpec->ProcessedSize); + + if (outStreamSpec) { if (outStreamSpec->Close() != S_OK) - { - PrintMessage("File closing error"); - return 1; - } + throw "File closing error"; } + return 0; } int MY_CDECL main(int numArgs, const char *args[]) { + NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter; + try { return main2(numArgs, args); } catch (const char *s) { - fprintf(stderr, "\nError: %s\n", s); + PrintError(s); return 1; } catch(...) { - PrintMessage("\nError\n"); + PrintError("Unknown Error"); return 1; } } diff --git a/CPP/7zip/Bundles/LzmaCon/resource.rc b/CPP/7zip/Bundles/LzmaCon/resource.rc index c68fdcc0..43b50738 100644 --- a/CPP/7zip/Bundles/LzmaCon/resource.rc +++ b/CPP/7zip/Bundles/LzmaCon/resource.rc @@ -1,3 +1,3 @@ -#include "../../../../C/7zVersion.rc" +#include "../../MyVersionInfo.rc" MY_VERSION_INFO_APP("LZMA", "lzma") diff --git a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp index 092fedcd..0cacd60c 100644 --- a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp +++ b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp @@ -117,14 +117,6 @@ SOURCE=..\..\Archive\Common\CoderMixer2.h # End Source File # Begin Source File -SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Common\CoderMixer2MT.h -# End Source File -# Begin Source File - SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp # End Source File # Begin Source File @@ -197,6 +189,14 @@ SOURCE=..\..\UI\Console\OpenCallbackConsole.h # End Source File # Begin Source File +SOURCE=..\..\UI\Console\PercentPrinter.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\PercentPrinter.h +# End Source File +# Begin Source File + SOURCE=..\..\UI\Console\UserInputUtils.cpp # End Source File # Begin Source File @@ -281,7 +281,15 @@ SOURCE=..\..\Compress\BcjRegister.cpp # End Source File # Begin Source File -SOURCE=..\..\Compress\BranchCoder.cpp +SOURCE=..\..\Compress\BranchMisc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchMisc.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchRegister.cpp # End Source File # Begin Source File @@ -293,6 +301,10 @@ SOURCE=..\..\Compress\CopyRegister.cpp # End Source File # Begin Source File +SOURCE=..\..\Compress\DeltaFilter.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Compress\Lzma2Decoder.cpp # End Source File # Begin Source File @@ -605,6 +617,14 @@ SOURCE=..\..\Common\PropId.cpp # End Source File # Begin Source File +SOURCE=..\..\Common\RegisterArc.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\RegisterCodec.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\StreamBinder.cpp # End Source File # Begin Source File @@ -758,6 +778,20 @@ SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Bcj2.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bcj2.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Bra.h # End Source File # Begin Source File @@ -767,11 +801,25 @@ SOURCE=..\..\..\..\C\Bra86.c # End Source File # Begin Source File +SOURCE=..\..\..\..\C\BraIA64.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\CpuArch.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Delta.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Delta.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Lzma2Dec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File diff --git a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp index c8837f9d..01089c5e 100644 --- a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp +++ b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp @@ -104,7 +104,7 @@ static const char *kHelpString = "\nUsage: 7zSFX [<command>] [<switches>...]\n" "\n" "<Commands>\n" - " l: List contents of archive\n" + // " l: List contents of archive\n" " t: Test integrity of archive\n" " x: eXtract files with full pathname (default)\n" "<Switches>\n" @@ -369,22 +369,22 @@ int Main2( { CExtractCallbackConsole *ecs = new CExtractCallbackConsole; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; - ecs->OutStream = g_StdStream; + ecs->Init(g_StdStream, &g_StdErr, g_StdStream); #ifndef _NO_CRYPTO ecs->PasswordIsDefined = passwordEnabled; ecs->Password = password; #endif - ecs->Init(); - + /* COpenCallbackConsole openCallback; - openCallback.OutStream = g_StdStream; + openCallback.Init(g_StdStream, g_StdStream); #ifndef _NO_CRYPTO openCallback.PasswordIsDefined = passwordEnabled; openCallback.Password = password; #endif + */ CExtractOptions eo; eo.StdOutMode = false; @@ -402,7 +402,7 @@ int Main2( codecs, CObjectVector<COpenType>(), CIntVector(), v1, v2, wildcardCensorHead, - eo, &openCallback, ecs, + eo, ecs, ecs, // NULL, // hash errorMessage, stat); if (!errorMessage.IsEmpty()) @@ -425,6 +425,9 @@ int Main2( } else { + throw CSystemException(E_NOTIMPL); + + /* UInt64 numErrors = 0; UInt64 numWarnings = 0; HRESULT result = ListArchives( @@ -447,6 +450,7 @@ int Main2( } if (result != S_OK) throw CSystemException(result); + */ } } return 0; diff --git a/CPP/7zip/Bundles/SFXCon/makefile b/CPP/7zip/Bundles/SFXCon/makefile index dd795b0b..d3d61372 100644 --- a/CPP/7zip/Bundles/SFXCon/makefile +++ b/CPP/7zip/Bundles/SFXCon/makefile @@ -14,6 +14,7 @@ CONSOLE_OBJS = \ $O\List.obj \ $O\MainAr.obj \ $O\OpenCallbackConsole.obj \ + $O\PercentPrinter.obj \ $O\UserInputUtils.obj \ COMMON_OBJS = \ @@ -48,7 +49,6 @@ WIN_OBJS = \ $O\InBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ - $O\LockedStream.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\PropId.obj \ @@ -72,7 +72,6 @@ AR_OBJS = \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ - $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\ItemNameUtils.obj \ $O\MultiStream.obj \ @@ -88,13 +87,15 @@ AR_COMMON_OBJS = \ $O\7zRegister.obj \ COMPRESS_OBJS = \ - $O\BranchCoder.obj \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ + $O\BranchMisc.obj \ + $O\BranchRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ + $O\DeltaFilter.obj \ $O\Lzma2Decoder.obj \ $O\Lzma2Register.obj \ $O\LzmaDecoder.obj \ @@ -109,8 +110,12 @@ CRYPTO_OBJS = \ C_OBJS = \ $O\Alloc.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ $O\Bra86.obj \ + $O\BraIA64.obj \ $O\CpuArch.obj \ + $O\Delta.obj \ $O\Lzma2Dec.obj \ $O\LzmaDec.obj \ $O\Ppmd7.obj \ diff --git a/CPP/7zip/Bundles/SFXCon/resource.rc b/CPP/7zip/Bundles/SFXCon/resource.rc index a83581c2..58331b81 100644 --- a/CPP/7zip/Bundles/SFXCon/resource.rc +++ b/CPP/7zip/Bundles/SFXCon/resource.rc @@ -1,4 +1,4 @@ -#include "../../../../C/7zVersion.rc" +#include "../../MyVersionInfo.rc" MY_VERSION_INFO_APP("7z Console SFX", "7z.sfx") diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp index 9fe98fc0..ac7df6b2 100644 --- a/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp +++ b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp @@ -58,6 +58,11 @@ HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, co #endif } +HRESULT CExtractCallbackImp::Open_Finished() +{ + return S_OK; +} + STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 size) { #ifndef _NO_PROGRESS @@ -83,7 +88,7 @@ void CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathPar { fullPath += us2fs(dirPathParts[i]); CreateDir(fullPath); - fullPath += FCHAR_PATH_SEPARATOR; + fullPath.Add_PathSepar(); } } @@ -95,18 +100,21 @@ STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index, return E_ABORT; #endif _outFileStream.Release(); - NCOM::CPropVariant propVariantName; - RINOK(_archiveHandler->GetProperty(index, kpidPath, &propVariantName)); + UString fullPath; - if (propVariantName.vt == VT_EMPTY) - fullPath = _itemDefaultName; - else { - if (propVariantName.vt != VT_BSTR) - return E_FAIL; - fullPath = propVariantName.bstrVal; + NCOM::CPropVariant prop; + RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop)); + if (prop.vt == VT_EMPTY) + fullPath = _itemDefaultName; + else + { + if (prop.vt != VT_BSTR) + return E_FAIL; + fullPath.SetFromBstr(prop.bstrVal); + } + _filePath = fullPath; } - _filePath = fullPath; if (askExtractMode == NArchive::NExtract::NAskMode::kExtract) { diff --git a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp index 3a8ae36b..1f076f7d 100644 --- a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp +++ b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp @@ -205,14 +205,6 @@ SOURCE=..\..\Archive\Common\CoderMixer2.h # End Source File # Begin Source File -SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Common\CoderMixer2MT.h -# End Source File -# Begin Source File - SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp # End Source File # Begin Source File @@ -257,7 +249,15 @@ SOURCE=..\..\Compress\BcjRegister.cpp # End Source File # Begin Source File -SOURCE=..\..\Compress\BranchCoder.cpp +SOURCE=..\..\Compress\BranchMisc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchMisc.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchRegister.cpp # End Source File # Begin Source File @@ -269,6 +269,10 @@ SOURCE=..\..\Compress\CopyRegister.cpp # End Source File # Begin Source File +SOURCE=..\..\Compress\DeltaFilter.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Compress\Lzma2Decoder.cpp # End Source File # Begin Source File @@ -513,14 +517,6 @@ SOURCE=..\..\Common\LimitedStreams.h # End Source File # Begin Source File -SOURCE=..\..\Common\LockedStream.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Common\LockedStream.h -# End Source File -# Begin Source File - SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File @@ -680,6 +676,20 @@ SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Bcj2.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bcj2.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Bra.h # End Source File # Begin Source File @@ -689,6 +699,11 @@ SOURCE=..\..\..\..\C\Bra86.c # End Source File # Begin Source File +SOURCE=..\..\..\..\C\BraIA64.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\CpuArch.c # SUBTRACT CPP /YX /Yc /Yu # End Source File @@ -698,6 +713,15 @@ SOURCE=..\..\..\..\C\CpuArch.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Delta.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Delta.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Lzma2Dec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File diff --git a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp index 20bde9e9..611ef651 100644 --- a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp +++ b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp @@ -94,12 +94,11 @@ static bool ReadDataString(CFSTR fileName, LPCSTR startID, } } -static char kStartID[] = ",!@Install@!UTF-8!"; -static char kEndID[] = ",!@InstallEnd@!"; +static char kStartID[] = { ',','!','@','I','n','s','t','a','l','l','@','!','U','T','F','-','8','!', 0 }; +static char kEndID[] = { ',','!','@','I','n','s','t','a','l','l','E','n','d','@','!', 0 }; -class CInstallIDInit +struct CInstallIDInit { -public: CInstallIDInit() { kStartID[0] = ';'; @@ -147,7 +146,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, switches.Trim(); bool assumeYes = false; - if (MyStringCompareNoCase_N(switches, L"-y", 2) == 0) + if (switches.IsPrefixedBy_Ascii_NoCase("-y")) { assumeYes = true; switches = switches.Ptr(2); @@ -177,7 +176,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, UString friendlyName = GetTextConfigValue(pairs, L"Title"); UString installPrompt = GetTextConfigValue(pairs, L"BeginPrompt"); UString progress = GetTextConfigValue(pairs, L"Progress"); - if (progress.IsEqualToNoCase(L"no")) + if (progress.IsEqualTo_Ascii_NoCase("no")) showProgress = false; int index = FindTextConfigItem(pairs, L"Directory"); if (index >= 0) @@ -265,8 +264,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, if (!switches.IsEmpty()) { - if (!executeParameters.IsEmpty()) - executeParameters += L' '; + executeParameters.Add_Space_if_NotEmpty(); executeParameters += switches; } @@ -315,7 +313,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, if (!switches.IsEmpty()) { - appLaunched += L' '; + appLaunched.Add_Space(); appLaunched += switches; } STARTUPINFO startupInfo; diff --git a/CPP/7zip/Bundles/SFXSetup/makefile b/CPP/7zip/Bundles/SFXSetup/makefile index ac5c6aa4..ae631988 100644 --- a/CPP/7zip/Bundles/SFXSetup/makefile +++ b/CPP/7zip/Bundles/SFXSetup/makefile @@ -44,7 +44,6 @@ WIN_CTRL_OBJS = \ $O\InBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ - $O\LockedStream.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\PropId.obj \ @@ -68,7 +67,6 @@ FM_OBJS = \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ - $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ @@ -82,13 +80,15 @@ AR_COMMON_OBJS = \ $O\7zRegister.obj \ COMPRESS_OBJS = \ - $O\BranchCoder.obj \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ + $O\BranchMisc.obj \ + $O\BranchRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ + $O\DeltaFilter.obj \ $O\Lzma2Decoder.obj \ $O\Lzma2Register.obj \ $O\LzmaDecoder.obj \ @@ -96,8 +96,12 @@ COMPRESS_OBJS = \ C_OBJS = \ $O\Alloc.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ $O\Bra86.obj \ + $O\BraIA64.obj \ $O\CpuArch.obj \ + $O\Delta.obj \ $O\Lzma2Dec.obj \ $O\LzmaDec.obj \ $O\Threads.obj \ diff --git a/CPP/7zip/Bundles/SFXSetup/resource.rc b/CPP/7zip/Bundles/SFXSetup/resource.rc index 8819a2c8..47e1b762 100644 --- a/CPP/7zip/Bundles/SFXSetup/resource.rc +++ b/CPP/7zip/Bundles/SFXSetup/resource.rc @@ -1,4 +1,4 @@ -#include "../../../../C/7zVersion.rc" +#include "../../MyVersionInfo.rc" #include "resource.h" MY_VERSION_INFO_APP("7z Setup SFX", "7zS.sfx") diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp index 55dbe377..3e11881b 100644 --- a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp +++ b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp @@ -197,14 +197,6 @@ SOURCE=..\..\Archive\Common\CoderMixer2.h # End Source File # Begin Source File -SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Archive\Common\CoderMixer2MT.h -# End Source File -# Begin Source File - SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp # End Source File # Begin Source File @@ -257,7 +249,15 @@ SOURCE=..\..\Compress\BcjRegister.cpp # End Source File # Begin Source File -SOURCE=..\..\Compress\BranchCoder.cpp +SOURCE=..\..\Compress\BranchMisc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchMisc.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchRegister.cpp # End Source File # Begin Source File @@ -269,6 +269,10 @@ SOURCE=..\..\Compress\CopyRegister.cpp # End Source File # Begin Source File +SOURCE=..\..\Compress\DeltaFilter.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Compress\Lzma2Decoder.cpp # End Source File # Begin Source File @@ -509,6 +513,14 @@ SOURCE=..\..\UI\FileManager\FormatUtils.h # End Source File # Begin Source File +SOURCE=..\..\UI\FileManager\PropertyName.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PropertyName.h +# End Source File +# Begin Source File + SOURCE=..\..\UI\FileManager\SysIconUtils.cpp # End Source File # Begin Source File @@ -858,6 +870,20 @@ SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Bcj2.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bcj2.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Bra.h # End Source File # Begin Source File @@ -867,11 +893,25 @@ SOURCE=..\..\..\..\C\Bra86.c # End Source File # Begin Source File +SOURCE=..\..\..\..\C\BraIA64.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\CpuArch.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Delta.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Delta.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Lzma2Dec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File diff --git a/CPP/7zip/Bundles/SFXWin/makefile b/CPP/7zip/Bundles/SFXWin/makefile index d6e1de78..7f2a78c1 100644 --- a/CPP/7zip/Bundles/SFXWin/makefile +++ b/CPP/7zip/Bundles/SFXWin/makefile @@ -56,7 +56,6 @@ WIN_CTRL_OBJS = \ $O\InBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ - $O\LockedStream.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\PropId.obj \ @@ -85,6 +84,7 @@ FM_OBJS = \ $O\OverwriteDialog.obj \ $O\PasswordDialog.obj \ $O\ProgressDialog2.obj \ + $O\PropertyName.obj \ $O\SysIconUtils.obj \ AR_OBJS = \ @@ -92,7 +92,6 @@ AR_OBJS = \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ - $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\ItemNameUtils.obj \ $O\MultiStream.obj \ @@ -107,13 +106,15 @@ AR_COMMON_OBJS = \ $O\7zRegister.obj \ COMPRESS_OBJS = \ - $O\BranchCoder.obj \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ + $O\BranchMisc.obj \ + $O\BranchRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ + $O\DeltaFilter.obj \ $O\Lzma2Decoder.obj \ $O\Lzma2Register.obj \ $O\LzmaDecoder.obj \ @@ -128,7 +129,11 @@ CRYPTO_OBJS = \ C_OBJS = \ $O\Alloc.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\Delta.obj \ $O\CpuArch.obj \ $O\Lzma2Dec.obj \ $O\LzmaDec.obj \ diff --git a/CPP/7zip/Bundles/SFXWin/resource.rc b/CPP/7zip/Bundles/SFXWin/resource.rc index ccde0cb2..91292b2f 100644 --- a/CPP/7zip/Bundles/SFXWin/resource.rc +++ b/CPP/7zip/Bundles/SFXWin/resource.rc @@ -1,4 +1,4 @@ -#include "../../../../C/7zVersion.rc" +#include "../../MyVersionInfo.rc" #include "../../GuiCommon.rc" #include "../../UI/GUI/ExtractDialogRes.h" #include "../../UI/FileManager/PropertyNameRes.h" diff --git a/CPP/7zip/Common/CreateCoder.cpp b/CPP/7zip/Common/CreateCoder.cpp index e5e09327..75074ad8 100644 --- a/CPP/7zip/Common/CreateCoder.cpp +++ b/CPP/7zip/Common/CreateCoder.cpp @@ -10,25 +10,40 @@ #include "FilterCoder.h" #include "RegisterCodec.h" -static const unsigned int kNumCodecsMax = 64; -unsigned int g_NumCodecs = 0; +static const unsigned kNumCodecsMax = 64; +unsigned g_NumCodecs = 0; const CCodecInfo *g_Codecs[kNumCodecsMax]; + +// We use g_ExternalCodecs in other stages. +/* +#ifdef EXTERNAL_CODECS +extern CExternalCodecs g_ExternalCodecs; +#define CHECK_GLOBAL_CODECS \ + if (!__externalCodecs || !__externalCodecs->IsSet()) __externalCodecs = &g_ExternalCodecs; +#endif +*/ + +#define CHECK_GLOBAL_CODECS + void RegisterCodec(const CCodecInfo *codecInfo) throw() { if (g_NumCodecs < kNumCodecsMax) g_Codecs[g_NumCodecs++] = codecInfo; } -static const unsigned int kNumHashersMax = 16; -unsigned int g_NumHashers = 0; +static const unsigned kNumHashersMax = 16; +unsigned g_NumHashers = 0; const CHasherInfo *g_Hashers[kNumHashersMax]; + void RegisterHasher(const CHasherInfo *hashInfo) throw() { if (g_NumHashers < kNumHashersMax) g_Hashers[g_NumHashers++] = hashInfo; } + #ifdef EXTERNAL_CODECS + static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res) { NWindows::NCOM::CPropVariant prop; @@ -55,102 +70,130 @@ static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, return S_OK; } -HRESULT CExternalCodecs::LoadCodecs() +HRESULT CExternalCodecs::Load() { + Codecs.Clear(); + Hashers.Clear(); + if (GetCodecs) { + CCodecInfoEx info; + + UString s; UInt32 num; - RINOK(GetCodecs->GetNumberOfMethods(&num)); + RINOK(GetCodecs->GetNumMethods(&num)); + for (UInt32 i = 0; i < num; i++) { - CCodecInfoEx info; NWindows::NCOM::CPropVariant prop; + RINOK(GetCodecs->GetProperty(i, NMethodPropID::kID, &prop)); - // if (prop.vt != VT_BSTR) - // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal); - // memcpy(info.Id.ID, prop.bstrVal, info.Id.IDSize); if (prop.vt != VT_UI8) continue; // old Interface info.Id = prop.uhVal.QuadPart; + prop.Clear(); + info.Name.Empty(); RINOK(GetCodecs->GetProperty(i, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) - info.Name = prop.bstrVal; + info.Name.SetFromWStr_if_Ascii(prop.bstrVal); else if (prop.vt != VT_EMPTY) - return E_INVALIDARG; + continue; - RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kInStreams, info.NumInStreams)); - RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kOutStreams, info.NumOutStreams)); + RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kPackStreams, info.NumStreams)); + { + UInt32 numUnpackStreams = 1; + RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kUnpackStreams, numUnpackStreams)); + if (numUnpackStreams != 1) + continue; + } RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned)); RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned)); Codecs.Add(info); } } + if (GetHashers) { UInt32 num = GetHashers->GetNumHashers(); + CHasherInfoEx info; + for (UInt32 i = 0; i < num; i++) { - CHasherInfoEx info; NWindows::NCOM::CPropVariant prop; + RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kID, &prop)); if (prop.vt != VT_UI8) continue; info.Id = prop.uhVal.QuadPart; + prop.Clear(); + info.Name.Empty(); RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) - info.Name = prop.bstrVal; + info.Name.SetFromWStr_if_Ascii(prop.bstrVal); else if (prop.vt != VT_EMPTY) - return E_INVALIDARG; + continue; Hashers.Add(info); } } + return S_OK; } #endif -bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS - const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams) + +bool FindMethod( + DECL_EXTERNAL_CODECS_LOC_VARS + const AString &name, + CMethodId &methodId, UInt32 &numStreams) { - UInt32 i; + unsigned i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; - if (name.IsEqualToNoCase(codec.Name)) + if (StringsAreEqualNoCase_Ascii(name, codec.Name)) { methodId = codec.Id; - numInStreams = codec.NumInStreams; - numOutStreams = 1; + numStreams = codec.NumStreams; return true; } } + #ifdef EXTERNAL_CODECS + + CHECK_GLOBAL_CODECS + if (__externalCodecs) - for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++) + for (i = 0; i < __externalCodecs->Codecs.Size(); i++) { const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; - if (codec.Name.IsEqualToNoCase(name)) + if (StringsAreEqualNoCase_Ascii(name, codec.Name)) { methodId = codec.Id; - numInStreams = codec.NumInStreams; - numOutStreams = codec.NumOutStreams; + numStreams = codec.NumStreams; return true; } } + #endif + return false; } -bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, UString &name) +bool FindMethod( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + AString &name) { - UInt32 i; + name.Empty(); + + unsigned i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; @@ -160,9 +203,13 @@ bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS return true; } } + #ifdef EXTERNAL_CODECS + + CHECK_GLOBAL_CODECS + if (__externalCodecs) - for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++) + for (i = 0; i < __externalCodecs->Codecs.Size(); i++) { const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; if (methodId == codec.Id) @@ -171,62 +218,79 @@ bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS return true; } } + #endif + return false; } -bool FindHashMethod(DECL_EXTERNAL_CODECS_LOC_VARS - const UString &name, - CMethodId &methodId) +bool FindHashMethod( + DECL_EXTERNAL_CODECS_LOC_VARS + const AString &name, + CMethodId &methodId) { - UInt32 i; + unsigned i; for (i = 0; i < g_NumHashers; i++) { const CHasherInfo &codec = *g_Hashers[i]; - if (name.IsEqualToNoCase(codec.Name)) + if (StringsAreEqualNoCase_Ascii(name, codec.Name)) { methodId = codec.Id; return true; } } + #ifdef EXTERNAL_CODECS + + CHECK_GLOBAL_CODECS + if (__externalCodecs) - for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++) + for (i = 0; i < __externalCodecs->Hashers.Size(); i++) { const CHasherInfoEx &codec = __externalCodecs->Hashers[i]; - if (codec.Name.IsEqualToNoCase(name)) + if (StringsAreEqualNoCase_Ascii(name, codec.Name)) { methodId = codec.Id; return true; } } + #endif + return false; } -void GetHashMethods(DECL_EXTERNAL_CODECS_LOC_VARS +void GetHashMethods( + DECL_EXTERNAL_CODECS_LOC_VARS CRecordVector<CMethodId> &methods) { methods.ClearAndSetSize(g_NumHashers); - UInt32 i; + unsigned i; for (i = 0; i < g_NumHashers; i++) methods[i] = (*g_Hashers[i]).Id; + #ifdef EXTERNAL_CODECS + + CHECK_GLOBAL_CODECS + if (__externalCodecs) - for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++) + for (i = 0; i < __externalCodecs->Hashers.Size(); i++) methods.Add(__externalCodecs->Hashers[i].Id); + #endif } HRESULT CreateCoder( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - CMyComPtr<ICompressFilter> &filter, - CMyComPtr<ICompressCoder> &coder, - CMyComPtr<ICompressCoder2> &coder2, - bool encode, bool onlyCoder) + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr<ICompressFilter> &filter, + CCreatedCoder &cod) { - UInt32 i; + cod.IsExternal = false; + cod.IsFilter = false; + cod.NumStreams = 1; + + unsigned i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; @@ -238,9 +302,9 @@ HRESULT CreateCoder( { void *p = codec.CreateEncoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; - else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; - else coder2 = (ICompressCoder2 *)p; - break; + else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p; + else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; } + return S_OK; } } else @@ -248,16 +312,21 @@ HRESULT CreateCoder( { void *p = codec.CreateDecoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; - else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; - else coder2 = (ICompressCoder2 *)p; - break; + else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p; + else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; } + return S_OK; } } } #ifdef EXTERNAL_CODECS - if (!filter && !coder && !coder2 && __externalCodecs) - for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++) + + CHECK_GLOBAL_CODECS + + if (__externalCodecs) + { + cod.IsExternal = true; + for (i = 0; i < __externalCodecs->Codecs.Size(); i++) { const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; if (codec.Id == methodId) @@ -266,125 +335,126 @@ HRESULT CreateCoder( { if (codec.EncoderIsAssigned) { - if (codec.IsSimpleCodec()) - { - HRESULT result = __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder); - if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) - return result; - if (!coder) - { - RINOK(__externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter)); - } - } - else + if (codec.NumStreams == 1) { - RINOK(__externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2)); + HRESULT res = __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder, (void **)&cod.Coder); + if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE) + return res; + if (cod.Coder) + return res; + return __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter); } - break; + cod.NumStreams = codec.NumStreams; + return __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2); } } else if (codec.DecoderIsAssigned) { - if (codec.IsSimpleCodec()) + if (codec.NumStreams == 1) { - HRESULT result = __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder); - if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) - return result; - if (!coder) - { - RINOK(__externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter)); - } + HRESULT res = __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder, (void **)&cod.Coder); + if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE) + return res; + if (cod.Coder) + return res; + return __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter); } - else - { - RINOK(__externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2)); - } - break; + cod.NumStreams = codec.NumStreams; + return __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2); } } } + } #endif - if (onlyCoder && filter) - { - CFilterCoder *coderSpec = new CFilterCoder; - coder = coderSpec; - coderSpec->Filter = filter; - } return S_OK; } HRESULT CreateCoder( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - CMyComPtr<ICompressCoder> &coder, - CMyComPtr<ICompressCoder2> &coder2, - bool encode) + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CCreatedCoder &cod) { CMyComPtr<ICompressFilter> filter; - return CreateCoder( - EXTERNAL_CODECS_LOC_VARS - methodId, - filter, coder, coder2, encode, true); + HRESULT res = CreateCoder( + EXTERNAL_CODECS_LOC_VARS + methodId, encode, + filter, cod); + + if (filter) + { + cod.IsFilter = true; + CFilterCoder *coderSpec = new CFilterCoder(encode); + cod.Coder = coderSpec; + coderSpec->Filter = filter; + } + + return res; } HRESULT CreateCoder( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - CMyComPtr<ICompressCoder> &coder, bool encode) + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr<ICompressCoder> &coder) { - CMyComPtr<ICompressFilter> filter; - CMyComPtr<ICompressCoder2> coder2; - return CreateCoder( - EXTERNAL_CODECS_LOC_VARS - methodId, - coder, coder2, encode); + CCreatedCoder cod; + HRESULT res = CreateCoder( + EXTERNAL_CODECS_LOC_VARS + methodId, encode, + cod); + coder = cod.Coder; + return res; } HRESULT CreateFilter( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - CMyComPtr<ICompressFilter> &filter, - bool encode) + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr<ICompressFilter> &filter) { - CMyComPtr<ICompressCoder> coder; - CMyComPtr<ICompressCoder2> coder2; + CCreatedCoder cod; return CreateCoder( - EXTERNAL_CODECS_LOC_VARS - methodId, - filter, coder, coder2, encode, false); + EXTERNAL_CODECS_LOC_VARS + methodId, encode, + filter, cod); } + HRESULT CreateHasher( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - UString &name, - CMyComPtr<IHasher> &hasher) + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + AString &name, + CMyComPtr<IHasher> &hasher) { - UInt32 i; + name.Empty(); + + unsigned i; for (i = 0; i < g_NumHashers; i++) { const CHasherInfo &codec = *g_Hashers[i]; if (codec.Id == methodId) { - hasher = (IHasher *)codec.CreateHasher(); + hasher = codec.CreateHasher(); name = codec.Name; break; } } #ifdef EXTERNAL_CODECS + + CHECK_GLOBAL_CODECS + if (!hasher && __externalCodecs) - for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++) + for (i = 0; i < __externalCodecs->Hashers.Size(); i++) { const CHasherInfoEx &codec = __externalCodecs->Hashers[i]; if (codec.Id == methodId) { name = codec.Name; - return __externalCodecs->GetHashers->CreateHasher(i, &hasher); + return __externalCodecs->GetHashers->CreateHasher((UInt32)i, &hasher); } } + #endif return S_OK; diff --git a/CPP/7zip/Common/CreateCoder.h b/CPP/7zip/Common/CreateCoder.h index 50a68ce1..f06064b6 100644 --- a/CPP/7zip/Common/CreateCoder.h +++ b/CPP/7zip/Common/CreateCoder.h @@ -5,29 +5,44 @@ #include "../../Common/MyCom.h" #include "../../Common/MyString.h" + #include "../ICoder.h" #include "MethodId.h" +/* + if EXTERNAL_CODECS is not defined, the code supports only codecs that + are statically linked at compile-time and link-time. + + if EXTERNAL_CODECS is defined, the code supports also codecs from another + executable modules, that can be linked dynamically at run-time: + - EXE module can use codecs from external DLL files. + - DLL module can use codecs from external EXE and DLL files. + + CExternalCodecs contains information about codecs and interfaces to create them. + + The order of codecs: + 1) Internal codecs + 2) External codecs +*/ + #ifdef EXTERNAL_CODECS struct CCodecInfoEx { - UString Name; CMethodId Id; - UInt32 NumInStreams; - UInt32 NumOutStreams; + AString Name; + UInt32 NumStreams; bool EncoderIsAssigned; bool DecoderIsAssigned; - bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; } CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {} }; struct CHasherInfoEx { - UString Name; CMethodId Id; + AString Name; }; #define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo, @@ -35,7 +50,7 @@ struct CHasherInfoEx #define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo); #define IMPL_ISetCompressCodecsInfo2(x) \ STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \ - COM_TRY_BEGIN __externalCodecs.GetCodecs = compressCodecsInfo; return __externalCodecs.LoadCodecs(); COM_TRY_END } + COM_TRY_BEGIN __externalCodecs.GetCodecs = compressCodecsInfo; return __externalCodecs.Load(); COM_TRY_END } #define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler) struct CExternalCodecs @@ -46,13 +61,36 @@ struct CExternalCodecs CObjectVector<CCodecInfoEx> Codecs; CObjectVector<CHasherInfoEx> Hashers; - HRESULT LoadCodecs(); + bool IsSet() const { return GetCodecs != NULL || GetHashers != NULL; } + + HRESULT Load(); + + void ClearAndRelease() + { + Hashers.Clear(); + Codecs.Clear(); + GetHashers.Release(); + GetCodecs.Release(); + } + + ~CExternalCodecs() + { + GetHashers.Release(); + GetCodecs.Release(); + } }; -#define EXTERNAL_CODECS_VARS2 &__externalCodecs +extern CExternalCodecs g_ExternalCodecs; + +#define EXTERNAL_CODECS_VARS2 (__externalCodecs.IsSet() ? &__externalCodecs : &g_ExternalCodecs) +#define EXTERNAL_CODECS_VARS2_L (&__externalCodecs) +#define EXTERNAL_CODECS_VARS2_G (&g_ExternalCodecs) #define DECL_EXTERNAL_CODECS_VARS CExternalCodecs __externalCodecs; -#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2, + +#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2, +#define EXTERNAL_CODECS_VARS_L EXTERNAL_CODECS_VARS2_L, +#define EXTERNAL_CODECS_VARS_G EXTERNAL_CODECS_VARS2_G, #define DECL_EXTERNAL_CODECS_LOC_VARS2 const CExternalCodecs *__externalCodecs #define EXTERNAL_CODECS_LOC_VARS2 __externalCodecs @@ -68,7 +106,9 @@ struct CExternalCodecs #define IMPL_ISetCompressCodecsInfo #define EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_VARS -#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2 +#define EXTERNAL_CODECS_VARS +#define EXTERNAL_CODECS_VARS_L +#define EXTERNAL_CODECS_VARS_G #define DECL_EXTERNAL_CODECS_LOC_VARS2 #define EXTERNAL_CODECS_LOC_VARS2 #define DECL_EXTERNAL_CODECS_LOC_VARS @@ -76,52 +116,67 @@ struct CExternalCodecs #endif + + + bool FindMethod( - DECL_EXTERNAL_CODECS_LOC_VARS - const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams); + DECL_EXTERNAL_CODECS_LOC_VARS + const AString &name, + CMethodId &methodId, UInt32 &numStreams); bool FindMethod( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, UString &name); + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + AString &name); bool FindHashMethod( - DECL_EXTERNAL_CODECS_LOC_VARS - const UString &name, CMethodId &methodId); + DECL_EXTERNAL_CODECS_LOC_VARS + const AString &name, + CMethodId &methodId); void GetHashMethods( - DECL_EXTERNAL_CODECS_LOC_VARS - CRecordVector<CMethodId> &methods); + DECL_EXTERNAL_CODECS_LOC_VARS + CRecordVector<CMethodId> &methods); + + +struct CCreatedCoder +{ + CMyComPtr<ICompressCoder> Coder; + CMyComPtr<ICompressCoder2> Coder2; + + bool IsExternal; + bool IsFilter; // = true, if Coder was created from filter + UInt32 NumStreams; + + // CCreatedCoder(): IsExternal(false), IsFilter(false), NumStreams(1) {} +}; + HRESULT CreateCoder( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - CMyComPtr<ICompressFilter> &filter, - CMyComPtr<ICompressCoder> &coder, - CMyComPtr<ICompressCoder2> &coder2, - bool encode, bool onlyCoder); + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr<ICompressFilter> &filter, + CCreatedCoder &cod); HRESULT CreateCoder( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - CMyComPtr<ICompressCoder> &coder, - CMyComPtr<ICompressCoder2> &coder2, - bool encode); + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CCreatedCoder &cod); HRESULT CreateCoder( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - CMyComPtr<ICompressCoder> &coder, bool encode); + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr<ICompressCoder> &coder); HRESULT CreateFilter( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - CMyComPtr<ICompressFilter> &filter, - bool encode); + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr<ICompressFilter> &filter); HRESULT CreateHasher( - DECL_EXTERNAL_CODECS_LOC_VARS - CMethodId methodId, - UString &name, - CMyComPtr<IHasher> &hacher); + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + AString &name, + CMyComPtr<IHasher> &hasher); #endif diff --git a/CPP/7zip/Common/FilePathAutoRename.cpp b/CPP/7zip/Common/FilePathAutoRename.cpp index 958360fa..d186e599 100644 --- a/CPP/7zip/Common/FilePathAutoRename.cpp +++ b/CPP/7zip/Common/FilePathAutoRename.cpp @@ -12,44 +12,40 @@ using namespace NWindows; static bool MakeAutoName(const FString &name, - const FString &extension, unsigned value, FString &path) + const FString &extension, UInt32 value, FString &path) { - FChar number[16]; - ConvertUInt32ToString(value, number); + char temp[16]; + ConvertUInt32ToString(value, temp); path = name; - path += number; + path.AddAscii(temp); path += extension; return NFile::NFind::DoesFileOrDirExist(path); } -bool AutoRenamePath(FString &fullProcessedPath) +bool AutoRenamePath(FString &path) { - FString path; - int dotPos = fullProcessedPath.ReverseFind(FTEXT('.')); + int dotPos = path.ReverseFind_Dot(); + int slashPos = path.ReverseFind_PathSepar(); - int slashPos = fullProcessedPath.ReverseFind(FTEXT('/')); - #ifdef _WIN32 - int slash1Pos = fullProcessedPath.ReverseFind(FTEXT('\\')); - slashPos = MyMax(slashPos, slash1Pos); - #endif - - FString name, extension; - if (dotPos > slashPos && dotPos > 0) + FString name = path; + FString extension; + if (dotPos > slashPos + 1) { - name.SetFrom(fullProcessedPath, dotPos); - extension = fullProcessedPath.Ptr(dotPos); + name.DeleteFrom(dotPos); + extension = path.Ptr(dotPos); } - else - name = fullProcessedPath; - name += L'_'; - unsigned left = 1, right = (1 << 30); + name += FTEXT('_'); + + FString temp; + + UInt32 left = 1, right = ((UInt32)1 << 30); while (left != right) { - unsigned mid = (left + right) / 2; - if (MakeAutoName(name, extension, mid, path)) + UInt32 mid = (left + right) / 2; + if (MakeAutoName(name, extension, mid, temp)) left = mid + 1; else right = mid; } - return !MakeAutoName(name, extension, right, fullProcessedPath); + return !MakeAutoName(name, extension, right, path); } diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp index 1523fad1..f3a322fc 100644 --- a/CPP/7zip/Common/FileStreams.cpp +++ b/CPP/7zip/Common/FileStreams.cpp @@ -29,25 +29,29 @@ static inline HRESULT ConvertBoolToHRESULT(bool result) #endif } -#ifdef SUPPORT_DEVICE_FILE static const UInt32 kClusterSize = 1 << 18; CInFileStream::CInFileStream(): + #ifdef SUPPORT_DEVICE_FILE VirtPos(0), PhyPos(0), Buf(0), BufSize(0), - SupportHardLinks(false) + #endif + SupportHardLinks(false), + Callback(NULL), + CallbackRef(0) { } -#endif - CInFileStream::~CInFileStream() { #ifdef SUPPORT_DEVICE_FILE MidFree(Buf); #endif + + if (Callback) + Callback->InFileStream_On_Destroy(CallbackRef); } STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) @@ -148,19 +152,37 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) bool result = File.ReadPart(data, size, realProcessedSize); if (processedSize) *processedSize = realProcessedSize; + #ifdef SUPPORT_DEVICE_FILE VirtPos += realProcessedSize; PhyPos += realProcessedSize; #endif - return ConvertBoolToHRESULT(result); - + + if (result) + return S_OK; + + { + DWORD error = ::GetLastError(); + + if (Callback) + return Callback->InFileStream_On_Error(CallbackRef, error); + if (error == 0) + return E_FAIL; + + return HRESULT_FROM_WIN32(error); + } + #else if (processedSize) *processedSize = 0; ssize_t res = File.Read(data, (size_t)size); if (res == -1) + { + if (Callback) + return Callback->InFileStream_On_Error(CallbackRef, E_FAIL); return E_FAIL; + } if (processedSize) *processedSize = (UInt32)res; return S_OK; @@ -321,7 +343,7 @@ STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *proces #ifdef USE_WIN_FILE UInt32 realProcessedSize; - bool result = File.WritePart(data, size, realProcessedSize); + bool result = File.Write(data, size, realProcessedSize); ProcessedSize += realProcessedSize; if (processedSize) *processedSize = realProcessedSize; @@ -346,6 +368,7 @@ STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo { if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION; + #ifdef USE_WIN_FILE UInt64 realNewPosition; @@ -369,6 +392,7 @@ STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo STDMETHODIMP COutFileStream::SetSize(UInt64 newSize) { #ifdef USE_WIN_FILE + UInt64 currentPos; if (!File.Seek(0, FILE_CURRENT, currentPos)) return E_FAIL; @@ -376,12 +400,21 @@ STDMETHODIMP COutFileStream::SetSize(UInt64 newSize) UInt64 currentPos2; result = result && File.Seek(currentPos, currentPos2); return result ? S_OK : E_FAIL; + #else + return E_FAIL; + #endif } +HRESULT COutFileStream::GetSize(UInt64 *size) +{ + return ConvertBoolToHRESULT(File.GetLength(*size)); +} + #ifdef UNDER_CE + STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { size_t s2 = fwrite(data, 1, size, stdout); @@ -389,13 +422,16 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro *processedSize = s2; return (s2 == size) ? S_OK : E_FAIL; } + #else + STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) *processedSize = 0; #ifdef _WIN32 + UInt32 realProcessedSize; BOOL res = TRUE; if (size > 0) @@ -407,6 +443,7 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro sizeTemp = size; res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), data, sizeTemp, (DWORD *)&realProcessedSize, NULL); + _size += realProcessedSize; size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); if (processedSize) @@ -417,18 +454,21 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro #else ssize_t res; + do { res = write(1, data, (size_t)size); } while (res < 0 && (errno == EINTR)); + if (res == -1) return E_FAIL; + + _size += (size_t)res; if (processedSize) *processedSize = (UInt32)res; return S_OK; - return S_OK; #endif } diff --git a/CPP/7zip/Common/FileStreams.h b/CPP/7zip/Common/FileStreams.h index 971366e9..ef2986fd 100644 --- a/CPP/7zip/Common/FileStreams.h +++ b/CPP/7zip/Common/FileStreams.h @@ -19,6 +19,18 @@ #include "../IStream.h" +#ifdef _WIN32 +typedef UINT_PTR My_UINT_PTR; +#else +typedef UINT My_UINT_PTR; +#endif + +struct IInFileStream_Callback +{ + virtual HRESULT InFileStream_On_Error(My_UINT_PTR val, DWORD error) = 0; + virtual void InFileStream_On_Destroy(My_UINT_PTR val) = 0; +}; + class CInFileStream: public IInStream, public IStreamGetSize, @@ -45,12 +57,13 @@ public: #endif bool SupportHardLinks; - + + IInFileStream_Callback *Callback; + My_UINT_PTR CallbackRef; + virtual ~CInFileStream(); - #ifdef SUPPORT_DEVICE_FILE CInFileStream(); - #endif bool Open(CFSTR fileName) { @@ -132,15 +145,20 @@ public: STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(UInt64 newSize); + + HRESULT GetSize(UInt64 *size); }; class CStdOutFileStream: public ISequentialOutStream, public CMyUnknownImp { + UInt64 _size; public: MY_UNKNOWN_IMP + UInt64 GetSize() const { return _size; } + CStdOutFileStream(): _size(0) {} virtual ~CStdOutFileStream() {} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; diff --git a/CPP/7zip/Common/FilterCoder.cpp b/CPP/7zip/Common/FilterCoder.cpp index 578a3193..4f3ae4e7 100644 --- a/CPP/7zip/Common/FilterCoder.cpp +++ b/CPP/7zip/Common/FilterCoder.cpp @@ -2,90 +2,144 @@ #include "StdAfx.h" -#include "../../../C/Alloc.h" - #include "../../Common/Defs.h" #include "FilterCoder.h" #include "StreamUtils.h" -static const UInt32 kBufferSize = 1 << 17; +/* + AES filters need 16-bytes alignment for HARDWARE-AES instructions. + So we call IFilter::Filter(, size), where (size != 16 * N) only for last data block. + + AES-CBC filters need data size aligned for 16-bytes. + So the encoder can add zeros to the end of original stream. + + Some filters (BCJ and others) don't process data at the end of stream in some cases. + So the encoder and decoder write such last bytes without change. +*/ + + +static const UInt32 kBufSize = 1 << 20; -CFilterCoder::CFilterCoder() +STDMETHODIMP CFilterCoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; } +STDMETHODIMP CFilterCoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; } + +HRESULT CFilterCoder::Alloc() { - _buffer = (Byte *)::MidAlloc(kBufferSize); - if (_buffer == 0) - throw 1; + UInt32 size = MyMin(_inBufSize, _outBufSize); + /* minimal bufSize is 16 bytes for AES and IA64 filter. + bufSize for AES must be aligned for 16 bytes. + We use (1 << 12) min size to support future aligned filters. */ + const UInt32 kMinSize = 1 << 12; + size &= ~(UInt32)(kMinSize - 1); + if (size < kMinSize) + size = kMinSize; + if (!_buf || _bufSize != size) + { + AllocAlignedMask(size, 16 - 1); + if (!_buf) + return E_OUTOFMEMORY; + _bufSize = size; + } + return S_OK; } -CFilterCoder::~CFilterCoder() +HRESULT CFilterCoder::Init_and_Alloc() { - ::MidFree(_buffer); + RINOK(Filter->Init()); + return Alloc(); } -HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size) +CFilterCoder::CFilterCoder(bool encodeMode): + _bufSize(0), + _inBufSize(kBufSize), + _outBufSize(kBufSize), + _encodeMode(encodeMode), + _outSizeIsDefined(false), + _outSize(0), + _nowPos64(0) + {} + +CFilterCoder::~CFilterCoder() { - if (_outSizeIsDefined) - { - UInt64 remSize = _outSize - _nowPos64; - if (size > remSize) - size = (UInt32)remSize; - } - RINOK(WriteStream(outStream, _buffer, size)); - _nowPos64 += size; - return S_OK; } STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { - RINOK(Init()); - UInt32 bufferPos = 0; - _outSizeIsDefined = (outSize != 0); - if (_outSizeIsDefined) - _outSize = *outSize; + RINOK(Init_and_Alloc()); + + UInt64 nowPos64 = 0; + bool inputFinished = false; + UInt32 pos = 0; - while (!_outSizeIsDefined || _nowPos64 < _outSize) + while (!outSize || nowPos64 < *outSize) { - size_t processedSize = kBufferSize - bufferPos; - - // Change it: It can be optimized using ReadPart - RINOK(ReadStream(inStream, _buffer + bufferPos, &processedSize)); + UInt32 endPos = pos; - UInt32 endPos = bufferPos + (UInt32)processedSize; - - bufferPos = Filter->Filter(_buffer, endPos); - if (bufferPos > endPos) + if (!inputFinished) { - for (; endPos < bufferPos; endPos++) - _buffer[endPos] = 0; - bufferPos = Filter->Filter(_buffer, endPos); + size_t processedSize = _bufSize - pos; + RINOK(ReadStream(inStream, _buf + pos, &processedSize)); + endPos = pos + (UInt32)processedSize; + inputFinished = (endPos != _bufSize); } - if (bufferPos == 0) + pos = Filter->Filter(_buf, endPos); + + if (pos > endPos) { - if (endPos == 0) - return S_OK; - return WriteWithLimit(outStream, endPos); + // AES + if (!inputFinished || pos > _bufSize) + return E_FAIL; + if (!_encodeMode) + return S_FALSE; + + do + _buf[endPos] = 0; + while (++endPos != pos); + + if (pos != Filter->Filter(_buf, pos)) + return E_FAIL; } - RINOK(WriteWithLimit(outStream, bufferPos)); - if (progress != NULL) + + if (endPos == 0) + return S_OK; + + UInt32 size = (pos != 0 ? pos : endPos); + if (outSize) { - RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64)); + UInt64 remSize = *outSize - nowPos64; + if (size > remSize) + size = (UInt32)remSize; } + + RINOK(WriteStream(outStream, _buf, size)); + nowPos64 += size; + + if (pos == 0) + return S_OK; + + if (progress) + RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64)); + UInt32 i = 0; - while (bufferPos < endPos) - _buffer[i++] = _buffer[bufferPos++]; - bufferPos = i; + while (pos < endPos) + _buf[i++] = _buf[pos++]; + pos = i; } + return S_OK; } + + +// ---------- Write to Filter ---------- + STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream) { - _bufferPos = 0; _outStream = outStream; - return Init(); + return S_OK; } STDMETHODIMP CFilterCoder::ReleaseOutStream() @@ -94,76 +148,154 @@ STDMETHODIMP CFilterCoder::ReleaseOutStream() return S_OK; } +HRESULT CFilterCoder::Flush2() +{ + while (_convSize != 0) + { + UInt32 num = _convSize; + if (_outSizeIsDefined) + { + UInt64 rem = _outSize - _nowPos64; + if (num > rem) + num = (UInt32)rem; + if (num == 0) + return k_My_HRESULT_WritingWasCut; + } + + UInt32 processed = 0; + HRESULT res = _outStream->Write(_buf + _convPos, num, &processed); + if (processed == 0) + return res != S_OK ? res : E_FAIL; + + _convPos += processed; + _convSize -= processed; + _nowPos64 += processed; + RINOK(res); + } + + if (_convPos != 0) + { + UInt32 num = _bufPos - _convPos; + for (UInt32 i = 0; i < num; i++) + _buf[i] = _buf[_convPos + i]; + _bufPos = num; + _convPos = 0; + } + + return S_OK; +} STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize) { - if (processedSize != NULL) + if (processedSize) *processedSize = 0; - while (size > 0) + + while (size != 0) { - UInt32 sizeTemp = MyMin(size, kBufferSize - _bufferPos); - memcpy(_buffer + _bufferPos, data, sizeTemp); - size -= sizeTemp; - if (processedSize != NULL) - *processedSize += sizeTemp; - data = (const Byte *)data + sizeTemp; - UInt32 endPos = _bufferPos + sizeTemp; - _bufferPos = Filter->Filter(_buffer, endPos); - if (_bufferPos == 0) + RINOK(Flush2()); + + // _convSize is 0 + // _convPos is 0 + // _bufPos is small + + if (_bufPos != _bufSize) { - _bufferPos = endPos; - break; + UInt32 num = MyMin(size, _bufSize - _bufPos); + memcpy(_buf + _bufPos, data, num); + size -= num; + data = (const Byte *)data + num; + if (processedSize) + *processedSize += num; + _bufPos += num; + if (_bufPos != _bufSize) + continue; } - if (_bufferPos > endPos) - { - if (size != 0) - return E_FAIL; + + // _bufPos == _bufSize + _convSize = Filter->Filter(_buf, _bufPos); + + if (_convSize == 0) break; + if (_convSize > _bufPos) + { + // that case is not possible. + _convSize = 0; + return E_FAIL; } - RINOK(WriteWithLimit(_outStream, _bufferPos)); - UInt32 i = 0; - while (_bufferPos < endPos) - _buffer[i++] = _buffer[_bufferPos++]; - _bufferPos = i; } + return S_OK; } -STDMETHODIMP CFilterCoder::Flush() +STDMETHODIMP CFilterCoder::OutStreamFinish() { - if (_bufferPos != 0) + for (;;) { - // _buffer contains only data refused by previous Filter->Filter call. - UInt32 endPos = Filter->Filter(_buffer, _bufferPos); - if (endPos > _bufferPos) + RINOK(Flush2()); + if (_bufPos == 0) + break; + _convSize = Filter->Filter(_buf, _bufPos); + if (_convSize == 0) + _convSize = _bufPos; + else if (_convSize > _bufPos) { - for (; _bufferPos < endPos; _bufferPos++) - _buffer[_bufferPos] = 0; - if (Filter->Filter(_buffer, endPos) != endPos) + // AES + if (_convSize > _bufSize) + { + _convSize = 0; + return E_FAIL; + } + if (!_encodeMode) + { + _convSize = 0; + return S_FALSE; + } + for (; _bufPos < _convSize; _bufPos++) + _buf[_bufPos] = 0; + _convSize = Filter->Filter(_buf, _bufPos); + if (_convSize != _bufPos) return E_FAIL; } - RINOK(WriteWithLimit(_outStream, _bufferPos)); - _bufferPos = 0; } - CMyComPtr<IOutStreamFlush> flush; - _outStream.QueryInterface(IID_IOutStreamFlush, &flush); - if (flush) - return flush->Flush(); + + CMyComPtr<IOutStreamFinish> finish; + _outStream.QueryInterface(IID_IOutStreamFinish, &finish); + if (finish) + return finish->OutStreamFinish(); return S_OK; } +// ---------- Init functions ---------- -void CFilterCoder::SetInStream_NoSubFilterInit(ISequentialInStream *inStream) +STDMETHODIMP CFilterCoder::InitEncoder() { - _convertedPosBegin = _convertedPosEnd = _bufferPos = 0; - _inStream = inStream; - Init2(); + InitSpecVars(); + return Init_and_Alloc(); +} + +HRESULT CFilterCoder::Init_NoSubFilterInit() +{ + InitSpecVars(); + return Alloc(); +} + +STDMETHODIMP CFilterCoder::SetOutStreamSize(const UInt64 *outSize) +{ + InitSpecVars(); + if (outSize) + { + _outSize = *outSize; + _outSizeIsDefined = true; + } + return Init_and_Alloc(); } +// ---------- Read from Filter ---------- + STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream) { - SetInStream_NoSubFilterInit(inStream); - return Init(); + _inStream = inStream; + return S_OK; } STDMETHODIMP CFilterCoder::ReleaseInStream() @@ -172,94 +304,115 @@ STDMETHODIMP CFilterCoder::ReleaseInStream() return S_OK; } + STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) { - if (processedSize != NULL) + if (processedSize) *processedSize = 0; - while (size > 0) + + while (size != 0) { - if (_convertedPosBegin != _convertedPosEnd) + if (_convSize != 0) { - UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin); - memcpy(data, _buffer + _convertedPosBegin, sizeTemp); - _convertedPosBegin += sizeTemp; - data = (void *)((Byte *)data + sizeTemp); - size -= sizeTemp; - if (processedSize != NULL) - *processedSize += sizeTemp; + if (size > _convSize) + size = _convSize; + if (_outSizeIsDefined) + { + UInt64 rem = _outSize - _nowPos64; + if (size > rem) + size = (UInt32)rem; + } + memcpy(data, _buf + _convPos, size); + _convPos += size; + _convSize -= size; + _nowPos64 += size; + if (processedSize) + *processedSize = size; break; } - UInt32 i; - for (i = 0; _convertedPosEnd + i < _bufferPos; i++) - _buffer[i] = _buffer[_convertedPosEnd + i]; - _bufferPos = i; - _convertedPosBegin = _convertedPosEnd = 0; - size_t processedSizeTemp = kBufferSize - _bufferPos; - RINOK(ReadStream(_inStream, _buffer + _bufferPos, &processedSizeTemp)); - _bufferPos += (UInt32)processedSizeTemp; - _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); - if (_convertedPosEnd == 0) + + if (_convPos != 0) + { + UInt32 num = _bufPos - _convPos; + for (UInt32 i = 0; i < num; i++) + _buf[i] = _buf[_convPos + i]; + _bufPos = num; + _convPos = 0; + } + + { + size_t readSize = _bufSize - _bufPos; + HRESULT res = ReadStream(_inStream, _buf + _bufPos, &readSize); + _bufPos += (UInt32)readSize; + RINOK(res); + } + + _convSize = Filter->Filter(_buf, _bufPos); + + if (_convSize == 0) { - if (_bufferPos == 0) + if (_bufPos == 0) break; - _convertedPosEnd = _bufferPos; // check it + // BCJ + _convSize = _bufPos; continue; } - if (_convertedPosEnd > _bufferPos) + + if (_convSize > _bufPos) { - for (; _bufferPos < _convertedPosEnd; _bufferPos++) - _buffer[_bufferPos] = 0; - _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); + // AES + if (_convSize > _bufSize) + return E_FAIL; + if (!_encodeMode) + return S_FALSE; + + do + _buf[_bufPos] = 0; + while (++_bufPos != _convSize); + + _convSize = Filter->Filter(_buf, _convSize); + if (_convSize != _bufPos) + return E_FAIL; } } + return S_OK; } + #ifndef _NO_CRYPTO STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size) -{ - return _setPassword->CryptoSetPassword(data, size); -} + { return _SetPassword->CryptoSetPassword(data, size); } STDMETHODIMP CFilterCoder::SetKey(const Byte *data, UInt32 size) -{ - return _cryptoProperties->SetKey(data, size); -} + { return _CryptoProperties->SetKey(data, size); } STDMETHODIMP CFilterCoder::SetInitVector(const Byte *data, UInt32 size) -{ - return _cryptoProperties->SetInitVector(data, size); -} + { return _CryptoProperties->SetInitVector(data, size); } #endif + #ifndef EXTRACT_ONLY + STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs, - const PROPVARIANT *properties, UInt32 numProperties) -{ - return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); -} + const PROPVARIANT *properties, UInt32 numProperties) + { return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); } STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream) -{ - return _writeCoderProperties->WriteCoderProperties(outStream); -} + { return _WriteCoderProperties->WriteCoderProperties(outStream); } /* STDMETHODIMP CFilterCoder::ResetSalt() -{ - return _CryptoResetSalt->ResetSalt(); -} + { return _CryptoResetSalt->ResetSalt(); } */ STDMETHODIMP CFilterCoder::ResetInitVector() -{ - return _CryptoResetInitVector->ResetInitVector(); -} + { return _CryptoResetInitVector->ResetInitVector(); } + #endif + STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size) -{ - return _setDecoderProperties->SetDecoderProperties2(data, size); -} + { return _SetDecoderProperties2->SetDecoderProperties2(data, size); } diff --git a/CPP/7zip/Common/FilterCoder.h b/CPP/7zip/Common/FilterCoder.h index 2b8f142f..cde33c88 100644 --- a/CPP/7zip/Common/FilterCoder.h +++ b/CPP/7zip/Common/FilterCoder.h @@ -3,106 +3,204 @@ #ifndef __FILTER_CODER_H #define __FILTER_CODER_H +#include "../../../C/Alloc.h" + #include "../../Common/MyCom.h" #include "../ICoder.h" + +#ifndef _NO_CRYPTO #include "../IPassword.h" +#endif #define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) else if (iid == IID_ ## i) \ { if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \ *outObject = (void *)(i *)this; } + +struct CAlignedMidBuffer +{ + #ifndef _WIN32 + + Byte *_buf; + + CAlignedMidBuffer(): _buf(NULL) {} + ~CAlignedMidBuffer() { ::MidFree(_buf); } + + void AllocAlignedMask(size_t size, size_t) + { + ::MidFree(_buf); + _buf = (Byte *)::MidAlloc(size); + } + + #else + + Byte *_bufBase; + Byte *_buf; + + CAlignedMidBuffer(): _bufBase(NULL), _buf(NULL) {} + ~CAlignedMidBuffer() { ::MidFree(_bufBase); } + + void AllocAlignedMask(size_t size, size_t alignMask) + { + ::MidFree(_bufBase); + _buf = NULL; + _bufBase = (Byte *)::MidAlloc(size + alignMask); + + if (_bufBase) + { + // _buf = (Byte *)(((uintptr_t)_bufBase + alignMask) & ~(uintptr_t)alignMask); + _buf = (Byte *)(((ptrdiff_t)_bufBase + alignMask) & ~(ptrdiff_t)alignMask); + } + } + + #endif +}; + class CFilterCoder: public ICompressCoder, + + public ICompressSetOutStreamSize, + public ICompressInitEncoder, + public ICompressSetInStream, public ISequentialInStream, + public ICompressSetOutStream, public ISequentialOutStream, - public IOutStreamFlush, + public IOutStreamFinish, + + public ICompressSetBufSize, #ifndef _NO_CRYPTO public ICryptoSetPassword, public ICryptoProperties, #endif + #ifndef EXTRACT_ONLY public ICompressSetCoderProperties, public ICompressWriteCoderProperties, // public ICryptoResetSalt, public ICryptoResetInitVector, #endif + public ICompressSetDecoderProperties2, - public CMyUnknownImp + public CMyUnknownImp, + public CAlignedMidBuffer { -protected: - Byte *_buffer; - CMyComPtr<ISequentialInStream> _inStream; - CMyComPtr<ISequentialOutStream> _outStream; - UInt32 _bufferPos; - UInt32 _convertedPosBegin; - UInt32 _convertedPosEnd; + UInt32 _bufSize; + UInt32 _inBufSize; + UInt32 _outBufSize; + + bool _encodeMode; bool _outSizeIsDefined; UInt64 _outSize; UInt64 _nowPos64; - void Init2() + CMyComPtr<ISequentialInStream> _inStream; + CMyComPtr<ISequentialOutStream> _outStream; + UInt32 _bufPos; + UInt32 _convPos; // current pos in buffer for converted data + UInt32 _convSize; // size of converted data starting from _convPos + + void InitSpecVars() { - _nowPos64 = 0; + _bufPos = 0; + _convPos = 0; + _convSize = 0; + _outSizeIsDefined = false; + _outSize = 0; + _nowPos64 = 0; } - HRESULT Init() - { - Init2(); - return Filter->Init(); - } + HRESULT Alloc(); + HRESULT Init_and_Alloc(); + HRESULT Flush2(); + + #ifndef _NO_CRYPTO + CMyComPtr<ICryptoSetPassword> _SetPassword; + CMyComPtr<ICryptoProperties> _CryptoProperties; + #endif - CMyComPtr<ICryptoSetPassword> _setPassword; - CMyComPtr<ICryptoProperties> _cryptoProperties; #ifndef EXTRACT_ONLY CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties; - CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties; + CMyComPtr<ICompressWriteCoderProperties> _WriteCoderProperties; // CMyComPtr<ICryptoResetSalt> _CryptoResetSalt; CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector; #endif - CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties; + + CMyComPtr<ICompressSetDecoderProperties2> _SetDecoderProperties2; + public: CMyComPtr<ICompressFilter> Filter; - CFilterCoder(); + CFilterCoder(bool encodeMode); ~CFilterCoder(); - HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size); -public: + class C_InStream_Releaser + { + public: + CFilterCoder *FilterCoder; + C_InStream_Releaser(): FilterCoder(NULL) {} + ~C_InStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); } + }; + + class C_OutStream_Releaser + { + public: + CFilterCoder *FilterCoder; + C_OutStream_Releaser(): FilterCoder(NULL) {} + ~C_OutStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); } + }; + MY_QUERYINTERFACE_BEGIN2(ICompressCoder) + + MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize) + MY_QUERYINTERFACE_ENTRY(ICompressInitEncoder) + MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) MY_QUERYINTERFACE_ENTRY(ISequentialInStream) + MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream) MY_QUERYINTERFACE_ENTRY(ISequentialOutStream) - MY_QUERYINTERFACE_ENTRY(IOutStreamFlush) + MY_QUERYINTERFACE_ENTRY(IOutStreamFinish) + + MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize) #ifndef _NO_CRYPTO - MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword) - MY_QUERYINTERFACE_ENTRY_AG(ICryptoProperties, Filter, _cryptoProperties) + MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _SetPassword) + MY_QUERYINTERFACE_ENTRY_AG(ICryptoProperties, Filter, _CryptoProperties) #endif #ifndef EXTRACT_ONLY MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties) - MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties) + MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _WriteCoderProperties) // MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt) MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector) #endif - MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties) + MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _SetDecoderProperties2) MY_QUERYINTERFACE_END MY_ADDREF_RELEASE + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); - STDMETHOD(ReleaseInStream)(); + + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + STDMETHOD(InitEncoder)(); + STDMETHOD(SetInStream)(ISequentialInStream *inStream); - STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \ + STDMETHOD(ReleaseInStream)(); + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(Flush)(); + STDMETHOD(OutStreamFinish)(); + + STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size); + STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size); #ifndef _NO_CRYPTO STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); @@ -110,6 +208,7 @@ public: STDMETHOD(SetKey)(const Byte *data, UInt32 size); STDMETHOD(SetInitVector)(const Byte *data, UInt32 size); #endif + #ifndef EXTRACT_ONLY STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties); @@ -117,26 +216,11 @@ public: // STDMETHOD(ResetSalt)(); STDMETHOD(ResetInitVector)(); #endif + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); - void SetInStream_NoSubFilterInit(ISequentialInStream *inStream); - -}; - -class CInStreamReleaser -{ -public: - CFilterCoder *FilterCoder; - CInStreamReleaser(): FilterCoder(0) {} - ~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); } -}; - -class COutStreamReleaser -{ -public: - CFilterCoder *FilterCoder; - COutStreamReleaser(): FilterCoder(0) {} - ~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); } + + HRESULT Init_NoSubFilterInit(); }; #endif diff --git a/CPP/7zip/Common/InOutTempBuffer.cpp b/CPP/7zip/Common/InOutTempBuffer.cpp index be65ba32..85d6a1aa 100644 --- a/CPP/7zip/Common/InOutTempBuffer.cpp +++ b/CPP/7zip/Common/InOutTempBuffer.cpp @@ -13,7 +13,7 @@ using namespace NWindows; using namespace NFile; using namespace NDir; -static const UInt32 kTempBufSize = (1 << 20); +static const size_t kTempBufSize = (1 << 20); static CFSTR kTempFilePrefixString = FTEXT("7zt"); @@ -58,15 +58,19 @@ bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size) bool CInOutTempBuffer::Write(const void *data, UInt32 size) { - if (_bufPos < kTempBufSize) + if (size == 0) + return true; + size_t cur = kTempBufSize - _bufPos; + if (cur != 0) { - UInt32 cur = MyMin(kTempBufSize - _bufPos, size); + if (cur > size) + cur = size; memcpy(_buf + _bufPos, data, cur); _crc = CrcUpdate(_crc, data, cur); _bufPos += cur; - size -= cur; - data = ((const Byte *)data) + cur; _size += cur; + size -= (UInt32)cur; + data = ((const Byte *)data) + cur; } return WriteToFile(data, size); } @@ -79,12 +83,13 @@ HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) UInt64 size = 0; UInt32 crc = CRC_INIT_VAL; - if (_bufPos > 0) + if (_bufPos != 0) { RINOK(WriteStream(stream, _buf, _bufPos)); crc = CrcUpdate(crc, _buf, _bufPos); size += _bufPos; } + if (_tempFileCreated) { NIO::CInFile inFile; @@ -102,18 +107,21 @@ HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) size += processed; } } + return (_crc == crc && size == _size) ? S_OK : E_FAIL; } +/* STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processed) { if (!_buf->Write(data, size)) { - if (processed != NULL) + if (processed) *processed = 0; return E_FAIL; } - if (processed != NULL) + if (processed) *processed = size; return S_OK; } +*/ diff --git a/CPP/7zip/Common/InOutTempBuffer.h b/CPP/7zip/Common/InOutTempBuffer.h index 256d7242..204a105f 100644 --- a/CPP/7zip/Common/InOutTempBuffer.h +++ b/CPP/7zip/Common/InOutTempBuffer.h @@ -13,10 +13,10 @@ class CInOutTempBuffer NWindows::NFile::NDir::CTempFile _tempFile; NWindows::NFile::NIO::COutFile _outFile; Byte *_buf; - UInt32 _bufPos; - bool _tempFileCreated; + size_t _bufPos; UInt64 _size; UInt32 _crc; + bool _tempFileCreated; bool WriteToFile(const void *data, UInt32 size); public: @@ -31,6 +31,7 @@ public: UInt64 GetDataSize() const { return _size; } }; +/* class CSequentialOutTempBufferImp: public ISequentialOutStream, public CMyUnknownImp @@ -42,5 +43,6 @@ public: STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; +*/ #endif diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp index de236040..2ea718e7 100644 --- a/CPP/7zip/Common/LimitedStreams.cpp +++ b/CPP/7zip/Common/LimitedStreams.cpp @@ -279,7 +279,10 @@ STDMETHODIMP CLimitedCachedInStream::Read(void *data, UInt32 size, UInt32 *proce if (newPos >= _cachePhyPos && offsetInCache <= _cacheSize && size <= _cacheSize - (size_t)offsetInCache) - memcpy(data, _cache + (size_t)offsetInCache, size); + { + if (size != 0) + memcpy(data, _cache + (size_t)offsetInCache, size); + } else { if (newPos != _physPos) diff --git a/CPP/7zip/Common/LockedStream.cpp b/CPP/7zip/Common/LockedStream.cpp index f05601cb..ca39fb45 100644 --- a/CPP/7zip/Common/LockedStream.cpp +++ b/CPP/7zip/Common/LockedStream.cpp @@ -1,23 +1,3 @@ // LockedStream.cpp #include "StdAfx.h" - -#include "LockedStream.h" - -HRESULT CLockedInStream::Read(UInt64 startPos, void *data, UInt32 size, - UInt32 *processedSize) -{ - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); - RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL)); - return _stream->Read(data, size, processedSize); -} - -STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) -{ - UInt32 realProcessedSize = 0; - HRESULT result = _lockedInStream->Read(_pos, data, size, &realProcessedSize); - _pos += realProcessedSize; - if (processedSize != NULL) - *processedSize = realProcessedSize; - return result; -} diff --git a/CPP/7zip/Common/LockedStream.h b/CPP/7zip/Common/LockedStream.h index 486e4220..efebf197 100644 --- a/CPP/7zip/Common/LockedStream.h +++ b/CPP/7zip/Common/LockedStream.h @@ -1,38 +1,6 @@ // LockedStream.h -#ifndef __LOCKEDSTREAM_H -#define __LOCKEDSTREAM_H - -#include "../../Windows/Synchronization.h" -#include "../../Common/MyCom.h" -#include "../IStream.h" - -class CLockedInStream -{ - CMyComPtr<IInStream> _stream; - NWindows::NSynchronization::CCriticalSection _criticalSection; -public: - void Init(IInStream *stream) - { _stream = stream; } - HRESULT Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize); -}; - -class CLockedSequentialInStreamImp: - public ISequentialInStream, - public CMyUnknownImp -{ - CLockedInStream *_lockedInStream; - UInt64 _pos; -public: - void Init(CLockedInStream *lockedInStream, UInt64 startPos) - { - _lockedInStream = lockedInStream; - _pos = startPos; - } - - MY_UNKNOWN_IMP - - STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); -}; +#ifndef __LOCKED_STREAM_H +#define __LOCKED_STREAM_H #endif diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp index f1c34ada..7c1e9979 100644 --- a/CPP/7zip/Common/MethodProps.cpp +++ b/CPP/7zip/Common/MethodProps.cpp @@ -10,12 +10,12 @@ using namespace NWindows; bool StringToBool(const UString &s, bool &res) { - if (s.IsEmpty() || s == L"+" || StringsAreEqualNoCase_Ascii(s, "ON")) + if (s.IsEmpty() || (s[0] == '+' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "ON")) { res = true; return true; } - if (s == L"-" || StringsAreEqualNoCase_Ascii(s, "OFF")) + if ((s[0] == '-' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "OFF")) { res = false; return true; @@ -137,11 +137,10 @@ static HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, UInt32 &resValue void CProps::AddProp32(PROPID propid, UInt32 level) { - CProp prop; + CProp &prop = Props.AddNew(); prop.IsOptional = true; prop.Id = propid; prop.Value = (UInt32)level; - Props.Add(prop); } class CCoderProps @@ -331,7 +330,7 @@ HRESULT CMethodProps::SetParam(const UString &name, const UString &value) int index = FindPropIdExact(name); if (index < 0) return E_INVALIDARG; - const CNameToPropID &nameToPropID = g_NameToPropID[index]; + const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index]; CProp prop; prop.Id = index; @@ -401,7 +400,7 @@ HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const int index = FindPropIdExact(realName); if (index < 0) return E_INVALIDARG; - const CNameToPropID &nameToPropID = g_NameToPropID[index]; + const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index]; CProp prop; prop.Id = index; @@ -422,12 +421,20 @@ HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const HRESULT COneMethodInfo::ParseMethodFromString(const UString &s) { - int splitPos = s.Find(':'); - MethodName = s; + MethodName.Empty(); + int splitPos = s.Find(L':'); + { + UString temp = s; + if (splitPos >= 0) + temp.DeleteFrom(splitPos); + if (!temp.IsAscii()) + return E_INVALIDARG; + MethodName.SetFromWStr_if_Ascii(temp); + } if (splitPos < 0) return S_OK; - MethodName.DeleteFrom(splitPos); - return ParseParamsFromString(s.Ptr(splitPos + 1)); + PropsString = s.Ptr(splitPos + 1); + return ParseParamsFromString(PropsString); } HRESULT COneMethodInfo::ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value) diff --git a/CPP/7zip/Common/MethodProps.h b/CPP/7zip/Common/MethodProps.h index 18672bde..765e425d 100644 --- a/CPP/7zip/Common/MethodProps.h +++ b/CPP/7zip/Common/MethodProps.h @@ -40,13 +40,12 @@ struct CProps void AddProp32(PROPID propid, UInt32 level); - void AddPropString(PROPID propid, const wchar_t *s) + void AddProp_Ascii(PROPID propid, const char *s) { - CProp prop; + CProp &prop = Props.AddNew(); prop.IsOptional = true; prop.Id = propid; prop.Value = s; - Props.Add(prop); } HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const; @@ -100,6 +99,14 @@ public: return level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)); } + bool Are_Lzma_Model_Props_Defined() const + { + if (FindProp(NCoderPropID::kPosStateBits) >= 0) return true; + if (FindProp(NCoderPropID::kLitContextBits) >= 0) return true; + if (FindProp(NCoderPropID::kLitPosBits) >= 0) return true; + return false; + } + UInt32 Get_Lzma_NumThreads(bool &fixedNumber) const { fixedNumber = false; @@ -153,12 +160,12 @@ public: return level >= 9 ? (192 << 20) : ((UInt32)1 << (level + 19)); } - void AddLevelProp(UInt32 level) + void AddProp_Level(UInt32 level) { AddProp32(NCoderPropID::kLevel, level); } - void AddNumThreadsProp(UInt32 numThreads) + void AddProp_NumThreads(UInt32 numThreads) { AddProp32(NCoderPropID::kNumThreads, numThreads); } @@ -170,12 +177,14 @@ public: class COneMethodInfo: public CMethodProps { public: - UString MethodName; + AString MethodName; + UString PropsString; void Clear() { CMethodProps::Clear(); MethodName.Empty(); + PropsString.Empty(); } bool IsEmpty() const { return MethodName.IsEmpty() && Props.IsEmpty(); } HRESULT ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value); diff --git a/CPP/7zip/Common/ProgressUtils.cpp b/CPP/7zip/Common/ProgressUtils.cpp index bac45c1c..41385ccb 100644 --- a/CPP/7zip/Common/ProgressUtils.cpp +++ b/CPP/7zip/Common/ProgressUtils.cpp @@ -4,11 +4,13 @@ #include "ProgressUtils.h" -CLocalProgress::CLocalProgress() -{ - ProgressOffset = InSize = OutSize = 0; - SendRatio = SendProgress = true; -} +CLocalProgress::CLocalProgress(): + ProgressOffset(0), + InSize(0), + OutSize(0), + SendRatio(true), + SendProgress(true) + {} void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain) { @@ -20,19 +22,26 @@ void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain) STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { - UInt64 inSizeNew = InSize, outSizeNew = OutSize; + UInt64 inSize2 = InSize; + UInt64 outSize2 = OutSize; + if (inSize) - inSizeNew += (*inSize); + inSize2 += (*inSize); if (outSize) - outSizeNew += (*outSize); + outSize2 += (*outSize); + if (SendRatio && _ratioProgress) { - RINOK(_ratioProgress->SetRatioInfo(&inSizeNew, &outSizeNew)); + RINOK(_ratioProgress->SetRatioInfo(&inSize2, &outSize2)); } - inSizeNew += ProgressOffset; - outSizeNew += ProgressOffset; + if (SendProgress) - return _progress->SetCompleted(_inSizeIsMain ? &inSizeNew : &outSizeNew); + { + inSize2 += ProgressOffset; + outSize2 += ProgressOffset; + return _progress->SetCompleted(_inSizeIsMain ? &inSize2 : &outSize2); + } + return S_OK; } diff --git a/CPP/7zip/Common/ProgressUtils.h b/CPP/7zip/Common/ProgressUtils.h index bae5395c..e94265ba 100644 --- a/CPP/7zip/Common/ProgressUtils.h +++ b/CPP/7zip/Common/ProgressUtils.h @@ -1,7 +1,7 @@ // ProgressUtils.h -#ifndef __PROGRESSUTILS_H -#define __PROGRESSUTILS_H +#ifndef __PROGRESS_UTILS_H +#define __PROGRESS_UTILS_H #include "../../Common/MyCom.h" @@ -23,10 +23,11 @@ public: bool SendProgress; CLocalProgress(); + void Init(IProgress *progress, bool inSizeIsMain); HRESULT SetCur(); - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ICompressProgressInfo) STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; diff --git a/CPP/7zip/Common/PropId.cpp b/CPP/7zip/Common/PropId.cpp index 10daef71..2ce6fd85 100644 --- a/CPP/7zip/Common/PropId.cpp +++ b/CPP/7zip/Common/PropId.cpp @@ -5,7 +5,7 @@ #include "../PropID.h" // VARTYPE -Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] = +const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] = { VT_EMPTY, VT_UI4, @@ -95,5 +95,11 @@ Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] = VT_BOOL, VT_BOOL, VT_UI8, - VT_UI8 + VT_UI8, + VT_BSTR, // kpidNtReparse + VT_BSTR, + VT_UI8, + VT_UI8, + VT_BOOL, + VT_BSTR // kpidOutName }; diff --git a/CPP/7zip/Common/RegisterArc.h b/CPP/7zip/Common/RegisterArc.h index edc3abdd..3421ba1b 100644 --- a/CPP/7zip/Common/RegisterArc.h +++ b/CPP/7zip/Common/RegisterArc.h @@ -7,18 +7,16 @@ struct CArcInfo { + UInt16 Flags; + Byte Id; + Byte SignatureSize; + UInt16 SignatureOffset; + + const Byte *Signature; const char *Name; const char *Ext; const char *AddExt; - Byte ClassId; - - Byte SignatureSize; - Byte Signature[20]; - UInt16 SignatureOffset; - - UInt16 Flags; - Func_CreateInArchive CreateInArchive; Func_CreateOutArchive CreateOutArchive; Func_IsArc IsArc; @@ -28,28 +26,53 @@ struct CArcInfo void RegisterArc(const CArcInfo *arcInfo) throw(); -#define REGISTER_ARC_NAME(x) CRegister ## x - -#define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \ - REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \ - static REGISTER_ARC_NAME(x) g_RegisterArc; - -#define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) { \ - REGISTER_ARC_NAME(x)() { g_ArcInfo.Signature[0]--; RegisterArc(&g_ArcInfo); }}; \ - static REGISTER_ARC_NAME(x) g_RegisterArc; - #define IMP_CreateArcIn_2(c) \ static IInArchive *CreateArc() { return new c; } -#define IMP_CreateArcIn IMP_CreateArcIn_2(CHandler) +#define IMP_CreateArcIn IMP_CreateArcIn_2(CHandler()) #ifdef EXTRACT_ONLY #define IMP_CreateArcOut - #define REF_CreateArc_Pair CreateArc, NULL + #define CreateArcOut NULL #else - #define IMP_CreateArcOut static IOutArchive *CreateArcOut() { return new CHandler; } - #define REF_CreateArc_Pair CreateArc, CreateArcOut + #define IMP_CreateArcOut static IOutArchive *CreateArcOut() { return new CHandler(); } #endif +#define REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \ + static const CArcInfo g_ArcInfo = { flags, id, sigSize, offs, sig, n, e, ae, crIn, crOut, isArc } ; \ + +#define REGISTER_ARC_R(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \ + REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \ + struct CRegisterArc { CRegisterArc() { RegisterArc(&g_ArcInfo); }}; \ + static CRegisterArc g_RegisterArc; + + +#define REGISTER_ARC_I_CLS(cls, n, e, ae, id, sig, offs, flags, isArc) \ + IMP_CreateArcIn_2(cls) \ + REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, NULL, isArc) + +#define REGISTER_ARC_I_CLS_NO_SIG(cls, n, e, ae, id, offs, flags, isArc) \ + IMP_CreateArcIn_2(cls) \ + REGISTER_ARC_R(n, e, ae, id, 0, NULL, offs, flags, CreateArc, NULL, isArc) + +#define REGISTER_ARC_I(n, e, ae, id, sig, offs, flags, isArc) \ + REGISTER_ARC_I_CLS(CHandler(), n, e, ae, id, sig, offs, flags, isArc) + +#define REGISTER_ARC_I_NO_SIG(n, e, ae, id, offs, flags, isArc) \ + REGISTER_ARC_I_CLS_NO_SIG(CHandler(), n, e, ae, id, offs, flags, isArc) + + +#define REGISTER_ARC_IO(n, e, ae, id, sig, offs, flags, isArc) \ + IMP_CreateArcIn \ + IMP_CreateArcOut \ + REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, CreateArcOut, isArc) + +#define REGISTER_ARC_IO_DECREMENT_SIG(n, e, ae, id, sig, offs, flags, isArc) \ + IMP_CreateArcIn \ + IMP_CreateArcOut \ + REGISTER_ARC_V(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, CreateArcOut, isArc) \ + struct CRegisterArcDecSig { CRegisterArcDecSig() { sig[0]--; RegisterArc(&g_ArcInfo); }}; \ + static CRegisterArcDecSig g_RegisterArc; + #endif diff --git a/CPP/7zip/Common/RegisterCodec.h b/CPP/7zip/Common/RegisterCodec.h index 4222a305..7ddb7604 100644 --- a/CPP/7zip/Common/RegisterCodec.h +++ b/CPP/7zip/Common/RegisterCodec.h @@ -4,48 +4,103 @@ #define __REGISTER_CODEC_H #include "../Common/MethodId.h" + #include "../ICoder.h" typedef void * (*CreateCodecP)(); + struct CCodecInfo { CreateCodecP CreateDecoder; CreateCodecP CreateEncoder; CMethodId Id; - const wchar_t *Name; - UInt32 NumInStreams; + const char *Name; + UInt32 NumStreams; bool IsFilter; }; void RegisterCodec(const CCodecInfo *codecInfo) throw(); + +#define REGISTER_CODEC_CREATE_2(name, cls, i) static void *name() { return (void *)(i *)(new cls); } +#define REGISTER_CODEC_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressCoder) + #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x +#define REGISTER_CODEC_VAR static const CCodecInfo g_CodecInfo = #define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \ REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \ static REGISTER_CODEC_NAME(x) g_RegisterCodec; + #define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x +#define REGISTER_CODECS_VAR static const CCodecInfo g_CodecsInfo[] = + #define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \ REGISTER_CODECS_NAME(x)() { for (unsigned i = 0; i < ARRAY_SIZE(g_CodecsInfo); i++) \ RegisterCodec(&g_CodecsInfo[i]); }}; \ static REGISTER_CODECS_NAME(x) g_RegisterCodecs; +#define REGISTER_CODEC_2(x, crDec, crEnc, id, name) \ + REGISTER_CODEC_VAR \ + { crDec, crEnc, id, name, 1, false }; \ + REGISTER_CODEC(x) + + +#ifdef EXTRACT_ONLY + #define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \ + REGISTER_CODEC_CREATE(CreateDec, clsDec) \ + REGISTER_CODEC_2(x, CreateDec, NULL, id, name) +#else + #define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \ + REGISTER_CODEC_CREATE(CreateDec, clsDec) \ + REGISTER_CODEC_CREATE(CreateEnc, clsEnc) \ + REGISTER_CODEC_2(x, CreateDec, CreateEnc, id, name) +#endif + + + +#define REGISTER_FILTER_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressFilter) + +#define REGISTER_FILTER_ITEM(crDec, crEnc, id, name) \ + { crDec, crEnc, id, name, 1, true } + +#define REGISTER_FILTER(x, crDec, crEnc, id, name) \ + REGISTER_CODEC_VAR \ + REGISTER_FILTER_ITEM(crDec, crEnc, id, name); \ + REGISTER_CODEC(x) + +#ifdef EXTRACT_ONLY + #define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \ + REGISTER_FILTER_CREATE(CreateDec, clsDec) \ + REGISTER_FILTER(x, CreateDec, NULL, id, name) +#else + #define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \ + REGISTER_FILTER_CREATE(CreateDec, clsDec) \ + REGISTER_FILTER_CREATE(CreateEnc, clsEnc) \ + REGISTER_FILTER(x, CreateDec, CreateEnc, id, name) +#endif + + + struct CHasherInfo { IHasher * (*CreateHasher)(); CMethodId Id; - const wchar_t *Name; + const char *Name; UInt32 DigestSize; }; void RegisterHasher(const CHasherInfo *hasher) throw(); -#define REGISTER_HASHER_NAME(x) CRegisterHasher ## x +#define REGISTER_HASHER_NAME(x) CRegHasher_ ## x -#define REGISTER_HASHER(x) struct REGISTER_HASHER_NAME(x) { \ - REGISTER_HASHER_NAME(x)() { RegisterHasher(&g_HasherInfo); }}; \ - static REGISTER_HASHER_NAME(x) g_RegisterHasher; +#define REGISTER_HASHER(cls, id, name, size) \ + STDMETHODIMP_(UInt32) cls::GetDigestSize() throw() { return size; } \ + static IHasher *CreateHasherSpec() { return new cls(); } \ + static const CHasherInfo g_HasherInfo = { CreateHasherSpec, id, name, size }; \ + struct REGISTER_HASHER_NAME(cls) { REGISTER_HASHER_NAME(cls)() { RegisterHasher(&g_HasherInfo); }}; \ + static REGISTER_HASHER_NAME(cls) g_RegisterHasher; #endif diff --git a/CPP/7zip/Common/StreamBinder.cpp b/CPP/7zip/Common/StreamBinder.cpp index 7a4c0ed2..435440c6 100644 --- a/CPP/7zip/Common/StreamBinder.cpp +++ b/CPP/7zip/Common/StreamBinder.cpp @@ -12,7 +12,7 @@ class CBinderInStream: { CStreamBinder *_binder; public: - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ISequentialInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); ~CBinderInStream() { _binder->CloseRead(); } CBinderInStream(CStreamBinder *binder): _binder(binder) {} @@ -27,7 +27,7 @@ class CBinderOutStream: { CStreamBinder *_binder; public: - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ISequentialOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); ~CBinderOutStream() { _binder->CloseWrite(); } CBinderOutStream(CStreamBinder *binder): _binder(binder) {} @@ -40,26 +40,38 @@ STDMETHODIMP CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *proc WRes CStreamBinder::CreateEvents() { - RINOK(_canWrite_Event.Create(true)); + RINOK(_canWrite_Event.Create()); RINOK(_canRead_Event.Create()); return _readingWasClosed_Event.Create(); } void CStreamBinder::ReInit() { - _waitWrite = true; + _canWrite_Event.Reset(); _canRead_Event.Reset(); _readingWasClosed_Event.Reset(); + + // _readingWasClosed = false; + _readingWasClosed2 = false; + + _waitWrite = true; + _bufSize = 0; + _buf = NULL; ProcessedSize = 0; + // WritingWasCut = false; } void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream) { + // _readingWasClosed = false; + _readingWasClosed2 = false; + _waitWrite = true; _bufSize = 0; _buf = NULL; ProcessedSize = 0; + // WritingWasCut = false; CBinderInStream *inStreamSpec = new CBinderInStream(this); CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); @@ -108,19 +120,37 @@ HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSiz { if (processedSize) *processedSize = 0; - if (size != 0) + if (size == 0) + return S_OK; + + if (!_readingWasClosed2) { _buf = data; _bufSize = size; - _canWrite_Event.Reset(); _canRead_Event.Set(); + + /* + _canWrite_Event.Lock(); + if (_readingWasClosed) + _readingWasClosed2 = true; + */ HANDLE events[2] = { _canWrite_Event, _readingWasClosed_Event }; DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); - if (waitResult != WAIT_OBJECT_0 + 0) - return S_FALSE; - if (processedSize) - *processedSize = size; + if (waitResult >= WAIT_OBJECT_0 + 2) + return E_FAIL; + + size -= _bufSize; + if (size != 0) + { + if (processedSize) + *processedSize = size; + return S_OK; + } + // if (waitResult == WAIT_OBJECT_0 + 1) + _readingWasClosed2 = true; } - return S_OK; + + // WritingWasCut = true; + return k_My_HRESULT_WritingWasCut; } diff --git a/CPP/7zip/Common/StreamBinder.h b/CPP/7zip/Common/StreamBinder.h index f3fb5322..12088a94 100644 --- a/CPP/7zip/Common/StreamBinder.h +++ b/CPP/7zip/Common/StreamBinder.h @@ -7,11 +7,27 @@ #include "../IStream.h" +/* +We don't use probably UNSAFE version: +reader thread: + _canWrite_Event.Set(); + _readingWasClosed = true + _canWrite_Event.Set(); +writer thread: + _canWrite_Event.Wait() + if (_readingWasClosed) +Can second call of _canWrite_Event.Set() be executed without memory barrier, if event is already set? +*/ + class CStreamBinder { - NWindows::NSynchronization::CManualResetEvent _canWrite_Event; + NWindows::NSynchronization::CAutoResetEvent _canWrite_Event; NWindows::NSynchronization::CManualResetEvent _canRead_Event; NWindows::NSynchronization::CManualResetEvent _readingWasClosed_Event; + + // bool _readingWasClosed; + bool _readingWasClosed2; + // bool WritingWasCut; bool _waitWrite; UInt32 _bufSize; const void *_buf; @@ -20,13 +36,23 @@ public: WRes CreateEvents(); void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream); + void ReInit(); + HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); - void CloseRead() { _readingWasClosed_Event.Set(); } + + void CloseRead() + { + _readingWasClosed_Event.Set(); + // _readingWasClosed = true; + // _canWrite_Event.Set(); + } + void CloseWrite() { - // _bufSize must be = 0 + _buf = NULL; + _bufSize = 0; _canRead_Event.Set(); } }; diff --git a/CPP/7zip/Common/StreamObjects.cpp b/CPP/7zip/Common/StreamObjects.cpp index 817017ab..8136716d 100644 --- a/CPP/7zip/Common/StreamObjects.cpp +++ b/CPP/7zip/Common/StreamObjects.cpp @@ -8,6 +8,41 @@ #include "StreamObjects.h" +STDMETHODIMP CBufferInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + if (_pos >= Buf.Size()) + return S_OK; + size_t rem = Buf.Size() - (size_t)_pos; + if (rem > size) + rem = (size_t)size; + memcpy(data, (const Byte *)Buf + (size_t)_pos, rem); + _pos += rem; + if (processedSize) + *processedSize = (UInt32)rem; + return S_OK; +} + +STDMETHODIMP CBufferInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _pos; break; + case STREAM_SEEK_END: offset += Buf.Size(); break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _pos = offset; + if (newPosition) + *newPosition = offset; + return S_OK; +} + STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) @@ -43,25 +78,22 @@ STDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosi return S_OK; } -/* -void Create_BufInStream_WithReference(const void *data, size_t size, ISequentialInStream **stream) +void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream) { + *stream = NULL; CBufInStream *inStreamSpec = new CBufInStream; CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec; - inStreamSpec->Init((const Byte *)data, size); + inStreamSpec->Init((const Byte *)data, size, ref); *stream = streamTemp.Detach(); } -*/ -void Create_BufInStream_WithNewBuf(const void *data, size_t size, ISequentialInStream **stream) +void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream) { - CReferenceBuf *referenceBuf = new CReferenceBuf; - CMyComPtr<IUnknown> ref = referenceBuf; - referenceBuf->Buf.CopyFrom((const Byte *)data, size); - - CBufInStream *inStreamSpec = new CBufInStream; + *stream = NULL; + CBufferInStream *inStreamSpec = new CBufferInStream; CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec; - inStreamSpec->Init(referenceBuf); + inStreamSpec->Buf.CopyFrom((const Byte *)data, size); + inStreamSpec->Init(); *stream = streamTemp.Detach(); } @@ -128,8 +160,11 @@ STDMETHODIMP CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *p size_t rem = _size - _pos; if (rem > size) rem = (size_t)size; - memcpy(_buffer + _pos, data, rem); - _pos += rem; + if (rem != 0) + { + memcpy(_buffer + _pos, data, rem); + _pos += rem; + } if (processedSize) *processedSize = (UInt32)rem; return (rem != 0 || size == 0) ? S_OK : E_FAIL; diff --git a/CPP/7zip/Common/StreamObjects.h b/CPP/7zip/Common/StreamObjects.h index d0c86b56..e20e9bd8 100644 --- a/CPP/7zip/Common/StreamObjects.h +++ b/CPP/7zip/Common/StreamObjects.h @@ -9,6 +9,21 @@ #include "../IStream.h" +class CBufferInStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _pos; +public: + CByteBuffer Buf; + void Init() { _pos = 0; } + + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + struct CReferenceBuf: public IUnknown, public CMyUnknownImp @@ -40,8 +55,10 @@ public: STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; -// void Create_BufInStream_WithReference(const void *data, size_t size, ISequentialInStream **stream); -void Create_BufInStream_WithNewBuf(const void *data, size_t size, ISequentialInStream **stream); +void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream); +void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream); +inline void Create_BufInStream_WithNewBuffer(const CByteBuffer &buf, ISequentialInStream **stream) + { Create_BufInStream_WithNewBuffer(buf, buf.Size(), stream); } class CByteDynBuffer { @@ -53,8 +70,8 @@ public: ~CByteDynBuffer() { Free(); } void Free() throw(); size_t GetCapacity() const { return _capacity; } - operator Byte*() const { return _buf; }; - operator const Byte*() const { return _buf; }; + operator Byte*() const { return _buf; } + operator const Byte*() const { return _buf; } bool EnsureCapacity(size_t capacity) throw(); }; diff --git a/CPP/7zip/Common/UniqBlocks.cpp b/CPP/7zip/Common/UniqBlocks.cpp index 7fcc88f5..a2cacdde 100644 --- a/CPP/7zip/Common/UniqBlocks.cpp +++ b/CPP/7zip/Common/UniqBlocks.cpp @@ -4,13 +4,13 @@ #include "UniqBlocks.h" -int CUniqBlocks::AddUniq(const Byte *data, size_t size) +unsigned CUniqBlocks::AddUniq(const Byte *data, size_t size) { unsigned left = 0, right = Sorted.Size(); while (left != right) { unsigned mid = (left + right) / 2; - int index = Sorted[mid]; + unsigned index = Sorted[mid]; const CByteBuffer &buf = Bufs[index]; size_t sizeMid = buf.Size(); if (size < sizeMid) @@ -19,6 +19,8 @@ int CUniqBlocks::AddUniq(const Byte *data, size_t size) left = mid + 1; else { + if (size == 0) + return index; int cmp = memcmp(data, buf, size); if (cmp == 0) return index; @@ -28,10 +30,9 @@ int CUniqBlocks::AddUniq(const Byte *data, size_t size) left = mid + 1; } } - int index = Bufs.Size(); + unsigned index = Bufs.Size(); Sorted.Insert(left, index); - CByteBuffer &buf = Bufs.AddNew(); - buf.CopyFrom(data, size); + Bufs.AddNew().CopyFrom(data, size); return index; } @@ -47,10 +48,8 @@ void CUniqBlocks::GetReverseMap() { unsigned num = Sorted.Size(); BufIndexToSortedIndex.ClearAndSetSize(num); - int *p = &BufIndexToSortedIndex[0]; - unsigned i; - for (i = 0; i < num; i++) - p[i] = 0; - for (i = 0; i < num; i++) - p[Sorted[i]] = i; + unsigned *p = &BufIndexToSortedIndex[0]; + const unsigned *sorted = &Sorted[0]; + for (unsigned i = 0; i < num; i++) + p[sorted[i]] = i; } diff --git a/CPP/7zip/Common/UniqBlocks.h b/CPP/7zip/Common/UniqBlocks.h index 9c08b09f..a376024e 100644 --- a/CPP/7zip/Common/UniqBlocks.h +++ b/CPP/7zip/Common/UniqBlocks.h @@ -10,20 +10,16 @@ struct CUniqBlocks { CObjectVector<CByteBuffer> Bufs; - CIntVector Sorted; - CIntVector BufIndexToSortedIndex; + CUIntVector Sorted; + CUIntVector BufIndexToSortedIndex; - int AddUniq(const Byte *data, size_t size); + unsigned AddUniq(const Byte *data, size_t size); UInt64 GetTotalSizeInBytes() const; void GetReverseMap(); bool IsOnlyEmpty() const { - if (Bufs.Size() == 0) - return true; - if (Bufs.Size() > 1) - return false; - return Bufs[0].Size() == 0; + return (Bufs.Size() == 0 || Bufs.Size() == 1 && Bufs[0].Size() == 0); } }; diff --git a/CPP/7zip/Compress/ArjDecoder1.cpp b/CPP/7zip/Compress/ArjDecoder1.cpp deleted file mode 100644 index 2eaa591c..00000000 --- a/CPP/7zip/Compress/ArjDecoder1.cpp +++ /dev/null @@ -1,309 +0,0 @@ -// ArjDecoder1.cpp - -#include "StdAfx.h" - -#include "ArjDecoder1.h" - -namespace NCompress{ -namespace NArj { -namespace NDecoder1 { - -static const UInt32 kHistorySize = 26624; -static const UInt32 kMatchMinLen = 3; -static const UInt32 kMatchMaxLen = 256; - -// static const UInt32 kNC = 255 + kMatchMaxLen + 2 - kMatchMinLen; - -void CCoder::MakeTable(int nchar, Byte *bitlen, int tablebits, - UInt32 *table, int tablesize) -{ - UInt32 count[17], weight[17], start[18], *p; - UInt32 i, k, len, ch, jutbits, avail, nextcode, mask; - - for (i = 1; i <= 16; i++) - count[i] = 0; - for (i = 0; (int)i < nchar; i++) - count[bitlen[i]]++; - - start[1] = 0; - for (i = 1; i <= 16; i++) - start[i + 1] = start[i] + (count[i] << (16 - i)); - if (start[17] != (UInt32) (1 << 16)) - throw "Data error"; - - jutbits = 16 - tablebits; - for (i = 1; (int)i <= tablebits; i++) - { - start[i] >>= jutbits; - weight[i] = 1 << (tablebits - i); - } - while (i <= 16) - { - weight[i] = 1 << (16 - i); - i++; - } - - i = start[tablebits + 1] >> jutbits; - if (i != (UInt32) (1 << 16)) - { - k = 1 << tablebits; - while (i != k) - table[i++] = 0; - } - - avail = nchar; - mask = 1 << (15 - tablebits); - for (ch = 0; (int)ch < nchar; ch++) - { - if ((len = bitlen[ch]) == 0) - continue; - k = start[len]; - nextcode = k + weight[len]; - if ((int)len <= tablebits) - { - if (nextcode > (UInt32)tablesize) - throw "Data error"; - for (i = start[len]; i < nextcode; i++) - table[i] = ch; - } - else - { - p = &table[k >> jutbits]; - i = len - tablebits; - while (i != 0) - { - if (*p == 0) - { - right[avail] = left[avail] = 0; - *p = avail++; - } - if (k & mask) - p = &right[*p]; - else - p = &left[*p]; - k <<= 1; - i--; - } - *p = ch; - } - start[len] = nextcode; - } -} - -void CCoder::read_pt_len(int nn, int nbit, int i_special) -{ - UInt32 n = m_InBitStream.ReadBits(nbit); - if (n == 0) - { - UInt32 c = m_InBitStream.ReadBits(nbit); - int i; - for (i = 0; i < nn; i++) - pt_len[i] = 0; - for (i = 0; i < 256; i++) - pt_table[i] = c; - } - else - { - UInt32 i = 0; - while (i < n) - { - UInt32 bitBuf = m_InBitStream.GetValue(16); - int c = bitBuf >> 13; - if (c == 7) - { - UInt32 mask = 1 << (12); - while (mask & bitBuf) - { - mask >>= 1; - c++; - } - } - m_InBitStream.MovePos((c < 7) ? 3 : (int)(c - 3)); - pt_len[i++] = (Byte)c; - if (i == (UInt32)i_special) - { - c = m_InBitStream.ReadBits(2); - while (--c >= 0) - pt_len[i++] = 0; - } - } - while (i < (UInt32)nn) - pt_len[i++] = 0; - MakeTable(nn, pt_len, 8, pt_table, PTABLESIZE); - } -} - -void CCoder::read_c_len() -{ - int i, c, n; - UInt32 mask; - - n = m_InBitStream.ReadBits(CBIT); - if (n == 0) - { - c = m_InBitStream.ReadBits(CBIT); - for (i = 0; i < NC; i++) - c_len[i] = 0; - for (i = 0; i < CTABLESIZE; i++) - c_table[i] = c; - } - else - { - i = 0; - while (i < n) - { - UInt32 bitBuf = m_InBitStream.GetValue(16); - c = pt_table[bitBuf >> (8)]; - if (c >= NT) - { - mask = 1 << (7); - do - { - if (bitBuf & mask) - c = right[c]; - else - c = left[c]; - mask >>= 1; - } while (c >= NT); - } - m_InBitStream.MovePos((int)(pt_len[c])); - if (c <= 2) - { - if (c == 0) - c = 1; - else if (c == 1) - c = m_InBitStream.ReadBits(4) + 3; - else - c = m_InBitStream.ReadBits(CBIT) + 20; - while (--c >= 0) - c_len[i++] = 0; - } - else - c_len[i++] = (Byte)(c - 2); - } - while (i < NC) - c_len[i++] = 0; - MakeTable(NC, c_len, 12, c_table, CTABLESIZE); - } -} - -UInt32 CCoder::decode_c() -{ - UInt32 j, mask; - UInt32 bitbuf = m_InBitStream.GetValue(16); - j = c_table[bitbuf >> 4]; - if (j >= NC) - { - mask = 1 << (3); - do - { - if (bitbuf & mask) - j = right[j]; - else - j = left[j]; - mask >>= 1; - } while (j >= NC); - } - m_InBitStream.MovePos((int)(c_len[j])); - return j; -} - -UInt32 CCoder::decode_p() -{ - UInt32 j, mask; - UInt32 bitbuf = m_InBitStream.GetValue(16); - j = pt_table[bitbuf >> (8)]; - if (j >= NP) - { - mask = 1 << (7); - do - { - if (bitbuf & mask) - j = right[j]; - else - j = left[j]; - mask >>= 1; - } while (j >= NP); - } - m_InBitStream.MovePos((int)(pt_len[j])); - if (j != 0) - { - j--; - j = (1 << j) + m_InBitStream.ReadBits((int)j); - } - return j; -} - - -HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) -{ - if (outSize == NULL) - return E_INVALIDARG; - - if (!m_OutWindowStream.Create(kHistorySize)) - return E_OUTOFMEMORY; - if (!m_InBitStream.Create(1 << 20)) - return E_OUTOFMEMORY; - - // check it - for (int i = 0; i < CTABLESIZE; i++) - c_table[i] = 0; - - UInt64 pos = 0; - m_OutWindowStream.SetStream(outStream); - m_OutWindowStream.Init(false); - m_InBitStream.SetStream(inStream); - m_InBitStream.Init(); - - CCoderReleaser coderReleaser(this); - - UInt32 blockSize = 0; - - while (pos < *outSize) - { - if (blockSize == 0) - { - if (progress != NULL) - { - UInt64 packSize = m_InBitStream.GetProcessedSize(); - RINOK(progress->SetRatioInfo(&packSize, &pos)); - } - blockSize = m_InBitStream.ReadBits(16); - read_pt_len(NT, TBIT, 3); - read_c_len(); - read_pt_len(NP, PBIT, -1); - } - blockSize--; - - UInt32 number = decode_c(); - if (number < 256) - { - m_OutWindowStream.PutByte((Byte)number); - pos++; - continue; - } - else - { - UInt32 len = number - 256 + kMatchMinLen; - UInt32 distance = decode_p(); - if (distance >= pos) - return S_FALSE; - m_OutWindowStream.CopyBlock(distance, len); - pos += len; - } - } - coderReleaser.NeedFlush = false; - return m_OutWindowStream.Flush(); -} - -STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) -{ - try { return CodeReal(inStream, outStream, inSize, outSize, progress);} - catch(const CInBufferException &e) { return e.ErrorCode; } - catch(const CLzOutWindowException &e) { return e.ErrorCode; } - catch(...) { return S_FALSE; } -} - -}}} diff --git a/CPP/7zip/Compress/ArjDecoder1.h b/CPP/7zip/Compress/ArjDecoder1.h deleted file mode 100644 index dd12e445..00000000 --- a/CPP/7zip/Compress/ArjDecoder1.h +++ /dev/null @@ -1,91 +0,0 @@ -// ArjDecoder1.h - -#ifndef __COMPRESS_ARJ_DECODER1_H -#define __COMPRESS_ARJ_DECODER1_H - -#include "../../Common/MyCom.h" - -#include "../ICoder.h" - -#include "../Common/InBuffer.h" - -#include "BitmDecoder.h" -#include "LzOutWindow.h" - -namespace NCompress { -namespace NArj { -namespace NDecoder1 { - -#define CODE_BIT 16 - -#define THRESHOLD 3 -#define DDICSIZ 26624 -#define MAXDICBIT 16 -#define MATCHBIT 8 -#define MAXMATCH 256 -#define NC (0xFF + MAXMATCH + 2 - THRESHOLD) -#define NP (MAXDICBIT + 1) -#define CBIT 9 -#define NT (CODE_BIT + 3) -#define PBIT 5 -#define TBIT 5 - -#if NT > NP -#define NPT NT -#else -#define NPT NP -#endif - -#define CTABLESIZE 4096 -#define PTABLESIZE 256 - - -class CCoder : - public ICompressCoder, - public CMyUnknownImp -{ - CLzOutWindow m_OutWindowStream; - NBitm::CDecoder<CInBuffer> m_InBitStream; - - UInt32 left[2 * NC - 1]; - UInt32 right[2 * NC - 1]; - Byte c_len[NC]; - Byte pt_len[NPT]; - - UInt32 c_table[CTABLESIZE]; - UInt32 pt_table[PTABLESIZE]; - - class CCoderReleaser - { - CCoder *m_Coder; - public: - bool NeedFlush; - CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {} - ~CCoderReleaser() - { - if (NeedFlush) - m_Coder->m_OutWindowStream.Flush(); - } - }; - friend class CCoderReleaser; - - void MakeTable(int nchar, Byte *bitlen, int tablebits, UInt32 *table, int tablesize); - - void read_c_len(); - void read_pt_len(int nn, int nbit, int i_special); - UInt32 decode_c(); - UInt32 decode_p(); - - HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); -public: - MY_UNKNOWN_IMP - - STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); - -}; - -}}} - -#endif diff --git a/CPP/7zip/Compress/ArjDecoder2.cpp b/CPP/7zip/Compress/ArjDecoder2.cpp deleted file mode 100644 index 4903605c..00000000 --- a/CPP/7zip/Compress/ArjDecoder2.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// ArjDecoder2.cpp - -#include "StdAfx.h" - -#include "ArjDecoder2.h" - -namespace NCompress{ -namespace NArj { -namespace NDecoder2 { - -static const UInt32 kHistorySize = 26624; -static const UInt32 kMatchMinLen = 3; - -HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo * /* progress */) -{ - if (outSize == NULL) - return E_INVALIDARG; - - if (!m_OutWindowStream.Create(kHistorySize)) - return E_OUTOFMEMORY; - if (!m_InBitStream.Create(1 << 20)) - return E_OUTOFMEMORY; - - UInt64 pos = 0; - m_OutWindowStream.SetStream(outStream); - m_OutWindowStream.Init(false); - m_InBitStream.SetStream(inStream); - m_InBitStream.Init(); - - CCoderReleaser coderReleaser(this); - - while (pos < *outSize) - { - const UInt32 kStartWidth = 0; - const UInt32 kStopWidth = 7; - UInt32 power = 1 << kStartWidth; - UInt32 width; - UInt32 len = 0; - for (width = kStartWidth; width < kStopWidth; width++) - { - if (m_InBitStream.ReadBits(1) == 0) - break; - len += power; - power <<= 1; - } - if (width != 0) - len += m_InBitStream.ReadBits(width); - if (len == 0) - { - m_OutWindowStream.PutByte((Byte)m_InBitStream.ReadBits(8)); - pos++; - continue; - } - else - { - len = len - 1 + kMatchMinLen; - const UInt32 kStartWidth = 9; - const UInt32 kStopWidth = 13; - UInt32 power = 1 << kStartWidth; - UInt32 width; - UInt32 distance = 0; - for (width = kStartWidth; width < kStopWidth; width++) - { - if (m_InBitStream.ReadBits(1) == 0) - break; - distance += power; - power <<= 1; - } - if (width != 0) - distance += m_InBitStream.ReadBits(width); - if (distance >= pos) - return S_FALSE; - m_OutWindowStream.CopyBlock(distance, len); - pos += len; - } - } - coderReleaser.NeedFlush = false; - return m_OutWindowStream.Flush(); -} - -STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) -{ - try { return CodeReal(inStream, outStream, inSize, outSize, progress);} - catch(const CInBufferException &e) { return e.ErrorCode; } - catch(const CLzOutWindowException &e) { return e.ErrorCode; } - catch(...) { return S_FALSE; } -} - -}}} diff --git a/CPP/7zip/Compress/ArjDecoder2.h b/CPP/7zip/Compress/ArjDecoder2.h deleted file mode 100644 index cf544d9e..00000000 --- a/CPP/7zip/Compress/ArjDecoder2.h +++ /dev/null @@ -1,52 +0,0 @@ -// ArjDecoder2.h - -#ifndef __COMPRESS_ARJ_DECODER2_H -#define __COMPRESS_ARJ_DECODER2_H - -#include "../../Common/MyCom.h" - -#include "../ICoder.h" - -#include "../Common/InBuffer.h" - -#include "BitmDecoder.h" -#include "LzOutWindow.h" - -namespace NCompress { -namespace NArj { -namespace NDecoder2 { - -class CCoder : - public ICompressCoder, - public CMyUnknownImp -{ - CLzOutWindow m_OutWindowStream; - NBitm::CDecoder<CInBuffer> m_InBitStream; - - class CCoderReleaser - { - CCoder *m_Coder; - public: - bool NeedFlush; - CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {} - ~CCoderReleaser() - { - if (NeedFlush) - m_Coder->m_OutWindowStream.Flush(); - } - }; - friend class CCoderReleaser; - - HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); -public: - MY_UNKNOWN_IMP - - STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); - -}; - -}}} - -#endif diff --git a/CPP/7zip/Compress/BZip2Const.h b/CPP/7zip/Compress/BZip2Const.h index 62427aa6..588f5ae0 100644 --- a/CPP/7zip/Compress/BZip2Const.h +++ b/CPP/7zip/Compress/BZip2Const.h @@ -25,29 +25,30 @@ const Byte kBlockSig3 = 0x26; const Byte kBlockSig4 = 0x53; const Byte kBlockSig5 = 0x59; -const int kNumOrigBits = 24; +const unsigned kNumOrigBits = 24; -const int kNumTablesBits = 3; -const int kNumTablesMin = 2; -const int kNumTablesMax = 6; +const unsigned kNumTablesBits = 3; +const unsigned kNumTablesMin = 2; +const unsigned kNumTablesMax = 6; -const int kNumLevelsBits = 5; +const unsigned kNumLevelsBits = 5; -const int kMaxHuffmanLen = 20; // Check it +const unsigned kMaxHuffmanLen = 20; // Check it -const int kMaxAlphaSize = 258; +const unsigned kMaxAlphaSize = 258; -const int kGroupSize = 50; +const unsigned kGroupSize = 50; + +const unsigned kBlockSizeMultMin = 1; +const unsigned kBlockSizeMultMax = 9; -const int kBlockSizeMultMin = 1; -const int kBlockSizeMultMax = 9; const UInt32 kBlockSizeStep = 100000; const UInt32 kBlockSizeMax = kBlockSizeMultMax * kBlockSizeStep; -const int kNumSelectorsBits = 15; +const unsigned kNumSelectorsBits = 15; const UInt32 kNumSelectorsMax = (2 + (kBlockSizeMax / kGroupSize)); -const int kRleModeRepSize = 4; +const unsigned kRleModeRepSize = 4; }} diff --git a/CPP/7zip/Compress/BZip2Decoder.cpp b/CPP/7zip/Compress/BZip2Decoder.cpp index 3798421e..db4d0933 100644 --- a/CPP/7zip/Compress/BZip2Decoder.cpp +++ b/CPP/7zip/Compress/BZip2Decoder.cpp @@ -105,10 +105,10 @@ HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps CMtf8Decoder mtf; mtf.StartInit(); - int numInUse = 0; + unsigned numInUse = 0; { Byte inUse16[16]; - int i; + unsigned i; for (i = 0; i < 16; i++) inUse16[i] = (Byte)ReadBit(); for (i = 0; i < 256; i++) @@ -121,9 +121,9 @@ HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps return S_FALSE; // mtf.Init(numInUse); } - int alphaSize = numInUse + 2; + unsigned alphaSize = numInUse + 2; - int numTables = ReadBits(kNumTablesBits); + unsigned numTables = ReadBits(kNumTablesBits); if (numTables < kNumTablesMin || numTables > kNumTablesMax) return S_FALSE; @@ -133,14 +133,14 @@ HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps { Byte mtfPos[kNumTablesMax]; - int t = 0; + unsigned t = 0; do mtfPos[t] = (Byte)t; while (++t < numTables); UInt32 i = 0; do { - int j = 0; + unsigned j = 0; while (ReadBit()) if (++j >= numTables) return S_FALSE; @@ -152,12 +152,12 @@ HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps while (++i < numSelectors); } - int t = 0; + unsigned t = 0; do { Byte lens[kMaxAlphaSize]; - int len = (int)ReadBits(kNumLevelsBits); - int i; + unsigned len = (unsigned)ReadBits(kNumLevelsBits); + unsigned i; for (i = 0; i < alphaSize; i++) { for (;;) @@ -166,7 +166,8 @@ HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps return S_FALSE; if (!ReadBit()) break; - len += 1 - (int)(ReadBit() << 1); + len++; + len -= (ReadBit() << 1); } lens[i] = (Byte)len; } @@ -178,7 +179,7 @@ HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps while (++t < numTables); { - for (int i = 0; i < 256; i++) + for (unsigned i = 0; i < 256; i++) charCounters[i] = 0; } @@ -187,7 +188,7 @@ HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps UInt32 groupIndex = 0; UInt32 groupSize = 0; CHuffmanDecoder *huffmanDecoder = 0; - int runPower = 0; + unsigned runPower = 0; UInt32 runCounter = 0; for (;;) @@ -224,7 +225,7 @@ HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps } if (nextSym <= (UInt32)numInUse) { - UInt32 b = (UInt32)mtf.GetAndMove((int)nextSym - 1); + UInt32 b = (UInt32)mtf.GetAndMove((unsigned)nextSym - 1); if (blockSize >= blockSizeMax) return S_FALSE; charCounters[b]++; @@ -510,7 +511,7 @@ HRESULT CDecoder::ReadSignature(UInt32 &crc) crc = 0; Byte s[10]; - int i; + unsigned i; for (i = 0; i < 10; i++) s[i] = ReadByte(); @@ -576,7 +577,7 @@ HRESULT CDecoder::DecodeFile(ICompressProgressInfo *progress) */ Byte s[4]; - int i; + unsigned i; for (i = 0; i < 4; i++) s[i] = ReadByte(); if (Base.BitDecoder.ExtraBitsWereRead()) diff --git a/CPP/7zip/Compress/BZip2Decoder.h b/CPP/7zip/Compress/BZip2Decoder.h index 2c28c5a1..8703d572 100644 --- a/CPP/7zip/Compress/BZip2Decoder.h +++ b/CPP/7zip/Compress/BZip2Decoder.h @@ -154,10 +154,6 @@ public: UInt32 BlockSizeMax; - bool IsBz; - bool BzWasFinished; // bzip stream was finished with end signature - bool CrcError; // it can CRC error of block or CRC error of whole stream. - ~CDecoder(); HRESULT Create(); void Free(); @@ -166,6 +162,10 @@ public: CState m_States[1]; #endif + bool IsBz; + bool BzWasFinished; // bzip stream was finished with end signature + bool CrcError; // it can CRC error of block or CRC error of whole stream. + CDecoder(); HRESULT SetRatioProgress(UInt64 packSize); diff --git a/CPP/7zip/Compress/BZip2Encoder.cpp b/CPP/7zip/Compress/BZip2Encoder.cpp index 2bdbe989..bd985dfe 100644 --- a/CPP/7zip/Compress/BZip2Encoder.cpp +++ b/CPP/7zip/Compress/BZip2Encoder.cpp @@ -13,10 +13,10 @@ namespace NCompress { namespace NBZip2 { -const int kMaxHuffmanLenForEncoding = 16; // it must be < kMaxHuffmanLen = 20 +const unsigned kMaxHuffmanLenForEncoding = 16; // it must be < kMaxHuffmanLen = 20 static const UInt32 kBufferSize = (1 << 17); -static const int kNumHuffPasses = 4; +static const unsigned kNumHuffPasses = 4; bool CThreadInfo::Alloc() { @@ -126,14 +126,16 @@ void CEncProps::Normalize(int level) { if (level < 0) level = 5; if (level > 9) level = 9; + if (NumPasses == (UInt32)(Int32)-1) NumPasses = (level >= 9 ? 7 : (level >= 7 ? 2 : 1)); - if (NumPasses < kBlockSizeMultMin) NumPasses = kBlockSizeMultMin; - if (NumPasses > kBlockSizeMultMax) NumPasses = kBlockSizeMultMax; + if (NumPasses < 1) NumPasses = 1; + if (NumPasses > kNumPassesMax) NumPasses = kNumPassesMax; + if (BlockSizeMult == (UInt32)(Int32)-1) BlockSizeMult = (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1)); - if (BlockSizeMult == 0) BlockSizeMult = 1; - if (BlockSizeMult > kNumPassesMax) BlockSizeMult = kNumPassesMax; + if (BlockSizeMult < kBlockSizeMultMin) BlockSizeMult = kBlockSizeMultMin; + if (BlockSizeMult > kBlockSizeMultMax) BlockSizeMult = kBlockSizeMultMax; } CEncoder::CEncoder() @@ -212,7 +214,7 @@ UInt32 CEncoder::ReadRleBlock(Byte *buffer) if (m_InStream.ReadByte(prevByte)) { UInt32 blockSize = _props.BlockSizeMult * kBlockSizeStep - 1; - int numReps = 1; + unsigned numReps = 1; buffer[i++] = prevByte; while (i < blockSize) // "- 1" to support RLE { @@ -246,19 +248,19 @@ UInt32 CEncoder::ReadRleBlock(Byte *buffer) void CThreadInfo::WriteBits2(UInt32 value, unsigned numBits) { m_OutStreamCurrent->WriteBits(value, numBits); } void CThreadInfo::WriteByte2(Byte b) { WriteBits2(b, 8); } -void CThreadInfo::WriteBit2(bool v) { WriteBits2((v ? 1 : 0), 1); } +void CThreadInfo::WriteBit2(Byte v) { WriteBits2(v, 1); } void CThreadInfo::WriteCrc2(UInt32 v) { - for (int i = 0; i < 4; i++) + for (unsigned i = 0; i < 4; i++) WriteByte2(((Byte)(v >> (24 - i * 8)))); } void CEncoder::WriteBits(UInt32 value, unsigned numBits) { m_OutStream.WriteBits(value, numBits); } void CEncoder::WriteByte(Byte b) { WriteBits(b, 8); } -void CEncoder::WriteBit(bool v) { WriteBits((v ? 1 : 0), 1); } +// void CEncoder::WriteBit(Byte v) { WriteBits(v, 1); } void CEncoder::WriteCrc(UInt32 v) { - for (int i = 0; i < 4; i++) + for (unsigned i = 0; i < 4; i++) WriteByte(((Byte)(v >> (24 - i * 8)))); } @@ -266,7 +268,7 @@ void CEncoder::WriteCrc(UInt32 v) // blockSize > 0 void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) { - WriteBit2(false); // Randomised = false + WriteBit2(0); // Randomised = false { UInt32 origPtr = BlockSort(m_BlockSorterIndex, block, blockSize); @@ -276,21 +278,21 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) } CMtf8Encoder mtf; - int numInUse = 0; + unsigned numInUse = 0; { - bool inUse[256]; - bool inUse16[16]; + Byte inUse[256]; + Byte inUse16[16]; UInt32 i; for (i = 0; i < 256; i++) - inUse[i] = false; + inUse[i] = 0; for (i = 0; i < 16; i++) - inUse16[i] = false; + inUse16[i] = 0; for (i = 0; i < blockSize; i++) - inUse[block[i]] = true; + inUse[block[i]] = 1; for (i = 0; i < 256; i++) if (inUse[i]) { - inUse16[i >> 4] = true; + inUse16[i >> 4] = 1; mtf.Buf[numInUse++] = (Byte)i; } for (i = 0; i < 16; i++) @@ -299,13 +301,13 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) if (inUse16[i >> 4]) WriteBit2(inUse[i]); } - int alphaSize = numInUse + 2; + unsigned alphaSize = numInUse + 2; Byte *mtfs = m_MtfArray; UInt32 mtfArraySize = 0; UInt32 symbolCounts[kMaxAlphaSize]; { - for (int i = 0; i < kMaxAlphaSize; i++) + for (unsigned i = 0; i < kMaxAlphaSize; i++) symbolCounts[i] = 0; } @@ -360,17 +362,17 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) UInt32 numSymbols = 0; { - for (int i = 0; i < kMaxAlphaSize; i++) + for (unsigned i = 0; i < kMaxAlphaSize; i++) numSymbols += symbolCounts[i]; } - int bestNumTables = kNumTablesMin; + unsigned bestNumTables = kNumTablesMin; UInt32 bestPrice = 0xFFFFFFFF; UInt32 startPos = m_OutStreamCurrent->GetPos(); Byte startCurByte = m_OutStreamCurrent->GetCurByte(); - for (int nt = kNumTablesMin; nt <= kNumTablesMax + 1; nt++) + for (unsigned nt = kNumTablesMin; nt <= kNumTablesMax + 1; nt++) { - int numTables; + unsigned numTables; if (m_OptimizeNumTables) { @@ -397,21 +399,21 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) { UInt32 remFreq = numSymbols; - int gs = 0; - int t = numTables; + unsigned gs = 0; + unsigned t = numTables; do { UInt32 tFreq = remFreq / t; - int ge = gs; + unsigned ge = gs; UInt32 aFreq = 0; while (aFreq < tFreq) // && ge < alphaSize) aFreq += symbolCounts[ge++]; - if (ge - 1 > gs && t != numTables && t != 1 && (((numTables - t) & 1) == 1)) + if (ge > gs + 1 && t != numTables && t != 1 && (((numTables - t) & 1) == 1)) aFreq -= symbolCounts[--ge]; Byte *lens = Lens[t - 1]; - int i = 0; + unsigned i = 0; do lens[i] = (Byte)((i >= gs && i < ge) ? 0 : 1); while (++i < alphaSize); @@ -422,10 +424,10 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) } - for (int pass = 0; pass < kNumHuffPasses; pass++) + for (unsigned pass = 0; pass < kNumHuffPasses; pass++) { { - int t = 0; + unsigned t = 0; do memset(Freqs[t], 0, sizeof(Freqs[t])); while (++t < numTables); @@ -437,7 +439,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) do { UInt32 symbols[kGroupSize]; - int i = 0; + unsigned i = 0; do { UInt32 symbol = mtfs[mtfPos++]; @@ -448,12 +450,12 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) while (++i < kGroupSize && mtfPos < mtfArraySize); UInt32 bestPrice = 0xFFFFFFFF; - int t = 0; + unsigned t = 0; do { const Byte *lens = Lens[t]; UInt32 price = 0; - int j = 0; + unsigned j = 0; do price += lens[symbols[j]]; while (++j < i); @@ -465,7 +467,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) } while (++t < numTables); UInt32 *freqs = Freqs[m_Selectors[g++]]; - int j = 0; + unsigned j = 0; do freqs[symbols[j]]++; while (++j < i); @@ -473,11 +475,11 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) while (mtfPos < mtfArraySize); } - int t = 0; + unsigned t = 0; do { UInt32 *freqs = Freqs[t]; - int i = 0; + unsigned i = 0; do if (freqs[i] == 0) freqs[i] = 1; @@ -490,7 +492,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) { Byte mtfSel[kNumTablesMax]; { - int t = 0; + unsigned t = 0; do mtfSel[t] = (Byte)t; while (++t < numTables); @@ -500,10 +502,10 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) do { Byte sel = m_Selectors[i]; - int pos; + unsigned pos; for (pos = 0; mtfSel[pos] != sel; pos++) - WriteBit2(true); - WriteBit2(false); + WriteBit2(1); + WriteBit2(0); for (; pos > 0; pos--) mtfSel[pos] = mtfSel[pos - 1]; mtfSel[0] = sel; @@ -512,31 +514,31 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) } { - int t = 0; + unsigned t = 0; do { const Byte *lens = Lens[t]; UInt32 len = lens[0]; WriteBits2(len, kNumLevelsBits); - int i = 0; + unsigned i = 0; do { UInt32 level = lens[i]; while (len != level) { - WriteBit2(true); + WriteBit2(1); if (len < level) { - WriteBit2(false); + WriteBit2(0); len++; } else { - WriteBit2(true); + WriteBit2(1); len--; } } - WriteBit2(false); + WriteBit2(0); } while (++i < alphaSize); } @@ -557,7 +559,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) if (groupSize == 0) { groupSize = kGroupSize; - int t = m_Selectors[groupIndex++]; + unsigned t = m_Selectors[groupIndex++]; lens = Lens[t]; codes = Codes[t]; } @@ -591,7 +593,7 @@ UInt32 CThreadInfo::EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize) WriteByte2(kBlockSig5); CBZip2Crc crc; - int numReps = 0; + unsigned numReps = 0; Byte prevByte = block[0]; UInt32 i = 0; do diff --git a/CPP/7zip/Compress/BZip2Encoder.h b/CPP/7zip/Compress/BZip2Encoder.h index 6b04eca1..bf05f59f 100644 --- a/CPP/7zip/Compress/BZip2Encoder.h +++ b/CPP/7zip/Compress/BZip2Encoder.h @@ -85,7 +85,7 @@ public: class CEncoder; -const int kNumPassesMax = 10; +const unsigned kNumPassesMax = 10; class CThreadInfo { @@ -111,7 +111,7 @@ private: void WriteBits2(UInt32 value, unsigned numBits); void WriteByte2(Byte b); - void WriteBit2(bool v); + void WriteBit2(Byte v); void WriteCrc2(UInt32 v); void EncodeBlock(const Byte *block, UInt32 blockSize); @@ -198,7 +198,7 @@ public: void WriteBits(UInt32 value, unsigned numBits); void WriteByte(Byte b); - void WriteBit(bool v); + // void WriteBit(Byte v); void WriteCrc(UInt32 v); #ifndef _7ZIP_ST diff --git a/CPP/7zip/Compress/BZip2Register.cpp b/CPP/7zip/Compress/BZip2Register.cpp index ef14204b..0dd6ec9a 100644 --- a/CPP/7zip/Compress/BZip2Register.cpp +++ b/CPP/7zip/Compress/BZip2Register.cpp @@ -6,15 +6,13 @@ #include "BZip2Decoder.h" -static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NBZip2::CDecoder); } +REGISTER_CODEC_CREATE(CreateDec, NCompress::NBZip2::CDecoder) + #if !defined(EXTRACT_ONLY) && !defined(BZIP2_EXTRACT_ONLY) #include "BZip2Encoder.h" -static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NBZip2::CEncoder); } +REGISTER_CODEC_CREATE(CreateEnc, NCompress::NBZip2::CEncoder) #else -#define CreateCodecOut 0 +#define CreateEnc NULL #endif -static CCodecInfo g_CodecInfo = - { CreateCodec, CreateCodecOut, 0x040202, L"BZip2", 1, false }; - -REGISTER_CODEC(BZip2) +REGISTER_CODEC_2(BZip2, CreateDec, CreateEnc, 0x40202, "BZip2") diff --git a/CPP/7zip/Compress/Bcj2Coder.cpp b/CPP/7zip/Compress/Bcj2Coder.cpp index 2d737e8a..fd7ce7ef 100644 --- a/CPP/7zip/Compress/Bcj2Coder.cpp +++ b/CPP/7zip/Compress/Bcj2Coder.cpp @@ -4,363 +4,655 @@ #include "../../../C/Alloc.h" +#include "../Common/StreamUtils.h" + #include "Bcj2Coder.h" namespace NCompress { namespace NBcj2 { -inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); } -inline bool IsJ(Byte b0, Byte b1) { return ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)); } -inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == 0xE9) ? 256 : 257)); } - -#ifndef EXTRACT_ONLY - -static const unsigned kBufSize = 1 << 17; - -#define NUM_BITS 2 -#define SIGN_BIT (1 << NUM_BITS) -#define MASK_HIGH (0x100 - (1 << (NUM_BITS + 1))) - -static const UInt32 kDefaultLimit = (1 << (24 + NUM_BITS)); +CBaseCoder::CBaseCoder() +{ + for (int i = 0; i < BCJ2_NUM_STREAMS + 1; i++) + { + _bufs[i] = NULL; + _bufsCurSizes[i] = 0; + _bufsNewSizes[i] = (1 << 18); + } +} -static bool inline Test86MSByte(Byte b) +CBaseCoder::~CBaseCoder() { - return (((b) + SIGN_BIT) & MASK_HIGH) == 0; + for (int i = 0; i < BCJ2_NUM_STREAMS + 1; i++) + ::MidFree(_bufs[i]); } -CEncoder::~CEncoder() +HRESULT CBaseCoder::Alloc(bool allocForOrig) { - ::MidFree(_buf); + unsigned num = allocForOrig ? BCJ2_NUM_STREAMS + 1 : BCJ2_NUM_STREAMS; + for (unsigned i = 0; i < num; i++) + { + UInt32 newSize = _bufsNewSizes[i]; + const UInt32 kMinBufSize = 1; + if (newSize < kMinBufSize) + newSize = kMinBufSize; + if (!_bufs[i] || newSize != _bufsCurSizes[i]) + { + if (_bufs[i]) + { + ::MidFree(_bufs[i]); + _bufs[i] = 0; + } + _bufsCurSizes[i] = 0; + Byte *buf = (Byte *)::MidAlloc(newSize); + _bufs[i] = buf; + if (!buf) + return E_OUTOFMEMORY; + _bufsCurSizes[i] = newSize; + } + } + return S_OK; } -HRESULT CEncoder::Flush() + + +#ifndef EXTRACT_ONLY + +CEncoder::CEncoder(): _relatLim(BCJ2_RELAT_LIMIT) {} +CEncoder::~CEncoder() {} + +STDMETHODIMP CEncoder::SetInBufSize(UInt32, UInt32 size) { _bufsNewSizes[BCJ2_NUM_STREAMS] = size; return S_OK; } +STDMETHODIMP CEncoder::SetOutBufSize(UInt32 streamIndex, UInt32 size) { _bufsNewSizes[streamIndex] = size; return S_OK; } + +STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) { - RINOK(_mainStream.Flush()); - RINOK(_callStream.Flush()); - RINOK(_jumpStream.Flush()); - _rc.FlushData(); - return _rc.FlushStream(); + UInt32 relatLim = BCJ2_RELAT_LIMIT; + + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = props[i]; + PROPID propID = propIDs[i]; + if (propID >= NCoderPropID::kReduceSize) + continue; + switch (propID) + { + /* + case NCoderPropID::kDefaultProp: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 v = prop.ulVal; + if (v > 31) + return E_INVALIDARG; + relatLim = (UInt32)1 << v; + break; + } + */ + case NCoderPropID::kDictionarySize: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + relatLim = prop.ulVal; + if (relatLim > ((UInt32)1 << 31)) + return E_INVALIDARG; + break; + } + + case NCoderPropID::kNumThreads: + continue; + case NCoderPropID::kLevel: + continue; + + default: return E_INVALIDARG; + } + } + + _relatLim = relatLim; + + return S_OK; } -HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, - ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, + +HRESULT CEncoder::CodeReal(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, + ISequentialOutStream * const *outStreams, const UInt64 * const * /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { - if (numInStreams != 1 || numOutStreams != 4) + if (numInStreams != 1 || numOutStreams != BCJ2_NUM_STREAMS) return E_INVALIDARG; - if (!_mainStream.Create(1 << 18)) return E_OUTOFMEMORY; - if (!_callStream.Create(1 << 18)) return E_OUTOFMEMORY; - if (!_jumpStream.Create(1 << 18)) return E_OUTOFMEMORY; - if (!_rc.Create(1 << 20)) return E_OUTOFMEMORY; - if (_buf == 0) + RINOK(Alloc()); + + UInt32 fileSize_for_Conv = 0; + if (inSizes && inSizes[0]) { - _buf = (Byte *)MidAlloc(kBufSize); - if (_buf == 0) - return E_OUTOFMEMORY; + UInt64 inSize = *inSizes[0]; + if (inSize <= BCJ2_FileSize_MAX) + fileSize_for_Conv = (UInt32)inSize; } - bool sizeIsDefined = false; - UInt64 inSize = 0; - if (inSizes) - if (inSizes[0]) + CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize; + inStreams[0]->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize); + + CBcj2Enc enc; + + enc.src = _bufs[BCJ2_NUM_STREAMS]; + enc.srcLim = enc.src; + + { + for (int i = 0; i < BCJ2_NUM_STREAMS; i++) { - inSize = *inSizes[0]; - if (inSize <= kDefaultLimit) - sizeIsDefined = true; + enc.bufs[i] = _bufs[i]; + enc.lims[i] = _bufs[i] + _bufsCurSizes[i]; } + } - ISequentialInStream *inStream = inStreams[0]; + size_t numBytes_in_ReadBuf = 0; + UInt64 prevProgress = 0; + UInt64 totalStreamRead = 0; // size read from InputStream + UInt64 currentInPos = 0; // data that was processed, it doesn't include data in input buffer and data in enc.temp + UInt64 outSizeRc = 0; - _mainStream.SetStream(outStreams[0]); _mainStream.Init(); - _callStream.SetStream(outStreams[1]); _callStream.Init(); - _jumpStream.SetStream(outStreams[2]); _jumpStream.Init(); - _rc.SetStream(outStreams[3]); _rc.Init(); - for (unsigned i = 0; i < 256 + 2; i++) - _statusEncoder[i].Init(); + Bcj2Enc_Init(&enc); - CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize; - { - inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize); - } + enc.fileIp = 0; + enc.fileSize = fileSize_for_Conv; - UInt32 nowPos = 0; - UInt64 nowPos64 = 0; - UInt32 bufPos = 0; + enc.relatLimit = _relatLim; - Byte prevByte = 0; + enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE; + bool needSubSize = false; UInt64 subStreamIndex = 0; UInt64 subStreamStartPos = 0; - UInt64 subStreamEndPos = 0; + bool readWasFinished = false; for (;;) { - UInt32 processedSize = 0; - for (;;) - { - UInt32 size = kBufSize - (bufPos + processedSize); - UInt32 processedSizeLoc; - if (size == 0) - break; - RINOK(inStream->Read(_buf + bufPos + processedSize, size, &processedSizeLoc)); - if (processedSizeLoc == 0) - break; - processedSize += processedSizeLoc; - } - UInt32 endPos = bufPos + processedSize; - - if (endPos < 5) - { - // change it - for (bufPos = 0; bufPos < endPos; bufPos++) - { - Byte b = _buf[bufPos]; - _mainStream.WriteByte(b); - UInt32 index; - if (b == 0xE8) - index = prevByte; - else if (b == 0xE9) - index = 256; - else if (IsJcc(prevByte, b)) - index = 257; - else - { - prevByte = b; - continue; - } - _statusEncoder[index].Encode(&_rc, 0); - prevByte = b; - } - return Flush(); - } - - bufPos = 0; - - UInt32 limit = endPos - 5; - while (bufPos <= limit) + if (needSubSize && getSubStreamSize) { - Byte b = _buf[bufPos]; - _mainStream.WriteByte(b); - if (!IsJ(prevByte, b)) + enc.fileIp = 0; + enc.fileSize = fileSize_for_Conv; + enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE; + + for (;;) { - bufPos++; - prevByte = b; - continue; - } - Byte nextByte = _buf[bufPos + 4]; - UInt32 src = - (UInt32(nextByte) << 24) | - (UInt32(_buf[bufPos + 3]) << 16) | - (UInt32(_buf[bufPos + 2]) << 8) | - (_buf[bufPos + 1]); - UInt32 dest = (nowPos + bufPos + 5) + src; - // if (Test86MSByte(nextByte)) - bool convert; - if (getSubStreamSize) - { - UInt64 currentPos = (nowPos64 + bufPos); - while (subStreamEndPos < currentPos) + UInt64 subStreamSize = 0; + HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize); + needSubSize = false; + + if (result == S_OK) { - UInt64 subStreamSize; - HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize); - if (result == S_OK) + UInt64 newEndPos = subStreamStartPos + subStreamSize; + + bool isAccurateEnd = (newEndPos < totalStreamRead || + (newEndPos <= totalStreamRead && readWasFinished)); + + if (newEndPos <= currentInPos && isAccurateEnd) { - subStreamStartPos = subStreamEndPos; - subStreamEndPos += subStreamSize; + subStreamStartPos = newEndPos; subStreamIndex++; + continue; } - else if (result == S_FALSE || result == E_NOTIMPL) + + enc.srcLim = _bufs[BCJ2_NUM_STREAMS] + numBytes_in_ReadBuf; + + if (isAccurateEnd) { - getSubStreamSize.Release(); - subStreamStartPos = 0; - subStreamEndPos = subStreamStartPos - 1; + // data in enc.temp is possible here + size_t rem = (size_t)(totalStreamRead - newEndPos); + + /* Pos_of(enc.src) <= old newEndPos <= newEndPos + in another case, it's fail in some code */ + if ((size_t)(enc.srcLim - enc.src) < rem) + return E_FAIL; + + enc.srcLim -= rem; + enc.finishMode = BCJ2_ENC_FINISH_MODE_END_BLOCK; } - else - return result; - } - if (getSubStreamSize == NULL) - { - if (sizeIsDefined) - convert = (dest < inSize); - else - convert = Test86MSByte(nextByte); + + if (subStreamSize <= BCJ2_FileSize_MAX) + { + enc.fileIp = enc.ip + (UInt32)(subStreamStartPos - currentInPos); + enc.fileSize = (UInt32)subStreamSize; + } + break; } - else if (subStreamEndPos - subStreamStartPos > kDefaultLimit) - convert = Test86MSByte(nextByte); - else + + if (result == S_FALSE) + break; + if (result == E_NOTIMPL) { - UInt64 dest64 = (currentPos + 5) + Int64(Int32(src)); - convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos); + getSubStreamSize.Release(); + break; } + return result; } - else if (sizeIsDefined) - convert = (dest < inSize); - else - convert = Test86MSByte(nextByte); - unsigned index = GetIndex(prevByte, b); - if (convert) + } + + if (readWasFinished && totalStreamRead - currentInPos == Bcj2Enc_Get_InputData_Size(&enc)) + enc.finishMode = BCJ2_ENC_FINISH_MODE_END_STREAM; + + Bcj2Enc_Encode(&enc); + + currentInPos = totalStreamRead - numBytes_in_ReadBuf + (enc.src - _bufs[BCJ2_NUM_STREAMS]) - enc.tempPos; + + if (Bcj2Enc_IsFinished(&enc)) + break; + + if (enc.state < BCJ2_NUM_STREAMS) + { + size_t curSize = enc.bufs[enc.state] - _bufs[enc.state]; + // printf("Write stream = %2d %6d\n", enc.state, curSize); + RINOK(WriteStream(outStreams[enc.state], _bufs[enc.state], curSize)); + if (enc.state == BCJ2_STREAM_RC) + outSizeRc += curSize; + + enc.bufs[enc.state] = _bufs[enc.state]; + enc.lims[enc.state] = _bufs[enc.state] + _bufsCurSizes[enc.state]; + } + else if (enc.state != BCJ2_ENC_STATE_ORIG) + return E_FAIL; + else + { + needSubSize = true; + + if (numBytes_in_ReadBuf != (size_t)(enc.src - _bufs[BCJ2_NUM_STREAMS])) { - _statusEncoder[index].Encode(&_rc, 1); - bufPos += 5; - COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; - for (int i = 24; i >= 0; i -= 8) - s.WriteByte((Byte)(dest >> i)); - prevByte = nextByte; + enc.srcLim = _bufs[BCJ2_NUM_STREAMS] + numBytes_in_ReadBuf; + continue; } - else + + if (readWasFinished) + continue; + + numBytes_in_ReadBuf = 0; + enc.src = _bufs[BCJ2_NUM_STREAMS]; + enc.srcLim = _bufs[BCJ2_NUM_STREAMS]; + + UInt32 curSize = _bufsCurSizes[BCJ2_NUM_STREAMS]; + RINOK(inStreams[0]->Read(_bufs[BCJ2_NUM_STREAMS], curSize, &curSize)); + + // printf("Read %6d bytes\n", curSize); + if (curSize == 0) { - _statusEncoder[index].Encode(&_rc, 0); - bufPos++; - prevByte = b; + readWasFinished = true; + continue; } + + numBytes_in_ReadBuf = curSize; + totalStreamRead += numBytes_in_ReadBuf; + enc.srcLim = _bufs[BCJ2_NUM_STREAMS] + numBytes_in_ReadBuf; } - nowPos += bufPos; - nowPos64 += bufPos; - if (progress) + if (progress && currentInPos - prevProgress >= (1 << 20)) { - /* - const UInt64 compressedSize = - _mainStream.GetProcessedSize() + - _callStream.GetProcessedSize() + - _jumpStream.GetProcessedSize() + - _rc.GetProcessedSize(); - */ - RINOK(progress->SetRatioInfo(&nowPos64, NULL)); + UInt64 outSize2 = currentInPos + outSizeRc + enc.bufs[BCJ2_STREAM_RC] - enc.bufs[BCJ2_STREAM_RC]; + prevProgress = currentInPos; + // printf("progress %8d, %8d\n", (int)inSize2, (int)outSize2); + RINOK(progress->SetRatioInfo(¤tInPos, &outSize2)); } - - UInt32 i = 0; - while (bufPos < endPos) - _buf[i++] = _buf[bufPos++]; - bufPos = i; } + + for (int i = 0; i < BCJ2_NUM_STREAMS; i++) + { + RINOK(WriteStream(outStreams[i], _bufs[i], enc.bufs[i] - _bufs[i])); + } + + // if (currentInPos != subStreamStartPos + subStreamSize) return E_FAIL; + + return S_OK; } -STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, - ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, +STDMETHODIMP CEncoder::Code(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, + ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } - catch(const COutBufferException &e) { return e.ErrorCode; } - catch(...) { return S_FALSE; } + catch(...) { return E_FAIL; } } #endif -STDMETHODIMP CDecoder::SetInBufSize(UInt32 streamIndex, UInt32 size) { _inBufSizes[streamIndex] = size; return S_OK; } -STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; } -CDecoder::CDecoder(): - _outBufSize(1 << 16) + + + +STDMETHODIMP CDecoder::SetInBufSize(UInt32 streamIndex, UInt32 size) { _bufsNewSizes[streamIndex] = size; return S_OK; } +STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _bufsNewSizes[BCJ2_NUM_STREAMS] = size; return S_OK; } + +CDecoder::CDecoder(): _finishMode(false), _outSizeDefined(false), _outSize(0) +{} + +STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode) { - _inBufSizes[0] = 1 << 20; - _inBufSizes[1] = 1 << 20; - _inBufSizes[2] = 1 << 20; - _inBufSizes[3] = 1 << 20; + _finishMode = (finishMode != 0); + return S_OK; } -HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams, - ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, +void CDecoder::InitCommon() +{ + { + for (int i = 0; i < BCJ2_NUM_STREAMS; i++) + dec.lims[i] = dec.bufs[i] = _bufs[i]; + } + + { + for (int i = 0; i < BCJ2_NUM_STREAMS; i++) + { + _extraReadSizes[i] = 0; + _inStreamsProcessed[i] = 0; + _readRes[i] = S_OK; + } + } + + Bcj2Dec_Init(&dec); +} + +HRESULT CDecoder::Code(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, + ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { - if (numInStreams != 4 || numOutStreams != 1) + if (numInStreams != BCJ2_NUM_STREAMS || numOutStreams != 1) return E_INVALIDARG; - if (!_mainStream.Create(_inBufSizes[0])) return E_OUTOFMEMORY; - if (!_callStream.Create(_inBufSizes[1])) return E_OUTOFMEMORY; - if (!_jumpStream.Create(_inBufSizes[2])) return E_OUTOFMEMORY; - if (!_rc.Create(_inBufSizes[3])) return E_OUTOFMEMORY; - if (!_outStream.Create(_outBufSize)) return E_OUTOFMEMORY; - - _mainStream.SetStream(inStreams[0]); - _callStream.SetStream(inStreams[1]); - _jumpStream.SetStream(inStreams[2]); - _rc.SetStream(inStreams[3]); - _outStream.SetStream(outStreams[0]); - - _mainStream.Init(); - _callStream.Init(); - _jumpStream.Init(); - _rc.Init(); - _outStream.Init(); - - for (unsigned i = 0; i < 256 + 2; i++) - _statusDecoder[i].Init(); - - Byte prevByte = 0; - UInt32 processedBytes = 0; + RINOK(Alloc()); + + InitCommon(); + + dec.destLim = dec.dest = _bufs[BCJ2_NUM_STREAMS]; + + UInt64 outSizeProcessed = 0; + UInt64 prevProgress = 0; + + HRESULT res = S_OK; + for (;;) { - if (processedBytes >= (1 << 20) && progress) + if (Bcj2Dec_Decode(&dec) != SZ_OK) + return S_FALSE; + + if (dec.state < BCJ2_NUM_STREAMS) { - /* - const UInt64 compressedSize = - _mainStream.GetProcessedSize() + - _callStream.GetProcessedSize() + - _jumpStream.GetProcessedSize() + - _rc.GetProcessedSize(); - */ - const UInt64 nowPos64 = _outStream.GetProcessedSize(); - RINOK(progress->SetRatioInfo(NULL, &nowPos64)); - processedBytes = 0; + size_t totalRead = _extraReadSizes[dec.state]; + { + Byte *buf = _bufs[dec.state]; + for (size_t i = 0; i < totalRead; i++) + buf[i] = dec.bufs[dec.state][i]; + dec.lims[dec.state] = + dec.bufs[dec.state] = buf; + } + + if (_readRes[dec.state] != S_OK) + { + res = _readRes[dec.state]; + break; + } + + do + { + UInt32 curSize = _bufsCurSizes[dec.state] - (UInt32)totalRead; + /* + we want to call Read even even if size is 0 + if (inSizes && inSizes[dec.state]) + { + UInt64 rem = *inSizes[dec.state] - _inStreamsProcessed[dec.state]; + if (curSize > rem) + curSize = (UInt32)rem; + } + */ + + HRESULT res2 = inStreams[dec.state]->Read(_bufs[dec.state] + totalRead, curSize, &curSize); + _readRes[dec.state] = res2; + if (curSize == 0) + break; + _inStreamsProcessed[dec.state] += curSize; + totalRead += curSize; + if (res2 != S_OK) + break; + } + while (totalRead < 4 && BCJ2_IS_32BIT_STREAM(dec.state)); + + if (_readRes[dec.state] != S_OK) + res = _readRes[dec.state]; + + if (totalRead == 0) + break; + + // res == S_OK; + + if (BCJ2_IS_32BIT_STREAM(dec.state)) + { + unsigned extraSize = ((unsigned)totalRead & 3); + _extraReadSizes[dec.state] = extraSize; + if (totalRead < 4) + { + res = (_readRes[dec.state] != S_OK) ? _readRes[dec.state] : S_FALSE; + break; + } + totalRead -= extraSize; + } + + dec.lims[dec.state] = _bufs[dec.state] + totalRead; } - UInt32 i; - Byte b = 0; - const UInt32 kBurstSize = (1 << 18); - for (i = 0; i < kBurstSize; i++) + else // if (dec.state <= BCJ2_STATE_ORIG) { - if (!_mainStream.ReadByte(b)) - return _outStream.Flush(); - _outStream.WriteByte(b); - if (IsJ(prevByte, b)) - break; - prevByte = b; + size_t curSize = dec.dest - _bufs[BCJ2_NUM_STREAMS]; + if (curSize != 0) + { + outSizeProcessed += curSize; + RINOK(WriteStream(outStreams[0], _bufs[BCJ2_NUM_STREAMS], curSize)); + } + dec.dest = _bufs[BCJ2_NUM_STREAMS]; + { + size_t rem = _bufsCurSizes[BCJ2_NUM_STREAMS]; + if (outSizes && outSizes[0]) + { + UInt64 outSize = *outSizes[0] - outSizeProcessed; + if (rem > outSize) + rem = (size_t)outSize; + } + dec.destLim = dec.dest + rem; + if (rem == 0) + break; + } } - processedBytes += i; - if (i == kBurstSize) - continue; - unsigned index = GetIndex(prevByte, b); - if (_statusDecoder[index].Decode(&_rc) == 1) + + if (progress) { - UInt32 src = 0; - CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; - for (unsigned i = 0; i < 4; i++) + UInt64 outSize2 = outSizeProcessed + (dec.dest - _bufs[BCJ2_NUM_STREAMS]); + if (outSize2 - prevProgress >= (1 << 22)) { - Byte b0; - if (!s.ReadByte(b0)) + UInt64 inSize2 = outSize2 + _inStreamsProcessed[BCJ2_STREAM_RC] - (dec.lims[BCJ2_STREAM_RC] - dec.bufs[BCJ2_STREAM_RC]); + RINOK(progress->SetRatioInfo(&inSize2, &outSize2)); + prevProgress = outSize2; + } + } + } + + size_t curSize = dec.dest - _bufs[BCJ2_NUM_STREAMS]; + if (curSize != 0) + { + outSizeProcessed += curSize; + RINOK(WriteStream(outStreams[0], _bufs[BCJ2_NUM_STREAMS], curSize)); + } + + if (res != S_OK) + return res; + + if (_finishMode) + { + if (!Bcj2Dec_IsFinished(&dec)) + return S_FALSE; + + // we still allow the cases when input streams are larger than required for decoding. + // so the case (dec.state == BCJ2_STATE_ORIG) is also allowed, if MAIN stream is larger than required. + if (dec.state != BCJ2_STREAM_MAIN && + dec.state != BCJ2_DEC_STATE_ORIG) + return S_FALSE; + + if (inSizes) + { + for (int i = 0; i < BCJ2_NUM_STREAMS; i++) + { + size_t rem = dec.lims[i] - dec.bufs[i] + _extraReadSizes[i]; + /* + if (rem != 0) + return S_FALSE; + */ + if (inSizes[i] && *inSizes[i] != _inStreamsProcessed[i] - rem) return S_FALSE; - src <<= 8; - src |= ((UInt32)b0); } - UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ; - _outStream.WriteByte((Byte)(dest)); - _outStream.WriteByte((Byte)(dest >> 8)); - _outStream.WriteByte((Byte)(dest >> 16)); - _outStream.WriteByte((Byte)(dest >> 24)); - prevByte = (Byte)(dest >> 24); - processedBytes += 4; } - else - prevByte = b; } + + return S_OK; } -STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, - ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, - ICompressProgressInfo *progress) +STDMETHODIMP CDecoder::SetInStream2(UInt32 streamIndex, ISequentialInStream *inStream) { - try + inStreams[streamIndex] = inStream; + return S_OK; +} + +STDMETHODIMP CDecoder::ReleaseInStream2(UInt32 streamIndex) +{ + inStreams[streamIndex].Release(); + return S_OK; +} + +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) +{ + _outSizeDefined = (outSize != NULL); + _outSize = 0; + if (_outSizeDefined) + _outSize = *outSize; + + _outSize_Processed = 0; + + HRESULT res = Alloc(false); + + InitCommon(); + dec.destLim = dec.dest = NULL; + + return res; +} + + +STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + + if (size == 0) + return S_OK; + + UInt32 totalProcessed = 0; + + if (_outSizeDefined) { - return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); + UInt64 rem = _outSize - _outSize_Processed; + if (size > rem) + size = (UInt32)rem; + } + dec.dest = (Byte *)data; + dec.destLim = (const Byte *)data + size; + + HRESULT res = S_OK; + + for (;;) + { + SRes sres = Bcj2Dec_Decode(&dec); + if (sres != SZ_OK) + return S_FALSE; + + { + UInt32 curSize = (UInt32)(dec.dest - (Byte *)data); + if (curSize != 0) + { + totalProcessed += curSize; + if (processedSize) + *processedSize = totalProcessed; + data = (void *)((Byte *)data + curSize); + size -= curSize; + _outSize_Processed += curSize; + } + } + + if (dec.state >= BCJ2_NUM_STREAMS) + break; + + { + size_t totalRead = _extraReadSizes[dec.state]; + { + Byte *buf = _bufs[dec.state]; + for (size_t i = 0; i < totalRead; i++) + buf[i] = dec.bufs[dec.state][i]; + dec.lims[dec.state] = + dec.bufs[dec.state] = buf; + } + + if (_readRes[dec.state] != S_OK) + return _readRes[dec.state]; + + do + { + UInt32 curSize = _bufsCurSizes[dec.state] - (UInt32)totalRead; + HRESULT res2 = inStreams[dec.state]->Read(_bufs[dec.state] + totalRead, curSize, &curSize); + _readRes[dec.state] = res2; + if (curSize == 0) + break; + _inStreamsProcessed[dec.state] += curSize; + totalRead += curSize; + if (res2 != S_OK) + break; + } + while (totalRead < 4 && BCJ2_IS_32BIT_STREAM(dec.state)); + + if (totalRead == 0) + { + if (totalProcessed == 0) + res = _readRes[dec.state]; + break; + } + + if (BCJ2_IS_32BIT_STREAM(dec.state)) + { + unsigned extraSize = ((unsigned)totalRead & 3); + _extraReadSizes[dec.state] = extraSize; + if (totalRead < 4) + { + if (totalProcessed != 0) + return S_OK; + return (_readRes[dec.state] != S_OK) ? _readRes[dec.state] : S_FALSE; + } + totalRead -= extraSize; + } + + dec.lims[dec.state] = _bufs[dec.state] + totalRead; + } + } + + if (_finishMode && _outSizeDefined && _outSize == _outSize_Processed) + { + if (!Bcj2Dec_IsFinished(&dec)) + return S_FALSE; + + if (dec.state != BCJ2_STREAM_MAIN && + dec.state != BCJ2_DEC_STATE_ORIG) + return S_FALSE; + + /* + for (int i = 0; i < BCJ2_NUM_STREAMS; i++) + if (dec.bufs[i] != dec.lims[i] || _extraReadSizes[i] != 0) + return S_FALSE; + */ } - catch(const CInBufferException &e) { return e.ErrorCode; } - catch(const COutBufferException &e) { return e.ErrorCode; } - catch(...) { return S_FALSE; } + + return res; } }} diff --git a/CPP/7zip/Compress/Bcj2Coder.h b/CPP/7zip/Compress/Bcj2Coder.h index d2b3bda3..627e505d 100644 --- a/CPP/7zip/Compress/Bcj2Coder.h +++ b/CPP/7zip/Compress/Bcj2Coder.h @@ -3,44 +3,57 @@ #ifndef __COMPRESS_BCJ2_CODER_H #define __COMPRESS_BCJ2_CODER_H +#include "../../../C/Bcj2.h" + #include "../../Common/MyCom.h" #include "../ICoder.h" -#include "RangeCoderBit.h" - namespace NCompress { namespace NBcj2 { -const unsigned kNumMoveBits = 5; +class CBaseCoder +{ +protected: + Byte *_bufs[BCJ2_NUM_STREAMS + 1]; + UInt32 _bufsCurSizes[BCJ2_NUM_STREAMS + 1]; + UInt32 _bufsNewSizes[BCJ2_NUM_STREAMS + 1]; + + HRESULT Alloc(bool allocForOrig = true); +public: + CBaseCoder(); + ~CBaseCoder(); +}; + #ifndef EXTRACT_ONLY class CEncoder: public ICompressCoder2, - public CMyUnknownImp + public ICompressSetCoderProperties, + public ICompressSetBufSize, + public CMyUnknownImp, + public CBaseCoder { - Byte *_buf; - - COutBuffer _mainStream; - COutBuffer _callStream; - COutBuffer _jumpStream; - NRangeCoder::CEncoder _rc; - NRangeCoder::CBitEncoder<kNumMoveBits> _statusEncoder[256 + 2]; + UInt32 _relatLim; - HRESULT Flush(); + HRESULT CodeReal(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, + ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams, + ICompressProgressInfo *progress); public: - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP3(ICompressCoder2, ICompressSetCoderProperties, ICompressSetBufSize) - HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, - ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, - ICompressProgressInfo *progress); - STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, - ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, + STDMETHOD(Code)(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, + ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); + + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); - CEncoder(): _buf(0) {}; + STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size); + STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size); + + CEncoder(); ~CEncoder(); }; @@ -48,29 +61,51 @@ public: class CDecoder: public ICompressCoder2, + public ICompressSetFinishMode, + public ICompressSetInStream2, + public ISequentialInStream, + public ICompressSetOutStreamSize, public ICompressSetBufSize, - public CMyUnknownImp + public CMyUnknownImp, + public CBaseCoder { - CInBuffer _mainStream; - CInBuffer _callStream; - CInBuffer _jumpStream; - NRangeCoder::CDecoder _rc; - NRangeCoder::CBitDecoder<kNumMoveBits> _statusDecoder[256 + 2]; - - COutBuffer _outStream; - UInt32 _inBufSizes[4]; - UInt32 _outBufSize; - + unsigned _extraReadSizes[BCJ2_NUM_STREAMS]; + UInt64 _inStreamsProcessed[BCJ2_NUM_STREAMS]; + HRESULT _readRes[BCJ2_NUM_STREAMS]; + CMyComPtr<ISequentialInStream> inStreams[BCJ2_NUM_STREAMS]; + + bool _finishMode; + bool _outSizeDefined; + UInt64 _outSize; + UInt64 _outSize_Processed; + CBcj2Dec dec; + + void InitCommon(); + // HRESULT ReadSpec(); + public: - MY_UNKNOWN_IMP1(ICompressSetBufSize); + MY_UNKNOWN_IMP6( + ICompressCoder2, + ICompressSetFinishMode, + ICompressSetInStream2, + ISequentialInStream, + ICompressSetOutStreamSize, + ICompressSetBufSize + ); - HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, - ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, - ICompressProgressInfo *progress); - STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, - ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, + STDMETHOD(Code)(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, + ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); + STDMETHOD(SetFinishMode)(UInt32 finishMode); + + STDMETHOD(SetInStream2)(UInt32 streamIndex, ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream2)(UInt32 streamIndex); + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size); STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size); diff --git a/CPP/7zip/Compress/Bcj2Register.cpp b/CPP/7zip/Compress/Bcj2Register.cpp index 8eb1e736..ef37ae0c 100644 --- a/CPP/7zip/Compress/Bcj2Register.cpp +++ b/CPP/7zip/Compress/Bcj2Register.cpp @@ -6,14 +6,14 @@ #include "Bcj2Coder.h" -static void *CreateCodec() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CDecoder()); } +REGISTER_CODEC_CREATE_2(CreateCodec, NCompress::NBcj2::CDecoder(), ICompressCoder2) #ifndef EXTRACT_ONLY -static void *CreateCodecOut() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CEncoder()); } +REGISTER_CODEC_CREATE_2(CreateCodecOut, NCompress::NBcj2::CEncoder(), ICompressCoder2) #else -#define CreateCodecOut 0 +#define CreateCodecOut NULL #endif -static CCodecInfo g_CodecInfo = - { CreateCodec, CreateCodecOut, 0x0303011B, L"BCJ2", 4, false }; +REGISTER_CODEC_VAR + { CreateCodec, CreateCodecOut, 0x303011B, "BCJ2", 4, false }; REGISTER_CODEC(BCJ2) diff --git a/CPP/7zip/Compress/BcjCoder.cpp b/CPP/7zip/Compress/BcjCoder.cpp index 0e34ef48..37815dce 100644 --- a/CPP/7zip/Compress/BcjCoder.cpp +++ b/CPP/7zip/Compress/BcjCoder.cpp @@ -4,12 +4,16 @@ #include "BcjCoder.h" -UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size) +STDMETHODIMP CBcjCoder::Init() { - return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 1); + _bufferPos = 0; + x86_Convert_Init(_prevMask); + return S_OK; } -UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size) +STDMETHODIMP_(UInt32) CBcjCoder::Filter(Byte *data, UInt32 size) { - return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 0); + UInt32 processed = (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, _encode); + _bufferPos += processed; + return processed; } diff --git a/CPP/7zip/Compress/BcjCoder.h b/CPP/7zip/Compress/BcjCoder.h index 0754bcd2..275fd4f2 100644 --- a/CPP/7zip/Compress/BcjCoder.h +++ b/CPP/7zip/Compress/BcjCoder.h @@ -5,15 +5,22 @@ #include "../../../C/Bra.h" -#include "BranchCoder.h" +#include "../../Common/MyCom.h" -struct CBranch86 +#include "../ICoder.h" + +class CBcjCoder: + public ICompressFilter, + public CMyUnknownImp { + UInt32 _bufferPos; UInt32 _prevMask; - void x86Init() { x86_Convert_Init(_prevMask); } -}; + int _encode; +public: + MY_UNKNOWN_IMP; + INTERFACE_ICompressFilter(;) -MyClassB(BCJ_x86, 0x01, 3, CBranch86 , - virtual void SubInit() { x86Init(); }) + CBcjCoder(int encode): _bufferPos(0), _encode(encode) { x86_Convert_Init(_prevMask); } +}; #endif diff --git a/CPP/7zip/Compress/BcjRegister.cpp b/CPP/7zip/Compress/BcjRegister.cpp index 648ad8e0..83c6830f 100644 --- a/CPP/7zip/Compress/BcjRegister.cpp +++ b/CPP/7zip/Compress/BcjRegister.cpp @@ -6,14 +6,7 @@ #include "BcjCoder.h" -static void *CreateCodec() { return (void *)(ICompressFilter *)(new CBCJ_x86_Decoder()); } -#ifndef EXTRACT_ONLY -static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new CBCJ_x86_Encoder()); } -#else -#define CreateCodecOut 0 -#endif - -static CCodecInfo g_CodecInfo = - { CreateCodec, CreateCodecOut, 0x03030103, L"BCJ", 1, true }; - -REGISTER_CODEC(BCJ) +REGISTER_FILTER_E(BCJ, + CBcjCoder(false), + CBcjCoder(true), + 0x3030103, "BCJ") diff --git a/CPP/7zip/Compress/BitmDecoder.h b/CPP/7zip/Compress/BitmDecoder.h index fef20e06..9b1c540e 100644 --- a/CPP/7zip/Compress/BitmDecoder.h +++ b/CPP/7zip/Compress/BitmDecoder.h @@ -72,7 +72,22 @@ public: return res; } + /* + unsigned ReadBit() + { + UInt32 res = ((_value >> (8 - _bitPos)) & kMask) >> (kNumValueBits - 1); + if (++_bitPos >= 8) + { + _value = (_value << 8) | _stream.ReadByte(); + _bitPos -= 8; + } + return (unsigned)res; + } + */ + void AlignToByte() { MovePos((kNumBigValueBits - _bitPos) & 7); } + + UInt32 ReadAlignBits() { return ReadBits((kNumBigValueBits - _bitPos) & 7); } }; } diff --git a/CPP/7zip/Compress/BranchCoder.cpp b/CPP/7zip/Compress/BranchCoder.cpp deleted file mode 100644 index 43170952..00000000 --- a/CPP/7zip/Compress/BranchCoder.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// BranchCoder.cpp - -#include "StdAfx.h" - -#include "BranchCoder.h" - -STDMETHODIMP CBranchConverter::Init() -{ - _bufferPos = 0; - SubInit(); - return S_OK; -} - -STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size) -{ - UInt32 processedSize = SubFilter(data, size); - _bufferPos += processedSize; - return processedSize; -} diff --git a/CPP/7zip/Compress/BranchCoder.h b/CPP/7zip/Compress/BranchCoder.h deleted file mode 100644 index 0e3a5c4e..00000000 --- a/CPP/7zip/Compress/BranchCoder.h +++ /dev/null @@ -1,44 +0,0 @@ -// BranchCoder.h - -#ifndef __COMPRESS_BRANCH_CODER_H -#define __COMPRESS_BRANCH_CODER_H - -#include "../../Common/MyCom.h" - -#include "../ICoder.h" - -class CBranchConverter: - public ICompressFilter, - public CMyUnknownImp -{ -protected: - UInt32 _bufferPos; - virtual void SubInit() {} - virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0; -public: - MY_UNKNOWN_IMP; - STDMETHOD(Init)(); - STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); -}; - -#define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \ - { public: UInt32 SubFilter(Byte *data, UInt32 size); }; - -#define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \ - { public: UInt32 SubFilter(Byte *data, UInt32 size); }; - -#define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ - { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; - -#define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ - { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; - -#define MyClassA(Name, id, subId) \ -MyClassEncoderA(Name ## _Encoder) \ -MyClassDecoderA(Name ## _Decoder) - -#define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT) \ -MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \ -MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT) - -#endif diff --git a/CPP/7zip/Compress/BranchMisc.cpp b/CPP/7zip/Compress/BranchMisc.cpp index 239f2513..0bf39b79 100644 --- a/CPP/7zip/Compress/BranchMisc.cpp +++ b/CPP/7zip/Compress/BranchMisc.cpp @@ -2,20 +2,17 @@ #include "StdAfx.h" -#include "../../../C/Bra.h" - #include "BranchMisc.h" -#define SUB_FILTER_IMP2(name, coderStr, coderNum) \ - UInt32 CBC_ ## name ## coderStr::SubFilter(Byte *data, UInt32 size) \ - { return (UInt32)::name ## Convert(data, size, _bufferPos, coderNum); } - -#define SUB_FILTER_IMP(name) \ - SUB_FILTER_IMP2(name, Encoder, 1) \ - SUB_FILTER_IMP2(name, Decoder, 0) \ +STDMETHODIMP CBranchCoder::Init() +{ + _bufferPos = 0; + return S_OK; +} -SUB_FILTER_IMP(ARM_) -SUB_FILTER_IMP(ARMT_) -SUB_FILTER_IMP(PPC_) -SUB_FILTER_IMP(SPARC_) -SUB_FILTER_IMP(IA64_) +STDMETHODIMP_(UInt32) CBranchCoder::Filter(Byte *data, UInt32 size) +{ + UInt32 processed = (UInt32)BraFunc(data, size, _bufferPos, _encode); + _bufferPos += processed; + return processed; +} diff --git a/CPP/7zip/Compress/BranchMisc.h b/CPP/7zip/Compress/BranchMisc.h index 81198b21..bbb5add9 100644 --- a/CPP/7zip/Compress/BranchMisc.h +++ b/CPP/7zip/Compress/BranchMisc.h @@ -3,12 +3,28 @@ #ifndef __COMPRESS_BRANCH_MISC_H #define __COMPRESS_BRANCH_MISC_H -#include "BranchCoder.h" +#include "../../Common/MyCom.h" -MyClassA(BC_ARM, 0x05, 1) -MyClassA(BC_ARMT, 0x07, 1) -MyClassA(BC_PPC, 0x02, 5) -MyClassA(BC_SPARC, 0x08, 5) -MyClassA(BC_IA64, 0x04, 1) +#include "../ICoder.h" + +EXTERN_C_BEGIN + +typedef SizeT (*Func_Bra)(Byte *data, SizeT size, UInt32 ip, int encoding); + +EXTERN_C_END + +class CBranchCoder: + public ICompressFilter, + public CMyUnknownImp +{ + UInt32 _bufferPos; + int _encode; + Func_Bra BraFunc; +public: + MY_UNKNOWN_IMP; + INTERFACE_ICompressFilter(;) + + CBranchCoder(Func_Bra bra, int encode): _bufferPos(0), _encode(encode), BraFunc(bra) {} +}; #endif diff --git a/CPP/7zip/Compress/BranchRegister.cpp b/CPP/7zip/Compress/BranchRegister.cpp index 380828c6..e1fcff6d 100644 --- a/CPP/7zip/Compress/BranchRegister.cpp +++ b/CPP/7zip/Compress/BranchRegister.cpp @@ -2,29 +2,35 @@ #include "StdAfx.h" +#include "../../../C/Bra.h" + #include "../Common/RegisterCodec.h" #include "BranchMisc.h" -#define CREATE_CODEC(x) \ - static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## _Decoder); } \ - static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## _Encoder); } +#define CREATE_BRA(n) \ + REGISTER_FILTER_CREATE(CreateBra_Decoder_ ## n, CBranchCoder(n ## _Convert, false)) \ + REGISTER_FILTER_CREATE(CreateBra_Encoder_ ## n, CBranchCoder(n ## _Convert, true)) \ -CREATE_CODEC(BC_PPC) -CREATE_CODEC(BC_IA64) -CREATE_CODEC(BC_ARM) -CREATE_CODEC(BC_ARMT) -CREATE_CODEC(BC_SPARC) +CREATE_BRA(PPC) +CREATE_BRA(IA64) +CREATE_BRA(ARM) +CREATE_BRA(ARMT) +CREATE_BRA(SPARC) -#define METHOD_ITEM(x, id1, id2, name) { CreateCodec ## x, CreateCodec ## x ## Out, 0x03030000 + (id1 * 256) + id2, name, 1, true } +#define METHOD_ITEM(n, id, name) \ + REGISTER_FILTER_ITEM( \ + CreateBra_Decoder_ ## n, \ + CreateBra_Encoder_ ## n, \ + 0x3030000 + id, name) -static CCodecInfo g_CodecsInfo[] = +REGISTER_CODECS_VAR { - METHOD_ITEM(BC_PPC, 0x02, 0x05, L"PPC"), - METHOD_ITEM(BC_IA64, 0x04, 1, L"IA64"), - METHOD_ITEM(BC_ARM, 0x05, 1, L"ARM"), - METHOD_ITEM(BC_ARMT, 0x07, 1, L"ARMT"), - METHOD_ITEM(BC_SPARC, 0x08, 0x05, L"SPARC") + METHOD_ITEM(PPC, 0x205, "PPC"), + METHOD_ITEM(IA64, 0x401, "IA64"), + METHOD_ITEM(ARM, 0x501, "ARM"), + METHOD_ITEM(ARMT, 0x701, "ARMT"), + METHOD_ITEM(SPARC, 0x805, "SPARC") }; REGISTER_CODECS(Branch) diff --git a/CPP/7zip/Compress/ByteSwap.cpp b/CPP/7zip/Compress/ByteSwap.cpp index 645b6ffc..f5620d6c 100644 --- a/CPP/7zip/Compress/ByteSwap.cpp +++ b/CPP/7zip/Compress/ByteSwap.cpp @@ -14,8 +14,7 @@ class CByteSwap2: { public: MY_UNKNOWN_IMP - STDMETHOD(Init)(); - STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); + INTERFACE_ICompressFilter(;) }; class CByteSwap4: @@ -24,8 +23,7 @@ class CByteSwap4: { public: MY_UNKNOWN_IMP - STDMETHOD(Init)(); - STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); + INTERFACE_ICompressFilter(;) }; STDMETHODIMP CByteSwap2::Init() { return S_OK; } @@ -33,14 +31,22 @@ STDMETHODIMP CByteSwap2::Init() { return S_OK; } STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size) { const UInt32 kStep = 2; - UInt32 i; - for (i = 0; i + kStep <= size; i += kStep) + if (size < kStep) + return 0; + size &= ~(kStep - 1); + + const Byte *end = data + (size_t)size; + + do { - Byte b = data[i]; - data[i] = data[i + 1]; - data[i + 1] = b; + Byte b0 = data[0]; + data[0] = data[1]; + data[1] = b0; + data += kStep; } - return i; + while (data != end); + + return size; } STDMETHODIMP CByteSwap4::Init() { return S_OK; } @@ -48,26 +54,34 @@ STDMETHODIMP CByteSwap4::Init() { return S_OK; } STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size) { const UInt32 kStep = 4; - UInt32 i; - for (i = 0; i + kStep <= size; i += kStep) + if (size < kStep) + return 0; + size &= ~(kStep - 1); + + const Byte *end = data + (size_t)size; + + do { - Byte b0 = data[i]; - Byte b1 = data[i + 1]; - data[i] = data[i + 3]; - data[i + 1] = data[i + 2]; - data[i + 2] = b1; - data[i + 3] = b0; + Byte b0 = data[0]; + Byte b1 = data[1]; + data[0] = data[3]; + data[1] = data[2]; + data[2] = b1; + data[3] = b0; + data += kStep; } - return i; + while (data != end); + + return size; } -static void *CreateCodec2() { return (void *)(ICompressFilter *)(new CByteSwap2); } -static void *CreateCodec4() { return (void *)(ICompressFilter *)(new CByteSwap4); } +REGISTER_FILTER_CREATE(CreateFilter2, CByteSwap2()) +REGISTER_FILTER_CREATE(CreateFilter4, CByteSwap4()) -static CCodecInfo g_CodecsInfo[] = +REGISTER_CODECS_VAR { - { CreateCodec2, CreateCodec2, 0x020302, L"Swap2", 1, true }, - { CreateCodec4, CreateCodec4, 0x020304, L"Swap4", 1, true } + REGISTER_FILTER_ITEM(CreateFilter2, CreateFilter2, 0x20302, "Swap2"), + REGISTER_FILTER_ITEM(CreateFilter4, CreateFilter4, 0x20304, "Swap4") }; REGISTER_CODECS(ByteSwap) diff --git a/CPP/7zip/Compress/CodecExports.cpp b/CPP/7zip/Compress/CodecExports.cpp index 726d35fc..019cb3c1 100644 --- a/CPP/7zip/Compress/CodecExports.cpp +++ b/CPP/7zip/Compress/CodecExports.cpp @@ -7,118 +7,164 @@ #include "../../Common/ComTry.h" #include "../../Common/MyCom.h" +#include "../../Windows/Defs.h" #include "../../Windows/PropVariant.h" #include "../ICoder.h" #include "../Common/RegisterCodec.h" -extern unsigned int g_NumCodecs; +extern unsigned g_NumCodecs; extern const CCodecInfo *g_Codecs[]; -extern unsigned int g_NumHashers; +extern unsigned g_NumHashers; extern const CHasherInfo *g_Hashers[]; -static const UInt16 kDecodeId = 0x2790; -static const UInt16 kEncodeId = 0x2791; -static const UInt16 kHasherId = 0x2792; - -DEFINE_GUID(CLSID_CCodec, -0x23170F69, 0x40C1, kDecodeId, 0, 0, 0, 0, 0, 0, 0, 0); - -static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) +static void SetPropFromAscii(const char *s, PROPVARIANT *prop) throw() { - if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) - value->vt = VT_BSTR; - return S_OK; + UINT len = (UINT)strlen(s); + OLECHAR *dest = ::SysAllocStringLen(NULL, len); + if (dest) + { + for (UINT i = 0; i <= len; i++) + dest[i] = (Byte)s[i]; + prop->bstrVal = dest; + prop->vt = VT_BSTR; + } } -static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) +static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) throw() { - return SetPropString((const char *)&guid, sizeof(GUID), value); + if ((value->bstrVal = ::SysAllocStringByteLen((const char *)&guid, sizeof(guid))) != NULL) + value->vt = VT_BSTR; + return S_OK; } -static HRESULT SetClassID(CMethodId id, UInt16 typeId, PROPVARIANT *value) +static HRESULT MethodToClassID(UInt16 typeId, CMethodId id, PROPVARIANT *value) throw() { GUID clsId; - clsId.Data1 = CLSID_CCodec.Data1; - clsId.Data2 = CLSID_CCodec.Data2; + clsId.Data1 = k_7zip_GUID_Data1; + clsId.Data2 = k_7zip_GUID_Data2; clsId.Data3 = typeId; SetUi64(clsId.Data4, id); return SetPropGUID(clsId, value); } -static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index) +static HRESULT FindCodecClassId(const GUID *clsid, bool isCoder2, bool isFilter, bool &encode, int &index) throw() { index = -1; - if (clsID->Data1 != CLSID_CCodec.Data1 || - clsID->Data2 != CLSID_CCodec.Data2) + if (clsid->Data1 != k_7zip_GUID_Data1 || + clsid->Data2 != k_7zip_GUID_Data2) return S_OK; + encode = true; - if (clsID->Data3 == kDecodeId) - encode = false; - else if (clsID->Data3 != kEncodeId) - return S_OK; - UInt64 id = GetUi64(clsID->Data4); + + if (clsid->Data3 == k_7zip_GUID_Data3_Decoder) encode = false; + else if (clsid->Data3 != k_7zip_GUID_Data3_Encoder) return S_OK; + + UInt64 id = GetUi64(clsid->Data4); + for (unsigned i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; - if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder) + + if (id != codec.Id + || (encode ? !codec.CreateEncoder : !codec.CreateDecoder) + || (isFilter ? !codec.IsFilter : codec.IsFilter)) continue; - if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || - codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) + + if (codec.NumStreams == 1 ? isCoder2 : !isCoder2) return E_NOINTERFACE; + index = i; return S_OK; } + return S_OK; } -STDAPI CreateCoder2(bool encode, int index, const GUID *iid, void **outObject) +static HRESULT CreateCoderMain(unsigned index, bool encode, void **coder) { COM_TRY_BEGIN - *outObject = 0; - bool isCoder = (*iid == IID_ICompressCoder) != 0; - bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; - bool isFilter = (*iid == IID_ICompressFilter) != 0; + const CCodecInfo &codec = *g_Codecs[index]; - if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || - codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) - return E_NOINTERFACE; + + void *c; if (encode) - { - if (!codec.CreateEncoder) - return CLASS_E_CLASSNOTAVAILABLE; - *outObject = codec.CreateEncoder(); - } + c = codec.CreateEncoder(); else + c = codec.CreateDecoder(); + + if (c) { - if (!codec.CreateDecoder) - return CLASS_E_CLASSNOTAVAILABLE; - *outObject = codec.CreateDecoder(); - } - if (*outObject) - { - if (isCoder) - ((ICompressCoder *)*outObject)->AddRef(); - else if (isCoder2) - ((ICompressCoder2 *)*outObject)->AddRef(); + IUnknown *unk; + if (codec.IsFilter) + unk = (IUnknown *)(ICompressFilter *)c; + else if (codec.NumStreams != 1) + unk = (IUnknown *)(ICompressCoder2 *)c; else - ((ICompressFilter *)*outObject)->AddRef(); + unk = (IUnknown *)(ICompressCoder *)c; + unk->AddRef(); + *coder = c; } return S_OK; + COM_TRY_END } +static HRESULT CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject) +{ + *outObject = NULL; + + const CCodecInfo &codec = *g_Codecs[index]; + + if (encode ? !codec.CreateEncoder : !codec.CreateDecoder) + return CLASS_E_CLASSNOTAVAILABLE; + + if (codec.IsFilter) + { + if (*iid != IID_ICompressFilter) return E_NOINTERFACE; + } + else if (codec.NumStreams != 1) + { + if (*iid != IID_ICompressCoder2) return E_NOINTERFACE; + } + else + { + if (*iid != IID_ICompressCoder) return E_NOINTERFACE; + } + + return CreateCoderMain(index, encode, outObject); +} + +STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject) +{ + return CreateCoder2(false, index, iid, outObject); +} + +STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject) +{ + return CreateCoder2(true, index, iid, outObject); +} + STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject) { - COM_TRY_BEGIN - *outObject = 0; + *outObject = NULL; + + bool isFilter = false; + bool isCoder2 = false; bool isCoder = (*iid == IID_ICompressCoder) != 0; - bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; - bool isFilter = (*iid == IID_ICompressFilter) != 0; - if (!isCoder && !isCoder2 && !isFilter) - return E_NOINTERFACE; + if (!isCoder) + { + isFilter = (*iid == IID_ICompressFilter) != 0; + if (!isFilter) + { + isCoder2 = (*iid == IID_ICompressCoder2) != 0; + if (!isCoder2) + return E_NOINTERFACE; + } + } + bool encode; int codecIndex; HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex); @@ -127,24 +173,9 @@ STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject) if (codecIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; - const CCodecInfo &codec = *g_Codecs[codecIndex]; - if (encode) - *outObject = codec.CreateEncoder(); - else - *outObject = codec.CreateDecoder(); - if (*outObject) - { - if (isCoder) - ((ICompressCoder *)*outObject)->AddRef(); - else if (isCoder2) - ((ICompressCoder2 *)*outObject)->AddRef(); - else - ((ICompressFilter *)*outObject)->AddRef(); - } - return S_OK; - COM_TRY_END + return CreateCoderMain(codecIndex, encode, outObject); } - + STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) { ::VariantClear((VARIANTARG *)value); @@ -156,24 +187,54 @@ STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) value->vt = VT_UI8; break; case NMethodPropID::kName: - if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0) - value->vt = VT_BSTR; + SetPropFromAscii(codec.Name, value); break; case NMethodPropID::kDecoder: if (codec.CreateDecoder) - return SetClassID(codec.Id, kDecodeId, value); + return MethodToClassID(k_7zip_GUID_Data3_Decoder, codec.Id, value); break; case NMethodPropID::kEncoder: if (codec.CreateEncoder) - return SetClassID(codec.Id, kEncodeId, value); + return MethodToClassID(k_7zip_GUID_Data3_Encoder, codec.Id, value); + break; + case NMethodPropID::kDecoderIsAssigned: + value->vt = VT_BOOL; + value->boolVal = BoolToVARIANT_BOOL(codec.CreateDecoder != NULL); + break; + case NMethodPropID::kEncoderIsAssigned: + value->vt = VT_BOOL; + value->boolVal = BoolToVARIANT_BOOL(codec.CreateEncoder != NULL); + break; + case NMethodPropID::kPackStreams: + if (codec.NumStreams != 1) + { + value->vt = VT_UI4; + value->ulVal = (ULONG)codec.NumStreams; + } break; - case NMethodPropID::kInStreams: - if (codec.NumInStreams != 1) + /* + case NMethodPropID::kIsFilter: + // if (codec.IsFilter) + { + value->vt = VT_BOOL; + value->boolVal = BoolToVARIANT_BOOL(codec.IsFilter); + } + break; + */ + /* + case NMethodPropID::kDecoderFlags: + { + value->vt = VT_UI4; + value->ulVal = (ULONG)codec.DecoderFlags; + } + break; + case NMethodPropID::kEncoderFlags: { value->vt = VT_UI4; - value->ulVal = (ULONG)codec.NumInStreams; + value->ulVal = (ULONG)codec.EncoderFlags; } break; + */ } return S_OK; } @@ -185,13 +246,15 @@ STDAPI GetNumberOfMethods(UINT32 *numCodecs) } -static int FindHasherClassId(const GUID *clsID) +// ---------- Hashers ---------- + +static int FindHasherClassId(const GUID *clsid) throw() { - if (clsID->Data1 != CLSID_CCodec.Data1 || - clsID->Data2 != CLSID_CCodec.Data2 || - clsID->Data3 != kHasherId) + if (clsid->Data1 != k_7zip_GUID_Data1 || + clsid->Data2 != k_7zip_GUID_Data2 || + clsid->Data3 != k_7zip_GUID_Data3_Hasher) return -1; - UInt64 id = GetUi64(clsID->Data4); + UInt64 id = GetUi64(clsid->Data4); for (unsigned i = 0; i < g_NumCodecs; i++) if (id == g_Hashers[i]->Id) return i; @@ -230,12 +293,11 @@ STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) value->vt = VT_UI8; break; case NMethodPropID::kName: - if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0) - value->vt = VT_BSTR; + SetPropFromAscii(codec.Name, value); break; case NMethodPropID::kEncoder: if (codec.CreateHasher) - return SetClassID(codec.Id, kHasherId, value); + return MethodToClassID(k_7zip_GUID_Data3_Hasher, codec.Id, value); break; case NMethodPropID::kDigestSize: value->ulVal = (ULONG)codec.DigestSize; diff --git a/CPP/7zip/Compress/CopyCoder.cpp b/CPP/7zip/Compress/CopyCoder.cpp index f0863202..ac6ab2e7 100644 --- a/CPP/7zip/Compress/CopyCoder.cpp +++ b/CPP/7zip/Compress/CopyCoder.cpp @@ -4,17 +4,15 @@ #include "../../../C/Alloc.h" -#include "../Common/StreamUtils.h" - #include "CopyCoder.h" namespace NCompress { -static const UInt32 kBufferSize = 1 << 17; +static const UInt32 kBufSize = 1 << 17; CCopyCoder::~CCopyCoder() { - ::MidFree(_buffer); + ::MidFree(_buf); } STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, @@ -22,35 +20,78 @@ STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { - if (!_buffer) + if (!_buf) { - _buffer = (Byte *)::MidAlloc(kBufferSize); - if (!_buffer) + _buf = (Byte *)::MidAlloc(kBufSize); + if (!_buf) return E_OUTOFMEMORY; } TotalSize = 0; + for (;;) { - UInt32 size = kBufferSize; + UInt32 size = kBufSize; if (outSize && size > *outSize - TotalSize) size = (UInt32)(*outSize - TotalSize); - RINOK(inStream->Read(_buffer, size, &size)); if (size == 0) - break; + return S_OK; + + HRESULT readRes = inStream->Read(_buf, size, &size); + + if (size == 0) + return readRes; + if (outStream) { - RINOK(WriteStream(outStream, _buffer, size)); + UInt32 pos = 0; + do + { + UInt32 curSize = size - pos; + HRESULT res = outStream->Write(_buf + pos, curSize, &curSize); + pos += curSize; + TotalSize += curSize; + RINOK(res); + if (curSize == 0) + return E_FAIL; + } + while (pos < size); } - TotalSize += size; + else + TotalSize += size; + + RINOK(readRes); + if (progress) { RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize)); } } +} + +STDMETHODIMP CCopyCoder::SetInStream(ISequentialInStream *inStream) +{ + _inStream = inStream; + TotalSize = 0; + return S_OK; +} + +STDMETHODIMP CCopyCoder::ReleaseInStream() +{ + _inStream.Release(); return S_OK; } +STDMETHODIMP CCopyCoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize = 0; + HRESULT res = _inStream->Read(data, size, &realProcessedSize); + TotalSize += realProcessedSize; + if (processedSize) + *processedSize = realProcessedSize; + return res; +} + STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value) { *value = TotalSize; diff --git a/CPP/7zip/Compress/CopyCoder.h b/CPP/7zip/Compress/CopyCoder.h index 5e0bb643..a21c0988 100644 --- a/CPP/7zip/Compress/CopyCoder.h +++ b/CPP/7zip/Compress/CopyCoder.h @@ -11,19 +11,30 @@ namespace NCompress { class CCopyCoder: public ICompressCoder, + public ICompressSetInStream, + public ISequentialInStream, public ICompressGetInStreamProcessedSize, public CMyUnknownImp { - Byte *_buffer; + Byte *_buf; + CMyComPtr<ISequentialInStream> _inStream; public: UInt64 TotalSize; - CCopyCoder(): TotalSize(0), _buffer(0) {}; + + CCopyCoder(): _buf(0), TotalSize(0) {}; ~CCopyCoder(); - MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize) + MY_UNKNOWN_IMP4( + ICompressCoder, + ICompressSetInStream, + ISequentialInStream, + ICompressGetInStreamProcessedSize) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); }; diff --git a/CPP/7zip/Compress/CopyRegister.cpp b/CPP/7zip/Compress/CopyRegister.cpp index efb9b9e9..703c52ca 100644 --- a/CPP/7zip/Compress/CopyRegister.cpp +++ b/CPP/7zip/Compress/CopyRegister.cpp @@ -6,9 +6,6 @@ #include "CopyCoder.h" -static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::CCopyCoder); } +REGISTER_CODEC_CREATE(CreateCodec, NCompress::CCopyCoder()) -static CCodecInfo g_CodecInfo = -{ CreateCodec, CreateCodec, 0x00, L"Copy", 1, false }; - -REGISTER_CODEC(Copy) +REGISTER_CODEC_2(Copy, CreateCodec, CreateCodec, 0, "Copy") diff --git a/CPP/7zip/Compress/Deflate64Register.cpp b/CPP/7zip/Compress/Deflate64Register.cpp index 509e675a..4b2cf0f7 100644 --- a/CPP/7zip/Compress/Deflate64Register.cpp +++ b/CPP/7zip/Compress/Deflate64Register.cpp @@ -6,15 +6,13 @@ #include "DeflateDecoder.h" -static void *CreateCodecDeflate64() { return (void *)(ICompressCoder *)(new NCompress::NDeflate::NDecoder::CCOMCoder64); } +REGISTER_CODEC_CREATE(CreateDec, NCompress::NDeflate::NDecoder::CCOMCoder64()) + #if !defined(EXTRACT_ONLY) && !defined(DEFLATE_EXTRACT_ONLY) #include "DeflateEncoder.h" -static void *CreateCodecOutDeflate64() { return (void *)(ICompressCoder *)(new NCompress::NDeflate::NEncoder::CCOMCoder64); } +REGISTER_CODEC_CREATE(CreateEnc, NCompress::NDeflate::NEncoder::CCOMCoder64()) #else -#define CreateCodecOutDeflate64 0 +#define CreateEnc NULL #endif -static CCodecInfo g_CodecInfo = - { CreateCodecDeflate64, CreateCodecOutDeflate64, 0x040109, L"Deflate64", 1, false }; - -REGISTER_CODEC(Deflate64) +REGISTER_CODEC_2(Deflate64, CreateDec, CreateEnc, 0x40109, "Deflate64") diff --git a/CPP/7zip/Compress/DeflateConst.h b/CPP/7zip/Compress/DeflateConst.h index c3ae5719..cfbbf886 100644 --- a/CPP/7zip/Compress/DeflateConst.h +++ b/CPP/7zip/Compress/DeflateConst.h @@ -6,37 +6,37 @@ namespace NCompress { namespace NDeflate { -const int kNumHuffmanBits = 15; +const unsigned kNumHuffmanBits = 15; const UInt32 kHistorySize32 = (1 << 15); const UInt32 kHistorySize64 = (1 << 16); -const UInt32 kDistTableSize32 = 30; -const UInt32 kDistTableSize64 = 32; +const unsigned kDistTableSize32 = 30; +const unsigned kDistTableSize64 = 32; -const UInt32 kNumLenSymbols32 = 256; -const UInt32 kNumLenSymbols64 = 255; // don't change it. It must be <= 255. -const UInt32 kNumLenSymbolsMax = kNumLenSymbols32; +const unsigned kNumLenSymbols32 = 256; +const unsigned kNumLenSymbols64 = 255; // don't change it. It must be <= 255. +const unsigned kNumLenSymbolsMax = kNumLenSymbols32; -const UInt32 kNumLenSlots = 29; +const unsigned kNumLenSlots = 29; -const UInt32 kFixedDistTableSize = 32; -const UInt32 kFixedLenTableSize = 31; +const unsigned kFixedDistTableSize = 32; +const unsigned kFixedLenTableSize = 31; -const UInt32 kSymbolEndOfBlock = 0x100; -const UInt32 kSymbolMatch = kSymbolEndOfBlock + 1; +const unsigned kSymbolEndOfBlock = 0x100; +const unsigned kSymbolMatch = kSymbolEndOfBlock + 1; -const UInt32 kMainTableSize = kSymbolMatch + kNumLenSlots; -const UInt32 kFixedMainTableSize = kSymbolMatch + kFixedLenTableSize; +const unsigned kMainTableSize = kSymbolMatch + kNumLenSlots; +const unsigned kFixedMainTableSize = kSymbolMatch + kFixedLenTableSize; -const UInt32 kLevelTableSize = 19; +const unsigned kLevelTableSize = 19; -const UInt32 kTableDirectLevels = 16; -const UInt32 kTableLevelRepNumber = kTableDirectLevels; -const UInt32 kTableLevel0Number = kTableLevelRepNumber + 1; -const UInt32 kTableLevel0Number2 = kTableLevel0Number + 1; +const unsigned kTableDirectLevels = 16; +const unsigned kTableLevelRepNumber = kTableDirectLevels; +const unsigned kTableLevel0Number = kTableLevelRepNumber + 1; +const unsigned kTableLevel0Number2 = kTableLevel0Number + 1; -const UInt32 kLevelMask = 0xF; +const unsigned kLevelMask = 0xF; const Byte kLenStart32[kFixedLenTableSize] = {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224, 255, 0, 0}; @@ -58,12 +58,12 @@ const Byte kLevelDirectBits[3] = {2, 3, 7}; const Byte kCodeLengthAlphabetOrder[kLevelTableSize] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; -const UInt32 kMatchMinLen = 3; -const UInt32 kMatchMaxLen32 = kNumLenSymbols32 + kMatchMinLen - 1; //256 + 2 -const UInt32 kMatchMaxLen64 = kNumLenSymbols64 + kMatchMinLen - 1; //255 + 2 -const UInt32 kMatchMaxLen = kMatchMaxLen32; +const unsigned kMatchMinLen = 3; +const unsigned kMatchMaxLen32 = kNumLenSymbols32 + kMatchMinLen - 1; // 256 + 2 +const unsigned kMatchMaxLen64 = kNumLenSymbols64 + kMatchMinLen - 1; // 255 + 2 +const unsigned kMatchMaxLen = kMatchMaxLen32; -const int kFinalBlockFieldSize = 1; +const unsigned kFinalBlockFieldSize = 1; namespace NFinalBlockField { @@ -74,7 +74,7 @@ namespace NFinalBlockField }; } -const int kBlockTypeFieldSize = 2; +const unsigned kBlockTypeFieldSize = 2; namespace NBlockType { @@ -86,17 +86,17 @@ namespace NBlockType }; } -const int kNumLenCodesFieldSize = 5; -const int kNumDistCodesFieldSize = 5; -const int kNumLevelCodesFieldSize = 4; +const unsigned kNumLenCodesFieldSize = 5; +const unsigned kNumDistCodesFieldSize = 5; +const unsigned kNumLevelCodesFieldSize = 4; -const UInt32 kNumLitLenCodesMin = 257; -const UInt32 kNumDistCodesMin = 1; -const UInt32 kNumLevelCodesMin = 4; +const unsigned kNumLitLenCodesMin = 257; +const unsigned kNumDistCodesMin = 1; +const unsigned kNumLevelCodesMin = 4; -const int kLevelFieldSize = 3; +const unsigned kLevelFieldSize = 3; -const int kStoredBlockLengthFieldSize = 16; +const unsigned kStoredBlockLengthFieldSize = 16; struct CLevels { @@ -105,7 +105,7 @@ struct CLevels void SubClear() { - UInt32 i; + unsigned i; for (i = kNumLitLenCodesMin; i < kFixedMainTableSize; i++) litLenLevels[i] = 0; for (i = 0; i < kFixedDistTableSize; i++) @@ -114,7 +114,7 @@ struct CLevels void SetFixedLevels() { - int i = 0; + unsigned i = 0; for (; i < 144; i++) litLenLevels[i] = 8; for (; i < 256; i++) litLenLevels[i] = 9; diff --git a/CPP/7zip/Compress/DeflateDecoder.cpp b/CPP/7zip/Compress/DeflateDecoder.cpp index 5285e143..5e2d5d3e 100644 --- a/CPP/7zip/Compress/DeflateDecoder.cpp +++ b/CPP/7zip/Compress/DeflateDecoder.cpp @@ -106,7 +106,7 @@ bool CCoder::ReadTables(void) Byte levelLevels[kLevelTableSize]; for (unsigned i = 0; i < kLevelTableSize; i++) { - int position = kCodeLengthAlphabetOrder[i]; + unsigned position = kCodeLengthAlphabetOrder[i]; if (i < numLevelCodes) levelLevels[position] = (Byte)ReadBits(kLevelFieldSize); else @@ -299,7 +299,7 @@ HRESULT CCoder::CodeReal(ISequentialOutStream *outStream, finishInputStream = true; } } - if (curSize == 0) + if (!finishInputStream && curSize == 0) break; RINOK(CodeSpec(curSize, finishInputStream)); if (_remainLen == kLenIdFinished) @@ -314,12 +314,12 @@ HRESULT CCoder::CodeReal(ISequentialOutStream *outStream, if (_remainLen == kLenIdFinished && ZlibMode) { m_InBitStream.AlignToByte(); - for (int i = 0; i < 4; i++) + for (unsigned i = 0; i < 4; i++) ZlibFooter[i] = ReadAlignedByte(); } flusher.NeedFlush = false; res = Flush(); - if (res == S_OK && InputEofError()) + if (res == S_OK && _remainLen != kLenIdNeedInit && InputEofError()) return S_FALSE; DEFLATE_TRY_END(res) return res; diff --git a/CPP/7zip/Compress/DeflateEncoder.cpp b/CPP/7zip/Compress/DeflateEncoder.cpp index 392ee93d..eb012e8d 100644 --- a/CPP/7zip/Compress/DeflateEncoder.cpp +++ b/CPP/7zip/Compress/DeflateEncoder.cpp @@ -21,7 +21,7 @@ namespace NCompress { namespace NDeflate { namespace NEncoder { -static const int kNumDivPassesMax = 10; // [0, 16); ratio/speed/ram tradeoff; use big value for better compression ratio. +static const unsigned kNumDivPassesMax = 10; // [0, 16); ratio/speed/ram tradeoff; use big value for better compression ratio. static const UInt32 kNumTables = (1 << kNumDivPassesMax); static const UInt32 kFixedHuffmanCodeBlockSizeMax = (1 << 8); // [0, (1 << 32)); ratio/speed tradeoff; use big value for better compression ratio. @@ -34,8 +34,8 @@ static const UInt32 kMatchArrayLimit = kMatchArraySize - kMatchMaxLen * 4 * size static const UInt32 kBlockUncompressedSizeThreshold = kMaxUncompressedBlockSize - kMatchMaxLen - kNumOpts; -static const int kMaxCodeBitLength = 11; -static const int kMaxLevelBitLength = 7; +static const unsigned kMaxCodeBitLength = 11; +static const unsigned kMaxLevelBitLength = 7; static const Byte kNoLiteralStatPrice = 11; static const Byte kNoLenStatPrice = 11; @@ -49,17 +49,17 @@ class CFastPosInit public: CFastPosInit() { - int i; + unsigned i; for (i = 0; i < kNumLenSlots; i++) { - int c = kLenStart32[i]; - int j = 1 << kLenDirectBits32[i]; - for (int k = 0; k < j; k++, c++) + unsigned c = kLenStart32[i]; + unsigned j = 1 << kLenDirectBits32[i]; + for (unsigned k = 0; k < j; k++, c++) g_LenSlots[c] = (Byte)i; } - const int kFastSlots = 18; - int c = 0; + const unsigned kFastSlots = 18; + unsigned c = 0; for (Byte slotFast = 0; slotFast < kFastSlots; slotFast++) { UInt32 k = (1 << kDistDirectBits[slotFast]); @@ -79,10 +79,6 @@ inline UInt32 GetPosSlot(UInt32 pos) return g_FastPos[pos >> 8] + 16; } -static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } -static void SzFree(void *p, void *address) { p = p; MyFree(address); } -static ISzAlloc g_Alloc = { SzAlloc, SzFree }; - void CEncProps::Normalize() { int level = Level; @@ -183,7 +179,7 @@ HRESULT CCoder::Create() if (!m_Created) { - _lzInWindow.btMode = _btMode ? 1 : 0; + _lzInWindow.btMode = (Byte)(_btMode ? 1 : 0); _lzInWindow.numHashBytes = 3; if (!MatchFinder_Create(&_lzInWindow, m_Deflate64Mode ? kHistorySize64 : kHistorySize32, @@ -348,7 +344,7 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes) MovePos(lenMain - 1); return lenMain; } - m_Optimum[1].Price = m_LiteralPrices[Inline_MatchFinder_GetIndexByte(&_lzInWindow, 0 - m_AdditionalOffset)]; + m_Optimum[1].Price = m_LiteralPrices[*(Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) - m_AdditionalOffset)]; m_Optimum[1].PosPrev = 0; m_Optimum[2].Price = kIfinityPrice; @@ -392,7 +388,7 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes) } } UInt32 curPrice = m_Optimum[cur].Price; - UInt32 curAnd1Price = curPrice + m_LiteralPrices[Inline_MatchFinder_GetIndexByte(&_lzInWindow, cur - m_AdditionalOffset)]; + UInt32 curAnd1Price = curPrice + m_LiteralPrices[*(Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) + cur - m_AdditionalOffset)]; COptimal &optimum = m_Optimum[cur + 1]; if (curAnd1Price < optimum.Price) { @@ -453,21 +449,23 @@ void CTables::InitStructures() distLevels[i] = 5; } -NO_INLINE void CCoder::LevelTableDummy(const Byte *levels, int numLevels, UInt32 *freqs) +NO_INLINE void CCoder::LevelTableDummy(const Byte *levels, unsigned numLevels, UInt32 *freqs) { - int prevLen = 0xFF; - int nextLen = levels[0]; - int count = 0; - int maxCount = 7; - int minCount = 4; + unsigned prevLen = 0xFF; + unsigned nextLen = levels[0]; + unsigned count = 0; + unsigned maxCount = 7; + unsigned minCount = 4; + if (nextLen == 0) { maxCount = 138; minCount = 3; } - for (int n = 0; n < numLevels; n++) + + for (unsigned n = 0; n < numLevels; n++) { - int curLen = nextLen; + unsigned curLen = nextLen; nextLen = (n < numLevels - 1) ? levels[n + 1] : 0xFF; count++; if (count < maxCount && curLen == nextLen) @@ -510,7 +508,7 @@ NO_INLINE void CCoder::LevelTableDummy(const Byte *levels, int numLevels, UInt32 } } -NO_INLINE void CCoder::WriteBits(UInt32 value, int numBits) +NO_INLINE void CCoder::WriteBits(UInt32 value, unsigned numBits) { m_OutStream.WriteBits(value, numBits); } @@ -518,28 +516,30 @@ NO_INLINE void CCoder::WriteBits(UInt32 value, int numBits) #define WRITE_HF2(codes, lens, i) m_OutStream.WriteBits(codes[i], lens[i]) #define WRITE_HF(i) WriteBits(codes[i], lens[i]) -NO_INLINE void CCoder::LevelTableCode(const Byte *levels, int numLevels, const Byte *lens, const UInt32 *codes) +NO_INLINE void CCoder::LevelTableCode(const Byte *levels, unsigned numLevels, const Byte *lens, const UInt32 *codes) { - int prevLen = 0xFF; - int nextLen = levels[0]; - int count = 0; - int maxCount = 7; - int minCount = 4; + unsigned prevLen = 0xFF; + unsigned nextLen = levels[0]; + unsigned count = 0; + unsigned maxCount = 7; + unsigned minCount = 4; + if (nextLen == 0) { maxCount = 138; minCount = 3; } - for (int n = 0; n < numLevels; n++) + + for (unsigned n = 0; n < numLevels; n++) { - int curLen = nextLen; + unsigned curLen = nextLen; nextLen = (n < numLevels - 1) ? levels[n + 1] : 0xFF; count++; if (count < maxCount && curLen == nextLen) continue; if (count < minCount) - for (int i = 0; i < count; i++) + for (unsigned i = 0; i < count; i++) WRITE_HF(curLen); else if (curLen != 0) { @@ -644,7 +644,7 @@ NO_INLINE void CCoder::TryBlock() } else { - Byte b = Inline_MatchFinder_GetIndexByte(&_lzInWindow, 0 - m_AdditionalOffset); + Byte b = *(Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) - m_AdditionalOffset); mainFreqs[b]++; codeValue.SetAsLiteral(); codeValue.Pos = b; @@ -719,13 +719,13 @@ NO_INLINE void CCoder::WriteBlock() WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, kSymbolEndOfBlock); } -static UInt32 GetStorePrice(UInt32 blockSize, int bitPosition) +static UInt32 GetStorePrice(UInt32 blockSize, unsigned bitPosition) { UInt32 price = 0; do { UInt32 nextBitPosition = (bitPosition + kFinalBlockFieldSize + kBlockTypeFieldSize) & 7; - int numBitsForAlign = nextBitPosition > 0 ? (8 - nextBitPosition): 0; + unsigned numBitsForAlign = nextBitPosition > 0 ? (8 - nextBitPosition): 0; UInt32 curBlockSize = (blockSize < (1 << 16)) ? blockSize : (1 << 16) - 1; price += kFinalBlockFieldSize + kBlockTypeFieldSize + numBitsForAlign + (2 + 2) * 8 + curBlockSize * 8; bitPosition = 0; @@ -754,7 +754,7 @@ void CCoder::WriteStoreBlock(UInt32 blockSize, UInt32 additionalOffset, bool fin while (blockSize != 0); } -NO_INLINE UInt32 CCoder::TryDynBlock(int tableIndex, UInt32 numPasses) +NO_INLINE UInt32 CCoder::TryDynBlock(unsigned tableIndex, UInt32 numPasses) { CTables &t = m_Tables[tableIndex]; BlockSizeRes = t.BlockSizeRes; @@ -806,7 +806,7 @@ NO_INLINE UInt32 CCoder::TryDynBlock(int tableIndex, UInt32 numPasses) m_NumLevelCodes * kLevelFieldSize + kFinalBlockFieldSize + kBlockTypeFieldSize; } -NO_INLINE UInt32 CCoder::TryFixedBlock(int tableIndex) +NO_INLINE UInt32 CCoder::TryFixedBlock(unsigned tableIndex) { CTables &t = m_Tables[tableIndex]; BlockSizeRes = t.BlockSizeRes; @@ -817,7 +817,7 @@ NO_INLINE UInt32 CCoder::TryFixedBlock(int tableIndex) return kFinalBlockFieldSize + kBlockTypeFieldSize + GetLzBlockPrice(); } -NO_INLINE UInt32 CCoder::GetBlockPrice(int tableIndex, int numDivPasses) +NO_INLINE UInt32 CCoder::GetBlockPrice(unsigned tableIndex, unsigned numDivPasses) { CTables &t = m_Tables[tableIndex]; t.StaticMode = false; @@ -864,12 +864,13 @@ NO_INLINE UInt32 CCoder::GetBlockPrice(int tableIndex, int numDivPasses) price = subPrice; } } + m_AdditionalOffset = additionalOffsetEnd; m_Pos = posTemp; return price; } -void CCoder::CodeBlock(int tableIndex, bool finalBlock) +void CCoder::CodeBlock(unsigned tableIndex, bool finalBlock) { CTables &t = m_Tables[tableIndex]; if (t.UseSubBlocks) @@ -888,8 +889,8 @@ void CCoder::CodeBlock(int tableIndex, bool finalBlock) { WriteBits(NBlockType::kFixedHuffman, kBlockTypeFieldSize); TryFixedBlock(tableIndex); - int i; - const int kMaxStaticHuffLen = 9; + unsigned i; + const unsigned kMaxStaticHuffLen = 9; for (i = 0; i < kFixedMainTableSize; i++) mainFreqs[i] = (UInt32)1 << (kMaxStaticHuffLen - m_NewLevels.litLenLevels[i]); for (i = 0; i < kFixedDistTableSize; i++) diff --git a/CPP/7zip/Compress/DeflateEncoder.h b/CPP/7zip/Compress/DeflateEncoder.h index d8e88f89..62423a34 100644 --- a/CPP/7zip/Compress/DeflateEncoder.h +++ b/CPP/7zip/Compress/DeflateEncoder.h @@ -91,8 +91,8 @@ public: UInt32 m_Pos; - int m_NumPasses; - int m_NumDivPasses; + unsigned m_NumPasses; + unsigned m_NumDivPasses; bool m_CheckStatic; bool m_IsMultiPass; UInt32 m_ValueBlockSize; @@ -106,8 +106,8 @@ public: bool m_Deflate64Mode; Byte m_LevelLevels[kLevelTableSize]; - int m_NumLitLenLevels; - int m_NumDistLevels; + unsigned m_NumLitLenLevels; + unsigned m_NumDistLevels; UInt32 m_NumLevelCodes; UInt32 m_ValueIndex; @@ -142,17 +142,17 @@ public: UInt32 GetOptimal(UInt32 &backRes); UInt32 GetOptimalFast(UInt32 &backRes); - void LevelTableDummy(const Byte *levels, int numLevels, UInt32 *freqs); + void LevelTableDummy(const Byte *levels, unsigned numLevels, UInt32 *freqs); - void WriteBits(UInt32 value, int numBits); - void LevelTableCode(const Byte *levels, int numLevels, const Byte *lens, const UInt32 *codes); + void WriteBits(UInt32 value, unsigned numBits); + void LevelTableCode(const Byte *levels, unsigned numLevels, const Byte *lens, const UInt32 *codes); void MakeTables(unsigned maxHuffLen); UInt32 GetLzBlockPrice() const; void TryBlock(); - UInt32 TryDynBlock(int tableIndex, UInt32 numPasses); + UInt32 TryDynBlock(unsigned tableIndex, UInt32 numPasses); - UInt32 TryFixedBlock(int tableIndex); + UInt32 TryFixedBlock(unsigned tableIndex); void SetPrices(const CLevels &levels); void WriteBlock(); @@ -165,8 +165,8 @@ public: void WriteBlockData(bool writeMode, bool finalBlock); - UInt32 GetBlockPrice(int tableIndex, int numDivPasses); - void CodeBlock(int tableIndex, bool finalBlock); + UInt32 GetBlockPrice(unsigned tableIndex, unsigned numDivPasses); + void CodeBlock(unsigned tableIndex, bool finalBlock); void SetProps(const CEncProps *props2); public: diff --git a/CPP/7zip/Compress/DeflateRegister.cpp b/CPP/7zip/Compress/DeflateRegister.cpp index 45f55219..32221fcc 100644 --- a/CPP/7zip/Compress/DeflateRegister.cpp +++ b/CPP/7zip/Compress/DeflateRegister.cpp @@ -6,16 +6,13 @@ #include "DeflateDecoder.h" -static void *CreateCodecDeflate() { return (void *)(ICompressCoder *)(new NCompress::NDeflate::NDecoder::CCOMCoder); } +REGISTER_CODEC_CREATE(CreateDec, NCompress::NDeflate::NDecoder::CCOMCoder) #if !defined(EXTRACT_ONLY) && !defined(DEFLATE_EXTRACT_ONLY) #include "DeflateEncoder.h" -static void *CreateCodecOutDeflate() { return (void *)(ICompressCoder *)(new NCompress::NDeflate::NEncoder::CCOMCoder); } +REGISTER_CODEC_CREATE(CreateEnc, NCompress::NDeflate::NEncoder::CCOMCoder) #else -#define CreateCodecOutDeflate 0 +#define CreateEnc NULL #endif -static CCodecInfo g_CodecInfo = - { CreateCodecDeflate, CreateCodecOutDeflate, 0x040108, L"Deflate", 1, false }; - -REGISTER_CODEC(Deflate) +REGISTER_CODEC_2(Deflate, CreateDec, CreateEnc, 0x40108, "Deflate") diff --git a/CPP/7zip/Compress/DeltaFilter.cpp b/CPP/7zip/Compress/DeltaFilter.cpp index d8378a60..d90f62f5 100644 --- a/CPP/7zip/Compress/DeltaFilter.cpp +++ b/CPP/7zip/Compress/DeltaFilter.cpp @@ -4,18 +4,24 @@ #include "../../../C/Delta.h" -#include "../Common/RegisterCodec.h" +#include "../../Common/MyCom.h" + +#include "../ICoder.h" -#include "BranchCoder.h" +#include "../Common/RegisterCodec.h" struct CDelta { unsigned _delta; Byte _state[DELTA_STATE_SIZE]; + CDelta(): _delta(1) {} void DeltaInit() { Delta_Init(_state); } }; + +#ifndef EXTRACT_ONLY + class CDeltaEncoder: public ICompressFilter, public ICompressSetCoderProperties, @@ -25,25 +31,11 @@ class CDeltaEncoder: { public: MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties) - STDMETHOD(Init)(); - STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); + INTERFACE_ICompressFilter(;) STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); }; -class CDeltaDecoder: - public ICompressFilter, - public ICompressSetDecoderProperties2, - CDelta, - public CMyUnknownImp -{ -public: - MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) - STDMETHOD(Init)(); - STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); - STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); -}; - STDMETHODIMP CDeltaEncoder::Init() { DeltaInit(); @@ -89,6 +81,21 @@ STDMETHODIMP CDeltaEncoder::WriteCoderProperties(ISequentialOutStream *outStream return outStream->Write(&prop, 1, NULL); } +#endif + + +class CDeltaDecoder: + public ICompressFilter, + public ICompressSetDecoderProperties2, + CDelta, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) + INTERFACE_ICompressFilter(;) + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); +}; + STDMETHODIMP CDeltaDecoder::Init() { DeltaInit(); @@ -109,17 +116,8 @@ STDMETHODIMP CDeltaDecoder::SetDecoderProperties2(const Byte *props, UInt32 size return S_OK; } -#define CREATE_CODEC(x) \ - static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## Decoder); } \ - static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## Encoder); } - -CREATE_CODEC(Delta) - -#define METHOD_ITEM(x, id, name) { CreateCodec ## x, CreateCodec ## x ## Out, id, name, 1, true } - -static CCodecInfo g_CodecsInfo[] = -{ - METHOD_ITEM(Delta, 3, L"Delta") -}; -REGISTER_CODECS(Delta) +REGISTER_FILTER_E(Delta, + CDeltaDecoder(), + CDeltaEncoder(), + 3, "Delta") diff --git a/CPP/7zip/Compress/DllExports2Compress.cpp b/CPP/7zip/Compress/DllExports2Compress.cpp index 286ef08b..a6ff6905 100644 --- a/CPP/7zip/Compress/DllExports2Compress.cpp +++ b/CPP/7zip/Compress/DllExports2Compress.cpp @@ -1,4 +1,4 @@ -// DllExports.cpp +// DllExports2Compress.cpp #include "StdAfx.h" @@ -20,11 +20,6 @@ BOOL WINAPI DllMain( return TRUE; } -static const UInt16 kDecodeId = 0x2790; - -DEFINE_GUID(CLSID_CCodec, -0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) diff --git a/CPP/7zip/Compress/DllExportsCompress.cpp b/CPP/7zip/Compress/DllExportsCompress.cpp index be429277..c58d2d5e 100644 --- a/CPP/7zip/Compress/DllExportsCompress.cpp +++ b/CPP/7zip/Compress/DllExportsCompress.cpp @@ -40,11 +40,6 @@ BOOL WINAPI DllMain( } #endif -static const UInt16 kDecodeId = 0x2790; - -DEFINE_GUID(CLSID_CCodec, -0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) diff --git a/CPP/7zip/Compress/HuffmanDecoder.h b/CPP/7zip/Compress/HuffmanDecoder.h index 21f96f0d..6faf8005 100644 --- a/CPP/7zip/Compress/HuffmanDecoder.h +++ b/CPP/7zip/Compress/HuffmanDecoder.h @@ -8,39 +8,42 @@ namespace NCompress { namespace NHuffman { -const int kNumTableBits = 9; +const unsigned kNumTableBits = 9; -template <int kNumBitsMax, UInt32 m_NumSymbols> +template <unsigned kNumBitsMax, UInt32 m_NumSymbols> class CDecoder { UInt32 m_Limits[kNumBitsMax + 1]; // m_Limits[i] = value limit for symbols with length = i UInt32 m_Positions[kNumBitsMax + 1]; // m_Positions[i] = index in m_Symbols[] of first symbol with length = i UInt32 m_Symbols[m_NumSymbols]; - Byte m_Lengths[1 << kNumTableBits]; // Table oh length for short codes. + Byte m_Lengths[1 << kNumTableBits]; // Table of length for short codes public: - - bool SetCodeLengths(const Byte *codeLengths) + + bool SetCodeLengths(const Byte *lens) { - int lenCounts[kNumBitsMax + 1]; + unsigned lenCounts[kNumBitsMax + 1]; UInt32 tmpPositions[kNumBitsMax + 1]; - int i; + unsigned i; for (i = 1; i <= kNumBitsMax; i++) lenCounts[i] = 0; UInt32 symbol; + for (symbol = 0; symbol < m_NumSymbols; symbol++) { - int len = codeLengths[symbol]; + unsigned len = lens[symbol]; if (len > kNumBitsMax) return false; lenCounts[len]++; m_Symbols[symbol] = 0xFFFFFFFF; } + lenCounts[0] = 0; m_Positions[0] = m_Limits[0] = 0; UInt32 startPos = 0; UInt32 index = 0; const UInt32 kMaxValue = (1 << kNumBitsMax); + for (i = 1; i <= kNumBitsMax; i++) { startPos += lenCounts[i] << (kNumBitsMax - i); @@ -56,19 +59,21 @@ public: m_Lengths[index] = (Byte)i; } } + for (symbol = 0; symbol < m_NumSymbols; symbol++) { - int len = codeLengths[symbol]; + unsigned len = lens[symbol]; if (len != 0) m_Symbols[tmpPositions[len]++] = symbol; } + return true; } template <class TBitDecoder> UInt32 DecodeSymbol(TBitDecoder *bitStream) { - int numBits; + unsigned numBits; UInt32 value = bitStream->GetValue(kNumBitsMax); if (value < m_Limits[kNumTableBits]) numBits = m_Lengths[value >> (kNumBitsMax - kNumTableBits)]; diff --git a/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp b/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp index 2170326e..d385d7b1 100644 --- a/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp +++ b/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp @@ -21,9 +21,9 @@ CDecoder::~CDecoder() bool CDecoder::SetCodeLengths(const Byte *codeLengths) { - // int lenCounts[kNumBitsInLongestCode + 1], tmpPositions[kNumBitsInLongestCode + 1]; - int lenCounts[kNumBitsInLongestCode + 2], tmpPositions[kNumBitsInLongestCode + 1]; - int i; + // unsigned lenCounts[kNumBitsInLongestCode + 1], tmpPositions[kNumBitsInLongestCode + 1]; + unsigned lenCounts[kNumBitsInLongestCode + 2], tmpPositions[kNumBitsInLongestCode + 1]; + unsigned i; for (i = 0; i <= kNumBitsInLongestCode; i++) lenCounts[i] = 0; UInt32 symbolIndex; @@ -67,7 +67,7 @@ UInt32 CDecoder::DecodeSymbol(CInBit *inStream) { UInt32 numBits = 0; UInt32 value = inStream->GetValue(kNumBitsInLongestCode); - int i; + unsigned i; for (i = kNumBitsInLongestCode; i > 0; i--) { if (value < m_Limitits[i]) diff --git a/CPP/7zip/Compress/ImplodeHuffmanDecoder.h b/CPP/7zip/Compress/ImplodeHuffmanDecoder.h index 6120a35a..691a8e93 100644 --- a/CPP/7zip/Compress/ImplodeHuffmanDecoder.h +++ b/CPP/7zip/Compress/ImplodeHuffmanDecoder.h @@ -11,7 +11,7 @@ namespace NCompress { namespace NImplode { namespace NHuffman { -const int kNumBitsInLongestCode = 16; +const unsigned kNumBitsInLongestCode = 16; typedef NBitl::CDecoder<CInBuffer> CInBit; diff --git a/CPP/7zip/Compress/LzOutWindow.h b/CPP/7zip/Compress/LzOutWindow.h index 507aa7f4..5591744d 100644 --- a/CPP/7zip/Compress/LzOutWindow.h +++ b/CPP/7zip/Compress/LzOutWindow.h @@ -35,10 +35,13 @@ public: } else do { + UInt32 pos2; if (pos == _bufSize) pos = 0; - _buf[_pos++] = _buf[pos++]; - if (_pos == _limitPos) + pos2 = _pos; + _buf[pos2++] = _buf[pos++]; + _pos = pos2; + if (pos2 == _limitPos) FlushWithCheck(); } while (--len != 0); @@ -47,15 +50,17 @@ public: void PutByte(Byte b) { - _buf[_pos++] = b; - if (_pos == _limitPos) + UInt32 pos = _pos; + _buf[pos++] = b; + _pos = pos; + if (pos == _limitPos) FlushWithCheck(); } Byte GetByte(UInt32 distance) const { UInt32 pos = _pos - distance - 1; - if (pos >= _bufSize) + if (distance >= _pos) pos += _bufSize; return _buf[pos]; } diff --git a/CPP/7zip/Compress/LzhDecoder.cpp b/CPP/7zip/Compress/LzhDecoder.cpp index ad6e873a..bf4a0b68 100644 --- a/CPP/7zip/Compress/LzhDecoder.cpp +++ b/CPP/7zip/Compress/LzhDecoder.cpp @@ -8,208 +8,240 @@ namespace NCompress{ namespace NLzh { namespace NDecoder { -static const UInt32 kHistorySize = (1 << 16); +static const UInt32 kWindowSizeMin = 1 << 16; -static const int kBlockSizeBits = 16; -static const int kNumCBits = 9; -static const int kNumLevelBits = 5; // smallest integer such that (1 << kNumLevelBits) > kNumLevelSymbols/ - -UInt32 CCoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); } - -HRESULT CCoder::ReadLevelTable() +static bool CheckCodeLens(const Byte *lens, unsigned num) { - int n = ReadBits(kNumLevelBits); - if (n == 0) - { - m_LevelHuffman.Symbol = ReadBits(kNumLevelBits); - if (m_LevelHuffman.Symbol >= kNumLevelSymbols) - return S_FALSE; - } - else + UInt32 sum = 0; + for (unsigned i = 0; i < num; i++) { - if (n > kNumLevelSymbols) - return S_FALSE; - m_LevelHuffman.Symbol = -1; - Byte lens[kNumLevelSymbols]; - int i = 0; - while (i < n) - { - int c = m_InBitStream.ReadBits(3); - if (c == 7) - while (ReadBits(1)) - if (c++ > kMaxHuffmanLen) - return S_FALSE; - lens[i++] = (Byte)c; - if (i == kNumSpecLevelSymbols) - { - c = ReadBits(2); - while (--c >= 0) - lens[i++] = 0; - } - } - while (i < kNumLevelSymbols) - lens[i++] = 0; - m_LevelHuffman.SetCodeLengths(lens); + unsigned len = lens[i]; + if (len != 0) + sum += ((UInt32)1 << (NUM_CODE_BITS - len)); } - return S_OK; + return sum == ((UInt32)1 << NUM_CODE_BITS); } -HRESULT CCoder::ReadPTable(int numBits) +bool CCoder::ReadTP(unsigned num, unsigned numBits, int spec) { - int n = ReadBits(numBits); + _symbolT = -1; + + UInt32 n = _inBitStream.ReadBits(numBits); if (n == 0) { - m_PHuffmanDecoder.Symbol = ReadBits(numBits); - if (m_PHuffmanDecoder.Symbol >= kNumDistanceSymbols) - return S_FALSE; + _symbolT = _inBitStream.ReadBits(numBits); + return ((unsigned)_symbolT < num); } - else + + if (n > num) + return false; + { - if (n > kNumDistanceSymbols) - return S_FALSE; - m_PHuffmanDecoder.Symbol = -1; - Byte lens[kNumDistanceSymbols]; - int i = 0; - while (i < n) + Byte lens[NPT]; + unsigned i; + for (i = 0; i < NPT; i++) + lens[i] = 0; + + i = 0; + + do { - int c = m_InBitStream.ReadBits(3); + UInt32 val = _inBitStream.GetValue(16); + unsigned c = val >> 13; + if (c == 7) - while (ReadBits(1)) + { + UInt32 mask = 1 << 12; + while (mask & val) { - if (c > kMaxHuffmanLen) - return S_FALSE; + mask >>= 1; c++; } + if (c > 16) + return false; + } + + _inBitStream.MovePos(c < 7 ? 3 : c - 3); lens[i++] = (Byte)c; + + if (i == (unsigned)spec) + i += _inBitStream.ReadBits(2); } - while (i < kNumDistanceSymbols) - lens[i++] = 0; - m_PHuffmanDecoder.SetCodeLengths(lens); + while (i < n); + + if (!CheckCodeLens(lens, NPT)) + return false; + return _decoderT.SetCodeLengths(lens); } - return S_OK; } -HRESULT CCoder::ReadCTable() +static const unsigned NUM_C_BITS = 9; + +bool CCoder::ReadC() { - int n = ReadBits(kNumCBits); + _symbolC = -1; + + unsigned n = _inBitStream.ReadBits(NUM_C_BITS); + if (n == 0) { - m_CHuffmanDecoder.Symbol = ReadBits(kNumCBits); - if (m_CHuffmanDecoder.Symbol >= kNumCSymbols) - return S_FALSE; + _symbolC = _inBitStream.ReadBits(NUM_C_BITS); + return ((unsigned)_symbolC < NC); } - else + + if (n > NC) + return false; + { - if (n > kNumCSymbols) - return S_FALSE; - m_CHuffmanDecoder.Symbol = -1; - Byte lens[kNumCSymbols]; - int i = 0; - while (i < n) + Byte lens[NC]; + + unsigned i = 0; + + do { - int c = m_LevelHuffman.Decode(&m_InBitStream); - if (c < kNumSpecLevelSymbols) + UInt32 c = (unsigned)_symbolT; + if (_symbolT < 0) + c = _decoderT.DecodeSymbol(&_inBitStream); + + if (c <= 2) { if (c == 0) c = 1; else if (c == 1) - c = ReadBits(4) + 3; + c = _inBitStream.ReadBits(4) + 3; else - c = ReadBits(kNumCBits) + 20; - while (--c >= 0) - { - if (i > kNumCSymbols) - return S_FALSE; + c = _inBitStream.ReadBits(NUM_C_BITS) + 20; + + if (i + c > n) + return false; + + do lens[i++] = 0; - } + while (--c); } else lens[i++] = (Byte)(c - 2); } - while (i < kNumCSymbols) + while (i < n); + + while (i < NC) lens[i++] = 0; - m_CHuffmanDecoder.SetCodeLengths(lens); + + if (!CheckCodeLens(lens, NC)) + return false; + return _decoderC.SetCodeLengths(lens); } - return S_OK; } -STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream, - ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, - ICompressProgressInfo *progress) +HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress) { - if (outSize == NULL) - return E_INVALIDARG; - - if (!m_OutWindowStream.Create(kHistorySize)) - return E_OUTOFMEMORY; - if (!m_InBitStream.Create(1 << 20)) - return E_OUTOFMEMORY; - - UInt64 pos = 0; - m_OutWindowStream.SetStream(outStream); - m_OutWindowStream.Init(false); - m_InBitStream.SetStream(inStream); - m_InBitStream.Init(); - - CCoderReleaser coderReleaser(this); - - int pbit; - if (m_NumDictBits <= 13) - pbit = 4; - else - pbit = 5; + unsigned pbit = (DictSize <= (1 << 14) ? 4 : 5); UInt32 blockSize = 0; - while (pos < *outSize) + while (rem != 0) { - // for (i = 0; i < dictSize; i++) dtext[i] = 0x20; - if (blockSize == 0) { - if (progress != NULL) + if (_inBitStream.ExtraBitsWereRead()) + return S_FALSE; + + if (progress) { - UInt64 packSize = m_InBitStream.GetProcessedSize(); + UInt64 packSize = _inBitStream.GetProcessedSize(); + UInt64 pos = _outWindow.GetProcessedSize(); RINOK(progress->SetRatioInfo(&packSize, &pos)); } - blockSize = ReadBits(kBlockSizeBits); - ReadLevelTable(); - ReadCTable(); - RINOK(ReadPTable(pbit)); + + blockSize = _inBitStream.ReadBits(16); + if (blockSize == 0) + return S_FALSE; + + if (!ReadTP(NT, 5, 3)) + return S_FALSE; + if (!ReadC()) + return S_FALSE; + if (!ReadTP(NP, pbit, -1)) + return S_FALSE; } + blockSize--; - UInt32 c = m_CHuffmanDecoder.Decode(&m_InBitStream); - if (c < 256) + + UInt32 number = (unsigned)_symbolC; + if (_symbolC < 0) + number = _decoderC.DecodeSymbol(&_inBitStream); + + if (number < 256) { - m_OutWindowStream.PutByte((Byte)c); - pos++; + _outWindow.PutByte((Byte)number); + rem--; } - else if (c >= kNumCSymbols) - return S_FALSE; else { - // offset = (interface->method == LARC_METHOD_NUM) ? 0x100 - 2 : 0x100 - 3; - UInt32 len = c - 256 + kMinMatch; - UInt32 distance = m_PHuffmanDecoder.Decode(&m_InBitStream); - if (distance != 0) - distance = (1 << (distance - 1)) + ReadBits(distance - 1); - if (distance >= pos) + UInt32 len = number - 256 + kMatchMinLen; + + UInt32 dist = (unsigned)_symbolT; + if (_symbolT < 0) + dist = _decoderT.DecodeSymbol(&_inBitStream); + + if (dist > 1) + { + dist--; + dist = ((UInt32)1 << dist) + _inBitStream.ReadBits((unsigned)dist); + } + + if (dist >= DictSize) return S_FALSE; - if (pos + len > *outSize) - len = (UInt32)(*outSize - pos); - pos += len; - m_OutWindowStream.CopyBlock(distance, len); + + if (len > rem) + len = (UInt32)rem; + + if (!_outWindow.CopyBlock(dist, len)) + return S_FALSE; + rem -= len; } } - coderReleaser.NeedFlush = false; - return m_OutWindowStream.Flush(); + + if (FinishMode) + { + if (blockSize != 0) + return S_FALSE; + if (_inBitStream.ReadAlignBits() != 0) + return S_FALSE; + } + + if (_inBitStream.ExtraBitsWereRead()) + return S_FALSE; + + return S_OK; } -STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, - ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, - ICompressProgressInfo *progress) + +STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { - try { return CodeReal(inStream, outStream, inSize, outSize, progress);} + try + { + if (!outSize) + return E_INVALIDARG; + + if (!_outWindow.Create(DictSize > kWindowSizeMin ? DictSize : kWindowSizeMin)) + return E_OUTOFMEMORY; + if (!_inBitStream.Create(1 << 17)) + return E_OUTOFMEMORY; + + _outWindow.SetStream(outStream); + _outWindow.Init(false); + _inBitStream.SetStream(inStream); + _inBitStream.Init(); + + CCoderReleaser coderReleaser(this); + + RINOK(CodeReal(*outSize, progress)); + + coderReleaser.Disable(); + return _outWindow.Flush(); + } catch(const CInBufferException &e) { return e.ErrorCode; } catch(const CLzOutWindowException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } diff --git a/CPP/7zip/Compress/LzhDecoder.h b/CPP/7zip/Compress/LzhDecoder.h index a0a7b244..5e13d823 100644 --- a/CPP/7zip/Compress/LzhDecoder.h +++ b/CPP/7zip/Compress/LzhDecoder.h @@ -17,89 +17,56 @@ namespace NCompress { namespace NLzh { namespace NDecoder { -const int kMaxHuffmanLen = 16; // Check it - -const int kNumSpecLevelSymbols = 3; -const int kNumLevelSymbols = kNumSpecLevelSymbols + kMaxHuffmanLen; - -const int kDictBitsMax = 16; -const int kNumDistanceSymbols = kDictBitsMax + 1; - -const int kMaxMatch = 256; -const int kMinMatch = 3; -const int kNumCSymbols = 256 + kMaxMatch + 2 - kMinMatch; - -template <UInt32 m_NumSymbols> -class CHuffmanDecoder:public NCompress::NHuffman::CDecoder<kMaxHuffmanLen, m_NumSymbols> -{ -public: - int Symbol; - template <class TBitDecoder> - UInt32 Decode(TBitDecoder *bitStream) - { - if (Symbol >= 0) - return (UInt32)Symbol; - return this->DecodeSymbol(bitStream); - } -}; - -class CCoder : +const unsigned kMatchMinLen = 3; +const unsigned kMatchMaxLen = 256; +const unsigned NC = (256 + kMatchMaxLen - kMatchMinLen + 1); +const unsigned NUM_CODE_BITS = 16; +const unsigned NUM_DIC_BITS_MAX = 25; +const unsigned NT = (NUM_CODE_BITS + 3); +const unsigned NP = (NUM_DIC_BITS_MAX + 1); +const unsigned NPT = NP; // Max(NT, NP) + +class CCoder: public ICompressCoder, public CMyUnknownImp { - CLzOutWindow m_OutWindowStream; - NBitm::CDecoder<CInBuffer> m_InBitStream; - - int m_NumDictBits; + CLzOutWindow _outWindow; + NBitm::CDecoder<CInBuffer> _inBitStream; - CHuffmanDecoder<kNumLevelSymbols> m_LevelHuffman; - CHuffmanDecoder<kNumDistanceSymbols> m_PHuffmanDecoder; - CHuffmanDecoder<kNumCSymbols> m_CHuffmanDecoder; + int _symbolT; + int _symbolC; - /* - void ReleaseStreams() - { - m_OutWindowStream.ReleaseStream(); - } - */ + NHuffman::CDecoder<NUM_CODE_BITS, NPT> _decoderT; + NHuffman::CDecoder<NUM_CODE_BITS, NC> _decoderC; class CCoderReleaser { - CCoder *m_Coder; + CCoder *_coder; public: - bool NeedFlush; - CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {} - ~CCoderReleaser() - { - if (NeedFlush) - m_Coder->m_OutWindowStream.Flush(); - // m_Coder->ReleaseStreams(); - } + CCoderReleaser(CCoder *coder): _coder(coder) {} + void Disable() { _coder = NULL; } + ~CCoderReleaser() { if (_coder) _coder->_outWindow.Flush(); } }; friend class CCoderReleaser; - void MakeTable(int nchar, Byte *bitlen, int tablebits, - UInt32 *table, int tablesize); - - UInt32 ReadBits(int numBits); - HRESULT ReadLevelTable(); - HRESULT ReadPTable(int numBits); - HRESULT ReadCTable(); + bool ReadTP(unsigned num, unsigned numBits, int spec); + bool ReadC(); + HRESULT CodeReal(UInt64 outSize, ICompressProgressInfo *progress); public: - MY_UNKNOWN_IMP - STDMETHOD(CodeReal)(ISequentialInStream *inStream, - ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, - ICompressProgressInfo *progress); + UInt32 DictSize; + bool FinishMode; + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); - STDMETHOD(Code)(ISequentialInStream *inStream, - ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, - ICompressProgressInfo *progress); + void SetDictSize(unsigned dictSize) { DictSize = dictSize; } + + CCoder(): DictSize(1 << 16), FinishMode(false) {} - void SetDictionary(int numDictBits) { m_NumDictBits = numDictBits; } - CCoder(): m_NumDictBits(0) {} + UInt64 GetInputProcessedSize() const { return _inBitStream.GetProcessedSize(); } }; }}} diff --git a/CPP/7zip/Compress/Lzma2Decoder.cpp b/CPP/7zip/Compress/Lzma2Decoder.cpp index 322015e2..05b136a7 100644 --- a/CPP/7zip/Compress/Lzma2Decoder.cpp +++ b/CPP/7zip/Compress/Lzma2Decoder.cpp @@ -24,32 +24,40 @@ static HRESULT SResToHRESULT(SRes res) namespace NCompress { namespace NLzma2 { -static const UInt32 kInBufSize = 1 << 20; - -CDecoder::CDecoder(): _inBuf(0), _outSizeDefined(false) +CDecoder::CDecoder(): + _inBuf(NULL), + _inBufSize(0), + _inBufSizeNew(1 << 20), + _outStepSize(1 << 22), + _outSizeDefined(false), + _finishMode(false) { Lzma2Dec_Construct(&_state); } -static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } -static void SzFree(void *p, void *address) { p = p; MyFree(address); } -static ISzAlloc g_Alloc = { SzAlloc, SzFree }; +STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSizeNew = size; return S_OK; } +STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outStepSize = size; return S_OK; } CDecoder::~CDecoder() { Lzma2Dec_Free(&_state, &g_Alloc); - MyFree(_inBuf); + MidFree(_inBuf); } STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size) { - if (size != 1) return SZ_ERROR_UNSUPPORTED; + if (size != 1) + return E_NOTIMPL; + RINOK(SResToHRESULT(Lzma2Dec_Allocate(&_state, prop[0], &g_Alloc))); - if (_inBuf == 0) + if (!_inBuf || _inBufSize != _inBufSizeNew) { - _inBuf = (Byte *)MyAlloc(kInBufSize); - if (_inBuf == 0) + MidFree(_inBuf); + _inBufSize = 0; + _inBuf = (Byte *)MidAlloc(_inBufSizeNew); + if (!_inBuf) return E_OUTOFMEMORY; + _inBufSize = _inBufSizeNew; } return S_OK; @@ -62,6 +70,7 @@ STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; } STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { _outSizeDefined = (outSize != NULL); + _outSize = 0; if (_outSizeDefined) _outSize = *outSize; @@ -72,39 +81,55 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) return S_OK; } +STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode) +{ + _finishMode = (finishMode != 0); + return S_OK; +} + STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, - ISequentialOutStream *outStream, const UInt64 * /* inSize */, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { - if (_inBuf == 0) + if (!_inBuf) return S_FALSE; SetOutStreamSize(outSize); + UInt32 step = _outStepSize; + const UInt32 kOutStepSize_Min = 1 << 12; + if (step < kOutStepSize_Min) + step = kOutStepSize_Min; + + SizeT wrPos = _state.decoder.dicPos; + + SizeT next = (_state.decoder.dicBufSize - _state.decoder.dicPos < step) ? + _state.decoder.dicBufSize : + _state.decoder.dicPos + step; + + HRESULT hres = S_OK; + for (;;) { if (_inPos == _inSize) { _inPos = _inSize = 0; - RINOK(inStream->Read(_inBuf, kInBufSize, &_inSize)); + hres = inStream->Read(_inBuf, _inBufSize, &_inSize); + if (hres != S_OK) + break; } SizeT dicPos = _state.decoder.dicPos; - SizeT curSize = _state.decoder.dicBufSize - dicPos; - const UInt32 kStepSize = ((UInt32)1 << 22); - if (curSize > kStepSize) - curSize = (SizeT)kStepSize; - + SizeT curSize = next - dicPos; + ELzmaFinishMode finishMode = LZMA_FINISH_ANY; if (_outSizeDefined) { const UInt64 rem = _outSize - _outSizeProcessed; - if (rem < curSize) + if (curSize >= rem) { curSize = (SizeT)rem; - /* - // finishMode = LZMA_FINISH_END; - we can't use LZMA_FINISH_END here to allow partial decoding - */ + if (_finishMode) + finishMode = LZMA_FINISH_END; } } @@ -117,71 +142,123 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, SizeT outSizeProcessed = _state.decoder.dicPos - dicPos; _outSizeProcessed += outSizeProcessed; - bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0); - bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize); + bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0 + || status == LZMA_STATUS_FINISHED_WITH_MARK); + bool outFinished = (_outSizeDefined && _outSizeProcessed >= _outSize); - if (res != 0 || _state.decoder.dicPos == _state.decoder.dicBufSize || finished || stopDecoding) + if (res != 0 + || _state.decoder.dicPos >= next + || finished + || outFinished) { - HRESULT res2 = WriteStream(outStream, _state.decoder.dic, _state.decoder.dicPos); + HRESULT res2 = WriteStream(outStream, _state.decoder.dic + wrPos, _state.decoder.dicPos - wrPos); + + if (_state.decoder.dicPos == _state.decoder.dicBufSize) + _state.decoder.dicPos = 0; + + wrPos = _state.decoder.dicPos; + + next = (_state.decoder.dicBufSize - _state.decoder.dicPos < step) ? + _state.decoder.dicBufSize : + _state.decoder.dicPos + step; + if (res != 0) return S_FALSE; RINOK(res2); - if (stopDecoding) - return S_OK; + if (finished) - return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE); - } - if (_state.decoder.dicPos == _state.decoder.dicBufSize) - _state.decoder.dicPos = 0; + { + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + { + if (_finishMode && inSize && *inSize != _inSizeProcessed) + return S_FALSE; + if (finishMode == LZMA_FINISH_END && !outFinished) + return S_FALSE; + return S_OK; + } + return (finishMode == LZMA_FINISH_END) ? S_FALSE : S_OK; + } - if (progress != NULL) + if (outFinished && finishMode == LZMA_FINISH_ANY) + return S_OK; + } + + if (progress) { RINOK(progress->SetRatioInfo(&_inSizeProcessed, &_outSizeProcessed)); } } + + HRESULT res2 = WriteStream(outStream, _state.decoder.dic + wrPos, _state.decoder.dicPos - wrPos); + if (hres != S_OK) + return hres; + return res2; } #ifndef NO_READ_FROM_CODER STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { + UInt32 totalProcessed = 0; + if (processedSize) *processedSize = 0; - do + + for (;;) { if (_inPos == _inSize) { _inPos = _inSize = 0; - RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize)); + RINOK(_inStream->Read(_inBuf, _inBufSize, &_inSize)); } { - SizeT inProcessed = _inSize - _inPos; - + ELzmaFinishMode finishMode = LZMA_FINISH_ANY; if (_outSizeDefined) { const UInt64 rem = _outSize - _outSizeProcessed; - if (rem < size) + if (rem <= size) + { size = (UInt32)rem; + if (_finishMode) + finishMode = LZMA_FINISH_END; + } } SizeT outProcessed = size; + SizeT inProcessed = _inSize - _inPos; + ELzmaStatus status; SRes res = Lzma2Dec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, - _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status); + _inBuf + _inPos, &inProcessed, finishMode, &status); + _inPos += (UInt32)inProcessed; _inSizeProcessed += inProcessed; _outSizeProcessed += outProcessed; size -= (UInt32)outProcessed; data = (Byte *)data + outProcessed; + + totalProcessed += (UInt32)outProcessed; if (processedSize) - *processedSize += (UInt32)outProcessed; - RINOK(SResToHRESULT(res)); + *processedSize = totalProcessed; + + if (res != SZ_OK) + { + if (totalProcessed != 0) + return S_OK; + return SResToHRESULT(res); + } + if (inProcessed == 0 && outProcessed == 0) return S_OK; + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + return S_OK; + if (outProcessed != 0) + { + if (finishMode != LZMA_FINISH_END || _outSize != _outSizeProcessed) + return S_OK; + } } } - while (size != 0); - return S_OK; } #endif diff --git a/CPP/7zip/Compress/Lzma2Decoder.h b/CPP/7zip/Compress/Lzma2Decoder.h index fd7ca2f3..a87912fb 100644 --- a/CPP/7zip/Compress/Lzma2Decoder.h +++ b/CPP/7zip/Compress/Lzma2Decoder.h @@ -15,7 +15,9 @@ namespace NLzma2 { class CDecoder: public ICompressCoder, public ICompressSetDecoderProperties2, + public ICompressSetFinishMode, public ICompressGetInStreamProcessedSize, + public ICompressSetBufSize, #ifndef NO_READ_FROM_CODER public ICompressSetInStream, public ICompressSetOutStreamSize, @@ -27,36 +29,49 @@ class CDecoder: Byte *_inBuf; UInt32 _inPos; UInt32 _inSize; - CLzma2Dec _state; + + bool _finishMode; bool _outSizeDefined; UInt64 _outSize; + UInt64 _inSizeProcessed; UInt64 _outSizeProcessed; + + UInt32 _inBufSize; + UInt32 _inBufSizeNew; + UInt32 _outStepSize; + + CLzma2Dec _state; public: + MY_QUERYINTERFACE_BEGIN2(ICompressCoder) + MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2) + MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode) + MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize) + MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize) #ifndef NO_READ_FROM_CODER - MY_UNKNOWN_IMP5( - ICompressSetDecoderProperties2, - ICompressGetInStreamProcessedSize, - ICompressSetInStream, - ICompressSetOutStreamSize, - ISequentialInStream) - #else - MY_UNKNOWN_IMP2( - ICompressSetDecoderProperties2, - ICompressGetInStreamProcessedSize) + MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) + MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize) + MY_QUERYINTERFACE_ENTRY(ISequentialInStream) #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE - STDMETHOD(Code)(ISequentialInStream *inStream, - ISequentialOutStream *outStream, const UInt64 *_inSize, const UInt64 *outSize, - ICompressProgressInfo *progress); + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + STDMETHOD(SetFinishMode)(UInt32 finishMode); + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); + STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size); + STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size); + STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); #ifndef NO_READ_FROM_CODER diff --git a/CPP/7zip/Compress/Lzma2Encoder.cpp b/CPP/7zip/Compress/Lzma2Encoder.cpp index 5e4c71be..dea297c4 100644 --- a/CPP/7zip/Compress/Lzma2Encoder.cpp +++ b/CPP/7zip/Compress/Lzma2Encoder.cpp @@ -19,14 +19,6 @@ HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep); namespace NLzma2 { -static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } -static void SzBigFree(void *, void *address) { BigFree(address); } -static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; - -static void *SzAlloc(void *, size_t size) { return MyAlloc(size); } -static void SzFree(void *, void *address) { MyFree(address); } -static ISzAlloc g_Alloc = { SzAlloc, SzFree }; - CEncoder::CEncoder() { _encoder = 0; diff --git a/CPP/7zip/Compress/Lzma2Register.cpp b/CPP/7zip/Compress/Lzma2Register.cpp index cace871e..d684d9d0 100644 --- a/CPP/7zip/Compress/Lzma2Register.cpp +++ b/CPP/7zip/Compress/Lzma2Register.cpp @@ -6,15 +6,12 @@ #include "Lzma2Decoder.h" -static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLzma2::CDecoder); } #ifndef EXTRACT_ONLY #include "Lzma2Encoder.h" -static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLzma2::CEncoder); } -#else -#define CreateCodecOut 0 #endif -static CCodecInfo g_CodecInfo = - { CreateCodec, CreateCodecOut, 0x21, L"LZMA2", 1, false }; - -REGISTER_CODEC(LZMA2) +REGISTER_CODEC_E(LZMA2, + NCompress::NLzma2::CDecoder(), + NCompress::NLzma2::CEncoder(), + 0x21, + "LZMA2") diff --git a/CPP/7zip/Compress/LzmaDecoder.cpp b/CPP/7zip/Compress/LzmaDecoder.cpp index a7ee31ba..d96be8ce 100644 --- a/CPP/7zip/Compress/LzmaDecoder.cpp +++ b/CPP/7zip/Compress/LzmaDecoder.cpp @@ -25,20 +25,16 @@ namespace NCompress { namespace NLzma { CDecoder::CDecoder(): _inBuf(0), _propsWereSet(false), _outSizeDefined(false), - _inBufSize(1 << 20), - _outBufSize(1 << 22), - FinishStream(false), - NeedMoreInput(false) + _inBufSize(1 << 20), + _outBufSize(1 << 22), + FinishStream(false), + NeedMoreInput(false) { _inSizeProcessed = 0; _inPos = _inSize = 0; LzmaDec_Construct(&_state); } -static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } -static void SzFree(void *p, void *address) { p = p; MyFree(address); } -static ISzAlloc g_Alloc = { SzAlloc, SzFree }; - CDecoder::~CDecoder() { LzmaDec_Free(&_state, &g_Alloc); @@ -87,6 +83,12 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) return S_OK; } +STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode) +{ + FinishStream = (finishMode != 0); + return S_OK; +} + HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) { if (_inBuf == 0 || !_propsWereSet) diff --git a/CPP/7zip/Compress/LzmaDecoder.h b/CPP/7zip/Compress/LzmaDecoder.h index 754eaa3f..f1f839a4 100644 --- a/CPP/7zip/Compress/LzmaDecoder.h +++ b/CPP/7zip/Compress/LzmaDecoder.h @@ -14,6 +14,7 @@ namespace NLzma { class CDecoder: public ICompressCoder, public ICompressSetDecoderProperties2, + public ICompressSetFinishMode, public ICompressSetBufSize, #ifndef NO_READ_FROM_CODER public ICompressSetInStream, @@ -45,6 +46,7 @@ class CDecoder: public: MY_QUERYINTERFACE_BEGIN2(ICompressCoder) MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2) + MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode) MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize) #ifndef NO_READ_FROM_CODER MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) @@ -57,6 +59,7 @@ public: STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + STDMETHOD(SetFinishMode)(UInt32 finishMode); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size); STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size); diff --git a/CPP/7zip/Compress/LzmaEncoder.cpp b/CPP/7zip/Compress/LzmaEncoder.cpp index 484d0452..0a7e294d 100644 --- a/CPP/7zip/Compress/LzmaEncoder.cpp +++ b/CPP/7zip/Compress/LzmaEncoder.cpp @@ -12,29 +12,21 @@ namespace NCompress { namespace NLzma { -static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } -static void SzBigFree(void *, void *address) { BigFree(address); } -static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; - -static void *SzAlloc(void *, size_t size) { return MyAlloc(size); } -static void SzFree(void *, void *address) { MyFree(address); } -static ISzAlloc g_Alloc = { SzAlloc, SzFree }; - CEncoder::CEncoder() { - _encoder = 0; + _encoder = NULL; _encoder = LzmaEnc_Create(&g_Alloc); - if (_encoder == 0) + if (!_encoder) throw 1; } CEncoder::~CEncoder() { - if (_encoder != 0) + if (_encoder) LzmaEnc_Destroy(_encoder, &g_Alloc, &g_BigAlloc); } -inline wchar_t GetUpperChar(wchar_t c) +static inline wchar_t GetUpperChar(wchar_t c) { if (c >= 'a' && c <= 'z') c -= 0x20; @@ -51,22 +43,21 @@ static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes) int numHashBytesLoc = (int)(*s++ - L'0'); if (numHashBytesLoc < 4 || numHashBytesLoc > 4) return 0; - if (*s++ != 0) + if (*s != 0) return 0; *btMode = 0; *numHashBytes = numHashBytesLoc; return 1; } + if (c != L'B') return 0; - if (GetUpperChar(*s++) != L'T') return 0; int numHashBytesLoc = (int)(*s++ - L'0'); if (numHashBytesLoc < 2 || numHashBytesLoc > 4) return 0; - c = GetUpperChar(*s++); - if (c != L'\0') + if (*s != 0) return 0; *btMode = 1; *numHashBytes = numHashBytesLoc; diff --git a/CPP/7zip/Compress/LzmaRegister.cpp b/CPP/7zip/Compress/LzmaRegister.cpp index 96ed0bae..c12416f2 100644 --- a/CPP/7zip/Compress/LzmaRegister.cpp +++ b/CPP/7zip/Compress/LzmaRegister.cpp @@ -6,15 +6,12 @@ #include "LzmaDecoder.h" -static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CDecoder); } #ifndef EXTRACT_ONLY #include "LzmaEncoder.h" -static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CEncoder); } -#else -#define CreateCodecOut 0 #endif -static CCodecInfo g_CodecInfo = - { CreateCodec, CreateCodecOut, 0x030101, L"LZMA", 1, false }; - -REGISTER_CODEC(LZMA) +REGISTER_CODEC_E(LZMA, + NCompress::NLzma::CDecoder(), + NCompress::NLzma::CEncoder(), + 0x30101, + "LZMA") diff --git a/CPP/7zip/Compress/PpmdDecoder.cpp b/CPP/7zip/Compress/PpmdDecoder.cpp index c02f44f1..ce00343b 100644 --- a/CPP/7zip/Compress/PpmdDecoder.cpp +++ b/CPP/7zip/Compress/PpmdDecoder.cpp @@ -23,10 +23,6 @@ enum kStatus_Error }; -static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } -static void SzBigFree(void *, void *address) { BigFree(address); } -static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; - CDecoder::~CDecoder() { ::MidFree(_outBuf); diff --git a/CPP/7zip/Compress/PpmdEncoder.cpp b/CPP/7zip/Compress/PpmdEncoder.cpp index 5bf83529..00ea9668 100644 --- a/CPP/7zip/Compress/PpmdEncoder.cpp +++ b/CPP/7zip/Compress/PpmdEncoder.cpp @@ -14,10 +14,6 @@ namespace NPpmd { static const UInt32 kBufSize = (1 << 20); -static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } -static void SzBigFree(void *, void *address) { BigFree(address); } -static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; - static const Byte kOrders[10] = { 3, 4, 4, 5, 5, 6, 8, 16, 24, 32 }; void CEncProps::Normalize(int level) @@ -40,7 +36,7 @@ void CEncProps::Normalize(int level) } } } - if (Order == -1) Order = kOrders[level]; + if (Order == -1) Order = kOrders[(unsigned)level]; } CEncoder::CEncoder(): diff --git a/CPP/7zip/Compress/PpmdRegister.cpp b/CPP/7zip/Compress/PpmdRegister.cpp index 9f59fcdd..17f84bd0 100644 --- a/CPP/7zip/Compress/PpmdRegister.cpp +++ b/CPP/7zip/Compress/PpmdRegister.cpp @@ -1,5 +1,4 @@ // PpmdRegister.cpp -// 2009-05-30 : Igor Pavlov : Public domain #include "StdAfx.h" @@ -7,15 +6,12 @@ #include "PpmdDecoder.h" -static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NPpmd::CDecoder); } #ifndef EXTRACT_ONLY #include "PpmdEncoder.h" -static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NPpmd::CEncoder); } -#else -#define CreateCodecOut 0 #endif -static CCodecInfo g_CodecInfo = - { CreateCodec, CreateCodecOut, 0x030401, L"PPMD", 1, false }; - -REGISTER_CODEC(PPMD) +REGISTER_CODEC_E(PPMD, + NCompress::NPpmd::CDecoder(), + NCompress::NPpmd::CEncoder(), + 0x30401, + "PPMD") diff --git a/CPP/7zip/Compress/PpmdZip.cpp b/CPP/7zip/Compress/PpmdZip.cpp index 036f3c72..24dd32f2 100644 --- a/CPP/7zip/Compress/PpmdZip.cpp +++ b/CPP/7zip/Compress/PpmdZip.cpp @@ -12,10 +12,6 @@ namespace NCompress { namespace NPpmdZip { -static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } -static void SzBigFree(void *, void *address) { BigFree(address); } -static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; - CDecoder::CDecoder(bool fullFileMode): _fullFileMode(fullFileMode) { @@ -260,14 +256,4 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream } } -/* -static void *CreateCodec() { return (void *)(ICompressCoder *)(new CDecoder(false)); } -static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new CEncoder); } - -static CCodecInfo g_CodecInfo = - { CreateCodec, CreateCodecOut, 0x040162, L"PPMdZIP", 1, false }; - -REGISTER_CODEC(PPMdZIP) -*/ - }} diff --git a/CPP/7zip/Compress/RangeCoder.h b/CPP/7zip/Compress/RangeCoder.h deleted file mode 100644 index 0b0d44ae..00000000 --- a/CPP/7zip/Compress/RangeCoder.h +++ /dev/null @@ -1,201 +0,0 @@ -// Compress/RangeCoder.h -// 2013-01-10 : Igor Pavlov : Public domain - -#ifndef __COMPRESS_RANGE_CODER_H -#define __COMPRESS_RANGE_CODER_H - -#include "../Common/InBuffer.h" -#include "../Common/OutBuffer.h" - -namespace NCompress { -namespace NRangeCoder { - -const unsigned kNumTopBits = 24; -const UInt32 kTopValue = (1 << kNumTopBits); - -class CEncoder -{ - UInt32 _cacheSize; - Byte _cache; -public: - UInt64 Low; - UInt32 Range; - COutBuffer Stream; - bool Create(UInt32 bufSize) { return Stream.Create(bufSize); } - - void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } - void Init() - { - Stream.Init(); - Low = 0; - Range = 0xFFFFFFFF; - _cacheSize = 1; - _cache = 0; - } - - void FlushData() - { - // Low += 1; - for (int i = 0; i < 5; i++) - ShiftLow(); - } - - HRESULT FlushStream() { return Stream.Flush(); } - - void Encode(UInt32 start, UInt32 size, UInt32 total) - { - Low += start * (Range /= total); - Range *= size; - while (Range < kTopValue) - { - Range <<= 8; - ShiftLow(); - } - } - - void ShiftLow() - { - if ((UInt32)Low < (UInt32)0xFF000000 || (unsigned)(Low >> 32) != 0) - { - Byte temp = _cache; - do - { - Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); - temp = 0xFF; - } - while (--_cacheSize != 0); - _cache = (Byte)((UInt32)Low >> 24); - } - _cacheSize++; - Low = (UInt32)Low << 8; - } - - void EncodeDirectBits(UInt32 value, int numBits) - { - for (numBits--; numBits >= 0; numBits--) - { - Range >>= 1; - Low += Range & (0 - ((value >> numBits) & 1)); - if (Range < kTopValue) - { - Range <<= 8; - ShiftLow(); - } - } - } - - void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol) - { - UInt32 newBound = (Range >> numTotalBits) * size0; - if (symbol == 0) - Range = newBound; - else - { - Low += newBound; - Range -= newBound; - } - while (Range < kTopValue) - { - Range <<= 8; - ShiftLow(); - } - } - - UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } -}; - -class CDecoder -{ -public: - CInBuffer Stream; - UInt32 Range; - UInt32 Code; - bool Create(UInt32 bufSize) { return Stream.Create(bufSize); } - - void Normalize() - { - while (Range < kTopValue) - { - Code = (Code << 8) | Stream.ReadByte(); - Range <<= 8; - } - } - - void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } - void Init() - { - Stream.Init(); - Code = 0; - Range = 0xFFFFFFFF; - for (int i = 0; i < 5; i++) - Code = (Code << 8) | Stream.ReadByte(); - } - - UInt32 GetThreshold(UInt32 total) - { - return (Code) / (Range /= total); - } - - void Decode(UInt32 start, UInt32 size) - { - Code -= start * Range; - Range *= size; - Normalize(); - } - - UInt32 DecodeDirectBits(int numTotalBits) - { - UInt32 range = Range; - UInt32 code = Code; - UInt32 result = 0; - for (int i = numTotalBits; i != 0; i--) - { - range >>= 1; - /* - result <<= 1; - if (code >= range) - { - code -= range; - result |= 1; - } - */ - UInt32 t = (code - range) >> 31; - code -= range & (t - 1); - result = (result << 1) | (1 - t); - - if (range < kTopValue) - { - code = (code << 8) | Stream.ReadByte(); - range <<= 8; - } - } - Range = range; - Code = code; - return result; - } - - UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) - { - UInt32 newBound = (Range >> numTotalBits) * size0; - UInt32 symbol; - if (Code < newBound) - { - symbol = 0; - Range = newBound; - } - else - { - symbol = 1; - Code -= newBound; - Range -= newBound; - } - Normalize(); - return symbol; - } - - UInt64 GetProcessedSize() { return Stream.GetProcessedSize(); } -}; - -}} - -#endif diff --git a/CPP/7zip/Compress/RangeCoderBit.h b/CPP/7zip/Compress/RangeCoderBit.h deleted file mode 100644 index 0eddd558..00000000 --- a/CPP/7zip/Compress/RangeCoderBit.h +++ /dev/null @@ -1,114 +0,0 @@ -// Compress/RangeCoderBit.h -// 2013-01-10 : Igor Pavlov : Public domain - -#ifndef __COMPRESS_RANGE_CODER_BIT_H -#define __COMPRESS_RANGE_CODER_BIT_H - -#include "RangeCoder.h" - -namespace NCompress { -namespace NRangeCoder { - -const unsigned kNumBitModelTotalBits = 11; -const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); - -const unsigned kNumMoveReducingBits = 4; - -const unsigned kNumBitPriceShiftBits = 4; -const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; - -extern UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; - -template <unsigned numMoveBits> -class CBitModel -{ -public: - UInt32 Prob; - void UpdateModel(UInt32 symbol) - { - /* - Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; - Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); - */ - if (symbol == 0) - Prob += (kBitModelTotal - Prob) >> numMoveBits; - else - Prob -= (Prob) >> numMoveBits; - } -public: - void Init() { Prob = kBitModelTotal / 2; } -}; - -template <unsigned numMoveBits> -class CBitEncoder: public CBitModel<numMoveBits> -{ -public: - void Encode(CEncoder *encoder, UInt32 symbol) - { - /* - encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); - this->UpdateModel(symbol); - */ - UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; - if (symbol == 0) - { - encoder->Range = newBound; - this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; - } - else - { - encoder->Low += newBound; - encoder->Range -= newBound; - this->Prob -= (this->Prob) >> numMoveBits; - } - if (encoder->Range < kTopValue) - { - encoder->Range <<= 8; - encoder->ShiftLow(); - } - } - UInt32 GetPrice(UInt32 symbol) const - { - return ProbPrices[(this->Prob ^ ((-(int)(Int32)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; - } - UInt32 GetPrice0() const { return ProbPrices[this->Prob >> kNumMoveReducingBits]; } - UInt32 GetPrice1() const { return ProbPrices[(this->Prob ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } -}; - - -template <unsigned numMoveBits> -class CBitDecoder: public CBitModel<numMoveBits> -{ -public: - UInt32 Decode(CDecoder *decoder) - { - UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob; - if (decoder->Code < newBound) - { - decoder->Range = newBound; - this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; - if (decoder->Range < kTopValue) - { - decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); - decoder->Range <<= 8; - } - return 0; - } - else - { - decoder->Range -= newBound; - decoder->Code -= newBound; - this->Prob -= (this->Prob) >> numMoveBits; - if (decoder->Range < kTopValue) - { - decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); - decoder->Range <<= 8; - } - return 1; - } - } -}; - -}} - -#endif diff --git a/CPP/7zip/Compress/Rar1Decoder.cpp b/CPP/7zip/Compress/Rar1Decoder.cpp index 8eb904df..12de7e19 100644 --- a/CPP/7zip/Compress/Rar1Decoder.cpp +++ b/CPP/7zip/Compress/Rar1Decoder.cpp @@ -9,13 +9,13 @@ namespace NCompress { namespace NRar1 { -static UInt32 PosL1[]={0,0,0,2,3,5,7,11,16,20,24,32,32, 256}; -static UInt32 PosL2[]={0,0,0,0,5,7,9,13,18,22,26,34,36, 256}; -static UInt32 PosHf0[]={0,0,0,0,0,8,16,24,33,33,33,33,33, 257}; -static UInt32 PosHf1[]={0,0,0,0,0,0,4,44,60,76,80,80,127, 257}; -static UInt32 PosHf2[]={0,0,0,0,0,0,2,7,53,117,233, 257,0}; -static UInt32 PosHf3[]={0,0,0,0,0,0,0,2,16,218,251, 257,0}; -static UInt32 PosHf4[]={0,0,0,0,0,0,0,0,0,255, 257,0,0}; +static const UInt32 PosL1[] = {0,0,0,2,3,5,7,11,16,20,24,32,32, 256}; +static const UInt32 PosL2[] = {0,0,0,0,5,7,9,13,18,22,26,34,36, 256}; +static const UInt32 PosHf0[] = {0,0,0,0,0,8,16,24,33,33,33,33,33, 257}; +static const UInt32 PosHf1[] = {0,0,0,0,0,0,4,44,60,76,80,80,127, 257}; +static const UInt32 PosHf2[] = {0,0,0,0,0,0,2,7,53,117,233, 257,0}; +static const UInt32 PosHf3[] = {0,0,0,0,0,0,0,2,16,218,251, 257,0}; +static const UInt32 PosHf4[] = {0,0,0,0,0,0,0,0,0,255, 257,0,0}; static const UInt32 kHistorySize = (1 << 16); @@ -67,18 +67,18 @@ UInt32 CDecoder::DecodeNum(const UInt32 *posTab) return((num >> (12 - startPos)) + posTab[startPos]); } -static Byte kShortLen1 [] = {1,3,4,4,5,6,7,8,8,4,4,5,6,6 }; -static Byte kShortLen1a[] = {1,4,4,4,5,6,7,8,8,4,4,5,6,6,4 }; -static Byte kShortLen2 [] = {2,3,3,3,4,4,5,6,6,4,4,5,6,6 }; -static Byte kShortLen2a[] = {2,3,3,4,4,4,5,6,6,4,4,5,6,6,4 }; -static UInt32 kShortXor1[] = {0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0}; -static UInt32 kShortXor2[] = {0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0}; +static const Byte kShortLen1 [] = {1,3,4,4,5,6,7,8,8,4,4,5,6,6 }; +static const Byte kShortLen1a[] = {1,4,4,4,5,6,7,8,8,4,4,5,6,6,4 }; +static const Byte kShortLen2 [] = {2,3,3,3,4,4,5,6,6,4,4,5,6,6 }; +static const Byte kShortLen2a[] = {2,3,3,4,4,4,5,6,6,4,4,5,6,6,4 }; +static const UInt32 kShortXor1[] = {0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0}; +static const UInt32 kShortXor2[] = {0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0}; HRESULT CDecoder::ShortLZ() { UInt32 len, saveLen, dist; int distancePlace; - Byte *kShortLen; + const Byte *kShortLen; const UInt32 *kShortXor; NumHuf = 0; @@ -143,17 +143,18 @@ HRESULT CDecoder::ShortLZ() AvrLn1 -= AvrLn1 >> 4; distancePlace = DecodeNum(PosHf2) & 0xff; - dist = ChSetA[distancePlace]; + dist = ChSetA[(unsigned)distancePlace]; if (--distancePlace != -1) { PlaceA[dist]--; - UInt32 lastDistance = ChSetA[distancePlace]; + UInt32 lastDistance = ChSetA[(unsigned)distancePlace]; PlaceA[lastDistance]++; - ChSetA[distancePlace + 1] = lastDistance; - ChSetA[distancePlace] = dist; + ChSetA[(unsigned)distancePlace + 1] = lastDistance; + ChSetA[(unsigned)distancePlace] = dist; } len += 2; } + m_RepDists[m_RepDistPtr++] = dist; m_RepDistPtr &= 3; LastLength = len; @@ -210,6 +211,7 @@ HRESULT CDecoder::LongLZ() AvrPlcB += distancePlace; AvrPlcB -= AvrPlcB >> 8; + for (;;) { dist = ChSetB[distancePlace & 0xff]; @@ -226,6 +228,7 @@ HRESULT CDecoder::LongLZ() dist = ((dist & 0xff00) >> 1) | ReadBits(7); oldAvr3 = AvrLn3; + if (len != 1 && len != 4) if (len == 0 && dist <= MaxDist3) { @@ -235,19 +238,24 @@ HRESULT CDecoder::LongLZ() else if (AvrLn3 > 0) AvrLn3--; + len += 3; + if (dist >= MaxDist3) len++; if (dist <= 256) len += 8; + if (oldAvr3 > 0xb0 || AvrPlc >= 0x2a00 && oldAvr2 < 0x40) MaxDist3 = 0x7f00; else MaxDist3 = 0x2001; + m_RepDists[m_RepDistPtr++] = --dist; m_RepDistPtr &= 3; LastLength = len; LastDist = dist; + return CopyBlock(dist, len); } @@ -264,6 +272,7 @@ HRESULT CDecoder::HuffDecode() else if (AvrPlc > 0x35ff) bytePlace = DecodeNum(PosHf2); else if (AvrPlc > 0x0dff) bytePlace = DecodeNum(PosHf1); else bytePlace = DecodeNum(PosHf0); + if (StMode) { if (--bytePlace == -1) @@ -284,10 +293,12 @@ HRESULT CDecoder::HuffDecode() } else if (NumHuf++ >= 16 && FlagsCnt == 0) StMode = 1; + bytePlace &= 0xff; AvrPlc += bytePlace; AvrPlc -= AvrPlc >> 8; Nhfb+=16; + if (Nhfb > 0xff) { Nhfb=0x90; diff --git a/CPP/7zip/Compress/Rar2Decoder.cpp b/CPP/7zip/Compress/Rar2Decoder.cpp index c4312f9b..6f42d2e6 100644 --- a/CPP/7zip/Compress/Rar2Decoder.cpp +++ b/CPP/7zip/Compress/Rar2Decoder.cpp @@ -20,19 +20,22 @@ Byte CFilter::Decode(int &channelDelta, Byte deltaByte) int predictedValue = ((8 * LastChar + K1 * D1 + K2 * D2 + K3 * D3 + K4 * D4 + K5 * channelDelta) >> 3); Byte realValue = (Byte)(predictedValue - deltaByte); - int i = ((int)(signed char)deltaByte) << 3; + + { + int i = ((int)(signed char)deltaByte) << 3; - Dif[0] += abs(i); - Dif[1] += abs(i - D1); - Dif[2] += abs(i + D1); - Dif[3] += abs(i - D2); - Dif[4] += abs(i + D2); - Dif[5] += abs(i - D3); - Dif[6] += abs(i + D3); - Dif[7] += abs(i - D4); - Dif[8] += abs(i + D4); - Dif[9] += abs(i - channelDelta); - Dif[10] += abs(i + channelDelta); + Dif[0] += abs(i); + Dif[1] += abs(i - D1); + Dif[2] += abs(i + D1); + Dif[3] += abs(i - D2); + Dif[4] += abs(i + D2); + Dif[5] += abs(i - D3); + Dif[6] += abs(i + D3); + Dif[7] += abs(i - D4); + Dif[8] += abs(i + D4); + Dif[9] += abs(i - channelDelta); + Dif[10] += abs(i + channelDelta); + } channelDelta = LastDelta = (signed char)(realValue - LastChar); LastChar = realValue; @@ -42,7 +45,8 @@ Byte CFilter::Decode(int &channelDelta, Byte deltaByte) UInt32 minDif = Dif[0]; UInt32 numMinDif = 0; Dif[0] = 0; - for (i = 1; i < sizeof(Dif) / sizeof(Dif[0]); i++) + + for (unsigned i = 1; i < ARRAY_SIZE(Dif); i++) { if (Dif[i] < minDif) { @@ -51,6 +55,7 @@ Byte CFilter::Decode(int &channelDelta, Byte deltaByte) } Dif[i] = 0; } + switch(numMinDif) { case 1: if (K1 >= -16) K1--; break; @@ -65,14 +70,13 @@ Byte CFilter::Decode(int &channelDelta, Byte deltaByte) case 10:if (K5 < 16) K5++; break; } } + return realValue; } } static const UInt32 kHistorySize = 1 << 20; -static const int kNumStats = 11; - static const UInt32 kWindowReservSize = (1 << 22) + 256; CDecoder::CDecoder(): @@ -83,14 +87,14 @@ CDecoder::CDecoder(): void CDecoder::InitStructures() { m_MmFilter.Init(); - for (int i = 0; i < kNumRepDists; i++) + for (unsigned i = 0; i < kNumRepDists; i++) m_RepDists[i] = 0; m_RepDistPtr = 0; m_LastLength = 0; memset(m_LastLevels, 0, kMaxTableSize); } -UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); } +UInt32 CDecoder::ReadBits(unsigned numBits) { return m_InBitStream.ReadBits(numBits); } #define RIF(x) { if (!(x)) return false; } @@ -102,7 +106,9 @@ bool CDecoder::ReadTables(void) if (ReadBits(1) == 0) memset(m_LastLevels, 0, kMaxTableSize); - int numLevels; + + unsigned numLevels; + if (m_AudioMode) { m_NumChannels = ReadBits(2) + 1; @@ -113,11 +119,13 @@ bool CDecoder::ReadTables(void) else numLevels = kHeapTablesSizesSum; - int i; + unsigned i; for (i = 0; i < kLevelTableSize; i++) levelLevels[i] = (Byte)ReadBits(4); RIF(m_LevelDecoder.SetCodeLengths(levelLevels)); + i = 0; + while (i < numLevels) { UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream); @@ -130,24 +138,25 @@ bool CDecoder::ReadTables(void) { if (number == kTableLevelRepNumber) { - int t = ReadBits(2) + 3; - for (int reps = t; reps > 0 && i < numLevels ; reps--, i++) + unsigned t = ReadBits(2) + 3; + for (unsigned reps = t; reps > 0 && i < numLevels; reps--, i++) newLevels[i] = newLevels[i - 1]; } else { - int num; + unsigned num; if (number == kTableLevel0Number) num = ReadBits(3) + 3; else if (number == kTableLevel0Number2) num = ReadBits(7) + 11; else return false; - for (;num > 0 && i < numLevels; num--) + for (; num > 0 && i < numLevels; num--) newLevels[i++] = 0; } } } + if (m_AudioMode) for (i = 0; i < m_NumChannels; i++) { @@ -159,6 +168,7 @@ bool CDecoder::ReadTables(void) RIF(m_DistDecoder.SetCodeLengths(&newLevels[kMainTableSize])); RIF(m_LenDecoder.SetCodeLengths(&newLevels[kMainTableSize + kDistTableSize])); } + memcpy(m_LastLevels, newLevels, kMaxTableSize); return true; } diff --git a/CPP/7zip/Compress/Rar2Decoder.h b/CPP/7zip/Compress/Rar2Decoder.h index 44b262c1..3a0535cc 100644 --- a/CPP/7zip/Compress/Rar2Decoder.h +++ b/CPP/7zip/Compress/Rar2Decoder.h @@ -18,10 +18,10 @@ namespace NCompress { namespace NRar2 { -const UInt32 kNumRepDists = 4; -const UInt32 kDistTableSize = 48; +const unsigned kNumRepDists = 4; +const unsigned kDistTableSize = 48; -const int kMMTableSize = 256 + 1; +const unsigned kMMTableSize = 256 + 1; const UInt32 kMainTableSize = 298; const UInt32 kLenTableSize = 28; @@ -89,14 +89,14 @@ struct CFilter }; -const int kNumChanelsMax = 4; +const unsigned kNumChanelsMax = 4; class CFilter2 { public: CFilter m_Filters[kNumChanelsMax]; int m_ChannelDelta; - int CurrentChannel; + unsigned CurrentChannel; void Init() { memset(this, 0, sizeof(*this)); } Byte Decode(Byte delta) @@ -110,7 +110,7 @@ public: typedef NBitm::CDecoder<CInBuffer> CBitDecoder; -const int kNumHuffmanBits = 15; +const unsigned kNumHuffmanBits = 15; class CDecoder : public ICompressCoder, @@ -128,7 +128,7 @@ class CDecoder : bool m_AudioMode; NMultimedia::CFilter2 m_MmFilter; - int m_NumChannels; + unsigned m_NumChannels; UInt32 m_RepDists[kNumRepDists]; UInt32 m_RepDistPtr; @@ -141,7 +141,7 @@ class CDecoder : bool m_IsSolid; void InitStructures(); - UInt32 ReadBits(int numBits); + UInt32 ReadBits(unsigned numBits); bool ReadTables(); bool ReadLastTables(); diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp index 3c70e1c0..f0553c85 100644 --- a/CPP/7zip/Compress/Rar3Decoder.cpp +++ b/CPP/7zip/Compress/Rar3Decoder.cpp @@ -15,10 +15,6 @@ namespace NCompress { namespace NRar3 { -static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } -static void SzBigFree(void *, void *address) { BigFree(address); } -static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; - static const UInt32 kNumAlignReps = 15; static const UInt32 kSymbolReadTable = 256; diff --git a/CPP/7zip/Compress/Rar3Vm.cpp b/CPP/7zip/Compress/Rar3Vm.cpp index 5b113bfa..3cbfb0e1 100644 --- a/CPP/7zip/Compress/Rar3Vm.cpp +++ b/CPP/7zip/Compress/Rar3Vm.cpp @@ -696,11 +696,11 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize) cmd->OpCode = (ECommand)inp.ReadBits(3); else cmd->OpCode = (ECommand)(8 + inp.ReadBits(5)); - if (kCmdFlags[cmd->OpCode] & CF_BYTEMODE) + if (kCmdFlags[(unsigned)cmd->OpCode] & CF_BYTEMODE) cmd->ByteMode = (inp.ReadBit()) ? true : false; else cmd->ByteMode = 0; - int opNum = (kCmdFlags[cmd->OpCode] & CF_OPMASK); + int opNum = (kCmdFlags[(unsigned)cmd->OpCode] & CF_OPMASK); if (opNum > 0) { DecodeArg(inp, cmd->Op1, cmd->ByteMode); @@ -708,7 +708,7 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize) DecodeArg(inp, cmd->Op2, cmd->ByteMode); else { - if (cmd->Op1.Type == OP_TYPE_INT && (kCmdFlags[cmd->OpCode] & (CF_JUMP | CF_PROC))) + if (cmd->Op1.Type == OP_TYPE_INT && (kCmdFlags[(unsigned)cmd->OpCode] & (CF_JUMP | CF_PROC))) { int dist = cmd->Op1.Data; if (dist >= 256) @@ -784,7 +784,7 @@ kStdFilters[]= static int FindStandardFilter(const Byte *code, UInt32 codeSize) { UInt32 crc = CrcCalc(code, codeSize); - for (int i = 0; i < sizeof(kStdFilters) / sizeof(kStdFilters[0]); i++) + for (unsigned i = 0; i < ARRAY_SIZE(kStdFilters); i++) { const CStandardFilterSignature &sfs = kStdFilters[i]; if (sfs.CRC == crc && sfs.Length == codeSize) @@ -857,6 +857,7 @@ static inline UInt32 ItaniumGetOpType(const Byte *data, int bitPos) return (data[(unsigned int)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}; static void ItaniumDecode(Byte *data, UInt32 dataSize, UInt32 fileOffset) { @@ -867,7 +868,6 @@ static void ItaniumDecode(Byte *data, UInt32 dataSize, UInt32 fileOffset) int b = (data[0] & 0x1F) - 0x10; if (b >= 0) { - static Byte kCmdMasks[16] = {4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0}; Byte cmdMask = kCmdMasks[b]; if (cmdMask != 0) for (int i = 0; i < 3; i++) @@ -993,7 +993,7 @@ static void AudioDecode(Byte *srcData, UInt32 dataSize, UInt32 numChannels) { UInt32 minDif = dif[0], numMinDif = 0; dif[0] = 0; - for (int j = 1; j < sizeof(dif) / sizeof(dif[0]); j++) + for (unsigned j = 1; j < ARRAY_SIZE(dif); j++) { if (dif[j] < minDif) { @@ -1029,7 +1029,7 @@ static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize) return destPos - dataSize; } -void CVm::ExecuteStandardFilter(int filterIndex) +void CVm::ExecuteStandardFilter(unsigned filterIndex) { UInt32 dataSize = R[4]; if (dataSize >= kGlobalOffset) diff --git a/CPP/7zip/Compress/Rar3Vm.h b/CPP/7zip/Compress/Rar3Vm.h index 55842b90..23f4abab 100644 --- a/CPP/7zip/Compress/Rar3Vm.h +++ b/CPP/7zip/Compress/Rar3Vm.h @@ -157,7 +157,7 @@ private: bool ExecuteCode(const CProgram *prg); #ifdef RARVM_STANDARD_FILTERS - void ExecuteStandardFilter(int filterIndex); + void ExecuteStandardFilter(unsigned filterIndex); #endif Byte *Mem; diff --git a/CPP/7zip/Compress/RarCodecsRegister.cpp b/CPP/7zip/Compress/RarCodecsRegister.cpp index e3f6a05c..66fcc9a9 100644 --- a/CPP/7zip/Compress/RarCodecsRegister.cpp +++ b/CPP/7zip/Compress/RarCodecsRegister.cpp @@ -8,19 +8,19 @@ #include "Rar2Decoder.h" #include "Rar3Decoder.h" -#define CREATE_CODEC(x) static void *CreateCodec ## x() { return (void *)(ICompressCoder *)(new NCompress::NRar ## x::CDecoder); } +#define CREATE_CODEC(x) REGISTER_CODEC_CREATE(CreateCodec ## x, NCompress::NRar ## x::CDecoder()) CREATE_CODEC(1) CREATE_CODEC(2) CREATE_CODEC(3) -#define RAR_CODEC(x, name) { CreateCodec ## x, 0, 0x040300 + x, L"Rar" name, 1, false } +#define RAR_CODEC(x, name) { CreateCodec ## x, NULL, 0x40300 + x, "Rar" name, 1, false } -static CCodecInfo g_CodecsInfo[] = +REGISTER_CODECS_VAR { - RAR_CODEC(1, L"1"), - RAR_CODEC(2, L"2"), - RAR_CODEC(3, L"3"), + RAR_CODEC(1, "1"), + RAR_CODEC(2, "2"), + RAR_CODEC(3, "3"), }; REGISTER_CODECS(Rar) diff --git a/CPP/7zip/Crc.mak b/CPP/7zip/Crc.mak index 7f2552c1..f2b0874c 100644 --- a/CPP/7zip/Crc.mak +++ b/CPP/7zip/Crc.mak @@ -1,6 +1,6 @@ C_OBJS = $(C_OBJS) \ $O\7zCrc.obj -!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS" +!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS" || "$(CPU)" == "ARM" C_OBJS = $(C_OBJS) \ !ELSE ASM_OBJS = $(ASM_OBJS) \ diff --git a/CPP/7zip/Crypto/7zAes.cpp b/CPP/7zip/Crypto/7zAes.cpp index 548c674b..a3c725eb 100644 --- a/CPP/7zip/Crypto/7zAes.cpp +++ b/CPP/7zip/Crypto/7zAes.cpp @@ -4,9 +4,12 @@ #include "../../../C/Sha256.h" +#include "../../Common/ComTry.h" + +#ifndef _7ZIP_ST #include "../../Windows/Synchronization.h" +#endif -#include "../Common/StreamObjects.h" #include "../Common/StreamUtils.h" #include "7zAes.h" @@ -16,60 +19,71 @@ #include "RandGen.h" #endif -using namespace NWindows; - namespace NCrypto { -namespace NSevenZ { +namespace N7z { + +static const unsigned k_NumCyclesPower_Supported_MAX = 24; bool CKeyInfo::IsEqualTo(const CKeyInfo &a) const { if (SaltSize != a.SaltSize || NumCyclesPower != a.NumCyclesPower) return false; - for (UInt32 i = 0; i < SaltSize; i++) + for (unsigned i = 0; i < SaltSize; i++) if (Salt[i] != a.Salt[i]) return false; return (Password == a.Password); } -void CKeyInfo::CalculateDigest() +void CKeyInfo::CalcKey() { if (NumCyclesPower == 0x3F) { - UInt32 pos; + unsigned pos; for (pos = 0; pos < SaltSize; pos++) Key[pos] = Salt[pos]; - for (UInt32 i = 0; i < Password.Size() && pos < kKeySize; i++) + for (unsigned i = 0; i < Password.Size() && pos < kKeySize; i++) Key[pos++] = Password[i]; for (; pos < kKeySize; pos++) Key[pos] = 0; } else { + size_t bufSize = 8 + SaltSize + Password.Size(); + CObjArray<Byte> buf(bufSize); + memcpy(buf, Salt, SaltSize); + memcpy(buf + SaltSize, Password, Password.Size()); + CSha256 sha; Sha256_Init(&sha); - const UInt64 numRounds = (UInt64)1 << NumCyclesPower; - Byte temp[8] = { 0,0,0,0,0,0,0,0 }; - for (UInt64 round = 0; round < numRounds; round++) + + Byte *ctr = buf + SaltSize + Password.Size(); + + for (unsigned i = 0; i < 8; i++) + ctr[i] = 0; + + UInt64 numRounds = (UInt64)1 << NumCyclesPower; + + do { - Sha256_Update(&sha, Salt, (size_t)SaltSize); - Sha256_Update(&sha, Password, Password.Size()); - Sha256_Update(&sha, temp, 8); - for (int i = 0; i < 8; i++) - if (++(temp[i]) != 0) + Sha256_Update(&sha, buf, bufSize); + for (unsigned i = 0; i < 8; i++) + if (++(ctr[i]) != 0) break; } + while(--numRounds != 0); + Sha256_Final(&sha, Key); } } -bool CKeyInfoCache::Find(CKeyInfo &key) +bool CKeyInfoCache::GetKey(CKeyInfo &key) { FOR_VECTOR (i, Keys) { const CKeyInfo &cached = Keys[i]; if (key.IsEqualTo(cached)) { - for (int j = 0; j < kKeySize; j++) + for (unsigned j = 0; j < kKeySize; j++) key.Key[j] = cached.Key[j]; if (i != 0) Keys.MoveToFront(i); @@ -79,40 +93,60 @@ bool CKeyInfoCache::Find(CKeyInfo &key) return false; } -void CKeyInfoCache::Add(CKeyInfo &key) +void CKeyInfoCache::FindAndAdd(const CKeyInfo &key) +{ + FOR_VECTOR (i, Keys) + { + const CKeyInfo &cached = Keys[i]; + if (key.IsEqualTo(cached)) + { + if (i != 0) + Keys.MoveToFront(i); + return; + } + } + Add(key); +} + +void CKeyInfoCache::Add(const CKeyInfo &key) { - if (Find(key)) - return; if (Keys.Size() >= Size) Keys.DeleteBack(); Keys.Insert(0, key); } static CKeyInfoCache g_GlobalKeyCache(32); -static NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection; + +#ifndef _7ZIP_ST + static NWindows::NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection; + #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection); +#else + #define MT_LOCK +#endif CBase::CBase(): _cachedKeys(16), _ivSize(0) { - for (int i = 0; i < sizeof(_iv); i++) + for (unsigned i = 0; i < sizeof(_iv); i++) _iv[i] = 0; } -void CBase::CalculateDigest() +void CBase::PrepareKey() { - NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection); - if (_cachedKeys.Find(_key)) - g_GlobalKeyCache.Add(_key); - else + // BCJ2 threads use same password. So we use long lock. + MT_LOCK + + bool finded = false; + if (!_cachedKeys.GetKey(_key)) { - if (!g_GlobalKeyCache.Find(_key)) - { - _key.CalculateDigest(); - g_GlobalKeyCache.Add(_key); - } + finded = g_GlobalKeyCache.GetKey(_key); + if (!finded) + _key.CalcKey(); _cachedKeys.Add(_key); } + if (!finded) + g_GlobalKeyCache.FindAndAdd(_key); } #ifndef EXTRACT_ONLY @@ -128,102 +162,114 @@ STDMETHODIMP CEncoder::ResetSalt() STDMETHODIMP CEncoder::ResetInitVector() { + for (unsigned i = 0; i < sizeof(_iv); i++) + _iv[i] = 0; _ivSize = 8; - g_RandomGenerator.Generate(_iv, (unsigned)_ivSize); + g_RandomGenerator.Generate(_iv, _ivSize); return S_OK; } STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) { - // _key.Init(); - for (UInt32 i = _ivSize; i < sizeof(_iv); i++) - _iv[i] = 0; + Byte props[2 + sizeof(_key.Salt) + sizeof(_iv)]; + unsigned propsSize = 1; - UInt32 ivSize = _ivSize; - - // _key.NumCyclesPower = 0x3F; - _key.NumCyclesPower = 19; + props[0] = (Byte)(_key.NumCyclesPower + | (_key.SaltSize == 0 ? 0 : (1 << 7)) + | (_ivSize == 0 ? 0 : (1 << 6))); - Byte firstByte = (Byte)(_key.NumCyclesPower | - (((_key.SaltSize == 0) ? 0 : 1) << 7) | - (((ivSize == 0) ? 0 : 1) << 6)); - RINOK(outStream->Write(&firstByte, 1, NULL)); - if (_key.SaltSize == 0 && ivSize == 0) - return S_OK; - Byte saltSizeSpec = (Byte)((_key.SaltSize == 0) ? 0 : (_key.SaltSize - 1)); - Byte ivSizeSpec = (Byte)((ivSize == 0) ? 0 : (ivSize - 1)); - Byte secondByte = (Byte)(((saltSizeSpec) << 4) | ivSizeSpec); - RINOK(outStream->Write(&secondByte, 1, NULL)); - if (_key.SaltSize > 0) + if (_key.SaltSize != 0 || _ivSize != 0) { - RINOK(WriteStream(outStream, _key.Salt, _key.SaltSize)); + props[1] = (Byte)( + ((_key.SaltSize == 0 ? 0 : _key.SaltSize - 1) << 4) + | (_ivSize == 0 ? 0 : _ivSize - 1)); + memcpy(props + 2, _key.Salt, _key.SaltSize); + propsSize = 2 + _key.SaltSize; + memcpy(props + propsSize, _iv, _ivSize); + propsSize += _ivSize; } - if (ivSize > 0) - { - RINOK(WriteStream(outStream, _iv, ivSize)); - } - return S_OK; + + return WriteStream(outStream, props, propsSize); } -HRESULT CEncoder::CreateFilter() +CEncoder::CEncoder() { + // _key.SaltSize = 4; g_RandomGenerator.Generate(_key.Salt, _key.SaltSize); + // _key.NumCyclesPower = 0x3F; + _key.NumCyclesPower = 19; _aesFilter = new CAesCbcEncoder(kKeySize); - return S_OK; } #endif +CDecoder::CDecoder() +{ + _aesFilter = new CAesCbcDecoder(kKeySize); +} + STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) { - _key.Init(); - UInt32 i; + _key.ClearProps(); + + _ivSize = 0; + unsigned i; for (i = 0; i < sizeof(_iv); i++) _iv[i] = 0; + if (size == 0) return S_OK; - UInt32 pos = 0; - Byte firstByte = data[pos++]; + + Byte b0 = data[0]; - _key.NumCyclesPower = firstByte & 0x3F; - if ((firstByte & 0xC0) == 0) - return S_OK; - _key.SaltSize = (firstByte >> 7) & 1; - UInt32 ivSize = (firstByte >> 6) & 1; + _key.NumCyclesPower = b0 & 0x3F; + if ((b0 & 0xC0) == 0) + return size == 1 ? S_OK : E_INVALIDARG; - if (pos >= size) + if (size <= 1) return E_INVALIDARG; - Byte secondByte = data[pos++]; - - _key.SaltSize += (secondByte >> 4); - ivSize += (secondByte & 0x0F); + + Byte b1 = data[1]; + + unsigned saltSize = ((b0 >> 7) & 1) + (b1 >> 4); + unsigned ivSize = ((b0 >> 6) & 1) + (b1 & 0x0F); - if (pos + _key.SaltSize + ivSize > size) + if (size != 2 + saltSize + ivSize) return E_INVALIDARG; - for (i = 0; i < _key.SaltSize; i++) - _key.Salt[i] = data[pos++]; + _key.SaltSize = saltSize; + data += 2; + for (i = 0; i < saltSize; i++) + _key.Salt[i] = *data++; for (i = 0; i < ivSize; i++) - _iv[i] = data[pos++]; - return (_key.NumCyclesPower <= 24) ? S_OK : E_NOTIMPL; + _iv[i] = *data++; + return (_key.NumCyclesPower <= k_NumCyclesPower_Supported_MAX + || _key.NumCyclesPower == 0x3F) ? S_OK : E_NOTIMPL; } + STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size) { + COM_TRY_BEGIN + _key.Password.CopyFrom(data, (size_t)size); return S_OK; + + COM_TRY_END } STDMETHODIMP CBaseCoder::Init() { - CalculateDigest(); - if (_aesFilter == 0) - { - RINOK(CreateFilter()); - } + COM_TRY_BEGIN + + PrepareKey(); CMyComPtr<ICryptoProperties> cp; RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp)); - RINOK(cp->SetKey(_key.Key, sizeof(_key.Key))); + if (!cp) + return E_FAIL; + RINOK(cp->SetKey(_key.Key, kKeySize)); RINOK(cp->SetInitVector(_iv, sizeof(_iv))); return _aesFilter->Init(); + + COM_TRY_END } STDMETHODIMP_(UInt32) CBaseCoder::Filter(Byte *data, UInt32 size) @@ -231,10 +277,4 @@ STDMETHODIMP_(UInt32) CBaseCoder::Filter(Byte *data, UInt32 size) return _aesFilter->Filter(data, size); } -HRESULT CDecoder::CreateFilter() -{ - _aesFilter = new CAesCbcDecoder(kKeySize); - return S_OK; -} - }} diff --git a/CPP/7zip/Crypto/7zAes.h b/CPP/7zip/Crypto/7zAes.h index 560af5c2..4bd7d291 100644 --- a/CPP/7zip/Crypto/7zAes.h +++ b/CPP/7zip/Crypto/7zAes.h @@ -11,28 +11,30 @@ #include "../IPassword.h" namespace NCrypto { -namespace NSevenZ { +namespace N7z { -const int kKeySize = 32; +const unsigned kKeySize = 32; +const unsigned kSaltSizeMax = 16; +const unsigned kIvSizeMax = 16; // AES_BLOCK_SIZE; class CKeyInfo { public: - int NumCyclesPower; - UInt32 SaltSize; - Byte Salt[16]; + unsigned NumCyclesPower; + unsigned SaltSize; + Byte Salt[kSaltSizeMax]; CByteBuffer Password; Byte Key[kKeySize]; bool IsEqualTo(const CKeyInfo &a) const; - void CalculateDigest(); + void CalcKey(); - CKeyInfo() { Init(); } - void Init() + CKeyInfo() { ClearProps(); } + void ClearProps() { NumCyclesPower = 0; SaltSize = 0; - for (int i = 0; i < sizeof(Salt); i++) + for (unsigned i = 0; i < sizeof(Salt); i++) Salt[i] = 0; } }; @@ -43,9 +45,9 @@ class CKeyInfoCache CObjectVector<CKeyInfo> Keys; public: CKeyInfoCache(unsigned size): Size(size) {} - bool Find(CKeyInfo &key); - // HRESULT Calculate(CKeyInfo &key); - void Add(CKeyInfo &key); + bool GetKey(CKeyInfo &key); + void Add(const CKeyInfo &key); + void FindAndAdd(const CKeyInfo &key); }; class CBase @@ -53,9 +55,10 @@ class CBase CKeyInfoCache _cachedKeys; protected: CKeyInfo _key; - Byte _iv[16]; - UInt32 _ivSize; - void CalculateDigest(); + Byte _iv[kIvSizeMax]; + unsigned _ivSize; + + void PrepareKey(); CBase(); }; @@ -68,13 +71,8 @@ class CBaseCoder: protected: CMyComPtr<ICompressFilter> _aesFilter; - virtual HRESULT CreateFilter() = 0; - #ifndef CRYPTO_AES - HRESULT CreateFilterFromDLL(REFCLSID clsID); - #endif public: - STDMETHOD(Init)(); - STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); + INTERFACE_ICompressFilter(;) STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); }; @@ -87,7 +85,6 @@ class CEncoder: // public ICryptoResetSalt, public ICryptoResetInitVector { - virtual HRESULT CreateFilter(); public: MY_UNKNOWN_IMP3( ICryptoSetPassword, @@ -97,19 +94,21 @@ public: STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); // STDMETHOD(ResetSalt)(); STDMETHOD(ResetInitVector)(); + CEncoder(); }; + #endif class CDecoder: public CBaseCoder, public ICompressSetDecoderProperties2 { - virtual HRESULT CreateFilter(); public: MY_UNKNOWN_IMP2( ICryptoSetPassword, ICompressSetDecoderProperties2) STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + CDecoder(); }; }} diff --git a/CPP/7zip/Crypto/7zAesRegister.cpp b/CPP/7zip/Crypto/7zAesRegister.cpp index 5e57748f..7debc7d1 100644 --- a/CPP/7zip/Crypto/7zAesRegister.cpp +++ b/CPP/7zip/Crypto/7zAesRegister.cpp @@ -3,16 +3,10 @@ #include "StdAfx.h" #include "../Common/RegisterCodec.h" -#include "7zAes.h" - -static void *CreateCodec() { return (void *)(ICompressFilter *)(new NCrypto::NSevenZ::CDecoder()); } -#ifndef EXTRACT_ONLY -static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new NCrypto::NSevenZ::CEncoder()); } -#else -#define CreateCodecOut 0 -#endif -static CCodecInfo g_CodecInfo = - { CreateCodec, CreateCodecOut, 0x06F10701, L"7zAES", 1, true }; +#include "7zAes.h" -REGISTER_CODEC(7zAES) +REGISTER_FILTER_E(7zAES, + NCrypto::N7z::CDecoder(), + NCrypto::N7z::CEncoder(), + 0x6F10701, "7zAES")
\ No newline at end of file diff --git a/CPP/7zip/Crypto/HmacSha1.cpp b/CPP/7zip/Crypto/HmacSha1.cpp index a66d6271..359b65bc 100644 --- a/CPP/7zip/Crypto/HmacSha1.cpp +++ b/CPP/7zip/Crypto/HmacSha1.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../C/CpuArch.h" + #include "HmacSha1.h" namespace NCrypto { @@ -11,24 +13,29 @@ void CHmac::SetKey(const Byte *key, size_t keySize) { Byte keyTemp[kBlockSize]; size_t i; + for (i = 0; i < kBlockSize; i++) keyTemp[i] = 0; - if(keySize > kBlockSize) + + if (keySize > kBlockSize) { _sha.Init(); _sha.Update(key, keySize); _sha.Final(keyTemp); - keySize = kDigestSize; } else for (i = 0; i < keySize; i++) keyTemp[i] = key[i]; + for (i = 0; i < kBlockSize; i++) keyTemp[i] ^= 0x36; + _sha.Init(); _sha.Update(keyTemp, kBlockSize); + for (i = 0; i < kBlockSize; i++) keyTemp[i] ^= 0x36 ^ 0x5C; + _sha2.Init(); _sha2.Update(keyTemp, kBlockSize); } @@ -39,18 +46,20 @@ void CHmac::Final(Byte *mac, size_t macSize) _sha.Final(digest); _sha2.Update(digest, kDigestSize); _sha2.Final(digest); - for(size_t i = 0; i < macSize; i++) + for (size_t i = 0; i < macSize; i++) mac[i] = digest[i]; } void CHmac32::SetKey(const Byte *key, size_t keySize) { - UInt32 keyTemp[kBlockSizeInWords]; + UInt32 keyTemp[kNumBlockWords]; size_t i; - for (i = 0; i < kBlockSizeInWords; i++) + + for (i = 0; i < kNumBlockWords; i++) keyTemp[i] = 0; - if(keySize > kBlockSize) + + if (keySize > kBlockSize) { CContext sha; sha.Init(); @@ -58,50 +67,52 @@ void CHmac32::SetKey(const Byte *key, size_t keySize) Byte digest[kDigestSize]; sha.Final(digest); - for (int i = 0 ; i < kDigestSizeInWords; i++) - keyTemp[i] = - ((UInt32)(digest[i * 4 + 0]) << 24) | - ((UInt32)(digest[i * 4 + 1]) << 16) | - ((UInt32)(digest[i * 4 + 2]) << 8) | - ((UInt32)(digest[i * 4 + 3])); - keySize = kDigestSizeInWords; + for (i = 0 ; i < kNumDigestWords; i++) + keyTemp[i] = GetBe32(digest + i * 4 + 0); } else - for (size_t i = 0; i < keySize; i++) + for (i = 0; i < keySize; i++) keyTemp[i / 4] |= (key[i] << (24 - 8 * (i & 3))); - for (i = 0; i < kBlockSizeInWords; i++) + + for (i = 0; i < kNumBlockWords; i++) keyTemp[i] ^= 0x36363636; + _sha.Init(); - _sha.Update(keyTemp, kBlockSizeInWords); - for (i = 0; i < kBlockSizeInWords; i++) + _sha.Update(keyTemp, kNumBlockWords); + + for (i = 0; i < kNumBlockWords; i++) keyTemp[i] ^= 0x36363636 ^ 0x5C5C5C5C; + _sha2.Init(); - _sha2.Update(keyTemp, kBlockSizeInWords); + _sha2.Update(keyTemp, kNumBlockWords); } void CHmac32::Final(UInt32 *mac, size_t macSize) { - UInt32 digest[kDigestSizeInWords]; + UInt32 digest[kNumDigestWords]; _sha.Final(digest); - _sha2.Update(digest, kDigestSizeInWords); + _sha2.Update(digest, kNumDigestWords); _sha2.Final(digest); - for(size_t i = 0; i < macSize; i++) + for (size_t i = 0; i < macSize; i++) mac[i] = digest[i]; } void CHmac32::GetLoopXorDigest(UInt32 *mac, UInt32 numIteration) { - UInt32 block[kBlockSizeInWords]; - UInt32 block2[kBlockSizeInWords]; - _sha.PrepareBlock(block, kDigestSizeInWords); - _sha2.PrepareBlock(block2, kDigestSizeInWords); - for(unsigned int s = 0; s < kDigestSizeInWords; s++) + UInt32 block[kNumBlockWords]; + UInt32 block2[kNumBlockWords]; + + _sha.PrepareBlock(block, kNumDigestWords); + _sha2.PrepareBlock(block2, kNumDigestWords); + + for (unsigned s = 0; s < kNumDigestWords; s++) block[s] = mac[s]; - for(UInt32 i = 0; i < numIteration; i++) + + for (UInt32 i = 0; i < numIteration; i++) { _sha.GetBlockDigest(block, block2); _sha2.GetBlockDigest(block2, block); - for (unsigned int s = 0; s < kDigestSizeInWords; s++) + for (unsigned s = 0; s < kNumDigestWords; s++) mac[s] ^= block[s]; } } diff --git a/CPP/7zip/Crypto/HmacSha1.h b/CPP/7zip/Crypto/HmacSha1.h index d7181329..6ba015e8 100644 --- a/CPP/7zip/Crypto/HmacSha1.h +++ b/CPP/7zip/Crypto/HmacSha1.h @@ -4,7 +4,7 @@ #ifndef __CRYPTO_HMAC_SHA1_H #define __CRYPTO_HMAC_SHA1_H -#include "Sha1.h" +#include "Sha1Cls.h" namespace NCrypto { namespace NSha1 { @@ -28,9 +28,9 @@ class CHmac32 public: void SetKey(const Byte *key, size_t keySize); void Update(const UInt32 *data, size_t dataSize) { _sha.Update(data, dataSize); } - void Final(UInt32 *mac, size_t macSize = kDigestSizeInWords); + void Final(UInt32 *mac, size_t macSize = kNumDigestWords); - // It'sa for hmac function. in,out: mac[kDigestSizeInWords]. + // It'sa for hmac function. in,out: mac[kNumDigestWords]. void GetLoopXorDigest(UInt32 *mac, UInt32 numIteration); }; diff --git a/CPP/7zip/Crypto/MyAes.h b/CPP/7zip/Crypto/MyAes.h index 99a17fef..289935eb 100644 --- a/CPP/7zip/Crypto/MyAes.h +++ b/CPP/7zip/Crypto/MyAes.h @@ -26,13 +26,17 @@ class CAesCbcCoder: Byte _iv[AES_BLOCK_SIZE]; bool SetFunctions(UInt32 algo); + public: CAesCbcCoder(bool encodeMode, unsigned keySize); + MY_UNKNOWN_IMP2(ICryptoProperties, ICompressSetCoderProperties) - STDMETHOD(Init)(); - STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); + + INTERFACE_ICompressFilter(;) + STDMETHOD(SetKey)(const Byte *data, UInt32 size); STDMETHOD(SetInitVector)(const Byte *data, UInt32 size); + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); }; @@ -46,7 +50,6 @@ struct CAesCbcDecoder: public CAesCbcCoder CAesCbcDecoder(unsigned keySize = 0): CAesCbcCoder(false, keySize) {} }; - } #endif diff --git a/CPP/7zip/Crypto/MyAesReg.cpp b/CPP/7zip/Crypto/MyAesReg.cpp index faaa104b..91d62b94 100644 --- a/CPP/7zip/Crypto/MyAesReg.cpp +++ b/CPP/7zip/Crypto/MyAesReg.cpp @@ -6,14 +6,7 @@ #include "MyAes.h" -static void *CreateCodecCbc() { return (void *)(ICompressFilter *)(new NCrypto::CAesCbcDecoder(32)); } -#ifndef EXTRACT_ONLY -static void *CreateCodecCbcOut() { return (void *)(ICompressFilter *)(new NCrypto::CAesCbcEncoder(32)); } -#else -#define CreateCodecCbcOut 0 -#endif - -static CCodecInfo g_CodecInfo = - { CreateCodecCbc, CreateCodecCbcOut, 0x06F00181, L"AES256CBC", 1, true }; -REGISTER_CODEC(AES256CBC) - +REGISTER_FILTER_E(AES256CBC, + NCrypto::CAesCbcDecoder(32), + NCrypto::CAesCbcEncoder(32), + 0x6F00181, "AES256CBC")
\ No newline at end of file diff --git a/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp b/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp index cbbdec89..a7fcb728 100644 --- a/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp +++ b/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp @@ -2,26 +2,34 @@ #include "StdAfx.h" +#include "../../../C/CpuArch.h" + #include "HmacSha1.h" namespace NCrypto { namespace NSha1 { -void Pbkdf2Hmac(const Byte *pwd, size_t pwdSize, const Byte *salt, size_t saltSize, - UInt32 numIterations, Byte *key, size_t keySize) +void Pbkdf2Hmac(const Byte *pwd, size_t pwdSize, + const Byte *salt, size_t saltSize, + UInt32 numIterations, + Byte *key, size_t keySize) { CHmac baseCtx; baseCtx.SetKey(pwd, pwdSize); - for (UInt32 i = 1; keySize > 0; i++) + + for (UInt32 i = 1; keySize != 0; i++) { CHmac ctx = baseCtx; ctx.Update(salt, saltSize); - Byte u[kDigestSize] = { (Byte)(i >> 24), (Byte)(i >> 16), (Byte)(i >> 8), (Byte)(i) }; - const unsigned int curSize = (keySize < kDigestSize) ? (unsigned int)keySize : kDigestSize; + + Byte u[kDigestSize]; + SetBe32(u, i); + ctx.Update(u, 4); ctx.Final(u, kDigestSize); - unsigned int s; + const unsigned curSize = (keySize < kDigestSize) ? (unsigned)keySize : kDigestSize; + unsigned s; for (s = 0; s < curSize; s++) key[s] = u[s]; @@ -39,26 +47,32 @@ void Pbkdf2Hmac(const Byte *pwd, size_t pwdSize, const Byte *salt, size_t saltSi } } -void Pbkdf2Hmac32(const Byte *pwd, size_t pwdSize, const UInt32 *salt, size_t saltSize, - UInt32 numIterations, UInt32 *key, size_t keySize) +void Pbkdf2Hmac32(const Byte *pwd, size_t pwdSize, + const UInt32 *salt, size_t saltSize, + UInt32 numIterations, + UInt32 *key, size_t keySize) { CHmac32 baseCtx; baseCtx.SetKey(pwd, pwdSize); - for (UInt32 i = 1; keySize > 0; i++) + + for (UInt32 i = 1; keySize != 0; i++) { CHmac32 ctx = baseCtx; ctx.Update(salt, saltSize); - UInt32 u[kDigestSizeInWords] = { i }; - const unsigned int curSize = (keySize < kDigestSizeInWords) ? (unsigned int)keySize : kDigestSizeInWords; + + UInt32 u[kNumDigestWords]; + u[0] = i; + ctx.Update(u, 1); - ctx.Final(u, kDigestSizeInWords); + ctx.Final(u, kNumDigestWords); // Speed-optimized code start ctx = baseCtx; ctx.GetLoopXorDigest(u, numIterations - 1); // Speed-optimized code end - unsigned int s; + const unsigned curSize = (keySize < kNumDigestWords) ? (unsigned)keySize : kNumDigestWords; + unsigned s; for (s = 0; s < curSize; s++) key[s] = u[s]; @@ -67,8 +81,8 @@ void Pbkdf2Hmac32(const Byte *pwd, size_t pwdSize, const UInt32 *salt, size_t sa for (UInt32 j = numIterations; j > 1; j--) { ctx = baseCtx; - ctx.Update(u, kDigestSizeInWords); - ctx.Final(u, kDigestSizeInWords); + ctx.Update(u, kNumDigestWords); + ctx.Final(u, kNumDigestWords); for (s = 0; s < curSize; s++) key[s] ^= u[s]; } diff --git a/CPP/7zip/Crypto/RandGen.cpp b/CPP/7zip/Crypto/RandGen.cpp index 0ed65a30..f5ea31f0 100644 --- a/CPP/7zip/Crypto/RandGen.cpp +++ b/CPP/7zip/Crypto/RandGen.cpp @@ -2,7 +2,9 @@ #include "StdAfx.h" +#ifndef _7ZIP_ST #include "../../Windows/Synchronization.h" +#endif #include "RandGen.h" @@ -85,14 +87,20 @@ void CRandomGenerator::Init() _needInit = false; } -static NWindows::NSynchronization::CCriticalSection g_CriticalSection; +#ifndef _7ZIP_ST + static NWindows::NSynchronization::CCriticalSection g_CriticalSection; + #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_CriticalSection); +#else + #define MT_LOCK +#endif void CRandomGenerator::Generate(Byte *data, unsigned size) { - g_CriticalSection.Enter(); + MT_LOCK + if (_needInit) Init(); - while (size > 0) + while (size != 0) { CSha256 hash; @@ -106,10 +114,9 @@ void CRandomGenerator::Generate(Byte *data, unsigned size) Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE); Byte buff[SHA256_DIGEST_SIZE]; Sha256_Final(&hash, buff); - for (unsigned i = 0; i < SHA256_DIGEST_SIZE && size > 0; i++, size--) + for (unsigned i = 0; i < SHA256_DIGEST_SIZE && size != 0; i++, size--) *data++ = buff[i]; } - g_CriticalSection.Leave(); } CRandomGenerator g_RandomGenerator; diff --git a/CPP/7zip/Crypto/Rar20Crypto.cpp b/CPP/7zip/Crypto/Rar20Crypto.cpp index c2df0e52..1523151d 100644 --- a/CPP/7zip/Crypto/Rar20Crypto.cpp +++ b/CPP/7zip/Crypto/Rar20Crypto.cpp @@ -11,9 +11,9 @@ namespace NCrypto { namespace NRar20 { -static const int kNumRounds = 32; +static const unsigned kNumRounds = 32; -static const Byte InitSubstTable[256] = { +static const Byte g_InitSubstTable[256] = { 215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42, 232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137, 255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6, @@ -34,8 +34,8 @@ static const Byte InitSubstTable[256] = { void CData::UpdateKeys(const Byte *data) { - for (int i = 0; i < 16; i += 4) - for (int j = 0; j < 4; j++) + for (unsigned i = 0; i < 16; i += 4) + for (unsigned j = 0; j < 4; j++) Keys[j] ^= g_CrcTable[data[i + j]]; } @@ -46,7 +46,7 @@ static void Swap(Byte *b1, Byte *b2) *b2 = b; } -void CData::SetPassword(const Byte *password, UInt32 passwordLen) +void CData::SetPassword(const Byte *data, UInt32 size) { Keys[0] = 0xD3A3B879L; Keys[1] = 0x3F6D12F7L; @@ -54,19 +54,22 @@ void CData::SetPassword(const Byte *password, UInt32 passwordLen) Keys[3] = 0xA4E7F123L; Byte psw[256]; + if (size >= sizeof(psw)) + size = sizeof(psw) - 1; memset(psw, 0, sizeof(psw)); - memcpy(psw, password, passwordLen); - memcpy(SubstTable, InitSubstTable, sizeof(SubstTable)); + if (size != 0) + memcpy(psw, data, size); + memcpy(SubstTable, g_InitSubstTable, sizeof(SubstTable)); for (UInt32 j = 0; j < 256; j++) - for (UInt32 i = 0; i < passwordLen; i += 2) + for (UInt32 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]); } - for (UInt32 i = 0; i < passwordLen; i+= 16) + for (UInt32 i = 0; i < size; i += 16) EncryptBlock(&psw[i]); } @@ -83,7 +86,7 @@ void CData::CryptBlock(Byte *buf, bool encrypt) if (!encrypt) memcpy(inBuf, buf, sizeof(inBuf)); - for (int i = 0; i < kNumRounds; i++) + for (unsigned i = 0; i < kNumRounds; i++) { UInt32 key = Keys[(encrypt ? i : (kNumRounds - 1 - i)) & 3]; T = ((C + rotlFixed(D, 11)) ^ key); diff --git a/CPP/7zip/Crypto/Rar20Crypto.h b/CPP/7zip/Crypto/Rar20Crypto.h index 1b6d6024..b0445932 100644 --- a/CPP/7zip/Crypto/Rar20Crypto.h +++ b/CPP/7zip/Crypto/Rar20Crypto.h @@ -11,17 +11,20 @@ namespace NCrypto { namespace NRar20 { +/* ICompressFilter::Init() does nothing for this filter. + Call CryptoSetPassword() to initialize filter. */ + class CData { Byte SubstTable[256]; UInt32 Keys[4]; - UInt32 SubstLong(UInt32 t) + UInt32 SubstLong(UInt32 t) const { - return (UInt32)SubstTable[(int)t & 255] | - ((UInt32)SubstTable[(int)(t >> 8) & 255] << 8) | - ((UInt32)SubstTable[(int)(t >> 16) & 255] << 16) | - ((UInt32)SubstTable[(int)(t >> 24) & 255] << 24); + return (UInt32)SubstTable[(unsigned)t & 255] + | ((UInt32)SubstTable[(unsigned)(t >> 8) & 255] << 8) + | ((UInt32)SubstTable[(unsigned)(t >> 16) & 255] << 16) + | ((UInt32)SubstTable[(unsigned)(t >> 24) & 255] << 24); } void UpdateKeys(const Byte *data); void CryptBlock(Byte *buf, bool encrypt); @@ -34,7 +37,8 @@ public: class CDecoder: public ICompressFilter, public ICryptoSetPassword, - public CMyUnknownImp + public CMyUnknownImp, + public CData { CData _cipher; public: diff --git a/CPP/7zip/Crypto/RarAes.cpp b/CPP/7zip/Crypto/RarAes.cpp index e8f716d9..f562023a 100644 --- a/CPP/7zip/Crypto/RarAes.cpp +++ b/CPP/7zip/Crypto/RarAes.cpp @@ -4,32 +4,36 @@ #include "StdAfx.h" #include "RarAes.h" -#include "Sha1.h" +#include "Sha1Cls.h" namespace NCrypto { namespace NRar29 { CDecoder::CDecoder(): - CAesCbcDecoder(kRarAesKeySize), - _thereIsSalt(false), - _needCalculate(true), - _rar350Mode(false) + CAesCbcDecoder(kRarAesKeySize), + _thereIsSalt(false), + _needCalc(true), + _rar350Mode(false) { - for (int i = 0; i < sizeof(_salt); i++) + for (unsigned i = 0; i < sizeof(_salt); i++) _salt[i] = 0; } STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) { - bool thereIsSaltPrev = _thereIsSalt; + bool prev = _thereIsSalt; _thereIsSalt = false; if (size == 0) + { + if (!_needCalc && prev) + _needCalc = true; return S_OK; + } if (size < 8) return E_INVALIDARG; _thereIsSalt = true; bool same = false; - if (_thereIsSalt == thereIsSaltPrev) + if (_thereIsSalt == prev) { same = true; if (_thereIsSalt) @@ -44,91 +48,88 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) } for (unsigned i = 0; i < sizeof(_salt); i++) _salt[i] = data[i]; - if (!_needCalculate && !same) - _needCalculate = true; + if (!_needCalc && !same) + _needCalc = true; return S_OK; } -static const unsigned kMaxPasswordLength = 127 * 2; +static const unsigned kPasswordLen_MAX = 127 * 2; STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size) { - if (size > kMaxPasswordLength) - size = kMaxPasswordLength; + if (size > kPasswordLen_MAX) + size = kPasswordLen_MAX; bool same = false; - if (size == buffer.Size()) + if (size == _password.Size()) { same = true; for (UInt32 i = 0; i < size; i++) - if (data[i] != buffer[i]) + if (data[i] != _password[i]) { same = false; break; } } - if (!_needCalculate && !same) - _needCalculate = true; - buffer.CopyFrom(data, (size_t)size); + if (!_needCalc && !same) + _needCalc = true; + _password.CopyFrom(data, (size_t)size); return S_OK; } STDMETHODIMP CDecoder::Init() { - Calculate(); - RINOK(SetKey(aesKey, kRarAesKeySize)); - RINOK(SetInitVector(_aesInit, AES_BLOCK_SIZE)); + CalcKey(); + RINOK(SetKey(_key, kRarAesKeySize)); + RINOK(SetInitVector(_iv, AES_BLOCK_SIZE)); return CAesCbcCoder::Init(); } -void CDecoder::Calculate() +void CDecoder::CalcKey() { - if (_needCalculate) - { - const unsigned kSaltSize = 8; - - Byte rawPassword[kMaxPasswordLength + kSaltSize]; - - memcpy(rawPassword, buffer, buffer.Size()); - - size_t rawLength = buffer.Size(); - - if (_thereIsSalt) - { - memcpy(rawPassword + rawLength, _salt, kSaltSize); - rawLength += kSaltSize; - } - - NSha1::CContext sha; - sha.Init(); + if (!_needCalc) + return; - // rar reverts hash for sha. - const unsigned kNumRounds = (1 << 18); - unsigned i; - for (i = 0; i < kNumRounds; i++) + const unsigned kSaltSize = 8; + + Byte buf[kPasswordLen_MAX + kSaltSize]; + + if (_password.Size() != 0) + memcpy(buf, _password, _password.Size()); + + size_t rawSize = _password.Size(); + + if (_thereIsSalt) + { + memcpy(buf + rawSize, _salt, kSaltSize); + rawSize += kSaltSize; + } + + NSha1::CContext sha; + sha.Init(); + + Byte digest[NSha1::kDigestSize]; + // rar reverts hash for sha. + const UInt32 kNumRounds = (1 << 18); + UInt32 i; + for (i = 0; i < kNumRounds; i++) + { + sha.UpdateRar(buf, rawSize, _rar350Mode); + Byte pswNum[3] = { (Byte)i, (Byte)(i >> 8), (Byte)(i >> 16) }; + sha.UpdateRar(pswNum, 3, _rar350Mode); + if (i % (kNumRounds / 16) == 0) { - sha.UpdateRar(rawPassword, rawLength, _rar350Mode); - Byte pswNum[3] = { (Byte)i, (Byte)(i >> 8), (Byte)(i >> 16) }; - sha.UpdateRar(pswNum, 3, _rar350Mode); - if (i % (kNumRounds / 16) == 0) - { - NSha1::CContext shaTemp = sha; - Byte digest[NSha1::kDigestSize]; - shaTemp.Final(digest); - _aesInit[i / (kNumRounds / 16)] = (Byte)digest[4 * 4 + 3]; - } + NSha1::CContext shaTemp = sha; + shaTemp.Final(digest); + _iv[i / (kNumRounds / 16)] = (Byte)digest[4 * 4 + 3]; } - /* - // it's test message for sha - const char *message = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; - sha.Update((const Byte *)message, strlen(message)); - */ - Byte digest[20]; - sha.Final(digest); - for (i = 0; i < 4; i++) - for (unsigned j = 0; j < 4; j++) - aesKey[i * 4 + j] = (digest[i * 4 + 3 - j]); } - _needCalculate = false; + + sha.Final(digest); + for (i = 0; i < 4; i++) + for (unsigned j = 0; j < 4; j++) + _key[i * 4 + j] = (digest[i * 4 + 3 - j]); + + _needCalc = false; } }} diff --git a/CPP/7zip/Crypto/RarAes.h b/CPP/7zip/Crypto/RarAes.h index 9d9ee127..197a0b2d 100644 --- a/CPP/7zip/Crypto/RarAes.h +++ b/CPP/7zip/Crypto/RarAes.h @@ -18,22 +18,24 @@ const UInt32 kRarAesKeySize = 16; class CDecoder: public CAesCbcDecoder, - public ICompressSetDecoderProperties2, + // public ICompressSetDecoderProperties2, public ICryptoSetPassword { Byte _salt[8]; bool _thereIsSalt; - CByteBuffer buffer; - Byte aesKey[kRarAesKeySize]; - Byte _aesInit[AES_BLOCK_SIZE]; - bool _needCalculate; + bool _needCalc; bool _rar350Mode; + + CByteBuffer _password; + + Byte _key[kRarAesKeySize]; + Byte _iv[AES_BLOCK_SIZE]; - void Calculate(); + void CalcKey(); public: - MY_UNKNOWN_IMP2( - ICryptoSetPassword, - ICompressSetDecoderProperties2) + MY_UNKNOWN_IMP1( + ICryptoSetPassword) + // ICompressSetDecoderProperties2 STDMETHOD(Init)(); STDMETHOD(CryptoSetPassword)(const Byte *aData, UInt32 aSize); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); diff --git a/CPP/7zip/Crypto/Sha1.cpp b/CPP/7zip/Crypto/Sha1.cpp deleted file mode 100644 index 2f284071..00000000 --- a/CPP/7zip/Crypto/Sha1.cpp +++ /dev/null @@ -1,229 +0,0 @@ -// Crypto/Sha1.cpp -// This file is based on public domain -// Steve Reid and Wei Dai's code from Crypto++ - -#include "StdAfx.h" - -#include "../../../C/RotateDefs.h" - -#include "Sha1.h" - -namespace NCrypto { -namespace NSha1 { - -// define it for speed optimization -// #define _SHA1_UNROLL - -static const unsigned kNumW = - #ifdef _SHA1_UNROLL - 16; - #else - 80; - #endif - - -#define w0(i) (W[(i)] = data[(i)]) - -#ifdef _SHA1_UNROLL -#define w1(i) (W[(i)&15] = rotlFixed(W[((i)-3)&15] ^ W[((i)-8)&15] ^ W[((i)-14)&15] ^ W[((i)-16)&15], 1)) -#else -#define w1(i) (W[(i)] = rotlFixed(W[(i)-3] ^ W[(i)-8] ^ W[(i)-14] ^ W[(i)-16], 1)) -#endif - -#define f1(x,y,z) (z^(x&(y^z))) -#define f2(x,y,z) (x^y^z) -#define f3(x,y,z) ((x&y)|(z&(x|y))) -#define f4(x,y,z) (x^y^z) - -#define RK1(a,b,c,d,e,i, f, w, k) e += f(b,c,d) + w(i) + k + rotlFixed(a,5); b = rotlFixed(b,30); - -#define R0(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f1, w0, 0x5A827999) -#define R1(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f1, w1, 0x5A827999) -#define R2(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f2, w1, 0x6ED9EBA1) -#define R3(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f3, w1, 0x8F1BBCDC) -#define R4(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f4, w1, 0xCA62C1D6) - -#define RX_1_4(rx1, rx4, i) rx1(a,b,c,d,e,i); rx4(e,a,b,c,d,i+1); rx4(d,e,a,b,c,i+2); rx4(c,d,e,a,b,i+3); rx4(b,c,d,e,a,i+4); -#define RX_5(rx, i) RX_1_4(rx, rx, i); - -void CContextBase::Init() -{ - _state[0] = 0x67452301; - _state[1] = 0xEFCDAB89; - _state[2] = 0x98BADCFE; - _state[3] = 0x10325476; - _state[4] = 0xC3D2E1F0; - _count = 0; -} - -void CContextBase::GetBlockDigest(UInt32 *data, UInt32 *destDigest, bool returnRes) -{ - UInt32 a, b, c, d, e; - UInt32 W[kNumW]; - - a = _state[0]; - b = _state[1]; - c = _state[2]; - d = _state[3]; - e = _state[4]; - #ifdef _SHA1_UNROLL - RX_5(R0, 0); RX_5(R0, 5); RX_5(R0, 10); - #else - int i; - for (i = 0; i < 15; i += 5) { RX_5(R0, i); } - #endif - - RX_1_4(R0, R1, 15); - - - #ifdef _SHA1_UNROLL - RX_5(R2, 20); RX_5(R2, 25); RX_5(R2, 30); RX_5(R2, 35); - RX_5(R3, 40); RX_5(R3, 45); RX_5(R3, 50); RX_5(R3, 55); - RX_5(R4, 60); RX_5(R4, 65); RX_5(R4, 70); RX_5(R4, 75); - #else - i = 20; - for (; i < 40; i += 5) { RX_5(R2, i); } - for (; i < 60; i += 5) { RX_5(R3, i); } - for (; i < 80; i += 5) { RX_5(R4, i); } - #endif - - destDigest[0] = _state[0] + a; - destDigest[1] = _state[1] + b; - destDigest[2] = _state[2] + c; - destDigest[3] = _state[3] + d; - destDigest[4] = _state[4] + e; - - if (returnRes) - for (int i = 0 ; i < 16; i++) - data[i] = W[kNumW - 16 + i]; - - // Wipe variables - // a = b = c = d = e = 0; -} - -void CContextBase::PrepareBlock(UInt32 *block, unsigned size) const -{ - unsigned curBufferPos = size & 0xF; - block[curBufferPos++] = 0x80000000; - while (curBufferPos != (16 - 2)) - block[curBufferPos++] = 0; - const UInt64 lenInBits = (_count << 9) + ((UInt64)size << 5); - block[curBufferPos++] = (UInt32)(lenInBits >> 32); - block[curBufferPos++] = (UInt32)(lenInBits); -} - -void CContext::Update(const Byte *data, size_t size) -{ - unsigned curBufferPos = _count2; - while (size--) - { - unsigned pos = (curBufferPos & 3); - if (pos == 0) - _buffer[curBufferPos >> 2] = 0; - _buffer[curBufferPos >> 2] |= ((UInt32)*data++) << (8 * (3 - pos)); - if (++curBufferPos == kBlockSize) - { - curBufferPos = 0; - CContextBase::UpdateBlock(_buffer, false); - } - } - _count2 = curBufferPos; -} - -void CContext::UpdateRar(Byte *data, size_t size, bool rar350Mode) -{ - bool returnRes = false; - unsigned curBufferPos = _count2; - while (size--) - { - unsigned pos = (curBufferPos & 3); - if (pos == 0) - _buffer[curBufferPos >> 2] = 0; - _buffer[curBufferPos >> 2] |= ((UInt32)*data++) << (8 * (3 - pos)); - if (++curBufferPos == kBlockSize) - { - curBufferPos = 0; - CContextBase::UpdateBlock(_buffer, returnRes); - if (returnRes) - for (unsigned i = 0; i < kBlockSizeInWords; i++) - { - UInt32 d = _buffer[i]; - data[(int)i * 4 + 0 - (int)kBlockSize] = (Byte)(d); - data[(int)i * 4 + 1 - (int)kBlockSize] = (Byte)(d >> 8); - data[(int)i * 4 + 2 - (int)kBlockSize] = (Byte)(d >> 16); - data[(int)i * 4 + 3 - (int)kBlockSize] = (Byte)(d >> 24); - } - returnRes = rar350Mode; - } - } - _count2 = curBufferPos; -} - -void CContext::Final(Byte *digest) -{ - const UInt64 lenInBits = (_count << 9) + ((UInt64)_count2 << 3); - unsigned curBufferPos = _count2; - unsigned pos = (curBufferPos & 3); - curBufferPos >>= 2; - if (pos == 0) - _buffer[curBufferPos] = 0; - _buffer[curBufferPos++] |= ((UInt32)0x80) << (8 * (3 - pos)); - - while (curBufferPos != (16 - 2)) - { - curBufferPos &= 0xF; - if (curBufferPos == 0) - UpdateBlock(); - _buffer[curBufferPos++] = 0; - } - _buffer[curBufferPos++] = (UInt32)(lenInBits >> 32); - _buffer[curBufferPos++] = (UInt32)(lenInBits); - UpdateBlock(); - - unsigned i; - for (i = 0; i < kDigestSizeInWords; i++) - { - UInt32 state = _state[i] & 0xFFFFFFFF; - *digest++ = (Byte)(state >> 24); - *digest++ = (Byte)(state >> 16); - *digest++ = (Byte)(state >> 8); - *digest++ = (Byte)(state); - } - Init(); -} - -/////////////////////////// -// Words version - -void CContext32::Update(const UInt32 *data, size_t size) -{ - while (size--) - { - _buffer[_count2++] = *data++; - if (_count2 == kBlockSizeInWords) - { - _count2 = 0; - UpdateBlock(); - } - } -} - -void CContext32::Final(UInt32 *digest) -{ - const UInt64 lenInBits = (_count << 9) + ((UInt64)_count2 << 5); - unsigned curBufferPos = _count2; - _buffer[curBufferPos++] = 0x80000000; - while (curBufferPos != (16 - 2)) - { - curBufferPos &= 0xF; - if (curBufferPos == 0) - UpdateBlock(); - _buffer[curBufferPos++] = 0; - } - _buffer[curBufferPos++] = (UInt32)(lenInBits >> 32); - _buffer[curBufferPos++] = (UInt32)(lenInBits); - GetBlockDigest(_buffer, digest); - Init(); -} - -}} diff --git a/CPP/7zip/Crypto/Sha1.h b/CPP/7zip/Crypto/Sha1.h deleted file mode 100644 index df9477d8..00000000 --- a/CPP/7zip/Crypto/Sha1.h +++ /dev/null @@ -1,69 +0,0 @@ -// Crypto/Sha1.h -// This file is based on public domain -// Steve Reid and Wei Dai's code from Crypto++ - -#ifndef __CRYPTO_SHA1_H -#define __CRYPTO_SHA1_H - -#include <stddef.h> - -#include "../../Common/MyTypes.h" - -// Sha1 implementation in RAR before version 3.60 has bug: -// it changes data bytes in some cases. -// So this class supports both versions: normal_SHA and rar3Mode - -namespace NCrypto { -namespace NSha1 { - -const unsigned kBlockSize = 64; -const unsigned kDigestSize = 20; - -const unsigned kBlockSizeInWords = (kBlockSize >> 2); -const unsigned kDigestSizeInWords = (kDigestSize >> 2); - -class CContextBase -{ -protected: - UInt32 _state[5]; - UInt64 _count; - void UpdateBlock(UInt32 *data, bool returnRes = false) - { - GetBlockDigest(data, _state, returnRes); - _count++; - } -public: - void Init(); - void GetBlockDigest(UInt32 *blockData, UInt32 *destDigest, bool returnRes = false); - // PrepareBlock can be used only when size <= 13. size in Words - void PrepareBlock(UInt32 *block, unsigned int size) const; -}; - -class CContextBase2: public CContextBase -{ -protected: - unsigned _count2; - UInt32 _buffer[kBlockSizeInWords]; - void UpdateBlock() { CContextBase::UpdateBlock(_buffer); } -public: - void Init() { CContextBase::Init(); _count2 = 0; } -}; - -class CContext: public CContextBase2 -{ -public: - void Update(const Byte *data, size_t size); - void UpdateRar(Byte *data, size_t size, bool rar350Mode); - void Final(Byte *digest); -}; - -class CContext32: public CContextBase2 -{ -public: - void Update(const UInt32 *data, size_t size); - void Final(UInt32 *digest); -}; - -}} - -#endif diff --git a/CPP/7zip/Crypto/Sha1Cls.h b/CPP/7zip/Crypto/Sha1Cls.h new file mode 100644 index 00000000..18c761f9 --- /dev/null +++ b/CPP/7zip/Crypto/Sha1Cls.h @@ -0,0 +1,51 @@ +// Crypto/Sha1.h + +#ifndef __CRYPTO_SHA1_H +#define __CRYPTO_SHA1_H + +#include "../../../C/Sha1.h" + +namespace NCrypto { +namespace NSha1 { + +const unsigned kNumBlockWords = SHA1_NUM_BLOCK_WORDS; +const unsigned kNumDigestWords = SHA1_NUM_DIGEST_WORDS; + +const unsigned kBlockSize = SHA1_BLOCK_SIZE; +const unsigned kDigestSize = SHA1_DIGEST_SIZE; + +class CContextBase +{ +protected: + CSha1 _s; + +public: + void Init() throw() { Sha1_Init(&_s); } + void GetBlockDigest(const UInt32 *blockData, UInt32 *destDigest) throw() { Sha1_GetBlockDigest(&_s, blockData, destDigest); } +}; + +class CContext: public CContextBase +{ +public: + void Update(const Byte *data, size_t size) throw() { Sha1_Update(&_s, data, size); } + void UpdateRar(Byte *data, size_t size, bool rar350Mode) throw() { Sha1_Update_Rar(&_s, data, size, rar350Mode ? 1 : 0); } + void Final(Byte *digest) throw() { Sha1_Final(&_s, digest); } +}; + +class CContext32: public CContextBase +{ +public: + void Update(const UInt32 *data, size_t size) throw() { Sha1_32_Update(&_s, data, size); } + void Final(UInt32 *digest) throw() { Sha1_32_Final(&_s, digest); } + + /* PrepareBlock can be used only when size <= 13. size in Words + _buffer must be empty (_count & 0xF) == 0) */ + void PrepareBlock(UInt32 *block, unsigned size) const throw() + { + Sha1_32_PrepareBlock(&_s, block, size); + } +}; + +}} + +#endif diff --git a/CPP/7zip/Crypto/Sha1Reg.cpp b/CPP/7zip/Crypto/Sha1Reg.cpp deleted file mode 100644 index a32972e4..00000000 --- a/CPP/7zip/Crypto/Sha1Reg.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// Sha1Reg.cpp - -#include "StdAfx.h" - -#include "../../Common/MyCom.h" - -#include "../ICoder.h" -#include "../Common/RegisterCodec.h" - -#include "Sha1.h" - -using namespace NCrypto; -using namespace NSha1; - -class CSha1Hasher: - public IHasher, - public CMyUnknownImp -{ - CContext _sha; -public: - CSha1Hasher() { Init(); } - - MY_UNKNOWN_IMP - - STDMETHOD_(void, Init)(); - STDMETHOD_(void, Update)(const void *data, UInt32 size); - STDMETHOD_(void, Final)(Byte *digest); - STDMETHOD_(UInt32, GetDigestSize)(); -}; - -STDMETHODIMP_(void) CSha1Hasher::Init() -{ - _sha.Init(); -} - -STDMETHODIMP_(void) CSha1Hasher::Update(const void *data, UInt32 size) -{ - _sha.Update((const Byte *)data, size); -} - -STDMETHODIMP_(void) CSha1Hasher::Final(Byte *digest) -{ - _sha.Final(digest); -} - -STDMETHODIMP_(UInt32) CSha1Hasher::GetDigestSize() -{ - return kDigestSize; -} - -static IHasher *CreateHasher() { return new CSha1Hasher; } - -static CHasherInfo g_HasherInfo = { CreateHasher, 0x201, L"SHA1", kDigestSize }; - -REGISTER_HASHER(Sha1) diff --git a/CPP/7zip/Crypto/WzAes.cpp b/CPP/7zip/Crypto/WzAes.cpp index 4194c02f..4572f06e 100644 --- a/CPP/7zip/Crypto/WzAes.cpp +++ b/CPP/7zip/Crypto/WzAes.cpp @@ -1,21 +1,22 @@ // Crypto/WzAes.cpp /* This code implements Brian Gladman's scheme -specified in password Based File Encryption Utility. +specified in "A Password Based File Encryption Utility". Note: you must include MyAes.cpp to project to initialize AES tables */ #include "StdAfx.h" -#include "../Common/StreamObjects.h" +#include "../../../C/CpuArch.h" + #include "../Common/StreamUtils.h" #include "Pbkdf2HmacSha1.h" #include "RandGen.h" #include "WzAes.h" -// define it if you don't want to use speed-optimized version of Pbkdf2HmacSha1 +// define it if you don't want to use speed-optimized version of NSha1::Pbkdf2Hmac // #define _NO_WZAES_OPTIMIZATIONS namespace NCrypto { @@ -33,69 +34,72 @@ STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size) return S_OK; } -#ifndef _NO_WZAES_OPTIMIZATIONS - -static void BytesToBeUInt32s(const Byte *src, UInt32 *dest, unsigned destSize) +void CBaseCoder::Init2() { - for (unsigned i = 0; i < destSize; i++) - dest[i] = - ((UInt32)(src[i * 4 + 0]) << 24) | - ((UInt32)(src[i * 4 + 1]) << 16) | - ((UInt32)(src[i * 4 + 2]) << 8) | - ((UInt32)(src[i * 4 + 3])); -} + const unsigned dkSizeMax32 = (2 * kAesKeySizeMax + kPwdVerifSize + 3) / 4; + Byte dk[dkSizeMax32 * 4]; -#endif - -STDMETHODIMP CBaseCoder::Init() -{ - UInt32 keySize = _key.GetKeySize(); - UInt32 keysTotalSize = 2 * keySize + kPwdVerifCodeSize; - Byte buf[2 * kAesKeySizeMax + kPwdVerifCodeSize]; + const unsigned keySize = _key.GetKeySize(); + const unsigned dkSize = 2 * keySize + kPwdVerifSize; // for (unsigned ii = 0; ii < 1000; ii++) { #ifdef _NO_WZAES_OPTIMIZATIONS NSha1::Pbkdf2Hmac( - _key.Password, _key.Password.Size(), - _key.Salt, _key.GetSaltSize(), - kNumKeyGenIterations, - buf, keysTotalSize); + _key.Password, _key.Password.Size(), + _key.Salt, _key.GetSaltSize(), + kNumKeyGenIterations, + dk, dkSize); #else - UInt32 buf32[(2 * kAesKeySizeMax + kPwdVerifCodeSize + 3) / 4]; - UInt32 key32SizeTotal = (keysTotalSize + 3) / 4; - UInt32 salt[kSaltSizeMax * 4]; - UInt32 saltSizeInWords = _key.GetSaltSize() / 4; - BytesToBeUInt32s(_key.Salt, salt, saltSizeInWords); + UInt32 dk32[dkSizeMax32]; + const unsigned dkSize32 = (dkSize + 3) / 4; + UInt32 salt[kSaltSizeMax / 4]; + unsigned numSaltWords = _key.GetNumSaltWords(); + + for (unsigned i = 0; i < numSaltWords; i++) + { + const Byte *src = _key.Salt + i * 4; + salt[i] = GetBe32(src); + } + NSha1::Pbkdf2Hmac32( - _key.Password, _key.Password.Size(), - salt, saltSizeInWords, - kNumKeyGenIterations, - buf32, key32SizeTotal); - for (UInt32 j = 0; j < keysTotalSize; j++) - buf[j] = (Byte)(buf32[j / 4] >> (24 - 8 * (j & 3))); + _key.Password, _key.Password.Size(), + salt, numSaltWords, + kNumKeyGenIterations, + dk32, dkSize32); + + /* + for (unsigned j = 0; j < dkSize; j++) + dk[j] = (Byte)(dk32[j / 4] >> (24 - 8 * (j & 3))); + */ + for (unsigned j = 0; j < dkSize32; j++) + SetBe32(dk + j * 4, dk32[j]); #endif } - _hmac.SetKey(buf + keySize, keySize); - memcpy(_key.PwdVerifComputed, buf + 2 * keySize, kPwdVerifCodeSize); + _hmac.SetKey(dk + keySize, keySize); + memcpy(_key.PwdVerifComputed, dk + 2 * keySize, kPwdVerifSize); - Aes_SetKey_Enc(_aes.aes + _aes.offset + 8, buf, keySize); + Aes_SetKey_Enc(_aes.aes + _aes.offset + 8, dk, keySize); AesCtr2_Init(&_aes); +} + +STDMETHODIMP CBaseCoder::Init() +{ return S_OK; } HRESULT CEncoder::WriteHeader(ISequentialOutStream *outStream) { - UInt32 saltSize = _key.GetSaltSize(); + unsigned saltSize = _key.GetSaltSize(); g_RandomGenerator.Generate(_key.Salt, saltSize); - Init(); + Init2(); RINOK(WriteStream(outStream, _key.Salt, saltSize)); - return WriteStream(outStream, _key.PwdVerifComputed, kPwdVerifCodeSize); + return WriteStream(outStream, _key.PwdVerifComputed, kPwdVerifSize); } HRESULT CEncoder::WriteFooter(ISequentialOutStream *outStream) @@ -105,6 +109,7 @@ HRESULT CEncoder::WriteFooter(ISequentialOutStream *outStream) return WriteStream(outStream, mac, kMacSize); } +/* STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) { if (size != 1) @@ -112,32 +117,34 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) _key.Init(); return SetKeyMode(data[0]) ? S_OK : E_INVALIDARG; } +*/ HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream) { - UInt32 saltSize = _key.GetSaltSize(); - UInt32 extraSize = saltSize + kPwdVerifCodeSize; - Byte temp[kSaltSizeMax + kPwdVerifCodeSize]; + unsigned saltSize = _key.GetSaltSize(); + unsigned extraSize = saltSize + kPwdVerifSize; + Byte temp[kSaltSizeMax + kPwdVerifSize]; RINOK(ReadStream_FAIL(inStream, temp, extraSize)); - UInt32 i; + unsigned i; for (i = 0; i < saltSize; i++) _key.Salt[i] = temp[i]; - for (i = 0; i < kPwdVerifCodeSize; i++) + for (i = 0; i < kPwdVerifSize; i++) _pwdVerifFromArchive[i] = temp[saltSize + i]; return S_OK; } -static bool CompareArrays(const Byte *p1, const Byte *p2, UInt32 size) +static inline bool CompareArrays(const Byte *p1, const Byte *p2, unsigned size) { - for (UInt32 i = 0; i < size; i++) + for (unsigned i = 0; i < size; i++) if (p1[i] != p2[i]) return false; return true; } -bool CDecoder::CheckPasswordVerifyCode() +bool CDecoder::Init_and_CheckPassword() { - return CompareArrays(_key.PwdVerifComputed, _pwdVerifFromArchive, kPwdVerifCodeSize); + Init2(); + return CompareArrays(_key.PwdVerifComputed, _pwdVerifFromArchive, kPwdVerifSize); } HRESULT CDecoder::CheckMac(ISequentialInStream *inStream, bool &isOK) @@ -165,12 +172,15 @@ void AesCtr2_Init(CAesCtr2 *p) p->pos = AES_BLOCK_SIZE; } +/* (size != 16 * N) is allowed only for last call */ + void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size) { unsigned pos = p->pos; UInt32 *buf32 = p->aes + p->offset; if (size == 0) return; + if (pos != AES_BLOCK_SIZE) { const Byte *buf = (const Byte *)buf32; @@ -178,6 +188,7 @@ void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size) *data++ ^= buf[pos++]; while (--size != 0 && pos != AES_BLOCK_SIZE); } + if (size >= 16) { SizeT size2 = size >> 4; @@ -187,6 +198,7 @@ void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size) size -= size2; pos = AES_BLOCK_SIZE; } + if (size != 0) { unsigned j; @@ -200,9 +212,12 @@ void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size) *data++ ^= buf[pos++]; while (--size != 0); } + p->pos = pos; } +/* (size != 16 * N) is allowed only for last Filter() call */ + STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size) { AesCtr2_Code(&_aes, data, size); diff --git a/CPP/7zip/Crypto/WzAes.h b/CPP/7zip/Crypto/WzAes.h index 980be8b3..41f9949e 100644 --- a/CPP/7zip/Crypto/WzAes.h +++ b/CPP/7zip/Crypto/WzAes.h @@ -1,7 +1,7 @@ // Crypto/WzAes.h /* This code implements Brian Gladman's scheme -specified in password Based File Encryption Utility: +specified in "A Password Based File Encryption Utility": - AES encryption (128,192,256-bit) in Counter (CTR) mode. - HMAC-SHA1 authentication for encrypted data (10 bytes) - Keys are derived by PPKDF2(RFC2898)-HMAC-SHA1 from ASCII password and @@ -25,13 +25,24 @@ specified in password Based File Encryption Utility: namespace NCrypto { namespace NWzAes { -const unsigned kSaltSizeMax = 16; -const unsigned kMacSize = 10; +/* ICompressFilter::Init() does nothing for this filter. + + Call to init: + Encoder: + CryptoSetPassword(); + WriteHeader(); + Decoder: + [CryptoSetPassword();] + ReadHeader(); + [CryptoSetPassword();] Init_and_CheckPassword(); + [CryptoSetPassword();] Init_and_CheckPassword(); +*/ const UInt32 kPasswordSizeMax = 99; // 128; -// Password Verification Code Size -const unsigned kPwdVerifCodeSize = 2; +const unsigned kSaltSizeMax = 16; +const unsigned kPwdVerifSize = 2; +const unsigned kMacSize = 10; enum EKeySizeMode { @@ -40,20 +51,19 @@ enum EKeySizeMode kKeySizeMode_AES256 = 3 }; -class CKeyInfo +struct CKeyInfo { -public: EKeySizeMode KeySizeMode; Byte Salt[kSaltSizeMax]; - Byte PwdVerifComputed[kPwdVerifCodeSize]; + Byte PwdVerifComputed[kPwdVerifSize]; CByteBuffer Password; - UInt32 GetKeySize() const { return (8 * (KeySizeMode & 3) + 8); } - UInt32 GetSaltSize() const { return (4 * (KeySizeMode & 3) + 4); } + unsigned GetKeySize() const { return (8 * KeySizeMode + 8); } + unsigned GetSaltSize() const { return (4 * KeySizeMode + 4); } + unsigned GetNumSaltWords() const { return (KeySizeMode + 1); } - CKeyInfo() { Init(); } - void Init() { KeySizeMode = kKeySizeMode_AES256; } + CKeyInfo(): KeySizeMode(kKeySizeMode_AES256) {} }; struct CAesCtr2 @@ -75,16 +85,19 @@ class CBaseCoder: protected: CKeyInfo _key; NSha1::CHmac _hmac; - Byte _pwdVerifFromArchive[kPwdVerifCodeSize]; CAesCtr2 _aes; + void Init2(); public: + MY_UNKNOWN_IMP1(ICryptoSetPassword) + + STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); + STDMETHOD(Init)(); - STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) = 0; - STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); + unsigned GetHeaderSize() const { return _key.GetSaltSize() + kPwdVerifSize; } + unsigned GetAddPackSize() const { return GetHeaderSize() + kMacSize; } - UInt32 GetHeaderSize() const { return _key.GetSaltSize() + kPwdVerifCodeSize; } bool SetKeyMode(unsigned mode) { if (mode < kKeySizeMode_AES128 || mode > kKeySizeMode_AES256) @@ -98,24 +111,22 @@ class CEncoder: public CBaseCoder { public: - MY_UNKNOWN_IMP1(ICryptoSetPassword) STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); HRESULT WriteHeader(ISequentialOutStream *outStream); HRESULT WriteFooter(ISequentialOutStream *outStream); }; class CDecoder: - public CBaseCoder, - public ICompressSetDecoderProperties2 + public CBaseCoder + // public ICompressSetDecoderProperties2 { + Byte _pwdVerifFromArchive[kPwdVerifSize]; public: - MY_UNKNOWN_IMP2( - ICryptoSetPassword, - ICompressSetDecoderProperties2) + // ICompressSetDecoderProperties2 + // STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); - STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); HRESULT ReadHeader(ISequentialInStream *inStream); - bool CheckPasswordVerifyCode(); + bool Init_and_CheckPassword(); HRESULT CheckMac(ISequentialInStream *inStream, bool &isOK); }; diff --git a/CPP/7zip/Crypto/ZipCrypto.cpp b/CPP/7zip/Crypto/ZipCrypto.cpp index baaaf98e..77aff83b 100644 --- a/CPP/7zip/Crypto/ZipCrypto.cpp +++ b/CPP/7zip/Crypto/ZipCrypto.cpp @@ -12,23 +12,27 @@ namespace NCrypto { namespace NZip { -void CCipher::UpdateKeys(Byte b) -{ - Keys[0] = CRC_UPDATE_BYTE(Keys[0], b); - Keys[1] = (Keys[1] + (Keys[0] & 0xFF)) * 0x8088405 + 1; - Keys[2] = CRC_UPDATE_BYTE(Keys[2], (Byte)(Keys[1] >> 24)); -} +#define UPDATE_KEYS(b) { \ + Key0 = CRC_UPDATE_BYTE(Key0, b); \ + Key1 = (Key1 + (Key0 & 0xFF)) * 0x8088405 + 1; \ + Key2 = CRC_UPDATE_BYTE(Key2, (Byte)(Key1 >> 24)); } \ + +#define DECRYPT_BYTE_1 UInt32 temp = Key2 | 2; +#define DECRYPT_BYTE_2 ((Byte)((temp * (temp ^ 1)) >> 8)) -STDMETHODIMP CCipher::CryptoSetPassword(const Byte *password, UInt32 passwordLen) +STDMETHODIMP CCipher::CryptoSetPassword(const Byte *data, UInt32 size) { - Keys[0] = 0x12345678; - Keys[1] = 0x23456789; - Keys[2] = 0x34567890; - UInt32 i; - for (i = 0; i < passwordLen; i++) - UpdateKeys(password[i]); - for (i = 0; i < 3; i++) - Keys2[i] = Keys[i]; + UInt32 Key0 = 0x12345678; + UInt32 Key1 = 0x23456789; + UInt32 Key2 = 0x34567890; + + for (UInt32 i = 0; i < size; i++) + UPDATE_KEYS(data[i]); + + KeyMem0 = Key0; + KeyMem1 = Key1; + KeyMem2 = Key2; + return S_OK; } @@ -37,18 +41,18 @@ STDMETHODIMP CCipher::Init() return S_OK; } -Byte CCipher::DecryptByteSpec() -{ - UInt32 temp = Keys[2] | 2; - return (Byte)((temp * (temp ^ 1)) >> 8); -} - -HRESULT CEncoder::WriteHeader(ISequentialOutStream *outStream, UInt32 crc) +HRESULT CEncoder::WriteHeader_Check16(ISequentialOutStream *outStream, UInt16 crc) { Byte h[kHeaderSize]; - g_RandomGenerator.Generate(h, kHeaderSize - 2); - h[kHeaderSize - 1] = (Byte)(crc >> 24); - h[kHeaderSize - 2] = (Byte)(crc >> 16); + + /* PKZIP before 2.0 used 2 byte CRC check. + PKZIP 2.0+ used 1 byte CRC check. It's more secure. + We also use 1 byte CRC. */ + + g_RandomGenerator.Generate(h, kHeaderSize - 1); + // h[kHeaderSize - 2] = (Byte)(crc); + h[kHeaderSize - 1] = (Byte)(crc >> 8); + RestoreKeys(); Filter(h, kHeaderSize); return WriteStream(outStream, h, kHeaderSize); @@ -56,32 +60,54 @@ HRESULT CEncoder::WriteHeader(ISequentialOutStream *outStream, UInt32 crc) STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size) { + UInt32 Key0 = this->Key0; + UInt32 Key1 = this->Key1; + UInt32 Key2 = this->Key2; + for (UInt32 i = 0; i < size; i++) { Byte b = data[i]; - data[i] = (Byte)(b ^ DecryptByteSpec());; - UpdateKeys(b); + DECRYPT_BYTE_1 + data[i] = (Byte)(b ^ DECRYPT_BYTE_2); + UPDATE_KEYS(b); } + + this->Key0 = Key0; + this->Key1 = Key1; + this->Key2 = Key2; + return size; } HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream) { - Byte h[kHeaderSize]; - RINOK(ReadStream_FAIL(inStream, h, kHeaderSize)); + return ReadStream_FAIL(inStream, _header, kHeaderSize); +} + +void CDecoder::Init_BeforeDecode() +{ RestoreKeys(); - Filter(h, kHeaderSize); - return S_OK; + Filter(_header, kHeaderSize); } STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size) { + UInt32 Key0 = this->Key0; + UInt32 Key1 = this->Key1; + UInt32 Key2 = this->Key2; + for (UInt32 i = 0; i < size; i++) { - Byte c = (Byte)(data[i] ^ DecryptByteSpec()); - UpdateKeys(c); - data[i] = c; + DECRYPT_BYTE_1 + Byte b = (Byte)(data[i] ^ DECRYPT_BYTE_2); + UPDATE_KEYS(b); + data[i] = b; } + + this->Key0 = Key0; + this->Key1 = Key1; + this->Key2 = Key2; + return size; } diff --git a/CPP/7zip/Crypto/ZipCrypto.h b/CPP/7zip/Crypto/ZipCrypto.h index 51b9e301..b23d4216 100644 --- a/CPP/7zip/Crypto/ZipCrypto.h +++ b/CPP/7zip/Crypto/ZipCrypto.h @@ -13,24 +13,41 @@ namespace NZip { const unsigned kHeaderSize = 12; +/* ICompressFilter::Init() does nothing for this filter. + Call to init: + Encoder: + CryptoSetPassword(); + WriteHeader(); + Decoder: + [CryptoSetPassword();] + ReadHeader(); + [CryptoSetPassword();] Init_and_GetCrcByte(); + [CryptoSetPassword();] Init_and_GetCrcByte(); +*/ + class CCipher: public ICompressFilter, public ICryptoSetPassword, public CMyUnknownImp { - UInt32 Keys[3]; - UInt32 Keys2[3]; - protected: - void UpdateKeys(Byte b); - Byte DecryptByteSpec(); + UInt32 Key0; + UInt32 Key1; + UInt32 Key2; + + UInt32 KeyMem0; + UInt32 KeyMem1; + UInt32 KeyMem2; + void RestoreKeys() { - for (int i = 0; i < 3; i++) - Keys[i] = Keys2[i]; + Key0 = KeyMem0; + Key1 = KeyMem1; + Key2 = KeyMem2; } public: + MY_UNKNOWN_IMP1(ICryptoSetPassword) STDMETHOD(Init)(); STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); }; @@ -38,17 +55,17 @@ public: class CEncoder: public CCipher { public: - MY_UNKNOWN_IMP1(ICryptoSetPassword) STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); - HRESULT WriteHeader(ISequentialOutStream *outStream, UInt32 crc); + HRESULT WriteHeader_Check16(ISequentialOutStream *outStream, UInt16 crc); }; class CDecoder: public CCipher { public: - MY_UNKNOWN_IMP1(ICryptoSetPassword) + Byte _header[kHeaderSize]; STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); HRESULT ReadHeader(ISequentialInStream *inStream); + void Init_BeforeDecode(); }; }} diff --git a/CPP/7zip/Crypto/ZipStrong.cpp b/CPP/7zip/Crypto/ZipStrong.cpp index a8765c26..c5e368b9 100644 --- a/CPP/7zip/Crypto/ZipStrong.cpp +++ b/CPP/7zip/Crypto/ZipStrong.cpp @@ -7,8 +7,7 @@ #include "../Common/StreamUtils.h" -#include "MyAes.h" -#include "Sha1.h" +#include "Sha1Cls.h" #include "ZipStrong.h" namespace NCrypto { @@ -57,25 +56,22 @@ STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size) return S_OK; } -HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream, UInt32 /* crc */, UInt64 /* unpackSize */) +STDMETHODIMP CBaseCoder::Init() +{ + return S_OK; +} + +HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream, UInt32 crc, UInt64 unpackSize) { Byte temp[4]; RINOK(ReadStream_FALSE(inStream, temp, 2)); _ivSize = GetUi16(temp); if (_ivSize == 0) { - return E_NOTIMPL; - - /* we don't know how to decode that case: - From Appnote: If IVSize is 0,then IV = CRC32 + Uncompressed File Size (as a 64 bit little-endian, unsigned integer value). - But it doesn't work. If you know solution, please write about it to 7-Zip developers. */ - - /* memset(_iv, 0, 16); - // unpackSize += crc; SetUi32(_iv + 0, crc); SetUi64(_iv + 4, unpackSize); - */ + _ivSize = 12; } else if (_ivSize == 16) { @@ -96,7 +92,7 @@ HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream, UInt32 /* crc */, UI return ReadStream_FALSE(inStream, _bufAligned, _remSize); } -HRESULT CDecoder::CheckPassword(bool &passwOK) +HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK) { passwOK = false; if (_remSize < 16) @@ -146,7 +142,7 @@ HRESULT CDecoder::CheckPassword(bool &passwOK) Byte fileKey[32]; NSha1::CContext sha; sha.Init(); - sha.Update(_iv, 16); + sha.Update(_iv, _ivSize); sha.Update(p, rdSize - 16); // we don't use last 16 bytes (PAD bytes) DeriveKey(sha, fileKey); @@ -161,8 +157,6 @@ HRESULT CDecoder::CheckPassword(bool &passwOK) if (GetUi32(validData + validSize) != CrcCalc(validData, validSize)) return S_OK; passwOK = true; - /* 9.31: The BUG in 9.24-9.30 was fixed. - We don't need to call CAesCbcCoder::Init() to reset IV for data. */ return S_OK; } diff --git a/CPP/7zip/Crypto/ZipStrong.h b/CPP/7zip/Crypto/ZipStrong.h index e3a43000..c5809e7b 100644 --- a/CPP/7zip/Crypto/ZipStrong.h +++ b/CPP/7zip/Crypto/ZipStrong.h @@ -12,10 +12,20 @@ namespace NCrypto { namespace NZipStrong { +/* ICompressFilter::Init() does nothing for this filter. + Call to init: + Decoder: + [CryptoSetPassword();] + ReadHeader(); + [CryptoSetPassword();] Init_and_CheckPassword(); + [CryptoSetPassword();] Init_and_CheckPassword(); +*/ + struct CKeyInfo { Byte MasterKey[32]; UInt32 KeySize; + void SetPassword(const Byte *data, UInt32 size); }; @@ -28,6 +38,7 @@ protected: CByteBuffer _buf; Byte *_bufAligned; public: + STDMETHOD(Init)(); STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); }; @@ -39,7 +50,7 @@ class CDecoder: public CBaseCoder public: MY_UNKNOWN_IMP1(ICryptoSetPassword) HRESULT ReadHeader(ISequentialInStream *inStream, UInt32 crc, UInt64 unpackSize); - HRESULT CheckPassword(bool &passwOK); + HRESULT Init_and_CheckPassword(bool &passwOK); }; }} diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt index 8ded1f96..64214e80 100644 --- a/CPP/7zip/Guid.txt +++ b/CPP/7zip/Guid.txt @@ -3,18 +3,23 @@ 00 IProgress.h 05 IProgress + // 050002 IProgress2 01 IFolderArchive.h // 05 IArchiveFolder // old // 06 IInFolderArchive // old 07 IFileExtractCallback.h::IFolderArchiveExtractCallback + 08 IFileExtractCallback.h::IFolderArchiveExtractCallback2 // 0A IOutFolderArchive 0B IFolderArchiveUpdateCallback 0C Agent.h::IArchiveFolderInternal 0D IArchiveFolder 0E IInFolderArchive 0F IOutFolderArchive + 10 IFolderArchiveUpdateCallback2 + 11 IFolderScanProgress + 20 IFileExtractCallback.h::IGetProp 30 IFileExtractCallback.h::IFolderExtractToStreamCallback @@ -25,7 +30,7 @@ 03 IInStream 04 IOutStream 06 IStreamGetSize - 07 IOutStreamFlush + 07 IOutStreamFinish 08 IStreamGetProps 09 IStreamGetProps2 @@ -41,12 +46,20 @@ 23 ICompressWriteCoderProperties 24 ICompressGetInStreamProcessedSize 25 ICompressSetCoderMt + 26 ICompressSetFinishMode + 30 ICompressGetSubStreamSize 31 ICompressSetInStream 32 ICompressSetOutStream - 33 ICompressSetInStreamSize +// 33 ICompressSetInStreamSize 34 ICompressSetOutStreamSize 35 ICompressSetBufSize + 36 ICompressInitEncoder + 37 ICompressSetInStream2 +// 38 ICompressSetOutStream2 +// 39 SetInStreamSize2 +// 3A SetOutStreamSize2 + 40 ICompressFilter 60 ICompressCodecsInfo 61 ISetCompressCodecsInfo @@ -72,7 +85,10 @@ 05 IArchiveAllowTail 10 IArchiveOpenCallback + 20 IArchiveExtractCallback + 21 IArchiveExtractCallbackMessage + 30 IArchiveOpenVolumeCallback 40 IInArchiveGetStream 50 IArchiveOpenSetSubArchiveName @@ -83,6 +99,8 @@ 80 IArchiveUpdateCallback 82 IArchiveUpdateCallback2 + 83 IArchiveUpdateCallbackFile + A0 IOutArchive @@ -112,6 +130,7 @@ 14 IFolderCalcItemFullSize 15 IFolderCompare 16 IFolderGetItemName + 17 IFolderAltStreams 09 IFolder.h :: FOLDER_MANAGER_INTERFACE @@ -180,12 +199,11 @@ Handler GUIDs: EE Tar EF GZip -{23170F69-40C1-278A-1000-000100030000} CAgentArchiveHandle {23170F69-40C1-278A-1000-000100020000} ContextMenu.h::CZipContextMenu -{23170F69-40C1-278B- old codecs clsids - -{23170F69-40C1-278D-1000-000100020000} OptionsDialog.h::CLSID_CSevenZipOptions +// {23170F69-40C1-278A-1000-000100030000} // CAgentArchiveHandler +// {23170F69-40C1-278B- old codecs clsids +// {23170F69-40C1-278D-1000-000100020000} OptionsDialog.h::CLSID_CSevenZipOptions {23170F69-40C1-2790-id} Codec Decoders {23170F69-40C1-2791-id} Codec Encoders diff --git a/CPP/7zip/ICoder.h b/CPP/7zip/ICoder.h index 74ee0e45..75db9399 100644 --- a/CPP/7zip/ICoder.h +++ b/CPP/7zip/ICoder.h @@ -10,6 +10,15 @@ CODER_INTERFACE(ICompressProgressInfo, 0x04) { STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; + + /* (inSize) can be NULL, if unknown + (outSize) can be NULL, if unknown + + returns: + S_OK + E_ABORT : Break by user + another error codes + */ }; CODER_INTERFACE(ICompressCoder, 0x05) @@ -21,11 +30,75 @@ CODER_INTERFACE(ICompressCoder, 0x05) CODER_INTERFACE(ICompressCoder2, 0x18) { - STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, - ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, + STDMETHOD(Code)(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, + ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) PURE; }; +/* + ICompressCoder::Code + ICompressCoder2::Code + + returns: + S_OK : OK + S_FALSE : data error (for decoders) + E_OUTOFMEMORY : memory allocation error + another error code : some error. For example, it can be error code received from inStream or outStream function. + + Parameters: + (inStream != NULL) + (outStream != NULL) + + if (inSize != NULL) + { + Encoders in 7-Zip ignore (inSize). + Decoder can use (*inSize) to check that stream was decoded correctly. + Some decoder in 7-Zip check it, if (full_decoding mode was set via ICompressSetFinishMode) + } + + If it's required to limit the reading from input stream (inStream), it can + be done with ISequentialInStream implementation. + + if (outSize != NULL) + { + Encoders in 7-Zip ignore (outSize). + Decoder unpacks no more than (*outSize) bytes. + } + + (progress == NULL) is allowed. + + + Decoding with Code() function + ----------------------------- + + You can request some interfaces before decoding + - ICompressSetDecoderProperties2 + - ICompressSetFinishMode + + If you need to decode full stream: + { + 1) try to set full_decoding mode with ICompressSetFinishMode::SetFinishMode(1); + 2) call the Code() function with specified (inSize) and (outSize), if these sizes are known. + } + + If you need to decode only part of stream: + { + 1) try to set partial_decoding mode with ICompressSetFinishMode::SetFinishMode(0); + 2) Call the Code() function with specified (inSize = NULL) and specified (outSize). + } + + Encoding with Code() function + ----------------------------- + + You can request some interfaces : + - ICompressSetCoderProperties - use it before encoding to set properties + - ICompressWriteCoderProperties - use it before or after encoding to request encoded properties. + + ICompressCoder2 is used when (numInStreams != 1 || numOutStreams != 1) + The rules are similar to ICompressCoder rules +*/ + + namespace NCoderPropID { enum EEnum @@ -64,6 +137,12 @@ CODER_INTERFACE(ICompressSetCoderProperties, 0x21) CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) { + /* returns: + S_OK + E_NOTIMP : unsupported properties + E_INVALIDARG : incorrect (or unsupported) properties + E_OUTOFMEMORY : memory allocation error + */ STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; }; @@ -82,9 +161,34 @@ CODER_INTERFACE(ICompressSetCoderMt, 0x25) STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE; }; +CODER_INTERFACE(ICompressSetFinishMode, 0x26) +{ + STDMETHOD(SetFinishMode)(UInt32 finishMode) PURE; + + /* finishMode: + 0 : partial decoding is allowed. It's default mode for ICompressCoder::Code(), if (outSize) is defined. + 1 : full decoding. The stream must be finished at the end of decoding. */ +}; + + CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) { STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; + + /* returns: + S_OK : (*value) contains the size or estimated size (can be incorrect size) + S_FALSE : size is undefined + E_NOTIMP : the feature is not implemented + + Let's (read_size) is size of data that was already read by ISequentialInStream::Read(). + The caller should call GetSubStreamSize() after each Read() and check sizes: + if (start_of_subStream + *value < read_size) + { + // (*value) is correct, and it's allowed to call GetSubStreamSize() for next subStream: + start_of_subStream += *value; + subStream++; + } + */ }; CODER_INTERFACE(ICompressSetInStream, 0x31) @@ -99,14 +203,21 @@ CODER_INTERFACE(ICompressSetOutStream, 0x32) STDMETHOD(ReleaseOutStream)() PURE; }; +/* CODER_INTERFACE(ICompressSetInStreamSize, 0x33) { STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; }; +*/ CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) { STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; + + /* That function initializes decoder structures. + Call this function only for stream version of decoder. + if (outSize == NULL), then output size is unknown + if (outSize != NULL), then the decoder must stop decoding after (*outSize) bytes. */ }; CODER_INTERFACE(ICompressSetBufSize, 0x35) @@ -115,25 +226,62 @@ CODER_INTERFACE(ICompressSetBufSize, 0x35) STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size) PURE; }; +CODER_INTERFACE(ICompressInitEncoder, 0x36) +{ + STDMETHOD(InitEncoder)() PURE; + + /* That function initializes encoder structures. + Call this function only for stream version of encoder. */ +}; + +CODER_INTERFACE(ICompressSetInStream2, 0x37) +{ + STDMETHOD(SetInStream2)(UInt32 streamIndex, ISequentialInStream *inStream) PURE; + STDMETHOD(ReleaseInStream2)(UInt32 streamIndex) PURE; +}; + +/* +CODER_INTERFACE(ICompressSetOutStream2, 0x38) +{ + STDMETHOD(SetOutStream2)(UInt32 streamIndex, ISequentialOutStream *outStream) PURE; + STDMETHOD(ReleaseOutStream2)(UInt32 streamIndex) PURE; +}; + +CODER_INTERFACE(ICompressSetInStreamSize2, 0x39) +{ + STDMETHOD(SetInStreamSize2)(UInt32 streamIndex, const UInt64 *inSize) PURE; +}; +*/ + + +/* + ICompressFilter + Filter() converts as most as possible bytes + returns: (outSize): + if (outSize <= size) : Filter have converted outSize bytes + if (outSize > size) : Filter have not converted anything. + and it needs at least outSize bytes to convert one block + (it's for crypto block algorithms). +*/ + +#define INTERFACE_ICompressFilter(x) \ + STDMETHOD(Init)() x; \ + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) x; \ + CODER_INTERFACE(ICompressFilter, 0x40) { - STDMETHOD(Init)() PURE; - STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE; - // Filter converts as most as possible bytes - // Filter return outSize (UInt32) - // if (outSize <= size): Filter have converted outSize bytes - // if (outSize > size): Filter have not converted anything. - // and it needs at least outSize bytes to convert one block - // (it's for crypto block algorithms). + INTERFACE_ICompressFilter(PURE); }; + CODER_INTERFACE(ICompressCodecsInfo, 0x60) { - STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods) PURE; + STDMETHOD(GetNumMethods)(UInt32 *numMethods) PURE; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE; STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE; }; + CODER_INTERFACE(ISetCompressCodecsInfo, 0x61) { STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE; @@ -155,6 +303,10 @@ CODER_INTERFACE(ICryptoResetSalt, 0x88) CODER_INTERFACE(ICryptoResetInitVector, 0x8C) { STDMETHOD(ResetInitVector)() PURE; + + /* Call ResetInitVector() only for encoding. + Call ResetInitVector() before encoding and before WriteCoderProperties(). + Crypto encoder can create random IV in that function. */ }; CODER_INTERFACE(ICryptoSetPassword, 0x90) @@ -167,8 +319,7 @@ CODER_INTERFACE(ICryptoSetCRC, 0xA0) STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; }; -////////////////////// -// It's for DLL file + namespace NMethodPropID { enum EEnum @@ -177,8 +328,8 @@ namespace NMethodPropID kName, kDecoder, kEncoder, - kInStreams, - kOutStreams, + kPackStreams, + kUnpackStreams, kDescription, kDecoderIsAssigned, kEncoderIsAssigned, @@ -186,12 +337,16 @@ namespace NMethodPropID }; } + +#define INTERFACE_IHasher(x) \ + STDMETHOD_(void, Init)() throw() x; \ + STDMETHOD_(void, Update)(const void *data, UInt32 size) throw() x; \ + STDMETHOD_(void, Final)(Byte *digest) throw() x; \ + STDMETHOD_(UInt32, GetDigestSize)() throw() x; \ + CODER_INTERFACE(IHasher, 0xC0) { - STDMETHOD_(void, Init)() PURE; - STDMETHOD_(void, Update)(const void *data, UInt32 size) PURE; - STDMETHOD_(void, Final)(Byte *digest) PURE; - STDMETHOD_(UInt32, GetDigestSize)() PURE; + INTERFACE_IHasher(PURE) }; CODER_INTERFACE(IHashers, 0xC1) @@ -205,7 +360,12 @@ extern "C" { typedef HRESULT (WINAPI *Func_GetNumberOfMethods)(UInt32 *numMethods); typedef HRESULT (WINAPI *Func_GetMethodProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); + typedef HRESULT (WINAPI *Func_CreateDecoder)(UInt32 index, const GUID *iid, void **outObject); + typedef HRESULT (WINAPI *Func_CreateEncoder)(UInt32 index, const GUID *iid, void **outObject); + typedef HRESULT (WINAPI *Func_GetHashers)(IHashers **hashers); + + typedef HRESULT (WINAPI *Func_SetCodecs)(ICompressCodecsInfo *compressCodecsInfo); } #endif diff --git a/CPP/7zip/IDecl.h b/CPP/7zip/IDecl.h index 8316eb3a..077ef0ee 100644 --- a/CPP/7zip/IDecl.h +++ b/CPP/7zip/IDecl.h @@ -5,10 +5,23 @@ #include "../Common/MyUnknown.h" +#define k_7zip_GUID_Data1 0x23170F69 +#define k_7zip_GUID_Data2 0x40C1 + +#define k_7zip_GUID_Data3_Common 0x278A + +#define k_7zip_GUID_Data3_Decoder 0x2790 +#define k_7zip_GUID_Data3_Encoder 0x2791 +#define k_7zip_GUID_Data3_Hasher 0x2792 + + #define DECL_INTERFACE_SUB(i, base, groupId, subId) \ -DEFINE_GUID(IID_ ## i, \ -0x23170F69, 0x40C1, 0x278A, 0, 0, 0, (groupId), 0, (subId), 0, 0); \ -struct i: public base + DEFINE_GUID(IID_ ## i, \ + k_7zip_GUID_Data1, \ + k_7zip_GUID_Data2, \ + k_7zip_GUID_Data3_Common, \ + 0, 0, 0, (groupId), 0, (subId), 0, 0); \ + struct i: public base #define DECL_INTERFACE(i, groupId, subId) DECL_INTERFACE_SUB(i, IUnknown, groupId, subId) diff --git a/CPP/7zip/IProgress.h b/CPP/7zip/IProgress.h index a270e693..59c55aea 100644 --- a/CPP/7zip/IProgress.h +++ b/CPP/7zip/IProgress.h @@ -1,4 +1,4 @@ -// Interface/IProgress.h +// IProgress.h #ifndef __IPROGRESS_H #define __IPROGRESS_H @@ -17,17 +17,4 @@ DECL_INTERFACE(IProgress, 0, 5) INTERFACE_IProgress(PURE) }; -/* -// {23170F69-40C1-278A-0000-000000050002} -DEFINE_GUID(IID_IProgress2, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000000050002") -IProgress2: public IUnknown -{ -public: - STDMETHOD(SetTotal)(const UInt64 *total) PURE; - STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE; -}; -*/ - #endif diff --git a/CPP/7zip/IStream.h b/CPP/7zip/IStream.h index c3a290b9..70cb3620 100644 --- a/CPP/7zip/IStream.h +++ b/CPP/7zip/IStream.h @@ -95,9 +95,9 @@ STREAM_INTERFACE(IStreamGetSize, 0x06) STDMETHOD(GetSize)(UInt64 *size) PURE; }; -STREAM_INTERFACE(IOutStreamFlush, 0x07) +STREAM_INTERFACE(IOutStreamFinish, 0x07) { - STDMETHOD(Flush)() PURE; + STDMETHOD(OutStreamFinish)() PURE; }; diff --git a/CPP/7zip/MyVersion.h b/CPP/7zip/MyVersion.h index 952333a8..8f52a126 100644 --- a/CPP/7zip/MyVersion.h +++ b/CPP/7zip/MyVersion.h @@ -1,6 +1,2 @@ -#include "..\..\C\7zVersion.h" - -#undef MY_COPYRIGHT -#undef MY_VERSION_COPYRIGHT_DATE -#define MY_COPYRIGHT "Copyright (c) 1999-2014 Igor Pavlov" -#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE +#define USE_COPYRIGHT_CR +#include "../../C/7zVersion.h" diff --git a/CPP/7zip/PropID.h b/CPP/7zip/PropID.h index 82a7462b..3f3acb2d 100644 --- a/CPP/7zip/PropID.h +++ b/CPP/7zip/PropID.h @@ -100,13 +100,15 @@ enum kpidHardLink, kpidINode, kpidStreamId, + kpidReadOnly, + kpidOutName, kpid_NUM_DEFINED, kpidUserDefined = 0x10000 }; -extern Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED]; // VARTYPE +extern const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED]; // VARTYPE const UInt32 kpv_ErrorFlags_IsNotArc = 1 << 0; const UInt32 kpv_ErrorFlags_HeadersError = 1 << 1; diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp index d8221754..557282eb 100644 --- a/CPP/7zip/UI/Agent/Agent.cpp +++ b/CPP/7zip/UI/Agent/Agent.cpp @@ -2,12 +2,20 @@ #include "StdAfx.h" +#include <wchar.h> + #include "../../../../C/Sort.h" #include "../../../Common/ComTry.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" #include "../../../Windows/PropVariantConv.h" +#ifndef _7ZIP_ST +#include "../../../Windows/Synchronization.h" +#endif + #include "../Common/ArchiveExtractCallback.h" #include "../FileManager/RegistryUtils.h" @@ -15,43 +23,109 @@ using namespace NWindows; +CCodecs *g_CodecsObj; + +#ifdef EXTERNAL_CODECS + CExternalCodecs g_ExternalCodecs; + CCodecs::CReleaser g_CodecsReleaser; +#else + CMyComPtr<IUnknown> g_CodecsRef; +#endif + +#ifndef _7ZIP_ST +static NSynchronization::CCriticalSection g_CriticalSection; +#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); +#else +#define MT_LOCK +#endif + +void FreeGlobalCodecs() +{ + MT_LOCK + + #ifdef EXTERNAL_CODECS + if (g_CodecsObj) + { + g_CodecsObj->CloseLibs(); + } + g_CodecsReleaser.Set(NULL); + g_CodecsObj = NULL; + g_ExternalCodecs.ClearAndRelease(); + #else + g_CodecsRef.Release(); + #endif +} + +HRESULT LoadGlobalCodecs() +{ + MT_LOCK + + if (g_CodecsObj) + return S_OK; + + g_CodecsObj = new CCodecs; + + #ifdef EXTERNAL_CODECS + g_ExternalCodecs.GetCodecs = g_CodecsObj; + g_ExternalCodecs.GetHashers = g_CodecsObj; + g_CodecsReleaser.Set(g_CodecsObj); + #else + g_CodecsRef.Release(); + g_CodecsRef = g_CodecsObj; + #endif + + RINOK(g_CodecsObj->Load()); + if (g_CodecsObj->Formats.IsEmpty()) + { + FreeGlobalCodecs(); + return E_NOTIMPL; + } + + #ifdef EXTERNAL_CODECS + RINOK(g_ExternalCodecs.Load()); + #endif + + return S_OK; +} + STDMETHODIMP CAgentFolder::GetAgentFolder(CAgentFolder **agentFolder) { *agentFolder = this; return S_OK; } -void CAgentFolder::LoadFolder(unsigned proxyFolderIndex) +void CAgentFolder::LoadFolder(unsigned proxyDirIndex) { - unsigned i; CProxyItem item; - item.ProxyFolderIndex = proxyFolderIndex; - if (_proxyArchive2) + item.DirIndex = proxyDirIndex; + + if (_proxy2) { - const CProxyFolder2 &folder = _proxyArchive2->Folders[proxyFolderIndex]; - for (i = 0; i < folder.SubFiles.Size(); i++) + const CProxyDir2 &dir = _proxy2->Dirs[proxyDirIndex]; + FOR_VECTOR (i, dir.Items) { item.Index = i; _items.Add(item); - const CProxyFile2 &file = _proxyArchive2->Files[folder.SubFiles[i]]; - int subFolderIndex = file.FolderIndex; - if (subFolderIndex >= 0) - LoadFolder(subFolderIndex); - subFolderIndex = file.AltStreamsFolderIndex; - if (subFolderIndex >= 0) - LoadFolder(subFolderIndex); + const CProxyFile2 &file = _proxy2->Files[dir.Items[i]]; + if (file.DirIndex >= 0) + LoadFolder(file.DirIndex); + if (_loadAltStreams && file.AltDirIndex >= 0) + LoadFolder(file.AltDirIndex); } return; } - const CProxyFolder &folder = _proxyArchive->Folders[proxyFolderIndex]; - for (i = 0; i < folder.Folders.Size(); i++) + + const CProxyDir &dir = _proxy->Dirs[proxyDirIndex]; + unsigned i; + for (i = 0; i < dir.SubDirs.Size(); i++) { item.Index = i; _items.Add(item); - LoadFolder(folder.Folders[i]); + LoadFolder(dir.SubDirs[i]); } - unsigned start = folder.Folders.Size(); - for (i = 0; i < folder.Files.Size(); i++) + + unsigned start = dir.SubDirs.Size(); + for (i = 0; i < dir.SubFiles.Size(); i++) { item.Index = start + i; _items.Add(item); @@ -64,7 +138,14 @@ STDMETHODIMP CAgentFolder::LoadItems() return E_FAIL; _items.Clear(); if (_flatMode) - LoadFolder(_proxyFolderItem); + { + LoadFolder(_proxyDirIndex); + if (_proxy2 && _loadAltStreams) + { + if (_proxyDirIndex == k_Proxy2_RootDirIndex) + LoadFolder(k_Proxy2_AltRootDirIndex); + } + } return S_OK; } @@ -72,37 +153,37 @@ STDMETHODIMP CAgentFolder::GetNumberOfItems(UInt32 *numItems) { if (_flatMode) *numItems = _items.Size(); - else if (_proxyArchive2) - *numItems = _proxyArchive2->Folders[_proxyFolderItem].SubFiles.Size(); + else if (_proxy2) + *numItems = _proxy2->Dirs[_proxyDirIndex].Items.Size(); else { - const CProxyFolder *folder = &_proxyArchive->Folders[_proxyFolderItem]; - *numItems = folder->Folders.Size() + folder ->Files.Size(); + const CProxyDir *dir = &_proxy->Dirs[_proxyDirIndex]; + *numItems = dir->SubDirs.Size() + dir->SubFiles.Size(); } return S_OK; } -#define SET_realIndex_AND_folder \ - UInt32 realIndex; const CProxyFolder *folder; \ - if (_flatMode) { const CProxyItem &item = _items[index]; folder = &_proxyArchive->Folders[item.ProxyFolderIndex]; realIndex = item.Index; } \ - else { folder = &_proxyArchive->Folders[_proxyFolderItem]; realIndex = index; } +#define SET_realIndex_AND_dir \ + unsigned realIndex; const CProxyDir *dir; \ + if (_flatMode) { const CProxyItem &item = _items[index]; dir = &_proxy->Dirs[item.DirIndex]; realIndex = item.Index; } \ + else { dir = &_proxy->Dirs[_proxyDirIndex]; realIndex = index; } -#define SET_realIndex_AND_folder_2 \ - UInt32 realIndex; const CProxyFolder2 *folder; \ - if (_flatMode) { const CProxyItem &item = _items[index]; folder = &_proxyArchive2->Folders[item.ProxyFolderIndex]; realIndex = item.Index; } \ - else { folder = &_proxyArchive2->Folders[_proxyFolderItem]; realIndex = index; } +#define SET_realIndex_AND_dir_2 \ + unsigned realIndex; const CProxyDir2 *dir; \ + if (_flatMode) { const CProxyItem &item = _items[index]; dir = &_proxy2->Dirs[item.DirIndex]; realIndex = item.Index; } \ + else { dir = &_proxy2->Dirs[_proxyDirIndex]; realIndex = index; } UString CAgentFolder::GetName(UInt32 index) const { - if (_proxyArchive2) + if (_proxy2) { - SET_realIndex_AND_folder_2 - return _proxyArchive2->Files[folder->SubFiles[realIndex]].Name; + SET_realIndex_AND_dir_2 + return _proxy2->Files[dir->Items[realIndex]].Name; } - SET_realIndex_AND_folder - if (realIndex < (UInt32)folder->Folders.Size()) - return _proxyArchive->Folders[folder->Folders[realIndex]].Name; - return folder->Files[realIndex - folder->Folders.Size()].Name; + SET_realIndex_AND_dir + if (realIndex < dir->SubDirs.Size()) + return _proxy->Dirs[dir->SubDirs[realIndex]].Name; + return _proxy->Files[dir->SubFiles[realIndex - dir->SubDirs.Size()]].Name; } void CAgentFolder::GetPrefix(UInt32 index, UString &prefix) const @@ -112,97 +193,101 @@ void CAgentFolder::GetPrefix(UInt32 index, UString &prefix) const prefix.Empty(); return; } + const CProxyItem &item = _items[index]; - unsigned proxyIndex = item.ProxyFolderIndex; - unsigned totalLen; - if (_proxyArchive2) + unsigned proxyIndex = item.DirIndex; + + if (_proxy2) { + // that code is unused. 7-Zip gets prefix via GetItemPrefix() . + unsigned len = 0; - while (proxyIndex != _proxyFolderItem) + while (proxyIndex != _proxyDirIndex && proxyIndex >= k_Proxy2_NumRootDirs) { - const CProxyFile2 &file = _proxyArchive2->Files[_proxyArchive2->Folders[proxyIndex].ArcIndex]; - len += file.NameSize + 1; - proxyIndex = (file.Parent < 0) ? 0 : _proxyArchive2->Files[file.Parent].GetFolderIndex(file.IsAltStream); + const CProxyFile2 &file = _proxy2->Files[_proxy2->Dirs[proxyIndex].ArcIndex]; + len += file.NameLen + 1; + proxyIndex = (file.Parent < 0) ? 0 : _proxy2->Files[file.Parent].GetDirIndex(file.IsAltStream); } - totalLen = len; - wchar_t *p = prefix.GetBuffer(len); - proxyIndex = item.ProxyFolderIndex; - while (proxyIndex != _proxyFolderItem) + wchar_t *p = prefix.GetBuf_SetEnd(len) + len; + proxyIndex = item.DirIndex; + while (proxyIndex != _proxyDirIndex && proxyIndex >= k_Proxy2_NumRootDirs) { - const CProxyFile2 &file = _proxyArchive2->Files[_proxyArchive2->Folders[proxyIndex].ArcIndex]; - MyStringCopy(p + len - file.NameSize - 1, file.Name); - p[--len] = WCHAR_PATH_SEPARATOR; - len -= file.NameSize; - proxyIndex = (file.Parent < 0) ? 0 : _proxyArchive2->Files[file.Parent].GetFolderIndex(file.IsAltStream); + const CProxyFile2 &file = _proxy2->Files[_proxy2->Dirs[proxyIndex].ArcIndex]; + p--; + *p = WCHAR_PATH_SEPARATOR; + p -= file.NameLen; + wmemcpy(p, file.Name, file.NameLen); + proxyIndex = (file.Parent < 0) ? 0 : _proxy2->Files[file.Parent].GetDirIndex(file.IsAltStream); } } else { unsigned len = 0; - while (proxyIndex != _proxyFolderItem) + while (proxyIndex != _proxyDirIndex) { - const CProxyFolder *folder = &_proxyArchive->Folders[proxyIndex]; - len += folder->Name.Len() + 1; - proxyIndex = folder->Parent; + const CProxyDir *dir = &_proxy->Dirs[proxyIndex]; + len += dir->NameLen + 1; + proxyIndex = dir->ParentDir; } - totalLen = len; - wchar_t *p = prefix.GetBuffer(len); - proxyIndex = item.ProxyFolderIndex; - while (proxyIndex != _proxyFolderItem) + wchar_t *p = prefix.GetBuf_SetEnd(len) + len; + proxyIndex = item.DirIndex; + while (proxyIndex != _proxyDirIndex) { - const CProxyFolder *folder = &_proxyArchive->Folders[proxyIndex]; - MyStringCopy(p + len - folder->Name.Len() - 1, (const wchar_t *)folder->Name); - p[--len] = WCHAR_PATH_SEPARATOR; - len -= folder->Name.Len(); - proxyIndex = folder->Parent; + const CProxyDir *dir = &_proxy->Dirs[proxyIndex]; + p--; + *p = WCHAR_PATH_SEPARATOR; + p -= dir->NameLen; + wmemcpy(p, dir->Name, dir->NameLen); + proxyIndex = dir->ParentDir; } } - prefix.ReleaseBuffer(totalLen); } -UString CAgentFolder::GetFullPathPrefixPlusPrefix(UInt32 index) const +UString CAgentFolder::GetFullPrefix(UInt32 index) const { - UString prefix; - GetPrefix(index, prefix); - if (_proxyArchive2) - return _proxyArchive2->GetFullPathPrefix(_proxyFolderItem) + prefix; + int foldIndex = _proxyDirIndex; + + if (_flatMode) + foldIndex = _items[index].DirIndex; + + if (_proxy2) + return _proxy2->Dirs[foldIndex].PathPrefix; else - return _proxyArchive->GetFullPathPrefix(_proxyFolderItem) + prefix; + return _proxy->GetDirPath_as_Prefix(foldIndex); } STDMETHODIMP_(UInt64) CAgentFolder::GetItemSize(UInt32 index) { unsigned arcIndex; - if (_proxyArchive2) + if (_proxy2) { - SET_realIndex_AND_folder_2 - arcIndex = folder->SubFiles[realIndex]; - const CProxyFile2 &item = _proxyArchive2->Files[arcIndex]; + SET_realIndex_AND_dir_2 + arcIndex = dir->Items[realIndex]; + const CProxyFile2 &item = _proxy2->Files[arcIndex]; if (item.IsDir()) { - const CProxyFolder2 &itemFolder = _proxyArchive2->Folders[item.FolderIndex]; + const CProxyDir2 &itemFolder = _proxy2->Dirs[item.DirIndex]; if (!_flatMode) return itemFolder.Size; } } else { - SET_realIndex_AND_folder - if (realIndex < (UInt32)folder->Folders.Size()) + SET_realIndex_AND_dir + if (realIndex < dir->SubDirs.Size()) { - const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]]; + const CProxyDir &item = _proxy->Dirs[dir->SubDirs[realIndex]]; if (!_flatMode) return item.Size; - if (!item.IsLeaf) + if (!item.IsLeaf()) return 0; - arcIndex = item.Index; + arcIndex = item.ArcIndex; } else { - const CProxyFile &item = folder->Files[realIndex - folder->Folders.Size()]; - arcIndex = item.Index; + arcIndex = dir->SubFiles[realIndex - dir->SubDirs.Size()]; } } NCOM::CPropVariant prop; @@ -227,11 +312,19 @@ STDMETHODIMP CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT prop = prefix; } } - else if (_proxyArchive2) + else if (_proxy2) { - SET_realIndex_AND_folder_2 - unsigned arcIndex = folder->SubFiles[realIndex]; - const CProxyFile2 &item = _proxyArchive2->Files[arcIndex]; + SET_realIndex_AND_dir_2 + unsigned arcIndex = dir->Items[realIndex]; + const CProxyFile2 &item = _proxy2->Files[arcIndex]; + /* + if (propID == kpidNumAltStreams) + { + if (item.AltDirIndex >= 0) + prop = _proxy2->Dirs[item.AltDirIndex].Items.Size(); + } + else + */ if (!item.IsDir()) { switch (propID) @@ -243,7 +336,7 @@ STDMETHODIMP CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT } else { - const CProxyFolder2 &itemFolder = _proxyArchive2->Folders[item.FolderIndex]; + const CProxyDir2 &itemFolder = _proxy2->Dirs[item.DirIndex]; if (!_flatMode && propID == kpidSize) prop = itemFolder.Size; else if (!_flatMode && propID == kpidPackSize) @@ -251,7 +344,7 @@ STDMETHODIMP CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT else switch (propID) { case kpidIsDir: prop = true; break; - case kpidNumSubDirs: prop = itemFolder.NumSubFolders; break; + case kpidNumSubDirs: prop = itemFolder.NumSubDirs; break; case kpidNumSubFiles: prop = itemFolder.NumSubFiles; break; case kpidName: prop = item.Name; break; case kpidCRC: @@ -274,10 +367,10 @@ STDMETHODIMP CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT } else { - SET_realIndex_AND_folder - if (realIndex < (UInt32)folder->Folders.Size()) + SET_realIndex_AND_dir + if (realIndex < dir->SubDirs.Size()) { - const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]]; + const CProxyDir &item = _proxy->Dirs[dir->SubDirs[realIndex]]; if (!_flatMode && propID == kpidSize) prop = item.Size; else if (!_flatMode && propID == kpidPackSize) @@ -286,33 +379,33 @@ STDMETHODIMP CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT switch (propID) { case kpidIsDir: prop = true; break; - case kpidNumSubDirs: prop = item.NumSubFolders; break; + case kpidNumSubDirs: prop = item.NumSubDirs; break; case kpidNumSubFiles: prop = item.NumSubFiles; break; case kpidName: prop = item.Name; break; case kpidCRC: { - if (item.IsLeaf) + if (item.IsLeaf()) { - RINOK(_agentSpec->GetArchive()->GetProperty(item.Index, propID, value)); + RINOK(_agentSpec->GetArchive()->GetProperty(item.ArcIndex, propID, value)); } if (item.CrcIsDefined && value->vt == VT_EMPTY) prop = item.Crc; break; } default: - if (item.IsLeaf) - return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value); + if (item.IsLeaf()) + return _agentSpec->GetArchive()->GetProperty(item.ArcIndex, propID, value); } } else { - const CProxyFile &item = folder->Files[realIndex - folder->Folders.Size()]; + unsigned arcIndex = dir->SubFiles[realIndex - dir->SubDirs.Size()]; switch (propID) { case kpidIsDir: prop = false; break; - case kpidName: prop = item.Name; break; + case kpidName: prop = _proxy->Files[arcIndex].Name; break; default: - return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value); + return _agentSpec->GetArchive()->GetProperty(arcIndex, propID, value); } } } @@ -334,30 +427,30 @@ static UInt64 GetUInt64Prop(IInArchive *archive, UInt32 index, PROPID propID) STDMETHODIMP CAgentFolder::GetItemName(UInt32 index, const wchar_t **name, unsigned *len) { - if (_proxyArchive2) + if (_proxy2) { - SET_realIndex_AND_folder_2 - unsigned arcIndex = folder->SubFiles[realIndex]; - const CProxyFile2 &item = _proxyArchive2->Files[arcIndex]; + SET_realIndex_AND_dir_2 + unsigned arcIndex = dir->Items[realIndex]; + const CProxyFile2 &item = _proxy2->Files[arcIndex]; *name = item.Name; - *len = item.NameSize; + *len = item.NameLen; return S_OK; } else { - SET_realIndex_AND_folder - if (realIndex < (UInt32)folder->Folders.Size()) + SET_realIndex_AND_dir + if (realIndex < dir->SubDirs.Size()) { - const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]]; + const CProxyDir &item = _proxy->Dirs[dir->SubDirs[realIndex]]; *name = item.Name; - *len = item.Name.Len(); + *len = item.NameLen; return S_OK; } else { - const CProxyFile &item = folder->Files[realIndex - folder->Folders.Size()]; + const CProxyFile &item = _proxy->Files[dir->SubFiles[realIndex - dir->SubDirs.Size()]]; *name = item.Name; - *len = item.Name.Len(); + *len = item.NameLen; return S_OK; } } @@ -369,26 +462,21 @@ STDMETHODIMP CAgentFolder::GetItemPrefix(UInt32 index, const wchar_t **name, uns *len = 0; if (!_flatMode) return S_OK; - if (_proxyArchive2) - { - SET_realIndex_AND_folder_2 - unsigned arcIndex = folder->SubFiles[realIndex]; - const CProxyFile2 &item = _proxyArchive2->Files[arcIndex]; - if (item.Parent >= 0) + if (_proxy2) + { + const CProxyItem &item = _items[index]; + const UString &s = _proxy2->Dirs[item.DirIndex].PathPrefix; + unsigned baseLen = _proxy2->Dirs[_proxyDirIndex].PathPrefix.Len(); + if (baseLen <= s.Len()) { - const CProxyFile2 &item2 = _proxyArchive2->Files[item.Parent]; - int foldInd = item2.GetFolderIndex(item.IsAltStream); - if (foldInd >= 0) - { - const UString &s = _proxyArchive2->Folders[foldInd].PathPrefix; - unsigned baseLen = _proxyArchive2->Folders[_proxyFolderItem].PathPrefix.Len(); - if (baseLen <= s.Len()) - { - *name = (const wchar_t *)s + baseLen; - *len = s.Len() - baseLen; - } - } + *name = (const wchar_t *)s + baseLen; + *len = s.Len() - baseLen; + } + else + { + return E_FAIL; + // throw 111l; } } return S_OK; @@ -437,21 +525,21 @@ static const wchar_t *GetExtension(const wchar_t *name) int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw) { - UInt32 realIndex1, realIndex2; - const CProxyFolder2 *folder1, *folder2; + unsigned realIndex1, realIndex2; + const CProxyDir2 *dir1, *dir2; if (_flatMode) { const CProxyItem &item1 = _items[index1]; const CProxyItem &item2 = _items[index2]; - folder1 = &_proxyArchive2->Folders[item1.ProxyFolderIndex]; - folder2 = &_proxyArchive2->Folders[item2.ProxyFolderIndex]; + dir1 = &_proxy2->Dirs[item1.DirIndex]; + dir2 = &_proxy2->Dirs[item2.DirIndex]; realIndex1 = item1.Index; realIndex2 = item2.Index; } else { - folder2 = folder1 = &_proxyArchive2->Folders[_proxyFolderItem]; + dir2 = dir1 = &_proxy2->Dirs[_proxyDirIndex]; realIndex1 = index1; realIndex2 = index2; } @@ -459,10 +547,10 @@ int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int UInt32 arcIndex1; UInt32 arcIndex2; bool isDir1, isDir2; - arcIndex1 = folder1->SubFiles[realIndex1]; - arcIndex2 = folder2->SubFiles[realIndex2]; - const CProxyFile2 &prox1 = _proxyArchive2->Files[arcIndex1]; - const CProxyFile2 &prox2 = _proxyArchive2->Files[arcIndex2]; + arcIndex1 = dir1->Items[realIndex1]; + arcIndex2 = dir2->Items[realIndex2]; + const CProxyFile2 &prox1 = _proxy2->Files[arcIndex1]; + const CProxyFile2 &prox2 = _proxy2->Files[arcIndex2]; if (propID == kpidName) { @@ -473,14 +561,9 @@ int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int { if (!_flatMode) return 0; - if (prox1.Parent < 0) return prox2.Parent < 0 ? 0 : -1; - if (prox2.Parent < 0) return 1; - - const CProxyFile2 &proxPar1 = _proxyArchive2->Files[prox1.Parent]; - const CProxyFile2 &proxPar2 = _proxyArchive2->Files[prox2.Parent]; return CompareFileNames_ForFolderList( - _proxyArchive2->Folders[proxPar1.GetFolderIndex(prox1.IsAltStream)].PathPrefix, - _proxyArchive2->Folders[proxPar2.GetFolderIndex(prox2.IsAltStream)].PathPrefix); + _proxy2->Dirs[_items[index1].DirIndex].PathPrefix, + _proxy2->Dirs[_items[index2].DirIndex].PathPrefix); } if (propID == kpidExtension) @@ -500,17 +583,17 @@ int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int return isDir1 ? -1 : 1; } - const CProxyFolder2 *proxFolder1 = NULL; - const CProxyFolder2 *proxFolder2 = NULL; - if (isDir1) proxFolder1 = &_proxyArchive2->Folders[prox1.FolderIndex]; - if (isDir2) proxFolder2 = &_proxyArchive2->Folders[prox2.FolderIndex]; + const CProxyDir2 *proxFolder1 = NULL; + const CProxyDir2 *proxFolder2 = NULL; + if (isDir1) proxFolder1 = &_proxy2->Dirs[prox1.DirIndex]; + if (isDir2) proxFolder2 = &_proxy2->Dirs[prox2.DirIndex]; if (propID == kpidNumSubDirs) { UInt32 n1 = 0; UInt32 n2 = 0; - if (isDir1) n1 = proxFolder1->NumSubFolders; - if (isDir2) n2 = proxFolder2->NumSubFolders; + if (isDir1) n1 = proxFolder1->NumSubDirs; + if (isDir2) n2 = proxFolder2->NumSubDirs; return MyCompare(n1, n2); } @@ -585,27 +668,29 @@ int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int STDMETHODIMP_(Int32) CAgentFolder::CompareItems(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw) { - COM_TRY_BEGIN - if (_proxyArchive2) + try { + if (_proxy2) return CompareItems2(index1, index2, propID, propIsRaw); - UInt32 realIndex1, realIndex2; - const CProxyFolder *folder1, *folder2; + unsigned realIndex1, realIndex2; + const CProxyDir *dir1, *dir2; + if (_flatMode) { const CProxyItem &item1 = _items[index1]; const CProxyItem &item2 = _items[index2]; - folder1 = &_proxyArchive->Folders[item1.ProxyFolderIndex]; - folder2 = &_proxyArchive->Folders[item2.ProxyFolderIndex]; + dir1 = &_proxy->Dirs[item1.DirIndex]; + dir2 = &_proxy->Dirs[item2.DirIndex]; realIndex1 = item1.Index; realIndex2 = item2.Index; } else { - folder2 = folder1 = &_proxyArchive->Folders[_proxyFolderItem]; + dir2 = dir1 = &_proxy->Dirs[_proxyDirIndex]; realIndex1 = index1; realIndex2 = index2; } + if (propID == kpidPrefix) { if (!_flatMode) @@ -615,109 +700,116 @@ STDMETHODIMP_(Int32) CAgentFolder::CompareItems(UInt32 index1, UInt32 index2, PR GetPrefix(index2, prefix2); return CompareFileNames_ForFolderList(prefix1, prefix2); } - const CProxyFile *prox1; - const CProxyFile *prox2; - const CProxyFolder *proxFolder1 = NULL; - const CProxyFolder *proxFolder2 = NULL; - bool isDir1, isDir2; - if (realIndex1 < (UInt32)folder1->Folders.Size()) + + UInt32 arcIndex1; + UInt32 arcIndex2; + + const CProxyDir *proxFolder1 = NULL; + const CProxyDir *proxFolder2 = NULL; + + if (realIndex1 < dir1->SubDirs.Size()) { - isDir1 = true; - prox1 = proxFolder1 = &_proxyArchive->Folders[folder1->Folders[realIndex1]]; + proxFolder1 = &_proxy->Dirs[dir1->SubDirs[realIndex1]]; + arcIndex1 = proxFolder1->ArcIndex; } else - { - isDir1 = false; - prox1 = &folder1->Files[realIndex1 - folder1->Folders.Size()]; - } + arcIndex1 = dir1->SubFiles[realIndex1 - dir1->SubDirs.Size()]; - if (realIndex2 < (UInt32)folder2->Folders.Size()) + if (realIndex2 < dir2->SubDirs.Size()) { - isDir2 = true; - prox2 = proxFolder2 = &_proxyArchive->Folders[folder2->Folders[realIndex2]]; + proxFolder2 = &_proxy->Dirs[dir2->SubDirs[realIndex2]]; + arcIndex2 = proxFolder2->ArcIndex; } else - { - isDir2 = false; - prox2 = &folder2->Files[realIndex2 - folder2->Folders.Size()]; - } + arcIndex2 = dir2->SubFiles[realIndex2 - dir2->SubDirs.Size()]; if (propID == kpidName) - { - return CompareFileNames_ForFolderList(prox1->Name, prox2->Name); - } + return CompareFileNames_ForFolderList( + proxFolder1 ? proxFolder1->Name : _proxy->Files[arcIndex1].Name, + proxFolder2 ? proxFolder2->Name : _proxy->Files[arcIndex2].Name); + if (propID == kpidExtension) - { - return CompareFileNames_ForFolderList( - GetExtension(prox1->Name), - GetExtension(prox2->Name)); - } + return CompareFileNames_ForFolderList( + GetExtension(proxFolder1 ? proxFolder1->Name : _proxy->Files[arcIndex1].Name), + GetExtension(proxFolder2 ? proxFolder2->Name : _proxy->Files[arcIndex2].Name)); if (propID == kpidIsDir) { - if (isDir1 == isDir2) - return 0; - return isDir1 ? -1 : 1; + if (proxFolder1) + return proxFolder2 ? 0 : -1; + return proxFolder2 ? 1 : 0; } + if (propID == kpidNumSubDirs) { UInt32 n1 = 0; UInt32 n2 = 0; - if (isDir1) n1 = proxFolder1->NumSubFolders; - if (isDir2) n2 = proxFolder2->NumSubFolders; + if (proxFolder1) n1 = proxFolder1->NumSubDirs; + if (proxFolder2) n2 = proxFolder2->NumSubDirs; return MyCompare(n1, n2); } + if (propID == kpidNumSubFiles) { UInt32 n1 = 0; UInt32 n2 = 0; - if (isDir1) n1 = proxFolder1->NumSubFiles; - if (isDir2) n2 = proxFolder2->NumSubFiles; + if (proxFolder1) n1 = proxFolder1->NumSubFiles; + if (proxFolder2) n2 = proxFolder2->NumSubFiles; return MyCompare(n1, n2); } + if (propID == kpidSize) { UInt64 n1, n2; - if (isDir1) + if (proxFolder1) n1 = _flatMode ? 0 : proxFolder1->Size; else - n1 = GetUInt64Prop(_agentSpec->GetArchive(), prox1->Index, kpidSize); - if (isDir2) + n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidSize); + if (proxFolder2) n2 = _flatMode ? 0 : proxFolder2->Size; else - n2 = GetUInt64Prop(_agentSpec->GetArchive(), prox2->Index, kpidSize); + n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidSize); return MyCompare(n1, n2); } + if (propID == kpidPackSize) { UInt64 n1, n2; - if (isDir1) + if (proxFolder1) n1 = _flatMode ? 0 : proxFolder1->PackSize; else - n1 = GetUInt64Prop(_agentSpec->GetArchive(), prox1->Index, kpidPackSize); - if (isDir2) + n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidPackSize); + if (proxFolder2) n2 = _flatMode ? 0 : proxFolder2->PackSize; else - n2 = GetUInt64Prop(_agentSpec->GetArchive(), prox2->Index, kpidPackSize); + n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidPackSize); return MyCompare(n1, n2); } if (propID == kpidCRC) { UInt64 n1, n2; - if (!isDir1 || proxFolder1->IsLeaf) - n1 = GetUInt64Prop(_agentSpec->GetArchive(), prox1->Index, kpidCRC); - else + if (proxFolder1 && !proxFolder1->IsLeaf()) n1 = proxFolder1->Crc; - if (!isDir2 || proxFolder2->IsLeaf) - n2 = GetUInt64Prop(_agentSpec->GetArchive(), prox2->Index, kpidCRC); else + n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidCRC); + if (proxFolder2 && !proxFolder2->IsLeaf()) n2 = proxFolder2->Crc; + else + n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidCRC); return MyCompare(n1, n2); } if (propIsRaw) - return CompareRawProps(_agentSpec->_archiveLink.GetArchiveGetRawProps(), prox1->Index, prox2->Index, propID); + { + bool isVirt1 = (proxFolder1 && !proxFolder1->IsLeaf()); + bool isVirt2 = (proxFolder2 && !proxFolder2->IsLeaf()); + if (isVirt1) + return isVirt2 ? 0 : -1; + if (isVirt2) + return 1; + return CompareRawProps(_agentSpec->_archiveLink.GetArchiveGetRawProps(), arcIndex1, arcIndex2, propID); + } NCOM::CPropVariant prop1, prop2; // Name must be first property @@ -733,21 +825,20 @@ STDMETHODIMP_(Int32) CAgentFolder::CompareItems(UInt32 index1, UInt32 index2, PR } return prop1.Compare(prop2); - COM_TRY_END + } catch(...) { return 0; } } -HRESULT CAgentFolder::BindToFolder_Internal(unsigned proxyFolderIndex, IFolderFolder **resultFolder) +HRESULT CAgentFolder::BindToFolder_Internal(unsigned proxyDirIndex, IFolderFolder **resultFolder) { + /* CMyComPtr<IFolderFolder> parentFolder; - if (_proxyArchive2) + if (_proxy2) { - parentFolder = NULL; // Change it; - const CProxyFolder2 &folder = _proxyArchive2->Folders[proxyFolderIndex]; - int par = _proxyArchive2->GetParentFolderOfFile(folder.ArcIndex); - if (par != (int)_proxyFolderItem) + const CProxyDir2 &dir = _proxy2->Dirs[proxyDirIndex]; + int par = _proxy2->GetParentFolderOfFile(dir.ArcIndex); + if (par != (int)_proxyDirIndex) { - // return E_FAIL; RINOK(BindToFolder_Internal(par, &parentFolder)); } else @@ -755,17 +846,18 @@ HRESULT CAgentFolder::BindToFolder_Internal(unsigned proxyFolderIndex, IFolderFo } else { - const CProxyFolder &folder = _proxyArchive->Folders[proxyFolderIndex]; - if (folder.Parent != (int)_proxyFolderItem) + const CProxyDir &dir = _proxy->Dirs[proxyDirIndex]; + if (dir.Parent != (int)_proxyDirIndex) { - RINOK(BindToFolder_Internal(folder.Parent, &parentFolder)); + RINOK(BindToFolder_Internal(dir.Parent, &parentFolder)); } else parentFolder = this; } + */ CAgentFolder *folderSpec = new CAgentFolder; CMyComPtr<IFolderFolder> agentFolder = folderSpec; - folderSpec->Init(_proxyArchive, _proxyArchive2, proxyFolderIndex, parentFolder, _agentSpec); + folderSpec->Init(_proxy, _proxy2, proxyDirIndex, /* parentFolder, */ _agentSpec); *resultFolder = agentFolder.Detach(); return S_OK; } @@ -773,51 +865,229 @@ HRESULT CAgentFolder::BindToFolder_Internal(unsigned proxyFolderIndex, IFolderFo STDMETHODIMP CAgentFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder) { COM_TRY_BEGIN - if (_proxyArchive2) + if (_proxy2) { - SET_realIndex_AND_folder_2 - unsigned arcIndex = folder->SubFiles[realIndex]; - const CProxyFile2 &item = _proxyArchive2->Files[arcIndex]; + SET_realIndex_AND_dir_2 + unsigned arcIndex = dir->Items[realIndex]; + const CProxyFile2 &item = _proxy2->Files[arcIndex]; if (!item.IsDir()) return E_INVALIDARG; - return BindToFolder_Internal(item.FolderIndex, resultFolder); + return BindToFolder_Internal(item.DirIndex, resultFolder); } - SET_realIndex_AND_folder - if (realIndex >= (UInt32)folder->Folders.Size()) + SET_realIndex_AND_dir + if (realIndex >= (UInt32)dir->SubDirs.Size()) return E_INVALIDARG; - return BindToFolder_Internal(folder->Folders[realIndex], resultFolder); + return BindToFolder_Internal(dir->SubDirs[realIndex], resultFolder); COM_TRY_END } STDMETHODIMP CAgentFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder) { COM_TRY_BEGIN - if (_proxyArchive2) + if (_proxy2) { - const CProxyFolder2 &folder = _proxyArchive2->Folders[_proxyFolderItem]; - FOR_VECTOR (i, folder.SubFiles) - { - const CProxyFile2 &file = _proxyArchive2->Files[folder.SubFiles[i]]; - if (file.FolderIndex >= 0) - if (StringsAreEqualNoCase(file.Name, name)) - return BindToFolder_Internal(file.FolderIndex, resultFolder); - } - return E_INVALIDARG; + int index = _proxy2->FindItem(_proxyDirIndex, name, true); + if (index < 0) + return E_INVALIDARG; + return BindToFolder_Internal(_proxy2->Files[_proxy2->Dirs[_proxyDirIndex].Items[index]].DirIndex, resultFolder); } - int index = _proxyArchive->FindDirSubItemIndex(_proxyFolderItem, name); + int index = _proxy->FindSubDir(_proxyDirIndex, name); if (index < 0) return E_INVALIDARG; return BindToFolder_Internal(index, resultFolder); COM_TRY_END } + + +// ---------- IFolderAltStreams ---------- + +HRESULT CAgentFolder::BindToAltStreams_Internal(unsigned proxyDirIndex, IFolderFolder **resultFolder) +{ + *resultFolder = NULL; + if (!_proxy2) + return S_OK; + + /* + CMyComPtr<IFolderFolder> parentFolder; + + int par = _proxy2->GetParentFolderOfFile(_proxy2->Dirs[proxyDirIndex].ArcIndex); + if (par != (int)_proxyDirIndex) + { + RINOK(BindToFolder_Internal(par, &parentFolder)); + if (!parentFolder) + return S_OK; + } + else + parentFolder = this; + */ + + CAgentFolder *folderSpec = new CAgentFolder; + CMyComPtr<IFolderFolder> agentFolder = folderSpec; + folderSpec->Init(_proxy, _proxy2, proxyDirIndex, /* parentFolder, */ _agentSpec); + *resultFolder = agentFolder.Detach(); + return S_OK; +} + +STDMETHODIMP CAgentFolder::BindToAltStreams(UInt32 index, IFolderFolder **resultFolder) +{ + COM_TRY_BEGIN + + *resultFolder = NULL; + + if (!_proxy2) + return S_OK; + + if (_proxy2->IsAltDir(_proxyDirIndex)) + return S_OK; + + { + if (index == (UInt32)(Int32)-1) + { + unsigned altDirIndex; + // IFolderFolder *parentFolder; + + if (_proxyDirIndex == k_Proxy2_RootDirIndex) + { + altDirIndex = k_Proxy2_AltRootDirIndex; + // parentFolder = this; // we want to use Root dir as parent for alt root + } + else + { + unsigned arcIndex = _proxy2->Dirs[_proxyDirIndex].ArcIndex; + const CProxyFile2 &item = _proxy2->Files[arcIndex]; + if (item.AltDirIndex < 0) + return S_OK; + altDirIndex = item.AltDirIndex; + // parentFolder = _parentFolder; + } + + CAgentFolder *folderSpec = new CAgentFolder; + CMyComPtr<IFolderFolder> agentFolder = folderSpec; + folderSpec->Init(_proxy, _proxy2, altDirIndex, /* parentFolder, */ _agentSpec); + *resultFolder = agentFolder.Detach(); + return S_OK; + } + + SET_realIndex_AND_dir_2 + unsigned arcIndex = dir->Items[realIndex]; + const CProxyFile2 &item = _proxy2->Files[arcIndex]; + if (item.AltDirIndex < 0) + return S_OK; + return BindToAltStreams_Internal(item.AltDirIndex, resultFolder); + } + + COM_TRY_END +} + +STDMETHODIMP CAgentFolder::BindToAltStreams(const wchar_t *name, IFolderFolder **resultFolder) +{ + COM_TRY_BEGIN + + *resultFolder = NULL; + + if (!_proxy2) + return S_OK; + + if (_proxy2->IsAltDir(_proxyDirIndex)) + return S_OK; + + if (name[0] == 0) + return BindToAltStreams((UInt32)(Int32)-1, resultFolder); + + { + const CProxyDir2 &dir = _proxy2->Dirs[_proxyDirIndex]; + FOR_VECTOR (i, dir.Items) + { + const CProxyFile2 &file = _proxy2->Files[dir.Items[i]]; + if (file.AltDirIndex >= 0) + if (CompareFileNames(file.Name, name) == 0) + return BindToAltStreams_Internal(file.AltDirIndex, resultFolder); + } + return E_INVALIDARG; + } + COM_TRY_END +} + +STDMETHODIMP CAgentFolder::AreAltStreamsSupported(UInt32 index, Int32 *isSupported) +{ + *isSupported = BoolToInt(false); + + if (!_proxy2) + return S_OK; + + if (_proxy2->IsAltDir(_proxyDirIndex)) + return S_OK; + + unsigned arcIndex; + + if (index == (UInt32)(Int32)-1) + { + if (_proxyDirIndex == k_Proxy2_RootDirIndex) + { + *isSupported = BoolToInt(true); + return S_OK; + } + arcIndex = _proxy2->Dirs[_proxyDirIndex].ArcIndex; + } + else + { + SET_realIndex_AND_dir_2 + arcIndex = dir->Items[realIndex]; + } + + if (_proxy2->Files[arcIndex].AltDirIndex >= 0) + *isSupported = BoolToInt(true); + return S_OK; +} + + STDMETHODIMP CAgentFolder::BindToParentFolder(IFolderFolder **resultFolder) { - // COM_TRY_BEGIN + COM_TRY_BEGIN + /* CMyComPtr<IFolderFolder> parentFolder = _parentFolder; *resultFolder = parentFolder.Detach(); + */ + *resultFolder = NULL; + + unsigned proxyDirIndex; + + if (_proxy2) + { + if (_proxyDirIndex == k_Proxy2_RootDirIndex) + return S_OK; + if (_proxyDirIndex == k_Proxy2_AltRootDirIndex) + proxyDirIndex = k_Proxy2_RootDirIndex; + else + { + const CProxyDir2 &fold = _proxy2->Dirs[_proxyDirIndex]; + const CProxyFile2 &file = _proxy2->Files[fold.ArcIndex]; + int parentIndex = file.Parent; + if (parentIndex < 0) + proxyDirIndex = k_Proxy2_RootDirIndex; + else + { + const CProxyFile2 &file = _proxy2->Files[parentIndex]; + proxyDirIndex = file.DirIndex; + } + } + } + else + { + int parent = _proxy->Dirs[_proxyDirIndex].ParentDir; + if (parent < 0) + return S_OK; + proxyDirIndex = parent; + } + + CAgentFolder *folderSpec = new CAgentFolder; + CMyComPtr<IFolderFolder> agentFolder = folderSpec; + folderSpec->Init(_proxy, _proxy2, proxyDirIndex, /* parentFolder, */ _agentSpec); + *resultFolder = agentFolder.Detach(); + return S_OK; - // COM_TRY_END + COM_TRY_END } STDMETHODIMP CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream) @@ -827,33 +1097,37 @@ STDMETHODIMP CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream) if (!getStream) return S_OK; - UInt32 indexInArchive; - if (_proxyArchive2) + UInt32 arcIndex; + if (_proxy2) { - SET_realIndex_AND_folder_2 - indexInArchive = folder->SubFiles[realIndex]; + SET_realIndex_AND_dir_2 + arcIndex = dir->Items[realIndex]; } else { - SET_realIndex_AND_folder + SET_realIndex_AND_dir - if (realIndex < (UInt32)folder->Folders.Size()) - { - const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]]; - if (!item.IsLeaf) - return S_OK; - indexInArchive = item.Index; - } - else - indexInArchive = folder->Files[realIndex - folder->Folders.Size()].Index; + if (realIndex < dir->SubDirs.Size()) + { + const CProxyDir &item = _proxy->Dirs[dir->SubDirs[realIndex]]; + if (!item.IsLeaf()) + return S_OK; + arcIndex = item.ArcIndex; + } + else + arcIndex = dir->SubFiles[realIndex - dir->SubDirs.Size()]; } - return getStream->GetStream(indexInArchive, stream); + return getStream->GetStream(arcIndex, stream); } +// static const unsigned k_FirstOptionalProp = 2; + static const PROPID kProps[] = { kpidNumSubDirs, kpidNumSubFiles, + + // kpidNumAltStreams, kpidPrefix }; @@ -872,9 +1146,13 @@ STDMETHODIMP CAgentFolder::GetNumberOfProperties(UInt32 *numProps) if (!_flatMode) (*numProps)--; /* - bool thereIsPathProp = _proxyArchive2 ? - _agentSpec->_proxyArchive2->ThereIsPathProp : - _agentSpec->_proxyArchive->ThereIsPathProp; + if (!_agentSpec->ThereIsAltStreamProp) + (*numProps)--; + */ + /* + bool thereIsPathProp = _proxy2 ? + _agentSpec->_proxy2->ThereIsPathProp : + _agentSpec->_proxy->ThereIsPathProp; */ // if there is kpidPath, we change kpidPath to kpidName @@ -892,9 +1170,9 @@ STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *pro _agentSpec->GetArchive()->GetNumberOfProperties(&numProps); /* - bool thereIsPathProp = _proxyArchive2 ? - _agentSpec->_proxyArchive2->ThereIsPathProp : - _agentSpec->_proxyArchive->ThereIsPathProp; + bool thereIsPathProp = _proxy2 ? + _agentSpec->_proxy2->ThereIsPathProp : + _agentSpec->_proxy->ThereIsPathProp; */ if (!_agentSpec->ThereIsPathProp) @@ -917,7 +1195,15 @@ STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *pro } else { - *propID = kProps[index - numProps]; + index -= numProps; + /* + if (index >= k_FirstOptionalProp) + { + if (!_agentSpec->ThereIsAltStreamProp) + index++; + } + */ + *propID = kProps[index]; *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID]; *name = 0; } @@ -940,44 +1226,47 @@ STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) NWindows::NCOM::CPropVariant prop; - if (_proxyArchive2) + if (propID == kpidReadOnly) + prop = _agentSpec->IsThereReadOnlyArc(); + else if (_proxy2) { - const CProxyFolder2 &folder = _proxyArchive2->Folders[_proxyFolderItem]; + const CProxyDir2 &dir = _proxy2->Dirs[_proxyDirIndex]; if (propID == kpidName) { - if (folder.ArcIndex >= 0) - prop = _proxyArchive2->Files[folder.ArcIndex].Name; + if (dir.ArcIndex >= 0) + prop = _proxy2->Files[dir.ArcIndex].Name; } else if (propID == kpidPath) { - prop = _proxyArchive2->GetFullPathPrefix(_proxyFolderItem); + bool isAltStreamFolder = false; + prop = _proxy2->GetDirPath_as_Prefix(_proxyDirIndex, isAltStreamFolder); } else switch (propID) { - case kpidSize: prop = folder.Size; break; - case kpidPackSize: prop = folder.PackSize; break; - case kpidNumSubDirs: prop = folder.NumSubFolders; break; - case kpidNumSubFiles: prop = folder.NumSubFiles; break; - // case kpidName: prop = folder.Name; break; - // case kpidPath: prop = _proxyArchive2->GetFullPathPrefix(_proxyFolderItem); break; + case kpidSize: prop = dir.Size; break; + case kpidPackSize: prop = dir.PackSize; break; + case kpidNumSubDirs: prop = dir.NumSubDirs; break; + case kpidNumSubFiles: prop = dir.NumSubFiles; break; + // case kpidName: prop = dir.Name; break; + // case kpidPath: prop = _proxy2->GetFullPathPrefix(_proxyDirIndex); break; case kpidType: prop = UString(L"7-Zip.") + _agentSpec->ArchiveType; break; - case kpidCRC: if (folder.CrcIsDefined) prop = folder.Crc; break; + case kpidCRC: if (dir.CrcIsDefined) prop = dir.Crc; break; } } else { - const CProxyFolder &folder = _proxyArchive->Folders[_proxyFolderItem]; + const CProxyDir &dir = _proxy->Dirs[_proxyDirIndex]; switch (propID) { - case kpidSize: prop = folder.Size; break; - case kpidPackSize: prop = folder.PackSize; break; - case kpidNumSubDirs: prop = folder.NumSubFolders; break; - case kpidNumSubFiles: prop = folder.NumSubFiles; break; - case kpidName: prop = folder.Name; break; - case kpidPath: prop = _proxyArchive->GetFullPathPrefix(_proxyFolderItem); break; + case kpidSize: prop = dir.Size; break; + case kpidPackSize: prop = dir.PackSize; break; + case kpidNumSubDirs: prop = dir.NumSubDirs; break; + case kpidNumSubFiles: prop = dir.NumSubFiles; break; + case kpidName: prop = dir.Name; break; + case kpidPath: prop = _proxy->GetDirPath_as_Prefix(_proxyDirIndex); break; case kpidType: prop = UString(L"7-Zip.") + _agentSpec->ArchiveType; break; - case kpidCRC: if (folder.CrcIsDefined) prop = folder.Crc; break; + case kpidCRC: if (dir.CrcIsDefined) prop = dir.Crc; break; } } prop.Detach(value); @@ -1022,31 +1311,28 @@ STDMETHODIMP CAgentFolder::GetRawProp(UInt32 index, PROPID propID, const void ** if (rawProps) { unsigned arcIndex; - if (_proxyArchive2) + if (_proxy2) { - SET_realIndex_AND_folder_2 - arcIndex = folder->SubFiles[realIndex]; + SET_realIndex_AND_dir_2 + arcIndex = dir->Items[realIndex]; } else { - SET_realIndex_AND_folder - if (realIndex < (UInt32)folder->Folders.Size()) + SET_realIndex_AND_dir + if (realIndex < dir->SubDirs.Size()) { - const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]]; - if (!item.IsLeaf) + const CProxyDir &item = _proxy->Dirs[dir->SubDirs[realIndex]]; + if (!item.IsLeaf()) { *data = NULL; *dataSize = 0; *propType = 0; return S_OK; } - arcIndex = item.Index; + arcIndex = item.ArcIndex; } else - { - const CProxyFile &item = folder->Files[realIndex - folder->Folders.Size()]; - arcIndex = item.Index; - } + arcIndex = dir->SubFiles[realIndex - dir->SubDirs.Size()]; } return rawProps->GetRawProp(arcIndex, propID, data, dataSize, propType); } @@ -1077,30 +1363,30 @@ int CAgentFolder::GetRealIndex(unsigned index) const { if (!_flatMode) { - if (_proxyArchive2) - return _proxyArchive2->GetRealIndex(_proxyFolderItem, index); + if (_proxy2) + return _proxy2->GetRealIndex(_proxyDirIndex, index); else - return _proxyArchive->GetRealIndex(_proxyFolderItem, index); + return _proxy->GetRealIndex(_proxyDirIndex, index); } { const CProxyItem &item = _items[index]; - if (_proxyArchive2) + if (_proxy2) { - const CProxyFolder2 *folder = &_proxyArchive2->Folders[item.ProxyFolderIndex]; - return folder->SubFiles[item.Index]; + const CProxyDir2 *dir = &_proxy2->Dirs[item.DirIndex]; + return dir->Items[item.Index]; } else { - const CProxyFolder *folder = &_proxyArchive->Folders[item.ProxyFolderIndex]; + const CProxyDir *dir = &_proxy->Dirs[item.DirIndex]; unsigned realIndex = item.Index; - if (realIndex < folder->Folders.Size()) + if (realIndex < dir->SubDirs.Size()) { - const CProxyFolder &f = _proxyArchive->Folders[folder->Folders[realIndex]]; - if (!f.IsLeaf) + const CProxyDir &f = _proxy->Dirs[dir->SubDirs[realIndex]]; + if (!f.IsLeaf()) return -1; - return f.Index; + return f.ArcIndex; } - return folder->Files[realIndex - folder->Folders.Size()].Index; + return dir->SubFiles[realIndex - dir->SubDirs.Size()]; } } } @@ -1109,43 +1395,46 @@ void CAgentFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, bool i { if (!_flatMode) { - if (_proxyArchive2) - _proxyArchive2->GetRealIndices(_proxyFolderItem, indices, numItems, includeAltStreams, realIndices); + if (_proxy2) + _proxy2->GetRealIndices(_proxyDirIndex, indices, numItems, includeAltStreams, realIndices); else - _proxyArchive->GetRealIndices(_proxyFolderItem, indices, numItems, realIndices); + _proxy->GetRealIndices(_proxyDirIndex, indices, numItems, realIndices); return; } + realIndices.Clear(); + for (UInt32 i = 0; i < numItems; i++) { const CProxyItem &item = _items[indices[i]]; - if (_proxyArchive2) + if (_proxy2) { - const CProxyFolder2 *folder = &_proxyArchive2->Folders[item.ProxyFolderIndex]; - _proxyArchive2->AddRealIndices_of_ArcItem(folder->SubFiles[item.Index], includeAltStreams, realIndices); + const CProxyDir2 *dir = &_proxy2->Dirs[item.DirIndex]; + _proxy2->AddRealIndices_of_ArcItem(dir->Items[item.Index], includeAltStreams, realIndices); continue; } UInt32 arcIndex; { - const CProxyFolder *folder = &_proxyArchive->Folders[item.ProxyFolderIndex]; + const CProxyDir *dir = &_proxy->Dirs[item.DirIndex]; unsigned realIndex = item.Index; - if (realIndex < folder->Folders.Size()) + if (realIndex < dir->SubDirs.Size()) { if (includeFolderSubItemsInFlatMode) { - _proxyArchive->AddRealIndices(folder->Folders[realIndex], realIndices); + _proxy->AddRealIndices(dir->SubDirs[realIndex], realIndices); continue; } - const CProxyFolder &f = _proxyArchive->Folders[folder->Folders[realIndex]]; - if (!f.IsLeaf) + const CProxyDir &f = _proxy->Dirs[dir->SubDirs[realIndex]]; + if (!f.IsLeaf()) continue; - arcIndex = f.Index; + arcIndex = f.ArcIndex; } else - arcIndex = folder->Files[realIndex - folder->Folders.Size()].Index; + arcIndex = dir->SubFiles[realIndex - dir->SubDirs.Size()]; } realIndices.Add(arcIndex); } + HeapSort(&realIndices.Front(), realIndices.Size()); } @@ -1163,10 +1452,11 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; UStringVector pathParts; - if (_proxyArchive2) - _proxyArchive2->GetPathParts(_proxyFolderItem, pathParts); + bool isAltStreamFolder = false; + if (_proxy2) + _proxy2->GetDirPathParts(_proxyDirIndex, pathParts, isAltStreamFolder); else - _proxyArchive->GetPathParts(_proxyFolderItem, pathParts); + _proxy->GetDirPathParts(_proxyDirIndex, pathParts); /* if (_flatMode) @@ -1177,7 +1467,14 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, FString pathU; if (path) + { pathU = us2fs(path); + if (!pathU.IsEmpty()) + { + NFile::NName::NormalizeDirPathPrefix(pathU); + NFile::NDir::CreateComplexDir(pathU); + } + } CExtractNtOptions extractNtOptions; extractNtOptions.AltStreams.Val = IntToBool(includeAltStreams); // change it!!! @@ -1191,12 +1488,12 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, extractCallback2, false, // stdOutMode IntToBool(testMode), - path ? pathU : FTEXT(""), - pathParts, + pathU, + pathParts, isAltStreamFolder, (UInt64)(Int64)-1); - if (_proxyArchive2) - extractCallbackSpec->SetBaseParentFolderIndex(_proxyArchive2->Folders[_proxyFolderItem].ArcIndex); + if (_proxy2) + extractCallbackSpec->SetBaseParentFolderIndex(_proxy2->Dirs[_proxyDirIndex].ArcIndex); CUIntVector realIndices; GetRealIndices(indices, numItems, IntToBool(includeAltStreams), @@ -1224,19 +1521,19 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, // CAgent CAgent::CAgent(): - _proxyArchive(NULL), - _proxyArchive2(NULL), - _isDeviceFile(false), - _codecs(0) + _proxy(NULL), + _proxy2(NULL), + _isDeviceFile(false), + _updatePathPrefix_is_AltFolder(false) { } CAgent::~CAgent() { - if (_proxyArchive) - delete _proxyArchive; - if (_proxyArchive2) - delete _proxyArchive2; + if (_proxy) + delete _proxy; + if (_proxy2) + delete _proxy2; } bool CAgent::CanUpdate() const @@ -1274,13 +1571,10 @@ STDMETHODIMP CAgent::Open( } CArcInfoEx archiverInfo0, archiverInfo1; - _compressCodecsInfo.Release(); - _codecs = new CCodecs; - _compressCodecsInfo = _codecs; - RINOK(_codecs->Load()); + RINOK(LoadGlobalCodecs()); CObjectVector<COpenType> types; - if (!ParseOpenTypes(*_codecs, arcFormat, types)) + if (!ParseOpenTypes(*g_CodecsObj, arcFormat, types)) return S_FALSE; /* @@ -1296,7 +1590,7 @@ STDMETHODIMP CAgent::Open( COpenOptions options; options.props = NULL; - options.codecs = _codecs; + options.codecs = g_CodecsObj; options.types = &types; CIntVector exl; options.excludedFormats = &exl; @@ -1326,15 +1620,15 @@ STDMETHODIMP CAgent::Open( STDMETHODIMP CAgent::ReOpen(IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN - if (_proxyArchive2) + if (_proxy2) { - delete _proxyArchive2; - _proxyArchive2 = NULL; + delete _proxy2; + _proxy2 = NULL; } - if (_proxyArchive) + if (_proxy) { - delete _proxyArchive; - _proxyArchive = NULL; + delete _proxy; + _proxy = NULL; } CObjectVector<COpenType> incl; @@ -1342,7 +1636,7 @@ STDMETHODIMP CAgent::ReOpen(IArchiveOpenCallback *openArchiveCallback) COpenOptions options; options.props = NULL; - options.codecs = _codecs; + options.codecs = g_CodecsObj; options.types = &incl; options.excludedFormats = &exl; options.stdInMode = false; @@ -1370,20 +1664,22 @@ STDMETHODIMP CAgent::EnumProperties(IEnumSTATPROPSTG **EnumProperties) HRESULT CAgent::ReadItems() { - if (_proxyArchive || _proxyArchive2) + if (_proxy || _proxy2) return S_OK; const CArc &arc = GetArc(); bool useProxy2 = (arc.GetRawProps && arc.IsTree); + // useProxy2 = false; if (useProxy2) - _proxyArchive2 = new CProxyArchive2(); + _proxy2 = new CProxyArc2(); else - _proxyArchive = new CProxyArchive(); + _proxy = new CProxyArc(); { ThereIsPathProp = false; + // ThereIsAltStreamProp = false; UInt32 numProps; arc.Archive->GetNumberOfProperties(&numProps); for (UInt32 i = 0; i < numProps; i++) @@ -1393,16 +1689,17 @@ HRESULT CAgent::ReadItems() VARTYPE varType; RINOK(arc.Archive->GetPropertyInfo(i, &name, &propID, &varType)); if (propID == kpidPath) - { ThereIsPathProp = true; - break; - } + /* + if (propID == kpidIsAltStream) + ThereIsAltStreamProp = true; + */ } } - if (_proxyArchive2) - return _proxyArchive2->Load(GetArc(), NULL); - return _proxyArchive->Load(GetArc(), NULL); + if (_proxy2) + return _proxy2->Load(GetArc(), NULL); + return _proxy->Load(GetArc(), NULL); } STDMETHODIMP CAgent::BindToRootFolder(IFolderFolder **resultFolder) @@ -1411,7 +1708,7 @@ STDMETHODIMP CAgent::BindToRootFolder(IFolderFolder **resultFolder) RINOK(ReadItems()); CAgentFolder *folderSpec = new CAgentFolder; CMyComPtr<IFolderFolder> rootFolder = folderSpec; - folderSpec->Init(_proxyArchive, _proxyArchive2, 0, NULL, this); + folderSpec->Init(_proxy, _proxy2, k_Proxy_RootDirIndex, /* NULL, */ this); *resultFolder = rootFolder.Detach(); return S_OK; COM_TRY_END @@ -1441,7 +1738,7 @@ STDMETHODIMP CAgent::Extract( false, // stdOutMode IntToBool(testMode), us2fs(path), - UStringVector(), + UStringVector(), false, (UInt64)(Int64)-1); #ifdef SUPPORT_LINKS @@ -1497,7 +1794,7 @@ STDMETHODIMP CAgent::GetArcProp(UInt32 level, PROPID propID, PROPVARIANT *value) break; case kpidErrorType: if (_archiveLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) - prop = _codecs->Formats[_archiveLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name; + prop = g_CodecsObj->Formats[_archiveLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name; break; } } @@ -1508,7 +1805,7 @@ STDMETHODIMP CAgent::GetArcProp(UInt32 level, PROPID propID, PROPVARIANT *value) { case kpidType: prop = GetTypeOfArc(arc); break; case kpidPath: prop = arc.Path; break; - case kpidErrorType: if (arc.ErrorInfo.ErrorFormatIndex >= 0) prop = _codecs->Formats[arc.ErrorInfo.ErrorFormatIndex].Name; break; + case kpidErrorType: if (arc.ErrorInfo.ErrorFormatIndex >= 0) prop = g_CodecsObj->Formats[arc.ErrorInfo.ErrorFormatIndex].Name; break; case kpidErrorFlags: { UInt32 flags = arc.ErrorInfo.GetErrorFlags(); diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h index e06f8576..2c505b84 100644 --- a/CPP/7zip/UI/Agent/Agent.h +++ b/CPP/7zip/UI/Agent/Agent.h @@ -18,6 +18,10 @@ #include "AgentProxy.h" #include "IFolderArchive.h" +extern CCodecs *g_CodecsObj; +HRESULT LoadGlobalCodecs(); +void FreeGlobalCodecs(); + class CAgentFolder; DECL_INTERFACE(IArchiveFolderInternal, 0x01, 0xC) @@ -27,7 +31,7 @@ DECL_INTERFACE(IArchiveFolderInternal, 0x01, 0xC) struct CProxyItem { - unsigned ProxyFolderIndex; + unsigned DirIndex; unsigned Index; }; @@ -44,6 +48,7 @@ enum AGENT_OP class CAgentFolder: public IFolderFolder, + public IFolderAltStreams, public IFolderProperties, public IArchiveGetRawProps, public IGetFolderArcProps, @@ -59,10 +64,11 @@ class CAgentFolder: #endif public CMyUnknownImp { - void LoadFolder(unsigned proxyFolderIndex); + void LoadFolder(unsigned proxyDirIndex); public: MY_QUERYINTERFACE_BEGIN2(IFolderFolder) + MY_QUERYINTERFACE_ENTRY(IFolderAltStreams) MY_QUERYINTERFACE_ENTRY(IFolderProperties) MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps) MY_QUERYINTERFACE_ENTRY(IGetFolderArcProps) @@ -79,7 +85,8 @@ public: MY_QUERYINTERFACE_END MY_ADDREF_RELEASE - HRESULT BindToFolder_Internal(unsigned proxyFolderIndex, IFolderFolder **resultFolder); + HRESULT BindToFolder_Internal(unsigned proxyDirIndex, IFolderFolder **resultFolder); + HRESULT BindToAltStreams_Internal(unsigned proxyDirIndex, IFolderFolder **resultFolder); int GetRealIndex(unsigned index) const; void GetRealIndices(const UInt32 *indices, UInt32 numItems, bool includeAltStreams, bool includeFolderSubItemsInFlatMode, CUIntVector &realIndices) const; @@ -87,6 +94,7 @@ public: // INTERFACE_FolderSetReplaceAltStreamCharsMode(;) INTERFACE_FolderFolder(;) + INTERFACE_FolderAltStreams(;) INTERFACE_FolderProperties(;) INTERFACE_IArchiveGetRawProps(;) INTERFACE_IFolderGetItemName(;) @@ -108,48 +116,57 @@ public: STDMETHOD(SetFlatMode)(Int32 flatMode); #endif - CAgentFolder(): _proxyFolderItem(0), _flatMode(0) /* , _replaceAltStreamCharsMode(0) */ {} - - void Init(const CProxyArchive *proxyArc, const CProxyArchive2 *proxyArc2, - unsigned proxyFolderItem, - IFolderFolder *parentFolder, + CAgentFolder(): + _proxyDirIndex(0), + _isAltStreamFolder(false), + _flatMode(false), + _loadAltStreams(false) // _loadAltStreams alt streams works in flat mode, but we don't use it now + /* , _replaceAltStreamCharsMode(0) */ + {} + + void Init(const CProxyArc *proxy, const CProxyArc2 *proxy2, + unsigned proxyDirIndex, + /* IFolderFolder *parentFolder, */ CAgent *agent) { - _proxyArchive = proxyArc; - _proxyArchive2 = proxyArc2; - _proxyFolderItem = proxyFolderItem; - _parentFolder = parentFolder; + _proxy = proxy; + _proxy2 = proxy2; + _proxyDirIndex = proxyDirIndex; + _isAltStreamFolder = false; + if (_proxy2) + _isAltStreamFolder = _proxy2->IsAltDir(proxyDirIndex); + // _parentFolder = parentFolder; _agent = (IInFolderArchive *)agent; _agentSpec = agent; } - void GetPathParts(UStringVector &pathParts); + void GetPathParts(UStringVector &pathParts, bool &isAltStreamFolder); HRESULT CommonUpdateOperation( AGENT_OP operation, bool moveMode, const wchar_t *newItemName, const NUpdateArchive::CActionSet *actionSet, const UInt32 *indices, UInt32 numItems, - IFolderArchiveUpdateCallback *updateCallback100); + IProgress *progress); void GetPrefix(UInt32 index, UString &prefix) const; UString GetName(UInt32 index) const; - UString GetFullPathPrefixPlusPrefix(UInt32 index) const; + UString GetFullPrefix(UInt32 index) const; // relative too root folder of archive public: - const CProxyArchive *_proxyArchive; - const CProxyArchive2 *_proxyArchive2; - // const CProxyFolder *_proxyFolderItem; - unsigned _proxyFolderItem; - CMyComPtr<IFolderFolder> _parentFolder; + const CProxyArc *_proxy; + const CProxyArc2 *_proxy2; + unsigned _proxyDirIndex; + bool _isAltStreamFolder; + // CMyComPtr<IFolderFolder> _parentFolder; CMyComPtr<IInFolderArchive> _agent; CAgent *_agentSpec; CRecordVector<CProxyItem> _items; bool _flatMode; + bool _loadAltStreams; // in Flat mode // Int32 _replaceAltStreamCharsMode; -private: }; class CAgent: @@ -193,29 +210,28 @@ public: IFolderArchiveUpdateCallback *updateCallback100); // ISetProperties - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); + STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); #endif - CCodecs *_codecs; - CMyComPtr<ICompressCodecsInfo> _compressCodecsInfo; - CAgent(); ~CAgent(); private: HRESULT ReadItems(); public: - CProxyArchive *_proxyArchive; - CProxyArchive2 *_proxyArchive2; + CProxyArc *_proxy; + CProxyArc2 *_proxy2; CArchiveLink _archiveLink; bool ThereIsPathProp; + // bool ThereIsAltStreamProp; UString ArchiveType; FStringVector _names; FString _folderPrefix; - UString _archiveNamePrefix; + bool _updatePathPrefix_is_AltFolder; + UString _updatePathPrefix; CAgentFolder *_agentFolder; UString _archiveFilePath; @@ -230,11 +246,22 @@ public: IInArchive *GetArchive() const { if ( _archiveLink.Arcs.IsEmpty()) return 0; return GetArc().Archive; } bool CanUpdate() const; + bool IsThereReadOnlyArc() const + { + FOR_VECTOR (i, _archiveLink.Arcs) + { + const CArc &arc = _archiveLink.Arcs[i]; + if (!g_CodecsObj->Formats[arc.FormatIndex].UpdateEnabled || arc.IsReadOnly) + return true; + } + return false; + } + UString GetTypeOfArc(const CArc &arc) const { if (arc.FormatIndex < 0) return L"Parser"; - return _codecs->GetFormatNamePtr(arc.FormatIndex); + return g_CodecsObj->GetFormatNamePtr(arc.FormatIndex); } UString GetErrorMessage() const @@ -246,25 +273,29 @@ public: UString s2; if (arc.ErrorInfo.ErrorFormatIndex >= 0) - s2 = L"Can not open the file as [" + _codecs->Formats[arc.ErrorInfo.ErrorFormatIndex].Name + L"] archive"; + { + s2.AddAscii("Can not open the file as ["); + s2 += g_CodecsObj->Formats[arc.ErrorInfo.ErrorFormatIndex].Name; + s2.AddAscii("] archive"); + } if (!arc.ErrorInfo.ErrorMessage.IsEmpty()) { if (!s2.IsEmpty()) - s2 += L"\n"; - s2 += L"\n["; + s2.Add_LF(); + s2.AddAscii("\n["); s2 += GetTypeOfArc(arc); - s2 += L"]: "; + s2.AddAscii("]: "); s2 += arc.ErrorInfo.ErrorMessage; } if (!s2.IsEmpty()) { if (!s.IsEmpty()) - s += L"--------------------\n"; + s.AddAscii("--------------------\n"); s += arc.Path; - s += L"\n"; + s.Add_LF(); s += s2; - s += L"\n"; + s.Add_LF(); } } return s; @@ -274,23 +305,20 @@ public: }; + #ifdef NEW_FOLDER_INTERFACE + class CArchiveFolderManager: public IFolderManager, public CMyUnknownImp { + void LoadFormats(); + int FindFormat(const UString &type); public: MY_UNKNOWN_IMP1(IFolderManager) - INTERFACE_IFolderManager(;) - - CArchiveFolderManager(): _codecs(0) {} -private: - void LoadFormats(); - int FindFormat(const UString &type); - CCodecs *_codecs; - CMyComPtr<ICompressCodecsInfo> _compressCodecsInfo; }; + #endif #endif diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp index 3fd25670..3fed8cba 100644 --- a/CPP/7zip/UI/Agent/AgentOut.cpp +++ b/CPP/7zip/UI/Agent/AgentOut.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../Common/Wildcard.h" + #include "../../../Windows/FileDir.h" #include "../../../Windows/FileName.h" #include "../../../Windows/TimeUtils.h" @@ -18,29 +20,33 @@ using namespace NCOM; STDMETHODIMP CAgent::SetFolder(IFolderFolder *folder) { - _archiveNamePrefix.Empty(); - if (folder == NULL) - { - _agentFolder = NULL; + _updatePathPrefix.Empty(); + _updatePathPrefix_is_AltFolder = false; + _agentFolder = NULL; + + if (!folder) return S_OK; - } { - CMyComPtr<IFolderFolder> archiveFolder = folder; - CMyComPtr<IArchiveFolderInternal> archiveFolderInternal; - RINOK(archiveFolder.QueryInterface(IID_IArchiveFolderInternal, &archiveFolderInternal)); - RINOK(archiveFolderInternal->GetAgentFolder(&_agentFolder)); + CMyComPtr<IArchiveFolderInternal> afi; + RINOK(folder->QueryInterface(IID_IArchiveFolderInternal, (void **)&afi)); + if (afi) + { + RINOK(afi->GetAgentFolder(&_agentFolder)); + } + if (!_agentFolder) + return E_FAIL; } - if (_proxyArchive2) - _archiveNamePrefix = _proxyArchive2->GetFullPathPrefix(_agentFolder->_proxyFolderItem); + if (_proxy2) + _updatePathPrefix = _proxy2->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex, _updatePathPrefix_is_AltFolder); else - _archiveNamePrefix = _proxyArchive->GetFullPathPrefix(_agentFolder->_proxyFolderItem); + _updatePathPrefix = _proxy->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex); return S_OK; } STDMETHODIMP CAgent::SetFiles(const wchar_t *folderPrefix, - const wchar_t **names, UInt32 numNames) + const wchar_t * const *names, UInt32 numNames) { _folderPrefix = us2fs(folderPrefix); _names.ClearAndReserve(numNames); @@ -50,54 +56,57 @@ STDMETHODIMP CAgent::SetFiles(const wchar_t *folderPrefix, } static HRESULT EnumerateArchiveItems(CAgent *agent, - const CProxyFolder &item, + const CProxyDir &item, const UString &prefix, CObjectVector<CArcItem> &arcItems) { unsigned i; - for (i = 0; i < item.Files.Size(); i++) + + for (i = 0; i < item.SubFiles.Size(); i++) { - const CProxyFile &fileItem = item.Files[i]; + unsigned arcIndex = item.SubFiles[i]; + const CProxyFile &fileItem = agent->_proxy->Files[arcIndex]; CArcItem ai; - RINOK(agent->GetArc().GetItemMTime(fileItem.Index, ai.MTime, ai.MTimeDefined)); - RINOK(agent->GetArc().GetItemSize(fileItem.Index, ai.Size, ai.SizeDefined)); + RINOK(agent->GetArc().GetItemMTime(arcIndex, ai.MTime, ai.MTimeDefined)); + RINOK(agent->GetArc().GetItemSize(arcIndex, ai.Size, ai.SizeDefined)); ai.IsDir = false; ai.Name = prefix + fileItem.Name; ai.Censored = true; // test it - ai.IndexInServer = fileItem.Index; + ai.IndexInServer = arcIndex; arcItems.Add(ai); } - for (i = 0; i < item.Folders.Size(); i++) + + for (i = 0; i < item.SubDirs.Size(); i++) { - const CProxyFolder &dirItem = agent->_proxyArchive->Folders[item.Folders[i]]; + const CProxyDir &dirItem = agent->_proxy->Dirs[item.SubDirs[i]]; UString fullName = prefix + dirItem.Name; - if (dirItem.IsLeaf) + if (dirItem.IsLeaf()) { CArcItem ai; - RINOK(agent->GetArc().GetItemMTime(dirItem.Index, ai.MTime, ai.MTimeDefined)); + RINOK(agent->GetArc().GetItemMTime(dirItem.ArcIndex, ai.MTime, ai.MTimeDefined)); ai.IsDir = true; ai.SizeDefined = false; ai.Name = fullName; ai.Censored = true; // test it - ai.IndexInServer = dirItem.Index; + ai.IndexInServer = dirItem.ArcIndex; arcItems.Add(ai); } - RINOK(EnumerateArchiveItems(agent, dirItem, fullName + UString(WCHAR_PATH_SEPARATOR), arcItems)); + RINOK(EnumerateArchiveItems(agent, dirItem, fullName + WCHAR_PATH_SEPARATOR, arcItems)); } + return S_OK; } static HRESULT EnumerateArchiveItems2(const CAgent *agent, - const CProxyArchive2 *proxyArchive2, - unsigned folderIndex, + unsigned dirIndex, const UString &prefix, CObjectVector<CArcItem> &arcItems) { - const CProxyFolder2 &folder = proxyArchive2->Folders[folderIndex]; - FOR_VECTOR (i, folder.SubFiles) + const CProxyDir2 &dir = agent->_proxy2->Dirs[dirIndex]; + FOR_VECTOR (i, dir.Items) { - unsigned arcIndex = folder.SubFiles[i]; - const CProxyFile2 &file = proxyArchive2->Files[arcIndex]; + unsigned arcIndex = dir.Items[i]; + const CProxyFile2 &file = agent->_proxy2->Files[arcIndex]; CArcItem ai; ai.IndexInServer = arcIndex; ai.Name = prefix + file.Name; @@ -105,15 +114,22 @@ static HRESULT EnumerateArchiveItems2(const CAgent *agent, RINOK(agent->GetArc().GetItemMTime(arcIndex, ai.MTime, ai.MTimeDefined)); ai.IsDir = file.IsDir(); ai.SizeDefined = false; + ai.IsAltStream = file.IsAltStream; if (!ai.IsDir) { RINOK(agent->GetArc().GetItemSize(arcIndex, ai.Size, ai.SizeDefined)); ai.IsDir = false; } arcItems.Add(ai); + + if (file.AltDirIndex >= 0) + { + RINOK(EnumerateArchiveItems2(agent, file.AltDirIndex, ai.Name + L':', arcItems)); + } + if (ai.IsDir) { - RINOK(EnumerateArchiveItems2(agent, proxyArchive2, file.FolderIndex, ai.Name + UString(WCHAR_PATH_SEPARATOR), arcItems)); + RINOK(EnumerateArchiveItems2(agent, file.DirIndex, ai.Name + WCHAR_PATH_SEPARATOR, arcItems)); } } return S_OK; @@ -126,10 +142,10 @@ struct CAgUpCallbackImp: public IUpdateProduceCallback CAgUpCallbackImp(const CObjectVector<CArcItem> *a, IFolderArchiveUpdateCallback *callback): _arcItems(a), _callback(callback) {} - HRESULT ShowDeleteFile(int arcIndex); + HRESULT ShowDeleteFile(unsigned arcIndex); }; -HRESULT CAgUpCallbackImp::ShowDeleteFile(int arcIndex) +HRESULT CAgUpCallbackImp::ShowDeleteFile(unsigned arcIndex) { return _callback->DeleteOperation((*_arcItems)[arcIndex].Name); } @@ -140,11 +156,40 @@ static void SetInArchiveInterfaces(CAgent *agent, CArchiveUpdateCallback *upd) if (agent->_archiveLink.Arcs.IsEmpty()) return; const CArc &arc = agent->GetArc(); + upd->Arc = &arc; upd->Archive = arc.Archive; - upd->GetRawProps = arc.GetRawProps; - upd->GetRootProps = arc.GetRootProps; } +struct CDirItemsCallback_AgentOut: public IDirItemsCallback +{ + CMyComPtr<IFolderScanProgress> FolderScanProgress; + IFolderArchiveUpdateCallback *FolderArchiveUpdateCallback; + HRESULT ErrorCode; + + CDirItemsCallback_AgentOut(): ErrorCode(S_OK), FolderArchiveUpdateCallback(NULL) {} + + HRESULT ScanError(const FString &name, DWORD systemError) + { + HRESULT hres = HRESULT_FROM_WIN32(systemError); + if (FolderArchiveUpdateCallback) + return FolderScanProgress->ScanError(fs2us(name), hres); + ErrorCode = hres; + return ErrorCode; + } + + HRESULT ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) + { + if (FolderScanProgress) + return FolderScanProgress->ScanProgress(st.NumDirs, st.NumFiles + st.NumAltStreams, + st.GetTotalBytes(), fs2us(path), BoolToInt(isDir)); + + if (FolderArchiveUpdateCallback) + return FolderArchiveUpdateCallback->SetNumFiles(st.NumFiles); + + return S_OK; + } +}; + STDMETHODIMP CAgent::DoOperation( FStringVector *requestedPaths, FStringVector *processedPaths, @@ -157,22 +202,43 @@ STDMETHODIMP CAgent::DoOperation( { if (!CanUpdate()) return E_NOTIMPL; + NUpdateArchive::CActionSet actionSet; - unsigned i; - for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) - actionSet.StateActions[i] = (NUpdateArchive::NPairAction::EEnum)stateActions[i]; + { + for (unsigned i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) + actionSet.StateActions[i] = (NUpdateArchive::NPairAction::EEnum)stateActions[i]; + } + CDirItemsCallback_AgentOut enumCallback; + if (updateCallback100) + { + enumCallback.FolderArchiveUpdateCallback = updateCallback100; + updateCallback100->QueryInterface(IID_IFolderScanProgress, (void **)&enumCallback.FolderScanProgress); + } + CDirItems dirItems; + dirItems.Callback = &enumCallback; { FString folderPrefix = _folderPrefix; NFile::NName::NormalizeDirPathPrefix(folderPrefix); - dirItems.EnumerateItems2(folderPrefix, _archiveNamePrefix, _names, requestedPaths); - if (dirItems.ErrorCodes.Size() > 0) - return dirItems.ErrorCodes.Front(); + + RINOK(dirItems.EnumerateItems2(folderPrefix, _updatePathPrefix, _names, requestedPaths)); + + if (_updatePathPrefix_is_AltFolder) + { + FOR_VECTOR(i, dirItems.Items) + { + CDirItem &item = dirItems.Items[i]; + if (item.IsDir()) + return E_NOTIMPL; + item.IsAltStream = true; + } + } } CMyComPtr<IOutArchive> outArchive; + if (GetArchive()) { RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive)); @@ -182,6 +248,7 @@ STDMETHODIMP CAgent::DoOperation( if (formatIndex < 0) return E_FAIL; RINOK(codecs->CreateOutArchive(formatIndex, outArchive)); + #ifdef EXTERNAL_CODECS { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; @@ -192,7 +259,6 @@ STDMETHODIMP CAgent::DoOperation( } } #endif - } NFileTimeType::EEnum fileTimeType; @@ -215,13 +281,14 @@ STDMETHODIMP CAgent::DoOperation( if (GetArchive()) { RINOK(ReadItems()); - if (_proxyArchive2) + if (_proxy2) { - RINOK(EnumerateArchiveItems2(this, _proxyArchive2, 0, L"", arcItems)); + RINOK(EnumerateArchiveItems2(this, k_Proxy2_RootDirIndex, L"", arcItems)); + RINOK(EnumerateArchiveItems2(this, k_Proxy2_AltRootDirIndex, L":", arcItems)); } else { - RINOK(EnumerateArchiveItems(this, _proxyArchive->Folders[0], L"", arcItems)); + RINOK(EnumerateArchiveItems(this, _proxy->Dirs[0], L"", arcItems)); } } @@ -235,9 +302,11 @@ STDMETHODIMP CAgent::DoOperation( } UInt32 numFiles = 0; - for (i = 0; i < updatePairs2.Size(); i++) - if (updatePairs2[i].NewData) - numFiles++; + { + FOR_VECTOR (i, updatePairs2) + if (updatePairs2[i].NewData) + numFiles++; + } if (updateCallback100) { @@ -262,7 +331,7 @@ STDMETHODIMP CAgent::DoOperation( { unsigned num = dirItems.Items.Size(); processedItems.Alloc(num); - for (i = 0; i < num; i++) + for (unsigned i = 0; i < num; i++) processedItems[i] = 0; updateCallbackSpec->ProcessedItemsStatuses = processedItems; } @@ -277,7 +346,7 @@ STDMETHODIMP CAgent::DoOperation( else { CRecordVector<const wchar_t *> names; - for(i = 0; i < m_PropNames.Size(); i++) + FOR_VECTOR (i, m_PropNames) names.Add((const wchar_t *)m_PropNames[i]); CPropVariant *propValues = new CPropVariant[m_PropValues.Size()]; @@ -311,9 +380,9 @@ STDMETHODIMP CAgent::DoOperation( HRESULT res = outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(), updateCallback); if (res == S_OK && processedPaths) { - for (i = 0; i < dirItems.Items.Size(); i++) + FOR_VECTOR (i, dirItems.Items) if (processedItems[i] != 0) - processedPaths->Add(us2fs(dirItems.GetPhyPath(i))); + processedPaths->Add(dirItems.GetPhyPath(i)); } return res; } @@ -324,7 +393,7 @@ STDMETHODIMP CAgent::DoOperation2( ISequentialOutStream *outArchiveStream, const Byte *stateActions, const wchar_t *sfxModule, IFolderArchiveUpdateCallback *updateCallback100) { - return DoOperation(requestedPaths, processedPaths, _codecs, -1, outArchiveStream, stateActions, sfxModule, updateCallback100); + return DoOperation(requestedPaths, processedPaths, g_CodecsObj, -1, outArchiveStream, stateActions, sfxModule, updateCallback100); } HRESULT CAgent::CommonUpdate(ISequentialOutStream *outArchiveStream, @@ -357,11 +426,17 @@ STDMETHODIMP CAgent::DeleteItems(ISequentialOutStream *outArchiveStream, unsigned curIndex = 0; UInt32 numItemsInArchive; RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive)); + + UString deletePath; + for (UInt32 i = 0; i < numItemsInArchive; i++) { if (curIndex < realIndices.Size()) if (realIndices[curIndex] == i) { + RINOK(GetArc().GetItemPath2(i, deletePath)); + RINOK(updateCallback100->DeleteOperation(deletePath)); + curIndex++; continue; } @@ -410,10 +485,12 @@ HRESULT CAgent::CreateFolder(ISequentialOutStream *outArchiveStream, di.Attrib = FILE_ATTRIBUTE_DIRECTORY; di.Size = 0; - if (_proxyArchive2) - di.Name = _proxyArchive2->GetFullPathPrefix(_agentFolder->_proxyFolderItem) + folderName; + bool isAltStreamFolder = false; + if (_proxy2) + di.Name = _proxy2->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex, isAltStreamFolder); else - di.Name = _proxyArchive->GetFullPathPrefix(_agentFolder->_proxyFolderItem) + folderName; + di.Name = _proxy->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex); + di.Name += folderName; FILETIME ft; NTime::GetCurUtcFileTime(ft); @@ -455,7 +532,7 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream, int mainRealIndex = _agentFolder->GetRealIndex(indices[0]); - UString fullPrefix = _agentFolder->GetFullPathPrefixPlusPrefix(indices[0]); + UString fullPrefix = _agentFolder->GetFullPrefix(indices[0]); UString oldItemPath = fullPrefix + _agentFolder->GetName(indices[0]); UString newItemPath = fullPrefix + newItemName; @@ -464,6 +541,7 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream, unsigned curIndex = 0; UInt32 numItemsInArchive; RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive)); + for (UInt32 i = 0; i < numItemsInArchive; i++) { CUpdatePair2 up2; @@ -477,7 +555,7 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream, UString oldFullPath; RINOK(GetArc().GetItemPath2(i, oldFullPath)); - if (MyStringCompareNoCase_N(oldFullPath, oldItemPath, oldItemPath.Len()) != 0) + if (!IsPath1PrefixedByPath2(oldFullPath, oldItemPath)) return E_INVALIDARG; up2.NewNameIndex = newNames.Add(newItemPath + oldFullPath.Ptr(oldItemPath.Len())); @@ -486,6 +564,7 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream, } updatePairs.Add(up2); } + updateCallbackSpec->Callback = &updateCallbackAgent; updateCallbackSpec->UpdatePairs = &updatePairs; updateCallbackSpec->NewNames = &newNames; @@ -553,7 +632,7 @@ HRESULT CAgent::UpdateOneFile(ISequentialOutStream *outArchiveStream, return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback); } -STDMETHODIMP CAgent::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) +STDMETHODIMP CAgent::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) { m_PropNames.Clear(); m_PropValues.Clear(); diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp index 301d3a33..543cfbaa 100644 --- a/CPP/7zip/UI/Agent/AgentProxy.cpp +++ b/CPP/7zip/UI/Agent/AgentProxy.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +// #include <stdio.h> + #include "../../../../C/Sort.h" #include "../../../../C/CpuArch.h" @@ -14,10 +16,10 @@ using namespace NWindows; -int CProxyArchive::FindDirSubItemIndex(unsigned folderIndex, const UString &name, unsigned &insertPos) const +int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name, unsigned &insertPos) const { - const CRecordVector<unsigned> &subFolders = Folders[folderIndex].Folders; - unsigned left = 0, right = subFolders.Size(); + const CRecordVector<unsigned> &subDirs = Dirs[dirIndex].SubDirs; + unsigned left = 0, right = subDirs.Size(); for (;;) { if (left == right) @@ -26,10 +28,10 @@ int CProxyArchive::FindDirSubItemIndex(unsigned folderIndex, const UString &name return -1; } unsigned mid = (left + right) / 2; - unsigned folderIndex = subFolders[mid]; - int compare = CompareFileNames(name, Folders[folderIndex].Name); + unsigned dirIndex = subDirs[mid]; + int compare = CompareFileNames(name, Dirs[dirIndex].Name); if (compare == 0) - return folderIndex; + return dirIndex; if (compare < 0) right = mid; else @@ -37,120 +39,117 @@ int CProxyArchive::FindDirSubItemIndex(unsigned folderIndex, const UString &name } } -int CProxyArchive::FindDirSubItemIndex(unsigned folderIndex, const UString &name) const +int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name) const { unsigned insertPos; - return FindDirSubItemIndex(folderIndex, name, insertPos); -} - -void CProxyFolder::AddFileSubItem(UInt32 index, const UString &name) -{ - CProxyFile &f = Files.AddNew(); - f.Index = index; - f.Name = name; + return FindSubDir(dirIndex, name, insertPos); } -unsigned CProxyArchive::AddDirSubItem(unsigned folderIndex, UInt32 index, bool leaf, const UString &name) +unsigned CProxyArc::AddDir(unsigned dirIndex, int arcIndex, const UString &name) { unsigned insertPos; - int subFolderIndex = FindDirSubItemIndex(folderIndex, name, insertPos); - if (subFolderIndex >= 0) + int subDirIndex = FindSubDir(dirIndex, name, insertPos); + if (subDirIndex >= 0) { - CProxyFolder &item = Folders[subFolderIndex]; - if (leaf) + if (arcIndex >= 0) { - item.Index = index; - item.IsLeaf = true; + CProxyDir &item = Dirs[subDirIndex]; + if (item.ArcIndex < 0) + item.ArcIndex = arcIndex; } - return subFolderIndex; + return subDirIndex; } - subFolderIndex = Folders.Size(); - Folders[folderIndex].Folders.Insert(insertPos, subFolderIndex); - CProxyFolder &item = Folders.AddNew(); - item.Name = name; - item.Index = index; - item.Parent = folderIndex; - item.IsLeaf = leaf; - return subFolderIndex; + subDirIndex = Dirs.Size(); + Dirs[dirIndex].SubDirs.Insert(insertPos, subDirIndex); + CProxyDir &item = Dirs.AddNew(); + + item.NameLen = name.Len(); + item.Name = new wchar_t[item.NameLen + 1]; + MyStringCopy((wchar_t *)item.Name, name); + + item.ArcIndex = arcIndex; + item.ParentDir = dirIndex; + return subDirIndex; } -void CProxyFolder::Clear() +void CProxyDir::Clear() { - Folders.Clear(); - Files.Clear(); + SubDirs.Clear(); + SubFiles.Clear(); } -void CProxyArchive::GetPathParts(int folderIndex, UStringVector &pathParts) const +void CProxyArc::GetDirPathParts(int dirIndex, UStringVector &pathParts) const { pathParts.Clear(); - while (folderIndex >= 0) + while (dirIndex >= 0) { - const CProxyFolder &folder = Folders[folderIndex]; - folderIndex = folder.Parent; - if (folderIndex < 0) + const CProxyDir &dir = Dirs[dirIndex]; + dirIndex = dir.ParentDir; + if (dirIndex < 0) break; - pathParts.Insert(0, folder.Name); + pathParts.Insert(0, dir.Name); } } -UString CProxyArchive::GetFullPathPrefix(int folderIndex) const +UString CProxyArc::GetDirPath_as_Prefix(int dirIndex) const { - UString result; - while (folderIndex >= 0) + UString s; + while (dirIndex >= 0) { - const CProxyFolder &folder = Folders[folderIndex]; - folderIndex = folder.Parent; - if (folderIndex < 0) + const CProxyDir &dir = Dirs[dirIndex]; + dirIndex = dir.ParentDir; + if (dirIndex < 0) break; - result = folder.Name + UString(WCHAR_PATH_SEPARATOR) + result; + s.InsertAtFront(WCHAR_PATH_SEPARATOR); + s.Insert(0, dir.Name); } - return result; + return s; } -void CProxyArchive::AddRealIndices(unsigned folderIndex, CUIntVector &realIndices) const +void CProxyArc::AddRealIndices(unsigned dirIndex, CUIntVector &realIndices) const { - const CProxyFolder &folder = Folders[folderIndex]; - if (folder.IsLeaf) - realIndices.Add(folder.Index); + const CProxyDir &dir = Dirs[dirIndex]; + if (dir.IsLeaf()) + realIndices.Add(dir.ArcIndex); unsigned i; - for (i = 0; i < folder.Folders.Size(); i++) - AddRealIndices(folder.Folders[i], realIndices); - for (i = 0; i < folder.Files.Size(); i++) - realIndices.Add(folder.Files[i].Index); + for (i = 0; i < dir.SubDirs.Size(); i++) + AddRealIndices(dir.SubDirs[i], realIndices); + for (i = 0; i < dir.SubFiles.Size(); i++) + realIndices.Add(dir.SubFiles[i]); } -int CProxyArchive::GetRealIndex(unsigned folderIndex, unsigned index) const +int CProxyArc::GetRealIndex(unsigned dirIndex, unsigned index) const { - const CProxyFolder &folder = Folders[folderIndex]; - unsigned numDirItems = folder.Folders.Size(); + const CProxyDir &dir = Dirs[dirIndex]; + unsigned numDirItems = dir.SubDirs.Size(); if (index < numDirItems) { - const CProxyFolder &f = Folders[folder.Folders[index]]; - if (f.IsLeaf) - return f.Index; + const CProxyDir &f = Dirs[dir.SubDirs[index]]; + if (f.IsLeaf()) + return f.ArcIndex; return -1; } - return folder.Files[index - numDirItems].Index; + return dir.SubFiles[index - numDirItems]; } -void CProxyArchive::GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const +void CProxyArc::GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const { - const CProxyFolder &folder = Folders[folderIndex]; + const CProxyDir &dir = Dirs[dirIndex]; realIndices.Clear(); for (UInt32 i = 0; i < numItems; i++) { UInt32 index = indices[i]; - unsigned numDirItems = folder.Folders.Size(); + unsigned numDirItems = dir.SubDirs.Size(); if (index < numDirItems) - AddRealIndices(folder.Folders[index], realIndices); + AddRealIndices(dir.SubDirs[index], realIndices); else - realIndices.Add(folder.Files[index - numDirItems].Index); + realIndices.Add(dir.SubFiles[index - numDirItems]); } HeapSort(&realIndices.Front(), realIndices.Size()); } /////////////////////////////////////////////// -// CProxyArchive +// CProxyArc static bool GetSize(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &size) { @@ -161,79 +160,131 @@ static bool GetSize(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &si return ConvertPropVariantToUInt64(prop, size); } -void CProxyArchive::CalculateSizes(unsigned folderIndex, IInArchive *archive) +void CProxyArc::CalculateSizes(unsigned dirIndex, IInArchive *archive) { - CProxyFolder &folder = Folders[folderIndex]; - folder.Size = folder.PackSize = 0; - folder.NumSubFolders = folder.Folders.Size(); - folder.NumSubFiles = folder.Files.Size(); - folder.CrcIsDefined = true; - folder.Crc = 0; + CProxyDir &dir = Dirs[dirIndex]; + dir.Size = dir.PackSize = 0; + dir.NumSubDirs = dir.SubDirs.Size(); + dir.NumSubFiles = dir.SubFiles.Size(); + dir.CrcIsDefined = true; + dir.Crc = 0; + unsigned i; - for (i = 0; i < folder.Files.Size(); i++) + + for (i = 0; i < dir.SubFiles.Size(); i++) { - UInt32 index = folder.Files[i].Index; + UInt32 index = (UInt32)dir.SubFiles[i]; UInt64 size, packSize; bool sizeDefined = GetSize(archive, index, kpidSize, size); - folder.Size += size; + dir.Size += size; GetSize(archive, index, kpidPackSize, packSize); - folder.PackSize += packSize; + dir.PackSize += packSize; { NCOM::CPropVariant prop; if (archive->GetProperty(index, kpidCRC, &prop) == S_OK) { if (prop.vt == VT_UI4) - folder.Crc += prop.ulVal; + dir.Crc += prop.ulVal; else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined) - folder.CrcIsDefined = false; + dir.CrcIsDefined = false; } else - folder.CrcIsDefined = false; + dir.CrcIsDefined = false; } } - for (i = 0; i < folder.Folders.Size(); i++) + + for (i = 0; i < dir.SubDirs.Size(); i++) { - unsigned subFolderIndex = folder.Folders[i]; - CProxyFolder &f = Folders[subFolderIndex]; - CalculateSizes(subFolderIndex, archive); - folder.Size += f.Size; - folder.PackSize += f.PackSize; - folder.NumSubFiles += f.NumSubFiles; - folder.NumSubFolders += f.NumSubFolders; - folder.Crc += f.Crc; + unsigned subDirIndex = dir.SubDirs[i]; + CalculateSizes(subDirIndex, archive); + CProxyDir &f = Dirs[subDirIndex]; + dir.Size += f.Size; + dir.PackSize += f.PackSize; + dir.NumSubFiles += f.NumSubFiles; + dir.NumSubDirs += f.NumSubDirs; + dir.Crc += f.Crc; if (!f.CrcIsDefined) - folder.CrcIsDefined = false; + dir.CrcIsDefined = false; } } -HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress) +HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) { - /* - DWORD tickCount = GetTickCount(); - for (int ttt = 0; ttt < 1000; ttt++) { - */ + // DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) { - Folders.Clear(); - Folders.AddNew(); + Files.Free(); + Dirs.Clear(); + + Dirs.AddNew(); IInArchive *archive = arc.Archive; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); + if (progress) RINOK(progress->SetTotal(numItems)); - UString filePath; - UString fileName; + + Files.Alloc(numItems); + + UString path; + UString name; + NCOM::CPropVariant prop; + for (UInt32 i = 0; i < numItems; i++) { - if (progress && (i & 0xFFFFF) == 0) + if (progress && (i & 0xFFFF) == 0) { UInt64 currentItemIndex = i; RINOK(progress->SetCompleted(¤tItemIndex)); } - RINOK(arc.GetItemPath(i, filePath)); + + const wchar_t *s = NULL; + unsigned len = 0; + bool isPtrName = false; + + #ifdef MY_CPU_LE + if (arc.GetRawProps) + { + const void *p; + UInt32 size; + UInt32 propType; + if (arc.GetRawProps->GetRawProp(i, kpidPath, &p, &size, &propType) == S_OK + && propType == NPropDataType::kUtf16z + && size > 2) + { + // is (size <= 2), it's empty name, and we call default arc.GetItemPath(); + len = size / 2 - 1; + s = (const wchar_t *)p; + isPtrName = true; + } + } + if (!s) + #endif + { + prop.Clear(); + RINOK(arc.Archive->GetProperty(i, kpidPath, &prop)); + if (prop.vt == VT_BSTR) + { + s = prop.bstrVal; + len = ::SysStringLen(prop.bstrVal); + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + if (len == 0) + { + RINOK(arc.GetDefaultItemPath(i, path)); + len = path.Len(); + s = path; + } + + /* + RINOK(arc.GetItemPath(i, path)); + len = path.Len(); + s = path; + */ + } + unsigned curItem = 0; - unsigned len = filePath.Len(); - fileName.Empty(); /* if (arc.Ask_Deleted) @@ -245,16 +296,16 @@ HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress) } */ + unsigned namePos = 0; for (unsigned j = 0; j < len; j++) { - wchar_t c = filePath[j]; + wchar_t c = s[j]; if (c == WCHAR_PATH_SEPARATOR || c == L'/') { - curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, fileName); - fileName.Empty(); + name.SetFrom(s + namePos, j - namePos); + curItem = AddDir(curItem, -1, name); + namePos = j + 1; } - else - fileName += c; } /* @@ -270,21 +321,35 @@ HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress) } */ - bool isFolder; - RINOK(Archive_IsItem_Folder(archive, i, isFolder)); - if (isFolder) - AddDirSubItem(curItem, i, true, fileName); + bool isDir; + RINOK(Archive_IsItem_Dir(archive, i, isDir)); + + CProxyFile &f = Files[i]; + + f.NameLen = len - namePos; + s += namePos; + + if (isPtrName) + f.Name = s; + else + { + f.Name = new wchar_t[f.NameLen + 1]; + f.NeedDeleteName = true; + MyStringCopy((wchar_t *)f.Name, s); + } + + if (isDir) + { + name = s; + AddDir(curItem, (int)i, name); + } else - Folders[curItem].AddFileSubItem(i, fileName); + Dirs[curItem].SubFiles.Add(i); } + CalculateSizes(0, archive); - /* - } - char s[128]; - sprintf(s, "load archive %7d ms", GetTickCount() - tickCount); - OutputDebugStringA(s); - */ + // } char s[128]; sprintf(s, "Load archive: %7d ms", GetTickCount() - tickCount); OutputDebugStringA(s); return S_OK; } @@ -293,151 +358,162 @@ HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress) // ---------- for Tree-mode archive ---------- -void CProxyArchive2::GetPathParts(int folderIndex, UStringVector &pathParts) const +void CProxyArc2::GetDirPathParts(int dirIndex, UStringVector &pathParts, bool &isAltStreamDir) const { pathParts.Clear(); - while (folderIndex > 0) + + isAltStreamDir = false; + + if (dirIndex == k_Proxy2_RootDirIndex) + return; + if (dirIndex == k_Proxy2_AltRootDirIndex) + { + isAltStreamDir = true; + return; + } + + while (dirIndex >= k_Proxy2_NumRootDirs) { - const CProxyFolder2 &folder = Folders[folderIndex]; - const CProxyFile2 &file = Files[folder.ArcIndex]; + const CProxyDir2 &dir = Dirs[dirIndex]; + const CProxyFile2 &file = Files[dir.ArcIndex]; + if (pathParts.IsEmpty() && dirIndex == file.AltDirIndex) + isAltStreamDir = true; pathParts.Insert(0, file.Name); int par = file.Parent; if (par < 0) break; - folderIndex = Files[par].FolderIndex; + dirIndex = Files[par].DirIndex; } } -UString CProxyArchive2::GetFullPathPrefix(unsigned folderIndex) const +bool CProxyArc2::IsAltDir(unsigned dirIndex) const +{ + if (dirIndex == k_Proxy2_RootDirIndex) + return false; + if (dirIndex == k_Proxy2_AltRootDirIndex) + return true; + const CProxyDir2 &dir = Dirs[dirIndex]; + const CProxyFile2 &file = Files[dir.ArcIndex]; + return ((int)dirIndex == file.AltDirIndex); +} + +UString CProxyArc2::GetDirPath_as_Prefix(unsigned dirIndex, bool &isAltStreamDir) const { - return Folders[folderIndex].PathPrefix; - /* - UString result; - while (folderIndex > 0) + isAltStreamDir = false; + const CProxyDir2 &dir = Dirs[dirIndex]; + if (dirIndex == k_Proxy2_AltRootDirIndex) + isAltStreamDir = true; + else if (dirIndex >= k_Proxy2_NumRootDirs) { - const CProxyFile2 &file = Files[Folders[folderIndex].ArcIndex]; - result = (UString)(file.Name) + (UString)WCHAR_PATH_SEPARATOR + result; - if (file.Parent < 0) - break; - folderIndex = Files[file.Parent].FolderIndex; + const CProxyFile2 &file = Files[dir.ArcIndex]; + isAltStreamDir = ((int)dirIndex == file.AltDirIndex); } - return result; - */ + return dir.PathPrefix; } -void CProxyArchive2::AddRealIndices_of_ArcItem(unsigned arcIndex, bool includeAltStreams, CUIntVector &realIndices) const +void CProxyArc2::AddRealIndices_of_ArcItem(unsigned arcIndex, bool includeAltStreams, CUIntVector &realIndices) const { realIndices.Add(arcIndex); const CProxyFile2 &file = Files[arcIndex]; - if (file.FolderIndex >= 0) - AddRealIndices_of_Folder(file.FolderIndex, includeAltStreams, realIndices); - if (includeAltStreams && file.AltStreamsFolderIndex >= 0) - AddRealIndices_of_Folder(file.AltStreamsFolderIndex, includeAltStreams, realIndices); + if (file.DirIndex >= 0) + AddRealIndices_of_Dir(file.DirIndex, includeAltStreams, realIndices); + if (includeAltStreams && file.AltDirIndex >= 0) + AddRealIndices_of_Dir(file.AltDirIndex, includeAltStreams, realIndices); } -void CProxyArchive2::AddRealIndices_of_Folder(unsigned folderIndex, bool includeAltStreams, CUIntVector &realIndices) const +void CProxyArc2::AddRealIndices_of_Dir(unsigned dirIndex, bool includeAltStreams, CUIntVector &realIndices) const { - const CRecordVector<unsigned> &subFiles = Folders[folderIndex].SubFiles; + const CRecordVector<unsigned> &subFiles = Dirs[dirIndex].Items; FOR_VECTOR (i, subFiles) { AddRealIndices_of_ArcItem(subFiles[i], includeAltStreams, realIndices); } } -unsigned CProxyArchive2::GetRealIndex(unsigned folderIndex, unsigned index) const +unsigned CProxyArc2::GetRealIndex(unsigned dirIndex, unsigned index) const { - return Folders[folderIndex].SubFiles[index]; + return Dirs[dirIndex].Items[index]; } -void CProxyArchive2::GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const +void CProxyArc2::GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const { - const CProxyFolder2 &folder = Folders[folderIndex]; + const CProxyDir2 &dir = Dirs[dirIndex]; realIndices.Clear(); for (UInt32 i = 0; i < numItems; i++) { - AddRealIndices_of_ArcItem(folder.SubFiles[indices[i]], includeAltStreams, realIndices); + AddRealIndices_of_ArcItem(dir.Items[indices[i]], includeAltStreams, realIndices); } HeapSort(&realIndices.Front(), realIndices.Size()); } -void CProxyArchive2::CalculateSizes(unsigned folderIndex, IInArchive *archive) +void CProxyArc2::CalculateSizes(unsigned dirIndex, IInArchive *archive) { - CProxyFolder2 &folder = Folders[folderIndex]; - folder.Size = folder.PackSize = 0; - folder.NumSubFolders = 0; // folder.Folders.Size(); - folder.NumSubFiles = 0; // folder.Files.Size(); - folder.CrcIsDefined = true; - folder.Crc = 0; - FOR_VECTOR (i, folder.SubFiles) + CProxyDir2 &dir = Dirs[dirIndex]; + dir.Size = dir.PackSize = 0; + dir.NumSubDirs = 0; // dir.SubDirs.Size(); + dir.NumSubFiles = 0; // dir.Files.Size(); + dir.CrcIsDefined = true; + dir.Crc = 0; + + FOR_VECTOR (i, dir.Items) { - UInt32 index = folder.SubFiles[i]; + UInt32 index = dir.Items[i]; UInt64 size, packSize; bool sizeDefined = GetSize(archive, index, kpidSize, size); - folder.Size += size; + dir.Size += size; GetSize(archive, index, kpidPackSize, packSize); - folder.PackSize += packSize; + dir.PackSize += packSize; { NCOM::CPropVariant prop; if (archive->GetProperty(index, kpidCRC, &prop) == S_OK) { if (prop.vt == VT_UI4) - folder.Crc += prop.ulVal; + dir.Crc += prop.ulVal; else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined) - folder.CrcIsDefined = false; + dir.CrcIsDefined = false; } else - folder.CrcIsDefined = false; + dir.CrcIsDefined = false; } const CProxyFile2 &subFile = Files[index]; - if (subFile.FolderIndex < 0) + if (subFile.DirIndex < 0) { - folder.NumSubFiles++; + dir.NumSubFiles++; } else { - folder.NumSubFolders++; - CProxyFolder2 &f = Folders[subFile.FolderIndex]; - f.PathPrefix = folder.PathPrefix + subFile.Name + WCHAR_PATH_SEPARATOR; - CalculateSizes(subFile.FolderIndex, archive); - folder.Size += f.Size; - folder.PackSize += f.PackSize; - folder.NumSubFiles += f.NumSubFiles; - folder.NumSubFolders += f.NumSubFolders; - folder.Crc += f.Crc; + dir.NumSubDirs++; + CProxyDir2 &f = Dirs[subFile.DirIndex]; + f.PathPrefix = dir.PathPrefix + subFile.Name + WCHAR_PATH_SEPARATOR; + CalculateSizes(subFile.DirIndex, archive); + dir.Size += f.Size; + dir.PackSize += f.PackSize; + dir.NumSubFiles += f.NumSubFiles; + dir.NumSubDirs += f.NumSubDirs; + dir.Crc += f.Crc; if (!f.CrcIsDefined) - folder.CrcIsDefined = false; + dir.CrcIsDefined = false; } - if (subFile.AltStreamsFolderIndex < 0) + if (subFile.AltDirIndex < 0) { - // folder.NumSubFiles++; + // dir.NumSubFiles++; } else { - // folder.NumSubFolders++; - CProxyFolder2 &f = Folders[subFile.AltStreamsFolderIndex]; - f.PathPrefix = folder.PathPrefix + subFile.Name + L":"; - CalculateSizes(subFile.AltStreamsFolderIndex, archive); - /* - folder.Size += f.Size; - folder.PackSize += f.PackSize; - folder.NumSubFiles += f.NumSubFiles; - folder.NumSubFolders += f.NumSubFolders; - folder.Crc += f.Crc; - if (!f.CrcIsDefined) - folder.CrcIsDefined = false; - */ + // dir.NumSubDirs++; + CProxyDir2 &f = Dirs[subFile.AltDirIndex]; + f.PathPrefix = dir.PathPrefix + subFile.Name + L':'; + CalculateSizes(subFile.AltDirIndex, archive); } - - } } -bool CProxyArchive2::IsThere_SubDir(unsigned folderIndex, const UString &name) const +bool CProxyArc2::IsThere_SubDir(unsigned dirIndex, const UString &name) const { - const CRecordVector<unsigned> &subFiles = Folders[folderIndex].SubFiles; + const CRecordVector<unsigned> &subFiles = Dirs[dirIndex].Items; FOR_VECTOR (i, subFiles) { const CProxyFile2 &file = Files[subFiles[i]]; @@ -448,14 +524,15 @@ bool CProxyArchive2::IsThere_SubDir(unsigned folderIndex, const UString &name) c return false; } -HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress) +HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress) { if (!arc.GetRawProps) return E_FAIL; - // DWORD tickCount = GetTickCount(); + // DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) { - Folders.Clear(); + Dirs.Clear(); + Files.Free(); IInArchive *archive = arc.Archive; @@ -464,9 +541,17 @@ HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress) if (progress) RINOK(progress->SetTotal(numItems)); UString fileName; + + + { + // Dirs[0] - root dir + /* CProxyDir2 &dir = */ Dirs.AddNew(); + } + { - CProxyFolder2 &folder = Folders.AddNew(); - folder.ArcIndex = -1; + // Dirs[1] - for alt streams of root dir + CProxyDir2 &dir = Dirs.AddNew(); + dir.PathPrefix = L':'; } Files.Alloc(numItems); @@ -491,9 +576,9 @@ HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress) if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE) { file.Name = (const wchar_t *)p; - file.NameSize = 0; + file.NameLen = 0; if (size >= sizeof(wchar_t)) - file.NameSize = size / sizeof(wchar_t) - 1; + file.NameLen = size / sizeof(wchar_t) - 1; } else #endif @@ -507,11 +592,12 @@ HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress) s = L"[Content]"; else return E_FAIL; - file.NameSize = MyStringLen(s); - file.Name = new wchar_t[file.NameSize + 1]; + file.NameLen = MyStringLen(s); + file.Name = new wchar_t[file.NameLen + 1]; file.NeedDeleteName = true; MyStringCopy((wchar_t *)file.Name, s); } + UInt32 parent = (UInt32)(Int32)-1; UInt32 parentType = 0; RINOK(arc.GetRawProps->GetParent(i, &parent, &parentType)); @@ -528,14 +614,14 @@ HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress) } } - bool isFolder; - RINOK(Archive_IsItem_Folder(archive, i, isFolder)); + bool isDir; + RINOK(Archive_IsItem_Dir(archive, i, isDir)); - if (isFolder) + if (isDir) { - file.FolderIndex = Folders.Size(); - CProxyFolder2 &folder = Folders.AddNew(); - folder.ArcIndex = i; + file.DirIndex = Dirs.Size(); + CProxyDir2 &dir = Dirs.AddNew(); + dir.ArcIndex = i; } if (arc.Ask_AltStream) RINOK(Archive_IsItem_AltStream(archive, i, file.IsAltStream)); @@ -544,34 +630,57 @@ HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress) for (i = 0; i < numItems; i++) { CProxyFile2 &file = Files[i]; + int dirIndex; + if (file.IsAltStream) { - if (file.Parent >= 0) + if (file.Parent < 0) + dirIndex = k_Proxy2_AltRootDirIndex; + else { - int &folderIndex = Files[file.Parent].AltStreamsFolderIndex; - if (folderIndex < 0) + int &folderIndex2 = Files[file.Parent].AltDirIndex; + if (folderIndex2 < 0) { - folderIndex = Folders.Size(); - CProxyFolder2 &folder = Folders.AddNew(); - folder.ArcIndex = file.Parent; // do we need it ??? + folderIndex2 = Dirs.Size(); + CProxyDir2 &dir = Dirs.AddNew(); + dir.ArcIndex = file.Parent; } - Folders[folderIndex].SubFiles.Add(i); + dirIndex = folderIndex2; } } else { - int folderIndex = GetParentFolderOfFile(i); - if (folderIndex < 0) - return E_FAIL; - Folders[folderIndex].SubFiles.Add(i); + if (file.Parent < 0) + dirIndex = k_Proxy2_RootDirIndex; + else + { + dirIndex = Files[file.Parent].DirIndex; + if (dirIndex < 0) + return E_FAIL; + } } + + Dirs[dirIndex].Items.Add(i); } - CalculateSizes(0, archive); + + for (i = 0; i < k_Proxy2_NumRootDirs; i++) + CalculateSizes(i, archive); + + // } char s[128]; sprintf(s, "Load archive: %7d ms", GetTickCount() - tickCount); OutputDebugStringA(s); - /* - char s[128]; - sprintf(s, "load archive %7d ms", GetTickCount() - tickCount); - OutputDebugStringA(s); - */ return S_OK; } + +int CProxyArc2::FindItem(unsigned dirIndex, const wchar_t *name, bool foldersOnly) const +{ + const CProxyDir2 &dir = Dirs[dirIndex]; + FOR_VECTOR (i, dir.Items) + { + const CProxyFile2 &file = Files[dir.Items[i]]; + if (foldersOnly && file.DirIndex < 0) + continue; + if (CompareFileNames(file.Name, name) == 0) + return i; + } + return -1; +} diff --git a/CPP/7zip/UI/Agent/AgentProxy.h b/CPP/7zip/UI/Agent/AgentProxy.h index 1755d444..49012676 100644 --- a/CPP/7zip/UI/Agent/AgentProxy.h +++ b/CPP/7zip/UI/Agent/AgentProxy.h @@ -7,46 +7,61 @@ struct CProxyFile { - UInt32 Index; - UString Name; + const wchar_t *Name; + unsigned NameLen; + bool NeedDeleteName; + + CProxyFile(): Name(NULL), NameLen(0), NeedDeleteName(false) {} + ~CProxyFile() { if (NeedDeleteName) delete [](wchar_t *)Name; } }; -class CProxyFolder: public CProxyFile +const unsigned k_Proxy_RootDirIndex = 0; + +struct CProxyDir { -public: - int Parent; - CRecordVector<unsigned> Folders; - CObjectVector<CProxyFile> Files; + const wchar_t *Name; + unsigned NameLen; + + int ArcIndex; // index in proxy->Files[] ; -1 if there is no item for that folder + int ParentDir; // index in proxy->Dirs[] ; -1 for root folder; ; + CRecordVector<unsigned> SubDirs; + CRecordVector<unsigned> SubFiles; + UInt64 Size; UInt64 PackSize; UInt32 Crc; - UInt32 NumSubFolders; + UInt32 NumSubDirs; UInt32 NumSubFiles; - bool IsLeaf; bool CrcIsDefined; - CProxyFolder(): Parent(-1) {}; - void AddFileSubItem(UInt32 index, const UString &name); + CProxyDir(): Name(NULL), NameLen(0), ParentDir(-1) {}; + ~CProxyDir() { delete [](wchar_t *)Name; } + void Clear(); + bool IsLeaf() const { return ArcIndex >= 0; } }; -class CProxyArchive +class CProxyArc { - int FindDirSubItemIndex(unsigned folderIndex, const UString &name, unsigned &insertPos) const; + int FindSubDir(unsigned dirIndex, const wchar_t *name, unsigned &insertPos) const; - void CalculateSizes(unsigned folderIndex, IInArchive *archive); - unsigned AddDirSubItem(unsigned folderIndex, UInt32 index, bool leaf, const UString &name); + void CalculateSizes(unsigned dirIndex, IInArchive *archive); + unsigned AddDir(unsigned dirIndex, int arcIndex, const UString &name); public: - CObjectVector<CProxyFolder> Folders; // Folders[0] - isRoot + CObjectVector<CProxyDir> Dirs; // Dirs[0] - root + CObjArray<CProxyFile> Files; // all items from archive in same order + + // returns index in Dirs[], or -1, + int FindSubDir(unsigned dirIndex, const wchar_t *name) const; - int FindDirSubItemIndex(unsigned folderIndex, const UString &name) const; - void GetPathParts(int folderIndex, UStringVector &pathParts) const; - UString GetFullPathPrefix(int folderIndex) const; + void GetDirPathParts(int dirIndex, UStringVector &pathParts) const; + // returns full path of Dirs[dirIndex], including back slash + UString GetDirPath_as_Prefix(int dirIndex) const; - // AddRealIndices DOES ADD also item represented by folderIndex (if it's Leaf) - void AddRealIndices(unsigned folderIndex, CUIntVector &realIndices) const; - int GetRealIndex(unsigned folderIndex, unsigned index) const; - void GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const; + // AddRealIndices DOES ADD also item represented by dirIndex (if it's Leaf) + void AddRealIndices(unsigned dirIndex, CUIntVector &realIndices) const; + int GetRealIndex(unsigned dirIndex, unsigned index) const; + void GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const; HRESULT Load(const CArc &arc, IProgress *progress); }; @@ -56,19 +71,25 @@ public: struct CProxyFile2 { - int FolderIndex; // >= 0 for dir. (index in ProxyArchive2->Folders) - int AltStreamsFolderIndex; // >= 0 if there are alt streams. (index in ProxyArchive2->Folders) - int Parent; // >= 0 if there is parent. (index in archive and in ProxyArchive2->Files) + int DirIndex; // >= 0 for dir. (index in ProxyArchive2->Dirs) + int AltDirIndex; // >= 0 if there are alt streams. (index in ProxyArchive2->Dirs) + int Parent; // >= 0 if there is parent. (index in archive and in ProxyArchive2->Files) const wchar_t *Name; - unsigned NameSize; + unsigned NameLen; + bool NeedDeleteName; bool Ignore; bool IsAltStream; - bool NeedDeleteName; - int GetFolderIndex(bool forAltStreams) const { return forAltStreams ? AltStreamsFolderIndex : FolderIndex; } - - bool IsDir() const { return FolderIndex >= 0; } - CProxyFile2(): FolderIndex(-1), AltStreamsFolderIndex(-1), Name(NULL), Ignore(false), IsAltStream(false), NeedDeleteName(false) {} + int GetDirIndex(bool forAltStreams) const { return forAltStreams ? AltDirIndex : DirIndex; } + + bool IsDir() const { return DirIndex >= 0; } + CProxyFile2(): + DirIndex(-1), AltDirIndex(-1), Parent(-1), + Name(NULL), NameLen(0), + NeedDeleteName(false), + Ignore(false), + IsAltStream(false) + {} ~CProxyFile2() { if (NeedDeleteName) @@ -76,53 +97,66 @@ struct CProxyFile2 } }; -class CProxyFolder2 +struct CProxyDir2 { -public: - Int32 ArcIndex; // = -1 for Root folder - CRecordVector<unsigned> SubFiles; + int ArcIndex; // = -1 for root folders, index in proxy->Files[] + CRecordVector<unsigned> Items; UString PathPrefix; UInt64 Size; UInt64 PackSize; bool CrcIsDefined; UInt32 Crc; - UInt32 NumSubFolders; + UInt32 NumSubDirs; UInt32 NumSubFiles; - CProxyFolder2(): ArcIndex(-1) {}; + CProxyDir2(): ArcIndex(-1) {}; void AddFileSubItem(UInt32 index, const UString &name); void Clear(); - }; -class CProxyArchive2 +const unsigned k_Proxy2_RootDirIndex = k_Proxy_RootDirIndex; +const unsigned k_Proxy2_AltRootDirIndex = 1; +const unsigned k_Proxy2_NumRootDirs = 2; + +class CProxyArc2 { - void CalculateSizes(unsigned folderIndex, IInArchive *archive); - // AddRealIndices_of_Folder DOES NOT ADD item itself represented by folderIndex - void AddRealIndices_of_Folder(unsigned folderIndex, bool includeAltStreams, CUIntVector &realIndices) const; + void CalculateSizes(unsigned dirIndex, IInArchive *archive); + // AddRealIndices_of_Dir DOES NOT ADD item itself represented by dirIndex + void AddRealIndices_of_Dir(unsigned dirIndex, bool includeAltStreams, CUIntVector &realIndices) const; public: - CObjectVector<CProxyFolder2> Folders; // Folders[0] - is root folder - CObjArray<CProxyFile2> Files; // all aitems from archive in same order + CObjectVector<CProxyDir2> Dirs; // Dirs[0] - root folder + // Dirs[1] - for alt streams of root dir + CObjArray<CProxyFile2> Files; // all items from archive in same order - bool IsThere_SubDir(unsigned folderIndex, const UString &name) const; + bool IsThere_SubDir(unsigned dirIndex, const UString &name) const; - void GetPathParts(int folderIndex, UStringVector &pathParts) const; - UString GetFullPathPrefix(unsigned folderIndex) const; + void GetDirPathParts(int dirIndex, UStringVector &pathParts, bool &isAltStreamDir) const; + UString GetDirPath_as_Prefix(unsigned dirIndex, bool &isAltStreamDir) const; + bool IsAltDir(unsigned dirIndex) const; // AddRealIndices_of_ArcItem DOES ADD item and subItems void AddRealIndices_of_ArcItem(unsigned arcIndex, bool includeAltStreams, CUIntVector &realIndices) const; - unsigned GetRealIndex(unsigned folderIndex, unsigned index) const; - void GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const; + unsigned GetRealIndex(unsigned dirIndex, unsigned index) const; + void GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const; HRESULT Load(const CArc &arc, IProgress *progress); - int GetParentFolderOfFile(UInt32 indexInArc) const + int GetParentDirOfFile(UInt32 arcIndex) const { - const CProxyFile2 &file = Files[indexInArc]; + const CProxyFile2 &file = Files[arcIndex]; + if (file.Parent < 0) - return 0; - return Files[file.Parent].FolderIndex; + return file.IsAltStream ? + k_Proxy2_AltRootDirIndex : + k_Proxy2_RootDirIndex; + + const CProxyFile2 &parentFile = Files[file.Parent]; + return file.IsAltStream ? + parentFile.AltDirIndex : + parentFile.DirIndex; } + + int FindItem(unsigned dirIndex, const wchar_t *name, bool foldersOnly) const; }; #endif diff --git a/CPP/7zip/UI/Agent/ArchiveFolder.cpp b/CPP/7zip/UI/Agent/ArchiveFolder.cpp index 81291f44..a20b4f24 100644 --- a/CPP/7zip/UI/Agent/ArchiveFolder.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolder.cpp @@ -28,9 +28,14 @@ STDMETHODIMP CAgentFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 CMyComPtr<IFolderOperationsExtractCallback> callbackWrap = callback; RINOK(callbackWrap.QueryInterface(IID_IFolderArchiveExtractCallback, &extractCallback2)); } - NExtract::NPathMode::EEnum pathMode = _flatMode ? - NExtract::NPathMode::kNoPaths : - NExtract::NPathMode::kCurPaths; + NExtract::NPathMode::EEnum pathMode; + if (!_flatMode) + pathMode = NExtract::NPathMode::kCurPaths; + else + pathMode = (_proxy2 && _loadAltStreams) ? + NExtract::NPathMode::kNoPathsAlt : + NExtract::NPathMode::kNoPaths; + return Extract(indices, numItems, includeAltStreams, replaceAltStreamCharsMode, pathMode, NExtract::NOverwriteMode::kAsk, diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp index 13d94bdf..62d5b1f8 100644 --- a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp @@ -2,21 +2,19 @@ #include "StdAfx.h" +#include "../../../Windows/DLL.h" + #include "Agent.h" void CArchiveFolderManager::LoadFormats() { - if (!_codecs) - { - _compressCodecsInfo = _codecs = new CCodecs; - _codecs->Load(); - } + LoadGlobalCodecs(); } int CArchiveFolderManager::FindFormat(const UString &type) { - FOR_VECTOR (i, _codecs->Formats) - if (type.IsEqualToNoCase(_codecs->Formats[i].Name)) + FOR_VECTOR (i, g_CodecsObj->Formats) + if (type.IsEqualTo_NoCase(g_CodecsObj->Formats[i].Name)) return i; return -1; } @@ -54,7 +52,7 @@ STDMETHODIMP CArchiveFolderManager::GetExtensions(const wchar_t *type, BSTR *ext if (formatIndex < 0) return E_INVALIDARG; // Exts[0].Ext; - return StringToBstr(_codecs.Formats[formatIndex].GetAllExtensions(), extensions); + return StringToBstr(g_CodecsObj.Formats[formatIndex].GetAllExtensions(), extensions); } */ @@ -62,8 +60,7 @@ static void AddIconExt(const CCodecIcons &lib, UString &dest) { FOR_VECTOR (i, lib.IconPairs) { - if (!dest.IsEmpty()) - dest += L' '; + dest.Add_Space_if_NotEmpty(); dest += lib.IconPairs[i].Ext; } } @@ -73,20 +70,30 @@ STDMETHODIMP CArchiveFolderManager::GetExtensions(BSTR *extensions) LoadFormats(); *extensions = 0; UString res; - FOR_VECTOR (i, _codecs->Libs) - AddIconExt(_codecs->Libs[i], res); - AddIconExt(_codecs->InternalIcons, res); + + #ifdef EXTERNAL_CODECS + + FOR_VECTOR (i, g_CodecsObj->Libs) + AddIconExt(g_CodecsObj->Libs[i], res); + + #endif + + AddIconExt(g_CodecsObj->InternalIcons, res); return StringToBstr(res, extensions); } STDMETHODIMP CArchiveFolderManager::GetIconPath(const wchar_t *ext, BSTR *iconPath, Int32 *iconIndex) { - LoadFormats(); *iconPath = 0; *iconIndex = 0; - FOR_VECTOR (i, _codecs->Libs) + + LoadFormats(); + + #ifdef EXTERNAL_CODECS + + FOR_VECTOR (i, g_CodecsObj->Libs) { - const CCodecLib &lib = _codecs->Libs[i]; + const CCodecLib &lib = g_CodecsObj->Libs[i]; int ii; if (lib.FindIconIndex(ext, ii)) { @@ -94,8 +101,11 @@ STDMETHODIMP CArchiveFolderManager::GetIconPath(const wchar_t *ext, BSTR *iconPa return StringToBstr(fs2us(lib.Path), iconPath); } } + + #endif + int ii; - if (_codecs->InternalIcons.FindIconIndex(ext, ii)) + if (g_CodecsObj->InternalIcons.FindIconIndex(ext, ii)) { FString path; if (NWindows::NDLL::MyGetModuleFileName(path)) @@ -112,13 +122,13 @@ STDMETHODIMP CArchiveFolderManager::GetTypes(BSTR *types) { LoadFormats(); UString typesStrings; - FOR_VECTOR(i, _codecs.Formats) + FOR_VECTOR(i, g_CodecsObj.Formats) { - const CArcInfoEx &ai = _codecs.Formats[i]; + const CArcInfoEx &ai = g_CodecsObj.Formats[i]; if (ai.AssociateExts.Size() == 0) continue; if (i != 0) - typesStrings += L' '; + typesStrings.Add_Space(); typesStrings += ai.Name; } return StringToBstr(typesStrings, types); diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp index 003f6d98..325d6426 100644 --- a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp @@ -1,4 +1,4 @@ -// FolderOut.cpp +// ArchiveFolderOut.cpp #include "StdAfx.h" @@ -19,12 +19,12 @@ using namespace NWindows; using namespace NFile; using namespace NDir; -void CAgentFolder::GetPathParts(UStringVector &pathParts) +void CAgentFolder::GetPathParts(UStringVector &pathParts, bool &isAltStreamFolder) { - if (_proxyArchive2) - _proxyArchive2->GetPathParts(_proxyFolderItem, pathParts); + if (_proxy2) + _proxy2->GetDirPathParts(_proxyDirIndex, pathParts, isAltStreamFolder); else - _proxyArchive->GetPathParts(_proxyFolderItem, pathParts); + _proxy->GetDirPathParts(_proxyDirIndex, pathParts); } static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path) @@ -55,16 +55,25 @@ HRESULT CAgentFolder::CommonUpdateOperation( const wchar_t *newItemName, const NUpdateArchive::CActionSet *actionSet, const UInt32 *indices, UInt32 numItems, - IFolderArchiveUpdateCallback *updateCallback100) + IProgress *progress) { if (!_agentSpec->CanUpdate()) return E_NOTIMPL; - //////////////////////////// - // Save FolderItem; + CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100; + if (progress) + progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&updateCallback100); + + try + { + + RINOK(_agentSpec->SetFolder(this)); + + // ---------- Save FolderItem ---------- UStringVector pathParts; - GetPathParts(pathParts); + bool isAltStreamFolder = false; + GetPathParts(pathParts, isAltStreamFolder); FStringVector requestedPaths; FStringVector processedPaths; @@ -153,25 +162,96 @@ HRESULT CAgentFolder::CommonUpdateOperation( } } - { CMyComPtr<IArchiveOpenCallback> openCallback; if (updateCallback100) - { - RINOK(updateCallback100->QueryInterface(IID_IArchiveOpenCallback, (void **)&openCallback)); - } + updateCallback100->QueryInterface(IID_IArchiveOpenCallback, (void **)&openCallback); RINOK(_agentSpec->ReOpen(openCallback)); } - // Restore FolderItem; + // CAgent::ReOpen() deletes _proxy and _proxy2 + _items.Clear(); + _proxy = NULL; + _proxy2 = NULL; + _proxyDirIndex = k_Proxy_RootDirIndex; + _isAltStreamFolder = false; + + + // ---------- Restore FolderItem ---------- CMyComPtr<IFolderFolder> archiveFolder; RINOK(_agentSpec->BindToRootFolder(&archiveFolder)); + + // CAgent::BindToRootFolder() changes _proxy and _proxy2 + _proxy = _agentSpec->_proxy; + _proxy2 = _agentSpec->_proxy2; + + if (_proxy) + { + FOR_VECTOR (i, pathParts) + { + int next = _proxy->FindSubDir(_proxyDirIndex, pathParts[i]); + if (next < 0) + break; + _proxyDirIndex = next; + } + } + + if (_proxy2) + { + if (pathParts.IsEmpty() && isAltStreamFolder) + { + _proxyDirIndex = k_Proxy2_AltRootDirIndex; + } + else FOR_VECTOR (i, pathParts) + { + bool dirOnly = (i + 1 < pathParts.Size() || !isAltStreamFolder); + int index = _proxy2->FindItem(_proxyDirIndex, pathParts[i], dirOnly); + if (index < 0) + break; + + const CProxyFile2 &file = _proxy2->Files[_proxy2->Dirs[_proxyDirIndex].Items[index]]; + + if (dirOnly) + _proxyDirIndex = file.DirIndex; + else + { + if (file.AltDirIndex >= 0) + _proxyDirIndex = file.AltDirIndex; + break; + } + } + } + + /* + if (pathParts.IsEmpty() && isAltStreamFolder) + { + CMyComPtr<IFolderAltStreams> folderAltStreams; + archiveFolder.QueryInterface(IID_IFolderAltStreams, &folderAltStreams); + if (folderAltStreams) + { + CMyComPtr<IFolderFolder> newFolder; + folderAltStreams->BindToAltStreams((UInt32)(Int32)-1, &newFolder); + if (newFolder) + archiveFolder = newFolder; + } + } + FOR_VECTOR (i, pathParts) { CMyComPtr<IFolderFolder> newFolder; - archiveFolder->BindToFolder(pathParts[i], &newFolder); - if(!newFolder) + + if (isAltStreamFolder && i == pathParts.Size() - 1) + { + CMyComPtr<IFolderAltStreams> folderAltStreams; + archiveFolder.QueryInterface(IID_IFolderAltStreams, &folderAltStreams); + if (folderAltStreams) + folderAltStreams->BindToAltStreams(pathParts[i], &newFolder); + } + else + archiveFolder->BindToFolder(pathParts[i], &newFolder); + + if (!newFolder) break; archiveFolder = newFolder; } @@ -180,63 +260,56 @@ HRESULT CAgentFolder::CommonUpdateOperation( RINOK(archiveFolder.QueryInterface(IID_IArchiveFolderInternal, &archiveFolderInternal)); CAgentFolder *agentFolder; RINOK(archiveFolderInternal->GetAgentFolder(&agentFolder)); - _proxyFolderItem = agentFolder->_proxyFolderItem; - _proxyArchive = agentFolder->_proxyArchive; - _proxyArchive2 = agentFolder->_proxyArchive2; - _parentFolder = agentFolder->_parentFolder; + _proxyDirIndex = agentFolder->_proxyDirIndex; + // _parentFolder = agentFolder->_parentFolder; + */ + + if (_proxy2) + _isAltStreamFolder = _proxy2->IsAltDir(_proxyDirIndex); return res; + + } + catch(const UString &s) + { + if (updateCallback100) + { + UString s2 = L"Error: "; + s2 += s; + RINOK(updateCallback100->UpdateErrorMessage(s2)); + return E_FAIL; + } + throw; + } } + + STDMETHODIMP CAgentFolder::CopyFrom(Int32 moveMode, const wchar_t *fromFolderPath, // test it - const wchar_t **itemsPaths, + const wchar_t * const *itemsPaths, UInt32 numItems, IProgress *progress) { COM_TRY_BEGIN - CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100; - if (progress) - { - RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&updateCallback100)); - } - try { RINOK(_agentSpec->SetFiles(fromFolderPath, itemsPaths, numItems)); - RINOK(_agentSpec->SetFolder(this)); return CommonUpdateOperation(AGENT_OP_Uni, (moveMode != 0), NULL, &NUpdateArchive::k_ActionSet_Add, - 0, 0, updateCallback100); - } - catch(const UString &s) - { - RINOK(updateCallback100->UpdateErrorMessage(UString(L"Error: ") + s)); - return E_FAIL; + NULL, 0, progress); } COM_TRY_END } -STDMETHODIMP CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPath, IProgress * progress) +STDMETHODIMP CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPath, IProgress *progress) { COM_TRY_BEGIN CUIntVector indices; indices.Add(destIndex); - CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100; - if (progress) - { - RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&updateCallback100)); - } - try { - RINOK(_agentSpec->SetFolder(this)); return CommonUpdateOperation(AGENT_OP_CopyFromFile, false, itemPath, &NUpdateArchive::k_ActionSet_Add, - &indices.Front(), indices.Size(), updateCallback100); - } - catch(const UString &s) - { - RINOK(updateCallback100->UpdateErrorMessage(UString(L"Error: ") + s)); - return E_FAIL; + &indices.Front(), indices.Size(), progress); } COM_TRY_END } @@ -244,40 +317,30 @@ STDMETHODIMP CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPat STDMETHODIMP CAgentFolder::Delete(const UInt32 *indices, UInt32 numItems, IProgress *progress) { COM_TRY_BEGIN - RINOK(_agentSpec->SetFolder(this)); - CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100; - if (progress) - { - CMyComPtr<IProgress> progressWrapper = progress; - RINOK(progressWrapper.QueryInterface( - IID_IFolderArchiveUpdateCallback, &updateCallback100)); - } return CommonUpdateOperation(AGENT_OP_Delete, false, NULL, - &NUpdateArchive::k_ActionSet_Delete, indices, numItems, updateCallback100); + &NUpdateArchive::k_ActionSet_Delete, indices, numItems, progress); COM_TRY_END } STDMETHODIMP CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress) { COM_TRY_BEGIN - if (_proxyArchive2) + + if (_isAltStreamFolder) + return E_NOTIMPL; + + if (_proxy2) { - if (_proxyArchive2->IsThere_SubDir(_proxyFolderItem, name)) + if (_proxy2->IsThere_SubDir(_proxyDirIndex, name)) return ERROR_ALREADY_EXISTS; } else { - if (_proxyArchive->FindDirSubItemIndex(_proxyFolderItem, name) >= 0) + if (_proxy->FindSubDir(_proxyDirIndex, name) >= 0) return ERROR_ALREADY_EXISTS; } - RINOK(_agentSpec->SetFolder(this)); - CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100; - if (progress) - { - CMyComPtr<IProgress> progressWrapper = progress; - RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100)); - } - return CommonUpdateOperation(AGENT_OP_CreateFolder, false, name, NULL, NULL, 0, updateCallback100); + + return CommonUpdateOperation(AGENT_OP_CreateFolder, false, name, NULL, NULL, 0, progress); COM_TRY_END } @@ -286,15 +349,8 @@ STDMETHODIMP CAgentFolder::Rename(UInt32 index, const wchar_t *newName, IProgres COM_TRY_BEGIN CUIntVector indices; indices.Add(index); - RINOK(_agentSpec->SetFolder(this)); - CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100; - if (progress) - { - CMyComPtr<IProgress> progressWrapper = progress; - RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100)); - } - return CommonUpdateOperation(AGENT_OP_Rename, false, newName, NULL, &indices.Front(), - indices.Size(), updateCallback100); + return CommonUpdateOperation(AGENT_OP_Rename, false, newName, NULL, + &indices.Front(), indices.Size(), progress); COM_TRY_END } diff --git a/CPP/7zip/UI/Agent/IFolderArchive.h b/CPP/7zip/UI/Agent/IFolderArchive.h index 0f87cb55..565e37b0 100644 --- a/CPP/7zip/UI/Agent/IFolderArchive.h +++ b/CPP/7zip/UI/Agent/IFolderArchive.h @@ -15,6 +15,15 @@ #define FOLDER_ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 0x01, x) #define FOLDER_ARCHIVE_INTERFACE(i, x) FOLDER_ARCHIVE_INTERFACE_SUB(i, IUnknown, x) +/* ---------- IArchiveFolder ---------- +IArchiveFolder is implemented by CAgentFolder (Agent/Agent.h) +IArchiveFolder is used by: + - FileManager/PanelCopy.cpp + CPanel::CopyTo(), if (options->testMode) + - FAR/PluginRead.cpp + CPlugin::ExtractFiles +*/ + #define INTERFACE_IArchiveFolder(x) \ STDMETHOD(Extract)(const UInt32 *indices, UInt32 numItems, \ Int32 includeAltStreams, \ @@ -29,6 +38,12 @@ FOLDER_ARCHIVE_INTERFACE(IArchiveFolder, 0x0D) INTERFACE_IArchiveFolder(PURE) }; + +/* ---------- IInFolderArchive ---------- +IInFolderArchive is implemented by CAgent (Agent/Agent.h) +IInFolderArchive Is used by FAR/Plugin +*/ + #define INTERFACE_IInFolderArchive(x) \ STDMETHOD(Open)(IInStream *inStream, const wchar_t *filePath, const wchar_t *arcFormat, BSTR *archiveTypeRes, IArchiveOpenCallback *openArchiveCallback) x; \ STDMETHOD(ReOpen)(IArchiveOpenCallback *openArchiveCallback) x; \ @@ -48,7 +63,7 @@ FOLDER_ARCHIVE_INTERFACE(IInFolderArchive, 0x0E) #define INTERFACE_IFolderArchiveUpdateCallback(x) \ STDMETHOD(CompressOperation)(const wchar_t *name) x; \ STDMETHOD(DeleteOperation)(const wchar_t *name) x; \ - STDMETHOD(OperationResult)(Int32 operationResult) x; \ + STDMETHOD(OperationResult)(Int32 opRes) x; \ STDMETHOD(UpdateErrorMessage)(const wchar_t *message) x; \ STDMETHOD(SetNumFiles)(UInt64 numFiles) x; \ @@ -59,7 +74,7 @@ FOLDER_ARCHIVE_INTERFACE_SUB(IFolderArchiveUpdateCallback, IProgress, 0x0B) #define INTERFACE_IOutFolderArchive(x) \ STDMETHOD(SetFolder)(IFolderFolder *folder) x; \ - STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t **names, UInt32 numNames) x; \ + STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t * const *names, UInt32 numNames) x; \ STDMETHOD(DeleteItems)(ISequentialOutStream *outArchiveStream, \ const UInt32 *indices, UInt32 numItems, IFolderArchiveUpdateCallback *updateCallback) x; \ STDMETHOD(DoOperation)( \ @@ -79,4 +94,26 @@ FOLDER_ARCHIVE_INTERFACE(IOutFolderArchive, 0x0F) INTERFACE_IOutFolderArchive(PURE) }; + +#define INTERFACE_IFolderArchiveUpdateCallback2(x) \ + STDMETHOD(OpenFileError)(const wchar_t *path, HRESULT errorCode) x; \ + STDMETHOD(ReadingFileError)(const wchar_t *path, HRESULT errorCode) x; \ + STDMETHOD(ReportExtractResult)(Int32 opRes, Int32 isEncrypted, const wchar_t *path) x; \ + STDMETHOD(ReportUpdateOperation)(UInt32 notifyOp, const wchar_t *path, Int32 isDir) x; \ + +FOLDER_ARCHIVE_INTERFACE(IFolderArchiveUpdateCallback2, 0x10) +{ + INTERFACE_IFolderArchiveUpdateCallback2(PURE) +}; + + +#define INTERFACE_IFolderScanProgress(x) \ + STDMETHOD(ScanError)(const wchar_t *path, HRESULT errorCode) x; \ + STDMETHOD(ScanProgress)(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, Int32 isDir) x; \ + +FOLDER_ARCHIVE_INTERFACE(IFolderScanProgress, 0x11) +{ + INTERFACE_IFolderScanProgress(PURE) +}; + #endif diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp index cfdacb2f..e2813c80 100644 --- a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp +++ b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp @@ -14,14 +14,24 @@ void CUpdateCallbackAgent::SetCallback(IFolderArchiveUpdateCallback *callback) { Callback = callback; _compressProgress.Release(); + Callback2.Release(); if (Callback) + { Callback.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); + Callback.QueryInterface(IID_IFolderArchiveUpdateCallback2, &Callback2); + } } -HRESULT CUpdateCallbackAgent::SetNumFiles(UInt64 numFiles) +HRESULT CUpdateCallbackAgent::SetNumItems(UInt64 numItems) { if (Callback) - return Callback->SetNumFiles(numFiles); + return Callback->SetNumFiles(numItems); + return S_OK; +} + + +HRESULT CUpdateCallbackAgent::WriteSfx(const wchar_t * /* name */, UInt64 /* size */) +{ return S_OK; } @@ -52,31 +62,65 @@ HRESULT CUpdateCallbackAgent::CheckBreak() return S_OK; } -HRESULT CUpdateCallbackAgent::Finilize() +/* +HRESULT CUpdateCallbackAgent::Finalize() { return S_OK; } +*/ -HRESULT CUpdateCallbackAgent::OpenFileError(const wchar_t *name, DWORD systemError) +HRESULT CUpdateCallbackAgent::OpenFileError(const FString &path, DWORD systemError) { + HRESULT hres = HRESULT_FROM_WIN32(systemError); // if (systemError == ERROR_SHARING_VIOLATION) { + if (Callback2) + { + RINOK(Callback2->OpenFileError(fs2us(path), hres)); + return S_FALSE; + } + if (Callback) { UString s = L"WARNING: "; s += NError::MyFormatMessage(systemError); s += L": "; - s += name; + s += fs2us(path); RINOK(Callback->UpdateErrorMessage(s)); return S_FALSE; } } // FailedFiles.Add(name); - return systemError; + return hres; +} + +HRESULT CUpdateCallbackAgent::ReadingFileError(const FString &path, DWORD systemError) +{ + HRESULT hres = HRESULT_FROM_WIN32(systemError); + + // if (systemError == ERROR_SHARING_VIOLATION) + { + if (Callback2) + { + RINOK(Callback2->ReadingFileError(fs2us(path), hres)); + } + else if (Callback) + { + UString s = L"ERROR: "; + s += NError::MyFormatMessage(systemError); + s += L": "; + s += fs2us(path); + RINOK(Callback->UpdateErrorMessage(s)); + } + } + // FailedFiles.Add(name); + return hres; } -HRESULT CUpdateCallbackAgent::GetStream(const wchar_t *name, bool /* isAnti */) +HRESULT CUpdateCallbackAgent::GetStream(const wchar_t *name, bool isDir, bool /* isAnti */, UInt32 mode) { + if (Callback2) + return Callback2->ReportUpdateOperation(mode, name, BoolToInt(isDir)); if (Callback) return Callback->CompressOperation(name); return S_OK; @@ -89,6 +133,50 @@ HRESULT CUpdateCallbackAgent::SetOperationResult(Int32 operationResult) return S_OK; } +void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s); + +HRESULT CUpdateCallbackAgent::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) +{ + if (Callback2) + { + return Callback2->ReportExtractResult(opRes, isEncrypted, name); + } + /* + if (mode != NArchive::NExtract::NOperationResult::kOK) + { + Int32 encrypted = 0; + UString s; + SetExtractErrorMessage(mode, encrypted, name, s); + // ProgressDialog->Sync.AddError_Message(s); + } + */ + return S_OK; +} + +HRESULT CUpdateCallbackAgent::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool isDir) +{ + if (Callback2) + { + return Callback2->ReportUpdateOperation(op, name, BoolToInt(isDir)); + } + return S_OK; +} + +/* +HRESULT CUpdateCallbackAgent::SetPassword(const UString & + #ifndef _NO_CRYPTO + password + #endif + ) +{ + #ifndef _NO_CRYPTO + PasswordIsDefined = true; + Password = password; + #endif + return S_OK; +} +*/ + HRESULT CUpdateCallbackAgent::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { *password = NULL; @@ -114,9 +202,7 @@ HRESULT CUpdateCallbackAgent::CryptoGetTextPassword(BSTR *password) return getTextPassword->CryptoGetTextPassword(password); } -/* -HRESULT CUpdateCallbackAgent::ShowDeleteFile(const wchar_t *name) +HRESULT CUpdateCallbackAgent::ShowDeleteFile(const wchar_t *name, bool /* isDir */) { return Callback->DeleteOperation(name); } -*/ diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.h b/CPP/7zip/UI/Agent/UpdateCallbackAgent.h index 3707a93c..4da7693c 100644 --- a/CPP/7zip/UI/Agent/UpdateCallbackAgent.h +++ b/CPP/7zip/UI/Agent/UpdateCallbackAgent.h @@ -10,8 +10,10 @@ class CUpdateCallbackAgent: public IUpdateCallbackUI { INTERFACE_IUpdateCallbackUI(;) + CMyComPtr<ICryptoGetTextPassword2> _cryptoGetTextPassword; CMyComPtr<IFolderArchiveUpdateCallback> Callback; + CMyComPtr<IFolderArchiveUpdateCallback2> Callback2; CMyComPtr<ICompressProgressInfo> _compressProgress; public: void SetCallback(IFolderArchiveUpdateCallback *callback); diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp index 0c7ae1c9..4df4b199 100644 --- a/CPP/7zip/UI/Client7z/Client7z.cpp +++ b/CPP/7zip/UI/Client7z/Client7z.cpp @@ -32,8 +32,14 @@ HINSTANCE g_hInstance = 0; // Tou can find the list of all GUIDs in Guid.txt file. // use another CLSIDs, if you want to support other formats (zip, rar, ...). // {23170F69-40C1-278A-1000-000110070000} + DEFINE_GUID(CLSID_CFormat7z, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00); +DEFINE_GUID(CLSID_CFormatXz, + 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x0C, 0x00, 0x00); + +#define CLSID_Format CLSID_CFormat7z +// #define CLSID_Format CLSID_CFormatXz using namespace NWindows; using namespace NFile; @@ -326,7 +332,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, { // Create folders for file - int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR); + int slashPos = _filePath.ReverseFind_PathSepar(); if (slashPos >= 0) CreateComplexDir(_directoryPath + us2fs(_filePath.Left(slashPos))); } @@ -662,7 +668,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOu ConvertUInt32ToString(index + 1, temp); UString res = temp; while (res.Len() < 2) - res = UString(L'0') + res; + res.InsertAtFront(L'0'); UString fileName = VolName; fileName += L'.'; fileName += res; @@ -774,7 +780,7 @@ int MY_CDECL main(int numArgs, const char *args[]) } CMyComPtr<IOutArchive> outArchive; - if (createObjectFunc(&CLSID_CFormat7z, &IID_IOutArchive, (void **)&outArchive) != S_OK) + if (createObjectFunc(&CLSID_Format, &IID_IOutArchive, (void **)&outArchive) != S_OK) { PrintError("Can not get class object"); return 1; @@ -845,7 +851,7 @@ int MY_CDECL main(int numArgs, const char *args[]) } CMyComPtr<IInArchive> archive; - if (createObjectFunc(&CLSID_CFormat7z, &IID_IInArchive, (void **)&archive) != S_OK) + if (createObjectFunc(&CLSID_Format, &IID_IInArchive, (void **)&archive) != S_OK) { PrintError("Can not get class object"); return 1; @@ -867,7 +873,8 @@ int MY_CDECL main(int numArgs, const char *args[]) // openCallbackSpec->PasswordIsDefined = true; // openCallbackSpec->Password = L"1"; - if (archive->Open(file, 0, openCallback) != S_OK) + const UInt64 scanSize = 1 << 23; + if (archive->Open(file, &scanSize, openCallback) != S_OK) { PrintError("Can not open file as archive", archiveName); return 1; diff --git a/CPP/7zip/UI/Client7z/resource.rc b/CPP/7zip/UI/Client7z/resource.rc index 1bb4d4e3..a09bb044 100644 --- a/CPP/7zip/UI/Client7z/resource.rc +++ b/CPP/7zip/UI/Client7z/resource.rc @@ -1,3 +1,3 @@ -#include "../../../../C/7zVersion.rc" +#include "../../MyVersionInfo.rc" MY_VERSION_INFO_APP("7-Zip client", "7zcl") diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp index 0bfed8ab..99013946 100644 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp @@ -59,17 +59,12 @@ static bool StringToUInt32(const wchar_t *s, UInt32 &v) return *end == 0; } -static void AddNewLine(UString &s) -{ - s += L'\n'; -} - CArcCmdLineException::CArcCmdLineException(const char *a, const wchar_t *u) { (*this) += MultiByteToUnicodeString(a); if (u) { - AddNewLine(*this); + this->Add_LF(); (*this) += u; } } @@ -82,37 +77,53 @@ enum Enum kHelp1 = 0, kHelp2, kHelp3, + kDisableHeaders, kDisablePercents, - kArchiveType, + kShowTime, + kLogLevel, + + kOutStream, + kErrStream, + kPercentStream, + kYes, - #ifndef _NO_CRYPTO - kPassword, - #endif + + kShowDialog, + kOverwrite, + + kArchiveType, + kExcludedArcType, + kProperty, kOutputDir, kWorkingDir, + kInclude, kExclude, kArInclude, kArExclude, kNoArName, + kUpdate, kVolume, kRecursed, + + kAffinity, kSfx, + kEmail, + kHash, + kStdIn, kStdOut, - kOverwrite, - kEmail, - kShowDialog, + kLargePages, kListfileCharSet, kConsoleCharSet, kTechMode, + kShareForWrite, kCaseSensitive, - kHash, kArcNameMode, kDisableWildcardParsing, @@ -127,8 +138,11 @@ enum Enum kWriteToAltStreamIfColon, kDeleteAfterCompressing, - kSetArcMTime, - kExcludedArcType + kSetArcMTime + + #ifndef _NO_CRYPTO + , kPassword + #endif }; } @@ -139,6 +153,8 @@ static const char *kRecursedPostCharSet = "0-"; static const char *k_ArcNameMode_PostCharSet = "sea"; +static const char *k_Stream_PostCharSet = "012"; + static inline const EArcNameMode ParseArcNameMode(int postCharIndex) { switch (postCharIndex) @@ -166,7 +182,7 @@ static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|! static const char *kOverwritePostCharSet = "asut"; -NExtract::NOverwriteMode::EEnum k_OverwriteModes[] = +static const NExtract::NOverwriteMode::EEnum k_OverwriteModes[] = { NExtract::NOverwriteMode::kOverwrite, NExtract::NOverwriteMode::kSkip, @@ -179,37 +195,53 @@ static const CSwitchForm kSwitchForms[] = { "?" }, { "h" }, { "-help" }, + { "ba" }, { "bd" }, - { "t", NSwitchType::kString, false, 1 }, + { "bt" }, + { "bb", NSwitchType::kString, false, 0 }, + + { "bso", NSwitchType::kChar, false, 1, k_Stream_PostCharSet }, + { "bse", NSwitchType::kChar, false, 1, k_Stream_PostCharSet }, + { "bsp", NSwitchType::kChar, false, 1, k_Stream_PostCharSet }, + { "y" }, - #ifndef _NO_CRYPTO - { "p", NSwitchType::kString }, - #endif + + { "ad" }, + { "ao", NSwitchType::kChar, false, 1, kOverwritePostCharSet}, + + { "t", NSwitchType::kString, false, 1 }, + { "stx", NSwitchType::kString, true, 1 }, + { "m", NSwitchType::kString, true, 1 }, { "o", NSwitchType::kString, false, 1 }, { "w", NSwitchType::kString }, + { "i", NSwitchType::kString, true, kSomeCludePostStringMinSize}, { "x", NSwitchType::kString, true, kSomeCludePostStringMinSize}, { "ai", NSwitchType::kString, true, kSomeCludePostStringMinSize}, { "ax", NSwitchType::kString, true, kSomeCludePostStringMinSize}, { "an" }, + { "u", NSwitchType::kString, true, 1}, { "v", NSwitchType::kString, true, 1}, { "r", NSwitchType::kChar, false, 0, kRecursedPostCharSet }, + + { "stm", NSwitchType::kString }, { "sfx", NSwitchType::kString }, + { "seml", NSwitchType::kString, false, 0}, + { "scrc", NSwitchType::kString, true, 0 }, + { "si", NSwitchType::kString }, { "so" }, - { "ao", NSwitchType::kChar, false, 1, kOverwritePostCharSet}, - { "seml", NSwitchType::kString, false, 0}, - { "ad" }, + { "slp", NSwitchType::kMinus }, { "scs", NSwitchType::kString }, { "scc", NSwitchType::kString }, { "slt" }, + { "ssw" }, { "ssc", NSwitchType::kMinus }, - { "scrc", NSwitchType::kString, true, 0 }, { "sa", NSwitchType::kChar, false, 1, k_ArcNameMode_PostCharSet }, { "spd" }, @@ -220,24 +252,24 @@ static const CSwitchForm kSwitchForms[] = { "snl", NSwitchType::kMinus }, { "sni" }, { "sns", NSwitchType::kMinus }, - { "snr" }, { "snc" }, { "sdel" }, - { "stl" }, - { "stx", NSwitchType::kString, true, 1 } + { "stl" } + + #ifndef _NO_CRYPTO + , { "p", NSwitchType::kString } + #endif }; static const wchar_t *kUniversalWildcard = L"*"; -static const int kMinNonSwitchWords = 1; -static const int kCommandIndex = 0; +static const unsigned kMinNonSwitchWords = 1; +static const unsigned kCommandIndex = 0; // static const char *kUserErrorMessage = "Incorrect command line"; static const char *kCannotFindListFile = "Cannot find listfile"; static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch."; -// static const char *kIncorrectWildcardInListFile = "Incorrect wildcard in listfile"; -// static const char *kIncorrectWildcardInCommandLine = "Incorrect wildcard in command line"; static const char *kTerminalOutError = "I won't write compressed data to a terminal"; static const char *kSameTerminalError = "I won't write data and program's messages to same terminal"; static const char *kEmptyFilePath = "Empty file path"; @@ -350,13 +382,13 @@ static void AddRenamePair(CObjectVector<CRenamePair> *renamePairs, { UString val; val += pair.OldName; - AddNewLine(val); + val.Add_LF(); val += pair.NewName; - AddNewLine(val); + val.Add_LF(); if (type == NRecursedType::kRecursed) - val += L"-r"; + val.AddAscii("-r"); else if (type == NRecursedType::kRecursed) - val += L"-r0"; + val.AddAscii("-r0"); throw CArcCmdLineException("Unsupported rename command:", val); } } @@ -411,7 +443,7 @@ static void AddToCensorFromNonSwitchesStrings( else if (renamePairs) { if (oldIndex == -1) - oldIndex = startIndex; + oldIndex = i; else { // NRecursedType::EEnum type is used for global wildcard (-i! switches) @@ -461,7 +493,7 @@ static const char *ParseMapWithPaths( if (pos2 < 0) return k_IncorrectMapCommand; - CEventSetEnd eventSetEnd((const wchar_t *)s + (pos2 + 1)); + CEventSetEnd eventSetEnd((const wchar_t *)s + ((unsigned)pos2 + 1)); s.DeleteFrom(pos2); UInt32 size; if (!StringToUInt32(s.Ptr(pos + 1), size) @@ -561,7 +593,7 @@ static void AddSwitchWildcardsToCensor( #endif else { - errorMessage = "Incorrect wildcarc type marker"; + errorMessage = "Incorrect wildcard type marker"; break; } } @@ -579,8 +611,10 @@ static void ConvertToLongName(const UString &prefix, UString &name) return; NFind::CFileInfo fi; const FString path = us2fs(prefix + name); + #ifndef UNDER_CE if (NFile::NName::IsDevicePath(path)) return; + #endif if (fi.Find(path)) name = fs2us(fi.Name); } @@ -617,7 +651,7 @@ static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &no for (unsigned j = i + 1; j < node.SubNodes.Size();) { const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j]; - if (nextNode1.Name.IsEqualToNoCase(nextNode2.Name)) + if (nextNode1.Name.IsEqualTo_NoCase(nextNode2.Name)) { nextNode1.IncludeItems += nextNode2.IncludeItems; nextNode1.ExcludeItems += nextNode2.ExcludeItems; @@ -685,9 +719,9 @@ static bool ParseUpdateCommandString2(const UString &command, c = command[i]; if (c < '0' || c >= '0' + kNumUpdatePairActions) return false; - int actionPos = c - '0'; - actionSet.StateActions[statePos] = (NUpdateArchive::NPairAction::EEnum)(actionPos); - if (kUpdatePairStateNotSupportedActions[statePos] == actionPos) + unsigned actionPos = c - '0'; + actionSet.StateActions[(unsigned)statePos] = (NUpdateArchive::NPairAction::EEnum)(actionPos); + if (kUpdatePairStateNotSupportedActions[(unsigned)statePos] == (int)actionPos) return false; i++; } @@ -817,6 +851,12 @@ static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &pr CArcCmdLineParser::CArcCmdLineParser(): parser(ARRAY_SIZE(kSwitchForms)) {} +static inline void SetStreamMode(const CSwitchResult &sw, unsigned &res) +{ + if (sw.ThereIs) + res = sw.PostCharIndex; +} + void CArcCmdLineParser::Parse1(const UStringVector &commandStrings, CArcCmdLineOptions &options) { @@ -826,10 +866,40 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings, options.IsInTerminal = MY_IS_TERMINAL(stdin); options.IsStdOutTerminal = MY_IS_TERMINAL(stdout); options.IsStdErrTerminal = MY_IS_TERMINAL(stderr); + + options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; + options.StdInMode = parser[NKey::kStdIn].ThereIs; options.StdOutMode = parser[NKey::kStdOut].ThereIs; options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs; - options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; + options.TechMode = parser[NKey::kTechMode].ThereIs; + options.ShowTime = parser[NKey::kShowTime].ThereIs; + + if (parser[NKey::kDisablePercents].ThereIs + || options.StdOutMode + || !options.IsStdOutTerminal) + options.Number_for_Percents = k_OutStream_disabled; + + if (options.StdOutMode) + options.Number_for_Out = k_OutStream_disabled; + + SetStreamMode(parser[NKey::kOutStream], options.Number_for_Out); + SetStreamMode(parser[NKey::kErrStream], options.Number_for_Errors); + SetStreamMode(parser[NKey::kPercentStream], options.Number_for_Percents); + + if (parser[NKey::kLogLevel].ThereIs) + { + const UString &s = parser[NKey::kLogLevel].PostStrings[0]; + if (s.IsEmpty()) + options.LogLevel = 1; + else + { + UInt32 v; + if (!StringToUInt32(s, v)) + throw CArcCmdLineException("Unsupported switch postfix -bb", s); + options.LogLevel = (unsigned)v; + } + } if (parser[NKey::kCaseSensitive].ThereIs) { @@ -838,12 +908,37 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings, options.CaseSensitive = g_CaseSensitive; } - #ifdef _WIN32 options.LargePages = false; if (parser[NKey::kLargePages].ThereIs) - { options.LargePages = !parser[NKey::kLargePages].WithMinus; + + + #ifndef UNDER_CE + + if (parser[NKey::kAffinity].ThereIs) + { + const UString &s = us2fs(parser[NKey::kAffinity].PostStrings[0]); + if (!s.IsEmpty()) + { + UInt32 v = 0; + AString a; + a.SetFromWStr_if_Ascii(s); + if (!a.IsEmpty()) + { + const char *end; + v = ConvertHexStringToUInt32(a, &end); + if (*end != 0) + a.Empty(); + } + if (a.IsEmpty()) + throw CArcCmdLineException("Unsupported switch postfix -stm", s); + + #ifdef _WIN32 + SetProcessAffinityMask(GetCurrentProcess(), v); + #endif + } } + #endif } @@ -855,7 +950,7 @@ struct CCodePagePair static const unsigned kNumByteOnlyCodePages = 3; -static CCodePagePair g_CodePagePairs[] = +static const CCodePagePair g_CodePagePairs[] = { { "utf-8", CP_UTF8 }, { "win", CP_ACP }, @@ -864,7 +959,7 @@ static CCodePagePair g_CodePagePairs[] = { "utf-16be", MY__CP_UTF16BE } }; -static Int32 FindCharset(const NCommandLineParser::CParser &parser, int keyIndex, +static Int32 FindCharset(const NCommandLineParser::CParser &parser, unsigned keyIndex, bool byteOnlyCodePages, Int32 defaultVal) { if (!parser[keyIndex].ThereIs) @@ -887,29 +982,26 @@ static Int32 FindCharset(const NCommandLineParser::CParser &parser, int keyIndex } } -void EnumerateDirItemsAndSort( - bool storeAltStreams, +HRESULT EnumerateDirItemsAndSort( NWildcard::CCensor &censor, NWildcard::ECensorPathMode censorPathMode, const UString &addPathPrefix, UStringVector &sortedPaths, - UStringVector &sortedFullPaths) + UStringVector &sortedFullPaths, + CDirItemsStat &st, + IDirItemsCallback *callback) { - UStringVector paths; + FStringVector paths; + { CDirItems dirItems; + dirItems.Callback = callback; { - dirItems.ScanAltStreams = storeAltStreams; - HRESULT res = EnumerateItems(censor, censorPathMode, addPathPrefix, dirItems, NULL); - if (res != S_OK || dirItems.ErrorPaths.Size() > 0) - { - UString errorPath; - if (dirItems.ErrorPaths.Size() > 0) - errorPath = fs2us(dirItems.ErrorPaths[0]); - throw CArcCmdLineException(kCannotFindArchive, - dirItems.ErrorPaths.Size() > 0 ? (const wchar_t *)errorPath : NULL); - } + HRESULT res = EnumerateItems(censor, censorPathMode, addPathPrefix, dirItems); + st = dirItems.Stat; + RINOK(res); } + FOR_VECTOR (i, dirItems.Items) { const CDirItem &dirItem = dirItems.Items[i]; @@ -924,24 +1016,29 @@ void EnumerateDirItemsAndSort( UStringVector fullPaths; unsigned i; + for (i = 0; i < paths.Size(); i++) { FString fullPath; - NFile::NDir::MyGetFullPathName(us2fs(paths[i]), fullPath); + NFile::NDir::MyGetFullPathName(paths[i], fullPath); fullPaths.Add(fs2us(fullPath)); } + CUIntVector indices; SortFileNames(fullPaths, indices); sortedPaths.ClearAndReserve(indices.Size()); sortedFullPaths.ClearAndReserve(indices.Size()); + for (i = 0; i < indices.Size(); i++) { unsigned index = indices[i]; - sortedPaths.AddInReserved(paths[index]); + sortedPaths.AddInReserved(fs2us(paths[index])); sortedFullPaths.AddInReserved(fullPaths[index]); if (i > 0 && CompareFileNames(sortedFullPaths[i], sortedFullPaths[i - 1]) == 0) throw CArcCmdLineException("Duplicate archive path:", sortedFullPaths[i]); } + + return S_OK; } static void SetBoolPair(NCommandLineParser::CParser &parser, unsigned switchID, CBoolPair &bp) @@ -954,14 +1051,13 @@ static void SetBoolPair(NCommandLineParser::CParser &parser, unsigned switchID, void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) { const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; - int numNonSwitchStrings = nonSwitchStrings.Size(); + unsigned numNonSwitchStrings = nonSwitchStrings.Size(); if (numNonSwitchStrings < kMinNonSwitchWords) throw CArcCmdLineException("The command must be spcified"); if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command)) throw CArcCmdLineException("Unsupported command:", nonSwitchStrings[kCommandIndex]); - options.TechMode = parser[NKey::kTechMode].ThereIs; if (parser[NKey::kHash].ThereIs) options.HashMethods = parser[NKey::kHash].PostStrings; @@ -1012,7 +1108,7 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) AddSwitchWildcardsToCensor(options.Censor, parser[NKey::kExclude].PostStrings, false, recursedType, wildcardMatching, codePage); - int curCommandIndex = kCommandIndex + 1; + unsigned curCommandIndex = kCommandIndex + 1; bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && options.Command.CommandType != NCommandType::kBenchmark && options.Command.CommandType != NCommandType::kInfo && @@ -1035,6 +1131,9 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) options.ArchiveName = nonSwitchStrings[curCommandIndex++]; if (options.ArchiveName.IsEmpty()) throw CArcCmdLineException("Archive name cannot by empty"); + #ifdef _WIN32 + // options.ArchiveName.Replace(L'/', WCHAR_PATH_SEPARATOR); + #endif } AddToCensorFromNonSwitchesStrings(isRename ? &options.UpdateOptions.RenamePairs : NULL, @@ -1060,15 +1159,6 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) SetMethodOptions(parser, options.Properties); - options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs; - - if (options.EnablePercents) - { - if ((options.StdOutMode && !options.IsStdErrTerminal) || - (!options.StdOutMode && !options.IsStdOutTerminal)) - options.EnablePercents = false; - } - if (parser[NKey::kNtSecurity].ThereIs) options.NtSecurity.SetTrueTrue(); SetBoolPair(parser, NKey::kAltStreams, options.AltStreams); @@ -1106,7 +1196,7 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) if (!options.Censor.AllAreRelative()) throw CArcCmdLineException("Cannot use absolute pathnames for this command"); - NWildcard::CCensor arcCensor; + NWildcard::CCensor &arcCensor = options.arcCensor; if (parser[NKey::kArInclude].ThereIs) AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, wildcardMatching, codePage); @@ -1125,21 +1215,7 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) arcCensor.ExtendExclude(); if (options.StdInMode) - { - UString arcName = parser[NKey::kStdIn].PostStrings.Front(); - options.ArchivePathsSorted.Add(arcName); - options.ArchivePathsFullSorted.Add(arcName); - } - else - { - EnumerateDirItemsAndSort( - false, // scanAltStreams - arcCensor, - NWildcard::k_RelatPath, - UString(), // addPathPrefix - options.ArchivePathsSorted, - options.ArchivePathsFullSorted); - } + options.ArcName_for_StdInMode = parser[NKey::kStdIn].PostStrings.Front(); if (isExtractGroupCommand) { @@ -1154,7 +1230,7 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) eo.OverwriteMode = NExtract::NOverwriteMode::kAsk; if (parser[NKey::kOverwrite].ThereIs) { - eo.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex]; + eo.OverwriteMode = k_OverwriteModes[(unsigned)parser[NKey::kOverwrite].PostCharIndex]; eo.OverwriteMode_Force = true; } else if (options.YesToAll) diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.h b/CPP/7zip/UI/Common/ArchiveCommandLine.h index 22e3d4bf..a345505c 100644 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.h +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.h @@ -40,13 +40,18 @@ struct CArcCommand NExtract::NPathMode::EEnum GetPathMode() const; }; +enum +{ + k_OutStream_disabled = 0, + k_OutStream_stdout = 1, + k_OutStream_stderr = 2 +}; + struct CArcCmdLineOptions { bool HelpMode; - #ifdef _WIN32 bool LargePages; - #endif bool CaseSensitiveChange; bool CaseSensitive; @@ -70,12 +75,16 @@ struct CArcCmdLineOptions #endif bool TechMode; + bool ShowTime; UStringVector HashMethods; bool AppendName; - UStringVector ArchivePathsSorted; - UStringVector ArchivePathsFullSorted; + // UStringVector ArchivePathsSorted; + // UStringVector ArchivePathsFullSorted; + NWildcard::CCensor arcCensor; + UString ArcName_for_StdInMode; + CObjectVector<CProperty> Properties; CExtractOptionsBase ExtractOptions; @@ -89,17 +98,32 @@ struct CArcCmdLineOptions CHashOptions HashOptions; UString ArcType; UStringVector ExcludedArcTypes; - bool EnablePercents; + + unsigned Number_for_Out; + unsigned Number_for_Errors; + unsigned Number_for_Percents; + unsigned LogLevel; + + // bool IsOutAllowed() const { return Number_for_Out != k_OutStream_disabled; } // Benchmark UInt32 NumIterations; CArcCmdLineOptions(): + LargePages(false), + CaseSensitiveChange(false), + CaseSensitive(false), + StdInMode(false), StdOutMode(false), - CaseSensitiveChange(false), - CaseSensitive(false) - {}; + + Number_for_Out(k_OutStream_stdout), + Number_for_Errors(k_OutStream_stderr), + Number_for_Percents(k_OutStream_stdout), + + LogLevel(0) + { + }; }; class CArcCmdLineParser @@ -111,12 +135,13 @@ public: void Parse2(CArcCmdLineOptions &options); }; -void EnumerateDirItemsAndSort( - bool storeAltStreams, +HRESULT EnumerateDirItemsAndSort( NWildcard::CCensor &censor, NWildcard::ECensorPathMode pathMode, const UString &addPathPrefix, UStringVector &sortedPaths, - UStringVector &sortedFullPaths); + UStringVector &sortedFullPaths, + CDirItemsStat &st, + IDirItemsCallback *callback); #endif diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp index c1d41238..8410756a 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp @@ -6,9 +6,11 @@ #undef printf #include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #include "../../../Common/Wildcard.h" +#include "../../../Windows/ErrorMsg.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileFind.h" #include "../../../Windows/FileName.h" @@ -84,7 +86,7 @@ int CHardLinkNode::Compare(const CHardLinkNode &a) const return MyCompare(INode, a.INode); } -HRESULT Archive_Get_HardLinkNode(IInArchive *archive, UInt32 index, CHardLinkNode &h, bool &defined) +static HRESULT Archive_Get_HardLinkNode(IInArchive *archive, UInt32 index, CHardLinkNode &h, bool &defined) { h.INode = 0; h.StreamId = (UInt64)(Int64)-1; @@ -128,9 +130,16 @@ HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *r { CHardLinkNode h; bool defined; - RINOK(Archive_Get_HardLinkNode(archive, realIndices ? (*realIndices)[i] : i, h, defined)); + UInt32 realIndex = realIndices ? (*realIndices)[i] : i; + + RINOK(Archive_Get_HardLinkNode(archive, realIndex, h, defined)); if (defined) - hardIDs.Add(h); + { + bool isAltStream = false; + RINOK(Archive_IsItem_AltStream(archive, realIndex, isAltStream)); + if (!isAltStream) + hardIDs.Add(h); + } } } @@ -181,7 +190,7 @@ void CArchiveExtractCallback::Init( IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, bool testMode, const FString &directoryPath, - const UStringVector &removePathParts, + const UStringVector &removePathParts, bool removePartsForAltStreams, UInt64 packSize) { _extractedFolderPaths.Clear(); @@ -191,17 +200,29 @@ void CArchiveExtractCallback::Init( _hardLinks.Clear(); #endif + #ifdef SUPPORT_ALT_STREAMS + _renamedFiles.Clear(); + #endif + _ntOptions = ntOptions; _wildcardCensor = wildcardCensor; _stdOutMode = stdOutMode; _testMode = testMode; - _unpTotal = 1; + + // _progressTotal = 0; + // _progressTotal_Defined = false; + + _progressTotal = _packTotal; + _progressTotal_Defined = true; + _packTotal = packSize; _extractCallback2 = extractCallback2; _compressProgress.Release(); _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); + _extractCallback2.QueryInterface(IID_IArchiveExtractCallbackMessage, &_callbackMessage); + _extractCallback2.QueryInterface(IID_IFolderArchiveExtractCallback2, &_folderArchiveExtractCallback2); #ifndef _SFX @@ -221,19 +242,31 @@ void CArchiveExtractCallback::Init( LocalProgressSpec->SendProgress = false; _removePathParts = removePathParts; + _removePartsForAltStreams = removePartsForAltStreams; + + #ifndef _SFX _baseParentFolder = (UInt32)(Int32)-1; _use_baseParentFolder_mode = false; + #endif _arc = arc; - _directoryPath = directoryPath; - NName::NormalizeDirPathPrefix(_directoryPath); - NDir::MyGetFullPathName(directoryPath, _directoryPathFull); + _dirPathPrefix = directoryPath; + _dirPathPrefix_Full = directoryPath; + #if defined(_WIN32) && !defined(UNDER_CE) + if (!NName::IsAltPathPrefix(_dirPathPrefix)) + #endif + { + NName::NormalizeDirPathPrefix(_dirPathPrefix); + NDir::MyGetFullPathName(directoryPath, _dirPathPrefix_Full); + NName::NormalizeDirPathPrefix(_dirPathPrefix_Full); + } } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size) { COM_TRY_BEGIN - _unpTotal = size; + _progressTotal = size; + _progressTotal_Defined = true; if (!_multiArchives && _extractCallback2) return _extractCallback2->SetTotal(size); return S_OK; @@ -262,18 +295,20 @@ static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal) STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue) { COM_TRY_BEGIN + if (!_extractCallback2) return S_OK; + UInt64 packCur; if (_multiArchives) { - if (completeValue != NULL) - { - UInt64 packCur = LocalProgressSpec->InSize + MyMultDiv64(*completeValue, _unpTotal, _packTotal); - return _extractCallback2->SetCompleted(&packCur); - } + packCur = LocalProgressSpec->InSize; + if (completeValue && _progressTotal_Defined) + packCur += MyMultDiv64(*completeValue, _progressTotal, _packTotal); + completeValue = &packCur; } return _extractCallback2->SetCompleted(completeValue); + COM_TRY_END } @@ -284,13 +319,6 @@ STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const U COM_TRY_END } -#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z') - -static inline bool IsDriveName(const UString &s) -{ - return s.Len() == 2 && s[1] == ':' && IS_LETTER_CHAR(s[0]); -} - void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath) { bool isAbsPath = false; @@ -300,10 +328,10 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat const UString &s = dirPathParts[0]; if (s.IsEmpty()) isAbsPath = true; - #ifdef _WIN32 + #if defined(_WIN32) && !defined(UNDER_CE) else { - if (dirPathParts.Size() > 1 && IsDriveName(s)) + if (NName::IsDrivePath2(s)) isAbsPath = true; } #endif @@ -312,17 +340,17 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat if (_pathMode == NExtract::NPathMode::kAbsPaths && isAbsPath) fullPath.Empty(); else - fullPath = _directoryPath; + fullPath = _dirPathPrefix; FOR_VECTOR (i, dirPathParts) { - if (i > 0) - fullPath += FCHAR_PATH_SEPARATOR; + if (i != 0) + fullPath.Add_PathSepar(); const UString &s = dirPathParts[i]; fullPath += us2fs(s); - #ifdef _WIN32 + #if defined(_WIN32) && !defined(UNDER_CE) if (_pathMode == NExtract::NPathMode::kAbsPaths) - if (i == 0 && IsDriveName(s)) + if (i == 0 && s.Len() == 2 && NName::IsDrivePath2(s)) continue; #endif CreateDir(fullPath); @@ -349,32 +377,57 @@ HRESULT CArchiveExtractCallback::GetUnpackSize() return _arc->GetItemSize(_index, _curSize, _curSizeDefined); } +static void AddPathToMessage(UString &s, const FString &path) +{ + s.AddAscii(" : "); + s += fs2us(path); +} + HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path) { - return _extractCallback2->MessageError( - UString(L"ERROR: ") + - GetUnicodeString(message) + L": " + fs2us(path)); + UString s; + s.AddAscii(message); + AddPathToMessage(s, path); + return _extractCallback2->MessageError(s); +} + +HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path) +{ + DWORD errorCode = GetLastError(); + UString s; + s.AddAscii(message); + if (errorCode != 0) + { + s.AddAscii(" : "); + s += NError::MyFormatMessage(errorCode); + } + AddPathToMessage(s, path); + return _extractCallback2->MessageError(s); } HRESULT CArchiveExtractCallback::SendMessageError2(const char *message, const FString &path1, const FString &path2) { - return _extractCallback2->MessageError( - UString(L"ERROR: ") + - GetUnicodeString(message) + UString(L": ") + fs2us(path1) + UString(L" : ") + fs2us(path2)); + UString s; + s.AddAscii(message); + AddPathToMessage(s, path1); + AddPathToMessage(s, path2); + return _extractCallback2->MessageError(s); } #ifndef _SFX STDMETHODIMP CGetProp::GetProp(PROPID propID, PROPVARIANT *value) { + /* if (propID == kpidName) { COM_TRY_BEGIN - NCOM::CPropVariant prop = Name.Ptr(); + NCOM::CPropVariant prop = Name; prop.Detach(value); return S_OK; COM_TRY_END } + */ return Arc->Archive->GetProperty(IndexInArc, propID, value); } @@ -388,9 +441,9 @@ static UString GetDirPrefixOf(const UString &src) UString s = src; if (!s.IsEmpty()) { - if (s.Back() == WCHAR_PATH_SEPARATOR) + if (IsPathSepar(s.Back())) s.DeleteBack(); - int pos = s.ReverseFind(WCHAR_PATH_SEPARATOR); + int pos = s.ReverseFind_PathSepar(); s.DeleteFrom(pos + 1); } return s; @@ -423,6 +476,71 @@ static bool IsSafePath(const UString &path) #endif +bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include) +{ + bool found = false; + + if (node.CheckPathVect(item.PathParts, !item.MainIsDir, include)) + { + if (!include) + return true; + + #ifdef SUPPORT_ALT_STREAMS + if (!item.IsAltStream) + return true; + #endif + + found = true; + } + + #ifdef SUPPORT_ALT_STREAMS + + if (!item.IsAltStream) + return false; + + UStringVector pathParts2 = item.PathParts; + if (pathParts2.IsEmpty()) + pathParts2.AddNew(); + UString &back = pathParts2.Back(); + back += L':'; + back += item.AltStreamName; + bool include2; + + if (node.CheckPathVect(pathParts2, + true, // isFile, + include2)) + { + include = include2; + return true; + } + + #endif + + return found; +} + +bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item) +{ + bool include; + if (CensorNode_CheckPath2(node, item, include)) + return include; + return false; +} + +static FString MakePath_from_2_Parts(const FString &prefix, const FString &path) +{ + FString s = prefix; + #if defined(_WIN32) && !defined(UNDER_CE) + if (!path.IsEmpty() && path[0] == ':' && !prefix.IsEmpty() && IsPathSepar(prefix.Back())) + { + if (!NName::IsDriveRootPath_SuperAllowed(prefix)) + s.DeleteBack(); + } + #endif + s += path; + return s; +} + STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { COM_TRY_BEGIN @@ -438,19 +556,31 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre _outFileStream.Release(); _encrypted = false; + _position = 0; _isSplit = false; - _isAltStream = false; + _curSize = 0; _curSizeDefined = false; _index = index; - UString fullPath; - IInArchive *archive = _arc->Archive; - RINOK(_arc->GetItemPath(index, fullPath)); - RINOK(Archive_IsItem_Folder(archive, index, _fi.IsDir)); - _filePath = fullPath; + #ifndef _SFX + _item._use_baseParentFolder_mode = _use_baseParentFolder_mode; + if (_use_baseParentFolder_mode) + { + _item._baseParentFolder = _baseParentFolder; + if (_pathMode == NExtract::NPathMode::kFullPaths || + _pathMode == NExtract::NPathMode::kAbsPaths) + _item._baseParentFolder = -1; + } + #endif + + #ifdef SUPPORT_ALT_STREAMS + _item.WriteToAltStreamIfColon = _ntOptions.WriteToAltStreamIfColon; + #endif + + RINOK(_arc->GetItem(index, _item)); { NCOM::CPropVariant prop; @@ -479,7 +609,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre if (prop.vt == VT_BSTR) { isHardLink = true; - linkPath = prop.bstrVal; + linkPath.SetFromBstr(prop.bstrVal); isRelative = false; // TAR: hard links are from root folder of archive } else if (prop.vt == VT_EMPTY) @@ -495,7 +625,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre if (prop.vt == VT_BSTR) { isHardLink = false; - linkPath = prop.bstrVal; + linkPath.SetFromBstr(prop.bstrVal); isRelative = true; // TAR: symbolic links are relative } else if (prop.vt == VT_EMPTY) @@ -528,7 +658,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre isJunction = reparse.IsMountPoint(); isRelative = reparse.IsRelative(); #ifndef _WIN32 - linkPath.Replace(WCHAR_PATH_SEPARATOR, '/', ); + linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); #endif } } @@ -537,7 +667,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre if (!linkPath.IsEmpty()) { #ifdef _WIN32 - linkPath.Replace('/', WCHAR_PATH_SEPARATOR); + linkPath.Replace(L'/', WCHAR_PATH_SEPARATOR); #endif for (;;) @@ -566,7 +696,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre } if (!badPrefix) pathParts.DeleteFrontal(_removePathParts.Size()); - linkPath = MakePathNameFromParts(pathParts); + linkPath = MakePathFromParts(pathParts); } #endif @@ -575,56 +705,97 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre RINOK(GetUnpackSize()); - RINOK(Archive_IsItem_AltStream(archive, index, _isAltStream)); - - if (!_ntOptions.AltStreams.Val && _isAltStream) + #ifdef SUPPORT_ALT_STREAMS + + if (!_ntOptions.AltStreams.Val && _item.IsAltStream) return S_OK; + #endif + + + UStringVector &pathParts = _item.PathParts; + if (_wildcardCensor) { - if (!_wildcardCensor->CheckPath(_isAltStream, fullPath, !_fi.IsDir)) + if (!CensorNode_CheckPath(*_wildcardCensor, _item)) return S_OK; } - - UStringVector pathParts; - + #ifndef _SFX if (_use_baseParentFolder_mode) { - int baseParent = _baseParentFolder; - if (_pathMode == NExtract::NPathMode::kFullPaths || - _pathMode == NExtract::NPathMode::kAbsPaths) - baseParent = -1; - RINOK(_arc->GetItemPathToParent(index, baseParent, pathParts)); - if (_pathMode == NExtract::NPathMode::kNoPaths && !pathParts.IsEmpty()) - pathParts.DeleteFrontal(pathParts.Size() - 1); + if (!pathParts.IsEmpty()) + { + unsigned numRemovePathParts = 0; + + #ifdef SUPPORT_ALT_STREAMS + if (_pathMode == NExtract::NPathMode::kNoPathsAlt && _item.IsAltStream) + numRemovePathParts = pathParts.Size(); + else + #endif + if (_pathMode == NExtract::NPathMode::kNoPaths || + _pathMode == NExtract::NPathMode::kNoPathsAlt) + numRemovePathParts = pathParts.Size() - 1; + pathParts.DeleteFrontal(numRemovePathParts); + } } else + #endif { - SplitPathToParts(fullPath, pathParts); - if (pathParts.IsEmpty()) - return E_FAIL; + { + if (_item.IsDir) + return S_OK; + /* + #ifdef SUPPORT_ALT_STREAMS + if (!_item.IsAltStream) + #endif + return E_FAIL; + */ + } + unsigned numRemovePathParts = 0; switch (_pathMode) { + case NExtract::NPathMode::kFullPaths: case NExtract::NPathMode::kCurPaths: { + if (_removePathParts.IsEmpty()) + break; bool badPrefix = false; - if (pathParts.Size() <= _removePathParts.Size()) + + if (pathParts.Size() < _removePathParts.Size()) badPrefix = true; else { + if (pathParts.Size() == _removePathParts.Size()) + { + if (_removePartsForAltStreams) + { + #ifdef SUPPORT_ALT_STREAMS + if (!_item.IsAltStream) + #endif + badPrefix = true; + } + else + { + if (!_item.MainIsDir) + badPrefix = true; + } + } + + if (!badPrefix) FOR_VECTOR (i, _removePathParts) { - if (!_removePathParts[i].IsEqualToNoCase(pathParts[i])) + if (CompareFileNames(_removePathParts[i], pathParts[i]) != 0) { badPrefix = true; break; } } } + if (badPrefix) { if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) @@ -634,9 +805,22 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre numRemovePathParts = _removePathParts.Size(); break; } + case NExtract::NPathMode::kNoPaths: { - numRemovePathParts = pathParts.Size() - 1; + if (!pathParts.IsEmpty()) + numRemovePathParts = pathParts.Size() - 1; + break; + } + case NExtract::NPathMode::kNoPathsAlt: + { + #ifdef SUPPORT_ALT_STREAMS + if (_item.IsAltStream) + numRemovePathParts = pathParts.Size(); + else + #endif + if (!pathParts.IsEmpty()) + numRemovePathParts = pathParts.Size() - 1; break; } /* @@ -660,9 +844,18 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre } GetProp_Spec->Arc = _arc; GetProp_Spec->IndexInArc = index; - GetProp_Spec->Name = MakePathNameFromParts(pathParts); + UString name = MakePathFromParts(pathParts); + + #ifdef SUPPORT_ALT_STREAMS + if (_item.IsAltStream) + { + if (!pathParts.IsEmpty() || (!_removePartsForAltStreams && _pathMode != NExtract::NPathMode::kNoPathsAlt)) + name += L':'; + name += _item.AltStreamName; + } + #endif - return ExtractToStreamCallback->GetStream7(GetProp_Spec->Name, _fi.IsDir, outStream, askExtractMode, GetProp); + return ExtractToStreamCallback->GetStream7(name, BoolToInt(_item.IsDir), outStream, askExtractMode, GetProp); } #endif @@ -698,18 +891,33 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) bool isAnti = false; RINOK(_arc->IsItemAnti(index, isAnti)); - bool replace = _isAltStream ? - _ntOptions.ReplaceColonForAltStream : - !_ntOptions.WriteToAltStreamIfColon; + Correct_FsPath(_pathMode == NExtract::NPathMode::kAbsPaths, pathParts, _item.MainIsDir); - if (_pathMode != NExtract::NPathMode::kAbsPaths) - MakeCorrectPath(_directoryPath.IsEmpty(), pathParts, replace); - Correct_IfEmptyLastPart(pathParts); - UString processedPath = MakePathNameFromParts(pathParts); + #ifdef SUPPORT_ALT_STREAMS + + if (_item.IsAltStream) + { + UString s = _item.AltStreamName; + Correct_AltStream_Name(s); + bool needColon = ((!_removePartsForAltStreams && _pathMode != NExtract::NPathMode::kNoPathsAlt) || !pathParts.IsEmpty()); + if (pathParts.IsEmpty()) + pathParts.AddNew(); + if (_pathMode == NExtract::NPathMode::kAbsPaths && + NWildcard::GetNumPrefixParts_if_DrivePath(pathParts) == pathParts.Size()) + pathParts.AddNew(); + UString &name = pathParts.Back(); + if (needColon) + name += (wchar_t)(_ntOptions.ReplaceColonForAltStream ? L'_' : L':'); + name += s; + } + + #endif + + UString processedPath = MakePathFromParts(pathParts); if (!isAnti) { - if (!_fi.IsDir) + if (!_item.IsDir) { if (!pathParts.IsEmpty()) pathParts.DeleteBack(); @@ -719,7 +927,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) { FString fullPathNew; CreateComplexDirectory(pathParts, fullPathNew); - if (_fi.IsDir) + if (_item.IsDir) { _extractedFolderPaths.Add(fullPathNew); _extractedFolderIndices.Add(index); @@ -733,11 +941,34 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) FString fullProcessedPath = us2fs(processedPath); - if (_pathMode != NExtract::NPathMode::kAbsPaths || - !NName::IsAbsolutePath(processedPath)) - fullProcessedPath = _directoryPath + fullProcessedPath; + if (_pathMode != NExtract::NPathMode::kAbsPaths + || !NName::IsAbsolutePath(processedPath)) + { + fullProcessedPath = MakePath_from_2_Parts(_dirPathPrefix, fullProcessedPath); + } - if (_fi.IsDir) + #ifdef SUPPORT_ALT_STREAMS + + if (_item.IsAltStream && _item.ParentIndex != (UInt32)(Int32)-1) + { + CIndexToPathPair pair(_item.ParentIndex); + int renIndex = _renamedFiles.FindInSorted(pair); + if (renIndex >= 0) + { + const CIndexToPathPair &pair = _renamedFiles[renIndex]; + fullProcessedPath = pair.Path; + fullProcessedPath += (FChar)':'; + UString s = _item.AltStreamName; + Correct_AltStream_Name(s); + fullProcessedPath += us2fs(s); + } + } + + #endif + + bool isRenamed = false; + + if (_item.IsDir) { _diskFilePath = fullProcessedPath; if (isAnti) @@ -749,6 +980,8 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) } else if (!_isSplit) { + + // ----- Is file (not split) ----- NFind::CFileInfo fileInfo; if (fileInfo.Find(fullProcessedPath)) { @@ -758,21 +991,17 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) return S_OK; case NExtract::NOverwriteMode::kAsk: { - int slashPos = fullProcessedPath.ReverseFind(FTEXT('/')); - #ifdef _WIN32 - int slash1Pos = fullProcessedPath.ReverseFind(FTEXT('\\')); - slashPos = MyMax(slashPos, slash1Pos); - #endif + int slashPos = fullProcessedPath.ReverseFind_PathSepar(); FString realFullProcessedPath = fullProcessedPath.Left(slashPos + 1) + fileInfo.Name; - Int32 overwiteResult; + Int32 overwriteResult; RINOK(_extractCallback2->AskOverwrite( - fs2us(realFullProcessedPath), &fileInfo.MTime, &fileInfo.Size, fullPath, + fs2us(realFullProcessedPath), &fileInfo.MTime, &fileInfo.Size, _item.Path, _fi.MTimeDefined ? &_fi.MTime : NULL, _curSizeDefined ? &_curSize : NULL, - &overwiteResult)) + &overwriteResult)) - switch (overwiteResult) + switch (overwriteResult) { case NOverwriteAnswer::kCancel: return E_ABORT; case NOverwriteAnswer::kNo: return S_OK; @@ -792,6 +1021,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) RINOK(SendMessageError(kCantAutoRename, fullProcessedPath)); return E_FAIL; } + isRenamed = true; } else if (_overwriteMode == NExtract::NOverwriteMode::kRenameExisting) { @@ -801,10 +1031,10 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) RINOK(SendMessageError(kCantAutoRename, fullProcessedPath)); return E_FAIL; } - // MyMoveFile can raname folders. So it's OK to use it folders too + // MyMoveFile can raname folders. So it's OK to use it for folders too if (!MyMoveFile(fullProcessedPath, existPath)) { - RINOK(SendMessageError(kCantRenameFile, fullProcessedPath)); + RINOK(SendMessageError2(kCantRenameFile, existPath, fullProcessedPath)); return E_FAIL; } } @@ -815,18 +1045,45 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) // do we need to delete all files in folder? if (!RemoveDir(fullProcessedPath)) { - RINOK(SendMessageError(kCantDeleteOutputDir, fullProcessedPath)); + RINOK(SendMessageError_with_LastError(kCantDeleteOutputDir, fullProcessedPath)); return S_OK; } } - else if (!DeleteFileAlways(fullProcessedPath)) + else { - RINOK(SendMessageError(kCantDeleteOutputFile, fullProcessedPath)); - return S_OK; - // return E_FAIL; + bool needDelete = true; + if (needDelete) + { + if (!DeleteFileAlways(fullProcessedPath)) + { + RINOK(SendMessageError_with_LastError(kCantDeleteOutputFile, fullProcessedPath)); + return S_OK; + // return E_FAIL; + } + } } } } + else // not Find(fullProcessedPath) + { + // we need to clear READ-ONLY of parent before creating alt stream + #if defined(_WIN32) && !defined(UNDER_CE) + int colonPos = NName::FindAltStreamColon(fullProcessedPath); + if (colonPos >= 0 && fullProcessedPath[(unsigned)colonPos + 1] != 0) + { + FString parentFsPath = fullProcessedPath; + parentFsPath.DeleteFrom(colonPos); + NFind::CFileInfo parentFi; + if (parentFi.Find(parentFsPath)) + { + if (parentFi.IsReadOnly()) + SetFileAttrib(parentFsPath, parentFi.Attrib & ~FILE_ATTRIBUTE_READONLY); + } + } + #endif + } + // ----- END of code for Is file (not split) ----- + } _diskFilePath = fullProcessedPath; @@ -841,7 +1098,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) UString relatPath; if (isRelative) - relatPath = GetDirPrefixOf(_filePath); + relatPath = GetDirPrefixOf(_item.Path); relatPath += linkPath; if (!IsSafePath(relatPath)) @@ -853,7 +1110,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) FString existPath; if (isHardLink || !isRelative) { - if (!NName::GetFullPath(_directoryPathFull, us2fs(relatPath), existPath)) + if (!NName::GetFullPath(_dirPathPrefix_Full, us2fs(relatPath), existPath)) { RINOK(SendMessageError("Incorrect path", us2fs(relatPath))); } @@ -876,7 +1133,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) else if (_ntOptions.SymLinks.Val) { // bool isSymLink = true; // = false for junction - if (_fi.IsDir && !isRelative) + if (_item.IsDir && !isRelative) { // if it's before Vista we use Junction Point // isJunction = true; @@ -889,12 +1146,13 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) CReparseAttr attr; if (!attr.Parse(data, data.Size())) { - return E_FAIL; // "Internal conversion error"; + RINOK(SendMessageError("Internal error for symbolic link file", _item.Path)); + // return E_FAIL; } - - if (!NFile::NIO::SetReparseData(fullProcessedPath, _fi.IsDir, data, (DWORD)data.Size())) + else + if (!NFile::NIO::SetReparseData(fullProcessedPath, _item.IsDir, data, (DWORD)data.Size())) { - RINOK(SendMessageError("Can not set reparse data", fullProcessedPath)); + RINOK(SendMessageError_with_LastError("Can not create symbolic link", fullProcessedPath)); } } } @@ -909,7 +1167,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) bool needWriteFile = true; #ifdef SUPPORT_LINKS - if (!_hardLinks.IDs.IsEmpty()) + if (!_hardLinks.IDs.IsEmpty() && !_item.IsAltStream) { CHardLinkNode h; bool defined; @@ -946,10 +1204,23 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) { // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) { - RINOK(SendMessageError("Can not open output file ", fullProcessedPath)); + RINOK(SendMessageError_with_LastError("Can not open output file", fullProcessedPath)); return S_OK; } } + + + #ifdef SUPPORT_ALT_STREAMS + if (isRenamed && !_item.IsAltStream) + { + CIndexToPathPair pair(index, fullProcessedPath); + unsigned oldSize = _renamedFiles.Size(); + unsigned insertIndex = _renamedFiles.AddToUniqueSorted(pair); + if (oldSize == _renamedFiles.Size()) + _renamedFiles[insertIndex].Path = fullProcessedPath; + } + #endif + if (_isSplit) { RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL)); @@ -1004,25 +1275,33 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) _extractMode = true; break; }; - return _extractCallback2->PrepareOperation(_filePath, _fi.IsDir, + + return _extractCallback2->PrepareOperation(_item.Path, BoolToInt(_item.IsDir), askExtractMode, _isSplit ? &_position: 0); + COM_TRY_END } -STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) +STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes) { COM_TRY_BEGIN #ifndef _SFX if (ExtractToStreamCallback) - return ExtractToStreamCallback->SetOperationResult7(operationResult, _encrypted); + return ExtractToStreamCallback->SetOperationResult7(opRes, BoolToInt(_encrypted)); #endif #ifndef _SFX if (_hashStreamWasUsed) { - _hashStreamSpec->_hash->Final(_fi.IsDir, _isAltStream, _filePath); + _hashStreamSpec->_hash->Final(_item.IsDir, + #ifdef SUPPORT_ALT_STREAMS + _item.IsAltStream + #else + false + #endif + , _item.Path); _curSize = _hashStreamSpec->GetSize(); _curSizeDefined = true; _hashStreamSpec->ReleaseStream(); @@ -1069,40 +1348,61 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) GetUnpackSize(); if (_curSizeDefined) { - if (_isAltStream) + #ifdef SUPPORT_ALT_STREAMS + if (_item.IsAltStream) AltStreams_UnpackSize += _curSize; else + #endif UnpackSize += _curSize; } - if (_fi.IsDir) + if (_item.IsDir) NumFolders++; - else if (_isAltStream) + #ifdef SUPPORT_ALT_STREAMS + else if (_item.IsAltStream) NumAltStreams++; + #endif else NumFiles++; if (_extractMode && _fi.AttribDefined) SetFileAttrib(_diskFilePath, _fi.Attrib); - RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted)); + RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted))); return S_OK; COM_TRY_END } -/* -STDMETHODIMP CArchiveExtractCallback::GetInStream( - const wchar_t *name, ISequentialInStream **inStream) +STDMETHODIMP CArchiveExtractCallback::ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes) { - COM_TRY_BEGIN - CInFileStream *inFile = new CInFileStream; - CMyComPtr<ISequentialInStream> inStreamTemp = inFile; - if (!inFile->Open(_srcDirectoryPrefix + name)) - return ::GetLastError(); - *inStream = inStreamTemp.Detach(); + if (_folderArchiveExtractCallback2) + { + bool isEncrypted = false; + wchar_t temp[16]; + UString s2; + const wchar_t *s = NULL; + + if (indexType == NArchive::NEventIndexType::kInArcIndex && index != (UInt32)(Int32)-1) + { + CReadArcItem item; + RINOK(_arc->GetItem(index, item)); + s2 = item.Path; + s = s2; + RINOK(Archive_GetItemBoolProp(_arc->Archive, index, kpidEncrypted, isEncrypted)); + } + else + { + temp[0] = '#'; + ConvertUInt32ToString(index, temp + 1); + s = temp; + // if (indexType == NArchive::NEventIndexType::kBlockIndex) {} + } + + return _folderArchiveExtractCallback2->ReportExtractResult(opRes, isEncrypted, s); + } + return S_OK; - COM_TRY_END } -*/ + STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) { @@ -1119,8 +1419,8 @@ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) struct CExtrRefSortPair { - int Len; - int Index; + unsigned Len; + unsigned Index; int Compare(const CExtrRefSortPair &a) const; }; @@ -1133,18 +1433,14 @@ int CExtrRefSortPair::Compare(const CExtrRefSortPair &a) const return MyCompare(Index, a.Index); } -static int GetNumSlashes(const FChar *s) +static unsigned GetNumSlashes(const FChar *s) { - for (int numSlashes = 0;;) + for (unsigned numSlashes = 0;;) { FChar c = *s++; if (c == 0) return numSlashes; - if ( - #ifdef _WIN32 - c == FTEXT('\\') || - #endif - c == FTEXT('/')) + if (IS_PATH_SEPAR(c)) numSlashes++; } } diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h index ed41ba8d..561a6e42 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h @@ -76,7 +76,7 @@ class CGetProp: public: const CArc *Arc; UInt32 IndexInArc; - UString Name; // relative path + // UString Name; // relative path MY_UNKNOWN_IMP1(IGetProp) INTERFACE_IGetProp(;) @@ -124,9 +124,27 @@ public: #endif +#ifdef SUPPORT_ALT_STREAMS + +struct CIndexToPathPair +{ + UInt32 Index; + FString Path; + + CIndexToPathPair(UInt32 index): Index(index) {} + CIndexToPathPair(UInt32 index, const FString &path): Index(index), Path(path) {} + + int Compare(const CIndexToPathPair &pair) const + { + return MyCompare(Index, pair.Index); + } +}; + +#endif + class CArchiveExtractCallback: public IArchiveExtractCallback, - // public IArchiveVolumeExtractCallback, + public IArchiveExtractCallbackMessage, public ICryptoGetTextPassword, public ICompressProgressInfo, public CMyUnknownImp @@ -134,12 +152,15 @@ class CArchiveExtractCallback: const CArc *_arc; CExtractNtOptions _ntOptions; - const NWildcard::CCensorNode *_wildcardCensor; + const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin) CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2; CMyComPtr<ICompressProgressInfo> _compressProgress; CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword; - FString _directoryPath; - FString _directoryPathFull; + CMyComPtr<IArchiveExtractCallbackMessage> _callbackMessage; + CMyComPtr<IFolderArchiveExtractCallback2> _folderArchiveExtractCallback2; + + FString _dirPathPrefix; + FString _dirPathPrefix_Full; NExtract::NPathMode::EEnum _pathMode; NExtract::NOverwriteMode::EEnum _overwriteMode; @@ -151,11 +172,10 @@ class CArchiveExtractCallback: #endif + CReadArcItem _item; FString _diskFilePath; - UString _filePath; UInt64 _position; bool _isSplit; - bool _isAltStream; bool _extractMode; @@ -176,8 +196,6 @@ class CArchiveExtractCallback: bool ATimeDefined; bool MTimeDefined; bool AttribDefined; - - bool IsDir; } _fi; UInt32 _index; @@ -194,9 +212,13 @@ class CArchiveExtractCallback: #endif + bool _removePartsForAltStreams; UStringVector _removePathParts; + + #ifndef _SFX bool _use_baseParentFolder_mode; UInt32 _baseParentFolder; + #endif bool _stdOutMode; bool _testMode; @@ -204,7 +226,9 @@ class CArchiveExtractCallback: CMyComPtr<ICompressProgressInfo> _localProgress; UInt64 _packTotal; - UInt64 _unpTotal; + + UInt64 _progressTotal; + bool _progressTotal_Defined; FStringVector _extractedFolderPaths; CRecordVector<UInt32> _extractedFolderIndices; @@ -218,6 +242,7 @@ class CArchiveExtractCallback: HRESULT GetUnpackSize(); HRESULT SendMessageError(const char *message, const FString &path); + HRESULT SendMessageError_with_LastError(const char *message, const FString &path); HRESULT SendMessageError2(const char *message, const FString &path1, const FString &path2); public: @@ -230,16 +255,13 @@ public: UInt64 UnpackSize; UInt64 AltStreams_UnpackSize; - MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo) - // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback) + MY_UNKNOWN_IMP3(IArchiveExtractCallbackMessage, ICryptoGetTextPassword, ICompressProgressInfo) INTERFACE_IArchiveExtractCallback(;) + INTERFACE_IArchiveExtractCallbackMessage(;) STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); - // IArchiveVolumeExtractCallback - // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream); - STDMETHOD(CryptoGetTextPassword)(BSTR *password); CArchiveExtractCallback(); @@ -274,7 +296,7 @@ public: IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, bool testMode, const FString &directoryPath, - const UStringVector &removePathParts, + const UStringVector &removePathParts, bool removePartsForAltStreams, UInt64 packSize); #ifdef SUPPORT_LINKS @@ -285,15 +307,23 @@ public: HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items #endif + #ifdef SUPPORT_ALT_STREAMS + CObjectVector<CIndexToPathPair> _renamedFiles; + #endif + // call it after Init() + #ifndef _SFX void SetBaseParentFolderIndex(UInt32 indexInArc) { - _use_baseParentFolder_mode = true; _baseParentFolder = indexInArc; + _use_baseParentFolder_mode = true; } + #endif HRESULT SetDirsTimes(); }; +bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item); + #endif diff --git a/CPP/7zip/UI/Common/ArchiveName.cpp b/CPP/7zip/UI/Common/ArchiveName.cpp index dcf6590e..06d2ab80 100644 --- a/CPP/7zip/UI/Common/ArchiveName.cpp +++ b/CPP/7zip/UI/Common/ArchiveName.cpp @@ -3,68 +3,76 @@ #include "StdAfx.h" #include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" #include "ExtractingFilePath.h" #include "ArchiveName.h" using namespace NWindows; +using namespace NFile; -UString CreateArchiveName(const NFile::NFind::CFileInfo fileInfo, bool keepName) +UString CreateArchiveName(const NFind::CFileInfo &fi, bool keepName) { - FString resultName = fileInfo.Name; - if (!fileInfo.IsDir() && !keepName) + FString resultName = fi.Name; + if (!fi.IsDir() && !keepName) { - int dotPos = resultName.ReverseFind(FTEXT('.')); + int dotPos = resultName.ReverseFind_Dot(); if (dotPos > 0) { FString archiveName2 = resultName.Left(dotPos); - if (archiveName2.ReverseFind(FTEXT('.')) < 0) + if (archiveName2.ReverseFind_Dot() < 0) resultName = archiveName2; } } - return GetCorrectFsPath(fs2us(resultName)); + return Get_Correct_FsFile_Name(fs2us(resultName)); } -static FString CreateArchiveName2(const FString &srcName, bool fromPrev, bool keepName) +static FString CreateArchiveName2(const FString &path, bool fromPrev, bool keepName) { FString resultName = FTEXT("Archive"); if (fromPrev) { FString dirPrefix; - if (NFile::NDir::GetOnlyDirPrefix(srcName, dirPrefix)) + if (NDir::GetOnlyDirPrefix(path, dirPrefix)) { - if (dirPrefix.Len() > 0) - if (dirPrefix.Back() == FCHAR_PATH_SEPARATOR) + if (!dirPrefix.IsEmpty() && IsPathSepar(dirPrefix.Back())) + { + #if defined(_WIN32) && !defined(UNDER_CE) + if (NName::IsDriveRootPath_SuperAllowed(dirPrefix)) + resultName = dirPrefix[dirPrefix.Len() - 3]; // only letter + else + #endif { dirPrefix.DeleteBack(); - NFile::NFind::CFileInfo fileInfo; - if (fileInfo.Find(dirPrefix)) - resultName = fileInfo.Name; + NFind::CFileInfo fi; + if (fi.Find(dirPrefix)) + resultName = fi.Name; } + } } } else { - NFile::NFind::CFileInfo fileInfo; - if (!fileInfo.Find(srcName)) - // return resultName; - return srcName; - resultName = fileInfo.Name; - if (!fileInfo.IsDir() && !keepName) + NFind::CFileInfo fi; + if (fi.Find(path)) { - int dotPos = resultName.ReverseFind('.'); - if (dotPos > 0) + resultName = fi.Name; + if (!fi.IsDir() && !keepName) { - FString archiveName2 = resultName.Left(dotPos); - if (archiveName2.ReverseFind(FTEXT('.')) < 0) - resultName = archiveName2; + int dotPos = resultName.ReverseFind_Dot(); + if (dotPos > 0) + { + FString name2 = resultName.Left(dotPos); + if (name2.ReverseFind_Dot() < 0) + resultName = name2; + } } } } return resultName; } -UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) +UString CreateArchiveName(const UString &path, bool fromPrev, bool keepName) { - return GetCorrectFsPath(fs2us(CreateArchiveName2(us2fs(srcName), fromPrev, keepName))); + return Get_Correct_FsFile_Name(fs2us(CreateArchiveName2(us2fs(path), fromPrev, keepName))); } diff --git a/CPP/7zip/UI/Common/ArchiveName.h b/CPP/7zip/UI/Common/ArchiveName.h index 99ba086c..ec2f1e8d 100644 --- a/CPP/7zip/UI/Common/ArchiveName.h +++ b/CPP/7zip/UI/Common/ArchiveName.h @@ -7,7 +7,7 @@ #include "../../../Windows/FileFind.h" -UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName); -UString CreateArchiveName(const NWindows::NFile::NFind::CFileInfo fileInfo, bool keepName); +UString CreateArchiveName(const UString &path, bool fromPrev, bool keepName); +UString CreateArchiveName(const NWindows::NFile::NFind::CFileInfo &fileInfo, bool keepName); #endif diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp index e698f56f..2ed68e80 100644 --- a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp @@ -119,6 +119,7 @@ STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password) } if (!Callback) return E_NOTIMPL; + PasswordWasAsked = true; return Callback->Open_CryptoGetTextPassword(password); COM_TRY_END } diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/CPP/7zip/UI/Common/ArchiveOpenCallback.h index 8627de00..afa03766 100644 --- a/CPP/7zip/UI/Common/ArchiveOpenCallback.h +++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.h @@ -20,9 +20,9 @@ #define INTERFACE_IOpenCallbackUI_Crypto(x) \ virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x; \ - virtual HRESULT Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) x; \ - virtual bool Open_WasPasswordAsked() x; \ - virtual void Open_ClearPasswordWasAskedFlag() x; \ + /* virtual HRESULT Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) x; */ \ + /* virtual bool Open_WasPasswordAsked() x; */ \ + /* virtual void Open_Clear_PasswordWasAsked_Flag() x; */ \ #endif @@ -30,6 +30,7 @@ virtual HRESULT Open_CheckBreak() x; \ virtual HRESULT Open_SetTotal(const UInt64 *files, const UInt64 *bytes) x; \ virtual HRESULT Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) x; \ + virtual HRESULT Open_Finished() x; \ INTERFACE_IOpenCallbackUI_Crypto(x) struct IOpenCallbackUI @@ -85,6 +86,8 @@ public: UStringVector FileNames; CBoolVector FileNames_WasUsed; CRecordVector<UInt64> FileSizes; + + bool PasswordWasAsked; IOpenCallbackUI *Callback; CMyComPtr<IArchiveOpenCallback> ReOpenCallback; @@ -101,6 +104,7 @@ public: FileSizes.Clear(); _subArchiveMode = false; // TotalSize = 0; + PasswordWasAsked = false; } bool SetSecondFileInfo(CFSTR newName) { diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp index 8cb65755..c38b132c 100644 --- a/CPP/7zip/UI/Common/Bench.cpp +++ b/CPP/7zip/UI/Common/Bench.cpp @@ -30,7 +30,7 @@ #include "../../../../C/Alloc.h" #include "../../../../C/CpuArch.h" -#if !defined(_7ZIP_ST) || defined(_WIN32) +#if defined(_WIN32) #include "../../../Windows/System.h" #endif @@ -212,7 +212,7 @@ STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processed for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; - if(processedSize != NULL) + if (processedSize) *processedSize = size; return S_OK; } @@ -224,7 +224,7 @@ class CBenchmarkOutStream: { // bool _overflow; public: - UInt32 Pos; + size_t Pos; bool RealCopy; bool CalcCrc; UInt32 Crc; @@ -247,12 +247,15 @@ STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *p size_t curSize = BufferSize - Pos; if (curSize > size) curSize = size; - if (RealCopy) - memcpy(Buffer + Pos, data, curSize); - if (CalcCrc) - Crc = CrcUpdate(Crc, data, curSize); - Pos += (UInt32)curSize; - if(processedSize != NULL) + if (curSize != 0) + { + if (RealCopy) + memcpy(Buffer + Pos, data, curSize); + if (CalcCrc) + Crc = CrcUpdate(Crc, data, curSize); + Pos += curSize; + } + if (processedSize) *processedSize = (UInt32)curSize; if (curSize != size) { @@ -280,7 +283,7 @@ STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *process { if (CalcCrc) Crc = CrcUpdate(Crc, data, size); - if (processedSize != NULL) + if (processedSize) *processedSize = size; return S_OK; } @@ -616,6 +619,7 @@ struct CEncoderInfo CBenchProgressInfo *progressInfoSpec[2]; CMyComPtr<ICompressProgressInfo> progressInfo[2]; UInt64 NumIterations; + #ifdef USE_ALLOCA size_t AllocaSize; #endif @@ -630,10 +634,11 @@ struct CEncoderInfo { CEncoderInfo *Encoder; UInt32 DecoderIndex; + bool CallbackMode; + #ifdef USE_ALLOCA size_t AllocaSize; #endif - bool CallbackMode; }; CDecoderInfo decodersInfo[2]; @@ -647,7 +652,7 @@ struct CEncoderInfo IBenchPrintCallback *printCallback; UInt32 crc; UInt32 kBufferSize; - UInt32 compressedSize; + size_t compressedSize; CBenchRandomGenerator rg; CBenchBuffer rgCopy; // it must be 16-byte aligned !!! CBenchmarkOutStream *propStreamSpec; @@ -671,6 +676,7 @@ struct CEncoderInfo outStreamSpec(0), callback(0), printCallback(0), propStreamSpec(0) {} #ifndef _7ZIP_ST + static THREAD_FUNC_DECL EncodeThreadFunction(void *param) { HRESULT res; @@ -680,6 +686,7 @@ struct CEncoderInfo #ifdef USE_ALLOCA alloca(encoder->AllocaSize); #endif + res = encoder->Encode(); encoder->Results[0] = res; } @@ -691,12 +698,15 @@ struct CEncoderInfo encoder->progressInfoSpec[0]->Status->SetResult(res); return 0; } + static THREAD_FUNC_DECL DecodeThreadFunction(void *param) { CDecoderInfo *decoder = (CDecoderInfo *)param; + #ifdef USE_ALLOCA alloca(decoder->AllocaSize); #endif + CEncoderInfo *encoder = decoder->Encoder; encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex); return 0; @@ -707,7 +717,7 @@ struct CEncoderInfo return thread[0].Create(EncodeThreadFunction, this); } - HRESULT CreateDecoderThread(int index, bool callbackMode + HRESULT CreateDecoderThread(unsigned index, bool callbackMode #ifdef USE_ALLOCA , size_t allocaSize #endif @@ -716,12 +726,15 @@ struct CEncoderInfo CDecoderInfo &decoder = decodersInfo[index]; decoder.DecoderIndex = index; decoder.Encoder = this; + #ifdef USE_ALLOCA decoder.AllocaSize = allocaSize; #endif + decoder.CallbackMode = callbackMode; return thread[index].Create(DecodeThreadFunction, &decoder); } + #endif }; @@ -945,7 +958,7 @@ HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) if (setDecProps) { - RINOK(setDecProps->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos)); + RINOK(setDecProps->SetDecoderProperties2(propStreamSpec->Buffer, (UInt32)propStreamSpec->Pos)); } { @@ -984,7 +997,7 @@ HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) return E_FAIL; memcpy(rgCopy.Buffer, outStreamSpec->Buffer, compressedSize); _decoderFilter->Init(); - _decoderFilter->Filter(rgCopy.Buffer, compressedSize); + _decoderFilter->Filter(rgCopy.Buffer, (UInt32)compressedSize); RINOK(WriteStream(crcOutStream, rgCopy.Buffer, rg.BufferSize)); } else @@ -1021,23 +1034,32 @@ static UInt64 GetNumIterations(UInt64 numCommands, UInt64 complexInCommands) static HRESULT MethodBench( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 complexInCommands, - bool oldLzmaBenchMode, - UInt32 numThreads, + bool + #ifndef _7ZIP_ST + oldLzmaBenchMode + #endif + , + UInt32 + #ifndef _7ZIP_ST + numThreads + #endif + , const COneMethodInfo &method2, UInt32 uncompressedDataSize, unsigned generateDictBits, + IBenchPrintCallback *printCallback, IBenchCallback *callback, CBenchProps *benchProps) { COneMethodInfo method = method2; UInt64 methodId; - UInt32 numInStreams, numOutStreams; + UInt32 numStreams; if (!FindMethod( EXTERNAL_CODECS_LOC_VARS - method.MethodName, methodId, numInStreams, numOutStreams)) + method.MethodName, methodId, numStreams)) return E_NOTIMPL; - if (numInStreams != 1 || numOutStreams != 1) + if (numStreams != 1) return E_INVALIDARG; UInt32 numEncoderThreads = 1; @@ -1051,7 +1073,7 @@ static HRESULT MethodBench( bool fixedNumber; UInt32 numLzmaThreads = method.Get_Lzma_NumThreads(fixedNumber); if (!fixedNumber && numThreads == 1) - method.AddNumThreadsProp(1); + method.AddProp_NumThreads(1); if (numThreads > 1 && numLzmaThreads > 1) { numEncoderThreads = numThreads / 2; @@ -1070,12 +1092,13 @@ static HRESULT MethodBench( encoder.callback = (i == 0) ? callback : 0; encoder.printCallback = printCallback; - CMyComPtr<ICompressCoder2> coder2; - RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId, - encoder._encoderFilter, encoder._encoder, coder2, true, false)); - if (!encoder._encoder && !encoder._encoderFilter) - return E_NOTIMPL; - // encoder._encoderFilter.Release(); // we can disable filter to check the speed of FilterCoder. + { + CCreatedCoder cod; + RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId, true, encoder._encoderFilter, cod)); + encoder._encoder = cod.Coder; + if (!encoder._encoder && !encoder._encoderFilter) + return E_NOTIMPL; + } encoder.CheckCrc_Enc = (benchProps->EncComplex) > 30 ; encoder.CheckCrc_Dec = (benchProps->DecComplexCompr + benchProps->DecComplexUnc) > 30 ; @@ -1086,10 +1109,10 @@ static HRESULT MethodBench( for (UInt32 j = 0; j < numSubDecoderThreads; j++) { - CMyComPtr<ICompressCoder2> coder2de; + CCreatedCoder cod; CMyComPtr<ICompressCoder> &decoder = encoder._decoders[j]; - RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId, - encoder._decoderFilter, decoder, coder2de, false, false)); + RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId, false, encoder._decoderFilter, cod)); + decoder = cod.Coder; if (!encoder._decoderFilter && !decoder) return E_NOTIMPL; } @@ -1135,6 +1158,7 @@ static HRESULT MethodBench( #ifdef USE_ALLOCA encoder.AllocaSize = (i * 16 * 21) & 0x7FF; #endif + RINOK(encoder.CreateEncoderThread()) } else @@ -1208,6 +1232,7 @@ static HRESULT MethodBench( RINOK(encoder.Decode(0)); } } + #ifndef _7ZIP_ST HRESULT res = S_OK; if (numDecoderThreads > 1) @@ -1221,8 +1246,10 @@ static HRESULT MethodBench( } RINOK(res); #endif + RINOK(status.Res); encoders[0].progressInfoSpec[0]->SetFinishTime(info); + #ifndef _7ZIP_ST #ifdef UNDER_CE if (numDecoderThreads > 1) @@ -1235,6 +1262,7 @@ static HRESULT MethodBench( } #endif #endif + info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations; @@ -1246,6 +1274,7 @@ static HRESULT MethodBench( } RINOK(callback->SetDecodeResult(info, false)); RINOK(callback->SetDecodeResult(info, true)); + return S_OK; } @@ -1301,7 +1330,6 @@ static HRESULT CrcBig(const void *data, UInt32 size, UInt64 numIterations, sum ^= GetUi32(hash + j); if (checkSum && sum != *checkSum) { - // printf(" %08X ", sum); return S_FALSE; } } @@ -1316,6 +1344,8 @@ UInt32 g_BenchCpuFreqTemp = 1; #define YY7 YY5 YY5 YY5 YY5 static const UInt32 kNumFreqCommands = 128; +EXTERN_C_BEGIN + static UInt32 CountCpuFreq(UInt32 sum, UInt32 num, UInt32 val) { for (UInt32 i = 0; i < num; i++) @@ -1325,6 +1355,9 @@ static UInt32 CountCpuFreq(UInt32 sum, UInt32 num, UInt32 val) return sum; } +EXTERN_C_END + + #ifndef _7ZIP_ST struct CFreqInfo @@ -1392,6 +1425,10 @@ struct CCrcInfo CMyComPtr<IHasher> Hasher; HRESULT Res; + #ifdef USE_ALLOCA + size_t AllocaSize; + #endif + void Wait() { Thread.Wait(); @@ -1402,6 +1439,11 @@ struct CCrcInfo static THREAD_FUNC_DECL CrcThreadFunction(void *param) { CCrcInfo *p = (CCrcInfo *)param; + + #ifdef USE_ALLOCA + alloca(p->AllocaSize); + #endif + p->Res = CrcBig(p->Data, p->Size, p->NumIterations, p->CheckSumDefined ? &p->CheckSum : NULL, p->Hasher, p->Callback); @@ -1475,6 +1517,7 @@ bool CrcInternalTest() struct CBenchMethod { + unsigned Weight; unsigned DictBits; UInt32 EncComplex; UInt32 DecComplexCompr; @@ -1484,27 +1527,33 @@ struct CBenchMethod static const CBenchMethod g_Bench[] = { - { 17, 357, 145, 20, "LZMA:x1" }, - { 24, 1220, 145, 20, "LZMA:x5:mt1" }, - { 24, 1220, 145, 20, "LZMA:x5:mt2" }, - { 16, 124, 40, 14, "Deflate:x1" }, - { 16, 376, 40, 14, "Deflate:x5" }, - { 16, 1082, 40, 14, "Deflate:x7" }, - { 17, 422, 40, 14, "Deflate64:x5" }, - { 15, 590, 69, 69, "BZip2:x1" }, - { 19, 815, 122, 122, "BZip2:x5" }, - { 19, 815, 122, 122, "BZip2:x5:mt2" }, - { 19, 2530, 122, 122, "BZip2:x7" }, - { 18, 1010, 0, 1150, "PPMD:x1" }, - { 22, 1655, 0, 1830, "PPMD:x5" }, - { 0, 6, 0, 6, "Delta:4" }, - { 0, 4, 0, 4, "BCJ" }, - { 0, 24, 0, 24, "AES256CBC:1" }, - { 0, 8, 0, 2, "AES256CBC:2" } + { 40, 17, 357, 145, 20, "LZMA:x1" }, + { 80, 24, 1220, 145, 20, "LZMA:x5:mt1" }, + { 80, 24, 1220, 145, 20, "LZMA:x5:mt2" }, + + { 10, 16, 124, 40, 14, "Deflate:x1" }, + { 20, 16, 376, 40, 14, "Deflate:x5" }, + { 10, 16, 1082, 40, 14, "Deflate:x7" }, + { 10, 17, 422, 40, 14, "Deflate64:x5" }, + + { 10, 15, 590, 69, 69, "BZip2:x1" }, + { 20, 19, 815, 122, 122, "BZip2:x5" }, + { 10, 19, 815, 122, 122, "BZip2:x5:mt2" }, + { 10, 19, 2530, 122, 122, "BZip2:x7" }, + + { 10, 18, 1010, 0, 1150, "PPMD:x1" }, + { 10, 22, 1655, 0, 1830, "PPMD:x5" }, + + { 2, 0, 6, 0, 6, "Delta:4" }, + { 2, 0, 4, 0, 4, "BCJ" }, + + { 10, 0, 24, 0, 24, "AES256CBC:1" }, + { 2, 0, 8, 0, 2, "AES256CBC:2" } }; struct CBenchHash { + unsigned Weight; UInt32 Complex; UInt32 CheckSum; const char *Name; @@ -1512,26 +1561,32 @@ struct CBenchHash static const CBenchHash g_Hash[] = { - { 558, 0x8F8FEDAB, "CRC32:4" }, - { 339, 0x8F8FEDAB, "CRC32:8" }, - { 512, 0xDF1C17CC, "CRC64" }, - { 11900, 0x2D79FF2E, "SHA256" }, - { 5230, 0x4C25132B, "SHA1" } + { 1, 1820, 0x8F8FEDAB, "CRC32:1" }, + { 10, 558, 0x8F8FEDAB, "CRC32:4" }, + { 10, 339, 0x8F8FEDAB, "CRC32:8" }, + { 10, 512, 0xDF1C17CC, "CRC64" }, + { 10, 5100, 0x2D79FF2E, "SHA256" }, + { 10, 2340, 0x4C25132B, "SHA1" } }; struct CTotalBenchRes { - UInt64 NumIterations; + // UInt64 NumIterations1; // for Usage + UInt64 NumIterations2; // for Rating / RPU + UInt64 Rating; UInt64 Usage; UInt64 RPU; - void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; } + + void Init() { /* NumIterations1 = 0; */ NumIterations2 = 0; Rating = 0; Usage = 0; RPU = 0; } + void SetSum(const CTotalBenchRes &r1, const CTotalBenchRes &r2) { Rating = (r1.Rating + r2.Rating); Usage = (r1.Usage + r2.Usage); RPU = (r1.RPU + r2.RPU); - NumIterations = (r1.NumIterations + r2.NumIterations); + // NumIterations1 = (r1.NumIterations1 + r2.NumIterations1); + NumIterations2 = (r1.NumIterations2 + r2.NumIterations2); } }; @@ -1580,7 +1635,7 @@ static void PrintPercents(IBenchPrintCallback &f, UInt64 val, UInt64 divider, in PrintNumber(f, (val * 100 + divider / 2) / divider, size); } -static void PrintChars(IBenchPrintCallback &f, char c, int size) +static void PrintChars(IBenchPrintCallback &f, char c, unsigned size) { char s[256]; memset(s, (Byte)c, size); @@ -1588,7 +1643,7 @@ static void PrintChars(IBenchPrintCallback &f, char c, int size) f.Print(s); } -static void PrintSpaces(IBenchPrintCallback &f, int size) +static void PrintSpaces(IBenchPrintCallback &f, unsigned size) { PrintChars(f, ' ', size); } @@ -1613,7 +1668,12 @@ static void PrintResults(IBenchPrintCallback &f, UInt64 usage, UInt64 rpu, UInt6 } } -static void PrintResults(IBenchPrintCallback *f, const CBenchInfo &info, UInt64 rating, bool showFreq, UInt64 cpuFreq, CTotalBenchRes *res) +static void PrintResults(IBenchPrintCallback *f, + const CBenchInfo &info, + unsigned weight, + UInt64 rating, + bool showFreq, UInt64 cpuFreq, + CTotalBenchRes *res) { UInt64 speed = info.GetSpeed(info.UnpackSize * info.NumIterations); if (f) @@ -1632,20 +1692,20 @@ static void PrintResults(IBenchPrintCallback *f, const CBenchInfo &info, UInt64 if (res) { - res->NumIterations++; - res->RPU += rpu; - res->Rating += rating; - res->Usage += usage; + // res->NumIterations1++; + res->NumIterations2 += weight; + res->RPU += (rpu * weight); + res->Rating += (rating * weight); + res->Usage += (usage * weight); } } static void PrintTotals(IBenchPrintCallback &f, bool showFreq, UInt64 cpuFreq, const CTotalBenchRes &res) { PrintSpaces(f, 1 + kFieldSize_Speed); - UInt64 numIterations = res.NumIterations; - if (numIterations == 0) - numIterations = 1; - PrintResults(f, res.Usage / numIterations, res.RPU / numIterations, res.Rating / numIterations, showFreq, cpuFreq); + // UInt64 numIterations1 = res.NumIterations1; if (numIterations1 == 0) numIterations1 = 1; + UInt64 numIterations2 = res.NumIterations2; if (numIterations2 == 0) numIterations2 = 1; + PrintResults(f, res.Usage / numIterations2, res.RPU / numIterations2, res.Rating / numIterations2, showFreq, cpuFreq); } static void PrintRequirements(IBenchPrintCallback &f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads) @@ -1673,7 +1733,17 @@ struct CBenchCallbackToPrint: public IBenchCallback bool ShowFreq; UInt64 CpuFreq; - CBenchCallbackToPrint(): Use2Columns(false), NameFieldSize(0), ShowFreq(false), CpuFreq(0) {} + unsigned EncodeWeight; + unsigned DecodeWeight; + + CBenchCallbackToPrint(): + Use2Columns(false), + NameFieldSize(0), + ShowFreq(false), + CpuFreq(0), + EncodeWeight(1), + DecodeWeight(1) + {} void Init() { EncodeRes.Init(); DecodeRes.Init(); } void Print(const char *s); @@ -1697,7 +1767,11 @@ HRESULT CBenchCallbackToPrint::SetEncodeResult(const CBenchInfo &info, bool fina if (final) { UInt64 rating = BenchProps.GetCompressRating(DictSize, info.GlobalTime, info.GlobalFreq, info.UnpackSize * info.NumIterations); - PrintResults(_file, info, rating, ShowFreq, CpuFreq, &EncodeRes); + PrintResults(_file, info, + EncodeWeight, rating, + ShowFreq, CpuFreq, &EncodeRes); + if (!Use2Columns) + _file->NewLine(); } return S_OK; } @@ -1713,15 +1787,14 @@ HRESULT CBenchCallbackToPrint::SetDecodeResult(const CBenchInfo &info, bool fina if (Use2Columns) _file->Print(kSep); else - { - _file->NewLine(); PrintSpaces(*_file, NameFieldSize); - } CBenchInfo info2 = info; info2.UnpackSize *= info2.NumIterations; info2.PackSize *= info2.NumIterations; info2.NumIterations = 1; - PrintResults(_file, info2, rating, ShowFreq, CpuFreq, &DecodeRes); + PrintResults(_file, info2, + DecodeWeight, rating, + ShowFreq, CpuFreq, &DecodeRes); } return S_OK; } @@ -1759,7 +1832,7 @@ static HRESULT TotalBench( { for (unsigned i = 0; i < ARRAY_SIZE(g_Bench); i++) { - CBenchMethod bench = g_Bench[i]; + const CBenchMethod &bench = g_Bench[i]; PrintLeft(*callback->_file, bench.Name, kFieldSize_Name); callback->BenchProps.DecComplexUnc = bench.DecComplexUnc; callback->BenchProps.DecComplexCompr = bench.DecComplexCompr; @@ -1767,12 +1840,15 @@ static HRESULT TotalBench( COneMethodInfo method; NCOM::CPropVariant propVariant; propVariant = bench.Name; - RINOK(method.ParseMethodFromPROPVARIANT(L"", propVariant)); + RINOK(method.ParseMethodFromPROPVARIANT(UString(), propVariant)); UInt32 unpackSize2 = unpackSize; if (!forceUnpackSize && bench.DictBits == 0) unpackSize2 = kFilterUnpackSize; + callback->EncodeWeight = bench.Weight; + callback->DecodeWeight = bench.Weight; + HRESULT res = MethodBench( EXTERNAL_CODECS_LOC_VARS complexInCommands, @@ -1874,7 +1950,10 @@ static HRESULT FreqBench( UInt64 numCommands = (UInt64)numIterations * bufferSize * numThreads * complexity; UInt64 rating = info.GetSpeed(numCommands); cpuFreq = rating / numThreads; - PrintResults(_file, info, rating, showFreq, showFreq ? cpuFreq : 0, NULL); + PrintResults(_file, info, + 0, // weight + rating, + showFreq, showFreq ? cpuFreq : 0, NULL); } RINOK(_file->CheckBreak()); } @@ -1889,7 +1968,7 @@ static HRESULT CrcBench( UInt64 complexInCommands, UInt32 numThreads, UInt32 bufferSize, UInt64 &speed, - UInt32 complexity, + UInt32 complexity, unsigned benchWeight, const UInt32 *checkSum, const COneMethodInfo &method, IBenchPrintCallback *_file, @@ -1903,7 +1982,7 @@ static HRESULT CrcBench( numThreads = 1; #endif - UString methodName = method.MethodName; + AString methodName = method.MethodName; // methodName.RemoveChar(L'-'); CMethodId hashID; if (!FindHashMethod( @@ -1932,11 +2011,12 @@ static HRESULT CrcBench( if (numThreads > 1) { threads.Items = new CCrcInfo[numThreads]; + UInt32 i; for (i = 0; i < numThreads; i++) { CCrcInfo &info = threads.Items[i]; - UString name; + AString name; RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, info.Hasher)); if (!info.Hasher) return E_NOTIMPL; @@ -1960,8 +2040,14 @@ static HRESULT CrcBench( info.CheckSum = *checkSum; info.CheckSumDefined = (checkSum && (i == 0)); } + + #ifdef USE_ALLOCA + info.AllocaSize = (i * 16 * 21) & 0x7FF; + #endif } + progressInfoSpec.SetStartTime(); + for (i = 0; i < numThreads; i++) { CCrcInfo &info = threads.Items[i]; @@ -1980,7 +2066,7 @@ static HRESULT CrcBench( /* UInt32 crc = */ RandGenCrc(buf, bufferSize, RG); progressInfoSpec.SetStartTime(); CMyComPtr<IHasher> hasher; - UString name; + AString name; RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, hasher)); if (!hasher) return E_NOTIMPL; @@ -1993,6 +2079,7 @@ static HRESULT CrcBench( } RINOK(CrcBig(buf, bufferSize, numIterations, checkSum, hasher, _file)); } + CBenchInfo info; progressInfoSpec.SetFinishTime(info); @@ -2007,7 +2094,9 @@ static HRESULT CrcBench( { UInt64 numCommands = unpSizeThreads * complexity / 256; UInt64 rating = info.GetSpeed(numCommands); - PrintResults(_file, info, rating, showFreq, cpuFreq, encodeRes); + PrintResults(_file, info, + benchWeight, rating, + showFreq, cpuFreq, encodeRes); } RINOK(_file->CheckBreak()); } @@ -2036,7 +2125,7 @@ static HRESULT TotalBench_Hash( COneMethodInfo method; NCOM::CPropVariant propVariant; propVariant = bench.Name; - RINOK(method.ParseMethodFromPROPVARIANT(L"", propVariant)); + RINOK(method.ParseMethodFromPROPVARIANT(UString(), propVariant)); UInt64 speed; HRESULT res = CrcBench( @@ -2044,7 +2133,8 @@ static HRESULT TotalBench_Hash( complexInCommands, numThreads, bufSize, speed, - bench.Complex, &bench.CheckSum, method, + bench.Complex, bench.Weight, + &bench.CheckSum, method, printCallback, encodeRes, showFreq, cpuFreq); if (res == E_NOTIMPL) { @@ -2087,19 +2177,103 @@ static UInt32 GetNumThreadsNext(unsigned i, UInt32 numThreads) return (num <= numThreads) ? num : numThreads; } -static bool AreSameMethodNames(const char *fullName, const wchar_t *shortName) +static bool AreSameMethodNames(const char *fullName, const char *shortName) { for (;;) { - wchar_t c2 = *shortName++; + char c2 = *shortName++; if (c2 == 0) return true; char c1 = *fullName++; - if ((unsigned char)MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) + if (MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) return false; } } + +#ifdef MY_CPU_X86_OR_AMD64 + +static void PrintCpuChars(AString &s, UInt32 v) +{ + for (int j = 0; j < 4; j++) + { + Byte b = (Byte)(v & 0xFF); + v >>= 8; + if (b == 0) + break; + s += (char)b; + } +} + +static void x86cpuid_to_String(const Cx86cpuid &c, AString &s) +{ + s.Empty(); + + UInt32 maxFunc2 = 0; + UInt32 t[3]; + + MyCPUID(0x80000000, &maxFunc2, &t[0], &t[1], &t[2]); + + bool fullNameIsAvail = (maxFunc2 >= 0x80000004); + + if (!fullNameIsAvail) + { + for (int i = 0; i < 3; i++) + PrintCpuChars(s, c.vendor[i]); + } + else + { + for (int i = 0; i < 3; i++) + { + UInt32 c[4] = { 0 }; + MyCPUID(0x80000002 + i, &c[0], &c[1], &c[2], &c[3]); + for (int j = 0; j < 4; j++) + PrintCpuChars(s, c[j]); + } + } + + s.Add_Space_if_NotEmpty(); + { + char temp[32]; + ConvertUInt32ToHex(c.ver, temp); + s += '('; + s += temp; + s += ')'; + } +} + +#endif + + +void GetCpuName(AString &s) +{ + s.Empty(); + + #ifdef MY_CPU_X86_OR_AMD64 + { + Cx86cpuid cpuid; + if (x86cpuid_CheckAndRead(&cpuid)) + { + x86cpuid_to_String(cpuid, s); + return; + } + #ifdef MY_CPU_AMD64 + s = "x64"; + #else + s = "x86"; + #endif + } + #else + + #ifdef MY_CPU_LE + s = "LE"; + #elif defined(MY_CPU_BE) + s = "BE"; + #endif + + #endif +} + HRESULT Bench( DECL_EXTERNAL_CODECS_LOC_VARS IBenchPrintCallback *printCallback, @@ -2113,16 +2287,21 @@ HRESULT Bench( UInt32 numCPUs = 1; UInt64 ramSize = (UInt64)512 << 20; + #ifndef _7ZIP_ST numCPUs = NSystem::GetNumberOfProcessors(); #endif - #if !defined(_7ZIP_ST) || defined(_WIN32) + + #if defined(_WIN32) ramSize = NSystem::GetRamSize(); #endif - UInt32 numThreads = numCPUs; + + UInt32 numThreadsSpecified = numCPUs; UInt32 testTime = kComplexInSeconds; + bool multiThreadTests = false; + COneMethodInfo method; unsigned i; for (i = 0; i < props.Size(); i++) @@ -2138,10 +2317,24 @@ HRESULT Bench( RINOK(ParsePropToUInt32(L"", propVariant, testTime)); continue; } - if (name.IsPrefixedBy(L"mt")) + if (name.IsPrefixedBy_Ascii_NoCase("mt")) { + UString s = name.Ptr(2); + if (s == L"*") + { + multiThreadTests = true; + continue; + } + if (s.IsEmpty() && propVariant.vt == VT_BSTR) + { + if (wcscmp(propVariant.bstrVal, L"*") == 0) + { + multiThreadTests = true; + continue; + } + } #ifndef _7ZIP_ST - RINOK(ParseMtProp(name.Ptr(2), propVariant, numCPUs, numThreads)); + RINOK(ParseMtProp(s, propVariant, numCPUs, numThreadsSpecified)); #endif continue; } @@ -2150,17 +2343,28 @@ HRESULT Bench( if (printCallback) { + AString s; + GetCpuName(s); + printCallback->Print(s); + printCallback->NewLine(); + } + + if (printCallback) + { printCallback->Print("CPU Freq:"); } UInt64 complexInCommands = kComplexInCommands; - if (printCallback) + if (printCallback /* || benchCallback */) { UInt64 numMilCommands = (1 << 6); for (int jj = 0;; jj++) { + if (printCallback) + RINOK(printCallback->CheckBreak()); + UInt64 start = ::GetTimeCount(); UInt32 sum = (UInt32)start; sum = CountCpuFreq(sum, (UInt32)(numMilCommands * 1000000 / kNumFreqCommands), g_BenchCpuFreqTemp); @@ -2168,12 +2372,18 @@ HRESULT Bench( if (start == 0) start = 1; UInt64 freq = GetFreq(); - UInt64 mipsVal = numMilCommands * freq / start; + UInt64 mips = numMilCommands * freq / start; if (printCallback) - PrintNumber(*printCallback, mipsVal, 5 + ((sum >> 31) & 1)); + PrintNumber(*printCallback, mips, 5 + ((sum == 0xF1541213) ? 1 : 0)); + + /* + if (benchCallback) + benchCallback->AddCpuFreq(mips); + */ + if (jj >= 3) { - SetComplexCommands(testTime, mipsVal * 1000000, complexInCommands); + SetComplexCommands(testTime, mips * 1000000, complexInCommands); if (jj >= 8 || start >= freq) break; // break; // change it @@ -2181,6 +2391,7 @@ HRESULT Bench( } } } + if (printCallback) { printCallback->NewLine(); @@ -2188,14 +2399,14 @@ HRESULT Bench( PrintRequirements(*printCallback, "size: ", ramSize, "CPU hardware threads:", numCPUs); } - if (numThreads < 1 || numThreads > kNumThreadsMax) + if (numThreadsSpecified < 1 || numThreadsSpecified > kNumThreadsMax) return E_INVALIDARG; UInt32 dict; bool dictIsDefined = method.Get_DicSize(dict); if (method.MethodName.IsEmpty()) - method.MethodName = L"LZMA"; + method.MethodName = "LZMA"; if (benchCallback) { @@ -2206,16 +2417,17 @@ HRESULT Bench( return MethodBench( EXTERNAL_CODECS_LOC_VARS complexInCommands, - true, numThreads, + true, numThreadsSpecified, method, uncompressedDataSize, kOldLzmaDictBits, printCallback, benchCallback, &benchProps); } - UString methodName = method.MethodName; - if (methodName.IsEqualToNoCase(L"CRC")) - methodName = L"crc32"; + AString methodName = method.MethodName; + if (methodName.IsEqualTo_Ascii_NoCase("CRC")) + methodName = "crc32"; method.MethodName = methodName; CMethodId hashID; + if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS methodName, hashID)) { if (!printCallback) @@ -2232,11 +2444,20 @@ HRESULT Bench( for (unsigned i = 0; i < ARRAY_SIZE(g_Hash); i++) { const CBenchHash &h = g_Hash[i]; - if (AreSameMethodNames(h.Name, methodName)) + AString s = h.Name; + AString hProp; + int propPos = s.Find(':'); + if (propPos >= 0) + { + hProp = s.Ptr(propPos + 1); + s.DeleteFrom(propPos); + } + + if (AreSameMethodNames(s, methodName)) { complexity = h.Complex; checkSum = &h.CheckSum; - if (strcmp(h.Name, "CRC32:4") != 0) + if (method.PropsString.IsEqualTo_Ascii_NoCase(hProp)) break; } } @@ -2248,10 +2469,10 @@ HRESULT Bench( unsigned numThreadsTests = 0; for (;;) { - UInt32 t = GetNumThreadsNext(numThreadsTests, numThreads); + UInt32 t = GetNumThreadsNext(numThreadsTests, numThreadsSpecified); PrintNumber(f, t, kFieldSize_CrcSpeed); numThreadsTests++; - if (t >= numThreads) + if (t >= numThreadsSpecified) break; } f.NewLine(); @@ -2272,7 +2493,7 @@ HRESULT Bench( break; char s[16]; ConvertUInt32ToString(pow, s); - int pos = MyStringLen(s); + unsigned pos = MyStringLen(s); s[pos++] = ':'; s[pos++] = ' '; s[pos] = 0; @@ -2281,10 +2502,12 @@ HRESULT Bench( for (unsigned ti = 0; ti < numThreadsTests; ti++) { RINOK(f.CheckBreak()); - UInt32 t = GetNumThreadsNext(ti, numThreads); + UInt32 t = GetNumThreadsNext(ti, numThreadsSpecified); UInt64 speed = 0; RINOK(CrcBench(EXTERNAL_CODECS_LOC_VARS complexInCommands, - t, bufSize, speed, complexity, + t, bufSize, speed, + complexity, + 1, // benchWeight, (pow == kNumHashDictBits) ? checkSum : NULL, method, NULL, NULL, false, 0)); PrintNumber(f, (speed >> 20), kFieldSize_CrcSpeed); speedTotals.Values[ti] += speed; @@ -2308,23 +2531,60 @@ HRESULT Bench( bool use2Columns = false; + bool totalBenchMode = (method.MethodName.IsEqualTo_Ascii_NoCase("*")); + + // ---------- Threads loop ---------- + for (unsigned threadsPassIndex = 0; threadsPassIndex < 3; threadsPassIndex++) + { + + UInt32 numThreads = numThreadsSpecified; + + if (!multiThreadTests) + { + if (threadsPassIndex != 0) + break; + } + else + { + numThreads = 1; + if (threadsPassIndex != 0) + { + if (numCPUs < 2) + break; + numThreads = numCPUs; + if (threadsPassIndex == 1) + { + if (numCPUs >= 4) + numThreads = numCPUs / 2; + } + else if (numCPUs < 4) + break; + } + } + CBenchCallbackToPrint callback; callback.Init(); callback._file = printCallback; + + IBenchPrintCallback &f = *printCallback; + + if (threadsPassIndex > 0) + { + f.NewLine(); + f.NewLine(); + } if (!dictIsDefined) { - int dicSizeLog; - for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--) + unsigned dicSizeLog = (totalBenchMode ? 24 : 25); + for (; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--) if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize) break; - dict = (1 << dicSizeLog); + dict = (UInt32)1 << dicSizeLog; } - IBenchPrintCallback &f = *printCallback; PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dict), "Benchmark threads: ", numThreads); - bool totalBenchMode = (method.MethodName == L"*"); f.NewLine(); if (totalBenchMode) @@ -2385,7 +2645,7 @@ HRESULT Bench( for (j = 0; j < 2; j++) { - PrintRight(f, "KB/s", kFieldSize_Speed + 1); + PrintRight(f, "KiB/s", kFieldSize_Speed + 1); PrintRight(f, "%", kFieldSize_Usage + 1); PrintRight(f, "MIPS", kFieldSize_RU + 1); PrintRight(f, "MIPS", kFieldSize_Rating + 1); @@ -2453,7 +2713,7 @@ HRESULT Bench( else { bool needSetComplexity = true; - if (!methodName.IsEqualToNoCase(L"LZMA")) + if (!methodName.IsEqualTo_Ascii_NoCase("LZMA")) { for (unsigned i = 0; i < ARRAY_SIZE(g_Bench); i++) { @@ -2492,7 +2752,7 @@ HRESULT Bench( COneMethodInfo method2 = method; - if (StringsAreEqualNoCase_Ascii(method2.MethodName, L"LZMA")) + if (StringsAreEqualNoCase_Ascii(method2.MethodName, "LZMA")) { // We add dictionary size property. // method2 can have two different dictionary size properties. @@ -2526,7 +2786,9 @@ HRESULT Bench( f.Print(kSep); PrintChars(f, '-', fileldSize); } + f.NewLine(); + if (use2Columns) { PrintLeft(f, "Avr:", callback.NameFieldSize); @@ -2535,10 +2797,13 @@ HRESULT Bench( PrintTotals(f, showFreq, cpuFreq, callback.DecodeRes); f.NewLine(); } + PrintLeft(f, "Tot:", callback.NameFieldSize); CTotalBenchRes midRes; midRes.SetSum(callback.EncodeRes, callback.DecodeRes); PrintTotals(f, showFreq, cpuFreq, midRes); f.NewLine(); + + } return S_OK; } diff --git a/CPP/7zip/UI/Common/CompressCall.cpp b/CPP/7zip/UI/Common/CompressCall.cpp index f5407b03..37da9d1a 100644 --- a/CPP/7zip/UI/Common/CompressCall.cpp +++ b/CPP/7zip/UI/Common/CompressCall.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include <wchar.h> + #include "../../../Common/IntToString.h" #include "../../../Common/MyCom.h" #include "../../../Common/Random.h" @@ -21,25 +23,32 @@ using namespace NWindows; #define MY_TRY_BEGIN try { + #define MY_TRY_FINISH } \ catch(...) { ErrorMessageHRESULT(E_FAIL); return E_FAIL; } + #define MY_TRY_FINISH_VOID } \ catch(...) { ErrorMessageHRESULT(E_FAIL); } -static LPCWSTR kShowDialogSwitch = L" -ad"; -static LPCWSTR kEmailSwitch = L" -seml."; -static LPCWSTR kIncludeSwitch = L" -i"; -static LPCWSTR kArchiveTypeSwitch = L" -t"; -static LPCWSTR kArcIncludeSwitches = L" -an -ai"; -static LPCWSTR kHashIncludeSwitches = L" -i"; -static LPCWSTR kStopSwitchParsing = L" --"; -static LPCWSTR kLargePagesDisable = L" -slp-"; +static const char *k7zGui = "7zG.exe"; + +static const char *kShowDialogSwitch = " -ad"; +static const char *kEmailSwitch = " -seml."; +static const char *kIncludeSwitch = " -i"; +static const char *kArchiveTypeSwitch = " -t"; +static const char *kArcIncludeSwitches = " -an -ai"; +static const char *kHashIncludeSwitches = " -i"; +static const char *kStopSwitchParsing = " --"; +static const char *kLargePagesDisable = " -slp-"; extern HWND g_HWND; UString GetQuotedString(const UString &s) { - return UString(L'\"') + s + UString(L'\"'); + UString s2 = L'\"'; + s2 += s; + s2 += L'\"'; + return s2; } static void ErrorMessage(LPCWSTR message) @@ -52,17 +61,20 @@ static void ErrorMessageHRESULT(HRESULT res, LPCWSTR s = NULL) UString s2 = NError::MyFormatMessage(res); if (s) { - s2 += L'\n'; + s2.Add_LF(); s2 += s; } ErrorMessage(s2); } -static HRESULT MyCreateProcess(LPCWSTR imageName, const UString ¶ms, +static HRESULT Call7zGui(const UString ¶ms, // LPCWSTR curDir, bool waitFinish, NSynchronization::CBaseEvent *event) { + UString imageName = fs2us(NWindows::NDLL::GetModuleDirPrefix()); + imageName.AddAscii(k7zGui); + CProcess process; WRes res = process.Create(imageName, params, NULL); // curDir); if (res != 0) @@ -83,12 +95,7 @@ static HRESULT MyCreateProcess(LPCWSTR imageName, const UString ¶ms, static void AddLagePagesSwitch(UString ¶ms) { if (!ReadLockMemoryEnable()) - params += kLargePagesDisable; -} - -static UString Get7zGuiPath() -{ - return fs2us(NWindows::NDLL::GetModuleDirPrefix()) + L"7zG.exe"; + params.AddAscii(kLargePagesDisable); } class CRandNameGenerator @@ -96,11 +103,12 @@ class CRandNameGenerator CRandom _random; public: CRandNameGenerator() { _random.Init(); } - UString GenerateName() + void GenerateName(UString &s, const char *prefix) { - wchar_t temp[16]; - ConvertUInt32ToString((UInt32)_random.Generate(), temp); - return temp; + s.AddAscii(prefix); + char temp[16]; + ConvertUInt32ToString((UInt32)(unsigned)_random.Generate(), temp); + s.AddAscii(temp); } }; @@ -108,9 +116,11 @@ static HRESULT CreateMap(const UStringVector &names, CFileMapping &fileMapping, NSynchronization::CManualResetEvent &event, UString ¶ms) { - UInt32 totalSize = 1; - FOR_VECTOR (i, names) - totalSize += (names[i].Len() + 1); + size_t totalSize = 1; + { + FOR_VECTOR (i, names) + totalSize += (names[i].Len() + 1); + } totalSize *= sizeof(wchar_t); CRandNameGenerator random; @@ -118,7 +128,7 @@ static HRESULT CreateMap(const UStringVector &names, UString mappingName; for (;;) { - mappingName = L"7zMap" + random.GenerateName(); + random.GenerateName(mappingName, "7zMap"); WRes res = fileMapping.Create(PAGE_READWRITE, totalSize, GetSystemString(mappingName)); if (fileMapping.IsCreated() && res == 0) @@ -131,7 +141,7 @@ static HRESULT CreateMap(const UStringVector &names, UString eventName; for (;;) { - eventName = L"7zEvent" + random.GenerateName(); + random.GenerateName(eventName, "7zEvent"); WRes res = event.CreateWithName(false, GetSystemString(eventName)); if (event.IsCreated() && res == 0) break; @@ -143,25 +153,25 @@ static HRESULT CreateMap(const UStringVector &names, params += L'#'; params += mappingName; params += L':'; - wchar_t temp[16]; - ConvertUInt32ToString(totalSize, temp); - params += temp; + char temp[32]; + ConvertUInt64ToString(totalSize, temp); + params.AddAscii(temp); params += L':'; params += eventName; LPVOID data = fileMapping.Map(FILE_MAP_WRITE, 0, totalSize); - if (data == NULL) + if (!data) return E_FAIL; CFileUnmapper unmapper(data); { wchar_t *cur = (wchar_t *)data; - *cur++ = 0; + *cur++ = 0; // it means wchar_t strings (UTF-16 in WIN32) FOR_VECTOR (i, names) { const UString &s = names[i]; - int len = s.Len() + 1; - memcpy(cur, (const wchar_t *)s, len * sizeof(wchar_t)); + unsigned len = s.Len() + 1; + wmemcpy(cur, (const wchar_t *)s, len); cur += len; } } @@ -181,33 +191,33 @@ HRESULT CompressFiles( CFileMapping fileMapping; NSynchronization::CManualResetEvent event; - params += kIncludeSwitch; + params.AddAscii(kIncludeSwitch); RINOK(CreateMap(names, fileMapping, event, params)); if (!arcType.IsEmpty()) { - params += kArchiveTypeSwitch; + params.AddAscii(kArchiveTypeSwitch); params += arcType; } if (email) - params += kEmailSwitch; + params.AddAscii(kEmailSwitch); if (showDialog) - params += kShowDialogSwitch; + params.AddAscii(kShowDialogSwitch); AddLagePagesSwitch(params); if (arcName.IsEmpty()) - params += L" -an"; + params.AddAscii(" -an"); if (addExtension) - params += L" -saa"; + params.AddAscii(" -saa"); else - params += L" -sae"; + params.AddAscii(" -sae"); - params += kStopSwitchParsing; - params += L' '; + params.AddAscii(kStopSwitchParsing); + params.Add_Space(); if (!arcName.IsEmpty()) { @@ -218,7 +228,7 @@ HRESULT CompressFiles( arcName); } - return MyCreateProcess(Get7zGuiPath(), params, + return Call7zGui(params, // (arcPathPrefix.IsEmpty()? 0: (LPCWSTR)arcPathPrefix), waitFinish, &event); MY_TRY_FINISH @@ -227,12 +237,12 @@ HRESULT CompressFiles( static void ExtractGroupCommand(const UStringVector &arcPaths, UString ¶ms, bool isHash) { AddLagePagesSwitch(params); - params += isHash ? kHashIncludeSwitches : kArcIncludeSwitches; + params.AddAscii(isHash ? kHashIncludeSwitches : kArcIncludeSwitches); CFileMapping fileMapping; NSynchronization::CManualResetEvent event; HRESULT result = CreateMap(arcPaths, fileMapping, event, params); if (result == S_OK) - result = MyCreateProcess(Get7zGuiPath(), params, false, &event); + result = Call7zGui(params, false, &event); if (result != S_OK) ErrorMessageHRESULT(result); } @@ -243,13 +253,13 @@ void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bo UString params = L'x'; if (!outFolder.IsEmpty()) { - params += L" -o"; + params.AddAscii(" -o"); params += GetQuotedString(outFolder); } if (elimDup) - params += L" -spe"; + params.AddAscii(" -spe"); if (showDialog) - params += kShowDialogSwitch; + params.AddAscii(kShowDialogSwitch); ExtractGroupCommand(arcPaths, params, false); MY_TRY_FINISH_VOID } @@ -268,7 +278,7 @@ void CalcChecksum(const UStringVector &paths, const UString &methodName) UString params = L'h'; if (!methodName.IsEmpty()) { - params += L" -scrc"; + params.AddAscii(" -scrc"); params += methodName; } ExtractGroupCommand(paths, params, true); @@ -278,7 +288,7 @@ void CalcChecksum(const UStringVector &paths, const UString &methodName) void Benchmark(bool totalMode) { MY_TRY_BEGIN - HRESULT result = MyCreateProcess(Get7zGuiPath(), totalMode ? L"b -mm=*" : L"b", false, NULL); + HRESULT result = Call7zGui(totalMode ? L"b -mm=*" : L"b", false, NULL); if (result != S_OK) ErrorMessageHRESULT(result); MY_TRY_FINISH_VOID diff --git a/CPP/7zip/UI/Common/CompressCall2.cpp b/CPP/7zip/UI/Common/CompressCall2.cpp index bd27f37b..b3421e5a 100644 --- a/CPP/7zip/UI/Common/CompressCall2.cpp +++ b/CPP/7zip/UI/Common/CompressCall2.cpp @@ -30,28 +30,39 @@ static void ThrowException_if_Error(HRESULT res) throw CSystemException(res); } +#ifdef EXTERNAL_CODECS + #define CREATE_CODECS \ CCodecs *codecs = new CCodecs; \ CMyComPtr<ICompressCodecsInfo> compressCodecsInfo = codecs; \ ThrowException_if_Error(codecs->Load()); -#ifdef EXTERNAL_CODECS - #define LOAD_EXTERNAL_CODECS \ CExternalCodecs __externalCodecs; \ __externalCodecs.GetCodecs = codecs; \ __externalCodecs.GetHashers = codecs; \ - ThrowException_if_Error(__externalCodecs.LoadCodecs()); + ThrowException_if_Error(__externalCodecs.Load()); #else -LOAD_EXTERNAL_CODECS +#define CREATE_CODECS \ + CCodecs *codecs = new CCodecs; \ + CMyComPtr<IUnknown> compressCodecsInfo = codecs; \ + ThrowException_if_Error(codecs->Load()); + +#define LOAD_EXTERNAL_CODECS #endif + + + UString GetQuotedString(const UString &s) { - return UString(L'\"') + s + UString(L'\"'); + UString s2 = L'\"'; + s2 += s; + s2 += L'\"'; + return s2; } static void ErrorMessage(LPCWSTR message) @@ -78,6 +89,7 @@ HRESULT CompressFiles( bool email, bool showDialog, bool /* waitFinish */) { MY_TRY_BEGIN + CREATE_CODECS CUpdateCallbackGUI callback; @@ -128,6 +140,7 @@ HRESULT CompressFiles( throw CSystemException(E_FAIL); return E_FAIL; } + MY_TRY_FINISH return S_OK; } @@ -136,6 +149,7 @@ static HRESULT ExtractGroupCommand(const UStringVector &arcPaths, bool showDialog, const UString &outFolder, bool testMode, bool elimDup = false) { MY_TRY_BEGIN + CREATE_CODECS CExtractOptions eo; @@ -160,7 +174,12 @@ static HRESULT ExtractGroupCommand(const UStringVector &arcPaths, arcCensor.AddPreItem(arcPaths[i]); } arcCensor.AddPathsToCensor(NWildcard::k_RelatPath); - EnumerateDirItemsAndSort(false, arcCensor, NWildcard::k_RelatPath, UString(), arcPathsSorted, arcFullPathsSorted); + CDirItemsStat st; + EnumerateDirItemsAndSort(arcCensor, NWildcard::k_RelatPath, UString(), + arcPathsSorted, arcFullPathsSorted, + st, + NULL // &scan: change it!!!! + ); } CObjectVector<COpenType> formatIndices; @@ -184,6 +203,7 @@ static HRESULT ExtractGroupCommand(const UStringVector &arcPaths, throw CSystemException(result); } return ecs->IsOK() ? S_OK : E_FAIL; + MY_TRY_FINISH return result; } @@ -201,6 +221,7 @@ void TestArchives(const UStringVector &arcPaths) void CalcChecksum(const UStringVector &paths, const UString &methodName) { MY_TRY_BEGIN + CREATE_CODECS LOAD_EXTERNAL_CODECS @@ -216,13 +237,14 @@ void CalcChecksum(const UStringVector &paths, const UString &methodName) CHashOptions options; options.Methods.Add(methodName); - result = HashCalcGUI(EXTERNAL_CODECS_VARS censor, options, messageWasDisplayed); + result = HashCalcGUI(EXTERNAL_CODECS_VARS_L censor, options, messageWasDisplayed); if (result != S_OK) { if (result != E_ABORT && messageWasDisplayed) return; // E_FAIL; throw CSystemException(result); } + MY_TRY_FINISH return; // result; } @@ -230,6 +252,7 @@ void CalcChecksum(const UStringVector &paths, const UString &methodName) void Benchmark(bool totalMode) { MY_TRY_BEGIN + CREATE_CODECS LOAD_EXTERNAL_CODECS @@ -241,6 +264,7 @@ void Benchmark(bool totalMode) prop.Value = L"*"; props.Add(prop); } - result = Benchmark(EXTERNAL_CODECS_VARS props, g_HWND); + result = Benchmark(EXTERNAL_CODECS_VARS_L props, g_HWND); + MY_TRY_FINISH } diff --git a/CPP/7zip/UI/Common/DefaultName.cpp b/CPP/7zip/UI/Common/DefaultName.cpp index ce0b327b..02f611c3 100644 --- a/CPP/7zip/UI/Common/DefaultName.cpp +++ b/CPP/7zip/UI/Common/DefaultName.cpp @@ -7,21 +7,23 @@ static UString GetDefaultName3(const UString &fileName, const UString &extension, const UString &addSubExtension) { - int extLength = extension.Len(); - int fileNameLength = fileName.Len(); - if (fileNameLength > extLength + 1) + const unsigned extLen = extension.Len(); + const unsigned fileNameLen = fileName.Len(); + + if (fileNameLen > extLen + 1) { - int dotPos = fileNameLength - (extLength + 1); + const unsigned dotPos = fileNameLen - (extLen + 1); if (fileName[dotPos] == '.') - if (extension.IsEqualToNoCase(fileName.Ptr(dotPos + 1))) + if (extension.IsEqualTo_NoCase(fileName.Ptr(dotPos + 1))) return fileName.Left(dotPos) + addSubExtension; } - int dotPos = fileName.ReverseFind(L'.'); + + int dotPos = fileName.ReverseFind_Dot(); if (dotPos > 0) return fileName.Left(dotPos) + addSubExtension; if (addSubExtension.IsEmpty()) - return fileName + L"~"; + return fileName + L'~'; else return fileName + addSubExtension; } diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h index ce48b582..4286b4e8 100644 --- a/CPP/7zip/UI/Common/DirItem.h +++ b/CPP/7zip/UI/Common/DirItem.h @@ -11,6 +11,38 @@ #include "../../Archive/IArchive.h" +struct CDirItemsStat +{ + UInt64 NumDirs; + UInt64 NumFiles; + UInt64 NumAltStreams; + UInt64 FilesSize; + UInt64 AltStreamsSize; + + UInt64 NumErrors; + // UInt64 GetTotalItems() const { return NumDirs + NumFiles + NumAltStreams; } + + UInt64 GetTotalBytes() const { return FilesSize + AltStreamsSize; } + + CDirItemsStat(): + NumDirs(0), + NumFiles(0), + NumAltStreams(0), + FilesSize(0), + AltStreamsSize(0), + NumErrors(0) + {} +}; + +#define INTERFACE_IDirItemsCallback(x) \ + virtual HRESULT ScanError(const FString &path, DWORD systemError) x; \ + virtual HRESULT ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) x; \ + +struct IDirItemsCallback +{ + INTERFACE_IDirItemsCallback(=0) +}; + struct CDirItem { UInt64 Size; @@ -46,7 +78,7 @@ class CDirItems UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const; - void EnumerateDir(int phyParent, int logParent, const FString &phyPrefix); + HRESULT EnumerateDir(int phyParent, int logParent, const FString &phyPrefix); public: CObjectVector<CDirItem> Items; @@ -54,26 +86,14 @@ public: bool SymLinks; bool ScanAltStreams; - FStringVector ErrorPaths; - CRecordVector<DWORD> ErrorCodes; - UInt64 TotalSize; - + + CDirItemsStat Stat; #ifndef UNDER_CE - void SetLinkInfo(CDirItem &dirItem, const NWindows::NFile::NFind::CFileInfo &fi, + HRESULT SetLinkInfo(CDirItem &dirItem, const NWindows::NFile::NFind::CFileInfo &fi, const FString &phyPrefix); #endif - void AddError(const FString &path, DWORD errorCode) - { - ErrorCodes.Add(errorCode); - ErrorPaths.Add(path); - } - - void AddError(const FString &path) - { - AddError(path, ::GetLastError()); - } #if defined(_WIN32) && !defined(UNDER_CE) @@ -82,19 +102,30 @@ public: bool _saclEnabled; bool ReadSecure; - void AddSecurityItem(const FString &path, int &secureIndex); + HRESULT AddSecurityItem(const FString &path, int &secureIndex); #endif + IDirItemsCallback *Callback; + CDirItems(); - int GetNumFolders() const { return Prefixes.Size(); } - UString GetPhyPath(unsigned index) const; + void AddDirFileInfo(int phyParent, int logParent, int secureIndex, + const NWindows::NFile::NFind::CFileInfo &fi); + + HRESULT AddError(const FString &path, DWORD errorCode); + HRESULT AddError(const FString &path); + + HRESULT ScanProgress(const FString &path); + + // unsigned GetNumFolders() const { return Prefixes.Size(); } + FString GetPhyPath(unsigned index) const; UString GetLogPath(unsigned index) const; unsigned AddPrefix(int phyParent, int logParent, const UString &prefix); void DeleteLastPrefix(); - void EnumerateItems2( + + HRESULT EnumerateItems2( const FString &phyPrefix, const UString &logPrefix, const FStringVector &filePaths, diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp index 14285cfe..3ebf25aa 100644 --- a/CPP/7zip/UI/Common/EnumDirItems.cpp +++ b/CPP/7zip/UI/Common/EnumDirItems.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include <wchar.h> + #include "../../../Common/Wildcard.h" #include "../../../Windows/FileDir.h" @@ -19,8 +21,8 @@ using namespace NWindows; using namespace NFile; using namespace NName; -void AddDirFileInfo(int phyParent, int logParent, int secureIndex, - const NFind::CFileInfo &fi, CObjectVector<CDirItem> &dirItems) +void CDirItems::AddDirFileInfo(int phyParent, int logParent, int secureIndex, + const NFind::CFileInfo &fi) { CDirItem di; di.Size = fi.Size; @@ -36,35 +38,72 @@ void AddDirFileInfo(int phyParent, int logParent, int secureIndex, #if defined(_WIN32) && !defined(UNDER_CE) // di.ShortName = fs2us(fi.ShortName); #endif - dirItems.Add(di); + Items.Add(di); + + if (fi.IsDir()) + Stat.NumDirs++; + else if (fi.IsAltStream) + { + Stat.NumAltStreams++; + Stat.AltStreamsSize += fi.Size; + } + else + { + Stat.NumFiles++; + Stat.FilesSize += fi.Size; + } +} + +HRESULT CDirItems::AddError(const FString &path, DWORD errorCode) +{ + Stat.NumErrors++; + if (Callback) + return Callback->ScanError(path, errorCode); + return S_OK; +} + +HRESULT CDirItems::AddError(const FString &path) +{ + return AddError(path, ::GetLastError()); +} + +static const unsigned kScanProgressStepMask = (1 << 12) - 1; + +HRESULT CDirItems::ScanProgress(const FString &dirPath) +{ + if (Callback) + return Callback->ScanProgress(Stat, dirPath, true); + return S_OK; } UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const { UString path; unsigned len = name.Len(); + int i; for (i = index; i >= 0; i = parents[i]) len += Prefixes[i].Len(); - unsigned totalLen = len; - wchar_t *p = path.GetBuffer(len); - p[len] = 0; - len -= name.Len(); - memcpy(p + len, (const wchar_t *)name, name.Len() * sizeof(wchar_t)); + + wchar_t *p = path.GetBuf_SetEnd(len) + len; + + p -= name.Len(); + wmemcpy(p, (const wchar_t *)name, name.Len()); + for (i = index; i >= 0; i = parents[i]) { const UString &s = Prefixes[i]; - len -= s.Len(); - memcpy(p + len, (const wchar_t *)s, s.Len() * sizeof(wchar_t)); + p -= s.Len(); + wmemcpy(p, (const wchar_t *)s, s.Len()); } - path.ReleaseBuffer(totalLen); + return path; } -UString CDirItems::GetPhyPath(unsigned index) const +FString CDirItems::GetPhyPath(unsigned index) const { const CDirItem &di = Items[index]; - return GetPrefixesPath(PhyParents, di.PhyParent, di.Name); + return us2fs(GetPrefixesPath(PhyParents, di.PhyParent, di.Name)); } UString CDirItems::GetLogPath(unsigned index) const @@ -99,10 +138,11 @@ bool InitLocalPrivileges(); CDirItems::CDirItems(): SymLinks(false), - TotalSize(0) + ScanAltStreams(false) #ifdef _USE_SECURITY_CODE , ReadSecure(false) #endif + , Callback(NULL) { #ifdef _USE_SECURITY_CODE _saclEnabled = InitLocalPrivileges(); @@ -111,7 +151,7 @@ CDirItems::CDirItems(): #ifdef _USE_SECURITY_CODE -void CDirItems::AddSecurityItem(const FString &path, int &secureIndex) +HRESULT CDirItems::AddSecurityItem(const FString &path, int &secureIndex) { secureIndex = -1; @@ -124,11 +164,13 @@ void CDirItems::AddSecurityItem(const FString &path, int &secureIndex) DWORD errorCode = 0; DWORD secureSize; + BOOL res = ::GetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(Byte *)TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize); + if (res) { if (secureSize == 0) - return; + return S_OK; if (secureSize > TempSecureBuf.Size()) errorCode = ERROR_INVALID_FUNCTION; } @@ -153,51 +195,61 @@ void CDirItems::AddSecurityItem(const FString &path, int &secureIndex) } } } + if (res) { secureIndex = SecureBlocks.AddUniq(TempSecureBuf, secureSize); - return; + return S_OK; } + if (errorCode == 0) errorCode = ERROR_INVALID_FUNCTION; - AddError(path, errorCode); + return AddError(path, errorCode); } #endif -void CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phyPrefix) +HRESULT CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phyPrefix) { + RINOK(ScanProgress(phyPrefix)); + NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK); - for (;;) + for (unsigned ttt = 0; ; ttt++) { NFind::CFileInfo fi; bool found; if (!enumerator.Next(fi, found)) { - AddError(phyPrefix); - return; + return AddError(phyPrefix); } if (!found) - break; + return S_OK; int secureIndex = -1; #ifdef _USE_SECURITY_CODE if (ReadSecure) - AddSecurityItem(phyPrefix + fi.Name, secureIndex); + { + RINOK(AddSecurityItem(phyPrefix + fi.Name, secureIndex)); + } #endif - AddDirFileInfo(phyParent, logParent, secureIndex, fi, Items); + AddDirFileInfo(phyParent, logParent, secureIndex, fi); + if (Callback && (ttt & kScanProgressStepMask) == kScanProgressStepMask) + { + RINOK(ScanProgress(phyPrefix)); + } + if (fi.IsDir()) { const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; unsigned parent = AddPrefix(phyParent, logParent, fs2us(name2)); - EnumerateDir(parent, parent, phyPrefix + name2); + RINOK(EnumerateDir(parent, parent, phyPrefix + name2)); } } } -void CDirItems::EnumerateItems2( +HRESULT CDirItems::EnumerateItems2( const FString &phyPrefix, const UString &logPrefix, const FStringVector &filePaths, @@ -213,13 +265,13 @@ void CDirItems::EnumerateItems2( const FString phyPath = phyPrefix + filePath; if (!fi.Find(phyPath)) { - AddError(phyPath); + RINOK(AddError(phyPath)); continue; } if (requestedPaths) requestedPaths->Add(phyPath); - int delimiter = filePath.ReverseFind(FCHAR_PATH_SEPARATOR); + int delimiter = filePath.ReverseFind_PathSepar(); FString phyPrefixCur; int phyParentCur = phyParent; if (delimiter >= 0) @@ -231,19 +283,23 @@ void CDirItems::EnumerateItems2( int secureIndex = -1; #ifdef _USE_SECURITY_CODE if (ReadSecure) - AddSecurityItem(phyPath, secureIndex); + { + RINOK(AddSecurityItem(phyPath, secureIndex)); + } #endif - AddDirFileInfo(phyParentCur, logParent, secureIndex, fi, Items); + AddDirFileInfo(phyParentCur, logParent, secureIndex, fi); if (fi.IsDir()) { const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; unsigned parent = AddPrefix(phyParentCur, logParent, fs2us(name2)); - EnumerateDir(parent, parent, phyPrefix + phyPrefixCur + name2); + RINOK(EnumerateDir(parent, parent, phyPrefix + phyPrefixCur + name2)); } } + ReserveDown(); + return S_OK; } @@ -256,8 +312,7 @@ static HRESULT EnumerateDirItems( int phyParent, int logParent, const FString &phyPrefix, const UStringVector &addArchivePrefix, CDirItems &dirItems, - bool enterToSubFolders, - IEnumDirItemCallback *callback); + bool enterToSubFolders); static HRESULT EnumerateDirItems_Spec( const NWildcard::CCensorNode &curNode, @@ -265,15 +320,14 @@ static HRESULT EnumerateDirItems_Spec( const FString &phyPrefix, const UStringVector &addArchivePrefix, CDirItems &dirItems, - bool enterToSubFolders, - IEnumDirItemCallback *callback) + bool enterToSubFolders) { const FString name2 = curFolderName + FCHAR_PATH_SEPARATOR; unsigned parent = dirItems.AddPrefix(phyParent, logParent, fs2us(name2)); unsigned numItems = dirItems.Items.Size(); HRESULT res = EnumerateDirItems( curNode, parent, parent, phyPrefix + name2, - addArchivePrefix, dirItems, enterToSubFolders, callback); + addArchivePrefix, dirItems, enterToSubFolders); if (numItems == dirItems.Items.Size()) dirItems.DeleteLastPrefix(); return res; @@ -281,14 +335,15 @@ static HRESULT EnumerateDirItems_Spec( #ifndef UNDER_CE -static void EnumerateAltStreams( +#ifdef _WIN32 + +static HRESULT EnumerateAltStreams( const NFind::CFileInfo &fi, const NWildcard::CCensorNode &curNode, - int phyParent, int logParent, const FString &phyPrefix, + int phyParent, int logParent, const FString &fullPath, const UStringVector &addArchivePrefix, // prefix from curNode CDirItems &dirItems) { - const FString fullPath = phyPrefix + fi.Name; NFind::CStreamEnumerator enumerator(fullPath); for (;;) { @@ -296,11 +351,10 @@ static void EnumerateAltStreams( bool found; if (!enumerator.Next(si, found)) { - dirItems.AddError(fullPath + FTEXT(":*"), (DWORD)E_FAIL); - break; + return dirItems.AddError(fullPath + FTEXT(":*")); // , (DWORD)E_FAIL } if (!found) - break; + return S_OK; if (si.IsMainStream()) continue; UStringVector addArchivePrefixNew = addArchivePrefix; @@ -313,26 +367,28 @@ static void EnumerateAltStreams( fi2.Size = si.Size; fi2.Attrib &= ~FILE_ATTRIBUTE_DIRECTORY; fi2.IsAltStream = true; - AddDirFileInfo(phyParent, logParent, -1, fi2, dirItems.Items); - dirItems.TotalSize += fi2.Size; + dirItems.AddDirFileInfo(phyParent, logParent, -1, fi2); } } -void CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi, +#endif + +HRESULT CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi, const FString &phyPrefix) { if (!SymLinks || !fi.HasReparsePoint()) - return; + return S_OK; const FString path = phyPrefix + fi.Name; CByteBuffer &buf = dirItem.ReparseData; if (NIO::GetReparseData(path, buf)) { CReparseAttr attr; if (attr.Parse(buf, buf.Size())) - return; + return S_OK; } - AddError(path); + DWORD res = ::GetLastError(); buf.Free(); + return AddError(path , res); } #endif @@ -343,8 +399,7 @@ static HRESULT EnumerateForItem( int phyParent, int logParent, const FString &phyPrefix, const UStringVector &addArchivePrefix, // prefix from curNode CDirItems &dirItems, - bool enterToSubFolders, - IEnumDirItemCallback *callback) + bool enterToSubFolders) { const UString name = fs2us(fi.Name); bool enterToSubFolders2 = enterToSubFolders; @@ -362,12 +417,13 @@ static HRESULT EnumerateForItem( int secureIndex = -1; #ifdef _USE_SECURITY_CODE if (dirItems.ReadSecure) - dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex); + { + RINOK(dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex)); + } #endif dirItemIndex = dirItems.Items.Size(); - AddDirFileInfo(phyParent, logParent, secureIndex, fi, dirItems.Items); - dirItems.TotalSize += fi.Size; + dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi); if (fi.IsDir()) enterToSubFolders2 = true; } @@ -375,14 +431,15 @@ static HRESULT EnumerateForItem( #ifndef UNDER_CE if (dirItems.ScanAltStreams) { - EnumerateAltStreams(fi, curNode, phyParent, logParent, phyPrefix, - addArchivePrefixNew, dirItems); + RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent, + phyPrefix + fi.Name, + addArchivePrefixNew, dirItems)); } if (dirItemIndex >= 0) { CDirItem &dirItem = dirItems.Items[dirItemIndex]; - dirItems.SetLinkInfo(dirItem, fi, phyPrefix); + RINOK(dirItems.SetLinkInfo(dirItem, fi, phyPrefix)); if (dirItem.ReparseData.Size() != 0) return S_OK; } @@ -412,7 +469,7 @@ static HRESULT EnumerateForItem( *nextNode, phyParent, logParent, fi.Name, phyPrefix, addArchivePrefixNew, dirItems, - enterToSubFolders2, callback); + enterToSubFolders2); } @@ -424,11 +481,13 @@ static bool CanUseFsDirect(const NWildcard::CCensorNode &curNode) if (item.Recursive || item.PathParts.Size() != 1) return false; const UString &name = item.PathParts.Front(); + /* if (name.IsEmpty()) return false; + */ - /* Windows doesn't support file name with wildcard. - but if another system supports file name with wildcard, + /* Windows doesn't support file name with wildcard + But if another system supports file name with wildcard, and wildcard mode is disabled, we can ignore wildcard in name */ /* if (!item.WildcardParsing) @@ -441,19 +500,30 @@ static bool CanUseFsDirect(const NWildcard::CCensorNode &curNode) } +#if defined(_WIN32) && !defined(UNDER_CE) + +static bool IsVirtualFsFolder(const FString &prefix, const UString &name) +{ + UString s = fs2us(prefix); + s += name; + s.Add_PathSepar(); + return IsPathSepar(s[0]) && GetRootPrefixSize(s) == 0; +} + +#endif + static HRESULT EnumerateDirItems( const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const FString &phyPrefix, const UStringVector &addArchivePrefix, // prefix from curNode CDirItems &dirItems, - bool enterToSubFolders, - IEnumDirItemCallback *callback) + bool enterToSubFolders) { if (!enterToSubFolders) if (curNode.NeedCheckSubDirs()) enterToSubFolders = true; - if (callback) - RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), dirItems.TotalSize, fs2us(phyPrefix), true)); + + RINOK(dirItems.ScanProgress(phyPrefix)); // try direct_names case at first if (addArchivePrefix.IsEmpty() && !enterToSubFolders) @@ -469,25 +539,68 @@ static HRESULT EnumerateDirItems( { const NWildcard::CItem &item = curNode.IncludeItems[i]; const UString &name = item.PathParts.Front(); - const FString fullPath = phyPrefix + us2fs(name); + FString fullPath = phyPrefix + us2fs(name); + + #if defined(_WIN32) && !defined(UNDER_CE) + bool needAltStreams = true; + #endif + + #ifdef _USE_SECURITY_CODE + bool needSecurity = true; + #endif + + if (phyPrefix.IsEmpty()) + { + if (!item.ForFile) + { + /* we don't like some names for alt streams inside archive: + ":sname" for "\" + "c:::sname" for "C:\" + So we ignore alt streams for these cases */ + if (name.IsEmpty()) + { + #if defined(_WIN32) && !defined(UNDER_CE) + needAltStreams = false; + #endif + + /* + // do we need to ignore security info for "\\" folder ? + #ifdef _USE_SECURITY_CODE + needSecurity = false; + #endif + */ + + fullPath = FCHAR_PATH_SEPARATOR; + } + #if defined(_WIN32) && !defined(UNDER_CE) + else if (item.IsDriveItem()) + { + needAltStreams = false; + fullPath.Add_PathSepar(); + } + #endif + } + } + NFind::CFileInfo fi; - #ifdef _WIN32 - if (phyPrefix.IsEmpty() && item.IsDriveItem()) + #if defined(_WIN32) && !defined(UNDER_CE) + if (IsVirtualFsFolder(phyPrefix, name)) { fi.SetAsDir(); - fi.Name = fullPath; + fi.Name = us2fs(name); } else #endif if (!fi.Find(fullPath)) { - dirItems.AddError(fullPath); + RINOK(dirItems.AddError(fullPath)); continue; } + bool isDir = fi.IsDir(); if (isDir && !item.ForDir || !isDir && !item.ForFile) { - dirItems.AddError(fullPath, (DWORD)E_FAIL); + RINOK(dirItems.AddError(fullPath, (DWORD)E_FAIL)); continue; } { @@ -499,30 +612,37 @@ static HRESULT EnumerateDirItems( int secureIndex = -1; #ifdef _USE_SECURITY_CODE - if (dirItems.ReadSecure) - dirItems.AddSecurityItem(fullPath, secureIndex); + if (needSecurity && dirItems.ReadSecure) + { + RINOK(dirItems.AddSecurityItem(fullPath, secureIndex)); + } #endif - AddDirFileInfo(phyParent, logParent, secureIndex, fi, dirItems.Items); + dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi); #ifndef UNDER_CE { CDirItem &dirItem = dirItems.Items.Back(); - dirItems.SetLinkInfo(dirItem, fi, phyPrefix); + RINOK(dirItems.SetLinkInfo(dirItem, fi, phyPrefix)); if (dirItem.ReparseData.Size() != 0) + { + if (fi.IsAltStream) + dirItems.Stat.AltStreamsSize -= fi.Size; + else + dirItems.Stat.FilesSize -= fi.Size; continue; + } } #endif - dirItems.TotalSize += fi.Size; #ifndef UNDER_CE - if (dirItems.ScanAltStreams) + if (needAltStreams && dirItems.ScanAltStreams) { UStringVector pathParts; pathParts.Add(fs2us(fi.Name)); - EnumerateAltStreams(fi, curNode, phyParent, logParent, phyPrefix, - pathParts, dirItems); + RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent, + fullPath, pathParts, dirItems)); } #endif @@ -546,7 +666,7 @@ static HRESULT EnumerateDirItems( } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix, - addArchivePrefixNew, dirItems, true, callback)); + addArchivePrefixNew, dirItems, true)); } for (i = 0; i < curNode.SubNodes.Size(); i++) @@ -555,31 +675,50 @@ static HRESULT EnumerateDirItems( if (!needEnterVector[i]) continue; const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; - const FString fullPath = phyPrefix + us2fs(nextNode.Name); + FString fullPath = phyPrefix + us2fs(nextNode.Name); NFind::CFileInfo fi; - #ifdef _WIN32 - if (phyPrefix.IsEmpty() && NWildcard::IsDriveColonName(nextNode.Name)) + + if (phyPrefix.IsEmpty()) + { + { + if (nextNode.Name.IsEmpty()) + fullPath = FCHAR_PATH_SEPARATOR; + #ifdef _WIN32 + else if (NWildcard::IsDriveColonName(nextNode.Name)) + fullPath.Add_PathSepar(); + #endif + } + } + + // we don't want to call fi.Find() for root folder or virtual folder + if (phyPrefix.IsEmpty() && nextNode.Name.IsEmpty() + #if defined(_WIN32) && !defined(UNDER_CE) + || IsVirtualFsFolder(phyPrefix, nextNode.Name) + #endif + ) { fi.SetAsDir(); - fi.Name = fullPath; + fi.Name = us2fs(nextNode.Name); } else - #endif - if (!fi.Find(fullPath)) { - if (!nextNode.AreThereIncludeItems()) + if (!fi.Find(fullPath)) + { + if (!nextNode.AreThereIncludeItems()) + continue; + RINOK(dirItems.AddError(fullPath)); continue; - dirItems.AddError(fullPath); - continue; - } - if (!fi.IsDir()) - { - dirItems.AddError(fullPath, (DWORD)E_FAIL); - continue; + } + + if (!fi.IsDir()) + { + RINOK(dirItems.AddError(fullPath, (DWORD)E_FAIL)); + continue; + } } RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix, - UStringVector(), dirItems, false, callback)); + UStringVector(), dirItems, false)); } return S_OK; @@ -625,7 +764,7 @@ static HRESULT EnumerateDirItems( fi.Name = driveName; RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix, - addArchivePrefix, dirItems, enterToSubFolders, callback)); + addArchivePrefix, dirItems, enterToSubFolders)); } return S_OK; } @@ -641,18 +780,21 @@ static HRESULT EnumerateDirItems( bool found; if (!enumerator.Next(fi, found)) { - dirItems.AddError(phyPrefix); + RINOK(dirItems.AddError(phyPrefix)); break; } if (!found) break; - if (callback && (ttt & 0xFF) == 0xFF) - RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), dirItems.TotalSize, fs2us(phyPrefix), true)); + if (dirItems.Callback && (ttt & kScanProgressStepMask) == kScanProgressStepMask) + { + RINOK(dirItems.ScanProgress(phyPrefix)); + } RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix, - addArchivePrefix, dirItems, enterToSubFolders, callback)); + addArchivePrefix, dirItems, enterToSubFolders)); } + return S_OK; } @@ -660,8 +802,7 @@ HRESULT EnumerateItems( const NWildcard::CCensor &censor, const NWildcard::ECensorPathMode pathMode, const UString &addPathPrefix, - CDirItems &dirItems, - IEnumDirItemCallback *callback) + CDirItems &dirItems) { FOR_VECTOR (i, censor.Pairs) { @@ -679,8 +820,8 @@ HRESULT EnumerateItems( RINOK(EnumerateDirItems(pair.Head, phyParent, logParent, us2fs(pair.Prefix), UStringVector(), dirItems, - false, // enterToSubFolders - callback)); + false // enterToSubFolders + )); } dirItems.ReserveDown(); @@ -719,7 +860,7 @@ void CDirItems::FillFixedReparse() // maybe we need to support networks paths also ? FString fullPathF; - if (!NDir::MyGetFullPathName(us2fs(GetPhyPath(i)), fullPathF)) + if (!NDir::MyGetFullPathName(GetPhyPath(i), fullPathF)) continue; UString fullPath = fs2us(fullPathF); const UString logPath = GetLogPath(i); @@ -729,7 +870,7 @@ void CDirItems::FillFixedReparse() continue; const UString prefix = fullPath.Left(fullPath.Len() - logPath.Len()); - if (prefix.Back() != WCHAR_PATH_SEPARATOR) + if (!IsPathSepar(prefix.Back())) continue; unsigned rootPrefixSize = GetRootPrefixSize(prefix); diff --git a/CPP/7zip/UI/Common/EnumDirItems.h b/CPP/7zip/UI/Common/EnumDirItems.h index 803a64e7..7afb800a 100644 --- a/CPP/7zip/UI/Common/EnumDirItems.h +++ b/CPP/7zip/UI/Common/EnumDirItems.h @@ -12,16 +12,10 @@ void AddDirFileInfo(int phyParent, int logParent, int secureIndex, const NWindows::NFile::NFind::CFileInfo &fi, CObjectVector<CDirItem> &dirItems); -struct IEnumDirItemCallback -{ - virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) = 0; -}; - HRESULT EnumerateItems( const NWildcard::CCensor &censor, NWildcard::ECensorPathMode pathMode, const UString &addPathPrefix, - CDirItems &dirItems, - IEnumDirItemCallback *callback); + CDirItems &dirItems); #endif diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp index 67cad3ac..14aa7407 100644 --- a/CPP/7zip/UI/Common/Extract.cpp +++ b/CPP/7zip/UI/Common/Extract.cpp @@ -51,19 +51,19 @@ static HRESULT DecompressArchive( replaceName = arc0.DefaultName; } - outDir.Replace(FSTRING_ANY_MASK, us2fs(GetCorrectFsPath(replaceName))); + outDir.Replace(FSTRING_ANY_MASK, us2fs(Get_Correct_FsFile_Name(replaceName))); bool elimIsPossible = false; UString elimPrefix; // only pure name without dir delimiter FString outDirReduced = outDir; - if (options.ElimDup.Val) + if (options.ElimDup.Val && options.PathMode != NExtract::NPathMode::kAbsPaths) { UString dirPrefix; SplitPathToParts_Smart(fs2us(outDir), dirPrefix, elimPrefix); if (!elimPrefix.IsEmpty()) { - if (IsCharDirLimiter(elimPrefix.Back())) + if (IsPathSepar(elimPrefix.Back())) elimPrefix.DeleteBack(); if (!elimPrefix.IsEmpty()) { @@ -73,37 +73,66 @@ static HRESULT DecompressArchive( } } + bool allFilesAreAllowed = wildcardCensor.AreAllAllowed(); + if (!options.StdInMode) { UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); - UString filePath; + CReadArcItem item; for (UInt32 i = 0; i < numItems; i++) { - RINOK(arc.GetItemPath(i, filePath)); + if (elimIsPossible || !allFilesAreAllowed) + { + RINOK(arc.GetItem(i, item)); + } + else + { + #ifdef SUPPORT_ALT_STREAMS + item.IsAltStream = false; + if (!options.NtOptions.AltStreams.Val && arc.Ask_AltStream) + { + RINOK(Archive_IsItem_AltStream(arc.Archive, i, item.IsAltStream)); + } + #endif + } - if (elimIsPossible && options.ElimDup.Val) + #ifdef SUPPORT_ALT_STREAMS + if (!options.NtOptions.AltStreams.Val && item.IsAltStream) + continue; + #endif + + if (elimIsPossible) { - if (!IsPath1PrefixedByPath2(filePath, elimPrefix)) + const UString &s = + #ifdef SUPPORT_ALT_STREAMS + item.MainPath; + #else + item.Path; + #endif + if (!IsPath1PrefixedByPath2(s, elimPrefix)) elimIsPossible = false; else { - wchar_t c = filePath[elimPrefix.Len()]; - if (c != 0 && !IsCharDirLimiter(c)) + wchar_t c = s[elimPrefix.Len()]; + if (c == 0) + { + if (!item.MainIsDir) + elimIsPossible = false; + } + else if (!IsPathSepar(c)) elimIsPossible = false; } } - bool isFolder; - RINOK(Archive_IsItem_Folder(archive, i, isFolder)); - bool isAltStream; - RINOK(Archive_IsItem_AltStream(archive, i, isAltStream)); - if (!options.NtOptions.AltStreams.Val && isAltStream) - continue; - if (!wildcardCensor.CheckPath(isAltStream, filePath, !isFolder)) - continue; + if (!allFilesAreAllowed) + { + if (!CensorNode_CheckPath(wildcardCensor, item)) + continue; + } + realIndices.Add(i); } @@ -115,7 +144,10 @@ static HRESULT DecompressArchive( } if (elimIsPossible) - outDir = outDirReduced; + { + removePathParts.Add(elimPrefix); + // outDir = outDirReduced; + } #ifdef _WIN32 // GetCorrectFullFsPath doesn't like "..". @@ -124,16 +156,21 @@ static HRESULT DecompressArchive( #endif if (outDir.IsEmpty()) - outDir = FString(FTEXT(".")) + FString(FSTRING_PATH_SEPARATOR); - else - if (!CreateComplexDir(outDir)) - { - HRESULT res = ::GetLastError(); - if (res == S_OK) - res = E_FAIL; - errorMessage = ((UString)L"Can not create output directory ") + fs2us(outDir); - return res; - } + outDir = FTEXT(".") FSTRING_PATH_SEPARATOR; + /* + #ifdef _WIN32 + else if (NName::IsAltPathPrefix(outDir)) {} + #endif + */ + else if (!CreateComplexDir(outDir)) + { + HRESULT res = ::GetLastError(); + if (res == S_OK) + res = E_FAIL; + errorMessage.SetFromAscii("Can not create output directory: "); + errorMessage += fs2us(outDir); + return res; + } ecs->Init( options.NtOptions, @@ -142,7 +179,7 @@ static HRESULT DecompressArchive( callback, options.StdOutMode, options.TestMode, outDir, - removePathParts, + removePathParts, false, packSize); @@ -209,15 +246,16 @@ HRESULT Extract( IHashCalc *hash, #endif UString &errorMessage, - CDecompressStat &stat) + CDecompressStat &st) { - stat.Clear(); + st.Clear(); UInt64 totalPackSize = 0; CRecordVector<UInt64> arcSizes; unsigned numArcs = options.StdInMode ? 1 : arcPaths.Size(); unsigned i; + for (i = 0; i < numArcs; i++) { NFind::CFileInfo fi; @@ -272,11 +310,13 @@ HRESULT Extract( throw "there is no such archive"; } + /* #ifndef _NO_CRYPTO - openCallback->Open_ClearPasswordWasAskedFlag(); + openCallback->Open_Clear_PasswordWasAsked_Flag(); #endif + */ - RINOK(extractCallback->BeforeOpen(arcPath)); + RINOK(extractCallback->BeforeOpen(arcPath, options.TestMode)); CArchiveLink arcLink; CObjectVector<COpenType> types2 = types; @@ -318,36 +358,17 @@ HRESULT Extract( op.stdInMode = options.StdInMode; op.stream = NULL; op.filePath = arcPath; - HRESULT result = arcLink.Open2(op, openCallback); + + HRESULT result = arcLink.Open3(op, openCallback); if (result == E_ABORT) return result; - bool crypted = false; - #ifndef _NO_CRYPTO - crypted = openCallback->Open_WasPasswordAsked(); - #endif - - if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) + if (result == S_OK && arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) result = S_FALSE; // arcLink.Set_ErrorsText(); - RINOK(extractCallback->OpenResult(arcPath, result, crypted)); - - - { - FOR_VECTOR (r, arcLink.Arcs) - { - const CArc &arc = arcLink.Arcs[r]; - const CArcErrorInfo &er = arc.ErrorInfo; - if (er.IsThereErrorOrWarning()) - { - RINOK(extractCallback->SetError(r, arc.Path, - er.GetErrorFlags(), er.ErrorMessage, - er.GetWarningFlags(), er.WarningMessage)); - } - } - } + RINOK(extractCallback->OpenResult(codecs, arcLink, arcPath, result)); if (result != S_OK) { @@ -379,8 +400,8 @@ HRESULT Extract( { if ((unsigned)index > i) { - skipArcs[index] = true; - correctionSize -= arcSizes[index]; + skipArcs[(unsigned)index] = true; + correctionSize -= arcSizes[(unsigned)index]; } } } @@ -395,6 +416,9 @@ HRESULT Extract( } } + /* + // Now openCallback and extractCallback use same object. So we don't need to send password. + #ifndef _NO_CRYPTO bool passwordIsDefined; UString password; @@ -404,31 +428,7 @@ HRESULT Extract( RINOK(extractCallback->SetPassword(password)); } #endif - - FOR_VECTOR (k, arcLink.Arcs) - { - const CArc &arc = arcLink.Arcs[k]; - const CArcErrorInfo &er = arc.ErrorInfo; - - if (er.ErrorFormatIndex >= 0) - { - RINOK(extractCallback->OpenTypeWarning(arc.Path, - codecs->GetFormatNamePtr(arc.FormatIndex), - codecs->GetFormatNamePtr(er.ErrorFormatIndex))) - /* - UString s = L"Can not open the file as [" + codecs->Formats[arc.ErrorFormatIndex].Name + L"] archive\n"; - s += L"The file is open as [" + codecs->Formats[arc.FormatIndex].Name + L"] archive"; - RINOK(extractCallback->MessageError(s)); - */ - } - { - const UString &s = er.ErrorMessage; - if (!s.IsEmpty()) - { - RINOK(extractCallback->MessageError(s)); - } - } - } + */ CArc &arc = arcLink.Arcs.Back(); arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice); @@ -450,6 +450,7 @@ HRESULT Extract( options, calcCrc, extractCallback, ecs, errorMessage, packProcessed)); + if (!options.StdInMode) packProcessed = fi.Size + arcLink.VolumesSize; totalPackProcessed += packProcessed; @@ -464,12 +465,13 @@ HRESULT Extract( RINOK(extractCallback->SetTotal(totalPackSize)); RINOK(extractCallback->SetCompleted(&totalPackProcessed)); } - stat.NumFolders = ecs->NumFolders; - stat.NumFiles = ecs->NumFiles; - stat.NumAltStreams = ecs->NumAltStreams; - stat.UnpackSize = ecs->UnpackSize; - stat.AltStreams_UnpackSize = ecs->AltStreams_UnpackSize; - stat.NumArchives = arcPaths.Size(); - stat.PackSize = ecs->LocalProgressSpec->InSize; + + st.NumFolders = ecs->NumFolders; + st.NumFiles = ecs->NumFiles; + st.NumAltStreams = ecs->NumAltStreams; + st.UnpackSize = ecs->UnpackSize; + st.AltStreams_UnpackSize = ecs->AltStreams_UnpackSize; + st.NumArchives = arcPaths.Size(); + st.PackSize = ecs->LocalProgressSpec->InSize; return S_OK; } diff --git a/CPP/7zip/UI/Common/Extract.h b/CPP/7zip/UI/Common/Extract.h index e6bd5cb7..03ac74b2 100644 --- a/CPP/7zip/UI/Common/Extract.h +++ b/CPP/7zip/UI/Common/Extract.h @@ -89,6 +89,6 @@ HRESULT Extract( IHashCalc *hash, #endif UString &errorMessage, - CDecompressStat &stat); + CDecompressStat &st); #endif diff --git a/CPP/7zip/UI/Common/ExtractMode.h b/CPP/7zip/UI/Common/ExtractMode.h index c2e43f6a..3b2b9a02 100644 --- a/CPP/7zip/UI/Common/ExtractMode.h +++ b/CPP/7zip/UI/Common/ExtractMode.h @@ -12,7 +12,8 @@ namespace NPathMode kFullPaths, kCurPaths, kNoPaths, - kAbsPaths + kAbsPaths, + kNoPathsAlt // alt streams must be extracted without name of base file }; } diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp index 37e15013..5ba14045 100644 --- a/CPP/7zip/UI/Common/ExtractingFilePath.cpp +++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp @@ -8,183 +8,228 @@ #include "ExtractingFilePath.h" -static UString ReplaceIncorrectChars(const UString &s, bool repaceColon) +static void ReplaceIncorrectChars(UString &s) { - #ifdef _WIN32 - UString res; - bool beforeColon = true; { for (unsigned i = 0; i < s.Len(); i++) { wchar_t c = s[i]; - if (beforeColon) - if (c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '"') - c = '_'; - if (c == ':') - { - if (repaceColon) - c = '_'; - else - beforeColon = false; - } - res += c; + if ( + #ifdef _WIN32 + c == ':' || c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '"' + || c == '/' || + #endif + c == WCHAR_PATH_SEPARATOR) + s.ReplaceOneCharAtPos(i, '_'); } } - if (beforeColon) + + #ifdef _WIN32 { - for (int i = res.Len() - 1; i >= 0; i--) + for (unsigned i = s.Len(); i != 0;) { - wchar_t c = res[i]; + wchar_t c = s[--i]; if (c != '.' && c != ' ') break; - res.ReplaceOneCharAtPos(i, '_'); + s.ReplaceOneCharAtPos(i, '_'); } } - return res; - #else - return s; #endif } #ifdef _WIN32 -static const wchar_t *g_ReservedNames[] = -{ - L"CON", L"PRN", L"AUX", L"NUL" -}; +/* WinXP-64 doesn't support ':', '\\' and '/' symbols in name of alt stream. + But colon in postfix ":$DATA" is allowed. + WIN32 functions don't allow empty alt stream name "name:" */ -static bool CheckTail(const UString &name, unsigned len) +void Correct_AltStream_Name(UString &s) { - int dotPos = name.Find(L'.'); - if (dotPos < 0) - dotPos = name.Len(); - UString s = name.Left(dotPos); - s.TrimRight(); - return s.Len() != len; + unsigned len = s.Len(); + const unsigned kPostfixSize = 6; + if (s.Len() >= kPostfixSize + && StringsAreEqualNoCase_Ascii(s.RightPtr(kPostfixSize), ":$DATA")) + len -= kPostfixSize; + for (unsigned i = 0; i < len; i++) + { + wchar_t c = s[i]; + if (c == ':' || c == '\\' || c == '/') + s.ReplaceOneCharAtPos(i, '_'); + } + if (s.IsEmpty()) + s = L'_'; } -static bool CheckNameNum(const UString &name, const wchar_t *reservedName) +static const unsigned g_ReservedWithNum_Index = 4; + +static const char * const g_ReservedNames[] = { - unsigned len = MyStringLen(reservedName); - if (name.Len() <= len) - return true; - if (MyStringCompareNoCase_N(name, reservedName, len) != 0) - return true; - wchar_t c = name[len]; - if (c < L'0' || c > L'9') - return true; - return CheckTail(name, len + 1); -} + "CON", "PRN", "AUX", "NUL", + "COM", "LPT" +}; static bool IsSupportedName(const UString &name) { for (unsigned i = 0; i < ARRAY_SIZE(g_ReservedNames); i++) { - const wchar_t *reservedName = g_ReservedNames[i]; + const char *reservedName = g_ReservedNames[i]; unsigned len = MyStringLen(reservedName); if (name.Len() < len) continue; - if (MyStringCompareNoCase_N(name, reservedName, len) != 0) + if (!name.IsPrefixedBy_Ascii_NoCase(reservedName)) continue; - if (!CheckTail(name, len)) - return false; + if (i >= g_ReservedWithNum_Index) + { + wchar_t c = name[len]; + if (c < L'0' || c > L'9') + continue; + len++; + } + for (;;) + { + wchar_t c = name[len++]; + if (c == 0 || c == '.') + return false; + if (c != ' ') + break; + } } - if (!CheckNameNum(name, L"COM")) - return false; - return CheckNameNum(name, L"LPT"); + return true; +} + +static void CorrectUnsupportedName(UString &name) +{ + if (!IsSupportedName(name)) + name.InsertAtFront(L'_'); } #endif -static UString GetCorrectFileName(const UString &path, bool repaceColon) +static void Correct_PathPart(UString &s) +{ + // "." and ".." + if (s[0] == '.' && (s[1] == 0 || s[1] == '.' && s[2] == 0)) + s.Empty(); + #ifdef _WIN32 + else + ReplaceIncorrectChars(s); + #endif +} + +// static const wchar_t *k_EmptyReplaceName = L"[]"; +static const wchar_t k_EmptyReplaceName = L'_'; + +UString Get_Correct_FsFile_Name(const UString &name) { - if (path == L".." || path == L".") - return UString(); - return ReplaceIncorrectChars(path, repaceColon); + UString res = name; + Correct_PathPart(res); + + #ifdef _WIN32 + CorrectUnsupportedName(res); + #endif + + if (res.IsEmpty()) + res = k_EmptyReplaceName; + return res; } -void MakeCorrectPath(bool isPathFromRoot, UStringVector &pathParts, bool replaceAltStreamColon) + +void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir) { - for (unsigned i = 0; i < pathParts.Size();) + unsigned i = 0; + + if (absIsAllowed) { - UString &s = pathParts[i]; - #ifdef _WIN32 - bool needReplaceColon = (replaceAltStreamColon || i != pathParts.Size() - 1); - if (i == 0 && isPathFromRoot && NWindows::NFile::NName::IsDrivePath(s)) + #if defined(_WIN32) && !defined(UNDER_CE) + bool isDrive = false; + #endif + if (parts[0].IsEmpty()) { - UString s2 = s[0]; - s2 += L'_'; - s2 += GetCorrectFileName(s.Ptr(2), needReplaceColon); - s = s2; + i = 1; + #if defined(_WIN32) && !defined(UNDER_CE) + if (parts.Size() > 1 && parts[1].IsEmpty()) + { + i = 2; + if (parts.Size() > 2 && parts[2] == L"?") + { + i = 3; + if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3])) + { + isDrive = true; + i = 4; + } + } + } + #endif } - else - s = GetCorrectFileName(s, needReplaceColon); + #if defined(_WIN32) && !defined(UNDER_CE) + else if (NWindows::NFile::NName::IsDrivePath2(parts[0])) + { + isDrive = true; + i = 1; + } + + if (isDrive) + { + // we convert "c:name" to "c:\name", if absIsAllowed path. + const UString &ds = parts[i - 1]; + if (ds.Len() != 2) + { + UString s = ds.Ptr(2); + parts.Insert(i, s); + } + } + #endif + } + + for (; i < parts.Size();) + { + UString &s = parts[i]; + + #ifdef _WIN32 + Correct_PathPart(s); #endif if (s.IsEmpty()) - pathParts.Delete(i); + { + if (isDir || i != parts.Size() - 1) + { + parts.Delete(i); + continue; + } + s = k_EmptyReplaceName; + } else { #ifdef _WIN32 - if (!IsSupportedName(s)) - s = (UString)L"_" + s; + CorrectUnsupportedName(s); #endif - i++; } + + i++; } -} - -UString MakePathNameFromParts(const UStringVector &parts) -{ - UString result; - FOR_VECTOR (i, parts) - { - if (i != 0) - result += WCHAR_PATH_SEPARATOR; - result += parts[i]; - } - return result; -} - -static const wchar_t *k_EmptyReplaceName = L"[]"; -void Correct_IfEmptyLastPart(UStringVector &parts) -{ - if (parts.IsEmpty()) - parts.Add(k_EmptyReplaceName); - else + if (!isDir) { - UString &s = parts.Back(); - if (s.IsEmpty()) - s = k_EmptyReplaceName; + if (parts.IsEmpty()) + parts.Add(k_EmptyReplaceName); + else + { + UString &s = parts.Back(); + if (s.IsEmpty()) + s = k_EmptyReplaceName; + } } } -UString GetCorrectFsPath(const UString &path) +UString MakePathFromParts(const UStringVector &parts) { - UString res = GetCorrectFileName(path, true); - #ifdef _WIN32 - if (!IsSupportedName(res)) - res = (UString)L"_" + res; - #endif - if (res.IsEmpty()) - res = k_EmptyReplaceName; - return res; -} - -UString GetCorrectFullFsPath(const UString &path) -{ - UStringVector parts; - SplitPathToParts(path, parts); + UString s; FOR_VECTOR (i, parts) { - UString &s = parts[i]; - #ifdef _WIN32 - while (!s.IsEmpty() && (s.Back() == '.' || s.Back() == ' ')) - s.DeleteBack(); - if (!IsSupportedName(s)) - s.InsertAtFront(L'_'); - #endif + if (i != 0) + s.Add_PathSepar(); + s += parts[i]; } - return MakePathNameFromParts(parts); + return s; } diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.h b/CPP/7zip/UI/Common/ExtractingFilePath.h index 751248a9..a52a1f4a 100644 --- a/CPP/7zip/UI/Common/ExtractingFilePath.h +++ b/CPP/7zip/UI/Common/ExtractingFilePath.h @@ -5,17 +5,15 @@ #include "../../../Common/MyString.h" -UString MakePathNameFromParts(const UStringVector &parts); +#ifdef _WIN32 +void Correct_AltStream_Name(UString &s); +#endif -/* for WIN32: - if (isRoot == true), and pathParts[0] contains path like "c:name", - it thinks that "c:" is drive prefix (it's not ":name alt stream) and - the function changes part to c_name */ -void MakeCorrectPath(bool isPathFromRoot, UStringVector &pathParts, bool replaceAltStreamColon); +// replaces unsuported characters, and replaces "." , ".." and "" to "[]" +UString Get_Correct_FsFile_Name(const UString &name); -UString GetCorrectFsPath(const UString &path); -UString GetCorrectFullFsPath(const UString &path); +void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir); -void Correct_IfEmptyLastPart(UStringVector &parts); +UString MakePathFromParts(const UStringVector &parts); #endif diff --git a/CPP/7zip/UI/Common/HashCalc.cpp b/CPP/7zip/UI/Common/HashCalc.cpp index 6abe59ac..c33f837f 100644 --- a/CPP/7zip/UI/Common/HashCalc.cpp +++ b/CPP/7zip/UI/Common/HashCalc.cpp @@ -30,23 +30,17 @@ public: ~CHashMidBuf() { ::MidFree(_data); } }; -struct CEnumDirItemCallback_Hash: public IEnumDirItemCallback -{ - IHashCallbackUI *Callback; - - HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) - { - return Callback->ScanProgress(numFolders, numFiles, totalSize, path, isDir); - } -}; - -static const wchar_t *k_DefaultHashMethod = L"CRC32"; +static const char *k_DefaultHashMethod = "CRC32"; HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &hashMethods) { UStringVector names = hashMethods; if (names.IsEmpty()) - names.Add(k_DefaultHashMethod); + { + UString s; + s.SetFromAscii(k_DefaultHashMethod); + names.Add(s); + } CRecordVector<CMethodId> ids; CObjectVector<COneMethodInfo> methods; @@ -60,7 +54,7 @@ HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVecto if (m.MethodName.IsEmpty()) m.MethodName = k_DefaultHashMethod; - if (m.MethodName == L"*") + if (m.MethodName == "*") { CRecordVector<CMethodId> tempMethods; GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods); @@ -68,7 +62,7 @@ HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVecto ids.Clear(); FOR_VECTOR (t, tempMethods) { - int index = ids.AddToUniqueSorted(tempMethods[t]); + unsigned index = ids.AddToUniqueSorted(tempMethods[t]); if (ids.Size() != methods.Size()) methods.Insert(index, m); } @@ -80,7 +74,7 @@ HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVecto CMethodId id; if (!FindHashMethod(EXTERNAL_CODECS_LOC_VARS m.MethodName, id)) return E_NOTIMPL; - int index = ids.AddToUniqueSorted(id); + unsigned index = ids.AddToUniqueSorted(id); if (ids.Size() != methods.Size()) methods.Insert(index, m); } @@ -89,7 +83,7 @@ HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVecto for (i = 0; i < ids.Size(); i++) { CMyComPtr<IHasher> hasher; - UString name; + AString name; RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS ids[i], name, hasher)); if (!hasher) throw "Can't create hasher"; @@ -98,9 +92,7 @@ HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVecto CMyComPtr<ICompressSetCoderProperties> scp; hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp); if (scp) - { RINOK(m.SetCoderProps(scp, NULL)); - } } UInt32 digestSize = hasher->GetDigestSize(); if (digestSize > k_HashCalc_DigestSize_Max) @@ -109,9 +101,10 @@ HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVecto h.Hasher = hasher; h.Name = name; h.DigestSize = digestSize; - for (int i = 0; i < k_HashCalc_NumGroups; i++) + for (unsigned i = 0; i < k_HashCalc_NumGroups; i++) memset(h.Digests[i], 0, digestSize); } + return S_OK; } @@ -203,13 +196,12 @@ HRESULT HashCalc( DECL_EXTERNAL_CODECS_LOC_VARS const NWildcard::CCensor &censor, const CHashOptions &options, - UString &errorInfo, + AString &errorInfo, IHashCallbackUI *callback) { CDirItems dirItems; + dirItems.Callback = callback; - UInt64 numErrors = 0; - UInt64 totalBytes = 0; if (options.StdInMode) { CDirItem di; @@ -222,34 +214,29 @@ HRESULT HashCalc( } else { - CEnumDirItemCallback_Hash enumCallback; - enumCallback.Callback = callback; RINOK(callback->StartScanning()); dirItems.ScanAltStreams = options.AltStreamsMode; + HRESULT res = EnumerateItems(censor, options.PathMode, UString(), - dirItems, &enumCallback); - totalBytes = dirItems.TotalSize; - FOR_VECTOR (i, dirItems.ErrorPaths) - { - RINOK(callback->CanNotFindError(fs2us(dirItems.ErrorPaths[i]), dirItems.ErrorCodes[i])); - } - numErrors = dirItems.ErrorPaths.Size(); + dirItems); + if (res != S_OK) { if (res != E_ABORT) - errorInfo = L"Scanning error"; + errorInfo = "Scanning error"; return res; } - RINOK(callback->FinishScanning()); + RINOK(callback->FinishScanning(dirItems.Stat)); } unsigned i; CHashBundle hb; RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS options.Methods)); hb.Init(); - hb.NumErrors = numErrors; + + hb.NumErrors = dirItems.Stat.NumErrors; if (options.StdInMode) { @@ -257,7 +244,7 @@ HRESULT HashCalc( } else { - RINOK(callback->SetTotal(totalBytes)); + RINOK(callback->SetTotal(dirItems.Stat.GetTotalBytes())); } const UInt32 kBufSize = 1 << 15; @@ -289,8 +276,8 @@ HRESULT HashCalc( path = dirItems.GetLogPath(i); if (!isDir) { - UString phyPath = dirItems.GetPhyPath(i); - if (!inStreamSpec->OpenShared(us2fs(phyPath), options.OpenShareForWrite)) + FString phyPath = dirItems.GetPhyPath(i); + if (!inStreamSpec->OpenShared(phyPath, options.OpenShareForWrite)) { HRESULT res = callback->OpenFileError(phyPath, ::GetLastError()); hb.NumErrors++; @@ -327,14 +314,15 @@ HRESULT HashCalc( } -static inline char GetHex(Byte value) +static inline char GetHex(unsigned v) { - return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); + return (char)((v < 10) ? ('0' + v) : ('A' + (v - 10))); } void AddHashHexToString(char *dest, const Byte *data, UInt32 size) { dest[size * 2] = 0; + if (!data) { for (UInt32 i = 0; i < size; i++) @@ -345,17 +333,19 @@ void AddHashHexToString(char *dest, const Byte *data, UInt32 size) } return; } + int step = 2; if (size <= 8) { step = -2; dest += size * 2 - 2; } + for (UInt32 i = 0; i < size; i++) { - Byte b = data[i]; - dest[0] = GetHex((Byte)((b >> 4) & 0xF)); - dest[1] = GetHex((Byte)(b & 0xF)); + unsigned b = data[i]; + dest[0] = GetHex((b >> 4) & 0xF); + dest[1] = GetHex(b & 0xF); dest += step; } } diff --git a/CPP/7zip/UI/Common/HashCalc.h b/CPP/7zip/UI/Common/HashCalc.h index 3d7b9bc8..38908e2e 100644 --- a/CPP/7zip/UI/Common/HashCalc.h +++ b/CPP/7zip/UI/Common/HashCalc.h @@ -8,6 +8,7 @@ #include "../../Common/CreateCoder.h" #include "../../Common/MethodProps.h" +#include "DirItem.h" #include "Property.h" const unsigned k_HashCalc_DigestSize_Max = 64; @@ -25,7 +26,7 @@ enum struct CHasherState { CMyComPtr<IHasher> Hasher; - UString Name; + AString Name; UInt32 DigestSize; Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max]; }; @@ -42,8 +43,8 @@ struct CHashBundle: public IHashCalc { CObjectVector<CHasherState> Hashers; - UInt64 NumFiles; UInt64 NumDirs; + UInt64 NumFiles; UInt64 NumAltStreams; UInt64 FilesSize; UInt64 AltStreamsSize; @@ -55,7 +56,7 @@ struct CHashBundle: public IHashCalc void Init() { - NumFiles = NumDirs = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0; + NumDirs = NumFiles = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0; } void InitForNewFile(); @@ -65,21 +66,20 @@ struct CHashBundle: public IHashCalc }; #define INTERFACE_IHashCallbackUI(x) \ + INTERFACE_IDirItemsCallback(x) \ virtual HRESULT StartScanning() x; \ - virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) x; \ - virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \ - virtual HRESULT FinishScanning() x; \ + virtual HRESULT FinishScanning(const CDirItemsStat &st) x; \ virtual HRESULT SetNumFiles(UInt64 numFiles) x; \ virtual HRESULT SetTotal(UInt64 size) x; \ virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \ virtual HRESULT CheckBreak() x; \ virtual HRESULT BeforeFirstFile(const CHashBundle &hb) x; \ virtual HRESULT GetStream(const wchar_t *name, bool isFolder) x; \ - virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \ + virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x; \ virtual HRESULT SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) x; \ virtual HRESULT AfterLastFile(const CHashBundle &hb) x; \ -struct IHashCallbackUI +struct IHashCallbackUI: public IDirItemsCallback { INTERFACE_IHashCallbackUI(=0) }; @@ -99,7 +99,7 @@ HRESULT HashCalc( DECL_EXTERNAL_CODECS_LOC_VARS const NWildcard::CCensor &censor, const CHashOptions &options, - UString &errorInfo, + AString &errorInfo, IHashCallbackUI *callback); void AddHashHexToString(char *dest, const Byte *data, UInt32 size); diff --git a/CPP/7zip/UI/Common/IFileExtractCallback.h b/CPP/7zip/UI/Common/IFileExtractCallback.h index 7bb85279..c456c862 100644 --- a/CPP/7zip/UI/Common/IFileExtractCallback.h +++ b/CPP/7zip/UI/Common/IFileExtractCallback.h @@ -7,6 +7,9 @@ #include "../../IDecl.h" +#include "LoadCodecs.h" +#include "OpenArchive.h" + namespace NOverwriteAnswer { enum EEnum @@ -20,35 +23,74 @@ namespace NOverwriteAnswer }; } + +/* ---------- IFolderArchiveExtractCallback ---------- +is implemented by + Console/ExtractCallbackConsole.h CExtractCallbackConsole + FileManager/ExtractCallback.h CExtractCallbackImp + FAR/ExtractEngine.cpp CExtractCallBackImp: (QueryInterface is not supported) + +IID_IFolderArchiveExtractCallback is requested by: + - Agent/ArchiveFolder.cpp + CAgentFolder::CopyTo(..., IFolderOperationsExtractCallback *callback) + is sent to IArchiveFolder::Extract() + + - FileManager/PanelCopy.cpp + CPanel::CopyTo(), if (options->testMode) + is sent to IArchiveFolder::Extract() + + IFolderArchiveExtractCallback is used by Common/ArchiveExtractCallback.cpp +*/ + +#define INTERFACE_IFolderArchiveExtractCallback(x) \ + STDMETHOD(AskOverwrite)( \ + const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, \ + const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, \ + Int32 *answer) x; \ + STDMETHOD(PrepareOperation)(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 *position) x; \ + STDMETHOD(MessageError)(const wchar_t *message) x; \ + STDMETHOD(SetOperationResult)(Int32 opRes, Int32 encrypted) x; \ + DECL_INTERFACE_SUB(IFolderArchiveExtractCallback, IProgress, 0x01, 0x07) { -public: - STDMETHOD(AskOverwrite)( - const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, - const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, - Int32 *answer) PURE; - STDMETHOD(PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position) PURE; - STDMETHOD(MessageError)(const wchar_t *message) PURE; - STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted) PURE; + INTERFACE_IFolderArchiveExtractCallback(PURE) +}; + +#define INTERFACE_IFolderArchiveExtractCallback2(x) \ + STDMETHOD(ReportExtractResult)(Int32 opRes, Int32 encrypted, const wchar_t *name) x; \ + +DECL_INTERFACE_SUB(IFolderArchiveExtractCallback2, IUnknown, 0x01, 0x08) +{ + INTERFACE_IFolderArchiveExtractCallback2(PURE) }; +/* ---------- IExtractCallbackUI ---------- +is implemented by + Console/ExtractCallbackConsole.h CExtractCallbackConsole + FileManager/ExtractCallback.h CExtractCallbackImp +*/ + +#ifdef _NO_CRYPTO + #define INTERFACE_IExtractCallbackUI_Crypto(x) +#else + #define INTERFACE_IExtractCallbackUI_Crypto(x) \ + virtual HRESULT SetPassword(const UString &password) x; +#endif + +#define INTERFACE_IExtractCallbackUI(x) \ + virtual HRESULT BeforeOpen(const wchar_t *name, bool testMode) x; \ + virtual HRESULT OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) x; \ + virtual HRESULT ThereAreNoFiles() x; \ + virtual HRESULT ExtractResult(HRESULT result) x; \ + INTERFACE_IExtractCallbackUI_Crypto(x) + struct IExtractCallbackUI: IFolderArchiveExtractCallback { - virtual HRESULT BeforeOpen(const wchar_t *name) = 0; - virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0; - virtual HRESULT SetError(int level, const wchar_t *name, - UInt32 errorFlags, const wchar_t *errors, - UInt32 warningFlags, const wchar_t *warnings) = 0; - virtual HRESULT ThereAreNoFiles() = 0; - virtual HRESULT ExtractResult(HRESULT result) = 0; - virtual HRESULT OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType) = 0; - - #ifndef _NO_CRYPTO - virtual HRESULT SetPassword(const UString &password) = 0; - #endif + INTERFACE_IExtractCallbackUI(PURE) }; + #define INTERFACE_IGetProp(x) \ STDMETHOD(GetProp)(PROPID propID, PROPVARIANT *value) x; \ @@ -61,7 +103,7 @@ DECL_INTERFACE_SUB(IGetProp, IUnknown, 0x01, 0x20) STDMETHOD(UseExtractToStream)(Int32 *res) x; \ STDMETHOD(GetStream7)(const wchar_t *name, Int32 isDir, ISequentialOutStream **outStream, Int32 askExtractMode, IGetProp *getProp) x; \ STDMETHOD(PrepareOperation7)(Int32 askExtractMode) x; \ - STDMETHOD(SetOperationResult7)(Int32 resultEOperationResult, bool encrypted) x; \ + STDMETHOD(SetOperationResult7)(Int32 resultEOperationResult, Int32 encrypted) x; \ DECL_INTERFACE_SUB(IFolderExtractToStreamCallback, IUnknown, 0x01, 0x30) { diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp index bbdf0fe8..696b6749 100644 --- a/CPP/7zip/UI/Common/LoadCodecs.cpp +++ b/CPP/7zip/UI/Common/LoadCodecs.cpp @@ -1,5 +1,36 @@ // LoadCodecs.cpp +/* +EXTERNAL_CODECS +--------------- + CCodecs::Load() tries to detect the directory with plugins. + It stops the checking, if it can find any of the following items: + - 7z.dll file + - "Formats" subdir + - "Codecs" subdir + The order of check: + 1) directory of client executable + 2) WIN32: directory for REGISTRY item [HKEY_*\Software\7-Zip\Path**] + The order for HKEY_* : Path** : + - HKEY_CURRENT_USER : PathXX + - HKEY_LOCAL_MACHINE : PathXX + - HKEY_CURRENT_USER : Path + - HKEY_LOCAL_MACHINE : Path + PathXX is Path32 in 32-bit code + PathXX is Path64 in 64-bit code + + +EXPORT_CODECS +------------- + if (EXTERNAL_CODECS) is defined, then the code exports internal + codecs of client from CCodecs object to external plugins. + 7-Zip doesn't use that feature. 7-Zip uses the scheme: + - client application without internal plugins. + - 7z.dll module contains all (or almost all) plugins. + 7z.dll can use codecs from another plugins, if required. +*/ + + #include "StdAfx.h" #include "../../../../C/7zVersion.h" @@ -23,13 +54,21 @@ using namespace NWindows; #ifdef EXTERNAL_CODECS -#include "../../../Windows/FileFind.h" -#include "../../../Windows/DLL.h" +// #define EXPORT_CODECS + +#endif + #ifdef NEW_FOLDER_INTERFACE +extern HINSTANCE g_hInstance; #include "../../../Windows/ResourceString.h" static const UINT kIconTypesResId = 100; #endif +#ifdef EXTERNAL_CODECS + +#include "../../../Windows/FileFind.h" +#include "../../../Windows/DLL.h" + #ifdef _WIN32 #include "../../../Windows/FileName.h" #include "../../../Windows/Registry.h" @@ -37,13 +76,18 @@ static const UINT kIconTypesResId = 100; using namespace NFile; -#ifdef _WIN32 -extern HINSTANCE g_hInstance; -#endif #define kCodecsFolderName FTEXT("Codecs") #define kFormatsFolderName FTEXT("Formats") -static CFSTR kMainDll = FTEXT("7z.dll"); + + +static CFSTR kMainDll = + // #ifdef _WIN32 + FTEXT("7z.dll"); + // #else + // FTEXT("7z.so"); + // #endif + #ifdef _WIN32 @@ -77,7 +121,7 @@ static bool ReadPathFromRegistry(HKEY baseKey, LPCWSTR value, FString &path) #endif // EXTERNAL_CODECS -static const unsigned kNumArcsMax = 48; +static const unsigned kNumArcsMax = 64; static unsigned g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; @@ -118,7 +162,7 @@ static void SplitString(const UString &srcString, UStringVector &destStrings) int CArcInfoEx::FindExtension(const UString &ext) const { FOR_VECTOR (i, Exts) - if (ext.IsEqualToNoCase(Exts[i].Ext)) + if (ext.IsEqualTo_NoCase(Exts[i].Ext)) return i; return -1; } @@ -182,6 +226,7 @@ static FString GetBaseFolderPrefixFromRegistry() return moduleFolderPrefix; } + static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 index, PROPID propId, CLSID &clsId, bool &isAssigned) { @@ -203,14 +248,18 @@ static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 in HRESULT CCodecs::LoadCodecs() { CCodecLib &lib = Libs.Back(); + + lib.CreateDecoder = (Func_CreateDecoder)lib.Lib.GetProc("CreateDecoder"); + lib.CreateEncoder = (Func_CreateEncoder)lib.Lib.GetProc("CreateEncoder"); lib.GetMethodProperty = (Func_GetMethodProperty)lib.Lib.GetProc("GetMethodProperty"); + if (lib.GetMethodProperty) { UInt32 numMethods = 1; - Func_GetNumberOfMethods getNumberOfMethodsFunc = (Func_GetNumberOfMethods)lib.Lib.GetProc("GetNumberOfMethods"); - if (getNumberOfMethodsFunc) + Func_GetNumberOfMethods getNumberOfMethods = (Func_GetNumberOfMethods)lib.Lib.GetProc("GetNumberOfMethods"); + if (getNumberOfMethods) { - RINOK(getNumberOfMethodsFunc(&numMethods)); + RINOK(getNumberOfMethods(&numMethods)); } for (UInt32 i = 0; i < numMethods; i++) { @@ -226,10 +275,10 @@ HRESULT CCodecs::LoadCodecs() Func_GetHashers getHashers = (Func_GetHashers)lib.Lib.GetProc("GetHashers"); if (getHashers) { - RINOK(getHashers(&lib.Hashers)); - if (lib.Hashers) + RINOK(getHashers(&lib.ComHashers)); + if (lib.ComHashers) { - UInt32 numMethods = lib.Hashers->GetNumHashers(); + UInt32 numMethods = lib.ComHashers->GetNumHashers(); for (UInt32 i = 0; i < numMethods; i++) { CDllHasherInfo info; @@ -239,6 +288,7 @@ HRESULT CCodecs::LoadCodecs() } } } + return S_OK; } @@ -295,7 +345,7 @@ static HRESULT GetProp_String( NCOM::CPropVariant prop; RINOK(GetProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BSTR) - res = prop.bstrVal; + res.SetFromBstr(prop.bstrVal); else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; @@ -416,54 +466,6 @@ HRESULT CCodecs::LoadFormats() return S_OK; } -#ifdef NEW_FOLDER_INTERFACE -void CCodecIcons::LoadIcons(HMODULE m) -{ - UString iconTypes; - MyLoadString(m, kIconTypesResId, iconTypes); - UStringVector pairs; - SplitString(iconTypes, pairs); - FOR_VECTOR (i, pairs) - { - const UString &s = pairs[i]; - int pos = s.Find(L':'); - CIconPair iconPair; - iconPair.IconIndex = -1; - if (pos < 0) - pos = s.Len(); - else - { - UString num = s.Ptr(pos + 1); - if (!num.IsEmpty()) - { - const wchar_t *end; - iconPair.IconIndex = ConvertStringToUInt32(num, &end); - if (*end != 0) - continue; - } - } - iconPair.Ext = s.Left(pos); - IconPairs.Add(iconPair); - } -} - -bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const -{ - iconIndex = -1; - FOR_VECTOR (i, IconPairs) - { - const CIconPair &pair = IconPairs[i]; - if (ext.IsEqualToNoCase(pair.Ext)) - { - iconIndex = pair.IconIndex; - return true; - } - } - return false; -} - -#endif // EXTERNAL_CODECS - #ifdef _7ZIP_LARGE_PAGES extern "C" { @@ -471,21 +473,28 @@ extern "C" } #endif -HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll) +HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loadedOK) { + if (loadedOK) + *loadedOK = false; + if (needCheckDll) { - NDLL::CLibrary library; - if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE)) + NDLL::CLibrary lib; + if (!lib.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE)) return S_OK; } - Libs.Add(CCodecLib()); + + Libs.AddNew(); CCodecLib &lib = Libs.Back(); lib.Path = dllPath; bool used = false; HRESULT res = S_OK; + if (lib.Lib.Load(dllPath)) { + if (loadedOK) + *loadedOK = true; #ifdef NEW_FOLDER_INTERFACE lib.LoadIcons(); #endif @@ -521,8 +530,10 @@ HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll) } } } + if (!used) Libs.DeleteBack(); + return res; } @@ -539,17 +550,42 @@ HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPrefix) return S_OK; } -#endif +void CCodecs::CloseLibs() +{ + // OutputDebugStringA("~CloseLibs start"); + /* + WIN32: FreeLibrary() (CLibrary::Free()) function doesn't work as expected, + if it's called from another FreeLibrary() call. + So we need to call FreeLibrary() before global destructors. + + Also we free global links from DLLs to object of this module before CLibrary::Free() call. + */ + + FOR_VECTOR(i, Libs) + { + const CCodecLib &lib = Libs[i]; + if (lib.SetCodecs) + lib.SetCodecs(NULL); + } + + // OutputDebugStringA("~CloseLibs after SetCodecs"); + Libs.Clear(); + // OutputDebugStringA("~CloseLibs end"); +} + +#endif // EXTERNAL_CODECS + HRESULT CCodecs::Load() { #ifdef NEW_FOLDER_INTERFACE - InternalIcons.LoadIcons(g_hInstance); + InternalIcons.LoadIcons(g_hInstance); #endif Formats.Clear(); #ifdef EXTERNAL_CODECS + MainDll_ErrorPath.Empty(); Codecs.Clear(); Hashers.Clear(); #endif @@ -593,11 +629,46 @@ HRESULT CCodecs::Load() #ifdef EXTERNAL_CODECS const FString baseFolder = GetBaseFolderPrefixFromRegistry(); - RINOK(LoadDll(baseFolder + kMainDll, false)); + { + bool loadedOK; + RINOK(LoadDll(baseFolder + kMainDll, false, &loadedOK)); + if (!loadedOK) + MainDll_ErrorPath = kMainDll; + } RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName FSTRING_PATH_SEPARATOR)); RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName FSTRING_PATH_SEPARATOR)); + + NeedSetLibCodecs = true; + + if (Libs.Size() == 0) + NeedSetLibCodecs = false; + else if (Libs.Size() == 1) + { + // we don't need to set ISetCompressCodecsInfo, if all arcs and codecs are in one external module. + #ifndef EXPORT_CODECS + if (g_NumArcs == 0) + NeedSetLibCodecs = false; + #endif + } + + if (NeedSetLibCodecs) + { + /* 15.00: now we call global function in DLL: SetCompressCodecsInfo(c) + old versions called only ISetCompressCodecsInfo::SetCompressCodecsInfo(c) for each archive handler */ + + FOR_VECTOR(i, Libs) + { + CCodecLib &lib = Libs[i]; + lib.SetCodecs = (Func_SetCodecs)lib.Lib.GetProc("SetCodecs"); + if (lib.SetCodecs) + { + RINOK(lib.SetCodecs(this)); + } + } + } + #endif - + return S_OK; } @@ -605,14 +676,13 @@ HRESULT CCodecs::Load() int CCodecs::FindFormatForArchiveName(const UString &arcPath) const { - int slashPos = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR); - int dotPos = arcPath.ReverseFind(L'.'); - if (dotPos < 0 || dotPos < slashPos) + int dotPos = arcPath.ReverseFind_Dot(); + if (dotPos <= arcPath.ReverseFind_PathSepar()) return -1; const UString ext = arcPath.Ptr(dotPos + 1); if (ext.IsEmpty()) return -1; - if (ext.IsEqualToNoCase(L"exe")) + if (ext.IsEqualTo_Ascii_NoCase("exe")) return -1; FOR_VECTOR (i, Formats) { @@ -640,7 +710,7 @@ int CCodecs::FindFormatForExtension(const UString &ext) const int CCodecs::FindFormatForArchiveType(const UString &arcType) const { FOR_VECTOR (i, Formats) - if (Formats[i].Name.IsEqualToNoCase(arcType)) + if (Formats[i].Name.IsEqualTo_NoCase(arcType)) return i; return -1; } @@ -650,7 +720,7 @@ bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &forma formatIndices.Clear(); for (unsigned pos = 0; pos < arcType.Len();) { - int pos2 = arcType.Find('.', pos); + int pos2 = arcType.Find(L'.', pos); if (pos2 < 0) pos2 = arcType.Len(); const UString name = arcType.Mid(pos, pos2 - pos); @@ -671,6 +741,56 @@ bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &forma #endif // _SFX +#ifdef NEW_FOLDER_INTERFACE + +void CCodecIcons::LoadIcons(HMODULE m) +{ + UString iconTypes; + MyLoadString(m, kIconTypesResId, iconTypes); + UStringVector pairs; + SplitString(iconTypes, pairs); + FOR_VECTOR (i, pairs) + { + const UString &s = pairs[i]; + int pos = s.Find(L':'); + CIconPair iconPair; + iconPair.IconIndex = -1; + if (pos < 0) + pos = s.Len(); + else + { + UString num = s.Ptr(pos + 1); + if (!num.IsEmpty()) + { + const wchar_t *end; + iconPair.IconIndex = ConvertStringToUInt32(num, &end); + if (*end != 0) + continue; + } + } + iconPair.Ext = s.Left(pos); + IconPairs.Add(iconPair); + } +} + +bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const +{ + iconIndex = -1; + FOR_VECTOR (i, IconPairs) + { + const CIconPair &pair = IconPairs[i]; + if (ext.IsEqualTo_NoCase(pair.Ext)) + { + iconIndex = pair.IconIndex; + return true; + } + } + return false; +} + +#endif // NEW_FOLDER_INTERFACE + + #ifdef EXTERNAL_CODECS // #define EXPORT_CODECS @@ -678,7 +798,8 @@ bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &forma #ifdef EXPORT_CODECS extern unsigned g_NumCodecs; -STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject); +STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject); +STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject); STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); #define NUM_EXPORT_CODECS g_NumCodecs @@ -694,7 +815,7 @@ STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); #endif // EXPORT_CODECS -STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods) +STDMETHODIMP CCodecs::GetNumMethods(UInt32 *numMethods) { *numMethods = NUM_EXPORT_CODECS #ifdef EXTERNAL_CODECS @@ -718,13 +839,14 @@ STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *valu propID == NMethodPropID::kEncoderIsAssigned) { NCOM::CPropVariant prop; - prop = (propID == NMethodPropID::kDecoderIsAssigned) ? + prop = (bool)((propID == NMethodPropID::kDecoderIsAssigned) ? ci.DecoderIsAssigned : - ci.EncoderIsAssigned; + ci.EncoderIsAssigned); prop.Detach(value); return S_OK; } - return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value); + const CCodecLib &lib = Libs[ci.LibIndex]; + return lib.GetMethodProperty(ci.CodecIndex, propID, value); #else return E_FAIL; #endif @@ -734,12 +856,18 @@ STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) - return CreateCoder2(false, index, iid, coder); + return CreateDecoder(index, iid, coder); #endif + #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; if (ci.DecoderIsAssigned) - return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder); + { + const CCodecLib &lib = Libs[ci.LibIndex]; + if (lib.CreateDecoder) + return lib.CreateDecoder(index - NUM_EXPORT_CODECS, iid, (void **)coder); + return lib.CreateObject(&ci.Decoder, iid, (void **)coder); + } return S_OK; #else return E_FAIL; @@ -750,12 +878,18 @@ STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) - return CreateCoder2(true, index, iid, coder); + return CreateEncoder(index, iid, coder); #endif + #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; if (ci.EncoderIsAssigned) - return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder); + { + const CCodecLib &lib = Libs[ci.LibIndex]; + if (lib.CreateEncoder) + return lib.CreateEncoder(index - NUM_EXPORT_CODECS, iid, (void **)coder); + return lib.CreateObject(&ci.Encoder, iid, (void **)coder); + } return S_OK; #else return E_FAIL; @@ -781,7 +915,7 @@ STDMETHODIMP CCodecs::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *va #ifdef EXTERNAL_CODECS const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; - return Libs[ci.LibIndex].Hashers->GetHasherProp(ci.HasherIndex, propID, value); + return Libs[ci.LibIndex].ComHashers->GetHasherProp(ci.HasherIndex, propID, value); #else return E_FAIL; #endif @@ -795,18 +929,19 @@ STDMETHODIMP CCodecs::CreateHasher(UInt32 index, IHasher **hasher) #endif #ifdef EXTERNAL_CODECS const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; - return Libs[ci.LibIndex].Hashers->CreateHasher(ci.HasherIndex, hasher); + return Libs[ci.LibIndex].ComHashers->CreateHasher(ci.HasherIndex, hasher); #else return E_FAIL; #endif } -int CCodecs::GetCodecLibIndex(UInt32 index) +int CCodecs::GetCodec_LibIndex(UInt32 index) const { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return -1; #endif + #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; return ci.LibIndex; @@ -821,6 +956,7 @@ int CCodecs::GetHasherLibIndex(UInt32 index) if (index < g_NumHashers) return -1; #endif + #ifdef EXTERNAL_CODECS const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; return ci.LibIndex; @@ -829,27 +965,62 @@ int CCodecs::GetHasherLibIndex(UInt32 index) #endif } -bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index) +bool CCodecs::GetCodec_DecoderIsAssigned(UInt32 index) const { #ifdef EXPORT_CODECS if (index < g_NumCodecs) { NCOM::CPropVariant prop; - if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK) - if (prop.vt != VT_EMPTY) - return true; + if (GetProperty(index, NMethodPropID::kDecoderIsAssigned, &prop) == S_OK) + { + if (prop.vt == VT_BOOL) + return VARIANT_BOOLToBool(prop.boolVal); + } return false; } #endif + #ifdef EXTERNAL_CODECS - const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; - return ci.EncoderIsAssigned; + return Codecs[index - NUM_EXPORT_CODECS].DecoderIsAssigned; #else return false; #endif } -HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id) +bool CCodecs::GetCodec_EncoderIsAssigned(UInt32 index) const +{ + #ifdef EXPORT_CODECS + if (index < g_NumCodecs) + { + NCOM::CPropVariant prop; + if (GetProperty(index, NMethodPropID::kEncoderIsAssigned, &prop) == S_OK) + { + if (prop.vt == VT_BOOL) + return VARIANT_BOOLToBool(prop.boolVal); + } + return false; + } + #endif + + #ifdef EXTERNAL_CODECS + return Codecs[index - NUM_EXPORT_CODECS].EncoderIsAssigned; + #else + return false; + #endif +} + +UInt32 CCodecs::GetCodec_NumStreams(UInt32 index) +{ + NCOM::CPropVariant prop; + RINOK(GetProperty(index, NMethodPropID::kPackStreams, &prop)); + if (prop.vt == VT_UI4) + return (UInt32)prop.ulVal; + if (prop.vt == VT_EMPTY) + return 1; + return 0; +} + +HRESULT CCodecs::GetCodec_Id(UInt32 index, UInt64 &id) { NCOM::CPropVariant prop; RINOK(GetProperty(index, NMethodPropID::kID, &prop)); @@ -859,32 +1030,33 @@ HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id) return S_OK; } -UString CCodecs::GetCodecName(UInt32 index) +AString CCodecs::GetCodec_Name(UInt32 index) { - UString s; + AString s; NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK) if (prop.vt == VT_BSTR) - s = prop.bstrVal; + s.SetFromWStr_if_Ascii(prop.bstrVal); return s; } UInt64 CCodecs::GetHasherId(UInt32 index) { NCOM::CPropVariant prop; - RINOK(GetHasherProp(index, NMethodPropID::kID, &prop)); + if (GetHasherProp(index, NMethodPropID::kID, &prop) != S_OK) + return 0; if (prop.vt != VT_UI8) return 0; return prop.uhVal.QuadPart; } -UString CCodecs::GetHasherName(UInt32 index) +AString CCodecs::GetHasherName(UInt32 index) { - UString s; + AString s; NCOM::CPropVariant prop; if (GetHasherProp(index, NMethodPropID::kName, &prop) == S_OK) if (prop.vt == VT_BSTR) - s = prop.bstrVal; + s.SetFromWStr_if_Ascii(prop.bstrVal); return s; } diff --git a/CPP/7zip/UI/Common/LoadCodecs.h b/CPP/7zip/UI/Common/LoadCodecs.h index 5a54d365..ac9eeac7 100644 --- a/CPP/7zip/UI/Common/LoadCodecs.h +++ b/CPP/7zip/UI/Common/LoadCodecs.h @@ -3,34 +3,82 @@ #ifndef __LOAD_CODECS_H #define __LOAD_CODECS_H +/* +Client application uses LoadCodecs.* to load plugins to +CCodecs object, that contains 3 lists of plugins: + 1) Formats - internal and external archive handlers + 2) Codecs - external codecs + 3) Hashers - external hashers + +EXTERNAL_CODECS +--------------- + + if EXTERNAL_CODECS is defined, then the code tries to load external + plugins from DLL files (shared libraries). + + There are two types of executables in 7-Zip: + + 1) Executable that uses external plugins must be compiled + with EXTERNAL_CODECS defined: + - 7z.exe, 7zG.exe, 7zFM.exe + + Note: EXTERNAL_CODECS is used also in CPP/7zip/Common/CreateCoder.h + that code is used in plugin module (7z.dll). + + 2) Standalone modules are compiled without EXTERNAL_CODECS: + - SFX modules: 7z.sfx, 7zCon.sfx + - standalone versions of console 7-Zip: 7za.exe, 7zr.exe + + if EXTERNAL_CODECS is defined, CCodecs class implements interfaces: + - ICompressCodecsInfo : for Codecs + - IHashers : for Hashers + + The client application can send CCodecs object to each plugin module. + And plugin module can use ICompressCodecsInfo or IHashers interface to access + another plugins. + + There are 2 ways to send (ICompressCodecsInfo * compressCodecsInfo) to plugin + 1) for old versions: + a) request ISetCompressCodecsInfo from created archive handler. + b) call ISetCompressCodecsInfo::SetCompressCodecsInfo(compressCodecsInfo) + 2) for new versions: + a) request "SetCodecs" function from DLL file + b) call SetCodecs(compressCodecsInfo) function from DLL file +*/ + #include "../../../Common/MyBuffer.h" #include "../../../Common/MyCom.h" #include "../../../Common/MyString.h" #include "../../../Common/ComTry.h" -#include "../../ICoder.h" - #ifdef EXTERNAL_CODECS #include "../../../Windows/DLL.h" #endif +#include "../../ICoder.h" + +#include "../../Archive/IArchive.h" + + +#ifdef EXTERNAL_CODECS + struct CDllCodecInfo { - CLSID Encoder; - CLSID Decoder; + unsigned LibIndex; + UInt32 CodecIndex; bool EncoderIsAssigned; bool DecoderIsAssigned; - int LibIndex; - UInt32 CodecIndex; + CLSID Encoder; + CLSID Decoder; }; struct CDllHasherInfo { - int LibIndex; + unsigned LibIndex; UInt32 HasherIndex; }; -#include "../../Archive/IArchive.h" +#endif struct CArcExtInfo { @@ -129,9 +177,8 @@ struct CArcInfoEx {} }; -#ifdef EXTERNAL_CODECS - #ifdef NEW_FOLDER_INTERFACE + struct CCodecIcons { struct CIconPair @@ -140,11 +187,15 @@ struct CCodecIcons int IconIndex; }; CObjectVector<CIconPair> IconPairs; + void LoadIcons(HMODULE m); bool FindIconIndex(const UString &ext, int &iconIndex) const; }; + #endif +#ifdef EXTERNAL_CODECS + struct CCodecLib #ifdef NEW_FOLDER_INTERFACE : public CCodecIcons @@ -152,56 +203,108 @@ struct CCodecLib { NWindows::NDLL::CLibrary Lib; FString Path; - Func_GetMethodProperty GetMethodProperty; + Func_CreateObject CreateObject; - CMyComPtr<IHashers> Hashers; + Func_GetMethodProperty GetMethodProperty; + Func_CreateDecoder CreateDecoder; + Func_CreateEncoder CreateEncoder; + Func_SetCodecs SetCodecs; + + CMyComPtr<IHashers> ComHashers; #ifdef NEW_FOLDER_INTERFACE void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); } #endif - CCodecLib(): GetMethodProperty(NULL) {} + CCodecLib(): + CreateObject(NULL), + GetMethodProperty(NULL), + CreateDecoder(NULL), + CreateEncoder(NULL), + SetCodecs(NULL) + {} }; + #endif + class CCodecs: #ifdef EXTERNAL_CODECS - public ICompressCodecsInfo, - public IHashers, + public ICompressCodecsInfo, + public IHashers, #else - public IUnknown, + public IUnknown, #endif public CMyUnknownImp { + CLASS_NO_COPY(CCodecs); public: #ifdef EXTERNAL_CODECS + CObjectVector<CCodecLib> Libs; - CRecordVector<CDllCodecInfo> Codecs; - CRecordVector<CDllHasherInfo> Hashers; + FString MainDll_ErrorPath; - #ifdef NEW_FOLDER_INTERFACE - CCodecIcons InternalIcons; - #endif + void CloseLibs(); + + class CReleaser + { + CLASS_NO_COPY(CReleaser); + + /* CCodecsReleaser object releases CCodecs links. + 1) CCodecs is COM object that is deleted when all links to that object will be released/ + 2) CCodecs::Libs[i] can hold (ICompressCodecsInfo *) link to CCodecs object itself. + To break that reference loop, we must close all CCodecs::Libs in CCodecsReleaser desttructor. */ + + CCodecs *_codecs; + + public: + CReleaser(): _codecs(NULL) {} + void Set(CCodecs *codecs) { _codecs = codecs; } + ~CReleaser() { if (_codecs) _codecs->CloseLibs(); } + }; + + bool NeedSetLibCodecs; // = false, if we don't need to set codecs for archive handler via ISetCompressCodecsInfo HRESULT LoadCodecs(); HRESULT LoadFormats(); - HRESULT LoadDll(const FString &path, bool needCheckDll); + HRESULT LoadDll(const FString &path, bool needCheckDll, bool *loadedOK = NULL); HRESULT LoadDllsFromFolder(const FString &folderPrefix); - HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const + HRESULT CreateArchiveHandler(const CArcInfoEx &ai, bool outHandler, void **archive) const { return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive); } + + #endif + + #ifdef NEW_FOLDER_INTERFACE + CCodecIcons InternalIcons; #endif -public: CObjectVector<CArcInfoEx> Formats; + + #ifdef EXTERNAL_CODECS + CRecordVector<CDllCodecInfo> Codecs; + CRecordVector<CDllHasherInfo> Hashers; + #endif + bool CaseSensitiveChange; bool CaseSensitive; - CCodecs(): CaseSensitiveChange(false), CaseSensitive(false) {} + CCodecs(): + #ifdef EXTERNAL_CODECS + NeedSetLibCodecs(true), + #endif + CaseSensitiveChange(false), + CaseSensitive(false) + {} + + ~CCodecs() + { + // OutputDebugStringA("~CCodecs"); + } - const wchar_t *GetFormatNamePtr(int formatIndex) + const wchar_t *GetFormatNamePtr(int formatIndex) const { return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[formatIndex].Name; } @@ -219,10 +322,10 @@ public: MY_UNKNOWN_IMP2(ICompressCodecsInfo, IHashers) - STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods); + STDMETHOD(GetNumMethods)(UInt32 *numMethods); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); - STDMETHOD(CreateDecoder)(UInt32 index, const GUID *interfaceID, void **coder); - STDMETHOD(CreateEncoder)(UInt32 index, const GUID *interfaceID, void **coder); + STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder); + STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder); STDMETHOD_(UInt32, GetNumHashers)(); STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value); @@ -234,16 +337,19 @@ public: #endif // EXTERNAL_CODECS + #ifdef EXTERNAL_CODECS - int GetCodecLibIndex(UInt32 index); - bool GetCodecEncoderIsAssigned(UInt32 index); - HRESULT GetCodecId(UInt32 index, UInt64 &id); - UString GetCodecName(UInt32 index); + int GetCodec_LibIndex(UInt32 index) const; + bool GetCodec_DecoderIsAssigned(UInt32 index) const; + bool GetCodec_EncoderIsAssigned(UInt32 index) const; + UInt32 GetCodec_NumStreams(UInt32 index); + HRESULT GetCodec_Id(UInt32 index, UInt64 &id); + AString GetCodec_Name(UInt32 index); int GetHasherLibIndex(UInt32 index); UInt64 GetHasherId(UInt32 index); - UString GetHasherName(UInt32 index); + AString GetHasherName(UInt32 index); UInt32 GetHasherDigestSize(UInt32 index); #endif @@ -261,7 +367,7 @@ public: COM_TRY_END } #ifdef EXTERNAL_CODECS - return CreateArchiveHandler(ai, (void **)&archive, false); + return CreateArchiveHandler(ai, false, (void **)&archive); #endif } @@ -279,8 +385,9 @@ public: return S_OK; COM_TRY_END } + #ifdef EXTERNAL_CODECS - return CreateArchiveHandler(ai, (void **)&archive, true); + return CreateArchiveHandler(ai, true, (void **)&archive); #endif } @@ -291,7 +398,7 @@ public: const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; - if (arc.Name.IsEqualToNoCase(name)) + if (arc.Name.IsEqualTo_NoCase(name)) return i; } return -1; @@ -300,4 +407,18 @@ public: #endif // _SFX }; +#ifdef EXTERNAL_CODECS + #define CREATE_CODECS_OBJECT \ + CCodecs *codecs = new CCodecs; \ + CExternalCodecs __externalCodecs; \ + __externalCodecs.GetCodecs = codecs; \ + __externalCodecs.GetHashers = codecs; \ + CCodecs::CReleaser codecsReleaser; \ + codecsReleaser.Set(codecs); +#else + #define CREATE_CODECS_OBJECT \ + CCodecs *codecs = new CCodecs; \ + CMyComPtr<IUnknown> __codecsRef = codecs; +#endif + #endif diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp index 2f5d816d..acc10876 100644 --- a/CPP/7zip/UI/Common/OpenArchive.cpp +++ b/CPP/7zip/UI/Common/OpenArchive.cpp @@ -195,17 +195,13 @@ public: } void AddUnknownItem(UInt64 next); - int FindInsertPos(const CParseItem &item); + int FindInsertPos(const CParseItem &item) const; void AddItem(const CParseItem &item); - // void Init(); - CHandler() - { - _maxEndOffset = 0; - } + CHandler(): _maxEndOffset(0) {} }; -int CHandler::FindInsertPos(const CParseItem &item) +int CHandler::FindInsertPos(const CParseItem &item) const { unsigned left = 0, right = _items.Size(); while (left != right) @@ -368,6 +364,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _items.Size(); @@ -429,7 +426,9 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, outStreamSpec->ReleaseStream(); RINOK(extractCallback->SetOperationResult(opRes)); } + return S_OK; + COM_TRY_END } @@ -458,7 +457,7 @@ HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bo return S_OK; } -HRESULT Archive_IsItem_Folder(IInArchive *arc, UInt32 index, bool &result) throw() +HRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw() { return Archive_GetItemBoolProp(arc, index, kpidIsDir, result); } @@ -478,7 +477,7 @@ HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &result) thro return Archive_GetItemBoolProp(arc, index, kpidIsDeleted, result); } -static HRESULT Archive_GetArcBoolProp(IInArchive *arc, PROPID propid, bool &result) +static HRESULT Archive_GetArcBoolProp(IInArchive *arc, PROPID propid, bool &result) throw() { NCOM::CPropVariant prop; result = false; @@ -524,16 +523,22 @@ static HRESULT Archive_GetArcProp_Int(IInArchive *arc, PROPID propid, Int64 &res return S_OK; } +#ifndef _SFX + HRESULT CArc::GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const { if (!GetRawProps) return E_FAIL; + if (index == parent) + return S_OK; UInt32 curIndex = index; + + UString s; + bool prevWasAltStream = false; + for (;;) { - UString s; - #ifdef MY_CPU_LE const void *p; UInt32 size; @@ -546,31 +551,59 @@ HRESULT CArc::GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &pa { NCOM::CPropVariant prop; RINOK(Archive->GetProperty(curIndex, kpidName, &prop)); - if (prop.vt == VT_BSTR) - s = prop.bstrVal; + if (prop.vt == VT_BSTR && prop.bstrVal) + s.SetFromBstr(prop.bstrVal); else if (prop.vt == VT_EMPTY) - s = L"[Content]"; + s.Empty(); else return E_FAIL; } - - if (prevWasAltStream) - parts[0] = s + L":" + parts[0]; - else - parts.Insert(0, s); UInt32 curParent = (UInt32)(Int32)-1; UInt32 parentType = 0; RINOK(GetRawProps->GetParent(curIndex, &curParent, &parentType)); + + if (parentType != NParentType::kAltStream) + { + for (;;) + { + int pos = s.ReverseFind_PathSepar(); + if (pos < 0) + { + break; + } + parts.Insert(0, s.Ptr(pos + 1)); + s.DeleteFrom(pos); + } + } + + parts.Insert(0, s); + + if (prevWasAltStream) + { + { + UString &s = parts[parts.Size() - 2]; + s += L':'; + s += parts.Back(); + } + parts.DeleteBack(); + } + if (parent == curParent) return S_OK; + + prevWasAltStream = false; + if (parentType == NParentType::kAltStream) + prevWasAltStream = true; + if (curParent == (UInt32)(Int32)-1) return E_FAIL; - prevWasAltStream = (parentType == NParentType::kAltStream); curIndex = curParent; } } +#endif + HRESULT CArc::GetItemPath(UInt32 index, UString &result) const { #ifdef MY_CPU_LE @@ -585,7 +618,7 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const propType == NPropDataType::kUtf16z) { unsigned len = size / 2 - 1; - wchar_t *s = result.GetBuffer(len); + wchar_t *s = result.GetBuf(len); for (unsigned i = 0; i < len; i++) { wchar_t c = GetUi16(p); @@ -596,7 +629,8 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const #endif *s++ = c; } - result.ReleaseBuffer(len); + *s = 0; + result.ReleaseBuf_SetLen(len); if (len != 0) return S_OK; } @@ -605,8 +639,10 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const else if (GetRawProps->GetRawProp(index, kpidName, &p, &size, &propType) == S_OK && p && propType == NPropDataType::kUtf16z) { + size -= 2; UInt32 totalSize = size; bool isOK = false; + { UInt32 index2 = index; for (;;) @@ -617,13 +653,16 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const break; if (parent == (UInt32)(Int32)-1) { + if (parentType != 0) + totalSize += 2; isOK = true; break; } index2 = parent; UInt32 size2; const void *p2; - if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK) + if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK && + p2 && propType == NPropDataType::kUtf16z) break; totalSize += size2; } @@ -631,9 +670,9 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const if (isOK) { - wchar_t *sz = result.GetBuffer(totalSize / 2); + wchar_t *sz = result.GetBuf_SetEnd(totalSize / 2); UInt32 pos = totalSize - size; - memcpy((Byte *)sz + pos, p, size - 2); + memcpy((Byte *)sz + pos, p, size); UInt32 index2 = index; for (;;) { @@ -642,7 +681,11 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK) break; if (parent == (UInt32)(Int32)-1) + { + if (parentType != 0) + sz[pos / 2 - 1] = L':'; break; + } index2 = parent; UInt32 size2; const void *p2; @@ -652,7 +695,6 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const memcpy((Byte *)sz + pos, p2, size2); sz[(pos + size2 - 2) / 2] = (parentType == 0) ? WCHAR_PATH_SEPARATOR : L':'; } - result.ReleaseBuffer((totalSize - 2) / 2); #ifdef _WIN32 // result.Replace(L'/', WCHAR_PATH_SEPARATOR); #endif @@ -666,8 +708,8 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const { NCOM::CPropVariant prop; RINOK(Archive->GetProperty(index, kpidPath, &prop)); - if (prop.vt == VT_BSTR) - result = prop.bstrVal; + if (prop.vt == VT_BSTR && prop.bstrVal) + result.SetFromBstr(prop.bstrVal); else if (prop.vt == VT_EMPTY) result.Empty(); else @@ -675,6 +717,16 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const } if (result.IsEmpty()) + return GetDefaultItemPath(index, result); + return S_OK; +} + +HRESULT CArc::GetDefaultItemPath(UInt32 index, UString &result) const +{ + result.Empty(); + bool isDir; + RINOK(Archive_IsItem_Dir(Archive, index, isDir)); + if (!isDir) { result = DefaultName; NCOM::CPropVariant prop; @@ -703,6 +755,161 @@ HRESULT CArc::GetItemPath2(UInt32 index, UString &result) const return S_OK; } +#ifdef SUPPORT_ALT_STREAMS + +int FindAltStreamColon_in_Path(const wchar_t *path) +{ + unsigned i = 0; + int colonPos = -1; + for (;; i++) + { + wchar_t c = path[i]; + if (c == 0) + return colonPos; + if (c == ':') + { + if (colonPos < 0) + colonPos = i; + continue; + } + if (c == WCHAR_PATH_SEPARATOR) + colonPos = -1; + } +} + +#endif + +HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const +{ + #ifdef SUPPORT_ALT_STREAMS + item.IsAltStream = false; + item.AltStreamName.Empty(); + item.MainPath.Empty(); + #endif + + item.IsDir = false; + item.Path.Empty(); + item.ParentIndex = (UInt32)(Int32)-1; + + item.PathParts.Clear(); + + RINOK(Archive_IsItem_Dir(Archive, index, item.IsDir)); + item.MainIsDir = item.IsDir; + + RINOK(GetItemPath2(index, item.Path)); + + #ifndef _SFX + UInt32 mainIndex = index; + #endif + + #ifdef SUPPORT_ALT_STREAMS + + item.MainPath = item.Path; + if (Ask_AltStream) + { + RINOK(Archive_IsItem_AltStream(Archive, index, item.IsAltStream)); + } + + bool needFindAltStream = false; + + if (item.IsAltStream) + { + needFindAltStream = true; + if (GetRawProps) + { + UInt32 parentType = 0; + UInt32 parentIndex; + RINOK(GetRawProps->GetParent(index, &parentIndex, &parentType)); + if (parentType == NParentType::kAltStream) + { + NCOM::CPropVariant prop; + RINOK(Archive->GetProperty(index, kpidName, &prop)); + if (prop.vt == VT_BSTR && prop.bstrVal) + item.AltStreamName.SetFromBstr(prop.bstrVal); + else if (prop.vt != VT_EMPTY) + return E_FAIL; + else + { + // item.IsAltStream = false; + } + /* + if (item.AltStreamName.IsEmpty()) + item.IsAltStream = false; + */ + + needFindAltStream = false; + item.ParentIndex = parentIndex; + mainIndex = parentIndex; + + if (parentIndex == (UInt32)(Int32)-1) + { + item.MainPath.Empty(); + item.MainIsDir = true; + } + else + { + RINOK(GetItemPath2(parentIndex, item.MainPath)); + RINOK(Archive_IsItem_Dir(Archive, parentIndex, item.MainIsDir)); + } + } + } + } + + if (item.WriteToAltStreamIfColon || needFindAltStream) + { + /* Good handler must support GetRawProps::GetParent for alt streams./ + So the following code currently is not used */ + int colon = FindAltStreamColon_in_Path(item.Path); + if (colon >= 0) + { + item.MainPath.DeleteFrom(colon); + item.AltStreamName = item.Path.Ptr(colon + 1); + item.MainIsDir = (colon == 0 || IsPathSepar(item.Path[colon - 1])); + item.IsAltStream = true; + } + } + + #endif + + #ifndef _SFX + if (item._use_baseParentFolder_mode) + { + RINOK(GetItemPathToParent(mainIndex, item._baseParentFolder, item.PathParts)); + + #ifdef SUPPORT_ALT_STREAMS + if ((item.WriteToAltStreamIfColon || needFindAltStream) && !item.PathParts.IsEmpty()) + { + int colon; + { + UString &s = item.PathParts.Back(); + colon = FindAltStreamColon_in_Path(s); + if (colon >= 0) + { + item.AltStreamName = s.Ptr(colon + 1); + item.MainIsDir = (colon == 0 || IsPathSepar(s[(unsigned)colon - 1])); + item.IsAltStream = true; + s.DeleteFrom(colon); + } + } + if (colon == 0) + item.PathParts.DeleteBack(); + } + #endif + + } + else + #endif + SplitPathToParts( + #ifdef SUPPORT_ALT_STREAMS + item.MainPath + #else + item.Path + #endif + , item.PathParts); + + return S_OK; +} + #ifndef _SFX static HRESULT Archive_GetItem_Size(IInArchive *archive, UInt32 index, UInt64 &size, bool &defined) @@ -824,10 +1031,10 @@ static void MakeCheckOrder(CCodecs *codecs, static bool IsExeExt(const UString &ext) { - return ext.IsEqualToNoCase(L"exe"); + return ext.IsEqualTo_Ascii_NoCase("exe"); } -static const char *k_PreArcFormats[] = +static const char * const k_PreArcFormats[] = { "pe" , "elf" @@ -836,7 +1043,7 @@ static const char *k_PreArcFormats[] = , "te" }; -static bool IsNameFromList(const UString &s, const char *names[], size_t num) +static bool IsNameFromList(const UString &s, const char * const names[], size_t num) { for (unsigned i = 0; i < num; i++) if (StringsAreEqualNoCase_Ascii(s, names[i])) @@ -852,7 +1059,7 @@ static bool IsPreArcFormat(const CArcInfoEx &ai) return IsNameFromList(ai.Name, k_PreArcFormats, ARRAY_SIZE(k_PreArcFormats)); } -static const char *k_Formats_with_simple_signuature[] = +static const char * const k_Formats_with_simple_signuature[] = { "7z" , "xz" @@ -984,14 +1191,14 @@ HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openR NCOM::CPropVariant prop; RINOK(archive->GetArchiveProperty(kpidError, &prop)); if (prop.vt != VT_EMPTY) - ErrorInfo.ErrorMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown error"; + ErrorInfo.ErrorMessage = (prop.vt == VT_BSTR ? prop.bstrVal : L"Unknown error"); } { NCOM::CPropVariant prop; RINOK(archive->GetArchiveProperty(kpidWarning, &prop)); if (prop.vt != VT_EMPTY) - ErrorInfo.WarningMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown warning"; + ErrorInfo.WarningMessage = (prop.vt == VT_BSTR ? prop.bstrVal : L"Unknown warning"); } if (openRes == S_OK || ErrorInfo.IsArc_After_NonOpen()) @@ -1039,30 +1246,40 @@ static PrintNumber(const char *s, int n) HRESULT CArc::PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive) { - // OutputDebugStringW(L"a1"); + // OutputDebugStringA("a1"); // PrintNumber("formatIndex", formatIndex); RINOK(op.codecs->CreateInArchive(formatIndex, archive)); - // OutputDebugStringW(L"a2"); + // OutputDebugStringA("a2"); if (!archive) return S_OK; #ifdef EXTERNAL_CODECS + if (op.codecs->NeedSetLibCodecs) { - CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; - archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); - if (setCompressCodecsInfo) + const CArcInfoEx &ai = op.codecs->Formats[formatIndex]; + if (ai.LibIndex >= 0 ? + !op.codecs->Libs[ai.LibIndex].SetCodecs : + !op.codecs->Libs.IsEmpty()) { - RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(op.codecs)); + CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; + archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); + if (setCompressCodecsInfo) + { + RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(op.codecs)); + } } } #endif - // OutputDebugStringW(ai.Name); - // OutputDebugStringW(L"a3"); #ifndef _SFX + const CArcInfoEx &ai = op.codecs->Formats[formatIndex]; + + // OutputDebugStringW(ai.Name); + // OutputDebugStringA("a3"); + if (ai.Flags_PreArc()) { /* we notify parsers that extract executables, that they don't need @@ -1072,6 +1289,7 @@ HRESULT CArc::PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyCom if (allowTail) allowTail->AllowTail(BoolToInt(true)); } + if (op.props) { /* @@ -1087,6 +1305,7 @@ HRESULT CArc::PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyCom */ RINOK(SetProperties(archive, *op.props)); } + #endif return S_OK; } @@ -1130,14 +1349,14 @@ static HRESULT ReadParseItemProps(IInArchive *archive, const CArcInfoEx &ai, NAr RINOK(archive->GetArchiveProperty(kpidName, &prop)); if (prop.vt == VT_BSTR) { - pi.Name = prop.bstrVal; + pi.Name.SetFromBstr(prop.bstrVal); pi.Extension.Empty(); } else { RINOK(archive->GetArchiveProperty(kpidExtension, &prop)); if (prop.vt == VT_BSTR) - pi.Extension = prop.bstrVal; + pi.Extension.SetFromBstr(prop.bstrVal); } } @@ -1145,7 +1364,7 @@ static HRESULT ReadParseItemProps(IInArchive *archive, const CArcInfoEx &ai, NAr NCOM::CPropVariant prop; RINOK(archive->GetArchiveProperty(kpidShortComment, &prop)); if (prop.vt == VT_BSTR) - pi.Comment = prop.bstrVal; + pi.Comment.SetFromBstr(prop.bstrVal); } @@ -1171,7 +1390,7 @@ static HRESULT ReadParseItemProps(IInArchive *archive, const CArcInfoEx &ai, NAr } bool isDir = false; - Archive_IsItem_Folder(archive, i, isDir); + Archive_IsItem_Dir(archive, i, isDir); if (isDir) pi.NumSubDirs++; else @@ -1336,13 +1555,13 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) IsParseArc = false; ArcStreamOffset = 0; - // OutputDebugStringW(L"1"); + // OutputDebugStringA("1"); // OutputDebugStringW(Path); const UString fileName = ExtractFileNameFromPath(Path); UString extension; { - int dotPos = fileName.ReverseFind(L'.'); + int dotPos = fileName.ReverseFind_Dot(); if (dotPos >= 0) extension = fileName.Ptr(dotPos + 1); } @@ -1378,7 +1597,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) isForced = true; orderIndices.Add(formatIndex); numMainTypes = 1; - isMainFormatArr[formatIndex] = true; + isMainFormatArr[(unsigned)formatIndex] = true; searchMarkerInHandler = true; } @@ -1443,7 +1662,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) { // signature search was here } - else if (extension == L"000" || extension == L"001") + else if (extension.IsEqualTo("000") || extension.IsEqualTo("001")) { int i = FindFormatForArchiveType(op.codecs, orderIndices, "rar"); if (i >= 0) @@ -1517,6 +1736,10 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) #else // _SFX numMainTypes = orderIndices.Size(); + + // we need correct numMainTypes for mutlivolume SFX (if some volume is missing) + if (numFinded != 0) + numMainTypes = numFinded; #endif } @@ -1557,10 +1780,13 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) for (unsigned i = 0; i < numCheckTypes; i++) { FormatIndex = orderIndices[i]; - const CArcInfoEx &ai = op.codecs->Formats[FormatIndex]; - // OutputDebugStringW(ai.Name); bool exactOnly = false; + + #ifndef _SFX + + const CArcInfoEx &ai = op.codecs->Formats[FormatIndex]; + // OutputDebugStringW(ai.Name); if (i >= numMainTypes) { if (!ai.Flags_BackwardOpen() @@ -1569,9 +1795,13 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) continue; exactOnly = true; } + + #endif // Some handlers do not set total bytes. So we set it here - RINOK(op.callback->SetTotal(NULL, &fileSize)); + if (op.callback) + RINOK(op.callback->SetTotal(NULL, &fileSize)); + if (op.stream) { RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); @@ -1607,7 +1837,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) #ifndef _SFX // if it's archive, we allow another open attempt for parser if (!mode.CanReturnParser || !isArc) - skipFrontalFormat[FormatIndex] = true; + skipFrontalFormat[(unsigned)FormatIndex] = true; #endif if (exactOnly) @@ -1650,7 +1880,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) #ifndef _SFX - bool isMainFormat = isMainFormatArr[FormatIndex]; + bool isMainFormat = isMainFormatArr[(unsigned)FormatIndex]; const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt); bool thereIsTail = ErrorInfo.ThereIsTail; @@ -1834,7 +2064,9 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) FormatIndex = sortedFormats[i]; const CArcInfoEx &ai = op.codecs->Formats[FormatIndex]; - RINOK(op.callback->SetTotal(NULL, &fileSize)); + if (op.callback) + RINOK(op.callback->SetTotal(NULL, &fileSize)); + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); CMyComPtr<IInArchive> archive; @@ -1856,7 +2088,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) if (result == S_FALSE) { - skipFrontalFormat[FormatIndex] = true; + skipFrontalFormat[(unsigned)FormatIndex] = true; // FIXME: maybe we must use LenIsUnknown. // printf(" OpenForSize Error"); continue; @@ -1900,7 +2132,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) if (mode.CanReturnArc) { - bool isMainFormat = isMainFormatArr[FormatIndex]; + bool isMainFormat = isMainFormatArr[(unsigned)FormatIndex]; const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt); bool openCur = false; @@ -1938,7 +2170,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) } } - skipFrontalFormat[FormatIndex] = true; + skipFrontalFormat[(unsigned)FormatIndex] = true; // if (!mode.CanReturnArc) @@ -2032,7 +2264,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) } thereAreHandlersForSearch = true; UInt32 v = HASH_VAL(sig, 0); - unsigned sigIndex = arc2sig[index] + k; + unsigned sigIndex = arc2sig[(unsigned)index] + k; prevs[sigIndex] = hash[v]; hash[v] = (Byte)sigIndex; } @@ -2065,7 +2297,9 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) } #endif - RINOK(op.callback->SetTotal(NULL, &fileSize)); + if (op.callback) + RINOK(op.callback->SetTotal(NULL, &fileSize)); + CByteBuffer &byteBuffer = limitedStreamSpec->Buffer; byteBuffer.Alloc(kBufSize); @@ -2607,11 +2841,12 @@ HRESULT CArc::OpenStream(const COpenOptions &op) RINOK(Archive_GetArcBoolProp(Archive, kpidIsAltStream, Ask_AltStream)); RINOK(Archive_GetArcBoolProp(Archive, kpidIsAux, Ask_Aux)); RINOK(Archive_GetArcBoolProp(Archive, kpidINode, Ask_INode)); + RINOK(Archive_GetArcBoolProp(Archive, kpidReadOnly, IsReadOnly)); const UString fileName = ExtractFileNameFromPath(Path); UString extension; { - int dotPos = fileName.ReverseFind(L'.'); + int dotPos = fileName.ReverseFind_Dot(); if (dotPos >= 0) extension = fileName.Ptr(dotPos + 1); } @@ -2621,7 +2856,7 @@ HRESULT CArc::OpenStream(const COpenOptions &op) { const CArcInfoEx &ai = op.codecs->Formats[FormatIndex]; if (ai.Exts.Size() == 0) - DefaultName = GetDefaultName2(fileName, L"", L""); + DefaultName = GetDefaultName2(fileName, UString(), UString()); else { int subExtIndex = ai.FindExtension(extension); @@ -2639,10 +2874,10 @@ HRESULT CArc::OpenStream(const COpenOptions &op) #ifdef _SFX #ifdef _WIN32 - static const wchar_t *k_ExeExt = L".exe"; + static const char *k_ExeExt = ".exe"; static const unsigned k_ExeExt_Len = 4; #else - static const wchar_t *k_ExeExt = L""; + static const char *k_ExeExt = ""; static const unsigned k_ExeExt_Len = 0; #endif @@ -2653,6 +2888,7 @@ HRESULT CArc::OpenStreamOrFile(COpenOptions &op) CMyComPtr<IInStream> fileStream; CMyComPtr<ISequentialInStream> seqStream; CInFileStream *fileStreamSpec = NULL; + if (op.stdInMode) { seqStream = new CStdInFileStream; @@ -2692,9 +2928,10 @@ HRESULT CArc::OpenStreamOrFile(COpenOptions &op) || !op.callbackSpec || NonOpen_ErrorInfo.IsArc_After_NonOpen()) return res; + { if (filePath.Len() > k_ExeExt_Len - && MyStringCompareNoCase(filePath.RightPtr(k_ExeExt_Len), k_ExeExt) == 0) + && StringsAreEqualNoCase_Ascii(filePath.RightPtr(k_ExeExt_Len), k_ExeExt)) { const UString path2 = filePath.Left(filePath.Len() - k_ExeExt_Len); FOR_VECTOR (i, op.codecs->Formats) @@ -2703,9 +2940,10 @@ HRESULT CArc::OpenStreamOrFile(COpenOptions &op) if (ai.IsSplit()) continue; UString path3 = path2; - path3 += L"."; + path3 += L'.'; path3 += ai.GetMainExt(); // "7z" for SFX. - Path = path3 + L".001"; + Path = path3; + Path.AddAscii(".001"); bool isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path)); if (!isOk) { @@ -2733,8 +2971,9 @@ HRESULT CArc::OpenStreamOrFile(COpenOptions &op) void CArchiveLink::KeepModeForNextOpen() { - for (int i = Arcs.Size() - 1; i >= 0; i--) + for (unsigned i = Arcs.Size(); i != 0;) { + i--; CMyComPtr<IArchiveKeepModeForNextOpen> keep; Arcs[i].Archive->QueryInterface(IID_IArchiveKeepModeForNextOpen, (void **)&keep); if (keep) @@ -2744,8 +2983,9 @@ void CArchiveLink::KeepModeForNextOpen() HRESULT CArchiveLink::Close() { - for (int i = Arcs.Size() - 1; i >= 0; i--) + for (unsigned i = Arcs.Size(); i != 0;) { + i--; RINOK(Arcs[i].Close()); } IsOpen = false; @@ -2771,20 +3011,20 @@ void CArchiveLink::Set_ErrorsText() if (!arc.ErrorFlagsText.IsEmpty()) { if (!ErrorsText.IsEmpty()) - ErrorsText += L'\n'; + ErrorsText.Add_LF(); ErrorsText += GetUnicodeString(arc.ErrorFlagsText); } if (!arc.ErrorMessage.IsEmpty()) { if (!ErrorsText.IsEmpty()) - ErrorsText += L'\n'; + ErrorsText.Add_LF(); ErrorsText += arc.ErrorMessage; } if (!arc.WarningMessage.IsEmpty()) { if (!ErrorsText.IsEmpty()) - ErrorsText += L'\n'; + ErrorsText.Add_LF(); ErrorsText += arc.WarningMessage; } } @@ -2909,10 +3149,14 @@ HRESULT CArchiveLink::Open(COpenOptions &op) bool zerosTailIsAllowed; RINOK(Archive_GetItemBoolProp(arc.Archive, mainSubfile, kpidZerosTailIsAllowed, zerosTailIsAllowed)); - CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName; - op.callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); - if (setSubArchiveName) - setSubArchiveName->SetSubArchiveName(arc2.Path); + + if (op.callback) + { + CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName; + op.callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); + if (setSubArchiveName) + setSubArchiveName->SetSubArchiveName(arc2.Path); + } arc2.SubfileIndex = mainSubfile; @@ -2951,23 +3195,7 @@ HRESULT CArchiveLink::Open(COpenOptions &op) return resSpec; } -static void SetCallback(const FString &filePath, - IOpenCallbackUI *callbackUI, - IArchiveOpenCallback *reOpenCallback, - CMyComPtr<IArchiveOpenCallback> &callback) -{ - COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; - callback = openCallbackSpec; - openCallbackSpec->Callback = callbackUI; - openCallbackSpec->ReOpenCallback = reOpenCallback; - - FString dirPrefix, fileName; - NFile::NDir::GetFullPathAndSplit(filePath, dirPrefix, fileName); - openCallbackSpec->Init(dirPrefix, fileName); -} - -HRESULT CArchiveLink::Open2(COpenOptions &op, - IOpenCallbackUI *callbackUI) +HRESULT CArchiveLink::Open2(COpenOptions &op, IOpenCallbackUI *callbackUI) { VolumesSize = 0; COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; @@ -2975,6 +3203,7 @@ HRESULT CArchiveLink::Open2(COpenOptions &op, openCallbackSpec->Callback = callbackUI; FString prefix, name; + if (!op.stream && !op.stdInMode) { NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), prefix, name); @@ -2987,7 +3216,13 @@ HRESULT CArchiveLink::Open2(COpenOptions &op, op.callback = callback; op.callbackSpec = openCallbackSpec; - RINOK(Open(op)); + + HRESULT res = Open(op); + + PasswordWasAsked = openCallbackSpec->PasswordWasAsked; + // Password = openCallbackSpec->Password; + + RINOK(res); // VolumePaths.Add(fs2us(prefix + name)); FOR_VECTOR (i, openCallbackSpec->FileNames_WasUsed) @@ -3044,6 +3279,15 @@ HRESULT CArc::ReOpen(const COpenOptions &op) return res; } +HRESULT CArchiveLink::Open3(COpenOptions &op, IOpenCallbackUI *callbackUI) +{ + HRESULT res = Open2(op, callbackUI); + if (callbackUI) + { + RINOK(callbackUI->Open_Finished()); + } + return res; +} HRESULT CArchiveLink::ReOpen(COpenOptions &op) { @@ -3060,8 +3304,17 @@ HRESULT CArchiveLink::ReOpen(COpenOptions &op) if (Arcs.Size() == 0) // ??? return Open2(op, NULL); - CMyComPtr<IArchiveOpenCallback> openCallbackNew; - SetCallback(us2fs(op.filePath), NULL, op.callback, openCallbackNew); + COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; + CMyComPtr<IArchiveOpenCallback> openCallbackNew = openCallbackSpec; + + openCallbackSpec->Callback = NULL; + openCallbackSpec->ReOpenCallback = op.callback; + { + FString dirPrefix, fileName; + NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), dirPrefix, fileName); + openCallbackSpec->Init(dirPrefix, fileName); + } + CInFileStream *fileStreamSpec = new CInFileStream; CMyComPtr<IInStream> stream(fileStreamSpec); @@ -3071,6 +3324,10 @@ HRESULT CArchiveLink::ReOpen(COpenOptions &op) CArc &arc = Arcs[0]; HRESULT res = arc.ReOpen(op); + + PasswordWasAsked = openCallbackSpec->PasswordWasAsked; + // Password = openCallbackSpec->Password; + IsOpen = (res == S_OK); return res; } @@ -3136,7 +3393,7 @@ static bool ParseTypeParams(const UString &s, COpenType &type) bool ParseType(CCodecs &codecs, const UString &s, COpenType &type) { - int pos2 = s.Find(':'); + int pos2 = s.Find(L':'); UString name; if (pos2 < 0) { @@ -3174,7 +3431,7 @@ bool ParseType(CCodecs &codecs, const UString &s, COpenType &type) for (unsigned i = pos2; i < s.Len();) { - int next = s.Find(':', i); + int next = s.Find(L':', i); if (next < 0) next = s.Len(); UString name = s.Mid(i, next - i); @@ -3193,7 +3450,7 @@ bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> types.Clear(); for (unsigned pos = 0; pos < s.Len();) { - int pos2 = s.Find('.', pos); + int pos2 = s.Find(L'.', pos); if (pos2 < 0) pos2 = s.Len(); UString name = s.Mid(pos, pos2 - pos); diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h index aab6669d..c62bf826 100644 --- a/CPP/7zip/UI/Common/OpenArchive.h +++ b/CPP/7zip/UI/Common/OpenArchive.h @@ -9,12 +9,22 @@ #include "LoadCodecs.h" #include "Property.h" +#ifndef _SFX + +#define SUPPORT_ALT_STREAMS + +#endif + HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw(); -HRESULT Archive_IsItem_Folder(IInArchive *arc, UInt32 index, bool &result) throw(); +HRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw(); HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw(); HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw(); HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &deleted) throw(); +#ifdef SUPPORT_ALT_STREAMS +int FindAltStreamColon_in_Path(const wchar_t *path); +#endif + /* struct COptionalOpenProperties { @@ -212,12 +222,53 @@ struct CArcErrorInfo } }; +struct CReadArcItem +{ + UString Path; // Path from root (including alt stream name, if alt stream) + UStringVector PathParts; // without altStream name, path from root or from _baseParentFolder, if _use_baseParentFolder_mode + + #ifdef SUPPORT_ALT_STREAMS + UString MainPath; + /* MainPath = Path for non-AltStream, + MainPath = Path of parent, if there is parent for AltStream. */ + UString AltStreamName; + bool IsAltStream; + bool WriteToAltStreamIfColon; + #endif + + bool IsDir; + bool MainIsDir; + UInt32 ParentIndex; // use it, if IsAltStream + + #ifndef _SFX + bool _use_baseParentFolder_mode; + int _baseParentFolder; + #endif + + CReadArcItem() + { + #ifdef SUPPORT_ALT_STREAMS + WriteToAltStreamIfColon = false; + #endif + + #ifndef _SFX + _use_baseParentFolder_mode = false; + _baseParentFolder = -1; + #endif + } +}; + class CArc { HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive); HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset); HRESULT OpenStream2(const COpenOptions &options); + #ifndef _SFX + // parts.Back() can contain alt stream name "nams:AltName" + HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const; + #endif + public: CMyComPtr<IInArchive> Archive; CMyComPtr<IInStream> InStream; @@ -256,6 +307,7 @@ public: bool IsParseArc; bool IsTree; + bool IsReadOnly; bool Ask_Deleted; bool Ask_AltStream; @@ -269,6 +321,7 @@ public: CArc(): MTimeDefined(false), IsTree(false), + IsReadOnly(false), Ask_Deleted(false), Ask_AltStream(false), Ask_Aux(false), @@ -286,13 +339,13 @@ public: return Archive->Close(); } - // AltStream's name is concatenated with base file name in one string in parts.Back() - HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const; - HRESULT GetItemPath(UInt32 index, UString &result) const; + HRESULT GetDefaultItemPath(UInt32 index, UString &result) const; // GetItemPath2 adds [DELETED] dir prefix for deleted items. HRESULT GetItemPath2(UInt32 index, UString &result) const; + + HRESULT GetItem(UInt32 index, CReadArcItem &item) const; HRESULT GetItemSize(UInt32 index, UInt64 &size, bool &defined) const; HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const; @@ -315,6 +368,9 @@ struct CArchiveLink UInt64 VolumesSize; bool IsOpen; + bool PasswordWasAsked; + // UString Password; + // int NonOpenErrorFormatIndex; // - 1 means no Error. UString NonOpen_ArcPath; @@ -323,7 +379,12 @@ struct CArchiveLink // UString ErrorsText; // void Set_ErrorsText(); - CArchiveLink(): VolumesSize(0), IsOpen(false) {} + CArchiveLink(): + VolumesSize(0), + IsOpen(false), + PasswordWasAsked(false) + {} + void KeepModeForNextOpen(); HRESULT Close(); void Release(); @@ -335,8 +396,8 @@ struct CArchiveLink IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; } HRESULT Open(COpenOptions &options); - HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI); + HRESULT Open3(COpenOptions &options, IOpenCallbackUI *callbackUI); HRESULT ReOpen(COpenOptions &options); }; diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp index c2ceceae..32001624 100644 --- a/CPP/7zip/UI/Common/PropIDUtils.cpp +++ b/CPP/7zip/UI/Common/PropIDUtils.cpp @@ -7,7 +7,6 @@ #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" -#include "../../../Windows/FileFind.h" #include "../../../Windows/FileIO.h" #include "../../../Windows/PropVariantConv.h" @@ -41,20 +40,53 @@ static const char g_WinAttribChars[16 + 1] = "RHS8DAdNTsLCOnE_"; 16 VIRTUAL */ -void ConvertWinAttribToString(char *s, UInt32 wa) +static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' }; +#define MY_ATTR_CHAR(a, n, c) ((a) & (1 << (n))) ? c : '-'; + +static void ConvertPosixAttribToString(char *s, UInt32 a) throw() +{ + s[0] = kPosixTypes[(a >> 12) & 0xF]; + for (int i = 6; i >= 0; i -= 3) + { + s[7 - i] = MY_ATTR_CHAR(a, i + 2, 'r'); + s[8 - i] = MY_ATTR_CHAR(a, i + 1, 'w'); + s[9 - i] = MY_ATTR_CHAR(a, i + 0, 'x'); + } + if ((a & 0x800) != 0) s[3] = ((a & (1 << 6)) ? 's' : 'S'); + if ((a & 0x400) != 0) s[6] = ((a & (1 << 3)) ? 's' : 'S'); + if ((a & 0x200) != 0) s[9] = ((a & (1 << 0)) ? 't' : 'T'); + s[10] = 0; + + a &= ~(UInt32)0xFFFF; + if (a != 0) + { + s[10] = ' '; + ConvertUInt32ToHex8Digits(a, s + 11); + } +} + +void ConvertWinAttribToString(char *s, UInt32 wa) throw() { for (int i = 0; i < 16; i++) if ((wa & (1 << i)) && i != 7) *s++ = g_WinAttribChars[i]; *s = 0; -} -static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' }; -#define MY_ATTR_CHAR(a, n, c) ((a) & (1 << (n))) ? c : '-'; + // we support p7zip trick that stores posix attributes in high 16 bits, and 0x8000 flag + // we also support ZIP archives created in Unix, that store posix attributes in high 16 bits without 0x8000 flag + + // if (wa & 0x8000) + if ((wa >> 16) != 0) + { + *s++ = ' '; + ConvertPosixAttribToString(s, wa >> 16); + } +} void ConvertPropertyToShortString(char *dest, const PROPVARIANT &prop, PROPID propID, bool full) throw() { *dest = 0; + if (prop.vt == VT_FILETIME) { FILETIME localFileTime; @@ -65,6 +97,7 @@ void ConvertPropertyToShortString(char *dest, const PROPVARIANT &prop, PROPID pr ConvertFileTimeToString(localFileTime, dest, true, full); return; } + switch (propID) { case kpidCRC: @@ -78,34 +111,21 @@ void ConvertPropertyToShortString(char *dest, const PROPVARIANT &prop, PROPID pr { if (prop.vt != VT_UI4) break; - ConvertWinAttribToString(dest, prop.ulVal); + UInt32 a = prop.ulVal; + + /* + if ((a & 0x8000) && (a & 0x7FFF) == 0) + ConvertPosixAttribToString(dest, a >> 16); + else + */ + ConvertWinAttribToString(dest, a); return; } case kpidPosixAttrib: { if (prop.vt != VT_UI4) break; - UString res; - UInt32 a = prop.ulVal; - - dest[0] = kPosixTypes[(a >> 12) & 0xF]; - for (int i = 6; i >= 0; i -= 3) - { - dest[7 - i] = MY_ATTR_CHAR(a, i + 2, 'r'); - dest[8 - i] = MY_ATTR_CHAR(a, i + 1, 'w'); - dest[9 - i] = MY_ATTR_CHAR(a, i + 0, 'x'); - } - if ((a & 0x800) != 0) dest[3] = ((a & (1 << 6)) ? 's' : 'S'); - if ((a & 0x400) != 0) dest[6] = ((a & (1 << 3)) ? 's' : 'S'); - if ((a & 0x200) != 0) dest[9] = ((a & (1 << 0)) ? 't' : 'T'); - dest[10] = 0; - - a &= ~(UInt32)0xFFFF; - if (a != 0) - { - dest[10] = ' '; - ConvertUInt32ToHex8Digits(a, dest + 11); - } + ConvertPosixAttribToString(dest, prop.ulVal); return; } case kpidINode: @@ -132,6 +152,7 @@ void ConvertPropertyToShortString(char *dest, const PROPVARIANT &prop, PROPID pr break; } } + ConvertPropVariantToShortString(prop, dest); } @@ -139,29 +160,25 @@ void ConvertPropertyToString(UString &dest, const PROPVARIANT &prop, PROPID prop { if (prop.vt == VT_BSTR) { - dest = prop.bstrVal; + dest.SetFromBstr(prop.bstrVal); return; } char temp[64]; ConvertPropertyToShortString(temp, prop, propID, full); - int len = MyStringLen(temp); - wchar_t *str = dest.GetBuffer(len); - for (int i = 0; i < len; i++) - str[i] = temp[i]; - dest.ReleaseBuffer(len); + dest.SetFromAscii(temp); } -static inline char GetHex(Byte value) +static inline unsigned GetHex(unsigned v) { - return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); + return (v < 10) ? ('0' + v) : ('A' + (v - 10)); } #ifndef _SFX -static inline void AddHexToString(AString &res, Byte value) +static inline void AddHexToString(AString &res, unsigned v) { - res += GetHex((Byte)(value >> 4)); - res += GetHex((Byte)(value & 0xF)); + res += (char)GetHex(v >> 4); + res += (char)GetHex(v & 0xF); res += ' '; } @@ -175,30 +192,30 @@ static AString Data_To_Hex(const Byte *data, size_t size) } */ -static const char *sidNames[] = +static const char * const sidNames[] = { - "0", - "Dialup", - "Network", - "Batch", - "Interactive", - "Logon", // S-1-5-5-X-Y - "Service", - "Anonymous", - "Proxy", - "EnterpriseDC", - "Self", - "AuthenticatedUsers", - "RestrictedCode", - "TerminalServer", - "RemoteInteractiveLogon", - "ThisOrganization", - "16", - "IUserIIS", - "LocalSystem", - "LocalService", - "NetworkService", - "Domains" + "0" + , "Dialup" + , "Network" + , "Batch" + , "Interactive" + , "Logon" // S-1-5-5-X-Y + , "Service" + , "Anonymous" + , "Proxy" + , "EnterpriseDC" + , "Self" + , "AuthenticatedUsers" + , "RestrictedCode" + , "TerminalServer" + , "RemoteInteractiveLogon" + , "ThisOrganization" + , "16" + , "IUserIIS" + , "LocalSystem" + , "LocalService" + , "NetworkService" + , "Domains" }; struct CSecID2Name @@ -207,7 +224,7 @@ struct CSecID2Name const char *sz; }; -const CSecID2Name sid_32_Names[] = +static const CSecID2Name sid_32_Names[] = { { 544, "Administrators" }, { 545, "Users" }, @@ -297,7 +314,7 @@ static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize) if (v0 == 32 && num == 2) { UInt32 v1 = Get32(p + 12); - for (int i = 0; i < ARRAY_SIZE(sid_32_Names); i++) + for (unsigned i = 0; i < ARRAY_SIZE(sid_32_Names); i++) if (sid_32_Names[i].n == v1) { s += sid_32_Names[i].sz; @@ -307,7 +324,7 @@ static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize) if (v0 == 21 && num == 5) { UInt32 v4 = Get32(p + 8 + 4 * 4); - for (int i = 0; i < ARRAY_SIZE(sid_21_Names); i++) + for (unsigned i = 0; i < ARRAY_SIZE(sid_21_Names); i++) if (sid_21_Names[i].n == v4) { s += sid_21_Names[i].sz; @@ -316,7 +333,7 @@ static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize) } if (v0 == 80 && num == 6) { - for (int i = 0; i < ARRAY_SIZE(services_to_name); i++) + for (unsigned i = 0; i < ARRAY_SIZE(services_to_name); i++) { const CServicesToName &sn = services_to_name[i]; int j; @@ -385,10 +402,11 @@ static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName return; if (Get16(p) != 2) // revision return; - // UInt32 aclSize = Get16(p + 2); UInt32 num = Get32(p + 4); AddUInt32ToString(s, num); + /* + UInt32 aclSize = Get16(p + 2); if (num >= (1 << 16)) return; if (aclSize > size) @@ -409,14 +427,15 @@ static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName UInt32 sidSize = 0; s += ' '; - s += ParseSid(p, size, sidSize); + ParseSid(s, p, size, sidSize); if (sidSize == 0) return; p += sidSize; size -= sidSize; } - if (size != 0) - s += " ERROR"; + + // the tail can contain zeros. So (size != 0) is not ERROR + // if (size != 0) s += " ERROR"; */ } @@ -461,7 +480,7 @@ void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s) #ifdef _WIN32 -static bool CheckSid(const Byte *data, UInt32 size, UInt32 pos) +static bool CheckSid(const Byte *data, UInt32 size, UInt32 pos) throw() { if (pos >= size) return false; @@ -475,7 +494,7 @@ static bool CheckSid(const Byte *data, UInt32 size, UInt32 pos) return (8 + num * 4 <= size); } -static bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset) +static bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset) throw() { UInt32 control = Get16(p + 2); if ((flags & control) == 0) @@ -491,7 +510,7 @@ static bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset) return (aclSize <= size); } -bool CheckNtSecure(const Byte *data, UInt32 size) +bool CheckNtSecure(const Byte *data, UInt32 size) throw() { if (size < 20) return false; @@ -515,11 +534,11 @@ bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s) if (attr.Parse(data, size)) { if (!attr.IsSymLink()) - s += L"Junction: "; + s.AddAscii("Junction: "); s += attr.GetPath(); if (!attr.IsOkNamePair()) { - s += L" : "; + s.AddAscii(" : "); s += attr.PrintName; } return true; @@ -536,16 +555,16 @@ bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s) char hex[16]; ConvertUInt32ToHex8Digits(tag, hex); - s.AddAsciiStr(hex); - s += L' '; + s.AddAscii(hex); + s.Add_Space(); data += 8; for (UInt32 i = 0; i < len; i++) { - Byte b = ((const Byte *)data)[i]; - s += (wchar_t)GetHex((Byte)((b >> 4) & 0xF)); - s += (wchar_t)GetHex((Byte)(b & 0xF)); + unsigned b = ((const Byte *)data)[i]; + s += (wchar_t)GetHex((b >> 4) & 0xF); + s += (wchar_t)GetHex(b & 0xF); } return true; } diff --git a/CPP/7zip/UI/Common/PropIDUtils.h b/CPP/7zip/UI/Common/PropIDUtils.h index 3ee2981d..1dea321e 100644 --- a/CPP/7zip/UI/Common/PropIDUtils.h +++ b/CPP/7zip/UI/Common/PropIDUtils.h @@ -11,7 +11,8 @@ void ConvertPropertyToString(UString &dest, const PROPVARIANT &propVariant, PROP bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s); void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s); -bool CheckNtSecure(const Byte *data, UInt32 size); -void ConvertWinAttribToString(char *s, UInt32 wa); +bool CheckNtSecure(const Byte *data, UInt32 size) throw();; + +void ConvertWinAttribToString(char *s, UInt32 wa) throw(); #endif diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp index d2895961..78eec82f 100644 --- a/CPP/7zip/UI/Common/Update.cpp +++ b/CPP/7zip/UI/Common/Update.cpp @@ -42,6 +42,19 @@ using namespace NName; static CFSTR kTempFolderPrefix = FTEXT("7zE"); +void CUpdateErrorInfo::SetFromLastError(const char *message) +{ + SystemError = ::GetLastError(); + Message = message; +} + +HRESULT CUpdateErrorInfo::SetFromLastError(const char *message, const FString &fileName) +{ + SetFromLastError(message); + FileNames.Add(fileName); + return Get_HRESULT_Error(); +} + static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path) { NFind::CFileInfo fileInfo; @@ -101,6 +114,8 @@ public: bool SetMTime(const FILETIME *mTime); HRESULT Close(); + UInt64 GetSize() const { return _length; } + MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); @@ -151,10 +166,10 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr FChar temp[16]; ConvertUInt32ToString(_streamIndex + 1, temp); - FString res = temp; - while (res.Len() < 3) - res = FString(FTEXT('0')) + res; - FString name = Prefix + res; + FString name = temp; + while (name.Len() < 3) + name.InsertAtFront(FTEXT('0')); + name.Insert(0, Prefix); altStream.StreamSpec = new COutFileStream; altStream.Stream = altStream.StreamSpec; if (!altStream.StreamSpec->Create(name, false)) @@ -279,7 +294,7 @@ void CArchivePath::ParseFromPath(const UString &path, EArcNameMode mode) return; } - int dotPos = Name.ReverseFind(L'.'); + int dotPos = Name.ReverseFind_Dot(); if (dotPos < 0) return; if ((unsigned)dotPos == Name.Len() - 1) @@ -289,7 +304,7 @@ void CArchivePath::ParseFromPath(const UString &path, EArcNameMode mode) return; } const UString ext = Name.Ptr(dotPos + 1); - if (BaseExtension.IsEqualToNoCase(ext)) + if (BaseExtension.IsEqualTo_NoCase(ext)) { BaseExtension = ext; Name.DeleteFrom(dotPos); @@ -302,7 +317,10 @@ UString CArchivePath::GetFinalPath() const { UString path = GetPathWithoutExt(); if (!BaseExtension.IsEmpty()) - path += UString(L'.') + BaseExtension; + { + path += L'.'; + path += BaseExtension; + } return path; } @@ -310,27 +328,34 @@ UString CArchivePath::GetFinalVolPath() const { UString path = GetPathWithoutExt(); if (!BaseExtension.IsEmpty()) - path += UString(L'.') + VolExtension; + { + path += L'.'; + path += VolExtension; + } return path; } FString CArchivePath::GetTempPath() const { - FString path = TempPrefix + us2fs(Name); + FString path = TempPrefix; + path += us2fs(Name); if (!BaseExtension.IsEmpty()) - path += FString(FTEXT('.')) + us2fs(BaseExtension); - path += FTEXT(".tmp"); + { + path += FTEXT('.'); + path += us2fs(BaseExtension); + } + path.AddAscii(".tmp"); path += TempPostfix; return path; } static const wchar_t *kDefaultArcType = L"7z"; static const wchar_t *kDefaultArcExt = L"7z"; -static const wchar_t *kSFXExtension = +static const char *kSFXExtension = #ifdef _WIN32 - L"exe"; + "exe"; #else - L""; + ""; #endif bool CUpdateOptions::InitFormatIndex(const CCodecs *codecs, @@ -375,7 +400,7 @@ bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath) } UString ext = typeExt; if (SfxMode) - ext = kSFXExtension; + ext.SetFromAscii(kSFXExtension); ArchivePath.BaseExtension = ext; ArchivePath.VolExtension = typeExt; ArchivePath.ParseFromPath(arcPath, ArcNameMode); @@ -389,7 +414,6 @@ bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath) return true; } -/* struct CUpdateProduceCallbackImp: public IUpdateProduceCallback { const CObjectVector<CArcItem> *_arcItems; @@ -397,14 +421,14 @@ struct CUpdateProduceCallbackImp: public IUpdateProduceCallback CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a, IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {} - virtual HRESULT ShowDeleteFile(int arcIndex); + virtual HRESULT ShowDeleteFile(unsigned arcIndex); }; -HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(int arcIndex) +HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(unsigned arcIndex) { - return _callback->ShowDeleteFile((*_arcItems)[arcIndex].Name); + const CArcItem &ai = (*_arcItems)[arcIndex]; + return _callback->ShowDeleteFile(ai.Name, ai.IsDir); } -*/ bool CRenamePair::Prepare() { @@ -417,9 +441,9 @@ bool CRenamePair::Prepare() extern bool g_CaseSensitive; -static int CompareTwoNames(const wchar_t *s1, const wchar_t *s2) +static unsigned CompareTwoNames(const wchar_t *s1, const wchar_t *s2) { - for (int i = 0;; i++) + for (unsigned i = 0;; i++) { wchar_t c1 = s1[i]; wchar_t c2 = s2[i]; @@ -429,7 +453,7 @@ static int CompareTwoNames(const wchar_t *s1, const wchar_t *s2) continue; if (!g_CaseSensitive && (MyCharUpper(c1) == MyCharUpper(c2))) continue; - if (IsCharDirLimiter(c1) && IsCharDirLimiter(c2)) + if (IsPathSepar(c1) && IsPathSepar(c2)) continue; return i; } @@ -437,10 +461,10 @@ static int CompareTwoNames(const wchar_t *s1, const wchar_t *s2) bool CRenamePair::GetNewPath(bool isFolder, const UString &src, UString &dest) const { - int num = CompareTwoNames(OldName, src); + unsigned num = CompareTwoNames(OldName, src); if (OldName[num] == 0) { - if (src[num] != 0 && !IsCharDirLimiter(src[num]) && num != 0 && !IsCharDirLimiter(src[num - 1])) + if (src[num] != 0 && !IsPathSepar(src[num]) && num != 0 && !IsPathSepar(src[num - 1])) return false; } else @@ -449,28 +473,23 @@ bool CRenamePair::GetNewPath(bool isFolder, const UString &src, UString &dest) c // OldName = "1\1a.txt" // src = "1" - if (!isFolder || - src[num] != 0 || - !IsCharDirLimiter(OldName[num]) || - OldName[num + 1] != 0) + if (!isFolder + || src[num] != 0 + || !IsPathSepar(OldName[num]) + || OldName[num + 1] != 0) return false; } dest = NewName + src.Ptr(num); return true; } -static int GetReverseSlashPos(const UString &name) -{ - int slashPos = name.ReverseFind(L'/'); - #ifdef _WIN32 - int slash1Pos = name.ReverseFind(L'\\'); - slashPos = MyMax(slashPos, slash1Pos); - #endif - return slashPos; -} +#ifdef SUPPORT_ALT_STREAMS +int FindAltStreamColon_in_Path(const wchar_t *path); +#endif static HRESULT Compress( const CUpdateOptions &options, + bool isUpdatingItself, CCodecs *codecs, const CActionSet &actionSet, const CArc *arc, @@ -481,10 +500,12 @@ static HRESULT Compress( const CDirItem *parentDirItem, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, - IUpdateCallbackUI *callback) + IUpdateCallbackUI *callback, + CFinishArchiveStat &st) { CMyComPtr<IOutArchive> outArchive; int formatIndex = options.MethodMode.Type.FormatIndex; + if (arc) { formatIndex = arc->FormatIndex; @@ -510,22 +531,25 @@ static HRESULT Compress( } #endif } + if (outArchive == 0) throw kUpdateIsNotSupoorted; NFileTimeType::EEnum fileTimeType; - UInt32 value; - RINOK(outArchive->GetFileTimeType(&value)); - - switch (value) { - case NFileTimeType::kWindows: - case NFileTimeType::kUnix: - case NFileTimeType::kDOS: - fileTimeType = (NFileTimeType::EEnum)value; - break; - default: - return E_FAIL; + UInt32 value; + RINOK(outArchive->GetFileTimeType(&value)); + + switch (value) + { + case NFileTimeType::kWindows: + case NFileTimeType::kUnix: + case NFileTimeType::kDOS: + fileTimeType = (NFileTimeType::EEnum)value; + break; + default: + return E_FAIL; + } } { @@ -559,9 +583,8 @@ static HRESULT Compress( } if (ai.IsAltStream) { - int colonPos = ai.Name.ReverseFind(':'); - int slashPosPos = GetReverseSlashPos(ai.Name); - if (colonPos > slashPosPos) + int colonPos = FindAltStreamColon_in_Path(ai.Name); + if (colonPos >= 0) { UString mainName = ai.Name.Left(colonPos); /* @@ -571,7 +594,7 @@ static HRESULT Compress( if (rp.GetNewPath(false, mainName, dest)) { needRename = true; - dest += ':'; + dest += L':'; dest += ai.Name.Ptr(colonPos + 1); break; } @@ -594,16 +617,18 @@ static HRESULT Compress( { CRecordVector<CUpdatePair> updatePairs; GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!! - // CUpdateProduceCallbackImp upCallback(&arcItems, callback); - UpdateProduce(updatePairs, actionSet, updatePairs2, NULL /* &upCallback */); + CUpdateProduceCallbackImp upCallback(&arcItems, callback); + + UpdateProduce(updatePairs, actionSet, updatePairs2, isUpdatingItself ? &upCallback : NULL); } - UInt32 numFiles = 0; - FOR_VECTOR (i, updatePairs2) - if (updatePairs2[i].NewData) - numFiles++; - - RINOK(callback->SetNumFiles(numFiles)); + { + UInt32 numItems = 0; + FOR_VECTOR (i, updatePairs2) + if (updatePairs2[i].NewData) + numItems++; + RINOK(callback->SetNumItems(numItems)); + } CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec); @@ -616,8 +641,6 @@ static HRESULT Compress( { // we set Archive to allow to transfer GetProperty requests back to DLL. updateCallbackSpec->Archive = arc->Archive; - updateCallbackSpec->GetRawProps = arc->GetRawProps; - updateCallbackSpec->GetRootProps = arc->GetRootProps; } updateCallbackSpec->DirItems = &dirItems; @@ -627,6 +650,7 @@ static HRESULT Compress( updateCallbackSpec->StoreHardLinks = options.HardLinks.Val; updateCallbackSpec->StoreSymLinks = options.SymLinks.Val; + updateCallbackSpec->Arc = arc; updateCallbackSpec->ArcItems = &arcItems; updateCallbackSpec->UpdatePairs = &updatePairs2; @@ -647,12 +671,16 @@ static HRESULT Compress( } COutFileStream *outStreamSpec = NULL; + CStdOutFileStream *stdOutFileStreamSpec = NULL; COutMultiVolStream *volStreamSpec = NULL; if (options.VolumesSizes.Size() == 0) { if (options.StdOutMode) - outStream = new CStdOutFileStream; + { + stdOutFileStreamSpec = new CStdOutFileStream; + outStream = stdOutFileStreamSpec; + } else { outStreamSpec = new COutFileStream; @@ -660,7 +688,8 @@ static HRESULT Compress( outStream = outSeekStream; bool isOK = false; FString realPath; - for (int i = 0; i < (1 << 16); i++) + + for (unsigned i = 0; i < (1 << 16); i++) { if (archivePath.Temp) { @@ -685,13 +714,9 @@ static HRESULT Compress( if (!archivePath.Temp) break; } + if (!isOK) - { - errorInfo.SystemError = ::GetLastError(); - errorInfo.FileName = realPath; - errorInfo.Message = L"7-Zip cannot open file"; - return E_FAIL; - } + return errorInfo.SetFromLastError("cannot open file", realPath); } } else @@ -705,7 +730,8 @@ static HRESULT Compress( outSeekStream = volStreamSpec; outStream = outSeekStream; volStreamSpec->Sizes = options.VolumesSizes; - volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath() + L"."); + volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath()); + volStreamSpec->Prefix += FTEXT('.'); volStreamSpec->TempFiles = &tempFiles; volStreamSpec->Init(); @@ -724,12 +750,7 @@ static HRESULT Compress( CInFileStream *sfxStreamSpec = new CInFileStream; CMyComPtr<IInStream> sfxStream(sfxStreamSpec); if (!sfxStreamSpec->Open(options.SfxModule)) - { - errorInfo.SystemError = ::GetLastError(); - errorInfo.Message = L"7-Zip cannot open SFX module"; - errorInfo.FileName = options.SfxModule; - return E_FAIL; - } + return errorInfo.SetFromLastError("cannot open SFX module", options.SfxModule); CMyComPtr<ISequentialOutStream> sfxOutStream; COutFileStream *outStreamSpec = NULL; @@ -741,14 +762,17 @@ static HRESULT Compress( sfxOutStream = outStreamSpec; FString realPath = us2fs(archivePath.GetFinalPath()); if (!outStreamSpec->Create(realPath, false)) - { - errorInfo.SystemError = ::GetLastError(); - errorInfo.FileName = realPath; - errorInfo.Message = L"7-Zip cannot open file"; - return E_FAIL; - } + return errorInfo.SetFromLastError("cannot open file", realPath); } + + { + UInt64 sfxSize; + RINOK(sfxStreamSpec->GetSize(&sfxSize)); + RINOK(callback->WriteSfx(fs2us(options.SfxModule), sfxSize)); + } + RINOK(NCompress::CopyStream(sfxStream, sfxOutStream, NULL)); + if (outStreamSpec) { RINOK(outStreamSpec->Close()); @@ -778,9 +802,15 @@ static HRESULT Compress( HRESULT result = outArchive->UpdateItems(tailStream, updatePairs2.Size(), updateCallback); - callback->Finilize(); + // callback->Finalize(); RINOK(result); + if (!updateCallbackSpec->AreAllFilesClosed()) + { + errorInfo.Message = "There are unclosed input file:"; + errorInfo.FileNames = updateCallbackSpec->_openFiles_Paths; + return E_FAIL; + } if (options.SetArcMTime) { @@ -810,6 +840,19 @@ static HRESULT Compress( } } + if (callback) + { + UInt64 size = 0; + if (outStreamSpec) + outStreamSpec->GetSize(&size); + else if (stdOutFileStreamSpec) + size = stdOutFileStreamSpec->GetSize(); + else + size = volStreamSpec->GetSize(); + + st.OutArcFileSize = size; + } + if (outStreamSpec) result = outStreamSpec->Close(); else if (volStreamSpec) @@ -817,6 +860,24 @@ static HRESULT Compress( return result; } +bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include); + +static bool Censor_CheckPath(const NWildcard::CCensor &censor, const CReadArcItem &item) +{ + bool finded = false; + FOR_VECTOR (i, censor.Pairs) + { + bool include; + if (CensorNode_CheckPath2(censor.Pairs[i].Head, item, include)) + { + if (!include) + return false; + finded = true; + } + } + return finded; +} + static HRESULT EnumerateInArchiveItems( // bool storeStreamsMode, const NWildcard::CCensor &censor, @@ -828,18 +889,29 @@ static HRESULT EnumerateInArchiveItems( IInArchive *archive = arc.Archive; RINOK(archive->GetNumberOfItems(&numItems)); arcItems.ClearAndReserve(numItems); + + CReadArcItem item; + for (UInt32 i = 0; i < numItems; i++) { CArcItem ai; - RINOK(arc.GetItemPath(i, ai.Name)); - RINOK(Archive_IsItem_Folder(archive, i, ai.IsDir)); - RINOK(Archive_IsItem_AltStream(archive, i, ai.IsAltStream)); + RINOK(arc.GetItem(i, item)); + ai.Name = item.Path; + ai.IsDir = item.IsDir; + ai.IsAltStream = + #ifdef SUPPORT_ALT_STREAMS + item.IsAltStream; + #else + false; + #endif + /* if (!storeStreamsMode && ai.IsAltStream) continue; */ - ai.Censored = censor.CheckPath(ai.IsAltStream, ai.Name, !ai.IsDir); + ai.Censored = Censor_CheckPath(censor, item); + RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined)); RINOK(arc.GetItemSize(i, ai.Size, ai.SizeDefined)); @@ -867,15 +939,6 @@ static HRESULT EnumerateInArchiveItems( return S_OK; } -struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback -{ - IUpdateCallbackUI2 *Callback; - HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) - { - return Callback->ScanProgress(numFolders, numFiles, totalSize, path, isDir); - } -}; - #if defined(_WIN32) && !defined(UNDER_CE) #include <mapi.h> @@ -884,8 +947,8 @@ struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback struct CRefSortPair { - int Len; - int Index; + unsigned Len; + unsigned Index; }; #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } @@ -896,18 +959,14 @@ static int CompareRefSortPair(const CRefSortPair *a1, const CRefSortPair *a2, vo return MyCompare(a1->Index, a2->Index); } -static int GetNumSlashes(const FChar *s) +static unsigned GetNumSlashes(const FChar *s) { - for (int numSlashes = 0;;) + for (unsigned numSlashes = 0;;) { FChar c = *s++; if (c == 0) return numSlashes; - if ( - #ifdef _WIN32 - c == FTEXT('\\') || - #endif - c == FTEXT('/')) + if (IS_PATH_SEPAR(c)) numSlashes++; } } @@ -963,12 +1022,11 @@ HRESULT UpdateArchive( if (options.SfxMode) { CProperty property; - property.Name = L"rsfx"; - property.Value = L"on"; + property.Name.SetFromAscii("rsfx"); options.MethodMode.Properties.Add(property); if (options.SfxModule.IsEmpty()) { - errorInfo.Message = L"SFX file is not specified"; + errorInfo.Message = "SFX file is not specified"; return E_FAIL; } bool found = false; @@ -984,12 +1042,7 @@ HRESULT UpdateArchive( if (!found) { if (!NFind::DoesFileExist(options.SfxModule)) - { - errorInfo.SystemError = ::GetLastError(); - errorInfo.Message = L"7-Zip cannot find specified SFX module"; - errorInfo.FileName = options.SfxModule; - return E_FAIL; - } + return errorInfo.SetFromLastError("cannot find specified SFX module", options.SfxModule); } } @@ -1048,24 +1101,28 @@ HRESULT UpdateArchive( op.stream = NULL; op.filePath = arcPath; - HRESULT result = arcLink.Open2(op, openCallback); + RINOK(callback->StartOpenArchive(arcPath)); + + HRESULT result = arcLink.Open3(op, openCallback); if (result == E_ABORT) return result; - const wchar_t *errorArcType = NULL; - if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex > 0) - errorArcType = codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name; - RINOK(callback->OpenResult(arcPath, result, errorArcType)); + if (result == S_OK && arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) + result = S_FALSE; + + HRESULT res2 = callback->OpenResult(codecs, arcLink, arcPath, result); /* if (result == S_FALSE) return E_FAIL; */ + RINOK(res2); RINOK(result); + if (arcLink.VolumePaths.Size() > 1) { errorInfo.SystemError = (DWORD)E_NOTIMPL; - errorInfo.Message = L"Updating for multivolume archives is not implemented"; + errorInfo.Message = "Updating for multivolume archives is not implemented"; return E_NOTIMPL; } @@ -1076,7 +1133,7 @@ HRESULT UpdateArchive( if (arc.ErrorInfo.ThereIsTail) { errorInfo.SystemError = (DWORD)E_NOTIMPL; - errorInfo.Message = L"There is some data block after the end of the archive"; + errorInfo.Message = "There is some data block after the end of the archive"; return E_NOTIMPL; } if (options.MethodMode.Type.FormatIndex < 0) @@ -1098,8 +1155,10 @@ HRESULT UpdateArchive( bool thereIsInArchive = arcLink.IsOpen; if (!thereIsInArchive && renameMode) return E_FAIL; - + CDirItems dirItems; + dirItems.Callback = callback; + CDirItem parentDirItem; CDirItem *parentDirItem_Ptr = NULL; @@ -1123,14 +1182,14 @@ HRESULT UpdateArchive( else { bool needScanning = false; + if (!renameMode) FOR_VECTOR (i, options.Commands) if (options.Commands[i].ActionSet.NeedScanning()) needScanning = true; + if (needScanning) { - CEnumDirItemUpdateCallback enumCallback; - enumCallback.Callback = callback; RINOK(callback->StartScanning()); dirItems.SymLinks = options.SymLinks.Val; @@ -1140,26 +1199,26 @@ HRESULT UpdateArchive( #endif dirItems.ScanAltStreams = options.AltStreams.Val; + HRESULT res = EnumerateItems(censor, options.PathMode, options.AddPathPrefix, - dirItems, &enumCallback); - FOR_VECTOR (i, dirItems.ErrorPaths) - { - RINOK(callback->CanNotFindError(fs2us(dirItems.ErrorPaths[i]), dirItems.ErrorCodes[i])); - } + dirItems); + if (res != S_OK) { if (res != E_ABORT) - errorInfo.Message = L"Scanning error"; + errorInfo.Message = "Scanning error"; return res; } - RINOK(callback->FinishScanning()); + + RINOK(callback->FinishScanning(dirItems.Stat)); if (censor.Pairs.Size() == 1) { NFind::CFileInfo fi; - FString prefix = us2fs(censor.Pairs[0].Prefix) + FTEXT("."); + FString prefix = us2fs(censor.Pairs[0].Prefix); + prefix += FTEXT('.'); // UString prefix = censor.Pairs[0].Prefix; /* if (prefix.Back() == WCHAR_PATH_SEPARATOR) @@ -1242,10 +1301,10 @@ HRESULT UpdateArchive( const FString path = us2fs(ap.GetFinalPath()); if (NFind::DoesFileOrDirExist(path)) { - errorInfo.SystemError = 0; - errorInfo.Message = L"The file already exists"; - errorInfo.FileName = path; - return E_FAIL; + errorInfo.SystemError = ERROR_FILE_EXISTS; + errorInfo.Message = "The file already exists"; + errorInfo.FileNames.Add(path); + return errorInfo.Get_HRESULT_Error(); } } } @@ -1274,27 +1333,40 @@ HRESULT UpdateArchive( processedItems[i] = 0; } + /* + #ifndef _NO_CRYPTO + if (arcLink.PasswordWasAsked) + { + // We set password, if open have requested password + RINOK(callback->SetPassword(arcLink.Password)); + } + #endif + */ + for (i = 0; i < options.Commands.Size(); i++) { - const CArc *arc = thereIsInArchive ? arcLink.GetArc() : 0; - // IInArchiveExtra *archiveExtra = thereIsInArchive ? arcLink.GetArchiveExtra() : 0; - // IArchiveGetRootProps *archiveGetRootProps = thereIsInArchive ? arcLink.GetArchiveGetRootProps() : 0; + const CArc *arc = thereIsInArchive ? arcLink.GetArc() : NULL; CUpdateArchiveCommand &command = options.Commands[i]; UString name; bool isUpdating; + if (options.StdOutMode) { - name = L"stdout"; - isUpdating = arc != 0; + name.SetFromAscii("stdout"); + isUpdating = thereIsInArchive; } else { name = command.ArchivePath.GetFinalPath(); - isUpdating = (i == 0 && options.UpdateArchiveItself && arc != 0); + isUpdating = (i == 0 && options.UpdateArchiveItself && thereIsInArchive); } + RINOK(callback->StartArchive(name, isUpdating)) + CFinishArchiveStat st; + RINOK(Compress(options, + isUpdating, codecs, command.ActionSet, arc, @@ -1306,9 +1378,9 @@ HRESULT UpdateArchive( parentDirItem_Ptr, tempFiles, - errorInfo, callback)); + errorInfo, callback, st)); - RINOK(callback->FinishArchive()); + RINOK(callback->FinishArchive(st)); } @@ -1325,21 +1397,16 @@ HRESULT UpdateArchive( { CArchivePath &ap = options.Commands[0].ArchivePath; const FString &tempPath = ap.GetTempPath(); + if (thereIsInArchive) if (!DeleteFileAlways(us2fs(arcPath))) - { - errorInfo.SystemError = ::GetLastError(); - errorInfo.Message = L"7-Zip cannot delete the file"; - errorInfo.FileName = us2fs(arcPath); - return E_FAIL; - } + return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath)); + if (!MyMoveFile(tempPath, us2fs(arcPath))) { - errorInfo.SystemError = ::GetLastError(); - errorInfo.Message = L"7-Zip cannot move the file"; - errorInfo.FileName = tempPath; - errorInfo.FileName2 = us2fs(arcPath); - return E_FAIL; + errorInfo.SetFromLastError("cannot move the file", tempPath); + errorInfo.FileNames.Add(us2fs(arcPath)); + return errorInfo.Get_HRESULT_Error(); } } catch(...) @@ -1350,48 +1417,47 @@ HRESULT UpdateArchive( #if defined(_WIN32) && !defined(UNDER_CE) + if (options.EMailMode) { NDLL::CLibrary mapiLib; if (!mapiLib.Load(FTEXT("Mapi32.dll"))) { - errorInfo.SystemError = ::GetLastError(); - errorInfo.Message = L"7-Zip cannot load Mapi32.dll"; - return E_FAIL; + errorInfo.SetFromLastError("cannot load Mapi32.dll"); + return errorInfo.Get_HRESULT_Error(); } /* LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments"); if (fnSend == 0) { - errorInfo.SystemError = ::GetLastError(); - errorInfo.Message = L"7-Zip cannot find MAPISendDocuments function"; - return E_FAIL; + errorInfo.SetFromLastError)("7-Zip cannot find MAPISendDocuments function"); + return errorInfo.Get_HRESULT_Error(); } */ + LPMAPISENDMAIL sendMail = (LPMAPISENDMAIL)mapiLib.GetProc("MAPISendMail"); if (sendMail == 0) { - errorInfo.SystemError = ::GetLastError(); - errorInfo.Message = L"7-Zip cannot find MAPISendMail function"; - return E_FAIL; + errorInfo.SetFromLastError("7-Zip cannot find MAPISendMail function"); + return errorInfo.Get_HRESULT_Error();; } FStringVector fullPaths; unsigned i; + for (i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; + FString finalPath = us2fs(ap.GetFinalPath()); FString arcPath; - if (!MyGetFullPathName(us2fs(ap.GetFinalPath()), arcPath)) - { - errorInfo.SystemError = ::GetLastError(); - errorInfo.Message = L"GetFullPathName error"; - return E_FAIL; - } + if (!MyGetFullPathName(finalPath, arcPath)) + return errorInfo.SetFromLastError("GetFullPathName error", finalPath); fullPaths.Add(arcPath); } + CCurrentDirRestorer curDirRestorer; + for (i = 0; i < fullPaths.Size(); i++) { UString arcPath = fs2us(fullPaths[i]); @@ -1426,16 +1492,18 @@ HRESULT UpdateArchive( sendMail((LHANDLE)0, 0, &m, MAPI_DIALOG, 0); } } + #endif if (options.DeleteAfterCompressing) { CRecordVector<CRefSortPair> pairs; FStringVector foldersNames; + for (i = 0; i < dirItems.Items.Size(); i++) { const CDirItem &dirItem = dirItems.Items[i]; - FString phyPath = us2fs(dirItems.GetPhyPath(i)); + FString phyPath = dirItems.GetPhyPath(i); if (dirItem.IsDir()) { CRefSortPair pair; @@ -1447,6 +1515,7 @@ HRESULT UpdateArchive( { if (processedItems[i] != 0 || dirItem.Size == 0) { + RINOK(callback->DeletingAfterArchiving(phyPath, false)); DeleteFileAlways(phyPath); } else @@ -1454,7 +1523,7 @@ HRESULT UpdateArchive( // file was skipped /* errorInfo.SystemError = 0; - errorInfo.Message = L"file was not processed"; + errorInfo.Message = "file was not processed"; errorInfo.FileName = phyPath; return E_FAIL; */ @@ -1463,15 +1532,19 @@ HRESULT UpdateArchive( } pairs.Sort(CompareRefSortPair, NULL); + for (i = 0; i < pairs.Size(); i++) { - FString phyPath = us2fs(dirItems.GetPhyPath(pairs[i].Index)); + FString phyPath = dirItems.GetPhyPath(pairs[i].Index); if (NFind::DoesDirExist(phyPath)) { - // printf("delete %S\n", phyPath); + RINOK(callback->DeletingAfterArchiving(phyPath, true)); RemoveDir(phyPath); } } + + RINOK(callback->FinishDeletingAfterArchiving()); } + return S_OK; } diff --git a/CPP/7zip/UI/Common/Update.h b/CPP/7zip/UI/Common/Update.h index 68e51d85..0301ae76 100644 --- a/CPP/7zip/UI/Common/Update.h +++ b/CPP/7zip/UI/Common/Update.h @@ -12,6 +12,8 @@ #include "UpdateAction.h" #include "UpdateCallback.h" +#include "DirItem.h" + enum EArcNameMode { k_ArcNameMode_Smart, @@ -144,32 +146,40 @@ struct CUpdateOptions CRecordVector<UInt64> VolumesSizes; }; -struct CErrorInfo +struct CUpdateErrorInfo { DWORD SystemError; - FString FileName; - FString FileName2; - UString Message; - // UStringVector ErrorPaths; - // CRecordVector<DWORD> ErrorCodes; - CErrorInfo(): SystemError(0) {}; + AString Message; + FStringVector FileNames; + + bool ThereIsError() const { return SystemError != 0 || !Message.IsEmpty() || !FileNames.IsEmpty(); } + HRESULT Get_HRESULT_Error() const { return SystemError == 0 ? E_FAIL : HRESULT_FROM_WIN32(SystemError); } + void SetFromLastError(const char *message); + HRESULT SetFromLastError(const char *message, const FString &fileName); + + CUpdateErrorInfo(): SystemError(0) {}; }; -struct CUpdateErrorInfo: public CErrorInfo +struct CFinishArchiveStat { + UInt64 OutArcFileSize; + + CFinishArchiveStat(): OutArcFileSize(0) {} }; #define INTERFACE_IUpdateCallbackUI2(x) \ INTERFACE_IUpdateCallbackUI(x) \ - virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, const wchar_t *errorArcType) x; \ + INTERFACE_IDirItemsCallback(x) \ + virtual HRESULT OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) x; \ virtual HRESULT StartScanning() x; \ - virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) x; \ - virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \ - virtual HRESULT FinishScanning() x; \ + virtual HRESULT FinishScanning(const CDirItemsStat &st) x; \ + virtual HRESULT StartOpenArchive(const wchar_t *name) x; \ virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \ - virtual HRESULT FinishArchive() x; \ + virtual HRESULT FinishArchive(const CFinishArchiveStat &st) x; \ + virtual HRESULT DeletingAfterArchiving(const FString &path, bool isDir) x; \ + virtual HRESULT FinishDeletingAfterArchiving() x; \ -struct IUpdateCallbackUI2: public IUpdateCallbackUI +struct IUpdateCallbackUI2: public IUpdateCallbackUI, public IDirItemsCallback { INTERFACE_IUpdateCallbackUI2(=0) }; diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp index 0115bda3..993ab266 100644 --- a/CPP/7zip/UI/Common/UpdateCallback.cpp +++ b/CPP/7zip/UI/Common/UpdateCallback.cpp @@ -2,6 +2,10 @@ #include "StdAfx.h" +#ifndef _7ZIP_ST +#include "../../../Windows/Synchronization.h" +#endif + #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" @@ -12,7 +16,6 @@ #include "../../../Windows/PropVariant.h" #include "../../../Windows/Synchronization.h" -#include "../../Common/FileStreams.h" #include "../../Common/StreamObjects.h" #include "UpdateCallback.h" @@ -25,25 +28,40 @@ using namespace NWindows; using namespace NFile; +#ifndef _7ZIP_ST +static NSynchronization::CCriticalSection g_CriticalSection; +#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); +#else +#define MT_LOCK +#endif + + #ifdef _USE_SECURITY_CODE bool InitLocalPrivileges(); #endif CArchiveUpdateCallback::CArchiveUpdateCallback(): - Callback(0), - ShareForWrite(false), - StdInMode(false), - DirItems(0), - ArcItems(0), - UpdatePairs(0), - NewNames(0), - KeepOriginalItemNames(false), - ProcessedItemsStatuses(NULL), - ParentDirItem(NULL), - StoreNtSecurity(false), - StoreHardLinks(false), - StoreSymLinks(false), - _hardIndex_From((UInt32)(Int32)-1) + _hardIndex_From((UInt32)(Int32)-1), + + Callback(NULL), + + DirItems(NULL), + ParentDirItem(NULL), + + Arc(NULL), + ArcItems(NULL), + UpdatePairs(NULL), + NewNames(NULL), + + ShareForWrite(false), + StdInMode(false), + + KeepOriginalItemNames(false), + StoreNtSecurity(false), + StoreHardLinks(false), + StoreSymLinks(false), + + ProcessedItemsStatuses(NULL) { #ifdef _USE_SECURITY_CODE _saclEnabled = InitLocalPrivileges(); @@ -175,8 +193,8 @@ STDMETHODIMP CArchiveUpdateCallback::GetRootRawProp(PROPID return S_OK; } - if (GetRootProps) - return GetRootProps->GetRootRawProp(propID, data, dataSize, propType); + if (Arc && Arc->GetRootProps) + return Arc->GetRootProps->GetRootRawProp(propID, data, dataSize, propType); } #endif return S_OK; @@ -198,8 +216,8 @@ STDMETHODIMP CArchiveUpdateCallback::GetRawProp(UInt32 index, PROPID propID, con return S_OK; const CUpdatePair2 &up = (*UpdatePairs)[index]; - if (up.UseArcProps && up.ExistInArchive() && GetRawProps) - return GetRawProps->GetRawProp( + if (up.UseArcProps && up.ExistInArchive() && Arc->GetRawProps) + return Arc->GetRawProps->GetRawProp( ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex, propID, data, dataSize, propType); @@ -290,7 +308,7 @@ static UString GetRelativePath(const UString &to, const UString &from) for (k = i; k < partsTo.Size(); k++) { if (k != i) - s += WCHAR_PATH_SEPARATOR; + s.Add_PathSepar(); s += partsTo[k]; } @@ -336,9 +354,9 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR prop = simpleName; else { - const UString phyPath = DirItems->GetPhyPath(up.DirIndex); + const FString phyPath = DirItems->GetPhyPath(up.DirIndex); FString fullPath; - if (NDir::MyGetFullPathName(us2fs(phyPath), fullPath)) + if (NDir::MyGetFullPathName(phyPath, fullPath)) { prop = GetRelativePath(simpleName, fs2us(fullPath)); } @@ -385,8 +403,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR { // we can generate new ShortName here; } - else if ((up.UseArcProps - || (KeepOriginalItemNames && (propID == kpidPath || propID == kpidIsAltStream))) + else if ((up.UseArcProps || (KeepOriginalItemNames && (propID == kpidPath || propID == kpidIsAltStream))) && up.ExistInArchive() && Archive) return Archive->GetProperty(ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex, propID, value); else if (up.ExistOnDisk()) @@ -414,7 +431,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR static NSynchronization::CCriticalSection CS; -STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) +STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 mode) { COM_TRY_BEGIN *inStream = NULL; @@ -423,7 +440,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream return E_FAIL; RINOK(Callback->CheckBreak()); - RINOK(Callback->Finilize()); + // RINOK(Callback->Finalize()); bool isDir = IsDir(up); @@ -434,7 +451,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream name = (*ArcItems)[up.ArcIndex].Name; else if (up.DirIndex >= 0) name = DirItems->GetLogPath(up.DirIndex); - RINOK(Callback->GetStream(name, true)); + RINOK(Callback->GetStream(name, isDir, true, mode)); /* 9.33: fixed. Handlers expect real stream object for files, even for anti-file. so we return empty stream */ @@ -449,13 +466,17 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream return S_OK; } - RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), false)); + RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), isDir, false, mode)); if (isDir) return S_OK; if (StdInMode) { + if (mode != NUpdateNotifyOp::kAdd && + mode != NUpdateNotifyOp::kUpdate) + return S_OK; + CStdInFileStream *inStreamSpec = new CStdInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); *inStream = inStreamLoc.Detach(); @@ -466,20 +487,24 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); inStreamSpec->SupportHardLinks = StoreHardLinks; + inStreamSpec->Callback = this; + inStreamSpec->CallbackRef = index; - const UString path = DirItems->GetPhyPath(up.DirIndex); + const FString path = DirItems->GetPhyPath(up.DirIndex); + _openFiles_Indexes.Add(index); + _openFiles_Paths.Add(path); #if defined(_WIN32) && !defined(UNDER_CE) if (DirItems->Items[up.DirIndex].AreReparseData()) { - if (!inStreamSpec->File.OpenReparse(us2fs(path))) + if (!inStreamSpec->File.OpenReparse(path)) { return Callback->OpenFileError(path, ::GetLastError()); } } else #endif - if (!inStreamSpec->OpenShared(us2fs(path), ShareForWrite)) + if (!inStreamSpec->OpenShared(path, ShareForWrite)) { return Callback->OpenFileError(path, ::GetLastError()); } @@ -512,7 +537,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream if (ProcessedItemsStatuses) { NSynchronization::CCriticalSectionLock lock(CS); - ProcessedItemsStatuses[up.DirIndex] = 1; + ProcessedItemsStatuses[(unsigned)up.DirIndex] = 1; } *inStream = inStreamLoc.Detach(); } @@ -521,10 +546,133 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream COM_TRY_END } -STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult) +STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 opRes) +{ + COM_TRY_BEGIN + return Callback->SetOperationResult(opRes); + COM_TRY_END +} + +STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { COM_TRY_BEGIN - return Callback->SetOperationResult(operationResult); + return GetStream2(index, inStream, + (*UpdatePairs)[index].ArcIndex < 0 ? + NUpdateNotifyOp::kAdd : + NUpdateNotifyOp::kUpdate); + COM_TRY_END +} + +STDMETHODIMP CArchiveUpdateCallback::ReportOperation(UInt32 indexType, UInt32 index, UInt32 op) +{ + COM_TRY_BEGIN + + bool isDir = false; + + if (indexType == NArchive::NEventIndexType::kOutArcIndex) + { + UString name; + if (index != (UInt32)(Int32)-1) + { + const CUpdatePair2 &up = (*UpdatePairs)[index]; + if (up.ExistOnDisk()) + { + name = DirItems->GetLogPath(up.DirIndex); + isDir = DirItems->Items[up.DirIndex].IsDir(); + } + } + return Callback->ReportUpdateOpeartion(op, name.IsEmpty() ? NULL : name.Ptr(), isDir); + } + + wchar_t temp[16]; + UString s2; + const wchar_t *s = NULL; + + if (indexType == NArchive::NEventIndexType::kInArcIndex) + { + if (index != (UInt32)(Int32)-1) + { + if (ArcItems) + { + const CArcItem &ai = (*ArcItems)[index]; + s = ai.Name; + isDir = ai.IsDir; + } + else if (Arc) + { + RINOK(Arc->GetItemPath(index, s2)); + s = s2; + RINOK(Archive_IsItem_Dir(Arc->Archive, index, isDir)); + } + } + } + else if (indexType == NArchive::NEventIndexType::kBlockIndex) + { + temp[0] = '#'; + ConvertUInt32ToString(index, temp + 1); + s = temp; + } + + if (!s) + s = L""; + + return Callback->ReportUpdateOpeartion(op, s, isDir); + + COM_TRY_END +} + +STDMETHODIMP CArchiveUpdateCallback::ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes) +{ + COM_TRY_BEGIN + + bool isEncrypted = false; + wchar_t temp[16]; + UString s2; + const wchar_t *s = NULL; + + if (indexType == NArchive::NEventIndexType::kOutArcIndex) + { + /* + UString name; + if (index != (UInt32)(Int32)-1) + { + const CUpdatePair2 &up = (*UpdatePairs)[index]; + if (up.ExistOnDisk()) + { + s2 = DirItems->GetLogPath(up.DirIndex); + s = s2; + } + } + */ + return E_FAIL; + } + + if (indexType == NArchive::NEventIndexType::kInArcIndex) + { + if (index != (UInt32)(Int32)-1) + { + if (ArcItems) + s = (*ArcItems)[index].Name; + else if (Arc) + { + RINOK(Arc->GetItemPath(index, s2)); + s = s2; + } + if (Archive) + { + RINOK(Archive_GetItemBoolProp(Archive, index, kpidEncrypted, isEncrypted)); + } + } + } + else if (indexType == NArchive::NEventIndexType::kBlockIndex) + { + temp[0] = '#'; + ConvertUInt32ToString(index, temp + 1); + s = temp; + } + + return Callback->ReportExtractResult(opRes, BoolToInt(isEncrypted), s); + COM_TRY_END } @@ -547,7 +695,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOu while (res.Len() < 2) res.InsertAtFront(FTEXT('0')); FString fileName = VolName; - fileName += L'.'; + fileName += FTEXT('.'); fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; @@ -572,3 +720,38 @@ STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword(BSTR *password) return Callback->CryptoGetTextPassword(password); COM_TRY_END } + +HRESULT CArchiveUpdateCallback::InFileStream_On_Error(UINT_PTR val, DWORD error) +{ + if (error == ERROR_LOCK_VIOLATION) + { + MT_LOCK + UInt32 index = (UInt32)val; + FOR_VECTOR(i, _openFiles_Indexes) + { + if (_openFiles_Indexes[i] == index) + { + RINOK(Callback->ReadingFileError(_openFiles_Paths[i], error)); + break; + } + } + } + return HRESULT_FROM_WIN32(error); +} + +void CArchiveUpdateCallback::InFileStream_On_Destroy(UINT_PTR val) +{ + MT_LOCK + UInt32 index = (UInt32)val; + FOR_VECTOR(i, _openFiles_Indexes) + { + if (_openFiles_Indexes[i] == index) + { + _openFiles_Indexes.Delete(i); + _openFiles_Paths.Delete(i); + return; + } + } + throw 20141125; +} + diff --git a/CPP/7zip/UI/Common/UpdateCallback.h b/CPP/7zip/UI/Common/UpdateCallback.h index 3372e628..4ff4a7eb 100644 --- a/CPP/7zip/UI/Common/UpdateCallback.h +++ b/CPP/7zip/UI/Common/UpdateCallback.h @@ -5,26 +5,35 @@ #include "../../../Common/MyCom.h" +#include "../../Common/FileStreams.h" + #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/UpdatePair.h" #include "../Common/UpdateProduce.h" +#include "OpenArchive.h" + #define INTERFACE_IUpdateCallbackUI(x) \ + virtual HRESULT WriteSfx(const wchar_t *name, UInt64 size) x; \ virtual HRESULT SetTotal(UInt64 size) x; \ virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \ virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \ virtual HRESULT CheckBreak() x; \ - virtual HRESULT Finilize() x; \ - virtual HRESULT SetNumFiles(UInt64 numFiles) x; \ - virtual HRESULT GetStream(const wchar_t *name, bool isAnti) x; \ - virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \ - virtual HRESULT SetOperationResult(Int32 operationResult) x; \ + /* virtual HRESULT Finalize() x; */ \ + virtual HRESULT SetNumItems(UInt64 numItems) x; \ + virtual HRESULT GetStream(const wchar_t *name, bool isDir, bool isAnti, UInt32 mode) x; \ + virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x; \ + virtual HRESULT ReadingFileError(const FString &path, DWORD systemError) x; \ + virtual HRESULT SetOperationResult(Int32 opRes) x; \ + virtual HRESULT ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) x; \ + virtual HRESULT ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool isDir) x; \ + /* virtual HRESULT SetPassword(const UString &password) x; */ \ virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \ virtual HRESULT CryptoGetTextPassword(BSTR *password) x; \ - /* virtual HRESULT ShowDeleteFile(const wchar_t *name) x; */ \ - /* virtual HRESULT CloseProgress() { return S_OK; }; */ + virtual HRESULT ShowDeleteFile(const wchar_t *name, bool isDir) x; \ + /* virtual HRESULT CloseProgress() { return S_OK; } */ struct IUpdateCallbackUI { @@ -48,11 +57,14 @@ struct CKeyKeyValPair class CArchiveUpdateCallback: public IArchiveUpdateCallback2, + public IArchiveUpdateCallbackFile, + public IArchiveExtractCallbackMessage, public IArchiveGetRawProps, public IArchiveGetRootProps, public ICryptoGetTextPassword2, public ICryptoGetTextPassword, public ICompressProgressInfo, + public IInFileStream_Callback, public CMyUnknownImp { #if defined(_WIN32) && !defined(UNDER_CE) @@ -64,41 +76,53 @@ class CArchiveUpdateCallback: UInt32 _hardIndex_To; public: - MY_UNKNOWN_IMP6( - IArchiveUpdateCallback2, - IArchiveGetRawProps, - IArchiveGetRootProps, - ICryptoGetTextPassword2, - ICryptoGetTextPassword, - ICompressProgressInfo) + MY_QUERYINTERFACE_BEGIN2(IArchiveUpdateCallback2) + MY_QUERYINTERFACE_ENTRY(IArchiveUpdateCallbackFile) + MY_QUERYINTERFACE_ENTRY(IArchiveExtractCallbackMessage) + MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps) + MY_QUERYINTERFACE_ENTRY(IArchiveGetRootProps) + MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword2) + MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword) + MY_QUERYINTERFACE_ENTRY(ICompressProgressInfo) + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); INTERFACE_IArchiveUpdateCallback2(;) + INTERFACE_IArchiveUpdateCallbackFile(;) + INTERFACE_IArchiveExtractCallbackMessage(;) INTERFACE_IArchiveGetRawProps(;) INTERFACE_IArchiveGetRootProps(;) STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); STDMETHOD(CryptoGetTextPassword)(BSTR *password); + CRecordVector<UInt32> _openFiles_Indexes; + FStringVector _openFiles_Paths; + + bool AreAllFilesClosed() const { return _openFiles_Indexes.IsEmpty(); } + virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error); + virtual void InFileStream_On_Destroy(UINT_PTR val); + CRecordVector<UInt64> VolumesSizes; FString VolName; FString VolExt; IUpdateCallbackUI *Callback; - bool ShareForWrite; - bool StdInMode; - const CDirItems *DirItems; const CDirItem *ParentDirItem; + const CArc *Arc; + CMyComPtr<IInArchive> Archive; const CObjectVector<CArcItem> *ArcItems; const CRecordVector<CUpdatePair2> *UpdatePairs; const UStringVector *NewNames; - CMyComPtr<IInArchive> Archive; - CMyComPtr<IArchiveGetRawProps> GetRawProps; - CMyComPtr<IArchiveGetRootProps> GetRootProps; + + bool ShareForWrite; + bool StdInMode; bool KeepOriginalItemNames; bool StoreNtSecurity; @@ -107,6 +131,7 @@ public: Byte *ProcessedItemsStatuses; + CArchiveUpdateCallback(); bool IsDir(const CUpdatePair2 &up) const diff --git a/CPP/7zip/UI/Common/UpdatePair.cpp b/CPP/7zip/UI/Common/UpdatePair.cpp index aad4a402..68701400 100644 --- a/CPP/7zip/UI/Common/UpdatePair.cpp +++ b/CPP/7zip/UI/Common/UpdatePair.cpp @@ -46,8 +46,8 @@ static void ThrowError(const char *message, const UString &s1, const UString &s2 { UString m; m.SetFromAscii(message); - m += L'\n'; m += s1; - m += L'\n'; m += s2; + m.Add_LF(); m += s1; + m.Add_LF(); m += s2; throw m; } diff --git a/CPP/7zip/UI/Common/UpdateProduce.cpp b/CPP/7zip/UI/Common/UpdateProduce.cpp index 3089d73c..e6eabcf1 100644 --- a/CPP/7zip/UI/Common/UpdateProduce.cpp +++ b/CPP/7zip/UI/Common/UpdateProduce.cpp @@ -24,15 +24,10 @@ void UpdateProduce( up2.NewData = up2.NewProps = true; up2.UseArcProps = false; - switch (actionSet.StateActions[pair.State]) + switch (actionSet.StateActions[(unsigned)pair.State]) { case NPairAction::kIgnore: - /* - if (pair.State != NPairState::kOnlyOnDisk) - IgnoreArchiveItem(m_ArchiveItems[pair.ArcIndex]); - // cout << "deleting"; - */ - if (callback) + if (pair.ArcIndex >= 0 && callback) callback->ShowDeleteFile(pair.ArcIndex); continue; @@ -67,7 +62,9 @@ void UpdateProduce( up2.UseArcProps = (pair.ArcIndex >= 0); break; } + operationChain.Add(up2); } + operationChain.ReserveDown(); } diff --git a/CPP/7zip/UI/Common/UpdateProduce.h b/CPP/7zip/UI/Common/UpdateProduce.h index f2adc771..64c58cc5 100644 --- a/CPP/7zip/UI/Common/UpdateProduce.h +++ b/CPP/7zip/UI/Common/UpdateProduce.h @@ -43,7 +43,7 @@ struct CUpdatePair2 struct IUpdateProduceCallback { - virtual HRESULT ShowDeleteFile(int arcIndex) = 0; + virtual HRESULT ShowDeleteFile(unsigned arcIndex) = 0; }; void UpdateProduce( diff --git a/CPP/7zip/UI/Common/WorkDir.cpp b/CPP/7zip/UI/Common/WorkDir.cpp index 9ad617f7..735cdda4 100644 --- a/CPP/7zip/UI/Common/WorkDir.cpp +++ b/CPP/7zip/UI/Common/WorkDir.cpp @@ -16,6 +16,7 @@ using namespace NDir; FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName) { NWorkDir::NMode::EEnum mode = workDirInfo.Mode; + #ifndef UNDER_CE if (workDirInfo.ForRemovableOnly) { @@ -36,13 +37,15 @@ FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FStr */ } #endif - int pos = path.ReverseFind(FCHAR_PATH_SEPARATOR) + 1; + + int pos = path.ReverseFind_PathSepar() + 1; fileName = path.Ptr(pos); + switch (mode) { case NWorkDir::NMode::kCurrent: { - return path.Left(pos);; + return path.Left(pos); } case NWorkDir::NMode::kSpecified: { diff --git a/CPP/7zip/UI/Console/BenchCon.cpp b/CPP/7zip/UI/Console/BenchCon.cpp index 596f447b..a7c9e676 100644 --- a/CPP/7zip/UI/Console/BenchCon.cpp +++ b/CPP/7zip/UI/Console/BenchCon.cpp @@ -23,7 +23,7 @@ void CPrintBenchCallback::Print(const char *s) void CPrintBenchCallback::NewLine() { - Print("\n"); + fputc('\n', _file); } HRESULT CPrintBenchCallback::CheckBreak() @@ -36,7 +36,6 @@ HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS { CPrintBenchCallback callback; callback._file = f; - callback.NewLine(); return Bench(EXTERNAL_CODECS_LOC_VARS &callback, NULL, props, numIterations, true); } diff --git a/CPP/7zip/UI/Console/Console.dsp b/CPP/7zip/UI/Console/Console.dsp index c75f4b6e..84ee4a6f 100644 --- a/CPP/7zip/UI/Console/Console.dsp +++ b/CPP/7zip/UI/Console/Console.dsp @@ -44,7 +44,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /FAs /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /FAs /Yu"StdAfx.h" /FD /GF /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe @@ -69,7 +69,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gr /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe @@ -77,7 +77,8 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\UTIL\7z.exe" /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\UTIL\7z.exe" /pdbtype:sept /ignore:4033 +# SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Console - Win32 ReleaseU" @@ -94,7 +95,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /c -# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe @@ -120,7 +121,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /Gz /W3 /Gm /GX /ZI /Od /I "../../../" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c -# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gr /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe @@ -380,6 +381,10 @@ SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\Common.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\ComTry.h # End Source File # Begin Source File diff --git a/CPP/7zip/UI/Console/ConsoleClose.cpp b/CPP/7zip/UI/Console/ConsoleClose.cpp index 5acae942..75bd9e51 100644 --- a/CPP/7zip/UI/Console/ConsoleClose.cpp +++ b/CPP/7zip/UI/Console/ConsoleClose.cpp @@ -4,11 +4,11 @@ #include "ConsoleClose.h" -static int g_BreakCounter = 0; -static const int kBreakAbortThreshold = 2; - namespace NConsoleClose { +unsigned g_BreakCounter = 0; +static const unsigned kBreakAbortThreshold = 2; + #if !defined(UNDER_CE) && defined(_WIN32) static BOOL WINAPI HandlerRoutine(DWORD ctrlType) { @@ -35,24 +35,13 @@ static BOOL WINAPI HandlerRoutine(DWORD ctrlType) } #endif -bool TestBreakSignal() -{ - #ifdef UNDER_CE - return false; - #else - /* - if (g_BreakCounter > 0) - return true; - */ - return (g_BreakCounter > 0); - #endif -} - +/* void CheckCtrlBreak() { if (TestBreakSignal()) throw CCtrlBreakException(); } +*/ CCtrlHandlerSetter::CCtrlHandlerSetter() { diff --git a/CPP/7zip/UI/Console/ConsoleClose.h b/CPP/7zip/UI/Console/ConsoleClose.h index 9019c4ce..11c1631c 100644 --- a/CPP/7zip/UI/Console/ConsoleClose.h +++ b/CPP/7zip/UI/Console/ConsoleClose.h @@ -1,11 +1,20 @@ -// ConsoleCloseUtils.h +// ConsoleClose.h -#ifndef __CONSOLECLOSEUTILS_H -#define __CONSOLECLOSEUTILS_H +#ifndef __CONSOLE_CLOSE_H +#define __CONSOLE_CLOSE_H namespace NConsoleClose { -bool TestBreakSignal(); +extern unsigned g_BreakCounter; + +inline bool TestBreakSignal() +{ + #ifdef UNDER_CE + return false; + #else + return (g_BreakCounter != 0); + #endif +} class CCtrlHandlerSetter { @@ -17,7 +26,7 @@ public: class CCtrlBreakException {}; -void CheckCtrlBreak(); +// void CheckCtrlBreak(); } diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp index d3366a39..8dac7fbc 100644 --- a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp +++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp @@ -2,12 +2,6 @@ #include "StdAfx.h" -// #undef sprintf - -#include "ConsoleClose.h" -#include "ExtractCallbackConsole.h" -#include "UserInputUtils.h" - #include "../../../Common/IntToString.h" #include "../../../Common/Wildcard.h" @@ -17,25 +11,146 @@ #include "../../../Windows/ErrorMsg.h" #include "../../../Windows/PropVariantConv.h" +#ifndef _7ZIP_ST +#include "../../../Windows/Synchronization.h" +#endif + #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" +#include "ConsoleClose.h" +#include "ExtractCallbackConsole.h" +#include "UserInputUtils.h" + using namespace NWindows; using namespace NFile; using namespace NDir; -static const char *kTestString = "Testing "; -static const char *kExtractString = "Extracting "; -static const char *kSkipString = "Skipping "; +static HRESULT CheckBreak2() +{ + return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK; +} + +static const char *kError = "ERROR: "; + + +void CExtractScanConsole::StartScanning() +{ + if (NeedPercents()) + _percent.Command = "Scan"; +} + +HRESULT CExtractScanConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */) +{ + if (NeedPercents()) + { + _percent.Files = st.NumDirs + st.NumFiles; + _percent.Completed = st.GetTotalBytes(); + _percent.FileName = fs2us(path); + _percent.Print(); + } + + return CheckBreak2(); +} + +HRESULT CExtractScanConsole::ScanError(const FString &path, DWORD systemError) +{ + ClosePercentsAndFlush(); + + if (_se) + { + *_se << endl << kError << NError::MyFormatMessage(systemError) << endl << + fs2us(path) << endl << endl; + _se->Flush(); + } + return HRESULT_FROM_WIN32(systemError); +} + + +void Print_UInt64_and_String(AString &s, UInt64 val, const char *name) +{ + char temp[32]; + ConvertUInt64ToString(val, temp); + s += temp; + s.Add_Space(); + s += name; +} + +void PrintSize_bytes_Smart(AString &s, UInt64 val) +{ + Print_UInt64_and_String(s, val, "bytes"); + + if (val == 0) + return; + + unsigned numBits = 10; + char c = 'K'; + char temp[4] = { 'K', 'i', 'B', 0 }; + if (val >= ((UInt64)10 << 30)) { numBits = 30; c = 'G'; } + else if (val >= ((UInt64)10 << 20)) { numBits = 20; c = 'M'; } + temp[0] = c; + s += " ("; + Print_UInt64_and_String(s, ((val + ((UInt64)1 << numBits) - 1) >> numBits), temp); + s += ')'; +} + +void Print_DirItemsStat(AString &s, const CDirItemsStat &st) +{ + if (st.NumDirs != 0) + { + Print_UInt64_and_String(s, st.NumDirs, st.NumDirs == 1 ? "folder" : "folders"); + s += ", "; + } + Print_UInt64_and_String(s, st.NumFiles, st.NumFiles == 1 ? "file" : "files"); + s += ", "; + PrintSize_bytes_Smart(s, st.FilesSize); + if (st.NumAltStreams != 0) + { + s.Add_LF(); + Print_UInt64_and_String(s, st.NumAltStreams, "alternate streams"); + s += ", "; + PrintSize_bytes_Smart(s, st.AltStreamsSize); + } +} + +void CExtractScanConsole::PrintStat(const CDirItemsStat &st) +{ + if (_so) + { + AString s; + Print_DirItemsStat(s, st); + *_so << s << endl; + } +} + + + + + + + +#ifndef _7ZIP_ST +static NSynchronization::CCriticalSection g_CriticalSection; +#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); +#else +#define MT_LOCK +#endif + + +static const char *kTestString = "T"; +static const char *kExtractString = "-"; +static const char *kSkipString = "."; // static const char *kCantAutoRename = "can not create file with auto name\n"; // static const char *kCantRenameFile = "can not rename existing file\n"; // static const char *kCantDeleteOutputFile = "can not delete output file "; -static const char *kError = "ERROR: "; + static const char *kMemoryExceptionMessage = "Can't allocate required memory!"; -static const char *kProcessing = "Processing archive: "; +static const char *kExtracting = "Extracting archive: "; +static const char *kTesting = "Testing archive: "; + static const char *kEverythingIsOk = "Everything is Ok"; static const char *kNoFiles = "No files to process"; @@ -49,8 +164,9 @@ static const char *kUnexpectedEnd = "Unexpected end of data"; static const char *kDataAfterEnd = "There are some data after the end of the payload data"; static const char *kIsNotArc = "Is not archive"; static const char *kHeadersError = "Headers Error"; +static const char *kWrongPassword = "Wrong password"; -static const char *k_ErrorFlagsMessages[] = +static const char * const k_ErrorFlagsMessages[] = { "Is not archive" , "Headers Error" @@ -65,31 +181,72 @@ static const char *k_ErrorFlagsMessages[] = , "CRC Error" }; +STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64 size) +{ + MT_LOCK + + if (NeedPercents()) + { + _percent.Total = size; + _percent.Print(); + } + return CheckBreak2(); +} -STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64) +STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *completeValue) { - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; - return S_OK; + MT_LOCK + + if (NeedPercents()) + { + if (completeValue) + _percent.Completed = *completeValue; + _percent.Print(); + } + return CheckBreak2(); } -STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *) +static const char *kTab = " "; + +static void PrintFileInfo(CStdOutStream *_so, const wchar_t *path, const FILETIME *ft, const UInt64 *size) { - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; - return S_OK; + *_so << kTab << "Path: " << path << endl; + if (size) + { + AString s; + PrintSize_bytes_Smart(s, *size); + *_so << kTab << "Size: " << s << endl; + } + if (ft) + { + char temp[64]; + FILETIME locTime; + if (FileTimeToLocalFileTime(ft, &locTime)) + if (ConvertFileTimeToString(locTime, temp, true, true)) + *_so << kTab << "Modified: " << temp << endl; + } } STDMETHODIMP CExtractCallbackConsole::AskOverwrite( - const wchar_t *existName, const FILETIME *, const UInt64 *, - const wchar_t *newName, const FILETIME *, const UInt64 *, + const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, + const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer) { - (*OutStream) << "file " << existName << endl << - "already exists. Overwrite with" << endl << - newName; + MT_LOCK - NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream); + RINOK(CheckBreak2()); + + ClosePercentsAndFlush(); + + if (_so) + { + *_so << endl << "Would you like to replace the existing file:\n"; + PrintFileInfo(_so, existName, existTime, existSize); + *_so << "with the file from archive:\n"; + PrintFileInfo(_so, newName, newTime, newSize); + } + + NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(_so); switch (overwriteAnswer) { @@ -101,86 +258,192 @@ STDMETHODIMP CExtractCallbackConsole::AskOverwrite( case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break; default: return E_FAIL; } - return S_OK; + + if (_so) + { + *_so << endl; + if (NeedFlush) + _so->Flush(); + } + + return CheckBreak2(); } -STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position) +STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int32 /* isFolder */, Int32 askExtractMode, const UInt64 *position) { + MT_LOCK + + _currentName = name; + const char *s; + unsigned requiredLevel = 1; + switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: s = kExtractString; break; case NArchive::NExtract::NAskMode::kTest: s = kTestString; break; - case NArchive::NExtract::NAskMode::kSkip: s = kSkipString; break; - default: s = ""; // return E_FAIL; + case NArchive::NExtract::NAskMode::kSkip: s = kSkipString; requiredLevel = 2; break; + default: s = "???"; requiredLevel = 2; }; - (*OutStream) << s << name; - if (position != 0) - (*OutStream) << " <" << *position << ">"; - return S_OK; + + bool show2 = (LogLevel >= requiredLevel && _so); + + if (show2) + { + ClosePercents_for_so(); + + _tempA = s; + if (name) + _tempA.Add_Space(); + *_so << _tempA; + + _tempU.Empty(); + if (name) + _tempU = name; + _so->PrintUString(_tempU, _tempA); + if (position) + *_so << " <" << *position << ">"; + *_so << endl; + + if (NeedFlush) + _so->Flush(); + } + + if (NeedPercents()) + { + if (PercentsNameLevel >= 1) + { + _percent.FileName.Empty(); + _percent.Command.Empty(); + if (PercentsNameLevel > 1 || !show2) + { + _percent.Command = s; + if (name) + _percent.FileName = name; + } + } + _percent.Print(); + } + + return CheckBreak2(); } STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message) { - (*OutStream) << message << endl; - NumFileErrorsInCurrent++; + MT_LOCK + + RINOK(CheckBreak2()); + + NumFileErrors_in_Current++; NumFileErrors++; - return S_OK; + + ClosePercentsAndFlush(); + if (_se) + { + *_se << kError << message << endl; + _se->Flush(); + } + + return CheckBreak2(); } -STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted) +void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest) { - switch (operationResult) + dest.Empty(); + const char *s = NULL; + + switch (opRes) + { + case NArchive::NExtract::NOperationResult::kUnsupportedMethod: + s = kUnsupportedMethod; + break; + case NArchive::NExtract::NOperationResult::kCRCError: + s = (encrypted ? kCrcFailedEncrypted : kCrcFailed); + break; + case NArchive::NExtract::NOperationResult::kDataError: + s = (encrypted ? kDataErrorEncrypted : kDataError); + break; + case NArchive::NExtract::NOperationResult::kUnavailable: + s = kUnavailableData; + break; + case NArchive::NExtract::NOperationResult::kUnexpectedEnd: + s = kUnexpectedEnd; + break; + case NArchive::NExtract::NOperationResult::kDataAfterEnd: + s = kDataAfterEnd; + break; + case NArchive::NExtract::NOperationResult::kIsNotArc: + s = kIsNotArc; + break; + case NArchive::NExtract::NOperationResult::kHeadersError: + s = kHeadersError; + break; + case NArchive::NExtract::NOperationResult::kWrongPassword: + s = kWrongPassword; + break; + } + + dest += kError; + if (s) + dest += s; + else + { + char temp[16]; + ConvertUInt32ToString(opRes, temp); + dest += "Error #"; + dest += temp; + } +} + +STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 opRes, Int32 encrypted) +{ + MT_LOCK + + if (opRes == NArchive::NExtract::NOperationResult::kOK) { - case NArchive::NExtract::NOperationResult::kOK: - break; - default: + if (NeedPercents()) { - NumFileErrorsInCurrent++; - NumFileErrors++; - (*OutStream) << " : "; - const char *s = NULL; - switch (operationResult) - { - case NArchive::NExtract::NOperationResult::kUnsupportedMethod: - s = kUnsupportedMethod; - break; - case NArchive::NExtract::NOperationResult::kCRCError: - s = (encrypted ? kCrcFailedEncrypted : kCrcFailed); - break; - case NArchive::NExtract::NOperationResult::kDataError: - s = (encrypted ? kDataErrorEncrypted : kDataError); - break; - case NArchive::NExtract::NOperationResult::kUnavailable: - s = kUnavailableData; - break; - case NArchive::NExtract::NOperationResult::kUnexpectedEnd: - s = kUnexpectedEnd; - break; - case NArchive::NExtract::NOperationResult::kDataAfterEnd: - s = kDataAfterEnd; - break; - case NArchive::NExtract::NOperationResult::kIsNotArc: - s = kIsNotArc; - break; - case NArchive::NExtract::NOperationResult::kHeadersError: - s = kHeadersError; - break; - } - if (s) - (*OutStream) << "Error : " << s; - else - { - char temp[16]; - ConvertUInt32ToString(operationResult, temp); - (*OutStream) << "Error #" << temp; - } + _percent.Command.Empty(); + _percent.FileName.Empty(); + _percent.Files++; } } - (*OutStream) << endl; - return S_OK; + else + { + NumFileErrors_in_Current++; + NumFileErrors++; + + if (_se) + { + ClosePercentsAndFlush(); + + AString s; + SetExtractErrorMessage(opRes, encrypted, s); + + *_se << s; + if (!_currentName.IsEmpty()) + *_se << " : " << _currentName; + *_se << endl; + _se->Flush(); + } + } + + return CheckBreak2(); } +STDMETHODIMP CExtractCallbackConsole::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name) +{ + if (opRes != NArchive::NExtract::NOperationResult::kOK) + { + _currentName = name; + return SetOperationResult(opRes, encrypted); + } + + return CheckBreak2(); +} + + + #ifndef _NO_CRYPTO HRESULT CExtractCallbackConsole::SetPassword(const UString &password) @@ -192,55 +455,39 @@ HRESULT CExtractCallbackConsole::SetPassword(const UString &password) STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password) { - if (!PasswordIsDefined) - { - Password = GetPassword(OutStream); - PasswordIsDefined = true; - } - return StringToBstr(Password, password); + COM_TRY_BEGIN + MT_LOCK + return Open_CryptoGetTextPassword(password); + COM_TRY_END } #endif -HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name) +HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name, bool testMode) { + RINOK(CheckBreak2()); + NumTryArcs++; - ThereIsErrorInCurrent = false; - ThereIsWarningInCurrent = false; - NumFileErrorsInCurrent = 0; - (*OutStream) << endl << kProcessing << name << endl; - return S_OK; -} + ThereIsError_in_Current = false; + ThereIsWarning_in_Current = false; + NumFileErrors_in_Current = 0; + + ClosePercents_for_so(); + if (_so) + *_so << endl << (testMode ? kTesting : kExtracting) << name << endl; -HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted) -{ - (*OutStream) << endl; - if (result != S_OK) - { - (*OutStream) << "Error: "; - if (result == S_FALSE) - { - (*OutStream) << (encrypted ? - "Can not open encrypted archive. Wrong password?" : - "Can not open file as archive"); - } - else - { - if (result == E_OUTOFMEMORY) - (*OutStream) << "Can't allocate required memory"; - else - (*OutStream) << NError::MyFormatMessage(result); - } - (*OutStream) << endl; - NumCantOpenArcs++; - ThereIsErrorInCurrent = true; - } + if (NeedPercents()) + _percent.Command = "Open"; return S_OK; } -AString GetOpenArcErrorMessage(UInt32 errorFlags) +HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); +HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); + +static AString GetOpenArcErrorMessage(UInt32 errorFlags) { AString s; + for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsMessages); i++) { UInt32 f = (1 << i); @@ -248,10 +495,11 @@ AString GetOpenArcErrorMessage(UInt32 errorFlags) continue; const char *m = k_ErrorFlagsMessages[i]; if (!s.IsEmpty()) - s += '\n'; + s.Add_LF(); s += m; errorFlags &= ~f; } + if (errorFlags != 0) { char sz[16]; @@ -259,125 +507,258 @@ AString GetOpenArcErrorMessage(UInt32 errorFlags) sz[1] = 'x'; ConvertUInt32ToHex(errorFlags, sz + 2); if (!s.IsEmpty()) - s += '\n'; + s.Add_LF(); s += sz; } + return s; } +void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags) +{ + if (errorFlags == 0) + return; + so << s << endl << GetOpenArcErrorMessage(errorFlags) << endl; +} + +void Add_Messsage_Pre_ArcType(UString &s, const char *pre, const wchar_t *arcType) +{ + s.Add_LF(); + s.AddAscii(pre); + s.AddAscii(" as ["); + s += arcType; + s.AddAscii("] archive"); +} -HRESULT CExtractCallbackConsole::SetError(int level, const wchar_t *name, - UInt32 errorFlags, const wchar_t *errors, - UInt32 warningFlags, const wchar_t *warnings) +void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc) { - if (level != 0) + const CArcErrorInfo &er = arc.ErrorInfo; + + UString s = L"WARNING:\n"; + s += arc.Path; + if (arc.FormatIndex == er.ErrorFormatIndex) { - (*OutStream) << name << endl; + s.Add_LF(); + s.AddAscii("The archive is open with offset"); } - - if (errorFlags != 0) + else { - (*OutStream) << "Errors: "; - (*OutStream) << endl; - (*OutStream) << GetOpenArcErrorMessage(errorFlags); - (*OutStream) << endl; - NumOpenArcErrors++; - ThereIsErrorInCurrent = true; + Add_Messsage_Pre_ArcType(s, "Can not open the file", codecs->GetFormatNamePtr(er.ErrorFormatIndex)); + Add_Messsage_Pre_ArcType(s, "The file is open", codecs->GetFormatNamePtr(arc.FormatIndex)); } + + *_so << s << endl << endl; +} + + +HRESULT CExtractCallbackConsole::OpenResult( + const CCodecs *codecs, const CArchiveLink &arcLink, + const wchar_t *name, HRESULT result) +{ + ClosePercents(); - if (errors && wcslen(errors) != 0) + if (NeedPercents()) { - (*OutStream) << "Errors: "; - (*OutStream) << endl; - (*OutStream) << errors; - (*OutStream) << endl; - NumOpenArcErrors++; - ThereIsErrorInCurrent = true; + _percent.Files = 0; + _percent.Command.Empty(); + _percent.FileName.Empty(); } - if (warningFlags != 0) + + ClosePercentsAndFlush(); + + FOR_VECTOR (level, arcLink.Arcs) { - (*OutStream) << "Warnings: "; - (*OutStream) << endl; - (*OutStream) << GetOpenArcErrorMessage(warningFlags); - (*OutStream) << endl; - NumOpenArcWarnings++; - ThereIsWarningInCurrent = true; - } + const CArc &arc = arcLink.Arcs[level]; + const CArcErrorInfo &er = arc.ErrorInfo; + + UInt32 errorFlags = er.GetErrorFlags(); + + if (errorFlags != 0 || !er.ErrorMessage.IsEmpty()) + { + if (_se) + { + *_se << endl; + if (level != 0) + *_se << arc.Path << endl; + } + + if (errorFlags != 0) + { + if (_se) + PrintErrorFlags(*_se, "ERRORS:", errorFlags); + NumOpenArcErrors++; + ThereIsError_in_Current = true; + } + + if (!er.ErrorMessage.IsEmpty()) + { + if (_se) + *_se << "ERRORS:" << endl << er.ErrorMessage << endl; + NumOpenArcErrors++; + ThereIsError_in_Current = true; + } + + if (_se) + { + *_se << endl; + _se->Flush(); + } + } + + UInt32 warningFlags = er.GetWarningFlags(); + + if (warningFlags != 0 || !er.WarningMessage.IsEmpty()) + { + if (_so) + { + *_so << endl; + if (level != 0) + *_so << arc.Path << endl; + } + + if (warningFlags != 0) + { + if (_so) + PrintErrorFlags(*_so, "WARNINGS:", warningFlags); + NumOpenArcWarnings++; + ThereIsWarning_in_Current = true; + } + + if (!er.WarningMessage.IsEmpty()) + { + if (_so) + *_so << "WARNINGS:" << endl << er.WarningMessage << endl; + NumOpenArcWarnings++; + ThereIsWarning_in_Current = true; + } + + if (_so) + { + *_so << endl; + if (NeedFlush) + _so->Flush(); + } + } - if (warnings && wcslen(warnings) != 0) + + if (er.ErrorFormatIndex >= 0) + { + if (_so) + { + Print_ErrorFormatIndex_Warning(_so, codecs, arc); + if (NeedFlush) + _so->Flush(); + } + ThereIsWarning_in_Current = true; + } + } + + if (result == S_OK) { - (*OutStream) << "Warnings: "; - (*OutStream) << endl; - (*OutStream) << warnings; - (*OutStream) << endl; - NumOpenArcWarnings++; - ThereIsWarningInCurrent = true; + if (_so) + { + RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink)); + *_so << endl; + } } - - (*OutStream) << endl; - return S_OK; + else + { + NumCantOpenArcs++; + if (_so) + _so->Flush(); + if (_se) + { + *_se << kError << name << endl; + HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink); + RINOK(res); + if (result == S_FALSE) + { + } + else + { + if (result == E_OUTOFMEMORY) + *_se << "Can't allocate required memory"; + else + *_se << NError::MyFormatMessage(result); + *_se << endl; + } + _se->Flush(); + } + } + + + return CheckBreak2(); } HRESULT CExtractCallbackConsole::ThereAreNoFiles() { - (*OutStream) << endl << kNoFiles << endl; - return S_OK; + ClosePercents_for_so(); + + if (_so) + { + *_so << endl << kNoFiles << endl; + if (NeedFlush) + _so->Flush(); + } + return CheckBreak2(); } HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) { - if (result == S_OK) + MT_LOCK + + if (NeedPercents()) { - (*OutStream) << endl; + _percent.ClosePrint(true); + _percent.Command.Empty(); + _percent.FileName.Empty(); + } - if (NumFileErrorsInCurrent == 0 && !ThereIsErrorInCurrent) + if (_so) + _so->Flush(); + + if (result == S_OK) + { + if (NumFileErrors_in_Current == 0 && !ThereIsError_in_Current) { - if (ThereIsWarningInCurrent) + if (ThereIsWarning_in_Current) NumArcsWithWarnings++; else NumOkArcs++; - (*OutStream) << kEverythingIsOk << endl; + if (_so) + *_so << kEverythingIsOk << endl; } else { NumArcsWithError++; - if (NumFileErrorsInCurrent != 0) - (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrent << endl; + if (_so) + { + *_so << endl; + if (NumFileErrors_in_Current != 0) + *_so << "Sub items Errors: " << NumFileErrors_in_Current << endl; + } } - return S_OK; + if (_so && NeedFlush) + _so->Flush(); } - - NumArcsWithError++; - if (result == E_ABORT || result == ERROR_DISK_FULL) - return result; - (*OutStream) << endl << kError; - if (result == E_OUTOFMEMORY) - (*OutStream) << kMemoryExceptionMessage; else - (*OutStream) << NError::MyFormatMessage(result); - (*OutStream) << endl; - return S_OK; -} - -HRESULT CExtractCallbackConsole::OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType) -{ - UString s = L"Warning:\n"; - if (wcscmp(okType, errorType) == 0) { - s += L"The archive is open with offset"; - } - else - { - s += name; - s += L"\nCan not open the file as ["; - s += errorType; - s += L"] archive\n"; - s += L"The file is open as ["; - s += okType; - s += L"] archive"; + NumArcsWithError++; + if (result == E_ABORT || result == ERROR_DISK_FULL) + return result; + + if (_se) + { + *_se << endl << kError; + if (result == E_OUTOFMEMORY) + *_se << kMemoryExceptionMessage; + else + *_se << NError::MyFormatMessage(result); + *_se << endl; + _se->Flush(); + } } - (*OutStream) << s << endl << endl; - ThereIsWarningInCurrent = true; - return S_OK; + + return CheckBreak2(); } diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.h b/CPP/7zip/UI/Console/ExtractCallbackConsole.h index 9a0afdc9..dc659521 100644 --- a/CPP/7zip/UI/Console/ExtractCallbackConsole.h +++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.h @@ -1,28 +1,95 @@ // ExtractCallbackConsole.h -#ifndef __EXTRACTCALLBACKCONSOLE_H -#define __EXTRACTCALLBACKCONSOLE_H +#ifndef __EXTRACT_CALLBACK_CONSOLE_H +#define __EXTRACT_CALLBACK_CONSOLE_H -#include "../../../Common/MyString.h" #include "../../../Common/StdOutStream.h" -#include "../../Common/FileStreams.h" - #include "../../IPassword.h" #include "../../Archive/IArchive.h" #include "../Common/ArchiveExtractCallback.h" +#include "PercentPrinter.h" + +#include "OpenCallbackConsole.h" + +class CExtractScanConsole: public IDirItemsCallback +{ + CStdOutStream *_so; + CStdOutStream *_se; + CPercentPrinter _percent; + + bool NeedPercents() const { return _percent._so != NULL; } + + void ClosePercentsAndFlush() + { + if (NeedPercents()) + _percent.ClosePrint(true); + if (_so) + _so->Flush(); + } + +public: + void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream) + { + _so = outStream; + _se = errorStream; + _percent._so = percentStream; + } + + void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; } + + void StartScanning(); + + INTERFACE_IDirItemsCallback(;) + + void CloseScanning() + { + if (NeedPercents()) + _percent.ClosePrint(true); + } + + void PrintStat(const CDirItemsStat &st); +}; + + + + class CExtractCallbackConsole: public IExtractCallbackUI, + // public IArchiveExtractCallbackMessage, + public IFolderArchiveExtractCallback2, #ifndef _NO_CRYPTO public ICryptoGetTextPassword, #endif + public COpenCallbackConsole, public CMyUnknownImp { + AString _tempA; + UString _tempU; + + UString _currentName; + + void ClosePercents_for_so() + { + if (NeedPercents() && _so == _percent._so) + _percent.ClosePrint(false); + } + + void ClosePercentsAndFlush() + { + if (NeedPercents()) + _percent.ClosePrint(true); + if (_so) + _so->Flush(); + } + public: MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback) + // MY_QUERYINTERFACE_ENTRY(IArchiveExtractCallbackMessage) + MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback2) #ifndef _NO_CRYPTO MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword) #endif @@ -32,57 +99,55 @@ public: STDMETHOD(SetTotal)(UInt64 total); STDMETHOD(SetCompleted)(const UInt64 *completeValue); - // IFolderArchiveExtractCallback - STDMETHOD(AskOverwrite)( - const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, - const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, - Int32 *answer); - STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position); - - STDMETHOD(MessageError)(const wchar_t *message); - STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted); + INTERFACE_IFolderArchiveExtractCallback(;) - HRESULT BeforeOpen(const wchar_t *name); - HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted); - HRESULT SetError(int level, const wchar_t *name, - UInt32 errorFlags, const wchar_t *errors, - UInt32 warningFlags, const wchar_t *warnings); + INTERFACE_IExtractCallbackUI(;) + // INTERFACE_IArchiveExtractCallbackMessage(;) + INTERFACE_IFolderArchiveExtractCallback2(;) - HRESULT ThereAreNoFiles(); - HRESULT ExtractResult(HRESULT result); - HRESULT OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType); - - #ifndef _NO_CRYPTO - HRESULT SetPassword(const UString &password); - STDMETHOD(CryptoGetTextPassword)(BSTR *password); - bool PasswordIsDefined; - UString Password; + STDMETHOD(CryptoGetTextPassword)(BSTR *password); #endif UInt64 NumTryArcs; - bool ThereIsErrorInCurrent; - bool ThereIsWarningInCurrent; + + bool ThereIsError_in_Current; + bool ThereIsWarning_in_Current; - UInt64 NumCantOpenArcs; UInt64 NumOkArcs; + UInt64 NumCantOpenArcs; UInt64 NumArcsWithError; UInt64 NumArcsWithWarnings; - UInt64 NumProblemArcsLevs; UInt64 NumOpenArcErrors; UInt64 NumOpenArcWarnings; UInt64 NumFileErrors; - UInt64 NumFileErrorsInCurrent; + UInt64 NumFileErrors_in_Current; - CStdOutStream *OutStream; + bool NeedFlush; + unsigned PercentsNameLevel; + unsigned LogLevel; - void Init() + CExtractCallbackConsole(): + NeedFlush(false), + PercentsNameLevel(1), + LogLevel(0) + {} + + void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; } + + void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream) { + COpenCallbackConsole::Init(outStream, errorStream, percentStream); + NumTryArcs = 0; + + ThereIsError_in_Current = false; + ThereIsWarning_in_Current = false; + NumOkArcs = 0; NumCantOpenArcs = 0; NumArcsWithError = 0; @@ -90,10 +155,10 @@ public: NumOpenArcErrors = 0; NumOpenArcWarnings = 0; + NumFileErrors = 0; - NumFileErrorsInCurrent = 0; + NumFileErrors_in_Current = 0; } - }; #endif diff --git a/CPP/7zip/UI/Console/HashCon.cpp b/CPP/7zip/UI/Console/HashCon.cpp index 273f21c8..a71e4b50 100644 --- a/CPP/7zip/UI/Console/HashCon.cpp +++ b/CPP/7zip/UI/Console/HashCon.cpp @@ -3,9 +3,6 @@ #include "StdAfx.h" #include "../../../Common/IntToString.h" -#include "../../../Common/StringConvert.h" - -#include "../../../Windows/ErrorMsg.h" #include "ConsoleClose.h" #include "HashCon.h" @@ -14,53 +11,85 @@ static const wchar_t *kEmptyFileAlias = L"[Content]"; static const char *kScanningMessage = "Scanning"; -HRESULT CHashCallbackConsole::CheckBreak() +static HRESULT CheckBreak2() { return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK; } +HRESULT CHashCallbackConsole::CheckBreak() +{ + return CheckBreak2(); +} + HRESULT CHashCallbackConsole::StartScanning() { - (*OutStream) << kScanningMessage; - return CheckBreak(); + if (PrintHeaders && _so) + *_so << kScanningMessage << endl; + if (NeedPercents()) + { + _percent.ClearCurState(); + _percent.Command = "Scan"; + } + return CheckBreak2(); } -HRESULT CHashCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, UInt64 /* totalSize */, const wchar_t * /* path */, bool /* isDir */) +HRESULT CHashCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */) { - return CheckBreak(); + if (NeedPercents()) + { + _percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams; + _percent.Completed = st.GetTotalBytes(); + _percent.FileName = fs2us(path); + _percent.Print(); + } + return CheckBreak2(); } -HRESULT CHashCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError) +HRESULT CHashCallbackConsole::ScanError(const FString &path, DWORD systemError) { - return CanNotFindError_Base(name, systemError); + return ScanError_Base(path, systemError); } -HRESULT CHashCallbackConsole::FinishScanning() +void Print_DirItemsStat(AString &s, const CDirItemsStat &st); + +HRESULT CHashCallbackConsole::FinishScanning(const CDirItemsStat &st) { - (*OutStream) << endl << endl; - return CheckBreak(); + if (NeedPercents()) + { + _percent.ClosePrint(true); + _percent.ClearCurState(); + } + if (PrintHeaders && _so) + { + Print_DirItemsStat(_s, st); + *_so << _s << endl << endl; + } + return CheckBreak2(); } HRESULT CHashCallbackConsole::SetNumFiles(UInt64 /* numFiles */) { - return CheckBreak(); + return CheckBreak2(); } HRESULT CHashCallbackConsole::SetTotal(UInt64 size) { - if (EnablePercents) - m_PercentPrinter.SetTotal(size); - return CheckBreak(); + if (NeedPercents()) + { + _percent.Total = size; + _percent.Print(); + } + return CheckBreak2(); } HRESULT CHashCallbackConsole::SetCompleted(const UInt64 *completeValue) { - if (completeValue && EnablePercents) + if (completeValue && NeedPercents()) { - m_PercentPrinter.SetRatio(*completeValue); - m_PercentPrinter.PrintRatio(); + _percent.Completed = *completeValue; + _percent.Print(); } - return CheckBreak(); + return CheckBreak2(); } static void AddMinuses(AString &s, unsigned num) @@ -69,171 +98,228 @@ static void AddMinuses(AString &s, unsigned num) s += '-'; } -static void SetSpaces(char *s, int num) +static void AddSpaces_if_Positive(AString &s, int num) { for (int i = 0; i < num; i++) - s[i] = ' '; + s.Add_Space(); } -static void SetSpacesAndNul(char *s, int num) +static void SetSpacesAndNul(char *s, unsigned num) { - SetSpaces(s, num); + for (unsigned i = 0; i < num; i++) + s[i] = ' '; s[num] = 0; } -static void AddSpaces(UString &s, int num) -{ - for (int i = 0; i < num; i++) - s += ' '; -} +static const unsigned kSizeField_Len = 13; +static const unsigned kNameField_Len = 12; -static const int kSizeField_Len = 13; -static const int kNameField_Len = 12; +static const unsigned kHashColumnWidth_Min = 4 * 2; static unsigned GetColumnWidth(unsigned digestSize) { unsigned width = digestSize * 2; - const unsigned kMinColumnWidth = 8; - return width < kMinColumnWidth ? kMinColumnWidth: width; + return width < kHashColumnWidth_Min ? kHashColumnWidth_Min: width; } void CHashCallbackConsole::PrintSeparatorLine(const CObjectVector<CHasherState> &hashers) { - AString s; + _s.Empty(); + for (unsigned i = 0; i < hashers.Size(); i++) { + if (i != 0) + _s.Add_Space(); const CHasherState &h = hashers[i]; - AddMinuses(s, GetColumnWidth(h.DigestSize)); - s += ' '; + AddMinuses(_s, GetColumnWidth(h.DigestSize)); + } + + if (PrintSize) + { + _s.Add_Space(); + AddMinuses(_s, kSizeField_Len); } - AddMinuses(s, kSizeField_Len); - s += " "; - AddMinuses(s, kNameField_Len); - m_PercentPrinter.PrintString(s); - m_PercentPrinter.PrintNewLine(); + + if (PrintName) + { + AddSpacesBeforeName(); + AddMinuses(_s, kNameField_Len); + } + + *_so << _s << endl; } HRESULT CHashCallbackConsole::BeforeFirstFile(const CHashBundle &hb) { - UString s; - FOR_VECTOR (i, hb.Hashers) + if (PrintHeaders && _so) { - const CHasherState &h = hb.Hashers[i]; - s += h.Name; - AddSpaces(s, (int)GetColumnWidth(h.DigestSize) - h.Name.Len() + 1); + _s.Empty(); + ClosePercents_for_so(); + + FOR_VECTOR (i, hb.Hashers) + { + if (i != 0) + _s.Add_Space(); + const CHasherState &h = hb.Hashers[i]; + _s += h.Name; + AddSpaces_if_Positive(_s, (int)GetColumnWidth(h.DigestSize) - (int)h.Name.Len()); + } + + if (PrintSize) + { + _s.Add_Space(); + const AString s2 = "Size"; + AddSpaces_if_Positive(_s, (int)kSizeField_Len - (int)s2.Len()); + _s += s2; + } + + if (PrintName) + { + AddSpacesBeforeName(); + _s += "Name"; + } + + *_so << _s << endl; + PrintSeparatorLine(hb.Hashers); } - UString s2 = L"Size"; - AddSpaces(s, kSizeField_Len - s2.Len()); - s += s2; - s += L" "; - s += L"Name"; - m_PercentPrinter.PrintString(s); - m_PercentPrinter.PrintNewLine(); - PrintSeparatorLine(hb.Hashers); - return CheckBreak(); + + return CheckBreak2(); } -HRESULT CHashCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError) +HRESULT CHashCallbackConsole::OpenFileError(const FString &path, DWORD systemError) { - FailedCodes.Add(systemError); - FailedFiles.Add(name); - // if (systemError == ERROR_SHARING_VIOLATION) - { - m_PercentPrinter.PrintString(name); - m_PercentPrinter.PrintString(": WARNING: "); - m_PercentPrinter.PrintString(NWindows::NError::MyFormatMessage(systemError)); - return S_FALSE; - } - // return systemError; + return OpenFileError_Base(path, systemError); } HRESULT CHashCallbackConsole::GetStream(const wchar_t *name, bool /* isFolder */) { - m_FileName = name; - return CheckBreak(); + _fileName = name; + + if (NeedPercents()) + { + if (PrintNameInPercents) + { + _percent.FileName.Empty(); + if (name) + _percent.FileName = name; + } + _percent.Print(); + } + return CheckBreak2(); } void CHashCallbackConsole::PrintResultLine(UInt64 fileSize, const CObjectVector<CHasherState> &hashers, unsigned digestIndex, bool showHash) { + ClosePercents_for_so(); + + _s.Empty(); + FOR_VECTOR (i, hashers) { const CHasherState &h = hashers[i]; - char s[k_HashCalc_DigestSize_Max * 2 + 64]; s[0] = 0; if (showHash) AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize); - SetSpacesAndNul(s + strlen(s), (int)GetColumnWidth(h.DigestSize) - (int)strlen(s) + 1); - m_PercentPrinter.PrintString(s); + SetSpacesAndNul(s + strlen(s), (int)GetColumnWidth(h.DigestSize) - (int)strlen(s)); + if (i != 0) + _s.Add_Space(); + _s += s; } - char s[64]; - s[0] = 0; - char *p = s; - if (showHash && fileSize != 0) + + if (PrintSize) { - p = s + 32; - ConvertUInt64ToString(fileSize, p); - int numSpaces = kSizeField_Len - (int)strlen(p); - if (numSpaces > 0) + _s.Add_Space(); + + char s[kSizeField_Len + 32]; + char *p = s; + + if (showHash) { - p -= numSpaces; - SetSpaces(p, numSpaces); + p = s + kSizeField_Len; + ConvertUInt64ToString(fileSize, p); + int numSpaces = kSizeField_Len - (int)strlen(p); + if (numSpaces > 0) + { + p -= (unsigned)numSpaces; + for (unsigned i = 0; i < (unsigned)numSpaces; i++) + p[i] = ' '; + } } + else + SetSpacesAndNul(s, kSizeField_Len); + + _s += p; } - else - SetSpacesAndNul(s, kSizeField_Len - (int)strlen(s)); - unsigned len = (unsigned)strlen(p); - p[len] = ' '; - p[len + 1] = ' '; - p[len + 2] = 0; - m_PercentPrinter.PrintString(p); + + if (PrintName) + AddSpacesBeforeName(); + + *_so << _s; } HRESULT CHashCallbackConsole::SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) { - PrintResultLine(fileSize, hb.Hashers, k_HashCalc_Index_Current, showHash); - if (m_FileName.IsEmpty()) - m_PercentPrinter.PrintString(kEmptyFileAlias); - else - m_PercentPrinter.PrintString(m_FileName); - m_PercentPrinter.PrintNewLine(); - return S_OK; + if (_so) + { + PrintResultLine(fileSize, hb.Hashers, k_HashCalc_Index_Current, showHash); + if (PrintName) + { + if (_fileName.IsEmpty()) + *_so << kEmptyFileAlias; + else + *_so << _fileName; + } + *_so << endl; + } + + if (NeedPercents()) + { + _percent.Files++; + _percent.Print(); + } + + return CheckBreak2(); } static const char *k_DigestTitles[] = { - " :" + " : " , " for data: " , " for data and names: " , " for streams and names: " }; -static void PrintSum(CStdOutStream &p, const CHasherState &h, unsigned digestIndex) +static void PrintSum(CStdOutStream &so, const CHasherState &h, unsigned digestIndex) { + so << h.Name; + + { + AString temp; + AddSpaces_if_Positive(temp, 6 - (int)h.Name.Len()); + so << temp; + } + + so << k_DigestTitles[digestIndex]; + char s[k_HashCalc_DigestSize_Max * 2 + 64]; - UString name = h.Name; - AddSpaces(name, 6 - (int)name.Len()); - p << name; - p << k_DigestTitles[digestIndex]; s[0] = 0; AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize); - p << s; - p << "\n"; + so << s << endl; } - -void PrintHashStat(CStdOutStream &p, const CHashBundle &hb) +void PrintHashStat(CStdOutStream &so, const CHashBundle &hb) { FOR_VECTOR (i, hb.Hashers) { const CHasherState &h = hb.Hashers[i]; - p << "\n"; - PrintSum(p, h, k_HashCalc_Index_DataSum); + PrintSum(so, h, k_HashCalc_Index_DataSum); if (hb.NumFiles != 1 || hb.NumDirs != 0) - PrintSum(p, h, k_HashCalc_Index_NamesSum); + PrintSum(so, h, k_HashCalc_Index_NamesSum); if (hb.NumAltStreams != 0) - PrintSum(p, h, k_HashCalc_Index_StreamsSum); + PrintSum(so, h, k_HashCalc_Index_StreamsSum); + so << endl; } } @@ -243,32 +329,39 @@ void CHashCallbackConsole::PrintProperty(const char *name, UInt64 value) s[0] = ':'; s[1] = ' '; ConvertUInt64ToString(value, s + 2); - m_PercentPrinter.PrintString(name); - m_PercentPrinter.PrintString(s); - m_PercentPrinter.PrintNewLine(); + *_so << name << s << endl; } HRESULT CHashCallbackConsole::AfterLastFile(const CHashBundle &hb) { - PrintSeparatorLine(hb.Hashers); - - PrintResultLine(hb.FilesSize, hb.Hashers, k_HashCalc_Index_DataSum, true); - m_PercentPrinter.PrintNewLine(); - m_PercentPrinter.PrintNewLine(); + ClosePercents2(); - if (hb.NumFiles != 1 || hb.NumDirs != 0) - { - if (hb.NumDirs != 0) - PrintProperty("Folders", hb.NumDirs); - PrintProperty("Files", hb.NumFiles); - } - PrintProperty("Size", hb.FilesSize); - if (hb.NumAltStreams != 0) + if (PrintHeaders && _so) { - PrintProperty("AltStreams", hb.NumAltStreams); - PrintProperty("AltStreams size", hb.AltStreamsSize); + PrintSeparatorLine(hb.Hashers); + + PrintResultLine(hb.FilesSize, hb.Hashers, k_HashCalc_Index_DataSum, true); + + *_so << endl << endl; + + if (hb.NumFiles != 1 || hb.NumDirs != 0) + { + if (hb.NumDirs != 0) + PrintProperty("Folders", hb.NumDirs); + PrintProperty("Files", hb.NumFiles); + } + + PrintProperty("Size", hb.FilesSize); + + if (hb.NumAltStreams != 0) + { + PrintProperty("Alternate streams", hb.NumAltStreams); + PrintProperty("Alternate streams size", hb.AltStreamsSize); + } + + *_so << endl; + PrintHashStat(*_so, hb); } - PrintHashStat(*m_PercentPrinter.OutStream, hb); - m_PercentPrinter.PrintNewLine(); + return S_OK; } diff --git a/CPP/7zip/UI/Console/HashCon.h b/CPP/7zip/UI/Console/HashCon.h index 7d3c72fd..5b30b69a 100644 --- a/CPP/7zip/UI/Console/HashCon.h +++ b/CPP/7zip/UI/Console/HashCon.h @@ -9,18 +9,40 @@ class CHashCallbackConsole: public IHashCallbackUI, public CCallbackConsoleBase { - UString m_FileName; + UString _fileName; + AString _s; + + void AddSpacesBeforeName() + { + _s.Add_Space(); + _s.Add_Space(); + } void PrintSeparatorLine(const CObjectVector<CHasherState> &hashers); void PrintResultLine(UInt64 fileSize, const CObjectVector<CHasherState> &hashers, unsigned digestIndex, bool showHash); void PrintProperty(const char *name, UInt64 value); + public: + bool PrintNameInPercents; + + bool PrintHeaders; + + bool PrintSize; + bool PrintName; + + CHashCallbackConsole(): + PrintNameInPercents(true), + PrintHeaders(false), + PrintSize(true), + PrintName(true) + {} + ~CHashCallbackConsole() { } INTERFACE_IHashCallbackUI(;) }; -void PrintHashStat(CStdOutStream &stdStream, const CHashBundle &hb); +void PrintHashStat(CStdOutStream &so, const CHashBundle &hb); #endif diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp index f02296ea..64abb1fb 100644 --- a/CPP/7zip/UI/Console/List.cpp +++ b/CPP/7zip/UI/Console/List.cpp @@ -23,9 +23,10 @@ using namespace NWindows; using namespace NCOM; +extern CStdOutStream *g_StdStream; +extern CStdOutStream *g_ErrStream; - -static const char *kPropIdToName[] = +static const char * const kPropIdToName[] = { "0" , "1" @@ -120,6 +121,8 @@ static const char *kPropIdToName[] = , "Hard Link" , "iNode" , "Stream ID" + , "Read-only" + , "Out Name" }; static const char kEmptyAttribChar = '.'; @@ -131,6 +134,8 @@ static const char *kString_Dirs = "folders"; static const char *kString_AltStreams = "alternate streams"; static const char *kString_Streams = "streams"; +static const char *kError = "ERROR: "; + static void GetAttribString(UInt32 wa, bool isDir, bool allAttribs, char *s) { if (isDir) @@ -163,8 +168,8 @@ struct CFieldInfo AString NameA; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; - int PrefixSpacesWidth; - int Width; + unsigned PrefixSpacesWidth; + unsigned Width; }; struct CFieldInfoInit @@ -173,8 +178,8 @@ struct CFieldInfoInit const char *Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; - int PrefixSpacesWidth; - int Width; + unsigned PrefixSpacesWidth; + unsigned Width; }; static const CFieldInfoInit kStandardFieldTable[] = @@ -186,71 +191,105 @@ static const CFieldInfoInit kStandardFieldTable[] = { kpidPath, "Name", kLeft, kLeft, 2, 24 } }; -const int kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width +const unsigned kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width static const char *g_Spaces = " " ; -static void PrintSpaces(int numSpaces) +static void PrintSpaces(unsigned numSpaces) { if (numSpaces > 0 && numSpaces <= kNumSpacesMax) g_StdOut << g_Spaces + (kNumSpacesMax - numSpaces); } -static void PrintSpacesToString(char *dest, int numSpaces) +static void PrintSpacesToString(char *dest, unsigned numSpaces) { - int i; + unsigned i; for (i = 0; i < numSpaces; i++) dest[i] = ' '; dest[i] = 0; } -static void PrintString(EAdjustment adj, int width, const UString &textString) +// extern int g_CodePage; + +static void PrintUString(EAdjustment adj, unsigned width, const UString &s, AString &temp) { - const int numSpaces = width - textString.Len(); - int numLeftSpaces = 0; - switch (adj) + /* + // we don't need multibyte align. + int codePage = g_CodePage; + if (codePage == -1) + codePage = CP_OEMCP; + if (codePage == CP_UTF8) + ConvertUnicodeToUTF8(s, temp); + else + UnicodeStringToMultiByte2(temp, s, (UINT)codePage); + */ + + unsigned numSpaces = 0; + + if (width > s.Len()) { - case kLeft: numLeftSpaces = 0; break; - case kCenter: numLeftSpaces = numSpaces / 2; break; - case kRight: numLeftSpaces = numSpaces; break; + numSpaces = width - s.Len(); + unsigned numLeftSpaces = 0; + switch (adj) + { + case kLeft: numLeftSpaces = 0; break; + case kCenter: numLeftSpaces = numSpaces / 2; break; + case kRight: numLeftSpaces = numSpaces; break; + } + PrintSpaces(numLeftSpaces); + numSpaces -= numLeftSpaces; } - PrintSpaces(numLeftSpaces); - g_StdOut << textString; - PrintSpaces(numSpaces - numLeftSpaces); + + g_StdOut.PrintUString(s, temp); + PrintSpaces(numSpaces); } -static void PrintString(EAdjustment adj, int width, const char *textString) +static void PrintString(EAdjustment adj, unsigned width, const char *s) { - const int numSpaces = width - (int)strlen(textString); - int numLeftSpaces = 0; - switch (adj) + unsigned numSpaces = 0; + unsigned len = (unsigned)strlen(s); + + if (width > len) { - case kLeft: numLeftSpaces = 0; break; - case kCenter: numLeftSpaces = numSpaces / 2; break; - case kRight: numLeftSpaces = numSpaces; break; + numSpaces = width - len; + unsigned numLeftSpaces = 0; + switch (adj) + { + case kLeft: numLeftSpaces = 0; break; + case kCenter: numLeftSpaces = numSpaces / 2; break; + case kRight: numLeftSpaces = numSpaces; break; + } + PrintSpaces(numLeftSpaces); + numSpaces -= numLeftSpaces; } - PrintSpaces(numLeftSpaces); - g_StdOut << textString; - PrintSpaces(numSpaces - numLeftSpaces); + + g_StdOut << s; + PrintSpaces(numSpaces); } -static void PrintStringToString(char *dest, EAdjustment adj, int width, const char *textString) +static void PrintStringToString(char *dest, EAdjustment adj, unsigned width, const char *textString) { - int len = (int)strlen(textString); - const int numSpaces = width - len; - int numLeftSpaces = 0; - switch (adj) + unsigned numSpaces = 0; + unsigned len = (unsigned)strlen(textString); + + if (width > len) { - case kLeft: numLeftSpaces = 0; break; - case kCenter: numLeftSpaces = numSpaces / 2; break; - case kRight: numLeftSpaces = numSpaces; break; - } - PrintSpacesToString(dest, numLeftSpaces); - if (numLeftSpaces > 0) + numSpaces = width - len; + unsigned numLeftSpaces = 0; + switch (adj) + { + case kLeft: numLeftSpaces = 0; break; + case kCenter: numLeftSpaces = numSpaces / 2; break; + case kRight: numLeftSpaces = numSpaces; break; + } + PrintSpacesToString(dest, numLeftSpaces); dest += numLeftSpaces; + numSpaces -= numLeftSpaces; + } + memcpy(dest, textString, len); dest += len; - PrintSpacesToString(dest, numSpaces - numLeftSpaces); + PrintSpacesToString(dest, numSpaces); } struct CListUInt64Def @@ -287,12 +326,12 @@ struct CListStat UInt64 NumFiles; CListStat(): NumFiles(0) {} - void Update(const CListStat &stat) + void Update(const CListStat &st) { - Size.Add(stat.Size); - PackSize.Add(stat.PackSize); - MTime.Update(stat.MTime); - NumFiles += stat.NumFiles; + Size.Add(st.Size); + PackSize.Add(st.PackSize); + MTime.Update(st.MTime); + NumFiles += st.NumFiles; } void SetSizeDefIfNoFiles() { if (NumFiles == 0) Size.Def = true; } }; @@ -305,11 +344,11 @@ struct CListStat2 CListStat2(): NumDirs(0) {} - void Update(const CListStat2 &stat) + void Update(const CListStat2 &st) { - MainFiles.Update(stat.MainFiles); - AltStreams.Update(stat.AltStreams); - NumDirs += stat.NumDirs; + MainFiles.Update(st.MainFiles); + AltStreams.Update(st.AltStreams); + NumDirs += st.NumDirs; } const UInt64 GetNumStreams() const { return MainFiles.NumFiles + AltStreams.NumFiles; } CListStat &GetStat(bool altStreamsMode) { return altStreamsMode ? AltStreams : MainFiles; } @@ -319,34 +358,34 @@ class CFieldPrinter { CObjectVector<CFieldInfo> _fields; - void AddProp(BSTR name, PROPID propID, bool isRawProp); + void AddProp(const wchar_t *name, PROPID propID, bool isRawProp); public: const CArc *Arc; bool TechMode; UString FilePath; AString TempAString; UString TempWString; - bool IsFolder; + bool IsDir; AString LinesString; void Clear() { _fields.Clear(); LinesString.Empty(); } - void Init(const CFieldInfoInit *standardFieldTable, int numItems); + void Init(const CFieldInfoInit *standardFieldTable, unsigned numItems); HRESULT AddMainProps(IInArchive *archive); HRESULT AddRawProps(IArchiveGetRawProps *getRawProps); void PrintTitle(); void PrintTitleLines(); - HRESULT PrintItemInfo(UInt32 index, const CListStat &stat); - void PrintSum(const CListStat &stat, UInt64 numDirs, const char *str); - void PrintSum(const CListStat2 &stat); + HRESULT PrintItemInfo(UInt32 index, const CListStat &st); + void PrintSum(const CListStat &st, UInt64 numDirs, const char *str); + void PrintSum(const CListStat2 &stat2); }; -void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems) +void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, unsigned numItems) { Clear(); - for (int i = 0; i < numItems; i++) + for (unsigned i = 0; i < numItems; i++) { CFieldInfo &f = _fields.AddNew(); const CFieldInfoInit &fii = standardFieldTable[i]; @@ -358,9 +397,9 @@ void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems) f.PrefixSpacesWidth = fii.PrefixSpacesWidth; f.Width = fii.Width; - int k; + unsigned k; for (k = 0; k < fii.PrefixSpacesWidth; k++) - LinesString += ' '; + LinesString.Add_Space(); for (k = 0; k < fii.Width; k++) LinesString += '-'; } @@ -383,13 +422,13 @@ static void GetPropName(PROPID propID, const wchar_t *name, AString &nameA, UStr } } -void CFieldPrinter::AddProp(BSTR name, PROPID propID, bool isRawProp) +void CFieldPrinter::AddProp(const wchar_t *name, PROPID propID, bool isRawProp) { CFieldInfo f; f.PropID = propID; f.IsRawProp = isRawProp; GetPropName(propID, name, f.NameA, f.NameU); - f.NameU += L" = "; + f.NameU.AddAscii(" = "); if (!f.NameA.IsEmpty()) f.NameA += " = "; else @@ -486,9 +525,9 @@ static void HexToString(char *dest, const Byte *data, UInt32 size) #endif -#define MY_ENDL '\n' +#define MY_ENDL endl -HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &stat) +HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st) { char temp[128]; size_t tempPos = 0; @@ -530,7 +569,7 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &stat) continue; } - int width = f.Width; + const unsigned width = f.Width; if (f.IsRawProp) { @@ -561,7 +600,7 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &stat) if (ConvertNtReparseToString((const Byte *)data, dataSize, s)) { needPrint = false; - g_StdOut << s; + g_StdOut.PrintUString(s, TempAString); } } @@ -593,15 +632,15 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &stat) CPropVariant prop; switch (f.PropID) { - case kpidSize: if (stat.Size.Def) prop = stat.Size.Val; break; - case kpidPackSize: if (stat.PackSize.Def) prop = stat.PackSize.Val; break; - case kpidMTime: if (stat.MTime.Def) prop = stat.MTime.Val; break; + case kpidSize: if (st.Size.Def) prop = st.Size.Val; break; + case kpidPackSize: if (st.PackSize.Def) prop = st.PackSize.Val; break; + case kpidMTime: if (st.MTime.Def) prop = st.MTime.Val; break; default: RINOK(Arc->Archive->GetProperty(index, f.PropID, &prop)); } if (f.PropID == kpidAttrib && (prop.vt == VT_EMPTY || prop.vt == VT_UI4)) { - GetAttribString((prop.vt == VT_EMPTY) ? 0 : prop.ulVal, IsFolder, techMode, temp + tempPos); + GetAttribString((prop.vt == VT_EMPTY) ? 0 : prop.ulVal, IsDir, techMode, temp + tempPos); if (techMode) g_StdOut << temp + tempPos; else @@ -626,24 +665,22 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &stat) tempPos += len; if (len < (unsigned)f.Width) { - len = (size_t)f.Width - len; - PrintSpacesToString(temp + tempPos, (int)len); + len = f.Width - len; + PrintSpacesToString(temp + tempPos, (unsigned)len); tempPos += len; } } } else if (prop.vt == VT_BSTR) { + TempWString.SetFromBstr(prop.bstrVal); if (techMode) { - int len = (int)wcslen(prop.bstrVal); - MyStringCopy(TempWString.GetBuffer(len), prop.bstrVal); // replace CR/LF here. - TempWString.ReleaseBuffer(len); g_StdOut.PrintUString(TempWString, TempAString); } else - PrintString(f.TextAdjustment, width, prop.bstrVal); + PrintUString(f.TextAdjustment, width, TempWString, TempAString); } else { @@ -665,55 +702,48 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &stat) return S_OK; } -static void PrintNumber(EAdjustment adj, int width, const CListUInt64Def &value) +static void PrintNumber(EAdjustment adj, unsigned width, const CListUInt64Def &value) { - wchar_t s[32]; + char s[32]; s[0] = 0; if (value.Def) ConvertUInt64ToString(value.Val, s); PrintString(adj, width, s); } -static void PrintNumberAndString(AString &s, UInt64 value, const char *text) -{ - char t[32]; - ConvertUInt64ToString(value, t); - s += t; - s += ' '; - s += text; -} +void Print_UInt64_and_String(AString &s, UInt64 val, const char *name); -void CFieldPrinter::PrintSum(const CListStat &stat, UInt64 numDirs, const char *str) +void CFieldPrinter::PrintSum(const CListStat &st, UInt64 numDirs, const char *str) { FOR_VECTOR (i, _fields) { const CFieldInfo &f = _fields[i]; PrintSpaces(f.PrefixSpacesWidth); if (f.PropID == kpidSize) - PrintNumber(f.TextAdjustment, f.Width, stat.Size); + PrintNumber(f.TextAdjustment, f.Width, st.Size); else if (f.PropID == kpidPackSize) - PrintNumber(f.TextAdjustment, f.Width, stat.PackSize); + PrintNumber(f.TextAdjustment, f.Width, st.PackSize); else if (f.PropID == kpidMTime) { char s[64]; s[0] = 0; - if (stat.MTime.Def) - PrintTime(s, &stat.MTime.Val); + if (st.MTime.Def) + PrintTime(s, &st.MTime.Val); PrintString(f.TextAdjustment, f.Width, s); } else if (f.PropID == kpidPath) { AString s; - PrintNumberAndString(s, stat.NumFiles, str); + Print_UInt64_and_String(s, st.NumFiles, str); if (numDirs != 0) { s += ", "; - PrintNumberAndString(s, numDirs, kString_Dirs); + Print_UInt64_and_String(s, numDirs, kString_Dirs); } PrintString(f.TextAdjustment, 0, s); } else - PrintString(f.TextAdjustment, f.Width, L""); + PrintString(f.TextAdjustment, f.Width, ""); } g_StdOut << endl; } @@ -724,9 +754,9 @@ void CFieldPrinter::PrintSum(const CListStat2 &stat2) if (stat2.AltStreams.NumFiles != 0) { PrintSum(stat2.AltStreams, 0, kString_AltStreams);; - CListStat stat = stat2.MainFiles; - stat.Update(stat2.AltStreams); - PrintSum(stat, 0, kString_Streams); + CListStat st = stat2.MainFiles; + st.Update(stat2.AltStreams); + PrintSum(st, 0, kString_Streams); } } @@ -757,12 +787,12 @@ static HRESULT GetItemMTime(IInArchive *archive, UInt32 index, CListFileTimeDef return S_OK; } -static void PrintPropNameAndNumber(const char *name, UInt64 val) +static void PrintPropNameAndNumber(CStdOutStream &so, const char *name, UInt64 val) { - g_StdOut << name << ": " << val << endl; + so << name << ": " << val << endl; } -static void PrintPropName_and_Eq(PROPID propID) +static void PrintPropName_and_Eq(CStdOutStream &so, PROPID propID) { const char *s; char temp[16]; @@ -773,28 +803,28 @@ static void PrintPropName_and_Eq(PROPID propID) ConvertUInt32ToString(propID, temp); s = temp; } - g_StdOut << s << " = "; + so << s << " = "; } -static void PrintPropNameAndNumber(PROPID propID, UInt64 val) +static void PrintPropNameAndNumber(CStdOutStream &so, PROPID propID, UInt64 val) { - PrintPropName_and_Eq(propID); - g_StdOut << val << endl; + PrintPropName_and_Eq(so, propID); + so << val << endl; } -static void PrintPropNameAndNumber_Signed(PROPID propID, Int64 val) +static void PrintPropNameAndNumber_Signed(CStdOutStream &so, PROPID propID, Int64 val) { - PrintPropName_and_Eq(propID); - g_StdOut << val << endl; + PrintPropName_and_Eq(so, propID); + so << val << endl; } -static void PrintPropPair(const char *name, const wchar_t *val) +static void PrintPropPair(CStdOutStream &so, const char *name, const wchar_t *val) { - g_StdOut << name << " = " << val << endl; + so << name << " = " << val << endl; } -static void PrintPropertyPair2(PROPID propID, const wchar_t *name, const CPropVariant &prop) +static void PrintPropertyPair2(CStdOutStream &so, PROPID propID, const wchar_t *name, const CPropVariant &prop) { UString s; ConvertPropertyToString(s, prop, propID); @@ -804,23 +834,23 @@ static void PrintPropertyPair2(PROPID propID, const wchar_t *name, const CPropVa UString nameU; GetPropName(propID, name, nameA, nameU); if (!nameA.IsEmpty()) - PrintPropPair(nameA, s); + PrintPropPair(so, nameA, s); else - g_StdOut << nameU << " = " << s << endl; + so << nameU << " = " << s << endl; } } -static HRESULT PrintArcProp(IInArchive *archive, PROPID propID, const wchar_t *name) +static HRESULT PrintArcProp(CStdOutStream &so, IInArchive *archive, PROPID propID, const wchar_t *name) { CPropVariant prop; RINOK(archive->GetArchiveProperty(propID, &prop)); - PrintPropertyPair2(propID, name, prop); + PrintPropertyPair2(so, propID, name, prop); return S_OK; } -static void PrintArcTypeError(const UString &type, bool isWarning) +static void PrintArcTypeError(CStdOutStream &so, const UString &type, bool isWarning) { - g_StdOut << "Open " << (isWarning ? "Warning" : "Error") + so << "Open " << (isWarning ? "WARNING" : "ERROR") << ": Can not open the file as [" << type << "] archive" @@ -829,25 +859,109 @@ static void PrintArcTypeError(const UString &type, bool isWarning) int Find_FileName_InSortedVector(const UStringVector &fileName, const UString& name); -AString GetOpenArcErrorMessage(UInt32 errorFlags); +void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags); -static void PrintErrorFlags(const char *s, UInt32 errorFlags) +static void ErrorInfo_Print(CStdOutStream &so, const CArcErrorInfo &er) { - g_StdOut << s << endl << GetOpenArcErrorMessage(errorFlags) << endl; + PrintErrorFlags(so, "ERRORS:", er.GetErrorFlags()); + if (!er.ErrorMessage.IsEmpty()) + PrintPropPair(so, "ERROR", er.ErrorMessage); + + PrintErrorFlags(so, "WARNINGS:", er.GetWarningFlags()); + if (!er.WarningMessage.IsEmpty()) + PrintPropPair(so, "WARNING", er.WarningMessage); } -static void ErrorInfo_Print(const CArcErrorInfo &er) +HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink) { - if (er.AreThereErrors()) - PrintErrorFlags("Errors:", er.GetErrorFlags()); - if (!er.ErrorMessage.IsEmpty()) - PrintPropPair("Error", er.ErrorMessage); - if (er.AreThereWarnings()) - PrintErrorFlags("Warnings:", er.GetWarningFlags()); - if (!er.WarningMessage.IsEmpty()) - PrintPropPair("Warning", er.WarningMessage); + FOR_VECTOR (r, arcLink.Arcs) + { + const CArc &arc = arcLink.Arcs[r]; + const CArcErrorInfo &er = arc.ErrorInfo; + + so << "--\n"; + PrintPropPair(so, "Path", arc.Path); + if (er.ErrorFormatIndex >= 0) + { + if (er.ErrorFormatIndex == arc.FormatIndex) + so << "Warning: The archive is open with offset" << endl; + else + PrintArcTypeError(so, codecs->GetFormatNamePtr(er.ErrorFormatIndex), true); + } + PrintPropPair(so, "Type", codecs->GetFormatNamePtr(arc.FormatIndex)); + + ErrorInfo_Print(so, er); + + Int64 offset = arc.GetGlobalOffset(); + if (offset != 0) + PrintPropNameAndNumber_Signed(so, kpidOffset, offset); + IInArchive *archive = arc.Archive; + RINOK(PrintArcProp(so, archive, kpidPhySize, NULL)); + if (er.TailSize != 0) + PrintPropNameAndNumber(so, kpidTailSize, er.TailSize); + UInt32 numProps; + RINOK(archive->GetNumberOfArchiveProperties(&numProps)); + + { + for (UInt32 j = 0; j < numProps; j++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE vt; + RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt)); + RINOK(PrintArcProp(so, archive, propID, name)); + } + } + + if (r != arcLink.Arcs.Size() - 1) + { + UInt32 numProps; + so << "----\n"; + if (archive->GetNumberOfProperties(&numProps) == S_OK) + { + UInt32 mainIndex = arcLink.Arcs[r + 1].SubfileIndex; + for (UInt32 j = 0; j < numProps; j++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE vt; + RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt)); + CPropVariant prop; + RINOK(archive->GetProperty(mainIndex, propID, &prop)); + PrintPropertyPair2(so, propID, name, prop); + } + } + } + } + return S_OK; +} + +HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink) +{ + #ifndef _NO_CRYPTO + if (arcLink.PasswordWasAsked) + so << "Can not open encrypted archive. Wrong password?"; + else + #endif + { + if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) + { + so << arcLink.NonOpen_ArcPath << endl; + PrintArcTypeError(so, codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false); + } + else + so << "Can not open the file as archive"; + } + + so << endl; + so << endl; + ErrorInfo_Print(so, arcLink.NonOpen_ErrorInfo); + + return S_OK; } +bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item); + HRESULT ListArchives(CCodecs *codecs, const CObjectVector<COpenType> &types, const CIntVector &excludedFormats, @@ -865,7 +979,7 @@ HRESULT ListArchives(CCodecs *codecs, UInt64 &numErrors, UInt64 &numWarnings) { - bool AllFilesAreAllowed = wildcardCensor.AreAllAllowed(); + bool allFilesAreAllowed = wildcardCensor.AreAllAllowed(); numErrors = 0; numWarnings = 0; @@ -874,7 +988,7 @@ HRESULT ListArchives(CCodecs *codecs, if (!techMode) fp.Init(kStandardFieldTable, ARRAY_SIZE(kStandardFieldTable)); - CListStat2 stat2; + CListStat2 stat2total; CBoolArr skipArcs(arcPaths.Size()); unsigned arcIndex; @@ -884,18 +998,34 @@ HRESULT ListArchives(CCodecs *codecs, UInt64 numArcs = 0; UInt64 totalArcSizes = 0; + HRESULT lastError = 0; + for (arcIndex = 0; arcIndex < arcPaths.Size(); arcIndex++) { if (skipArcs[arcIndex]) continue; - const UString &archiveName = arcPaths[arcIndex]; + const UString &arcPath = arcPaths[arcIndex]; UInt64 arcPackSize = 0; + if (!stdInMode) { NFile::NFind::CFileInfo fi; - if (!fi.Find(us2fs(archiveName)) || fi.IsDir()) + if (!fi.Find(us2fs(arcPath))) { - g_StdOut << endl << "Error: " << archiveName << " is not file" << endl; + DWORD errorCode = GetLastError(); + if (errorCode == 0) + errorCode = ERROR_FILE_NOT_FOUND; + lastError = HRESULT_FROM_WIN32(lastError);; + g_StdOut.Flush(); + *g_ErrStream << endl << kError << NError::MyFormatMessage(errorCode) << + endl << arcPath << endl << endl; + numErrors++; + continue; + } + if (fi.IsDir()) + { + g_StdOut.Flush(); + *g_ErrStream << endl << kError << arcPath << " is not a file" << endl << endl; numErrors++; continue; } @@ -906,7 +1036,7 @@ HRESULT ListArchives(CCodecs *codecs, CArchiveLink arcLink; COpenCallbackConsole openCallback; - openCallback.OutStream = &g_StdOut; + openCallback.Init(&g_StdOut, g_ErrStream, NULL); #ifndef _NO_CRYPTO @@ -930,40 +1060,39 @@ HRESULT ListArchives(CCodecs *codecs, options.excludedFormats = &excludedFormats; options.stdInMode = stdInMode; options.stream = NULL; - options.filePath = archiveName; - HRESULT result = arcLink.Open2(options, &openCallback); + options.filePath = arcPath; + + if (enableHeaders) + { + g_StdOut << endl << kListing << arcPath << endl << endl; + } + + HRESULT result = arcLink.Open3(options, &openCallback); if (result != S_OK) { if (result == E_ABORT) return result; - g_StdOut << endl << "Error: " << archiveName << ": "; + g_StdOut.Flush(); + *g_ErrStream << endl << kError << arcPath << " : "; if (result == S_FALSE) { - #ifndef _NO_CRYPTO - if (openCallback.Open_WasPasswordAsked()) - g_StdOut << "Can not open encrypted archive. Wrong password?"; - else - #endif - { - if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) - { - PrintArcTypeError(codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false); - } - else - g_StdOut << "Can not open the file as archive"; - } - g_StdOut << endl; - ErrorInfo_Print(arcLink.NonOpen_ErrorInfo); + Print_OpenArchive_Error(*g_ErrStream, codecs, arcLink); } - else if (result == E_OUTOFMEMORY) - g_StdOut << "Can't allocate required memory"; else - g_StdOut << NError::MyFormatMessage(result); - g_StdOut << endl; + { + lastError = result; + *g_ErrStream << "opening : "; + if (result == E_OUTOFMEMORY) + *g_ErrStream << "Can't allocate required memory"; + else + *g_ErrStream << NError::MyFormatMessage(result); + } + *g_ErrStream << endl; numErrors++; continue; } + { if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) numErrors++; @@ -998,72 +1127,15 @@ HRESULT ListArchives(CCodecs *codecs, { int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]); if (index >= 0 && (unsigned)index > arcIndex) - skipArcs[index] = true; + skipArcs[(unsigned)index] = true; } } if (enableHeaders) { - g_StdOut << endl << kListing << archiveName << endl << endl; + RINOK(Print_OpenArchive_Props(g_StdOut, codecs, arcLink)); - FOR_VECTOR (r, arcLink.Arcs) - { - const CArc &arc = arcLink.Arcs[r]; - const CArcErrorInfo &er = arc.ErrorInfo; - - g_StdOut << "--\n"; - PrintPropPair("Path", arc.Path); - if (er.ErrorFormatIndex >= 0) - { - if (er.ErrorFormatIndex == arc.FormatIndex) - g_StdOut << "Warning: The archive is open with offset" << endl; - else - PrintArcTypeError(codecs->GetFormatNamePtr(er.ErrorFormatIndex), true); - } - PrintPropPair("Type", codecs->GetFormatNamePtr(arc.FormatIndex)); - - ErrorInfo_Print(er); - - Int64 offset = arc.GetGlobalOffset(); - if (offset != 0) - PrintPropNameAndNumber_Signed(kpidOffset, offset); - IInArchive *archive = arc.Archive; - RINOK(PrintArcProp(archive, kpidPhySize, NULL)); - if (er.TailSize != 0) - PrintPropNameAndNumber(kpidTailSize, er.TailSize); - UInt32 numProps; - RINOK(archive->GetNumberOfArchiveProperties(&numProps)); - { - for (UInt32 j = 0; j < numProps; j++) - { - CMyComBSTR name; - PROPID propID; - VARTYPE vt; - RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt)); - RINOK(PrintArcProp(archive, propID, name)); - } - } - if (r != arcLink.Arcs.Size() - 1) - { - UInt32 numProps; - g_StdOut << "----\n"; - if (archive->GetNumberOfProperties(&numProps) == S_OK) - { - UInt32 mainIndex = arcLink.Arcs[r + 1].SubfileIndex; - for (UInt32 j = 0; j < numProps; j++) - { - CMyComBSTR name; - PROPID propID; - VARTYPE vt; - RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt)); - CPropVariant prop; - RINOK(archive->GetProperty(mainIndex, propID, &prop)); - PrintPropertyPair2(propID, name, prop); - } - } - } - } g_StdOut << endl; if (techMode) g_StdOut << "----------\n"; @@ -1091,10 +1163,14 @@ HRESULT ListArchives(CCodecs *codecs, } } - CListStat2 stat; + CListStat2 stat2; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); + + CReadArcItem item; + UStringVector pathParts; + for (UInt32 i = 0; i < numItems; i++) { if (NConsoleClose::TestBreakSignal()) @@ -1122,12 +1198,25 @@ HRESULT ListArchives(CCodecs *codecs, continue; } - RINOK(Archive_IsItem_Folder(archive, i, fp.IsFolder)); + RINOK(Archive_IsItem_Dir(archive, i, fp.IsDir)); - if (!AllFilesAreAllowed) + if (!allFilesAreAllowed) { - if (!wildcardCensor.CheckPath(isAltStream, fp.FilePath, !fp.IsFolder)) - continue; + if (isAltStream) + { + RINOK(arc.GetItem(i, item)); + if (!CensorNode_CheckPath(wildcardCensor, item)) + continue; + } + else + { + SplitPathToParts(fp.FilePath, pathParts);; + bool include; + if (!wildcardCensor.CheckPathVect(pathParts, !fp.IsDir, include)) + continue; + if (!include) + continue; + } } CListStat st; @@ -1136,33 +1225,35 @@ HRESULT ListArchives(CCodecs *codecs, RINOK(GetUInt64Value(archive, i, kpidPackSize, st.PackSize)); RINOK(GetItemMTime(archive, i, st.MTime)); - if (fp.IsFolder) - stat.NumDirs++; + if (fp.IsDir) + stat2.NumDirs++; else st.NumFiles = 1; - stat.GetStat(isAltStream).Update(st); + stat2.GetStat(isAltStream).Update(st); if (isAltStream && !showAltStreams) continue; RINOK(fp.PrintItemInfo(i, st)); } - UInt64 numStreams = stat.GetNumStreams(); + UInt64 numStreams = stat2.GetNumStreams(); if (!stdInMode - && !stat.MainFiles.PackSize.Def - && !stat.AltStreams.PackSize.Def) + && !stat2.MainFiles.PackSize.Def + && !stat2.AltStreams.PackSize.Def) { if (arcLink.VolumePaths.Size() != 0) arcPackSize += arcLink.VolumesSize; - stat.MainFiles.PackSize.Add((numStreams == 0) ? 0 : arcPackSize); + stat2.MainFiles.PackSize.Add((numStreams == 0) ? 0 : arcPackSize); } - stat.MainFiles.SetSizeDefIfNoFiles(); - stat.AltStreams.SetSizeDefIfNoFiles(); + + stat2.MainFiles.SetSizeDefIfNoFiles(); + stat2.AltStreams.SetSizeDefIfNoFiles(); + if (enableHeaders && !techMode) { fp.PrintTitleLines(); g_StdOut << endl; - fp.PrintSum(stat); + fp.PrintSum(stat2); } if (enableHeaders) @@ -1170,23 +1261,30 @@ HRESULT ListArchives(CCodecs *codecs, if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) { g_StdOut << "----------\n"; - PrintPropPair("Path", arcLink.NonOpen_ArcPath); - PrintArcTypeError(codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false); + PrintPropPair(g_StdOut, "Path", arcLink.NonOpen_ArcPath); + PrintArcTypeError(g_StdOut, codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false); } } - stat2.Update(stat); - fflush(stdout); + + stat2total.Update(stat2); + + g_StdOut.Flush(); } + if (enableHeaders && !techMode && (arcPaths.Size() > 1 || numVolumes > 1)) { g_StdOut << endl; fp.PrintTitleLines(); g_StdOut << endl; - fp.PrintSum(stat2); + fp.PrintSum(stat2total); g_StdOut << endl; - PrintPropNameAndNumber("Archives", numArcs); - PrintPropNameAndNumber("Volumes", numVolumes); - PrintPropNameAndNumber("Total archives size", totalArcSizes); + PrintPropNameAndNumber(g_StdOut, "Archives", numArcs); + PrintPropNameAndNumber(g_StdOut, "Volumes", numVolumes); + PrintPropNameAndNumber(g_StdOut, "Total archives size", totalArcSizes); } + + if (numErrors == 1 && lastError != 0) + return lastError; + return S_OK; } diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp index 2f56fecb..83e6ef5b 100644 --- a/CPP/7zip/UI/Console/Main.cpp +++ b/CPP/7zip/UI/Console/Main.cpp @@ -4,6 +4,8 @@ #include <Psapi.h> +#include "../../../../C/CpuArch.h" + #if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES) #include "../../../../C/Alloc.h" #endif @@ -15,25 +17,26 @@ #include "../../../Common/MyException.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" +#include "../../../Common/UTFConvert.h" #include "../../../Windows/ErrorMsg.h" + #ifdef _WIN32 #include "../../../Windows/MemoryLock.h" #endif -#ifndef _7ZIP_ST -#include "../../../Windows/Synchronization.h" -#endif - #include "../../../Windows/TimeUtils.h" #include "../Common/ArchiveCommandLine.h" #include "../Common/ExitCode.h" #include "../Common/Extract.h" + #ifdef EXTERNAL_CODECS #include "../Common/LoadCodecs.h" #endif +#include "../../Common/RegisterCodec.h" + #include "BenchCon.h" #include "ConsoleClose.h" #include "ExtractCallbackConsole.h" @@ -56,7 +59,15 @@ using namespace NCommandLineParser; #ifdef _WIN32 HINSTANCE g_hInstance = 0; #endif + extern CStdOutStream *g_StdStream; +extern CStdOutStream *g_ErrStream; + +extern unsigned g_NumCodecs; +extern const CCodecInfo *g_Codecs[]; + +extern unsigned g_NumHashers; +extern const CHasherInfo *g_Hashers[]; static const char *kCopyrightString = "\n7-Zip" #ifndef EXTERNAL_CODECS @@ -67,14 +78,16 @@ static const char *kCopyrightString = "\n7-Zip" #endif #endif -#ifdef _WIN64 +#ifdef MY_CPU_64BIT " [64]" +#elif defined MY_CPU_32BIT +" [32]" #endif -" " MY_VERSION_COPYRIGHT_DATE "\n"; +" " MY_VERSION_COPYRIGHT_DATE "\n\n"; static const char *kHelpString = - "\nUsage: 7z" + "Usage: 7z" #ifndef EXTERNAL_CODECS #ifdef PROG_VARIANT_R "r" @@ -91,6 +104,7 @@ static const char *kHelpString = " d : Delete files from archive\n" " e : Extract files from archive (without using directory names)\n" " h : Calculate hash values for files\n" + " i : Show information about supported formats\n" " l : List contents of archive\n" // " l[a|t][f] : List contents of archive\n" // " a - with Additional fields\n" @@ -113,6 +127,7 @@ static const char *kHelpString = #endif " -r[-|0] : Recurse subdirectories\n" " -scs{UTF-8|UTF-16LE|UTF-16BE|WIN|DOS|{id}} : set charset for list files\n" + " -sdel : Delete files after compression\n" " -sfx[{name}] : Create SFX archive\n" " -si[{name}] : read data from stdin\n" " -slt : show technical information for l (List) command\n" @@ -137,9 +152,10 @@ static const char *kUnsupportedArcTypeMessage = "Unsupported archive type"; static CFSTR kDefaultSfxModule = FTEXT("7zCon.sfx"); -static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code) +static void ShowMessageAndThrowException(LPCSTR message, NExitCode::EEnum code) { - s << endl << "Error: " << message << endl; + if (g_ErrStream) + *g_ErrStream << endl << "ERROR: " << message << endl; throw code; } @@ -155,48 +171,47 @@ static void GetArguments(int numArgs, const char *args[], UStringVector &parts) } #endif -static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp) +static void ShowCopyrightAndHelp(CStdOutStream *so, bool needHelp) { - s << kCopyrightString; - // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\n"; + if (!so) + return; + *so << kCopyrightString; + // *so << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << endl; if (needHelp) - s << kHelpString; + *so << kHelpString; } -#ifdef EXTERNAL_CODECS -static void PrintString(CStdOutStream &stdStream, const AString &s, int size) +static void PrintStringRight(CStdOutStream &so, const AString &s, unsigned size) { - int len = s.Len(); - for (int i = len; i < size; i++) - stdStream << ' '; - stdStream << s; + unsigned len = s.Len(); + for (unsigned i = len; i < size; i++) + so << ' '; + so << s; } -static void PrintUInt32(CStdOutStream &stdStream, UInt32 val, int size) +static void PrintUInt32(CStdOutStream &so, UInt32 val, unsigned size) { char s[16]; ConvertUInt32ToString(val, s); - PrintString(stdStream, s, size); + PrintStringRight(so, s, size); } -static void PrintLibIndex(CStdOutStream &stdStream, int libIndex) +static void PrintLibIndex(CStdOutStream &so, int libIndex) { if (libIndex >= 0) - PrintUInt32(stdStream, libIndex, 2); + PrintUInt32(so, libIndex, 2); else - stdStream << " "; - stdStream << ' '; + so << " "; + so << ' '; } -#endif - -static void PrintString(CStdOutStream &stdStream, const UString &s, int size) +static void PrintString(CStdOutStream &so, const UString &s, unsigned size) { - int len = s.Len(); - stdStream << s; - for (int i = len; i < size; i++) - stdStream << ' '; + unsigned len = s.Len(); + so << s; + for (unsigned i = len; i < size; i++) + so << ' '; } static inline char GetHex(unsigned val) @@ -204,82 +219,78 @@ static inline char GetHex(unsigned val) return (char)((val < 10) ? ('0' + val) : ('A' + (val - 10))); } +static void PrintWarningsPaths(const CErrorPathCodes &pc, CStdOutStream &so) +{ + FOR_VECTOR(i, pc.Paths) + { + so << pc.Paths[i] << " : "; + so << NError::MyFormatMessage(pc.Codes[i]) << endl; + } + so << "----------------" << endl; +} + static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback, - const CErrorInfo &errorInfo, CStdOutStream &stdStream) + const CUpdateErrorInfo &errorInfo, CStdOutStream &so, bool showHeaders) { int exitCode = NExitCode::kSuccess; - if (callback.CantFindFiles.Size() > 0) + if (callback.ScanErrors.Paths.Size() != 0) { - stdStream << endl; - stdStream << "WARNINGS for files:" << endl << endl; - unsigned numErrors = callback.CantFindFiles.Size(); - for (unsigned i = 0; i < numErrors; i++) - { - stdStream << callback.CantFindFiles[i] << " : "; - stdStream << NError::MyFormatMessage(callback.CantFindCodes[i]) << endl; - } - stdStream << "----------------" << endl; - stdStream << "WARNING: Cannot find " << numErrors << " file"; - if (numErrors > 1) - stdStream << "s"; - stdStream << endl; + so << endl; + so << "Scan WARNINGS for files and folders:" << endl << endl; + PrintWarningsPaths(callback.ScanErrors, so); + so << "Scan WARNINGS: " << callback.ScanErrors.Paths.Size(); + so << endl; exitCode = NExitCode::kWarning; } - if (result != S_OK) + if (result != S_OK || errorInfo.ThereIsError()) { UString message; if (!errorInfo.Message.IsEmpty()) { - message += errorInfo.Message; - message += L"\n"; + message.AddAscii(errorInfo.Message); + message.Add_LF(); } - if (!errorInfo.FileName.IsEmpty()) { - message += fs2us(errorInfo.FileName); - message += L"\n"; - } - if (!errorInfo.FileName2.IsEmpty()) - { - message += fs2us(errorInfo.FileName2); - message += L"\n"; + FOR_VECTOR(i, errorInfo.FileNames) + { + message += fs2us(errorInfo.FileNames[i]); + message.Add_LF(); + } } if (errorInfo.SystemError != 0) { message += NError::MyFormatMessage(errorInfo.SystemError); - message += L"\n"; + message.Add_LF(); } if (!message.IsEmpty()) - stdStream << L"\nError:\n" << message; + so << L"\nError:\n" << message; // we will work with (result) later // throw CSystemException(result); return NExitCode::kFatalError; } - unsigned numErrors = callback.FailedFiles.Size(); + unsigned numErrors = callback.FailedFiles.Paths.Size(); if (numErrors == 0) { - if (callback.CantFindFiles.Size() == 0) - stdStream << kEverythingIsOk << endl; + if (showHeaders) + if (callback.ScanErrors.Paths.Size() == 0) + so << kEverythingIsOk << endl; } else { - stdStream << endl; - stdStream << "WARNINGS for files:" << endl << endl; - for (unsigned i = 0; i < numErrors; i++) - { - stdStream << callback.FailedFiles[i] << " : "; - stdStream << NError::MyFormatMessage(callback.FailedCodes[i]) << endl; - } - stdStream << "----------------" << endl; - stdStream << "WARNING: Cannot open " << numErrors << " file"; + so << endl; + so << "WARNINGS for files:" << endl << endl; + PrintWarningsPaths(callback.FailedFiles, so); + so << "WARNING: Cannot open " << numErrors << " file"; if (numErrors > 1) - stdStream << "s"; - stdStream << endl; + so << 's'; + so << endl; exitCode = NExitCode::kWarning; } + return exitCode; } @@ -413,6 +424,13 @@ static void PrintStat() *g_StdStream << endl; } +static void PrintHexId(CStdOutStream &so, UInt64 id) +{ + char s[32]; + ConvertUInt64ToHex(id, s); + PrintStringRight(so, s, 8); +} + int Main2( #ifndef _WIN32 int numArgs, const char *args[] @@ -424,6 +442,7 @@ int Main2( #endif UStringVector commandStrings; + #ifdef _WIN32 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #else @@ -432,7 +451,7 @@ int Main2( if (commandStrings.Size() == 1) { - ShowCopyrightAndHelp(g_StdOut, true); + ShowCopyrightAndHelp(g_StdStream, true); return 0; } @@ -444,15 +463,30 @@ int Main2( parser.Parse1(commandStrings, options); + + if (options.Number_for_Out != k_OutStream_stdout) + g_StdStream = (options.Number_for_Out == k_OutStream_stderr ? &g_StdErr : NULL); + + if (options.Number_for_Errors != k_OutStream_stderr) + g_ErrStream = (options.Number_for_Errors == k_OutStream_stdout ? &g_StdOut : NULL); + + 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_StdOut, true); + ShowCopyrightAndHelp(g_StdStream, true); return 0; } #if defined(_WIN32) && !defined(UNDER_CE) NSecurity::EnablePrivilege_SymLink(); #endif + #ifdef _7ZIP_LARGE_PAGES if (options.LargePages) { @@ -463,22 +497,38 @@ int Main2( } #endif - CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut; - g_StdStream = &stdStream; - if (options.EnableHeaders) - ShowCopyrightAndHelp(stdStream, false); + ShowCopyrightAndHelp(g_StdStream, false); parser.Parse2(options); - CCodecs *codecs = new CCodecs; - #ifdef EXTERNAL_CODECS - CExternalCodecs __externalCodecs; - __externalCodecs.GetCodecs = codecs; - __externalCodecs.GetHashers = codecs; - #else - CMyComPtr<IUnknown> compressCodecsInfo = codecs; - #endif + unsigned percentsNameLevel = 1; + if (options.LogLevel == 0 || options.Number_for_Percents != options.Number_for_Out) + percentsNameLevel = 2; + + unsigned consoleWidth = 80; + + if (percentsStream) + { + #ifdef _WIN32 + + #if !defined(UNDER_CE) + CONSOLE_SCREEN_BUFFER_INFO consoleInfo; + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo)) + consoleWidth = consoleInfo.dwSize.X; + #endif + + #else + + struct winsize w; + if (ioctl(0, TIOCGWINSZ, &w) == ) + consoleWidth = w.ws_col; + + #endif + } + + CREATE_CODECS_OBJECT + codecs->CaseSensitiveChange = options.CaseSensitiveChange; codecs->CaseSensitive = options.CaseSensitive; ThrowException_if_Error(codecs->Load()); @@ -489,7 +539,18 @@ int Main2( (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList || options.Command.IsFromUpdateGroup())) + { + #ifdef EXTERNAL_CODECS + if (!codecs->MainDll_ErrorPath.IsEmpty()) + { + UString s = L"Can't load module "; + s += fs2us(codecs->MainDll_ErrorPath); + throw s; + } + #endif + throw kNoFormats; + } CObjectVector<COpenType> types; if (!ParseOpenTypes(*codecs, options.ArcType, types)) @@ -511,16 +572,19 @@ int Main2( if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kHash || options.Command.CommandType == NCommandType::kBenchmark) - ThrowException_if_Error(__externalCodecs.LoadCodecs()); + ThrowException_if_Error(__externalCodecs.Load()); #endif int retCode = NExitCode::kSuccess; HRESULT hresultMain = S_OK; - bool showStat = true; + // bool showStat = options.ShowTime; + + /* if (!options.EnableHeaders || options.TechMode) showStat = false; + */ if (options.Command.CommandType == NCommandType::kInfo) @@ -528,15 +592,15 @@ int Main2( unsigned i; #ifdef EXTERNAL_CODECS - stdStream << endl << "Libs:" << endl; + so << endl << "Libs:" << endl; for (i = 0; i < codecs->Libs.Size(); i++) { - PrintLibIndex(stdStream, i); - stdStream << ' ' << codecs->Libs[i].Path << endl; + PrintLibIndex(so, i); + so << ' ' << codecs->Libs[i].Path << endl; } #endif - stdStream << endl << "Formats:" << endl; + so << endl << "Formats:" << endl; const char *kArcFlags = "KSNFMGOPBELH"; const unsigned kNumArcFlags = (unsigned)strlen(kArcFlags); @@ -544,26 +608,30 @@ int Main2( for (i = 0; i < codecs->Formats.Size(); i++) { const CArcInfoEx &arc = codecs->Formats[i]; + #ifdef EXTERNAL_CODECS - PrintLibIndex(stdStream, arc.LibIndex); + PrintLibIndex(so, arc.LibIndex); #else - stdStream << " "; + so << " "; #endif - stdStream << (char)(arc.UpdateEnabled ? 'C' : ' '); + + so << (char)(arc.UpdateEnabled ? 'C' : ' '); + for (unsigned b = 0; b < kNumArcFlags; b++) { - stdStream << (char) + so << (char) ((arc.Flags & ((UInt32)1 << b)) != 0 ? kArcFlags[b] : ' '); } - stdStream << ' '; - PrintString(stdStream, arc.Name, 8); - stdStream << ' '; + so << ' '; + PrintString(so, arc.Name, 8); + so << ' '; UString s; + FOR_VECTOR (t, arc.Exts) { if (t != 0) - s += L' '; + s.Add_Space(); const CArcExtInfo &ext = arc.Exts[t]; s += ext.Ext; if (!ext.AddExt.IsEmpty()) @@ -573,68 +641,112 @@ int Main2( s += L')'; } } - PrintString(stdStream, s, 13); - stdStream << ' '; + + PrintString(so, s, 13); + so << ' '; + if (arc.SignatureOffset != 0) - stdStream << "offset=" << arc.SignatureOffset << ' '; + so << "offset=" << arc.SignatureOffset << ' '; FOR_VECTOR(si, arc.Signatures) { if (si != 0) - stdStream << " || "; + so << " || "; const CByteBuffer &sig = arc.Signatures[si]; for (size_t j = 0; j < sig.Size(); j++) { if (j != 0) - stdStream << ' '; + so << ' '; Byte b = sig[j]; if (b > 0x20 && b < 0x80) { - stdStream << (char)b; + so << (char)b; } else { - stdStream << GetHex((b >> 4) & 0xF); - stdStream << GetHex(b & 0xF); + so << GetHex((b >> 4) & 0xF); + so << GetHex(b & 0xF); } } } - stdStream << endl; + so << endl; + } + + so << endl << "Codecs:" << endl; // << "Lib ID Name" << endl; + + for (i = 0; i < g_NumCodecs; i++) + { + const CCodecInfo &cod = *g_Codecs[i]; + + PrintLibIndex(so, -1); + + if (cod.NumStreams == 1) + so << ' '; + else + so << cod.NumStreams; + + so << (char)(cod.CreateEncoder ? 'E' : ' '); + so << (char)(cod.CreateDecoder ? 'D' : ' '); + + so << ' '; + PrintHexId(so, cod.Id); + so << ' ' << cod.Name << endl; } + #ifdef EXTERNAL_CODECS - stdStream << endl << "Codecs:" << endl << "Lib ID Name" << endl; UInt32 numMethods; - if (codecs->GetNumberOfMethods(&numMethods) == S_OK) + if (codecs->GetNumMethods(&numMethods) == S_OK) for (UInt32 j = 0; j < numMethods; j++) { - PrintLibIndex(stdStream, codecs->GetCodecLibIndex(j)); - stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' '); + PrintLibIndex(so, codecs->GetCodec_LibIndex(j)); + + UInt32 numStreams = codecs->GetCodec_NumStreams(j); + if (numStreams == 1) + so << ' '; + else + so << numStreams; + + so << (char)(codecs->GetCodec_EncoderIsAssigned(j) ? 'E' : ' '); + so << (char)(codecs->GetCodec_DecoderIsAssigned(j) ? 'D' : ' '); + + so << ' '; UInt64 id; - stdStream << " "; - HRESULT res = codecs->GetCodecId(j, id); + HRESULT res = codecs->GetCodec_Id(j, id); if (res != S_OK) id = (UInt64)(Int64)-1; - char s[32]; - ConvertUInt64ToHex(id, s); - PrintString(stdStream, s, 8); - stdStream << " " << codecs->GetCodecName(j) << endl; + PrintHexId(so, id); + so << ' ' << codecs->GetCodec_Name(j) << endl; + } + + #endif + + + so << endl << "Hashers:" << endl; // << " L Size ID Name" << endl; + + for (i = 0; i < g_NumHashers; i++) + { + const CHasherInfo &codec = *g_Hashers[i]; + PrintLibIndex(so, -1); + PrintUInt32(so, codec.DigestSize, 4); + so << ' '; + PrintHexId(so, codec.Id); + so << ' ' << codec.Name << endl; } + + #ifdef EXTERNAL_CODECS - stdStream << endl << "Hashers:" << endl << " L Size ID Name" << endl; numMethods = codecs->GetNumHashers(); for (UInt32 j = 0; j < numMethods; j++) { - PrintLibIndex(stdStream, codecs->GetHasherLibIndex(j)); - PrintUInt32(stdStream, codecs->GetHasherDigestSize(j), 4); - stdStream << ' '; - char s[32]; - ConvertUInt64ToHex(codecs->GetHasherId(j), s); - PrintString(stdStream, s, 6); - stdStream << " " << codecs->GetHasherName(j) << endl; + PrintLibIndex(so, codecs->GetHasherLibIndex(j)); + PrintUInt32(so, codecs->GetHasherDigestSize(j), 4); + so << ' '; + PrintHexId(so, codecs->GetHasherId(j)); + so << ' ' << codecs->GetHasherName(j) << endl; } #endif @@ -642,41 +754,102 @@ int Main2( } else if (options.Command.CommandType == NCommandType::kBenchmark) { - hresultMain = BenchCon(EXTERNAL_CODECS_VARS - options.Properties, options.NumIterations, (FILE *)stdStream); + hresultMain = BenchCon(EXTERNAL_CODECS_VARS_L + options.Properties, options.NumIterations, (FILE *)so); if (hresultMain == S_FALSE) { - stdStream << "\nDecoding Error\n"; + if (g_ErrStream) + *g_ErrStream << "\nDecoding ERROR\n"; retCode = NExitCode::kFatalError; hresultMain = S_OK; } } else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { + UStringVector ArchivePathsSorted; + UStringVector ArchivePathsFullSorted; + + if (options.StdInMode) + { + ArchivePathsSorted.Add(options.ArcName_for_StdInMode); + ArchivePathsFullSorted.Add(options.ArcName_for_StdInMode); + } + else + { + CExtractScanConsole scan; + + scan.Init(options.EnableHeaders ? g_StdStream : NULL, g_ErrStream, percentsStream); + scan.SetWindowWidth(consoleWidth); + + if (g_StdStream && options.EnableHeaders) + *g_StdStream << "Scanning the drive for archives:" << endl; + + CDirItemsStat st; + + scan.StartScanning(); + + hresultMain = EnumerateDirItemsAndSort( + options.arcCensor, + NWildcard::k_RelatPath, + UString(), // addPathPrefix + ArchivePathsSorted, + ArchivePathsFullSorted, + st, + &scan); + + scan.CloseScanning(); + + if (hresultMain == S_OK) + { + if (options.EnableHeaders) + scan.PrintStat(st); + } + else + { + /* + if (res != E_ABORT) + { + throw CSystemException(res); + // errorInfo.Message = "Scanning error"; + } + return res; + */ + } + } + + if (hresultMain == S_OK) if (isExtractGroupCommand) { CExtractCallbackConsole *ecs = new CExtractCallbackConsole; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; - ecs->OutStream = &stdStream; - #ifndef _NO_CRYPTO ecs->PasswordIsDefined = options.PasswordEnabled; ecs->Password = options.Password; #endif - ecs->Init(); + ecs->Init(g_StdStream, g_ErrStream, percentsStream); + ecs->MutiArcMode = (ArchivePathsSorted.Size() > 1); + + ecs->LogLevel = options.LogLevel; + ecs->PercentsNameLevel = percentsNameLevel; + + if (percentsStream) + ecs->SetWindowWidth(consoleWidth); + /* COpenCallbackConsole openCallback; - openCallback.OutStream = &stdStream; + openCallback.Init(g_StdStream, g_ErrStream); #ifndef _NO_CRYPTO openCallback.PasswordIsDefined = options.PasswordEnabled; openCallback.Password = options.Password; #endif + */ CExtractOptions eo; (CExtractOptionsBase &)eo = options.ExtractOptions; + eo.StdInMode = options.StdInMode; eo.StdOutMode = options.StdOutMode; eo.YesToAll = options.YesToAll; @@ -694,58 +867,63 @@ int Main2( if (!options.HashMethods.IsEmpty()) { hashCalc = &hb; - ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS options.HashMethods)); + ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS_L options.HashMethods)); hb.Init(); } + hresultMain = Extract( codecs, types, excludedFormats, - options.ArchivePathsSorted, - options.ArchivePathsFullSorted, + ArchivePathsSorted, + ArchivePathsFullSorted, options.Censor.Pairs.Front().Head, - eo, &openCallback, ecs, hashCalc, errorMessage, stat); + eo, ecs, ecs, hashCalc, errorMessage, stat); + + ecs->ClosePercents(); + if (!errorMessage.IsEmpty()) { - stdStream << endl << "Error: " << errorMessage; + if (g_ErrStream) + *g_ErrStream << endl << "ERROR:" << endl << errorMessage << endl; if (hresultMain == S_OK) hresultMain = E_FAIL; } - stdStream << endl; + so << endl; if (ecs->NumTryArcs > 1) { - stdStream << "Archives: " << ecs->NumTryArcs << endl; - stdStream << "OK archives: " << ecs->NumOkArcs << endl; + so << "Archives: " << ecs->NumTryArcs << endl; + so << "OK archives: " << ecs->NumOkArcs << endl; } bool isError = false; if (ecs->NumCantOpenArcs != 0) { isError = true; - stdStream << "Can't open as archive: " << ecs->NumCantOpenArcs << endl; + so << "Can't open as archive: " << ecs->NumCantOpenArcs << endl; } if (ecs->NumArcsWithError != 0) { isError = true; - stdStream << "Archives with Errors: " << ecs->NumArcsWithError << endl; + so << "Archives with Errors: " << ecs->NumArcsWithError << endl; } if (ecs->NumArcsWithWarnings != 0) - stdStream << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl; + so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl; if (ecs->NumOpenArcWarnings != 0) { - stdStream << endl; + so << endl; if (ecs->NumOpenArcWarnings != 0) - stdStream << "Warnings: " << ecs->NumOpenArcWarnings << endl; + so << "Warnings: " << ecs->NumOpenArcWarnings << endl; } if (ecs->NumOpenArcErrors != 0) { isError = true; - stdStream << endl; + so << endl; if (ecs->NumOpenArcErrors != 0) - stdStream << "Open Errors: " << ecs->NumOpenArcErrors << endl; + so << "Open Errors: " << ecs->NumOpenArcErrors << endl; } if (isError) @@ -755,29 +933,31 @@ int Main2( { // if (ecs->NumArchives > 1) { - stdStream << endl; + so << endl; if (ecs->NumFileErrors != 0) - stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl; + so << "Sub items Errors: " << ecs->NumFileErrors << endl; } } else if (hresultMain == S_OK) { - - if (stat.NumFolders != 0) - stdStream << "Folders: " << stat.NumFolders << endl; - if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0) - stdStream << "Files: " << stat.NumFiles << endl; - if (stat.NumAltStreams != 0) - { - stdStream << "Alternate Streams: " << stat.NumAltStreams << endl; - stdStream << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl; - } - - stdStream - << "Size: " << stat.UnpackSize << endl - << "Compressed: " << stat.PackSize << endl; - if (hashCalc) - PrintHashStat(stdStream, hb); + if (stat.NumFolders != 0) + so << "Folders: " << stat.NumFolders << endl; + if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0) + so << "Files: " << stat.NumFiles << endl; + if (stat.NumAltStreams != 0) + { + so << "Alternate Streams: " << stat.NumAltStreams << endl; + so << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl; + } + + so + << "Size: " << stat.UnpackSize << endl + << "Compressed: " << stat.PackSize << endl; + if (hashCalc) + { + so << endl; + PrintHashStat(so, hb); + } } } else @@ -792,8 +972,8 @@ int Main2( types, excludedFormats, options.StdInMode, - options.ArchivePathsSorted, - options.ArchivePathsFullSorted, + ArchivePathsSorted, + ArchivePathsFullSorted, options.ExtractOptions.NtOptions.AltStreams.Val, options.AltStreams.Val, // we don't want to show AltStreams by default options.Censor.Pairs.Front().Head, @@ -806,9 +986,10 @@ int Main2( &options.Properties, numErrors, numWarnings); - if (options.EnableHeaders) - if (numWarnings > 0) - g_StdOut << endl << "Warnings: " << numWarnings << endl; + if (options.EnableHeaders) + if (numWarnings > 0) + g_StdOut << endl << "Warnings: " << numWarnings << endl; + if (numErrors > 0) { if (options.EnableHeaders) @@ -824,25 +1005,32 @@ int Main2( uo.SfxModule = kDefaultSfxModule; COpenCallbackConsole openCallback; - openCallback.OutStream = &stdStream; + openCallback.Init(g_StdStream, g_ErrStream, percentsStream); #ifndef _NO_CRYPTO bool passwordIsDefined = - options.PasswordEnabled && !options.Password.IsEmpty(); + (options.PasswordEnabled && !options.Password.IsEmpty()); openCallback.PasswordIsDefined = passwordIsDefined; openCallback.Password = options.Password; #endif CUpdateCallbackConsole callback; - callback.EnablePercents = options.EnablePercents; + callback.LogLevel = options.LogLevel; + callback.PercentsNameLevel = percentsNameLevel; + + if (percentsStream) + callback.SetWindowWidth(consoleWidth); #ifndef _NO_CRYPTO callback.PasswordIsDefined = passwordIsDefined; - callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty(); + callback.AskPassword = (options.PasswordEnabled && options.Password.IsEmpty()); callback.Password = options.Password; #endif + callback.StdOutMode = uo.StdOutMode; - callback.Init(&stdStream); + callback.Init( + // NULL, + g_StdStream, g_ErrStream, percentsStream); CUpdateErrorInfo errorInfo; @@ -856,29 +1044,36 @@ int Main2( options.Censor, uo, errorInfo, &openCallback, &callback, true); - retCode = WarningsCheck(hresultMain, callback, errorInfo, stdStream); + + callback.ClosePercents2(); + + retCode = WarningsCheck(hresultMain, callback, errorInfo, so, + // options.EnableHeaders + true); } else if (options.Command.CommandType == NCommandType::kHash) { const CHashOptions &uo = options.HashOptions; CHashCallbackConsole callback; - callback.EnablePercents = options.EnablePercents; - - callback.Init(&stdStream); + if (percentsStream) + callback.SetWindowWidth(consoleWidth); + + callback.Init(g_StdStream, g_ErrStream, percentsStream); + callback.PrintHeaders = options.EnableHeaders; - UString errorInfoString; - hresultMain = HashCalc(EXTERNAL_CODECS_VARS + AString errorInfoString; + hresultMain = HashCalc(EXTERNAL_CODECS_VARS_L options.Censor, uo, errorInfoString, &callback); - CErrorInfo errorInfo; + CUpdateErrorInfo errorInfo; errorInfo.Message = errorInfoString; - retCode = WarningsCheck(hresultMain, callback, errorInfo, stdStream); + retCode = WarningsCheck(hresultMain, callback, errorInfo, so, options.EnableHeaders); } else - ShowMessageAndThrowException(stdStream, kUserErrorMessage, NExitCode::kUserError); + ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError); - if (showStat) + if (options.ShowTime && g_StdStream) PrintStat(); ThrowException_if_Error(hresultMain); diff --git a/CPP/7zip/UI/Console/MainAr.cpp b/CPP/7zip/UI/Console/MainAr.cpp index 1cb01689..f3f977f5 100644 --- a/CPP/7zip/UI/Console/MainAr.cpp +++ b/CPP/7zip/UI/Console/MainAr.cpp @@ -15,7 +15,8 @@ using namespace NWindows; -CStdOutStream *g_StdStream = 0; +CStdOutStream *g_StdStream = NULL; +CStdOutStream *g_ErrStream = NULL; extern int Main2( #ifndef _WIN32 @@ -23,14 +24,27 @@ extern int Main2( #endif ); -static const char *kException_CmdLine_Error_Message = "\n\nCommand Line Error:\n"; -static const char *kExceptionErrorMessage = "\n\nError:\n"; -static const char *kUserBreak = "\nBreak signaled\n"; -static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n"; -static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n"; +static const char *kException_CmdLine_Error_Message = "Command Line Error:"; +static const char *kExceptionErrorMessage = "ERROR:"; +static const char *kUserBreakMessage = "Break signaled"; +static const char *kMemoryExceptionMessage = "ERROR: Can't allocate required memory!"; +static const char *kUnknownExceptionMessage = "Unknown Error"; static const char *kInternalExceptionMessage = "\n\nInternal Error #"; -#define NT_CHECK_FAIL_ACTION (*g_StdStream) << "Unsupported Windows version"; return NExitCode::kFatalError; +static void FlushStreams() +{ + if (g_StdStream) + g_StdStream->Flush(); +} + +static void PrintError(const char *message) +{ + FlushStreams(); + if (g_ErrStream) + *g_ErrStream << "\n\n" << message << endl; +} + +#define NT_CHECK_FAIL_ACTION *g_StdStream << "Unsupported Windows version"; return NExitCode::kFatalError; int MY_CDECL main ( @@ -39,12 +53,14 @@ int MY_CDECL main #endif ) { + g_ErrStream = &g_StdErr; g_StdStream = &g_StdOut; NT_CHECK NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter; int res = 0; + try { res = Main2( @@ -55,71 +71,97 @@ int MY_CDECL main } catch(const CNewException &) { - (*g_StdStream) << kMemoryExceptionMessage; + PrintError(kMemoryExceptionMessage); return (NExitCode::kMemoryError); } catch(const NConsoleClose::CCtrlBreakException &) { - (*g_StdStream) << endl << kUserBreak; + PrintError(kUserBreakMessage); return (NExitCode::kUserBreak); } catch(const CArcCmdLineException &e) { - (*g_StdStream) << kException_CmdLine_Error_Message << e << endl; + PrintError(kException_CmdLine_Error_Message); + if (g_ErrStream) + *g_ErrStream << e << endl; return (NExitCode::kUserError); } catch(const CSystemException &systemError) { if (systemError.ErrorCode == E_OUTOFMEMORY) { - (*g_StdStream) << kMemoryExceptionMessage; + PrintError(kMemoryExceptionMessage); return (NExitCode::kMemoryError); } if (systemError.ErrorCode == E_ABORT) { - (*g_StdStream) << endl << kUserBreak; + PrintError(kUserBreakMessage); return (NExitCode::kUserBreak); } - (*g_StdStream) << endl << endl << "System error:" << endl << - NError::MyFormatMessage(systemError.ErrorCode) << endl; + if (g_ErrStream) + { + PrintError("System ERROR:"); + *g_ErrStream << NError::MyFormatMessage(systemError.ErrorCode) << endl; + } return (NExitCode::kFatalError); } catch(NExitCode::EEnum &exitCode) { - (*g_StdStream) << kInternalExceptionMessage << exitCode << endl; + FlushStreams(); + if (g_ErrStream) + *g_ErrStream << kInternalExceptionMessage << exitCode << endl; return (exitCode); } - /* - catch(const NExitCode::CMultipleErrors &multipleErrors) - { - (*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl; - return (NExitCode::kFatalError); - } - */ catch(const UString &s) { - (*g_StdStream) << kExceptionErrorMessage << s << endl; + if (g_ErrStream) + { + PrintError(kExceptionErrorMessage); + *g_ErrStream << s << endl; + } return (NExitCode::kFatalError); } catch(const AString &s) { - (*g_StdStream) << kExceptionErrorMessage << s << endl; + if (g_ErrStream) + { + PrintError(kExceptionErrorMessage); + *g_ErrStream << s << endl; + } return (NExitCode::kFatalError); } catch(const char *s) { - (*g_StdStream) << kExceptionErrorMessage << s << endl; + if (g_ErrStream) + { + PrintError(kExceptionErrorMessage); + *g_ErrStream << s << endl; + } return (NExitCode::kFatalError); } - catch(int t) + catch(const wchar_t *s) { - (*g_StdStream) << kInternalExceptionMessage << t << endl; + if (g_ErrStream) + { + PrintError(kExceptionErrorMessage); + *g_ErrStream << s << endl; + } return (NExitCode::kFatalError); } + catch(int t) + { + if (g_ErrStream) + { + FlushStreams(); + *g_ErrStream << kInternalExceptionMessage << t << endl; + return (NExitCode::kFatalError); + } + } catch(...) { - (*g_StdStream) << kUnknownExceptionMessage; + PrintError(kUnknownExceptionMessage); return (NExitCode::kFatalError); } + return res; } diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.cpp b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp index f64fd493..5b2377be 100644 --- a/CPP/7zip/UI/Console/OpenCallbackConsole.cpp +++ b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp @@ -7,37 +7,89 @@ #include "ConsoleClose.h" #include "UserInputUtils.h" +static HRESULT CheckBreak2() +{ + return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK; +} + HRESULT COpenCallbackConsole::Open_CheckBreak() { - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; - return S_OK; + return CheckBreak2(); } -HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *, const UInt64 *) +HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *files, const UInt64 *bytes) { - return Open_CheckBreak(); + if (!MutiArcMode && NeedPercents()) + { + if (files) + { + _totalFilesDefined = true; + // _totalFiles = *files; + _percent.Total = *files; + } + else + _totalFilesDefined = false; + + if (bytes) + { + _totalBytesDefined = true; + // _totalBytes = *bytes; + if (!files) + _percent.Total = *bytes; + } + else + _totalBytesDefined = false; + } + + return CheckBreak2(); } -HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *, const UInt64 *) +HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) { - return Open_CheckBreak(); + if (!MutiArcMode && NeedPercents()) + { + if (files) + { + _percent.Files = *files; + if (_totalFilesDefined) + _percent.Completed = *files; + } + + if (bytes) + { + if (!_totalFilesDefined) + _percent.Completed = *bytes; + } + _percent.Print(); + } + + return CheckBreak2(); } - + +HRESULT COpenCallbackConsole::Open_Finished() +{ + ClosePercents(); + return S_OK; +} + + #ifndef _NO_CRYPTO HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password) { - PasswordWasAsked = true; - RINOK(Open_CheckBreak()); + *password = NULL; + RINOK(CheckBreak2()); + if (!PasswordIsDefined) { - Password = GetPassword(OutStream); + ClosePercents(); + Password = GetPassword(_so); PasswordIsDefined = true; } return StringToBstr(Password, password); } +/* HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) { passwordIsDefined = PasswordIsDefined; @@ -50,9 +102,10 @@ bool COpenCallbackConsole::Open_WasPasswordAsked() return PasswordWasAsked; } -void COpenCallbackConsole::Open_ClearPasswordWasAskedFlag() +void COpenCallbackConsole::Open_Clear_PasswordWasAsked_Flag () { PasswordWasAsked = false; } +*/ #endif diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.h b/CPP/7zip/UI/Console/OpenCallbackConsole.h index 5828af99..66d1fafa 100644 --- a/CPP/7zip/UI/Console/OpenCallbackConsole.h +++ b/CPP/7zip/UI/Console/OpenCallbackConsole.h @@ -7,18 +7,58 @@ #include "../Common/ArchiveOpenCallback.h" +#include "PercentPrinter.h" + class COpenCallbackConsole: public IOpenCallbackUI { +protected: + CPercentPrinter _percent; + + CStdOutStream *_so; + CStdOutStream *_se; + + bool _totalFilesDefined; + bool _totalBytesDefined; + // UInt64 _totalFiles; + // UInt64 _totalBytes; + + bool NeedPercents() const { return _percent._so != NULL; } + public: - INTERFACE_IOpenCallbackUI(;) + + bool MutiArcMode; + + void ClosePercents() + { + if (NeedPercents()) + _percent.ClosePrint(true); + } + + COpenCallbackConsole(): + _totalFilesDefined(false), + _totalBytesDefined(false), + MutiArcMode(false) + + #ifndef _NO_CRYPTO + , PasswordIsDefined(false) + // , PasswordWasAsked(false) + #endif + + {} - CStdOutStream *OutStream; + void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream) + { + _so = outStream; + _se = errorStream; + _percent._so = percentStream; + } + INTERFACE_IOpenCallbackUI(;) + #ifndef _NO_CRYPTO bool PasswordIsDefined; - bool PasswordWasAsked; + // bool PasswordWasAsked; UString Password; - COpenCallbackConsole(): PasswordIsDefined(false), PasswordWasAsked(false) {} #endif }; diff --git a/CPP/7zip/UI/Console/PercentPrinter.cpp b/CPP/7zip/UI/Console/PercentPrinter.cpp index f2889957..e3e8d599 100644 --- a/CPP/7zip/UI/Console/PercentPrinter.cpp +++ b/CPP/7zip/UI/Console/PercentPrinter.cpp @@ -2,101 +2,180 @@ #include "StdAfx.h" -#include "../../../Common/Defs.h" #include "../../../Common/IntToString.h" #include "PercentPrinter.h" -static const unsigned kPaddingSize = 2; static const unsigned kPercentsSize = 4; -static const unsigned kMaxExtraSize = kPaddingSize + 32 + kPercentsSize; -static void ClearPrev(char *p, unsigned num) +CPercentPrinter::~CPercentPrinter() { - unsigned i; - for (i = 0; i < num; i++) *p++ = '\b'; - for (i = 0; i < num; i++) *p++ = ' '; - for (i = 0; i < num; i++) *p++ = '\b'; - *p = '\0'; -} - -void CPercentPrinter::ClosePrint() -{ - if (m_NumExtraChars == 0) - return; - char s[kMaxExtraSize * 3 + 1]; - ClearPrev(s, m_NumExtraChars); - (*OutStream) << s; - m_NumExtraChars = 0; + ClosePrint(false); } -void CPercentPrinter::PrintString(const char *s) +void CPercentPrinterState::ClearCurState() { - ClosePrint(); - (*OutStream) << s; + Completed = 0; + Total = ((UInt64)(Int64)-1); + Files = 0; + Command.Empty(); + FileName.Empty(); } -void CPercentPrinter::PrintString(const wchar_t *s) +void CPercentPrinter::ClosePrint(bool needFlush) { - ClosePrint(); - (*OutStream) << s; -} + unsigned num = _printedString.Len(); + if (num != 0) + { -void CPercentPrinter::PrintNewLine() -{ - ClosePrint(); - (*OutStream) << "\n"; + unsigned i; + + /* '\r' in old MAC OS means "new line". + So we can't use '\r' in some systems */ + + #ifdef _WIN32 + char *start = _temp.GetBuf(num + 2); + char *p = start; + *p++ = '\r'; + for (i = 0; i < num; i++) *p++ = ' '; + *p++ = '\r'; + #else + char *start = _temp.GetBuf(num * 3); + char *p = start; + for (i = 0; i < num; i++) *p++ = '\b'; + for (i = 0; i < num; i++) *p++ = ' '; + for (i = 0; i < num; i++) *p++ = '\b'; + #endif + + *p = 0; + _temp.ReleaseBuf_SetLen((unsigned)(p - start)); + *_so << _temp; + } + if (needFlush) + _so->Flush(); + _printedString.Empty(); } -void CPercentPrinter::RePrintRatio() +void CPercentPrinter::GetPercents() { char s[32]; unsigned size; { char c = '%'; - UInt64 value = 0; - if (m_Total == (UInt64)(Int64)-1) + UInt64 val = 0; + if (Total == (UInt64)(Int64)-1) { - value = m_CurValue >> 20; + val = Completed >> 20; c = 'M'; } - else if (m_Total != 0) - value = m_CurValue * 100 / m_Total; - ConvertUInt64ToString(value, s); + else if (Total != 0) + val = Completed * 100 / Total; + ConvertUInt64ToString(val, s); size = (unsigned)strlen(s); s[size++] = c; - s[size] = '\0'; + s[size] = 0; } - unsigned extraSize = kPaddingSize + MyMax(size, kPercentsSize); - if (extraSize < m_NumExtraChars) - extraSize = m_NumExtraChars; - - char fullString[kMaxExtraSize * 3]; - char *p = fullString; - unsigned i; - if (m_NumExtraChars == 0) + while (size < kPercentsSize) { - for (i = 0; i < extraSize; i++) - *p++ = ' '; - m_NumExtraChars = extraSize; + _s += ' '; + size++; } - for (i = 0; i < m_NumExtraChars; i++) - *p++ = '\b'; - m_NumExtraChars = extraSize; - for (; size < extraSize; size++) - *p++ = ' '; - MyStringCopy(p, s); - (*OutStream) << fullString; - OutStream->Flush(); - m_PrevValue = m_CurValue; + _s += s; } -void CPercentPrinter::PrintRatio() +void CPercentPrinter::Print() { - if (m_CurValue < m_PrevValue + m_MinStepSize && - m_CurValue + m_MinStepSize > m_PrevValue && m_NumExtraChars != 0) + DWORD tick = 0; + if (_tickStep != 0) + tick = GetTickCount(); + + bool onlyPercentsChanged = false; + + if (!_printedString.IsEmpty()) + { + if (_tickStep != 0 && (UInt32)(tick - _prevTick) < _tickStep) + return; + + CPercentPrinterState &st = *this; + if (_printedState.Command == st.Command + && _printedState.FileName == st.FileName + && _printedState.Files == st.Files) + { + if (_printedState.Total == st.Total + && _printedState.Completed == st.Completed) + return; + onlyPercentsChanged = true; + } + } + + _s.Empty(); + + GetPercents(); + + if (onlyPercentsChanged && _s == _printedPercents) return; - RePrintRatio(); + + _printedPercents = _s; + + if (Files != 0) + { + char s[32]; + ConvertUInt64ToString(Files, s); + // unsigned size = (unsigned)strlen(s); + // for (; size < 3; size++) _s += ' '; + _s += ' '; + _s += s; + // _s += "f"; + } + + + if (!Command.IsEmpty()) + { + _s += ' '; + _s += Command; + } + + if (!FileName.IsEmpty() && _s.Len() < MaxLen) + { + _s += ' '; + + StdOut_Convert_UString_to_AString(FileName, _temp); + _temp.Replace('\n', ' '); + if (_s.Len() + _temp.Len() > MaxLen) + { + unsigned len = FileName.Len(); + for (; len != 0;) + { + unsigned delta = len / 8; + if (delta == 0) + delta = 1; + len -= delta; + _tempU = FileName; + _tempU.Delete(len / 2, FileName.Len() - len); + _tempU.Insert(len / 2, L" . "); + StdOut_Convert_UString_to_AString(_tempU, _temp); + if (_s.Len() + _temp.Len() <= MaxLen) + break; + } + if (len == 0) + _temp.Empty(); + } + _s += _temp; + } + + if (_printedString != _s) + { + ClosePrint(false); + *_so << _s; + if (NeedFlush) + _so->Flush(); + _printedString = _s; + } + + _printedState = *this; + + if (_tickStep != 0) + _prevTick = tick; } diff --git a/CPP/7zip/UI/Console/PercentPrinter.h b/CPP/7zip/UI/Console/PercentPrinter.h index 509bab5f..95290b37 100644 --- a/CPP/7zip/UI/Console/PercentPrinter.h +++ b/CPP/7zip/UI/Console/PercentPrinter.h @@ -5,26 +5,58 @@ #include "../../../Common/StdOutStream.h" -class CPercentPrinter +struct CPercentPrinterState { - UInt64 m_MinStepSize; - UInt64 m_PrevValue; - UInt64 m_CurValue; - UInt64 m_Total; - unsigned m_NumExtraChars; + UInt64 Completed; + UInt64 Total; + + UInt64 Files; + + AString Command; + UString FileName; + + void ClearCurState(); + + CPercentPrinterState(): + Completed(0), + Total((UInt64)(Int64)-1), + Files(0) + {} +}; + +class CPercentPrinter: public CPercentPrinterState +{ + UInt32 _tickStep; + DWORD _prevTick; + + AString _s; + + AString _printedString; + AString _temp; + UString _tempU; + + CPercentPrinterState _printedState; + AString _printedPercents; + + void GetPercents(); + public: - CStdOutStream *OutStream; - - CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize), - m_PrevValue(0), m_CurValue(0), m_Total((UInt64)(Int64)-1), m_NumExtraChars(0) {} - void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; } - void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; } - void PrintString(const char *s); - void PrintString(const wchar_t *s); - void PrintNewLine(); - void ClosePrint(); - void RePrintRatio(); - void PrintRatio(); + CStdOutStream *_so; + + bool NeedFlush; + unsigned MaxLen; + + CPercentPrinter(UInt32 tickStep = 200): + _tickStep(tickStep), + _prevTick(0), + NeedFlush(true), + MaxLen(80 - 1) + {} + + ~CPercentPrinter(); + + void ClosePrint(bool needFlush); + void Print(); }; #endif diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp index 749021c4..f4f2d102 100644 --- a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp +++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp @@ -2,7 +2,10 @@ #include "StdAfx.h" +#include "../../../Common/IntToString.h" + #include "../../../Windows/ErrorMsg.h" + #ifndef _7ZIP_ST #include "../../../Windows/Synchronization.h" #endif @@ -22,195 +25,590 @@ static NSynchronization::CCriticalSection g_CriticalSection; static const wchar_t *kEmptyFileAlias = L"[Content]"; -static const char *kCreatingArchiveMessage = "Creating archive "; -static const char *kUpdatingArchiveMessage = "Updating archive "; -static const char *kScanningMessage = "Scanning"; +static const char *kOpenArchiveMessage = "Open archive: "; +static const char *kCreatingArchiveMessage = "Creating archive: "; +static const char *kUpdatingArchiveMessage = "Updating archive: "; +static const char *kScanningMessage = "Scanning the drive:"; +static const char *kError = "ERROR: "; +static const char *kWarning = "WARNING: "; -HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result, const wchar_t *errorArcType) +static HRESULT CheckBreak2() { - (*OutStream) << endl; - if (result != S_OK) + return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK; +} + +HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); +HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); + +void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags); + +void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc); + +HRESULT CUpdateCallbackConsole::OpenResult( + const CCodecs *codecs, const CArchiveLink &arcLink, + const wchar_t *name, HRESULT result) +{ + ClosePercents2(); + + FOR_VECTOR (level, arcLink.Arcs) { - (*OutStream) << "Error: " << name; - if (errorArcType) - (*OutStream) << " : can not open the file as [" << errorArcType << "] archive"; - else - (*OutStream) << " is not supported archive"; - (*OutStream) << endl; + const CArc &arc = arcLink.Arcs[level]; + const CArcErrorInfo &er = arc.ErrorInfo; + + UInt32 errorFlags = er.GetErrorFlags(); + + if (errorFlags != 0 || !er.ErrorMessage.IsEmpty()) + { + if (_se) + { + *_se << endl; + if (level != 0) + *_se << arc.Path << endl; + } + + if (errorFlags != 0) + { + if (_se) + PrintErrorFlags(*_se, "ERRORS:", errorFlags); + } + + if (!er.ErrorMessage.IsEmpty()) + { + if (_se) + *_se << "ERRORS:" << endl << er.ErrorMessage << endl; + } + + if (_se) + { + *_se << endl; + _se->Flush(); + } + } + + UInt32 warningFlags = er.GetWarningFlags(); + + if (warningFlags != 0 || !er.WarningMessage.IsEmpty()) + { + if (_so) + { + *_so << endl; + if (level != 0) + *_so << arc.Path << endl; + } + + if (warningFlags != 0) + { + if (_so) + PrintErrorFlags(*_so, "WARNINGS:", warningFlags); + } + + if (!er.WarningMessage.IsEmpty()) + { + if (_so) + *_so << "WARNINGS:" << endl << er.WarningMessage << endl; + } + + if (_so) + { + *_so << endl; + if (NeedFlush) + _so->Flush(); + } + } + + + if (er.ErrorFormatIndex >= 0) + { + if (_so) + { + Print_ErrorFormatIndex_Warning(_so, codecs, arc); + if (NeedFlush) + _so->Flush(); + } + } } + + if (result == S_OK) + { + if (_so) + { + RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink)); + *_so << endl; + } + } + else + { + if (_so) + _so->Flush(); + if (_se) + { + *_se << kError << name << endl; + HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink); + RINOK(res); + _se->Flush(); + } + } + return S_OK; } HRESULT CUpdateCallbackConsole::StartScanning() { - (*OutStream) << kScanningMessage; + if (_so) + *_so << kScanningMessage << endl; + _percent.Command = "Scan "; return S_OK; } -HRESULT CUpdateCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, UInt64 /* totalSize */, const wchar_t * /* path */, bool /* isDir */) +HRESULT CUpdateCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */) { + if (NeedPercents()) + { + _percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams; + _percent.Completed = st.GetTotalBytes(); + _percent.FileName = fs2us(path); + _percent.Print(); + } + return CheckBreak(); } -HRESULT CCallbackConsoleBase::CanNotFindError_Base(const wchar_t *name, DWORD systemError) +void CCallbackConsoleBase::CommonError(const FString &path, DWORD systemError, bool isWarning) { - CantFindFiles.Add(name); - CantFindCodes.Add(systemError); - // m_PercentPrinter.ClosePrint(); - if (!m_WarningsMode) + ClosePercents2(); + + if (_se) { - (*OutStream) << endl << endl; - m_PercentPrinter.PrintNewLine(); - m_WarningsMode = true; + if (_so) + _so->Flush(); + + *_se << endl << (isWarning ? kWarning : kError) + << NError::MyFormatMessage(systemError) + << endl << fs2us(path) << endl << endl; + _se->Flush(); } - m_PercentPrinter.PrintString(name); - m_PercentPrinter.PrintString(": WARNING: "); - m_PercentPrinter.PrintString(NError::MyFormatMessage(systemError)); - m_PercentPrinter.PrintNewLine(); +} + + +HRESULT CCallbackConsoleBase::ScanError_Base(const FString &path, DWORD systemError) +{ + MT_LOCK + + ScanErrors.AddError(path, systemError); + CommonError(path, systemError, true); + return S_OK; } -HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError) +HRESULT CCallbackConsoleBase::OpenFileError_Base(const FString &path, DWORD systemError) +{ + MT_LOCK + FailedFiles.AddError(path, systemError); + /* + if (systemError == ERROR_SHARING_VIOLATION) + { + */ + CommonError(path, systemError, true); + return S_FALSE; + /* + } + return systemError; + */ +} + +HRESULT CCallbackConsoleBase::ReadingFileError_Base(const FString &path, DWORD systemError) +{ + MT_LOCK + CommonError(path, systemError, false); + return HRESULT_FROM_WIN32(systemError); +} + +HRESULT CUpdateCallbackConsole::ScanError(const FString &path, DWORD systemError) +{ + return ScanError_Base(path, systemError); +} + + +static void PrintPropPair(AString &s, const char *name, UInt64 val) { - return CanNotFindError_Base(name, systemError); + char temp[32]; + ConvertUInt64ToString(val, temp); + s += name; + s += ": "; + s += temp; } -HRESULT CUpdateCallbackConsole::FinishScanning() +void PrintSize_bytes_Smart(AString &s, UInt64 val); +void Print_DirItemsStat(AString &s, const CDirItemsStat &st); + +HRESULT CUpdateCallbackConsole::FinishScanning(const CDirItemsStat &st) { - (*OutStream) << endl << endl; + if (NeedPercents()) + { + _percent.ClosePrint(true); + _percent.ClearCurState(); + } + + if (_so) + { + AString s; + Print_DirItemsStat(s, st); + *_so << s << endl << endl; + } + return S_OK; +} + +static const char *k_StdOut_ArcName = "StdOut"; + +HRESULT CUpdateCallbackConsole::StartOpenArchive(const wchar_t *name) +{ + if (_so) + { + *_so << kOpenArchiveMessage; + if (name) + *_so << name; + else + *_so << k_StdOut_ArcName; + *_so << endl; + } return S_OK; } HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating) { - if(updating) - (*OutStream) << kUpdatingArchiveMessage; - else - (*OutStream) << kCreatingArchiveMessage; - if (name != 0) - (*OutStream) << name; - else - (*OutStream) << "StdOut"; - (*OutStream) << endl << endl; + if (_so) + { + *_so << (updating ? kUpdatingArchiveMessage : kCreatingArchiveMessage); + if (name != 0) + *_so << name; + else + *_so << k_StdOut_ArcName; + *_so << endl << endl; + } return S_OK; } -HRESULT CUpdateCallbackConsole::FinishArchive() +HRESULT CUpdateCallbackConsole::FinishArchive(const CFinishArchiveStat &st) { - (*OutStream) << endl; + ClosePercents2(); + + if (_so) + { + AString s; + // Print_UInt64_and_String(s, _percent.Files == 1 ? "file" : "files", _percent.Files); + PrintPropPair(s, "Files read from disk", _percent.Files); + s.Add_LF(); + s += "Archive size: "; + PrintSize_bytes_Smart(s, st.OutArcFileSize); + s.Add_LF(); + *_so << endl; + *_so << s; + // *_so << endl; + } + return S_OK; } -HRESULT CUpdateCallbackConsole::CheckBreak() +HRESULT CUpdateCallbackConsole::WriteSfx(const wchar_t *name, UInt64 size) { - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; + if (_so) + { + *_so << "Write SFX: "; + *_so << name; + AString s = " : "; + PrintSize_bytes_Smart(s, size); + *_so << s << endl; + } return S_OK; } -HRESULT CUpdateCallbackConsole::Finilize() + +HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool /* isDir */) { - MT_LOCK - if (m_NeedBeClosed) + if (LogLevel > 0 && _so) { - if (EnablePercents) + ClosePercents_for_so(); + + if (!DeleteMessageWasShown) + { + if (_so) + *_so << endl << ": Removing files after including to archive" << endl; + } + { - m_PercentPrinter.ClosePrint(); + { + _tempA = "Removing"; + _tempA.Add_Space(); + *_so << _tempA; + _tempU = fs2us(path); + _so->PrintUString(_tempU, _tempA); + *_so << endl; + if (NeedFlush) + _so->Flush(); + } } - if (!StdOutMode && m_NeedNewLine) + } + + if (!DeleteMessageWasShown) + { + if (NeedPercents()) { - m_PercentPrinter.PrintNewLine(); - m_NeedNewLine = false; + _percent.ClearCurState(); } - m_NeedBeClosed = false; + DeleteMessageWasShown = true; + } + else + { + _percent.Files++; } + + if (NeedPercents()) + { + // if (!FullLog) + { + _percent.Command = "Removing"; + _percent.FileName = fs2us(path); + } + _percent.Print(); + } + + return S_OK; +} + + +HRESULT CUpdateCallbackConsole::FinishDeletingAfterArchiving() +{ + ClosePercents2(); + if (_so && DeleteMessageWasShown) + *_so << endl; + return S_OK; +} + +HRESULT CUpdateCallbackConsole::CheckBreak() +{ + return CheckBreak2(); +} + +/* +HRESULT CUpdateCallbackConsole::Finalize() +{ + // MT_LOCK return S_OK; } +*/ -HRESULT CUpdateCallbackConsole::SetNumFiles(UInt64 /* numFiles */) +HRESULT CUpdateCallbackConsole::SetNumItems(UInt64 numItems) { + if (_so) + { + ClosePercents_for_so(); + AString s; + PrintPropPair(s, "Items to compress", numItems); + *_so << s << endl << endl; + } return S_OK; } HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size) { MT_LOCK - if (EnablePercents) - m_PercentPrinter.SetTotal(size); + if (NeedPercents()) + { + _percent.Total = size; + _percent.Print(); + } return S_OK; } HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue) { MT_LOCK - if (completeValue != NULL) + if (completeValue) { - if (EnablePercents) + if (NeedPercents()) { - m_PercentPrinter.SetRatio(*completeValue); - m_PercentPrinter.PrintRatio(); - m_NeedBeClosed = true; + _percent.Completed = *completeValue; + _percent.Print(); } } - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; - return S_OK; + return CheckBreak2(); } HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */) { - if (NConsoleClose::TestBreakSignal()) - return E_ABORT; - return S_OK; + return CheckBreak2(); } -HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti) +HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, const char *command, bool showInLog) { MT_LOCK + + bool show2 = (showInLog && _so); + + if (show2) + { + ClosePercents_for_so(); + + _tempA = command; + if (name) + _tempA.Add_Space(); + *_so << _tempA; + + _tempU.Empty(); + if (name) + _tempU = name; + _so->PrintUString(_tempU, _tempA); + *_so << endl; + if (NeedFlush) + _so->Flush(); + } + + if (NeedPercents()) + { + if (PercentsNameLevel >= 1) + { + _percent.FileName.Empty(); + _percent.Command.Empty(); + if (PercentsNameLevel > 1 || !show2) + { + _percent.Command = command; + if (name) + _percent.FileName = name; + } + } + _percent.Print(); + } + + return CheckBreak2(); +} + +HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool /* isDir */, bool isAnti, UInt32 mode) +{ if (StdOutMode) return S_OK; - if(isAnti) - m_PercentPrinter.PrintString("Anti item "); - else - m_PercentPrinter.PrintString("Compressing "); - if (name[0] == 0) + + if (!name || name[0] == 0) name = kEmptyFileAlias; - m_PercentPrinter.PrintString(name); - if (EnablePercents) - m_PercentPrinter.RePrintRatio(); - return S_OK; + + unsigned requiredLevel = 1; + + const char *s; + if (mode == NUpdateNotifyOp::kAdd || + mode == NUpdateNotifyOp::kUpdate) + { + if (isAnti) + s = "Anti"; + else if (mode == NUpdateNotifyOp::kAdd) + s = "+"; + else + s = "U"; + } + else + { + requiredLevel = 3; + if (mode == NUpdateNotifyOp::kAnalyze) + s = "A"; + else + s = "Reading"; + } + + return PrintProgress(name, s, LogLevel >= requiredLevel); +} + +HRESULT CUpdateCallbackConsole::OpenFileError(const FString &path, DWORD systemError) +{ + return OpenFileError_Base(path, systemError); +} + +HRESULT CUpdateCallbackConsole::ReadingFileError(const FString &path, DWORD systemError) +{ + return ReadingFileError_Base(path, systemError); } -HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError) +HRESULT CUpdateCallbackConsole::SetOperationResult(Int32) { MT_LOCK - FailedCodes.Add(systemError); - FailedFiles.Add(name); - /* - if (systemError == ERROR_SHARING_VIOLATION) + _percent.Files++; + return S_OK; +} + +void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest); + +HRESULT CUpdateCallbackConsole::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) +{ + // if (StdOutMode) return S_OK; + + if (opRes != NArchive::NExtract::NOperationResult::kOK) { - */ - m_PercentPrinter.ClosePrint(); - m_PercentPrinter.PrintNewLine(); - m_PercentPrinter.PrintString("WARNING: "); - m_PercentPrinter.PrintString(NError::MyFormatMessage(systemError)); - return S_FALSE; - /* + ClosePercents2(); + + if (_se) + { + if (_so) + _so->Flush(); + + AString s; + SetExtractErrorMessage(opRes, isEncrypted, s); + *_se << s << " : " << endl << name << endl << endl; + _se->Flush(); + } + return S_OK; } - return systemError; - */ + return S_OK; } -HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 ) + +HRESULT CUpdateCallbackConsole::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool /* isDir */) +{ + // if (StdOutMode) return S_OK; + + char temp[16]; + const char *s; + + unsigned requiredLevel = 1; + + switch (op) + { + case NUpdateNotifyOp::kAdd: s = "+"; break; + case NUpdateNotifyOp::kUpdate: s = "U"; break; + case NUpdateNotifyOp::kAnalyze: s = "A"; requiredLevel = 3; break; + case NUpdateNotifyOp::kReplicate: s = "="; requiredLevel = 3; break; + case NUpdateNotifyOp::kRepack: s = "R"; requiredLevel = 2; break; + case NUpdateNotifyOp::kSkip: s = "."; requiredLevel = 2; break; + case NUpdateNotifyOp::kDelete: s = "D"; requiredLevel = 3; break; + case NUpdateNotifyOp::kHeader: s = "Header creation"; requiredLevel = 100; break; + default: + { + temp[0] = 'o'; + temp[1] = 'p'; + ConvertUInt64ToString(op, temp + 2); + s = temp; + } + } + + return PrintProgress(name, s, LogLevel >= requiredLevel); +} + +/* +HRESULT CUpdateCallbackConsole::SetPassword(const UString & + #ifndef _NO_CRYPTO + password + #endif + ) { - m_NeedBeClosed = true; - m_NeedNewLine = true; + #ifndef _NO_CRYPTO + PasswordIsDefined = true; + Password = password; + #endif return S_OK; } +*/ HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { + COM_TRY_BEGIN + *password = NULL; #ifdef _NO_CRYPTO @@ -224,7 +622,7 @@ HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, { if (AskPassword) { - Password = GetPassword(OutStream); + Password = GetPassword(_so); PasswordIsDefined = true; } } @@ -232,10 +630,14 @@ HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, return StringToBstr(Password, password); #endif + + COM_TRY_END } HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password) { + COM_TRY_BEGIN + *password = NULL; #ifdef _NO_CRYPTO @@ -247,30 +649,26 @@ HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password) if (!PasswordIsDefined) { { - Password = GetPassword(OutStream); + Password = GetPassword(_so); PasswordIsDefined = true; } } return StringToBstr(Password, password); #endif + COM_TRY_END } -/* -HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name) +HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool /* isDir */) { - // MT_LOCK if (StdOutMode) return S_OK; - RINOK(Finilize()); - m_PercentPrinter.PrintString("Deleting "); - if (name[0] == 0) - name = kEmptyFileAlias; - m_PercentPrinter.PrintString(name); - if (EnablePercents) - m_PercentPrinter.RePrintRatio(); - m_NeedBeClosed = true; - m_NeedNewLine = true; + + if (LogLevel > 7) + { + if (!name || name[0] == 0) + name = kEmptyFileAlias; + return PrintProgress(name, "D", true); + } return S_OK; } -*/ diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/CPP/7zip/UI/Console/UpdateCallbackConsole.h index 77e0e178..ba8614eb 100644 --- a/CPP/7zip/UI/Console/UpdateCallbackConsole.h +++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.h @@ -9,44 +9,91 @@ #include "PercentPrinter.h" +struct CErrorPathCodes +{ + FStringVector Paths; + CRecordVector<DWORD> Codes; + + void AddError(const FString &path, DWORD systemError) + { + Paths.Add(path); + Codes.Add(systemError); + } + void Clear() + { + Paths.Clear(); + Codes.Clear(); + } +}; + class CCallbackConsoleBase { - bool m_WarningsMode; protected: - CPercentPrinter m_PercentPrinter; + CPercentPrinter _percent; + + CStdOutStream *_so; + CStdOutStream *_se; + + void CommonError(const FString &path, DWORD systemError, bool isWarning); + + HRESULT ScanError_Base(const FString &path, DWORD systemError); + HRESULT OpenFileError_Base(const FString &name, DWORD systemError); + HRESULT ReadingFileError_Base(const FString &name, DWORD systemError); - CStdOutStream *OutStream; - HRESULT CanNotFindError_Base(const wchar_t *name, DWORD systemError); public: - bool EnablePercents; + bool NeedPercents() const { return _percent._so != NULL; }; + bool StdOutMode; + bool NeedFlush; + unsigned PercentsNameLevel; + unsigned LogLevel; + + AString _tempA; + UString _tempU; + CCallbackConsoleBase(): - m_PercentPrinter(1 << 16), StdOutMode(false), - EnablePercents(true), - m_WarningsMode(false) + NeedFlush(false), + PercentsNameLevel(1), + LogLevel(0) {} - void Init(CStdOutStream *outStream) + void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; } + + void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream) { FailedFiles.Clear(); - FailedCodes.Clear(); - OutStream = outStream; - m_PercentPrinter.OutStream = outStream; + + _so = outStream; + _se = errorStream; + _percent._so = percentStream; } - UStringVector FailedFiles; - CRecordVector<HRESULT> FailedCodes; + void ClosePercents2() + { + if (NeedPercents()) + _percent.ClosePrint(true); + } + + void ClosePercents_for_so() + { + if (NeedPercents() && _so == _percent._so) + _percent.ClosePrint(false); + } + + + CErrorPathCodes FailedFiles; + CErrorPathCodes ScanErrors; + + HRESULT PrintProgress(const wchar_t *name, const char *command, bool showInLog); - UStringVector CantFindFiles; - CRecordVector<HRESULT> CantFindCodes; }; class CUpdateCallbackConsole: public IUpdateCallbackUI2, public CCallbackConsoleBase { - bool m_NeedBeClosed; - bool m_NeedNewLine; + // void PrintPropPair(const char *name, const wchar_t *val); + public: #ifndef _NO_CRYPTO bool PasswordIsDefined; @@ -54,21 +101,23 @@ public: bool AskPassword; #endif + bool DeleteMessageWasShown; + CUpdateCallbackConsole() + : DeleteMessageWasShown(false) #ifndef _NO_CRYPTO - : - PasswordIsDefined(false), - AskPassword(false) + , PasswordIsDefined(false) + , AskPassword(false) #endif {} + /* void Init(CStdOutStream *outStream) { - m_NeedBeClosed = false; - m_NeedNewLine = false; CCallbackConsoleBase::Init(outStream); } - ~CUpdateCallbackConsole() { Finilize(); } + */ + // ~CUpdateCallbackConsole() { if (NeedPercents()) _percent.ClosePrint(); } INTERFACE_IUpdateCallbackUI2(;) }; diff --git a/CPP/7zip/UI/Console/UserInputUtils.cpp b/CPP/7zip/UI/Console/UserInputUtils.cpp index a0d4af38..2974a5b9 100644 --- a/CPP/7zip/UI/Console/UserInputUtils.cpp +++ b/CPP/7zip/UI/Console/UserInputUtils.cpp @@ -14,7 +14,7 @@ static const char kNoAll = 's'; static const char kAutoRenameAll = 'u'; static const char kQuit = 'q'; -static const char *kFirstQuestionMessage = "?\n"; +static const char *kFirstQuestionMessage = "? "; static const char *kHelpQuestionMessage = "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? "; @@ -22,11 +22,15 @@ static const char *kHelpQuestionMessage = NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream) { - (*outStream) << kFirstQuestionMessage; + if (outStream) + *outStream << kFirstQuestionMessage; for (;;) { - (*outStream) << kHelpQuestionMessage; - outStream->Flush(); + if (outStream) + { + *outStream << kHelpQuestionMessage; + outStream->Flush(); + } AString scannedString = g_StdIn.ScanStringUntilNewLine(); scannedString.Trim(); if (!scannedString.IsEmpty()) @@ -50,14 +54,18 @@ NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream) UString GetPassword(CStdOutStream *outStream) { - (*outStream) << "\nEnter password" + if (outStream) + { + *outStream << "\nEnter password" #ifdef MY_DISABLE_ECHO " (will not be echoed)" #endif ":"; - outStream->Flush(); + outStream->Flush(); + } #ifdef MY_DISABLE_ECHO + HANDLE console = GetStdHandle(STD_INPUT_HANDLE); bool wasChanged = false; DWORD mode = 0; @@ -67,10 +75,16 @@ UString GetPassword(CStdOutStream *outStream) UString res = g_StdIn.ScanUStringUntilNewLine(); if (wasChanged) SetConsoleMode(console, mode); - (*outStream) << "\n"; - outStream->Flush(); + if (outStream) + { + *outStream << endl; + outStream->Flush(); + } return res; + #else + return g_StdIn.ScanUStringUntilNewLine(); + #endif } diff --git a/CPP/7zip/UI/Console/makefile b/CPP/7zip/UI/Console/makefile index efabf91c..98ad91c2 100644 --- a/CPP/7zip/UI/Console/makefile +++ b/CPP/7zip/UI/Console/makefile @@ -7,8 +7,6 @@ CFLAGS = $(CFLAGS) \ CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -D_7ZIP_LARGE_PAGES -DSUPPORT_DEVICE_FILE !ENDIF -CURRENT_OBJS = \ - COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp index d0fc1725..64a916b2 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp @@ -115,7 +115,7 @@ STDMETHODIMP CZipContextMenu::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT return GetFileNames(dataObject, _fileNames); } -HRESULT CZipContextMenu::InitContextMenu(const wchar_t * /* folder */, const wchar_t **names, unsigned numFiles) +HRESULT CZipContextMenu::InitContextMenu(const wchar_t * /* folder */, const wchar_t * const *names, unsigned numFiles) { _isMenuForFM = true; _fileNames.Clear(); @@ -278,7 +278,7 @@ static bool MyInsertMenu(CMenu &menu, int pos, UINT id, const UString &s, HBITMA // ::SetMenuItemBitmaps(menu, pos, MF_BYPOSITION, bitmap, NULL); } -static const char *kArcExts[] = +static const char * const kArcExts[] = { "7z" , "bz2" @@ -297,29 +297,28 @@ static bool IsItArcExt(const UString &ext2) return false; } -static UString GetSubFolderNameForExtract(const UString &archiveName) +static UString GetSubFolderNameForExtract(const UString &arcName) { - int dotPos = archiveName.ReverseFind(L'.'); + int dotPos = arcName.ReverseFind_Dot(); if (dotPos < 0) - { - return GetCorrectFsPath(archiveName) + L"~"; - } - const UString ext = archiveName.Ptr(dotPos + 1); - UString res = archiveName.Left(dotPos); + return Get_Correct_FsFile_Name(arcName) + L'~'; + + const UString ext = arcName.Ptr(dotPos + 1); + UString res = arcName.Left(dotPos); res.TrimRight(); - dotPos = res.ReverseFind(L'.'); + dotPos = res.ReverseFind_Dot(); if (dotPos > 0) { const UString ext2 = res.Ptr(dotPos + 1); - if (ext.IsEqualToNoCase(L"rar") && - (ext2.IsEqualToNoCase(L"part001") || - ext2.IsEqualToNoCase(L"part01") || - ext2.IsEqualToNoCase(L"part1")) || - IsItArcExt(ext2) && ext.IsEqualToNoCase(L"001")) + if (ext.IsEqualTo_Ascii_NoCase("001") && IsItArcExt(ext2) + || ext.IsEqualTo_Ascii_NoCase("rar") && + ( ext2.IsEqualTo_Ascii_NoCase("part001") + || ext2.IsEqualTo_Ascii_NoCase("part01") + || ext2.IsEqualTo_Ascii_NoCase("part1"))) res.DeleteFrom(dotPos); res.TrimRight(); } - return GetCorrectFullFsPath(res); + return Get_Correct_FsFile_Name(res); } static void ReduceString(UString &s) @@ -339,6 +338,11 @@ static UString GetQuotedReducedString(const UString &s) return GetQuotedString(s2); } +static void MyFormatNew_ReducedName(UString &s, const UString &name) +{ + s = MyFormatNew(s, GetQuotedReducedString(name)); +} + static const char *kExtractExludeExtensions = " 3gp" " aac ans ape asc asm asp aspx avi awk" @@ -368,7 +372,7 @@ static const char *kNoOpenAsExtensions = " 7z arj bz2 cab chm cpio flv gz lha lzh lzma rar swm tar tbz2 tgz wim xar xz z zip "; */ -static const char *kOpenTypes[] = +static const char * const kOpenTypes[] = { "" , "*" @@ -383,11 +387,12 @@ static const char *kOpenTypes[] = static bool FindExt(const char *p, const FString &name) { - int dotPos = name.ReverseFind('.'); + int dotPos = name.ReverseFind_Dot(); if (dotPos < 0 || dotPos == (int)name.Len() - 1) return false; AString s; + for (unsigned pos = dotPos + 1;; pos++) { wchar_t c = name[pos]; @@ -397,6 +402,7 @@ static bool FindExt(const char *p, const FString &name) return false; s += (char)MyCharLower_Ascii((char)c); } + for (unsigned i = 0; p[i] != 0;) { unsigned j; @@ -405,6 +411,7 @@ static bool FindExt(const char *p, const FString &name) return true; i = j + 1; } + return false; } @@ -475,7 +482,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (_fileNames.Size() > 0) { const UString &fileName = _fileNames.Front(); - #ifdef _WIN32 + #if defined(_WIN32) && !defined(UNDER_CE) if (NName::IsDevicePath(us2fs(fileName))) { // CFileInfo::Find can be slow for device files. So we don't call it. @@ -584,7 +591,8 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, commandMapItem.Folder = _dropPath; else commandMapItem.Folder = fs2us(folderPrefix); - commandMapItem.Folder += GetSubFolderNameForExtract(fs2us(fi0.Name)) + UString(WCHAR_PATH_SEPARATOR); + commandMapItem.Folder += GetSubFolderNameForExtract(fs2us(fi0.Name)); + commandMapItem.Folder.Add_PathSepar(); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); _commandMap.Add(commandMapItem); } @@ -608,17 +616,16 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, CCommandMapItem commandMapItem; UString s; FillCommand(kExtractTo, s, commandMapItem); - UString folder; + UString folder = L'*'; if (_fileNames.Size() == 1) folder = GetSubFolderNameForExtract(fs2us(fi0.Name)); - else - folder = L'*'; if (_dropMode) commandMapItem.Folder = _dropPath; else commandMapItem.Folder = fs2us(folderPrefix); commandMapItem.Folder += folder; - s = MyFormatNew(s, GetQuotedReducedString(folder + UString(WCHAR_PATH_SEPARATOR))); + folder.Add_PathSepar(); + MyFormatNew_ReducedName(s, folder); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); } @@ -632,13 +639,13 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, } } - UString archiveName; + UString arcName; if (_fileNames.Size() == 1) - archiveName = CreateArchiveName(fi0, false); + arcName = CreateArchiveName(fi0, false); else - archiveName = CreateArchiveName(fileName, _fileNames.Size() > 1, false); - UString archiveName7z = archiveName + L".7z"; - UString archiveNameZip = archiveName + L".zip"; + arcName = CreateArchiveName(fileName, _fileNames.Size() > 1, false); + UString arcName7z = arcName + L".7z"; + UString arcNameZip = arcName + L".zip"; // Compress if ((contextMenuFlags & NContextMenuFlags::kCompress) != 0) @@ -648,7 +655,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, commandMapItem.Folder = _dropPath; else commandMapItem.Folder = fs2us(folderPrefix); - commandMapItem.ArcName = archiveName; + commandMapItem.ArcName = arcName; FillCommand(kCompress, mainString, commandMapItem); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); _commandMap.Add(commandMapItem); @@ -659,7 +666,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if ((contextMenuFlags & NContextMenuFlags::kCompressEmail) != 0 && !_dropMode) { CCommandMapItem commandMapItem; - commandMapItem.ArcName = archiveName; + commandMapItem.ArcName = arcName; FillCommand(kCompressEmail, mainString, commandMapItem); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); _commandMap.Add(commandMapItem); @@ -668,7 +675,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, // CompressTo7z if (contextMenuFlags & NContextMenuFlags::kCompressTo7z && - !archiveName7z.IsEqualToNoCase(fs2us(fi0.Name))) + !arcName7z.IsEqualTo_NoCase(fs2us(fi0.Name))) { CCommandMapItem commandMapItem; UString s; @@ -677,9 +684,9 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, commandMapItem.Folder = _dropPath; else commandMapItem.Folder = fs2us(folderPrefix); - commandMapItem.ArcName = archiveName7z; - commandMapItem.ArcType = L"7z"; - s = MyFormatNew(s, GetQuotedReducedString(archiveName7z)); + commandMapItem.ArcName = arcName7z; + commandMapItem.ArcType.SetFromAscii("7z"); + MyFormatNew_ReducedName(s, arcName7z); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); } @@ -691,9 +698,9 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, CCommandMapItem commandMapItem; UString s; FillCommand(kCompressTo7zEmail, s, commandMapItem); - commandMapItem.ArcName = archiveName7z; - commandMapItem.ArcType = L"7z"; - s = MyFormatNew(s, GetQuotedReducedString(archiveName7z)); + commandMapItem.ArcName = arcName7z; + commandMapItem.ArcType.SetFromAscii("7z"); + MyFormatNew_ReducedName(s, arcName7z); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); } @@ -701,7 +708,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, // CompressToZip if (contextMenuFlags & NContextMenuFlags::kCompressToZip && - !archiveNameZip.IsEqualToNoCase(fs2us(fi0.Name))) + !arcNameZip.IsEqualTo_NoCase(fs2us(fi0.Name))) { CCommandMapItem commandMapItem; UString s; @@ -710,9 +717,9 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, commandMapItem.Folder = _dropPath; else commandMapItem.Folder = fs2us(folderPrefix); - commandMapItem.ArcName = archiveNameZip; - commandMapItem.ArcType = L"zip"; - s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip)); + commandMapItem.ArcName = arcNameZip; + commandMapItem.ArcType.SetFromAscii("zip"); + MyFormatNew_ReducedName(s, arcNameZip); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); } @@ -724,9 +731,9 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, CCommandMapItem commandMapItem; UString s; FillCommand(kCompressToZipEmail, s, commandMapItem); - commandMapItem.ArcName = archiveNameZip; - commandMapItem.ArcType = L"zip"; - s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip)); + commandMapItem.ArcName = arcNameZip; + commandMapItem.ArcType.SetFromAscii("zip"); + MyFormatNew_ReducedName(s, arcNameZip); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); } @@ -747,7 +754,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, mi.fMask |= MIIM_CHECKMARKS; mi.wID = currentCommandID++; mi.hSubMenu = popupMenu.Detach(); - mi.StringValue = L"7-Zip"; // LangString(IDS_CONTEXT_POPUP_CAPTION); + mi.StringValue.SetFromAscii("7-Zip"); // LangString(IDS_CONTEXT_POPUP_CAPTION); mi.hbmpUnchecked = bitmap; CMenu menu; menu.Attach(hMenu); @@ -774,7 +781,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, mi.fMask |= MIIM_CHECKMARKS; mi.wID = currentCommandID++; mi.hSubMenu = subMenu; - mi.StringValue = L"CRC SHA"; + mi.StringValue.SetFromAscii("CRC SHA"); mi.hbmpUnchecked = bitmap; CMenu menu; menu.Attach(hMenu); diff --git a/CPP/7zip/UI/Explorer/ContextMenu.h b/CPP/7zip/UI/Explorer/ContextMenu.h index b314bb38..a3b1174b 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.h +++ b/CPP/7zip/UI/Explorer/ContextMenu.h @@ -45,7 +45,7 @@ public: STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO lpici); STDMETHOD(GetCommandString)(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax); - HRESULT InitContextMenu(const wchar_t *folder, const wchar_t **names, unsigned numFiles); + HRESULT InitContextMenu(const wchar_t *folder, const wchar_t * const *names, unsigned numFiles); CZipContextMenu(); ~CZipContextMenu(); diff --git a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp index 478f6e97..d620cb70 100644 --- a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp +++ b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp @@ -28,7 +28,10 @@ // {23170F69-40C1-278A-1000-000100020000} DEFINE_GUID(CLSID_CZipContextMenu, -0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00); + k_7zip_GUID_Data1, + k_7zip_GUID_Data2, + k_7zip_GUID_Data3_Common, + 0x10, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00); using namespace NWindows; diff --git a/CPP/7zip/UI/Far/ExtractEngine.cpp b/CPP/7zip/UI/Far/ExtractEngine.cpp index 4384c6ec..e1db1c9f 100644 --- a/CPP/7zip/UI/Far/ExtractEngine.cpp +++ b/CPP/7zip/UI/Far/ExtractEngine.cpp @@ -2,6 +2,10 @@ #include "StdAfx.h" +#ifndef _7ZIP_ST +#include "../../../Windows/Synchronization.h" +#endif + #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" @@ -13,13 +17,26 @@ using namespace NWindows; using namespace NFar; +#ifndef _7ZIP_ST +static NSynchronization::CCriticalSection g_CriticalSection; +#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); +#else +#define MT_LOCK +#endif + + +static HRESULT CheckBreak2() +{ + return WasEscPressed() ? E_ABORT : S_OK; +} + extern void PrintMessage(const char *message); -CExtractCallBackImp::~CExtractCallBackImp() +CExtractCallbackImp::~CExtractCallbackImp() { } -void CExtractCallBackImp::Init( +void CExtractCallbackImp::Init( UINT codePage, CProgressBox *progressBox, bool passwordIsDefined, @@ -28,35 +45,41 @@ void CExtractCallBackImp::Init( m_PasswordIsDefined = passwordIsDefined; m_Password = password; m_CodePage = codePage; - m_ProgressBox = progressBox; + _percent = progressBox; } -STDMETHODIMP CExtractCallBackImp::SetTotal(UInt64 size) +STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 size) { - _total = size; - _totalIsDefined = true; - return S_OK; + MT_LOCK + + if (_percent) + { + _percent->Total = size; + _percent->Print(); + } + return CheckBreak2(); } -STDMETHODIMP CExtractCallBackImp::SetCompleted(const UInt64 *completeValue) +STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *completeValue) { - if (WasEscPressed()) - return E_ABORT; - _processedIsDefined = (completeValue != NULL); - if (_processedIsDefined) - _processed = *completeValue; - if (m_ProgressBox != 0) - m_ProgressBox->Progress( - _totalIsDefined ? &_total: NULL, - _processedIsDefined ? &_processed: NULL, AString()); - return S_OK; + MT_LOCK + + if (_percent) + { + if (completeValue) + _percent->Completed = *completeValue; + _percent->Print(); + } + return CheckBreak2(); } -STDMETHODIMP CExtractCallBackImp::AskOverwrite( +STDMETHODIMP CExtractCallbackImp::AskOverwrite( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer) { + MT_LOCK + NOverwriteDialog::CFileInfo oldFileInfo, newFileInfo; oldFileInfo.TimeIsDefined = (existTime != 0); if (oldFileInfo.TimeIsDefined) @@ -101,44 +124,62 @@ STDMETHODIMP CExtractCallBackImp::AskOverwrite( default: return E_FAIL; } - return S_OK; + + return CheckBreak2(); } -STDMETHODIMP CExtractCallBackImp::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 /* askExtractMode */, const UInt64 * /* position */) +static const char *kTestString = "Testing"; +static const char *kExtractString = "Extracting"; +static const char *kSkipString = "Skipping"; + +STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, Int32 /* isFolder */, Int32 askExtractMode, const UInt64 * /* position */) { - if (WasEscPressed()) - return E_ABORT; + MT_LOCK + m_CurrentFilePath = name; - return S_OK; + const char *s; + + switch (askExtractMode) + { + case NArchive::NExtract::NAskMode::kExtract: s = kExtractString; break; + case NArchive::NExtract::NAskMode::kTest: s = kTestString; break; + case NArchive::NExtract::NAskMode::kSkip: s = kSkipString; break; + default: s = "???"; // return E_FAIL; + }; + + if (_percent) + { + _percent->Command = s; + _percent->FileName = name; + _percent->Print(); + } + + return CheckBreak2(); } -STDMETHODIMP CExtractCallBackImp::MessageError(const wchar_t *message) +STDMETHODIMP CExtractCallbackImp::MessageError(const wchar_t *message) { + MT_LOCK + AString s = UnicodeStringToMultiByte(message, CP_OEMCP); - if (g_StartupInfo.ShowMessage((const char *)s) == -1) + if (g_StartupInfo.ShowErrorMessage((const char *)s) == -1) return E_ABORT; - return S_OK; -} -static void ReduceString(UString &s, unsigned size) -{ - if (s.Len() > size) - { - s.Delete(size / 2, s.Len() - size); - s.Insert(size / 2, L" ... "); - } + return CheckBreak2(); } -STDMETHODIMP CExtractCallBackImp::SetOperationResult(Int32 operationResult, bool encrypted) +void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &s) { - switch (operationResult) + s.Empty(); + + switch (opRes) { case NArchive::NExtract::NOperationResult::kOK: - break; + return; default: { UINT messageID = 0; - switch (operationResult) + switch (opRes) { case NArchive::NExtract::NOperationResult::kUnsupportedMethod: messageID = NMessageID::kExtractUnsupportedMethod; @@ -154,44 +195,78 @@ STDMETHODIMP CExtractCallBackImp::SetOperationResult(Int32 operationResult, bool NMessageID::kExtractDataError; break; } - UString name = m_CurrentFilePath; - ReduceString(name, 70); - AString s; if (messageID != 0) { s = g_StartupInfo.GetMsgString(messageID); s.Replace(" '%s'", ""); } - else if (operationResult == NArchive::NExtract::NOperationResult::kUnavailable) + else if (opRes == NArchive::NExtract::NOperationResult::kUnavailable) s = "Unavailable data"; - else if (operationResult == NArchive::NExtract::NOperationResult::kUnexpectedEnd) + else if (opRes == NArchive::NExtract::NOperationResult::kUnexpectedEnd) s = "Unexpected end of data"; - else if (operationResult == NArchive::NExtract::NOperationResult::kDataAfterEnd) + else if (opRes == NArchive::NExtract::NOperationResult::kDataAfterEnd) s = "There are some data after the end of the payload data"; - else if (operationResult == NArchive::NExtract::NOperationResult::kIsNotArc) + else if (opRes == NArchive::NExtract::NOperationResult::kIsNotArc) s = "Is not archive"; - else if (operationResult == NArchive::NExtract::NOperationResult::kHeadersError) + else if (opRes == NArchive::NExtract::NOperationResult::kHeadersError) s = "kHeaders Error"; else { char temp[16]; - ConvertUInt32ToString(operationResult, temp); + ConvertUInt32ToString(opRes, temp); s = "Error #"; s += temp; } - s += "\n"; - s += UnicodeStringToMultiByte(name, m_CodePage); - if (g_StartupInfo.ShowMessageLines(s) == -1) - return E_ABORT; } } - return S_OK; +} + +STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 opRes, Int32 encrypted) +{ + MT_LOCK + + if (opRes == NArchive::NExtract::NOperationResult::kOK) + { + if (_percent) + { + _percent->Command.Empty(); + _percent->FileName.Empty(); + _percent->Files++; + } + } + else + { + AString s; + SetExtractErrorMessage(opRes, encrypted, s); + if (PrintErrorMessage(s, m_CurrentFilePath) == -1) + return E_ABORT; + } + + return CheckBreak2(); +} + + +STDMETHODIMP CExtractCallbackImp::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name) +{ + MT_LOCK + + if (opRes != NArchive::NExtract::NOperationResult::kOK) + { + AString s; + SetExtractErrorMessage(opRes, encrypted, s); + if (PrintErrorMessage(s, name) == -1) + return E_ABORT; + } + + return CheckBreak2(); } extern HRESULT GetPassword(UString &password); -STDMETHODIMP CExtractCallBackImp::CryptoGetTextPassword(BSTR *password) +STDMETHODIMP CExtractCallbackImp::CryptoGetTextPassword(BSTR *password) { + MT_LOCK + if (!m_PasswordIsDefined) { RINOK(GetPassword(m_Password)); diff --git a/CPP/7zip/UI/Far/ExtractEngine.h b/CPP/7zip/UI/Far/ExtractEngine.h index f57602a9..5861d92c 100644 --- a/CPP/7zip/UI/Far/ExtractEngine.h +++ b/CPP/7zip/UI/Far/ExtractEngine.h @@ -11,40 +11,29 @@ #include "ProgressBox.h" -class CExtractCallBackImp: +class CExtractCallbackImp: public IFolderArchiveExtractCallback, + public IFolderArchiveExtractCallback2, public ICryptoGetTextPassword, public CMyUnknownImp { public: - MY_UNKNOWN_IMP1(ICryptoGetTextPassword) + MY_UNKNOWN_IMP2(ICryptoGetTextPassword, IFolderArchiveExtractCallback2) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); - // IExtractCallBack - STDMETHOD(AskOverwrite)( - const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, - const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, - Int32 *result); - STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position); + INTERFACE_IFolderArchiveExtractCallback(;) + INTERFACE_IFolderArchiveExtractCallback2(;) - STDMETHOD(MessageError)(const wchar_t *message); - STDMETHOD(SetOperationResult)(Int32 resultEOperationResult, bool encrypted); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *password); private: - UInt64 _total; - UInt64 _processed; - - bool _totalIsDefined; - bool _processedIsDefined; - UString m_CurrentFilePath; - CProgressBox *m_ProgressBox; + CProgressBox *_percent; UINT m_CodePage; bool m_PasswordIsDefined; @@ -58,8 +47,8 @@ private: */ void AddErrorMessage(LPCTSTR message); public: - CExtractCallBackImp(): _totalIsDefined(false), _processedIsDefined(false) {} - ~CExtractCallBackImp(); + // CExtractCallbackImp() {} + ~CExtractCallbackImp(); void Init(UINT codePage, CProgressBox *progressBox, bool passwordIsDefined, const UString &password); diff --git a/CPP/7zip/UI/Far/Far.cpp b/CPP/7zip/UI/Far/Far.cpp index 38fed101..3ae5bba2 100644 --- a/CPP/7zip/UI/Far/Far.cpp +++ b/CPP/7zip/UI/Far/Far.cpp @@ -1,3 +1,4 @@ +// Far.cpp // Test Align for updating !!!!!!!!!!!!!!!!!! #include "StdAfx.h" @@ -11,8 +12,6 @@ #include "../../Common/FileStreams.h" -#include "../Agent/Agent.h" - #include "Messages.h" #include "Plugin.h" #include "ProgressBox.h" @@ -22,6 +21,8 @@ using namespace NFile; using namespace NDir; using namespace NFar; +static const DWORD kShowProgressTime_ms = 100; + static const char *kCommandPrefix = "7-zip"; static const TCHAR *kRegisrtryMainKeyName = TEXT(""); static const TCHAR *kRegisrtryValueNameEnabled = TEXT("UsedByDefault3"); @@ -30,6 +31,12 @@ static bool kPluginEnabledDefault = true; HINSTANCE g_hInstance; +namespace NFar { + +const char *g_PluginName_for_Error = "7-Zip"; + +} + #define NT_CHECK_FAIL_ACTION return FALSE; BOOL WINAPI DllMain( @@ -42,9 +49,14 @@ BOOL WINAPI DllMain( { if (dwReason == DLL_PROCESS_ATTACH) { + // OutputDebugStringA("7-Zip FAR DLL_PROCESS_ATTACH"); g_hInstance = (HINSTANCE)hInstance; NT_CHECK } + if (dwReason == DLL_PROCESS_DETACH) + { + // OutputDebugStringA("7-Zip FAR DLL_PROCESS_DETACH"); + } return TRUE; } @@ -55,6 +67,18 @@ static struct COptions static const TCHAR *kPliginNameForRegestry = TEXT("7-ZIP"); +EXTERN_C void WINAPI ExitFAR() +{ + /* WIN32: + it's not allowed to call FreeLibrary() from FreeLibrary(). + So we try to free all DLLs before destructors */ + // OutputDebugStringA("-- ExitFAR --- START"); + + FreeGlobalCodecs(); + + // OutputDebugStringA("-- ExitFAR --- END"); +} + EXTERN_C void WINAPI SetStartupInfo(const PluginStartupInfo *info) { MY_TRY_BEGIN; @@ -62,6 +86,10 @@ EXTERN_C void WINAPI SetStartupInfo(const PluginStartupInfo *info) g_Options.Enabled = g_StartupInfo.QueryRegKeyValue( HKEY_CURRENT_USER, kRegisrtryMainKeyName, kRegisrtryValueNameEnabled, kPluginEnabledDefault); + + // OutputDebugStringA("SetStartupInfo"); + // LoadGlobalCodecs(); + MY_TRY_END1("SetStartupInfo"); } @@ -77,17 +105,8 @@ class COpenArchiveCallback: CProgressBox _progressBox; - UInt64 _numFilesTotal; - UInt64 _numFilesCur; - UInt64 _numBytesTotal; - UInt64 _numBytesCur; - bool _numFilesTotalDefined; - bool _numFilesCurDefined; bool _numBytesTotalDefined; - bool _numBytesCurDefined; - - DWORD m_PrevTickCount; NFind::CFileInfo _fileInfo; public: @@ -123,12 +142,13 @@ public: PasswordIsDefined = false; _numFilesTotalDefined = false; - _numFilesCurDefined = false; _numBytesTotalDefined = false; - _numBytesCurDefined = false; m_MessageBoxIsShown = false; - m_PrevTickCount = GetTickCount(); + + _progressBox.Init( + // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle), + g_StartupInfo.GetMsgString(NMessageID::kReading)); } void ShowMessage(); @@ -140,113 +160,60 @@ public: } }; +static HRESULT CheckBreak2() +{ + return WasEscPressed() ? E_ABORT : S_OK; +} + void COpenArchiveCallback::ShowMessage() { - DWORD currentTime = GetTickCount(); if (!m_MessageBoxIsShown) { - if (currentTime - m_PrevTickCount < 100) + DWORD currentTime = GetTickCount(); + if (currentTime - _progressBox.StartTick < kShowProgressTime_ms) return; - _progressBox.Init( - // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle), - g_StartupInfo.GetMsgString(NMessageID::kReading), 48); - m_MessageBoxIsShown = true; } - else - { - if (currentTime - m_PrevTickCount < 200) - return; - } - m_PrevTickCount = currentTime; - UInt64 total = 0, cur = 0; - bool curIsDefined = false, totalIsDefined = false; - - char message[256]; - message[0] = 0; - if (_numFilesCurDefined) - ConvertUInt64ToStringAligned(_numFilesCur, message, 5); - - if (_numFilesTotalDefined) - { - strcat(message, " / "); - ConvertUInt64ToStringAligned(_numFilesTotal, message + strlen(message), 5); - total = _numFilesTotal; - totalIsDefined = true; - if (_numFilesCurDefined) - { - cur = _numFilesCur; - curIsDefined = true; - } - } - else if (_numBytesTotalDefined) - { - total = _numBytesTotal; - totalIsDefined = true; - if (_numBytesCurDefined) - { - cur = _numBytesCur; - curIsDefined = true; - } - } - _progressBox.Progress( - totalIsDefined ? &total: NULL, - curIsDefined ? &cur: NULL, - message); + _progressBox.UseBytesForPercents = !_numFilesTotalDefined; + _progressBox.Print(); } STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 *numFiles, const UInt64 *numBytes) { - if (WasEscPressed()) - return E_ABORT; - _numFilesTotalDefined = (numFiles != NULL); if (_numFilesTotalDefined) - _numFilesTotal = *numFiles; + _progressBox.FilesTotal = *numFiles; _numBytesTotalDefined = (numBytes != NULL); if (_numBytesTotalDefined) - _numBytesTotal = *numBytes; + _progressBox.Total = *numBytes; - return S_OK; + return CheckBreak2(); } STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 *numFiles, const UInt64 *numBytes) { - if (WasEscPressed()) - return E_ABORT; + if (numFiles) + _progressBox.Files = *numFiles; - _numFilesCurDefined = (numFiles != NULL); - if (_numFilesCurDefined) - _numFilesCur = *numFiles; + if (numBytes) + _progressBox.Completed = *numBytes; - _numBytesCurDefined = (numBytes != NULL); - if (_numBytesCurDefined) - _numBytesCur = *numBytes; - - // if (*numFiles % 100 != 0) - // return S_OK; ShowMessage(); - return S_OK; + return CheckBreak2(); } STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 /* total */) { - if (WasEscPressed()) - return E_ABORT; - return S_OK; + return CheckBreak2(); } -STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 *completed) +STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 * /* completed */) { - if (WasEscPressed()) - return E_ABORT; - if (completed == NULL) - return S_OK; ShowMessage(); - return S_OK; + return CheckBreak2(); } STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **inStream) @@ -303,7 +270,7 @@ HRESULT GetPassword(UString &password) // sprintf(DialogItems[1].Data,GetMsg(MGetPasswordForFile),FileName); if (g_StartupInfo.ShowDialog(76, 6, NULL, dialogItems, kNumItems) < 0) - return (E_ABORT); + return E_ABORT; AString oemPassword = dialogItems[2].Data; password = MultiByteToUnicodeString(oemPassword, CP_OEMCP); @@ -383,26 +350,28 @@ static HANDLE MyOpenFilePluginW(const wchar_t *name) { if (result == E_ABORT) return (HANDLE)-2; + ShowSysErrorMessage(result); return INVALID_HANDLE_VALUE; } UString errorMessage = agent->GetErrorMessage(); if (!errorMessage.IsEmpty()) - PrintErrorMessage("7-Zip", UnicodeStringToMultiByte(errorMessage, CP_OEMCP)); + g_StartupInfo.ShowErrorMessage(UnicodeStringToMultiByte(errorMessage, CP_OEMCP)); // ::OutputDebugStringA("after OpenArchive\n"); CPlugin *plugin = new CPlugin( fullName, // defaultName, - archiveHandler, + agent, (const wchar_t *)archiveType ); - if (plugin == NULL) - return(INVALID_HANDLE_VALUE); + if (!plugin) + return INVALID_HANDLE_VALUE; plugin->PasswordIsDefined = openArchiveCallbackSpec->PasswordIsDefined; plugin->Password = openArchiveCallbackSpec->Password; + // OutputDebugStringA("--- OpenFilePlugin ---- END"); return (HANDLE)(plugin); } @@ -420,6 +389,7 @@ static HANDLE MyOpenFilePlugin(const char *name) EXTERN_C HANDLE WINAPI OpenFilePlugin(char *name, const unsigned char * /* data */, int /* dataSize */) { MY_TRY_BEGIN; + // OutputDebugStringA("--- OpenFilePlugin"); if (name == NULL || (!g_Options.Enabled)) { // if (!Opt.ProcessShiftF1) @@ -474,9 +444,14 @@ EXTERN_C HANDLE WINAPI OpenPlugin(int openFrom, INT_PTR item) case 1: { CObjectVector<PluginPanelItem> pluginPanelItem; - if(!g_StartupInfo.ControlGetActivePanelSelectedOrCurrentItems(pluginPanelItem)) + if (!g_StartupInfo.ControlGetActivePanelSelectedOrCurrentItems(pluginPanelItem)) throw 142134; - if (CompressFiles(pluginPanelItem) == S_OK) + HRESULT res = CompressFiles(pluginPanelItem); + if (res != S_OK && res != E_ABORT) + { + ShowSysErrorMessage(res); + } + // if (res == S_OK) { /* int t = */ g_StartupInfo.ControlClearPanelSelection(); g_StartupInfo.ControlRequestActivePanel(FCTL_UPDATEPANEL, NULL); @@ -496,8 +471,10 @@ EXTERN_C HANDLE WINAPI OpenPlugin(int openFrom, INT_PTR item) EXTERN_C void WINAPI ClosePlugin(HANDLE plugin) { + // OutputDebugStringA("-- ClosePlugin --- START"); MY_TRY_BEGIN; delete (CPlugin *)plugin; + // OutputDebugStringA("-- ClosePlugin --- END"); MY_TRY_END1("ClosePlugin"); } @@ -599,14 +576,14 @@ EXTERN_C void WINAPI GetOpenPluginInfo(HANDLE plugin,struct OpenPluginInfo *info EXTERN_C int WINAPI PutFiles(HANDLE plugin, struct PluginPanelItem *panelItems, int itemsNumber, int move, int opMode) { MY_TRY_BEGIN; - return(((CPlugin *)plugin)->PutFiles(panelItems, itemsNumber, move, opMode)); + return (((CPlugin *)plugin)->PutFiles(panelItems, itemsNumber, move, opMode)); MY_TRY_END2("PutFiles", NFileOperationReturnCode::kError); } EXTERN_C int WINAPI DeleteFiles(HANDLE plugin, PluginPanelItem *panelItems, int itemsNumber, int opMode) { MY_TRY_BEGIN; - return(((CPlugin *)plugin)->DeleteFiles(panelItems, itemsNumber, opMode)); + return (((CPlugin *)plugin)->DeleteFiles(panelItems, itemsNumber, opMode)); MY_TRY_END2("DeleteFiles", FALSE); } diff --git a/CPP/7zip/UI/Far/Far.def b/CPP/7zip/UI/Far/Far.def index 39f3a5e2..1de9acdf 100644 --- a/CPP/7zip/UI/Far/Far.def +++ b/CPP/7zip/UI/Far/Far.def @@ -3,6 +3,7 @@ LIBRARY "7-ZipFar" EXPORTS + ExitFAR SetStartupInfo OpenPlugin OpenFilePlugin diff --git a/CPP/7zip/UI/Far/Far.dsp b/CPP/7zip/UI/Far/Far.dsp index bd50fd93..26365152 100644 --- a/CPP/7zip/UI/Far/Far.dsp +++ b/CPP/7zip/UI/Far/Far.dsp @@ -43,7 +43,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /YX /FD /c -# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /D "EXTERNAL_CODECS" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /D "EXTERNAL_CODECS" /D "NEW_FOLDER_INTERFACE" /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -70,7 +70,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /D "EXTERNAL_CODECS" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /D "EXTERNAL_CODECS" /D "NEW_FOLDER_INTERFACE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -342,6 +342,14 @@ SOURCE=..\..\..\Windows\Registry.h # End Source File # Begin Source File +SOURCE=..\..\..\Windows\ResourceString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ResourceString.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File @@ -526,6 +534,18 @@ SOURCE=..\Agent\AgentProxy.h # End Source File # Begin Source File +SOURCE=..\Agent\ArchiveFolder.cpp +# End Source File +# Begin Source File + +SOURCE=..\Agent\ArchiveFolderOpen.cpp +# End Source File +# Begin Source File + +SOURCE=..\Agent\ArchiveFolderOut.cpp +# End Source File +# Begin Source File + SOURCE=..\Agent\IFolderArchive.h # End Source File # Begin Source File @@ -554,6 +574,14 @@ SOURCE=..\..\Compress\CopyCoder.h # PROP Default_Filter "" # Begin Source File +SOURCE=..\..\Common\CreateCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CreateCoder.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\FilePathAutoRename.cpp # End Source File # Begin Source File @@ -570,6 +598,14 @@ SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File +SOURCE=..\..\Common\FilterCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilterCoder.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\LimitedStreams.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/UI/Far/FarPlugin.h b/CPP/7zip/UI/Far/FarPlugin.h index a6185a1d..859d319f 100644 --- a/CPP/7zip/UI/Far/FarPlugin.h +++ b/CPP/7zip/UI/Far/FarPlugin.h @@ -104,18 +104,27 @@ typedef int (WINAPI *FARAPIDIALOG)( ); enum { - FMSG_WARNING=1, - FMSG_ERRORTYPE=2, - FMSG_KEEPBACKGROUND=4, - FMSG_DOWN=8, - FMSG_LEFTALIGN=16 + FMSG_WARNING = 0x00000001, + FMSG_ERRORTYPE = 0x00000002, + FMSG_KEEPBACKGROUND = 0x00000004, + FMSG_DOWN = 0x00000008, + FMSG_LEFTALIGN = 0x00000010, + + FMSG_ALLINONE = 0x00000020, + + FMSG_MB_OK = 0x00010000, + FMSG_MB_OKCANCEL = 0x00020000, + FMSG_MB_ABORTRETRYIGNORE = 0x00030000, + FMSG_MB_YESNO = 0x00040000, + FMSG_MB_YESNOCANCEL = 0x00050000, + FMSG_MB_RETRYCANCEL = 0x00060000 }; typedef int (WINAPI *FARAPIMESSAGE)( INT_PTR PluginNumber, unsigned int Flags, - char *HelpTopic, - char **Items, + const char *HelpTopic, + const char * const *Items, int ItemsNumber, int ButtonsNumber ); @@ -424,21 +433,22 @@ struct OpenPluginInfo { int StructSize; DWORD Flags; - char *HostFile; - char *CurDir; - char *Format; - char *PanelTitle; - struct InfoPanelLine *InfoLines; + const char *HostFile; + const char *CurDir; + const char *Format; + const char *PanelTitle; + const struct InfoPanelLine *InfoLines; int InfoLinesNumber; - char **DescrFiles; + const char * const *DescrFiles; int DescrFilesNumber; - struct PanelMode *PanelModesArray; + const struct PanelMode *PanelModesArray; int PanelModesNumber; int StartPanelMode; int StartSortMode; int StartSortOrder; - struct KeyBarTitles *KeyBar; - char *ShortcutData; + const struct KeyBarTitles *KeyBar; + const char *ShortcutData; + // long Reserverd; }; enum { diff --git a/CPP/7zip/UI/Far/FarUtils.cpp b/CPP/7zip/UI/Far/FarUtils.cpp index 14343522..28a4ada9 100644 --- a/CPP/7zip/UI/Far/FarUtils.cpp +++ b/CPP/7zip/UI/Far/FarUtils.cpp @@ -2,6 +2,7 @@ #include "StdAfx.h" +#include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #ifndef UNDER_CE @@ -35,8 +36,8 @@ const char *CStartupInfo::GetMsgString(int messageId) int CStartupInfo::ShowMessage(unsigned int flags, const char *helpTopic, const char **items, int numItems, int numButtons) { - return m_Data.Message(m_Data.ModuleNumber, flags, (char *)helpTopic, - (char **)items, numItems, numButtons); + return m_Data.Message(m_Data.ModuleNumber, flags, helpTopic, + items, numItems, numButtons); } namespace NMessageID @@ -50,12 +51,40 @@ namespace NMessageID }; } -int CStartupInfo::ShowMessage(const char *message) +int CStartupInfo::ShowWarningWithOk(const char **items, int numItems) { - const char *items[]= { GetMsgString(NMessageID::kError), message, GetMsgString(NMessageID::kOk) }; - return ShowMessage(FMSG_WARNING, NULL, items, ARRAY_SIZE(items), 1); + return ShowMessage(FMSG_WARNING | FMSG_MB_OK, NULL, items, numItems, 0); } +extern const char *g_PluginName_for_Error; + +void CStartupInfo::SetErrorTitle(AString &s) +{ + if (g_PluginName_for_Error) + { + s += g_PluginName_for_Error; + s += ": "; + } + s += GetMsgString(NMessageID::kError); +} + +int CStartupInfo::ShowErrorMessage(const char *message) +{ + AString s; + SetErrorTitle(s); + const char *items[]= { s, message }; + return ShowWarningWithOk(items, ARRAY_SIZE(items)); +} + +int CStartupInfo::ShowErrorMessage2(const char *m1, const char *m2) +{ + AString s; + SetErrorTitle(s); + const char *items[]= { s, m1, m2 }; + return ShowWarningWithOk(items, ARRAY_SIZE(items)); +} + +/* static void SplitString(const AString &srcString, AStringVector &destStrings) { destStrings.Clear(); @@ -80,7 +109,9 @@ static void SplitString(const AString &srcString, AStringVector &destStrings) if (!string.IsEmpty()) destStrings.Add(string); } +*/ +/* int CStartupInfo::ShowMessageLines(const char *message) { AStringVector strings; @@ -94,10 +125,22 @@ int CStartupInfo::ShowMessageLines(const char *message) return ShowMessage(FMSG_WARNING, NULL, items, pos, 1); } +*/ + +/* +int CStartupInfo::ShowMessageLines(const char *message) +{ + AString s = GetMsgString(NMessageID::kError); + s.Add_LF(); + s += message; + return ShowMessage(FMSG_WARNING | FMSG_MB_OK | FMSG_ALLINONE, NULL, + (const char **)(const char *)s, 1, 0); +} +*/ int CStartupInfo::ShowMessage(int messageId) { - return ShowMessage(GetMsgString(messageId)); + return ShowErrorMessage(GetMsgString(messageId)); } int CStartupInfo::ShowDialog(int X1, int Y1, int X2, int Y2, @@ -129,14 +172,14 @@ void CStartupInfo::InitDialogItems(const CInitDialogItem *srcItems, destItem.X2 = srcItem.X2; destItem.Y2 = srcItem.Y2; destItem.Focus = GetBOOLValue(srcItem.Focus); - if(srcItem.HistoryName != NULL) + if (srcItem.HistoryName != NULL) destItem.History = srcItem.HistoryName; else destItem.Selected = GetBOOLValue(srcItem.Selected); destItem.Flags = srcItem.Flags; destItem.DefaultButton = GetBOOLValue(srcItem.DefaultButton); - if(srcItem.DataMessageId < 0) + if (srcItem.DataMessageId < 0) MyStringCopy(destItem.Data, srcItem.DataString); else MyStringCopy(destItem.Data, GetMsgString(srcItem.DataMessageId)); @@ -220,7 +263,7 @@ CSysString CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyN return valueDefault; CSysString value; - if(regKey.QueryValue(valueName, value) != ERROR_SUCCESS) + if (regKey.QueryValue(valueName, value) != ERROR_SUCCESS) return valueDefault; return value; @@ -234,7 +277,7 @@ UInt32 CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyName, return valueDefault; UInt32 value; - if(regKey.QueryValue(valueName, value) != ERROR_SUCCESS) + if (regKey.QueryValue(valueName, value) != ERROR_SUCCESS) return valueDefault; return value; @@ -248,7 +291,7 @@ bool CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyName, return valueDefault; bool value; - if(regKey.QueryValue(valueName, value) != ERROR_SUCCESS) + if (regKey.QueryValue(valueName, value) != ERROR_SUCCESS) return valueDefault; return value; @@ -278,9 +321,9 @@ bool CStartupInfo::ControlGetActivePanelCurrentItemInfo( PluginPanelItem &pluginPanelItem) { PanelInfo panelInfo; - if(!ControlGetActivePanelInfo(panelInfo)) + if (!ControlGetActivePanelInfo(panelInfo)) return false; - if(panelInfo.ItemsNumber <= 0) + if (panelInfo.ItemsNumber <= 0) throw "There are no items"; pluginPanelItem = panelInfo.PanelItems[panelInfo.CurrentItem]; return true; @@ -291,9 +334,9 @@ bool CStartupInfo::ControlGetActivePanelSelectedOrCurrentItems( { pluginPanelItems.Clear(); PanelInfo panelInfo; - if(!ControlGetActivePanelInfo(panelInfo)) + if (!ControlGetActivePanelInfo(panelInfo)) return false; - if(panelInfo.ItemsNumber <= 0) + if (panelInfo.ItemsNumber <= 0) throw "There are no items"; if (panelInfo.SelectedItemsNumber == 0) pluginPanelItems.Add(panelInfo.PanelItems[panelInfo.CurrentItem]); @@ -306,7 +349,7 @@ bool CStartupInfo::ControlGetActivePanelSelectedOrCurrentItems( bool CStartupInfo::ControlClearPanelSelection() { PanelInfo panelInfo; - if(!ControlGetActivePanelInfo(panelInfo)) + if (!ControlGetActivePanelInfo(panelInfo)) return false; for (int i = 0; i < panelInfo.ItemsNumber; i++) panelInfo.PanelItems[i].Flags &= ~PPIF_SELECTED; @@ -375,7 +418,7 @@ CScreenRestorer::~CScreenRestorer() } void CScreenRestorer::Save() { - if(m_Saved) + if (m_Saved) return; m_HANDLE = g_StartupInfo.SaveScreen(); m_Saved = true; @@ -383,41 +426,67 @@ void CScreenRestorer::Save() void CScreenRestorer::Restore() { - if(m_Saved) + if (m_Saved) { g_StartupInfo.RestoreScreen(m_HANDLE); m_Saved = false; } }; -static AString DWORDToString(DWORD number) +int PrintErrorMessage(const char *message, unsigned code) { - char buffer[32]; - _ultoa(number, buffer, 10); - return buffer; + AString s = message; + s += " #"; + char temp[16]; + ConvertUInt32ToString((UInt32)code, temp); + s += temp; + return g_StartupInfo.ShowErrorMessage(s); } -void PrintErrorMessage(const char *message, int code) +int PrintErrorMessage(const char *message, const char *text) { - AString tmp = message; - tmp += " #"; - tmp += DWORDToString(code); - g_StartupInfo.ShowMessage(tmp); + return g_StartupInfo.ShowErrorMessage2(message, text); } -void PrintErrorMessage(const char *message, const char *text) + +static void ReduceString(UString &s, unsigned size) { - AString tmp = message; - tmp += ":\n"; - tmp += text; - g_StartupInfo.ShowMessageLines(tmp); + if (s.Len() > size) + { + if (size > 5) + size -= 5; + s.Delete(size / 2, s.Len() - size); + s.Insert(size / 2, L" ... "); + } } -void PrintErrorMessage(const char *message, const wchar_t *text) +int PrintErrorMessage(const char *message, const wchar_t *name, unsigned maxLen) { - PrintErrorMessage(message, UnicodeStringToMultiByte(text, CP_OEMCP)); + UString s = name; + ReduceString(s, maxLen); + return PrintErrorMessage(message, UnicodeStringToMultiByte(s, CP_OEMCP)); } +int ShowSysErrorMessage(DWORD errorCode) +{ + UString message = NError::MyFormatMessage(errorCode); + return g_StartupInfo.ShowErrorMessage(UnicodeStringToMultiByte(message, CP_OEMCP)); +} + +int ShowLastErrorMessage() +{ + return ShowSysErrorMessage(::GetLastError()); +} + +int ShowSysErrorMessage(DWORD errorCode, const wchar_t *name) +{ + UString s = NError::MyFormatMessage(errorCode); + AString s1 = UnicodeStringToMultiByte(s, CP_OEMCP); + AString s2 = UnicodeStringToMultiByte(name, CP_OEMCP); + return g_StartupInfo.ShowErrorMessage2(s1, s2); +} + + bool WasEscPressed() { #ifdef UNDER_CE @@ -425,19 +494,19 @@ bool WasEscPressed() #else NConsole::CIn inConsole; HANDLE handle = ::GetStdHandle(STD_INPUT_HANDLE); - if(handle == INVALID_HANDLE_VALUE) + if (handle == INVALID_HANDLE_VALUE) return true; inConsole.Attach(handle); for (;;) { DWORD numEvents; - if(!inConsole.GetNumberOfEvents(numEvents)) + if (!inConsole.GetNumberOfEvents(numEvents)) return true; - if(numEvents == 0) + if (numEvents == 0) return false; INPUT_RECORD event; - if(!inConsole.ReadEvent(event, numEvents)) + if (!inConsole.ReadEvent(event, numEvents)) return true; if (event.EventType == KEY_EVENT && event.Event.KeyEvent.bKeyDown && @@ -447,17 +516,4 @@ bool WasEscPressed() #endif } -void ShowErrorMessage(DWORD errorCode) -{ - UString message = NError::MyFormatMessage(errorCode); - message.RemoveChar(L'\x0D'); - message.Replace(L'\x0A', L' '); - g_StartupInfo.ShowMessage(UnicodeStringToMultiByte(message, CP_OEMCP)); -} - -void ShowLastErrorMessage() -{ - ShowErrorMessage(::GetLastError()); -} - } diff --git a/CPP/7zip/UI/Far/FarUtils.h b/CPP/7zip/UI/Far/FarUtils.h index 1a5a49c7..edec4cf9 100644 --- a/CPP/7zip/UI/Far/FarUtils.h +++ b/CPP/7zip/UI/Far/FarUtils.h @@ -59,10 +59,15 @@ public: void Init(const PluginStartupInfo &pluginStartupInfo, const CSysString &pluginNameForRegestry); const char *GetMsgString(int messageId); + int ShowMessage(unsigned int flags, const char *helpTopic, const char **items, int numItems, int numButtons); - int ShowMessage(const char *message); - int ShowMessageLines(const char *message); + int ShowWarningWithOk(const char **items, int numItems); + + void SetErrorTitle(AString &s); + int ShowErrorMessage(const char *message); + int ShowErrorMessage2(const char *m1, const char *m2); + // int ShowMessageLines(const char *messageLines); int ShowMessage(int messageId); int ShowDialog(int X1, int Y1, int X2, int Y2, @@ -158,30 +163,32 @@ public: extern CStartupInfo g_StartupInfo; -void PrintErrorMessage(const char *message, int code); -void PrintErrorMessage(const char *message, const char *text); -void PrintErrorMessage(const char *message, const wchar_t *text); -#define MY_TRY_BEGIN try\ - { +int PrintErrorMessage(const char *message, unsigned code); +int PrintErrorMessage(const char *message, const char *text); +int PrintErrorMessage(const char *message, const wchar_t *name, unsigned maxLen = 70); -#define MY_TRY_END1(x) }\ - catch(int n) { PrintErrorMessage(x, n); return; }\ +#define MY_TRY_BEGIN try { + +#define MY_TRY_END1(x) }\ + catch(unsigned n) { PrintErrorMessage(x, n); return; }\ catch(const CSysString &s) { PrintErrorMessage(x, s); return; }\ catch(const char *s) { PrintErrorMessage(x, s); return; }\ - catch(...) { g_StartupInfo.ShowMessage(x); return; } + catch(...) { g_StartupInfo.ShowErrorMessage(x); return; } -#define MY_TRY_END2(x, y) }\ - catch(int n) { PrintErrorMessage(x, n); return y; }\ +#define MY_TRY_END2(x, y) }\ + catch(unsigned n) { PrintErrorMessage(x, n); return y; }\ catch(const AString &s) { PrintErrorMessage(x, s); return y; }\ catch(const char *s) { PrintErrorMessage(x, s); return y; }\ catch(const UString &s) { PrintErrorMessage(x, s); return y; }\ catch(const wchar_t *s) { PrintErrorMessage(x, s); return y; }\ - catch(...) { g_StartupInfo.ShowMessage(x); return y; } + catch(...) { g_StartupInfo.ShowErrorMessage(x); return y; } + +int ShowSysErrorMessage(DWORD errorCode); +int ShowSysErrorMessage(DWORD errorCode, const wchar_t *name); +int ShowLastErrorMessage(); bool WasEscPressed(); -void ShowErrorMessage(DWORD errorCode); -void ShowLastErrorMessage(); } diff --git a/CPP/7zip/UI/Far/Plugin.cpp b/CPP/7zip/UI/Far/Plugin.cpp index bebd47de..8df7b512 100644 --- a/CPP/7zip/UI/Far/Plugin.cpp +++ b/CPP/7zip/UI/Far/Plugin.cpp @@ -27,14 +27,15 @@ int CompareFileNames_ForFolderList(const wchar_t *s1, const wchar_t *s2) } -CPlugin::CPlugin(const FString &fileName, IInFolderArchive *archiveHandler, UString archiveTypeName): - m_ArchiveHandler(archiveHandler), +CPlugin::CPlugin(const FString &fileName, CAgent *agent, UString archiveTypeName): + _agent(agent), m_FileName(fileName), _archiveTypeName(archiveTypeName) { + m_ArchiveHandler = agent; if (!m_FileInfo.Find(m_FileName)) throw "error"; - archiveHandler->BindToRootFolder(&_folder); + m_ArchiveHandler->BindToRootFolder(&_folder); } CPlugin::~CPlugin() {} @@ -194,7 +195,7 @@ void CPlugin::EnterToDirectory(const UString &dirName) if (dirName == kDotsReplaceStringU) s = L".."; _folder->BindToFolder(s, &newFolder); - if (newFolder == NULL) + if (!newFolder) if (dirName.IsEmpty()) return; else @@ -214,7 +215,7 @@ int CPlugin::SetDirectory(const char *aszDir, int /* opMode */) { CMyComPtr<IFolderFolder> newFolder; _folder->BindToParentFolder(&newFolder); - if (newFolder == NULL) + if (!newFolder) throw 40312; _folder = newFolder; } @@ -245,7 +246,7 @@ void CPlugin::GetPathParts(UStringVector &pathParts) { CMyComPtr<IFolderFolder> newFolder; folderItem->BindToParentFolder(&newFolder); - if (newFolder == NULL) + if (!newFolder) break; NCOM::CPropVariant prop; if (folderItem->GetFolderProperty(kpidName, &prop) == S_OK) @@ -258,16 +259,29 @@ void CPlugin::GetPathParts(UStringVector &pathParts) void CPlugin::SetCurrentDirVar() { m_CurrentDir.Empty(); + + /* + // kpidPath path has tail slash, but we don't need it for compatibility with default FAR style + NCOM::CPropVariant prop; + if (_folder->GetFolderProperty(kpidPath, &prop) == S_OK) + if (prop.vt == VT_BSTR) + { + m_CurrentDir = (wchar_t *)prop.bstrVal; + // if (!m_CurrentDir.IsEmpty()) + } + m_CurrentDir.InsertAtFront(WCHAR_PATH_SEPARATOR); + */ + UStringVector pathParts; GetPathParts(pathParts); FOR_VECTOR (i, pathParts) { - m_CurrentDir += WCHAR_PATH_SEPARATOR; + m_CurrentDir.Add_PathSepar(); m_CurrentDir += pathParts[i]; } } -static char *kPluginFormatName = "7-ZIP"; +static const char *kPluginFormatName = "7-ZIP"; static int FindPropNameID(PROPID propID) @@ -290,19 +304,19 @@ static CPropertyIDInfo kPropertyIDInfos[] = { { kpidName, "N", 0}, { kpidSize, "S", 8}, - { kpidPackedSize, "P", 8}, + { kpidPackSize, "P", 8}, { kpidAttrib, "A", 0}, { kpidCTime, "DC", 14}, { kpidATime, "DA", 14}, { kpidMTime, "DM", 14}, { kpidSolid, NULL, 0, 'S'}, - { kpidEncrypted, NULL, 0, 'P'} + { kpidEncrypted, NULL, 0, 'P'}, { kpidDictionarySize, IDS_PROPERTY_DICTIONARY_SIZE }, { kpidSplitBefore, NULL, 'B'}, { kpidSplitAfter, NULL, 'A'}, - { kpidComment, , NULL, 'C'}, + { kpidComment, NULL, 'C'}, { kpidCRC, IDS_PROPERTY_CRC } // { kpidType, L"Type" } }; @@ -394,17 +408,20 @@ static AString ConvertSizeToString(UInt64 value) static AString PropToString(const NCOM::CPropVariant &prop, PROPID propID) { - AString s; - if (prop.vt == VT_BSTR) - s = UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP); - else if (prop.vt == VT_BOOL) + { + AString s = UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP); + s.Replace((char)0xA, ' '); + s.Replace((char)0xD, ' '); + return s; + } + if (prop.vt == VT_BOOL) { int messageID = VARIANT_BOOLToBool(prop.boolVal) ? NMessageID::kYes : NMessageID::kNo; return g_StartupInfo.GetMsgString(messageID); } - else if (prop.vt != VT_EMPTY) + if (prop.vt != VT_EMPTY) { if ((prop.vt == VT_UI8 || prop.vt == VT_UI4) && ( propID == kpidSize || @@ -420,18 +437,15 @@ static AString PropToString(const NCOM::CPropVariant &prop, PROPID propID) { UInt64 v = 0; ConvertPropVariantToUInt64(prop, v); - s = ConvertSizeToString(v); + return ConvertSizeToString(v); } - else { - UString temp; - ConvertPropertyToString(temp, prop, propID); - s = UnicodeStringToMultiByte(temp, CP_OEMCP); + char sz[64]; + ConvertPropertyToShortString(sz, prop, propID); + return sz; } } - s.Replace((char)0xA, ' '); - s.Replace((char)0xD, ' '); - return s; + return AString(); } static AString PropToString2(const NCOM::CPropVariant &prop, PROPID propID) @@ -489,12 +503,11 @@ void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info) name = fs2us(fileName); } - m_PannelTitle = - UString(L' ') + - _archiveTypeName + - UString(L':') + - name + - UString(L' '); + m_PannelTitle = L' '; + m_PannelTitle += _archiveTypeName; + m_PannelTitle += L':'; + m_PannelTitle += name; + m_PannelTitle.Add_Space(); if (!m_CurrentDir.IsEmpty()) { // m_PannelTitle += '\\'; @@ -629,25 +642,25 @@ void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info) /* AddColumn(kpidName); AddColumn(kpidSize); - AddColumn(kpidPackedSize); + AddColumn(kpidPackSize); AddColumn(kpidMTime); AddColumn(kpidCTime); AddColumn(kpidATime); AddColumn(kpidAttrib); - PanelMode.ColumnTypes = (char *)(const char *)PanelModeColumnTypes; - PanelMode.ColumnWidths = (char *)(const char *)PanelModeColumnWidths; - PanelMode.ColumnTitles = NULL; - PanelMode.FullScreen = TRUE; - PanelMode.DetailedStatus = FALSE; - PanelMode.AlignExtensions = FALSE; - PanelMode.CaseConversion = FALSE; - PanelMode.StatusColumnTypes = "N"; - PanelMode.StatusColumnWidths = "0"; - PanelMode.Reserved[0] = 0; - PanelMode.Reserved[1] = 0; - - info->PanelModesArray = &PanelMode; + _PanelMode.ColumnTypes = (char *)(const char *)PanelModeColumnTypes; + _PanelMode.ColumnWidths = (char *)(const char *)PanelModeColumnWidths; + _PanelMode.ColumnTitles = NULL; + _PanelMode.FullScreen = TRUE; + _PanelMode.DetailedStatus = FALSE; + _PanelMode.AlignExtensions = FALSE; + _PanelMode.CaseConversion = FALSE; + _PanelMode.StatusColumnTypes = "N"; + _PanelMode.StatusColumnWidths = "0"; + _PanelMode.Reserved[0] = 0; + _PanelMode.Reserved[1] = 0; + + info->PanelModesArray = &_PanelMode; info->PanelModesNumber = 1; */ @@ -667,6 +680,11 @@ struct CArchiveItemProperty VARTYPE Type; }; +static inline char GetHex(Byte value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + HRESULT CPlugin::ShowAttributesWindow() { PluginPanelItem pluginPanelItem; @@ -691,7 +709,7 @@ HRESULT CPlugin::ShowAttributesWindow() prop.Type = vt; prop.ID = propID; if (prop.ID == kpidPath) - prop.ID = kpidName; + prop.ID = kpidName; prop.Name = GetNameOfProp(propID, name); properties.Add(prop); } @@ -705,12 +723,16 @@ HRESULT CPlugin::ShowAttributesWindow() initDialogItems.Add(idi); AStringVector values; + const int kStartY = 3; + for (i = 0; i < properties.Size(); i++) { const CArchiveItemProperty &property = properties[i]; + int startY = kStartY + values.Size(); + CInitDialogItem idi = - { DI_TEXT, 5, 3 + i, 0, 0, false, false, 0, false, 0, NULL, NULL }; + { DI_TEXT, 5, startY, 0, 0, false, false, 0, false, 0, NULL, NULL }; idi.DataMessageId = FindPropNameID(property.ID); if (idi.DataMessageId < 0) idi.DataString = property.Name; @@ -723,11 +745,91 @@ HRESULT CPlugin::ShowAttributesWindow() { CInitDialogItem idi = - { DI_TEXT, 30, 3 + i, 0, 0, false, false, 0, false, -1, NULL, NULL }; + { DI_TEXT, 30, startY, 0, 0, false, false, 0, false, -1, NULL, NULL }; initDialogItems.Add(idi); } } + CMyComPtr<IArchiveGetRawProps> _folderRawProps; + _folder.QueryInterface(IID_IArchiveGetRawProps, &_folderRawProps); + + CObjectVector<CArchiveItemProperty> properties2; + + if (_folderRawProps) + { + _folderRawProps->GetNumRawProps(&numProps); + + for (i = 0; i < numProps; i++) + { + CMyComBSTR name; + PROPID propID; + if (_folderRawProps->GetRawPropInfo(i, &name, &propID) != S_OK) + continue; + CArchiveItemProperty prop; + prop.Type = VT_EMPTY; + prop.ID = propID; + if (prop.ID == kpidPath) + prop.ID = kpidName; + prop.Name = GetNameOfProp(propID, name); + properties2.Add(prop); + } + + for (unsigned i = 0; i < properties2.Size(); i++) + { + const CArchiveItemProperty &property = properties2[i]; + CMyComBSTR name; + + const void *data; + UInt32 dataSize; + UInt32 propType; + if (_folderRawProps->GetRawProp(itemIndex, property.ID, &data, &dataSize, &propType) != S_OK) + continue; + + if (dataSize != 0) + { + AString s; + if (property.ID == kpidNtSecure) + ConvertNtSecureToString((const Byte *)data, dataSize, s); + else + { + const UInt32 kMaxDataSize = 64; + if (dataSize > kMaxDataSize) + { + char temp[64]; + s += "data:"; + ConvertUInt32ToString(dataSize, temp); + s += temp; + } + else + { + for (UInt32 i = 0; i < dataSize; i++) + { + Byte b = ((const Byte *)data)[i]; + s += GetHex((Byte)((b >> 4) & 0xF)); + s += GetHex((Byte)(b & 0xF)); + } + } + } + + int startY = kStartY + values.Size(); + CInitDialogItem idi = + { DI_TEXT, 5, startY, 0, 0, false, false, 0, false, 0, NULL, NULL }; + idi.DataMessageId = FindPropNameID(property.ID); + if (idi.DataMessageId < 0) + idi.DataString = property.Name; + initDialogItems.Add(idi); + + values.Add(s); + + { + CInitDialogItem idi = + { DI_TEXT, 30, startY, 0, 0, false, false, 0, false, -1, NULL, NULL }; + initDialogItems.Add(idi); + } + } + } + } + unsigned numLines = values.Size(); for (i = 0; i < numLines; i++) { @@ -741,6 +843,7 @@ HRESULT CPlugin::ShowAttributesWindow() g_StartupInfo.InitDialogItems(&initDialogItems.Front(), dialogItems, numDialogItems); unsigned maxLen = 0; + for (i = 0; i < numLines; i++) { FarDialogItem &dialogItem = dialogItems[1 + i * 2]; @@ -748,8 +851,10 @@ HRESULT CPlugin::ShowAttributesWindow() if (len > maxLen) maxLen = len; } + unsigned maxLen2 = 0; const unsigned kSpace = 10; + for (i = 0; i < numLines; i++) { FarDialogItem &dialogItem = dialogItems[1 + i * 2 + 1]; @@ -758,6 +863,7 @@ HRESULT CPlugin::ShowAttributesWindow() maxLen2 = len; dialogItem.X1 = maxLen + kSpace; } + size = numLines + 6; xSize = maxLen + kSpace + maxLen2 + 5; FarDialogItem &firstDialogItem = dialogItems[0]; @@ -770,6 +876,12 @@ HRESULT CPlugin::ShowAttributesWindow() int CPlugin::ProcessKey(int key, unsigned int controlState) { + if (key == VK_F7 && controlState == 0) + { + CreateFolder(); + return TRUE; + } + if (controlState == PKF_CONTROL && key == 'A') { HRESULT result = ShowAttributesWindow(); @@ -779,6 +891,7 @@ int CPlugin::ProcessKey(int key, unsigned int controlState) return FALSE; throw "Error"; } + if ((controlState & PKF_ALT) != 0 && key == VK_F6) { FString folderPath; diff --git a/CPP/7zip/UI/Far/Plugin.h b/CPP/7zip/UI/Far/Plugin.h index f01dc435..1fe190e4 100644 --- a/CPP/7zip/UI/Far/Plugin.h +++ b/CPP/7zip/UI/Far/Plugin.h @@ -5,13 +5,13 @@ #include "../../../Common/MyCom.h" -#include "../../../Windows/COM.h" +// #include "../../../Windows/COM.h" #include "../../../Windows/FileFind.h" #include "../../../Windows/PropVariant.h" #include "../Common/WorkDir.h" -#include "../Agent/IFolderArchive.h" +#include "../Agent/Agent.h" #include "FarUtils.h" @@ -19,10 +19,18 @@ const UInt32 kNumInfoLinesMax = 64; class CPlugin { - NWindows::NCOM::CComInitializer m_ComInitializer; + CAgent *_agent; + CMyComPtr<IInFolderArchive> m_ArchiveHandler; + CMyComPtr<IFolderFolder> _folder; + + // NWindows::NCOM::CComInitializer m_ComInitializer; UString m_CurrentDir; UString m_PannelTitle; + FString m_FileName; + NWindows::NFile::NFind::CFileInfo m_FileInfo; + + UString _archiveTypeName; InfoPanelLine m_InfoLines[kNumInfoLinesMax]; @@ -32,26 +40,20 @@ class CPlugin AString PanelModeColumnTypes; AString PanelModeColumnWidths; - PanelMode PanelMode; + // PanelMode _PanelMode; void AddColumn(PROPID aPropID); void EnterToDirectory(const UString &dirName); void GetPathParts(UStringVector &pathParts); void SetCurrentDirVar(); - HRESULT AfterUpdate(CWorkDirTempFile &tempFile, const UStringVector &pathVector); -public: - FString m_FileName; - NWindows::NFile::NFind::CFileInfo m_FileInfo; + // HRESULT AfterUpdate(CWorkDirTempFile &tempFile, const UStringVector &pathVector); - CMyComPtr<IInFolderArchive> m_ArchiveHandler; - CMyComPtr<IFolderFolder> _folder; - - UString _archiveTypeName; +public: bool PasswordIsDefined; UString Password; - CPlugin(const FString &fileName, IInFolderArchive *archiveHandler, UString archiveTypeName); + CPlugin(const FString &fileName, CAgent *agent, UString archiveTypeName); ~CPlugin(); void ReadPluginPanelItem(PluginPanelItem &panelItem, UInt32 itemIndex); @@ -80,6 +82,7 @@ public: NFar::NFileOperationReturnCode::EEnum PutFiles(struct PluginPanelItem *panelItems, int itemsNumber, int move, int opMode); + HRESULT CreateFolder(); HRESULT ShowAttributesWindow(); diff --git a/CPP/7zip/UI/Far/PluginDelete.cpp b/CPP/7zip/UI/Far/PluginDelete.cpp index 1adf91a7..e1a103ac 100644 --- a/CPP/7zip/UI/Far/PluginDelete.cpp +++ b/CPP/7zip/UI/Far/PluginDelete.cpp @@ -14,13 +14,11 @@ int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode) { if (numItems == 0) return FALSE; - /* - if (!m_ArchiverInfo.UpdateEnabled) + if (_agent->IsThereReadOnlyArc()) { g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive); return FALSE; } - */ if ((opMode & OPM_SILENT) == 0) { const char *msgItems[]= @@ -55,21 +53,21 @@ int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode) progressBoxPointer = &progressBox; progressBox.Init( // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle), - g_StartupInfo.GetMsgString(NMessageID::kDeleting), 48); + g_StartupInfo.GetMsgString(NMessageID::kDeleting)); } + /* CWorkDirTempFile tempFile; if (tempFile.CreateTempFile(m_FileName) != S_OK) return FALSE; + */ CObjArray<UInt32> indices(numItems); int i; for (i = 0; i < numItems; i++) indices[i] = (UInt32)panelItems[i].UserData; - //////////////////////////// - // Save _folder; - + /* UStringVector pathVector; GetPathParts(pathVector); @@ -80,13 +78,15 @@ int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode) g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive); return FALSE; } - outArchive->SetFolder(_folder); + */ CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp; CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec); updateCallbackSpec->Init(/* m_ArchiveHandler, */ progressBoxPointer); + /* + outArchive->SetFolder(_folder); result = outArchive->DeleteItems(tempFile.OutStream, indices, numItems, updateCallback); updateCallback.Release(); outArchive.Release(); @@ -95,11 +95,24 @@ int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode) { result = AfterUpdate(tempFile, pathVector); } + */ + + HRESULT result; + { + CMyComPtr<IFolderOperations> folderOperations; + result = _folder.QueryInterface(IID_IFolderOperations, &folderOperations); + if (folderOperations) + result = folderOperations->Delete(indices, numItems, updateCallback); + else if (result != S_OK) + result = E_FAIL; + } + if (result != S_OK) { - ShowErrorMessage(result); + ShowSysErrorMessage(result); return FALSE; } + SetCurrentDirVar(); return TRUE; } diff --git a/CPP/7zip/UI/Far/PluginRead.cpp b/CPP/7zip/UI/Far/PluginRead.cpp index 6e77a9d5..433e8140 100644 --- a/CPP/7zip/UI/Far/PluginRead.cpp +++ b/CPP/7zip/UI/Far/PluginRead.cpp @@ -47,11 +47,11 @@ HRESULT CPlugin::ExtractFiles( progressBoxPointer = &progressBox; progressBox.Init( // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle), - g_StartupInfo.GetMsgString(NMessageID::kExtracting), 48); + g_StartupInfo.GetMsgString(NMessageID::kExtracting)); } - CExtractCallBackImp *extractCallbackSpec = new CExtractCallBackImp; + CExtractCallbackImp *extractCallbackSpec = new CExtractCallbackImp; CMyComPtr<IFolderArchiveExtractCallback> extractCallback(extractCallbackSpec); extractCallbackSpec->Init( @@ -100,7 +100,7 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa NName::NormalizeDirPathPrefix(destPathU); destPath = UnicodeStringToMultiByte(destPathU, CP_OEMCP); - bool extractSelectedFiles = true; + // bool extractSelectedFiles = true; NExtract::CInfo extractionInfo; extractionInfo.PathMode = NExtract::NPathMode::kCurPaths; @@ -211,7 +211,7 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa if (destPathU.Back() == kDirDelimiter) break; } - g_StartupInfo.ShowMessage("You must specify directory path"); + g_StartupInfo.ShowErrorMessage("You must specify directory path"); } if (dialogItems[kPathModeRadioIndex].Selected) @@ -246,9 +246,13 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa extractionInfo.Save(); if (dialogItems[kFilesModeIndex].Selected) - extractSelectedFiles = true; + { + // extractSelectedFiles = true; + } else if (dialogItems[kFilesModeIndex + 1].Selected) - extractSelectedFiles = false; + { + // extractSelectedFiles = false; + } else throw 31806; @@ -278,7 +282,7 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa { if (result == E_ABORT) return NFileOperationReturnCode::kInterruptedByUser; - ShowErrorMessage(result); + ShowSysErrorMessage(result); return NFileOperationReturnCode::kError; } diff --git a/CPP/7zip/UI/Far/PluginWrite.cpp b/CPP/7zip/UI/Far/PluginWrite.cpp index e36f3911..8afba039 100644 --- a/CPP/7zip/UI/Far/PluginWrite.cpp +++ b/CPP/7zip/UI/Far/PluginWrite.cpp @@ -49,6 +49,7 @@ static HRESULT SetOutProperties(IOutFolderArchive *outArchive, UInt32 method) return S_OK; } +/* HRESULT CPlugin::AfterUpdate(CWorkDirTempFile &tempFile, const UStringVector &pathVector) { _folder.Release(); @@ -69,26 +70,28 @@ HRESULT CPlugin::AfterUpdate(CWorkDirTempFile &tempFile, const UStringVector &pa } return S_OK; } +*/ NFileOperationReturnCode::EEnum CPlugin::PutFiles( struct PluginPanelItem *panelItems, int numItems, int moveMode, int opMode) { + /* if (moveMode != 0) { g_StartupInfo.ShowMessage(NMessageID::kMoveIsNotSupported); return NFileOperationReturnCode::kError; } + */ + if (numItems == 0) return NFileOperationReturnCode::kError; - /* - if (!m_ArchiverInfo.UpdateEnabled) + if (_agent->IsThereReadOnlyArc()) { g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive); return NFileOperationReturnCode::kError; } - */ const int kYSize = 14; const int kXMid = 38; @@ -184,7 +187,7 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( progressBoxPointer = &progressBox; progressBox.Init( // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle), - g_StartupInfo.GetMsgString(NMessageID::kUpdating), 48); + g_StartupInfo.GetMsgString(NMessageID::kUpdating)); } UStringVector pathVector; @@ -205,12 +208,12 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive); return NFileOperationReturnCode::kError; } - outArchive->SetFolder(_folder); - outArchive->SetFiles(L"", fileNamePointers, numItems); + /* BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues]; for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) actionSetByte[i] = (BYTE)actionSet->StateActions[i]; + */ CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp; CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec ); @@ -220,6 +223,9 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( if (SetOutProperties(outArchive, compressionInfo.Level) != S_OK) return NFileOperationReturnCode::kError; + /* + outArchive->SetFolder(_folder); + outArchive->SetFiles(L"", fileNamePointers, numItems); // FStringVector requestedPaths; // FStringVector processedPaths; result = outArchive->DoOperation2( @@ -233,28 +239,33 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( { result = AfterUpdate(tempFile, pathVector); } - if (result != S_OK) - { - ShowErrorMessage(result); - return NFileOperationReturnCode::kError; - } + */ - /* - if (moveMode != 0) { - for (int i = 0; i < numItems; i++) + result = _agent->SetFiles(L"", fileNamePointers, numItems); + if (result == S_OK) { - const PluginPanelItem &pluginPanelItem = panelItems[i]; - bool result; - if (NFile::NFind::NAttributes::IsDir(pluginPanelItem.FindData.dwFileAttributes)) - result = NFile::NDirectory::RemoveDirectoryWithSubItems(pluginPanelItem.FindData.cFileName); + CAgentFolder *agentFolder = NULL; + { + CMyComPtr<IArchiveFolderInternal> afi; + _folder.QueryInterface(IID_IArchiveFolderInternal, &afi); + if (afi) + afi->GetAgentFolder(&agentFolder); + } + if (agentFolder) + result = agentFolder->CommonUpdateOperation(AGENT_OP_Uni, + (moveMode != 0), NULL, actionSet, NULL, 0, updateCallback); else - result = NFile::NDirectory::DeleteFileAlways(pluginPanelItem.FindData.cFileName); - if (!result) - return NFileOperationReturnCode::kError; + result = E_FAIL; } } - */ + + if (result != S_OK) + { + ShowSysErrorMessage(result); + return NFileOperationReturnCode::kError; + } + return NFileOperationReturnCode::kSuccess; } @@ -335,11 +346,18 @@ UString CParsedPath::MergePath() const } -/* -// {23170F69-40C1-278A-1000-000100030000} -DEFINE_GUID(CLSID_CAgentArchiveHandler, - 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00); -*/ +static void SetArcName(UString &arcName, const CArcInfoEx &arcInfo) +{ + if (!arcInfo.Flags_KeepName()) + { + int dotPos = arcName.ReverseFind_Dot(); + int slashPos = arcName.ReverseFind_PathSepar(); + if (dotPos > slashPos + 1) + arcName.DeleteFrom(dotPos); + } + arcName += L'.'; + arcName += arcInfo.GetMainExt(); +} HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) { @@ -368,12 +386,20 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) NCompression::CInfo compressionInfo; compressionInfo.Load(); - int archiverIndex = 0; + int archiverIndex = -1; + /* CCodecs *codecs = new CCodecs; CMyComPtr<ICompressCodecsInfo> compressCodecsInfo = codecs; if (codecs->Load() != S_OK) throw "Can't load 7-Zip codecs"; + */ + + if (LoadGlobalCodecs() != S_OK) + throw "Can't load 7-Zip codecs"; + + CCodecs *codecs = g_CodecsObj; + { FOR_VECTOR (i, codecs->Formats) { @@ -388,6 +414,8 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) } } + if (archiverIndex < 0) + throw "there is no output handler"; UString resultPath; { @@ -407,26 +435,18 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) } } UString archiveNameSrc = resultPath; - UString archiveName = archiveNameSrc; + UString arcName = archiveNameSrc; const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex]; int prevFormat = archiverIndex; - if (!arcInfo.Flags_KeepName()) - { - int dotPos = archiveName.ReverseFind('.'); - int slashPos = MyMax(archiveName.ReverseFind('\\'), archiveName.ReverseFind('/')); - if (dotPos > slashPos) - archiveName = archiveName.Left(dotPos); - } - archiveName += L'.'; - archiveName += arcInfo.GetMainExt(); + SetArcName(arcName, arcInfo); const CActionSet *actionSet = &k_ActionSet_Add; for (;;) { - AString archiveNameA = UnicodeStringToMultiByte(archiveName, CP_OEMCP); + AString archiveNameA = UnicodeStringToMultiByte(arcName, CP_OEMCP); const int kYSize = 16; const int kXMid = 38; @@ -458,7 +478,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, -1, updateAddToArchiveString, NULL }, { DI_EDIT, 5, 3, 70, 3, true, false, DIF_HISTORY, false, -1, archiveNameA, kArchiveHistoryKeyName}, - // { DI_EDIT, 5, 3, 70, 3, true, false, 0, false, -1, archiveName, NULL}, + // { DI_EDIT, 5, 3, 70, 3, true, false, 0, false, -1, arcName, NULL}, { DI_SINGLEBOX, 4, 4, kXMid - 2, 4 + 7, false, false, 0, false, NMessageID::kUpdateMethod, NULL, NULL }, @@ -495,7 +515,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) archiveNameA = dialogItems[kArchiveNameIndex].Data; archiveNameA.Trim(); - archiveName = MultiByteToUnicodeString(archiveNameA, CP_OEMCP); + MultiByteToUnicodeString2(arcName, archiveNameA, CP_OEMCP); compressionInfo.Level = g_MethodMap[0]; for (i = 0; i < ARRAY_SIZE(g_MethodMap); i++) @@ -532,15 +552,14 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) { const UString &prevExtension = prevArchiverInfo.GetMainExt(); const unsigned prevExtensionLen = prevExtension.Len(); - if (archiveName.Len() >= prevExtensionLen && - MyStringCompareNoCase(archiveName.RightPtr(prevExtensionLen), prevExtension) == 0) + if (arcName.Len() >= prevExtensionLen && + MyStringCompareNoCase(arcName.RightPtr(prevExtensionLen), prevExtension) == 0) { - int pos = archiveName.Len() - prevExtensionLen; - if (pos > 1) + int pos = arcName.Len() - prevExtensionLen; + if (pos > 2) { - int dotPos = archiveName.ReverseFind('.'); - if (dotPos == pos - 1) - archiveName = archiveName.Left(dotPos); + if (arcName[pos - 1] == '.') + arcName.DeleteFrom(pos - 1); } } } @@ -550,16 +569,8 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) prevFormat = archiverIndex; if (arcInfo.Flags_KeepName()) - archiveName = archiveNameSrc; - else - { - int dotPos = archiveName.ReverseFind('.'); - int slashPos = MyMax(archiveName.ReverseFind('\\'), archiveName.ReverseFind('/')); - if (dotPos > slashPos) - archiveName = archiveName.Left(dotPos); - } - archiveName += L'.'; - archiveName += arcInfo.GetMainExt(); + arcName = archiveNameSrc; + SetArcName(arcName, arcInfo); } continue; } @@ -577,12 +588,12 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) NWorkDir::CInfo workDirInfo; workDirInfo.Load(); - FString fullArchiveName; - if (!MyGetFullPathName(us2fs(archiveName), fullArchiveName)) + FString fullArcName; + if (!MyGetFullPathName(us2fs(arcName), fullArcName)) return E_FAIL; CWorkDirTempFile tempFile; - RINOK(tempFile.CreateTempFile(fullArchiveName)); + RINOK(tempFile.CreateTempFile(fullArcName)); CScreenRestorer screenRestorer; CProgressBox progressBox; @@ -593,7 +604,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) progressBoxPointer = &progressBox; progressBox.Init( // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle), - g_StartupInfo.GetMsgString(NMessageID::kUpdating), 48); + g_StartupInfo.GetMsgString(NMessageID::kUpdating)); NFind::CFileInfo fileInfo; @@ -601,7 +612,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) CMyComPtr<IOutFolderArchive> outArchive; CMyComPtr<IInFolderArchive> archiveHandler; - if (fileInfo.Find(fullArchiveName)) + if (fileInfo.Find(fullArcName)) { if (fileInfo.IsDir()) throw "There is Directory with such name"; @@ -611,7 +622,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) // CLSID realClassID; CMyComBSTR archiveType; RINOK(agentSpec->Open(NULL, - GetUnicodeString(fullArchiveName, CP_OEMCP), UString(), + GetUnicodeString(fullArcName, CP_OEMCP), UString(), // &realClassID, &archiveType, NULL)); @@ -675,7 +686,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) if (result != S_OK) { - ShowErrorMessage(result); + ShowSysErrorMessage(result); return result; } @@ -687,8 +698,122 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) result = tempFile.MoveToOriginal(archiveHandler != NULL); if (result != S_OK) { - ShowErrorMessage(result); + ShowSysErrorMessage(result); + return result; + } + return S_OK; +} + + +static const char *k_CreateFolder_History = "NewFolder"; // we use default FAR folder name + +HRESULT CPlugin::CreateFolder() +{ + if (_agent->IsThereReadOnlyArc()) + { + g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive); + return TRUE; + } + + UString destPathU; + { + const int kXSize = 60; + const int kYSize = 8; + const int kPathIndex = 2; + + AString destPath = "New Folder"; + + const struct CInitDialogItem initItems[]={ + { DI_DOUBLEBOX, 3, 1, kXSize - 4, kYSize - 2, false, false, 0, false, + -1, "Create Folder", NULL }, + + { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, -1, "Folder name:", NULL }, + + { DI_EDIT, 5, 3, kXSize - 6, 3, true, false, DIF_HISTORY, false, -1, destPath, k_CreateFolder_History }, + + { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kOk, NULL, NULL }, + { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kCancel, NULL, NULL } + }; + + const int kNumDialogItems = ARRAY_SIZE(initItems); + const int kOkButtonIndex = kNumDialogItems - 2; + + FarDialogItem dialogItems[kNumDialogItems]; + g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems); + for (;;) + { + int askCode = g_StartupInfo.ShowDialog(kXSize, kYSize, + NULL, // kHelpTopic + dialogItems, kNumDialogItems); + if (askCode != kOkButtonIndex) + return E_ABORT; + destPath = dialogItems[kPathIndex].Data; + destPathU = GetUnicodeString(destPath, CP_OEMCP); + destPathU.Trim(); + if (!destPathU.IsEmpty()) + break; + g_StartupInfo.ShowErrorMessage("You must specify folder name"); + } + + } + + CScreenRestorer screenRestorer; + CProgressBox progressBox; + CProgressBox *progressBoxPointer = NULL; + // if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0) + { + screenRestorer.Save(); + + progressBoxPointer = &progressBox; + progressBox.Init( + // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle), + g_StartupInfo.GetMsgString(NMessageID::kDeleting)); + } + + CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp; + CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec); + + updateCallbackSpec->Init(/* m_ArchiveHandler, */ progressBoxPointer); + + HRESULT result; + { + CMyComPtr<IFolderOperations> folderOperations; + result = _folder.QueryInterface(IID_IFolderOperations, &folderOperations); + if (folderOperations) + result = folderOperations->CreateFolder(destPathU, updateCallback); + else if (result != S_OK) + result = E_FAIL; + } + + if (result != S_OK) + { + ShowSysErrorMessage(result); return result; } + + g_StartupInfo.Control(this, FCTL_UPDATEPANEL, (void *)1); + g_StartupInfo.Control(this, FCTL_REDRAWPANEL, NULL); + + PanelInfo panelInfo; + + if (g_StartupInfo.ControlGetActivePanelInfo(panelInfo)) + { + AString destPath = GetOemString(destPathU); + + for (int i = 0; i < panelInfo.ItemsNumber; i++) + { + const PluginPanelItem &pi = panelInfo.PanelItems[i]; + if (strcmp(destPath, pi.FindData.cFileName) == 0) + { + PanelRedrawInfo panelRedrawInfo; + panelRedrawInfo.CurrentItem = i; + panelRedrawInfo.TopPanelItem = 0; + g_StartupInfo.Control(this, FCTL_REDRAWPANEL, &panelRedrawInfo); + break; + } + } + } + + SetCurrentDirVar(); return S_OK; } diff --git a/CPP/7zip/UI/Far/ProgressBox.cpp b/CPP/7zip/UI/Far/ProgressBox.cpp index 3ad0560a..75467864 100644 --- a/CPP/7zip/UI/Far/ProgressBox.cpp +++ b/CPP/7zip/UI/Far/ProgressBox.cpp @@ -2,112 +2,305 @@ #include "StdAfx.h" -#include <stdio.h> - #include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" #include "FarUtils.h" #include "ProgressBox.h" -static void CopySpaces(char *dest, int numSpaces) +void CPercentPrinterState::ClearCurState() { - int i; - for (i = 0; i < numSpaces; i++) - dest[i] = ' '; - dest[i] = '\0'; + Completed = 0; + Total = ((UInt64)(Int64)-1); + Files = 0; + FilesTotal = 0; + Command.Empty(); + FileName.Empty(); } -void ConvertUInt64ToStringAligned(UInt64 value, char *s, int alignSize) +void CProgressBox::Init(const AString &title) { - char temp[32]; - ConvertUInt64ToString(value, temp); - int len = (int)strlen(temp); - int numSpaces = 0; - if (len < alignSize) + _title = title; + _wasPrinted = false; + StartTick = GetTickCount(); + _prevTick = StartTick; + _prevElapsedSec = 0; +} + +static unsigned GetPower32(UInt32 val) +{ + const unsigned kStart = 32; + UInt32 mask = ((UInt32)1 << (kStart - 1)); + for (unsigned i = kStart;; i--) { - numSpaces = alignSize - len; - CopySpaces(s, numSpaces); + if (i == 0 || (val & mask) != 0) + return i; + mask >>= 1; } - strcpy(s + numSpaces, temp); } +static unsigned GetPower64(UInt64 val) +{ + UInt32 high = (UInt32)(val >> 32); + if (high == 0) + return GetPower32((UInt32)val); + return GetPower32(high) + 32; +} -// ---------- CMessageBox ---------- +static UInt64 MyMultAndDiv(UInt64 mult1, UInt64 mult2, UInt64 divider) +{ + unsigned pow1 = GetPower64(mult1); + unsigned pow2 = GetPower64(mult2); + while (pow1 + pow2 > 64) + { + if (pow1 > pow2) { pow1--; mult1 >>= 1; } + else { pow2--; mult2 >>= 1; } + divider >>= 1; + } + UInt64 res = mult1 * mult2; + if (divider != 0) + res /= divider; + return res; +} -static const int kMaxLen = 255; +#define UINT_TO_STR_2(val) { s[0] = (char)('0' + (val) / 10); s[1] = (char)('0' + (val) % 10); s += 2; } -void CMessageBox::Init(const AString &title, int width) +static void GetTimeString(UInt64 timeValue, char *s) { - _title = title; - _width = MyMin(width, kMaxLen); + UInt64 hours = timeValue / 3600; + UInt32 seconds = (UInt32)(timeValue - hours * 3600); + UInt32 minutes = seconds / 60; + seconds %= 60; + if (hours > 99) + { + ConvertUInt64ToString(hours, s); + for (; *s != 0; s++); + } + else + { + UInt32 hours32 = (UInt32)hours; + UINT_TO_STR_2(hours32); + } + *s++ = ':'; UINT_TO_STR_2(minutes); + *s++ = ':'; UINT_TO_STR_2(seconds); + *s = 0; +} + +void CProgressBox::ReduceString(const UString &src, AString &dest) +{ + UnicodeStringToMultiByte2(dest, src, CP_OEMCP); + + if (dest.Len() <= MaxLen) + return; + unsigned len = FileName.Len(); + for (; len != 0;) + { + unsigned delta = len / 8; + if (delta == 0) + delta = 1; + len -= delta; + _tempU = FileName; + _tempU.Delete(len / 2, FileName.Len() - len); + _tempU.Insert(len / 2, L" . "); + UnicodeStringToMultiByte2(dest, _tempU, CP_OEMCP); + if (dest.Len() <= MaxLen) + return; + } + dest.Empty(); +} + +static void Print_UInt64_and_String(AString &s, UInt64 val, const char *name) +{ + char temp[32]; + ConvertUInt64ToString(val, temp); + s += temp; + s.Add_Space(); + s += name; } -void CMessageBox::ShowMessages(const char *strings[], int numStrings) + +static void PrintSize_bytes_Smart(AString &s, UInt64 val) { - const int kNumStaticStrings = 1; - const int kNumStringsMax = 10; + // Print_UInt64_and_String(s, val, "bytes"); + { + char temp[32]; + ConvertUInt64ToString(val, temp); + s += temp; + } - if (numStrings > kNumStringsMax) - numStrings = kNumStringsMax; + if (val == 0) + return; + + unsigned numBits = 10; + char c = 'K'; + char temp[4] = { 'K', 'i', 'B', 0 }; + if (val >= ((UInt64)10 << 30)) { numBits = 30; c = 'G'; } + else if (val >= ((UInt64)10 << 20)) { numBits = 20; c = 'M'; } + temp[0] = c; + s += " ("; + Print_UInt64_and_String(s, ((val + ((UInt64)1 << numBits) - 1) >> numBits), temp); + s += ')'; +} - const char *msgItems[kNumStaticStrings + kNumStringsMax]; - msgItems[0] = _title; - char formattedMessages[kNumStringsMax][kMaxLen + 1]; +static const unsigned kPercentsSize = 4; - for (int i = 0; i < numStrings; i++) +void CProgressBox::Print() +{ + DWORD tick = GetTickCount(); + DWORD elapsedTicks = tick - StartTick; + DWORD elapsedSec = elapsedTicks / 1000; + + if (_wasPrinted) { - char *formattedMessage = formattedMessages[i]; - const char *s = strings[i]; - int len = (int)strlen(s); - if (len < kMaxLen) + if (elapsedSec == _prevElapsedSec) { - int size = MyMax(_width, len); - int startPos = (size - len) / 2; - CopySpaces(formattedMessage, startPos); - strcpy(formattedMessage + startPos, s); - CopySpaces(formattedMessage + startPos + len, size - startPos - len); + if ((UInt32)(tick - _prevTick) < _tickStep) + return; + if (_printedState.IsEqualTo((const CPercentPrinterState &)*this)) + return; } - else + } + + UInt64 cur = Completed; + UInt64 total = Total; + + if (!UseBytesForPercents) + { + cur = Files; + total = FilesTotal; + } + + { + _timeStr.Empty(); + _timeStr = "Elapsed time: "; + char s[40]; + GetTimeString(elapsedSec, s); + _timeStr += s; + + if (cur != 0) { - strncpy(formattedMessage, s, kMaxLen); - formattedMessage[kMaxLen] = 0; + UInt64 remainingTime = 0; + if (cur < total) + remainingTime = MyMultAndDiv(elapsedTicks, total - cur, cur); + UInt64 remainingSec = remainingTime / 1000; + _timeStr += " Remaining time: "; + + GetTimeString(remainingSec, s); + _timeStr += s; } - msgItems[kNumStaticStrings + i] = formattedMessage; } - NFar::g_StartupInfo.ShowMessage(0, NULL, msgItems, kNumStaticStrings + numStrings, 0); -} -// ---------- CProgressBox ---------- + { + _perc.Empty(); + char s[32]; + unsigned size; + { + UInt64 val = 0; + if (total != (UInt64)(Int64)-1 && total != 0) + val = cur * 100 / Total; + + ConvertUInt64ToString(val, s); + size = (unsigned)strlen(s); + s[size++] = '%'; + s[size] = 0; + } + + unsigned len = size; + while (len < kPercentsSize) + len = kPercentsSize; + len++; + + if (len < MaxLen) + { + unsigned numChars = MaxLen - len; + unsigned filled = 0; + if (total != (UInt64)(Int64)-1 && total != 0) + filled = (unsigned)(cur * numChars / total); + unsigned i = 0; + if (filled < numChars) + { + for (i = 0; i < filled; i++) + _perc += '='; + } + for (; i < numChars; i++) + _perc += '.'; + } + + _perc.Add_Space(); + while (size < kPercentsSize) + { + _perc.Add_Space(); + size++; + } + _perc += s; + } -void CProgressBox::Init(const AString &title, int width) -{ - CMessageBox::Init(title, width); - _prevMessage.Empty(); - _prevPercentMessage.Empty(); - _wasShown = false; -} + _files.Empty(); + if (Files != 0 || FilesTotal != 0) + { + _files += "Files: "; + char s[32]; + // if (Files != 0) + { + ConvertUInt64ToString(Files, s); + _files += s; + } + if (FilesTotal != 0) + { + _files += " / "; + ConvertUInt64ToString(FilesTotal, s); + _files += s; + } + } -void CProgressBox::Progress(const UInt64 *total, const UInt64 *completed, const AString &message) -{ - AString percentMessage; - if (total != 0 && completed != 0) + _sizesStr.Empty(); + if (Total != 0) + { + _sizesStr += "Size: "; + PrintSize_bytes_Smart(_sizesStr, Completed); + if (Total != 0 && Total != (UInt64)(Int64)-1) + { + _sizesStr += " / "; + PrintSize_bytes_Smart(_sizesStr, Total); + } + } + + _name1.Empty(); + _name2.Empty(); + + if (!FileName.IsEmpty()) { - UInt64 totalVal = *total; - if (totalVal == 0) - totalVal = 1; - char buf[32]; - ConvertUInt64ToStringAligned(*completed * 100 / totalVal, buf, 3); - strcat(buf, "%"); - percentMessage = buf; + _name1U.Empty(); + _name2U.Empty(); + + /* + if (_isDir) + s1 = _filePath; + else + */ + { + int slashPos = FileName.ReverseFind_PathSepar(); + if (slashPos >= 0) + { + _name1U.SetFrom(FileName, slashPos + 1); + _name2U = FileName.Ptr(slashPos + 1); + } + else + _name2U = FileName; + } + ReduceString(_name1U, _name1); + ReduceString(_name2U, _name2); } - if (message != _prevMessage || percentMessage != _prevPercentMessage || !_wasShown) + { - _prevMessage = message; - _prevPercentMessage = percentMessage; - const char *strings[] = { message, percentMessage }; - ShowMessages(strings, ARRAY_SIZE(strings)); - _wasShown = true; + const char *strings[] = { _title, _timeStr, _files, _sizesStr, Command, _name1, _name2, _perc }; + NFar::g_StartupInfo.ShowMessage(FMSG_LEFTALIGN, NULL, strings, ARRAY_SIZE(strings), 0); } + + _wasPrinted = true; + _printedState = *this; + _prevTick = tick; + _prevElapsedSec = elapsedSec; } diff --git a/CPP/7zip/UI/Far/ProgressBox.h b/CPP/7zip/UI/Far/ProgressBox.h index 9c26763d..83731b38 100644 --- a/CPP/7zip/UI/Far/ProgressBox.h +++ b/CPP/7zip/UI/Far/ProgressBox.h @@ -6,25 +6,78 @@ #include "../../../Common/MyString.h" #include "../../../Common/MyTypes.h" -void ConvertUInt64ToStringAligned(UInt64 value, char *s, int alignSize); - -class CMessageBox +struct CPercentPrinterState { - AString _title; - int _width; -public: - void Init(const AString &title, int width); - void ShowMessages(const char *strings[], int numStrings); + UInt64 Completed; + UInt64 Total; + + UInt64 Files; + UInt64 FilesTotal; + + AString Command; + UString FileName; + + void ClearCurState(); + + bool IsEqualTo(const CPercentPrinterState &s) const + { + return + Completed == s.Completed + && Total == s.Total + && Files == s.Files + && FilesTotal == s.FilesTotal + && Command == s.Command + && FileName == s.FileName; + } + + CPercentPrinterState(): + Completed(0), + Total((UInt64)(Int64)-1), + Files(0), + FilesTotal(0) + {} }; -class CProgressBox: public CMessageBox +class CProgressBox: public CPercentPrinterState { - AString _prevMessage; - AString _prevPercentMessage; - bool _wasShown; + UInt32 _tickStep; + DWORD _prevTick; + DWORD _prevElapsedSec; + + bool _wasPrinted; + + UString _tempU; + UString _name1U; + UString _name2U; + + CPercentPrinterState _printedState; + + AString _title; + + AString _timeStr; + AString _files; + AString _sizesStr; + AString _name1; + AString _name2; + AString _perc; + + void ReduceString(const UString &src, AString &dest); + public: - void Init(const AString &title, int width); - void Progress(const UInt64 *total, const UInt64 *completed, const AString &message); + DWORD StartTick; + bool UseBytesForPercents; + unsigned MaxLen; + + CProgressBox(UInt32 tickStep = 200): + _tickStep(tickStep), + _prevTick(0), + StartTick(0), + UseBytesForPercents(true), + MaxLen(60) + {} + + void Init(const AString &title); + void Print(); }; #endif diff --git a/CPP/7zip/UI/Far/UpdateCallbackFar.cpp b/CPP/7zip/UI/Far/UpdateCallbackFar.cpp index f2877888..18d1a2c9 100644 --- a/CPP/7zip/UI/Far/UpdateCallbackFar.cpp +++ b/CPP/7zip/UI/Far/UpdateCallbackFar.cpp @@ -2,59 +2,206 @@ #include "StdAfx.h" +#ifndef _7ZIP_ST +#include "../../../Windows/Synchronization.h" +#endif + #include "../../../Common/StringConvert.h" #include "FarUtils.h" #include "UpdateCallbackFar.h" +using namespace NWindows; using namespace NFar; -STDMETHODIMP CUpdateCallback100Imp::SetNumFiles(UInt64 /* numFiles */) +#ifndef _7ZIP_ST +static NSynchronization::CCriticalSection g_CriticalSection; +#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); +#else +#define MT_LOCK +#endif + +static HRESULT CheckBreak2() +{ + return WasEscPressed() ? E_ABORT : S_OK; +} + + +STDMETHODIMP CUpdateCallback100Imp::ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, Int32 /* isDir */) +{ + MT_LOCK + + if (_percent) + { + _percent->FilesTotal = numFolders + numFiles; + _percent->Total = totalSize; + _percent->Command = "Scanning"; + _percent->FileName = path; + _percent->Print(); + _percent->Print(); + } + return CheckBreak2(); +} + +STDMETHODIMP CUpdateCallback100Imp::ScanError(const wchar_t *path, HRESULT errorCode) { - return S_OK; + if (ShowSysErrorMessage(errorCode, path) == -1) + return E_ABORT; + return CheckBreak2(); +} + +STDMETHODIMP CUpdateCallback100Imp::SetNumFiles(UInt64 numFiles) +{ + MT_LOCK + + if (_percent) + { + _percent->FilesTotal = numFiles; + _percent->Print(); + } + return CheckBreak2(); } STDMETHODIMP CUpdateCallback100Imp::SetTotal(UInt64 size) { - _total = size; - return S_OK; + MT_LOCK + + if (_percent) + { + _percent->Total = size; + _percent->Print(); + } + return CheckBreak2(); } STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UInt64 *completeValue) { - if (WasEscPressed()) - return E_ABORT; - if (_progressBox != 0) - _progressBox->Progress(&_total, completeValue, AString()); - return S_OK; + MT_LOCK + + if (_percent) + { + if (completeValue) + _percent->Completed = *completeValue; + _percent->Print(); + } + return CheckBreak2(); } -STDMETHODIMP CUpdateCallback100Imp::CompressOperation(const wchar_t* /* name */) +STDMETHODIMP CUpdateCallback100Imp::CompressOperation(const wchar_t *name) { - return S_OK; + MT_LOCK + + if (_percent) + { + _percent->Command = "Adding"; + _percent->FileName = name; + _percent->Print(); + } + return CheckBreak2();; } -STDMETHODIMP CUpdateCallback100Imp::DeleteOperation(const wchar_t* /* name */) +STDMETHODIMP CUpdateCallback100Imp::DeleteOperation(const wchar_t *name) { - return S_OK; + MT_LOCK + + if (_percent) + { + _percent->Command = "Deleting"; + _percent->FileName = name; + _percent->Print(); + } + return CheckBreak2();; } STDMETHODIMP CUpdateCallback100Imp::OperationResult(Int32 /* opRes */) { - return S_OK; + MT_LOCK + + if (_percent) + { + _percent->Files++; + } + return CheckBreak2(); } STDMETHODIMP CUpdateCallback100Imp::UpdateErrorMessage(const wchar_t *message) { - if (g_StartupInfo.ShowMessage(UnicodeStringToMultiByte(message, CP_OEMCP)) == -1) + MT_LOCK + + if (g_StartupInfo.ShowErrorMessage(UnicodeStringToMultiByte(message, CP_OEMCP)) == -1) + return E_ABORT; + return CheckBreak2(); +} + +HRESULT CUpdateCallback100Imp::OpenFileError(const wchar_t *path, HRESULT errorCode) +{ + if (ShowSysErrorMessage(errorCode, path) == -1) + return E_ABORT; + return CheckBreak2(); +} + +STDMETHODIMP CUpdateCallback100Imp::ReadingFileError(const wchar_t *path, HRESULT errorCode) +{ + if (ShowSysErrorMessage(errorCode, path) == -1) return E_ABORT; - return S_OK; + return CheckBreak2(); } +void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &s); + +STDMETHODIMP CUpdateCallback100Imp::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) +{ + MT_LOCK + + if (opRes != NArchive::NExtract::NOperationResult::kOK) + { + AString s; + SetExtractErrorMessage(opRes, isEncrypted, s); + if (PrintErrorMessage(s, name) == -1) + return E_ABORT; + } + + return CheckBreak2(); +} + + +STDMETHODIMP CUpdateCallback100Imp::ReportUpdateOperation(UInt32 op, const wchar_t *name, Int32 /* isDir */) +{ + const char *s; + switch (op) + { + case NUpdateNotifyOp::kAdd: s = "Adding"; break; + case NUpdateNotifyOp::kUpdate: s = "Updating"; break; + case NUpdateNotifyOp::kAnalyze: s = "Analyzing"; break; + case NUpdateNotifyOp::kReplicate: s = "Replicating"; break; + case NUpdateNotifyOp::kRepack: s = "Repacking"; break; + case NUpdateNotifyOp::kSkip: s = "Skipping"; break; + case NUpdateNotifyOp::kHeader: s = "Header creating"; break; + case NUpdateNotifyOp::kDelete: s = "Deleting"; break; + default: s = "Unknown operation"; + } + + MT_LOCK + + if (_percent) + { + _percent->Command = s; + _percent->FileName.Empty(); + if (name) + _percent->FileName = name; + _percent->Print(); + } + + return CheckBreak2();; +} + + extern HRESULT GetPassword(UString &password); STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password) { + MT_LOCK + *password = NULL; if (!m_PasswordIsDefined) { diff --git a/CPP/7zip/UI/Far/UpdateCallbackFar.h b/CPP/7zip/UI/Far/UpdateCallbackFar.h index b2980f21..a2328669 100644 --- a/CPP/7zip/UI/Far/UpdateCallbackFar.h +++ b/CPP/7zip/UI/Far/UpdateCallbackFar.h @@ -13,31 +13,38 @@ class CUpdateCallback100Imp: public IFolderArchiveUpdateCallback, + public IFolderArchiveUpdateCallback2, + public IFolderScanProgress, public ICryptoGetTextPassword, public CMyUnknownImp { // CMyComPtr<IInFolderArchive> _archiveHandler; - CProgressBox *_progressBox; + CProgressBox *_percent; UInt64 _total; bool m_PasswordIsDefined; UString m_Password; public: - MY_UNKNOWN_IMP1(ICryptoGetTextPassword) + MY_UNKNOWN_IMP4( + IFolderArchiveUpdateCallback, + IFolderArchiveUpdateCallback2, + IFolderScanProgress, + ICryptoGetTextPassword) INTERFACE_IProgress(;) INTERFACE_IFolderArchiveUpdateCallback(;) + INTERFACE_IFolderArchiveUpdateCallback2(;) + INTERFACE_IFolderScanProgress(;) + STDMETHOD(CryptoGetTextPassword)(BSTR *password); CUpdateCallback100Imp(): _total(0) {} void Init(/* IInFolderArchive *archiveHandler, */ CProgressBox *progressBox) { // _archiveHandler = archiveHandler; - _progressBox = progressBox; + _percent = progressBox; m_PasswordIsDefined = false; } }; - - #endif diff --git a/CPP/7zip/UI/Far/makefile b/CPP/7zip/UI/Far/makefile index 2c32d533..0fff95a2 100644 --- a/CPP/7zip/UI/Far/makefile +++ b/CPP/7zip/UI/Far/makefile @@ -1,7 +1,8 @@ PROG = 7-ZipFar.dll DEF_FILE = Far.def CFLAGS = $(CFLAGS) \ - -DEXTERNAL_CODECS + -DEXTERNAL_CODECS \ + -DNEW_FOLDER_INTERFACE !IFNDEF UNDER_CE CFLAGS = $(CFLAGS) -DWIN_LONG_PATH @@ -40,12 +41,15 @@ WIN_OBJS = \ $O\PropVariant.obj \ $O\PropVariantConv.obj \ $O\Registry.obj \ + $O\ResourceString.obj \ $O\Synchronization.obj \ $O\TimeUtils.obj \ 7ZIP_COMMON_OBJS = \ + $O\CreateCoder.obj \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ + $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\ProgressUtils.obj \ $O\PropId.obj \ @@ -78,6 +82,9 @@ AGENT_OBJS = \ $O\Agent.obj \ $O\AgentOut.obj \ $O\AgentProxy.obj \ + $O\ArchiveFolder.obj \ + $O\ArchiveFolderOpen.obj \ + $O\ArchiveFolderOut.obj \ $O\UpdateCallbackAgent.obj \ COMPRESS_OBJS = \ diff --git a/CPP/7zip/UI/FileManager/AboutDialog.cpp b/CPP/7zip/UI/FileManager/AboutDialog.cpp index 10d76671..35e67753 100644 --- a/CPP/7zip/UI/FileManager/AboutDialog.cpp +++ b/CPP/7zip/UI/FileManager/AboutDialog.cpp @@ -29,7 +29,7 @@ bool CAboutDialog::OnInit() UString s = L"7-Zip " LLL(MY_VERSION); #ifdef MY_CPU_64BIT s += L" ["; - s += LangString(IDS_PROP_BIT64); + AddLangString(s, IDS_PROP_BIT64); s += L']'; #endif diff --git a/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp b/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp new file mode 100644 index 00000000..c209bf35 --- /dev/null +++ b/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp @@ -0,0 +1,839 @@ +// AltStreamsFolder.cpp + +#include "StdAfx.h" + +#include "../../../Common/ComTry.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileIO.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" + +#include "../Common/ExtractingFilePath.h" + +#include "../Agent/IFolderArchive.h" + +#include "AltStreamsFolder.h" +#include "FSDrives.h" +#include "FSFolder.h" + +#include "SysIconUtils.h" + +using namespace NWindows; +using namespace NFile; +using namespace NFind; +using namespace NDir; +using namespace NName; + +#ifndef USE_UNICODE_FSTRING +int CompareFileNames_ForFolderList(const FChar *s1, const FChar *s2); +#endif + +#ifndef UNDER_CE + +namespace NFsFolder +{ +bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size); +} + +#endif + +namespace NAltStreamsFolder { + +static const Byte kProps[] = +{ + kpidName, + kpidSize, + kpidPackSize +}; + +static unsigned GetFsParentPrefixSize(const FString &path) +{ + if (IsNetworkShareRootPath(path)) + return 0; + unsigned prefixSize = GetRootPrefixSize(path); + if (prefixSize == 0 || prefixSize >= path.Len()) + return 0; + FString parentPath = path; + int pos = parentPath.ReverseFind_PathSepar(); + if (pos < 0) + return 0; + if (pos == (int)parentPath.Len() - 1) + { + parentPath.DeleteBack(); + pos = parentPath.ReverseFind_PathSepar(); + if (pos < 0) + return 0; + } + if ((unsigned)pos + 1 < prefixSize) + return 0; + return pos + 1; +} + +HRESULT CAltStreamsFolder::Init(const FString &path /* , IFolderFolder *parentFolder */) +{ + // _parentFolder = parentFolder; + if (path.Back() != ':') + return E_FAIL; + + _pathPrefix = path; + _pathBaseFile = path; + _pathBaseFile.DeleteBack(); + + { + CFileInfo fi; + if (!fi.Find(_pathBaseFile)) + return GetLastError(); + } + + unsigned prefixSize = GetFsParentPrefixSize(_pathBaseFile); + if (prefixSize == 0) + return S_OK; + FString parentPath = _pathBaseFile; + parentPath.DeleteFrom(prefixSize); + + _findChangeNotification.FindFirst(parentPath, false, + FILE_NOTIFY_CHANGE_FILE_NAME + | FILE_NOTIFY_CHANGE_DIR_NAME + | FILE_NOTIFY_CHANGE_ATTRIBUTES + | FILE_NOTIFY_CHANGE_SIZE + | FILE_NOTIFY_CHANGE_LAST_WRITE + /* + | FILE_NOTIFY_CHANGE_LAST_ACCESS + | FILE_NOTIFY_CHANGE_CREATION + | FILE_NOTIFY_CHANGE_SECURITY + */ + ); + /* + if (_findChangeNotification.IsHandleAllocated()) + return S_OK; + return GetLastError(); + */ + return S_OK; +} + +STDMETHODIMP CAltStreamsFolder::LoadItems() +{ + Int32 dummy; + WasChanged(&dummy); + Clear(); + + CStreamEnumerator enumerator(_pathBaseFile); + + CStreamInfo si; + for (;;) + { + bool found; + if (!enumerator.Next(si, found)) + { + // if (GetLastError() == ERROR_ACCESS_DENIED) + // break; + // return E_FAIL; + break; + } + if (!found) + break; + if (si.IsMainStream()) + continue; + CAltStream ss; + ss.Name = si.GetReducedName(); + if (!ss.Name.IsEmpty() && ss.Name[0] == ':') + ss.Name.Delete(0); + + ss.Size = si.Size; + ss.PackSize_Defined = false; + ss.PackSize = si.Size; + Streams.Add(ss); + } + + return S_OK; +} + +STDMETHODIMP CAltStreamsFolder::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = Streams.Size(); + return S_OK; +} + +#ifdef USE_UNICODE_FSTRING + +STDMETHODIMP CAltStreamsFolder::GetItemPrefix(UInt32 /* index */, const wchar_t **name, unsigned *len) +{ + *name = 0; + *len = 0; + return S_OK; +} + +STDMETHODIMP CAltStreamsFolder::GetItemName(UInt32 index, const wchar_t **name, unsigned *len) +{ + *name = 0; + *len = 0; + { + const CAltStream &ss = Streams[index]; + *name = ss.Name; + *len = ss.Name.Len(); + } + return S_OK; +} + +STDMETHODIMP_(UInt64) CAltStreamsFolder::GetItemSize(UInt32 index) +{ + return Streams[index].Size; +} + +#endif + + +STDMETHODIMP CAltStreamsFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + { + CAltStream &ss = Streams[index]; + switch (propID) + { + case kpidIsDir: prop = false; break; + case kpidIsAltStream: prop = true; break; + case kpidName: prop = ss.Name; break; + case kpidSize: prop = ss.Size; break; + case kpidPackSize: + #ifdef UNDER_CE + prop = ss.Size; + #else + if (!ss.PackSize_Defined) + { + ss.PackSize_Defined = true; + if (!NFsFolder::MyGetCompressedFileSizeW(_pathPrefix + us2fs(ss.Name), ss.PackSize)) + ss.PackSize = ss.Size; + } + prop = ss.PackSize; + #endif + break; + } + } + + prop.Detach(value); + return S_OK; +} + + +// returns Position of extension including '.' + +static inline const wchar_t *GetExtensionPtr(const UString &name) +{ + int dotPos = name.ReverseFind_Dot(); + return name.Ptr((dotPos < 0) ? name.Len() : dotPos); +} + +STDMETHODIMP_(Int32) CAltStreamsFolder::CompareItems(UInt32 index1, UInt32 index2, PROPID propID, Int32 /* propIsRaw */) +{ + const CAltStream &ss1 = Streams[index1]; + const CAltStream &ss2 = Streams[index2]; + + switch (propID) + { + case kpidName: + { + return CompareFileNames_ForFolderList(ss1.Name, ss2.Name); + // return MyStringCompareNoCase(ss1.Name, ss2.Name); + } + case kpidSize: + return MyCompare(ss1.Size, ss2.Size); + case kpidPackSize: + { + #ifdef UNDER_CE + return MyCompare(ss1.Size, ss2.Size); + #else + // PackSize can be undefined here + return MyCompare( + ss1.PackSize, + ss2.PackSize); + #endif + } + + case kpidExtension: + return CompareFileNames_ForFolderList( + GetExtensionPtr(ss1.Name), + GetExtensionPtr(ss2.Name)); + } + + return 0; +} + +STDMETHODIMP CAltStreamsFolder::BindToFolder(UInt32 /* index */, IFolderFolder **resultFolder) +{ + *resultFolder = 0; + return E_INVALIDARG; +} + +STDMETHODIMP CAltStreamsFolder::BindToFolder(const wchar_t * /* name */, IFolderFolder **resultFolder) +{ + *resultFolder = 0; + return E_INVALIDARG; +} + +static const CFSTR kSuperPrefix = FTEXT("\\\\?\\"); + +STDMETHODIMP CAltStreamsFolder::BindToParentFolder(IFolderFolder **resultFolder) +{ + *resultFolder = 0; + /* + if (_parentFolder) + { + CMyComPtr<IFolderFolder> parentFolder = _parentFolder; + *resultFolder = parentFolder.Detach(); + return S_OK; + } + */ + + if (IsDriveRootPath_SuperAllowed(_pathBaseFile)) + { + CFSDrives *drivesFolderSpec = new CFSDrives; + CMyComPtr<IFolderFolder> drivesFolder = drivesFolderSpec; + drivesFolderSpec->Init(); + *resultFolder = drivesFolder.Detach(); + return S_OK; + } + + /* + parentPath.DeleteFrom(pos + 1); + + if (parentPath == kSuperPrefix) + { + #ifdef UNDER_CE + *resultFolder = 0; + #else + CFSDrives *drivesFolderSpec = new CFSDrives; + CMyComPtr<IFolderFolder> drivesFolder = drivesFolderSpec; + drivesFolderSpec->Init(false, true); + *resultFolder = drivesFolder.Detach(); + #endif + return S_OK; + } + + FString parentPathReduced = parentPath.Left(pos); + + #ifndef UNDER_CE + pos = parentPathReduced.ReverseFind_PathSepar(); + if (pos == 1) + { + if (!IS_PATH_SEPAR_CHAR(parentPath[0])) + return E_FAIL; + CNetFolder *netFolderSpec = new CNetFolder; + CMyComPtr<IFolderFolder> netFolder = netFolderSpec; + netFolderSpec->Init(fs2us(parentPath)); + *resultFolder = netFolder.Detach(); + return S_OK; + } + #endif + + CFSFolder *parentFolderSpec = new CFSFolder; + CMyComPtr<IFolderFolder> parentFolder = parentFolderSpec; + RINOK(parentFolderSpec->Init(parentPath, 0)); + *resultFolder = parentFolder.Detach(); + */ + + return S_OK; +} + +STDMETHODIMP CAltStreamsFolder::GetNumberOfProperties(UInt32 *numProperties) +{ + *numProperties = ARRAY_SIZE(kProps); + return S_OK; +} + +STDMETHODIMP CAltStreamsFolder::GetPropertyInfo IMP_IFolderFolder_GetProp(kProps) + +STDMETHODIMP CAltStreamsFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch (propID) + { + case kpidType: prop = "AltStreamsFolder"; break; + case kpidPath: prop = fs2us(_pathPrefix); break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CAltStreamsFolder::WasChanged(Int32 *wasChanged) +{ + bool wasChangedMain = false; + for (;;) + { + if (!_findChangeNotification.IsHandleAllocated()) + { + *wasChanged = BoolToInt(false); + return S_OK; + } + + DWORD waitResult = ::WaitForSingleObject(_findChangeNotification, 0); + bool wasChangedLoc = (waitResult == WAIT_OBJECT_0); + if (wasChangedLoc) + { + _findChangeNotification.FindNext(); + wasChangedMain = true; + } + else + break; + } + *wasChanged = BoolToInt(wasChangedMain); + return S_OK; +} + +STDMETHODIMP CAltStreamsFolder::Clone(IFolderFolder **resultFolder) +{ + CAltStreamsFolder *folderSpec = new CAltStreamsFolder; + CMyComPtr<IFolderFolder> folderNew = folderSpec; + folderSpec->Init(_pathPrefix); + *resultFolder = folderNew.Detach(); + return S_OK; +} + +void CAltStreamsFolder::GetAbsPath(const wchar_t *name, FString &absPath) +{ + absPath.Empty(); + if (!IsAbsolutePath(name)) + absPath += _pathPrefix; + absPath += us2fs(name); +} + + + +static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback, + const wchar_t *message, const FString &fileName) +{ + UString s = message; + s += L" : "; + s += fs2us(fileName); + return callback->ShowMessage(s); +} + +static HRESULT SendMessageError(IFolderArchiveUpdateCallback *callback, + const wchar_t *message, const FString &fileName) +{ + UString s = message; + s += L" : "; + s += fs2us(fileName); + return callback->UpdateErrorMessage(s); +} + +static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback, + const char *message, const FString &fileName) +{ + return SendMessageError(callback, MultiByteToUnicodeString(message), fileName); +} + +/* +static HRESULT SendMessageError(IFolderArchiveUpdateCallback *callback, + const char *message, const FString &fileName) +{ + return SendMessageError(callback, MultiByteToUnicodeString(message), fileName); +} +*/ + +STDMETHODIMP CAltStreamsFolder::CreateFolder(const wchar_t * /* name */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CAltStreamsFolder::CreateFile(const wchar_t *name, IProgress * /* progress */) +{ + FString absPath; + GetAbsPath(name, absPath); + NIO::COutFile outFile; + if (!outFile.Create(absPath, false)) + return ::GetLastError(); + return S_OK; +} + +static DWORD Return_LastError_or_FAIL() +{ + DWORD errorCode = GetLastError(); + if (errorCode == 0) + errorCode = (DWORD)E_FAIL; + return errorCode; +} + +static UString GetLastErrorMessage() +{ + return NError::MyFormatMessage(Return_LastError_or_FAIL()); +} + +static HRESULT UpdateFile(NFsFolder::CCopyStateIO &state, CFSTR inPath, CFSTR outPath, IFolderArchiveUpdateCallback *callback) +{ + if (NFind::DoesFileOrDirExist(outPath)) + { + RINOK(SendMessageError(callback, NError::MyFormatMessage(ERROR_ALREADY_EXISTS), outPath)); + CFileInfo fi; + if (fi.Find(inPath)) + { + if (state.TotalSize >= fi.Size) + state.TotalSize -= fi.Size; + } + return S_OK; + } + + { + if (callback) + RINOK(callback->CompressOperation(fs2us(inPath))); + RINOK(state.MyCopyFile(inPath, outPath)); + if (state.ErrorFileIndex >= 0) + { + if (state.ErrorMessage.IsEmpty()) + state.ErrorMessage = GetLastErrorMessage(); + FString errorName; + if (state.ErrorFileIndex == 0) + errorName = inPath; + else + errorName = outPath; + if (callback) + RINOK(SendMessageError(callback, state.ErrorMessage, errorName)); + } + if (callback) + RINOK(callback->OperationResult(0)); + } + + return S_OK; +} + +STDMETHODIMP CAltStreamsFolder::Rename(UInt32 index, const wchar_t *newName, IProgress *progress) +{ + CMyComPtr<IFolderArchiveUpdateCallback> callback; + if (progress) + { + RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&callback)); + } + + FString destPath = _pathPrefix + us2fs(newName); + + const CAltStream &ss = Streams[index]; + + if (callback) + { + RINOK(callback->SetNumFiles(1)); + RINOK(callback->SetTotal(ss.Size)); + } + + NFsFolder::CCopyStateIO state; + state.Progress = progress; + state.TotalSize = 0; + state.DeleteSrcFile = true; + + return UpdateFile(state, _pathPrefix + us2fs(ss.Name), destPath, callback); +} + +STDMETHODIMP CAltStreamsFolder::Delete(const UInt32 *indices, UInt32 numItems,IProgress *progress) +{ + RINOK(progress->SetTotal(numItems)); + for (UInt32 i = 0; i < numItems; i++) + { + const CAltStream &ss = Streams[indices[i]]; + const FString fullPath = _pathPrefix + us2fs(ss.Name); + bool result = DeleteFileAlways(fullPath); + if (!result) + return Return_LastError_or_FAIL(); + UInt64 completed = i; + RINOK(progress->SetCompleted(&completed)); + } + return S_OK; +} + +STDMETHODIMP CAltStreamsFolder::SetProperty(UInt32 /* index */, PROPID /* propID */, + const PROPVARIANT * /* value */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CAltStreamsFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex) +{ + const CAltStream &ss = Streams[index]; + *iconIndex = 0; + int iconIndexTemp; + if (GetRealIconIndex(_pathPrefix + us2fs(ss.Name), + 0 // fi.Attrib + , iconIndexTemp) != 0) + { + *iconIndex = iconIndexTemp; + return S_OK; + } + return Return_LastError_or_FAIL(); +} + +/* +class CGetProp: + public IGetProp, + public CMyUnknownImp +{ +public: + // const CArc *Arc; + // UInt32 IndexInArc; + UString Name; // relative path + UInt64 Size; + + MY_UNKNOWN_IMP1(IGetProp) + INTERFACE_IGetProp(;) +}; + +STDMETHODIMP CGetProp::GetProp(PROPID propID, PROPVARIANT *value) +{ + if (propID == kpidName) + { + COM_TRY_BEGIN + NCOM::CPropVariant prop = Name; + prop.Detach(value); + return S_OK; + COM_TRY_END + } + if (propID == kpidSize) + { + NCOM::CPropVariant prop = Size; + prop.Detach(value); + return S_OK; + } + NCOM::CPropVariant prop; + prop.Detach(value); + return S_OK; +} +*/ + +static HRESULT CopyStream( + NFsFolder::CCopyStateIO &state, + const FString &srcPath, + const CFileInfo &srcFileInfo, + const CAltStream &srcAltStream, + const FString &destPathSpec, + IFolderOperationsExtractCallback *callback) +{ + FString destPath = destPathSpec; + if (CompareFileNames(destPath, srcPath) == 0) + { + RINOK(SendMessageError(callback, "can not copy file onto itself", destPath)); + return E_ABORT; + } + + Int32 writeAskResult; + CMyComBSTR destPathResult; + RINOK(callback->AskWrite( + fs2us(srcPath), + BoolToInt(false), + &srcFileInfo.MTime, &srcAltStream.Size, + fs2us(destPath), + &destPathResult, + &writeAskResult)); + + if (IntToBool(writeAskResult)) + { + RINOK(callback->SetCurrentFilePath(fs2us(srcPath))); + FString destPathNew = us2fs((LPCOLESTR)destPathResult); + RINOK(state.MyCopyFile(srcPath, destPathNew)); + if (state.ErrorFileIndex >= 0) + { + if (state.ErrorMessage.IsEmpty()) + state.ErrorMessage = GetLastErrorMessage(); + FString errorName; + if (state.ErrorFileIndex == 0) + errorName = srcPath; + else + errorName = destPathNew; + RINOK(SendMessageError(callback, state.ErrorMessage, errorName)); + return E_ABORT; + } + state.StartPos += state.CurrentSize; + } + else + { + if (state.TotalSize >= srcAltStream.Size) + { + state.TotalSize -= srcAltStream.Size; + RINOK(state.Progress->SetTotal(state.TotalSize)); + } + } + return S_OK; +} + +STDMETHODIMP CAltStreamsFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems, + Int32 /* includeAltStreams */, Int32 /* replaceAltStreamColon */, + const wchar_t *path, IFolderOperationsExtractCallback *callback) +{ + if (numItems == 0) + return S_OK; + + /* + CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback; + RINOK(callback->QueryInterface(IID_IFolderExtractToStreamCallback, (void **)&ExtractToStreamCallback)); + if (ExtractToStreamCallback) + { + Int32 useStreams = 0; + if (ExtractToStreamCallback->UseExtractToStream(&useStreams) != S_OK) + useStreams = 0; + if (useStreams == 0) + ExtractToStreamCallback.Release(); + } + */ + + UInt64 totalSize = 0; + { + UInt32 i; + for (i = 0; i < numItems; i++) + { + totalSize += Streams[indices[i]].Size; + } + RINOK(callback->SetTotal(totalSize)); + RINOK(callback->SetNumFiles(numItems)); + } + + /* + if (ExtractToStreamCallback) + { + CGetProp *GetProp_Spec = new CGetProp; + CMyComPtr<IGetProp> GetProp= GetProp_Spec; + + for (UInt32 i = 0; i < numItems; i++) + { + UInt32 index = indices[i]; + const CAltStream &ss = Streams[index]; + GetProp_Spec->Name = ss.Name; + GetProp_Spec->Size = ss.Size; + CMyComPtr<ISequentialOutStream> outStream; + RINOK(ExtractToStreamCallback->GetStream7(GetProp_Spec->Name, BoolToInt(false), &outStream, + NArchive::NExtract::NAskMode::kExtract, GetProp)); // isDir + FString srcPath; + GetFullPath(ss, srcPath); + RINOK(ExtractToStreamCallback->PrepareOperation7(NArchive::NExtract::NAskMode::kExtract)); + RINOK(ExtractToStreamCallback->SetOperationResult7(NArchive::NExtract::NOperationResult::kOK, BoolToInt(false))); // _encrypted + // RINOK(CopyStream(state, srcPath, fi, ss, destPath2, callback, completedSize)); + } + return S_OK; + } + */ + + FString destPath = us2fs(path); + if (destPath.IsEmpty() /* && !ExtractToStreamCallback */) + return E_INVALIDARG; + + bool isAltDest = NName::IsAltPathPrefix(destPath);; + bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back())); + + if (isDirectPath) + { + if (numItems > 1) + return E_INVALIDARG; + } + + CFileInfo fi; + if (!fi.Find(_pathBaseFile)) + return GetLastError(); + + NFsFolder::CCopyStateIO state; + state.Progress = callback; + state.DeleteSrcFile = IntToBool(moveMode); + state.TotalSize = totalSize; + + for (UInt32 i = 0; i < numItems; i++) + { + UInt32 index = indices[i]; + const CAltStream &ss = Streams[index]; + FString destPath2 = destPath; + if (!isDirectPath) + destPath2 += us2fs(Get_Correct_FsFile_Name(ss.Name)); + FString srcPath; + GetFullPath(ss, srcPath); + RINOK(CopyStream(state, srcPath, fi, ss, destPath2, callback)); + } + + return S_OK; +} + +STDMETHODIMP CAltStreamsFolder::CopyFrom(Int32 /* moveMode */, const wchar_t * /* fromFolderPath */, + const wchar_t * const * /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */) +{ + /* + if (numItems == 0) + return S_OK; + + CMyComPtr<IFolderArchiveUpdateCallback> callback; + if (progress) + { + RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&callback)); + } + + if (CompareFileNames(fromFolderPath, fs2us(_pathPrefix)) == 0) + { + RINOK(SendMessageError(callback, "can not copy file onto itself", _pathPrefix)); + return E_ABORT; + } + + if (callback) + RINOK(callback->SetNumFiles(numItems)); + + UInt64 totalSize = 0; + + UInt32 i; + + FString path; + for (i = 0; i < numItems; i++) + { + path = us2fs(fromFolderPath); + path += us2fs(itemsPaths[i]); + + CFileInfo fi; + if (!fi.Find(path)) + return ::GetLastError(); + if (fi.IsDir()) + return E_NOTIMPL; + totalSize += fi.Size; + } + + RINOK(progress->SetTotal(totalSize)); + + // UInt64 completedSize = 0; + + NFsFolder::CCopyStateIO state; + state.Progress = progress; + state.DeleteSrcFile = IntToBool(moveMode); + state.TotalSize = totalSize; + + // we need to clear READ-ONLY of parent before creating alt stream + { + DWORD attrib = GetFileAttrib(_pathBaseFile); + if (attrib != INVALID_FILE_ATTRIBUTES + && (attrib & FILE_ATTRIBUTE_READONLY) != 0) + { + if (!SetFileAttrib(_pathBaseFile, attrib & ~FILE_ATTRIBUTE_READONLY)) + { + if (callback) + { + RINOK(SendMessageError(callback, GetLastErrorMessage(), _pathBaseFile)); + return S_OK; + } + return Return_LastError_or_FAIL(); + } + } + } + + for (i = 0; i < numItems; i++) + { + path = us2fs(fromFolderPath); + path += us2fs(itemsPaths[i]); + + FString destPath = _pathPrefix + us2fs(itemsPaths[i]); + + RINOK(UpdateFile(state, path, destPath, callback)); + } + + return S_OK; + */ + return E_NOTIMPL; +} + +STDMETHODIMP CAltStreamsFolder::CopyFromFile(UInt32 /* index */, const wchar_t * /* fullFilePath */, IProgress * /* progress */) +{ + return E_NOTIMPL; +} + +} diff --git a/CPP/7zip/UI/FileManager/AltStreamsFolder.h b/CPP/7zip/UI/FileManager/AltStreamsFolder.h new file mode 100644 index 00000000..ccd0a58f --- /dev/null +++ b/CPP/7zip/UI/FileManager/AltStreamsFolder.h @@ -0,0 +1,100 @@ +// AltStreamsFolder.h + +#ifndef __ALT_STREAMS_FOLDER_H +#define __ALT_STREAMS_FOLDER_H + +#include "../../../Common/MyCom.h" + +#include "../../../Windows/FileFind.h" + +#include "../../Archive/IArchive.h" + +#include "IFolder.h" + +namespace NAltStreamsFolder { + +class CAltStreamsFolder; + +struct CAltStream +{ + UInt64 Size; + UInt64 PackSize; + bool PackSize_Defined; + UString Name; +}; + + +class CAltStreamsFolder: + public IFolderFolder, + public IFolderCompare, + #ifdef USE_UNICODE_FSTRING + public IFolderGetItemName, + #endif + public IFolderWasChanged, + public IFolderOperations, + // public IFolderOperationsDeleteToRecycleBin, + public IFolderClone, + public IFolderGetSystemIconIndex, + public CMyUnknownImp +{ +public: + MY_QUERYINTERFACE_BEGIN2(IFolderFolder) + MY_QUERYINTERFACE_ENTRY(IFolderCompare) + #ifdef USE_UNICODE_FSTRING + MY_QUERYINTERFACE_ENTRY(IFolderGetItemName) + #endif + MY_QUERYINTERFACE_ENTRY(IFolderWasChanged) + // MY_QUERYINTERFACE_ENTRY(IFolderOperationsDeleteToRecycleBin) + MY_QUERYINTERFACE_ENTRY(IFolderOperations) + MY_QUERYINTERFACE_ENTRY(IFolderClone) + MY_QUERYINTERFACE_ENTRY(IFolderGetSystemIconIndex) + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + + INTERFACE_FolderFolder(;) + INTERFACE_FolderOperations(;) + + STDMETHOD_(Int32, CompareItems)(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw); + + #ifdef USE_UNICODE_FSTRING + INTERFACE_IFolderGetItemName(;) + #endif + STDMETHOD(WasChanged)(Int32 *wasChanged); + STDMETHOD(Clone)(IFolderFolder **resultFolder); + + STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex); + +private: + FString _pathBaseFile; // folder + FString _pathPrefix; // folder: + + CObjectVector<CAltStream> Streams; + // CMyComPtr<IFolderFolder> _parentFolder; + + NWindows::NFile::NFind::CFindChangeNotification _findChangeNotification; + + HRESULT GetItemFullSize(unsigned index, UInt64 &size, IProgress *progress); + void GetAbsPath(const wchar_t *name, FString &absPath); + +public: + // path must be with ':' at tail + HRESULT Init(const FString &path /* , IFolderFolder *parentFolder */); + + CAltStreamsFolder() {} + + void GetFullPath(const CAltStream &item, FString &path) const + { + path = _pathPrefix; + path += us2fs(item.Name); + } + + void Clear() + { + Streams.Clear(); + } +}; + +} + +#endif diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp index 51c8d2db..b6a66975 100644 --- a/CPP/7zip/UI/FileManager/App.cpp +++ b/CPP/7zip/UI/FileManager/App.cpp @@ -140,8 +140,8 @@ HRESULT CApp::CreateOnePanel(int panelIndex, const UString &mainPath, const UStr } static void CreateToolbar(HWND parent, - NWindows::NControl::CImageList &imageList, - NWindows::NControl::CToolBar &toolBar, + NControl::CImageList &imageList, + NControl::CToolBar &toolBar, bool largeButtons) { toolBar.Attach(::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, 0 @@ -364,7 +364,8 @@ void CApp::Save() if (panel._parentFolders.IsEmpty()) path = panel._currentFolderPrefix; else - path = GetFolderPath(panel._parentFolders[0].ParentFolder); + path = panel._parentFolders[0].ParentFolderPath; + // GetFolderPath(panel._parentFolders[0].ParentFolder); SavePanelPath(i, path); listMode.Panels[i] = panel.GetListViewMode(); SaveFlatView(i, panel._flatModeForArc); @@ -380,9 +381,12 @@ void CApp::Release() Panels[i].Release(); } -// reduces path to part that exists on disk +// reduces path to part that exists on disk (or root prefix of path) +// output path is normalized (with WCHAR_PATH_SEPARATOR) static void ReducePathToRealFileSystemPath(UString &path) { + unsigned prefixSize = GetRootPrefixSize(path); + while (!path.IsEmpty()) { if (NFind::DoesDirExist(us2fs(path))) @@ -390,63 +394,59 @@ static void ReducePathToRealFileSystemPath(UString &path) NName::NormalizeDirPathPrefix(path); break; } - int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR); + int pos = path.ReverseFind_PathSepar(); if (pos < 0) { path.Empty(); break; } path.DeleteFrom(pos + 1); - if (path.Len() == 3 && path[1] == L':') + if ((unsigned)pos + 1 == prefixSize) break; - if (path.Len() > 2 && path[0] == '\\' && path[1] == '\\') - { - int nextPos = path.Find(WCHAR_PATH_SEPARATOR, 2); // pos after \\COMPNAME - if (nextPos > 0 && path.Find(WCHAR_PATH_SEPARATOR, nextPos + 1) == pos) - break; - } path.DeleteFrom(pos); } } -// return true for dir\, if dir exist +// returns: true, if such dir exists or is root +/* static bool CheckFolderPath(const UString &path) { UString pathReduced = path; ReducePathToRealFileSystemPath(pathReduced); return (pathReduced == path); } +*/ extern UString ConvertSizeToString(UInt64 value); -static UString AddSizeValue(UInt64 size) +static void AddSizeValue(UString &s, UInt64 size) { - return MyFormatNew(IDS_FILE_SIZE, ConvertSizeToString(size)); + s += MyFormatNew(IDS_FILE_SIZE, ConvertSizeToString(size)); } static void AddValuePair1(UString &s, UINT resourceID, UInt64 size) { - s += LangString(resourceID); + AddLangString(s, resourceID); s += L": "; - s += AddSizeValue(size); - s += L'\n'; + AddSizeValue(s, size); + s.Add_LF(); } void AddValuePair2(UString &s, UINT resourceID, UInt64 num, UInt64 size) { if (num == 0) return; - s += LangString(resourceID); + AddLangString(s, resourceID); s += L": "; s += ConvertSizeToString(num); if (size != (UInt64)(Int64)-1) { s += L" ( "; - s += AddSizeValue(size); + AddSizeValue(s, size); s += L" )"; } - s += L'\n'; + s.Add_LF(); } static void AddPropValueToSum(IFolderFolder *folder, int index, PROPID propID, UInt64 &sum) @@ -490,7 +490,7 @@ UString CPanel::GetItemsInfoString(const CRecordVector<UInt32> &indices) if (numDefined == 2) AddValuePair1(info, IDS_PROP_SIZE, filesSize + foldersSize); - info += L"\n"; + info.Add_LF(); info += _currentFolderPrefix; for (i = 0; i < indices.Size() && (int)i < (int)kCopyDialog_NumInfoLines - 6; i++) @@ -499,7 +499,7 @@ UString CPanel::GetItemsInfoString(const CRecordVector<UInt32> &indices) int index = indices[i]; info += GetItemRelPath(index); if (IsItem_Folder(index)) - info += WCHAR_PATH_SEPARATOR; + info.Add_PathSepar(); } if (i != indices.Size()) info += L"\n ..."; @@ -508,6 +508,20 @@ UString CPanel::GetItemsInfoString(const CRecordVector<UInt32> &indices) bool IsCorrectFsName(const UString &name); + + +/* Returns true, if path is path that can be used as path for File System functions +*/ + +/* +static bool IsFsPath(const FString &path) +{ + if (!IsAbsolutePath(path)) + return false; + unsigned prefixSize = GetRootPrefixSize(path); +} +*/ + void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) { int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); @@ -517,7 +531,12 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) CPanel::CDisableTimerProcessing disableTimerProcessing1(destPanel); CPanel::CDisableTimerProcessing disableTimerProcessing2(srcPanel); - if (!srcPanel.DoesItSupportOperations()) + if (move) + { + if (!srcPanel.CheckBeforeUpdate(IDS_MOVE)) + return; + } + else if (!srcPanel.DoesItSupportOperations()) { srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; @@ -544,13 +563,15 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) srcPanel.GetOperatedIndicesSmart(indices); if (indices.Size() == 0) return; - destPath = destPanel._currentFolderPrefix; + destPath = destPanel.GetFsPath(); if (NumPanels == 1) ReducePathToRealFileSystemPath(destPath); } } + UStringVector copyFolders; ReadCopyHistory(copyFolders); + { CCopyDialog copyDialog; @@ -583,10 +604,10 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) if (IsAbsolutePath(destPath)) destPath.Empty(); else - destPath = srcPanel._currentFolderPrefix; + destPath = srcPanel.GetFsPath(); destPath += correctName; - #ifndef UNDER_CE + #if defined(_WIN32) && !defined(UNDER_CE) if (destPath.Len() > 0 && destPath[0] == '\\') if (destPath.Len() == 1 || destPath[1] != '\\') { @@ -595,59 +616,112 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) } #endif - if (indices.Size() > 1 || - (!destPath.IsEmpty() && destPath.Back() == WCHAR_PATH_SEPARATOR) || - NFind::DoesDirExist(us2fs(destPath)) || - srcPanel.IsArcFolder()) + bool possibleToUseDestPanel = false; + + if (CompareFileNames(destPath, destPanel.GetFsPath()) == 0) { - CreateComplexDir(us2fs(destPath)); - NName::NormalizeDirPathPrefix(destPath); - if (!CheckFolderPath(destPath)) + if (NumPanels == 1 || CompareFileNames(destPath, srcPanel.GetFsPath()) == 0) { - if (NumPanels < 2 || destPath != destPanel._currentFolderPrefix || !destPanel.DoesItSupportOperations()) - { - srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); - return; - } - useDestPanel = true; + srcPanel.MessageBoxMyError(L"Can not copy files onto itself"); + return; } + + if (destPanel.DoesItSupportOperations()) + possibleToUseDestPanel = true; } - else + + bool destIsFsPath = false; + + if (possibleToUseDestPanel) { - if (!IsCorrectFsName(destPath)) + if (destPanel.IsFSFolder() || destPanel.IsAltStreamsFolder()) + destIsFsPath = true; + else if (destPanel.IsFSDrivesFolder() || destPanel.IsRootFolder()) { - srcPanel.MessageBoxError(E_INVALIDARG); + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } - int pos = destPath.ReverseFind(WCHAR_PATH_SEPARATOR); - if (pos >= 0) + } + else + { + if (IsAltPathPrefix(us2fs(destPath))) { - UString prefix = destPath.Left(pos + 1); - CreateComplexDir(us2fs(prefix)); - if (!CheckFolderPath(prefix)) + // we allow alt streams dest only to alt stream folder in second panel + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); + return; + /* + FString basePath = us2fs(destPath); + basePath.DeleteBack(); + if (!DoesFileOrDirExist(basePath)) { - srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); + srcPanel.MessageBoxError2Lines(basePath, ERROR_FILE_NOT_FOUND); // GetLastError() return; } + destIsFsPath = true; + */ + } + else + { + if (indices.Size() == 1 && + !destPath.IsEmpty() && destPath.Back() != WCHAR_PATH_SEPARATOR) + { + int pos = destPath.ReverseFind_PathSepar(); + if (pos < 0) + { + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); + return; + } + { + /* + #ifdef _WIN32 + UString name = destPath.Ptr(pos + 1); + if (name.Find(L':') >= 0) + { + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); + return; + } + #endif + */ + UString prefix = destPath.Left(pos + 1); + if (!CreateComplexDir(us2fs(prefix))) + { + srcPanel.MessageBoxError2Lines(prefix, GetLastError()); + return; + } + } + // bool isFolder = srcPanael.IsItem_Folder(indices[0]); + } + else + { + NName::NormalizeDirPathPrefix(destPath); + if (!CreateComplexDir(us2fs(destPath))) + { + srcPanel.MessageBoxError2Lines(destPath, GetLastError()); + return; + } + } + destIsFsPath = true; } } + if (!destIsFsPath) + useDestPanel = true; + AddUniqueStringToHeadOfList(copyFolders, destPath); while (copyFolders.Size() > 20) copyFolders.DeleteBack(); SaveCopyHistory(copyFolders); } - /* - if (destPath == destPanel._currentFolderPrefix) - { - if (destPanel.GetFolderTypeID() == L"PhysDrive") - useDestPanel = true; - } - */ + bool useSrcPanel = !useDestPanel || !srcPanel.Is_IO_FS_Folder(); - bool useSrcPanel = (!useDestPanel || !srcPanel.IsFsOrDrivesFolder() || destPanel.IsFSFolder()); bool useTemp = useSrcPanel && useDestPanel; + if (useTemp && NumPanels == 1) + { + srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); + return; + } + CTempDir tempDirectory; FString tempDirPrefix; if (useTemp) @@ -666,6 +740,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) CPanel::CDisableNotify disableNotify2(srcPanel); HRESULT result = S_OK; + if (useSrcPanel) { CCopyToOptions options; @@ -685,12 +760,13 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) if (useTemp) folderPrefix = fs2us(tempDirPrefix); else - folderPrefix = srcPanel._currentFolderPrefix; + folderPrefix = srcPanel.GetFsPath(); filePaths.ClearAndReserve(indices.Size()); FOR_VECTOR (i, indices) - filePaths.AddInReserved(srcPanel.GetItemRelPath(indices[i])); + filePaths.AddInReserved(srcPanel.GetItemRelPath2(indices[i])); result = destPanel.CopyFrom(move, folderPrefix, filePaths, true, 0); } + if (result != S_OK) { // disableNotify1.Restore(); @@ -705,15 +781,18 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) } RefreshTitleAlways(); + if (copyToSame || move) { srcPanel.RefreshListCtrl(srcSelState); } + if (!copyToSame) { destPanel.RefreshListCtrl(destSelState); srcPanel.KillSelection(); } + disableNotify1.Restore(); disableNotify2.Restore(); srcPanel.SetFocusToList(); @@ -831,7 +910,7 @@ void CApp::RefreshTitle(int panelIndex, bool always) void AddUniqueStringToHead(UStringVector &list, const UString &s) { for (unsigned i = 0; i < list.Size();) - if (s.IsEqualToNoCase(list[i])) + if (s.IsEqualTo_NoCase(list[i])) list.Delete(i); else i++; @@ -848,7 +927,7 @@ void CFolderHistory::Normalize() void CFolderHistory::AddString(const UString &s) { - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); + NSynchronization::CCriticalSectionLock lock(_criticalSection); AddUniqueStringToHead(Strings, s); Normalize(); } diff --git a/CPP/7zip/UI/FileManager/App.h b/CPP/7zip/UI/FileManager/App.h index c775cc2e..5fe95e0b 100644 --- a/CPP/7zip/UI/FileManager/App.h +++ b/CPP/7zip/UI/FileManager/App.h @@ -195,6 +195,7 @@ public: void CopyTo() { OnCopy(false, false, GetFocusedPanelIndex()); } void MoveTo() { OnCopy(true, false, GetFocusedPanelIndex()); } void Delete(bool toRecycleBin) { GetFocusedPanel().DeleteItems(toRecycleBin); } + HRESULT CalculateCrc2(const UString &methodName); void CalculateCrc(const UString &methodName); void DiffFiles(); void Split(); @@ -204,6 +205,7 @@ public: #ifndef UNDER_CE void Link(); + void OpenAltStreams() { GetFocusedPanel().OpenAltStreams(); } #endif void CreateFolder() { GetFocusedPanel().CreateFolder(); } diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp index 32db8f8f..89a6b45a 100644 --- a/CPP/7zip/UI/FileManager/BrowseDialog.cpp +++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp @@ -77,7 +77,7 @@ static void MessageBox_HResError(HWND wnd, HRESULT errorCode, const wchar_t *nam UString s = HResultToMessage(errorCode); if (name) { - s += L'\n'; + s.Add_LF(); s += name; } MessageBox_Error_Global(wnd, s); @@ -209,7 +209,7 @@ bool CBrowseDialog::OnInit() FOR_VECTOR (i, Filters) { if (i != 0) - s += L' '; + s.Add_Space(); s += Filters[i]; } } @@ -256,14 +256,16 @@ bool CBrowseDialog::OnInit() _topDirPrefix.Empty(); { int rootSize = GetRootPrefixSize(FilePath); + #if defined(_WIN32) && !defined(UNDER_CE) // We can go up from root folder to drives list - if (NName::IsDrivePath(FilePath)) + if (IsDrivePath(FilePath)) rootSize = 0; else if (IsSuperPath(FilePath)) { - if (NName::IsDrivePath(&FilePath[kSuperPathPrefixSize])) + if (IsDrivePath(FilePath.Ptr(kSuperPathPrefixSize))) rootSize = kSuperPathPrefixSize; } + #endif _topDirPrefix.SetFrom(FilePath, rootSize); } @@ -466,7 +468,7 @@ bool CBrowseDialog::GetParentPath(const UString &path, UString &parentPrefix, US return false; if (s.Back() == WCHAR_PATH_SEPARATOR) return false; - int pos = s.ReverseFind(WCHAR_PATH_SEPARATOR); + int pos = s.ReverseFind_PathSepar(); parentPrefix.SetFrom(s, pos + 1); name = s.Ptr(pos + 1); return true; @@ -856,7 +858,7 @@ bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path, return false; { UString s = errorMessage; - s += L"\n"; + s.Add_LF(); s += path; MessageBox_Error_Global(owner, s); } @@ -904,27 +906,32 @@ bool CorrectFsPath(const UString &relBase, const UString &path2, UString &result result.Empty(); UString path = path2; - path.Replace('/', WCHAR_PATH_SEPARATOR); + path.Replace(L'/', WCHAR_PATH_SEPARATOR); unsigned start = 0; UString base; - if (NName::IsAbsolutePath(path)) + + if (IsAbsolutePath(path)) { + #if defined(_WIN32) && !defined(UNDER_CE) if (IsSuperOrDevicePath(path)) { result = path; return true; } + #endif int pos = GetRootPrefixSize(path); if (pos > 0) start = pos; } else { + #if defined(_WIN32) && !defined(UNDER_CE) if (IsSuperOrDevicePath(relBase)) { result = path; return true; } + #endif base = relBase; } @@ -954,6 +961,7 @@ bool CorrectFsPath(const UString &relBase, const UString &path2, UString &result result += path.Left(start); bool checkExist = true; UString cur; + for (;;) { if (start == path.Len()) @@ -979,7 +987,7 @@ bool CorrectFsPath(const UString &relBase, const UString &path2, UString &result result += cur; if (slashPos < 0) break; - result += WCHAR_PATH_SEPARATOR; + result.Add_PathSepar(); start = slashPos + 1; } diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.h b/CPP/7zip/UI/FileManager/BrowseDialog.h index 77c749b5..957af2e2 100644 --- a/CPP/7zip/UI/FileManager/BrowseDialog.h +++ b/CPP/7zip/UI/FileManager/BrowseDialog.h @@ -9,7 +9,7 @@ bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultP bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path, LPCWSTR filterDescription, LPCWSTR filter, UString &resultPath); /* CorrectFsPath removes undesirable characters in names (dots and spaces at the end of file) - But it doesn't change "bad" name in any of the following caes: + But it doesn't change "bad" name in any of the following cases: - path is Super Path (with \\?\ prefix) - path is relative and relBase is Super Path - there is file or dir in filesystem with specified "bad" name */ diff --git a/CPP/7zip/UI/FileManager/EditPage.rc b/CPP/7zip/UI/FileManager/EditPage.rc index f5618d04..38f74ea1 100644 --- a/CPP/7zip/UI/FileManager/EditPage.rc +++ b/CPP/7zip/UI/FileManager/EditPage.rc @@ -1,7 +1,7 @@ #include "EditPageRes.h" #include "../../GuiCommon.rc" -#define xc 200 +#define xc 240 #define yc 80 IDD_EDIT MY_PAGE diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp index ed4bb884..50c43163 100644 --- a/CPP/7zip/UI/FileManager/ExtractCallback.cpp +++ b/CPP/7zip/UI/FileManager/ExtractCallback.cpp @@ -22,6 +22,7 @@ #endif #include "../GUI/ExtractRes.h" +#include "resourceGui.h" #include "ExtractCallback.h" #include "FormatUtils.h" @@ -30,6 +31,7 @@ #ifndef _NO_CRYPTO #include "PasswordDialog.h" #endif +#include "PropertyName.h" using namespace NWindows; using namespace NFile; @@ -39,6 +41,10 @@ CExtractCallbackImp::~CExtractCallbackImp() {} void CExtractCallbackImp::Init() { + _lang_Extracting = LangString(IDS_PROGRESS_EXTRACTING); + _lang_Testing = LangString(IDS_PROGRESS_TESTING); + _lang_Skipping = LangString(IDS_PROGRESS_SKIPPING); + NumArchiveErrors = 0; ThereAreMessageErrors = false; #ifndef _SFX @@ -97,6 +103,11 @@ HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, co return ProgressDialog->Sync.CheckStop(); } +HRESULT CExtractCallbackImp::Open_Finished() +{ + return ProgressDialog->Sync.CheckStop(); +} + #ifndef _NO_CRYPTO HRESULT CExtractCallbackImp::Open_CryptoGetTextPassword(BSTR *password) @@ -104,6 +115,7 @@ HRESULT CExtractCallbackImp::Open_CryptoGetTextPassword(BSTR *password) return CryptoGetTextPassword(password); } +/* HRESULT CExtractCallbackImp::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) { passwordIsDefined = PasswordIsDefined; @@ -116,10 +128,11 @@ bool CExtractCallbackImp::Open_WasPasswordAsked() return PasswordWasAsked; } -void CExtractCallbackImp::Open_ClearPasswordWasAskedFlag() +void CExtractCallbackImp::Open_Clear_PasswordWasAsked_Flag() { PasswordWasAsked = false; } +*/ #endif @@ -179,10 +192,21 @@ STDMETHODIMP CExtractCallbackImp::AskOverwrite( } -STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, bool isFolder, Int32 /* askExtractMode */, const UInt64 * /* position */) +STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 * /* position */) { - _isFolder = isFolder; - return SetCurrentFilePath2(name); + _isFolder = IntToBool(isFolder); + _currentFilePath = name; + + const UString *msg = &_lang_Empty; + switch (askExtractMode) + { + case NArchive::NExtract::NAskMode::kExtract: msg = &_lang_Extracting; break; + case NArchive::NExtract::NAskMode::kTest: msg = &_lang_Testing; break; + case NArchive::NExtract::NAskMode::kSkip: msg = &_lang_Skipping; break; + // default: s = "Unknown operation"; + } + + return ProgressDialog->Sync.Set_Status2(*msg, name, IntToBool(isFolder)); } STDMETHODIMP CExtractCallbackImp::MessageError(const wchar_t *s) @@ -208,101 +232,108 @@ STDMETHODIMP CExtractCallbackImp::ShowMessage(const wchar_t *s) #endif -STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 opRes, bool encrypted) +void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s) { + s.Empty(); + + if (opRes == NArchive::NExtract::NOperationResult::kOK) + return; + + UINT messageID = 0; + UINT id = 0; + switch (opRes) { - case NArchive::NExtract::NOperationResult::kOK: + case NArchive::NExtract::NOperationResult::kUnsupportedMethod: + messageID = IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD; + id = IDS_EXTRACT_MSG_UNSUPPORTED_METHOD; + break; + case NArchive::NExtract::NOperationResult::kDataError: + messageID = encrypted ? + IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED: + IDS_EXTRACT_MESSAGE_DATA_ERROR; + id = IDS_EXTRACT_MSG_DATA_ERROR; + break; + case NArchive::NExtract::NOperationResult::kCRCError: + messageID = encrypted ? + IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED: + IDS_EXTRACT_MESSAGE_CRC_ERROR; + id = IDS_EXTRACT_MSG_CRC_ERROR; + break; + case NArchive::NExtract::NOperationResult::kUnavailable: + id = IDS_EXTRACT_MSG_UNAVAILABLE_DATA; + break; + case NArchive::NExtract::NOperationResult::kUnexpectedEnd: + id = IDS_EXTRACT_MSG_UEXPECTED_END; break; + case NArchive::NExtract::NOperationResult::kDataAfterEnd: + id = IDS_EXTRACT_MSG_DATA_AFTER_END; + break; + case NArchive::NExtract::NOperationResult::kIsNotArc: + id = IDS_EXTRACT_MSG_IS_NOT_ARC; + break; + case NArchive::NExtract::NOperationResult::kHeadersError: + id = IDS_EXTRACT_MSG_HEADERS_ERROR; + break; + case NArchive::NExtract::NOperationResult::kWrongPassword: + id = IDS_EXTRACT_MSG_WRONG_PSW_CLAIM; + break; + /* default: - { - UINT messageID = 0; - UINT id = 0; - - switch (opRes) - { - case NArchive::NExtract::NOperationResult::kUnsupportedMethod: - messageID = IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD; - id = IDS_EXTRACT_MSG_UNSUPPORTED_METHOD; - break; - case NArchive::NExtract::NOperationResult::kDataError: - messageID = encrypted ? - IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED: - IDS_EXTRACT_MESSAGE_DATA_ERROR; - id = IDS_EXTRACT_MSG_DATA_ERROR; - break; - case NArchive::NExtract::NOperationResult::kCRCError: - messageID = encrypted ? - IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED: - IDS_EXTRACT_MESSAGE_CRC_ERROR; - id = IDS_EXTRACT_MSG_CRC_ERROR; - break; - case NArchive::NExtract::NOperationResult::kUnavailable: - id = IDS_EXTRACT_MSG_UNAVAILABLE_DATA; - break; - case NArchive::NExtract::NOperationResult::kUnexpectedEnd: - id = IDS_EXTRACT_MSG_UEXPECTED_END; - break; - case NArchive::NExtract::NOperationResult::kDataAfterEnd: - id = IDS_EXTRACT_MSG_DATA_AFTER_END; - break; - case NArchive::NExtract::NOperationResult::kIsNotArc: - id = IDS_EXTRACT_MSG_IS_NOT_ARC; - break; - case NArchive::NExtract::NOperationResult::kHeadersError: - id = IDS_EXTRACT_MSG_HEADERS_ERROR; - break; - /* - default: - messageID = IDS_EXTRACT_MESSAGE_UNKNOWN_ERROR; - break; - */ - } - if (_needWriteArchivePath) - { - if (!_currentArchivePath.IsEmpty()) - AddError_Message(_currentArchivePath); - _needWriteArchivePath = false; - } + messageID = IDS_EXTRACT_MESSAGE_UNKNOWN_ERROR; + break; + */ + } - UString msg; - UString msgOld; + UString msg; + UString msgOld; - #ifndef _SFX - if (id != 0) - LangString_OnlyFromLangFile(id, msg); - if (messageID != 0 && msg.IsEmpty()) - LangString_OnlyFromLangFile(messageID, msgOld); - #endif + #ifndef _SFX + if (id != 0) + LangString_OnlyFromLangFile(id, msg); + if (messageID != 0 && msg.IsEmpty()) + LangString_OnlyFromLangFile(messageID, msgOld); + #endif - UString s; - if (msg.IsEmpty() && !msgOld.IsEmpty()) - s = MyFormatNew(msgOld, _currentFilePath); - else - { - if (msg.IsEmpty()) - LangString(id, msg); - if (!msg.IsEmpty()) - s += msg; - else - { - wchar_t temp[16]; - ConvertUInt32ToString(opRes, temp); - s += L"Error #"; - s += temp; - } + if (msg.IsEmpty() && !msgOld.IsEmpty()) + s = MyFormatNew(msgOld, fileName); + else + { + if (msg.IsEmpty() && id != 0) + LangString(id, msg); + if (!msg.IsEmpty()) + s += msg; + else + { + char temp[16]; + ConvertUInt32ToString(opRes, temp); + s.AddAscii("Error #"); + s.AddAscii(temp); + } - if (encrypted) - { - // s += L" : "; - // s += LangString(IDS_EXTRACT_MSG_ENCRYPTED); - s += L" : "; - s += LangString(IDS_EXTRACT_MSG_WRONG_PSW); - } - s += L" : "; - s += _currentFilePath; - } + if (encrypted && opRes != NArchive::NExtract::NOperationResult::kWrongPassword) + { + // s.AddAscii(" : "); + // AddLangString(s, IDS_EXTRACT_MSG_ENCRYPTED); + s.AddAscii(" : "); + AddLangString(s, IDS_EXTRACT_MSG_WRONG_PSW_GUESS); + } + s.AddAscii(" : "); + s += fileName; + } +} +STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 opRes, Int32 encrypted) +{ + switch (opRes) + { + case NArchive::NExtract::NOperationResult::kOK: + break; + default: + { + UString s; + SetExtractErrorMessage(opRes, encrypted, _currentFilePath, s); + Add_ArchiveName_Error(); AddError_Message(s); } } @@ -318,10 +349,22 @@ STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 opRes, bool encrypted return S_OK; } +STDMETHODIMP CExtractCallbackImp::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name) +{ + if (opRes != NArchive::NExtract::NOperationResult::kOK) + { + UString s; + SetExtractErrorMessage(opRes, encrypted, name, s); + Add_ArchiveName_Error(); + AddError_Message(s); + } + return S_OK; +} + //////////////////////////////////////// // IExtractCallbackUI -HRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name) +HRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name, bool /* testMode */) { #ifndef _SFX RINOK(ProgressDialog->Sync.CheckStop()); @@ -357,27 +400,6 @@ HRESULT CExtractCallbackImp::SetCurrentFilePath(const wchar_t *path) UString HResultToMessage(HRESULT errorCode); -HRESULT CExtractCallbackImp::OpenResult(const wchar_t *name, HRESULT result, bool encrypted) -{ - if (result != S_OK) - { - UString s; - if (result == S_FALSE) - s = MyFormatNew(encrypted ? IDS_CANT_OPEN_ENCRYPTED_ARCHIVE : IDS_CANT_OPEN_ARCHIVE, name); - else - { - s = name; - s += L": "; - s += HResultToMessage(result); - } - MessageError(s); - NumArchiveErrors++; - } - _currentArchivePath = name; - _needWriteArchivePath = true; - return S_OK; -} - static const UInt32 k_ErrorFlagsIds[] = { IDS_EXTRACT_MSG_IS_NOT_ARC, @@ -393,9 +415,16 @@ static const UInt32 k_ErrorFlagsIds[] = IDS_EXTRACT_MSG_CRC_ERROR }; +static void AddNewLineString(UString &s, const UString &m) +{ + s += m; + s.Add_LF(); +} + UString GetOpenArcErrorMessage(UInt32 errorFlags) { UString s; + for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsIds); i++) { UInt32 f = ((UInt32)1 << i); @@ -407,14 +436,15 @@ UString GetOpenArcErrorMessage(UInt32 errorFlags) continue; if (f == kpv_ErrorFlags_EncryptedHeadersError) { - m += L" : "; - m += LangString(IDS_EXTRACT_MSG_WRONG_PSW); + m.AddAscii(" : "); + AddLangString(m, IDS_EXTRACT_MSG_WRONG_PSW_GUESS); } if (!s.IsEmpty()) - s += L'\n'; + s.Add_LF(); s += m; errorFlags &= ~f; } + if (errorFlags != 0) { char sz[16]; @@ -422,76 +452,153 @@ UString GetOpenArcErrorMessage(UInt32 errorFlags) sz[1] = 'x'; ConvertUInt32ToHex(errorFlags, sz + 2); if (!s.IsEmpty()) - s += L'\n'; - s += GetUnicodeString(AString(sz)); + s.Add_LF(); + s.AddAscii(sz); } + return s; } -HRESULT CExtractCallbackImp::SetError(int level, const wchar_t *name, - UInt32 errorFlags, const wchar_t *errors, - UInt32 warningFlags, const wchar_t *warnings) +static void ErrorInfo_Print(UString &s, const CArcErrorInfo &er) { - NumArchiveErrors++; + UInt32 errorFlags = er.GetErrorFlags(); + UInt32 warningFlags = er.GetWarningFlags(); - if (_needWriteArchivePath) + if (errorFlags != 0) + AddNewLineString(s, GetOpenArcErrorMessage(errorFlags)); + + if (!er.ErrorMessage.IsEmpty()) + AddNewLineString(s, er.ErrorMessage); + + if (warningFlags != 0) { - if (!_currentArchivePath.IsEmpty()) - AddError_Message(_currentArchivePath); - _needWriteArchivePath = false; + s += GetNameOfProperty(kpidWarningFlags, L"Warnings"); + s.AddAscii(":"); + s.Add_LF(); + AddNewLineString(s, GetOpenArcErrorMessage(warningFlags)); } - - if (level != 0) + + if (!er.WarningMessage.IsEmpty()) { - UString s; - s += name; - s += L": "; - MessageError(s); + s += GetNameOfProperty(kpidWarning, L"Warning"); + s.AddAscii(": "); + s += er.WarningMessage; + s.Add_LF(); } +} - if (errorFlags != 0) - MessageError(GetOpenArcErrorMessage(errorFlags)); +static UString GetBracedType(const wchar_t *type) +{ + UString s = L'['; + s += type; + s += L']'; + return s; +} - if (errors && wcslen(errors) != 0) - MessageError(errors); +void OpenResult_GUI(UString &s, const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) +{ + FOR_VECTOR (level, arcLink.Arcs) + { + const CArc &arc = arcLink.Arcs[level]; + const CArcErrorInfo &er = arc.ErrorInfo; - if (warningFlags != 0) - MessageError((UString)L"Warnings: " + GetOpenArcErrorMessage(warningFlags)); + if (!er.IsThereErrorOrWarning() && er.ErrorFormatIndex < 0) + continue; - if (warnings && wcslen(warnings) != 0) - MessageError((UString)L"Warnings: " + warnings); + if (s.IsEmpty()) + { + s += name; + s.Add_LF(); + } + + if (level != 0) + { + AddNewLineString(s, arc.Path); + } + + ErrorInfo_Print(s, er); - return S_OK; -} + if (er.ErrorFormatIndex >= 0) + { + AddNewLineString(s, GetNameOfProperty(kpidWarning, L"Warning")); + if (arc.FormatIndex == er.ErrorFormatIndex) + { + AddNewLineString(s, LangString(IDS_IS_OPEN_WITH_OFFSET)); + } + else + { + AddNewLineString(s, MyFormatNew(IDS_CANT_OPEN_AS_TYPE, GetBracedType(codecs->GetFormatNamePtr(er.ErrorFormatIndex)))); + AddNewLineString(s, MyFormatNew(IDS_IS_OPEN_AS_TYPE, GetBracedType(codecs->GetFormatNamePtr(arc.FormatIndex)))); + } + } + } -HRESULT CExtractCallbackImp::OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType) -{ - UString s = L"Warning:\n"; - s += name; - s += L"\n"; - if (wcscmp(okType, errorType) == 0) + if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0 || result != S_OK) { - s += L"The archive is open with offset"; + s += name; + s.Add_LF(); + if (!arcLink.Arcs.IsEmpty()) + AddNewLineString(s, arcLink.NonOpen_ArcPath); + + if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0 || result == S_FALSE) + { + UINT id = IDS_CANT_OPEN_ARCHIVE; + UString param; + if (arcLink.PasswordWasAsked) + id = IDS_CANT_OPEN_ENCRYPTED_ARCHIVE; + else if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) + { + id = IDS_CANT_OPEN_AS_TYPE; + param = GetBracedType(codecs->GetFormatNamePtr(arcLink.NonOpen_ErrorInfo.ErrorFormatIndex)); + } + UString s2 = MyFormatNew(id, param); + s2.Replace(L" ''", L""); + s2.Replace(L"''", L""); + s += s2; + } + else + s += HResultToMessage(result); + + s.Add_LF(); + ErrorInfo_Print(s, arcLink.NonOpen_ErrorInfo); } - else + + if (!s.IsEmpty() && s.Back() == '\n') + s.DeleteBack(); +} + +HRESULT CExtractCallbackImp::OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) +{ + _currentArchivePath = name; + _needWriteArchivePath = true; + + UString s; + OpenResult_GUI(s, codecs, arcLink, name, result); + if (!s.IsEmpty()) { - s += L"Can not open the file as ["; - s += errorType; - s += L"] archive\n"; - s += L"The file is open as ["; - s += okType; - s += L"] archive"; + NumArchiveErrors++; + AddError_Message(s); + _needWriteArchivePath = false; } - MessageError(s); - NumArchiveErrors++; + return S_OK; } - + HRESULT CExtractCallbackImp::ThereAreNoFiles() { return S_OK; } +void CExtractCallbackImp::Add_ArchiveName_Error() +{ + if (_needWriteArchivePath) + { + if (!_currentArchivePath.IsEmpty()) + AddError_Message(_currentArchivePath); + _needWriteArchivePath = false; + } +} + HRESULT CExtractCallbackImp::ExtractResult(HRESULT result) { if (result == S_OK) @@ -499,7 +606,10 @@ HRESULT CExtractCallbackImp::ExtractResult(HRESULT result) NumArchiveErrors++; if (result == E_ABORT || result == ERROR_DISK_FULL) return result; - MessageError(_currentFilePath); + + Add_ArchiveName_Error(); + if (!_currentFilePath.IsEmpty()) + MessageError(_currentFilePath); MessageError(NError::MyFormatMessage(result)); return S_OK; } @@ -564,7 +674,7 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( { if (!destFileInfo.IsDir()) { - RINOK(MessageError("can not replace file with folder with same name: ", destPathSys)); + RINOK(MessageError("can not replace file with folder with same name", destPathSys)); return E_ABORT; } *writeAnswer = BoolToInt(false); @@ -573,8 +683,9 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( if (destFileInfo.IsDir()) { - RINOK(MessageError("can not replace folder with file with same name: ", destPathSys)); - return E_FAIL; + RINOK(MessageError("can not replace folder with file with same name", destPathSys)); + *writeAnswer = BoolToInt(false); + return S_OK; } switch (OverwriteMode) @@ -583,13 +694,9 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( return S_OK; case NExtract::NOverwriteMode::kAsk: { - Int32 overwiteResult; + Int32 overwriteResult; UString destPathSpec = destPath; - int slashPos = destPathSpec.ReverseFind(L'/'); - #ifdef _WIN32 - int slash1Pos = destPathSpec.ReverseFind(L'\\'); - slashPos = MyMax(slashPos, slash1Pos); - #endif + int slashPos = destPathSpec.ReverseFind_PathSepar(); destPathSpec.DeleteFrom(slashPos + 1); destPathSpec += fs2us(destFileInfo.Name); @@ -598,9 +705,9 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( &destFileInfo.MTime, &destFileInfo.Size, srcPath, srcTime, srcSize, - &overwiteResult)); + &overwriteResult)); - switch (overwiteResult) + switch (overwriteResult) { case NOverwriteAnswer::kCancel: return E_ABORT; case NOverwriteAnswer::kNo: return S_OK; @@ -618,7 +725,7 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( { if (!AutoRenamePath(destPathSys)) { - RINOK(MessageError("can not create name for file: ", destPathSys)); + RINOK(MessageError("can not create name for file", destPathSys)); return E_ABORT; } destPathResultTemp = fs2us(destPathSys); @@ -626,7 +733,7 @@ STDMETHODIMP CExtractCallbackImp::AskWrite( else if (!NDir::DeleteFileAlways(destPathSys)) { - RINOK(MessageError("can not delete output file: ", destPathSys)); + RINOK(MessageError("can not delete output file", destPathSys)); return E_ABORT; } } @@ -783,7 +890,7 @@ STDMETHODIMP CExtractCallbackImp::PrepareOperation7(Int32 askExtractMode) COM_TRY_END } -STDMETHODIMP CExtractCallbackImp::SetOperationResult7(Int32 opRes, bool encrypted) +STDMETHODIMP CExtractCallbackImp::SetOperationResult7(Int32 opRes, Int32 encrypted) { COM_TRY_BEGIN if (VirtFileSystem && _newVirtFileWasAdded) @@ -865,7 +972,7 @@ HRESULT CVirtFileSystem::FlushToDisk(bool closeLast) while (_numFlushed < Files.Size()) { const CVirtFile &file = Files[_numFlushed]; - const FString path = DirPrefix + us2fs(GetCorrectFsPath(file.Name)); + const FString path = DirPrefix + us2fs(Get_Correct_FsFile_Name(file.Name)); if (!_fileIsOpen) { if (!_outFileStreamSpec->Create(path, false)) diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.h b/CPP/7zip/UI/FileManager/ExtractCallback.h index 71e48e5e..1654bcd6 100644 --- a/CPP/7zip/UI/FileManager/ExtractCallback.h +++ b/CPP/7zip/UI/FileManager/ExtractCallback.h @@ -36,8 +36,7 @@ class CGrowBuf Byte *_items; size_t _size; - CGrowBuf(const CGrowBuf &buffer); - void operator=(const CGrowBuf &buffer); + CLASS_NO_COPY(CGrowBuf); public: bool ReAlloc_KeepData(size_t newSize, size_t keepSize) @@ -45,7 +44,8 @@ public: void *buf = MyAlloc(newSize); if (!buf) return false; - memcpy(buf, _items, keepSize); + if (keepSize != 0) + memcpy(buf, _items, keepSize); MyFree(_items); _items = (Byte *)buf; _size = newSize; @@ -55,8 +55,8 @@ public: CGrowBuf(): _items(0), _size(0) {} ~CGrowBuf() { MyFree(_items); } - operator Byte *() { return _items; }; - operator const Byte *() const { return _items; }; + operator Byte *() { return _items; } + operator const Byte *() const { return _items; } size_t Size() const { return _size; } }; @@ -135,10 +135,11 @@ public: { if (_fileMode) return false; - if (Files.Size() < 1 || Files[0].IsAltStream || Files[0].IsDir) + if (Files.Size() < 1 || /* Files[0].IsAltStream || */ Files[0].IsDir) return false; return true; } + size_t GetMemStreamWrittenSize() const { return _pos; } CVirtFileSystem(): _outFileStreamSpec(NULL), MaxTotalAllocSize((UInt64)0 - 1) {} @@ -165,6 +166,7 @@ public: class CExtractCallbackImp: public IExtractCallbackUI, // it includes IFolderArchiveExtractCallback public IOpenCallbackUI, + public IFolderArchiveExtractCallback2, #ifndef _SFX public IFolderOperationsExtractCallback, public IFolderExtractToStreamCallback, @@ -176,8 +178,10 @@ class CExtractCallbackImp: public CMyUnknownImp { HRESULT MessageError(const char *message, const FString &path); + void Add_ArchiveName_Error(); public: MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback) + MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback2) #ifndef _SFX MY_QUERYINTERFACE_ENTRY(IFolderOperationsExtractCallback) MY_QUERYINTERFACE_ENTRY(IFolderExtractToStreamCallback) @@ -191,33 +195,12 @@ public: INTERFACE_IProgress(;) INTERFACE_IOpenCallbackUI(;) - - // IFolderArchiveExtractCallback + INTERFACE_IFolderArchiveExtractCallback(;) + INTERFACE_IFolderArchiveExtractCallback2(;) // STDMETHOD(SetTotalFiles)(UInt64 total); // STDMETHOD(SetCompletedFiles)(const UInt64 *value); - STDMETHOD(AskOverwrite)( - const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, - const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, - Int32 *answer); - STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position); - STDMETHOD(MessageError)(const wchar_t *message); - STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted); - - // IExtractCallbackUI - - HRESULT BeforeOpen(const wchar_t *name); - HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted); - HRESULT SetError(int level, const wchar_t *name, - UInt32 errorFlags, const wchar_t *errors, - UInt32 warningFlags, const wchar_t *warnings); - HRESULT ThereAreNoFiles(); - HRESULT ExtractResult(HRESULT result); - HRESULT OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType); - - #ifndef _NO_CRYPTO - HRESULT SetPassword(const UString &password); - #endif + INTERFACE_IExtractCallbackUI(;) #ifndef _SFX // IFolderOperationsExtractCallback @@ -295,6 +278,12 @@ public: UString Password; #endif + + UString _lang_Extracting; + UString _lang_Testing; + UString _lang_Skipping; + UString _lang_Empty; + CExtractCallbackImp(): #ifndef _NO_CRYPTO PasswordIsDefined(false), diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp index 537103ae..00b152c8 100644 --- a/CPP/7zip/UI/FileManager/FM.cpp +++ b/CPP/7zip/UI/FileManager/FM.cpp @@ -49,6 +49,9 @@ static UString g_MainPath; static UString g_ArcFormat; static bool g_Maximized = false; +// HRESULT LoadGlobalCodecs(); +void FreeGlobalCodecs(); + #ifndef UNDER_CE DWORD g_ComCtl32Version; @@ -568,6 +571,13 @@ static int WINAPI WinMain2(int nCmdShow) if (!InitInstance (nCmdShow)) return FALSE; + // we will load Global_Codecs at first use instead. + /* + OutputDebugStringW(L"Before LoadGlobalCodecs"); + LoadGlobalCodecs(); + OutputDebugStringW(L"After LoadGlobalCodecs"); + */ + #ifndef _UNICODE if (g_IsNT) { @@ -597,6 +607,10 @@ static int WINAPI WinMain2(int nCmdShow) } } + // Destructor of g_CodecsReleaser can release DLLs. + // But we suppose that it's better to release DLLs here (before destructor). + FreeGlobalCodecs(); + g_HWND = 0; #ifndef UNDER_CE OleUninitialize(); @@ -780,35 +794,45 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) xSizes[1] = 0; g_App.CreateDragTarget(); + bool archiveIsOpened; bool encrypted; bool needOpenFile = false; - if (!g_MainPath.IsEmpty() /* && g_OpenArchive */) + + UString fullPath = g_MainPath; + if (!fullPath.IsEmpty() /* && g_OpenArchive */) { - if (NFile::NFind::DoesFileExist(us2fs(g_MainPath))) + if (!NFile::NName::IsAbsolutePath(fullPath)) + { + FString fullPathF; + if (NFile::NName::GetFullPath(us2fs(fullPath), fullPathF)) + fullPath = fs2us(fullPathF); + } + if (NFile::NFind::DoesFileExist(us2fs(fullPath))) needOpenFile = true; } - HRESULT res = g_App.Create(hWnd, g_MainPath, g_ArcFormat, xSizes, archiveIsOpened, encrypted); + + HRESULT res = g_App.Create(hWnd, fullPath, g_ArcFormat, xSizes, archiveIsOpened, encrypted); if (res == E_ABORT) - { return -1; - } + if (needOpenFile && !archiveIsOpened || res != S_OK) { UString message = L"Error"; if (res == S_FALSE || res == S_OK) { message = MyFormatNew(encrypted ? - IDS_CANT_OPEN_ENCRYPTED_ARCHIVE : - IDS_CANT_OPEN_ARCHIVE, - g_MainPath); + IDS_CANT_OPEN_ENCRYPTED_ARCHIVE : + IDS_CANT_OPEN_ARCHIVE, + fullPath); } else if (res != S_OK) message = HResultToMessage(res); ErrorMessage(message); return -1; } + // g_SplitterPos = 0; // ::DragAcceptFiles(hWnd, TRUE); @@ -816,6 +840,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) break; } + case WM_DESTROY: { // ::DragAcceptFiles(hWnd, FALSE); @@ -839,11 +864,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) g_StartCaptureSplitterPos = g_Splitter.GetPos(); ::SetCapture(hWnd); break; + case WM_LBUTTONUP: { ::ReleaseCapture(); break; } + case WM_MOUSEMOVE: { if ((wParam & MK_LBUTTON) != 0 && ::GetCapture() == hWnd) @@ -880,10 +907,12 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) return 0; break; } + case WM_SETFOCUS: // g_App.SetFocus(g_App.LastFocusedPanel); g_App.SetFocusToLastItem(); break; + /* case WM_ACTIVATE: { @@ -900,6 +929,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) break; } */ + /* case kLangWasChangedMessage: MyLoadMenu(); @@ -910,11 +940,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_SETTINGCHANGE: break; */ + case WM_NOTIFY: { g_App.OnNotify((int)wParam, (LPNMHDR)lParam); break; } + /* case WM_DROPFILES: { diff --git a/CPP/7zip/UI/FileManager/FM.dsp b/CPP/7zip/UI/FileManager/FM.dsp index 4a7f16a6..f18e5441 100644 --- a/CPP/7zip/UI/FileManager/FM.dsp +++ b/CPP/7zip/UI/FileManager/FM.dsp @@ -219,6 +219,14 @@ SOURCE=.\Test.bmp # PROP Default_Filter "" # Begin Source File +SOURCE=.\AltStreamsFolder.cpp +# End Source File +# Begin Source File + +SOURCE=.\AltStreamsFolder.h +# End Source File +# Begin Source File + SOURCE=.\FSDrives.cpp # End Source File # Begin Source File @@ -1026,6 +1034,10 @@ SOURCE=..\..\..\Windows\Window.h # PROP Default_Filter "" # Begin Source File +SOURCE=..\..\..\Common\Common.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\ComTry.h # End Source File # Begin Source File @@ -1399,6 +1411,14 @@ SOURCE=..\GUI\HashGUI.cpp SOURCE=..\GUI\HashGUI.h # End Source File +# Begin Source File + +SOURCE=..\GUI\UpdateCallbackGUI2.cpp +# End Source File +# Begin Source File + +SOURCE=..\GUI\UpdateCallbackGUI2.h +# End Source File # End Group # End Group # Begin Group "Compress" diff --git a/CPP/7zip/UI/FileManager/FM.mak b/CPP/7zip/UI/FileManager/FM.mak index 234a5920..6a85ea2f 100644 --- a/CPP/7zip/UI/FileManager/FM.mak +++ b/CPP/7zip/UI/FileManager/FM.mak @@ -60,6 +60,7 @@ FM_OBJS = \ !IFNDEF UNDER_CE FM_OBJS = $(FM_OBJS) \ + $O\AltStreamsFolder.obj \ $O\FSDrives.obj \ $O\LinkDialog.obj \ $O\NetFolder.obj \ diff --git a/CPP/7zip/UI/FileManager/FSDrives.cpp b/CPP/7zip/UI/FileManager/FSDrives.cpp index 84639de7..69f89325 100644 --- a/CPP/7zip/UI/FileManager/FSDrives.cpp +++ b/CPP/7zip/UI/FileManager/FSDrives.cpp @@ -11,6 +11,7 @@ #include "../../../Windows/FileDir.h" #include "../../../Windows/FileIO.h" +#include "../../../Windows/FileName.h" #include "../../../Windows/FileSystem.h" #include "../../../Windows/PropVariant.h" @@ -27,8 +28,8 @@ using namespace NWindows; using namespace NFile; using namespace NFind; -static CFSTR kVolPrefix = FTEXT("\\\\.\\"); -static CFSTR kLongPrefix = FTEXT("\\\\?\\"); +static const CFSTR kVolPrefix = FTEXT("\\\\.\\"); +static const CFSTR kSuperPrefix = FTEXT("\\\\?\\"); FString CDriveInfo::GetDeviceFileIoName() const { @@ -53,6 +54,7 @@ static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt if (!inFile.GetLength(fileSize)) ::GetLastError(); } + NIO::COutFile outFile; if (writeToDisk) { @@ -62,6 +64,7 @@ static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt else if (!outFile.Create(toPath, true)) return GetLastError(); + CPhysTempBuffer tempBuffer; tempBuffer.buffer = MidAlloc(bufferSize); if (!tempBuffer.buffer) @@ -93,12 +96,14 @@ static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt return E_FAIL; pos += curSize; } + return S_OK; } static const PROPID kProps[] = { kpidName, + // kpidOutName, kpidTotalSize, kpidFreeSpace, kpidType, @@ -107,7 +112,7 @@ static const PROPID kProps[] = kpidClusterSize }; -static const char *kDriveTypes[] = +static const char * const kDriveTypes[] = { "Unknown" , "No Root Dir" @@ -219,6 +224,16 @@ STDMETHODIMP CFSDrives::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT { case kpidIsDir: prop = !_volumeMode; break; case kpidName: prop = di.Name; break; + case kpidOutName: + if (!di.Name.IsEmpty() && di.Name.Back() == ':') + { + FString s = di.Name; + s.DeleteBack(); + AddExt(s, itemIndex); + prop = s; + } + break; + case kpidTotalSize: if (di.KnownSize) prop = di.DriveSize; break; case kpidFreeSpace: if (di.KnownSizes) prop = di.FreeSpace; break; case kpidClusterSize: if (di.KnownSizes) prop = di.ClusterSize; break; @@ -240,14 +255,11 @@ HRESULT CFSDrives::BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder) return S_OK; NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder; CMyComPtr<IFolderFolder> subFolder = fsFolderSpec; - if (_longMode) - { - RINOK(fsFolderSpec->Init((FString)kLongPrefix + name, 0)); - } - else - { - RINOK(fsFolderSpec->Init(name, 0)); - } + FString path; + if (_superMode) + path = kSuperPrefix; + path += name; + RINOK(fsFolderSpec->Init(path)); *resultFolder = subFolder.Detach(); return S_OK; } @@ -295,8 +307,8 @@ STDMETHODIMP CFSDrives::GetFolderProperty(PROPID propID, PROPVARIANT *value) case kpidPath: if (_volumeMode) prop = kVolPrefix; - else if (_longMode) - prop = kLongPrefix; + else if (_superMode) + prop = kSuperPrefix; else prop = (UString)LangString(IDS_COMPUTER) + WCHAR_PATH_SEPARATOR; break; @@ -322,19 +334,20 @@ STDMETHODIMP CFSDrives::GetSystemIconIndex(UInt32 index, Int32 *iconIndex) return GetLastError(); } -const wchar_t *CFSDrives::GetExt(unsigned index) const +void CFSDrives::AddExt(FString &s, unsigned index) const { + s += FTEXT('.'); const CDriveInfo &di = _drives[index]; - const wchar_t *ext; + const char *ext; if (di.DriveType == DRIVE_CDROM) - ext = L"iso"; - else if (di.FileSystemName.Find(L"NTFS") >= 0) - ext = L"ntfs"; - else if (di.FileSystemName.Find(L"FAT") >= 0) - ext = L"fat"; + ext = "iso"; + else if (di.FileSystemName.IsPrefixedBy_Ascii_NoCase("NTFS")) + ext = "ntfs"; + else if (di.FileSystemName.IsPrefixedBy_Ascii_NoCase("FAT")) + ext = "fat"; else - ext = L"img"; - return ext; + ext = "img"; + s.AddAscii(ext); } HRESULT CFSDrives::GetFileSize(unsigned index, UInt64 &fileSize) const @@ -352,12 +365,12 @@ STDMETHODIMP CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num Int32 /* includeAltStreams */, Int32 /* replaceAltStreamColon */, const wchar_t *path, IFolderOperationsExtractCallback *callback) { - if (moveMode) - return E_NOTIMPL; - if (numItems == 0) return S_OK; + if (moveMode) + return E_NOTIMPL; + if (!_volumeMode) return E_NOTIMPL; @@ -372,11 +385,14 @@ STDMETHODIMP CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num RINOK(callback->SetTotal(totalSize)); RINOK(callback->SetNumFiles(numItems)); - UString destPath = path; + FString destPath = us2fs(path); if (destPath.IsEmpty()) return E_INVALIDARG; - bool directName = (destPath.Back() != WCHAR_PATH_SEPARATOR); - if (directName) + + bool isAltDest = NName::IsAltPathPrefix(destPath); + bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back())); + + if (isDirectPath) { if (numItems > 1) return E_INVALIDARG; @@ -389,19 +405,19 @@ STDMETHODIMP CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num { unsigned index = indices[i]; const CDriveInfo &di = _drives[index]; - UString destPath2 = destPath; - UString name = fs2us(di.Name); - if (!directName) + FString destPath2 = destPath; + + if (!isDirectPath) { - UString destName = name; - if (!destName.IsEmpty() && destName.Back() == L':') + FString destName = di.Name; + if (!destName.IsEmpty() && destName.Back() == ':') { destName.DeleteBack(); - destName += L'.'; - destName += GetExt(index); + AddExt(destName, index); } destPath2 += destName; } + FString srcPath = di.GetDeviceFileIoName(); UInt64 fileSize = 0; @@ -410,15 +426,23 @@ STDMETHODIMP CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num return E_FAIL; } if (!di.KnownSize) + { totalSize += fileSize; - RINOK(callback->SetTotal(totalSize)); + RINOK(callback->SetTotal(totalSize)); + } Int32 writeAskResult; CMyComBSTR destPathResult; RINOK(callback->AskWrite(fs2us(srcPath), BoolToInt(false), NULL, &fileSize, - destPath2, &destPathResult, &writeAskResult)); + fs2us(destPath2), &destPathResult, &writeAskResult)); + if (!IntToBool(writeAskResult)) + { + if (totalSize >= fileSize) + totalSize -= fileSize; + RINOK(callback->SetTotal(totalSize)); continue; + } RINOK(callback->SetCurrentFilePath(fs2us(srcPath))); @@ -427,11 +451,12 @@ STDMETHODIMP CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num RINOK(CopyFileSpec(srcPath, us2fs(destPathResult), false, fileSize, bufferSize, completedSize, callback)); completedSize += fileSize; } + return S_OK; } STDMETHODIMP CFSDrives::CopyFrom(Int32 /* moveMode */, const wchar_t * /* fromFolderPath */, - const wchar_t ** /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */) + const wchar_t * const * /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */) { return E_NOTIMPL; } diff --git a/CPP/7zip/UI/FileManager/FSDrives.h b/CPP/7zip/UI/FileManager/FSDrives.h index a8e25d7d..f12e4da8 100644 --- a/CPP/7zip/UI/FileManager/FSDrives.h +++ b/CPP/7zip/UI/FileManager/FSDrives.h @@ -36,10 +36,10 @@ class CFSDrives: { CObjectVector<CDriveInfo> _drives; bool _volumeMode; - bool _longMode; + bool _superMode; HRESULT BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder); - const wchar_t *GetExt(unsigned index) const; + void AddExt(FString &s, unsigned index) const; HRESULT GetFileSize(unsigned index, UInt64 &fileSize) const; public: MY_UNKNOWN_IMP2(IFolderGetSystemIconIndex, IFolderOperations) @@ -49,10 +49,10 @@ public: STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex); - void Init(bool volMode = false, bool longMode = false) + void Init(bool volMode = false, bool superMode = false) { _volumeMode = volMode; - _longMode = longMode; + _superMode = superMode; } }; diff --git a/CPP/7zip/UI/FileManager/FSFolder.cpp b/CPP/7zip/UI/FileManager/FSFolder.cpp index a27066c3..e46afb9e 100644 --- a/CPP/7zip/UI/FileManager/FSFolder.cpp +++ b/CPP/7zip/UI/FileManager/FSFolder.cpp @@ -29,7 +29,7 @@ // But real support version for that function is NT 3.1 (probably) // So we must define GetCompressedFileSizeW EXTERN_C_BEGIN -WINBASEAPI DWORD WINAPI GetCompressedFileSizeW(LPCWSTR lpFileName, LPDWORD lpFileSizeHigh ); +WINBASEAPI DWORD WINAPI GetCompressedFileSizeW(LPCWSTR lpFileName, LPDWORD lpFileSizeHigh); EXTERN_C_END #endif #endif @@ -68,20 +68,23 @@ static const Byte kProps[] = kpidPrefix }; -HRESULT CFSFolder::Init(const FString &path, IFolderFolder *parentFolder) +HRESULT CFSFolder::Init(const FString &path /* , IFolderFolder *parentFolder */) { - _parentFolder = parentFolder; + // _parentFolder = parentFolder; _path = path; _findChangeNotification.FindFirst(_path, false, - FILE_NOTIFY_CHANGE_FILE_NAME | - FILE_NOTIFY_CHANGE_DIR_NAME | - FILE_NOTIFY_CHANGE_ATTRIBUTES | - FILE_NOTIFY_CHANGE_SIZE | - FILE_NOTIFY_CHANGE_LAST_WRITE /*| - FILE_NOTIFY_CHANGE_LAST_ACCESS | - FILE_NOTIFY_CHANGE_CREATION | - FILE_NOTIFY_CHANGE_SECURITY */); + FILE_NOTIFY_CHANGE_FILE_NAME + | FILE_NOTIFY_CHANGE_DIR_NAME + | FILE_NOTIFY_CHANGE_ATTRIBUTES + | FILE_NOTIFY_CHANGE_SIZE + | FILE_NOTIFY_CHANGE_LAST_WRITE + /* + | FILE_NOTIFY_CHANGE_LAST_ACCESS + | FILE_NOTIFY_CHANGE_CREATION + | FILE_NOTIFY_CHANGE_SECURITY + */ + ); if (!_findChangeNotification.IsHandleAllocated()) { DWORD lastError = GetLastError(); @@ -99,7 +102,7 @@ HRESULT CFsFolderStat::Enumerate() { RINOK(Progress->SetCompleted(NULL)); } - Path += FCHAR_PATH_SEPARATOR; + Path.Add_PathSepar(); unsigned len = Path.Len(); Path += FCHAR_ANY_MASK; CEnumerator enumerator(Path); @@ -124,7 +127,7 @@ HRESULT CFsFolderStat::Enumerate() #ifndef UNDER_CE -static bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size) +bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size) { DWORD highPart; DWORD lowPart = INVALID_FILE_SIZE; @@ -140,10 +143,10 @@ static bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size) #ifdef WIN_LONG_PATH if (USE_SUPER_PATH) { - UString longPath; - if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) { - lowPart = ::GetCompressedFileSizeW(longPath, &highPart); + lowPart = ::GetCompressedFileSizeW(superPath, &highPart); if (lowPart != INVALID_FILE_SIZE || ::GetLastError() == NO_ERROR) { size = ((UInt64)highPart << 32) | lowPart; @@ -279,11 +282,10 @@ bool CFSFolder::LoadComments() if (len >= (1 << 28)) return false; AString s; - char *p = s.GetBuffer((unsigned)((size_t)len + 1)); + char *p = s.GetBuf((unsigned)(size_t)len); UInt32 processedSize; file.Read(p, (UInt32)len, processedSize); - p[len] = 0; - s.ReleaseBuffer(); + s.ReleaseBuf_CalcLen((unsigned)(size_t)len); if (processedSize != len) return false; file.Close(); @@ -293,14 +295,6 @@ bool CFSFolder::LoadComments() return _comments.ReadFromString(unicodeString); } -static bool IsAscii(const AString &s) -{ - for (unsigned i = 0; i < s.Len(); i++) - if ((Byte)s[i] >= 0x80) - return false; - return true; -} - bool CFSFolder::SaveComments() { AString utf; @@ -309,7 +303,7 @@ bool CFSFolder::SaveComments() _comments.SaveToString(unicode); ConvertUnicodeToUTF8(unicode, utf); } - if (!IsAscii(utf)) + if (!utf.IsAscii()) utf.Insert(0, "\xEF\xBB\xBF" "\r\n"); FString path = _path + kDescriptionFileName; @@ -576,7 +570,7 @@ STDMETHODIMP CFSFolder::GetRawProp(UInt32 static inline CFSTR GetExtensionPtr(const FString &name) { - int dotPos = name.ReverseFind(FTEXT('.')); + int dotPos = name.ReverseFind_Dot(); return name.Ptr((dotPos < 0) ? name.Len() : dotPos); } @@ -686,7 +680,7 @@ HRESULT CFSFolder::BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder) *resultFolder = 0; CFSFolder *folderSpec = new CFSFolder; CMyComPtr<IFolderFolder> subFolder = folderSpec; - RINOK(folderSpec->Init(_path + name + FCHAR_PATH_SEPARATOR, 0)); + RINOK(folderSpec->Init(_path + name + FCHAR_PATH_SEPARATOR)); *resultFolder = subFolder.Detach(); return S_OK; } @@ -700,6 +694,7 @@ void CFSFolder::GetPrefix(const CDirItem &item, FString &prefix) const prefix.Empty(); } */ + /* void CFSFolder::GetPrefix(const CDirItem &item, FString &prefix) const { @@ -714,20 +709,17 @@ void CFSFolder::GetPrefix(const CDirItem &item, FString &prefix) const parent = cur.Parent; } - unsigned totalLen = len; - wchar_t *p = prefix.GetBuffer(len); + wchar_t *p = prefix.GetBuf_SetEnd(len) + len; parent = item.Parent; while (parent >= 0) { const CDirItem &cur = Files[parent]; - // path = cur->Name + FCHAR_PATH_SEPARATOR + path; - MyStringCopy(p + len - cur.Name.Len() - 1, (const wchar_t *)cur.Name); - p[--len] = FCHAR_PATH_SEPARATOR; - len -= cur.Name.Len(); + *(--p) = FCHAR_PATH_SEPARATOR; + p -= cur.Name.Len(); + wmemcpy(p, cur.Name, cur.Name.Len()); parent = cur.Parent; } - prefix.ReleaseBuffer(totalLen); } */ @@ -752,24 +744,26 @@ STDMETHODIMP CFSFolder::BindToFolder(const wchar_t *name, IFolderFolder **result return BindToFolderSpec(us2fs(name), resultFolder); } -static CFSTR kLongPrefix = FTEXT("\\\\?\\"); +static const CFSTR kSuperPrefix = FTEXT("\\\\?\\"); STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder) { *resultFolder = 0; + /* if (_parentFolder) { CMyComPtr<IFolderFolder> parentFolder = _parentFolder; *resultFolder = parentFolder.Detach(); return S_OK; } + */ if (_path.IsEmpty()) return E_INVALIDARG; - int pos = _path.ReverseFind(FCHAR_PATH_SEPARATOR); + int pos = _path.ReverseFind_PathSepar(); if (pos < 0 || pos != (int)_path.Len() - 1) return E_FAIL; FString parentPath = _path.Left(pos); - pos = parentPath.ReverseFind(FCHAR_PATH_SEPARATOR); + pos = parentPath.ReverseFind_PathSepar(); if (pos < 0) { #ifdef UNDER_CE @@ -783,9 +777,10 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder) return S_OK; } + /* parentPath.DeleteFrom(pos + 1); - if (parentPath == kLongPrefix) + if (parentPath == kSuperPrefix) { #ifdef UNDER_CE *resultFolder = 0; @@ -801,10 +796,10 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder) FString parentPathReduced = parentPath.Left(pos); #ifndef UNDER_CE - pos = parentPathReduced.ReverseFind(FCHAR_PATH_SEPARATOR); + pos = parentPathReduced.ReverseFind_PathSepar(); if (pos == 1) { - if (parentPath[0] != FCHAR_PATH_SEPARATOR) + if (!IS_PATH_SEPAR_CHAR(parentPath[0])) return E_FAIL; CNetFolder *netFolderSpec = new CNetFolder; CMyComPtr<IFolderFolder> netFolder = netFolderSpec; @@ -818,6 +813,7 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder) CMyComPtr<IFolderFolder> parentFolder = parentFolderSpec; RINOK(parentFolderSpec->Init(parentPath, 0)); *resultFolder = parentFolder.Detach(); + */ return S_OK; } @@ -837,7 +833,7 @@ STDMETHODIMP CFSFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) NWindows::NCOM::CPropVariant prop; switch (propID) { - case kpidType: prop = L"FSFolder"; break; + case kpidType: prop = "FSFolder"; break; case kpidPath: prop = fs2us(_path); break; } prop.Detach(value); @@ -874,7 +870,7 @@ STDMETHODIMP CFSFolder::Clone(IFolderFolder **resultFolder) { CFSFolder *fsFolderSpec = new CFSFolder; CMyComPtr<IFolderFolder> folderNew = fsFolderSpec; - fsFolderSpec->Init(_path, 0); + fsFolderSpec->Init(_path); *resultFolder = folderNew.Detach(); return S_OK; } @@ -1060,7 +1056,7 @@ STDMETHODIMP CFSFolder::SetProperty(UInt32 index, PROPID propID, CTextPair pair; pair.ID = filename; pair.ID.Trim(); - pair.Value = value->bstrVal; + pair.Value.SetFromBstr(value->bstrVal); pair.Value.Trim(); if (pair.Value.IsEmpty()) _comments.DeletePair(filename); diff --git a/CPP/7zip/UI/FileManager/FSFolder.h b/CPP/7zip/UI/FileManager/FSFolder.h index cb0d4ec2..057ba14c 100644 --- a/CPP/7zip/UI/FileManager/FSFolder.h +++ b/CPP/7zip/UI/FileManager/FSFolder.h @@ -8,9 +8,10 @@ #include "../../../Windows/FileFind.h" +#include "../../Archive/IArchive.h" + #include "IFolder.h" #include "TextPairs.h" -#include "..\..\Archive\IArchive.h" namespace NFsFolder { @@ -133,7 +134,7 @@ private: CObjectVector<CDirItem> Files; FStringVector Folders; // CObjectVector<CAltStream> Streams; - CMyComPtr<IFolderFolder> _parentFolder; + // CMyComPtr<IFolderFolder> _parentFolder; bool _commentsAreLoaded; CPairsStorage _comments; @@ -158,9 +159,9 @@ private: #endif public: - HRESULT Init(const FString &path, IFolderFolder *parentFolder); - #ifdef UNDER_CE - HRESULT InitToRoot() { return Init(FTEXT("\\"), NULL); } + HRESULT Init(const FString &path /* , IFolderFolder *parentFolder */); + #if !defined(_WIN32) || defined(UNDER_CE) + HRESULT InitToRoot() { return Init(FSTRING_PATH_SEPARATOR /* , NULL */); } #endif CFSFolder() : _flatMode(false) @@ -178,6 +179,7 @@ public: } // void GetPrefix(const CDirItem &item, FString &prefix) const; + FString GetRelPath(const CDirItem &item) const; void Clear() @@ -188,6 +190,24 @@ public: } }; +struct CCopyStateIO +{ + IProgress *Progress; + UInt64 TotalSize; + UInt64 StartPos; + UInt64 CurrentSize; + bool DeleteSrcFile; + + int ErrorFileIndex; + UString ErrorMessage; + + CCopyStateIO(): DeleteSrcFile(false), TotalSize(0), StartPos(0) {} + + HRESULT MyCopyFile(CFSTR inPath, CFSTR outPath); +}; + +HRESULT SendLastErrorMessage(IFolderOperationsExtractCallback *callback, const FString &fileName); + } #endif diff --git a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp index 3f2fc9af..54dabc57 100644 --- a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp +++ b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp @@ -29,6 +29,75 @@ extern bool g_IsNT; namespace NFsFolder { +HRESULT CCopyStateIO::MyCopyFile(CFSTR inPath, CFSTR outPath) +{ + ErrorFileIndex = -1; + ErrorMessage.Empty(); + CurrentSize = 0; + + { + const size_t kBufSize = 1 << 16; + CByteArr buf(kBufSize); + + NIO::CInFile inFile; + NIO::COutFile outFile; + + if (!inFile.Open(inPath)) + { + ErrorFileIndex = 0; + return S_OK; + } + + if (!outFile.Create(outPath, true)) + { + ErrorFileIndex = 1; + return S_OK; + } + + for (;;) + { + UInt32 num; + if (!inFile.Read(buf, kBufSize, num)) + { + ErrorFileIndex = 0; + return S_OK; + } + if (num == 0) + break; + + UInt32 written = 0; + if (!outFile.Write(buf, num, written)) + { + ErrorFileIndex = 1; + return S_OK; + } + if (written != num) + { + ErrorMessage = L"Write error"; + return S_OK; + } + CurrentSize += num; + if (Progress) + { + UInt64 completed = StartPos + CurrentSize; + RINOK(Progress->SetCompleted(&completed)); + } + } + } + + if (DeleteSrcFile) + { + if (!DeleteFileAlways(inPath)) + { + ErrorFileIndex = 0; + return S_OK; + } + } + + return S_OK; +} + + /* static bool IsItWindows2000orHigher() { @@ -43,8 +112,13 @@ static bool IsItWindows2000orHigher() struct CProgressInfo { + UInt64 TotalSize; UInt64 StartPos; + UInt64 FileSize; IProgress *Progress; + HRESULT ProgressResult; + + void Init() { ProgressResult = S_OK; } }; #ifndef PROGRESS_CONTINUE @@ -71,7 +145,7 @@ DWORD #endif static DWORD CALLBACK CopyProgressRoutine( - LARGE_INTEGER /* TotalFileSize */, // file size + LARGE_INTEGER TotalFileSize, // file size LARGE_INTEGER TotalBytesTransferred, // bytes transferred LARGE_INTEGER /* StreamSize */, // bytes in stream LARGE_INTEGER /* StreamBytesTransferred */, // bytes transferred for stream @@ -82,14 +156,27 @@ static DWORD CALLBACK CopyProgressRoutine( LPVOID lpData // from CopyFileEx ) { - CProgressInfo &progressInfo = *(CProgressInfo *)lpData; - UInt64 completed = progressInfo.StartPos + TotalBytesTransferred.QuadPart; - if (progressInfo.Progress->SetCompleted(&completed) != S_OK) - return PROGRESS_CANCEL; - return PROGRESS_CONTINUE; + TotalFileSize = TotalFileSize; + // TotalBytesTransferred = TotalBytesTransferred; + // StreamSize = StreamSize; + // StreamBytesTransferred = StreamBytesTransferred; + // dwStreamNumber = dwStreamNumber; + // dwCallbackReason = dwCallbackReason; + + CProgressInfo &pi = *(CProgressInfo *)lpData; + + if ((UInt64)TotalFileSize.QuadPart > pi.FileSize) + { + pi.TotalSize += (UInt64)TotalFileSize.QuadPart - pi.FileSize; + pi.FileSize = (UInt64)TotalFileSize.QuadPart; + pi.ProgressResult = pi.Progress->SetTotal(pi.TotalSize); + } + UInt64 completed = pi.StartPos + TotalBytesTransferred.QuadPart; + pi.ProgressResult = pi.Progress->SetCompleted(&completed); + return (pi.ProgressResult == S_OK ? PROGRESS_CONTINUE : PROGRESS_CANCEL); } -typedef BOOL (WINAPI * CopyFileExPointer)( +typedef BOOL (WINAPI * Func_CopyFileExA)( IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName, IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, @@ -98,7 +185,7 @@ typedef BOOL (WINAPI * CopyFileExPointer)( IN DWORD dwCopyFlags ); -typedef BOOL (WINAPI * CopyFileExPointerW)( +typedef BOOL (WINAPI * Func_CopyFileExW)( IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, @@ -107,110 +194,152 @@ typedef BOOL (WINAPI * CopyFileExPointerW)( IN DWORD dwCopyFlags ); -static bool FsCopyFile(CFSTR oldFile, CFSTR newFile, IProgress *progress, UInt64 &completedSize) +typedef BOOL (WINAPI * Func_MoveFileWithProgressW)( + IN LPCWSTR lpExistingFileName, + IN LPCWSTR lpNewFileName, + IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, + IN LPVOID lpData OPTIONAL, + IN DWORD dwFlags + ); + +struct CCopyState { - CProgressInfo progressInfo; - progressInfo.Progress = progress; - progressInfo.StartPos = completedSize; - BOOL CancelFlag = FALSE; + CProgressInfo ProgressInfo; + IFolderOperationsExtractCallback *Callback; + UInt64 TotalSize; + bool MoveMode; + bool UseReadWriteMode; + + Func_CopyFileExW my_CopyFileExW; + #ifndef UNDER_CE + Func_MoveFileWithProgressW my_MoveFileWithProgressW; + #endif #ifndef _UNICODE - if (g_IsNT) + Func_CopyFileExA my_CopyFileExA; + #endif + + void Prepare(); + bool CopyFile_NT(const wchar_t *oldFile, const wchar_t *newFile); + bool CopyFile_Sys(CFSTR oldFile, CFSTR newFile); + bool MoveFile_Sys(CFSTR oldFile, CFSTR newFile); + + HRESULT CallProgress(); + + bool IsCallbackProgressError() { return ProgressInfo.ProgressResult != S_OK; } +}; + +HRESULT CCopyState::CallProgress() +{ + return ProgressInfo.Progress->SetCompleted(&ProgressInfo.StartPos); +} + +void CCopyState::Prepare() +{ + my_CopyFileExW = NULL; + #ifndef UNDER_CE + my_MoveFileWithProgressW = NULL; #endif + #ifndef _UNICODE + my_CopyFileExA = NULL; + if (!g_IsNT) { - const wchar_t *k_DllName = - #ifdef UNDER_CE + my_CopyFileExA = (Func_CopyFileExA)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "CopyFileExA"); + } + else + #endif + { + HMODULE module = ::GetModuleHandleW( + #ifdef UNDER_CE L"coredll.dll" - #else + #else L"kernel32.dll" - #endif - ; - CopyFileExPointerW copyFunctionW = (CopyFileExPointerW) - My_GetProcAddress(::GetModuleHandleW(k_DllName), "CopyFileExW"); - + #endif + ); + my_CopyFileExW = (Func_CopyFileExW)My_GetProcAddress(module, "CopyFileExW"); + #ifndef UNDER_CE + my_MoveFileWithProgressW = (Func_MoveFileWithProgressW)My_GetProcAddress(module, "MoveFileWithProgressW"); + #endif + } +} + +/* WinXP-64: + CopyFileW(fromFile, toFile:altStream) + OK - there are NO alt streams in fromFile + ERROR_INVALID_PARAMETER - there are alt streams in fromFile +*/ + +bool CCopyState::CopyFile_NT(const wchar_t *oldFile, const wchar_t *newFile) +{ + BOOL cancelFlag = FALSE; + if (my_CopyFileExW) + return BOOLToBool(my_CopyFileExW(oldFile, newFile, CopyProgressRoutine, + &ProgressInfo, &cancelFlag, COPY_FILE_FAIL_IF_EXISTS)); + return BOOLToBool(::CopyFileW(oldFile, newFile, TRUE)); +} + +bool CCopyState::CopyFile_Sys(CFSTR oldFile, CFSTR newFile) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + if (my_CopyFileExA) + { + BOOL cancelFlag = FALSE; + if (my_CopyFileExA(fs2fas(oldFile), fs2fas(newFile), + CopyProgressRoutine, &ProgressInfo, &cancelFlag, COPY_FILE_FAIL_IF_EXISTS)) + return true; + if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return false; + } + return BOOLToBool(::CopyFile(fs2fas(oldFile), fs2fas(newFile), TRUE)); + } + else + #endif + { IF_USE_MAIN_PATH_2(oldFile, newFile) { - if (copyFunctionW == 0) - return BOOLToBool(::CopyFileW(fs2us(oldFile), fs2us(newFile), TRUE)); - if (copyFunctionW(fs2us(oldFile), fs2us(newFile), CopyProgressRoutine, - &progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS)) + if (CopyFile_NT(fs2us(oldFile), fs2us(newFile))) return true; } #ifdef WIN_LONG_PATH if (USE_SUPER_PATH_2) { - UString longPathExisting, longPathNew; - if (!GetSuperPaths(oldFile, newFile, longPathExisting, longPathNew, USE_MAIN_PATH_2)) + if (IsCallbackProgressError()) + return false; + UString superPathOld, superPathNew; + if (!GetSuperPaths(oldFile, newFile, superPathOld, superPathNew, USE_MAIN_PATH_2)) return false; - if (copyFunctionW(longPathExisting, longPathNew, CopyProgressRoutine, - &progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS)) + if (CopyFile_NT(superPathOld, superPathNew)) return true; } #endif return false; } - #ifndef _UNICODE - else - { - CopyFileExPointer copyFunction = (CopyFileExPointer) - ::GetProcAddress(::GetModuleHandleA("kernel32.dll"), - "CopyFileExA"); - if (copyFunction != 0) - { - if (copyFunction(fs2fas(oldFile), fs2fas(newFile), - CopyProgressRoutine,&progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS)) - return true; - if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) - return false; - } - return BOOLToBool(::CopyFile(fs2fas(oldFile), fs2fas(newFile), TRUE)); - } - #endif } -typedef BOOL (WINAPI * MoveFileWithProgressPointer)( - IN LPCWSTR lpExistingFileName, - IN LPCWSTR lpNewFileName, - IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, - IN LPVOID lpData OPTIONAL, - IN DWORD dwFlags - ); - -#ifdef UNDER_CE -#define NON_CE_VAR(_v_) -#else -#define NON_CE_VAR(_v_) _v_ -#endif - -static bool FsMoveFile(CFSTR oldFile, CFSTR newFile, - IProgress * NON_CE_VAR(progress), - UInt64 & NON_CE_VAR(completedSize)) +bool CCopyState::MoveFile_Sys(CFSTR oldFile, CFSTR newFile) { #ifndef UNDER_CE // if (IsItWindows2000orHigher()) // { - CProgressInfo progressInfo; - progressInfo.Progress = progress; - progressInfo.StartPos = completedSize; - - MoveFileWithProgressPointer moveFunction = (MoveFileWithProgressPointer) - My_GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), - "MoveFileWithProgressW"); - if (moveFunction != 0) + if (my_MoveFileWithProgressW) { IF_USE_MAIN_PATH_2(oldFile, newFile) { - if (moveFunction(fs2us(oldFile), fs2us(newFile), CopyProgressRoutine, - &progressInfo, MOVEFILE_COPY_ALLOWED)) + if (my_MoveFileWithProgressW(fs2us(oldFile), fs2us(newFile), CopyProgressRoutine, + &ProgressInfo, MOVEFILE_COPY_ALLOWED)) return true; } #ifdef WIN_LONG_PATH if ((!(USE_MAIN_PATH_2) || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) && USE_SUPER_PATH_2) { - UString longPathExisting, longPathNew; - if (!GetSuperPaths(oldFile, newFile, longPathExisting, longPathNew, USE_MAIN_PATH_2)) + if (IsCallbackProgressError()) + return false; + UString superPathOld, superPathNew; + if (!GetSuperPaths(oldFile, newFile, superPathOld, superPathNew, USE_MAIN_PATH_2)) return false; - if (moveFunction(longPathExisting, longPathNew, CopyProgressRoutine, - &progressInfo, MOVEFILE_COPY_ALLOWED)) + if (my_MoveFileWithProgressW(superPathOld, superPathNew, CopyProgressRoutine, + &ProgressInfo, MOVEFILE_COPY_ALLOWED)) return true; } #endif @@ -226,7 +355,10 @@ static bool FsMoveFile(CFSTR oldFile, CFSTR newFile, static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback, const wchar_t *message, const FString &fileName) { - return callback->ShowMessage(message + fs2us(fileName)); + UString s = message; + s += L" : "; + s += fs2us(fileName); + return callback->ShowMessage(s); } static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback, @@ -235,41 +367,104 @@ static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback, return SendMessageError(callback, MultiByteToUnicodeString(message), fileName); } -static HRESULT FsCopyFile( +static DWORD Return_LastError_or_FAIL() +{ + DWORD errorCode = GetLastError(); + if (errorCode == 0) + errorCode = (DWORD)E_FAIL; + return errorCode; +} + +static UString GetLastErrorMessage() +{ + return NError::MyFormatMessage(Return_LastError_or_FAIL()); +} + +HRESULT SendLastErrorMessage(IFolderOperationsExtractCallback *callback, const FString &fileName) +{ + return SendMessageError(callback, GetLastErrorMessage(), fileName); +} + +static HRESULT CopyFile_Ask( + CCopyState &state, const FString &srcPath, const CFileInfo &srcFileInfo, - const FString &destPathSpec, - IFolderOperationsExtractCallback *callback, - UInt64 &completedSize) + const FString &destPath) { - FString destPath = destPathSpec; if (CompareFileNames(destPath, srcPath) == 0) { - RINOK(SendMessageError(callback, "can not copy file onto itself: ", destPath)); + RINOK(SendMessageError(state.Callback, + state.MoveMode ? + "can not move file onto itself" : + "can not copy file onto itself" + , destPath)); return E_ABORT; } Int32 writeAskResult; CMyComBSTR destPathResult; - RINOK(callback->AskWrite( + RINOK(state.Callback->AskWrite( fs2us(srcPath), BoolToInt(false), &srcFileInfo.MTime, &srcFileInfo.Size, fs2us(destPath), &destPathResult, &writeAskResult)); + if (IntToBool(writeAskResult)) { - FString destPathNew = us2fs((const wchar_t *)(BSTR)destPathResult); - RINOK(callback->SetCurrentFilePath(fs2us(srcPath))); - if (!FsCopyFile(srcPath, destPathNew, callback, completedSize)) + FString destPathNew = us2fs((LPCOLESTR)destPathResult); + RINOK(state.Callback->SetCurrentFilePath(fs2us(srcPath))); + + if (state.UseReadWriteMode) { - RINOK(SendMessageError(callback, NError::MyFormatMessage(GetLastError()) + L" : ", destPathNew)); - return E_ABORT; + NFsFolder::CCopyStateIO state2; + state2.Progress = state.Callback; + state2.DeleteSrcFile = state.MoveMode; + state2.TotalSize = state.TotalSize; + state2.StartPos = state.ProgressInfo.StartPos; + RINOK(state2.MyCopyFile(srcPath, destPathNew)); + if (state2.ErrorFileIndex >= 0) + { + if (state2.ErrorMessage.IsEmpty()) + state2.ErrorMessage = GetLastErrorMessage(); + FString errorName; + if (state2.ErrorFileIndex == 0) + errorName = srcPath; + else + errorName = destPathNew; + RINOK(SendMessageError(state.Callback, state2.ErrorMessage, errorName)); + return E_ABORT; + } + state.ProgressInfo.StartPos += state2.CurrentSize; + } + else + { + state.ProgressInfo.FileSize = srcFileInfo.Size; + bool res; + if (state.MoveMode) + res = state.MoveFile_Sys(srcPath, destPathNew); + else + res = state.CopyFile_Sys(srcPath, destPathNew); + RINOK(state.ProgressInfo.ProgressResult); + if (!res) + { + // GetLastError() is ERROR_REQUEST_ABORTED in case of PROGRESS_CANCEL. + RINOK(SendMessageError(state.Callback, GetLastErrorMessage(), destPathNew)); + return E_ABORT; + } + state.ProgressInfo.StartPos += state.ProgressInfo.FileSize; } } - completedSize += srcFileInfo.Size; - return callback->SetCompleted(&completedSize); + else + { + if (state.TotalSize >= srcFileInfo.Size) + { + state.TotalSize -= srcFileInfo.Size; + RINOK(state.ProgressInfo.Progress->SetTotal(state.TotalSize)); + } + } + return state.CallProgress(); } static FString CombinePath(const FString &folderPath, const FString &fileName) @@ -288,123 +483,70 @@ static bool IsDestChild(const FString &src, const FString &dest) } static HRESULT CopyFolder( - const FString &srcPath, - const FString &destPath, - IFolderOperationsExtractCallback *callback, - UInt64 &completedSize) + CCopyState &state, + const FString &srcPath, // without TAIL separator + const FString &destPath) // without TAIL separator { - RINOK(callback->SetCompleted(&completedSize)); + RINOK(state.CallProgress()); if (IsDestChild(srcPath, destPath)) { - RINOK(SendMessageError(callback, "can not copy folder onto itself: ", destPath)); + RINOK(SendMessageError(state.Callback, + state.MoveMode ? + "can not copy folder onto itself" : + "can not move folder onto itself" + , destPath)); return E_ABORT; } + if (state.MoveMode) + { + if (state.MoveFile_Sys(srcPath, destPath)) + return S_OK; + + // MSDN: MoveFile() fails for dirs on different volumes. + } + if (!CreateComplexDir(destPath)) { - RINOK(SendMessageError(callback, "can not create folder: ", destPath)); + RINOK(SendMessageError(state.Callback, "can not create folder", destPath)); return E_ABORT; } + CEnumerator enumerator(CombinePath(srcPath, FSTRING_ANY_MASK)); - CDirItem fi; - while (enumerator.Next(fi)) + + for (;;) { + NFind::CFileInfo fi; + bool found; + if (!enumerator.Next(fi, found)) + { + SendLastErrorMessage(state.Callback, srcPath); + return S_OK; + } + if (!found) + break; const FString srcPath2 = CombinePath(srcPath, fi.Name); const FString destPath2 = CombinePath(destPath, fi.Name); if (fi.IsDir()) { - RINOK(CopyFolder(srcPath2, destPath2, callback, completedSize)) + RINOK(CopyFolder(state, srcPath2, destPath2)) } else { - RINOK(FsCopyFile(srcPath2, fi, destPath2, callback, completedSize)); + RINOK(CopyFile_Ask(state, srcPath2, fi, destPath2)); } } - return S_OK; -} - -///////////////////////////////////////////////// -// Move Operations - -static HRESULT FsMoveFile( - const FString &srcPath, - const CFileInfo &srcFileInfo, - const FString &destPath, - IFolderOperationsExtractCallback *callback, - UInt64 &completedSize) -{ - if (CompareFileNames(destPath, srcPath) == 0) - { - RINOK(SendMessageError(callback, "can not move file onto itself: ", srcPath)); - return E_ABORT; - } - - Int32 writeAskResult; - CMyComBSTR destPathResult; - RINOK(callback->AskWrite( - fs2us(srcPath), - BoolToInt(false), - &srcFileInfo.MTime, &srcFileInfo.Size, - fs2us(destPath), - &destPathResult, - &writeAskResult)); - if (IntToBool(writeAskResult)) - { - FString destPathNew = us2fs((const wchar_t *)(BSTR)destPathResult); - RINOK(callback->SetCurrentFilePath(fs2us(srcPath))); - if (!FsMoveFile(srcPath, destPathNew, callback, completedSize)) - { - RINOK(SendMessageError(callback, "can not move to file: ", destPathNew)); - } - } - completedSize += srcFileInfo.Size; - RINOK(callback->SetCompleted(&completedSize)); - return S_OK; -} - -static HRESULT FsMoveFolder( - const FString &srcPath, - const FString &destPath, - IFolderOperationsExtractCallback *callback, - UInt64 &completedSize) -{ - if (IsDestChild(srcPath, destPath)) - { - RINOK(SendMessageError(callback, "can not move folder onto itself: ", destPath)); - return E_ABORT; - } - if (FsMoveFile(srcPath, destPath, callback, completedSize)) - return S_OK; - - if (!CreateComplexDir(destPath)) + if (state.MoveMode) { - RINOK(SendMessageError(callback, "can not create folder: ", destPath)); - return E_ABORT; - } - { - CEnumerator enumerator(CombinePath(srcPath, FSTRING_ANY_MASK)); - CDirItem fi; - while (enumerator.Next(fi)) + if (!RemoveDir(srcPath)) { - const FString srcPath2 = CombinePath(srcPath, fi.Name); - const FString destPath2 = CombinePath(destPath, fi.Name); - if (fi.IsDir()) - { - RINOK(FsMoveFolder(srcPath2, destPath2, callback, completedSize)); - } - else - { - RINOK(FsMoveFile(srcPath2, fi, destPath2, callback, completedSize)); - } + RINOK(SendMessageError(state.Callback, "can not remove folder", srcPath)); + return E_ABORT; } } - if (!RemoveDir(srcPath)) - { - RINOK(SendMessageError(callback, "can not remove folder: ", srcPath)); - return E_ABORT; - } + return S_OK; } @@ -415,33 +557,44 @@ STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num if (numItems == 0) return S_OK; - CFsFolderStat stat; - stat.Progress = callback; - RINOK(GetItemsFullSize(indices, numItems, stat)); - RINOK(callback->SetTotal(stat.Size)); - RINOK(callback->SetNumFiles(stat.NumFiles)); - FString destPath = us2fs(path); if (destPath.IsEmpty()) return E_INVALIDARG; - bool directName = (destPath.Back() != FCHAR_PATH_SEPARATOR); - if (directName) + + bool isAltDest = NName::IsAltPathPrefix(destPath);; + bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back())); + + if (isDirectPath) { if (numItems > 1) return E_INVALIDARG; } - else - { - // Does CreateComplexDir work in network ? - if (!CreateComplexDir(destPath)) - { - RINOK(SendMessageError(callback, "can not create folder: ", destPath)); - return E_ABORT; - } - } + + CFsFolderStat stat; + stat.Progress = callback; + RINOK(GetItemsFullSize(indices, numItems, stat)); + + if (stat.NumFolders != 0 && isAltDest) + return E_NOTIMPL; + + RINOK(callback->SetTotal(stat.Size)); + RINOK(callback->SetNumFiles(stat.NumFiles)); UInt64 completedSize = 0; RINOK(callback->SetCompleted(&completedSize)); + + CCopyState state; + state.ProgressInfo.TotalSize = stat.Size; + state.ProgressInfo.TotalSize = stat.Size; + state.ProgressInfo.StartPos = 0; + state.ProgressInfo.Progress = callback; + state.ProgressInfo.Init(); + state.Callback = callback; + state.MoveMode = IntToBool(moveMode); + state.UseReadWriteMode = isAltDest; + state.Prepare(); + state.TotalSize = stat.Size; + for (UInt32 i = 0; i < numItems; i++) { UInt32 index = indices[i]; @@ -449,38 +602,25 @@ STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num continue; const CDirItem &fi = Files[index]; FString destPath2 = destPath; - if (!directName) + if (!isDirectPath) destPath2 += fi.Name; FString srcPath; GetFullPath(fi, srcPath); + if (fi.IsDir()) { - if (moveMode) - { - RINOK(FsMoveFolder(srcPath, destPath2, callback, completedSize)); - } - else - { - RINOK(CopyFolder(srcPath, destPath2, callback, completedSize)); - } + RINOK(CopyFolder(state, srcPath, destPath2)); } else { - if (moveMode) - { - RINOK(FsMoveFile(srcPath, fi, destPath2, callback, completedSize)); - } - else - { - RINOK(FsCopyFile(srcPath, fi, destPath2, callback, completedSize)); - } + RINOK(CopyFile_Ask(state, srcPath, fi, destPath2)); } } return S_OK; } STDMETHODIMP CFSFolder::CopyFrom(Int32 /* moveMode */, const wchar_t * /* fromFolderPath */, - const wchar_t ** /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */) + const wchar_t * const * /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */) { /* UInt64 numFolders, numFiles, totalSize; diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp index 2d3b1d92..dc46ff5b 100644 --- a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp +++ b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp @@ -55,12 +55,10 @@ static int FindPlugin(const CObjectVector<CPluginInfo> &plugins, const UString & } */ -static const FChar kExtensionDelimiter = FTEXT('.'); - static void SplitNameToPureNameAndExtension(const FString &fullName, FString &pureName, FString &extensionDelimiter, FString &extension) { - int index = fullName.ReverseFind(kExtensionDelimiter); + int index = fullName.ReverseFind_Dot(); if (index < 0) { pureName = fullName; @@ -70,7 +68,7 @@ static void SplitNameToPureNameAndExtension(const FString &fullName, else { pureName.SetFrom(fullName, index); - extensionDelimiter = kExtensionDelimiter; + extensionDelimiter = FTEXT('.'); extension = fullName.Ptr(index + 1); } } @@ -89,7 +87,7 @@ HRESULT OpenFileFolderPlugin( FString extension, name, pureName, dot; - int slashPos = path.ReverseFind(FCHAR_PATH_SEPARATOR); + int slashPos = path.ReverseFind_PathSepar(); FString dirPrefix; FString fileName; if (slashPos >= 0) diff --git a/CPP/7zip/UI/FileManager/FilePlugins.cpp b/CPP/7zip/UI/FileManager/FilePlugins.cpp index 556c54fd..46000301 100644 --- a/CPP/7zip/UI/FileManager/FilePlugins.cpp +++ b/CPP/7zip/UI/FileManager/FilePlugins.cpp @@ -11,7 +11,7 @@ int CExtDatabase::FindExt(const UString &ext) { FOR_VECTOR (i, Exts) - if (Exts[i].Ext.IsEqualToNoCase(ext)) + if (Exts[i].Ext.IsEqualTo_NoCase(ext)) return i; return -1; } diff --git a/CPP/7zip/UI/FileManager/FoldersPage.rc b/CPP/7zip/UI/FileManager/FoldersPage.rc index fb48ee6e..cb345ea6 100644 --- a/CPP/7zip/UI/FileManager/FoldersPage.rc +++ b/CPP/7zip/UI/FileManager/FoldersPage.rc @@ -1,7 +1,7 @@ #include "FoldersPageRes.h" #include "../../GuiCommon.rc" -#define xc 196 +#define xc 240 #define yc 100 IDD_FOLDERS MY_PAGE diff --git a/CPP/7zip/UI/FileManager/IFolder.h b/CPP/7zip/UI/FileManager/IFolder.h index 60991a71..c5cff06e 100644 --- a/CPP/7zip/UI/FileManager/IFolder.h +++ b/CPP/7zip/UI/FileManager/IFolder.h @@ -36,6 +36,21 @@ FOLDER_INTERFACE(IFolderFolder, 0x00) INTERFACE_FolderFolder(PURE) }; +/* + IFolderAltStreams:: + BindToAltStreams((UInt32)(Int32)-1, ... ) means alt streams of that folder +*/ + +#define INTERFACE_FolderAltStreams(x) \ + STDMETHOD(BindToAltStreams)(UInt32 index, IFolderFolder **resultFolder) x; \ + STDMETHOD(BindToAltStreams)(const wchar_t *name, IFolderFolder **resultFolder) x; \ + STDMETHOD(AreAltStreamsSupported)(UInt32 index, Int32 *isSupported) x; \ + +FOLDER_INTERFACE(IFolderAltStreams, 0x17) +{ + INTERFACE_FolderAltStreams(PURE) +}; + FOLDER_INTERFACE(IFolderWasChanged, 0x04) { STDMETHOD(WasChanged)(Int32 *wasChanged) PURE; @@ -67,7 +82,7 @@ FOLDER_INTERFACE_SUB(IFolderOperationsExtractCallback, IProgress, 0x0B) Int32 includeAltStreams, Int32 replaceAltStreamCharsMode, \ const wchar_t *path, IFolderOperationsExtractCallback *callback) x; \ STDMETHOD(CopyFrom)(Int32 moveMode, const wchar_t *fromFolderPath, \ - const wchar_t **itemsPaths, UInt32 numItems, IProgress *progress) x; \ + const wchar_t * const *itemsPaths, UInt32 numItems, IProgress *progress) x; \ STDMETHOD(SetProperty)(UInt32 index, PROPID propID, const PROPVARIANT *value, IProgress *progress) x; \ STDMETHOD(CopyFromFile)(UInt32 index, const wchar_t *fullFilePath, IProgress *progress) x; \ diff --git a/CPP/7zip/UI/FileManager/LangPage.cpp b/CPP/7zip/UI/FileManager/LangPage.cpp index 54253295..d9dc6c52 100644 --- a/CPP/7zip/UI/FileManager/LangPage.cpp +++ b/CPP/7zip/UI/FileManager/LangPage.cpp @@ -63,8 +63,7 @@ bool CLangPage::OnInit() if (!LangOpen(lang, dirPrefix + fi.Name)) { - if (!error.IsEmpty()) - error += L' '; + error.Add_Space_if_NotEmpty(); error += fs2us(fi.Name); continue; } @@ -80,7 +79,7 @@ bool CLangPage::OnInit() index = (int)_langCombo.AddString(s); _langCombo.SetItemData(index, _paths.Size()); _paths.Add(shortName); - if (g_LangID.IsEqualToNoCase(shortName)) + if (g_LangID.IsEqualTo_NoCase(shortName)) _langCombo.SetCurSel(index); } diff --git a/CPP/7zip/UI/FileManager/LangPage.rc b/CPP/7zip/UI/FileManager/LangPage.rc index 5aeaf406..164e2d30 100644 --- a/CPP/7zip/UI/FileManager/LangPage.rc +++ b/CPP/7zip/UI/FileManager/LangPage.rc @@ -1,7 +1,7 @@ #include "LangPageRes.h" #include "../../GuiCommon.rc" -#define xc 148 +#define xc 160 #define yc 100 IDD_LANG DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT diff --git a/CPP/7zip/UI/FileManager/LangUtils.cpp b/CPP/7zip/UI/FileManager/LangUtils.cpp index 15d68f43..9723704a 100644 --- a/CPP/7zip/UI/FileManager/LangUtils.cpp +++ b/CPP/7zip/UI/FileManager/LangUtils.cpp @@ -115,6 +115,11 @@ UString LangString(UInt32 langID) return MyLoadString(langID); } +void AddLangString(UString &s, UInt32 langID) +{ + s += LangString(langID); +} + void LangString(UInt32 langID, UString &dest) { const wchar_t *s = g_Lang.Get(langID); @@ -166,7 +171,7 @@ static void FindShortNames(UInt32 primeLang, UStringVector &names) p++; } while (p != p2) - s += (wchar_t)*p++; + s += (wchar_t)(Byte)*p++; names.Add(s); } p = p2 + 1; diff --git a/CPP/7zip/UI/FileManager/LangUtils.h b/CPP/7zip/UI/FileManager/LangUtils.h index 509a5ae3..d63a443c 100644 --- a/CPP/7zip/UI/FileManager/LangUtils.h +++ b/CPP/7zip/UI/FileManager/LangUtils.h @@ -25,13 +25,15 @@ void LangSetDlgItems_Colon(HWND dialog, const UInt32 *ids, unsigned numItems); void LangSetWindowText(HWND window, UInt32 langID); UString LangString(UInt32 langID); +void AddLangString(UString &s, UInt32 langID); void LangString(UInt32 langID, UString &dest); void LangString_OnlyFromLangFile(UInt32 langID, UString &dest); - + #else inline UString LangString(UInt32 langID) { return NWindows::MyLoadString(langID); } inline void LangString(UInt32 langID, UString &dest) { NWindows::MyLoadString(langID, dest); } +inline void AddLangString(UString &s, UInt32 langID) { s += NWindows::MyLoadString(langID); } #endif diff --git a/CPP/7zip/UI/FileManager/LinkDialog.cpp b/CPP/7zip/UI/FileManager/LinkDialog.cpp index a24ec601..bc482e4b 100644 --- a/CPP/7zip/UI/FileManager/LinkDialog.cpp +++ b/CPP/7zip/UI/FileManager/LinkDialog.cpp @@ -321,14 +321,14 @@ void CApp::Link() int index = indices[0]; const UString itemName = srcPanel.GetItemName(index); - UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index); + UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index); UString path = srcPath; { int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); CPanel &destPanel = Panels[destPanelIndex]; if (NumPanels > 1) if (destPanel.IsFSFolder()) - path = destPanel._currentFolderPrefix; + path = destPanel.GetFsPath(); } CLinkDialog dlg; diff --git a/CPP/7zip/UI/FileManager/MenuPage.rc b/CPP/7zip/UI/FileManager/MenuPage.rc index 626f415e..f20c574e 100644 --- a/CPP/7zip/UI/FileManager/MenuPage.rc +++ b/CPP/7zip/UI/FileManager/MenuPage.rc @@ -1,7 +1,7 @@ #include "MenuPageRes.h" #include "../../GuiCommon.rc" -#define xc 196 +#define xc 240 #define yc 196 IDD_MENU MY_PAGE diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp index 401e48ef..b0f6615e 100644 --- a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp +++ b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp @@ -13,6 +13,7 @@ #include "App.h" #include "HelpUtils.h" #include "LangUtils.h" +#include "MyLoadMenu.h" #include "RegistryUtils.h" #include "resource.h" @@ -100,19 +101,19 @@ public: #define MIIM_FTYPE 0x00000100 #endif -static UINT Get_fMaskForString() +static UINT Get_fMask_for_String() { return g_IsNew_fMask ? MIIM_STRING : MIIM_TYPE; } -static UINT Get_fMaskForFTypeAndString() +static UINT Get_fMask_for_FType_and_String() { return g_IsNew_fMask ? (MIIM_STRING | MIIM_FTYPE) : MIIM_TYPE; } */ -static inline UINT Get_fMaskForString() { return MIIM_TYPE; } -static inline UINT Get_fMaskForFTypeAndString() { return MIIM_TYPE; } +static inline UINT Get_fMask_for_String() { return MIIM_TYPE; } +static inline UINT Get_fMask_for_FType_and_String() { return MIIM_TYPE; } static void MyChangeMenu(HMENU menuLoc, int level, int menuIndex) { @@ -121,7 +122,7 @@ static void MyChangeMenu(HMENU menuLoc, int level, int menuIndex) for (int i = 0;; i++) { CMenuItem item; - item.fMask = Get_fMaskForString() | MIIM_SUBMENU | MIIM_ID; + item.fMask = Get_fMask_for_String() | MIIM_SUBMENU | MIIM_ID; item.fType = MFT_STRING; if (!menu.GetItem(i, true, item)) break; @@ -157,14 +158,13 @@ static void MyChangeMenu(HMENU menuLoc, int level, int menuIndex) if (newString.IsEmpty()) continue; - UString shorcutString = item.StringValue; - int tabPos = shorcutString.ReverseFind(wchar_t('\t')); + int tabPos = item.StringValue.ReverseFind(L'\t'); if (tabPos >= 0) - newString += shorcutString.Ptr(tabPos); + newString += item.StringValue.Ptr(tabPos); } { item.StringValue = newString; - item.fMask = Get_fMaskForString(); + item.fMask = Get_fMask_for_String(); item.fType = MFT_STRING; menu.SetItem(i, true, item); } @@ -203,7 +203,7 @@ static void CopyMenu(HMENU srcMenuSpec, HMENU destMenuSpec) for (int i = 0;; i++) { CMenuItem item; - item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMaskForFTypeAndString(); + item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMask_for_FType_and_String(); item.fType = MFT_STRING; if (!srcMenu.GetItem(i, true, item)) @@ -307,13 +307,14 @@ void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position) subMenu.Attach(menu.GetSubMenu(0)); subMenu.RemoveAllItems(); int i; + for (i = 0; i < 10; i++) { UString s = LangString(IDS_BOOKMARK); - s += L' '; + s.Add_Space(); wchar_t c = (wchar_t)(L'0' + i); s += c; - s += L"\tAlt+Shift+"; + s.AddAscii("\tAlt+Shift+"); s += c; subMenu.AppendItem(MF_STRING, kSetBookmarkMenuID + i, s); } @@ -332,7 +333,7 @@ void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position) } if (s.IsEmpty()) s = L'-'; - s += L"\tAlt+"; + s.AddAscii("\tAlt+"); s += (wchar_t)(L'0' + i); menu.AppendItem(MF_STRING, kOpenBookmarkMenuID + i, s); } @@ -348,8 +349,7 @@ void OnMenuUnActivating(HWND hWnd, HMENU hMenu, int id) } */ -void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu, - bool isFsFolder, int numItems, bool allAreFiles) +void CFileMenu::Load(HMENU hMenu, unsigned startPos) { CMenu destMenu; destMenu.Attach(hMenu); @@ -357,15 +357,17 @@ void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu, UString diffPath; ReadRegDiff(diffPath); - int numRealItems = startPos; - for (int i = 0;; i++) + unsigned numRealItems = startPos; + for (unsigned i = 0;; i++) { CMenuItem item; - item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMaskForFTypeAndString(); + item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMask_for_FType_and_String(); item.fType = MFT_STRING; + if (!g_FileMenu.GetItem(i, true, item)) break; + { if (!programMenu && item.wID == IDCLOSE) continue; @@ -376,6 +378,26 @@ void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu, bool isOneFsFile = (isFsFolder && numItems == 1 && allAreFiles); bool disable = (!isOneFsFile && (item.wID == IDM_SPLIT || item.wID == IDM_COMBINE)); + if (readOnly) + { + switch (item.wID) + { + case IDM_RENAME: + case IDM_MOVE_TO: + case IDM_DELETE: + case IDM_COMMENT: + case IDM_CREATE_FOLDER: + case IDM_CREATE_FILE: + disable = true; + } + } + + if (item.wID == IDM_LINK && numItems != 1) + disable = true; + + if (item.wID == IDM_ALT_STREAMS) + disable = !isAltStreamsSupported; + bool isBigScreen = NControl::IsDialogSizeOK(40, 200); if (!isBigScreen && (disable || item.IsSeparator())) @@ -434,6 +456,7 @@ bool ExecuteFileCommand(int id) case IDM_CREATE_FILE: g_App.CreateFile(); break; #ifndef UNDER_CE case IDM_LINK: g_App.Link(); break; + case IDM_ALT_STREAMS: g_App.OpenAltStreams(); break; #endif default: return false; } diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.h b/CPP/7zip/UI/FileManager/MyLoadMenu.h index 53e9d0ef..02569e52 100644 --- a/CPP/7zip/UI/FileManager/MyLoadMenu.h +++ b/CPP/7zip/UI/FileManager/MyLoadMenu.h @@ -9,8 +9,28 @@ void OnMenuActivating(HWND hWnd, HMENU hMenu, int position); bool OnMenuCommand(HWND hWnd, int id); void MyLoadMenu(); -void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu, - bool isFsFolder, int numItems, bool allAreFiles); + +struct CFileMenu +{ + bool programMenu; + bool readOnly; + bool isFsFolder; + bool allAreFiles; + bool isAltStreamsSupported; + int numItems; + + CFileMenu(): + programMenu(false), + readOnly(false), + isFsFolder(false), + allAreFiles(false), + isAltStreamsSupported(true), + numItems(0) + {} + + void Load(HMENU hMenu, unsigned startPos); +}; + bool ExecuteFileCommand(int id); #endif diff --git a/CPP/7zip/UI/FileManager/NetFolder.cpp b/CPP/7zip/UI/FileManager/NetFolder.cpp index f3d531ab..bfccc353 100644 --- a/CPP/7zip/UI/FileManager/NetFolder.cpp +++ b/CPP/7zip/UI/FileManager/NetFolder.cpp @@ -73,7 +73,15 @@ void CNetFolder::Init(const NWindows::NNet::CResourceW *netResource, _netResourcePointer = &_netResource; // if (_netResource.DisplayType == RESOURCEDISPLAYTYPE_SERVER) - _path = _netResource.RemoteName + WCHAR_PATH_SEPARATOR; + _path = _netResource.RemoteName; + + /* WinXP-64: When we move UP from Network share without _parentFolder chain, + we can get empty _netResource.RemoteName. Do we need to use Provider there ? */ + if (_path.IsEmpty()) + _path = _netResource.Provider; + + if (!_path.IsEmpty()) + _path.Add_PathSepar(); } _parentFolder = parentFolder; } @@ -111,7 +119,7 @@ STDMETHODIMP CNetFolder::LoadItems() if (!resource.RemoteNameIsDefined) // For Win 98, I don't know what's wrong resource.RemoteName = resource.Comment; resource.Name = resource.RemoteName; - int pos = resource.Name.ReverseFind(WCHAR_PATH_SEPARATOR); + int pos = resource.Name.ReverseFind_PathSepar(); if (pos >= 0) { // _path = resource.Name.Left(pos + 1); @@ -186,7 +194,7 @@ STDMETHODIMP CNetFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder { NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder; CMyComPtr<IFolderFolder> subFolder = fsFolderSpec; - RINOK(fsFolderSpec->Init(us2fs(resource.RemoteName + WCHAR_PATH_SEPARATOR), this)); + RINOK(fsFolderSpec->Init(us2fs(resource.RemoteName + WCHAR_PATH_SEPARATOR))); // , this *resultFolder = subFolder.Detach(); } else @@ -237,7 +245,7 @@ STDMETHODIMP CNetFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) NWindows::NCOM::CPropVariant prop; switch(propID) { - case kpidType: prop = L"NetFolder"; break; + case kpidType: prop = "NetFolder"; break; case kpidPath: prop = _path; break; } prop.Detach(value); diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp index a657bc90..c6feb902 100644 --- a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp +++ b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp @@ -50,7 +50,7 @@ void COverwriteDialog::SetFileInfoControl(int textID, int iconID, sizeString = MyFormatNew(IDS_FILE_SIZE, NumberToString(fileInfo.Size)); const UString &fileName = fileInfo.Name; - int slashPos = fileName.ReverseFind(WCHAR_PATH_SEPARATOR); + int slashPos = fileName.ReverseFind_PathSepar(); UString s1 = fileName.Left(slashPos + 1); UString s2 = fileName.Ptr(slashPos + 1); @@ -58,18 +58,18 @@ void COverwriteDialog::SetFileInfoControl(int textID, int iconID, ReduceString(s2); UString s = s1; - s += L'\n'; + s.Add_LF(); s += s2; - s += L'\n'; + s.Add_LF(); s += sizeString; - s += L'\n'; + s.Add_LF(); if (fileInfo.TimeIsDefined) { FILETIME localFileTime; if (!FileTimeToLocalFileTime(&fileInfo.Time, &localFileTime)) throw 4190402; - s += LangString(IDS_PROP_MTIME); + AddLangString(s, IDS_PROP_MTIME); s += L": "; wchar_t t[32]; ConvertFileTimeToString(localFileTime, t); diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp index d63bdc17..a7416a4c 100644 --- a/CPP/7zip/UI/FileManager/Panel.cpp +++ b/CPP/7zip/UI/FileManager/Panel.cpp @@ -477,7 +477,7 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */) _comboBoxEdit.SetUserDataLongPtr(LONG_PTR(&_comboBoxEdit)); _comboBoxEdit._panel = this; #ifndef _UNICODE - if(g_IsNT) + if (g_IsNT) _comboBoxEdit._origWindowProc = (WNDPROC)_comboBoxEdit.SetLongPtrW(GWLP_WNDPROC, LONG_PTR(ComboBoxEditSubclassProc)); else @@ -675,7 +675,7 @@ void CPanel::MessageBoxError2Lines(LPCWSTR message, HRESULT errorCode) UString m = message; if (errorCode != 0) { - m += L'\n'; + m.Add_LF(); m += HResultToMessage(errorCode); } MessageBoxMyError(m); @@ -708,29 +708,32 @@ void CPanel::SetFocusToLastRememberedItem() UString CPanel::GetFolderTypeID() const { - NCOM::CPropVariant prop; - if (_folder->GetFolderProperty(kpidType, &prop) == S_OK) - if (prop.vt == VT_BSTR) - return (const wchar_t *)prop.bstrVal; - return L""; + { + NCOM::CPropVariant prop; + if (_folder->GetFolderProperty(kpidType, &prop) == S_OK) + if (prop.vt == VT_BSTR) + return (const wchar_t *)prop.bstrVal; + } + return UString(); } -bool CPanel::IsFolderTypeEqTo(const wchar_t *s) const +bool CPanel::IsFolderTypeEqTo(const char *s) const { - return GetFolderTypeID() == s; + return StringsAreEqual_Ascii(GetFolderTypeID(), s); } -bool CPanel::IsRootFolder() const { return IsFolderTypeEqTo(L"RootFolder"); } -bool CPanel::IsFSFolder() const { return IsFolderTypeEqTo(L"FSFolder"); } -bool CPanel::IsFSDrivesFolder() const { return IsFolderTypeEqTo(L"FSDrives"); } +bool CPanel::IsRootFolder() const { return IsFolderTypeEqTo("RootFolder"); } +bool CPanel::IsFSFolder() const { return IsFolderTypeEqTo("FSFolder"); } +bool CPanel::IsFSDrivesFolder() const { return IsFolderTypeEqTo("FSDrives"); } +bool CPanel::IsAltStreamsFolder() const { return IsFolderTypeEqTo("AltStreamsFolder"); } bool CPanel::IsArcFolder() const { - return GetFolderTypeID().IsPrefixedBy(L"7-Zip"); + return GetFolderTypeID().IsPrefixedBy_Ascii_NoCase("7-Zip"); } UString CPanel::GetFsPath() const { - if (IsFSDrivesFolder() && !IsDeviceDrivesPrefix()) + if (IsFSDrivesFolder() && !IsDeviceDrivesPrefix() && !IsSuperDrivesPrefix()) return UString(); return _currentFolderPrefix; } @@ -744,12 +747,6 @@ UString CPanel::GetDriveOrNetworkPrefix() const return drive; } -bool CPanel::DoesItSupportOperations() const -{ - CMyComPtr<IFolderOperations> folderOperations; - return _folder.QueryInterface(IID_IFolderOperations, &folderOperations) == S_OK; -} - void CPanel::SetListViewMode(UInt32 index) { if (index >= 4) @@ -805,7 +802,7 @@ void CPanel::AddToArchive() { CRecordVector<UInt32> indices; GetOperatedItemIndices(indices); - if (!IsFsOrDrivesFolder()) + if (!Is_IO_FS_Folder()) { MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; @@ -817,20 +814,16 @@ void CPanel::AddToArchive() } UStringVector names; - UString curPrefix = _currentFolderPrefix; - UString destCurDirPrefix = _currentFolderPrefix; + const UString curPrefix = GetFsPath(); + UString destCurDirPrefix = curPrefix; if (IsFSDrivesFolder()) - { destCurDirPrefix = ROOT_FS_FOLDER; - if (!IsDeviceDrivesPrefix()) - curPrefix.Empty(); - } FOR_VECTOR (i, indices) - names.Add(curPrefix + GetItemRelPath(indices[i])); + names.Add(curPrefix + GetItemRelPath2(indices[i])); bool fromPrev = (names.Size() > 1); - const UString archiveName = CreateArchiveName(names.Front(), fromPrev, false); - HRESULT res = CompressFiles(destCurDirPrefix, archiveName, L"", + const UString arcName = CreateArchiveName(names.Front(), fromPrev, false); + HRESULT res = CompressFiles(destCurDirPrefix, arcName, L"", true, // addExtension names, false, true, false); if (res != S_OK) @@ -841,23 +834,24 @@ void CPanel::AddToArchive() // KillSelection(); } -static UString GetSubFolderNameForExtract(const UString &archiveName) +static UString GetSubFolderNameForExtract(const UString &arcPath) { - UString res = archiveName; - int slashPos = res.ReverseFind(WCHAR_PATH_SEPARATOR); - int dotPos = res.ReverseFind(L'.'); - if (dotPos < 0 || slashPos > dotPos) - res += L'~'; + UString s = arcPath; + int slashPos = s.ReverseFind_PathSepar(); + int dotPos = s.ReverseFind_Dot(); + if (dotPos <= slashPos + 1) + s += L'~'; else { - res.DeleteFrom(dotPos); - res.TrimRight(); + s.DeleteFrom(dotPos); + s.TrimRight(); } - return res; + return s; } void CPanel::GetFilePaths(const CRecordVector<UInt32> &indices, UStringVector &paths, bool allowFolders) { + const UString prefix = GetFsPath(); FOR_VECTOR (i, indices) { int index = indices[i]; @@ -866,7 +860,7 @@ void CPanel::GetFilePaths(const CRecordVector<UInt32> &indices, UStringVector &p paths.Clear(); break; } - paths.Add(GetItemFullPath(index)); + paths.Add(prefix + GetItemRelPath2(index)); } if (paths.Size() == 0) { @@ -888,26 +882,31 @@ void CPanel::ExtractArchives() GetFilePaths(indices, paths); if (paths.IsEmpty()) return; - UString folderName; + + UString outFolder = GetFsPath(); if (indices.Size() == 1) - folderName = GetSubFolderNameForExtract(GetItemRelPath(indices[0])); + outFolder += GetSubFolderNameForExtract(GetItemRelPath(indices[0])); else - folderName = L"*"; - ::ExtractArchives(paths, _currentFolderPrefix + folderName + UString(WCHAR_PATH_SEPARATOR) + outFolder += L'*'; + outFolder.Add_PathSepar(); + + ::ExtractArchives(paths, outFolder , true // showDialog , false // elimDup ); } -void AddValuePair(UINT resourceID, UInt64 value, UString &s) +/* +static void AddValuePair(UINT resourceID, UInt64 value, UString &s) { - wchar_t sz[32]; - s += LangString(resourceID); + AddLangString(s, resourceID); + char sz[32]; s += L": "; ConvertUInt64ToString(value, sz); - s += sz; - s += L'\n'; + s.AddAsciiStr(sz); + s.Add_LF(); } +*/ class CThreadTest: public CProgressThreadVirt { @@ -939,8 +938,8 @@ HRESULT CThreadTest::ProcessVirt() AddValuePair(IDS_PROP_FILES, ExtractCallbackSpec->NumFiles, s); // AddValuePair(IDS_PROP_SIZE, ExtractCallbackSpec->UnpackSize, s); // AddSizePair(IDS_COMPRESSED_COLON, Stat.PackSize, s); - s += L'\n'; - s += LangString(IDS_MESSAGE_NO_ERRORS); + s.Add_LF(); + AddLangString(s, IDS_MESSAGE_NO_ERRORS); FinalMessage.OkMessage.Message = s; } return S_OK; @@ -948,18 +947,18 @@ HRESULT CThreadTest::ProcessVirt() */ /* -static void AddSizePair(UINT resourceID, UInt32 langID, UInt64 value, UString &s) +static void AddSizePair(UInt32 langID, UInt64 value, UString &s) { - wchar_t sz[32]; - s += LangString(resourceID, langID); + char sz[32]; + AddLangString(s, langID); s += L' '; ConvertUInt64ToString(value, sz); - s += sz; + s.AddAsciiStr(sz); ConvertUInt64ToString(value >> 20, sz); - s += L" ("; - s += sz; - s += L" MB)"; - s += L'\n'; + s.AddAsciiStr(" ("); + s.AddAsciiStr(sz); + s.AddAsciiStr(" MB)"); + s.Add_LF(); } */ diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h index dc293729..39915a27 100644 --- a/CPP/7zip/UI/FileManager/Panel.h +++ b/CPP/7zip/UI/FileManager/Panel.h @@ -11,6 +11,7 @@ #include "../../../Windows/DLL.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileFind.h" +#include "../../../Windows/FileName.h" #include "../../../Windows/Handle.h" #include "../../../Windows/Synchronization.h" @@ -43,10 +44,10 @@ const int kParentFolderID = 100; const int kParentIndex = -1; -#ifdef UNDER_CE +#if !defined(_WIN32) || defined(UNDER_CE) #define ROOT_FS_FOLDER L"\\" #else -#define ROOT_FS_FOLDER L"C:\\\\" +#define ROOT_FS_FOLDER L"C:\\" #endif struct CPanelCallback @@ -117,12 +118,13 @@ struct CTempFileInfo struct CFolderLink: public CTempFileInfo { NWindows::NDLL::CLibrary Library; - CMyComPtr<IFolderFolder> ParentFolder; + CMyComPtr<IFolderFolder> ParentFolder; // can be NULL, if parent is FS folder (in _parentFolders[0]) + UString ParentFolderPath; // including tail slash (doesn't include paths parts of parent in next level) bool UsePassword; UString Password; bool IsVirtual; - UString VirtualPath; + UString VirtualPath; // without tail slash CFolderLink(): UsePassword(false), IsVirtual(false) {} bool WasChanged(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const @@ -146,7 +148,7 @@ enum MyMessages #endif }; -UString GetFolderPath(IFolderFolder * folder); +UString GetFolderPath(IFolderFolder *folder); class CPanel; @@ -380,27 +382,11 @@ public: CMyComPtr<IFolderCompare> _folderCompare; CMyComPtr<IFolderGetItemName> _folderGetItemName; CMyComPtr<IArchiveGetRawProps> _folderRawProps; + CMyComPtr<IFolderAltStreams> _folderAltStreams; + CMyComPtr<IFolderOperations> _folderOperations; - void ReleaseFolder() - { - _folderCompare.Release(); - _folderGetItemName.Release(); - _folderRawProps.Release(); - _folder.Release(); - _thereAreDeletedItems = false; - } - - void SetNewFolder(IFolderFolder *newFolder) - { - ReleaseFolder(); - _folder = newFolder; - if (_folder) - { - _folder.QueryInterface(IID_IFolderCompare, &_folderCompare); - _folder.QueryInterface(IID_IFolderGetItemName, &_folderGetItemName); - _folder.QueryInterface(IID_IArchiveGetRawProps, &_folderRawProps); - } - } + void ReleaseFolder(); + void SetNewFolder(IFolderFolder *newFolder); // CMyComPtr<IFolderGetSystemIconIndex> _folderGetSystemIconIndex; @@ -417,9 +403,11 @@ public: bool IsItem_AltStream(int itemIndex) const; UString GetItemName(int itemIndex) const; - void GetItemNameFast(int itemIndex, UString &s) const; + UString GetItemName_for_Copy(int itemIndex) const; + void GetItemName(int itemIndex, UString &s) const; UString GetItemPrefix(int itemIndex) const; UString GetItemRelPath(int itemIndex) const; + UString GetItemRelPath2(int itemIndex) const; UString GetItemFullPath(int itemIndex) const; UInt64 GetItemSize(int itemIndex) const; @@ -438,6 +426,7 @@ public: void LoadFullPathAndShow(); void FoldersHistory(); void OpenParentFolder(); + void CloseOneLevel(); void CloseOpenFolders(); void OpenRootFolder(); @@ -554,19 +543,65 @@ public: void KillSelection(); UString GetFolderTypeID() const; - bool IsFolderTypeEqTo(const wchar_t *s) const; + + bool IsFolderTypeEqTo(const char *s) const; bool IsRootFolder() const; bool IsFSFolder() const; bool IsFSDrivesFolder() const; + bool IsAltStreamsFolder() const; bool IsArcFolder() const; - bool IsFsOrDrivesFolder() const { return IsFSFolder() || IsFSDrivesFolder(); } + + /* + c:\Dir + Computer\ + \\?\ + \\.\ + */ + bool Is_IO_FS_Folder() const + { + return IsFSFolder() || IsFSDrivesFolder() || IsAltStreamsFolder(); + } + + bool Is_Slow_Icon_Folder() const + { + return IsFSFolder() || IsAltStreamsFolder(); + } + + // bool IsFsOrDrivesFolder() const { return IsFSFolder() || IsFSDrivesFolder(); } bool IsDeviceDrivesPrefix() const { return _currentFolderPrefix == L"\\\\.\\"; } + bool IsSuperDrivesPrefix() const { return _currentFolderPrefix == L"\\\\?\\"; } + + /* + c:\Dir + Computer\ + \\?\ + */ bool IsFsOrPureDrivesFolder() const { return IsFSFolder() || (IsFSDrivesFolder() && !IsDeviceDrivesPrefix()); } + /* + c:\Dir + Computer\ + \\?\ + \\SERVER\ + */ + bool IsFolder_with_FsItems() const + { + if (IsFsOrPureDrivesFolder()) + return true; + #if defined(_WIN32) && !defined(UNDER_CE) + FString prefix = us2fs(GetFsPath()); + return (prefix.Len() == NWindows::NFile::NName::GetNetworkServerPrefixSize(prefix)); + #else + return false; + #endif + } + UString GetFsPath() const; UString GetDriveOrNetworkPrefix() const; - bool DoesItSupportOperations() const; + bool DoesItSupportOperations() const { return _folderOperations != NULL; } + bool IsThereReadOnlyFolder() const; + bool CheckBeforeUpdate(UINT resourceID); bool _processTimer; bool _processNotify; @@ -574,37 +609,35 @@ public: class CDisableTimerProcessing { - bool _processTimerMem; - - CPanel &_panel; + CLASS_NO_COPY(CDisableTimerProcessing); - CDisableTimerProcessing(const CDisableTimerProcessing &); - CDisableTimerProcessing& operator=(const CDisableTimerProcessing &); + bool _processTimer; + CPanel &_panel; + public: CDisableTimerProcessing(CPanel &panel): _panel(panel) { Disable(); } ~CDisableTimerProcessing() { Restore(); } void Disable() { - _processTimerMem = _panel._processTimer; + _processTimer = _panel._processTimer; _panel._processTimer = false; } void Restore() { - _panel._processTimer = _processTimerMem; + _panel._processTimer = _processTimer; } }; class CDisableNotify { - bool _processNotifyMem; - bool _processStatusBarMem; + CLASS_NO_COPY(CDisableNotify); - CPanel &_panel; + bool _processNotify; + bool _processStatusBar; - CDisableNotify(const CDisableNotify &); - CDisableNotify& operator=(const CDisableNotify &); + CPanel &_panel; public: @@ -612,20 +645,20 @@ public: ~CDisableNotify() { Restore(); } void Disable() { - _processNotifyMem = _panel._processNotify; - _processStatusBarMem = _panel._processStatusBar; + _processNotify = _panel._processNotify; + _processStatusBar = _panel._processStatusBar; _panel._processNotify = false; _panel._processStatusBar = false; } void SetMemMode_Enable() { - _processNotifyMem = true; - _processStatusBarMem = true; + _processNotify = true; + _processStatusBar = true; } void Restore() { - _panel._processNotify = _processNotifyMem; - _panel._processStatusBar = _processStatusBarMem; + _panel._processNotify = _processNotify; + _panel._processStatusBar = _processStatusBar; } }; @@ -647,10 +680,12 @@ public: void MessageBoxLastError(LPCWSTR caption); void MessageBoxLastError(); - void MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID); + // void MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID); void MessageBoxErrorLang(UINT resourceID); + void OpenAltStreams(); + void OpenFocusedItemAsInternal(); void OpenSelectedItems(bool internal); diff --git a/CPP/7zip/UI/FileManager/PanelCopy.cpp b/CPP/7zip/UI/FileManager/PanelCopy.cpp index d11368cf..fb418963 100644 --- a/CPP/7zip/UI/FileManager/PanelCopy.cpp +++ b/CPP/7zip/UI/FileManager/PanelCopy.cpp @@ -1,4 +1,4 @@ -/// PanelExtract.cpp +/// PanelCopy.cpp #include "StdAfx.h" @@ -79,18 +79,25 @@ HRESULT CPanelCopyThread::ProcessVirt() return Result; } + +/* +#ifdef EXTERNAL_CODECS + static void ThrowException_if_Error(HRESULT res) { if (res != S_OK) throw CSystemException(res); } +#endif +*/ + + HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &indices, UStringVector *messages, bool &usePassword, UString &password) { - CMyComPtr<IFolderOperations> folderOperations; - if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + if (!_folderOperations) { UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED); if (options.showErrorMessages) @@ -100,8 +107,17 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind return E_FAIL; } - HRESULT res; + HRESULT res = S_OK; + { + /* + #ifdef EXTERNAL_CODECS + CExternalCodecs g_ExternalCodecs; + #endif + */ + /* extracter.Hash uses g_ExternalCodecs + extracter must be declared after g_ExternalCodecs for correct destructor order !!! */ + CPanelCopyThread extracter; extracter.ExtractCallbackSpec = new CExtractCallbackImp; @@ -113,11 +129,6 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind extracter.ExtractCallbackSpec->StreamMode = options.streamMode; - #ifdef EXTERNAL_CODECS - CExternalCodecs __externalCodecs; - #else - CMyComPtr<IUnknown> compressCodecsInfo; - #endif if (indices.Size() == 1) extracter.FirstFilePath = GetItemRelPath(indices[0]); @@ -131,19 +142,16 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind if (!options.hashMethods.IsEmpty()) { - { - CCodecs *codecs = new CCodecs; - ThrowException_if_Error(codecs->Load()); - #ifdef EXTERNAL_CODECS - __externalCodecs.GetCodecs = codecs; - __externalCodecs.GetHashers = codecs; - ThrowException_if_Error(__externalCodecs.LoadCodecs()); - #else - compressCodecsInfo = codecs; - #endif - } + /* this code is used when we call CRC calculation for files in side archive + But new code uses global codecs so we don't need to call LoadGlobalCodecs again */ + + /* + #ifdef EXTERNAL_CODECS + ThrowException_if_Error(LoadGlobalCodecs()); + #endif + */ - extracter.Hash.SetMethods(EXTERNAL_CODECS_VARS options.hashMethods); + extracter.Hash.SetMethods(EXTERNAL_CODECS_VARS_G options.hashMethods); extracter.ExtractCallbackSpec->SetHashMethods(&extracter.Hash); } else if (options.testMode) @@ -153,7 +161,6 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind extracter.Hash.Init(); - UString title; { UInt32 titleID = IDS_COPYING; @@ -185,7 +192,7 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind extracter.ExtractCallbackSpec->OverwriteMode = NExtract::NOverwriteMode::kAsk; extracter.ExtractCallbackSpec->Init(); extracter.Indices = indices; - extracter.FolderOperations = folderOperations; + extracter.FolderOperations = _folderOperations; extracter.ExtractCallbackSpec->PasswordIsDefined = usePassword; extracter.ExtractCallbackSpec->Password = password; @@ -244,10 +251,8 @@ struct CThreadUpdate HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStringVector &filePaths, bool showErrorMessages, UStringVector *messages) { - CMyComPtr<IFolderOperations> folderOperations; - _folder.QueryInterface(IID_IFolderOperations, &folderOperations); HRESULT res; - if (!folderOperations) + if (!_folderOperations) res = E_NOINTERFACE; else { @@ -255,6 +260,7 @@ HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStri updater.MoveMode = moveMode; updater.UpdateCallbackSpec = new CUpdateCallback100Imp; updater.UpdateCallback = updater.UpdateCallbackSpec; + updater.UpdateCallbackSpec->Init(); updater.UpdateCallbackSpec->ProgressDialog = &updater.ProgressDialog; @@ -263,10 +269,18 @@ HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStri updater.ProgressDialog.MainWindow = GetParent(); updater.ProgressDialog.MainTitle = progressWindowTitle; - updater.ProgressDialog.MainAddTitle = title + UString(L' '); + updater.ProgressDialog.MainAddTitle = title + L' '; - updater.UpdateCallbackSpec->Init(false, L""); - updater.FolderOperations = folderOperations; + { + if (!_parentFolders.IsEmpty()) + { + const CFolderLink &fl = _parentFolders.Back(); + updater.UpdateCallbackSpec->PasswordIsDefined = fl.UsePassword; + updater.UpdateCallbackSpec->Password = fl.Password; + } + } + + updater.FolderOperations = _folderOperations; updater.FolderPrefix = folderPrefix; updater.FileNames.ClearAndReserve(filePaths.Size()); unsigned i; diff --git a/CPP/7zip/UI/FileManager/PanelCrc.cpp b/CPP/7zip/UI/FileManager/PanelCrc.cpp index ab93ecba..3b0ee052 100644 --- a/CPP/7zip/UI/FileManager/PanelCrc.cpp +++ b/CPP/7zip/UI/FileManager/PanelCrc.cpp @@ -6,6 +6,7 @@ #include "../../../Windows/FileFind.h" #include "../../../Windows/FileIO.h" +#include "../../../Windows/FileName.h" #include "../Common/LoadCodecs.h" @@ -19,12 +20,18 @@ using namespace NWindows; using namespace NFile; +#ifdef EXTERNAL_CODECS +extern CExternalCodecs g_ExternalCodecs; +HRESULT LoadGlobalCodecs(); +#endif + static const UInt32 kBufSize = (1 << 15); struct CDirEnumerator { bool EnterToDirs; FString BasePrefix; + FString BasePrefix_for_Open; FStringVector FilePaths; CObjectVector<NFind::CEnumerator> Enumerators; @@ -54,22 +61,27 @@ DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &r { filled = false; resPath.Empty(); + for (;;) { + #if defined(_WIN32) && !defined(UNDER_CE) + bool isRootPrefix = (BasePrefix.IsEmpty() || (NName::IsSuperPath(BasePrefix) && BasePrefix[NName::kSuperPathPrefixSize] == 0)); + #endif + if (Enumerators.IsEmpty()) { if (Index >= FilePaths.Size()) return S_OK; const FString &path = FilePaths[Index++]; - int pos = path.ReverseFind(FCHAR_PATH_SEPARATOR); + int pos = path.ReverseFind_PathSepar(); if (pos >= 0) resPath.SetFrom(path, pos + 1); - #ifdef _WIN32 - if (BasePrefix.IsEmpty() && path.Len() == 2 && path[1] == ':') + #if defined(_WIN32) && !defined(UNDER_CE) + if (isRootPrefix && path.Len() == 2 && NName::IsDrivePath2(path)) { // we use "c:" item as directory item - fi.Clear(); + fi.ClearBase(); fi.Name = path; fi.SetAsDir(); fi.Size = 0; @@ -82,9 +94,12 @@ DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &r resPath = path; return error; } + break; } + bool found; + if (Enumerators.Back().Next(fi, found)) { if (found) @@ -101,18 +116,22 @@ DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &r Prefixes.DeleteBack(); return error; } + Enumerators.DeleteBack(); Prefixes.DeleteBack(); } + resPath += fi.Name; + if (EnterToDirs && fi.IsDir()) { FString s = resPath; - s += FCHAR_PATH_SEPARATOR; + s.Add_PathSepar(); Prefixes.Add(s); s += FCHAR_ANY_MASK; Enumerators.Add(NFind::CEnumerator(BasePrefix + s)); } + filled = true; return S_OK; } @@ -137,10 +156,9 @@ void CThreadCrc::AddErrorMessage(DWORD systemError, const FChar *name) void CThreadCrc::SetStatus(const UString &s2) { UString s = s2; - if (Enumerator.BasePrefix) + if (!Enumerator.BasePrefix.IsEmpty()) { - if (!s.IsEmpty()) - s += L' '; + s.Add_Space_if_NotEmpty(); s += fs2us(Enumerator.BasePrefix); } ProgressDialog.Sync.Set_Status(s); @@ -201,10 +219,10 @@ HRESULT CThreadCrc::ProcessVirt() */ if (needPrint) { - RINOK(sync.ScanProgress(numFiles, totalSize, fs2us(path), fi.IsDir())); + RINOK(sync.ScanProgress(numFiles, totalSize, path, fi.IsDir())); } } - RINOK(sync.ScanProgress(numFiles, totalSize, L"", false)); + RINOK(sync.ScanProgress(numFiles, totalSize, FString(), false)); // sync.SetNumFilesTotal(numFiles); // sync.SetProgress(totalSize, 0); // SetStatus(LangString(IDS_CHECKSUM_CALCULATING)); @@ -235,7 +253,7 @@ HRESULT CThreadCrc::ProcessVirt() if (!fi.IsDir()) { NIO::CInFile inFile; - tempPath = Enumerator.BasePrefix; + tempPath = Enumerator.BasePrefix_for_Open; tempPath += path; if (!inFile.Open(tempPath)) { @@ -289,13 +307,8 @@ HRESULT CThreadCrc::ProcessVirt() return S_OK; } -static void ThrowException_if_Error(HRESULT res) -{ - if (res != S_OK) - throw CSystemException(res); -} -void CApp::CalculateCrc(const UString &methodName) +HRESULT CApp::CalculateCrc2(const UString &methodName) { int srcPanelIndex = GetFocusedPanelIndex(); CPanel &srcPanel = Panels[srcPanelIndex]; @@ -303,9 +316,9 @@ void CApp::CalculateCrc(const UString &methodName) CRecordVector<UInt32> indices; srcPanel.GetOperatedIndicesSmart(indices); if (indices.IsEmpty()) - return; + return S_OK; - if (!srcPanel.IsFsOrDrivesFolder()) + if (!srcPanel.Is_IO_FS_Folder()) { CCopyToOptions options; options.streamMode = true; @@ -313,27 +326,13 @@ void CApp::CalculateCrc(const UString &methodName) options.hashMethods.Add(methodName); UStringVector messages; - HRESULT res = srcPanel.CopyTo(options, indices, &messages); - if (res != S_OK) - { - if (res != E_ABORT) - srcPanel.MessageBoxError(res); - } - return; + return srcPanel.CopyTo(options, indices, &messages); } - CCodecs *codecs = new CCodecs; #ifdef EXTERNAL_CODECS - CExternalCodecs __externalCodecs; - __externalCodecs.GetCodecs = codecs; - __externalCodecs.GetHashers = codecs; - #else - CMyComPtr<IUnknown> compressCodecsInfo = codecs; - #endif - ThrowException_if_Error(codecs->Load()); - #ifdef EXTERNAL_CODECS - ThrowException_if_Error(__externalCodecs.LoadCodecs()); + LoadGlobalCodecs(); + #endif { @@ -341,11 +340,23 @@ void CApp::CalculateCrc(const UString &methodName) { UStringVector methods; methods.Add(methodName); - t.Hash.SetMethods(EXTERNAL_CODECS_VARS methods); + RINOK(t.Hash.SetMethods(EXTERNAL_CODECS_VARS_G methods)); } FOR_VECTOR (i, indices) t.Enumerator.FilePaths.Add(us2fs(srcPanel.GetItemRelPath(indices[i]))); - t.Enumerator.BasePrefix = us2fs(srcPanel.GetFsPath()); + + UString basePrefix = srcPanel.GetFsPath(); + UString basePrefix2 = basePrefix; + if (basePrefix2.Back() == ':') + { + int pos = basePrefix2.ReverseFind_PathSepar(); + if (pos >= 0) + basePrefix2.DeleteFrom(pos + 1); + } + + t.Enumerator.BasePrefix = us2fs(basePrefix); + t.Enumerator.BasePrefix_for_Open = us2fs(basePrefix2); + t.Enumerator.EnterToDirs = !GetFlatMode(); t.ProgressDialog.ShowCompressionInfo = false; @@ -354,10 +365,22 @@ void CApp::CalculateCrc(const UString &methodName) t.ProgressDialog.MainWindow = _window; t.ProgressDialog.MainTitle = L"7-Zip"; // LangString(IDS_APP_TITLE); - t.ProgressDialog.MainAddTitle = title + UString(L' '); + t.ProgressDialog.MainAddTitle = title; + t.ProgressDialog.MainAddTitle.Add_Space(); - if (t.Create(title, _window) != S_OK) - return; + RINOK(t.Create(title, _window)); } RefreshTitleAlways(); + return S_OK; +} + +void CApp::CalculateCrc(const UString &methodName) +{ + HRESULT res = CalculateCrc2(methodName); + if (res != S_OK && res != E_ABORT) + { + int srcPanelIndex = GetFocusedPanelIndex(); + CPanel &srcPanel = Panels[srcPanelIndex]; + srcPanel.MessageBoxError(res); + } } diff --git a/CPP/7zip/UI/FileManager/PanelDrag.cpp b/CPP/7zip/UI/FileManager/PanelDrag.cpp index 9434d156..e20ddd63 100644 --- a/CPP/7zip/UI/FileManager/PanelDrag.cpp +++ b/CPP/7zip/UI/FileManager/PanelDrag.cpp @@ -296,9 +296,11 @@ static bool CopyNamesToHGlobal(NMemory::CGlobal &hgDrop, const UStringVector &na void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */) { - CDisableTimerProcessing disableTimerProcessing2(*this); if (!DoesItSupportOperations()) return; + + CDisableTimerProcessing disableTimerProcessing2(*this); + CRecordVector<UInt32> indices; GetOperatedItemIndices(indices); if (indices.Size() == 0) @@ -312,7 +314,7 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */) bool isFSFolder = IsFSFolder(); if (isFSFolder) - dirPrefix = us2fs(_currentFolderPrefix); + dirPrefix = us2fs(GetFsPath()); else { tempDirectory.Create(kTempDirPrefix); @@ -580,7 +582,9 @@ bool CDropTarget::IsItSameDrive() const return false; if (!IsFsFolderPath()) return false; + UString drive; + if (m_Panel->IsFSFolder()) { drive = m_Panel->GetDriveOrNetworkPrefix(); @@ -594,13 +598,14 @@ bool CDropTarget::IsItSameDrive() const if (m_SourcePaths.Size() == 0) return false; + FOR_VECTOR (i, m_SourcePaths) { - if (MyStringCompareNoCase_N(m_SourcePaths[i], drive, drive.Len()) != 0) + if (!m_SourcePaths[i].IsPrefixedBy_NoCase(drive)) return false; } + return true; - } DWORD CDropTarget::GetEffect(DWORD keyState, POINTL /* pt */, DWORD allowedEffect) @@ -635,13 +640,11 @@ UString CDropTarget::GetTargetPath() const { if (!IsFsFolderPath()) return UString(); - UString path = m_Panel->_currentFolderPrefix; - if (m_Panel->IsFSDrivesFolder()) - path.Empty(); + UString path = m_Panel->GetFsPath(); if (m_SubFolderIndex >= 0 && !m_SubFolderName.IsEmpty()) { path += m_SubFolderName; - path += WCHAR_PATH_SEPARATOR; + path.Add_PathSepar(); } return path; } @@ -728,7 +731,7 @@ STDMETHODIMP CDropTarget::Drop(IDataObject *dataObject, DWORD keyState, UString path = GetTargetPath(); if (m_IsAppTarget && m_Panel) if (m_Panel->IsFSFolder()) - path = m_Panel->_currentFolderPrefix; + path = m_Panel->GetFsPath(); m_Panel->DropObject(dataObject, path); } } @@ -779,7 +782,7 @@ static bool AreThereNamesFromTemp(const UStringVector &fileNames) if (tempPath.IsEmpty()) return false; FOR_VECTOR (i, fileNames) - if (MyStringCompareNoCase_N(fileNames[i], tempPath, tempPath.Len()) == 0) + if (fileNames[i].IsPrefixedBy_NoCase(tempPath)) return true; return false; } diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp index 83993bb1..cd70c727 100644 --- a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp +++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp @@ -28,10 +28,38 @@ using namespace NWindows; using namespace NFile; using namespace NFind; +void CPanel::ReleaseFolder() +{ + _folder.Release(); + + _folderCompare.Release(); + _folderGetItemName.Release(); + _folderRawProps.Release(); + _folderAltStreams.Release(); + _folderOperations.Release(); + + _thereAreDeletedItems = false; +} + +void CPanel::SetNewFolder(IFolderFolder *newFolder) +{ + ReleaseFolder(); + _folder = newFolder; + if (_folder) + { + _folder.QueryInterface(IID_IFolderCompare, &_folderCompare); + _folder.QueryInterface(IID_IFolderGetItemName, &_folderGetItemName); + _folder.QueryInterface(IID_IArchiveGetRawProps, &_folderRawProps); + _folder.QueryInterface(IID_IFolderAltStreams, &_folderAltStreams); + _folder.QueryInterface(IID_IFolderOperations, &_folderOperations); + } +} + void CPanel::SetToRootFolder() { ReleaseFolder(); _library.Free(); + CRootFolder *rootFolderSpec = new CRootFolder; SetNewFolder(rootFolderSpec); rootFolderSpec->Init(); @@ -39,105 +67,188 @@ void CPanel::SetToRootFolder() HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bool &archiveIsOpened, bool &encrypted) { + UString path = fullPath; + #ifdef _WIN32 + path.Replace(L'/', WCHAR_PATH_SEPARATOR); + #endif + archiveIsOpened = false; encrypted = false; + CDisableTimerProcessing disableTimerProcessing(*this); CDisableNotify disableNotify(*this); - if (_parentFolders.Size() > 0) + for (; !_parentFolders.IsEmpty(); CloseOneLevel()) { - const UString &virtPath = _parentFolders.Back().VirtualPath; - if (fullPath.IsPrefixedBy(virtPath)) + // ---------- we try to use open archive ---------- + + const CFolderLink &link = _parentFolders.Back(); + const UString &virtPath = link.VirtualPath; + if (!path.IsPrefixedBy(virtPath)) + continue; + UString relatPath = path.Ptr(virtPath.Len()); + if (!relatPath.IsEmpty()) { - for (;;) - { - CMyComPtr<IFolderFolder> newFolder; - HRESULT res = _folder->BindToParentFolder(&newFolder); - if (!newFolder || res != S_OK) - break; - SetNewFolder(newFolder); - } - UStringVector parts; - SplitPathToParts(fullPath.Ptr(virtPath.Len()), parts); - FOR_VECTOR (i, parts) + if (!IS_PATH_SEPAR(relatPath[0])) + continue; + else + relatPath.Delete(0); + } + + UString relatPath2 = relatPath; + if (!relatPath2.IsEmpty() && !IS_PATH_SEPAR(relatPath2.Back())) + relatPath2.Add_PathSepar(); + + for (;;) + { + const UString foldPath = GetFolderPath(_folder); + if (relatPath2 == foldPath) + break; + if (relatPath.IsPrefixedBy(foldPath)) { - const UString &s = parts[i]; - if ((i == 0 || i == parts.Size() - 1) && s.IsEmpty()) - continue; - CMyComPtr<IFolderFolder> newFolder; - HRESULT res = _folder->BindToFolder(s, &newFolder); - if (!newFolder || res != S_OK) - break; - SetNewFolder(newFolder); + path = relatPath.Ptr(foldPath.Len()); + break; } - return S_OK; + CMyComPtr<IFolderFolder> newFolder; + if (_folder->BindToParentFolder(&newFolder) != S_OK) + throw 20140918; + if (!newFolder) // we exit from loop above if (relatPath.IsPrefixedBy(empty path for root folder) + throw 20140918; + SetNewFolder(newFolder); } + break; } - CloseOpenFolders(); - UString sysPath = fullPath; - CFileInfo fileInfo; - UStringVector reducedParts; - while (!sysPath.IsEmpty()) + if (_parentFolders.IsEmpty()) { - if (fileInfo.Find(us2fs(sysPath))) - break; - int pos = sysPath.ReverseFind(WCHAR_PATH_SEPARATOR); - if (pos < 0) + // ---------- we open file or folder from file system ---------- + + CloseOpenFolders(); + UString sysPath = path; + + unsigned prefixSize = NName::GetRootPrefixSize(sysPath); + if (prefixSize == 0 || sysPath[prefixSize] == 0) sysPath.Empty(); + + #if defined(_WIN32) && !defined(UNDER_CE) + if (!sysPath.IsEmpty() && sysPath.Back() == ':' && + (sysPath.Len() != 2 || !NName::IsDrivePath2(sysPath))) + { + UString baseFile = sysPath; + baseFile.DeleteBack(); + if (NFind::DoesFileOrDirExist(us2fs(baseFile))) + sysPath.Empty(); + } + #endif + + CFileInfo fileInfo; + + while (!sysPath.IsEmpty()) + { + if (fileInfo.Find(us2fs(sysPath))) + break; + int pos = sysPath.ReverseFind_PathSepar(); + if (pos < 0) + sysPath.Empty(); + else + { + /* + if (reducedParts.Size() > 0 || pos < (int)sysPath.Len() - 1) + reducedParts.Add(sysPath.Ptr(pos + 1)); + */ + #if defined(_WIN32) && !defined(UNDER_CE) + if (pos == 2 && NName::IsDrivePath2(sysPath) && sysPath.Len() > 3) + pos++; + #endif + + sysPath.DeleteFrom(pos); + } + } + + SetToRootFolder(); + + CMyComPtr<IFolderFolder> newFolder; + + if (sysPath.IsEmpty()) + { + _folder->BindToFolder(path, &newFolder); + } + else if (fileInfo.IsDir()) + { + NName::NormalizeDirPathPrefix(sysPath); + _folder->BindToFolder(sysPath, &newFolder); + } else { - if (reducedParts.Size() > 0 || pos < (int)sysPath.Len() - 1) - reducedParts.Add(sysPath.Ptr(pos + 1)); - sysPath.DeleteFrom(pos); + FString dirPrefix, fileName; + NDir::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName); + HRESULT res; + // = OpenItemAsArchive(fs2us(fileName), arcFormat, encrypted); + { + CTempFileInfo tfi; + tfi.RelPath = fs2us(fileName); + tfi.FolderPath = dirPrefix; + tfi.FilePath = us2fs(sysPath); + res = OpenItemAsArchive(NULL, tfi, sysPath, arcFormat, encrypted); + } + + if (res == S_FALSE) + _folder->BindToFolder(fs2us(dirPrefix), &newFolder); + else + { + RINOK(res); + archiveIsOpened = true; + _parentFolders.Back().ParentFolderPath = fs2us(dirPrefix); + path.DeleteFrontal(sysPath.Len()); + if (!path.IsEmpty() && IS_PATH_SEPAR(path[0])) + path.Delete(0); + } } - } - SetToRootFolder(); - CMyComPtr<IFolderFolder> newFolder; - if (sysPath.IsEmpty()) - { - if (_folder->BindToFolder(fullPath, &newFolder) == S_OK) - SetNewFolder(newFolder); - } - else if (fileInfo.IsDir()) - { - NName::NormalizeDirPathPrefix(sysPath); - if (_folder->BindToFolder(sysPath, &newFolder) == S_OK) + if (newFolder) + { SetNewFolder(newFolder); + // LoadFullPath(); + return S_OK; + } } - else + { - FString dirPrefix, fileName; - NDir::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName); - if (_folder->BindToFolder(fs2us(dirPrefix), &newFolder) == S_OK) + // ---------- we open folder remPath in archive and sub archives ---------- + + for (unsigned curPos = 0; curPos != path.Len();) { - SetNewFolder(newFolder); - LoadFullPath(); + UString s = path.Ptr(curPos); + int slashPos = NName::FindSepar(s); + unsigned skipLen = s.Len(); + if (slashPos >= 0) { - HRESULT res = OpenItemAsArchive(fs2us(fileName), arcFormat, encrypted); - if (res != S_FALSE) - { - RINOK(res); - } - /* - if (res == E_ABORT) - return res; - */ - if (res == S_OK) + s.DeleteFrom(slashPos); + skipLen = slashPos + 1; + } + + CMyComPtr<IFolderFolder> newFolder; + _folder->BindToFolder(s, &newFolder); + if (newFolder) + curPos += skipLen; + else if (_folderAltStreams) + { + int pos = s.Find(L':'); + if (pos >= 0) { - archiveIsOpened = true; - for (int i = reducedParts.Size() - 1; i >= 0; i--) - { - CMyComPtr<IFolderFolder> newFolder; - _folder->BindToFolder(reducedParts[i], &newFolder); - if (!newFolder) - break; - SetNewFolder(newFolder); - } + UString baseName = s; + baseName.DeleteFrom(pos); + if (_folderAltStreams->BindToAltStreams(baseName, &newFolder) == S_OK && newFolder) + curPos += pos + 1; } } + + if (!newFolder) + break; + + SetNewFolder(newFolder); } } + return S_OK; } @@ -163,10 +274,12 @@ void CPanel::OpenBookmark(int index) UString GetFolderPath(IFolderFolder *folder) { - NCOM::CPropVariant prop; - if (folder->GetFolderProperty(kpidPath, &prop) == S_OK) - if (prop.vt == VT_BSTR) - return (wchar_t *)prop.bstrVal; + { + NCOM::CPropVariant prop; + if (folder->GetFolderProperty(kpidPath, &prop) == S_OK) + if (prop.vt == VT_BSTR) + return (wchar_t *)prop.bstrVal; + } return UString(); } @@ -176,9 +289,10 @@ void CPanel::LoadFullPath() FOR_VECTOR (i, _parentFolders) { const CFolderLink &folderLink = _parentFolders[i]; - _currentFolderPrefix += GetFolderPath(folderLink.ParentFolder); + _currentFolderPrefix += folderLink.ParentFolderPath; + // GetFolderPath(folderLink.ParentFolder); _currentFolderPrefix += folderLink.RelPath; - _currentFolderPrefix += WCHAR_PATH_SEPARATOR; + _currentFolderPrefix.Add_PathSepar(); } if (_folder) _currentFolderPrefix += GetFolderPath(_folder); @@ -364,7 +478,7 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result) { UString name = pathParts[i]; sumPass += name; - sumPass += WCHAR_PATH_SEPARATOR; + sumPass.Add_PathSepar(); CFileInfo info; DWORD attrib = FILE_ATTRIBUTE_DIRECTORY; if (info.Find(us2fs(sumPass))) @@ -496,73 +610,104 @@ void CPanel::FoldersHistory() void CPanel::OpenParentFolder() { LoadFullPath(); // Maybe we don't need it ?? - UString focucedName; - if (!_currentFolderPrefix.IsEmpty() && - _currentFolderPrefix.Back() == WCHAR_PATH_SEPARATOR) + + UString parentFolderPrefix; + UString focusedName; + + if (!_currentFolderPrefix.IsEmpty()) { - focucedName = _currentFolderPrefix; - focucedName.DeleteBack(); - if (focucedName != L"\\\\.") + wchar_t c = _currentFolderPrefix.Back(); + if (c == WCHAR_PATH_SEPARATOR || c == ':') { - int pos = focucedName.ReverseFind(WCHAR_PATH_SEPARATOR); - if (pos >= 0) - focucedName.DeleteFrontal(pos + 1); + focusedName = _currentFolderPrefix; + focusedName.DeleteBack(); + /* + if (c == ':' && !focusedName.IsEmpty() && focusedName.Back() == WCHAR_PATH_SEPARATOR) + { + focusedName.DeleteBack(); + } + else + */ + if (focusedName != L"\\\\." && + focusedName != L"\\\\?") + { + int pos = focusedName.ReverseFind_PathSepar(); + if (pos >= 0) + { + parentFolderPrefix = focusedName; + parentFolderPrefix.DeleteFrom(pos + 1); + focusedName.DeleteFrontal(pos + 1); + } + } } } CDisableTimerProcessing disableTimerProcessing(*this); CDisableNotify disableNotify(*this); + CMyComPtr<IFolderFolder> newFolder; _folder->BindToParentFolder(&newFolder); + + // newFolder.Release(); // for test + if (newFolder) SetNewFolder(newFolder); else { - if (_parentFolders.IsEmpty()) + bool needSetFolder = true; + if (!_parentFolders.IsEmpty()) { - SetToRootFolder(); - if (focucedName.IsEmpty()) - focucedName = GetItemName(0); + { + const CFolderLink &link = _parentFolders.Back(); + parentFolderPrefix = link.ParentFolderPath; + focusedName = link.RelPath; + } + CloseOneLevel(); + needSetFolder = (!_folder); } - else + + if (needSetFolder) { - ReleaseFolder(); - _library.Free(); - CFolderLink &link = _parentFolders.Back(); - SetNewFolder(link.ParentFolder); - _library.Attach(link.Library.Detach()); - focucedName = link.RelPath; - if (_parentFolders.Size() > 1) - OpenParentArchiveFolder(); - _parentFolders.DeleteBack(); - if (_parentFolders.IsEmpty()) - _flatMode = _flatModeForDisk; + { + bool archiveIsOpened; + bool encrypted; + BindToPath(parentFolderPrefix, UString(), archiveIsOpened, encrypted); + } } } - + UStringVector selectedItems; /* - if (!focucedName.IsEmpty()) - selectedItems.Add(focucedName); + if (!focusedName.IsEmpty()) + selectedItems.Add(focusedName); */ LoadFullPath(); // ::SetCurrentDirectory(::_currentFolderPrefix); - RefreshListCtrl(focucedName, -1, true, selectedItems); + RefreshListCtrl(focusedName, -1, true, selectedItems); // _listView.EnsureVisible(_listView.GetFocusedItem(), false); } -void CPanel::CloseOpenFolders() +void CPanel::CloseOneLevel() { - while (_parentFolders.Size() > 0) + ReleaseFolder(); + _library.Free(); { - ReleaseFolder(); - _library.Free(); - SetNewFolder(_parentFolders.Back().ParentFolder); - _library.Attach(_parentFolders.Back().Library.Detach()); - if (_parentFolders.Size() > 1) - OpenParentArchiveFolder(); - _parentFolders.DeleteBack(); + CFolderLink &link = _parentFolders.Back(); + if (link.ParentFolder) + SetNewFolder(link.ParentFolder); + _library.Attach(link.Library.Detach()); } + if (_parentFolders.Size() > 1) + OpenParentArchiveFolder(); + _parentFolders.DeleteBack(); + if (_parentFolders.IsEmpty()) + _flatMode = _flatModeForDisk; +} + +void CPanel::CloseOpenFolders() +{ + while (!_parentFolders.IsEmpty()) + CloseOneLevel(); _flatMode = _flatModeForDisk; ReleaseFolder(); _library.Free(); @@ -618,3 +763,45 @@ void CPanel::OpenFolder(int index) _listView.SetItemState_Selected(_listView.GetFocusedItem()); _listView.EnsureVisible(_listView.GetFocusedItem(), false); } + +void CPanel::OpenAltStreams() +{ + CRecordVector<UInt32> indices; + GetOperatedItemIndices(indices); + Int32 realIndex = -1; + if (indices.Size() > 1) + return; + if (indices.Size() == 1) + realIndex = indices[0]; + + if (_folderAltStreams) + { + CMyComPtr<IFolderFolder> newFolder; + _folderAltStreams->BindToAltStreams(realIndex, &newFolder); + if (newFolder) + { + CDisableTimerProcessing disableTimerProcessing(*this); + CDisableNotify disableNotify(*this); + SetNewFolder(newFolder); + RefreshListCtrl(UString(), -1, true, UStringVector()); + return; + } + return; + } + + #if defined(_WIN32) && !defined(UNDER_CE) + UString path; + if (realIndex >= 0) + path = GetItemFullPath(realIndex); + else + { + path = GetFsPath(); + if (!NName::IsDriveRootPath_SuperAllowed(us2fs(path))) + if (!path.IsEmpty() && IS_PATH_SEPAR(path.Back())) + path.DeleteBack(); + } + + path += L':'; + BindToPathAndRefresh(path); + #endif +} diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp index d9beedb8..a485522f 100644 --- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp +++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp @@ -157,7 +157,8 @@ public: static bool IsNameVirus(const UString &name) { - return (name.Find(L" ") >= 0); + // return (name.Find(L" ") >= 0); + return (wcsstr(name, L" ") != NULL); } struct CTmpProcessInfo: public CTempFileInfo @@ -223,7 +224,13 @@ HRESULT CPanel::OpenItemAsArchive(IInStream *inStream, folderLink.Password = password; folderLink.UsePassword = encrypted; - folderLink.ParentFolder = _folder; + if (_folder) + folderLink.ParentFolderPath = GetFolderPath(_folder); + else + folderLink.ParentFolderPath = _currentFolderPrefix; + if (!_parentFolders.IsEmpty()) + folderLink.ParentFolder = _folder; + _parentFolders.Add(folderLink); _parentFolders.Back().Library.Attach(_library.Detach()); @@ -272,7 +279,7 @@ HRESULT CPanel::OpenItemAsArchive(IInStream *inStream, if (!values[0].IsEmpty()) { if (!s2.IsEmpty()) - s2 += L"\n"; + s2.Add_LF(); s2 += L"["; s2 += values[2]; s2 += L"] Error: "; @@ -283,7 +290,7 @@ HRESULT CPanel::OpenItemAsArchive(IInStream *inStream, if (!s.IsEmpty()) s += L"--------------------\n"; s += values[1]; - s += L"\n"; + s.Add_LF(); s += s2; } } @@ -305,8 +312,8 @@ HRESULT CPanel::OpenItemAsArchive(const UString &relPath, const UString &arcForm { CTempFileInfo tfi; tfi.RelPath = relPath; - tfi.FolderPath = us2fs(_currentFolderPrefix); - const UString fullPath = _currentFolderPrefix + relPath; + tfi.FolderPath = us2fs(GetFsPath()); + const UString fullPath = GetFsPath() + relPath; tfi.FilePath = us2fs(fullPath); return OpenItemAsArchive(NULL, tfi, fullPath, arcFormat, encrypted); } @@ -316,7 +323,7 @@ HRESULT CPanel::OpenItemAsArchive(int index) CDisableTimerProcessing disableTimerProcessing1(*this); CDisableNotify disableNotify(*this); bool encrypted; - HRESULT res = OpenItemAsArchive(GetItemRelPath(index), UString(), encrypted); + HRESULT res = OpenItemAsArchive(GetItemRelPath2(index), UString(), encrypted); if (res != S_OK) { RefreshTitle(true); // in case of error we must refresh changed title of 7zFM @@ -379,7 +386,7 @@ static const char *kStartExtensions = static bool FindExt(const char *p, const UString &name) { - int dotPos = name.ReverseFind('.'); + int dotPos = name.ReverseFind_Dot(); if (dotPos < 0 || dotPos == (int)name.Len() - 1) return false; @@ -409,10 +416,7 @@ static bool DoItemAlwaysStart(const UString &name) return FindExt(kStartExtensions, name); } -static UString GetQuotedString(const UString &s) -{ - return UString(L'\"') + s + UString(L'\"'); -} +UString GetQuotedString(const UString &s); static HRESULT StartEditApplication(const UString &path, bool useEditor, HWND window, CProcess &process) { @@ -455,13 +459,17 @@ void CApp::DiffFiles() { const CPanel &destPanel = Panels[1 - LastFocusedPanel]; path1 = panel.GetItemFullPath(indices[0]); - const UString relPath = panel.GetItemRelPath(indices[0]); CRecordVector<UInt32> indices2; destPanel.GetSelectedItemsIndices(indices2); if (indices2.Size() == 1) path2 = destPanel.GetItemFullPath(indices2[0]); else + { + UString relPath = panel.GetItemRelPath2(indices[0]); + if (panel._flatMode && !destPanel._flatMode) + relPath = panel.GetItemName(indices[0]); path2 = destPanel._currentFolderPrefix + relPath; + } } else return; @@ -471,7 +479,9 @@ void CApp::DiffFiles() if (command.IsEmpty()) return; - UString param = GetQuotedString(path1) + L' ' + GetQuotedString(path2); + UString param = GetQuotedString(path1); + param.Add_Space(); + param += GetQuotedString(path2); HRESULT res = MyCreateProcess(command, param); if (res == SZ_OK) @@ -573,11 +583,11 @@ void CPanel::OpenFolderExternal(int index) UString name; if (index == kParentIndex) { - int pos = fsPrefix.ReverseFind(WCHAR_PATH_SEPARATOR); + int pos = fsPrefix.ReverseFind_PathSepar(); if (pos >= 0 && pos == (int)fsPrefix.Len() - 1) { UString s = fsPrefix.Left(pos); - pos = s.ReverseFind(WCHAR_PATH_SEPARATOR); + pos = s.ReverseFind_PathSepar(); if (pos >= 0) fsPrefix.SetFrom(s, pos + 1); } @@ -591,7 +601,7 @@ void CPanel::OpenFolderExternal(int index) void CPanel::OpenItem(int index, bool tryInternal, bool tryExternal) { CDisableTimerProcessing disableTimerProcessing(*this); - UString name = GetItemRelPath(index); + UString name = GetItemRelPath2(index); if (IsNameVirus(name)) { MessageBoxErrorLang(IDS_VIRUS); @@ -650,8 +660,7 @@ HRESULT CThreadCopyFrom::ProcessVirt() HRESULT CPanel::OnOpenItemChanged(UInt32 index, const wchar_t *fullFilePath, bool usePassword, const UString &password) { - CMyComPtr<IFolderOperations> folderOperations; - if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + if (!_folderOperations) { MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return E_FAIL; @@ -663,8 +672,13 @@ HRESULT CPanel::OnOpenItemChanged(UInt32 index, const wchar_t *fullFilePath, t.UpdateCallbackSpec->ProgressDialog = &t.ProgressDialog; t.ItemIndex = index; t.FullPath = fullFilePath; - t.FolderOperations = folderOperations; - t.UpdateCallbackSpec->Init(usePassword, password); + t.FolderOperations = _folderOperations; + + t.UpdateCallbackSpec->Init(); + t.UpdateCallbackSpec->PasswordIsDefined = usePassword; + t.UpdateCallbackSpec->Password = password; + + RINOK(t.Create(GetItemName(index), (HWND)*this)); return t.Result; } @@ -862,8 +876,11 @@ STDMETHODIMP CBufSeqOutStream_WithFile::Write(const void *data, UInt32 size, UIn { if (_size - _pos >= size) { - memcpy(_buffer + _pos, data, size); - _pos += size; + if (size != 0) + { + memcpy(_buffer + _pos, data, size); + _pos += size; + } if (processedSize) *processedSize = (UInt32)size; return S_OK; @@ -931,8 +948,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo return; } - CMyComPtr<IFolderOperations> folderOperations; - if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + if (!_folderOperations) { MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; @@ -951,7 +967,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo FString tempDir = tempDirectory.GetPath(); FString tempDirNorm = tempDir; NName::NormalizeDirPathPrefix(tempDirNorm); - const FString tempFilePath = tempDirNorm + us2fs(GetCorrectFsPath(name)); + const FString tempFilePath = tempDirNorm + us2fs(Get_Correct_FsFile_Name(name)); CTempFileInfo tempFileInfo; tempFileInfo.FileIndex = index; @@ -1029,7 +1045,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo bool isAltStream = IsItem_AltStream(index); CCopyToOptions options; - options.includeAltStreams = false; + options.includeAltStreams = true; options.replaceAltStreamChars = isAltStream; if (tryAsArchive) @@ -1137,11 +1153,11 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo return; CProcess process; - /* HRESULT res; */ + // HRESULT res; if (editMode) /* res = */ StartEditApplication(fs2us(tempFilePath), useEditor, (HWND)*this, process); else - /* res = */ StartApplication(fs2us(tempDirNorm), fs2us(tempFilePath), (HWND)*this, process); + /* res = */ StartApplication(fs2us(tempDirNorm), fs2us(tempFilePath), (HWND)*this, process); if ((HANDLE)process == 0) return; diff --git a/CPP/7zip/UI/FileManager/PanelItems.cpp b/CPP/7zip/UI/FileManager/PanelItems.cpp index 8d74b8cd..491a36ad 100644 --- a/CPP/7zip/UI/FileManager/PanelItems.cpp +++ b/CPP/7zip/UI/FileManager/PanelItems.cpp @@ -4,6 +4,7 @@ #include "../../../../C/Sort.h" +#include "../../../Windows/FileName.h" #include "../../../Windows/Menu.h" #include "../../../Windows/PropVariant.h" #include "../../../Windows/PropVariantConv.h" @@ -103,7 +104,7 @@ HRESULT CPanel::InitColumns() _properties.Clear(); _needSaveInfo = true; - bool isFsFolder = IsFSFolder(); + bool isFsFolder = IsFSFolder() || IsAltStreamsFolder(); { UInt32 numProps; @@ -401,7 +402,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool int cursorIndex = -1; CMyComPtr<IFolderGetSystemIconIndex> folderGetSystemIconIndex; - if (!IsFSFolder() || _showRealFileIcons) + if (!Is_Slow_Icon_Folder() || _showRealFileIcons) _folder.QueryInterface(IID_IFolderGetSystemIconIndex, &folderGetSystemIconIndex); if (!IsFSFolder()) @@ -436,7 +437,8 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool int subItem = 0; item.iSubItem = subItem++; item.lParam = kParentIndex; - item.pszText = const_cast<wchar_t *>((const wchar_t *)itemName); + // item.pszText = const_cast<wchar_t *>((const wchar_t *)itemName); + item.pszText = LPSTR_TEXTCALLBACKW; UInt32 attrib = FILE_ATTRIBUTE_DIRECTORY; item.iImage = _extToIconMap.GetIconIndex(attrib, itemName); if (item.iImage < 0) @@ -451,19 +453,23 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool UString correctedName; UString itemName; UString relPath; + for (UInt32 i = 0; i < numItems; i++) { const wchar_t *name = NULL; unsigned nameLen = 0; + if (_folderGetItemName) _folderGetItemName->GetItemName(i, &name, &nameLen); - if (name == NULL) + if (!name) { - GetItemNameFast(i, itemName); + GetItemName(i, itemName); name = itemName; nameLen = itemName.Len(); } + bool selected = false; + if (!focusedName.IsEmpty() || !selectedNames.IsEmpty()) { relPath.Empty(); @@ -495,6 +501,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool if (selectedNames.FindInSorted(relPath) >= 0) selected = true; } + _selectedStatusVector.AddInReserved(selected); item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; @@ -567,6 +574,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool // } bool defined = false; + if (folderGetSystemIconIndex) { folderGetSystemIconIndex->GetSystemIconIndex(i, &item.iImage); @@ -585,6 +593,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool item.iImage = _extToIconMap.GetIconIndex(attrib, name); } } + if (item.iImage < 0) item.iImage = 0; @@ -592,6 +601,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool return E_FAIL; listViewItemCount++; } + // OutputDebugStringA("End2\n"); if (_listView.GetItemCount() > 0 && cursorIndex >= 0) @@ -831,7 +841,24 @@ UString CPanel::GetItemName(int itemIndex) const return prop.bstrVal; } -void CPanel::GetItemNameFast(int itemIndex, UString &s) const +UString CPanel::GetItemName_for_Copy(int itemIndex) const +{ + if (itemIndex == kParentIndex) + return L".."; + { + NCOM::CPropVariant prop; + if (_folder->GetProperty(itemIndex, kpidOutName, &prop) == S_OK) + { + if (prop.vt == VT_BSTR) + return prop.bstrVal; + if (prop.vt != VT_EMPTY) + throw 2723401; + } + } + return GetItemName(itemIndex); +} + +void CPanel::GetItemName(int itemIndex, UString &s) const { if (itemIndex == kParentIndex) { @@ -843,8 +870,7 @@ void CPanel::GetItemNameFast(int itemIndex, UString &s) const throw 2723400; if (prop.vt != VT_BSTR) throw 2723401; - s.Empty(); - s += prop.bstrVal; + s.SetFromBstr(prop.bstrVal); } UString CPanel::GetItemPrefix(int itemIndex) const @@ -856,7 +882,7 @@ UString CPanel::GetItemPrefix(int itemIndex) const throw 2723400; UString prefix; if (prop.vt == VT_BSTR) - prefix = prop.bstrVal; + prefix.SetFromBstr(prop.bstrVal); return prefix; } @@ -865,9 +891,22 @@ UString CPanel::GetItemRelPath(int itemIndex) const return GetItemPrefix(itemIndex) + GetItemName(itemIndex); } +UString CPanel::GetItemRelPath2(int itemIndex) const +{ + UString s = GetItemRelPath(itemIndex); + #if defined(_WIN32) && !defined(UNDER_CE) + if (s.Len() == 2 && NFile::NName::IsDrivePath2(s)) + { + if (IsFSDrivesFolder() && !IsDeviceDrivesPrefix()) + s.Add_PathSepar(); + } + #endif + return s; +} + UString CPanel::GetItemFullPath(int itemIndex) const { - return _currentFolderPrefix + GetItemRelPath(itemIndex); + return GetFsPath() + GetItemRelPath2(itemIndex); } bool CPanel::GetItem_BoolProp(UInt32 itemIndex, PROPID propID) const @@ -928,6 +967,7 @@ void CPanel::ReadListViewInfo() void CPanel::SaveListViewInfo() { unsigned i; + for (i = 0; i < _visibleProperties.Size(); i++) { CItemProperty &prop = _visibleProperties[i]; @@ -945,6 +985,7 @@ void CPanel::SaveListViewInfo() PROPID sortPropID = _sortID; _visibleProperties.Sort(); + for (i = 0; i < _visibleProperties.Size(); i++) { const CItemProperty &prop = _visibleProperties[i]; @@ -954,6 +995,7 @@ void CPanel::SaveListViewInfo() columnInfo.Width = prop.Width; viewInfo.Columns.Add(columnInfo); } + for (i = 0; i < _properties.Size(); i++) { const CItemProperty &prop = _properties[i]; @@ -1025,21 +1067,24 @@ void CPanel::ShowColumnsContextMenu(int x, int y) else { int visibleIndex = _visibleProperties.FindItemWithID(prop.ID); - _visibleProperties.Delete(visibleIndex); - /* - if (_sortIndex == index) + if (visibleIndex >= 0) { + _visibleProperties.Delete(visibleIndex); + /* + if (_sortIndex == index) + { _sortIndex = 0; _ascending = true; + } + */ + if (_sortID == prop.ID) + { + _sortID = kpidName; + _ascending = true; + } + + _listView.DeleteColumn(visibleIndex); } - */ - if (_sortID == prop.ID) - { - _sortID = kpidName; - _ascending = true; - } - - _listView.DeleteColumn(visibleIndex); } } } diff --git a/CPP/7zip/UI/FileManager/PanelListNotify.cpp b/CPP/7zip/UI/FileManager/PanelListNotify.cpp index 7be6aa62..2f37db14 100644 --- a/CPP/7zip/UI/FileManager/PanelListNotify.cpp +++ b/CPP/7zip/UI/FileManager/PanelListNotify.cpp @@ -19,30 +19,57 @@ using namespace NWindows; -static void ConvertSizeToString(UInt64 value, wchar_t *dest) +#define INT_TO_STR_SPEC(v) \ + while (v >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(v % 10)); v /= 10; } \ + *s++ = (unsigned char)('0' + (unsigned)v); + +static void ConvertSizeToString(UInt64 val, wchar_t *s) throw() { - char s[32]; - ConvertUInt64ToString(value, s); - unsigned i = MyStringLen(s); - unsigned pos = ARRAY_SIZE(s); - s[--pos] = 0; - while (i > 3) + unsigned char temp[32]; + unsigned i = 0; + + if (val <= (UInt32)0xFFFFFFFF) + { + UInt32 val32 = (UInt32)val; + INT_TO_STR_SPEC(val32) + } + else { - s[--pos] = s[--i]; - s[--pos] = s[--i]; - s[--pos] = s[--i]; - s[--pos] = L' '; + INT_TO_STR_SPEC(val) } - while (i > 0) - s[--pos] = s[--i]; - for (;;) + if (i < 3) { - char c = s[pos++]; - *dest++ = (unsigned char)c; - if (c == 0) - break; + if (i != 0) + { + *s++ = temp[i - 1]; + if (i == 2) + *s++ = temp[0]; + } + *s = 0; + return; + } + + unsigned r = i % 3; + if (r != 0) + { + s[0] = temp[--i]; + if (r == 2) + s[1] = temp[--i]; + s += r; } + + do + { + s[0] = ' '; + s[1] = temp[i - 1]; + s[2] = temp[i - 2]; + s[3] = temp[i - 3]; + s += 4; + } + while (i -= 3); + + *s = 0; } UString ConvertSizeToString(UInt64 value) @@ -52,29 +79,62 @@ UString ConvertSizeToString(UInt64 value) return s; } -static inline char GetHex(Byte value) +static inline unsigned GetHex(unsigned v) { - return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); + return (v < 10) ? ('0' + v) : ('A' + (v - 10)); } -void HexToString(char *dest, const Byte *data, UInt32 size) +/* +static void HexToString(char *dest, const Byte *data, UInt32 size) { for (UInt32 i = 0; i < size; i++) { - Byte b = data[i]; - dest[0] = GetHex((Byte)((b >> 4) & 0xF)); - dest[1] = GetHex((Byte)(b & 0xF)); + unsigned b = data[i]; + dest[0] = GetHex((b >> 4) & 0xF); + dest[1] = GetHex(b & 0xF); dest += 2; } *dest = 0; } +*/ -LRESULT CPanel::SetItemText(LVITEMW &item) +bool IsSizeProp(UINT propID) throw() { + switch (propID) + { + case kpidSize: + case kpidPackSize: + case kpidNumSubDirs: + case kpidNumSubFiles: + case kpidOffset: + case kpidLinks: + case kpidNumBlocks: + case kpidNumVolumes: + case kpidPhySize: + case kpidHeadersSize: + case kpidTotalSize: + case kpidFreeSpace: + case kpidClusterSize: + case kpidNumErrors: + case kpidNumStreams: + case kpidNumAltStreams: + case kpidAltStreamsSize: + case kpidVirtualSize: + case kpidUnpackSize: + case kpidTotalPhySize: + case kpidTailSize: + case kpidEmbeddedStubSize: + return true; + } + return false; +} +LRESULT CPanel::SetItemText(LVITEMW &item) +{ if (_dontShowMode) return 0; UInt32 realIndex = GetRealIndex(item); + /* if ((item.mask & LVIF_IMAGE) != 0) { @@ -107,10 +167,31 @@ LRESULT CPanel::SetItemText(LVITEMW &item) if ((item.mask & LVIF_TEXT) == 0) return 0; - if (realIndex == kParentIndex) + LPWSTR text = item.pszText; + + if (item.cchTextMax > 0) + text[0] = 0; + + if (item.cchTextMax <= 1) return 0; + const CItemProperty &property = _visibleProperties[item.iSubItem]; PROPID propID = property.ID; + + if (realIndex == kParentIndex) + { + if (propID == kpidName) + { + if (item.cchTextMax > 2) + { + text[0] = '.'; + text[1] = '.'; + text[2] = 0; + } + } + return 0; + } + if (property.IsRawProp) { @@ -118,10 +199,10 @@ LRESULT CPanel::SetItemText(LVITEMW &item) UInt32 dataSize; UInt32 propType; RINOK(_folderRawProps->GetRawProp(realIndex, propID, &data, &dataSize, &propType)); - int limit = item.cchTextMax - 1; + unsigned limit = item.cchTextMax - 1; if (dataSize == 0) { - item.pszText[0] = 0; + text[0] = 0; return 0; } @@ -131,15 +212,15 @@ LRESULT CPanel::SetItemText(LVITEMW &item) ConvertNtReparseToString((const Byte *)data, dataSize, s); if (!s.IsEmpty()) { - int i; + unsigned i; for (i = 0; i < limit; i++) { wchar_t c = s[i]; if (c == 0) break; - item.pszText[i] = c; + text[i] = c; } - item.pszText[i] = 0; + text[i] = 0; return 0; } } @@ -149,45 +230,45 @@ LRESULT CPanel::SetItemText(LVITEMW &item) ConvertNtSecureToString((const Byte *)data, dataSize, s); if (!s.IsEmpty()) { - int i; + unsigned i; for (i = 0; i < limit; i++) { - wchar_t c = s[i]; + wchar_t c = (Byte)s[i]; if (c == 0) break; - item.pszText[i] = c; + text[i] = c; } - item.pszText[i] = 0; + text[i] = 0; return 0; } } { - const UInt32 kMaxDataSize = 64; + const unsigned kMaxDataSize = 64; if (dataSize > kMaxDataSize) { - char temp[64]; + char temp[32]; MyStringCopy(temp, "data:"); ConvertUInt32ToString(dataSize, temp + 5); - int i; + unsigned i; for (i = 0; i < limit; i++) { - wchar_t c = temp[i]; + wchar_t c = (Byte)temp[i]; if (c == 0) break; - item.pszText[i] = c; + text[i] = c; } - item.pszText[i] = 0; + text[i] = 0; } else { - if ((int)dataSize > limit) + if (dataSize > limit) dataSize = limit; - WCHAR *dest = item.pszText; + WCHAR *dest = text; for (UInt32 i = 0; i < dataSize; i++) { - Byte b = ((const Byte *)data)[i]; - dest[0] = GetHex((Byte)((b >> 4) & 0xF)); - dest[1] = GetHex((Byte)(b & 0xF)); + unsigned b = ((const Byte *)data)[i]; + dest[0] = (WCHAR)GetHex((b >> 4) & 0xF); + dest[1] = (WCHAR)GetHex(b & 0xF); dest += 2; } *dest = 0; @@ -230,11 +311,7 @@ LRESULT CPanel::SetItemText(LVITEMW &item) */ if (item.cchTextMax < 32) - { - if (item.cchTextMax > 0) - item.pszText[0] = 0; return 0; - } if (propID == kpidName) { @@ -245,35 +322,36 @@ LRESULT CPanel::SetItemText(LVITEMW &item) _folderGetItemName->GetItemName(realIndex, &name, &nameLen); if (name) { - int dest = 0; - int limit = item.cchTextMax - 1; - for (int i = 0; dest < limit;) + unsigned dest = 0; + unsigned limit = item.cchTextMax - 1; + for (unsigned i = 0; dest < limit;) { wchar_t c = name[i++]; if (c == 0) break; - item.pszText[dest++] = c; + text[dest++] = c; if (c != ' ') continue; if (name[i + 1] != ' ') continue; - int t = 2; + unsigned t = 2; for (; name[i + t] == ' '; t++); if (t >= 4 && dest + 4 <= limit) { - item.pszText[dest++] = '.'; - item.pszText[dest++] = '.'; - item.pszText[dest++] = '.'; - item.pszText[dest++] = ' '; + text[dest++] = '.'; + text[dest++] = '.'; + text[dest++] = '.'; + text[dest++] = ' '; i += t; } } - item.pszText[dest] = 0; + text[dest] = 0; return 0; } } } + if (propID == kpidPrefix) { if (_folderGetItemName) @@ -283,73 +361,65 @@ LRESULT CPanel::SetItemText(LVITEMW &item) _folderGetItemName->GetItemPrefix(realIndex, &name, &nameLen); if (name) { - int dest = 0; - int limit = item.cchTextMax - 1; - for (int i = 0; dest < limit;) + unsigned dest = 0; + unsigned limit = item.cchTextMax - 1; + for (unsigned i = 0; dest < limit;) { wchar_t c = name[i++]; if (c == 0) break; - item.pszText[dest++] = c; + text[dest++] = c; } - item.pszText[dest] = 0; + text[dest] = 0; return 0; } } } + HRESULT res = _folder->GetProperty(realIndex, propID, &prop); + if (res != S_OK) { - MyStringCopy(item.pszText, L"Error: "); + MyStringCopy(text, L"Error: "); // s = UString(L"Error: ") + HResultToMessage(res); } - else if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && ( - propID == kpidSize || - propID == kpidPackSize || - propID == kpidNumSubDirs || - propID == kpidNumSubFiles || - propID == kpidPosition || - propID == kpidNumBlocks || - propID == kpidClusterSize || - propID == kpidTotalSize || - propID == kpidFreeSpace || - propID == kpidUnpackSize - )) + else if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && IsSizeProp(propID)) { UInt64 v = 0; ConvertPropVariantToUInt64(prop, v); - ConvertSizeToString(v, item.pszText); + ConvertSizeToString(v, text); } else if (prop.vt == VT_BSTR) { - int limit = item.cchTextMax - 1; + unsigned limit = item.cchTextMax - 1; const wchar_t *src = prop.bstrVal; - int i; + unsigned i; for (i = 0; i < limit; i++) { wchar_t c = src[i]; if (c == 0) break; if (c == 0xA) c = ' '; if (c == 0xD) c = ' '; - item.pszText[i] = c; + text[i] = c; } - item.pszText[i] = 0; + text[i] = 0; } else { char temp[64]; ConvertPropertyToShortString(temp, prop, propID, false); - int i; - int limit = item.cchTextMax - 1; + unsigned i; + unsigned limit = item.cchTextMax - 1; for (i = 0; i < limit; i++) { - wchar_t c = temp[i]; + wchar_t c = (Byte)temp[i]; if (c == 0) break; - item.pszText[i] = c; + text[i] = c; } - item.pszText[i] = 0; + text[i] = 0; } + return 0; } @@ -606,7 +676,7 @@ void CPanel::Refresh_StatusBar() if (indices.Size() > 0) { - // for (int ttt = 0; ttt < 1000; ttt++) { + // for (unsigned ttt = 0; ttt < 1000; ttt++) { UInt64 totalSize = 0; FOR_VECTOR (i, indices) totalSize += GetItemSize(indices[i]); @@ -632,10 +702,10 @@ void CPanel::Refresh_StatusBar() char dateString2[32]; dateString2[0] = 0; ConvertPropertyToShortString(dateString2, prop, kpidMTime, false); - for (int i = 0;; i++) + for (unsigned i = 0;; i++) { char c = dateString2[i]; - dateString[i] = c; + dateString[i] = (Byte)c; if (c == 0) break; } diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp index d7108204..5a527cb4 100644 --- a/CPP/7zip/UI/FileManager/PanelMenu.cpp +++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp @@ -49,11 +49,12 @@ void CPanel::InvokeSystemCommand(const char *command) contextMenu->InvokeCommand(&ci); } -static const wchar_t *kSeparator = L"----------------------------\n"; -static const wchar_t *kSeparatorSmall = L"----\n"; -static const wchar_t *kPropValueSeparator = L": "; +static const char *kSeparator = "----------------------------\n"; +static const char *kSeparatorSmall = "----\n"; +static const char *kPropValueSeparator = ": "; -extern UString ConvertSizeToString(UInt64 value); +extern UString ConvertSizeToString(UInt64 value) throw(); +bool IsSizeProp(UINT propID) throw(); UString GetOpenArcErrorMessage(UInt32 errorFlags); @@ -74,20 +75,7 @@ static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR, val = GetOpenArcErrorMessage(flags); } if (val.IsEmpty()) - if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && ( - propID == kpidSize || - propID == kpidPackSize || - propID == kpidNumSubDirs || - propID == kpidNumSubFiles || - propID == kpidNumBlocks || - propID == kpidClusterSize || - propID == kpidTotalSize || - propID == kpidFreeSpace || - propID == kpidPhySize || - propID == kpidHeadersSize || - propID == kpidFreeSpace || - propID == kpidUnpackSize - )) + if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && IsSizeProp(propID)) { UInt64 v = 0; ConvertPropVariantToUInt64(prop, v); @@ -99,13 +87,13 @@ static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR, if (!val.IsEmpty()) { s += GetNameOfProperty(propID, nameBSTR); - s += kPropValueSeparator; + s.AddAscii(kPropValueSeparator); /* if (propID == kpidComment) - s += L'\n'; + s.Add_LF(); */ s += val; - s += L'\n'; + s.Add_LF(); } } } @@ -210,21 +198,21 @@ void CPanel::Properties() } } message += GetNameOfProperty(propID, name); - message += kPropValueSeparator; - message += GetUnicodeString(s); - message += L'\n'; + message.AddAscii(kPropValueSeparator); + message.AddAscii(s); + message.Add_LF(); } } } - message += kSeparator; + message.AddAscii(kSeparator); } /* - message += LangString(IDS_PROP_FILE_TYPE, 0x02000214); + AddLangString(message, IDS_PROP_FILE_TYPE); message += kPropValueSeparator; message += GetFolderTypeID(); - message += L"\n"; + message.Add_LF(); */ { @@ -277,7 +265,7 @@ void CPanel::Properties() { const int kNumSpecProps = ARRAY_SIZE(kSpecProps); - message += kSeparator; + message.AddAscii(kSeparator); for (Int32 i = -(int)kNumSpecProps; i < (Int32)numProps; i++) { @@ -302,7 +290,7 @@ void CPanel::Properties() UInt32 numProps; if (getProps->GetArcNumProps2(level, &numProps) == S_OK) { - message += kSeparatorSmall; + message.AddAscii(kSeparatorSmall); for (Int32 i = 0; i < (Int32)numProps; i++) { CMyComBSTR name; @@ -414,9 +402,7 @@ HRESULT CPanel::CreateShellContextMenu( FOR_VECTOR (i, operatedIndices) { LPITEMIDLIST pidl; - UString fileName = GetItemRelPath(operatedIndices[i]); - if (IsFSDrivesFolder()) - fileName += WCHAR_PATH_SEPARATOR; + UString fileName = GetItemRelPath2(operatedIndices[i]); RINOK(parentFolder->ParseDisplayName(GetParent(), 0, (wchar_t *)(const wchar_t *)fileName, &eaten, &pidl, 0)); pidls.AddInReserved(pidl); @@ -574,11 +560,11 @@ void CPanel::CreateSevenZipMenu(HMENU menuSpec, if (contextMenu.QueryInterface(IID_IInitContextMenu, &initContextMenu) != S_OK) return; */ - UString currentFolderUnicode = _currentFolderPrefix; + UString currentFolderUnicode = GetFsPath(); UStringVector names; unsigned i; for (i = 0; i < operatedIndices.Size(); i++) - names.Add(currentFolderUnicode + GetItemRelPath(operatedIndices[i])); + names.Add(currentFolderUnicode + GetItemRelPath2(operatedIndices[i])); CRecordVector<const wchar_t *> namePointers; for (i = 0; i < operatedIndices.Size(); i++) namePointers.Add(names[i]); @@ -598,6 +584,74 @@ void CPanel::CreateSevenZipMenu(HMENU menuSpec, } } +static bool IsReadOnlyFolder(IFolderFolder *folder) +{ + if (!folder) + return false; + + bool res = false; + { + NCOM::CPropVariant prop; + if (folder->GetFolderProperty(kpidReadOnly, &prop) == S_OK) + if (prop.vt == VT_BOOL) + res = VARIANT_BOOLToBool(prop.boolVal); + } + return res; +} + +bool CPanel::IsThereReadOnlyFolder() const +{ + if (!_folderOperations) + return true; + if (IsReadOnlyFolder(_folder)) + return true; + FOR_VECTOR (i, _parentFolders) + { + if (IsReadOnlyFolder(_parentFolders[i].ParentFolder)) + return true; + } + return false; +} + +bool CPanel::CheckBeforeUpdate(UINT resourceID) +{ + if (!_folderOperations) + { + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); + // resourceID = resourceID; + // MessageBoxErrorForUpdate(E_NOINTERFACE, resourceID); + return false; + } + + for (int i = (int)_parentFolders.Size(); i >= 0; i--) + { + IFolderFolder *folder; + if (i == (int)_parentFolders.Size()) + folder = _folder; + else + folder = _parentFolders[i].ParentFolder; + + if (!IsReadOnlyFolder(folder)) + continue; + + UString s; + AddLangString(s, resourceID); + s.Add_LF(); + AddLangString(s, IDS_OPERATION_IS_NOT_SUPPORTED); + s.Add_LF(); + if (i == 0) + s += GetFolderPath(folder); + else + s += _parentFolders[i - 1].VirtualPath; + s.Add_LF(); + AddLangString(s, IDS_PROP_READ_ONLY); + MessageBoxMyError(s); + return false; + } + + return true; +} + void CPanel::CreateFileMenu(HMENU menuSpec, CMyComPtr<IContextMenu> &sevenZipContextMenu, CMyComPtr<IContextMenu> &systemContextMenu, @@ -631,8 +685,38 @@ void CPanel::CreateFileMenu(HMENU menuSpec, if (IsItem_Folder(operatedIndices[i])) break; bool allAreFiles = (i == operatedIndices.Size()); - LoadFileMenu(menu, menu.GetItemCount(), programMenu, - IsFSFolder(), operatedIndices.Size(), allAreFiles); + + CFileMenu fm; + + fm.readOnly = IsThereReadOnlyFolder(); + fm.isFsFolder = Is_IO_FS_Folder(); + fm.programMenu = programMenu; + fm.allAreFiles = allAreFiles; + fm.numItems = operatedIndices.Size(); + + fm.isAltStreamsSupported = false; + + if (_folderAltStreams) + { + if (operatedIndices.Size() <= 1) + { + Int32 realIndex = -1; + if (operatedIndices.Size() == 1) + realIndex = operatedIndices[0]; + Int32 val = 0; + if (_folderAltStreams->AreAltStreamsSupported(realIndex, &val) == S_OK) + fm.isAltStreamsSupported = IntToBool(val); + } + } + else + { + if (fm.numItems == 0) + fm.isAltStreamsSupported = IsFSFolder(); + else + fm.isAltStreamsSupported = IsFolder_with_FsItems(); + } + + fm.Load(menu, menu.GetItemCount()); } bool CPanel::InvokePluginCommand(int id) @@ -654,26 +738,31 @@ bool CPanel::InvokePluginCommand(int id, else offset = id - kSevenZipStartMenuID; - #ifndef use_CMINVOKECOMMANDINFOEXR - CMINVOKECOMMANDINFO + #ifdef use_CMINVOKECOMMANDINFOEX + CMINVOKECOMMANDINFOEX #else - CMINVOKECOMMANDINFOEX + CMINVOKECOMMANDINFO #endif - commandInfo; + commandInfo; + memset(&commandInfo, 0, sizeof(commandInfo)); commandInfo.cbSize = sizeof(commandInfo); + commandInfo.fMask = 0 - #ifdef use_CMINVOKECOMMANDINFOEXR - | CMIC_MASK_UNICODE + #ifdef use_CMINVOKECOMMANDINFOEX + | CMIC_MASK_UNICODE #endif - ; + ; + commandInfo.hwnd = GetParent(); commandInfo.lpVerb = (LPCSTR)(MAKEINTRESOURCE(offset)); commandInfo.lpParameters = NULL; CSysString currentFolderSys = GetSystemString(_currentFolderPrefix); commandInfo.lpDirectory = (LPCSTR)(LPCTSTR)(currentFolderSys); commandInfo.nShow = SW_SHOW; - #ifdef use_CMINVOKECOMMANDINFOEXR + + #ifdef use_CMINVOKECOMMANDINFOEX + commandInfo.lpParametersW = NULL; commandInfo.lpTitle = ""; commandInfo.lpVerbW = (LPCWSTR)(MAKEINTRESOURCEW(offset)); @@ -684,7 +773,9 @@ bool CPanel::InvokePluginCommand(int id, // commandInfo.ptInvoke.y = yPos; commandInfo.ptInvoke.x = 0; commandInfo.ptInvoke.y = 0; + #endif + HRESULT result; if (isSystemMenu) result = systemContextMenu->InvokeCommand(LPCMINVOKECOMMANDINFO(&commandInfo)); diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp index 28c945e5..62a08e13 100644 --- a/CPP/7zip/UI/FileManager/PanelOperations.cpp +++ b/CPP/7zip/UI/FileManager/PanelOperations.cpp @@ -85,16 +85,15 @@ HRESULT CThreadFolderOperations::DoOperation(CPanel &panel, const UString &progr ProgressDialog.Sync.FinalMessage.ErrorMessage.Title = titleError; Result = S_OK; - bool usePassword = false; - UString password; + UpdateCallbackSpec->Init(); + if (panel._parentFolders.Size() > 0) { const CFolderLink &fl = panel._parentFolders.Back(); - usePassword = fl.UsePassword; - password = fl.Password; + UpdateCallbackSpec->PasswordIsDefined = fl.UsePassword; + UpdateCallbackSpec->Password = fl.Password; } - UpdateCallbackSpec->Init(usePassword, password); ProgressDialog.MainWindow = panel._mainWindow; // panel.GetParent() ProgressDialog.MainTitle = L"7-Zip"; // LangString(IDS_APP_TITLE); @@ -108,6 +107,7 @@ HRESULT CThreadFolderOperations::DoOperation(CPanel &panel, const UString &progr typedef int (WINAPI * SHFileOperationWP)(LPSHFILEOPSTRUCTW lpFileOp); #endif +/* void CPanel::MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID) { if (errorCode == E_NOINTERFACE) @@ -115,6 +115,7 @@ void CPanel::MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID) else MessageBoxError(errorCode, LangString(resourceID)); } +*/ void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin)) { @@ -137,8 +138,8 @@ void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin)) CDynamicBuffer<CHAR> buffer; FOR_VECTOR (i, indices) { - const AString path = GetSystemString(GetFsPath() + GetItemRelPath(indices[i])); - memcpy(buffer.GetCurPtrAndGrow(path.Len() + 1), (const CHAR *)path, (path.Len() + 1) * sizeof(CHAR)); + const AString path = GetSystemString(GetItemFullPath(indices[i])); + buffer.AddData(path, path.Len() + 1); } *buffer.GetCurPtrAndGrow(1) = 0; SHFILEOPSTRUCTA fo; @@ -163,13 +164,14 @@ void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin)) { CDynamicBuffer<WCHAR> buffer; unsigned maxLen = 0; + const UString prefix = GetFsPath(); FOR_VECTOR (i, indices) { // L"\\\\?\\") doesn't work here. - const UString path = GetFsPath() + GetItemRelPath(indices[i]); + const UString path = prefix + GetItemRelPath2(indices[i]); if (path.Len() > maxLen) maxLen = path.Len(); - memcpy(buffer.GetCurPtrAndGrow(path.Len() + 1), (const WCHAR *)path, (path.Len() + 1) * sizeof(WCHAR)); + buffer.AddData(path, path.Len() + 1); } *buffer.GetCurPtrAndGrow(1) = 0; if (maxLen >= MAX_PATH) @@ -220,19 +222,15 @@ void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin)) // DeleteItemsInternal - CMyComPtr<IFolderOperations> folderOperations; - if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) - { - MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_ERROR_DELETING); + if (!CheckBeforeUpdate(IDS_ERROR_DELETING)) return; - } UInt32 titleID, messageID; UString messageParam; if (indices.Size() == 1) { int index = indices[0]; - messageParam = GetItemRelPath(index); + messageParam = GetItemRelPath2(index); if (IsItem_Folder(index)) { titleID = IDS_CONFIRM_FOLDER_DELETE; @@ -256,7 +254,7 @@ void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin)) CDisableNotify disableNotify(*this); { CThreadFolderOperations op(FOLDER_TYPE_DELETE); - op.FolderOperations = folderOperations; + op.FolderOperations = _folderOperations; op.Indices = indices; op.DoOperation(*this, LangString(IDS_DELETING), @@ -271,25 +269,14 @@ BOOL CPanel::OnBeginLabelEdit(LV_DISPINFOW * lpnmh) int realIndex = GetRealIndex(lpnmh->item); if (realIndex == kParentIndex) return TRUE; - CMyComPtr<IFolderOperations> folderOperations; - if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + if (IsThereReadOnlyFolder()) return TRUE; return FALSE; } -static UString GetLastPart(const UString name) -{ - int slashPos = name.ReverseFind(L'/'); - #ifdef _WIN32 - int slash1Pos = name.ReverseFind(L'\\'); - slashPos = MyMax(slashPos, slash1Pos); - #endif - return name.Ptr(slashPos + 1); -} - bool IsCorrectFsName(const UString &name) { - const UString lastPart = GetLastPart(name); + const UString lastPart = name.Ptr(name.ReverseFind_PathSepar() + 1); return lastPart != L"." && lastPart != L".."; @@ -299,7 +286,7 @@ bool CorrectFsPath(const UString &relBase, const UString &path, UString &result) bool CPanel::CorrectFsPath(const UString &path2, UString &result) { - return ::CorrectFsPath(_currentFolderPrefix, path2, result); + return ::CorrectFsPath(GetFsPath(), path2, result); } BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh) @@ -307,12 +294,10 @@ BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh) if (lpnmh->item.pszText == NULL) return FALSE; CDisableTimerProcessing disableTimerProcessing2(*this); - CMyComPtr<IFolderOperations> folderOperations; - if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) - { - MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_ERROR_RENAMING); + + if (!CheckBeforeUpdate(IDS_ERROR_RENAMING)) return FALSE; - } + UString newName = lpnmh->item.pszText; if (!IsCorrectFsName(newName)) { @@ -342,7 +327,7 @@ BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh) CDisableNotify disableNotify(*this); { CThreadFolderOperations op(FOLDER_TYPE_RENAME); - op.FolderOperations = folderOperations; + op.FolderOperations = _folderOperations; op.Index = realIndex; op.Name = newName; /* HRESULTres = */ op.DoOperation(*this, @@ -377,12 +362,9 @@ bool Dlg_CreateFolder(HWND wnd, UString &destName); void CPanel::CreateFolder() { - CMyComPtr<IFolderOperations> folderOperations; - if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) - { - MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_CREATE_FOLDER_ERROR); + if (!CheckBeforeUpdate(IDS_CREATE_FOLDER_ERROR)) return; - } + CDisableTimerProcessing disableTimerProcessing2(*this); CSelectedState state; SaveSelectedState(state); @@ -412,7 +394,7 @@ void CPanel::CreateFolder() CDisableNotify disableNotify(*this); { CThreadFolderOperations op(FOLDER_TYPE_CREATE_FOLDER); - op.FolderOperations = folderOperations; + op.FolderOperations = _folderOperations; op.Name = newName; res = op.DoOperation(*this, LangString(IDS_CREATE_FOLDER), @@ -439,12 +421,9 @@ void CPanel::CreateFolder() void CPanel::CreateFile() { - CMyComPtr<IFolderOperations> folderOperations; - if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) - { - MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_CREATE_FILE_ERROR); + if (!CheckBeforeUpdate(IDS_CREATE_FILE_ERROR)) return; - } + CDisableTimerProcessing disableTimerProcessing2(*this); CSelectedState state; SaveSelectedState(state); @@ -471,10 +450,11 @@ void CPanel::CreateFile() newName = correctName; } - HRESULT result = folderOperations->CreateFile(newName, 0); + HRESULT result = _folderOperations->CreateFile(newName, 0); if (result != S_OK) { - MessageBoxErrorForUpdate(result, IDS_CREATE_FILE_ERROR); + MessageBoxError(result, LangString(IDS_CREATE_FILE_ERROR)); + // MessageBoxErrorForUpdate(result, IDS_CREATE_FILE_ERROR); return; } int pos = newName.Find(WCHAR_PATH_SEPARATOR); @@ -489,6 +469,8 @@ void CPanel::CreateFile() void CPanel::RenameFile() { + if (!CheckBeforeUpdate(IDS_ERROR_RENAMING)) + return; int index = _listView.GetFocusedItem(); if (index >= 0) _listView.EditLabel(index); @@ -496,6 +478,8 @@ void CPanel::RenameFile() void CPanel::ChangeComment() { + if (!CheckBeforeUpdate(IDS_COMMENT)) + return; CDisableTimerProcessing disableTimerProcessing2(*this); int index = _listView.GetFocusedItem(); if (index < 0) @@ -505,13 +489,6 @@ void CPanel::ChangeComment() return; CSelectedState state; SaveSelectedState(state); - CMyComPtr<IFolderOperations> folderOperations; - if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) - { - MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); - return; - } - UString comment; { NCOM::CPropVariant propVariant; @@ -522,17 +499,19 @@ void CPanel::ChangeComment() else if (propVariant.vt != VT_EMPTY) return; } - UString name = GetItemRelPath(realIndex); + UString name = GetItemRelPath2(realIndex); CComboDialog dlg; - dlg.Title = name + L' ' + LangString(IDS_COMMENT); + dlg.Title = name; + dlg.Title += L" : "; + AddLangString(dlg.Title, IDS_COMMENT); dlg.Value = comment; LangString(IDS_COMMENT2, dlg.Static); if (dlg.Create(GetParent()) != IDOK) return; - NCOM::CPropVariant propVariant = (const wchar_t *)dlg.Value; + NCOM::CPropVariant propVariant = dlg.Value.Ptr(); CDisableNotify disableNotify(*this); - HRESULT result = folderOperations->SetProperty(realIndex, kpidComment, &propVariant, NULL); + HRESULT result = _folderOperations->SetProperty(realIndex, kpidComment, &propVariant, NULL); if (result != S_OK) { if (result == E_NOINTERFACE) diff --git a/CPP/7zip/UI/FileManager/PanelSelect.cpp b/CPP/7zip/UI/FileManager/PanelSelect.cpp index a40997c2..7b53eb00 100644 --- a/CPP/7zip/UI/FileManager/PanelSelect.cpp +++ b/CPP/7zip/UI/FileManager/PanelSelect.cpp @@ -22,7 +22,9 @@ void CPanel::OnShiftSelectMessage() return; int startItem = MyMin(focusedItem, _prevFocusedItem); int finishItem = MyMax(focusedItem, _prevFocusedItem); - for (int i = 0; i < _listView.GetItemCount(); i++) + + int numItems = _listView.GetItemCount(); + for (int i = 0; i < numItems; i++) { int realIndex = GetRealItemIndex(i); if (realIndex == kParentIndex) @@ -34,6 +36,7 @@ void CPanel::OnShiftSelectMessage() _listView.RedrawItem(i); } } + _prevFocusedItem = focusedItem; } @@ -45,6 +48,7 @@ void CPanel::OnArrowWithShift() if (focusedItem < 0) return; int realIndex = GetRealItemIndex(focusedItem); + if (_selectionIsDefined) { if (realIndex != kParentIndex) @@ -64,6 +68,7 @@ void CPanel::OnArrowWithShift() _selectedStatusVector[realIndex] = _selectMark; } } + _prevFocusedItem = focusedItem; PostMessage(kShiftSelectMessage); _listView.RedrawItem(focusedItem); @@ -165,13 +170,6 @@ void CPanel::SelectByType(bool selectMode) UString name = GetItemName(realIndex); bool isItemFolder = IsItem_Folder(realIndex); - /* - UInt32 numItems; - _folder->GetNumberOfItems(&numItems); - if ((UInt32)_selectedStatusVector.Size() != numItems) - throw 11111; - */ - if (isItemFolder) { FOR_VECTOR (i, _selectedStatusVector) @@ -180,11 +178,11 @@ void CPanel::SelectByType(bool selectMode) } else { - int pos = name.ReverseFind(L'.'); + int pos = name.ReverseFind_Dot(); if (pos < 0) { FOR_VECTOR (i, _selectedStatusVector) - if (IsItem_Folder(i) == isItemFolder && GetItemName(i).ReverseFind(L'.') < 0) + if (IsItem_Folder(i) == isItemFolder && GetItemName(i).ReverseFind_Dot() < 0) _selectedStatusVector[i] = selectMode; } else @@ -196,6 +194,7 @@ void CPanel::SelectByType(bool selectMode) _selectedStatusVector[i] = selectMode; } } + UpdateSelection(); } @@ -253,10 +252,11 @@ void CPanel::OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate) { if (itemActivate->hdr.hwndFrom != HWND(_listView)) return; - // It will be work only for Version 4.71 (IE 4); + // It will work only for Version 4.71 (IE 4); int indexInList = itemActivate->iItem; if (indexInList < 0) return; + #ifndef UNDER_CE if ((itemActivate->uKeyFlags & LVKF_SHIFT) != 0) { @@ -264,9 +264,11 @@ void CPanel::OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate) int focusedIndex = _startGroupSelect; if (focusedIndex < 0) return; - unsigned startItem = MyMin((unsigned)focusedIndex, (unsigned)indexInList); - unsigned finishItem = MyMax((unsigned)focusedIndex, (unsigned)indexInList); - FOR_VECTOR (i, _selectedStatusVector) + int startItem = MyMin(focusedIndex, indexInList); + int finishItem = MyMax(focusedIndex, indexInList); + + int numItems = _listView.GetItemCount(); + for (int i = 0; i < numItems; i++) { int realIndex = GetRealItemIndex(i); if (realIndex == kParentIndex) @@ -283,6 +285,7 @@ void CPanel::OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate) #endif { _startGroupSelect = indexInList; + #ifndef UNDER_CE if ((itemActivate->uKeyFlags & LVKF_CONTROL) != 0) { @@ -295,5 +298,6 @@ void CPanel::OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate) } #endif } + return; } diff --git a/CPP/7zip/UI/FileManager/PanelSort.cpp b/CPP/7zip/UI/FileManager/PanelSort.cpp index fe5d3ffd..82d6756e 100644 --- a/CPP/7zip/UI/FileManager/PanelSort.cpp +++ b/CPP/7zip/UI/FileManager/PanelSort.cpp @@ -76,7 +76,7 @@ static int CompareFileNames_Le16(const Byte *s1, unsigned size1, const Byte *s2, static inline const wchar_t *GetExtensionPtr(const UString &name) { - int dotPos = name.ReverseFind(L'.'); + int dotPos = name.ReverseFind_Dot(); return name.Ptr((dotPos < 0) ? name.Len() : dotPos); } diff --git a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp index ce15fcc5..a8c0d352 100644 --- a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp +++ b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp @@ -138,7 +138,7 @@ HRESULT CThreadSplit::ProcessVirt() if (!outFile.Create(name, false)) { HRESULT res = GetLastError(); - SetErrorPath1(name); + AddErrorPath(name); return res; } } @@ -165,7 +165,7 @@ void CApp::Split() { int srcPanelIndex = GetFocusedPanelIndex(); CPanel &srcPanel = Panels[srcPanelIndex]; - if (!srcPanel.IsFSFolder()) + if (!srcPanel.Is_IO_FS_Folder()) { srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; @@ -187,13 +187,13 @@ void CApp::Split() } const UString itemName = srcPanel.GetItemName(index); - UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index); + UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index); UString path = srcPath; int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); CPanel &destPanel = Panels[destPanelIndex]; if (NumPanels > 1) if (destPanel.IsFSFolder()) - path = destPanel._currentFolderPrefix; + path = destPanel.GetFsPath(); CSplitDialog splitDialog; splitDialog.FilePath = srcPanel.GetItemRelPath(index); splitDialog.Path = path; @@ -243,12 +243,13 @@ void CApp::Split() progressDialog.MainWindow = _window; progressDialog.MainTitle = progressWindowTitle; - progressDialog.MainAddTitle = title + L' '; + progressDialog.MainAddTitle = title; + progressDialog.MainAddTitle.Add_Space(); progressDialog.Sync.Set_TitleFileName(itemName); spliter.FilePath = us2fs(srcPath + itemName); - spliter.VolBasePath = us2fs(path + itemName); + spliter.VolBasePath = us2fs(path + srcPanel.GetItemName_for_Copy(index)); spliter.VolumeSizes = splitDialog.VolumeSizes; // if (splitDialog.VolumeSizes.Size() == 0) return; @@ -285,7 +286,7 @@ HRESULT CThreadCombine::ProcessVirt() if (!outFile.Create(OutputPath, false)) { HRESULT res = GetLastError(); - SetErrorPath1(OutputPath); + AddErrorPath(OutputPath); return res; } @@ -304,7 +305,7 @@ HRESULT CThreadCombine::ProcessVirt() if (!inFile.Open(nextName)) { HRESULT res = GetLastError(); - SetErrorPath1(nextName); + AddErrorPath(nextName); return res; } sync.Set_FilePath(fs2us(nextName)); @@ -314,7 +315,7 @@ HRESULT CThreadCombine::ProcessVirt() if (!inFile.Read(buffer, kBufSize, processedSize)) { HRESULT res = GetLastError(); - SetErrorPath1(nextName); + AddErrorPath(nextName); return res; } if (processedSize == 0) @@ -323,7 +324,7 @@ HRESULT CThreadCombine::ProcessVirt() if (!outFile.Write(buffer, needSize, processedSize)) { HRESULT res = GetLastError(); - SetErrorPath1(OutputPath); + AddErrorPath(OutputPath); return res; } if (needSize != processedSize) @@ -364,13 +365,13 @@ void CApp::Combine() } const UString itemName = srcPanel.GetItemName(index); - UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index); + UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index); UString path = srcPath; int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); CPanel &destPanel = Panels[destPanelIndex]; if (NumPanels > 1) if (destPanel.IsFSFolder()) - path = destPanel._currentFolderPrefix; + path = destPanel.GetFsPath(); CVolSeqName volSeqName; if (!volSeqName.ParseName(itemName)) @@ -408,7 +409,7 @@ void CApp::Combine() UString info; AddValuePair2(info, IDS_PROP_FILES, combiner.Names.Size(), combiner.TotalSize); - info += L"\n"; + info.Add_LF(); info += srcPath; unsigned i; @@ -425,7 +426,7 @@ void CApp::Combine() CCopyDialog copyDialog; copyDialog.Value = path; LangString(IDS_COMBINE, copyDialog.Title); - copyDialog.Title += ' '; + copyDialog.Title.Add_Space(); copyDialog.Title += srcPanel.GetItemRelPath(index); LangString(IDS_COMBINE_TO, copyDialog.Static); copyDialog.Info = info; @@ -468,7 +469,8 @@ void CApp::Combine() progressDialog.MainWindow = _window; progressDialog.MainTitle = progressWindowTitle; - progressDialog.MainAddTitle = title + L' '; + progressDialog.MainAddTitle = title; + progressDialog.MainAddTitle.Add_Space(); combiner.InputDirPrefix = us2fs(srcPath); diff --git a/CPP/7zip/UI/FileManager/PluginInterface.h b/CPP/7zip/UI/FileManager/PluginInterface.h index 3ce5fa8e..37654a03 100644 --- a/CPP/7zip/UI/FileManager/PluginInterface.h +++ b/CPP/7zip/UI/FileManager/PluginInterface.h @@ -11,7 +11,7 @@ PLUGIN_INTERFACE(IInitContextMenu, 0x00) { - STDMETHOD(InitContextMenu)(const wchar_t *folder, const wchar_t **names, UInt32 numFiles) PURE; + STDMETHOD(InitContextMenu)(const wchar_t *folder, const wchar_t * const *names, UInt32 numFiles) PURE; }; PLUGIN_INTERFACE(IPluginOptionsCallback, 0x01) diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp index c9ca3942..231d0ace 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp @@ -28,7 +28,7 @@ static const UINT kTimerElapse = #ifdef UNDER_CE 500 #else - 100 + 200 #endif ; @@ -104,13 +104,13 @@ HRESULT CProgressSync::CheckStop() } } -HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const UString &fileName, bool isDir) +HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir) { { CRITICAL_LOCK _totalFiles = numFiles; _totalBytes = totalSize; - _filePath = fileName; + _filePath = fs2us(fileName); _isDir = isDir; // _completedBytes = 0; CHECK_STOP @@ -118,10 +118,14 @@ HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const USt return CheckStop(); } -void CProgressSync::Set_NumFilesTotal(UInt64 val) +HRESULT CProgressSync::Set_NumFilesTotal(UInt64 val) { - CRITICAL_LOCK - _totalFiles = val; + { + CRITICAL_LOCK + _totalFiles = val; + CHECK_STOP + } + return CheckStop(); } void CProgressSync::Set_NumBytesTotal(UInt64 val) @@ -171,16 +175,34 @@ void CProgressSync::Set_TitleFileName(const UString &fileName) CRITICAL_LOCK _titleFileName = fileName; } + void CProgressSync::Set_Status(const UString &s) { CRITICAL_LOCK _status = s; } -void CProgressSync::Set_FilePath(const UString &path, bool isDir) +HRESULT CProgressSync::Set_Status2(const UString &s, const wchar_t *path, bool isDir) +{ + { + CRITICAL_LOCK + _status = s; + if (path) + _filePath = path; + else + _filePath.Empty(); + _isDir = isDir; + } + return CheckStop(); +} + +void CProgressSync::Set_FilePath(const wchar_t *path, bool isDir) { CRITICAL_LOCK - _filePath = path; + if (path) + _filePath = path; + else + _filePath.Empty(); _isDir = isDir; } @@ -199,7 +221,7 @@ void CProgressSync::AddError_Message_Name(const wchar_t *message, const wchar_t if (message && *message != 0 ) { if (!s.IsEmpty()) - s += L'\n'; + s.Add_LF(); s += message; if (!s.IsEmpty() && s.Back() == L'\n') s.DeleteBack(); @@ -633,7 +655,6 @@ static unsigned GetPower64(UInt64 val) if (high == 0) return GetPower32((UInt32)val); return GetPower32(high) + 32; - } static UInt64 MyMultAndDiv(UInt64 mult1, UInt64 mult2, UInt64 divider) @@ -867,7 +888,7 @@ void CProgressDialog::UpdateStatInfo(bool showAll) s1 = _filePath; else { - int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR); + int slashPos = _filePath.ReverseFind_PathSepar(); if (slashPos >= 0) { s1.SetFrom(_filePath, slashPos + 1); @@ -878,7 +899,7 @@ void CProgressDialog::UpdateStatInfo(bool showAll) } ReduceString(s1, _numReduceSymbols); ReduceString(s2, _numReduceSymbols); - s1 += L'\n'; + s1.Add_LF(); s1 += s2; SetItemText(IDT_PROGRESS_FILE_NAME, s1); } @@ -1025,22 +1046,22 @@ void CProgressDialog::SetTitleText() if (Sync.Get_Paused()) { s += _paused_String; - s += L' '; + s.Add_Space(); } if (IS_DEFINED_VAL(_prevPercentValue)) { - wchar_t temp[32]; + char temp[32]; ConvertUInt64ToString(_prevPercentValue, temp); - s += temp; + s.AddAscii(temp); s += L'%'; } if (!_foreground) { - s += L' '; + s.Add_Space(); s += _backgrounded_String; } - s += L' '; + s.Add_Space(); #ifndef _SFX { unsigned len = s.Len(); @@ -1055,7 +1076,7 @@ void CProgressDialog::SetTitleText() { UString fileName = _titleFileName; ReduceString(fileName, kTitleFileNameSizeLimit); - s += L' '; + s.Add_Space(); s += fileName; } SetText(s); @@ -1239,7 +1260,7 @@ static void AddMessageToString(UString &dest, const UString &src) if (!src.IsEmpty()) { if (!dest.IsEmpty()) - dest += L'\n'; + dest.Add_LF(); dest += src; } } @@ -1266,8 +1287,15 @@ void CProgressThreadVirt::Process() m = HResultToMessage(Result); } AddMessageToString(m, FinalMessage.ErrorMessage.Message); - AddMessageToString(m, fs2us(ErrorPath1)); - AddMessageToString(m, fs2us(ErrorPath2)); + + { + FOR_VECTOR(i, ErrorPaths) + { + if (i >= 32) + break; + AddMessageToString(m, fs2us(ErrorPaths[i])); + } + } CProgressSync &sync = ProgressDialog.Sync; NSynchronization::CCriticalSectionLock lock(sync._cs); diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.h b/CPP/7zip/UI/FileManager/ProgressDialog2.h index ea1559a7..03f836da 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.h +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.h @@ -80,9 +80,9 @@ public: } HRESULT CheckStop(); - HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const UString &fileName, bool isDir = false); + HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir = false); - void Set_NumFilesTotal(UInt64 val); + HRESULT Set_NumFilesTotal(UInt64 val); void Set_NumBytesTotal(UInt64 val); void Set_NumFilesCur(UInt64 val); HRESULT Set_NumBytesCur(const UInt64 *val); @@ -91,7 +91,8 @@ public: void Set_TitleFileName(const UString &fileName); void Set_Status(const UString &s); - void Set_FilePath(const UString &path, bool isDir = false); + HRESULT Set_Status2(const UString &s, const wchar_t *path, bool isDir = false); + void Set_FilePath(const wchar_t *path, bool isDir = false); void AddError_Message(const wchar_t *message); void AddError_Message_Name(const wchar_t *message, const wchar_t *name); @@ -274,9 +275,8 @@ public: class CProgressThreadVirt { - FString ErrorPath1; - FString ErrorPath2; protected: + FStringVector ErrorPaths; CProgressFinalMessage FinalMessage; // error if any of HRESULT, ErrorMessage, ErrorPath @@ -299,8 +299,7 @@ public: return 0; } - void SetErrorPath1(const FString &path) { ErrorPath1 = path; } - void SetErrorPath2(const FString &path) { ErrorPath2 = path; } + void AddErrorPath(const FString &path) { ErrorPaths.Add(path); } HRESULT Create(const UString &title, HWND parentWindow = 0); CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {} diff --git a/CPP/7zip/UI/FileManager/PropertyName.rc b/CPP/7zip/UI/FileManager/PropertyName.rc index 43c4584f..8b8c7899 100644 --- a/CPP/7zip/UI/FileManager/PropertyName.rc +++ b/CPP/7zip/UI/FileManager/PropertyName.rc @@ -94,4 +94,6 @@ BEGIN IDS_PROP_HARD_LINK "Hard Link" IDS_PROP_INODE "iNode" IDS_PROP_STREAM_ID "Stream ID" + IDS_PROP_READ_ONLY "Read-only" + IDS_PROP_OUT_NAME "Out Name" END diff --git a/CPP/7zip/UI/FileManager/PropertyNameRes.h b/CPP/7zip/UI/FileManager/PropertyNameRes.h index 199aa6da..3696ed2e 100644 --- a/CPP/7zip/UI/FileManager/PropertyNameRes.h +++ b/CPP/7zip/UI/FileManager/PropertyNameRes.h @@ -90,3 +90,5 @@ #define IDS_PROP_HARD_LINK 1090 #define IDS_PROP_INODE 1091 #define IDS_PROP_STREAM_ID 1092 +#define IDS_PROP_READ_ONLY 1093 +#define IDS_PROP_OUT_NAME 1094 diff --git a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp index ee944350..93ba40c2 100644 --- a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp +++ b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp @@ -86,8 +86,7 @@ bool CShellExtInfo::ReadFromRegistry(HKEY hkey, const CSysString &ext) bool CShellExtInfo::IsIt7Zip() const { - UString s = GetUnicodeString(k7zipPrefix); - return MyStringCompareNoCase_N(GetUnicodeString(ProgramKey), s, s.Len()) == 0; + return IsString1PrefixedByString2_NoCase(GetUnicodeString(ProgramKey), GetUnicodeString(k7zipPrefix)); } LONG DeleteShellExtensionInfo(HKEY hkey, const CSysString &ext) diff --git a/CPP/7zip/UI/FileManager/RootFolder.cpp b/CPP/7zip/UI/FileManager/RootFolder.cpp index 234c51dd..c5b57821 100644 --- a/CPP/7zip/UI/FileManager/RootFolder.cpp +++ b/CPP/7zip/UI/FileManager/RootFolder.cpp @@ -10,11 +10,25 @@ #include "../../PropID.h" +#if defined(_WIN32) && !defined(UNDER_CE) +#define USE_WIN_PATHS +#endif + +static const unsigned kNumRootFolderItems = + #ifdef USE_WIN_PATHS + 4 + #else + 1 + #endif + ; + + #include "FSFolder.h" #include "LangUtils.h" -#ifndef UNDER_CE +#ifdef USE_WIN_PATHS #include "NetFolder.h" #include "FSDrives.h" +#include "AltStreamsFolder.h" #endif #include "RootFolder.h" #include "SysIconUtils.h" @@ -30,10 +44,10 @@ static const PROPID kProps[] = UString RootFolder_GetName_Computer(int &iconIndex) { - #ifdef UNDER_CE - GetRealIconIndex(FTEXT("\\"), FILE_ATTRIBUTE_DIRECTORY, iconIndex); - #else + #ifdef USE_WIN_PATHS iconIndex = GetIconIndexForCSIDL(CSIDL_DRIVES); + #else + GetRealIconIndex(FSTRING_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, iconIndex); #endif return LangString(IDS_COMPUTER); } @@ -53,21 +67,21 @@ UString RootFolder_GetName_Documents(int &iconIndex) enum { ROOT_INDEX_COMPUTER = 0 - #ifndef UNDER_CE + #ifdef USE_WIN_PATHS , ROOT_INDEX_DOCUMENTS , ROOT_INDEX_NETWORK , ROOT_INDEX_VOLUMES #endif }; -#ifndef UNDER_CE +#ifdef USE_WIN_PATHS static const wchar_t *kVolPrefix = L"\\\\."; #endif void CRootFolder::Init() { _names[ROOT_INDEX_COMPUTER] = RootFolder_GetName_Computer(_iconIndices[ROOT_INDEX_COMPUTER]); - #ifndef UNDER_CE + #ifdef USE_WIN_PATHS _names[ROOT_INDEX_DOCUMENTS] = RootFolder_GetName_Documents(_iconIndices[ROOT_INDEX_DOCUMENTS]); _names[ROOT_INDEX_NETWORK] = RootFolder_GetName_Network(_iconIndices[ROOT_INDEX_NETWORK]); _names[ROOT_INDEX_VOLUMES] = kVolPrefix; @@ -124,8 +138,7 @@ UString GetMyDocsPath() us = GetUnicodeString(s2); } #endif - if (us.Len() > 0 && us.Back() != WCHAR_PATH_SEPARATOR) - us += WCHAR_PATH_SEPARATOR; + NFile::NName::NormalizeDirPathPrefix(us); return us; } @@ -133,14 +146,8 @@ STDMETHODIMP CRootFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolde { *resultFolder = NULL; CMyComPtr<IFolderFolder> subFolder; - #ifdef UNDER_CE - if (index == ROOT_INDEX_COMPUTER) - { - NFsFolder::CFSFolder *fsFolder = new NFsFolder::CFSFolder; - subFolder = fsFolder; - fsFolder->InitToRoot(); - } - #else + + #ifdef USE_WIN_PATHS if (index == ROOT_INDEX_COMPUTER || index == ROOT_INDEX_VOLUMES) { CFSDrives *fsDrivesSpec = new CFSDrives; @@ -160,12 +167,20 @@ STDMETHODIMP CRootFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolde { NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder; subFolder = fsFolderSpec; - RINOK(fsFolderSpec->Init(us2fs(s), NULL)); + RINOK(fsFolderSpec->Init(us2fs(s))); } } + #else + if (index == ROOT_INDEX_COMPUTER) + { + NFsFolder::CFSFolder *fsFolder = new NFsFolder::CFSFolder; + subFolder = fsFolder; + fsFolder->InitToRoot(); + } #endif else return E_INVALIDARG; + *resultFolder = subFolder.Detach(); return S_OK; } @@ -185,6 +200,7 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu *resultFolder = 0; UString name2 = name; name2.Trim(); + if (name2.IsEmpty()) { CRootFolder *rootFolderSpec = new CRootFolder; @@ -193,21 +209,25 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu *resultFolder = rootFolder.Detach(); return S_OK; } - for (int i = 0; i < kNumRootFolderItems; i++) + + for (unsigned i = 0; i < kNumRootFolderItems; i++) if (AreEqualNames(name2, _names[i])) return BindToFolder((UInt32)i, resultFolder); - #ifdef UNDER_CE - if (name2 == L"\\") - return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder); - #else + + #ifdef USE_WIN_PATHS if (AreEqualNames(name2, L"My Documents") || AreEqualNames(name2, L"Documents")) return BindToFolder((UInt32)ROOT_INDEX_DOCUMENTS, resultFolder); + #else + if (name2 == WSTRING_PATH_SEPARATOR) + return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder); #endif + if (AreEqualNames(name2, L"My Computer") || AreEqualNames(name2, L"Computer")) return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder); - if (name2 == UString(WCHAR_PATH_SEPARATOR)) + + if (name2 == WSTRING_PATH_SEPARATOR) { CMyComPtr<IFolderFolder> subFolder = this; *resultFolder = subFolder.Detach(); @@ -219,7 +239,7 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu CMyComPtr<IFolderFolder> subFolder; - #ifndef UNDER_CE + #ifdef USE_WIN_PATHS if (name2.IsPrefixedBy(kVolPrefix)) { CFSDrives *folderSpec = new CFSDrives; @@ -232,16 +252,22 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu subFolder = folderSpec; folderSpec->Init(false, true); } + else if (name2.Back() == ':') + { + NAltStreamsFolder::CAltStreamsFolder *folderSpec = new NAltStreamsFolder::CAltStreamsFolder; + subFolder = folderSpec; + if (folderSpec->Init(us2fs(name2)) != S_OK) + return E_INVALIDARG; + } else #endif { - if (name2[name2.Len() - 1] != WCHAR_PATH_SEPARATOR) - name2 += WCHAR_PATH_SEPARATOR; + NFile::NName::NormalizeDirPathPrefix(name2); NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder; subFolder = fsFolderSpec; - if (fsFolderSpec->Init(us2fs(name2), 0) != S_OK) + if (fsFolderSpec->Init(us2fs(name2)) != S_OK) { - #ifndef UNDER_CE + #ifdef USE_WIN_PATHS if (name2[0] == WCHAR_PATH_SEPARATOR) { CNetFolder *netFolderSpec = new CNetFolder; @@ -253,6 +279,7 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu return E_INVALIDARG; } } + *resultFolder = subFolder.Detach(); return S_OK; } @@ -267,11 +294,11 @@ IMP_IFolderFolder_Props(CRootFolder) STDMETHODIMP CRootFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) { - NWindows::NCOM::CPropVariant prop; - switch(propID) + NCOM::CPropVariant prop; + switch (propID) { - case kpidType: prop = L"RootFolder"; break; - case kpidPath: prop = L""; break; + case kpidType: prop = "RootFolder"; break; + case kpidPath: prop = ""; break; } prop.Detach(value); return S_OK; diff --git a/CPP/7zip/UI/FileManager/RootFolder.h b/CPP/7zip/UI/FileManager/RootFolder.h index e9ef2d8c..e2537837 100644 --- a/CPP/7zip/UI/FileManager/RootFolder.h +++ b/CPP/7zip/UI/FileManager/RootFolder.h @@ -7,21 +7,15 @@ #include "IFolder.h" -const int kNumRootFolderItems = - #ifdef UNDER_CE - 1 - #else - 4 - #endif - ; +const unsigned kNumRootFolderItems_Max = 4; class CRootFolder: public IFolderFolder, public IFolderGetSystemIconIndex, public CMyUnknownImp { - UString _names[kNumRootFolderItems]; - int _iconIndices[kNumRootFolderItems]; + UString _names[kNumRootFolderItems_Max]; + int _iconIndices[kNumRootFolderItems_Max]; public: MY_UNKNOWN_IMP1(IFolderGetSystemIconIndex) diff --git a/CPP/7zip/UI/FileManager/SettingsPage.rc b/CPP/7zip/UI/FileManager/SettingsPage.rc index 3e4a611e..c724fcb7 100644 --- a/CPP/7zip/UI/FileManager/SettingsPage.rc +++ b/CPP/7zip/UI/FileManager/SettingsPage.rc @@ -1,7 +1,7 @@ #include "SettingsPageRes.h" #include "../../GuiCommon.rc" -#define xc 200 +#define xc 240 #define yc 120 IDD_SETTINGS MY_PAGE diff --git a/CPP/7zip/UI/FileManager/SplitDialog.cpp b/CPP/7zip/UI/FileManager/SplitDialog.cpp index d35d76c9..d7d14d7c 100644 --- a/CPP/7zip/UI/FileManager/SplitDialog.cpp +++ b/CPP/7zip/UI/FileManager/SplitDialog.cpp @@ -38,7 +38,7 @@ bool CSplitDialog::OnInit() { UString title; GetText(title); - title += L' '; + title.Add_Space(); title += FilePath; SetText(title); } diff --git a/CPP/7zip/UI/FileManager/StringUtils.cpp b/CPP/7zip/UI/FileManager/StringUtils.cpp index fb38a735..10056549 100644 --- a/CPP/7zip/UI/FileManager/StringUtils.cpp +++ b/CPP/7zip/UI/FileManager/StringUtils.cpp @@ -54,14 +54,17 @@ void SplitString(const UString &srcString, UStringVector &destStrings) destStrings.Add(s); } +/* UString JoinStrings(const UStringVector &srcStrings) { + UString s; FOR_VECTOR (i, srcStrings) { if (i != 0) - s += L' '; + s.Add_Space(); s += srcStrings[i]; } return s; } +*/ diff --git a/CPP/7zip/UI/FileManager/SystemPage.cpp b/CPP/7zip/UI/FileManager/SystemPage.cpp index a40c4e3d..a7f0c3fb 100644 --- a/CPP/7zip/UI/FileManager/SystemPage.cpp +++ b/CPP/7zip/UI/FileManager/SystemPage.cpp @@ -3,6 +3,7 @@ #include "StdAfx.h" #include "../../../Common/StringConvert.h" +#include "../../../Common/Defs.h" #include "../../../Windows/DLL.h" #include "../../../Windows/ErrorMsg.h" @@ -16,6 +17,10 @@ using namespace NWindows; +#ifndef _UNICODE +extern bool g_IsNT; +#endif + static const UInt32 kLangIDs[] = { IDT_SYSTEM_ASSOCIATE @@ -48,8 +53,8 @@ int CSystemPage::AddIcon(const UString &iconPath, int iconIndex) // we expand path from REG_EXPAND_SZ registry item. UString path; DWORD size = MAX_PATH + 10; - DWORD needLen = ::ExpandEnvironmentStringsW(iconPath, path.GetBuffer((int)size + 1), size); - path.ReleaseBuffer(); + DWORD needLen = ::ExpandEnvironmentStringsW(iconPath, path.GetBuf(size + 2), size); + path.ReleaseBuf_CalcLen(size); if (needLen == 0 || needLen >= size) path = iconPath; int num = ExtractIconExW(path, iconIndex, NULL, &hicon, 1); @@ -140,32 +145,49 @@ bool CSystemPage::OnInit() _listView.InsertColumn(0, LangString(IDS_PROP_FILE_TYPE), 72); - CSysString s; + UString s; #if NUM_EXT_GROUPS == 1 - s = TEXT("Program"); + s.SetFromAscii("Program"); #else #ifndef UNDER_CE - DWORD size = 256; - BOOL res = GetUserName(s.GetBuffer(size), &size); - s.ReleaseBuffer(); + const unsigned kSize = 256; + BOOL res; + + DWORD size = kSize; + #ifndef _UNICODE + if (!g_IsNT) + { + AString s2; + res = GetUserNameA(s2.GetBuf(size), &size); + s2.ReleaseBuf_CalcLen(MyMin((unsigned)size, kSize)); + s = GetUnicodeString(s2); + } + else + #endif + { + res = GetUserNameW(s.GetBuf(size), &size); + s.ReleaseBuf_CalcLen(MyMin((unsigned)size, kSize)); + } + if (!res) #endif - s = TEXT("Current User"); + s.SetFromAscii("Current User"); #endif - LVCOLUMN ci; + LV_COLUMNW ci; ci.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM; - ci.cx = 100; - ci.pszText = (TCHAR *)(const TCHAR *)s; - ci.iSubItem = 1; + ci.cx = 128; ci.fmt = LVCFMT_CENTER; + ci.pszText = (WCHAR *)(const WCHAR *)s; + ci.iSubItem = 1; _listView.InsertColumn(1, &ci); #if NUM_EXT_GROUPS > 1 { + LangString(IDS_SYSTEM_ALL_USERS, s); + ci.pszText = (WCHAR *)(const WCHAR *)s; ci.iSubItem = 2; - ci.pszText = (LPTSTR)TEXT("All Users"); _listView.InsertColumn(2, &ci); } #endif diff --git a/CPP/7zip/UI/FileManager/SystemPage.h b/CPP/7zip/UI/FileManager/SystemPage.h index 0bf6aae7..d38bd1b0 100644 --- a/CPP/7zip/UI/FileManager/SystemPage.h +++ b/CPP/7zip/UI/FileManager/SystemPage.h @@ -40,7 +40,7 @@ struct CModifiedExtInfo: public NRegistryAssoc::CShellExtInfo Other = true; if (IsIt7Zip()) { - Other7Zip = !iconPath.IsEqualToNoCase(IconPath); + Other7Zip = !iconPath.IsEqualTo_NoCase(IconPath); if (!Other7Zip) { State = kExtState_7Zip; diff --git a/CPP/7zip/UI/FileManager/SystemPage.rc b/CPP/7zip/UI/FileManager/SystemPage.rc index 42e72cf1..3bb143a4 100644 --- a/CPP/7zip/UI/FileManager/SystemPage.rc +++ b/CPP/7zip/UI/FileManager/SystemPage.rc @@ -1,18 +1,18 @@ #include "SystemPageRes.h" #include "../../GuiCommon.rc" -#define xc 200 -#define yc 250 +#define xc 240 +#define yc 252 IDD_SYSTEM DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT CAPTION "System" BEGIN LTEXT "Associate 7-Zip with:", IDT_SYSTEM_ASSOCIATE, m, m, xc, 8 - PUSHBUTTON "+", IDB_SYSTEM_CURRENT, 72, m + 12, 40, bys - PUSHBUTTON "+", IDB_SYSTEM_ALL, 140, m + 12, 40, bys + PUSHBUTTON "+", IDB_SYSTEM_CURRENT, 80, m + 12, 40, bys + PUSHBUTTON "+", IDB_SYSTEM_ALL, 166, m + 12, 40, bys CONTROL "List1", IDL_SYSTEM_ASSOCIATE, "SysListView32", LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, - m, m + 32, xc, (yc - m - 32 - 1) + m, m + 32, xc, (yc - 32) END #ifdef UNDER_CE @@ -32,7 +32,12 @@ BEGIN PUSHBUTTON "+", IDB_SYSTEM_CURRENT, 60, m + 12, 40, bys CONTROL "List1", IDL_SYSTEM_ASSOCIATE, "SysListView32", LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, - m, m + 32, xc, (yc - m - 32 - 1 - 8) + m, m + 32, xc, (yc - 32) END #endif + +STRINGTABLE +BEGIN + IDS_SYSTEM_ALL_USERS "All users" +END diff --git a/CPP/7zip/UI/FileManager/SystemPageRes.h b/CPP/7zip/UI/FileManager/SystemPageRes.h index edc576f7..c8944482 100644 --- a/CPP/7zip/UI/FileManager/SystemPageRes.h +++ b/CPP/7zip/UI/FileManager/SystemPageRes.h @@ -2,6 +2,7 @@ #define IDD_SYSTEM_2 12200 #define IDT_SYSTEM_ASSOCIATE 2201 +#define IDS_SYSTEM_ALL_USERS 2202 #define IDL_SYSTEM_ASSOCIATE 100 #define IDB_SYSTEM_CURRENT 101 diff --git a/CPP/7zip/UI/FileManager/TextPairs.cpp b/CPP/7zip/UI/FileManager/TextPairs.cpp index 354b479f..0fac2506 100644 --- a/CPP/7zip/UI/FileManager/TextPairs.cpp +++ b/CPP/7zip/UI/FileManager/TextPairs.cpp @@ -185,6 +185,6 @@ void CPairsStorage::SaveToString(UString &text) const text += L' '; text += pair.Value; text += L'\x0D'; - text += L'\n'; + text.Add_LF(); } } diff --git a/CPP/7zip/UI/FileManager/TextPairs.h b/CPP/7zip/UI/FileManager/TextPairs.h index d27cd97c..0a71d044 100644 --- a/CPP/7zip/UI/FileManager/TextPairs.h +++ b/CPP/7zip/UI/FileManager/TextPairs.h @@ -19,7 +19,7 @@ class CPairsStorage int FindID(const UString &id) const; void Sort(); public: - void Clear() { Pairs.Clear(); }; + void Clear() { Pairs.Clear(); } bool ReadFromString(const UString &text); void SaveToString(UString &text) const; diff --git a/CPP/7zip/UI/FileManager/UpdateCallback100.cpp b/CPP/7zip/UI/FileManager/UpdateCallback100.cpp index 4141f01d..67e70fb7 100644 --- a/CPP/7zip/UI/FileManager/UpdateCallback100.cpp +++ b/CPP/7zip/UI/FileManager/UpdateCallback100.cpp @@ -2,15 +2,29 @@ #include "StdAfx.h" -#include "PasswordDialog.h" +#include "../../../Windows/ErrorMsg.h" + +#include "../GUI/resource3.h" + +#include "LangUtils.h" #include "UpdateCallback100.h" -STDMETHODIMP CUpdateCallback100Imp::SetNumFiles(UInt64 numFiles) +STDMETHODIMP CUpdateCallback100Imp::ScanProgress(UInt64 /* numFolders */, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, Int32 /* isDir */) +{ + return ProgressDialog->Sync.ScanProgress(numFiles, totalSize, us2fs(path)); +} + +STDMETHODIMP CUpdateCallback100Imp::ScanError(const wchar_t *path, HRESULT errorCode) { - ProgressDialog->Sync.Set_NumFilesTotal(numFiles); + ProgressDialog->Sync.AddError_Code_Name(errorCode, path); return S_OK; } +STDMETHODIMP CUpdateCallback100Imp::SetNumFiles(UInt64 numFiles) +{ + return ProgressDialog->Sync.Set_NumFilesTotal(numFiles); +} + STDMETHODIMP CUpdateCallback100Imp::SetTotal(UInt64 size) { ProgressDialog->Sync.Set_NumBytesTotal(size); @@ -30,35 +44,63 @@ STDMETHODIMP CUpdateCallback100Imp::SetRatioInfo(const UInt64 *inSize, const UIn STDMETHODIMP CUpdateCallback100Imp::CompressOperation(const wchar_t *name) { - ProgressDialog->Sync.Set_FilePath(name); - return S_OK; + return SetOperation_Base(NUpdateNotifyOp::kAdd, name, false); } STDMETHODIMP CUpdateCallback100Imp::DeleteOperation(const wchar_t *name) { - ProgressDialog->Sync.Set_FilePath(name); - return S_OK; + return SetOperation_Base(NUpdateNotifyOp::kDelete, name, false); } STDMETHODIMP CUpdateCallback100Imp::OperationResult(Int32 /* operationResult */) { - ProgressDialog->Sync.Set_NumFilesCur(++_numFiles); + ProgressDialog->Sync.Set_NumFilesCur(++NumFiles); + return S_OK; +} + +void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s); + +HRESULT CUpdateCallback100Imp::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) +{ + if (opRes != NArchive::NExtract::NOperationResult::kOK) + { + UString s; + SetExtractErrorMessage(opRes, isEncrypted, name, s); + ProgressDialog->Sync.AddError_Message(s); + } return S_OK; } +HRESULT CUpdateCallback100Imp::ReportUpdateOperation(UInt32 notifyOp, const wchar_t *name, Int32 isDir) +{ + return SetOperation_Base(notifyOp, name, IntToBool(isDir)); +} + STDMETHODIMP CUpdateCallback100Imp::UpdateErrorMessage(const wchar_t *message) { ProgressDialog->Sync.AddError_Message(message); return S_OK; } +HRESULT CUpdateCallback100Imp::OpenFileError(const wchar_t *path, HRESULT errorCode) +{ + ProgressDialog->Sync.AddError_Code_Name(errorCode, path); + return S_OK; +} + +STDMETHODIMP CUpdateCallback100Imp::ReadingFileError(const wchar_t *path, HRESULT errorCode) +{ + ProgressDialog->Sync.AddError_Code_Name(errorCode, path); + return S_OK; +} + STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { *password = NULL; - *passwordIsDefined = BoolToInt(_passwordIsDefined); - if (!_passwordIsDefined) + *passwordIsDefined = BoolToInt(PasswordIsDefined); + if (!PasswordIsDefined) return S_OK; - return StringToBstr(_password, password); + return StringToBstr(Password, password); } STDMETHODIMP CUpdateCallback100Imp::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */) @@ -74,14 +116,9 @@ STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UInt64 * /* files */, con STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password) { *password = NULL; - if (!_passwordIsDefined) + if (!PasswordIsDefined) { - CPasswordDialog dialog; - ProgressDialog->WaitCreating(); - if (dialog.Create(*ProgressDialog) != IDOK) - return E_ABORT; - _password = dialog.Password; - _passwordIsDefined = true; + RINOK(ShowAskPasswordDialog()) } - return StringToBstr(_password, password); + return StringToBstr(Password, password); } diff --git a/CPP/7zip/UI/FileManager/UpdateCallback100.h b/CPP/7zip/UI/FileManager/UpdateCallback100.h index 944453a1..7cbc11e3 100644 --- a/CPP/7zip/UI/FileManager/UpdateCallback100.h +++ b/CPP/7zip/UI/FileManager/UpdateCallback100.h @@ -9,26 +9,29 @@ #include "../Agent/IFolderArchive.h" +#include "../GUI/UpdateCallbackGUI2.h" + #include "ProgressDialog2.h" class CUpdateCallback100Imp: public IFolderArchiveUpdateCallback, + public IFolderArchiveUpdateCallback2, + public IFolderScanProgress, public ICryptoGetTextPassword2, public ICryptoGetTextPassword, public IArchiveOpenCallback, public ICompressProgressInfo, + public CUpdateCallbackGUI2, public CMyUnknownImp { - bool _passwordIsDefined; - UString _password; - UInt64 _numFiles; public: - CProgressDialog *ProgressDialog; - CUpdateCallback100Imp(): ProgressDialog(0) {} + // CUpdateCallback100Imp() {} - MY_UNKNOWN_IMP5( + MY_UNKNOWN_IMP7( IFolderArchiveUpdateCallback, + IFolderArchiveUpdateCallback2, + IFolderScanProgress, ICryptoGetTextPassword2, ICryptoGetTextPassword, IArchiveOpenCallback, @@ -37,18 +40,13 @@ public: INTERFACE_IProgress(;) INTERFACE_IArchiveOpenCallback(;) INTERFACE_IFolderArchiveUpdateCallback(;) + INTERFACE_IFolderArchiveUpdateCallback2(;) + INTERFACE_IFolderScanProgress(;) STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); STDMETHOD(CryptoGetTextPassword)(BSTR *password); STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); - - void Init(bool passwordIsDefined, const UString &password) - { - _passwordIsDefined = passwordIsDefined; - _password = password; - _numFiles = 0; - } }; #endif diff --git a/CPP/7zip/UI/FileManager/ViewSettings.cpp b/CPP/7zip/UI/FileManager/ViewSettings.cpp index 9688a4a5..2818d0f3 100644 --- a/CPP/7zip/UI/FileManager/ViewSettings.cpp +++ b/CPP/7zip/UI/FileManager/ViewSettings.cpp @@ -302,7 +302,7 @@ void ReadCopyHistory(UStringVector &folders) void AddUniqueStringToHeadOfList(UStringVector &list, const UString &s) { for (unsigned i = 0; i < list.Size();) - if (s.IsEqualToNoCase(list[i])) + if (s.IsEqualTo_NoCase(list[i])) list.Delete(i); else i++; diff --git a/CPP/7zip/UI/FileManager/makefile b/CPP/7zip/UI/FileManager/makefile index 96ae902f..d9e81780 100644 --- a/CPP/7zip/UI/FileManager/makefile +++ b/CPP/7zip/UI/FileManager/makefile @@ -97,6 +97,7 @@ EXPLORER_OBJS = \ GUI_OBJS = \ $O\HashGUI.obj \ + $O\UpdateCallbackGUI2.obj \ COMPRESS_OBJS = \ $O\CopyCoder.obj \ diff --git a/CPP/7zip/UI/FileManager/resource.h b/CPP/7zip/UI/FileManager/resource.h index 55af3555..23e64edc 100644 --- a/CPP/7zip/UI/FileManager/resource.h +++ b/CPP/7zip/UI/FileManager/resource.h @@ -45,6 +45,7 @@ #define IDM_CREATE_FILE 556 // #define IDM_EXIT 557 #define IDM_LINK 558 +#define IDM_ALT_STREAMS 559 #define IDM_SELECT_ALL 600 #define IDM_DESELECT_ALL 601 diff --git a/CPP/7zip/UI/FileManager/resource.rc b/CPP/7zip/UI/FileManager/resource.rc index 61cf33e8..fb57e4f0 100644 --- a/CPP/7zip/UI/FileManager/resource.rc +++ b/CPP/7zip/UI/FileManager/resource.rc @@ -48,6 +48,7 @@ BEGIN MENUITEM "Create File\tCtrl+N", IDM_CREATE_FILE MENUITEM SEPARATOR MENUITEM "&Link...", IDM_LINK + MENUITEM "&Alternate streams", IDM_ALT_STREAMS MENUITEM SEPARATOR MENUITEM "E&xit\tAlt+F4", IDCLOSE END @@ -252,5 +253,6 @@ END #include "SplitDialog.rc" #include "SystemPage.rc" #include "../GUI/Extract.rc" +#include "../GUI/resource3.rc" #include "../Explorer/resource2.rc" #include "resourceGui.rc" diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp index 1f4bcab5..2f118846 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../../C/CpuArch.h" + #include "../../../Common/Defs.h" #include "../../../Common/IntToString.h" #include "../../../Common/MyException.h" @@ -15,10 +17,14 @@ #include "../FileManager/HelpUtils.h" +#include "../../MyVersion.h" + #include "BenchmarkDialog.h" using namespace NWindows; +void GetCpuName(AString &s); + static LPCWSTR kHelpTopic = L"fm/benchmark.htm"; static const UINT_PTR kTimerID = 4; @@ -72,7 +78,7 @@ static const int kMinDicLogSize = 21; #endif static const UInt32 kMinDicSize = (1 << kMinDicLogSize); static const UInt32 kMaxDicSize = - #ifdef _WIN64 + #ifdef MY_CPU_64BIT (1 << 30); #else (1 << 27); @@ -111,6 +117,34 @@ bool CBenchmarkDialog::OnInit() _consoleEdit.SendMessage(WM_SETFONT, (WPARAM)_font._font, TRUE); } + { + TCHAR s[40]; + s[0] = '/'; + s[1] = ' '; + ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2); + SetItemText(IDT_BENCH_HARDWARE_THREADS, s); + } + + { + UString s; + { + AString cpuName; + GetCpuName(cpuName); + s.SetFromAscii(cpuName); + SetItemText(IDT_BENCH_CPU, s); + } + + s.SetFromAscii("7-Zip " MY_VERSION " [" + #ifdef MY_CPU_64BIT + "64-bit" + #elif defined MY_CPU_32BIT + "32-bit" + #endif + "]"); + SetItemText(IDT_BENCH_VER, s); + } + + UInt32 numCPUs = NSystem::GetNumberOfProcessors(); if (numCPUs < 1) numCPUs = 1; @@ -270,9 +304,7 @@ void CBenchmarkDialog::OnChangeSettings() { EnableItem(IDB_STOP, true); UInt32 dictionary = OnChangeDictionary(); - TCHAR s[40] = { TEXT('/'), TEXT(' '), 0 }; - ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2); - SetItemText(IDT_BENCH_HARDWARE_THREADS, s); + for (int i = 0; i < ARRAY_SIZE(g_IDs); i++) SetItemText(g_IDs[i], kProcessingString); _startTime = GetTickCount(); @@ -394,6 +426,14 @@ bool CBenchmarkDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */) ConvertUInt64ToString(Sync.NumPasses, s); SetItemText(IDT_BENCH_PASSES_VAL, s); + /* + if (Sync.FreqWasChanged) + { + SetItemText(IDT_BENCH_FREQ, Sync.Freq); + Sync.FreqWasChanged = false; + } + */ + { UInt32 dicSizeTemp = (UInt32)MyMax(Sync.ProcessedSize, UInt64(1) << 20); dicSizeTemp = MyMin(dicSizeTemp, Sync.DictionarySize), @@ -498,11 +538,26 @@ struct CBenchCallback: public IBenchCallback UInt32 dictionarySize; CProgressSyncInfo *Sync; + // void AddCpuFreq(UInt64 cpuFreq); HRESULT SetFreq(bool showFreq, UInt64 cpuFreq); HRESULT SetEncodeResult(const CBenchInfo &info, bool final); HRESULT SetDecodeResult(const CBenchInfo &info, bool final); }; +/* +void CBenchCallback::AddCpuFreq(UInt64 cpuFreq) +{ + NSynchronization::CCriticalSectionLock lock(Sync->CS); + { + wchar_t s[32]; + ConvertUInt64ToString(cpuFreq, s); + Sync->Freq.Add_Space_if_NotEmpty(); + Sync->Freq += s; + Sync->FreqWasChanged = true; + } +} +*/ + HRESULT CBenchCallback::SetFreq(bool /* showFreq */, UInt64 /* cpuFreq */) { return S_OK; @@ -605,6 +660,7 @@ HRESULT CThreadBenchmark::Process() CBenchCallback2 callback2; callback2.Sync = &sync; HRESULT result; + try { CObjectVector<CProperty> props; @@ -624,11 +680,11 @@ HRESULT CThreadBenchmark::Process() } { CProperty prop; - prop.Name = L"d"; + prop.Name = L'd'; wchar_t s[16]; ConvertUInt32ToString(dictionarySize, s); prop.Name += s; - prop.Name += 'b'; + prop.Name += L'b'; props.Add(prop); } } @@ -724,7 +780,7 @@ HRESULT Benchmark( const CProperty &prop = props[i]; UString name = prop.Name; name.MakeLower_Ascii(); - if (name.IsEqualToNoCase(L"m") && prop.Value == L"*") + if (name.IsEqualTo_Ascii_NoCase("m") && prop.Value == L"*") { bd.TotalMode = true; continue; diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.h b/CPP/7zip/UI/GUI/BenchmarkDialog.h index 82531117..a5f0292a 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.h +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.h @@ -51,11 +51,15 @@ public: AString Text; bool TextWasChanged; + // UString Freq; + // bool FreqWasChanged; + CProgressSyncInfo() { if (_startEvent.Create() != S_OK) throw 3986437; } + void Init() { Changed = false; @@ -70,9 +74,13 @@ public: NumPasses = 0; + // Freq.SetFromAscii("MHz: "); + // FreqWasChanged = true; + Text.Empty(); TextWasChanged = true; } + void Stop() { NWindows::NSynchronization::CCriticalSectionLock lock(CS); diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.rc b/CPP/7zip/UI/GUI/BenchmarkDialog.rc index a31d2f25..cae9097b 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.rc +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.rc @@ -2,7 +2,7 @@ #include "../../GuiCommon.rc" #define xc 332 -#define yc 228 +#define yc 248 #undef g0xs #undef g1x @@ -42,10 +42,13 @@ #define g3x (m + g2xs) #undef GROUP_Y_SIZE +#undef GROUP_Y2_SIZE #ifdef UNDER_CE #define GROUP_Y_SIZE 8 +#define GROUP_Y2_SIZE 8 #else #define GROUP_Y_SIZE 40 +#define GROUP_Y2_SIZE 32 #endif IDD_BENCH DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE | WS_MINIMIZEBOX @@ -101,11 +104,14 @@ BEGIN RTEXT "", IDT_BENCH_DECOMPR_RPU2, xRpu, 136, sRpu, 8 RTEXT "", IDT_BENCH_DECOMPR_RATING2, xRating, 136, sRating, 8 - GROUPBOX "Total Rating", IDG_BENCH_TOTAL_RATING, xTotalRating, 163, sTotalRating, GROUP_Y_SIZE + GROUPBOX "Total Rating", IDG_BENCH_TOTAL_RATING, xTotalRating, 163, sTotalRating, GROUP_Y2_SIZE - RTEXT "", IDT_BENCH_TOTAL_USAGE_VAL, xUsage, 181, sUsage, 8 - RTEXT "", IDT_BENCH_TOTAL_RPU_VAL, xRpu, 181, sRpu, 8 - RTEXT "", IDT_BENCH_TOTAL_RATING_VAL, xRating, 181, sRating, 8 + RTEXT "", IDT_BENCH_TOTAL_USAGE_VAL, xUsage, 176, sUsage, 8 + RTEXT "", IDT_BENCH_TOTAL_RPU_VAL, xRpu, 176, sRpu, 8 + RTEXT "", IDT_BENCH_TOTAL_RATING_VAL, xRating, 176, sRating, 8 + + RTEXT "", IDT_BENCH_CPU, m, 202, xc, 8 + RTEXT "", IDT_BENCH_VER, m, 216, xc, 8 LTEXT "Elapsed time:", IDT_BENCH_ELAPSED, m, 163, g2xs, 8 LTEXT "Size:", IDT_BENCH_SIZE, m, 176, g2xs, 8 diff --git a/CPP/7zip/UI/GUI/BenchmarkDialogRes.h b/CPP/7zip/UI/GUI/BenchmarkDialogRes.h index 7dd6d031..a632d764 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialogRes.h +++ b/CPP/7zip/UI/GUI/BenchmarkDialogRes.h @@ -9,6 +9,9 @@ #define IDC_BENCH_NUM_THREADS 103 #define IDT_BENCH_HARDWARE_THREADS 104 +#define IDT_BENCH_VER 105 +#define IDT_BENCH_CPU 106 + #define IDT_BENCH_COMPRESS_SPEED1 110 #define IDT_BENCH_COMPRESS_SPEED2 111 #define IDT_BENCH_COMPRESS_RATING1 112 diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp index a2d0ac2b..23b6f52f 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.cpp +++ b/CPP/7zip/UI/GUI/CompressDialog.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../../C/CpuArch.h" + #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" @@ -76,7 +78,7 @@ using namespace NFile; using namespace NName; using namespace NDir; -static const int kHistorySize = 20; +static const unsigned kHistorySize = 20; static LPCWSTR kExeExt = L".exe"; static LPCWSTR k7zFormat = L"7z"; @@ -170,7 +172,7 @@ struct CFormatInfo LPCWSTR Name; UInt32 LevelsMask; const EMethodID *MathodIDs; - int NumMethods; + unsigned NumMethods; bool Filter; bool Solid; bool MultiThread; @@ -372,7 +374,7 @@ bool CCompressDialog::OnInit() m_Format.SetCurSel(index); continue; } - if (i == 0 || ai.Name.IsEqualToNoCase(m_RegistryInfo.ArcType)) + if (i == 0 || ai.Name.IsEqualTo_NoCase(m_RegistryInfo.ArcType)) { m_Format.SetCurSel(index); Info.FormatIndex = arcIndex; @@ -455,7 +457,7 @@ void CCompressDialog::UpdatePasswordControl() bool CCompressDialog::OnButtonClicked(int buttonID, HWND buttonHWND) { - switch(buttonID) + switch (buttonID) { case IDB_COMPRESS_SET_ARCHIVE: { @@ -554,9 +556,8 @@ bool CCompressDialog::IsSFX() static int GetExtDotPos(const UString &s) { - int dotPos = s.ReverseFind('.'); - int slashPos = MyMax(s.ReverseFind(WCHAR_PATH_SEPARATOR), s.ReverseFind('/')); - if (dotPos >= 0 && dotPos > slashPos + 1) + int dotPos = s.ReverseFind_Dot(); + if (dotPos > s.ReverseFind_PathSepar() + 1) return dotPos; return -1; } @@ -578,7 +579,7 @@ void CCompressDialog::OnButtonSFX() if (dotPos >= 0) { UString ext = fileName.Ptr(dotPos); - if (ext.IsEqualToNoCase(kExeExt)) + if (ext.IsEqualTo_NoCase(kExeExt)) { fileName.DeleteFrom(dotPos); m_ArchivePath.SetText(fileName); @@ -690,8 +691,7 @@ void CCompressDialog::OnOK() return; } UString method = GetEncryptionMethodSpec(); - method.MakeLower_Ascii(); - if (method.Find(L"aes") == 0) + if (method.IsPrefixedBy_Ascii_NoCase("aes")) { if (Info.Password.Len() > 99) { @@ -820,7 +820,7 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam) { if (code == CBN_SELCHANGE) { - switch(itemID) + switch (itemID) { case IDC_COMPRESS_ARCHIVE: { @@ -914,7 +914,7 @@ void CCompressDialog::SetArchiveName2(bool prevWasSFX) if (prevWasSFX) prevExtension = kExeExt; else - prevExtension = UString('.') + prevArchiverInfo.GetMainExt(); + prevExtension = UString(L'.') + prevArchiverInfo.GetMainExt(); const unsigned prevExtensionLen = prevExtension.Len(); if (fileName.Len() >= prevExtensionLen) if (StringsAreEqualNoCase(fileName.RightPtr(prevExtensionLen), prevExtension)) @@ -962,7 +962,7 @@ int CCompressDialog::FindRegistryFormat(const UString &name) FOR_VECTOR (i, m_RegistryInfo.Formats) { const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[i]; - if (name.IsEqualToNoCase(GetUnicodeString(fo.FormatID))) + if (name.IsEqualTo_NoCase(GetUnicodeString(fo.FormatID))) return i; } return -1; @@ -984,7 +984,7 @@ int CCompressDialog::GetStaticFormatIndex() { const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; for (unsigned i = 0; i < ARRAY_SIZE(g_Formats); i++) - if (ai.Name.IsEqualToNoCase(g_Formats[i].Name)) + if (ai.Name.IsEqualTo_NoCase(g_Formats[i].Name)) return i; return 0; // -1; } @@ -1016,8 +1016,8 @@ void CCompressDialog::SetLevel() else level = 9; } - int i; - for (i = 0; i <= 9; i++) + + for (unsigned i = 0; i <= 9; i++) { if ((fi.LevelsMask & (1 << i)) != 0) { @@ -1051,7 +1051,8 @@ void CCompressDialog::SetMethod(int keepMethodId) } bool isSfx = IsSFX(); bool weUseSameMethod = false; - for (int m = 0; m < fi.NumMethods; m++) + + for (unsigned m = 0; m < fi.NumMethods; m++) { EMethodID methodID = fi.MathodIDs[m]; if (isSfx) @@ -1066,9 +1067,10 @@ void CCompressDialog::SetMethod(int keepMethodId) weUseSameMethod = true; continue; } - if ((defaultMethod.IsEqualToNoCase(method) || m == 0) && !weUseSameMethod) + if ((defaultMethod.IsEqualTo_NoCase(method) || m == 0) && !weUseSameMethod) m_Method.SetCurSel(itemIndex); } + if (!weUseSameMethod) { SetDictionary(); @@ -1079,19 +1081,19 @@ void CCompressDialog::SetMethod(int keepMethodId) bool CCompressDialog::IsZipFormat() { const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; - return ai.Name.IsEqualToNoCase(L"zip"); + return ai.Name.IsEqualTo_Ascii_NoCase("zip"); } void CCompressDialog::SetEncryptionMethod() { _encryptionMethod.ResetContent(); const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; - if (ai.Name.IsEqualToNoCase(L"7z")) + if (ai.Name.IsEqualTo_Ascii_NoCase("7z")) { _encryptionMethod.AddString(TEXT("AES-256")); _encryptionMethod.SetCurSel(0); } - else if (ai.Name.IsEqualToNoCase(L"zip")) + else if (ai.Name.IsEqualTo_Ascii_NoCase("zip")) { int index = FindRegistryFormat(ai.Name); UString encryptionMethod; @@ -1102,7 +1104,7 @@ void CCompressDialog::SetEncryptionMethod() } _encryptionMethod.AddString(TEXT("ZipCrypto")); _encryptionMethod.AddString(TEXT("AES-256")); - _encryptionMethod.SetCurSel(encryptionMethod.Find(L"AES") == 0 ? 1 : 0); + _encryptionMethod.SetCurSel(encryptionMethod.IsPrefixedBy_Ascii_NoCase("aes") ? 1 : 0); } } @@ -1155,138 +1157,149 @@ void CCompressDialog::SetDictionary() m_Dictionary.ResetContent(); const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; int index = FindRegistryFormat(ai.Name); - UInt32 defaultDictionary = (UInt32)(Int32)-1; + UInt32 defaultDict = (UInt32)(Int32)-1; + if (index >= 0) { const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - if (fo.Method.IsEqualToNoCase(GetMethodSpec())) - defaultDictionary = fo.Dictionary; + if (fo.Method.IsEqualTo_NoCase(GetMethodSpec())) + defaultDict = fo.Dictionary; } + int methodID = GetMethodID(); UInt32 level = GetLevel2(); if (methodID < 0) return; const UInt64 maxRamSize = GetMaxRamSizeForProgram(); + switch (methodID) { case kLZMA: case kLZMA2: { static const UInt32 kMinDicSize = (1 << 16); - if (defaultDictionary == (UInt32)(Int32)-1) + if (defaultDict == (UInt32)(Int32)-1) { - if (level >= 9) defaultDictionary = (1 << 26); - else if (level >= 7) defaultDictionary = (1 << 25); - else if (level >= 5) defaultDictionary = (1 << 24); - else if (level >= 3) defaultDictionary = (1 << 20); - else defaultDictionary = (kMinDicSize); + if (level >= 9) defaultDict = (1 << 26); + else if (level >= 7) defaultDict = (1 << 25); + else if (level >= 5) defaultDict = (1 << 24); + else if (level >= 3) defaultDict = (1 << 20); + else defaultDict = (kMinDicSize); } - int i; + AddDictionarySize(kMinDicSize); m_Dictionary.SetCurSel(0); - for (i = 20; i <= 30; i++) - for (int j = 0; j < 2; j++) + + for (unsigned i = 20; i <= 31; i++) + for (unsigned j = 0; j < 2; j++) { if (i == 20 && j > 0) continue; - UInt32 dictionary = (1 << i) + (j << (i - 1)); - if (dictionary > - #ifdef _WIN64 - (1 << 30) + UInt32 dict = ((UInt32)(2 + j) << (i - 1)); + if (dict > + #ifdef MY_CPU_64BIT + (3 << 29) #else (1 << 26) #endif ) continue; - AddDictionarySize(dictionary); + AddDictionarySize(dict); UInt64 decomprSize; - UInt64 requiredComprSize = GetMemoryUsage(dictionary, decomprSize); - if (dictionary <= defaultDictionary && requiredComprSize <= maxRamSize) + UInt64 requiredComprSize = GetMemoryUsage(dict, decomprSize); + if (dict <= defaultDict && requiredComprSize <= maxRamSize) m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1); } - // SetNearestSelectComboBox(m_Dictionary, defaultDictionary); + // SetNearestSelectComboBox(m_Dictionary, defaultDict); break; } + case kPPMd: { - if (defaultDictionary == (UInt32)(Int32)-1) + if (defaultDict == (UInt32)(Int32)-1) { - if (level >= 9) defaultDictionary = (192 << 20); - else if (level >= 7) defaultDictionary = ( 64 << 20); - else if (level >= 5) defaultDictionary = ( 16 << 20); - else defaultDictionary = ( 4 << 20); + if (level >= 9) defaultDict = (192 << 20); + else if (level >= 7) defaultDict = ( 64 << 20); + else if (level >= 5) defaultDict = ( 16 << 20); + else defaultDict = ( 4 << 20); } - int i; - for (i = 20; i < 31; i++) - for (int j = 0; j < 2; j++) + + for (unsigned i = 20; i < 31; i++) + for (unsigned j = 0; j < 2; j++) { if (i == 20 && j > 0) continue; - UInt32 dictionary = (1 << i) + (j << (i - 1)); - if (dictionary > - #ifdef _WIN64 + UInt32 dict = ((UInt32)(2 + j) << (i - 1)); + if (dict > + #ifdef MY_CPU_64BIT (1 << 30) #else (1 << 29) #endif ) continue; - AddDictionarySize(dictionary); + AddDictionarySize(dict); UInt64 decomprSize; - UInt64 requiredComprSize = GetMemoryUsage(dictionary, decomprSize); - if (dictionary <= defaultDictionary && requiredComprSize <= maxRamSize || m_Dictionary.GetCount() == 0) + UInt64 requiredComprSize = GetMemoryUsage(dict, decomprSize); + if (dict <= defaultDict && requiredComprSize <= maxRamSize || m_Dictionary.GetCount() == 0) m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1); } - SetNearestSelectComboBox(m_Dictionary, defaultDictionary); + + SetNearestSelectComboBox(m_Dictionary, defaultDict); break; } + case kDeflate: { AddDictionarySize(32 << 10); m_Dictionary.SetCurSel(0); break; } + case kDeflate64: { AddDictionarySize(64 << 10); m_Dictionary.SetCurSel(0); break; } + case kBZip2: { - if (defaultDictionary == (UInt32)(Int32)-1) + if (defaultDict == (UInt32)(Int32)-1) { - if (level >= 5) - defaultDictionary = (900 << 10); - else if (level >= 3) - defaultDictionary = (500 << 10); - else - defaultDictionary = (100 << 10); + if (level >= 5) defaultDict = (900 << 10); + else if (level >= 3) defaultDict = (500 << 10); + else defaultDict = (100 << 10); } - for (int i = 1; i <= 9; i++) + + for (unsigned i = 1; i <= 9; i++) { - UInt32 dictionary = (i * 100) << 10; - AddDictionarySize(dictionary); - if (dictionary <= defaultDictionary || m_Dictionary.GetCount() == 0) + UInt32 dict = ((UInt32)i * 100) << 10; + AddDictionarySize(dict); + if (dict <= defaultDict || m_Dictionary.GetCount() == 0) m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1); } + break; } + case kPPMdZip: { - if (defaultDictionary == (UInt32)(Int32)-1) - defaultDictionary = (1 << (19 + (level > 8 ? 8 : level))); - for (int i = 20; i <= 28; i++) + if (defaultDict == (UInt32)(Int32)-1) + defaultDict = (1 << (19 + (level > 8 ? 8 : level))); + + for (unsigned i = 20; i <= 28; i++) { - UInt32 dictionary = (1 << i); - AddDictionarySize(dictionary); + UInt32 dict = (1 << i); + AddDictionarySize(dict); UInt64 decomprSize; - UInt64 requiredComprSize = GetMemoryUsage(dictionary, decomprSize); - if (dictionary <= defaultDictionary && requiredComprSize <= maxRamSize || m_Dictionary.GetCount() == 0) + UInt64 requiredComprSize = GetMemoryUsage(dict, decomprSize); + if (dict <= defaultDict && requiredComprSize <= maxRamSize || m_Dictionary.GetCount() == 0) m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1); } - SetNearestSelectComboBox(m_Dictionary, defaultDictionary); + + SetNearestSelectComboBox(m_Dictionary, defaultDict); break; } } @@ -1322,16 +1335,19 @@ void CCompressDialog::SetOrder() const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; int index = FindRegistryFormat(ai.Name); UInt32 defaultOrder = (UInt32)(Int32)-1; + if (index >= 0) { const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - if (fo.Method.IsEqualToNoCase(GetMethodSpec())) + if (fo.Method.IsEqualTo_NoCase(GetMethodSpec())) defaultOrder = fo.Order; } + int methodID = GetMethodID(); UInt32 level = GetLevel2(); if (methodID < 0) return; + switch (methodID) { case kLZMA: @@ -1339,10 +1355,10 @@ void CCompressDialog::SetOrder() { if (defaultOrder == (UInt32)(Int32)-1) defaultOrder = (level >= 7) ? 64 : 32; - for (int i = 3; i <= 8; i++) - for (int j = 0; j < 2; j++) + for (unsigned i = 3; i <= 8; i++) + for (unsigned j = 0; j < 2; j++) { - UInt32 order = (1 << i) + (j << (i - 1)); + UInt32 order = ((UInt32)(2 + j) << (i - 1)); if (order <= 256) AddOrder(order); } @@ -1350,66 +1366,64 @@ void CCompressDialog::SetOrder() SetNearestSelectComboBox(m_Order, defaultOrder); break; } + case kPPMd: { if (defaultOrder == (UInt32)(Int32)-1) { - if (level >= 9) - defaultOrder = 32; - else if (level >= 7) - defaultOrder = 16; - else if (level >= 5) - defaultOrder = 6; - else - defaultOrder = 4; + if (level >= 9) defaultOrder = 32; + else if (level >= 7) defaultOrder = 16; + else if (level >= 5) defaultOrder = 6; + else defaultOrder = 4; } - int i; + AddOrder(2); AddOrder(3); - for (i = 2; i < 8; i++) - for (int j = 0; j < 4; j++) + + for (unsigned i = 2; i < 8; i++) + for (unsigned j = 0; j < 4; j++) { - UInt32 order = (1 << i) + (j << (i - 2)); + UInt32 order = (4 + j) << (i - 2); if (order < 32) AddOrder(order); } + AddOrder(32); SetNearestSelectComboBox(m_Order, defaultOrder); break; } + case kDeflate: case kDeflate64: { if (defaultOrder == (UInt32)(Int32)-1) { - if (level >= 9) - defaultOrder = 128; - else if (level >= 7) - defaultOrder = 64; - else - defaultOrder = 32; + if (level >= 9) defaultOrder = 128; + else if (level >= 7) defaultOrder = 64; + else defaultOrder = 32; } - int i; - for (i = 3; i <= 8; i++) - for (int j = 0; j < 2; j++) + + for (unsigned i = 3; i <= 8; i++) + for (unsigned j = 0; j < 2; j++) { - UInt32 order = (1 << i) + (j << (i - 1)); + UInt32 order = ((UInt32)(2 + j) << (i - 1));; if (order <= 256) AddOrder(order); } + AddOrder(methodID == kDeflate64 ? 257 : 258); SetNearestSelectComboBox(m_Order, defaultOrder); break; } + case kBZip2: - { break; - } + case kPPMdZip: { if (defaultOrder == (UInt32)(Int32)-1) defaultOrder = level + 3; - for (int i = 2; i <= 16; i++) + for (unsigned i = 2; i <= 16; i++) AddOrder(i); SetNearestSelectComboBox(m_Order, defaultOrder); break; @@ -1442,9 +1456,9 @@ void CCompressDialog::SetSolidBlockSize() if (level == 0) return; - UInt32 dictionary = GetDictionarySpec(); - if (dictionary == (UInt32)(Int32)-1) - dictionary = 1; + UInt32 dict = GetDictionarySpec(); + if (dict == (UInt32)(Int32)-1) + dict = 1; UInt32 defaultBlockSize = (UInt32)(Int32)-1; @@ -1453,7 +1467,7 @@ void CCompressDialog::SetSolidBlockSize() if (index >= 0) { const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - if (fo.Method.IsEqualToNoCase(GetMethodSpec())) + if (fo.Method.IsEqualTo_NoCase(GetMethodSpec())) defaultBlockSize = fo.BlockLogSize; } @@ -1461,9 +1475,10 @@ void CCompressDialog::SetSolidBlockSize() m_Solid.SetItemData(index, (UInt32)kNoSolidBlockSize); m_Solid.SetCurSel(0); bool needSet = defaultBlockSize == (UInt32)(Int32)-1; - for (int i = 20; i <= 36; i++) + + for (unsigned i = 20; i <= 36; i++) { - if (needSet && dictionary >= (((UInt64)1 << (i - 7))) && i <= 32) + if (needSet && dict >= (((UInt64)1 << (i - 7))) && i <= 32) defaultBlockSize = i; TCHAR s[40]; ConvertUInt32ToString(1 << (i % 10), s); @@ -1473,6 +1488,7 @@ void CCompressDialog::SetSolidBlockSize() int index = (int)m_Solid.AddString(s); m_Solid.SetItemData(index, (UInt32)i); } + index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_SOLID)); m_Solid.SetItemData(index, kSolidBlockSize); if (defaultBlockSize == (UInt32)(Int32)-1) @@ -1497,7 +1513,7 @@ void CCompressDialog::SetNumThreads() if (index >= 0) { const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - if (fo.Method.IsEqualToNoCase(GetMethodSpec()) && fo.NumThreads != (UInt32)(Int32)-1) + if (fo.Method.IsEqualTo_NoCase(GetMethodSpec()) && fo.NumThreads != (UInt32)(Int32)-1) defaultValue = fo.NumThreads; } @@ -1521,7 +1537,7 @@ void CCompressDialog::SetNumThreads() SetNearestSelectComboBox(m_NumThreads, defaultValue); } -UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemory) +UInt64 CCompressDialog::GetMemoryUsage(UInt32 dict, UInt64 &decompressMemory) { decompressMemory = UInt64(Int64(-1)); UInt32 level = GetLevel2(); @@ -1536,6 +1552,7 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemo if (fi.Filter && level >= 9) size += (12 << 20) * 2 + (5 << 20); UInt32 numThreads = GetNumThreads2(); + if (IsZipFormat()) { UInt32 numSubThreads = 1; @@ -1545,13 +1562,15 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemo if (numMainThreads > 1) size += (UInt64)numMainThreads << 25; } + int methidId = GetMethodID(); + switch (methidId) { case kLZMA: case kLZMA2: { - UInt32 hs = dictionary - 1; + UInt32 hs = dict - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); @@ -1562,9 +1581,9 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemo hs >>= 1; hs++; UInt64 size1 = (UInt64)hs * 4; - size1 += (UInt64)dictionary * 4; + size1 += (UInt64)dict * 4; if (level >= 5) - size1 += (UInt64)dictionary * 4; + size1 += (UInt64)dict * 4; size1 += (2 << 20); UInt32 numThreads1 = 1; @@ -1573,27 +1592,31 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemo size1 += (2 << 20) + (4 << 20); numThreads1 = 2; } + UInt32 numBlockThreads = numThreads / numThreads1; + if (methidId == kLZMA || numBlockThreads == 1) - size1 += (UInt64)dictionary * 3 / 2; + size1 += (UInt64)dict * 3 / 2; else { - UInt64 chunkSize = (UInt64)dictionary << 2; + UInt64 chunkSize = (UInt64)dict << 2; chunkSize = MyMax(chunkSize, (UInt64)(1 << 20)); chunkSize = MyMin(chunkSize, (UInt64)(1 << 28)); - chunkSize = MyMax(chunkSize, (UInt64)dictionary); + chunkSize = MyMax(chunkSize, (UInt64)dict); size1 += chunkSize * 2; } size += size1 * numBlockThreads; - decompressMemory = dictionary + (2 << 20); + decompressMemory = dict + (2 << 20); return size; } + case kPPMd: { - decompressMemory = dictionary + (2 << 20); + decompressMemory = dict + (2 << 20); return size + decompressMemory; } + case kDeflate: case kDeflate64: { @@ -1606,18 +1629,21 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemo decompressMemory = (2 << 20); return size; } + case kBZip2: { decompressMemory = (7 << 20); UInt64 memForOneThread = (10 << 20); return size + memForOneThread * numThreads; } + case kPPMdZip: { - decompressMemory = dictionary + (2 << 20); + decompressMemory = dict + (2 << 20); return size + (UInt64)decompressMemory * numThreads; } } + return (UInt64)(Int64)-1; } diff --git a/CPP/7zip/UI/GUI/CompressDialog.h b/CPP/7zip/UI/GUI/CompressDialog.h index 3463fefc..a7a3a3a7 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.h +++ b/CPP/7zip/UI/GUI/CompressDialog.h @@ -164,7 +164,7 @@ class CCompressDialog: public NWindows::NControl::CModalDialog void SetSolidBlockSize(); void SetNumThreads(); - UInt64 GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemory); + UInt64 GetMemoryUsage(UInt32 dict, UInt64 &decompressMemory); UInt64 GetMemoryUsage(UInt64 &decompressMemory); void PrintMemUsage(UINT res, UInt64 value); void SetMemoryUsage(); diff --git a/CPP/7zip/UI/GUI/CompressDialog.rc b/CPP/7zip/UI/GUI/CompressDialog.rc index 6c555a7e..d6ce5ac0 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.rc +++ b/CPP/7zip/UI/GUI/CompressDialog.rc @@ -80,7 +80,7 @@ BEGIN LTEXT "&Solid Block size:", IDT_COMPRESS_SOLID, m, 146, g0xs, 8 COMBOBOX IDC_COMPRESS_SOLID, g1x, 144, g1xs, 140, MY_COMBO - LTEXT "&Number of CPU threads:", IDT_COMPRESS_THREADS, m, 167, g0xs, 8 + LTEXT "Number of CPU &threads:", IDT_COMPRESS_THREADS, m, 167, g0xs, 8 COMBOBOX IDC_COMPRESS_THREADS, g1x, 165, g1xs - 35, 140, MY_COMBO RTEXT "", IDT_COMPRESS_HARDWARE_THREADS, g1x + g1xs - 35 + 10, 167, 25, 8 @@ -95,7 +95,7 @@ BEGIN LTEXT "Split to &volumes, bytes:", IDT_SPLIT_TO_VOLUMES, m, 225, gSize, 8 COMBOBOX IDC_COMPRESS_VOLUME, m, 237, gSize, 73, MY_COMBO_WITH_EDIT - LTEXT "&Parameters:", IDT_COMPRESS_PARAMETERS, m, 256, gSize, 8 + LTEXT "Parameters:", IDT_COMPRESS_PARAMETERS, m, 256, gSize, 8 EDITTEXT IDE_COMPRESS_PARAMETERS, m, 268, gSize, 14, ES_AUTOHSCROLL @@ -130,7 +130,7 @@ BEGIN GROUPBOX "Encryption", IDG_COMPRESS_ENCRYPTION, g4x, yPsw, g4xs, GROUP_Y_SIZE_ENCRYPT - LTEXT "Enter password:", IDT_PASSWORD_ENTER, g4x2, yPsw + 14, g4xs2, 8 + LTEXT "Enter &password:", IDT_PASSWORD_ENTER, g4x2, yPsw + 14, g4xs2, 8 EDITTEXT IDE_COMPRESS_PASSWORD1, g4x2, yPsw + 26, g4xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL LTEXT "Reenter password:", IDT_PASSWORD_REENTER, g4x2, yPsw + 46, g4xs2, 8 EDITTEXT IDE_COMPRESS_PASSWORD2, g4x2, yPsw + 58, g4xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL @@ -179,7 +179,7 @@ BEGIN LTEXT "Split to &volumes, bytes:", IDT_SPLIT_TO_VOLUMES, m, 60, 32, 8 COMBOBOX IDC_COMPRESS_VOLUME, m + 32, 58, 44, 73, MY_COMBO_WITH_EDIT - LTEXT "&Parameters:", IDT_COMPRESS_PARAMETERS, m + 80, 60, 48, 8 + LTEXT "Parameters:", IDT_COMPRESS_PARAMETERS, m + 80, 60, 48, 8 EDITTEXT IDE_COMPRESS_PARAMETERS, m + 128, 58, 24, 13, ES_AUTOHSCROLL COMBOBOX IDC_COMPRESS_UPDATE_MODE, m, 76, 88, 80, MY_COMBO @@ -187,7 +187,7 @@ BEGIN CONTROL "Compress shared files", IDX_COMPRESS_SHARED, MY_CHECKBOX, m, 94, xc, 10 - LTEXT "Enter password:", IDT_PASSWORD_ENTER, m, 112, 60, 8 + LTEXT "Enter &password:", IDT_PASSWORD_ENTER, m, 112, 60, 8 EDITTEXT IDE_COMPRESS_PASSWORD1, m + 60, 110, 44, 13, ES_PASSWORD | ES_AUTOHSCROLL CONTROL "Show Password", IDX_PASSWORD_SHOW, MY_CHECKBOX, m + 108, 112, 44, 10 diff --git a/CPP/7zip/UI/GUI/Extract.rc b/CPP/7zip/UI/GUI/Extract.rc index defcfcc4..f75b2e6f 100644 --- a/CPP/7zip/UI/GUI/Extract.rc +++ b/CPP/7zip/UI/GUI/Extract.rc @@ -11,8 +11,14 @@ BEGIN IDS_CANT_OPEN_ENCRYPTED_ARCHIVE "Can not open encrypted archive '{0}'. Wrong password?" IDS_UNSUPPORTED_ARCHIVE_TYPE "Unsupported archive type" + IDS_CANT_OPEN_AS_TYPE "Can not open the file as {0} archive" + IDS_IS_OPEN_AS_TYPE "The file is open as {0} archive" + IDS_IS_OPEN_WITH_OFFSET "The archive is open with offset" + IDS_PROGRESS_EXTRACTING "Extracting" + IDS_PROGRESS_SKIPPING "Skipping" + IDS_EXTRACT_SET_FOLDER "Specify a location for extracted files." IDS_EXTRACT_PATHS_FULL "Full pathnames" @@ -32,7 +38,7 @@ BEGIN IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED "Data error in encrypted file '{0}'. Wrong password?" IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED "CRC failed in encrypted file '{0}'. Wrong password?" - IDS_EXTRACT_MSG_WRONG_PSW "Wrong password?" + IDS_EXTRACT_MSG_WRONG_PSW_GUESS "Wrong password?" // IDS_EXTRACT_MSG_ENCRYPTED "Encrypted file" IDS_EXTRACT_MSG_UNSUPPORTED_METHOD "Unsupported compression method" @@ -43,6 +49,7 @@ BEGIN IDS_EXTRACT_MSG_DATA_AFTER_END "There are some data after the end of the payload data" IDS_EXTRACT_MSG_IS_NOT_ARC "Is not archive" IDS_EXTRACT_MSG_HEADERS_ERROR "Headers Error" + IDS_EXTRACT_MSG_WRONG_PSW_CLAIM "Wrong password" IDS_OPEN_MSG_UNAVAILABLE_START "Unavailable start of archive" IDS_OPEN_MSG_UNCONFIRMED_START "Unconfirmed start of archive" diff --git a/CPP/7zip/UI/GUI/ExtractDialog.cpp b/CPP/7zip/UI/GUI/ExtractDialog.cpp index d1ce8255..9a14c6c4 100644 --- a/CPP/7zip/UI/GUI/ExtractDialog.cpp +++ b/CPP/7zip/UI/GUI/ExtractDialog.cpp @@ -143,7 +143,7 @@ bool CExtractDialog::OnInit() GetText(s); if (!ArcPath.IsEmpty()) { - s += L" : "; + s.AddAscii(" : "); s += ArcPath; } SetText(s); @@ -289,7 +289,7 @@ void CExtractDialog::OnButtonSetPath() void AddUniqueString(UStringVector &list, const UString &s) { FOR_VECTOR (i, list) - if (s.IsEqualToNoCase(list[i])) + if (s.IsEqualTo_NoCase(list[i])) return; list.Add(s); } diff --git a/CPP/7zip/UI/GUI/ExtractGUI.cpp b/CPP/7zip/UI/GUI/ExtractGUI.cpp index b5fbeaec..e58f6b2b 100644 --- a/CPP/7zip/UI/GUI/ExtractGUI.cpp +++ b/CPP/7zip/UI/GUI/ExtractGUI.cpp @@ -40,20 +40,20 @@ static const wchar_t *kIncorrectOutDir = L"Incorrect output directory path"; static void AddValuePair(UString &s, UINT resourceID, UInt64 value, bool addColon = true) { - wchar_t sz[32]; - s += LangString(resourceID); + AddLangString(s, resourceID); if (addColon) s += L':'; - s += L' '; + s.Add_Space(); + char sz[32]; ConvertUInt64ToString(value, sz); - s += sz; - s += L'\n'; + s.AddAscii(sz); + s.Add_LF(); } static void AddSizePair(UString &s, UINT resourceID, UInt64 value) { wchar_t sz[32]; - s += LangString(resourceID); + AddLangString(s, resourceID); s += L": "; ConvertUInt64ToString(value, sz); s += MyFormatNew(IDS_FILE_SIZE, sz); @@ -65,7 +65,7 @@ static void AddSizePair(UString &s, UINT resourceID, UInt64 value) s += sz; s += L" MB)"; } - s += L'\n'; + s.Add_LF(); } #endif @@ -122,7 +122,7 @@ HRESULT CThreadExtracting::ProcessVirt() AddSizePair(s, IDS_PROP_SIZE, Stat.UnpackSize); if (Stat.NumAltStreams != 0) { - s += L'\n'; + s.Add_LF(); AddValuePair(s, IDS_PROP_NUM_ALT_STREAMS, Stat.NumAltStreams); AddSizePair(s, IDS_PROP_ALT_STREAMS_SIZE, Stat.AltStreams_UnpackSize); } @@ -130,12 +130,12 @@ HRESULT CThreadExtracting::ProcessVirt() if (HashBundle) { - s += L'\n'; + s.Add_LF(); AddHashBundleRes(s, *HashBundle, UString()); } - s += L'\n'; - s += LangString(IDS_MESSAGE_NO_ERRORS); + s.Add_LF(); + AddLangString(s, IDS_MESSAGE_NO_ERRORS); FinalMessage.OkMessage.Title = Title; FinalMessage.OkMessage.Message = s; @@ -237,7 +237,9 @@ HRESULT ExtractGUI( 0x02000603, #endif options.OutputDir); - MyMessageBox(s2 + UString(L'\n') + s); + s2.Add_LF(); + s2 += s; + MyMessageBox(s2); return E_FAIL; } */ diff --git a/CPP/7zip/UI/GUI/ExtractRes.h b/CPP/7zip/UI/GUI/ExtractRes.h index 48738bbb..634ba6b5 100644 --- a/CPP/7zip/UI/GUI/ExtractRes.h +++ b/CPP/7zip/UI/GUI/ExtractRes.h @@ -6,8 +6,14 @@ #define IDS_CANT_OPEN_ENCRYPTED_ARCHIVE 3006 #define IDS_UNSUPPORTED_ARCHIVE_TYPE 3007 +#define IDS_CANT_OPEN_AS_TYPE 3017 +#define IDS_IS_OPEN_AS_TYPE 3018 +#define IDS_IS_OPEN_WITH_OFFSET 3019 + #define IDS_PROGRESS_EXTRACTING 3300 +#define IDS_PROGRESS_SKIPPING 3325 + #define IDS_EXTRACT_SET_FOLDER 3402 #define IDS_EXTRACT_PATHS_FULL 3411 @@ -27,7 +33,7 @@ #define IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED 3703 #define IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED 3704 -#define IDS_EXTRACT_MSG_WRONG_PSW 3710 +#define IDS_EXTRACT_MSG_WRONG_PSW_GUESS 3710 // #define IDS_EXTRACT_MSG_ENCRYPTED 3711 #define IDS_EXTRACT_MSG_UNSUPPORTED_METHOD 3721 @@ -38,6 +44,7 @@ #define IDS_EXTRACT_MSG_DATA_AFTER_END 3726 #define IDS_EXTRACT_MSG_IS_NOT_ARC 3727 #define IDS_EXTRACT_MSG_HEADERS_ERROR 3728 +#define IDS_EXTRACT_MSG_WRONG_PSW_CLAIM 3729 #define IDS_OPEN_MSG_UNAVAILABLE_START 3763 #define IDS_OPEN_MSG_UNCONFIRMED_START 3764 diff --git a/CPP/7zip/UI/GUI/GUI.cpp b/CPP/7zip/UI/GUI/GUI.cpp index 592f7673..134ac021 100644 --- a/CPP/7zip/UI/GUI/GUI.cpp +++ b/CPP/7zip/UI/GUI/GUI.cpp @@ -126,14 +126,8 @@ static int Main2() #endif #endif - CCodecs *codecs = new CCodecs; - #ifdef EXTERNAL_CODECS - CExternalCodecs __externalCodecs; - __externalCodecs.GetCodecs = codecs; - __externalCodecs.GetHashers = codecs; - #else - CMyComPtr<IUnknown> compressCodecsInfo = codecs; - #endif + CREATE_CODECS_OBJECT + codecs->CaseSensitiveChange = options.CaseSensitiveChange; codecs->CaseSensitive = options.CaseSensitive; ThrowException_if_Error(codecs->Load()); @@ -144,8 +138,18 @@ static int Main2() (isExtractGroupCommand || options.Command.IsFromUpdateGroup())) + { + #ifdef EXTERNAL_CODECS + if (!codecs->MainDll_ErrorPath.IsEmpty()) + { + UString s = L"7-Zip cannot load module "; + s += fs2us(codecs->MainDll_ErrorPath); + throw s; + } + #endif throw kNoFormats; - + } + CObjectVector<COpenType> formatIndices; if (!ParseOpenTypes(*codecs, options.ArcType, formatIndices)) { @@ -171,12 +175,12 @@ static int Main2() if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kHash || options.Command.CommandType == NCommandType::kBenchmark) - ThrowException_if_Error(__externalCodecs.LoadCodecs()); + ThrowException_if_Error(__externalCodecs.Load()); #endif if (options.Command.CommandType == NCommandType::kBenchmark) { - HRESULT res = Benchmark(EXTERNAL_CODECS_VARS options.Properties); + HRESULT res = Benchmark(EXTERNAL_CODECS_VARS_L options.Properties); /* if (res == S_FALSE) { @@ -188,6 +192,9 @@ static int Main2() } else if (isExtractGroupCommand) { + UStringVector ArchivePathsSorted; + UStringVector ArchivePathsFullSorted; + CExtractCallbackImp *ecs = new CExtractCallbackImp; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; @@ -218,14 +225,35 @@ static int Main2() if (!options.HashMethods.IsEmpty()) { hb_ptr = &hb; - ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS options.HashMethods)); + ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS_L options.HashMethods)); } #endif + { + CDirItemsStat st; + HRESULT hresultMain = EnumerateDirItemsAndSort( + options.arcCensor, + NWildcard::k_RelatPath, + UString(), // addPathPrefix + ArchivePathsSorted, + ArchivePathsFullSorted, + st, + NULL // &scan: change it!!!! + ); + if (hresultMain != S_OK) + { + /* + if (hresultMain != E_ABORT && messageWasDisplayed) + return NExitCode::kFatalError; + */ + throw CSystemException(hresultMain); + } + } + HRESULT result = ExtractGUI(codecs, formatIndices, excludedFormatIndices, - options.ArchivePathsSorted, - options.ArchivePathsFullSorted, + ArchivePathsSorted, + ArchivePathsFullSorted, options.Censor.Pairs.Front().Head, eo, #ifndef _SFX @@ -291,7 +319,7 @@ static int Main2() else if (options.Command.CommandType == NCommandType::kHash) { bool messageWasDisplayed = false; - HRESULT result = HashCalcGUI(EXTERNAL_CODECS_VARS + HRESULT result = HashCalcGUI(EXTERNAL_CODECS_VARS_L options.Censor, options.HashOptions, messageWasDisplayed); if (result != S_OK) diff --git a/CPP/7zip/UI/GUI/GUI.dsp b/CPP/7zip/UI/GUI/GUI.dsp index 1cbdbfd4..63cdb2fd 100644 --- a/CPP/7zip/UI/GUI/GUI.dsp +++ b/CPP/7zip/UI/GUI/GUI.dsp @@ -45,7 +45,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c -# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -72,7 +72,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /Gr /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -99,7 +99,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c -# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -127,7 +127,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c -# ADD CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /Gr /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -513,6 +513,14 @@ SOURCE=..\FileManager\ProgramLocation.h # End Source File # Begin Source File +SOURCE=..\FileManager\PropertyName.cpp +# End Source File +# Begin Source File + +SOURCE=..\FileManager\PropertyName.h +# End Source File +# Begin Source File + SOURCE=..\FileManager\RegistryUtils.cpp # End Source File # Begin Source File @@ -577,6 +585,14 @@ SOURCE=.\UpdateCallbackGUI.h # End Source File # Begin Source File +SOURCE=.\UpdateCallbackGUI2.cpp +# End Source File +# Begin Source File + +SOURCE=.\UpdateCallbackGUI2.h +# End Source File +# Begin Source File + SOURCE=.\UpdateGUI.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/UI/GUI/HashGUI.cpp b/CPP/7zip/UI/GUI/HashGUI.cpp index 903e41fc..3eb7d7d4 100644 --- a/CPP/7zip/UI/GUI/HashGUI.cpp +++ b/CPP/7zip/UI/GUI/HashGUI.cpp @@ -22,7 +22,6 @@ using namespace NWindows; class CHashCallbackGUI: public CProgressThreadVirt, public IHashCallbackUI { UInt64 NumFiles; - UStringVector FailedFiles; bool _curIsFolder; UString FirstFileName; @@ -45,33 +44,28 @@ public: } }; -static void NewLine(UString &s) -{ - s += L'\n'; -} - static void AddValuePair(UString &s, UINT resourceID, UInt64 value) { - s += LangString(resourceID); - s += L": "; - wchar_t sz[32]; + AddLangString(s, resourceID); + s.AddAscii(": "); + char sz[32]; ConvertUInt64ToString(value, sz); - s += sz; - NewLine(s); + s.AddAscii(sz); + s.Add_LF(); } static void AddSizeValuePair(UString &s, UINT resourceID, UInt64 value) { - s += LangString(resourceID); - s += L": "; + AddLangString(s, resourceID); + s.AddAscii(": "); wchar_t sz[32]; ConvertUInt64ToString(value, sz); s += MyFormatNew(IDS_FILE_SIZE, sz); ConvertUInt64ToString(value >> 20, sz); - s += L" ("; + s.AddAscii(" ("); s += sz; - s += L" MB)"; - NewLine(s); + s.AddAscii(" MB)"); + s.Add_LF(); } HRESULT CHashCallbackGUI::StartScanning() @@ -81,23 +75,20 @@ HRESULT CHashCallbackGUI::StartScanning() return CheckBreak(); } -HRESULT CHashCallbackGUI::ScanProgress(UInt64 /* numFolders */, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) +HRESULT CHashCallbackGUI::ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) { - return ProgressDialog.Sync.ScanProgress(numFiles, totalSize, path, isDir); + return ProgressDialog.Sync.ScanProgress(st.NumFiles, st.GetTotalBytes(), path, isDir); } -HRESULT CHashCallbackGUI::CanNotFindError(const wchar_t *name, DWORD systemError) +HRESULT CHashCallbackGUI::ScanError(const FString &path, DWORD systemError) { - FailedFiles.Add(name); - AddErrorMessage(systemError, name); + AddErrorMessage(systemError, fs2us(path)); return CheckBreak(); } -HRESULT CHashCallbackGUI::FinishScanning() +HRESULT CHashCallbackGUI::FinishScanning(const CDirItemsStat &st) { - CProgressSync &sync = ProgressDialog.Sync; - sync.Set_FilePath(L""); - return CheckBreak(); + return ScanProgress(st, FString(), false); } HRESULT CHashCallbackGUI::CheckBreak() @@ -139,12 +130,11 @@ HRESULT CHashCallbackGUI::GetStream(const wchar_t *name, bool isFolder) return CheckBreak(); } -HRESULT CHashCallbackGUI::OpenFileError(const wchar_t *name, DWORD systemError) +HRESULT CHashCallbackGUI::OpenFileError(const FString &path, DWORD systemError) { - FailedFiles.Add(name); // if (systemError == ERROR_SHARING_VIOLATION) { - AddErrorMessage(systemError, name); + AddErrorMessage(systemError, fs2us(path)); return S_FALSE; } // return systemError; @@ -159,20 +149,22 @@ HRESULT CHashCallbackGUI::SetOperationResult(UInt64 /* fileSize */, const CHashB return CheckBreak(); } -static void AddHashString(UString &s, const CHasherState &h, int digestIndex, const wchar_t *title) +static void AddHashString(UString &s, const CHasherState &h, unsigned digestIndex, const wchar_t *title) { s += title; - s += L' '; + s.Add_Space(); char temp[k_HashCalc_DigestSize_Max * 2 + 4]; AddHashHexToString(temp, h.Digests[digestIndex], h.DigestSize); - s.AddAsciiStr(temp); - NewLine(s); + s.AddAscii(temp); + s.Add_LF(); } -static void AddHashResString(UString &s, const CHasherState &h, int digestIndex, UInt32 resID) +static void AddHashResString(UString &s, const CHasherState &h, unsigned digestIndex, UInt32 resID) { UString s2 = LangString(resID); - s2.Replace(L"CRC", h.Name); + UString name; + name.SetFromAscii(h.Name); + s2.Replace(L"CRC", name); AddHashString(s, h, digestIndex, s2); } @@ -181,14 +173,14 @@ void AddHashBundleRes(UString &s, const CHashBundle &hb, const UString &firstFil if (hb.NumErrors != 0) { AddValuePair(s, IDS_PROP_NUM_ERRORS, hb.NumErrors); - NewLine(s); + s.Add_LF(); } if (hb.NumFiles == 1 && hb.NumDirs == 0 && !firstFileName.IsEmpty()) { - s += LangString(IDS_PROP_NAME); - s += L": "; + AddLangString(s, IDS_PROP_NAME); + s.AddAscii(": "); s += firstFileName; - NewLine(s); + s.Add_LF(); } else { @@ -200,23 +192,23 @@ void AddHashBundleRes(UString &s, const CHashBundle &hb, const UString &firstFil if (hb.NumAltStreams != 0) { - NewLine(s); + s.Add_LF(); AddValuePair(s, IDS_PROP_NUM_ALT_STREAMS, hb.NumAltStreams); AddSizeValuePair(s, IDS_PROP_ALT_STREAMS_SIZE, hb.AltStreamsSize); } FOR_VECTOR (i, hb.Hashers) { - NewLine(s); + s.Add_LF(); const CHasherState &h = hb.Hashers[i]; if (hb.NumFiles == 1 && hb.NumDirs == 0) { - s += h.Name; + s.AddAscii(h.Name); AddHashString(s, h, k_HashCalc_Index_DataSum, L":"); } else { - AddHashResString(s, h, k_HashCalc_Index_DataSum, IDS_CHECKSUM_CRC_DATA); + AddHashResString(s, h, k_HashCalc_Index_DataSum, IDS_CHECKSUM_CRC_DATA); AddHashResString(s, h, k_HashCalc_Index_NamesSum, IDS_CHECKSUM_CRC_DATA_NAMES); } if (hb.NumAltStreams != 0) @@ -245,7 +237,7 @@ HRESULT CHashCallbackGUI::ProcessVirt() { NumFiles = 0; - UString errorInfo; + AString errorInfo; HRESULT res = HashCalc(EXTERNAL_CODECS_LOC_VARS *censor, *options, errorInfo, this); @@ -270,7 +262,8 @@ HRESULT HashCalcGUI( const UString title = LangString(IDS_CHECKSUM_CALCULATING); t.ProgressDialog.MainTitle = L"7-Zip"; // LangString(IDS_APP_TITLE); - t.ProgressDialog.MainAddTitle = title + L' '; + t.ProgressDialog.MainAddTitle = title; + t.ProgressDialog.MainAddTitle.Add_Space(); RINOK(t.Create(title)); messageWasDisplayed = t.ThreadFinishedOK && t.ProgressDialog.MessagesDisplayed; diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp index 36af147b..240f4880 100644 --- a/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp +++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp @@ -7,7 +7,7 @@ #include "../../../Windows/PropVariant.h" -#include "../FileManager/PasswordDialog.h" +#include "../FileManager/FormatUtils.h" #include "../FileManager/LangUtils.h" #include "../FileManager/resourceGUI.h" @@ -18,29 +18,26 @@ using namespace NWindows; -CUpdateCallbackGUI::~CUpdateCallbackGUI() {} +// CUpdateCallbackGUI::~CUpdateCallbackGUI() {} void CUpdateCallbackGUI::Init() { + CUpdateCallbackGUI2::Init(); FailedFiles.Clear(); - NumFiles = 0; } -HRESULT CUpdateCallbackGUI::OpenResult(const wchar_t *name, HRESULT result, const wchar_t *errorArcType) +void OpenResult_GUI(UString &s, const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result); + +HRESULT CUpdateCallbackGUI::OpenResult( + const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) { - if (result != S_OK) + UString s; + OpenResult_GUI(s, codecs, arcLink, name, result); + if (!s.IsEmpty()) { - UString s; - if (errorArcType) - { - s += L"Can not open the file as ["; - s += errorArcType; - s += L"] archive"; - } - else - s += L"The file is not supported archive"; - ProgressDialog->Sync.AddError_Message_Name(s, name); + ProgressDialog->Sync.AddError_Message(s); } + return S_OK; } @@ -51,16 +48,18 @@ HRESULT CUpdateCallbackGUI::StartScanning() return S_OK; } -HRESULT CUpdateCallbackGUI::CanNotFindError(const wchar_t *name, DWORD systemError) +HRESULT CUpdateCallbackGUI::ScanError(const FString &path, DWORD systemError) { - FailedFiles.Add(name); - ProgressDialog->Sync.AddError_Code_Name(systemError, name); + FailedFiles.Add(path); + ProgressDialog->Sync.AddError_Code_Name(systemError, fs2us(path)); return S_OK; } -HRESULT CUpdateCallbackGUI::FinishScanning() +HRESULT CUpdateCallbackGUI::FinishScanning(const CDirItemsStat &st) { CProgressSync &sync = ProgressDialog->Sync; + RINOK(ProgressDialog->Sync.ScanProgress(st.NumFiles + st.NumAltStreams, + st.GetTotalBytes(), FString(), true)); sync.Set_Status(L""); return S_OK; } @@ -73,7 +72,7 @@ HRESULT CUpdateCallbackGUI::StartArchive(const wchar_t *name, bool /* updating * return S_OK; } -HRESULT CUpdateCallbackGUI::FinishArchive() +HRESULT CUpdateCallbackGUI::FinishArchive(const CFinishArchiveStat & /* st */) { CProgressSync &sync = ProgressDialog->Sync; sync.Set_Status(L""); @@ -85,19 +84,22 @@ HRESULT CUpdateCallbackGUI::CheckBreak() return ProgressDialog->Sync.CheckStop(); } -HRESULT CUpdateCallbackGUI::ScanProgress(UInt64 /* numFolders */, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) +HRESULT CUpdateCallbackGUI::ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) { - return ProgressDialog->Sync.ScanProgress(numFiles, totalSize, path, isDir); + return ProgressDialog->Sync.ScanProgress(st.NumFiles + st.NumAltStreams, + st.GetTotalBytes(), path, isDir); } -HRESULT CUpdateCallbackGUI::Finilize() +/* +HRESULT CUpdateCallbackGUI::Finalize() { return S_OK; } +*/ -HRESULT CUpdateCallbackGUI::SetNumFiles(UInt64 numFiles) +HRESULT CUpdateCallbackGUI::SetNumItems(UInt64 numItems) { - ProgressDialog->Sync.Set_NumFilesTotal(numFiles); + ProgressDialog->Sync.Set_NumFilesTotal(numItems); return S_OK; } @@ -118,18 +120,17 @@ HRESULT CUpdateCallbackGUI::SetRatioInfo(const UInt64 *inSize, const UInt64 *out return CheckBreak(); } -HRESULT CUpdateCallbackGUI::GetStream(const wchar_t *name, bool /* isAnti */) +HRESULT CUpdateCallbackGUI::GetStream(const wchar_t *name, bool isDir, bool /* isAnti */, UInt32 mode) { - ProgressDialog->Sync.Set_FilePath(name); - return S_OK; + return SetOperation_Base(mode, name, isDir); } -HRESULT CUpdateCallbackGUI::OpenFileError(const wchar_t *name, DWORD systemError) +HRESULT CUpdateCallbackGUI::OpenFileError(const FString &path, DWORD systemError) { - FailedFiles.Add(name); + FailedFiles.Add(path); // if (systemError == ERROR_SHARING_VIOLATION) { - ProgressDialog->Sync.AddError_Code_Name(systemError, name); + ProgressDialog->Sync.AddError_Code_Name(systemError, fs2us(path)); return S_FALSE; } // return systemError; @@ -142,22 +143,37 @@ HRESULT CUpdateCallbackGUI::SetOperationResult(Int32 /* operationResult */) return S_OK; } +void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s); + +HRESULT CUpdateCallbackGUI::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) +{ + if (opRes != NArchive::NExtract::NOperationResult::kOK) + { + UString s; + SetExtractErrorMessage(opRes, isEncrypted, name, s); + ProgressDialog->Sync.AddError_Message(s); + } + return S_OK; +} + +HRESULT CUpdateCallbackGUI::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool isDir) +{ + return SetOperation_Base(op, name, isDir); +} + HRESULT CUpdateCallbackGUI::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { *password = NULL; + if (passwordIsDefined) + *passwordIsDefined = BoolToInt(PasswordIsDefined); if (!PasswordIsDefined) { - if (passwordIsDefined == 0 || AskPassword) + if (AskPassword) { - CPasswordDialog dialog; - ProgressDialog->WaitCreating(); - if (dialog.Create(*ProgressDialog) != IDOK) - return E_ABORT; - Password = dialog.Password; - PasswordIsDefined = true; + RINOK(ShowAskPasswordDialog()) } } - if (passwordIsDefined != 0) + if (passwordIsDefined) *passwordIsDefined = BoolToInt(PasswordIsDefined); return StringToBstr(Password, password); } @@ -201,6 +217,7 @@ HRESULT CUpdateCallbackGUI::Open_CryptoGetTextPassword(BSTR *password) return CryptoGetTextPassword2(NULL, password); } +/* HRESULT CUpdateCallbackGUI::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) { passwordIsDefined = PasswordIsDefined; @@ -213,17 +230,51 @@ bool CUpdateCallbackGUI::Open_WasPasswordAsked() return PasswordWasAsked; } -void CUpdateCallbackGUI::Open_ClearPasswordWasAskedFlag() +void CUpdateCallbackGUI::Open_Clear_PasswordWasAsked_Flag() { PasswordWasAsked = false; } +*/ -/* -HRESULT CUpdateCallbackGUI::ShowDeleteFile(const wchar_t *name) +HRESULT CUpdateCallbackGUI::ShowDeleteFile(const wchar_t *name, bool isDir) { - ProgressDialog->Sync.SetCurrentFileName(name); + return SetOperation_Base(NUpdateNotifyOp::kDelete, name, isDir); +} + +HRESULT CUpdateCallbackGUI::FinishDeletingAfterArchiving() +{ + // ClosePercents2(); + return S_OK; +} + +HRESULT CUpdateCallbackGUI::DeletingAfterArchiving(const FString &path, bool isDir) +{ + return ProgressDialog->Sync.Set_Status2(_lang_Removing, fs2us(path), isDir); +} + +HRESULT CUpdateCallbackGUI::StartOpenArchive(const wchar_t * /* name */) +{ + return S_OK; +} + +HRESULT CUpdateCallbackGUI::ReadingFileError(const FString &path, DWORD systemError) +{ + FailedFiles.Add(path); + ProgressDialog->Sync.AddError_Code_Name(systemError, fs2us(path)); + return S_OK; +} + +HRESULT CUpdateCallbackGUI::WriteSfx(const wchar_t * /* name */, UInt64 /* size */) +{ + CProgressSync &sync = ProgressDialog->Sync; + sync.Set_Status(L"WriteSfx"); + return S_OK; +} + +HRESULT CUpdateCallbackGUI::Open_Finished() +{ + // ClosePercents(); return S_OK; } -*/ #endif diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI.h b/CPP/7zip/UI/GUI/UpdateCallbackGUI.h index 21b6f432..2e0c111b 100644 --- a/CPP/7zip/UI/GUI/UpdateCallbackGUI.h +++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI.h @@ -5,34 +5,30 @@ #include "../Common/Update.h" #include "../Common/ArchiveOpenCallback.h" -#include "../FileManager/ProgressDialog2.h" + +#include "UpdateCallbackGUI2.h" class CUpdateCallbackGUI: public IOpenCallbackUI, - public IUpdateCallbackUI2 + public IUpdateCallbackUI2, + public CUpdateCallbackGUI2 { public: - bool PasswordIsDefined; - UString Password; + // CUpdateCallbackGUI(); + // ~CUpdateCallbackGUI(); + bool AskPassword; - bool PasswordWasAsked; - UInt64 NumFiles; + + void Init(); CUpdateCallbackGUI(): - PasswordIsDefined(false), - PasswordWasAsked(false), AskPassword(false) {} - - ~CUpdateCallbackGUI(); - void Init(); INTERFACE_IUpdateCallbackUI2(;) INTERFACE_IOpenCallbackUI(;) - UStringVector FailedFiles; - - CProgressDialog *ProgressDialog; + FStringVector FailedFiles; }; #endif diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI2.cpp b/CPP/7zip/UI/GUI/UpdateCallbackGUI2.cpp new file mode 100644 index 00000000..4eeead7d --- /dev/null +++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI2.cpp @@ -0,0 +1,59 @@ +// UpdateCallbackGUI2.cpp + +#include "StdAfx.h" + +#include "../FileManager/LangUtils.h" +#include "../FileManager/PasswordDialog.h" + +#include "resource2.h" +#include "resource3.h" +#include "ExtractRes.h" + +#include "UpdateCallbackGUI.h" + +using namespace NWindows; + +static const UINT k_UpdNotifyLangs[] = +{ + IDS_PROGRESS_ADD, + IDS_PROGRESS_UPDATE, + IDS_PROGRESS_ANALYZE, + IDS_PROGRESS_REPLICATE, + IDS_PROGRESS_REPACK, + IDS_PROGRESS_SKIPPING, + IDS_PROGRESS_DELETE, + IDS_PROGRESS_HEADER +}; + +void CUpdateCallbackGUI2::Init() +{ + NumFiles = 0; + + _lang_Removing = LangString(IDS_PROGRESS_REMOVE); + _lang_Ops.Clear(); + for (unsigned i = 0; i < ARRAY_SIZE(k_UpdNotifyLangs); i++) + _lang_Ops.Add(LangString(k_UpdNotifyLangs[i])); +} + +HRESULT CUpdateCallbackGUI2::SetOperation_Base(UInt32 notifyOp, const wchar_t *name, bool isDir) +{ + const UString *s = NULL; + if (notifyOp < _lang_Ops.Size()) + s = &(_lang_Ops[(unsigned)notifyOp]); + else + s = &_emptyString; + + return ProgressDialog->Sync.Set_Status2(*s, name, isDir); +} + + +HRESULT CUpdateCallbackGUI2::ShowAskPasswordDialog() +{ + CPasswordDialog dialog; + ProgressDialog->WaitCreating(); + if (dialog.Create(*ProgressDialog) != IDOK) + return E_ABORT; + Password = dialog.Password; + PasswordIsDefined = true; + return S_OK; +} diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI2.h b/CPP/7zip/UI/GUI/UpdateCallbackGUI2.h new file mode 100644 index 00000000..2b30ad21 --- /dev/null +++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI2.h @@ -0,0 +1,35 @@ +// UpdateCallbackGUI2.h + +#ifndef __UPDATE_CALLBACK_GUI2_H +#define __UPDATE_CALLBACK_GUI2_H + +#include "../FileManager/ProgressDialog2.h" + +class CUpdateCallbackGUI2 +{ + UStringVector _lang_Ops; + UString _emptyString; +public: + UString Password; + bool PasswordIsDefined; + bool PasswordWasAsked; + UInt64 NumFiles; + + UString _lang_Removing; + + CUpdateCallbackGUI2(): + PasswordIsDefined(false), + PasswordWasAsked(false), + NumFiles(0) + {} + + // ~CUpdateCallbackGUI2(); + void Init(); + + CProgressDialog *ProgressDialog; + + HRESULT SetOperation_Base(UInt32 notifyOp, const wchar_t *name, bool isDir); + HRESULT ShowAskPasswordDialog(); +}; + +#endif diff --git a/CPP/7zip/UI/GUI/UpdateGUI.cpp b/CPP/7zip/UI/GUI/UpdateGUI.cpp index a7af4e94..64501306 100644 --- a/CPP/7zip/UI/GUI/UpdateGUI.cpp +++ b/CPP/7zip/UI/GUI/UpdateGUI.cpp @@ -6,7 +6,7 @@ #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" -// #include "../../../Windows/Error.h" +#include "../../../Windows/DLL.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileName.h" #include "../../../Windows/Thread.h" @@ -54,9 +54,8 @@ HRESULT CThreadUpdating::ProcessVirt() HRESULT res = UpdateArchive(codecs, *formatIndices, *cmdArcPath, *WildcardCensor, *Options, ei, UpdateCallbackGUI, UpdateCallbackGUI, needSetPath); - FinalMessage.ErrorMessage.Message = ei.Message; - SetErrorPath1(ei.FileName); - SetErrorPath2(ei.FileName2); + FinalMessage.ErrorMessage.Message.SetFromAscii(ei.Message); + ErrorPaths = ei.FileNames; if (ei.SystemError != S_OK && ei.SystemError != E_FAIL && ei.SystemError != E_ABORT) return ei.SystemError; return res; @@ -260,7 +259,7 @@ static HRESULT ShowDialog( FOR_VECTOR (i, item.PathParts) { if (i > 0) - name += WCHAR_PATH_SEPARATOR; + name.Add_PathSepar(); name += item.PathParts[i]; } if (fileInfo.Find(us2fs(name))) @@ -306,8 +305,8 @@ static HRESULT ShowDialog( if (!oneFile && ai.Flags_KeepName()) continue; if ((int)i != di.FormatIndex) - if (ai.Name.IsEqualToNoCase(L"swfc")) - if (!oneFile || name.Len() < 4 || !StringsAreEqualNoCase(name.RightPtr(4), L".swf")) + if (ai.Name.IsEqualTo_Ascii_NoCase("swfc")) + if (!oneFile || name.Len() < 4 || !StringsAreEqualNoCase_Ascii(name.RightPtr(4), ".swf")) continue; dialog.ArcIndices.Add(i); } @@ -387,7 +386,7 @@ static HRESULT ShowDialog( options.MethodMode.Properties.Clear(); - bool is7z = archiverInfo.Name.IsEqualToNoCase(L"7z"); + bool is7z = archiverInfo.Name.IsEqualTo_Ascii_NoCase("7z"); bool methodOverride = IsThereMethodOverride(is7z, di.Options); SetOutProperties( diff --git a/CPP/7zip/UI/GUI/makefile b/CPP/7zip/UI/GUI/makefile index 60cfcd4b..bcafa0e5 100644 --- a/CPP/7zip/UI/GUI/makefile +++ b/CPP/7zip/UI/GUI/makefile @@ -18,6 +18,7 @@ GUI_OBJS = \ $O\GUI.obj \ $O\HashGUI.obj \ $O\UpdateCallbackGUI.obj \ + $O\UpdateCallbackGUI2.obj \ $O\UpdateGUI.obj \ COMMON_OBJS = \ @@ -107,6 +108,7 @@ FM_OBJS = \ $O\LangUtils.obj \ $O\OpenCallback.obj \ $O\ProgramLocation.obj \ + $O\PropertyName.obj \ $O\RegistryUtils.obj \ $O\SplitUtils.obj \ $O\StringUtils.obj \ diff --git a/CPP/7zip/UI/GUI/resource.rc b/CPP/7zip/UI/GUI/resource.rc index 0f7c6235..13a09c64 100644 --- a/CPP/7zip/UI/GUI/resource.rc +++ b/CPP/7zip/UI/GUI/resource.rc @@ -2,6 +2,8 @@ // #include <winnt.h> #include "resource2.rc" +#include "resource3.rc" + #include "../FileManager/resourceGui.rc" MY_VERSION_INFO(MY_VFT_APP, "7-Zip GUI", "7zg", "7zg.exe") diff --git a/CPP/7zip/UI/GUI/resource3.h b/CPP/7zip/UI/GUI/resource3.h new file mode 100644 index 00000000..1758d525 --- /dev/null +++ b/CPP/7zip/UI/GUI/resource3.h @@ -0,0 +1,10 @@ +#define IDS_PROGRESS_REMOVE 3305 + +#define IDS_PROGRESS_ADD 3320 +#define IDS_PROGRESS_UPDATE 3321 +#define IDS_PROGRESS_ANALYZE 3322 +#define IDS_PROGRESS_REPLICATE 3323 +#define IDS_PROGRESS_REPACK 3324 + +#define IDS_PROGRESS_DELETE 3326 +#define IDS_PROGRESS_HEADER 3327 diff --git a/CPP/7zip/UI/GUI/resource3.rc b/CPP/7zip/UI/GUI/resource3.rc new file mode 100644 index 00000000..cfc8bc35 --- /dev/null +++ b/CPP/7zip/UI/GUI/resource3.rc @@ -0,0 +1,15 @@ +#include "resource3.h" + +STRINGTABLE +BEGIN + IDS_PROGRESS_REMOVE "Removing" + + IDS_PROGRESS_ADD "Adding" + IDS_PROGRESS_UPDATE "Updating" + IDS_PROGRESS_ANALYZE "Analyzing" + IDS_PROGRESS_REPLICATE "Replicating" + IDS_PROGRESS_REPACK "Repacking" + + IDS_PROGRESS_DELETE "Deleting" + IDS_PROGRESS_HEADER "Header creating" +END |