diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2017-04-30 03:00:00 +0300 |
---|---|---|
committer | Kornel <kornel@geekhood.net> | 2017-05-05 20:56:20 +0300 |
commit | 2efa10565ac395d2ce9a679ead46e70fb2f963eb (patch) | |
tree | 84c8df4deb69ec44ea15af9378f24347db55c357 /CPP | |
parent | 603abd5528c97346e9448c0ff47949f818fe558c (diff) |
17.0017.00
Diffstat (limited to 'CPP')
368 files changed, 13720 insertions, 7244 deletions
diff --git a/CPP/7zip/Aes.mak b/CPP/7zip/Aes.mak index c5a58f28..fbd70aae 100644 --- a/CPP/7zip/Aes.mak +++ b/CPP/7zip/Aes.mak @@ -1,7 +1,7 @@ C_OBJS = $(C_OBJS) \ $O\Aes.obj -!IF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS" && "$(CPU)" != "ARM" +!IF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS" && "$(CPU)" != "ARM" && "$(CPU)" != "ARM64" ASM_OBJS = $(ASM_OBJS) \ $O\AesOpt.obj !ENDIF diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp index b0d6dd83..d2687479 100644 --- a/CPP/7zip/Archive/7z/7zDecode.cpp +++ b/CPP/7zip/Archive/7z/7zDecode.cpp @@ -226,11 +226,13 @@ HRESULT CDecoder::Decode( , ISequentialOutStream *outStream , ICompressProgressInfo *compressProgress + , ISequentialInStream ** + #ifdef USE_MIXER_ST + inStreamMainRes + #endif - #ifdef USE_MIXER_ST - inStreamMainRes - #endif + , bool &dataAfterEnd_Error _7Z_DECODER_CRYPRO_VARS_DECL @@ -239,6 +241,8 @@ HRESULT CDecoder::Decode( #endif ) { + dataAfterEnd_Error = false; + const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]]; CFolderEx folderInfo; folders.ParseFolderEx(folderIndex, folderInfo); @@ -415,12 +419,14 @@ HRESULT CDecoder::Decode( } #endif + bool finishMode = false; { CMyComPtr<ICompressSetFinishMode> setFinishMode; decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode); if (setFinishMode) { - RINOK(setFinishMode->SetFinishMode(BoolToInt(fullUnpack))); + finishMode = fullUnpack; + RINOK(setFinishMode->SetFinishMode(BoolToInt(finishMode))); } } @@ -450,7 +456,7 @@ HRESULT CDecoder::Decode( unpackSize : &folders.CoderUnpackSizes[unpackStreamIndexStart + i]; - _mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers); + _mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers, finishMode); } if (outStream) @@ -530,7 +536,9 @@ HRESULT CDecoder::Decode( progress2 = new CDecProgress(compressProgress); ISequentialOutStream *outStreamPointer = outStream; - return _mixer->Code(inStreamPointers, &outStreamPointer, progress2 ? (ICompressProgressInfo *)progress2 : compressProgress); + return _mixer->Code(inStreamPointers, &outStreamPointer, + progress2 ? (ICompressProgressInfo *)progress2 : compressProgress, + dataAfterEnd_Error); } #ifdef USE_MIXER_ST diff --git a/CPP/7zip/Archive/7z/7zDecode.h b/CPP/7zip/Archive/7z/7zDecode.h index 5b729f6c..62a38038 100644 --- a/CPP/7zip/Archive/7z/7zDecode.h +++ b/CPP/7zip/Archive/7z/7zDecode.h @@ -53,7 +53,9 @@ public: , ISequentialOutStream *outStream , ICompressProgressInfo *compressProgress + , ISequentialInStream **inStreamMainRes + , bool &dataAfterEnd_Error _7Z_DECODER_CRYPRO_VARS_DECL diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp index 97e9ad7a..b206faa5 100644 --- a/CPP/7zip/Archive/7z/7zEncode.cpp +++ b/CPP/7zip/Archive/7z/7zEncode.cpp @@ -333,7 +333,7 @@ HRESULT CEncoder::Encode( } for (i = 0; i < numMethods; i++) - _mixer->SetCoderInfo(i, NULL, NULL); + _mixer->SetCoderInfo(i, NULL, NULL, false); /* inStreamSize can be used by BCJ2 to set optimal range of conversion. @@ -429,10 +429,12 @@ HRESULT CEncoder::Encode( for (i = 1; i < _bindInfo.PackStreams.Size(); i++) outStreamPointers.Add(tempBuffers[i - 1]); + bool dataAfterEnd_Error; + RINOK(_mixer->Code( &inStreamPointer, &outStreamPointers.Front(), - mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress)); + mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress, dataAfterEnd_Error)); if (_bindInfo.PackStreams.Size() != 0) packSizes.Add(outStreamSizeCountSpec->GetSize()); diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp index 05fd80de..8fea5aa5 100644 --- a/CPP/7zip/Archive/7z/7zExtract.cpp +++ b/CPP/7zip/Archive/7z/7zExtract.cpp @@ -348,6 +348,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, #endif + bool dataAfterEnd_Error = false; + HRESULT result = decoder.Decode( EXTERNAL_CODECS_VARS _inStream, @@ -358,6 +360,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, outStream, progress, NULL // *inStreamMainRes + , dataAfterEnd_Error _7Z_DECODER_CRYPRO_VARS #if !defined(_7ZIP_ST) && !defined(_SFX) @@ -365,13 +368,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, #endif ); - if (result == S_FALSE || result == E_NOTIMPL) + if (result == S_FALSE || result == E_NOTIMPL || dataAfterEnd_Error) { bool wasFinished = folderOutStream->WasWritingFinished(); - - int resOp = (result == S_FALSE ? - NExtract::NOperationResult::kDataError : - NExtract::NOperationResult::kUnsupportedMethod); + + int resOp = NExtract::NOperationResult::kDataError; + + if (result != S_FALSE) + { + if (result == E_NOTIMPL) + resOp = NExtract::NOperationResult::kUnsupportedMethod; + else if (wasFinished && dataAfterEnd_Error) + resOp = NExtract::NOperationResult::kDataAfterEnd; + } RINOK(folderOutStream->FlushCorrupted(resOp)); diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp index ccd2c624..2642e691 100644 --- a/CPP/7zip/Archive/7z/7zHandler.cpp +++ b/CPP/7zip/Archive/7z/7zHandler.cpp @@ -540,7 +540,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val */ const CFileItem &item = _db.Files[index]; - UInt32 index2 = index; + const UInt32 index2 = index; switch (propID) { @@ -575,7 +575,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidCTime: SetFileTimeProp_From_UInt64Def(value, _db.CTime, index2); break; case kpidATime: SetFileTimeProp_From_UInt64Def(value, _db.ATime, index2); break; case kpidMTime: SetFileTimeProp_From_UInt64Def(value, _db.MTime, index2); break; - case kpidAttrib: if (item.AttribDefined) PropVarEm_Set_UInt32(value, item.Attrib); break; + case kpidAttrib: if (_db.Attrib.ValidAndDefined(index2)) PropVarEm_Set_UInt32(value, _db.Attrib.Vals[index2]); break; case kpidCRC: if (item.CrcDefined) PropVarEm_Set_UInt32(value, item.Crc); break; case kpidEncrypted: PropVarEm_Set_Bool(value, IsFolderEncrypted(_db.FileIndexToFolderIndexMap[index2])); break; case kpidIsAnti: PropVarEm_Set_Bool(value, _db.IsItemAnti(index2)); break; diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h index d46401af..89e3275f 100644 --- a/CPP/7zip/Archive/7z/7zHandler.h +++ b/CPP/7zip/Archive/7z/7zHandler.h @@ -54,6 +54,7 @@ public: CBoolPair Write_CTime; CBoolPair Write_ATime; CBoolPair Write_MTime; + CBoolPair Write_Attrib; bool _useMultiThreadMixer; diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp index 2b86ed26..c4fabed7 100644 --- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp +++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp @@ -18,11 +18,12 @@ using namespace NWindows; namespace NArchive { namespace N7z { -static const char *k_LZMA_Name = "LZMA"; -static const char *kDefaultMethodName = "LZMA2"; -static const char *k_Copy_Name = "Copy"; +#define k_LZMA_Name "LZMA" +#define kDefaultMethodName "LZMA2" +#define k_Copy_Name "Copy" + +#define k_MatchFinder_ForHeaders "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 = @@ -113,11 +114,11 @@ HRESULT CHandler::SetMainMethod( FOR_VECTOR (i, methods) { COneMethodInfo &oneMethodInfo = methods[i]; - SetGlobalLevelAndThreads(oneMethodInfo - #ifndef _7ZIP_ST - , numThreads - #endif - ); + + SetGlobalLevelTo(oneMethodInfo); + #ifndef _7ZIP_ST + CMultiMethodProps::SetMethodThreadsTo(oneMethodInfo, numThreads); + #endif CMethodFull &methodFull = methodMode.Methods.AddNew(); RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo)); @@ -282,15 +283,18 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt bool need_CTime = (Write_CTime.Def && Write_CTime.Val); bool need_ATime = (Write_ATime.Def && Write_ATime.Val); bool need_MTime = (Write_MTime.Def && Write_MTime.Val || !Write_MTime.Def); + bool need_Attrib = (Write_Attrib.Def && Write_Attrib.Val || !Write_Attrib.Def); if (db && !db->Files.IsEmpty()) { if (!Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty(); if (!Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty(); if (!Write_MTime.Def) need_MTime = !db->MTime.Defs.IsEmpty(); + if (!Write_Attrib.Def) need_Attrib = !db->Attrib.Defs.IsEmpty(); } - UString s; + // UString s; + UString name; for (UInt32 i = 0; i < numItems; i++) { @@ -307,7 +311,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.IsAnti = false; ui.Size = 0; - UString name; + name.Empty(); // bool isAltStream = false; if (ui.IndexInArchive != -1) { @@ -334,6 +338,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (ui.NewProps) { bool folderStatusIsDefined; + if (need_Attrib) { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidAttrib, &prop)); @@ -377,7 +382,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt return E_INVALIDARG; else { - name = NItemName::MakeLegalName(prop.bstrVal); + name = prop.bstrVal; + NItemName::ReplaceSlashes_OsToUnix(name); } } { @@ -614,6 +620,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt options.HeaderOptions.WriteCTime = Write_CTime; options.HeaderOptions.WriteATime = Write_ATime; options.HeaderOptions.WriteMTime = Write_MTime; + options.HeaderOptions.WriteAttrib = Write_Attrib; */ options.NumSolidFiles = _numSolidFiles; @@ -705,6 +712,7 @@ void COutHandler::InitProps() Write_CTime.Init(); Write_ATime.Init(); Write_MTime.Init(); + Write_Attrib.Init(); _useMultiThreadMixer = true; @@ -830,6 +838,8 @@ 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("tr")) return PROPVARIANT_to_BoolPair(value, Write_Attrib); + if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer); if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting); diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp index d8c27175..3db5f515 100644 --- a/CPP/7zip/Archive/7z/7zIn.cpp +++ b/CPP/7zip/Archive/7z/7zIn.cpp @@ -32,6 +32,21 @@ using namespace NCOM; namespace NArchive { namespace N7z { +unsigned BoolVector_CountSum(const CBoolVector &v) +{ + unsigned sum = 0; + const unsigned size = v.Size(); + for (unsigned i = 0; i < size; i++) + if (v[i]) + sum++; + return sum; +} + +static inline bool BoolVector_Item_IsValidAndTrue(const CBoolVector &v, unsigned i) +{ + return (i < v.Size() ? v[i] : false); +} + static void BoolVector_Fill_False(CBoolVector &v, unsigned size) { v.ClearAndSetSize(size); @@ -40,6 +55,7 @@ static void BoolVector_Fill_False(CBoolVector &v, unsigned size) p[i] = false; } + class CInArchiveException {}; class CUnsupportedFeatureException: public CInArchiveException {}; @@ -566,21 +582,30 @@ void CInArchive::WaitId(UInt64 id) } } -void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs) + +void CInArchive::Read_UInt32_Vector(CUInt32DefVector &v) { - ReadBoolVector2(numItems, crcs.Defs); - crcs.Vals.ClearAndSetSize(numItems); - UInt32 *p = &crcs.Vals[0]; - const bool *defs = &crcs.Defs[0]; + unsigned numItems = v.Defs.Size(); + v.Vals.ClearAndSetSize(numItems); + UInt32 *p = &v.Vals[0]; + const bool *defs = &v.Defs[0]; for (unsigned i = 0; i < numItems; i++) { - UInt32 crc = 0; + UInt32 a = 0; if (defs[i]) - crc = ReadUInt32(); - p[i] = crc; + a = ReadUInt32(); + p[i] = a; } } + +void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs) +{ + ReadBoolVector2(numItems, crcs.Defs); + Read_UInt32_Vector(crcs); +} + + #define k_Scan_NumCoders_MAX 64 #define k_Scan_NumCodersStreams_in_Folder_MAX 64 @@ -1075,6 +1100,8 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; outStreamSpec->Init(data, unpackSize); + bool dataAfterEnd_Error = false; + HRESULT result = decoder.Decode( EXTERNAL_CODECS_LOC_VARS _stream, baseOffset + dataOffset, @@ -1083,16 +1110,23 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( outStream, NULL, // *compressProgress + NULL // **inStreamMainRes + , dataAfterEnd_Error _7Z_DECODER_CRYPRO_VARS #if !defined(_7ZIP_ST) && !defined(_SFX) , false // mtMode , 1 // numThreads #endif + ); + RINOK(result); + if (dataAfterEnd_Error) + ThereIsHeaderError = true; + if (folders.FolderCRCs.ValidAndDefined(i)) if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i]) ThrowIncorrect(); @@ -1148,19 +1182,10 @@ HRESULT CInArchive::ReadHeader( type = ReadID(); } - db.Files.Clear(); - if (type == NID::kFilesInfo) { const CNum numFiles = ReadNum(); - db.Files.ClearAndSetSize(numFiles); - /* - db.Files.Reserve(numFiles); - CNum i; - for (i = 0; i < numFiles; i++) - db.Files.Add(CFileItem()); - */ db.ArcInfo.FileInfoPopIDs.Add(NID::kSize); // if (!db.PackSizes.IsEmpty()) @@ -1169,7 +1194,6 @@ HRESULT CInArchive::ReadHeader( db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC); CBoolVector emptyStreamVector; - BoolVector_Fill_False(emptyStreamVector, (unsigned)numFiles); CBoolVector emptyFileVector; CBoolVector antiFileVector; CNum numEmptyStreams = 0; @@ -1197,10 +1221,10 @@ HRESULT CInArchive::ReadHeader( size_t rem = _inByteBack->GetRem(); db.NamesBuf.Alloc(rem); ReadBytes(db.NamesBuf, rem); - db.NameOffsets.Alloc(db.Files.Size() + 1); + db.NameOffsets.Alloc(numFiles + 1); size_t pos = 0; unsigned i; - for (i = 0; i < db.Files.Size(); i++) + for (i = 0; i < numFiles; i++) { size_t curRem = (rem - pos) / 2; const UInt16 *buf = (const UInt16 *)(db.NamesBuf + pos); @@ -1216,36 +1240,31 @@ HRESULT CInArchive::ReadHeader( ThereIsHeaderError = true; break; } + case NID::kWinAttrib: { - CBoolVector boolVector; - ReadBoolVector2(db.Files.Size(), boolVector); + ReadBoolVector2(numFiles, db.Attrib.Defs); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); - for (CNum i = 0; i < numFiles; i++) - { - CFileItem &file = db.Files[i]; - file.AttribDefined = boolVector[i]; - if (file.AttribDefined) - file.Attrib = ReadUInt32(); - } + Read_UInt32_Vector(db.Attrib); break; } + /* case NID::kIsAux: { - ReadBoolVector(db.Files.Size(), db.IsAux); + ReadBoolVector(numFiles, db.IsAux); break; } case NID::kParent: { db.IsTree = true; // CBoolVector boolVector; - // ReadBoolVector2(db.Files.Size(), boolVector); + // ReadBoolVector2(numFiles, boolVector); // CStreamSwitch streamSwitch; // streamSwitch.Set(this, &dataVector); CBoolVector boolVector; - ReadBoolVector2(db.Files.Size(), boolVector); + ReadBoolVector2(numFiles, boolVector); db.ThereAreAltStreams = false; for (i = 0; i < numFiles; i++) @@ -1264,14 +1283,9 @@ HRESULT CInArchive::ReadHeader( case NID::kEmptyStream: { ReadBoolVector(numFiles, emptyStreamVector); - numEmptyStreams = 0; - for (CNum i = 0; i < (CNum)emptyStreamVector.Size(); i++) - if (emptyStreamVector[i]) - numEmptyStreams++; - - BoolVector_Fill_False(emptyFileVector, numEmptyStreams); - BoolVector_Fill_False(antiFileVector, numEmptyStreams); - + numEmptyStreams = BoolVector_CountSum(emptyStreamVector); + emptyFileVector.Clear(); + antiFileVector.Clear(); break; } case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break; @@ -1314,7 +1328,7 @@ HRESULT CInArchive::ReadHeader( ReadBytes(db.SecureBuf + offset, db.SecureOffsets[i + 1] - offset); } db.SecureIDs.Clear(); - for (unsigned i = 0; i < db.Files.Size(); i++) + for (unsigned i = 0; i < numFiles; i++) { db.SecureIDs.Add(ReadNum()); // db.SecureIDs.Add(ReadUInt32()); @@ -1359,22 +1373,21 @@ HRESULT CInArchive::ReadHeader( CNum emptyFileIndex = 0; CNum sizeIndex = 0; - CNum numAntiItems = 0; + const CNum numAntiItems = BoolVector_CountSum(antiFileVector); - CNum i; + if (numAntiItems != 0) + db.IsAnti.ClearAndSetSize(numFiles); - for (i = 0; i < numEmptyStreams; i++) - if (antiFileVector[i]) - numAntiItems++; + db.Files.ClearAndSetSize(numFiles); - for (i = 0; i < numFiles; i++) + for (CNum i = 0; i < numFiles; i++) { CFileItem &file = db.Files[i]; bool isAnti; - file.HasStream = !emptyStreamVector[i]; file.Crc = 0; - if (file.HasStream) + if (!BoolVector_Item_IsValidAndTrue(emptyStreamVector, i)) { + file.HasStream = true; file.IsDir = false; isAnti = false; file.Size = unpackSizes[sizeIndex]; @@ -1385,26 +1398,31 @@ HRESULT CInArchive::ReadHeader( } else { - file.IsDir = !emptyFileVector[emptyFileIndex]; - isAnti = antiFileVector[emptyFileIndex]; + file.HasStream = false; + file.IsDir = !BoolVector_Item_IsValidAndTrue(emptyFileVector, emptyFileIndex); + isAnti = BoolVector_Item_IsValidAndTrue(antiFileVector, emptyFileIndex); emptyFileIndex++; file.Size = 0; file.CrcDefined = false; } if (numAntiItems != 0) - db.IsAnti.Add(isAnti); + db.IsAnti[i] = isAnti; } + } + db.FillLinks(); - /* - if (type != NID::kEnd) - ThrowIncorrect(); - if (_inByteBack->GetRem() != 0) - ThrowIncorrect(); - */ + + if (type != NID::kEnd || _inByteBack->GetRem() != 0) + { + db.UnsupportedFeatureWarning = true; + // ThrowIncorrect(); + } + return S_OK; } + void CDbEx::FillLinks() { FolderStartFileIndex.Alloc(NumFolders); @@ -1466,6 +1484,7 @@ void CDbEx::FillLinks() } } + HRESULT CInArchive::ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CDbEx &db @@ -1610,6 +1629,7 @@ HRESULT CInArchive::ReadDatabase2( ); } + HRESULT CInArchive::ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CDbEx &db diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h index 3592e99b..2d5fbb79 100644 --- a/CPP/7zip/Archive/7z/7zIn.h +++ b/CPP/7zip/Archive/7z/7zIn.h @@ -115,6 +115,7 @@ struct CDatabase: public CFolders CUInt64DefVector ATime; CUInt64DefVector MTime; CUInt64DefVector StartPos; + CUInt32DefVector Attrib; CBoolVector IsAnti; /* CBoolVector IsAux; @@ -146,6 +147,7 @@ struct CDatabase: public CFolders ATime.Clear(); MTime.Clear(); StartPos.Clear(); + Attrib.Clear(); IsAnti.Clear(); // IsAux.Clear(); } @@ -369,6 +371,8 @@ class CInArchive void SkipData() { _inByteBack->SkipData(); } void WaitId(UInt64 id); + void Read_UInt32_Vector(CUInt32DefVector &v); + void ReadArchiveProperties(CInArchiveInfo &archiveInfo); void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs); diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h index 5e2b58f2..ee4aed3f 100644 --- a/CPP/7zip/Archive/7z/7zItem.h +++ b/CPP/7zip/Archive/7z/7zItem.h @@ -26,12 +26,14 @@ struct CCoderInfo bool IsSimpleCoder() const { return NumStreams == 1; } }; + struct CBond { UInt32 PackIndex; UInt32 UnpackIndex; }; + struct CFolder { CLASS_NO_COPY(CFolder) @@ -87,6 +89,7 @@ public: } }; + struct CUInt32DefVector { CBoolVector Defs; @@ -110,9 +113,25 @@ struct CUInt32DefVector Vals.ReserveDown(); } + bool GetItem(unsigned index, UInt32 &value) const + { + if (index < Defs.Size() && Defs[index]) + { + value = Vals[index]; + return true; + } + value = 0; + return false; + } + bool ValidAndDefined(unsigned i) const { return i < Defs.Size() && Defs[i]; } + + bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; } + + void SetItem(unsigned index, bool defined, UInt32 value); }; + struct CUInt64DefVector { CBoolVector Defs; @@ -141,15 +160,15 @@ struct CUInt64DefVector return false; } - void SetItem(unsigned index, bool defined, UInt64 value); - bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; } + + void SetItem(unsigned index, bool defined, UInt64 value); }; + struct CFileItem { UInt64 Size; - UInt32 Attrib; UInt32 Crc; /* int Parent; @@ -159,23 +178,23 @@ struct CFileItem // stream in some folder. It can be empty stream bool IsDir; bool CrcDefined; - bool AttribDefined; + + /* + void Clear() + { + HasStream = true; + IsDir = false; + CrcDefined = false; + } CFileItem(): - /* - Parent(-1), - IsAltStream(false), - */ + // Parent(-1), + // IsAltStream(false), HasStream(true), IsDir(false), CrcDefined(false), - AttribDefined(false) {} - void SetAttrib(UInt32 attrib) - { - AttribDefined = true; - Attrib = attrib; - } + */ }; }} diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp index 3e70f466..904e32c5 100644 --- a/CPP/7zip/Archive/7z/7zOut.cpp +++ b/CPP/7zip/Archive/7z/7zOut.cpp @@ -330,13 +330,11 @@ void COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector) WriteBoolVector(boolVector); } +unsigned BoolVector_CountSum(const CBoolVector &v); + void COutArchive::WriteHashDigests(const CUInt32DefVector &digests) { - unsigned numDefined = 0; - unsigned i; - for (i = 0; i < digests.Defs.Size(); i++) - if (digests.Defs[i]) - numDefined++; + const unsigned numDefined = BoolVector_CountSum(digests.Defs); if (numDefined == 0) return; @@ -348,7 +346,8 @@ void COutArchive::WriteHashDigests(const CUInt32DefVector &digests) WriteByte(0); WriteBoolVector(digests.Defs); } - for (i = 0; i < digests.Defs.Size(); i++) + + for (unsigned i = 0; i < digests.Defs.Size(); i++) if (digests.Defs[i]) WriteUInt32(digests.Vals[i]); } @@ -453,10 +452,12 @@ void COutArchive::WriteSubStreamsInfo(const CObjectVector<CFolder> &folders, // 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field. -void COutArchive::SkipAlign(unsigned pos, unsigned alignSize) +void COutArchive::SkipToAligned(unsigned pos, unsigned alignShifts) { if (!_useAlign) return; + + const unsigned alignSize = (unsigned)1 << alignShifts; pos += (unsigned)GetPos(); pos &= (alignSize - 1); if (pos == 0) @@ -471,11 +472,11 @@ void COutArchive::SkipAlign(unsigned pos, unsigned alignSize) WriteByte(0); } -void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSize) +void COutArchive::WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts) { const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v); - const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2; - SkipAlign(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSize); + const UInt64 dataSize = ((UInt64)numDefined << itemSizeShifts) + bvSize + 2; + SkipToAligned(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSizeShifts); WriteByte(type); WriteNumber(dataSize); @@ -486,24 +487,18 @@ void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefin WriteByte(0); WriteBoolVector(v); } - WriteByte(0); + WriteByte(0); // 0 means no switching to external stream } void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type) { - unsigned numDefined = 0; - - unsigned i; - for (i = 0; i < v.Defs.Size(); i++) - if (v.Defs[i]) - numDefined++; - + const unsigned numDefined = BoolVector_CountSum(v.Defs); if (numDefined == 0) return; - WriteAlignedBoolHeader(v.Defs, numDefined, type, 8); + WriteAlignedBools(v.Defs, numDefined, type, 3); - for (i = 0; i < v.Defs.Size(); i++) + for (unsigned i = 0; i < v.Defs.Size(); i++) if (v.Defs[i]) WriteUInt64(v.Vals[i]); } @@ -648,7 +643,7 @@ void COutArchive::WriteHeader( if (numDefined > 0) { namesDataSize++; - SkipAlign(2 + GetBigNumberSize(namesDataSize), 16); + SkipToAligned(2 + GetBigNumberSize(namesDataSize), 4); WriteByte(NID::kName); WriteNumber(namesDataSize); @@ -673,28 +668,15 @@ void COutArchive::WriteHeader( { /* ---------- Write Attrib ---------- */ - CBoolVector boolVector; - boolVector.ClearAndSetSize(db.Files.Size()); - unsigned numDefined = 0; - - { - FOR_VECTOR (i, db.Files) - { - bool defined = db.Files[i].AttribDefined; - boolVector[i] = defined; - if (defined) - numDefined++; - } - } + const unsigned numDefined = BoolVector_CountSum(db.Attrib.Defs); if (numDefined != 0) { - WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttrib, 4); - FOR_VECTOR (i, db.Files) + WriteAlignedBools(db.Attrib.Defs, numDefined, NID::kWinAttrib, 2); + FOR_VECTOR (i, db.Attrib.Defs) { - const CFileItem &file = db.Files[i]; - if (file.AttribDefined) - WriteUInt32(file.Attrib); + if (db.Attrib.Defs[i]) + WriteUInt32(db.Attrib.Vals[i]); } } } @@ -702,18 +684,8 @@ void COutArchive::WriteHeader( /* { // ---------- Write IsAux ---------- - unsigned numAux = 0; - const CBoolVector &isAux = db.IsAux; - for (i = 0; i < isAux.Size(); i++) - if (isAux[i]) - numAux++; - if (numAux > 0) - { - const unsigned bvSize = Bv_GetSizeInBytes(isAux); - WriteByte(NID::kIsAux); - WriteNumber(bvSize); - WriteBoolVector(isAux); - } + if (BoolVector_CountSum(db.IsAux) != 0) + WritePropBoolVector(NID::kIsAux, db.IsAux); } { @@ -734,10 +706,10 @@ void COutArchive::WriteHeader( } if (numParentLinks > 0) { - // WriteAlignedBoolHeader(boolVector, numDefined, NID::kParent, 4); + // WriteAlignedBools(boolVector, numDefined, NID::kParent, 2); const unsigned bvSize = (numIsDir == boolVector.Size()) ? 0 : Bv_GetSizeInBytes(boolVector); const UInt64 dataSize = (UInt64)db.Files.Size() * 4 + bvSize + 1; - SkipAlign(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 4); + SkipToAligned(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 2); WriteByte(NID::kParent); WriteNumber(dataSize); @@ -765,7 +737,7 @@ void COutArchive::WriteHeader( // secureDataSize += db.SecureIDs.Size() * 4; for (i = 0; i < db.SecureIDs.Size(); i++) secureDataSize += GetBigNumberSize(db.SecureIDs[i]); - SkipAlign(2 + GetBigNumberSize(secureDataSize), 4); + SkipToAligned(2 + GetBigNumberSize(secureDataSize), 2); WriteByte(NID::kNtSecure); WriteNumber(secureDataSize); WriteByte(0); @@ -888,6 +860,18 @@ HRESULT COutArchive::WriteDatabase( } } +void CUInt32DefVector::SetItem(unsigned index, bool defined, UInt32 value) +{ + while (index >= Defs.Size()) + Defs.Add(false); + Defs[index] = defined; + if (!defined) + return; + while (index >= Vals.Size()) + Vals.Add(0); + Vals[index] = value; +} + void CUInt64DefVector::SetItem(unsigned index, bool defined, UInt64 value) { while (index >= Defs.Size()) @@ -907,6 +891,7 @@ void CArchiveDatabaseOut::AddFile(const CFileItem &file, const CFileItem2 &file2 ATime.SetItem(index, file2.ATimeDefined, file2.ATime); MTime.SetItem(index, file2.MTimeDefined, file2.MTime); StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos); + Attrib.SetItem(index, file2.AttribDefined, file2.Attrib); SetItem_Anti(index, file2.IsAnti); // SetItem_Aux(index, file2.IsAux); Names.Add(name); diff --git a/CPP/7zip/Archive/7z/7zOut.h b/CPP/7zip/Archive/7z/7zOut.h index 6c902668..1ebad56d 100644 --- a/CPP/7zip/Archive/7z/7zOut.h +++ b/CPP/7zip/Archive/7z/7zOut.h @@ -45,6 +45,7 @@ public: size_t GetPos() const { return _pos; } }; + struct CHeaderOptions { bool CompressMainHeader; @@ -71,24 +72,31 @@ struct CFileItem2 UInt64 ATime; UInt64 MTime; UInt64 StartPos; + UInt32 Attrib; + bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool StartPosDefined; + bool AttribDefined; bool IsAnti; // bool IsAux; + /* void Init() { CTimeDefined = false; ATimeDefined = false; MTimeDefined = false; StartPosDefined = false; + AttribDefined = false; IsAnti = false; // IsAux = false; } + */ }; + struct COutFolders { CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only. @@ -111,6 +119,7 @@ struct COutFolders } }; + struct CArchiveDatabaseOut: public COutFolders { CRecordVector<UInt64> PackSizes; @@ -123,10 +132,11 @@ struct CArchiveDatabaseOut: public COutFolders CUInt64DefVector ATime; CUInt64DefVector MTime; CUInt64DefVector StartPos; - CRecordVector<bool> IsAnti; + CUInt32DefVector Attrib; + CBoolVector IsAnti; /* - CRecordVector<bool> IsAux; + CBoolVector IsAux; CByteBuffer SecureBuf; CRecordVector<UInt32> SecureSizes; @@ -154,6 +164,7 @@ struct CArchiveDatabaseOut: public COutFolders ATime.Clear(); MTime.Clear(); StartPos.Clear(); + Attrib.Clear(); IsAnti.Clear(); /* @@ -176,6 +187,7 @@ struct CArchiveDatabaseOut: public COutFolders ATime.ReserveDown(); MTime.ReserveDown(); StartPos.ReserveDown(); + Attrib.ReserveDown(); IsAnti.ReserveDown(); /* @@ -196,11 +208,12 @@ struct CArchiveDatabaseOut: public COutFolders { unsigned size = Files.Size(); return ( - CTime.CheckSize(size) && - ATime.CheckSize(size) && - MTime.CheckSize(size) && - StartPos.CheckSize(size) && - (size == IsAnti.Size() || IsAnti.Size() == 0)); + CTime.CheckSize(size) + && ATime.CheckSize(size) + && MTime.CheckSize(size) + && StartPos.CheckSize(size) + && Attrib.CheckSize(size) + && (size == IsAnti.Size() || IsAnti.Size() == 0)); } bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); } @@ -224,6 +237,7 @@ struct CArchiveDatabaseOut: public COutFolders void AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name); }; + class COutArchive { UInt64 _prefixHeaderPos; @@ -261,8 +275,8 @@ class COutArchive const CRecordVector<UInt64> &unpackSizes, const CUInt32DefVector &digests); - void SkipAlign(unsigned pos, unsigned alignSize); - void WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSize); + void SkipToAligned(unsigned pos, unsigned alignShifts); + void WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts); void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type); HRESULT EncodeStream( diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp index 68e57f09..e0740e46 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp @@ -1088,18 +1088,23 @@ static HRESULT MakeExeMethod(CCompressionMethodMode &mode, } -static void FromUpdateItemToFileItem(const CUpdateItem &ui, - CFileItem &file, CFileItem2 &file2) +static void UpdateItem_To_FileItem2(const CUpdateItem &ui, CFileItem2 &file2) { - if (ui.AttribDefined) - file.SetAttrib(ui.Attrib); - + file2.Attrib = ui.Attrib; file2.AttribDefined = ui.AttribDefined; file2.CTime = ui.CTime; file2.CTimeDefined = ui.CTimeDefined; file2.ATime = ui.ATime; file2.ATimeDefined = ui.ATimeDefined; file2.MTime = ui.MTime; file2.MTimeDefined = ui.MTimeDefined; file2.IsAnti = ui.IsAnti; // file2.IsAux = false; file2.StartPosDefined = false; + // file2.StartPos = 0; +} + + +static void UpdateItem_To_FileItem(const CUpdateItem &ui, + CFileItem &file, CFileItem2 &file2) +{ + UpdateItem_To_FileItem2(ui, file2); file.Size = ui.Size; file.IsDir = ui.IsDir; @@ -1107,6 +1112,8 @@ static void FromUpdateItemToFileItem(const CUpdateItem &ui, // file.IsAltStream = ui.IsAltStream; } + + class CRepackInStreamWithSizes: public ISequentialInStream, public ICompressGetSubStreamSize, @@ -1437,6 +1444,7 @@ public: #ifndef _7ZIP_ST + bool dataAfterEnd_Error; HRESULT Result; CMyComPtr<IInStream> InStream; @@ -1479,7 +1487,9 @@ void CThreadDecoder::Execute() bool passwordIsDefined = false; UString password; #endif - + + dataAfterEnd_Error = false; + Result = Decoder.Decode( EXTERNAL_CODECS_LOC_VARS InStream, @@ -1491,12 +1501,15 @@ void CThreadDecoder::Execute() Fos, NULL, // compressProgress + NULL // *inStreamMainRes + , dataAfterEnd_Error _7Z_DECODER_CRYPRO_VARS #ifndef _7ZIP_ST , MtMode, NumThreads #endif + ); } catch(...) @@ -1541,6 +1554,7 @@ static void GetFile(const CDatabase &inDb, unsigned index, CFileItem &file, CFil file2.ATimeDefined = inDb.ATime.GetItem(index, file2.ATime); file2.MTimeDefined = inDb.MTime.GetItem(index, file2.MTime); file2.StartPosDefined = inDb.StartPos.GetItem(index, file2.StartPos); + file2.AttribDefined = inDb.Attrib.GetItem(index, file2.Attrib); file2.IsAnti = inDb.IsItemAnti(index); // file2.IsAux = inDb.IsItemAux(index); } @@ -1837,7 +1851,7 @@ HRESULT Update( continue; secureID = ui.SecureIndex; if (ui.NewProps) - FromUpdateItemToFileItem(ui, file, file2); + UpdateItem_To_FileItem(ui, file, file2); else GetFile(*db, ui.IndexInArchive, file, file2); } @@ -1887,7 +1901,8 @@ HRESULT Update( UString name; if (ui.NewProps) { - FromUpdateItemToFileItem(ui, file, file2); + UpdateItem_To_FileItem(ui, file, file2); + file.CrcDefined = false; name = ui.Name; } else @@ -2107,6 +2122,8 @@ HRESULT Update( #endif CMyComPtr<ISequentialInStream> decodedStream; + bool dataAfterEnd_Error = false; + HRESULT res = threadDecoder.Decoder.Decode( EXTERNAL_CODECS_LOC_VARS inStream, @@ -2117,13 +2134,16 @@ HRESULT Update( NULL, // *outStream NULL, // *compressProgress + &decodedStream + , dataAfterEnd_Error _7Z_DECODER_CRYPRO_VARS #ifndef _7ZIP_ST , false // mtMode , 1 // numThreads #endif + ); RINOK(res); @@ -2175,16 +2195,19 @@ HRESULT Update( HRESULT decodeRes = threadDecoder.Result; // if (res == k_My_HRESULT_CRC_ERROR) - if (decodeRes == S_FALSE) + if (decodeRes == S_FALSE || threadDecoder.dataAfterEnd_Error) { if (extractCallback) { RINOK(extractCallback->ReportExtractResult( NEventIndexType::kInArcIndex, db->FolderStartFileIndex[folderIndex], // NEventIndexType::kBlockIndex, (UInt32)folderIndex, - NExtract::NOperationResult::kDataError)); + (decodeRes != S_OK ? + NExtract::NOperationResult::kDataError : + NExtract::NOperationResult::kDataAfterEnd))); } - return E_FAIL; + if (decodeRes != S_OK) + return E_FAIL; } RINOK(decodeRes); if (encodeRes == S_OK) @@ -2224,12 +2247,7 @@ HRESULT Update( CNum indexInFolder = 0; for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) { - CFileItem file; - CFileItem2 file2; - GetFile(*db, fi, file, file2); - UString name; - db->GetPath(fi, name); - if (file.HasStream) + if (db->Files[fi].HasStream) { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fi]; @@ -2238,17 +2256,21 @@ HRESULT Update( const CUpdateItem &ui = updateItems[updateIndex]; if (ui.NewData) continue; + + UString name; + CFileItem file; + CFileItem2 file2; + GetFile(*db, fi, file, file2); + if (ui.NewProps) { - CFileItem uf; - FromUpdateItemToFileItem(ui, uf, file2); - uf.Size = file.Size; - uf.Crc = file.Crc; - uf.CrcDefined = file.CrcDefined; - uf.HasStream = file.HasStream; - file = uf; + UpdateItem_To_FileItem2(ui, file2); + file.IsDir = ui.IsDir; name = ui.Name; } + else + db->GetPath(fi, name); + /* file.Parent = ui.ParentFolderIndex; if (ui.TreeFolderIndex >= 0) @@ -2292,7 +2314,7 @@ HRESULT Update( const CUpdateItem &ui = updateItems[index]; CFileItem file; if (ui.NewProps) - FromUpdateItemToFileItem(ui, file); + UpdateItem_To_FileItem(ui, file); else file = db.Files[ui.IndexInArchive]; if (file.IsAnti || file.IsDir) @@ -2367,7 +2389,7 @@ HRESULT Update( UString name; if (ui.NewProps) { - FromUpdateItemToFileItem(ui, file, file2); + UpdateItem_To_FileItem(ui, file, file2); name = ui.Name; } else @@ -2386,7 +2408,7 @@ HRESULT Update( { skippedSize += ui.Size; continue; - // file.Name.AddAscii(".locked"); + // file.Name += ".locked"; } file.Crc = inStreamSpec->CRCs[subIndex]; diff --git a/CPP/7zip/Archive/ApmHandler.cpp b/CPP/7zip/Archive/ApmHandler.cpp index 51719d53..4d3f2728 100644 --- a/CPP/7zip/Archive/ApmHandler.cpp +++ b/CPP/7zip/Archive/ApmHandler.cpp @@ -6,7 +6,6 @@ #include "../../Common/ComTry.h" #include "../../Common/Defs.h" -#include "../../Common/IntToString.h" #include "../../Windows/PropVariant.h" @@ -232,7 +231,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) int mainIndex = -1; FOR_VECTOR (i, _items) { - AString s = GetString(_items[i].Type); + AString s (GetString(_items[i].Type)); if (s != "Apple_Free" && s != "Apple_partition_map") { @@ -279,14 +278,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { case kpidPath: { - AString s = GetString(item.Name); + AString s (GetString(item.Name)); if (s.IsEmpty()) - { - char s2[32]; - ConvertUInt32ToString(index, s2); - s = s2; - } - AString type = GetString(item.Type); + s.Add_UInt32(index); + AString type (GetString(item.Type)); if (type == "Apple_HFS") type = "hfs"; if (!type.IsEmpty()) diff --git a/CPP/7zip/Archive/ArHandler.cpp b/CPP/7zip/Archive/ArHandler.cpp index 83ed5a02..816a84e4 100644 --- a/CPP/7zip/Archive/ArHandler.cpp +++ b/CPP/7zip/Archive/ArHandler.cpp @@ -688,7 +688,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidShortComment: case kpidSubType: { - AString s = k_TypeExtionsions[(unsigned)_type]; + AString s (k_TypeExtionsions[(unsigned)_type]); if (_subType == kSubType_BSD) s += ":BSD"; prop = s; @@ -720,7 +720,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val if (item.TextFileIndex >= 0) prop = (item.TextFileIndex == 0) ? "1.txt" : "2.txt"; else - prop = (const wchar_t *)NItemName::GetOSName2(MultiByteToUnicodeString(item.Name, CP_OEMCP)); + prop = (const wchar_t *)NItemName::GetOsPath_Remove_TailSlash(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break; case kpidSize: case kpidPackSize: diff --git a/CPP/7zip/Archive/ArjHandler.cpp b/CPP/7zip/Archive/ArjHandler.cpp index 90819753..fb9e3e7a 100644 --- a/CPP/7zip/Archive/ArjHandler.cpp +++ b/CPP/7zip/Archive/ArjHandler.cpp @@ -5,10 +5,10 @@ #include "../../../C/CpuArch.h" #include "../../Common/ComTry.h" -#include "../../Common/IntToString.h" #include "../../Common/StringConvert.h" #include "../../Windows/PropVariant.h" +#include "../../Windows/PropVariantUtils.h" #include "../../Windows/TimeUtils.h" #include "../Common/LimitedStreams.h" @@ -642,16 +642,7 @@ static void SetTime(UInt32 dosTime, NCOM::CPropVariant &prop) static void SetHostOS(Byte hostOS, NCOM::CPropVariant &prop) { - char temp[16]; - const char *s = NULL; - if (hostOS < ARRAY_SIZE(kHostOS)) - s = kHostOS[hostOS]; - else - { - ConvertUInt32ToString(hostOS, temp); - s = temp; - } - prop = s; + TYPE_TO_PROP(kHostOS, hostOS, prop); } static void SetUnicodeString(const AString &s, NCOM::CPropVariant &prop) @@ -703,7 +694,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val const CItem &item = _items[index]; switch (propID) { - case kpidPath: prop = NItemName::GetOSName(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break; + case kpidPath: prop = NItemName::GetOsPath(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break; case kpidIsDir: prop = item.IsDir(); break; case kpidSize: prop = item.Size; break; case kpidPackSize: prop = item.PackSize; break; diff --git a/CPP/7zip/Archive/Bz2Handler.cpp b/CPP/7zip/Archive/Bz2Handler.cpp index d1d5f727..98428430 100644 --- a/CPP/7zip/Archive/Bz2Handler.cpp +++ b/CPP/7zip/Archive/Bz2Handler.cpp @@ -179,6 +179,7 @@ STDMETHODIMP CHandler::Close() return S_OK; } + STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { @@ -191,8 +192,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (_packSize_Defined) extractCallback->SetTotal(_packSize); - // RINOK(extractCallback->SetCompleted(&packSize)); - CMyComPtr<ISequentialOutStream> realOutStream; Int32 askMode = testMode ? NExtract::NAskMode::kTest : @@ -203,7 +202,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, extractCallback->PrepareOperation(askMode); - if (_needSeekToStart) { if (!_stream) @@ -213,14 +211,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, else _needSeekToStart = true; - Int32 opRes; - - try - { + // try { NCompress::NBZip2::CDecoder *decoderSpec = new NCompress::NBZip2::CDecoder; CMyComPtr<ICompressCoder> decoder = decoderSpec; - decoderSpec->SetInStream(_seqStream); #ifndef _7ZIP_ST RINOK(decoderSpec->SetNumberOfThreads(_props._numThreads)); @@ -237,74 +231,43 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, true); - UInt64 packSize = 0; - UInt64 unpackedSize = 0; - UInt64 numStreams = 0; - - decoderSpec->InitNumBlocks(); + decoderSpec->FinishMode = true; + decoderSpec->Base.DecodeAllStreams = true; - HRESULT result = S_OK; + _dataAfterEnd = false; + _needMoreInput = false; - for (;;) + lps->InSize = 0; + lps->OutSize = 0; + + HRESULT result = decoderSpec->Code(_seqStream, outStream, NULL, NULL, progress); + + if (result != S_FALSE && result != S_OK) + return result; + + if (decoderSpec->Base.NumStreams == 0) { - lps->InSize = packSize; - lps->OutSize = unpackedSize; - - RINOK(lps->SetCur()); - - result = decoderSpec->CodeResume(outStream, progress); - - if (result != S_FALSE && result != S_OK) - return result; - - if (decoderSpec->IsBz) - numStreams++; - else if (numStreams == 0) - { - _isArc = false; - result = S_FALSE; - break; - } - - unpackedSize = outStreamSpec->GetSize(); - UInt64 streamSize = decoderSpec->GetStreamSize(); + _isArc = false; + result = S_FALSE; + } + else + { + const UInt64 inProcessedSize = decoderSpec->GetInputProcessedSize(); + UInt64 packSize = inProcessedSize; - if (streamSize == packSize) - { - // no new bytes in input stream, So it's good end of archive. - result = S_OK; - break; - } + if (decoderSpec->Base.NeedMoreInput) + _needMoreInput = true; - if (!decoderSpec->IsBz) + if (!decoderSpec->Base.IsBz) { - _dataAfterEnd = true; - result = S_FALSE; - break; + packSize = decoderSpec->Base.FinishedPackSize; + if (packSize != inProcessedSize) + _dataAfterEnd = true; } - if (decoderSpec->Base.BitDecoder.ExtraBitsWereRead()) - { - _needMoreInput = true; - packSize = streamSize; - result = S_FALSE; - break; - } - - packSize = decoderSpec->GetInputProcessedSize(); - - if (packSize > streamSize) - return E_FAIL; - - if (result != S_OK) - break; - } - - if (numStreams != 0) - { _packSize = packSize; - _unpackSize = unpackedSize; - _numStreams = numStreams; + _unpackSize = decoderSpec->GetOutProcessedSize(); + _numStreams = decoderSpec->Base.NumStreams; _numBlocks = decoderSpec->GetNumBlocks(); _packSize_Defined = true; @@ -313,32 +276,36 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, _numBlocks_Defined = true; } - decoderSpec->ReleaseInStream(); outStream.Release(); + Int32 opRes; + if (!_isArc) opRes = NExtract::NOperationResult::kIsNotArc; else if (_needMoreInput) opRes = NExtract::NOperationResult::kUnexpectedEnd; - else if (decoderSpec->CrcError) + else if (decoderSpec->GetCrcError()) opRes = NExtract::NOperationResult::kCRCError; else if (_dataAfterEnd) opRes = NExtract::NOperationResult::kDataAfterEnd; else if (result == S_FALSE) opRes = NExtract::NOperationResult::kDataError; + else if (decoderSpec->Base.MinorError) + opRes = NExtract::NOperationResult::kDataError; else if (result == S_OK) opRes = NExtract::NOperationResult::kOK; else return result; - } - catch(const CInBufferException &e) { return e.ErrorCode; } - return extractCallback->SetOperationResult(opRes); + // } catch(...) { return E_FAIL; } + COM_TRY_END } + + static HRESULT UpdateArchive( UInt64 unpackSize, ISequentialOutStream *outStream, diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp index 18f58b3d..c62efbd8 100644 --- a/CPP/7zip/Archive/Cab/CabHandler.cpp +++ b/CPP/7zip/Archive/Cab/CabHandler.cpp @@ -226,12 +226,9 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) if (ai.SetID != 0) { AString s; - char temp[32]; - ConvertUInt32ToString(ai.SetID, temp); - s += temp; - ConvertUInt32ToString(ai.CabinetNumber + 1, temp); + s.Add_UInt32(ai.SetID); s += '_'; - s += temp; + s.Add_UInt32(ai.CabinetNumber + 1); s += ".cab"; prop = s; } @@ -288,7 +285,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val ConvertUTF8ToUnicode(item.Name, unicodeName); else unicodeName = MultiByteToUnicodeString(item.Name, CP_ACP); - prop = (const wchar_t *)NItemName::WinNameToOSName(unicodeName); + prop = (const wchar_t *)NItemName::WinPathToOsPath(unicodeName); break; } @@ -491,7 +488,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, if (!_errorMessage.IsEmpty()) _errorMessage.Add_LF(); - _errorMessage.AddAscii("Can't open volume: "); + _errorMessage += "Can't open volume: "; _errorMessage += fullName; if (prevChecked) diff --git a/CPP/7zip/Archive/Chm/ChmHandler.cpp b/CPP/7zip/Archive/Chm/ChmHandler.cpp index b890d8ff..7ffdafe0 100644 --- a/CPP/7zip/Archive/Chm/ChmHandler.cpp +++ b/CPP/7zip/Archive/Chm/ChmHandler.cpp @@ -135,7 +135,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val if (us.Len() > 1 && us[0] == L'/') us.Delete(0); } - NItemName::ConvertToOSName2(us); + NItemName::ReplaceToOsSlashes_Remove_TailSlash(us); prop = us; } break; diff --git a/CPP/7zip/Archive/Chm/ChmIn.cpp b/CPP/7zip/Archive/Chm/ChmIn.cpp index 02ecfadd..7e3f155b 100644 --- a/CPP/7zip/Archive/Chm/ChmIn.cpp +++ b/CPP/7zip/Archive/Chm/ChmIn.cpp @@ -38,20 +38,13 @@ struct CHeaderErrorException {}; // define CHM_LOW, if you want to see low level items // #define CHM_LOW -static const GUID kChmLzxGuid = { 0x7FC28940, 0x9D31, 0x11D0, { 0x9B, 0x27, 0x00, 0xA0, 0xC9, 0x1E, 0x9C, 0x7C } }; -static const GUID kHelp2LzxGuid = { 0x0A9007C6, 0x4076, 0x11D3, { 0x87, 0x89, 0x00, 0x00, 0xF8, 0x10, 0x57, 0x54 } }; -static const GUID kDesGuid = { 0x67F6E4A2, 0x60BF, 0x11D3, { 0x85, 0x40, 0x00, 0xC0, 0x4F, 0x58, 0xC3, 0xCF } }; +static const Byte kChmLzxGuid[16] = { 0x40, 0x89, 0xC2, 0x7F, 0x31, 0x9D, 0xD0, 0x11, 0x9B, 0x27, 0x00, 0xA0, 0xC9, 0x1E, 0x9C, 0x7C }; +static const Byte kHelp2LzxGuid[16] = { 0xC6, 0x07, 0x90, 0x0A, 0x76, 0x40, 0xD3, 0x11, 0x87, 0x89, 0x00, 0x00, 0xF8, 0x10, 0x57, 0x54 }; +static const Byte kDesGuid[16] = { 0xA2, 0xE4, 0xF6, 0x67, 0xBF, 0x60, 0xD3, 0x11, 0x85, 0x40, 0x00, 0xC0, 0x4F, 0x58, 0xC3, 0xCF }; -static bool AreGuidsEqual(REFGUID g1, REFGUID g2) +static bool inline AreGuidsEqual(const Byte *g1, const Byte *g2) { - if (g1.Data1 != g2.Data1 || - g1.Data2 != g2.Data2 || - g1.Data3 != g2.Data3) - return false; - for (int i = 0; i < 8; i++) - if (g1.Data4[i] != g2.Data4[i]) - return false; - return true; + return memcmp(g1, g2, 16) == 0; } static char GetHex(unsigned v) @@ -65,35 +58,12 @@ static void PrintByte(Byte b, AString &s) s += GetHex(b & 0xF); } -static void PrintUInt16(UInt16 v, AString &s) -{ - PrintByte((Byte)(v >> 8), s); - PrintByte((Byte)v, s); -} - -static void PrintUInt32(UInt32 v, AString &s) -{ - PrintUInt16((UInt16)(v >> 16), s); - PrintUInt16((UInt16)v, s); -} - AString CMethodInfo::GetGuidString() const { - AString s; - s += '{'; - PrintUInt32(Guid.Data1, s); - s += '-'; - PrintUInt16(Guid.Data2, s); - s += '-'; - PrintUInt16(Guid.Data3, s); - s += '-'; - PrintByte(Guid.Data4[0], s); - PrintByte(Guid.Data4[1], s); - s += '-'; - for (int i = 2; i < 8; i++) - PrintByte(Guid.Data4[i], s); - s += '}'; - return s; + char s[48]; + RawLeGuidToString_Braced(Guid, s); + // MyStringUpper_Ascii(s); + return (AString)s; } bool CMethodInfo::IsLzx() const @@ -108,32 +78,28 @@ bool CMethodInfo::IsDes() const return AreGuidsEqual(Guid, kDesGuid); } -UString CMethodInfo::GetName() const +AString CMethodInfo::GetName() const { - UString s; + AString s; if (IsLzx()) { - s.SetFromAscii("LZX:"); - char temp[16]; - ConvertUInt32ToString(LzxInfo.GetNumDictBits(), temp); - s.AddAscii(temp); + s = "LZX:"; + s.Add_UInt32(LzxInfo.GetNumDictBits()); } else { - AString s2; if (IsDes()) - s2 = "DES"; + s = "DES"; else { - s2 = GetGuidString(); + s = GetGuidString(); if (ControlData.Size() > 0) { - s2 += ':'; + s += ':'; for (size_t i = 0; i < ControlData.Size(); i++) - PrintByte(ControlData[i], s2); + PrintByte(ControlData[i], s); } } - ConvertUTF8ToUnicode(s2, s); } return s; } @@ -153,7 +119,7 @@ UString CSectionInfo::GetMethodName() const UString temp; if (ConvertUTF8ToUnicode(Name, temp)) s += temp; - s.AddAscii(": "); + s += ": "; } FOR_VECTOR (i, Methods) { @@ -220,12 +186,9 @@ UInt64 CInArchive::ReadEncInt() throw CHeaderErrorException(); } -void CInArchive::ReadGUID(GUID &g) +void CInArchive::ReadGUID(Byte *g) { - g.Data1 = ReadUInt32(); - g.Data2 = ReadUInt16(); - g.Data3 = ReadUInt16(); - ReadBytes(g.Data4, 8); + ReadBytes(g, 16); } void CInArchive::ReadString(unsigned size, AString &s) @@ -299,7 +262,7 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database) // The third and fourth bytes may contain even more fractional bits. // The 4 least significant bits in the last byte are constant. /* UInt32 lang = */ ReadUInt32(); - GUID g; + Byte g[16]; ReadGUID(g); // {7C01FD10-7BAA-11D0-9E0C-00A0-C922-E6EC} ReadGUID(g); // {7C01FD11-7BAA-11D0-9E0C-00A0-C922-E6EC} const unsigned kNumSections = 2; @@ -422,7 +385,7 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database) IsArc = true; ReadUInt32(); // Len of post-header table - GUID g; + Byte g[16]; ReadGUID(g); // {0A9007C1-4076-11D3-8789-0000F8105754} // header section table @@ -637,18 +600,18 @@ HRESULT CInArchive::DecompressStream(IInStream *inStream, const CDatabase &datab #define DATA_SPACE "::DataSpace/" -static const char *kNameList = DATA_SPACE "NameList"; -static const char *kStorage = DATA_SPACE "Storage/"; -static const char *kContent = "Content"; -static const char *kControlData = "ControlData"; -static const char *kSpanInfo = "SpanInfo"; -static const char *kTransform = "Transform/"; -static const char *kResetTable = "/InstanceData/ResetTable"; -static const char *kTransformList = "List"; +#define kNameList DATA_SPACE "NameList" +#define kStorage DATA_SPACE "Storage/" +#define kContent "Content" +#define kControlData "ControlData" +#define kSpanInfo "SpanInfo" +#define kTransform "Transform/" +#define kResetTable "/InstanceData/ResetTable" +#define kTransformList "List" static AString GetSectionPrefix(const AString &name) { - AString s = kStorage; + AString s (kStorage); s += name; s += '/'; return s; @@ -743,7 +706,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database) { { // The NameList file - RINOK(DecompressStream(inStream, database, kNameList)); + RINOK(DecompressStream(inStream, database, (AString)kNameList)); /* UInt16 length = */ ReadUInt16(); UInt16 numSections = ReadUInt16(); for (unsigned i = 0; i < numSections; i++) @@ -764,7 +727,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database) for (si = 1; si < database.Sections.Size(); si++) { CSectionInfo §ion = database.Sections[si]; - AString sectionPrefix = GetSectionPrefix(section.Name); + AString sectionPrefix (GetSectionPrefix(section.Name)); { // Content int index = database.FindItem(sectionPrefix + kContent); @@ -774,7 +737,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database) section.Offset = item.Offset; section.CompressedSize = item.Size; } - AString transformPrefix = sectionPrefix + kTransform; + AString transformPrefix (sectionPrefix + kTransform); if (database.Help2Format) { // Transform List @@ -794,7 +757,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database) else { CMethodInfo method; - method.Guid = kChmLzxGuid; + memcpy(method.Guid, kChmLzxGuid, 16); section.Methods.Add(method); } diff --git a/CPP/7zip/Archive/Chm/ChmIn.h b/CPP/7zip/Archive/Chm/ChmIn.h index bf51616f..f7b75d81 100644 --- a/CPP/7zip/Archive/Chm/ChmIn.h +++ b/CPP/7zip/Archive/Chm/ChmIn.h @@ -149,14 +149,14 @@ struct CLzxInfo struct CMethodInfo { - GUID Guid; + Byte Guid[16]; CByteBuffer ControlData; CLzxInfo LzxInfo; bool IsLzx() const; bool IsDes() const; AString GetGuidString() const; - UString GetName() const; + AString GetName() const; }; @@ -243,7 +243,7 @@ class CInArchive UInt64 ReadEncInt(); void ReadString(unsigned size, AString &s); void ReadUString(unsigned size, UString &s); - void ReadGUID(GUID &g); + void ReadGUID(Byte *g); HRESULT ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size); diff --git a/CPP/7zip/Archive/ComHandler.cpp b/CPP/7zip/Archive/ComHandler.cpp index c6d2bd25..d2dc6c5f 100644 --- a/CPP/7zip/Archive/ComHandler.cpp +++ b/CPP/7zip/Archive/ComHandler.cpp @@ -239,9 +239,6 @@ HRESULT CDatabase::AddNode(int parent, UInt32 did) return S_OK; } -static const wchar_t kCharOpenBracket = L'['; -static const wchar_t kCharCloseBracket = L']'; - static UString CompoundNameToFileName(const UString &s) { UString res; @@ -250,11 +247,9 @@ static UString CompoundNameToFileName(const UString &s) wchar_t c = s[i]; if (c < 0x20) { - res += kCharOpenBracket; - wchar_t buf[32]; - ConvertUInt32ToString(c, buf); - res += buf; - res += kCharCloseBracket; + res += '['; + res.Add_UInt32(c); + res += ']'; } else res += c; @@ -265,8 +260,8 @@ static UString CompoundNameToFileName(const UString &s) static const char k_Msi_Chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._"; -// static const char *k_Msi_ID = ""; // "{msi}"; -static const wchar_t k_Msi_SpecChar = L'!'; +// static const char * const k_Msi_ID = ""; // "{msi}"; +static const char k_Msi_SpecChar = '!'; static const unsigned k_Msi_NumBits = 6; static const unsigned k_Msi_NumChars = 1 << k_Msi_NumBits; @@ -316,10 +311,10 @@ static bool CompoundMsiNameToFileName(const UString &name, UString &res) if (c1 <= k_Msi_NumChars) { - res += (wchar_t)(Byte)k_Msi_Chars[c0]; + res += k_Msi_Chars[c0]; if (c1 == k_Msi_NumChars) break; - res += (wchar_t)(Byte)k_Msi_Chars[c1]; + res += k_Msi_Chars[c1]; } else res += k_Msi_SpecChar; diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp index 41b5805c..7834c605 100644 --- a/CPP/7zip/Archive/Common/CoderMixer2.cpp +++ b/CPP/7zip/Archive/Common/CoderMixer2.cpp @@ -60,6 +60,62 @@ static void BoolVector_Fill_False(CBoolVector &v, unsigned size) p[i] = false; } + +HRESULT CCoder::CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const +{ + if (Coder) + { + if (PackSizePointers.IsEmpty() || !PackSizePointers[0]) + return S_OK; + CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize; + Coder.QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize); + // if (!getInStreamProcessedSize) return E_FAIL; + if (getInStreamProcessedSize) + { + UInt64 processed; + RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&processed)); + if (processed != (UInt64)(Int64)-1) + { + const UInt64 size = PackSizes[0]; + if (processed < size && Finish) + dataAfterEnd_Error = true; + if (processed > size) + { + // InternalPackSizeError = true; + // return S_FALSE; + } + } + } + } + else if (Coder2) + { + CMyComPtr<ICompressGetInStreamProcessedSize2> getInStreamProcessedSize2; + Coder2.QueryInterface(IID_ICompressGetInStreamProcessedSize2, (void **)&getInStreamProcessedSize2); + FOR_VECTOR (i, PackSizePointers) + { + if (!PackSizePointers[i]) + continue; + UInt64 processed; + RINOK(getInStreamProcessedSize2->GetInStreamProcessedSize2(i, &processed)); + if (processed != (UInt64)(Int64)-1) + { + const UInt64 size = PackSizes[i]; + if (processed < size && Finish) + dataAfterEnd_Error = true; + else if (processed > size) + { + // InternalPackSizeError = true; + // return S_FALSE; + } + } + } + } + + return S_OK; +} + + + class CBondsChecks { CBoolVector _coderUsed; @@ -151,8 +207,10 @@ bool CBindInfo::CalcMapsAndCheck() } -void CCoder::SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes) +void CCoder::SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) { + Finish = finish; + if (unpackSize) { UnpackSize = *unpackSize; @@ -640,8 +698,12 @@ void CMixerST::SelectMainCoder(bool useFirst) HRESULT CMixerST::Code( ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams, - ICompressProgressInfo *progress) + ICompressProgressInfo *progress, + bool &dataAfterEnd_Error) { + // InternalPackSizeError = false; + dataAfterEnd_Error = false; + _binderStreams.Clear(); unsigned ci = MainCoderIndex; @@ -742,7 +804,16 @@ HRESULT CMixerST::Code( if (res == k_My_HRESULT_WritingWasCut) res = S_OK; - return res; + + if (res != S_OK) + return res; + + for (i = 0; i < _coders.Size(); i++) + { + RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /*, InternalPackSizeError */)); + } + + return S_OK; } @@ -988,8 +1059,12 @@ HRESULT CMixerMT::ReturnIfError(HRESULT code) HRESULT CMixerMT::Code( ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams, - ICompressProgressInfo *progress) + ICompressProgressInfo *progress, + bool &dataAfterEnd_Error) { + // InternalPackSizeError = false; + dataAfterEnd_Error = false; + Init(inStreams, outStreams); unsigned i; @@ -1031,6 +1106,11 @@ HRESULT CMixerMT::Code( return result; } + for (i = 0; i < _coders.Size(); i++) + { + RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /* , InternalPackSizeError */)); + } + return S_OK; } diff --git a/CPP/7zip/Archive/Common/CoderMixer2.h b/CPP/7zip/Archive/Common/CoderMixer2.h index e63f2ff0..798411ab 100644 --- a/CPP/7zip/Archive/Common/CoderMixer2.h +++ b/CPP/7zip/Archive/Common/CoderMixer2.h @@ -201,9 +201,13 @@ public: CRecordVector<UInt64> PackSizes; CRecordVector<const UInt64 *> PackSizePointers; - CCoder() {} + bool Finish; - void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes); + CCoder(): Finish(false) {} + + void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish); + + HRESULT CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const; IUnknown *GetUnknown() const { @@ -239,9 +243,12 @@ protected: public: unsigned MainCoderIndex; + // bool InternalPackSizeError; + CMixer(bool encodeMode): EncodeMode(encodeMode), MainCoderIndex(0) + // , InternalPackSizeError(false) {} /* @@ -273,11 +280,12 @@ public: 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 void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) = 0; virtual HRESULT Code( ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams, - ICompressProgressInfo *progress) = 0; + ICompressProgressInfo *progress, + bool &dataAfterEnd_Error) = 0; virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0; bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex); @@ -338,12 +346,13 @@ public: 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 void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) + { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); } virtual HRESULT Code( ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams, - ICompressProgressInfo *progress); + ICompressProgressInfo *progress, + bool &dataAfterEnd_Error); virtual UInt64 GetBondStreamSize(unsigned bondIndex) const; HRESULT GetMainUnpackStream( @@ -419,12 +428,13 @@ public: 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 void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) + { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); } virtual HRESULT Code( ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams, - ICompressProgressInfo *progress); + ICompressProgressInfo *progress, + bool &dataAfterEnd_Error); virtual UInt64 GetBondStreamSize(unsigned bondIndex) const; CMixerMT(bool encodeMode): CMixer(encodeMode) {} diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp index 30ca73bd..ea320e66 100644 --- a/CPP/7zip/Archive/Common/HandlerOut.cpp +++ b/CPP/7zip/Archive/Common/HandlerOut.cpp @@ -20,20 +20,19 @@ static void SetMethodProp32(COneMethodInfo &m, PROPID propID, UInt32 value) m.AddProp32(propID, value); } -void CMultiMethodProps::SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo - #ifndef _7ZIP_ST - , UInt32 numThreads - #endif - ) +void CMultiMethodProps::SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const { UInt32 level = _level; if (level != (UInt32)(Int32)-1) SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level); - - #ifndef _7ZIP_ST +} + +#ifndef _7ZIP_ST +void CMultiMethodProps::SetMethodThreadsTo(COneMethodInfo &oneMethodInfo, UInt32 numThreads) +{ SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); - #endif } +#endif void CMultiMethodProps::Init() { @@ -73,7 +72,7 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN return S_OK; } - if (name.IsEqualTo("crc")) + if (name.IsPrefixedBy_Ascii_NoCase("crc")) { name.Delete(0, 3); _crcSize = 4; diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h index 5a18d980..e24686da 100644 --- a/CPP/7zip/Archive/Common/HandlerOut.h +++ b/CPP/7zip/Archive/Common/HandlerOut.h @@ -22,11 +22,13 @@ public: COneMethodInfo _filterMethod; bool _autoFilter; - void SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo - #ifndef _7ZIP_ST - , UInt32 numThreads - #endif - ); + + void SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const; + + #ifndef _7ZIP_ST + static void SetMethodThreadsTo(COneMethodInfo &oneMethodInfo, UInt32 numThreads); + #endif + unsigned GetNumEmptyMethods() const { diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/CPP/7zip/Archive/Common/ItemNameUtils.cpp index 7cd3037b..d5093a24 100644 --- a/CPP/7zip/Archive/Common/ItemNameUtils.cpp +++ b/CPP/7zip/Archive/Common/ItemNameUtils.cpp @@ -7,58 +7,57 @@ namespace NArchive { namespace NItemName { -static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR; -static const wchar_t kDirDelimiter = L'/'; +static const wchar_t kOsPathSepar = WCHAR_PATH_SEPARATOR; +static const wchar_t kUnixPathSepar = L'/'; -void ReplaceToOsPathSeparator(wchar_t *s) -{ - #ifdef _WIN32 - for (;;) +void ReplaceSlashes_OsToUnix +#if WCHAR_PATH_SEPARATOR != L'/' + (UString &name) { - wchar_t c = *s; - if (c == 0) - break; - if (c == kDirDelimiter) - *s = kOSDirDelimiter; - s++; + name.Replace(kOsPathSepar, kUnixPathSepar); } - #endif -} +#else + (UString &) {} +#endif -UString MakeLegalName(const UString &name) -{ - UString zipName = name; - zipName.Replace(kOSDirDelimiter, kDirDelimiter); - return zipName; -} -UString GetOSName(const UString &name) +UString GetOsPath(const UString &name) { - UString newName = name; - newName.Replace(kDirDelimiter, kOSDirDelimiter); - return newName; + #if WCHAR_PATH_SEPARATOR != L'/' + UString newName = name; + newName.Replace(kUnixPathSepar, kOsPathSepar); + return newName; + #else + return name; + #endif } -UString GetOSName2(const UString &name) + +UString GetOsPath_Remove_TailSlash(const UString &name) { if (name.IsEmpty()) return UString(); - UString newName = GetOSName(name); - if (newName.Back() == kOSDirDelimiter) + UString newName = GetOsPath(name); + if (newName.Back() == kOsPathSepar) newName.DeleteBack(); return newName; } -void ConvertToOSName2(UString &name) + +void ReplaceToOsSlashes_Remove_TailSlash(UString &name) { if (!name.IsEmpty()) { - name.Replace(kDirDelimiter, kOSDirDelimiter); - if (name.Back() == kOSDirDelimiter) + #if WCHAR_PATH_SEPARATOR != L'/' + name.Replace(kUnixPathSepar, kOsPathSepar); + #endif + + if (name.Back() == kOsPathSepar) name.DeleteBack(); } } + bool HasTailSlash(const AString &name, UINT #if defined(_WIN32) && !defined(UNDER_CE) codePage @@ -67,20 +66,21 @@ bool HasTailSlash(const AString &name, UINT { if (name.IsEmpty()) return false; - LPCSTR prev = - #if defined(_WIN32) && !defined(UNDER_CE) - CharPrevExA((WORD)codePage, name, &name[name.Len()], 0); - #else - (LPCSTR)(name) + (name.Len() - 1); - #endif - return (*prev == '/'); + char c = + #if defined(_WIN32) && !defined(UNDER_CE) + *CharPrevExA((WORD)codePage, name, name.Ptr(name.Len()), 0); + #else + name.Back(); + #endif + return (c == '/'); } + #ifndef _WIN32 -UString WinNameToOSName(const UString &name) +UString WinPathToOsPath(const UString &name) { UString newName = name; - newName.Replace(L'\\', kOSDirDelimiter); + newName.Replace(L'\\', WCHAR_PATH_SEPARATOR); return newName; } #endif diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.h b/CPP/7zip/Archive/Common/ItemNameUtils.h index d0dc76a4..31150864 100644 --- a/CPP/7zip/Archive/Common/ItemNameUtils.h +++ b/CPP/7zip/Archive/Common/ItemNameUtils.h @@ -8,19 +8,20 @@ namespace NArchive { namespace NItemName { - void ReplaceToOsPathSeparator(wchar_t *s); - - UString MakeLegalName(const UString &name); - UString GetOSName(const UString &name); - UString GetOSName2(const UString &name); - void ConvertToOSName2(UString &name); - bool HasTailSlash(const AString &name, UINT codePage); - - #ifdef _WIN32 - inline UString WinNameToOSName(const UString &name) { return name; } - #else - UString WinNameToOSName(const UString &name); - #endif +void ReplaceSlashes_OsToUnix(UString &name); + +UString GetOsPath(const UString &name); +UString GetOsPath_Remove_TailSlash(const UString &name); + +void ReplaceToOsSlashes_Remove_TailSlash(UString &name); + +bool HasTailSlash(const AString &name, UINT codePage); + +#ifdef _WIN32 + inline UString WinPathToOsPath(const UString &name) { return name; } +#else + UString WinPathToOsPath(const UString &name); +#endif }} diff --git a/CPP/7zip/Archive/CpioHandler.cpp b/CPP/7zip/Archive/CpioHandler.cpp index e8898cac..b8fb530f 100644 --- a/CPP/7zip/Archive/CpioHandler.cpp +++ b/CPP/7zip/Archive/CpioHandler.cpp @@ -36,7 +36,7 @@ static const Byte kMagicHex = '1'; // New ASCII Format static const Byte kMagicHexCrc = '2'; // New CRC Format static const Byte kMagicOct = '7'; // Portable ASCII Format -static const char *kName_TRAILER = "TRAILER!!!"; +static const char * const kName_TRAILER = "TRAILER!!!"; static const unsigned k_BinRecord_Size = 2 + 8 * 2 + 2 * 4; static const unsigned k_OctRecord_Size = 6 + 8 * 6 + 2 * 11; @@ -627,7 +627,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val #endif if (needConvert) res = MultiByteToUnicodeString(item.Name, CP_OEMCP); - prop = NItemName::GetOSName(res); + prop = NItemName::GetOsPath(res); break; } case kpidIsDir: prop = item.IsDir(); break; diff --git a/CPP/7zip/Archive/DmgHandler.cpp b/CPP/7zip/Archive/DmgHandler.cpp index 09952ac8..8acbcea6 100644 --- a/CPP/7zip/Archive/DmgHandler.cpp +++ b/CPP/7zip/Archive/DmgHandler.cpp @@ -183,6 +183,30 @@ struct CExtraFile }; #endif + +struct CForkPair +{ + UInt64 Offset; + UInt64 Len; + + void Parse(const Byte *p) + { + Offset = Get64(p); + Len = Get64(p + 8); + } + + bool UpdateTop(UInt64 limit, UInt64 &top) + { + if (Offset > limit || Len > limit - Offset) + return false; + UInt64 top2 = Offset + Len; + if (top <= top2) + top = top2; + return true; + } +}; + + class CHandler: public IInArchive, public IInArchiveGetStream, @@ -191,14 +215,19 @@ class CHandler: CMyComPtr<IInStream> _inStream; CObjectVector<CFile> _files; bool _masterCrcError; + bool _headersError; UInt64 _startPos; UInt64 _phySize; + + AString _name; #ifdef DMG_SHOW_RAW CObjectVector<CExtraFile> _extras; #endif + HRESULT ReadData(IInStream *stream, const CForkPair &pair, CByteBuffer &buf); + bool ParseBlob(const CByteBuffer &data); HRESULT Open2(IInStream *stream); HRESULT Extract(IInStream *stream); public: @@ -249,24 +278,20 @@ void CMethods::GetString(AString &res) const case METHOD_BZIP2: s = "BZip2"; break; default: ConvertUInt32ToString(type, buf); s = buf; } - res.Add_Space_if_NotEmpty(); - res += s; + res.Add_OptSpaced(s); } for (i = 0; i < ChecksumTypes.Size(); i++) { + res.Add_Space_if_NotEmpty(); UInt32 type = ChecksumTypes[i]; - char buf[32]; - const char *s; switch (type) { - case kCheckSumType_CRC: s = "CRC"; break; + case kCheckSumType_CRC: res += "CRC"; break; default: - ConvertUInt32ToString(type, MyStpCpy(buf, "Check")); - s = buf; + res += "Check"; + res.Add_UInt32(type); } - res.Add_Space_if_NotEmpty(); - res += s; } } @@ -308,7 +333,8 @@ IMP_IInArchive_Props static const Byte kArcProps[] = { kpidMethod, - kpidNumBlocks + kpidNumBlocks, + kpidComment }; STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) @@ -372,9 +398,30 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidWarning: if (_masterCrcError) prop = "Master CRC error"; + + case kpidWarningFlags: + { + UInt32 v = 0; + if (_headersError) v |= kpv_ErrorFlags_HeadersError; + if (v != 0) + prop = v; break; + } + case kpidOffset: prop = _startPos; break; case kpidPhySize: prop = _phySize; break; + + case kpidComment: + if (!_name.IsEmpty() && _name.Len() < 256) + prop = _name; + break; + + case kpidName: + if (!_name.IsEmpty() && _name.Len() < 256) + { + prop = _name + ".dmg"; + } + break; } prop.Detach(value); return S_OK; @@ -461,7 +508,7 @@ HRESULT CFile::Parse(const Byte *p, UInt32 size) return S_OK; } -static int FindKeyPair(const CXmlItem &item, const AString &key, const AString &nextTag) +static int FindKeyPair(const CXmlItem &item, const char *key, const char *nextTag) { for (unsigned i = 0; i + 1 < item.SubItems.Size(); i++) { @@ -472,7 +519,7 @@ static int FindKeyPair(const CXmlItem &item, const AString &key, const AString & return -1; } -static const AString *GetStringFromKeyPair(const CXmlItem &item, const AString &key, const AString &nextTag) +static const AString *GetStringFromKeyPair(const CXmlItem &item, const char *key, const char *nextTag) { int index = FindKeyPair(item, key, nextTag); if (index >= 0) @@ -498,6 +545,83 @@ static inline bool IsKoly(const Byte *p) */ } + +HRESULT CHandler::ReadData(IInStream *stream, const CForkPair &pair, CByteBuffer &buf) +{ + size_t size = (size_t)pair.Len; + if (size != pair.Len) + return E_OUTOFMEMORY; + buf.Alloc(size); + RINOK(stream->Seek(_startPos + pair.Offset, STREAM_SEEK_SET, NULL)); + return ReadStream_FALSE(stream, buf, size); +} + + +bool CHandler::ParseBlob(const CByteBuffer &data) +{ + if (data.Size() < 12) + return false; + const Byte *p = (const Byte *)data; + if (Get32(p) != 0xFADE0CC0) + return true; + const UInt32 size = Get32(p + 4); + if (size != data.Size()) + return false; + const UInt32 num = Get32(p + 8); + if (num > (size - 12) / 8) + return false; + + for (UInt32 i = 0; i < num; i++) + { + // UInt32 type = Get32(p + i * 8 + 12); + UInt32 offset = Get32(p + i * 8 + 12 + 4); + if (size - offset < 8) + return false; + const Byte *p2 = (const Byte *)data + offset; + const UInt32 magic = Get32(p2); + const UInt32 len = Get32(p2 + 4); + if (size - offset < len || len < 8) + return false; + + #ifdef DMG_SHOW_RAW + CExtraFile &extra = _extras.AddNew(); + extra.Name = "_blob_"; + extra.Data.CopyFrom(p2, len); + #endif + + if (magic == 0xFADE0C02) + { + #ifdef DMG_SHOW_RAW + extra.Name += "codedir"; + #endif + + if (len < 11 * 4) + return false; + UInt32 idOffset = Get32(p2 + 0x14); + if (idOffset >= len) + return false; + UInt32 len2 = len - idOffset; + if (len2 < (1 << 10)) + _name.SetFrom_CalcLen((const char *)(p2 + idOffset), len2); + } + #ifdef DMG_SHOW_RAW + else if (magic == 0xFADE0C01) + extra.Name += "requirements"; + else if (magic == 0xFADE0B01) + extra.Name += "signed"; + else + { + char temp[16]; + ConvertUInt32ToHex8Digits(magic, temp); + extra.Name += temp; + } + #endif + } + + return true; +} + + HRESULT CHandler::Open2(IInStream *stream) { RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_startPos)); @@ -522,35 +646,69 @@ HRESULT CHandler::Open2(IInStream *stream) // UInt32 flags = Get32(buf + 12); // UInt64 runningDataForkOffset = Get64(buf + 0x10); - UInt64 dataForkOffset = Get64(buf + 0x18); - UInt64 dataForkLen = Get64(buf + 0x20); - UInt64 rsrcOffset = Get64(buf + 0x28); - UInt64 rsrcLen = Get64(buf + 0x30); + + CForkPair dataForkPair, rsrcPair, xmlPair, blobPair; + + dataForkPair.Parse(buf + 0x18); + rsrcPair.Parse(buf + 0x28); + xmlPair.Parse(buf + 0xD8); + blobPair.Parse(buf + 0x128); + // UInt32 segmentNumber = Get32(buf + 0x38); // UInt32 segmentCount = Get32(buf + 0x3C); // Byte segmentGUID[16]; // CChecksum dataForkChecksum; // dataForkChecksum.Parse(buf + 0x50); - 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; - _startPos = headerPos - totalLen; - _phySize = totalLen + HEADER_SIZE; - headerPos = totalLen; + _startPos = 0; + + UInt64 top = 0; + if (!dataForkPair.UpdateTop(headerPos, top)) return S_FALSE; + if (!xmlPair.UpdateTop(headerPos, top)) return S_FALSE; + if (!rsrcPair.UpdateTop(headerPos, top)) return S_FALSE; + + /* Some old dmg files contain garbage data in blobPair field. + So we need to ignore such garbage case; + And we still need to detect offset of start of archive for "parser" mode. */ + + bool useBlob = blobPair.UpdateTop(headerPos, top); + + _startPos = 0; + _phySize = headerPos + HEADER_SIZE; + + if (top != headerPos) + { + CForkPair xmlPair2 = xmlPair; + const char *sz = "<?xml version"; + const unsigned len = (unsigned)strlen(sz); + if (xmlPair2.Len > len) + xmlPair2.Len = len; + CByteBuffer buf2; + if (ReadData(stream, xmlPair2, buf2) != S_OK + || memcmp(buf2, sz, len) != 0) + { + _startPos = headerPos - top; + _phySize = top + HEADER_SIZE; + } + } // Byte reserved[0x78] + if (useBlob && blobPair.Len != 0) + { + #ifdef DMG_SHOW_RAW + CExtraFile &extra = _extras.AddNew(); + extra.Name = "_blob.bin"; + CByteBuffer &blobBuf = extra.Data; + #else + CByteBuffer blobBuf; + #endif + RINOK(ReadData(stream, blobPair, blobBuf)); + if (!ParseBlob(blobBuf)) + _headersError = true; + } + + CChecksum masterChecksum; masterChecksum.Parse(buf + 0x160); @@ -562,7 +720,7 @@ HRESULT CHandler::Open2(IInStream *stream) // We don't know the size of the field "offset" in rsrc. // We suppose that it uses 24 bits. So we use Rsrc, only if the rsrcLen < (1 << 24). - bool useRsrc = (rsrcLen > RSRC_HEAD_SIZE && rsrcLen < ((UInt32)1 << 24)); + bool useRsrc = (rsrcPair.Len > RSRC_HEAD_SIZE && rsrcPair.Len < ((UInt32)1 << 24)); // useRsrc = false; if (useRsrc) @@ -575,21 +733,18 @@ HRESULT CHandler::Open2(IInStream *stream) CByteBuffer rsrcBuf; #endif - size_t rsrcLenT = (size_t)rsrcLen; - rsrcBuf.Alloc(rsrcLenT); - RINOK(stream->Seek(_startPos + rsrcOffset, STREAM_SEEK_SET, NULL)); - RINOK(ReadStream_FALSE(stream, rsrcBuf, rsrcLenT)); + RINOK(ReadData(stream, rsrcPair, rsrcBuf)); const Byte *p = rsrcBuf; UInt32 headSize = Get32(p + 0); UInt32 footerOffset = Get32(p + 4); UInt32 mainDataSize = Get32(p + 8); UInt32 footerSize = Get32(p + 12); - if (headSize != RSRC_HEAD_SIZE || - footerOffset >= rsrcLenT || - mainDataSize >= rsrcLenT || - footerOffset + footerSize != rsrcLenT || - footerOffset != headSize + mainDataSize) + if (headSize != RSRC_HEAD_SIZE + || footerOffset >= rsrcPair.Len + || mainDataSize >= rsrcPair.Len + || footerOffset + footerSize != rsrcPair.Len + || footerOffset != headSize + mainDataSize) return S_FALSE; if (footerSize < 16) return S_FALSE; @@ -600,7 +755,7 @@ HRESULT CHandler::Open2(IInStream *stream) if ((UInt32)Get16(p + 0x18) != 0x1C) return S_FALSE; - UInt32 namesOffset = Get16(p + 0x1A); + const UInt32 namesOffset = Get16(p + 0x1A); if (namesOffset > footerSize) return S_FALSE; @@ -612,12 +767,15 @@ HRESULT CHandler::Open2(IInStream *stream) { const Byte *p2 = p + 0x1E + i * 8; - UInt32 typeId = Get32(p2); + const UInt32 typeId = Get32(p2); + + #ifndef DMG_SHOW_RAW if (typeId != 0x626C6B78) // blkx continue; + #endif - UInt32 numFiles = (UInt32)Get16(p2 + 4) + 1; - UInt32 offs = Get16(p2 + 6); + const UInt32 numFiles = (UInt32)Get16(p2 + 4) + 1; + const UInt32 offs = Get16(p2 + 6); if (0x1C + offs + 12 * numFiles > namesOffset) return S_FALSE; @@ -625,7 +783,7 @@ HRESULT CHandler::Open2(IInStream *stream) { const Byte *p3 = p + 0x1C + offs + k * 12; // UInt32 id = Get16(p3); - UInt32 namePos = Get16(p3 + 2); + const UInt32 namePos = Get16(p3 + 2); // Byte attributes = p3[4]; // = 0x50 for blkx // we don't know how many bits we can use. So we use 24 bits only UInt32 blockOffset = Get32(p3 + 4); @@ -634,21 +792,12 @@ HRESULT CHandler::Open2(IInStream *stream) if (blockOffset + 4 >= mainDataSize) return S_FALSE; const Byte *pBlock = rsrcBuf + headSize + blockOffset; - UInt32 blockSize = Get32(pBlock); - - #ifdef DMG_SHOW_RAW - { - CExtraFile &extra = _extras.AddNew(); - { - char extraName[16]; - ConvertUInt32ToString(_files.Size(), extraName); - extra.Name = extraName; - } - extra.Data.CopyFrom(pBlock + 4, blockSize); - } - #endif + const UInt32 blockSize = Get32(pBlock); + if (mainDataSize - (blockOffset + 4) < blockSize) + return S_FALSE; + + AString name; - CFile &file = _files.AddNew(); if (namePos != 0xFFFF) { UInt32 namesBlockSize = footerSize - namesOffset; @@ -663,22 +812,56 @@ HRESULT CHandler::Open2(IInStream *stream) Byte c = namePtr[r]; if (c < 0x20 || c >= 0x80) break; - file.Name += (char)c; + name += (char)c; + } + } + + if (typeId == 0x626C6B78) // blkx + { + CFile &file = _files.AddNew(); + file.Name = name; + RINOK(file.Parse(pBlock + 4, blockSize)); + } + + #ifdef DMG_SHOW_RAW + { + AString name2; + + name2.Add_UInt32(i); + name2 += '_'; + + { + char temp[4 + 1] = { 0 }; + memcpy(temp, p2, 4); + name2 += temp; + } + name2.Trim(); + name2 += '_'; + name2.Add_UInt32(k); + + if (!name.IsEmpty()) + { + name2 += '_'; + name2 += name; } + + CExtraFile &extra = _extras.AddNew(); + extra.Name = name2; + extra.Data.CopyFrom(pBlock + 4, blockSize); } - RINOK(file.Parse(pBlock + 4, blockSize)); + #endif } } } else { - if (xmlLen >= kXmlSizeMax || xmlLen == 0) + if (xmlPair.Len >= kXmlSizeMax || xmlPair.Len == 0) return S_FALSE; - size_t size = (size_t)xmlLen; - if (size != xmlLen) + size_t size = (size_t)xmlPair.Len; + if (size != xmlPair.Len) return S_FALSE; - RINOK(stream->Seek(_startPos + dataForkLen, STREAM_SEEK_SET, NULL)); + RINOK(stream->Seek(_startPos + xmlPair.Offset, STREAM_SEEK_SET, NULL)); CXml xml; { @@ -733,16 +916,12 @@ HRESULT CHandler::Open2(IInStream *stream) const Byte *endPtr = Base64ToBin(rawBuf, *dataString); if (!endPtr) return S_FALSE; - destLen = (unsigned)(endPtr - rawBuf); + destLen = (unsigned)(endPtr - (const Byte *)rawBuf); } #ifdef DMG_SHOW_RAW CExtraFile &extra = _extras.AddNew(); - { - char extraName[16]; - ConvertUInt32ToString(_files.Size(), extraName); - extra.Name = extraName; - } + extra.Name.Add_UInt32(_files.Size()); extra.Data.CopyFrom(rawBuf, destLen); #endif } @@ -800,6 +979,8 @@ STDMETHODIMP CHandler::Close() _inStream.Release(); _files.Clear(); _masterCrcError = false; + _headersError = false; + _name.Empty(); #ifdef DMG_SHOW_RAW _extras.Clear(); #endif @@ -867,9 +1048,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidPath: { UString name; - wchar_t s[16]; - ConvertUInt32ToString(index, s); - name = s; + name.Add_UInt32(index); unsigned num = 10; unsigned numDigits; for (numDigits = 1; num < _files.Size(); numDigits++) @@ -908,7 +1087,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } UString name2; ConvertUTF8ToUnicode(subName, name2); - name += L'.'; + name += '.'; name += name2; } else @@ -916,7 +1095,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val UString name2; ConvertUTF8ToUnicode(item.Name, name2); if (!name2.IsEmpty()) - name.AddAscii(" - "); + name += "_"; name += name2; } prop = name; diff --git a/CPP/7zip/Archive/ElfHandler.cpp b/CPP/7zip/Archive/ElfHandler.cpp index 4543b067..62674774 100644 --- a/CPP/7zip/Archive/ElfHandler.cpp +++ b/CPP/7zip/Archive/ElfHandler.cpp @@ -158,21 +158,21 @@ bool CHeader::Parse(const Byte *p) static const char * const g_SegnmentTypes[] = { - "Unused", - "Loadable segment", - "Dynamic linking tables", - "Program interpreter path name", - "Note section", - "SHLIB", - "Program header table", - "TLS" + "Unused" + , "Loadable segment" + , "Dynamic linking tables" + , "Program interpreter path name" + , "Note section" + , "SHLIB" + , "Program header table" + , "TLS" }; -static const CUInt32PCharPair g_SegmentFlags[] = +static const char * const g_SegmentFlags[] = { - { 0, "Execute" }, - { 1, "Write" }, - { 2, "Read" } + "Execute" + , "Write" + , "Read" }; struct CSegment @@ -359,173 +359,215 @@ bool CSection::Parse(const Byte *p, bool mode64, bool be) return true; } -static const CUInt32PCharPair g_Machines[] = + +static const char * const g_Machines[] = { - { 0, "None" }, - { 1, "AT&T WE 32100" }, - { 2, "SPARC" }, - { 3, "Intel 386" }, - { 4, "Motorola 68000" }, - { 5, "Motorola 88000" }, - { 6, "Intel 486" }, - { 7, "Intel i860" }, - { 8, "MIPS" }, - { 9, "IBM S/370" }, - { 10, "MIPS RS3000 LE" }, - { 11, "RS6000" }, - - { 15, "PA-RISC" }, - { 16, "nCUBE" }, - { 17, "Fujitsu VPP500" }, - { 18, "SPARC 32+" }, - { 19, "Intel i960" }, - { 20, "PowerPC" }, - { 21, "PowerPC 64-bit" }, - { 22, "IBM S/390" }, - { 23, "SPU" }, - - { 36, "NEX v800" }, - { 37, "Fujitsu FR20" }, - { 38, "TRW RH-32" }, - { 39, "Motorola RCE" }, - { 40, "ARM" }, - { 41, "Alpha" }, - { 42, "Hitachi SH" }, - { 43, "SPARC-V9" }, - { 44, "Siemens Tricore" }, - { 45, "ARC" }, - { 46, "H8/300" }, - { 47, "H8/300H" }, - { 48, "H8S" }, - { 49, "H8/500" }, - { 50, "IA-64" }, - { 51, "Stanford MIPS-X" }, - { 52, "Motorola ColdFire" }, - { 53, "M68HC12" }, - { 54, "Fujitsu MMA" }, - { 55, "Siemens PCP" }, - { 56, "Sony nCPU" }, - { 57, "Denso NDR1" }, - { 58, "Motorola StarCore" }, - { 59, "Toyota ME16" }, - { 60, "ST100" }, - { 61, "Advanced Logic TinyJ" }, - { 62, "AMD64" }, - { 63, "Sony DSP" }, - - - { 66, "Siemens FX66" }, - { 67, "ST9+" }, - { 68, "ST7" }, - { 69, "MC68HC16" }, - { 70, "MC68HC11" }, - { 71, "MC68HC08" }, - { 72, "MC68HC05" }, - { 73, "Silicon Graphics SVx" }, - { 74, "ST19" }, - { 75, "Digital VAX" }, - { 76, "Axis CRIS" }, - { 77, "Infineon JAVELIN" }, - { 78, "Element 14 FirePath" }, - { 79, "LSI ZSP" }, - { 80, "MMIX" }, - { 81, "HUANY" }, - { 82, "SiTera Prism" }, - { 83, "Atmel AVR" }, - { 84, "Fujitsu FR30" }, - { 85, "Mitsubishi D10V" }, - { 86, "Mitsubishi D30V" }, - { 87, "NEC v850" }, - { 88, "Mitsubishi M32R" }, - { 89, "Matsushita MN10300" }, - { 90, "Matsushita MN10200" }, - { 91, "picoJava" }, - { 92, "OpenRISC" }, - { 93, "ARC Tangent-A5" }, - { 94, "Tensilica Xtensa" }, - { 95, "Alphamosaic VideoCore" }, - { 96, "Thompson MM GPP" }, - { 97, "National Semiconductor 32K" }, - { 98, "Tenor Network TPC" }, - { 99, "Trebia SNP 1000" }, - { 100, "ST200" }, - { 101, "Ubicom IP2xxx" }, - { 102, "MAX" }, - { 103, "NS CompactRISC" }, - { 104, "Fujitsu F2MC16" }, - { 105, "TI msp430" }, - { 106, "Blackfin (DSP)" }, - { 107, "SE S1C33" }, - { 108, "Sharp embedded" }, - { 109, "Arca RISC" }, - { 110, "Unicore" }, - { 111, "eXcess" }, - { 112, "DXP" }, - { 113, "Altera Nios II" }, - { 114, "NS CRX" }, - { 115, "Motorola XGATE" }, - { 116, "Infineon C16x/XC16x" }, - { 117, "Renesas M16C" }, - { 118, "Microchip Technology dsPIC30F" }, - { 119, "Freescale CE" }, - { 120, "Renesas M32C" }, - - { 131, "Altium TSK3000" }, - { 132, "Freescale RS08" }, - { 133, "Analog Devices SHARC" }, - { 134, "Cyan Technology eCOG2" }, - { 135, "Sunplus S+core7 RISC" }, - { 136, "NJR 24-bit DSP" }, - { 137, "Broadcom VideoCore III" }, - { 138, "Lattice FPGA" }, - { 139, "SE C17" }, - { 140, "TI TMS320C6000" }, - { 141, "TI TMS320C2000" }, - { 142, "TI TMS320C55x" }, - - { 160, "STM 64bit VLIW Data Signal" }, - { 161, "Cypress M8C" }, - { 162, "Renesas R32C" }, - { 163, "NXP TriMedia" }, - { 164, "Qualcomm Hexagon" }, - { 165, "Intel 8051" }, - { 166, "STMicroelectronics STxP7x" }, - { 167, "Andes" }, - { 168, "Cyan Technology eCOG1X" }, - { 169, "Dallas Semiconductor MAXQ30" }, - { 170, "NJR 16-bit DSP" }, - { 171, "M2000" }, - { 172, "Cray NV2" }, - { 173, "Renesas RX" }, - { 174, "Imagination Technologies META" }, - { 175, "MCST Elbrus" }, - { 176, "Cyan Technology eCOG16" }, - { 177, "National Semiconductor CR16" }, - { 178, "Freescale ETPUnit" }, - { 179, "Infineon SLE9X" }, - { 180, "Intel L10M" }, - { 181, "Intel K10M" }, - - { 183, "ARM64" }, - - { 185, "Atmel AVR32" }, - { 186, "STM8" }, - { 187, "Tilera TILE64" }, - { 188, "Tilera TILEPro" }, - { 189, "Xilinx MicroBlaze" }, - { 190, "NVIDIA CUDA" }, - { 191, "Tilera TILE-Gx" }, - { 192, "CloudShield" }, - { 193, "KIPO-KAIST Core-A 1st" }, - { 194, "KIPO-KAIST Core-A 2nd" }, - { 195, "Synopsys ARCompact V2" }, - { 196, "Open8" }, - { 197, "Renesas RL78" }, - { 198, "Broadcom VideoCore V" }, - { 199, "Renesas 78KOR" }, - { 200, "Freescale 56800EX" }, - - { 47787, "Xilinx MicroBlaze" }, + "None" + , "AT&T WE 32100" + , "SPARC" + , "Intel 386" + , "Motorola 68000" + , "Motorola 88000" + , "Intel 486" + , "Intel i860" + , "MIPS" + , "IBM S/370" + , "MIPS RS3000 LE" + , "RS6000" + , NULL + , NULL + , NULL + , "PA-RISC" + , "nCUBE" + , "Fujitsu VPP500" + , "SPARC 32+" + , "Intel i960" + , "PowerPC" + , "PowerPC 64-bit" + , "IBM S/390" + , "SPU" + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , "NEX v800" + , "Fujitsu FR20" + , "TRW RH-32" + , "Motorola RCE" + , "ARM" + , "Alpha" + , "Hitachi SH" + , "SPARC-V9" + , "Siemens Tricore" + , "ARC" + , "H8/300" + , "H8/300H" + , "H8S" + , "H8/500" + , "IA-64" + , "Stanford MIPS-X" + , "Motorola ColdFire" + , "M68HC12" + , "Fujitsu MMA" + , "Siemens PCP" + , "Sony nCPU" + , "Denso NDR1" + , "Motorola StarCore" + , "Toyota ME16" + , "ST100" + , "Advanced Logic TinyJ" + , "AMD64" + , "Sony DSP" + , NULL + , NULL + , "Siemens FX66" + , "ST9+" + , "ST7" + , "MC68HC16" + , "MC68HC11" + , "MC68HC08" + , "MC68HC05" + , "Silicon Graphics SVx" + , "ST19" + , "Digital VAX" + , "Axis CRIS" + , "Infineon JAVELIN" + , "Element 14 FirePath" + , "LSI ZSP" + , "MMIX" + , "HUANY" + , "SiTera Prism" + , "Atmel AVR" + , "Fujitsu FR30" + , "Mitsubishi D10V" + , "Mitsubishi D30V" + , "NEC v850" + , "Mitsubishi M32R" + , "Matsushita MN10300" + , "Matsushita MN10200" + , "picoJava" + , "OpenRISC" + , "ARC Tangent-A5" + , "Tensilica Xtensa" + , "Alphamosaic VideoCore" + , "Thompson MM GPP" + , "National Semiconductor 32K" + , "Tenor Network TPC" + , "Trebia SNP 1000" + , "ST200" + , "Ubicom IP2xxx" + , "MAX" + , "NS CompactRISC" + , "Fujitsu F2MC16" + , "TI msp430" + , "Blackfin (DSP)" + , "SE S1C33" + , "Sharp embedded" + , "Arca RISC" + , "Unicore" + , "eXcess" + , "DXP" + , "Altera Nios II" + , "NS CRX" + , "Motorola XGATE" + , "Infineon C16x/XC16x" + , "Renesas M16C" + , "Microchip Technology dsPIC30F" + , "Freescale CE" + , "Renesas M32C" + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , "Altium TSK3000" + , "Freescale RS08" + , "Analog Devices SHARC" + , "Cyan Technology eCOG2" + , "Sunplus S+core7 RISC" + , "NJR 24-bit DSP" + , "Broadcom VideoCore III" + , "Lattice FPGA" + , "SE C17" + , "TI TMS320C6000" + , "TI TMS320C2000" + , "TI TMS320C55x" + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , "STM 64bit VLIW Data Signal" + , "Cypress M8C" + , "Renesas R32C" + , "NXP TriMedia" + , "Qualcomm Hexagon" + , "Intel 8051" + , "STMicroelectronics STxP7x" + , "Andes" + , "Cyan Technology eCOG1X" + , "Dallas Semiconductor MAXQ30" + , "NJR 16-bit DSP" + , "M2000" + , "Cray NV2" + , "Renesas RX" + , "Imagination Technologies META" + , "MCST Elbrus" + , "Cyan Technology eCOG16" + , "National Semiconductor CR16" + , "Freescale ETPUnit" + , "Infineon SLE9X" + , "Intel L10M" + , "Intel K10M" + , NULL + , "ARM64" + , NULL + , "Atmel AVR32" + , "STM8" + , "Tilera TILE64" + , "Tilera TILEPro" + , "Xilinx MicroBlaze" + , "NVIDIA CUDA" + , "Tilera TILE-Gx" + , "CloudShield" + , "KIPO-KAIST Core-A 1st" + , "KIPO-KAIST Core-A 2nd" + , "Synopsys ARCompact V2" + , "Open8" + , "Renesas RL78" + , "Broadcom VideoCore V" + , "Renesas 78KOR" + , "Freescale 56800EX" // 200 +}; + +static const CUInt32PCharPair g_MachinePairs[] = +{ + { 47787, "Xilinx MicroBlaze" } // { 0x9026, "Alpha" } }; @@ -554,6 +596,7 @@ static const CUInt32PCharPair g_OS[] = { 255, "Standalone" } }; +#define k_Machine_MIPS 8 #define k_Machine_ARM 40 /* @@ -566,12 +609,29 @@ static const CUInt32PCharPair g_OS[] = static const CUInt32PCharPair g_ARM_Flags[] = { + { 1, "HasEntry" }, { 9, "SF" }, { 10, "HF" }, { 23, "BE8" } }; +static const CUInt32PCharPair g_MIPS_Flags[] = +{ + { 0, "NOREORDER" }, + { 1, "PIC" }, + { 2, "CPIC" }, + { 3, "XGOT" }, + { 4, "64BIT_WHIRL" }, + { 5, "ABI2" }, + { 6, "ABI_ON32" }, + { 10, "NAN2008" }, + { 25, "MicroMIPS" }, + { 26, "M16" }, + { 27, "MDMX" } +}; + + #define ET_NONE 0 #define ET_REL 1 #define ET_EXEC 2 @@ -580,11 +640,11 @@ static const CUInt32PCharPair g_ARM_Flags[] = static const char * const g_Types[] = { - "None", - "Relocatable file", - "Executable file", - "Shared object file", - "Core file" + "None" + , "Relocatable file" + , "Executable file" + , "Shared object file" + , "Core file" }; @@ -643,8 +703,7 @@ static const Byte kArcProps[] = kpidBigEndian, kpidHostOS, kpidCharacts, - kpidHeadersSize, - kpidName + kpidHeadersSize }; enum @@ -683,21 +742,49 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidCpu: { - AString s = TypePairToString(g_Machines, ARRAY_SIZE(g_Machines), _header.Machine); + AString s; + if (_header.Machine < ARRAY_SIZE(g_Machines)) + { + const char *name = g_Machines[_header.Machine]; + if (name) + s = name; + } + if (s.IsEmpty()) + s = TypePairToString(g_MachinePairs, ARRAY_SIZE(g_MachinePairs), _header.Machine); UInt32 flags = _header.Flags; if (flags != 0) { - char sz[16]; s.Add_Space(); if (_header.Machine == k_Machine_ARM) { s += FlagsToString(g_ARM_Flags, ARRAY_SIZE(g_ARM_Flags), flags & (((UInt32)1 << 24) - 1)); s += " ABI:"; - ConvertUInt32ToString(flags >> 24, sz); + s.Add_UInt32(flags >> 24); + } + else if (_header.Machine == k_Machine_MIPS) + { + UInt32 ver = flags >> 28; + s += "v"; + s.Add_UInt32(ver); + flags &= (((UInt32)1 << 28) - 1); + + UInt32 abi = (flags >> 12) & 7; + if (abi != 0) + { + s += " ABI:"; + s.Add_UInt32(abi); + } + flags &= ~((UInt32)7 << 12); + + s.Add_Space(); + s += FlagsToString(g_MIPS_Flags, ARRAY_SIZE(g_MIPS_Flags), flags); } else + { + char sz[16]; ConvertUInt32ToHex(flags, sz); - s += sz; + s += sz; + } } prop = s; break; diff --git a/CPP/7zip/Archive/ExtHandler.cpp b/CPP/7zip/Archive/ExtHandler.cpp index 6c2cd726..3b690d07 100644 --- a/CPP/7zip/Archive/ExtHandler.cpp +++ b/CPP/7zip/Archive/ExtHandler.cpp @@ -20,7 +20,6 @@ #include "../../../C/CpuArch.h" #include "../../Common/ComTry.h" -#include "../../Common/IntToString.h" #include "../../Common/MyLinux.h" #include "../../Common/StringConvert.h" #include "../../Common/UTFConvert.h" @@ -37,6 +36,8 @@ using namespace NWindows; +UInt32 LzhCrc16Update(UInt32 crc, const void *data, size_t size); + namespace NArchive { namespace NExt { @@ -87,33 +88,9 @@ static UInt32 Crc32C_Calc(Byte const *data, size_t size) */ -// CRC-16-ANSI. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) -static UInt16 g_Crc16Table[256]; - -static struct CInitCrc16 -{ - CInitCrc16() - { - for (unsigned i = 0; i < 256; i++) - { - UInt32 r = i; - unsigned j; - for (j = 0; j < 8; j++) - r = (r >> 1) ^ (0xA001 & ~((r & 1) - 1)); - g_Crc16Table[i] = (UInt16)r; - } - } -} g_InitCrc16; - -#define CRC16_UPDATE_BYTE(crc, b) (g_Crc16Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) #define CRC16_INIT_VAL 0xFFFF -static UInt32 Crc16Update(UInt32 crc, Byte const *data, size_t size) -{ - for (size_t i = 0; i < size; i++) - crc = CRC16_UPDATE_BYTE(crc, data[i]); - return crc; -} +#define Crc16Update(crc, data, size) LzhCrc16Update(crc, data, size) static UInt32 Crc16Calc(Byte const *data, size_t size) { @@ -161,64 +138,64 @@ static const char * const kHostOS[] = , "Lites" }; -static const CUInt32PCharPair g_FeatureCompat_Flags[] = -{ - { 0, "DIR_PREALLOC" }, - { 1, "IMAGIC_INODES" }, - { 2, "HAS_JOURNAL" }, - { 3, "EXT_ATTR" }, - { 4, "RESIZE_INODE" }, - { 5, "DIR_INDEX" }, - { 6, "LAZY_BG" }, // not in Linux - // { 7, "EXCLUDE_INODE" }, // not used - // { 8, "EXCLUDE_BITMAP" }, // not in kernel - { 9, "SPARSE_SUPER2" } +static const char * const g_FeatureCompat_Flags[] = +{ + "DIR_PREALLOC" + , "IMAGIC_INODES" + , "HAS_JOURNAL" + , "EXT_ATTR" + , "RESIZE_INODE" + , "DIR_INDEX" + , "LAZY_BG" // not in Linux + , NULL // { 7, "EXCLUDE_INODE" // not used + , NULL // { 8, "EXCLUDE_BITMAP" // not in kernel + , "SPARSE_SUPER2" }; #define EXT4_FEATURE_INCOMPAT_FILETYPE (1 << 1) #define EXT4_FEATURE_INCOMPAT_64BIT (1 << 7) -static const CUInt32PCharPair g_FeatureIncompat_Flags[] = -{ - { 0, "COMPRESSION" }, - { 1, "FILETYPE" }, - { 2, "RECOVER" }, /* Needs recovery */ - { 3, "JOURNAL_DEV" }, /* Journal device */ - { 4, "META_BG" }, - - { 6, "EXTENTS" }, /* extents support */ - { 7, "64BIT" }, - { 8, "MMP" }, - { 9, "FLEX_BG" }, - { 10, "EA_INODE" }, /* EA in inode */ - - { 12, "DIRDATA" }, /* data in dirent */ - { 13, "BG_USE_META_CSUM" }, /* use crc32c for bg */ - { 14, "LARGEDIR" }, /* >2GB or 3-lvl htree */ - { 15, "INLINE_DATA" }, /* data in inode */ - { 16, "ENCRYPT" } +static const char * const g_FeatureIncompat_Flags[] = +{ + "COMPRESSION" + , "FILETYPE" + , "RECOVER" /* Needs recovery */ + , "JOURNAL_DEV" /* Journal device */ + , "META_BG" + , NULL + , "EXTENTS" /* extents support */ + , "64BIT" + , "MMP" + , "FLEX_BG" + , "EA_INODE" /* EA in inode */ + , NULL + , "DIRDATA" /* data in dirent */ + , "BG_USE_META_CSUM" /* use crc32c for bg */ + , "LARGEDIR" /* >2GB or 3-lvl htree */ + , "INLINE_DATA" /* data in inode */ + , "ENCRYPT" // 16 }; static const UInt32 RO_COMPAT_GDT_CSUM = 1 << 4; static const UInt32 RO_COMPAT_METADATA_CSUM = 1 << 10; -static const CUInt32PCharPair g_FeatureRoCompat_Flags[] = -{ - { 0, "SPARSE_SUPER" }, - { 1, "LARGE_FILE" }, - { 2, "BTREE_DIR" }, - { 3, "HUGE_FILE" }, - { 4, "GDT_CSUM" }, - { 5, "DIR_NLINK" }, - { 6, "EXTRA_ISIZE" }, - { 7, "HAS_SNAPSHOT" }, - { 8, "QUOTA" }, - { 9, "BIGALLOC" }, - { 10, "METADATA_CSUM" }, - { 11, "REPLICA" }, - { 12, "READONLY" } +static const char * const g_FeatureRoCompat_Flags[] = +{ + "SPARSE_SUPER" + , "LARGE_FILE" + , "BTREE_DIR" + , "HUGE_FILE" + , "GDT_CSUM" + , "DIR_NLINK" + , "EXTRA_ISIZE" + , "HAS_SNAPSHOT" + , "QUOTA" + , "BIGALLOC" + , "METADATA_CSUM" + , "REPLICA" + , "READONLY" // 12 }; @@ -227,33 +204,37 @@ static const UInt32 k_NodeFlags_HUGE = (UInt32)1 << 18; static const UInt32 k_NodeFlags_EXTENTS = (UInt32)1 << 19; -static const CUInt32PCharPair g_NodeFlags[] = -{ - { 0, "SECRM" }, - { 1, "UNRM" }, - { 2, "COMPR" }, - { 3, "SYNC" }, - { 4, "IMMUTABLE" }, - { 5, "APPEND" }, - { 6, "NODUMP" }, - { 7, "NOATIME" }, - { 8, "DIRTY" }, - { 9, "COMPRBLK" }, - { 10, "NOCOMPR" }, - { 11, "ENCRYPT" }, - { 12, "INDEX" }, - { 13, "IMAGIC" }, - { 14, "JOURNAL_DATA" }, - { 15, "NOTAIL" }, - { 16, "DIRSYNC" }, - { 17, "TOPDIR" }, - { 18, "HUGE_FILE" }, - { 19, "EXTENTS" }, - - { 21, "EA_INODE" }, - { 22, "EOFBLOCKS" }, - - { 28, "INLINE_DATA" } +static const char * const g_NodeFlags[] = +{ + "SECRM" + , "UNRM" + , "COMPR" + , "SYNC" + , "IMMUTABLE" + , "APPEND" + , "NODUMP" + , "NOATIME" + , "DIRTY" + , "COMPRBLK" + , "NOCOMPR" + , "ENCRYPT" + , "INDEX" + , "IMAGIC" + , "JOURNAL_DATA" + , "NOTAIL" + , "DIRSYNC" + , "TOPDIR" + , "HUGE_FILE" + , "EXTENTS" + , NULL + , "EA_INODE" + , "EOFBLOCKS" + , NULL + , NULL + , NULL + , NULL + , NULL + , "INLINE_DATA" // 28 }; @@ -1540,20 +1521,16 @@ HRESULT CHandler::Open2(IInStream *inStream) useUnknown = true; if (item.Name.IsEmpty()) - { - char temp[16]; - ConvertUInt32ToString(item.Node, temp); - item.Name = temp; - } + item.Name.Add_UInt32(item.Node); _items.Add(item); } } if (useSys) - _auxSysIndex = _auxItems.Add("[SYS]"); + _auxSysIndex = _auxItems.Add((AString)"[SYS]"); if (useUnknown) - _auxUnknownIndex = _auxItems.Add("[UNKNOWN]"); + _auxUnknownIndex = _auxItems.Add((AString)"[UNKNOWN]"); } return S_OK; @@ -1834,16 +1811,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidHostOS: { - char temp[16]; - const char *s = NULL; - if (_h.CreatorOs < ARRAY_SIZE(kHostOS)) - s = kHostOS[_h.CreatorOs]; - else - { - ConvertUInt32ToString(_h.CreatorOs, temp); - s = temp; - } - prop = s; + TYPE_TO_PROP(kHostOS, _h.CreatorOs, prop); break; } @@ -1995,39 +1963,34 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data static void ExtTimeToProp(const CExtTime &t, NCOM::CPropVariant &prop) { - /* - UInt32 nano = 0; - if (t.Extra != 0) - { - UInt32 mask = t.Extra & 3; - if (mask != 0) - return; - nano = t.Extra >> 2; - } - UInt64 v; - if (t.Val == 0 && nano == 0) + if (t.Val == 0 && t.Extra == 0) return; - if (!NTime::UnixTime_to_FileTime64(t.Val, v)) - return; - if (nano != 0) - v += nano / 100; FILETIME ft; - ft.dwLowDateTime = (DWORD)v; - ft.dwHighDateTime = (DWORD)(v >> 32); - prop = ft; - */ - if (t.Val == 0) - return; - if (t.Extra != 0) + // if (t.Extra != 0) { - UInt32 mask = t.Extra & 3; - if (mask != 0) - return; + // 1901-2446 : + Int64 v = (Int64)(Int32)t.Val; + v += (UInt64)(t.Extra & 3) << 32; // 2 low bits are offset for main timestamp + UInt64 ft64 = NTime::UnixTime64ToFileTime64(v); + const UInt32 ns = (t.Extra >> 2); + if (ns < 1000000000) + ft64 += ns / 100; + ft.dwLowDateTime = (DWORD)ft64; + ft.dwHighDateTime = (DWORD)(ft64 >> 32); } - FILETIME ft; - if (NTime::UnixTime64ToFileTime(t.Val, ft)) - prop = ft; + /* + else + { + // 1901-2038 : that code is good for ext4 and compatibility with Extra + NTime::UnixTime64ToFileTime((Int32)t.Val, ft); // for + + // 1970-2106 : that code is good if timestamp is used as unsigned 32-bit + // are there such systems? + // NTime::UnixTimeToFileTime(t.Val, ft); // for + } + */ + prop = ft; } @@ -2043,8 +2006,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidPath: case kpidName: { - AString s = _auxItems[index - _items.Size()]; - prop = s; + prop = _auxItems[index - _items.Size()]; break; } case kpidIsDir: prop = true; break; diff --git a/CPP/7zip/Archive/GptHandler.cpp b/CPP/7zip/Archive/GptHandler.cpp index 52c7aab9..a86ad37c 100644 --- a/CPP/7zip/Archive/GptHandler.cpp +++ b/CPP/7zip/Archive/GptHandler.cpp @@ -123,33 +123,11 @@ static int FindPartType(const Byte *guid) return -1; } -static inline char GetHex(unsigned t) { return (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))); } -static void PrintHex(unsigned v, char *s) +static void RawLeGuidToString_Upper(const Byte *g, char *s) { - s[0] = GetHex((v >> 4) & 0xF); - s[1] = GetHex(v & 0xF); -} - -static void ConvertUInt16ToHex4Digits(UInt32 val, char *s) throw() -{ - PrintHex(val >> 8, s); - PrintHex(val & 0xFF, s + 2); -} - -static void GuidToString(const Byte *g, char *s) -{ - ConvertUInt32ToHex8Digits(Get32(g ), s); s += 8; *s++ = '-'; - ConvertUInt16ToHex4Digits(Get16(g + 4), s); s += 4; *s++ = '-'; - ConvertUInt16ToHex4Digits(Get16(g + 6), s); s += 4; *s++ = '-'; - for (unsigned i = 0; i < 8; i++) - { - if (i == 2) - *s++ = '-'; - PrintHex(g[8 + i], s); - s += 2; - } - *s = 0; + RawLeGuidToString(g, s); + // MyStringUpper_Ascii(s); } @@ -328,7 +306,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidId: { char s[48]; - GuidToString(Guid, s); + RawLeGuidToString_Upper(Guid, s); prop = s; break; } @@ -364,18 +342,16 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val s += c; } if (s.IsEmpty()) + s.Add_UInt32(index); { - char temp[16]; - ConvertUInt32ToString(index, temp); - s.AddAscii(temp); - } - { + s += '.'; + const char *ext = NULL; int typeIndex = FindPartType(item.Type); - s += L'.'; - const char *ext = "img"; - if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Ext) + if (typeIndex >= 0) ext = kPartTypes[(unsigned)typeIndex].Ext; - s.AddAscii(ext); + if (!ext) + ext = "img"; + s += ext; } prop = s; break; @@ -394,7 +370,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val res = kPartTypes[(unsigned)typeIndex].Type; else { - GuidToString(item.Type, s); + RawLeGuidToString_Upper(item.Type, s); res = s; } prop = res; @@ -404,7 +380,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidId: { char s[48]; - GuidToString(item.Id, s); + RawLeGuidToString_Upper(item.Id, s); prop = s; break; } diff --git a/CPP/7zip/Archive/GzHandler.cpp b/CPP/7zip/Archive/GzHandler.cpp index d8979ada..130f8b35 100644 --- a/CPP/7zip/Archive/GzHandler.cpp +++ b/CPP/7zip/Archive/GzHandler.cpp @@ -11,6 +11,7 @@ #include "../../Common/StringConvert.h" #include "../../Windows/PropVariant.h" +#include "../../Windows/PropVariantUtils.h" #include "../../Windows/TimeUtils.h" #include "../Common/ProgressUtils.h" @@ -109,7 +110,6 @@ static const char * const kHostOSes[] = , "OS/X" }; -static const char *kUnknownOS = "Unknown"; class CItem { @@ -537,7 +537,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) if (_item.NameIsPresent()) { UString s = MultiByteToUnicodeString(_item.Name, CP_ACP); - s.AddAscii(".gz"); + s += ".gz"; prop = s; } break; @@ -587,8 +587,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN prop = _packSize; break; } - case kpidHostOS: prop = (_item.HostOS < ARRAY_SIZE(kHostOSes)) ? - kHostOSes[_item.HostOS] : kUnknownOS; break; + case kpidHostOS: TYPE_TO_PROP(kHostOSes, _item.HostOS, prop); break; case kpidCRC: if (_stream) prop = _item.Crc; break; } prop.Detach(value); @@ -1035,7 +1034,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR static const Byte k_Signature[] = { kSignature_0, kSignature_1, kSignature_2 }; REGISTER_ARC_IO( - "gzip", "gz gzip tgz tpz", "* * .tar .tar", 0xEF, + "gzip", "gz gzip tgz tpz apk", "* * .tar .tar .tar", 0xEF, k_Signature, 0, NArcInfoFlags::kKeepName, diff --git a/CPP/7zip/Archive/HfsHandler.cpp b/CPP/7zip/Archive/HfsHandler.cpp index 185df7f0..d02f0725 100644 --- a/CPP/7zip/Archive/HfsHandler.cpp +++ b/CPP/7zip/Archive/HfsHandler.cpp @@ -28,7 +28,7 @@ namespace NArchive { namespace NHfs { -static const char *kResFileName = "rsrc"; // "com.apple.ResourceFork"; +static const char * const kResFileName = "rsrc"; // "com.apple.ResourceFork"; struct CExtent { @@ -497,11 +497,14 @@ struct CHeaderRec // UInt32 Attributes; // UInt32 Reserved3[16]; - HRESULT Parse(const Byte *p); + HRESULT Parse2(const CByteBuffer &buf); }; -HRESULT CHeaderRec::Parse(const Byte *p) +HRESULT CHeaderRec::Parse2(const CByteBuffer &buf) { + if (buf.Size() < kNodeDescriptor_Size + 0x2A + 16 * 4) + return S_FALSE; + const Byte * p = (const Byte *)buf + kNodeDescriptor_Size; // TreeDepth = Get16(p); // RootNode = Get32(p + 2); // LeafRecords = Get32(p + 6); @@ -527,6 +530,10 @@ HRESULT CHeaderRec::Parse(const Byte *p) for (int i = 0; i < 16; i++) Reserved3[i] = Get32(p + 0x2A + i * 4); */ + + if ((buf.Size() >> NodeSizeLog) < TotalNodes) + return S_FALSE; + return S_OK; } @@ -553,10 +560,7 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec // CNodeDescriptor nodeDesc; // nodeDesc.Parse(p); CHeaderRec hr; - RINOK(hr.Parse(p + kNodeDescriptor_Size)); - - if ((buf.Size() >> hr.NodeSizeLog) < hr.TotalNodes) - return S_FALSE; + RINOK(hr.Parse2(buf)); UInt32 node = hr.FirstLeafNode; if (node == 0) @@ -695,13 +699,10 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe // CNodeDescriptor nodeDesc; // nodeDesc.Parse(p); CHeaderRec hr; - RINOK(hr.Parse(p + kNodeDescriptor_Size)); + RINOK(hr.Parse2(AttrBuf)); // CaseSensetive = (Header.IsHfsX() && hr.KeyCompareType == 0xBC); - if ((AttrBuf.Size() >> hr.NodeSizeLog) < hr.TotalNodes) - return S_FALSE; - UInt32 node = hr.FirstLeafNode; if (node == 0) return S_OK; @@ -876,13 +877,10 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents // CNodeDescriptor nodeDesc; // nodeDesc.Parse(p); CHeaderRec hr; - RINOK(hr.Parse(p + kNodeDescriptor_Size)); + RINOK(hr.Parse2(buf)); // CaseSensetive = (Header.IsHfsX() && hr.KeyCompareType == 0xBC); - if ((buf.Size() >> hr.NodeSizeLog) < hr.TotalNodes) - return S_FALSE; - CByteBuffer usedBuf(hr.TotalNodes); memset(usedBuf, 0, hr.TotalNodes); @@ -966,13 +964,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.SetFromAscii("[HFS+ Private Data]"); + item.Name = "[HFS+ Private Data]"; } } // Some dmg files have ' ' folder item. if (item.Name.IsEmpty() || item.Name[0] == L' ') - item.Name.SetFromAscii("[]"); + item.Name = "[]"; } } @@ -1228,7 +1226,7 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress) return S_FALSE; */ - ResFileName.SetFromAscii(kResFileName); + ResFileName = kResFileName; CFork extentsFork, catalogFork, attrFork; // allocationFork.Parse(p + 0x70 + 0x50 * 0); diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp index 5a19516c..2230cd23 100644 --- a/CPP/7zip/Archive/Iso/IsoHandler.cpp +++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp @@ -3,7 +3,6 @@ #include "StdAfx.h" #include "../../../Common/ComTry.h" -#include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #include "../../../Windows/PropVariant.h" @@ -176,12 +175,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { case kpidPath: { - AString s = "[BOOT]" STRING_PATH_SEPARATOR; + AString s ("[BOOT]" STRING_PATH_SEPARATOR); if (_archive.BootEntries.Size() != 1) { - char temp[16]; - ConvertUInt32ToString(index + 1, temp); - s += temp; + s.Add_UInt32(index + 1); s += '-'; } s += be.GetName(); @@ -216,7 +213,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val if (!s.IsEmpty() && s.Back() == L'.') s.DeleteBack(); - NItemName::ConvertToOSName2(s); + NItemName::ReplaceToOsSlashes_Remove_TailSlash(s); prop = s; } break; diff --git a/CPP/7zip/Archive/Iso/IsoHeader.cpp b/CPP/7zip/Archive/Iso/IsoHeader.cpp index 59c283c1..3b59060a 100644 --- a/CPP/7zip/Archive/Iso/IsoHeader.cpp +++ b/CPP/7zip/Archive/Iso/IsoHeader.cpp @@ -7,6 +7,6 @@ namespace NArchive { namespace NIso { -const char *kElToritoSpec = "EL TORITO SPECIFICATION\0\0\0\0\0\0\0\0\0"; +const char * const kElToritoSpec = "EL TORITO SPECIFICATION\0\0\0\0\0\0\0\0\0"; }} diff --git a/CPP/7zip/Archive/Iso/IsoHeader.h b/CPP/7zip/Archive/Iso/IsoHeader.h index db0b1df9..e6a4d327 100644 --- a/CPP/7zip/Archive/Iso/IsoHeader.h +++ b/CPP/7zip/Archive/Iso/IsoHeader.h @@ -25,7 +25,7 @@ namespace NFileFlags const Byte kNonFinalExtent = 1 << 7; } -extern const char *kElToritoSpec; +extern const char * const kElToritoSpec; const UInt32 kStartPos = 0x8000; diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp index 8530a25e..65be1146 100644 --- a/CPP/7zip/Archive/Iso/IsoIn.cpp +++ b/CPP/7zip/Archive/Iso/IsoIn.cpp @@ -47,17 +47,13 @@ bool CBootInitialEntry::Parse(const Byte *p) AString CBootInitialEntry::GetName() const { - AString s = (Bootable ? "Boot" : "NotBoot"); + AString s (Bootable ? "Boot" : "NotBoot"); s += '-'; if (BootMediaType < ARRAY_SIZE(kMediaTypes)) s += kMediaTypes[BootMediaType]; else - { - char name[16]; - ConvertUInt32ToString(BootMediaType, name); - s += name; - } + s.Add_UInt32(BootMediaType); if (VendorSpec[0] == 1) { diff --git a/CPP/7zip/Archive/Iso/IsoIn.h b/CPP/7zip/Archive/Iso/IsoIn.h index 4000fc92..347f9e9b 100644 --- a/CPP/7zip/Archive/Iso/IsoIn.h +++ b/CPP/7zip/Archive/Iso/IsoIn.h @@ -3,7 +3,6 @@ #ifndef __ARCHIVE_ISO_IN_H #define __ARCHIVE_ISO_IN_H -#include "../../../Common/IntToString.h" #include "../../../Common/MyCom.h" #include "../../IStream.h" diff --git a/CPP/7zip/Archive/Iso/IsoItem.h b/CPP/7zip/Archive/Iso/IsoItem.h index c4950e60..5ae13a60 100644 --- a/CPP/7zip/Archive/Iso/IsoItem.h +++ b/CPP/7zip/Archive/Iso/IsoItem.h @@ -223,6 +223,7 @@ struct CDirRecord const bool GetPx(int skipSize, unsigned pxType, UInt32 &val) const { + val = 0; const Byte *p = NULL; unsigned len = 0; p = FindSuspRecord(skipSize, 'P', 'X', len); diff --git a/CPP/7zip/Archive/LzhHandler.cpp b/CPP/7zip/Archive/LzhHandler.cpp index c8d3ff6d..53d69db7 100644 --- a/CPP/7zip/Archive/LzhHandler.cpp +++ b/CPP/7zip/Archive/LzhHandler.cpp @@ -9,6 +9,7 @@ #include "../../Common/StringConvert.h" #include "../../Windows/PropVariant.h" +#include "../../Windows/PropVariantUtils.h" #include "../../Windows/TimeUtils.h" #include "../ICoder.h" @@ -31,10 +32,44 @@ using namespace NTime; #define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) + +// CRC-16 (-IBM, -ANSI). The poly is 0x8005 (x^16 + x^15 + x^2 + 1) + +static const UInt16 kCrc16Poly = 0xA001; + +static UInt16 g_LzhCrc16Table[256]; + +#define CRC16_UPDATE_BYTE(crc, b) (g_LzhCrc16Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt32 LzhCrc16Update(UInt32 crc, const void *data, size_t size) +{ + const Byte *p = (const Byte *)data; + const Byte *pEnd = p + size; + for (; p != pEnd; p++) + crc = CRC16_UPDATE_BYTE(crc, *p); + return crc; +} + +static class CLzhCrc16TableInit +{ +public: + CLzhCrc16TableInit() + { + for (UInt32 i = 0; i < 256; i++) + { + UInt32 r = i; + for (unsigned j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrc16Poly & ((UInt32)0 - (r & 1))); + g_LzhCrc16Table[i] = (UInt16)r; + } + } +} g_LzhCrc16TableInit; + + namespace NArchive { namespace NLzh{ -const int kMethodIdSize = 5; +const unsigned kMethodIdSize = 5; const Byte kExtIdFileName = 0x01; const Byte kExtIdDirName = 0x02; @@ -125,7 +160,7 @@ struct CItem return false; } - int GetNumDictBits() const + unsigned GetNumDictBits() const { if (!IsLhMethod()) return 0; @@ -185,7 +220,7 @@ struct CItem AString GetName() const { - AString dirName = GetDirName(); + AString dirName (GetDirName()); const char kDirSeparator = '\\'; // check kDirSeparator in Linux dirName.Replace((char)(unsigned char)0xFF, kDirSeparator); @@ -310,13 +345,8 @@ static HRESULT GetNextItem(ISequentialInStream *stream, bool &filled, CItem &ite return S_OK; } -struct COsPair -{ - Byte Id; - const char *Name; -}; -static const COsPair g_OsPairs[] = +static const CUInt32PCharPair g_OsPairs[] = { { 0, "MS-DOS" }, { 'M', "MS-DOS" }, @@ -337,15 +367,6 @@ static const COsPair g_OsPairs[] = { 'J', "Java VM" } }; -static const char *kUnknownOS = "Unknown"; - -static const char *GetOS(Byte osId) -{ - for (unsigned i = 0; i < ARRAY_SIZE(g_OsPairs); i++) - if (g_OsPairs[i].Id == osId) - return g_OsPairs[i].Name; - return kUnknownOS; -} static const Byte kProps[] = { @@ -360,52 +381,6 @@ static const Byte kProps[] = kpidHostOS }; -class CCRC -{ - UInt16 _value; -public: - static UInt16 Table[256]; - static void InitTable(); - - CCRC(): _value(0) {} - void Init() { _value = 0; } - void Update(const void *data, size_t size); - UInt16 GetDigest() const { return _value; } -}; - -static const UInt16 kCRCPoly = 0xA001; - -UInt16 CCRC::Table[256]; - -void CCRC::InitTable() -{ - for (UInt32 i = 0; i < 256; i++) - { - UInt32 r = i; - for (int j = 0; j < 8; j++) - if (r & 1) - r = (r >> 1) ^ kCRCPoly; - else - r >>= 1; - CCRC::Table[i] = (UInt16)r; - } -} - -class CCRCTableInit -{ -public: - CCRCTableInit() { CCRC::InitTable(); } -} g_CRCTableInit; - -void CCRC::Update(const void *data, size_t size) -{ - UInt16 v = _value; - const Byte *p = (const Byte *)data; - for (; size > 0; size--, p++) - v = (UInt16)(Table[((Byte)(v)) ^ *p] ^ (v >> 8)); - _value = v; -} - class COutStreamWithCRC: public ISequentialOutStream, @@ -416,41 +391,36 @@ public: STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); private: - CCRC _crc; + UInt32 _crc; CMyComPtr<ISequentialOutStream> _stream; public: void Init(ISequentialOutStream *stream) { _stream = stream; - _crc.Init(); + _crc = 0; } void ReleaseStream() { _stream.Release(); } - UInt32 GetCRC() const { return _crc.GetDigest(); } - void InitCRC() { _crc.Init(); } + UInt32 GetCRC() const { return _crc; } }; STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) { - UInt32 realProcessedSize; - HRESULT result; - if (!_stream) - { - realProcessedSize = size; - result = S_OK; - } - else - result = _stream->Write(data, size, &realProcessedSize); - _crc.Update(data, realProcessedSize); - if (processedSize != NULL) - *processedSize = realProcessedSize; - return result; + HRESULT res = S_OK; + if (_stream) + res = _stream->Write(data, size, &size); + _crc = LzhCrc16Update(_crc, data, size); + if (processedSize) + *processedSize = size; + return res; } + struct CItemEx: public CItem { UInt64 DataPosition; }; + class CHandler: public IInArchive, public CMyUnknownImp @@ -503,7 +473,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { case kpidPath: { - UString s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetName(), CP_OEMCP)); + UString s = NItemName::WinPathToOsPath(MultiByteToUnicodeString(item.GetName(), CP_OEMCP)); if (!s.IsEmpty()) { if (s.Back() == WCHAR_PATH_SEPARATOR) @@ -516,7 +486,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidSize: prop = item.Size; break; case kpidPackSize: prop = item.PackSize; break; case kpidCRC: prop = (UInt32)item.CRC; break; - case kpidHostOS: prop = GetOS(item.OsId); break; + case kpidHostOS: PAIR_TO_PROP(g_OsPairs, item.OsId, prop); break; case kpidMTime: { FILETIME utc; @@ -571,15 +541,15 @@ STDMETHODIMP CHandler::Open(IInStream *stream, { CItemEx item; bool filled; - HRESULT result = GetNextItem(stream, filled, item); + HRESULT res = GetNextItem(stream, filled, item); RINOK(stream->Seek(0, STREAM_SEEK_CUR, &item.DataPosition)); - if (result == S_FALSE) + if (res == S_FALSE) { _errorFlags = kpv_ErrorFlags_HeadersError; break; } - if (result != S_OK) + if (res != S_OK) return S_FALSE; _phySize = item.DataPosition; if (!filled) @@ -720,14 +690,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, streamSpec->Init(item.PackSize); - HRESULT result = S_OK; + HRESULT res = S_OK; Int32 opRes = NExtract::NOperationResult::kOK; if (item.IsCopyMethod()) { - result = copyCoder->Code(inStream, outStream, NULL, NULL, progress); - if (result == S_OK && copyCoderSpec->TotalSize != item.PackSize) - result = S_FALSE; + res = copyCoder->Code(inStream, outStream, NULL, NULL, progress); + if (res == S_OK && copyCoderSpec->TotalSize != item.PackSize) + res = S_FALSE; } else if (item.IsLh4GroupMethod()) { @@ -738,9 +708,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } 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; + res = lzhDecoder->Code(inStream, outStream, NULL, ¤tItemUnPacked, progress); + if (res == S_OK && lzhDecoderSpec->GetInputProcessedSize() != item.PackSize) + res = S_FALSE; } /* else if (item.IsLh1GroupMethod()) @@ -751,7 +721,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, lzh1Decoder = lzh1DecoderSpec; } lzh1DecoderSpec->SetDictionary(item.GetNumDictBits()); - result = lzh1Decoder->Code(inStream, outStream, NULL, ¤tItemUnPacked, progress); + res = lzh1Decoder->Code(inStream, outStream, NULL, ¤tItemUnPacked, progress); } */ else @@ -759,11 +729,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (opRes == NExtract::NOperationResult::kOK) { - if (result == S_FALSE) + if (res == S_FALSE) opRes = NExtract::NOperationResult::kDataError; else { - RINOK(result); + RINOK(res); if (outStreamSpec->GetCRC() != item.CRC) opRes = NExtract::NOperationResult::kCRCError; } diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp index 121cd67c..afdc2bfa 100644 --- a/CPP/7zip/Archive/LzmaHandler.cpp +++ b/CPP/7zip/Archive/LzmaHandler.cpp @@ -44,7 +44,8 @@ static const Byte kProps[] = static const Byte kArcProps[] = { - kpidNumStreams + kpidNumStreams, + kpidMethod }; struct CHeader @@ -53,6 +54,7 @@ struct CHeader Byte FilterID; Byte LzmaProps[5]; + Byte GetProp() const { return LzmaProps[0]; } UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); } bool HasSize() const { return (Size != (UInt64)(Int64)-1); } bool Parse(const Byte *buf, bool isThereFilter); @@ -197,6 +199,8 @@ class CHandler: UInt64 _unpackSize; UInt64 _numStreams; + void GetMethod(NCOM::CPropVariant &prop); + public: MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq) @@ -220,6 +224,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidPhySize: if (_packSize_Defined) prop = _packSize; break; case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break; case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break; + case kpidMethod: GetMethod(prop); break; case kpidErrorFlags: { UInt32 v = 0; @@ -229,6 +234,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod; if (_dataError) v |= kpv_ErrorFlags_DataError; prop = v; + break; } } prop.Detach(value); @@ -241,23 +247,60 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } -static void DictSizeToString(UInt32 value, char *s) + +static void DictSizeToString(UInt32 val, char *s) { - for (int i = 0; i <= 31; i++) - if (((UInt32)1 << i) == value) + for (unsigned i = 0; i <= 31; i++) + if (((UInt32)1 << i) == val) { ::ConvertUInt32ToString(i, s); return; } char c = 'b'; - if ((value & ((1 << 20) - 1)) == 0) { value >>= 20; c = 'm'; } - else if ((value & ((1 << 10) - 1)) == 0) { value >>= 10; c = 'k'; } - ::ConvertUInt32ToString(value, s); + if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; } + else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; } + ::ConvertUInt32ToString(val, s); s += MyStringLen(s); *s++ = c; *s = 0; } +static char *AddProp32(char *s, const char *name, UInt32 v) +{ + *s++ = ':'; + s = MyStpCpy(s, name); + ::ConvertUInt32ToString(v, s); + return s + MyStringLen(s); +} + +void CHandler::GetMethod(NCOM::CPropVariant &prop) +{ + if (!_stream) + return; + + char sz[64]; + char *s = sz; + if (_header.FilterID != 0) + s = MyStpCpy(s, "BCJ "); + s = MyStpCpy(s, "LZMA:"); + DictSizeToString(_header.GetDicSize(), s); + s += strlen(s); + + UInt32 d = _header.GetProp(); + // if (d != 0x5D) + { + UInt32 lc = d % 9; + d /= 9; + UInt32 pb = d / 5; + UInt32 lp = d % 5; + if (lc != 3) s = AddProp32(s, "lc", lc); + if (lp != 0) s = AddProp32(s, "lp", lp); + if (pb != 2) s = AddProp32(s, "pb", pb); + } + prop = sz; +} + + STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; @@ -265,18 +308,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN { case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break; case kpidPackSize: if (_packSize_Defined) prop = _packSize; break; - case kpidMethod: - if (_stream) - { - char sz[64]; - char *s = sz; - if (_header.FilterID != 0) - s = MyStpCpy(s, "BCJ "); - s = MyStpCpy(s, "LZMA:"); - DictSizeToString(_header.GetDicSize(), s); - prop = sz; - } - break; + case kpidMethod: GetMethod(prop); break; } prop.Detach(value); return S_OK; @@ -396,9 +428,9 @@ STDMETHODIMP CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const { if (Callback) { - UInt64 files = 0; - UInt64 value = Offset + *inSize; - return Callback->SetCompleted(&files, &value); + const UInt64 files = 0; + const UInt64 val = Offset + *inSize; + return Callback->SetCompleted(&files, &val); } return S_OK; } @@ -510,7 +542,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { if (dataAfterEnd) _dataAfterEnd = true; - else if (decoder._lzmaDecoderSpec->NeedMoreInput) + else if (decoder._lzmaDecoderSpec->NeedsMoreInput()) _needMoreInput = true; _packSize = packSize; diff --git a/CPP/7zip/Archive/MachoHandler.cpp b/CPP/7zip/Archive/MachoHandler.cpp index 26260686..1f65574d 100644 --- a/CPP/7zip/Archive/MachoHandler.cpp +++ b/CPP/7zip/Archive/MachoHandler.cpp @@ -37,6 +37,7 @@ namespace NMacho { #define CPU_TYPE_PPC64 (CPU_ARCH_ABI64 | CPU_TYPE_PPC) #define CPU_TYPE_AMD64 (CPU_ARCH_ABI64 | CPU_TYPE_386) +#define CPU_TYPE_ARM64 (CPU_ARCH_ABI64 | CPU_TYPE_ARM) #define CPU_SUBTYPE_LIB64 (1 << 31) @@ -60,6 +61,8 @@ static const char * const k_PowerPc_SubTypes[] = static const CUInt32PCharPair g_CpuPairs[] = { + { CPU_TYPE_AMD64, "x64" }, + { CPU_TYPE_ARM64, "ARM64" }, { CPU_TYPE_386, "x86" }, { CPU_TYPE_ARM, "ARM" }, { CPU_TYPE_SPARC, "SPARC" }, @@ -168,7 +171,7 @@ static const CUInt32PCharPair g_Flags[] = { 8, "LOC_RELOC" } }; -static const int kNameSize = 16; +static const unsigned kNameSize = 16; struct CSegment { @@ -255,16 +258,16 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) AString s; char temp[16]; UInt32 cpu = _cpuType & ~(UInt32)CPU_ARCH_ABI64; - if (_cpuType == CPU_TYPE_AMD64) - s = "x64"; - else + UInt32 flag64 = _cpuType & (UInt32)CPU_ARCH_ABI64; { const char *n = NULL; for (unsigned i = 0; i < ARRAY_SIZE(g_CpuPairs); i++) { const CUInt32PCharPair &pair = g_CpuPairs[i]; - if (pair.Value == cpu) + if (pair.Value == cpu || pair.Value == _cpuType) { + if (pair.Value == _cpuType) + flag64 = 0; n = pair.Name; break; } @@ -276,10 +279,10 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) } s = n; - if (_cpuType & CPU_ARCH_ABI64) + if (flag64 != 0) s += " 64-bit"; - else if (_cpuSubType & CPU_SUBTYPE_LIB64) - s += " 64-bit lib"; + else if ((_cpuSubType & CPU_SUBTYPE_LIB64) && _cpuType != CPU_TYPE_AMD64) + s += " 64-bit-lib"; } UInt32 t = _cpuSubType & ~(UInt32)CPU_SUBTYPE_LIB64; if (t != 0 && (t != CPU_SUBTYPE_I386_ALL || cpu != CPU_TYPE_386)) @@ -306,8 +309,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidCharacts: { // TYPE_TO_PROP(g_FileTypes, _type, prop); break; - AString res = TypeToString(g_FileTypes, ARRAY_SIZE(g_FileTypes), _type); - AString s = FlagsToString(g_ArcFlags, ARRAY_SIZE(g_ArcFlags), _flags); + AString res (TypeToString(g_FileTypes, ARRAY_SIZE(g_FileTypes), _type)); + AString s (FlagsToString(g_ArcFlags, ARRAY_SIZE(g_ArcFlags), _flags)); if (!s.IsEmpty()) { res.Add_Space(); @@ -345,20 +348,9 @@ static AString GetName(const char *name) char res[kNameSize + 1]; memcpy(res, name, kNameSize); res[kNameSize] = 0; - return res; + return (AString)res; } -static AString SectFlagsToString(UInt32 flags) -{ - AString res = TypeToString(g_SectTypes, ARRAY_SIZE(g_SectTypes), flags & SECT_TYPE_MASK); - AString s = FlagsToString(g_Flags, ARRAY_SIZE(g_Flags), flags & SECT_ATTR_MASK); - if (!s.IsEmpty()) - { - res.Add_Space(); - res += s; - } - return res; -} STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { @@ -369,7 +361,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { case kpidPath: { - AString s = GetName(_segments[item.SegmentIndex].Name); + AString s (GetName(_segments[item.SegmentIndex].Name)); if (!item.IsDummy) s += GetName(item.Name); prop = MultiByteToUnicodeString(s); @@ -377,7 +369,19 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } case kpidSize: /* prop = (UInt64)item.VSize; break; */ case kpidPackSize: prop = (UInt64)item.GetPackSize(); break; - case kpidCharacts: if (!item.IsDummy) prop = SectFlagsToString(item.Flags); break; + case kpidCharacts: + if (!item.IsDummy) + { + AString res (TypeToString(g_SectTypes, ARRAY_SIZE(g_SectTypes), item.Flags & SECT_TYPE_MASK)); + AString s (FlagsToString(g_Flags, ARRAY_SIZE(g_Flags), item.Flags & SECT_ATTR_MASK)); + if (!s.IsEmpty()) + { + res.Add_Space(); + res += s; + } + prop = res; + } + break; case kpidOffset: prop = item.Pa; break; case kpidVa: prop = item.Va; break; } @@ -386,6 +390,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val COM_TRY_END } + HRESULT CHandler::Open2(ISequentialInStream *stream) { const UInt32 kStartHeaderSize = 7 * 4; @@ -402,6 +407,9 @@ HRESULT CHandler::Open2(ISequentialInStream *stream) default: return S_FALSE; } + _mode64 = mode64; + _be = be; + UInt32 numCommands = Get32(header + 0x10, be); UInt32 commandsSize = Get32(header + 0x14, be); diff --git a/CPP/7zip/Archive/MbrHandler.cpp b/CPP/7zip/Archive/MbrHandler.cpp index b92755ae..14a1224c 100644 --- a/CPP/7zip/Archive/MbrHandler.cpp +++ b/CPP/7zip/Archive/MbrHandler.cpp @@ -63,21 +63,14 @@ static int CompareChs(const CChs &c1, const CChs &c2) } */ -static void AddUIntToString(UInt32 val, AString &res) -{ - char s[16]; - ConvertUInt32ToString(val, s); - res += s; -} - void CChs::ToString(NCOM::CPropVariant &prop) const { AString s; - AddUIntToString(GetCyl(), s); + s.Add_UInt32(GetCyl()); s += '-'; - AddUIntToString(Head, s); + s.Add_UInt32(Head); s += '-'; - AddUIntToString(GetSector(), s); + s.Add_UInt32(GetSector()); prop = s; } @@ -137,7 +130,7 @@ struct CPartType const char *Name; }; -static const char *kFat = "fat"; +#define kFat "fat" static const CPartType kPartTypes[] = { @@ -156,6 +149,7 @@ static const CPartType kPartTypes[] = { 0x1B, kFat, "FAT32-Hidden" }, { 0x1C, kFat, "FAT32-LBA-Hidden" }, { 0x1E, kFat, "FAT16-LBA-WIN95-Hidden" }, + { 0x27, "ntfs", "NTFS-WinRE" }, { 0x82, 0, "Solaris x86 / Linux swap" }, { 0x83, 0, "Linux" }, { 0x8E, "lvm", "Linux LVM" }, @@ -399,14 +393,16 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidPath: { AString s; - AddUIntToString(index, s); + s.Add_UInt32(index); if (item.IsReal) { - int typeIndex = FindPartType(part.Type); s += '.'; - const char *ext = "img"; - if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Ext) + const char *ext = NULL; + int typeIndex = FindPartType(part.Type); + if (typeIndex >= 0) ext = kPartTypes[(unsigned)typeIndex].Ext; + if (!ext) + ext = "img"; s += ext; } prop = s; diff --git a/CPP/7zip/Archive/MslzHandler.cpp b/CPP/7zip/Archive/MslzHandler.cpp index ec375733..6f9057a6 100644 --- a/CPP/7zip/Archive/MslzHandler.cpp +++ b/CPP/7zip/Archive/MslzHandler.cpp @@ -159,7 +159,7 @@ void CHandler::ParseName(Byte replaceByte, IArchiveOpenCallback *callback) } if (replaceByte >= 0x20 && replaceByte < 0x80) - _name += (wchar_t)replaceByte; + _name += (char)replaceByte; } STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */, diff --git a/CPP/7zip/Archive/MubHandler.cpp b/CPP/7zip/Archive/MubHandler.cpp index 56b8aa32..6d054356 100644 --- a/CPP/7zip/Archive/MubHandler.cpp +++ b/CPP/7zip/Archive/MubHandler.cpp @@ -31,6 +31,7 @@ namespace NMub { #define MACH_CPU_TYPE_PPC64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_PPC) #define MACH_CPU_TYPE_AMD64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_386) +#define MACH_CPU_TYPE_ARM64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_ARM) #define MACH_CPU_SUBTYPE_LIB64 (1 << 31) @@ -105,17 +106,20 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val const char *ext = 0; switch (item.Type) { - case MACH_CPU_TYPE_386: ext = "x86"; break; + case MACH_CPU_TYPE_386: ext = "x86"; break; case MACH_CPU_TYPE_ARM: ext = "arm"; break; case MACH_CPU_TYPE_SPARC: ext = "sparc"; break; case MACH_CPU_TYPE_PPC: ext = "ppc"; break; - case MACH_CPU_TYPE_PPC64: ext = "ppc64"; break; case MACH_CPU_TYPE_AMD64: ext = "x64"; break; + case MACH_CPU_TYPE_ARM64: ext = "arm64"; break; + case MACH_CPU_TYPE_PPC64: ext = "ppc64"; break; default: temp[0] = 'c'; temp[1] = 'p'; temp[2] = 'u'; - ConvertUInt32ToString(item.Type, temp + 3); + ConvertUInt32ToString(item.Type & ~MACH_CPU_ARCH_ABI64, temp + 3); + if (item.Type & MACH_CPU_ARCH_ABI64) + MyStringCopy(temp + MyStringLen(temp), "_64"); break; } if (ext) diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.cpp b/CPP/7zip/Archive/Nsis/NsisDecode.cpp index daf3df6e..e2822184 100644 --- a/CPP/7zip/Archive/Nsis/NsisDecode.cpp +++ b/CPP/7zip/Archive/Nsis/NsisDecode.cpp @@ -11,13 +11,24 @@ #include "../../Common/MethodId.h" #include "../../Compress/BcjCoder.h" -#include "../../Compress/BZip2Decoder.h" #define Get32(p) GetUi32(p) namespace NArchive { namespace NNsis { +UInt64 CDecoder::GetInputProcessedSize() const +{ + if (_lzmaDecoder) + return _lzmaDecoder->GetInputProcessedSize(); + if (_deflateDecoder) + return _deflateDecoder->GetInputProcessedSize(); + if (_bzDecoder) + return _bzDecoder->GetInputProcessedSize(); + return 0; +} + + HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter) { useFilter = false; @@ -36,7 +47,10 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter) _deflateDecoder = new NCompress::NDeflate::NDecoder::CCOMCoder(); _codecInStream = _deflateDecoder; break; - case NMethodType::kBZip2: _codecInStream = new NCompress::NBZip2::CNsisDecoder(); break; + case NMethodType::kBZip2: + _bzDecoder = new NCompress::NBZip2::CNsisDecoder(); + _codecInStream = _bzDecoder; + break; case NMethodType::kLZMA: _lzmaDecoder = new NCompress::NLzma::CDecoder(); _codecInStream = _lzmaDecoder; @@ -103,15 +117,15 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter) return S_OK; } + static const UInt32 kMask_IsCompressed = (UInt32)1 << 31; + HRESULT CDecoder::SetToPos(UInt64 pos, ICompressProgressInfo *progress) { if (StreamPos > pos) return E_FAIL; - UInt64 inSizeStart = 0; - if (_lzmaDecoder) - inSizeStart = _lzmaDecoder->GetInputProcessedSize(); + const UInt64 inSizeStart = GetInputProcessedSize(); UInt64 offset = 0; while (StreamPos < pos) { @@ -122,14 +136,13 @@ HRESULT CDecoder::SetToPos(UInt64 pos, ICompressProgressInfo *progress) StreamPos += size; offset += size; - UInt64 inSize = 0; - if (_lzmaDecoder) - inSize = _lzmaDecoder->GetInputProcessedSize() - inSizeStart; + const UInt64 inSize = GetInputProcessedSize() - inSizeStart; RINOK(progress->SetRatioInfo(&inSize, &offset)); } return S_OK; } + HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unpackSize, ISequentialOutStream *realOutStream, ICompressProgressInfo *progress, UInt32 &packSizeRes, UInt32 &unpackSizeRes) @@ -144,9 +157,9 @@ HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unp Byte temp[4]; size_t processedSize = 4; RINOK(Read(temp, &processedSize)); + StreamPos += processedSize; if (processedSize != 4) return S_FALSE; - StreamPos += processedSize; UInt32 size = Get32(temp); if (unpackSizeDefined && size != unpackSize) return S_FALSE; @@ -156,8 +169,13 @@ HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unp else { Byte temp[4]; - RINOK(ReadStream_FALSE(InputStream, temp, 4)); - StreamPos += 4; + { + size_t processedSize = 4; + RINOK(ReadStream(InputStream, temp, &processedSize)); + StreamPos += processedSize; + if (processedSize != 4) + return S_FALSE; + } UInt32 size = Get32(temp); if ((size & kMask_IsCompressed) == 0) @@ -209,9 +227,7 @@ HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unp outBuf->Alloc(unpackSize); } - UInt64 inSizeStart = 0; - if (_lzmaDecoder) - inSizeStart = _lzmaDecoder->GetInputProcessedSize(); + const UInt64 inSizeStart = GetInputProcessedSize(); // we don't allow files larger than 4 GB; if (!unpackSizeDefined) @@ -254,9 +270,8 @@ HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unp StreamPos += size; offset += (UInt32)size; - UInt64 inSize = 0; // it can be improved: we need inSize for Deflate and BZip2 too. - if (_lzmaDecoder) - inSize = _lzmaDecoder->GetInputProcessedSize() - inSizeStart; + const UInt64 inSize = GetInputProcessedSize() - inSizeStart; + if (Solid) packSizeRes = (UInt32)inSize; unpackSizeRes += (UInt32)size; diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.h b/CPP/7zip/Archive/Nsis/NsisDecode.h index ec713d05..2153d785 100644 --- a/CPP/7zip/Archive/Nsis/NsisDecode.h +++ b/CPP/7zip/Archive/Nsis/NsisDecode.h @@ -8,6 +8,7 @@ #include "../../Common/FilterCoder.h" #include "../../Common/StreamUtils.h" +#include "../../Compress/BZip2Decoder.h" #include "../../Compress/DeflateDecoder.h" #include "../../Compress/LzmaDecoder.h" @@ -38,6 +39,7 @@ class CDecoder CMyComPtr<ISequentialInStream> _codecInStream; CMyComPtr<ISequentialInStream> _decoderInStream; + NCompress::NBZip2::CNsisDecoder *_bzDecoder; NCompress::NDeflate::NDecoder::CCOMCoder *_deflateDecoder; NCompress::NLzma::CDecoder *_lzmaDecoder; @@ -50,13 +52,17 @@ public: bool Solid; bool IsNsisDeflate; - CByteBuffer Buffer; // temp buf. + CByteBuffer Buffer; // temp buf CDecoder(): FilterFlag(false), Solid(true), IsNsisDeflate(true) - {} + { + _bzDecoder = NULL; + _deflateDecoder = NULL; + _lzmaDecoder = NULL; + } void Release() { @@ -64,10 +70,16 @@ public: _codecInStream.Release(); _decoderInStream.Release(); InputStream.Release(); + + _bzDecoder = NULL; + _deflateDecoder = NULL; _lzmaDecoder = NULL; } + + UInt64 GetInputProcessedSize() const; HRESULT Init(ISequentialInStream *inStream, bool &useFilter); + HRESULT Read(void *data, size_t *processedSize) { return ReadStream(_decoderInStream, data, processedSize);; diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.cpp b/CPP/7zip/Archive/Nsis/NsisHandler.cpp index 971c8464..095105fe 100644 --- a/CPP/7zip/Archive/Nsis/NsisHandler.cpp +++ b/CPP/7zip/Archive/Nsis/NsisHandler.cpp @@ -23,8 +23,8 @@ using namespace NWindows; namespace NArchive { namespace NNsis { -static const char *kBcjMethod = "BCJ"; -static const char *kUnknownMethod = "Unknown"; +#define kBcjMethod "BCJ" +#define kUnknownMethod "Unknown" static const char * const kMethods[] = { @@ -64,7 +64,7 @@ static AString UInt32ToString(UInt32 val) { char s[16]; ConvertUInt32ToString(val, s); - return s; + return (AString)s; } static AString GetStringForSizeValue(UInt32 val) @@ -123,7 +123,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) // case kpidCodePage: if (_archive.IsUnicode) prop = "UTF-16"; break; case kpidSubType: { - AString s = _archive.GetFormatDescription(); + AString s (_archive.GetFormatDescription()); if (!_archive.IsInstaller) { s.Add_Space_if_NotEmpty(); @@ -308,7 +308,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidOffset: prop = item.Pos; break; case kpidPath: { - UString s = NItemName::WinNameToOSName(_archive.GetReducedName(index)); + UString s = NItemName::WinPathToOsPath(_archive.GetReducedName(index)); if (!s.IsEmpty()) prop = (const wchar_t *)s; break; @@ -481,7 +481,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 askMode = testMode ? NExtract::NAskMode::kTest : NExtract::NAskMode::kExtract; - UInt32 index = allFilesMode ? i : indices[i]; + const UInt32 index = allFilesMode ? i : indices[i]; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); @@ -647,6 +647,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { UInt32 curPacked2 = 0; UInt32 curUnpacked2 = 0; + + if (!_archive.IsSolid) + { + RINOK(_archive.SeekTo(_archive.GetPosOfNonSolidItem(index) + 4 + curPacked )); + } + HRESULT res = _archive.Decoder.Decode( writeToTemp ? &tempBuf2 : NULL, false, 0, diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp index a3bfcaec..f739b0ff 100644 --- a/CPP/7zip/Archive/Nsis/NsisIn.cpp +++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp @@ -398,11 +398,9 @@ static const char * const kShellStrings[] = }; -static void UIntToString(AString &s, UInt32 v) +static inline void UIntToString(AString &s, UInt32 v) { - char sz[16]; - ConvertUInt32ToString(v, sz); - s += sz; + s.Add_UInt32(v); } #ifdef NSIS_SCRIPT @@ -461,7 +459,7 @@ void CInArchive::AddLicense(UInt32 param, Int32 langID) } } } - AString fileName = "[LICENSE]"; + AString fileName ("[LICENSE]"); if (langID >= 0) { fileName += "\\license-"; @@ -940,7 +938,7 @@ void CInArchive::GetNsisString_Unicode_Raw(const Byte *p) break; if (c < 0x80) { - Raw_UString += (wchar_t)c; + Raw_UString += (char)c; continue; } @@ -963,7 +961,7 @@ void CInArchive::GetNsisString_Unicode_Raw(const Byte *p) else // if (c == PARK_CODE_LANG) Add_LangStr(Raw_AString, n); } - Raw_UString.AddAscii(Raw_AString); + Raw_UString += Raw_AString.Ptr(); // check it ! continue; } c = n; @@ -1009,7 +1007,7 @@ void CInArchive::GetNsisString_Unicode_Raw(const Byte *p) else // if (c == NS_3_CODE_LANG) Add_LangStr(Raw_AString, n); } - Raw_UString.AddAscii(Raw_AString); + Raw_UString += Raw_AString.Ptr(); } } @@ -1145,7 +1143,7 @@ void CInArchive::ReadString2_Raw(UInt32 pos) GetNsisString_Raw(_data + _stringsPos + pos); return; } - Raw_UString.SetFromAscii(Raw_AString); + Raw_UString = Raw_AString.Ptr(); } bool CInArchive::IsGoodString(UInt32 param) const @@ -2309,7 +2307,7 @@ static void AddString(AString &dest, const char *src) AString CInArchive::GetFormatDescription() const { - AString s = "NSIS-"; + AString s ("NSIS-"); char c; if (IsPark()) { @@ -3185,8 +3183,8 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) UString spec_outdir_U; AString spec_outdir_A; - UPrefixes.Add(L"$INSTDIR"); - APrefixes.Add("$INSTDIR"); + UPrefixes.Add(UString("$INSTDIR")); + APrefixes.Add(AString("$INSTDIR")); p = _data + bh.Offset; @@ -4021,7 +4019,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) case EW_INTOP: { AddParam_Var(params[0]); - const char *kOps = "+-*/|&^!|&%<>"; // NSIS 2.01+ + const char * const kOps = "+-*/|&^!|&%<>"; // NSIS 2.01+ // "+-*/|&^!|&%"; // NSIS 2.0b4+ // "+-*/|&^~!|&%"; // NSIS old UInt32 opIndex = params[3]; @@ -4857,11 +4855,11 @@ static int CompareItems(void *const *p1, void *const *p2, void *param) { if (i1.Prefix < 0) return -1; if (i2.Prefix < 0) return 1; - RINOZ(wcscmp( - inArchive->UPrefixes[i1.Prefix], + RINOZ( + inArchive->UPrefixes[i1.Prefix].Compare( inArchive->UPrefixes[i2.Prefix])); } - RINOZ(wcscmp(i1.NameU, i2.NameU)); + RINOZ(i1.NameU.Compare(i2.NameU)); } else { @@ -4934,7 +4932,7 @@ HRESULT CInArchive::SortItems() for (i = 0; i < Items.Size(); i++) { CItem &item = Items[i]; - RINOK(_stream->Seek(GetPosOfNonSolidItem(i), STREAM_SEEK_SET, NULL)); + RINOK(SeekToNonSolidItem(i)); const UInt32 kSigSize = 4 + 1 + 1 + 4; // size,[flag],prop,dict BYTE sig[kSigSize]; size_t processedSize = kSigSize; @@ -4997,6 +4995,9 @@ HRESULT CInArchive::Parse() // ???? offset == FirstHeader.HeaderSize const Byte *p = _data; + if (_size < 4 + 8 * 8) + return S_FALSE; + CBlockHeader bhEntries, bhStrings, bhLangTables; bhEntries.Parse(p + 4 + 8 * 2); bhStrings.Parse(p + 4 + 8 * 3); @@ -5014,12 +5015,14 @@ HRESULT CInArchive::Parse() #endif _stringsPos = bhStrings.Offset; - if (_stringsPos > _size) + if (_stringsPos > _size + || bhLangTables.Offset > _size + || bhEntries.Offset > _size) return S_FALSE; { if (bhLangTables.Offset < bhStrings.Offset) return S_FALSE; - UInt32 stringTableSize = bhLangTables.Offset - bhStrings.Offset; + const UInt32 stringTableSize = bhLangTables.Offset - bhStrings.Offset; if (stringTableSize < 2) return S_FALSE; const Byte *strData = _data + _stringsPos; @@ -5035,13 +5038,10 @@ HRESULT CInArchive::Parse() if (strData[stringTableSize - 2] != 0) return S_FALSE; } - } if (bhEntries.Num > (1 << 25)) return S_FALSE; - if (bhEntries.Offset > _size) - return S_FALSE; if (bhEntries.Num * kCmdSize > _size - bhEntries.Offset) return S_FALSE; @@ -5595,16 +5595,19 @@ HRESULT CInArchive::Open2(const Byte *sig, size_t size) if (IsSolid) { - RINOK(_stream->Seek(DataStreamOffset, STREAM_SEEK_SET, NULL)); + RINOK(SeekTo_DataStreamOffset()); } else { _headerIsCompressed = ((compressedHeaderSize & kMask_IsCompressed) != 0); compressedHeaderSize &= ~kMask_IsCompressed; _nonSolidStartOffset = compressedHeaderSize; - RINOK(_stream->Seek(DataStreamOffset + 4, STREAM_SEEK_SET, NULL)); + RINOK(SeekTo(DataStreamOffset + 4)); } + if (FirstHeader.HeaderSize == 0) + return S_FALSE; + _data.Alloc(FirstHeader.HeaderSize); _size = (size_t)FirstHeader.HeaderSize; diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h index d8e6808b..028e4a5d 100644 --- a/CPP/7zip/Archive/Nsis/NsisIn.h +++ b/CPP/7zip/Archive/Nsis/NsisIn.h @@ -350,14 +350,19 @@ public: return Decoder.Init(_stream, useFilter); } + HRESULT SeekTo(UInt64 pos) + { + return _stream->Seek(pos, STREAM_SEEK_SET, NULL); + } + HRESULT SeekTo_DataStreamOffset() { - return _stream->Seek(DataStreamOffset, STREAM_SEEK_SET, NULL); + return SeekTo(DataStreamOffset); } HRESULT SeekToNonSolidItem(unsigned index) { - return _stream->Seek(GetPosOfNonSolidItem(index), STREAM_SEEK_SET, NULL); + return SeekTo(GetPosOfNonSolidItem(index)); } void Clear(); @@ -403,23 +408,23 @@ public: s = MultiByteToUnicodeString(APrefixes[item.Prefix]); if (s.Len() > 0) if (s.Back() != L'\\') - s += L'\\'; + s += '\\'; } if (IsUnicode) { s += item.NameU; if (item.NameU.IsEmpty()) - s += L"file"; + s += "file"; } else { s += MultiByteToUnicodeString(item.NameA); if (item.NameA.IsEmpty()) - s += L"file"; + s += "file"; } - const char *kRemoveStr = "$INSTDIR\\"; + const char * const kRemoveStr = "$INSTDIR\\"; if (s.IsPrefixedBy_Ascii_NoCase(kRemoveStr)) { s.Delete(0, MyStringLen(kRemoveStr)); @@ -427,7 +432,7 @@ public: s.DeleteFrontal(1); } if (item.IsUninstaller && ExeStub.Size() == 0) - s += L".nsis"; + s += ".nsis"; return s; } diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp index a6350944..dff7701d 100644 --- a/CPP/7zip/Archive/NtfsHandler.cpp +++ b/CPP/7zip/Archive/NtfsHandler.cpp @@ -56,9 +56,9 @@ using namespace NWindows; namespace NArchive { namespace Ntfs { -static const wchar_t *kVirtualFolder_System = L"[SYSTEM]"; -static const wchar_t *kVirtualFolder_Lost_Normal = L"[LOST]"; -static const wchar_t *kVirtualFolder_Lost_Deleted = L"[UNKNOWN]"; +static const wchar_t * const kVirtualFolder_System = L"[SYSTEM]"; +static const wchar_t * const kVirtualFolder_Lost_Normal = L"[LOST]"; +static const wchar_t * const kVirtualFolder_Lost_Deleted = L"[UNKNOWN]"; static const unsigned kNumSysRecs = 16; @@ -394,7 +394,7 @@ static int CompareAttr(void *const *elem1, void *const *elem2, void *) return 1; else { - RINOZ(wcscmp(a1.Name.GetRawPtr(), a2.Name.GetRawPtr())); + RINOZ(a1.Name.Compare(a2.Name.GetRawPtr())); } return MyCompare(a1.LowVcn, a2.LowVcn); } @@ -2340,7 +2340,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) } case kpidFileSystem: { - AString s = "NTFS"; + AString s ("NTFS"); FOR_VECTOR (i, VolAttrs) { const CAttr &attr = VolAttrs[i]; @@ -2350,12 +2350,9 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) if (attr.ParseVolInfo(vi)) { s.Add_Space(); - char temp[16]; - ConvertUInt32ToString(vi.MajorVer, temp); - s += temp; + s.Add_UInt32(vi.MajorVer); s += '.'; - ConvertUInt32ToString(vi.MinorVer, temp); - s += temp; + s.Add_UInt32(vi.MinorVer); } break; } @@ -2722,18 +2719,14 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR for (UInt32 i = 0; i < numProps; i++) { - UString name = names[i]; - name.MakeLower_Ascii(); - if (name.IsEmpty()) - return E_INVALIDARG; - + const wchar_t *name = names[i]; const PROPVARIANT &prop = values[i]; - if (name.IsEqualTo("ld")) + if (StringsAreEqualNoCase_Ascii(name, "ld")) { RINOK(PROPVARIANT_to_bool(prop, _showDeletedFiles)); } - else if (name.IsEqualTo("ls")) + else if (StringsAreEqualNoCase_Ascii(name, "ls")) { RINOK(PROPVARIANT_to_bool(prop, _showSystemFiles)); } diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp index 7175cef3..30a60843 100644 --- a/CPP/7zip/Archive/PeHandler.cpp +++ b/CPP/7zip/Archive/PeHandler.cpp @@ -85,12 +85,6 @@ static HRESULT CalcCheckSum(ISequentialInStream *stream, UInt32 size, UInt32 exc return S_OK; } -static AString GetDecString(UInt32 v) -{ - char sz[16]; - ConvertUInt32ToString(v, sz); - return sz; -} struct CVersion { @@ -407,13 +401,16 @@ static const CUInt32PCharPair g_HeaderCharacts[] = static const CUInt32PCharPair g_DllCharacts[] = { + { 5, "HighEntropyVA" }, { 6, "Relocated" }, { 7, "Integrity" }, { 8, "NX-Compatible" }, { 9, "NoIsolation" }, { 10, "NoSEH" }, { 11, "NoBind" }, + { 12, "AppContainer" }, { 13, "WDM" }, + { 14, "GuardCF" }, { 15, "TerminalServerAware" } }; @@ -467,22 +464,30 @@ static const CUInt32PCharPair g_MachinePairs[] = { 0x0EBC, "EFI" }, { 0x8664, "x64" }, { 0x9041, "M32R" }, + { 0xAA64, "ARM64" }, { 0xC0EE, "CEE" } }; -static const CUInt32PCharPair g_SubSystems[] = -{ - { 0, "Unknown" }, - { 1, "Native" }, - { 2, "Windows GUI" }, - { 3, "Windows CUI" }, - { 7, "Posix" }, - { 9, "Windows CE" }, - { 10, "EFI" }, - { 11, "EFI Boot" }, - { 12, "EFI Runtime" }, - { 13, "EFI ROM" }, - { 14, "XBOX" } +static const char * const g_SubSystems[] = +{ + "Unknown" + , "Native" + , "Windows GUI" + , "Windows CUI" + , NULL // "Old Windows CE" + , "OS2" + , NULL + , "Posix" + , "Win9x" + , "Windows CE" + , "EFI" + , "EFI Boot" + , "EFI Runtime" + , "EFI ROM" + , "XBOX" + , NULL + , "Windows Boot" + , "XBOX Catalog" // 17 }; static const char * const g_ResTypes[] = @@ -878,7 +883,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidCpu: PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop); break; case kpidBit64: if (_optHeader.Is64Bit()) prop = true; break; - case kpidSubSystem: PAIR_TO_PROP(g_SubSystems, _optHeader.SubSystem, prop); break; + case kpidSubSystem: TYPE_TO_PROP(g_SubSystems, _optHeader.SubSystem, prop); break; case kpidMTime: case kpidCTime: TimeToProp(_header.Time, prop); break; @@ -950,9 +955,7 @@ void CHandler::AddResNameToString(UString &s, UInt32 id) const return; } } - wchar_t sz[16]; - ConvertUInt32ToString(id, sz); - s += sz; + s.Add_UInt32(id); } void CHandler::AddLangPrefix(UString &s, UInt32 lang) const @@ -978,7 +981,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { UString s = _resourcesPrefix; AddLangPrefix(s, item.Lang); - s.AddAscii("string.txt"); + s += "string.txt"; prop = s; break; } @@ -996,7 +999,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { UString s = _resourcesPrefix; AddLangPrefix(s, item.Lang); - s.AddAscii("version.txt"); + s += "version.txt"; prop = s; break; } @@ -1019,7 +1022,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val if (item.Type < ARRAY_SIZE(g_ResTypes)) p = g_ResTypes[item.Type]; if (p) - s.AddAscii(p); + s += p; else AddResNameToString(s, item.Type); } @@ -1028,9 +1031,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val if (item.HeaderSize != 0) { if (item.IsBmp()) - s.AddAscii(".bmp"); + s += ".bmp"; else if (item.IsIcon()) - s.AddAscii(".ico"); + s += ".ico"; } prop = s; break; @@ -1112,7 +1115,8 @@ HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection) thereIsSection = true; CSection § = _sections.AddNew(); - sect.Name = ".debug" + GetDecString(i); + sect.Name = ".debug"; + sect.Name.Add_UInt32(i); sect.IsDebug = true; sect.Time = de.Time; sect.Va = de.Va; @@ -1384,11 +1388,9 @@ static void PrintUInt32(CTextFile &f, UInt32 v) f.AddString(s); } -static void PrintUInt32(UString &dest, UInt32 v) +static inline void PrintUInt32(UString &dest, UInt32 v) { - wchar_t s[16]; - ConvertUInt32ToString(v, s); - dest += s; + dest.Add_UInt32(v); } static void PrintHex(CTextFile &f, UInt32 val) @@ -1410,9 +1412,9 @@ static void PrintVersion(CTextFile &f, UInt32 ms, UInt32 ls) static void PrintVersion(UString &s, UInt32 ms, UInt32 ls) { - PrintUInt32(s, HIWORD(ms)); s += L'.'; - PrintUInt32(s, LOWORD(ms)); s += L'.'; - PrintUInt32(s, HIWORD(ls)); s += L'.'; + PrintUInt32(s, HIWORD(ms)); s += '.'; + PrintUInt32(s, LOWORD(ms)); s += '.'; + PrintUInt32(s, HIWORD(ls)); s += '.'; PrintUInt32(s, LOWORD(ls)); } @@ -1694,7 +1696,7 @@ bool CVersionBlock::Parse(const Byte *p, UInt32 size) return false; TotalLen = Get16(p); ValueLen = Get16(p + 2); - if (TotalLen == 0 || TotalLen > size) + if (TotalLen < k_ResoureBlockHeader_Size || TotalLen > size) return false; switch (Get16(p + 4)) { @@ -2114,7 +2116,8 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi static inline bool CheckPeOffset(UInt32 pe) { - return (pe >= 0x40 && pe <= 0x1000 && (pe & 7) == 0); + // ((pe & 7) == 0) is for most PE files. But there is unusual EFI-PE file that uses unaligned pe value. + return pe >= 0x40 && pe <= 0x1000 /* && (pe & 7) == 0 */ ; } static const unsigned kStartSize = 0x40; @@ -2290,7 +2293,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) s2.PSize = s2.VSize = s.Pa - limit; s2.IsAdditionalSection = true; s2.Name = '['; - s2.Name += GetDecString(num++); + s2.Name.Add_UInt32(num++); s2.Name += ']'; limit = s.Pa; } @@ -2332,10 +2335,11 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) mixItem.SectionIndex = i; if (_parseResources && sect.Name == ".rsrc" && _items.IsEmpty()) { + const unsigned numMixItems = _mixItems.Size(); HRESULT res = OpenResources(i, stream, callback); if (res == S_OK) { - _resourcesPrefix.SetFromAscii(sect.Name); + _resourcesPrefix = sect.Name.Ptr(); _resourcesPrefix.Add_PathSepar(); FOR_VECTOR (j, _items) { @@ -2387,6 +2391,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) } if (res != S_FALSE) return res; + _mixItems.DeleteFrom(numMixItems); CloseResources(); } if (sect.IsAdditionalSection) @@ -2422,7 +2427,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) _versionFullString.Add_LF(); const CStringKeyValue &k = _versionKeys[i]; _versionFullString += k.Key; - _versionFullString += L": "; + _versionFullString += ": "; _versionFullString += k.Value; } @@ -2702,7 +2707,8 @@ static bool FindValue(const CUInt32PCharPair *pairs, unsigned num, UInt32 value) return false; } -#define MY_FIND_VALUE(pairs, value) FindValue(pairs, ARRAY_SIZE(pairs), value) +#define MY_FIND_VALUE(pairs, val) FindValue(pairs, ARRAY_SIZE(pairs), val) +#define MY_FIND_VALUE_2(strings, val) (val < ARRAY_SIZE(strings) && strings[val]) static const UInt32 kNumSection_MAX = 32; @@ -2751,7 +2757,7 @@ bool CHeader::Parse(const Byte *p) } return MY_FIND_VALUE(NPe::g_MachinePairs, Machine) && - MY_FIND_VALUE(NPe::g_SubSystems, SubSystem); + MY_FIND_VALUE_2(NPe::g_SubSystems, SubSystem); } API_FUNC_static_IsArc IsArc_Te(const Byte *p, size_t size) @@ -2864,7 +2870,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { case kpidPhySize: prop = _totalSize; break; case kpidCpu: PAIR_TO_PROP(NPe::g_MachinePairs, _h.Machine, prop); break; - case kpidSubSystem: PAIR_TO_PROP(NPe::g_SubSystems, _h.SubSystem, prop); break; + case kpidSubSystem: TYPE_TO_PROP(NPe::g_SubSystems, _h.SubSystem, prop); break; /* case kpidImageBase: prop = _h.ImageBase; break; case kpidAddressOfEntryPoint: prop = _h.AddressOfEntryPoint; break; diff --git a/CPP/7zip/Archive/PpmdHandler.cpp b/CPP/7zip/Archive/PpmdHandler.cpp index 528c5ceb..c80400bc 100644 --- a/CPP/7zip/Archive/PpmdHandler.cpp +++ b/CPP/7zip/Archive/PpmdHandler.cpp @@ -12,7 +12,6 @@ This code is based on: #include "../../../C/Ppmd8.h" #include "../../Common/ComTry.h" -#include "../../Common/IntToString.h" #include "../../Common/StringConvert.h" #include "../../Windows/PropVariant.h" @@ -104,6 +103,8 @@ class CHandler: UInt64 _packSize; CMyComPtr<ISequentialInStream> _stream; + void GetVersion(NCOM::CPropVariant &prop); + public: MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq) INTERFACE_IInArchive(;) @@ -118,8 +119,30 @@ static const Byte kProps[] = kpidMethod }; +static const Byte kArcProps[] = +{ + kpidMethod +}; + IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO_Table +IMP_IInArchive_ArcProps + +void CHandler::GetVersion(NCOM::CPropVariant &prop) +{ + AString s ("PPMd"); + s += (char)('A' + _item.Ver); + s += ":o"; + s.Add_UInt32(_item.Order); + s += ":mem"; + s.Add_UInt32(_item.MemInMB); + s += 'm'; + if (_item.Ver >= kNewHeaderVer && _item.Restor != 0) + { + s += ":r"; + s.Add_UInt32(_item.Restor); + } + prop = s; +} STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { @@ -127,6 +150,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) switch (propID) { case kpidPhySize: if (_packSize_Defined) prop = _packSize; break; + case kpidMethod: GetVersion(prop); break; } prop.Detach(value); return S_OK; @@ -139,14 +163,6 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } -static void UIntToString(AString &s, const char *prefix, unsigned value) -{ - s += prefix; - char temp[16]; - ::ConvertUInt32ToString((UInt32)value, temp); - s += temp; -} - STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN @@ -164,17 +180,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN } case kpidAttrib: prop = _item.Attrib; break; case kpidPackSize: if (_packSize_Defined) prop = _packSize; break; - case kpidMethod: - { - AString s = "PPMd"; - s += (char)('A' + _item.Ver); - UIntToString(s, ":o", _item.Order); - UIntToString(s, ":mem", _item.MemInMB); - s += 'm'; - if (_item.Ver >= kNewHeaderVer && _item.Restor != 0) - UIntToString(s, ":r", _item.Restor); - prop = s; - } + case kpidMethod: GetVersion(prop); break; } prop.Detach(value); return S_OK; @@ -217,7 +223,7 @@ static const UInt32 kBot = (1 << 15); struct CRangeDecoder { - IPpmd7_RangeDec s; + IPpmd7_RangeDec vt; UInt32 Range; UInt32 Code; UInt32 Low; @@ -251,15 +257,17 @@ public: extern "C" { -static UInt32 Range_GetThreshold(void *pp, UInt32 total) +#define GET_RangeDecoder CRangeDecoder *p = CONTAINER_FROM_VTBL(pp, CRangeDecoder, vt); + +static UInt32 Range_GetThreshold(const IPpmd7_RangeDec *pp, UInt32 total) { - CRangeDecoder *p = (CRangeDecoder *)pp; + GET_RangeDecoder return p->Code / (p->Range /= total); } -static void Range_Decode(void *pp, UInt32 start, UInt32 size) +static void Range_Decode(const IPpmd7_RangeDec *pp, UInt32 start, UInt32 size) { - CRangeDecoder *p = (CRangeDecoder *)pp; + GET_RangeDecoder start *= p->Range; p->Low += start; p->Code -= start; @@ -267,17 +275,17 @@ static void Range_Decode(void *pp, UInt32 start, UInt32 size) p->Normalize(); } -static UInt32 Range_DecodeBit(void *pp, UInt32 size0) +static UInt32 Range_DecodeBit(const IPpmd7_RangeDec *pp, UInt32 size0) { - CRangeDecoder *p = (CRangeDecoder *)pp; + GET_RangeDecoder if (p->Code / (p->Range >>= 14) < size0) { - Range_Decode(p, 0, size0); + Range_Decode(&p->vt, 0, size0); return 0; } else { - Range_Decode(p, size0, (1 << 14) - size0); + Range_Decode(&p->vt, size0, (1 << 14) - size0); return 1; } } @@ -286,9 +294,9 @@ static UInt32 Range_DecodeBit(void *pp, UInt32 size0) CRangeDecoder::CRangeDecoder() { - s.GetThreshold = Range_GetThreshold; - s.Decode = Range_Decode; - s.DecodeBit = Range_DecodeBit; + vt.GetThreshold = Range_GetThreshold; + vt.Decode = Range_Decode; + vt.DecodeBit = Range_DecodeBit; } struct CPpmdCpp @@ -336,7 +344,7 @@ struct CPpmdCpp } else { - _ppmd8.Stream.In = &inStream->p; + _ppmd8.Stream.In = &inStream->vt; return Ppmd8_RangeDec_Init(&_ppmd8) != 0; } } @@ -412,7 +420,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { for (i = 0; i < kBufSize; i++) { - sym = Ppmd7_DecodeSymbol(&ppmd._ppmd7, &ppmd._rc.s); + sym = Ppmd7_DecodeSymbol(&ppmd._ppmd7, &ppmd._rc.vt); if (inBuf.Extra || sym < 0) break; outBuf.Buf[i] = (Byte)sym; diff --git a/CPP/7zip/Archive/QcowHandler.cpp b/CPP/7zip/Archive/QcowHandler.cpp index a84fdc9b..065f59b3 100644 --- a/CPP/7zip/Archive/QcowHandler.cpp +++ b/CPP/7zip/Archive/QcowHandler.cpp @@ -284,11 +284,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) if (_cryptMethod == 1) s += "AES"; else - { - char temp[16]; - ConvertUInt32ToString(_cryptMethod, temp); - s += temp; - } + s.Add_UInt32(_cryptMethod); } if (!s.IsEmpty()) diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.cpp b/CPP/7zip/Archive/Rar/Rar5Handler.cpp index d70a5686..f166730e 100644 --- a/CPP/7zip/Archive/Rar/Rar5Handler.cpp +++ b/CPP/7zip/Archive/Rar/Rar5Handler.cpp @@ -50,22 +50,59 @@ static const Byte kMarker[kMarkerSize] = SIGNATURE; static const size_t kCommentSize_Max = (size_t)1 << 16; + static const char * const kHostOS[] = { "Windows" , "Unix" }; -static const CUInt32PCharPair k_ArcFlags[] = + +static const char * const k_ArcFlags[] = +{ + "Volume" + , "VolumeField" + , "Solid" + , "Recovery" + , "Lock" // 4 +}; + + +static const char * const k_FileFlags[] = +{ + "Dir" + , "UnixTime" + , "CRC" + , "UnknownSize" +}; + + +static const char * const g_ExtraTypes[] = +{ + "0" + , "Crypto" + , "Hash" + , "Time" + , "Version" + , "Link" + , "UnixOwner" + , "Subdata" +}; + + +static const char * const g_LinkTypes[] = { - { 0, "Volume" }, - { 1, "VolumeField" }, - { 2, "Solid" }, - { 3, "Recovery" }, - { 4, "Lock" } + "0" + , "UnixSymLink" + , "WinSymLink" + , "WinJunction" + , "HardLink" + , "FileCopy" }; +static const char g_ExtraTimeFlags[] = { 'u', 'M', 'C', 'A', 'n' }; + template <unsigned alignMask> struct CAlignedBuffer @@ -106,7 +143,8 @@ static unsigned ReadVarInt(const Byte *p, size_t maxSize, UInt64 *val) { Byte b = p[i]; if (i < 10) - *val |= (UInt64)(b & 0x7F) << (7 * i++); + *val |= (UInt64)(b & 0x7F) << (7 * i); + i++; if ((b & 0x80) == 0) return i; } @@ -114,7 +152,54 @@ static unsigned ReadVarInt(const Byte *p, size_t maxSize, UInt64 *val) } -int CItem::FindExtra(unsigned type, unsigned &recordDataSize) const +bool CLinkInfo::Parse(const Byte *p, unsigned size) +{ + const Byte *pStart = p; + unsigned num = ReadVarInt(p, size, &Type); + if (num == 0) return false; p += num; size -= num; + + num = ReadVarInt(p, size, &Flags); + if (num == 0) return false; p += num; size -= num; + + UInt64 len; + num = ReadVarInt(p, size, &len); + if (num == 0) return false; p += num; size -= num; + + if (size != len) + return false; + + NameLen = (unsigned)len; + NameOffset = (unsigned)(p - pStart); + return true; +} + + +static void AddHex64(AString &s, UInt64 v) +{ + char sz[32]; + sz[0] = '0'; + sz[1] = 'x'; + ConvertUInt64ToHex(v, sz + 2); + s += sz; +} + + +static void PrintType(AString &s, const char * const table[], unsigned num, UInt64 val) +{ + char sz[32]; + const char *p = NULL; + if (val < num) + p = table[(unsigned)val]; + if (!p) + { + ConvertUInt64ToString(val, sz); + p = sz; + } + s += p; +} + + +int CItem::FindExtra(unsigned extraID, unsigned &recordDataSize) const { recordDataSize = 0; size_t offset = 0; @@ -137,8 +222,8 @@ int CItem::FindExtra(unsigned type, unsigned &recordDataSize) const rem = (size_t)size; } { - UInt64 type2; - unsigned num = ReadVarInt(Extra + offset, rem, &type2); + UInt64 id; + unsigned num = ReadVarInt(Extra + offset, rem, &id); if (num == 0) return -1; offset += num; @@ -147,12 +232,12 @@ int CItem::FindExtra(unsigned type, unsigned &recordDataSize) const // There was BUG in RAR 5.21- : it stored (size-1) instead of (size) // for Subdata record in Service header. // That record always was last in bad archives, so we can fix that case. - if (type2 == NExtraRecordType::kSubdata + if (id == NExtraID::kSubdata && RecordType == NHeaderType::kService && rem + 1 == Extra.Size() - offset) rem++; - if (type2 == type) + if (id == extraID) { recordDataSize = (unsigned)rem; return (int)offset; @@ -164,19 +249,118 @@ int CItem::FindExtra(unsigned type, unsigned &recordDataSize) const } +void CItem::PrintInfo(AString &s) const +{ + size_t offset = 0; + + for (;;) + { + size_t rem = Extra.Size() - offset; + if (rem == 0) + return; + + { + UInt64 size; + unsigned num = ReadVarInt(Extra + offset, rem, &size); + if (num == 0) + return; + offset += num; + rem -= num; + if (size > rem) + break; + rem = (size_t)size; + } + { + UInt64 id; + { + unsigned num = ReadVarInt(Extra + offset, rem, &id); + if (num == 0) + break; + offset += num; + rem -= num; + } + + // There was BUG in RAR 5.21- : it stored (size-1) instead of (size) + // for Subdata record in Service header. + // That record always was last in bad archives, so we can fix that case. + if (id == NExtraID::kSubdata + && RecordType == NHeaderType::kService + && rem + 1 == Extra.Size() - offset) + rem++; + + s.Add_Space_if_NotEmpty(); + PrintType(s, g_ExtraTypes, ARRAY_SIZE(g_ExtraTypes), id); + + if (id == NExtraID::kTime) + { + const Byte *p = Extra + offset; + UInt64 flags; + unsigned num = ReadVarInt(p, rem, &flags); + if (num != 0) + { + s += ':'; + for (unsigned i = 0; i < ARRAY_SIZE(g_ExtraTimeFlags); i++) + if ((flags & ((UInt64)1 << i)) != 0) + s += g_ExtraTimeFlags[i]; + flags &= ~(((UInt64)1 << ARRAY_SIZE(g_ExtraTimeFlags)) - 1); + if (flags != 0) + { + s += '_'; + AddHex64(s, flags); + } + } + } + else if (id == NExtraID::kLink) + { + CLinkInfo linkInfo; + if (linkInfo.Parse(Extra + offset, (unsigned)rem)) + { + s += ':'; + PrintType(s, g_LinkTypes, ARRAY_SIZE(g_LinkTypes), linkInfo.Type); + UInt64 flags = linkInfo.Flags; + if (flags != 0) + { + s += ':'; + if (flags & NLinkFlags::kTargetIsDir) + { + s += 'D'; + flags &= ~((UInt64)NLinkFlags::kTargetIsDir); + } + if (flags != 0) + { + s += '_'; + AddHex64(s, flags); + } + } + } + } + + offset += rem; + } + } + + s.Add_OptSpaced("ERROR"); +} + + bool CCryptoInfo::Parse(const Byte *p, size_t size) { + Algo = 0; + Flags = 0; + Cnt = 0; + unsigned num = ReadVarInt(p, size, &Algo); if (num == 0) return false; p += num; size -= num; num = ReadVarInt(p, size, &Flags); if (num == 0) return false; p += num; size -= num; + if (size > 0) + Cnt = p[0]; + if (size != 1 + 16 + 16 + (unsigned)(IsThereCheck() ? 12 : 0)) return false; - Cnt = p[0]; - return true; } @@ -184,7 +368,7 @@ bool CCryptoInfo::Parse(const Byte *p, size_t size) bool CItem::FindExtra_Version(UInt64 &version) const { unsigned size; - int offset = FindExtra(NExtraRecordType::kVersion, size); + int offset = FindExtra(NExtraID::kVersion, size); if (offset < 0) return false; const Byte *p = Extra + (unsigned)offset; @@ -202,26 +386,12 @@ bool CItem::FindExtra_Version(UInt64 &version) const bool CItem::FindExtra_Link(CLinkInfo &link) const { unsigned size; - int offset = FindExtra(NExtraRecordType::kLink, size); + int offset = FindExtra(NExtraID::kLink, size); if (offset < 0) return false; - const Byte *p = Extra + (unsigned)offset; - - unsigned num = ReadVarInt(p, size, &link.Type); - if (num == 0) return false; p += num; size -= num; - - num = ReadVarInt(p, size, &link.Flags); - if (num == 0) return false; p += num; size -= num; - - UInt64 len; - num = ReadVarInt(p, size, &len); - if (num == 0) return false; p += num; size -= num; - - if (size != len) + if (!link.Parse(Extra + (unsigned)offset, size)) return false; - - link.NameLen = (unsigned)len; - link.NameOffset = (unsigned)(p - Extra); + link.NameOffset += offset; return true; } @@ -268,14 +438,14 @@ void CItem::Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) UString unicode; if (ConvertUTF8ToUnicode(s, unicode)) - prop = NItemName::GetOSName(unicode); + prop = NItemName::GetOsPath(unicode); } bool CItem::GetAltStreamName(AString &name) const { name.Empty(); unsigned size; - int offset = FindExtra(NExtraRecordType::kSubdata, size); + int offset = FindExtra(NExtraID::kSubdata, size); if (offset < 0) return false; name.SetFrom_CalcLen((const char *)(Extra + (unsigned)offset), size); @@ -578,7 +748,7 @@ HRESULT CInArchive::ReadBlockHeader(CHeader &h) /* -int CInArcInfo::FindExtra(unsigned type, unsigned &recordDataSize) const +int CInArcInfo::FindExtra(unsigned extraID, unsigned &recordDataSize) const { recordDataSize = 0; size_t offset = 0; @@ -601,14 +771,14 @@ int CInArcInfo::FindExtra(unsigned type, unsigned &recordDataSize) const rem = (size_t)size; } { - UInt64 type2; - unsigned num = ReadVarInt(Extra + offset, rem, &type2); + UInt64 id; + unsigned num = ReadVarInt(Extra + offset, rem, &id); if (num == 0) return -1; offset += num; rem -= num; - if (type2 == type) + if (id == extraID) { recordDataSize = (unsigned)rem; return (int)offset; @@ -929,7 +1099,7 @@ HRESULT CUnpacker::Create(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, bool } unsigned cryptoSize = 0; - int cryptoOffset = item.FindExtra(NExtraRecordType::kCrypto, cryptoSize); + int cryptoOffset = item.FindExtra(NExtraID::kCrypto, cryptoSize); if (cryptoOffset >= 0) { @@ -1023,7 +1193,7 @@ HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSiz // if (res == S_OK) { unsigned cryptoSize = 0; - int cryptoOffset = lastItem.FindExtra(NExtraRecordType::kCrypto, cryptoSize); + int cryptoOffset = lastItem.FindExtra(NExtraID::kCrypto, cryptoSize); NCrypto::NRar5::CDecoder *crypto = NULL; if (cryptoOffset >= 0) @@ -1190,7 +1360,7 @@ static const Byte kProps[] = kpidCRC, kpidHostOS, kpidMethod, - + kpidCharacts, kpidSymLink, kpidHardLink, kpidCopyLink, @@ -1308,8 +1478,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { if (/* &_missingVol || */ !_missingVolName.IsEmpty()) { - UString s; - s.SetFromAscii("Missing volume : "); + UString s ("Missing volume : "); s += _missingVolName; prop = s; } @@ -1339,13 +1508,11 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { if (arcInfo->IsVolume()) { - char sz[32]; - ConvertUInt64ToString(arcInfo->GetVolIndex() + 1, sz); - unsigned len = MyStringLen(sz); - AString s = "part"; - for (; len < 2; len++) + AString s ("part"); + UInt32 v = (UInt32)arcInfo->GetVolIndex() + 1; + if (v < 10) s += '0'; - s += sz; + s.Add_UInt32(v); s += ".rar"; prop = s; } @@ -1452,7 +1619,7 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data static void TimeRecordToProp(const CItem &item, unsigned stampIndex, NCOM::CPropVariant &prop) { unsigned size; - int offset = item.FindExtra(NExtraRecordType::kTime, size); + int offset = item.FindExtra(NExtraID::kTime, size); if (offset < 0) return; @@ -1470,29 +1637,43 @@ static void TimeRecordToProp(const CItem &item, unsigned stampIndex, NCOM::CProp return; unsigned numStamps = 0; + unsigned curStamp = 0; unsigned i; for (i = 0; i < 3; i++) if ((flags & (NTimeRecord::NFlags::kMTime << i)) != 0) + { + if (i == stampIndex) + curStamp = numStamps; numStamps++; - unsigned stampSizeLog = ((flags & NTimeRecord::NFlags::kUnixTime) != 0) ? 2 : 3; - - if ((numStamps << stampSizeLog) != size) - return; - - numStamps = 0; - for (i = 0; i < stampIndex; i++) - if ((flags & (NTimeRecord::NFlags::kMTime << i)) != 0) - numStamps++; - - p += (numStamps << stampSizeLog); + } FILETIME ft; + if ((flags & NTimeRecord::NFlags::kUnixTime) != 0) - NWindows::NTime::UnixTimeToFileTime(Get32(p), ft); + { + curStamp *= 4; + if (curStamp + 4 > size) + return; + const Byte *p2 = p + curStamp; + UInt64 val = NTime::UnixTimeToFileTime64(Get32(p2)); + numStamps *= 4; + if ((flags & NTimeRecord::NFlags::kUnixNs) != 0 && numStamps * 2 <= size) + { + const UInt32 ns = Get32(p2 + numStamps) & 0x3FFFFFFF; + if (ns < 1000000000) + val += ns / 100; + } + ft.dwLowDateTime = (DWORD)val; + ft.dwHighDateTime = (DWORD)(val >> 32); + } else { - ft.dwLowDateTime = Get32(p); - ft.dwHighDateTime = Get32(p + 4); + curStamp *= 8; + if (curStamp + 8 > size) + return; + const Byte *p2 = p + curStamp; + ft.dwLowDateTime = Get32(p2); + ft.dwHighDateTime = Get32(p2 + 4); } prop = ft; @@ -1537,19 +1718,19 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val break; if (item.Version_Defined) { - wchar_t temp[32]; + char temp[32]; // temp[0] = ';'; // ConvertUInt64ToString(item.Version, temp + 1); // unicodeName += temp; ConvertUInt64ToString(item.Version, temp); - UString s2 = L"[VER]" WSTRING_PATH_SEPARATOR; + UString s2 ("[VER]" STRING_PATH_SEPARATOR); s2 += temp; s2.Add_PathSepar(); unicodeName.Insert(0, s2); } } - NItemName::ConvertToOSName2(unicodeName); + NItemName::ReplaceToOsSlashes_Remove_TailSlash(unicodeName); prop = unicodeName; break; @@ -1623,7 +1804,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidMethod: { - char temp[64]; + char temp[128]; unsigned algo = item.GetAlgoVersion(); char *s = temp; if (algo != 0) @@ -1645,16 +1826,28 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } unsigned cryptoSize = 0; - int cryptoOffset = item.FindExtra(NExtraRecordType::kCrypto, cryptoSize); + int cryptoOffset = item.FindExtra(NExtraID::kCrypto, cryptoSize); if (cryptoOffset >= 0) { s = temp + strlen(temp); *s++ = ' '; - strcpy(s, "AES:"); + CCryptoInfo cryptoInfo; - if (cryptoInfo.Parse(item.Extra + (unsigned)cryptoOffset, cryptoSize)) + + bool isOK = cryptoInfo.Parse(item.Extra + (unsigned)cryptoOffset, cryptoSize); + + if (cryptoInfo.Algo == 0) + s = MyStpCpy(s, "AES"); + else { + s = MyStpCpy(s, "Crypto_"); + ConvertUInt64ToString(cryptoInfo.Algo, s); s += strlen(s); + } + + if (isOK) + { + *s++ = ':'; ConvertUInt32ToString(cryptoInfo.Cnt, s); s += strlen(s); *s++ = ':'; @@ -1666,6 +1859,35 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val break; } + case kpidCharacts: + { + AString s; + + if (item.ACL >= 0) + { + s.Add_OptSpaced("ACL"); + } + + UInt32 flags = item.Flags; + // flags &= ~(6); // we don't need compression related bits here. + + if (flags != 0) + { + AString s2 = FlagsToString(k_FileFlags, ARRAY_SIZE(k_FileFlags), flags); + if (!s2.IsEmpty()) + { + s.Add_OptSpaced(s2); + } + } + + item.PrintInfo(s); + + if (!s.IsEmpty()) + prop = s; + break; + } + + case kpidHostOS: if (item.HostOS < ARRAY_SIZE(kHostOS)) prop = kHostOS[(size_t)item.HostOS]; @@ -1788,7 +2010,7 @@ void CHandler::FillLinks() const CItem &item = _items[ref.Item]; if (item.IsDir() || item.IsService() || item.PackSize != 0) continue; - CItem::CLinkInfo linkInfo; + CLinkInfo linkInfo; if (!item.FindExtra_Link(linkInfo) || linkInfo.Type != NLinkType::kFileCopy) continue; link.SetFrom_CalcLen((const char *)(item.Extra + linkInfo.NameOffset), linkInfo.NameLen); diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.h b/CPP/7zip/Archive/Rar/Rar5Handler.h index 27e937de..d3e33d7c 100644 --- a/CPP/7zip/Archive/Rar/Rar5Handler.h +++ b/CPP/7zip/Archive/Rar/Rar5Handler.h @@ -85,7 +85,7 @@ enum EHostOS // ---------- Extra ---------- -namespace NExtraRecordType +namespace NExtraID { enum { @@ -99,7 +99,7 @@ namespace NExtraRecordType }; } -// const unsigned kCryptoAlgo_AES = 0; +const unsigned kCryptoAlgo_AES = 0; namespace NCryptoFlags { @@ -133,8 +133,9 @@ namespace NTimeRecord { const unsigned kUnixTime = 1 << 0; const unsigned kMTime = 1 << 1; - // const unsigned kCTime = 1 << 2; - // const unsigned kATime = 1 << 3; + const unsigned kCTime = 1 << 2; + const unsigned kATime = 1 << 3; + const unsigned kUnixNs = 1 << 4; } } @@ -156,6 +157,17 @@ namespace NLinkFlags } +struct CLinkInfo +{ + UInt64 Type; + UInt64 Flags; + unsigned NameOffset; + unsigned NameLen; + + bool Parse(const Byte *p, unsigned size); +}; + + struct CItem { UInt32 CommonFlags; @@ -230,18 +242,20 @@ struct CItem bool Is_ACL() const { return IsService() && Name == "ACL"; } // bool Is_QO() const { return IsService() && Name == "QO"; } - int FindExtra(unsigned type, unsigned &recordDataSize) const; + int FindExtra(unsigned extraID, unsigned &recordDataSize) const; + void PrintInfo(AString &s) const; + bool IsEncrypted() const { unsigned size; - return FindExtra(NExtraRecordType::kCrypto, size) >= 0; + return FindExtra(NExtraID::kCrypto, size) >= 0; } int FindExtra_Blake() const { unsigned size = 0; - int offset = FindExtra(NExtraRecordType::kHash, size); + int offset = FindExtra(NExtraID::kHash, size); if (offset >= 0 && size == BLAKE2S_DIGEST_SIZE + 1 && Extra[(unsigned)offset] == kHashID_Blake2sp) @@ -251,14 +265,6 @@ struct CItem bool FindExtra_Version(UInt64 &version) const; - struct CLinkInfo - { - UInt64 Type; - UInt64 Flags; - unsigned NameOffset; - unsigned NameLen; - }; - bool FindExtra_Link(CLinkInfo &link) const; void Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) const; bool Is_CopyLink() const; @@ -313,7 +319,7 @@ struct CInArcInfo bool Is_Recovery() const { return (Flags & NLocatorFlags::kRecovery) != 0; } }; - int FindExtra(unsigned type, unsigned &recordDataSize) const; + int FindExtra(unsigned extraID, unsigned &recordDataSize) const; bool FindExtra_Locator(CLocator &locator) const; */ diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp index e858c1ea..c097b15c 100644 --- a/CPP/7zip/Archive/Rar/RarHandler.cpp +++ b/CPP/7zip/Archive/Rar/RarHandler.cpp @@ -104,20 +104,18 @@ static const char * const kHostOS[] = , "BeOS" }; -static const char *kUnknownOS = "Unknown"; - -static const CUInt32PCharPair k_Flags[] = +static const char * const k_Flags[] = { - { 0, "Volume" }, - { 1, "Comment" }, - { 2, "Lock" }, - { 3, "Solid" }, - { 4, "NewVolName" }, // pack_comment in old versuons - { 5, "Authenticity" }, - { 6, "Recovery" }, - { 7, "BlockEncryption" }, - { 8, "FirstVolume" }, - { 9, "EncryptVer" } + "Volume" + , "Comment" + , "Lock" + , "Solid" + , "NewVolName" // pack_comment in old versuons + , "Authenticity" + , "Recovery" + , "BlockEncryption" + , "FirstVolume" + , "EncryptVer" // 9 }; enum EErrorType @@ -132,13 +130,13 @@ class CInArchive { IInStream *m_Stream; UInt64 m_StreamStartPosition; - CBuffer<wchar_t> _unicodeNameBuffer; + UString _unicodeNameBuffer; CByteBuffer _comment; CByteBuffer m_FileHeaderData; NHeader::NBlock::CBlock m_BlockHeader; NCrypto::NRar3::CDecoder *m_RarAESSpec; CMyComPtr<ICompressFilter> m_RarAES; - CBuffer<Byte> m_DecryptedData; + CByteBuffer m_DecryptedData; Byte *m_DecryptedDataAligned; UInt32 m_DecryptedDataSize; bool m_CryptoMode; @@ -272,14 +270,19 @@ bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size) return processed == size; } -static void DecodeUnicodeFileName(const Byte *name, const Byte *encName, + +static unsigned DecodeUnicodeFileName(const Byte *name, const Byte *encName, unsigned encSize, wchar_t *unicodeName, unsigned maxDecSize) { unsigned encPos = 0; unsigned decPos = 0; unsigned flagBits = 0; Byte flags = 0; - Byte highByte = encName[encPos++]; + + if (encPos >= encSize) + return 0; // error + const unsigned highBits = ((unsigned)encName[encPos++]) << 8; + while (encPos < encSize && decPos < maxDecSize) { if (flagBits == 0) @@ -287,40 +290,46 @@ static void DecodeUnicodeFileName(const Byte *name, const Byte *encName, flags = encName[encPos++]; flagBits = 8; } - switch (flags >> 6) + + if (encPos >= encSize) + break; // error + unsigned len = encName[encPos++]; + + flagBits -= 2; + const unsigned mode = (flags >> flagBits) & 3; + + if (mode != 3) { - case 0: - unicodeName[decPos++] = encName[encPos++]; - break; - case 1: - unicodeName[decPos++] = (wchar_t)(encName[encPos++] + (highByte << 8)); - break; - case 2: - unicodeName[decPos++] = (wchar_t)(encName[encPos] + (encName[encPos + 1] << 8)); - encPos += 2; - break; - case 3: - { - unsigned len = encName[encPos++]; - if (len & 0x80) - { - Byte correction = encName[encPos++]; - for (len = (len & 0x7f) + 2; - len > 0 && decPos < maxDecSize; len--, decPos++) - unicodeName[decPos] = (wchar_t)(((name[decPos] + correction) & 0xff) + (highByte << 8)); - } - else - for (len += 2; len > 0 && decPos < maxDecSize; len--, decPos++) - unicodeName[decPos] = name[decPos]; - } - break; + if (mode == 1) + len += highBits; + else if (mode == 2) + { + if (encPos >= encSize) + break; // error + len += ((unsigned)encName[encPos++] << 8); + } + unicodeName[decPos++] = (wchar_t)len; + } + else + { + if (len & 0x80) + { + if (encPos >= encSize) + break; // error + Byte correction = encName[encPos++]; + for (len = (len & 0x7f) + 2; len > 0 && decPos < maxDecSize; len--, decPos++) + unicodeName[decPos] = (wchar_t)(((name[decPos] + correction) & 0xff) + highBits); + } + else + for (len += 2; len > 0 && decPos < maxDecSize; len--, decPos++) + unicodeName[decPos] = name[decPos]; } - flags <<= 2; - flagBits -= 2; } - unicodeName[decPos < maxDecSize ? decPos : maxDecSize - 1] = 0; + + return decPos < maxDecSize ? decPos : maxDecSize - 1; } + void CInArchive::ReadName(const Byte *p, unsigned nameSize, CItem &item) { item.UnicodeName.Empty(); @@ -336,8 +345,8 @@ void CInArchive::ReadName(const Byte *p, unsigned nameSize, CItem &item) { i++; unsigned uNameSizeMax = MyMin(nameSize, (unsigned)0x400); - _unicodeNameBuffer.AllocAtLeast(uNameSizeMax + 1); - DecodeUnicodeFileName(p, p + i, nameSize - i, _unicodeNameBuffer, uNameSizeMax); + unsigned len = DecodeUnicodeFileName(p, p + i, nameSize - i, _unicodeNameBuffer.GetBuf(uNameSizeMax), uNameSizeMax); + _unicodeNameBuffer.ReleaseBuf_SetEnd(len); item.UnicodeName = _unicodeNameBuffer; } else if (!ConvertUTF8ToUnicode(item.Name, item.UnicodeName)) @@ -818,7 +827,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidSolid: prop = _arcInfo.IsSolid(); break; case kpidCharacts: { - AString s = FlagsToString(k_Flags, ARRAY_SIZE(k_Flags), _arcInfo.Flags); + AString s (FlagsToString(k_Flags, ARRAY_SIZE(k_Flags), _arcInfo.Flags)); // FLAGS_TO_PROP(k_Flags, _arcInfo.Flags, prop); if (_arcInfo.Is_DataCRC_Defined()) { @@ -871,8 +880,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) if (/* &_missingVol || */ !_missingVolName.IsEmpty()) { - UString s; - s.SetFromAscii("Missing volume : "); + UString s ("Missing volume : "); s += _missingVolName; prop = s; } @@ -900,13 +908,11 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { if (_arcInfo.Is_VolNumber_Defined()) { - char sz[16]; - ConvertUInt32ToString((UInt32)_arcInfo.VolNumber + 1, sz); - unsigned len = MyStringLen(sz); - AString s = "part"; - for (; len < 2; len++) + AString s ("part"); + UInt32 v = (UInt32)_arcInfo.VolNumber + 1; + if (v < 10) s += '0'; - s += sz; + s.Add_UInt32(v); s += ".rar"; prop = s; } @@ -974,7 +980,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val u = mainItem->GetName(); u += item.GetName(); */ - prop = (const wchar_t *)NItemName::WinNameToOSName(item.GetName()); + prop = (const wchar_t *)NItemName::WinPathToOsPath(item.GetName()); break; } case kpidIsDir: prop = item.IsDir(); break; @@ -1015,7 +1021,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val prop = s; break; } - case kpidHostOS: prop = (item.HostOS < ARRAY_SIZE(kHostOS)) ? kHostOS[item.HostOS] : kUnknownOS; break; + case kpidHostOS: + TYPE_TO_PROP(kHostOS, item.HostOS, prop); + break; } prop.Detach(value); return S_OK; @@ -1324,7 +1332,13 @@ STDMETHODIMP CVolsInStream::Read(void *data, UInt32 size, UInt32 *processedSize) if (_curIndex >= _refItem.NumItems) break; const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex]; - IInStream *s = (*_arcs)[_refItem.VolumeIndex + _curIndex].Stream; + unsigned volIndex = _refItem.VolumeIndex + _curIndex; + if (volIndex >= _arcs->Size()) + { + return S_OK; + // return S_FALSE; + } + IInStream *s = (*_arcs)[volIndex].Stream; RINOK(s->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL)); _stream = s; _calcCrc = (CrcIsOK && item.IsSplitAfter()); diff --git a/CPP/7zip/Archive/Rar/RarVol.h b/CPP/7zip/Archive/Rar/RarVol.h index 2d2ce473..310369d4 100644 --- a/CPP/7zip/Archive/Rar/RarVol.h +++ b/CPP/7zip/Archive/Rar/RarVol.h @@ -41,7 +41,7 @@ public: } else if (ext.IsEqualTo_Ascii_NoCase("exe")) { - _after.SetFromAscii(".rar"); + _after = ".rar"; base.DeleteFrom(dotPos); } else if (!newStyle) @@ -76,8 +76,8 @@ public: _after.Empty(); _before = base; - _before += L'.'; - _changed.SetFromAscii("r00"); + _before += '.'; + _changed = "r00"; _needChangeForNext = false; return true; } diff --git a/CPP/7zip/Archive/RpmHandler.cpp b/CPP/7zip/Archive/RpmHandler.cpp index 08df1ae7..e0ec28ce 100644 --- a/CPP/7zip/Archive/RpmHandler.cpp +++ b/CPP/7zip/Archive/RpmHandler.cpp @@ -11,6 +11,7 @@ #include "../../Common/UTFConvert.h" #include "../../Windows/PropVariant.h" +#include "../../Windows/PropVariantUtils.h" #include "../../Windows/TimeUtils.h" #include "../Common/RegisterArc.h" @@ -167,6 +168,16 @@ struct CEntry } }; + +#ifdef _SHOW_RPM_METADATA +struct CMetaFile +{ + UInt32 Tag; + UInt32 Offset; + UInt32 Size; +}; +#endif + class CHandler: public CHandlerCont { UInt64 _headersSize; // is equal to start offset of payload data @@ -198,6 +209,7 @@ class CHandler: public CHandlerCont #ifdef _SHOW_RPM_METADATA AString _metadata; + CRecordVector<CMetaFile> _metaFiles; #endif void SetTime(NCOM::CPropVariant &prop) const @@ -205,8 +217,8 @@ class CHandler: public CHandlerCont if (_time_Defined && _buildTime != 0) { FILETIME ft; - if (NTime::UnixTime64ToFileTime(_buildTime, ft)) - prop = ft; + NTime::UnixTimeToFileTime(_buildTime, ft); + prop = ft; } } @@ -266,16 +278,10 @@ void CHandler::AddCPU(AString &s) const { if (_lead.Type == kRpmType_Bin) { - char temp[16]; - const char *p; if (_lead.Cpu < ARRAY_SIZE(k_CPUs)) - p = k_CPUs[_lead.Cpu]; + s += k_CPUs[_lead.Cpu]; else - { - ConvertUInt32ToString(_lead.Cpu, temp); - p = temp; - } - s += p; + s.Add_UInt32(_lead.Cpu); } } } @@ -376,29 +382,18 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) SetStringProp(_os, prop); else { - char temp[16]; - const char *p; - if (_lead.Os < ARRAY_SIZE(k_OS)) - p = k_OS[_lead.Os]; - else - { - ConvertUInt32ToString(_lead.Os, temp); - p = temp; - } - prop = p; + TYPE_TO_PROP(k_OS, _lead.Os, prop); } break; } #ifdef _SHOW_RPM_METADATA - case kpidComment: SetStringProp(_metadata, prop); break; + // case kpidComment: SetStringProp(_metadata, prop); break; #endif case kpidName: { - AString s = GetBaseName(); - s += ".rpm"; - SetStringProp(s, prop); + SetStringProp(GetBaseName() + ".rpm", prop); break; } } @@ -408,9 +403,10 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) } -STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant prop; + if (index == 0) switch (propID) { case kpidSize: @@ -425,7 +421,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN case kpidPath: { - AString s = GetBaseName(); + AString s (GetBaseName()); s += '.'; AddSubFileExtension(s); SetStringProp(s, prop); @@ -440,6 +436,37 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN } */ } + #ifdef _SHOW_RPM_METADATA + else + { + index--; + if (index > _metaFiles.Size()) + return E_INVALIDARG; + const CMetaFile &meta = _metaFiles[index]; + switch (propID) + { + case kpidSize: + case kpidPackSize: + prop = meta.Size; + break; + + case kpidMTime: + case kpidCTime: + SetTime(prop); + break; + + case kpidPath: + { + AString s ("[META]"); + s.Add_PathSepar(); + s.Add_UInt32(meta.Tag); + prop = s; + break; + } + } + } + #endif + prop.Detach(value); return S_OK; } @@ -499,10 +526,7 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader) { #ifdef _SHOW_RPM_METADATA { - char temp[16]; - ConvertUInt32ToString(entry.Tag, temp); - - _metadata += temp; + _metadata.Add_UInt32(entry.Tag); _metadata += ": "; } #endif @@ -515,7 +539,7 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader) for (j = 0; j < rem && p[j] != 0; j++); if (j == rem) return S_FALSE; - AString s = (const char *)p; + AString s((const char *)p); switch (entry.Tag) { case RPMTAG_NAME: _name = s; break; @@ -548,9 +572,7 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader) { if (t != 0) _metadata.Add_Space(); - char temp[16]; - ConvertUInt32ToString(Get32(p + t * 4), temp); - _metadata += temp; + _metadata.Add_UInt32(Get32(p + t * 4)); } #endif } @@ -587,9 +609,7 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader) { if (t != 0) _metadata.Add_Space(); - char temp[16]; - ConvertUInt32ToString(Get16(p + t * 2), temp); - _metadata += temp; + _metadata.Add_UInt32(Get16(p + t * 2)); } } else if (entry.Type == k_EntryType_BIN) @@ -607,9 +627,18 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader) { // p = p; } + _metadata += '\n'; #endif } + + #ifdef _SHOW_RPM_METADATA + CMetaFile meta; + meta.Offset = entry.Offset; + meta.Tag = entry.Tag; + meta.Size = entry.Count; + _metaFiles.Add(meta); + #endif } headerSize += k_HeaderSig_Size; @@ -715,6 +744,7 @@ STDMETHODIMP CHandler::Close() #ifdef _SHOW_RPM_METADATA _metadata.Empty(); + _metaFiles.Size(); #endif _stream.Release(); @@ -723,7 +753,12 @@ STDMETHODIMP CHandler::Close() STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { - *numItems = 1; + *numItems = 1 + #ifdef _SHOW_RPM_METADATA + + _metaFiles.Size() + #endif + ; + return S_OK; } diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp index 72b52fe7..f4a10b1d 100644 --- a/CPP/7zip/Archive/SplitHandler.cpp +++ b/CPP/7zip/Archive/SplitHandler.cpp @@ -181,7 +181,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) seqName._splitStyle = splitStyle; if (prefix.Len() < 1) - _subName.SetFromAscii("file"); + _subName = "file"; else _subName.SetFrom(prefix, prefix.Len() - 1); diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp index 3bcb2862..29e3bb6c 100644 --- a/CPP/7zip/Archive/SquashfsHandler.cpp +++ b/CPP/7zip/Archive/SquashfsHandler.cpp @@ -11,6 +11,7 @@ #include "../../Common/MyLinux.h" #include "../../Common/IntToString.h" #include "../../Common/StringConvert.h" +#include "../../Common/UTFConvert.h" #include "../../Windows/PropVariantUtils.h" #include "../../Windows/TimeUtils.h" @@ -67,7 +68,7 @@ static const UInt32 kSignature32_LZ = 0x71736873; static const char * const k_Methods[] = { - "Unknown" + "0" , "ZLIB" , "LZMA" , "LZO" @@ -109,16 +110,16 @@ enum kFlag_EXPORT }; -static const CUInt32PCharPair k_Flags[] = +static const char * const k_Flags[] = { - { kFlag_UNC_INODES, "UNCOMPRESSED_INODES" }, - { kFlag_UNC_DATA, "UNCOMPRESSED_DATA" }, - { kFlag_CHECK, "CHECK" }, - { kFlag_UNC_FRAGS, "UNCOMPRESSED_FRAGMENTS" }, - { kFlag_NO_FRAGS, "NO_FRAGMENTS" }, - { kFlag_ALWAYS_FRAG, "ALWAYS_FRAGMENTS" }, - { kFlag_DUPLICATE, "DUPLICATES_REMOVED" }, - { kFlag_EXPORT, "EXPORTABLE" } + "UNCOMPRESSED_INODES" + , "UNCOMPRESSED_DATA" + , "CHECK" + , "UNCOMPRESSED_FRAGMENTS" + , "NO_FRAGMENTS" + , "ALWAYS_FRAGMENTS" + , "DUPLICATES_REMOVED" + , "EXPORTABLE" }; static const UInt32 kNotCompressedBit16 = (1 << 15); @@ -841,6 +842,8 @@ class CHandler: CHeader _h; bool _noPropsLZMA; bool _needCheckLzma; + + UInt32 _openCodePage; CMyComPtr<IInStream> _stream; UInt64 _sizeCalculated; @@ -944,7 +947,8 @@ static const Byte kArcProps[] = kpidClusterSize, kpidBigEndian, kpidCTime, - kpidCharacts + kpidCharacts, + kpidCodePage // kpidNumBlocks }; @@ -1333,6 +1337,8 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned return S_FALSE; rem = fileSize; + AString tempString; + CRecordVector<CTempItem> tempItems; while (rem != 0) { @@ -1398,7 +1404,7 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned } CItem item; - item.Ptr = (UInt32)(p - _dirs.Data); + item.Ptr = (UInt32)(p - (const Byte *)_dirs.Data); UInt32 size; if (_h.IsOldVersion()) @@ -1432,6 +1438,14 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned size++; if (rem < size) return S_FALSE; + + if (_openCodePage == CP_UTF8) + { + tempString.SetFrom_CalcLen((const char *)p, size); + if (!CheckUTF8(tempString)) + _openCodePage = CP_OEMCP; + } + p += size; rem -= size; item.Parent = parent; @@ -1706,6 +1720,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb STDMETHODIMP CHandler::Close() { + _openCodePage = CP_UTF8; _sizeCalculated = 0; _limitedInStreamSpec->ReleaseStream(); @@ -1829,6 +1844,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { case kpidMethod: { + char sz[16]; const char *s; if (_noPropsLZMA) s = "LZMA Spec"; @@ -1836,25 +1852,27 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) s = "LZMA ZLIB"; else { - s = k_Methods[0]; + s = NULL; if (_h.Method < ARRAY_SIZE(k_Methods)) s = k_Methods[_h.Method]; + if (!s) + { + ConvertUInt32ToString(_h.Method, sz); + s = sz; + } } prop = s; break; } case kpidFileSystem: { - AString res = "SquashFS"; + AString res ("SquashFS"); if (_h.SeveralMethods) res += "-LZMA"; res.Add_Space(); - char s[16]; - ConvertUInt32ToString(_h.Major, s); - res += s; + res.Add_UInt32(_h.Major); res += '.'; - ConvertUInt32ToString(_h.Minor, s); - res += s; + res.Add_UInt32(_h.Minor); prop = res; break; } @@ -1875,6 +1893,24 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) if (_sizeCalculated >= _h.InodeTable) prop = _sizeCalculated - _h.InodeTable; break; + + case kpidCodePage: + { + char sz[16]; + const char *name = NULL; + switch (_openCodePage) + { + case CP_OEMCP: name = "OEM"; break; + case CP_UTF8: name = "UTF-8"; break; + } + if (!name) + { + ConvertUInt32ToString(_openCodePage, sz); + name = sz; + } + prop = name; + break; + } } prop.Detach(value); return S_OK; @@ -1892,7 +1928,17 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val switch (propID) { - case kpidPath: prop = MultiByteToUnicodeString(GetPath(index), CP_OEMCP); break; + case kpidPath: + { + AString path (GetPath(index)); + UString s; + if (_openCodePage == CP_UTF8) + ConvertUTF8ToUnicode(path, s); + else + MultiByteToUnicodeString2(s, path, _openCodePage); + prop = s; + break; + } case kpidIsDir: prop = isDir; break; // case kpidOffset: if (!node.IsLink()) prop = (UInt64)node.StartBlock; break; case kpidSize: if (!isDir) prop = node.GetSize(); break; diff --git a/CPP/7zip/Archive/SwfHandler.cpp b/CPP/7zip/Archive/SwfHandler.cpp index 06ed2106..16a6e6f9 100644 --- a/CPP/7zip/Archive/SwfHandler.cpp +++ b/CPP/7zip/Archive/SwfHandler.cpp @@ -10,6 +10,7 @@ #include "../../Common/MyString.h" #include "../../Windows/PropVariant.h" +#include "../../Windows/PropVariantUtils.h" #include "../Common/InBuffer.h" #include "../Common/LimitedStreams.h" @@ -562,14 +563,13 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR { _lzmaMode = false; RINOK(_props.SetProperties(names, values, numProps)); - AString m = _props.MethodName; - m.MakeLower_Ascii(); - if (m.IsEqualTo("lzma")) + const AString &m = _props.MethodName; + if (m.IsEqualTo_Ascii_NoCase("lzma")) { return E_NOTIMPL; // _lzmaMode = true; } - else if (m.IsEqualTo("deflate") || m.IsEmpty()) + else if (m.IsEqualTo_Ascii_NoCase("Deflate") || m.IsEmpty()) _lzmaMode = false; else return E_INVALIDARG; @@ -762,12 +762,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidPackSize: prop = (UInt64)tag.Buf.Size(); break; case kpidComment: - if (tag.Type < ARRAY_SIZE(g_TagDesc)) - { - const char *s = g_TagDesc[tag.Type]; - if (s != NULL) - prop = s; - } + TYPE_TO_PROP(g_TagDesc, tag.Type, prop); break; } prop.Detach(value); diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp index baa43c79..72fbf74e 100644 --- a/CPP/7zip/Archive/Tar/TarHandler.cpp +++ b/CPP/7zip/Archive/Tar/TarHandler.cpp @@ -81,20 +81,19 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidCodePage: { + char sz[16]; const char *name = NULL; switch (_openCodePage) { case CP_OEMCP: name = "OEM"; break; - case CP_UTF8: name = "UTF-8"; break; + case CP_UTF8: name = "UTF-8"; break; } - if (name != NULL) - prop = name; - else + if (!name) { - char sz[16]; ConvertUInt32ToString(_openCodePage, sz); - prop = sz; - }; + name = sz; + } + prop = name; break; } } @@ -316,7 +315,7 @@ void CHandler::TarStringToUnicode(const AString &s, NWindows::NCOM::CPropVariant else MultiByteToUnicodeString2(dest, s, _curCodePage); if (toOs) - NItemName::ConvertToOSName2(dest); + NItemName::ReplaceToOsSlashes_Remove_TailSlash(dest); prop = dest; } @@ -353,7 +352,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val prop = ft; } break; - case kpidPosixAttrib: prop = item->Mode; break; + case kpidPosixAttrib: prop = item->Get_Combined_Mode(); break; case kpidUser: TarStringToUnicode(item->User, prop); break; case kpidGroup: TarStringToUnicode(item->Group, prop); break; case kpidSymLink: if (item->LinkFlag == NFileHeader::NLinkFlag::kSymLink && !item->LinkName.IsEmpty()) TarStringToUnicode(item->LinkName, prop); break; diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp index 0b67a285..41934339 100644 --- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp +++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp @@ -35,7 +35,7 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro { UString s = prop.bstrVal; if (convertSlash) - s = NItemName::MakeLegalName(s); + NItemName::ReplaceSlashes_OsToUnix(s); if (codePage == CP_UTF8) { @@ -123,6 +123,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt return E_INVALIDARG; else ui.Mode = prop.ulVal; + // FIXME : we can clear high file type bits to be more compatible with tars created by GNU TAR. + // ui.Mode &= ~(UInt32)MY_LIN_S_IFMT; } { diff --git a/CPP/7zip/Archive/Tar/TarHeader.cpp b/CPP/7zip/Archive/Tar/TarHeader.cpp index 70be09f3..a22f36bd 100644 --- a/CPP/7zip/Archive/Tar/TarHeader.cpp +++ b/CPP/7zip/Archive/Tar/TarHeader.cpp @@ -8,15 +8,15 @@ namespace NArchive { namespace NTar { namespace NFileHeader { - const char *kLongLink = "././@LongLink"; - const char *kLongLink2 = "@LongLink"; + const char * const kLongLink = "././@LongLink"; + const char * const kLongLink2 = "@LongLink"; // The magic field is filled with this if uname and gname are valid. namespace NMagic { - // const char *kUsTar = "ustar"; // 5 chars - // const char *kGNUTar = "GNUtar "; // 7 chars and a null - // const char *kEmpty = "\0\0\0\0\0\0\0\0"; + // const char * const kUsTar = "ustar"; // 5 chars + // const char * const kGNUTar = "GNUtar "; // 7 chars and a null + // const char * const kEmpty = "\0\0\0\0\0\0\0\0"; const char kUsTar_00[8] = { 'u', 's', 't', 'a', 'r', 0, '0', '0' } ; } diff --git a/CPP/7zip/Archive/Tar/TarHeader.h b/CPP/7zip/Archive/Tar/TarHeader.h index df594d81..47971b58 100644 --- a/CPP/7zip/Archive/Tar/TarHeader.h +++ b/CPP/7zip/Archive/Tar/TarHeader.h @@ -67,15 +67,15 @@ namespace NFileHeader the last file name. */ } - extern const char *kLongLink; // = "././@LongLink"; - extern const char *kLongLink2; // = "@LongLink"; + extern const char * const kLongLink; // = "././@LongLink"; + extern const char * const kLongLink2; // = "@LongLink"; namespace NMagic { - // extern const char *kUsTar; // = "ustar"; // 5 chars - // extern const char *kGNUTar; // = "GNUtar "; // 7 chars and a null - // extern const char *kEmpty; // = "\0\0\0\0\0\0\0\0" - extern const char kUsTar_00[]; + // extern const char * const kUsTar; // = "ustar"; // 5 chars + // extern const char * const kGNUTar; // = "GNUtar "; // 7 chars and a null + // extern const char * const kEmpty; // = "\0\0\0\0\0\0\0\0" + extern const char kUsTar_00[8]; } } diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp index 57e18ac0..64807bfc 100644 --- a/CPP/7zip/Archive/Tar/TarIn.cpp +++ b/CPP/7zip/Archive/Tar/TarIn.cpp @@ -91,6 +91,16 @@ static bool ParseInt64(const char *p, Int64 &val) return res; } +static bool ParseInt64_MTime(const char *p, Int64 &val) +{ + // rare case tar contains spaces instead of MTime + for (unsigned i = 0; i < 12; i++) + if (p[i] != ' ') + return ParseInt64(p, val); + val = 0; + return true; +} + static bool ParseSize(const char *p, UInt64 &val) { if (GetBe32(p) == (UInt32)1 << 31) @@ -124,7 +134,7 @@ API_FUNC_IsArc IsArc_Tar(const Byte *p2, size_t size) Int64 time; UInt32 checkSum; CHECK(ParseSize(p, packSize)); p += 12; - CHECK(ParseInt64(p, time)); p += 12; + CHECK(ParseInt64_MTime(p, time)); p += 12; CHECK(OctalToNumber32(p, 8, checkSum)); return k_IsArc_Res_YES; } @@ -192,7 +202,7 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE RIF(ParseSize(p, item.PackSize)); item.Size = item.PackSize; p += 12; - RIF(ParseInt64(p, item.MTime)); p += 12; + RIF(ParseInt64_MTime(p, item.MTime)); p += 12; UInt32 checkSum; RIF(OctalToNumber32(p, 8, checkSum)); diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h index 5245aaa4..bc3b4084 100644 --- a/CPP/7zip/Archive/Tar/TarItem.h +++ b/CPP/7zip/Archive/Tar/TarItem.h @@ -3,6 +3,8 @@ #ifndef __ARCHIVE_TAR_ITEM_H #define __ARCHIVE_TAR_ITEM_H +#include "../../../Common/MyLinux.h" + #include "../Common/ItemNameUtils.h" #include "TarHeader.h" @@ -56,6 +58,32 @@ struct CItem return false; } + UInt32 Get_Combined_Mode() const + { + return (Mode & ~(UInt32)MY_LIN_S_IFMT) | Get_FileTypeMode_from_LinkFlag(); + } + + UInt32 Get_FileTypeMode_from_LinkFlag() const + { + switch (LinkFlag) + { + /* + case NFileHeader::NLinkFlag::kDirectory: + case NFileHeader::NLinkFlag::kDumpDir: + return MY_LIN_S_IFDIR; + */ + case NFileHeader::NLinkFlag::kSymLink: return MY_LIN_S_IFLNK; + case NFileHeader::NLinkFlag::kBlock: return MY_LIN_S_IFBLK; + case NFileHeader::NLinkFlag::kCharacter: return MY_LIN_S_IFCHR; + case NFileHeader::NLinkFlag::kFIFO: return MY_LIN_S_IFIFO; + // case return MY_LIN_S_IFSOCK; + } + + if (IsDir()) + return MY_LIN_S_IFDIR; + return MY_LIN_S_IFREG; + } + bool IsDir() const { switch (LinkFlag) diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp index d52db9f4..cfe6c5ad 100644 --- a/CPP/7zip/Archive/Udf/UdfIn.cpp +++ b/CPP/7zip/Archive/Udf/UdfIn.cpp @@ -51,13 +51,13 @@ void MY_FAST_CALL Crc16GenerateTable(void) for (i = 0; i < 256; i++) { UInt32 r = (i << 8); - for (int j = 8; j > 0; j--) - r = ((r & 0x8000) ? ((r << 1) ^ kCrc16Poly) : (r << 1)) & 0xFFFF; + for (unsigned j = 0; j < 8; j++) + r = ((r << 1) ^ (kCrc16Poly & ((UInt32)0 - (r >> 15)))) & 0xFFFF; g_Crc16Table[i] = (UInt16)r; } } -UInt16 MY_FAST_CALL Crc16_Update(UInt16 v, const void *data, size_t size) +UInt32 MY_FAST_CALL Crc16_Update(UInt32 v, const void *data, size_t size) { const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) @@ -65,12 +65,12 @@ UInt16 MY_FAST_CALL Crc16_Update(UInt16 v, const void *data, size_t size) return v; } -UInt16 MY_FAST_CALL Crc16Calc(const void *data, size_t size) +UInt32 MY_FAST_CALL Crc16Calc(const void *data, size_t size) { return Crc16_Update(CRC16_INIT_VAL, data, size); } -struct CCrc16TableInit { CCrc16TableInit() { Crc16GenerateTable(); } } g_Crc16TableInit; +static struct CCrc16TableInit { CCrc16TableInit() { Crc16GenerateTable(); } } g_Crc16TableInit; @@ -109,7 +109,7 @@ static UString ParseDString(const Byte *data, unsigned size) } } else - return L"[unknow]"; + return UString("[unknow]"); *p = 0; res.ReleaseBuf_SetLen((unsigned)(p - (const wchar_t *)res)); } @@ -179,12 +179,12 @@ HRESULT CTag::Parse(const Byte *buf, size_t size) Id = Get16(buf); Version = Get16(buf + 2); // SerialNumber = Get16(buf + 6); - UInt16 crc = Get16(buf + 8); - UInt16 crcLen = Get16(buf + 10); + UInt32 crc = Get16(buf + 8); + UInt32 crcLen = Get16(buf + 10); // TagLocation = Get32(buf + 12); - if (size >= 16 + (size_t)crcLen) - if (crc == Crc16Calc(buf + 16, crcLen)) + if (size >= 16 + crcLen) + if (crc == Crc16Calc(buf + 16, (size_t)crcLen)) return S_OK; return S_FALSE; } @@ -1077,14 +1077,7 @@ static UString GetSpecName(const UString &name) UString name2 = name; name2.Trim(); if (name2.IsEmpty()) - { - /* - wchar_t s[32]; - ConvertUInt64ToString(id, s); - return L"[" + (UString)s + L"]"; - */ - return L"[]"; - } + return UString("[]"); return name; } @@ -1116,22 +1109,19 @@ UString CInArchive::GetItemPath(int volIndex, int fsIndex, int refIndex, if (showFsName) { - wchar_t s[32]; - ConvertUInt32ToString(fsIndex, s); - UString newName = L"File Set "; - newName += s; + UString newName ("File Set "); + newName.Add_UInt32(fsIndex); UpdateWithName(name, newName); } if (showVolName) { - wchar_t s[32]; - ConvertUInt32ToString(volIndex, s); - UString newName = s; + UString newName; + newName.Add_UInt32(volIndex); UString newName2 = vol.GetName(); if (newName2.IsEmpty()) - newName2 = L"Volume"; - newName += L'-'; + newName2 = "Volume"; + newName += '-'; newName += newName2; UpdateWithName(name, newName); } diff --git a/CPP/7zip/Archive/UefiHandler.cpp b/CPP/7zip/Archive/UefiHandler.cpp index ff0737a0..f49b62c8 100644 --- a/CPP/7zip/Archive/UefiHandler.cpp +++ b/CPP/7zip/Archive/UefiHandler.cpp @@ -46,20 +46,58 @@ static const size_t kBufTotalSizeMax = (1 << 29); static const unsigned kNumFilesMax = (1 << 18); static const unsigned kLevelMax = 64; +static const Byte k_IntelMeSignature[] = +{ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x5A, 0xA5, 0xF0, 0x0F +}; + +bool IsIntelMe(const Byte *p) +{ + return memcmp(p, k_IntelMeSignature, sizeof(k_IntelMeSignature)) == 0; +} + static const unsigned kFvHeaderSize = 0x38; 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[kGuidSize] = CAPSULE_SIGNATURE; + +#define CAPSULE_SIGNATURE 0xBD,0x86,0x66,0x3B,0x76,0x0D,0x30,0x40,0xB7,0x0E,0xB5,0x51,0x9E,0x2F,0xC5,0xA0 +#define CAPSULE2_SIGNATURE 0x8B,0xA6,0x3C,0x4A,0x23,0x77,0xFB,0x48,0x80,0x3D,0x57,0x8C,0xC1,0xFE,0xC4,0x4D +#define CAPSULE_UEFI_SIGNATURE 0xB9,0x82,0x91,0x53,0xB5,0xAB,0x91,0x43,0xB6,0x9A,0xE3,0xA9,0x43,0xF7,0x2F,0xCC +/* + 6dcbd5ed-e82d-4c44-bda1-7194199ad92a : Firmware Management ` +*/ + +static const Byte k_Guids_Capsules[][kGuidSize] = +{ + { CAPSULE_SIGNATURE }, + { CAPSULE2_SIGNATURE }, + { CAPSULE_UEFI_SIGNATURE } +}; + 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; -static const Byte k_MacFS_Guid[kGuidSize] = - { 0xAD,0xEE,0xAD,0x04,0xFF,0x61,0x31,0x4D,0xB6,0xBA,0x64,0xF8,0xBF,0x90,0x1F,0x5A }; +#define FFS1_SIGNATURE 0xD9,0x54,0x93,0x7A,0x68,0x04,0x4A,0x44,0x81,0xCE,0x0B,0xF6,0x17,0xD8,0x90,0xDF +#define FFS2_SIGNATURE 0x78,0xE5,0x8C,0x8C,0x3D,0x8A,0x1C,0x4F,0x99,0x35,0x89,0x61,0x85,0xC3,0x2D,0xD3 +#define MACFS_SIGNATURE 0xAD,0xEE,0xAD,0x04,0xFF,0x61,0x31,0x4D,0xB6,0xBA,0x64,0xF8,0xBF,0x90,0x1F,0x5A +// APPLE_BOOT +/* + "FFS3": "5473c07a-3dcb-4dca-bd6f-1e9689e7349a", + "NVRAM_EVSA": "fff12b8d-7696-4c8b-a985-2747075b4f50", + "NVRAM_NVAR": "cef5b9a3-476d-497f-9fdc-e98143e0422c", + "NVRAM_EVSA2": "00504624-8a59-4eeb-bd0f-6b36e96128e0", +static const Byte k_NVRAM_NVAR_Guid[kGuidSize] = + { 0xA3,0xB9,0xF5,0xCE,0x6D,0x47,0x7F,0x49,0x9F,0xDC,0xE9,0x81,0x43,0xE0,0x42,0x2C }; +*/ + +static const Byte k_Guids_FS[][kGuidSize] = +{ + { FFS1_SIGNATURE }, + { FFS2_SIGNATURE }, + { MACFS_SIGNATURE } +}; + static const UInt32 kFvSignature = 0x4856465F; // "_FVH" @@ -80,6 +118,8 @@ static const Byte kGuids[][kGuidSize] = { 0x18,0x88,0x53,0x4A,0xE0,0x5A,0xB2,0x4E,0xB2,0xEB,0x48,0x8B,0x23,0x65,0x70,0x22 } }; +static const Byte k_Guid_LZMA_COMPRESSED[kGuidSize] = + { 0x98,0x58,0x4E,0xEE,0x14,0x39,0x59,0x42,0x9D,0x6E,0xDC,0x7B,0xD7,0x94,0x03,0xCF }; static const char * const kGuidNames[] = { @@ -180,7 +220,12 @@ static int FindGuid(const Byte *p) static bool IsFfs(const Byte *p) { - return (Get32(p + 0x28) == kFvSignature && AreGuidsEq(p + kFfsGuidOffset, k_FFS_Guid)); + if (Get32(p + 0x28) != kFvSignature) + return false; + for (unsigned i = 0; i < ARRAY_SIZE(k_Guids_FS); i++) + if (AreGuidsEq(p + kFfsGuidOffset, k_Guids_FS[i])) + return true; + return false; } #define FVB_ERASE_POLARITY (1 << 11) @@ -329,39 +374,15 @@ static const char * const g_Methods[] = , "LZMA" }; -static AString UInt32ToString(UInt32 val) -{ - char sz[16]; - ConvertUInt32ToString(val, sz); - return sz; -} -static void ConvertByteToHex(unsigned value, char *s) +static void AddGuid(AString &dest, const Byte *p, bool full) { - for (int i = 0; i < 2; i++) - { - unsigned t = value & 0xF; - value >>= 4; - s[1 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); - } -} - -static AString GuidToString(const Byte *p, bool full) -{ - char s[16 * 2 + 8]; - int i; - for (i = 0; i < 4; i++) - ConvertByteToHex(p[3 - i], s + i * 2); - s[8] = 0; - - if (full) - { - s[8] = '-'; - for (i = 4; i < kGuidSize; i++) - ConvertByteToHex(p[i], s + 1 + i * 2); - s[32 + 1] = 0; - } - return s; + char s[64]; + ::RawLeGuidToString(p, s); + // MyStringUpper_Ascii(s); + if (!full) + s[8] = 0; + dest += s; } static const char * const kExpressionCommands[] = @@ -383,7 +404,7 @@ static bool ParseDepedencyExpression(const Byte *p, UInt32 size, AString &res) if (i + kGuidSize > size) return false; res.Add_Space(); - res += GuidToString(p + i, false); + AddGuid(res, p + i, false); i += kGuidSize; } res += "; "; @@ -433,6 +454,7 @@ static void AddSpaceAndString(AString &res, const AString &newString) class CFfsFileHeader { +PRF(public:) Byte CheckHeader; Byte CheckFile; Byte Attrib; @@ -530,7 +552,7 @@ public: if (align != 0) { s += " Align:"; - s += UInt32ToString((UInt32)1 << g_Allignment[align]); + s.Add_UInt32((UInt32)1 << g_Allignment[align]); } */ return s; @@ -538,6 +560,7 @@ public: }; #define G32(_offs_, dest) dest = Get32(p + (_offs_)); +#define G16(_offs_, dest) dest = Get16(p + (_offs_)); struct CCapsuleHeader { @@ -557,23 +580,51 @@ struct CCapsuleHeader void Clear() { memset(this, 0, sizeof(*this)); } - void Parse(const Byte *p) + bool Parse(const Byte *p) { + Clear(); G32(0x10, HeaderSize); G32(0x14, Flags); G32(0x18, CapsuleImageSize); - G32(0x1C, SequenceNumber); - G32(0x30, OffsetToSplitInformation); - G32(0x34, OffsetToCapsuleBody); - G32(0x38, OffsetToOemDefinedHeader); - G32(0x3C, OffsetToAuthorInformation); - G32(0x40, OffsetToRevisionInformation); - G32(0x44, OffsetToShortDescription); - G32(0x48, OffsetToLongDescription); - G32(0x4C, OffsetToApplicableDevices); + if (HeaderSize < 0x1C) + return false; + if (AreGuidsEq(p, k_Guids_Capsules[0])) + { + const unsigned kHeaderSize = 80; + if (HeaderSize != kHeaderSize) + return false; + G32(0x1C, SequenceNumber); + G32(0x30, OffsetToSplitInformation); + G32(0x34, OffsetToCapsuleBody); + G32(0x38, OffsetToOemDefinedHeader); + G32(0x3C, OffsetToAuthorInformation); + G32(0x40, OffsetToRevisionInformation); + G32(0x44, OffsetToShortDescription); + G32(0x48, OffsetToLongDescription); + G32(0x4C, OffsetToApplicableDevices); + return true; + } + else if (AreGuidsEq(p, k_Guids_Capsules[1])) + { + // capsule v2 + G16(0x1C, OffsetToCapsuleBody); + G16(0x1E, OffsetToOemDefinedHeader); + return true; + } + else if (AreGuidsEq(p, k_Guids_Capsules[2])) + { + OffsetToCapsuleBody = HeaderSize; + return true; + } + else + { + // here we must check for another capsule types + return false; + } } }; + struct CItem { AString Name; @@ -605,7 +656,10 @@ void CItem::SetGuid(const Byte *guidName, bool full) if (index >= 0) Name = kGuidNames[(unsigned)index]; else - Name = GuidToString(guidName, full); + { + Name.Empty(); + AddGuid(Name, guidName, full); + } } AString CItem::GetName(int numChildsInParent) const @@ -616,11 +670,14 @@ AString CItem::GetName(int numChildsInParent) const char sz2[32]; ConvertUInt32ToString(NameIndex, sz); ConvertUInt32ToString(numChildsInParent - 1, sz2); - unsigned numZeros = (unsigned)strlen(sz2) - (unsigned)strlen(sz); + int numZeros = (int)strlen(sz2) - (int)strlen(sz); AString res; - for (unsigned i = 0; i < numZeros; i++) + for (int i = 0; i < numZeros; i++) res += '0'; - return res + (AString)sz + '.' + Name; + res += sz; + res += '.'; + res += Name; + return res; } struct CItem2 @@ -644,21 +701,30 @@ class CHandler: UString _comment; UInt32 _methodsMask; bool _capsuleMode; + bool _headersError; size_t _totalBufsSize; CCapsuleHeader _h; UInt64 _phySize; - void AddCommentString(const wchar_t *name, UInt32 pos); + void AddCommentString(const char *name, UInt32 pos); int AddItem(const CItem &item); int AddFileItemWithIndex(CItem &item); int AddDirItem(CItem &item); unsigned AddBuf(size_t size); - HRESULT ParseSections(int bufIndex, UInt32 pos, UInt32 size, int parent, int method, unsigned level); + HRESULT DecodeLzma(const Byte *data, size_t inputSize); + + HRESULT ParseSections(int bufIndex, UInt32 pos, UInt32 size, int parent, int method, unsigned level, bool &error); + + HRESULT ParseIntelMe(int bufIndex, UInt32 posBase, + UInt32 exactSize, UInt32 limitSize, + int parent, int method, int level); + HRESULT ParseVolume(int bufIndex, UInt32 posBase, UInt32 exactSize, UInt32 limitSize, int parent, int method, int level); + HRESULT OpenCapsule(IInStream *stream); HRESULT OpenFv(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback); HRESULT Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback); @@ -674,6 +740,7 @@ static const Byte kProps[] = kpidPath, kpidIsDir, kpidSize, + // kpidOffset, kpidMethod, kpidCharacts }; @@ -698,7 +765,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { case kpidPath: { - AString path = item2.Name; + AString path (item2.Name); int cur = item2.Parent; while (cur >= 0) { @@ -714,13 +781,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val 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; + // case kpidOffset: if (!item.IsDir) prop = item.Offset; break; } prop.Detach(value); return S_OK; COM_TRY_END } -void CHandler::AddCommentString(const wchar_t *name, UInt32 pos) +void CHandler::AddCommentString(const char *name, UInt32 pos) { UString s; const Byte *buf = _bufs[0]; @@ -747,7 +815,7 @@ void CHandler::AddCommentString(const wchar_t *name, UInt32 pos) return; _comment.Add_LF(); _comment += name; - _comment.AddAscii(": "); + _comment += ": "; _comment += s; } @@ -762,13 +830,22 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) AString s; for (unsigned i = 0; i < 32; i++) if ((_methodsMask & ((UInt32)1 << i)) != 0) - AddSpaceAndString(s, g_Methods[i]); + AddSpaceAndString(s, (AString)g_Methods[i]); if (!s.IsEmpty()) prop = s; break; } case kpidComment: if (!_comment.IsEmpty()) prop = _comment; break; case kpidPhySize: prop = (UInt64)_phySize; break; + + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_headersError) v |= kpv_ErrorFlags_HeadersError; + if (v != 0) + prop = v; + break; + } } prop.Detach(value); return S_OK; @@ -785,7 +862,7 @@ static void PrintLevel(int level) static void MyPrint(UInt32 posBase, UInt32 size, int level, const char *name) { PrintLevel(level); - PRF(printf("%s, pos = %6x, size = %6d", name, posBase, size)); + PRF(printf("%s, pos = %6x, size = %6x", name, posBase, size)); } #else #define PrintLevel(level) @@ -829,8 +906,36 @@ unsigned CHandler::AddBuf(size_t size) return index; } -HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int parent, int method, unsigned level) + +HRESULT CHandler::DecodeLzma(const Byte *data, size_t inputSize) +{ + if (inputSize < 5 + 8) + return S_FALSE; + const UInt64 unpackSize = Get64(data + 5); + if (unpackSize > ((UInt32)1 << 30)) + return S_FALSE; + SizeT destLen = (SizeT)unpackSize; + const unsigned newBufIndex = AddBuf((size_t)unpackSize); + CByteBuffer &buf = _bufs[newBufIndex]; + ELzmaStatus status; + SizeT srcLen = inputSize - (5 + 8); + const SizeT srcLen2 = srcLen; + SRes res = LzmaDecode(buf, &destLen, data + 13, &srcLen, + data, 5, LZMA_FINISH_END, &status, &g_Alloc); + if (res != 0) + return S_FALSE; + if (srcLen != srcLen2 || destLen != unpackSize || ( + status != LZMA_STATUS_FINISHED_WITH_MARK && + status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) + return S_FALSE; + return S_OK; +} + + +HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int parent, int method, unsigned level, bool &error) { + error = false; + if (level > kLevelMax) return S_FALSE; MyPrint(posBase, size, level, "Sections"); @@ -842,7 +947,7 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p if (size == pos) return S_OK; PrintLevel(level); - PRF(printf("%s, pos = %6x", "Sect", pos)); + PRF(printf("%s, abs = %6x, relat = %6x", "Sect", posBase + pos, pos)); pos = (pos + 3) & ~(UInt32)3; if (pos > size) return S_FALSE; @@ -851,14 +956,23 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p return S_OK; if (rem < 4) return S_FALSE; + const Byte *p = bufData + posBase + pos; - UInt32 sectSize = Get24(p); - if (sectSize > rem || sectSize < 4) - return S_FALSE; - Byte type = p[3]; - PrintLevel(level); - PRF(printf("%s, type = %2x, pos = %6x, size = %6d", "Sect", type, pos, sectSize)); + const UInt32 sectSize = Get24(p); + const Byte type = p[3]; + + // PrintLevel(level); + PRF(printf(" type = %2x, sectSize = %6x", type, sectSize)); + + if (sectSize > rem || sectSize < 4) + { + _headersError = true; + error = true; + return S_OK; + // return S_FALSE; + } + CItem item; item.Method = method; item.BufIndex = bufIndex; @@ -891,7 +1005,8 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p // int parent = AddDirItem(item); if (compressionType == COMPRESSION_TYPE_NONE) { - RINOK(ParseSections(bufIndex, newOffset, newSectSize, parent, method, level)); + bool error2; + RINOK(ParseSections(bufIndex, newOffset, newSectSize, parent, method, level, error2)); } else if (compressionType == COMPRESSION_TYPE_LZH) { @@ -910,6 +1025,9 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p return S_FALSE; UInt32 packSize = Get32(src); UInt32 unpackSize = Get32(src + 4); + + PRF(printf(" LZH packSize = %6x, unpackSize = %6x", packSize, unpackSize)); + if (uncompressedSize != unpackSize || newSectSize - 8 != packSize) return S_FALSE; if (packSize < 1) @@ -921,30 +1039,34 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p 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. + EFI 1.1 probably used LZH with small dictionary and (pbit = 4). It was named "Efi compression". 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. + We check both LZH versions: Tiano and then Efi. */ - 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; + HRESULT res = S_FALSE; + + for (unsigned m = 0 ; m < 2; m++) + { + inStreamSpec->Init(src, packSize); + outStreamSpec->Init(buf, uncompressedSize); + lzhDecoderSpec->SetDictSize((m == 0) ? ((UInt32)1 << 19) : ((UInt32)1 << 14)); + res = lzhDecoder->Code(inStream, outStream, NULL, &uncompressedSize64, NULL); + if (res == S_OK) + break; + } + RINOK(res); } - RINOK(ParseSections(newBufIndex, 0, uncompressedSize, parent, compressionType, level)); + bool error2; + RINOK(ParseSections(newBufIndex, 0, uncompressedSize, parent, compressionType, level, error2)); } else { @@ -964,26 +1086,14 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p // firstSectType can be 0 in some archives } pStart += addSize; - UInt64 lzmaUncompressedSize = Get64(pStart + 5); - if (lzmaUncompressedSize > (1 << 30)) - return S_FALSE; + + RINOK(DecodeLzma(pStart, newSectSize - addSize)); + const size_t lzmaUncompressedSize = _bufs.Back().Size(); + // if (lzmaUncompressedSize != uncompressedSize) if (lzmaUncompressedSize < uncompressedSize) return S_FALSE; - SizeT destLen = (SizeT)lzmaUncompressedSize; - unsigned newBufIndex = AddBuf((size_t)lzmaUncompressedSize); - CByteBuffer &buf = _bufs[newBufIndex]; - ELzmaStatus status; - SizeT srcLen = newSectSize - (addSize + 5 + 8); - SizeT srcLen2 = srcLen; - SRes res = LzmaDecode(buf, &destLen, pStart + 13, &srcLen, - pStart, 5, LZMA_FINISH_END, &status, &g_Alloc); - if (res != 0) - return S_FALSE; - if (srcLen != srcLen2 || destLen != lzmaUncompressedSize || ( - status != LZMA_STATUS_FINISHED_WITH_MARK && - status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) - return S_FALSE; - RINOK(ParseSections(newBufIndex, 0, (UInt32)lzmaUncompressedSize, parent, compressionType, level)); + bool error2; + RINOK(ParseSections(_bufs.Size() - 1, 0, (UInt32)lzmaUncompressedSize, parent, compressionType, level, error2)); } _methodsMask |= (1 << compressionType); } @@ -1003,9 +1113,26 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p UInt32 newOffset = posBase + pos + dataOffset; item.Offset = newOffset; UInt32 propsSize = dataOffset - kHeaderSize; - bool needDir = true; AddSpaceAndString(item.Characts, FLAGS_TO_STRING(g_GUIDED_SECTION_ATTRIBUTES, attrib)); - if (AreGuidsEq(p + 0x4, kGuids[kGuidIndex_CRC]) && propsSize == 4) + + bool needDir = true; + unsigned newBufIndex = bufIndex; + int newMethod = method; + + if (AreGuidsEq(p + 0x4, k_Guid_LZMA_COMPRESSED)) + { + // item.Name = "guid.lzma"; + // AddItem(item); + const Byte *pStart = bufData + newOffset; + // do we need correct pStart here for lzma steram offset? + RINOK(DecodeLzma(pStart, newSectSize)); + _methodsMask |= (1 << COMPRESSION_TYPE_LZMA); + newBufIndex = _bufs.Size() - 1; + newOffset = 0; + newSectSize = (UInt32)_bufs.Back().Size(); + newMethod = COMPRESSION_TYPE_LZMA; + } + else if (AreGuidsEq(p + 0x4, kGuids[kGuidIndex_CRC]) && propsSize == 4) { needDir = false; item.KeepName = false; @@ -1023,10 +1150,12 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p AddItem(item2); } } + int newParent = parent; if (needDir) newParent = AddDirItem(item); - RINOK(ParseSections(bufIndex, newOffset, newSectSize, newParent, method, level)); + bool error2; + RINOK(ParseSections(newBufIndex, newOffset, newSectSize, newParent, newMethod, level, error2)); } else if (type == SECTION_FIRMWARE_VOLUME_IMAGE) { @@ -1100,8 +1229,8 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p AString s; if (ParseUtf16zString2(p + 6, sectDataSize - 2, s)) { - AString s2 = "ver:"; - s2 += UInt32ToString(Get16(p + 4)); + AString s2 ("ver:"); + s2.Add_UInt32(Get16(p + 4)); s2.Add_Space(); s2 += s; AddSpaceAndString(_items[item.Parent].Characts, s2); @@ -1135,6 +1264,7 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p if (needAdd) AddFileItemWithIndex(item); } + pos += sectSize; } } @@ -1174,6 +1304,7 @@ bool CVolFfsHeader::Parse(const Byte *p) return true; }; + HRESULT CHandler::ParseVolume( int bufIndex, UInt32 posBase, UInt32 exactSize, UInt32 limitSize, @@ -1181,14 +1312,13 @@ HRESULT CHandler::ParseVolume( { if (level > kLevelMax) return S_FALSE; - MyPrint(posBase, size, level, "Volume"); + MyPrint(posBase, exactSize, level, "Volume"); level++; if (exactSize < kFvHeaderSize) return S_FALSE; const Byte *p = _bufs[bufIndex] + posBase; // first 16 bytes must be zeros, but they are not zeros sometimes. - if (!AreGuidsEq(p + kFfsGuidOffset, k_FFS_Guid) && - !AreGuidsEq(p + kFfsGuidOffset, k_MacFS_Guid)) + if (!IsFfs(p)) { CItem item; item.Method = method; @@ -1196,8 +1326,10 @@ HRESULT CHandler::ParseVolume( item.Parent = parent; item.Offset = posBase; item.Size = exactSize; - item.SetGuid(p + kFfsGuidOffset); - item.Name += " [VOLUME]"; + if (!Is_FF_Stream(p + kFfsGuidOffset, 16)) + item.SetGuid(p + kFfsGuidOffset); + // if (item.Name.IsEmpty()) + item.Name += "[VOL]"; AddItem(item); return S_OK; } @@ -1268,9 +1400,13 @@ HRESULT CHandler::ParseVolume( item.Size = rem - num_FF_bytes; AddItem(item); } + PrintLevel(level); PRF(printf("== FF FF reminder")); + break; } - PrintLevel(level); PRF(printf("%s, pos = %6x, size = %6d", "FILE", posBase + pos, fh.Size)); + + PrintLevel(level); PRF(printf("%s, type = %3d, pos = %7x, size = %7x", "FILE", fh.Type, posBase + pos, fh.Size)); + if (!fh.Check(pFile, rem)) return S_FALSE; @@ -1295,9 +1431,16 @@ HRESULT CHandler::ParseVolume( item.SetGuid(fh.GuidName, full); item.Characts = fh.GetCharacts(); - PrintLevel(level); - PRF(printf("%s", item.Characts)); - + // PrintLevel(level); + PRF(printf(" : %s", item.Characts)); + + { + PRF(printf(" attrib = %2d State = %3d ", (unsigned)fh.Attrib, (unsigned)fh.State)); + PRF(char s[64]); + PRF(RawLeGuidToString(fh.GuidName, s)); + PRF(printf(" : %s ", s)); + } + if (fh.Type == FV_FILETYPE_FFS_PAD || fh.Type == FV_FILETYPE_RAW) { @@ -1321,23 +1464,127 @@ HRESULT CHandler::ParseVolume( } else { - int newParent = AddDirItem(item); - RINOK(ParseSections(bufIndex, offset, sectSize, newParent, method, level)); + /* + if (fh.Type == FV_FILETYPE_FREEFORM) + { + // in intel bio example: one FV_FILETYPE_FREEFORM file is wav file (not sections) + // AddItem(item); + } + else + */ + { + int newParent = AddDirItem(item); + bool error2; + RINOK(ParseSections(bufIndex, offset, sectSize, newParent, method, level + 1, error2)); + if (error2) + { + // in intel bio example: one FV_FILETYPE_FREEFORM file is wav file (not sections) + item.IsDir = false; + item.Size = sectSize; + item.Name.Insert(0, "[ERROR]"); + AddItem(item); + } + } } } + + return S_OK; +} + + +static const char * const kRegionName[] = +{ + "Descriptor" + , "BIOS" + , "ME" + , "GbE" + , "PDR" + , "Region5" + , "Region6" + , "Region7" +}; + + +HRESULT CHandler::ParseIntelMe( + int bufIndex, UInt32 posBase, + UInt32 exactSize, UInt32 limitSize, + int parent, int method, int level) +{ + UNUSED_VAR(limitSize) + level++; + const Byte *p = _bufs[bufIndex] + posBase; + if (exactSize < 16 + 16) + return S_FALSE; + if (!IsIntelMe(p)) + return S_FALSE; + + UInt32 v0 = GetUi32(p + 20); + // UInt32 numRegions = (v0 >> 24) & 0x7; + UInt32 regAddr = (v0 >> 12) & 0xFF0; + // UInt32 numComps = (v0 >> 8) & 0x3; + // UInt32 fcba = (v0 << 4) & 0xFF0; + + // (numRegions == 0) in header in some new images. + // So we don't use the value from header + UInt32 numRegions = 7; + + for (unsigned i = 0; i <= numRegions; i++) + { + UInt32 offset = regAddr + i * 4; + if (offset + 4 > exactSize) + break; + UInt32 val = GetUi32(p + offset); + + // only 12 bits probably are OK. + // How does it work for files larger than 16 MB? + const UInt32 kMask = 0xFFF; + // const UInt32 kMask = 0xFFFF; // 16-bit is more logical + const UInt32 lim = (val >> 16) & kMask; + const UInt32 base = (val & kMask); + + /* + strange combinations: + PDR: base = 0x1FFF lim = 0; + empty: base = 0xFFFF lim = 0xFFFF; + + PDR: base = 0x7FFF lim = 0; + empty: base = 0x7FFF lim = 0; + */ + if (base == kMask && lim == 0) + continue; // unused + + if (lim < base) + continue; // unused + + CItem item; + item.Name = kRegionName[i]; + item.Method = method; + item.BufIndex = bufIndex; + item.Parent = parent; + item.Offset = posBase + (base << 12); + if (item.Offset > exactSize) + continue; + item.Size = (lim + 1 - base) << 12; + // item.SetGuid(p + kFfsGuidOffset); + // item.Name += " [VOLUME]"; + AddItem(item); + } return S_OK; } + HRESULT CHandler::OpenCapsule(IInStream *stream) { const unsigned kHeaderSize = 80; Byte buf[kHeaderSize]; RINOK(ReadStream_FALSE(stream, buf, kHeaderSize)); - _h.Parse(buf); - if (_h.HeaderSize != kHeaderSize || - _h.CapsuleImageSize < kHeaderSize || - _h.OffsetToCapsuleBody < kHeaderSize || - _h.OffsetToCapsuleBody > _h.CapsuleImageSize) + if (!_h.Parse(buf)) + return S_FALSE; + if (_h.CapsuleImageSize < kHeaderSize + || _h.CapsuleImageSize < _h.HeaderSize + || _h.OffsetToCapsuleBody < _h.HeaderSize + || _h.OffsetToCapsuleBody > _h.CapsuleImageSize + ) return S_FALSE; _phySize = _h.CapsuleImageSize; @@ -1350,17 +1597,21 @@ HRESULT CHandler::OpenCapsule(IInStream *stream) memcpy(buf0, buf, kHeaderSize); ReadStream_FALSE(stream, buf0 + kHeaderSize, _h.CapsuleImageSize - kHeaderSize); - AddCommentString(L"Author", _h.OffsetToAuthorInformation); - AddCommentString(L"Revision", _h.OffsetToRevisionInformation); - AddCommentString(L"Short Description", _h.OffsetToShortDescription); - AddCommentString(L"Long Description", _h.OffsetToLongDescription); + AddCommentString("Author", _h.OffsetToAuthorInformation); + AddCommentString("Revision", _h.OffsetToRevisionInformation); + AddCommentString("Short Description", _h.OffsetToShortDescription); + AddCommentString("Long Description", _h.OffsetToLongDescription); + + + const UInt32 size = _h.CapsuleImageSize - _h.OffsetToCapsuleBody; - return ParseVolume(bufIndex, _h.OffsetToCapsuleBody, - _h.CapsuleImageSize - _h.OffsetToCapsuleBody, - _h.CapsuleImageSize - _h.OffsetToCapsuleBody, - -1, -1, 0); + if (size >= 32 && IsIntelMe(buf0 + _h.OffsetToCapsuleBody)) + return ParseIntelMe(bufIndex, _h.OffsetToCapsuleBody, size, size, -1, -1, 0); + + return ParseVolume(bufIndex, _h.OffsetToCapsuleBody, size, size, -1, -1, 0); } + HRESULT CHandler::OpenFv(IInStream *stream, const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback * /* callback */) { Byte buf[kFvHeaderSize]; @@ -1380,6 +1631,7 @@ HRESULT CHandler::OpenFv(IInStream *stream, const UInt64 * /* maxCheckStartPosit return ParseVolume(bufIndex, 0, fvSize32, fvSize32, -1, -1, 0); } + HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback) { if (_capsuleMode) @@ -1432,8 +1684,8 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, int parent = item.Parent; if (parent >= 0) numItems = numChilds[(unsigned)parent]; - AString name2 = item.GetName(numItems); - AString characts2 = item.Characts; + AString name2 (item.GetName(numItems)); + AString characts2 (item.Characts); if (item.KeepName) name = name2; @@ -1444,7 +1696,7 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, break; if (item3.KeepName) { - AString name3 = item3.GetName(-1); + AString name3 (item3.GetName(-1)); if (name.IsEmpty()) name = name3; else @@ -1500,6 +1752,7 @@ STDMETHODIMP CHandler::Close() _items2.Clear(); _bufs.Clear(); _comment.Empty(); + _headersError = false; _h.Clear(); return S_OK; } @@ -1580,11 +1833,12 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) CBufInStream *streamSpec = new CBufInStream; CMyComPtr<IInStream> streamTemp = streamSpec; const CByteBuffer &buf = _bufs[item.BufIndex]; - /* - if (item.Offset + item.Size > buf.GetCapacity()) + if (item.Offset > buf.Size()) return S_FALSE; - */ - streamSpec->Init(buf + item.Offset, item.Size, (IInArchive *)this); + size_t size = buf.Size() - item.Offset; + if (size > item.Size) + size = item.Size; + streamSpec->Init(buf + item.Offset, size, (IInArchive *)this); *stream = streamTemp.Detach(); return S_OK; COM_TRY_END @@ -1593,11 +1847,19 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) namespace UEFIc { +static const Byte k_Capsule_Signatures[] = +{ + 16, CAPSULE_SIGNATURE, + 16, CAPSULE2_SIGNATURE, + 16, CAPSULE_UEFI_SIGNATURE +}; + REGISTER_ARC_I_CLS( CHandler(true), "UEFIc", "scap", 0, 0xD0, - kCapsuleSig, + k_Capsule_Signatures, 0, + NArcInfoFlags::kMultiSignature | NArcInfoFlags::kFindSignature, NULL) @@ -1605,11 +1867,19 @@ REGISTER_ARC_I_CLS( namespace UEFIf { +static const Byte k_FFS_Signatures[] = +{ + 16, FFS1_SIGNATURE, + 16, FFS2_SIGNATURE +}; + + REGISTER_ARC_I_CLS( CHandler(false), "UEFIf", "uefif", 0, 0xD1, - k_FFS_Guid, + k_FFS_Signatures, kFfsGuidOffset, + NArcInfoFlags::kMultiSignature | NArcInfoFlags::kFindSignature, NULL) diff --git a/CPP/7zip/Archive/VdiHandler.cpp b/CPP/7zip/Archive/VdiHandler.cpp index a8d3fe36..b8ef35bb 100644 --- a/CPP/7zip/Archive/VdiHandler.cpp +++ b/CPP/7zip/Archive/VdiHandler.cpp @@ -11,12 +11,14 @@ #include "../../Common/MyBuffer.h" #include "../../Windows/PropVariant.h" +#include "../../Windows/PropVariantUtils.h" #include "../Common/RegisterArc.h" #include "../Common/StreamUtils.h" #include "HandlerCont.h" +#define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) #define Get64(p) GetUi64(p) @@ -33,6 +35,7 @@ static const unsigned k_ClusterBits = 20; static const UInt32 k_ClusterSize = (UInt32)1 << k_ClusterBits; static const UInt32 k_UnusedCluster = 0xFFFFFFFF; + // static const UInt32 kDiskType_Dynamic = 1; // static const UInt32 kDiskType_Static = 2; @@ -41,8 +44,38 @@ static const char * const kDiskTypes[] = "0" , "Dynamic" , "Static" + , "Undo" + , "Diff" +}; + + +enum EGuidType +{ + k_GuidType_Creat, + k_GuidType_Modif, + k_GuidType_Link, + k_GuidType_PModif }; +static const unsigned kNumGuids = 4; +static const char * const kGuidNames[kNumGuids] = +{ + "Creat " + , "Modif " + , "Link " + , "PModif" +}; + +static bool IsEmptyGuid(const Byte *data) +{ + for (unsigned i = 0; i < 16; i++) + if (data[i] != 0) + return false; + return true; +} + + + class CHandler: public CHandlerImg { UInt32 _dataOffset; @@ -52,6 +85,8 @@ class CHandler: public CHandlerImg bool _isArc; bool _unsupported; + Byte Guids[kNumGuids][16]; + HRESULT Seek(UInt64 offset) { _posInArc = offset; @@ -137,7 +172,9 @@ static const Byte kProps[] = static const Byte kArcProps[] = { kpidHeadersSize, - kpidMethod + kpidMethod, + kpidComment, + kpidName }; IMP_IInArchive_Props @@ -156,16 +193,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidMethod: { - char s[16]; - const char *ptr; - if (_imageType < ARRAY_SIZE(kDiskTypes)) - ptr = kDiskTypes[_imageType]; - else - { - ConvertUInt32ToString(_imageType, s); - ptr = s; - } - prop = ptr; + TYPE_TO_PROP(kDiskTypes, _imageType, prop); break; } @@ -181,6 +209,42 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) prop = v; break; } + + case kpidComment: + { + AString s; + for (unsigned i = 0; i < kNumGuids; i++) + { + const Byte *guid = Guids[i]; + if (!IsEmptyGuid(guid)) + { + s.Add_LF(); + s += kGuidNames[i]; + s += " : "; + char temp[64]; + RawLeGuidToString_Braced(guid, temp); + MyStringLower_Ascii(temp); + s += temp; + } + } + if (!s.IsEmpty()) + prop = s; + break; + } + + case kpidName: + { + const Byte *guid = Guids[k_GuidType_Creat]; + if (!IsEmptyGuid(guid)) + { + char temp[64]; + RawLeGuidToString_Braced(guid, temp); + MyStringLower_Ascii(temp); + strcat(temp, ".vdi"); + prop = temp; + } + break; + } } prop.Detach(value); @@ -207,15 +271,6 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN } -static bool IsEmptyGuid(const Byte *data) -{ - for (unsigned i = 0; i < 16; i++) - if (data[i] != 0) - return false; - return true; -} - - HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback * /* openCallback */) { const unsigned kHeaderSize = 512; @@ -225,45 +280,65 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback * /* openCallbac if (memcmp(buf + 0x40, k_Signature, sizeof(k_Signature)) != 0) return S_FALSE; - UInt32 version = Get32(buf + 0x44); + const UInt32 version = Get32(buf + 0x44); if (version >= 0x20000) return S_FALSE; + if (version < 0x10000) + { + _unsupported = true; + return S_FALSE; + } - UInt32 headerSize = Get32(buf + 0x48); - if (headerSize < 0x140 || headerSize > 0x1B8) + const unsigned kHeaderOffset = 0x48; + const unsigned kGuidsOffsets = 0x188; + const UInt32 headerSize = Get32(buf + kHeaderOffset); + if (headerSize < kGuidsOffsets - kHeaderOffset || headerSize > 0x200 - kHeaderOffset) return S_FALSE; _imageType = Get32(buf + 0x4C); - _dataOffset = Get32(buf + 0x158); + // Int32 flags = Get32(buf + 0x50); + // Byte Comment[0x100] - UInt32 tableOffset = Get32(buf + 0x154); + const UInt32 tableOffset = Get32(buf + 0x154); if (tableOffset < 0x200) return S_FALSE; + + _dataOffset = Get32(buf + 0x158); + + // UInt32 geometry[3]; - UInt32 sectorSize = Get32(buf + 0x168); + const UInt32 sectorSize = Get32(buf + 0x168); if (sectorSize != 0x200) return S_FALSE; _size = Get64(buf + 0x170); + const UInt32 blockSize = Get32(buf + 0x178); + const UInt32 totalBlocks = Get32(buf + 0x180); + const UInt32 numAllocatedBlocks = Get32(buf + 0x184); + _isArc = true; - if (_imageType > 2) - { - _unsupported = true; - return S_FALSE; - } - if (_dataOffset < tableOffset) return S_FALSE; - UInt32 blockSize = Get32(buf + 0x178); - if (blockSize != ((UInt32)1 << k_ClusterBits)) + if (_imageType > 4) + _unsupported = true; + + if (blockSize != k_ClusterSize) { _unsupported = true; return S_FALSE; } - UInt32 totalBlocks = Get32(buf + 0x180); + if (headerSize >= kGuidsOffsets + kNumGuids * 16 - kHeaderOffset) + { + for (unsigned i = 0; i < kNumGuids; i++) + memcpy(Guids[i], buf + kGuidsOffsets + 16 * i, 16); + + if (!IsEmptyGuid(Guids[k_GuidType_Link]) || + !IsEmptyGuid(Guids[k_GuidType_PModif])) + _unsupported = true; + } { UInt64 size2 = (UInt64)totalBlocks << k_ClusterBits; @@ -278,18 +353,6 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback * /* openCallbac */ } - if (headerSize >= 0x180) - { - if (!IsEmptyGuid(buf + 0x1A8) || - !IsEmptyGuid(buf + 0x1B8)) - { - _unsupported = true; - return S_FALSE; - } - } - - UInt32 numAllocatedBlocks = Get32(buf + 0x184); - { UInt32 tableReserved = _dataOffset - tableOffset; if ((tableReserved >> 2) < totalBlocks) @@ -298,11 +361,11 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback * /* openCallbac _phySize = _dataOffset + ((UInt64)numAllocatedBlocks << k_ClusterBits); - size_t numBytes = (size_t)totalBlocks * 4; + const size_t numBytes = (size_t)totalBlocks * 4; if ((numBytes >> 2) != totalBlocks) { _unsupported = true; - return S_FALSE; + return E_OUTOFMEMORY; } _table.Alloc(numBytes); @@ -316,7 +379,10 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback * /* openCallbac if (v == k_UnusedCluster) continue; if (v >= numAllocatedBlocks) + { + _unsupported = true; return S_FALSE; + } } Stream = stream; @@ -332,6 +398,9 @@ STDMETHODIMP CHandler::Close() _isArc = false; _unsupported = false; + for (unsigned i = 0; i < kNumGuids; i++) + memset(Guids[i], 0, 16); + _imgExt = NULL; Stream.Release(); return S_OK; diff --git a/CPP/7zip/Archive/VhdHandler.cpp b/CPP/7zip/Archive/VhdHandler.cpp index 12cbfa04..d79ae907 100644 --- a/CPP/7zip/Archive/VhdHandler.cpp +++ b/CPP/7zip/Archive/VhdHandler.cpp @@ -5,7 +5,6 @@ #include "../../../C/CpuArch.h" #include "../../Common/ComTry.h" -#include "../../Common/IntToString.h" #include "../../Windows/PropVariant.h" @@ -69,17 +68,16 @@ struct CFooter UInt32 NumCyls() const { return DiskGeometry >> 16; } UInt32 NumHeads() const { return (DiskGeometry >> 8) & 0xFF; } UInt32 NumSectorsPerTrack() const { return DiskGeometry & 0xFF; } - AString GetTypeString() const; + void AddTypeString(AString &s) const; bool Parse(const Byte *p); }; -AString CFooter::GetTypeString() const +void CFooter::AddTypeString(AString &s) const { if (Type < ARRAY_SIZE(kDiskTypes)) - return kDiskTypes[Type]; - char s[16]; - ConvertUInt32ToString(Type, s); - return s; + s += kDiskTypes[Type]; + else + s.Add_UInt32(Type); } static bool CheckBlock(const Byte *p, unsigned size, unsigned checkSumOffset, unsigned zeroOffset) @@ -234,12 +232,15 @@ class CHandler: public CHandlerImg UString _errorMessage; // bool _unexpectedEnd; - void AddErrorMessage(const wchar_t *s) + void AddErrorMessage(const char *message, const wchar_t *name = NULL) { if (!_errorMessage.IsEmpty()) _errorMessage.Add_LF(); - _errorMessage += s; + _errorMessage += message; + if (name) + _errorMessage += name; } + void UpdatePhySize(UInt64 value) { if (_phySize < value) @@ -262,7 +263,7 @@ class CHandler: public CHandlerImg while (p && p->NeedParent()) { if (!res.IsEmpty()) - res.AddAscii(" -> "); + res += " -> "; UString mainName; UString anotherName; if (Dyn.RelativeNameWasUsed) @@ -279,9 +280,9 @@ class CHandler: public CHandlerImg if (mainName != anotherName && !anotherName.IsEmpty()) { res.Add_Space(); - res += L'('; + res += '('; res += anotherName; - res += L')'; + res += ')'; } p = p->Parent; } @@ -522,7 +523,7 @@ HRESULT CHandler::Open3() } _posInArcLimit = _phySize; _phySize += kHeaderSize; - AddErrorMessage(L"Can't find footer"); + AddErrorMessage("Can't find footer"); return S_OK; } @@ -679,7 +680,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidShortComment: case kpidMethod: { - AString s = Footer.GetTypeString(); + AString s; + Footer.AddTypeString(s); if (NeedParent()) { s += " -> "; @@ -689,7 +691,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) if (!p) s += '?'; else - s += p->Footer.GetTypeString(); + p->Footer.AddTypeString(s); } prop = s; break; @@ -698,14 +700,12 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { char s[16]; StringToAString(s, Footer.CreatorApp); - AString res = s; + AString res (s); res.Trim(); - ConvertUInt32ToString(Footer.CreatorVersion >> 16, s); res.Add_Space(); - res += s; + res.Add_UInt32(Footer.CreatorVersion >> 16); res += '.'; - ConvertUInt32ToString(Footer.CreatorVersion & 0xFFFF, s); - res += s; + res.Add_UInt32(Footer.CreatorVersion & 0xFFFF); prop = res; break; } @@ -806,10 +806,7 @@ HRESULT CHandler::Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback if (res == S_FALSE || !nextStream) { - UString s; - s.SetFromAscii("Missing volume : "); - s += name; - AddErrorMessage(s); + AddErrorMessage("Missing volume : ", name); return S_OK; } @@ -837,8 +834,7 @@ HRESULT CHandler::Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback p = p->Parent; if (!p) { - AddErrorMessage(L"Can't open parent VHD file:"); - AddErrorMessage(Dyn.ParentName); + AddErrorMessage("Can't open parent VHD file : ", Dyn.ParentName); break; } } diff --git a/CPP/7zip/Archive/VmdkHandler.cpp b/CPP/7zip/Archive/VmdkHandler.cpp index 5f93c738..942bd792 100644 --- a/CPP/7zip/Archive/VmdkHandler.cpp +++ b/CPP/7zip/Archive/VmdkHandler.cpp @@ -296,10 +296,15 @@ bool CDescriptor::Parse(const Byte *p, size_t size) AString name; AString val; - for (size_t i = 0;; i++) + for (;;) { - const char c = p[i]; - if (i == size || c == 0 || c == 0xA || c == 0xD) + char c = 0; + if (size != 0) + { + size--; + c = *p++; + } + if (c == 0 || c == 0xA || c == 0xD) { if (!s.IsEmpty() && s[0] != '#') { @@ -322,14 +327,12 @@ bool CDescriptor::Parse(const Byte *p, size_t size) } s.Empty(); - if (c == 0 || i >= size) - break; + if (c == 0) + return true; } else s += (char)c; } - - return true; } @@ -819,9 +822,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) else if (algo != (int)h.algo) { s.Add_Space_if_NotEmpty(); - char temp[16]; - ConvertUInt32ToString(h.algo, temp); - s += temp; + s.Add_UInt32(h.algo); algo = h.algo; } } @@ -831,16 +832,10 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) } if (zlib) - { - s.Add_Space_if_NotEmpty(); - s += "zlib"; - } + s.Add_OptSpaced("zlib"); if (marker) - { - s.Add_Space_if_NotEmpty(); - s += "Marker"; - } + s.Add_OptSpaced("Marker"); if (!s.IsEmpty()) prop = s; @@ -888,8 +883,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { if (_missingVol || !_missingVolName.IsEmpty()) { - UString s; - s.SetFromAscii("Missing volume : "); + UString s ("Missing volume : "); if (!_missingVolName.IsEmpty()) s += _missingVolName; prop = s; @@ -983,6 +977,9 @@ void CHandler::CloseAtError() } +static const char * const kSignature_Descriptor = "# Disk DescriptorFile"; + + HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) { const unsigned kSectoreSize = 512; @@ -997,7 +994,6 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) if (memcmp(buf, k_Signature, sizeof(k_Signature)) != 0) { - const char *kSignature_Descriptor = "# Disk DescriptorFile"; const size_t k_SigDesc_Size = strlen(kSignature_Descriptor); if (headerSize < k_SigDesc_Size) return S_FALSE; diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp index 234780dd..927a0b38 100644 --- a/CPP/7zip/Archive/Wim/WimHandler.cpp +++ b/CPP/7zip/Archive/Wim/WimHandler.cpp @@ -94,15 +94,6 @@ static void AddErrorMessage(AString &s, const char *message) s += message; } -static void ConvertByteToHex(unsigned value, char *s) -{ - for (int i = 0; i < 2; i++) - { - unsigned t = value & 0xF; - value >>= 4; - s[1 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); - } -} STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { @@ -177,17 +168,14 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) UInt32 ver2 = (_version >> 8) & 0xFF; UInt32 ver3 = (_version) & 0xFF; - char s[16]; - ConvertUInt32ToString(ver1, s); - AString res = s; + AString res; + res.Add_UInt32(ver1); res += '.'; - ConvertUInt32ToString(ver2, s); - res += s; + res.Add_UInt32(ver2); if (ver3 != 0) { res += '.'; - ConvertUInt32ToString(ver3, s); - res += s; + res.Add_UInt32(ver3); } prop = res; break; @@ -229,22 +217,16 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) const CHeader &h = _volumes[_firstVolumeIndex].Header; if (GetUi32(h.Guid) != 0) { - char temp[16 * 2 + 4]; - int i; - for (i = 0; i < 4; i++) - ConvertByteToHex(h.Guid[i], temp + i * 2); - temp[i * 2] = 0; - AString s = temp; + char temp[64]; + RawLeGuidToString(h.Guid, temp); + temp[8] = 0; // for reduced GUID + AString s (temp); const char *ext = ".wim"; if (h.NumParts != 1) { s += '_'; if (h.PartNumber != 1) - { - char sz[16]; - ConvertUInt32ToString(h.PartNumber, sz); - s += sz; - } + s.Add_UInt32(h.PartNumber); ext = ".swm"; } s += ext; @@ -262,9 +244,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) AString s; if (h.PartNumber != 1) { - char sz[16]; - ConvertUInt32ToString(h.PartNumber, sz); - s = sz; + s.Add_UInt32(h.PartNumber); s += '.'; } s += "swm"; @@ -312,19 +292,15 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) if (methodUnknown != 0) { - char temp[32]; - ConvertUInt32ToString(methodUnknown, temp); res.Add_Space_if_NotEmpty(); - res += temp; + res.Add_UInt32(methodUnknown); numMethods++; } if (numMethods == 1 && chunkSizeBits != 0) { - char temp[32]; - temp[0] = ':'; - ConvertUInt32ToString((UInt32)chunkSizeBits, temp + 1); - res += temp; + res += ':'; + res.Add_UInt32((UInt32)chunkSizeBits); } prop = res; @@ -391,7 +367,7 @@ static void MethodToProp(int method, int chunksSizeBits, NCOM::CPropVariant &pro if ((unsigned)method < ARRAY_SIZE(k_Methods)) strcpy(temp, k_Methods[(unsigned)method]); else - ConvertUInt32ToString((unsigned)method, temp); + ConvertUInt32ToString((UInt32)(unsigned)method, temp); if (chunksSizeBits >= 0) { @@ -436,9 +412,6 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val _db.GetItemPath(realIndex, _showImageNumber, prop); else { - char sz[16]; - ConvertUInt32ToString(item.StreamIndex, sz); - AString s = sz; /* while (s.Len() < _nameLenForStreams) s = '0' + s; @@ -448,7 +421,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val s = (AString)("[Free]" STRING_PATH_SEPARATOR) + sz; else */ - s = (AString)(FILES_DIR_NAME STRING_PATH_SEPARATOR) + sz; + AString s (FILES_DIR_NAME STRING_PATH_SEPARATOR); + s.Add_UInt32(item.StreamIndex); prop = s; } break; @@ -874,9 +848,10 @@ public: UString GetNextName(UInt32 index) const { - wchar_t s[16]; - ConvertUInt32ToString(index, s); - return _before + (UString)s + _after; + UString s = _before; + s.Add_UInt32(index); + s += _after; + return s; } }; @@ -970,11 +945,9 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCal if (_xmls.IsEmpty() || xml.Data != _xmls[0].Data) { - char sz[16]; - ConvertUInt32ToString(xml.VolIndex, sz); - xml.FileName = L'['; - xml.FileName.AddAscii(sz); - xml.FileName.AddAscii("].xml"); + xml.FileName = '['; + xml.FileName.Add_UInt32(xml.VolIndex); + xml.FileName += "].xml"; _xmls.Add(xml); } diff --git a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp index 1d198df0..99fd46ef 100644 --- a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp +++ b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp @@ -1828,7 +1828,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu curPos += kStreamInfoSize; } - AString xml = "<WIM>"; + AString xml ("<WIM>"); AddTagUInt64_ToString(xml, "TOTALBYTES", curPos); for (i = 0; i < trees.Size(); i++) { diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp index f35c2d50..b934478e 100644 --- a/CPP/7zip/Archive/Wim/WimIn.cpp +++ b/CPP/7zip/Archive/Wim/WimIn.cpp @@ -442,7 +442,7 @@ static inline void ParseStream(bool oldVersion, const Byte *p, CStreamInfo &s) } -static const char *kLongPath = "[LongPath]"; +#define kLongPath "[LongPath]" void CDatabase::GetShortName(unsigned index, NWindows::NCOM::CPropVariant &name) const { diff --git a/CPP/7zip/Archive/Wim/WimRegister.cpp b/CPP/7zip/Archive/Wim/WimRegister.cpp index 6ad28acc..ecebe8d9 100644 --- a/CPP/7zip/Archive/Wim/WimRegister.cpp +++ b/CPP/7zip/Archive/Wim/WimRegister.cpp @@ -10,7 +10,7 @@ namespace NArchive { namespace NWim { REGISTER_ARC_IO( - "wim", "wim swm esd", 0, 0xE6, + "wim", "wim swm esd ppkg", 0, 0xE6, kSignature, 0, NArcInfoFlags::kAltStreams | diff --git a/CPP/7zip/Archive/XarHandler.cpp b/CPP/7zip/Archive/XarHandler.cpp index 96386809..f20b1eb9 100644 --- a/CPP/7zip/Archive/XarHandler.cpp +++ b/CPP/7zip/Archive/XarHandler.cpp @@ -153,7 +153,7 @@ IMP_IInArchive_ArcProps static bool ParseUInt64(const CXmlItem &item, const char *name, UInt64 &res) { - const AString s = item.GetSubStringForTag(name); + const AString s (item.GetSubStringForTag(name)); if (s.IsEmpty()) return false; const char *end; @@ -163,7 +163,7 @@ static bool ParseUInt64(const CXmlItem &item, const char *name, UInt64 &res) static UInt64 ParseTime(const CXmlItem &item, const char *name) { - const AString s = item.GetSubStringForTag(name); + const AString s (item.GetSubStringForTag(name)); if (s.Len() < 20) return 0; const char *p = s; @@ -198,10 +198,10 @@ static bool ParseSha1(const CXmlItem &item, const char *name, Byte *digest) if (index < 0) return false; const CXmlItem &checkItem = item.SubItems[index]; - const AString style = checkItem.GetPropVal("style"); + const AString style (checkItem.GetPropVal("style")); if (style == "SHA1") { - const AString s = checkItem.GetSubString(); + const AString s (checkItem.GetSubString()); if (s.Len() != SHA1_DIGEST_SIZE * 2) return false; for (unsigned i = 0; i < s.Len(); i += 2) @@ -227,7 +227,7 @@ static bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int paren file.Parent = parent; parent = files.Size(); file.Name = item.GetSubStringForTag("name"); - AString type = item.GetSubStringForTag("type"); + const AString type (item.GetSubStringForTag("type")); if (type == "directory") file.IsDir = true; else if (type == "file") @@ -254,14 +254,14 @@ static bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int paren const CXmlItem &encodingItem = dataItem.SubItems[encodingIndex]; if (encodingItem.IsTag) { - AString s = encodingItem.GetPropVal("style"); + AString s (encodingItem.GetPropVal("style")); if (!s.IsEmpty()) { - const AString appl = "application/"; + const AString appl ("application/"); if (s.IsPrefixedBy(appl)) { s.DeleteFrontal(appl.Len()); - const AString xx = "x-"; + const AString xx ("x-"); if (s.IsPrefixedBy(xx)) { s.DeleteFrontal(xx.Len()); @@ -280,7 +280,7 @@ static bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int paren file.ATime = ParseTime(item, "atime"); { - const AString s = item.GetSubStringForTag("mode"); + const AString s (item.GetSubStringForTag("mode")); if (s[0] == '0') { const char *end; diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp index 318be190..fd90c88d 100644 --- a/CPP/7zip/Archive/XzHandler.cpp +++ b/CPP/7zip/Archive/XzHandler.cpp @@ -3,8 +3,6 @@ #include "StdAfx.h" #include "../../../C/Alloc.h" -#include "../../../C/XzCrc64.h" -#include "../../../C/XzEnc.h" #include "../../Common/ComTry.h" #include "../../Common/Defs.h" @@ -12,14 +10,14 @@ #include "../../Windows/PropVariant.h" -#include "../ICoder.h" - #include "../Common/CWrappers.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" #include "../Common/StreamUtils.h" #include "../Compress/CopyCoder.h" +#include "../Compress/XzDecoder.h" +#include "../Compress/XzEncoder.h" #include "IArchive.h" @@ -27,46 +25,13 @@ #include "Common/HandlerOut.h" #endif -#include "XzHandler.h" - using namespace NWindows; -namespace NCompress { -namespace NLzma2 { - -HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props); - -}} - namespace NArchive { namespace NXz { -struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit; - -static const char *k_LZMA2_Name = "LZMA2"; +#define k_LZMA2_Name "LZMA2" -void CStatInfo::Clear() -{ - InSize = 0; - OutSize = 0; - PhySize = 0; - - 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, @@ -78,7 +43,7 @@ class CHandler: #endif public CMyUnknownImp { - CStatInfo _stat; + NCompress::NXz::CStatInfo _stat; bool _isArc; bool _needSeekToStart; @@ -104,9 +69,12 @@ class CHandler: HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback); HRESULT Decode2(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, - CDecoder &decoder, ICompressProgressInfo *progress) + NCompress::NXz::CDecoder &decoder, ICompressProgressInfo *progress) { - RINOK(decoder.Decode(seqInStream, outStream, progress)); + RINOK(decoder.Decode(seqInStream, outStream, + NULL, // *outSizeLimit + true, // finishStream + progress)); _stat = decoder; _phySize_Defined = true; return S_OK; @@ -169,13 +137,6 @@ static inline void AddHexToString(AString &s, Byte value) s += GetHex(value & 0xF); } -static void AddUInt32ToString(AString &s, UInt32 value) -{ - char temp[16]; - ConvertUInt32ToString(value, temp); - s += temp; -} - static void Lzma2PropToString(AString &s, unsigned prop) { char c = 0; @@ -192,7 +153,7 @@ static void Lzma2PropToString(AString &s, unsigned prop) c = 'm'; } } - AddUInt32ToString(s, size); + s.Add_UInt32(size); if (c != 0) s += c; } @@ -232,7 +193,7 @@ static AString GetMethodString(const CXzFilter &f) p = temp; } - AString s = p; + AString s (p); if (f.propsSize > 0) { @@ -240,7 +201,7 @@ static AString GetMethodString(const CXzFilter &f) if (f.id == XZ_ID_LZMA2 && f.propsSize == 1) Lzma2PropToString(s, f.props[0]); else if (f.id == XZ_ID_Delta && f.propsSize == 1) - AddUInt32ToString(s, (UInt32)f.props[0] + 1); + s.Add_UInt32((UInt32)f.props[0] + 1); else { s += '['; @@ -294,7 +255,7 @@ static AString GetCheckString(const CXzs &xzs) else { s2 = "Check-"; - AddUInt32ToString(s2, (UInt32)i); + s2.Add_UInt32((UInt32)i); } AddString(s, s2); } @@ -354,27 +315,28 @@ STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value) struct COpenCallbackWrap { - ICompressProgress p; + ICompressProgress vt; IArchiveOpenCallback *OpenCallback; HRESULT Res; COpenCallbackWrap(IArchiveOpenCallback *progress); }; -static SRes OpenCallbackProgress(void *pp, UInt64 inSize, UInt64 /* outSize */) +static SRes OpenCallbackProgress(const ICompressProgress *pp, UInt64 inSize, UInt64 /* outSize */) { - COpenCallbackWrap *p = (COpenCallbackWrap *)pp; + COpenCallbackWrap *p = CONTAINER_FROM_VTBL(pp, COpenCallbackWrap, vt); if (p->OpenCallback) p->Res = p->OpenCallback->SetCompleted(NULL, &inSize); - return (SRes)p->Res; + return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS); } COpenCallbackWrap::COpenCallbackWrap(IArchiveOpenCallback *callback) { - p.Progress = OpenCallbackProgress; + vt.Progress = OpenCallbackProgress; OpenCallback = callback; Res = SZ_OK; } + struct CXzsCPP { CXzs p; @@ -382,6 +344,30 @@ struct CXzsCPP ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); } }; +#define kInputBufSize ((size_t)1 << 10) + +struct CLookToRead2_CPP: public CLookToRead2 +{ + CLookToRead2_CPP() + { + buf = NULL; + LookToRead2_CreateVTable(this, + True // Lookahead ? + ); + } + void Alloc(size_t allocSize) + { + buf = (Byte *)MyAlloc(allocSize); + if (buf) + this->bufSize = allocSize; + } + ~CLookToRead2_CPP() + { + MyFree(buf); + } +}; + + static HRESULT SRes_to_Open_HRESULT(SRes res) { switch (res) @@ -401,14 +387,18 @@ static HRESULT SRes_to_Open_HRESULT(SRes res) return S_FALSE; } + + HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback) { _needSeekToStart = true; { CXzStreamFlags st; - CSeqInStreamWrap inStreamWrap(inStream); - SRes res = Xz_ReadHeader(&st, &inStreamWrap.p); + CSeqInStreamWrap inStreamWrap; + + inStreamWrap.Init(inStream); + SRes res = Xz_ReadHeader(&st, &inStreamWrap.vt); if (res != SZ_OK) return SRes_to_Open_HRESULT(res); @@ -416,7 +406,7 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal CXzBlock block; Bool isIndex; UInt32 headerSizeRes; - SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.p, &isIndex, &headerSizeRes); + SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.vt, &isIndex, &headerSizeRes); if (res2 == SZ_OK && !isIndex) { unsigned numFilters = XzBlock_GetNumFilters(&block); @@ -432,18 +422,25 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal RINOK(callback->SetTotal(NULL, &_stat.PhySize)); } - CSeekInStreamWrap inStreamImp(inStream); + CSeekInStreamWrap inStreamImp;; + + inStreamImp.Init(inStream); + + CLookToRead2_CPP lookStream; + + lookStream.Alloc(kInputBufSize); + + if (!lookStream.buf) + return E_OUTOFMEMORY; - CLookToRead lookStream; - LookToRead_CreateVTable(&lookStream, True); - lookStream.realStream = &inStreamImp.p; - LookToRead_Init(&lookStream); + lookStream.realStream = &inStreamImp.vt; + LookToRead2_Init(&lookStream); COpenCallbackWrap openWrap(callback); CXzsCPP xzs; Int64 startPosition; - SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.s, &startPosition, &openWrap.p, &g_Alloc); + SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.vt, &startPosition, &openWrap.vt, &g_Alloc); if (res == SZ_ERROR_PROGRESS) return (openWrap.Res == S_OK) ? E_FAIL : openWrap.Res; /* @@ -511,6 +508,8 @@ STDMETHODIMP CHandler::Close() return S_OK; } + + class CSeekToSeqStream: public IInStream, public CMyUnknownImp @@ -530,169 +529,12 @@ STDMETHODIMP CSeekToSeqStream::Read(void *data, UInt32 size, UInt32 *processedSi STDMETHODIMP CSeekToSeqStream::Seek(Int64, UInt32, UInt64 *) { return E_NOTIMPL; } -CXzUnpackerCPP::CXzUnpackerCPP(): InBuf(0), OutBuf(0) -{ - XzUnpacker_Construct(&p, &g_Alloc); -} - -CXzUnpackerCPP::~CXzUnpackerCPP() -{ - XzUnpacker_Free(&p); - MyFree(InBuf); - MyFree(OutBuf); -} - -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; - - XzUnpacker_Init(&xzu.p); - 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; - - for (;;) - { - if (inPos == inSize) - { - inPos = inSize = 0; - RINOK(seqInStream->Read(xzu.InBuf, kInBufSize, &inSize)); - } - - SizeT inLen = inSize - inPos; - SizeT outLen = kOutBufSize - outPos; - ECoderStatus status; - - SRes res = XzUnpacker_Code(&xzu.p, - xzu.OutBuf + outPos, &outLen, - xzu.InBuf + inPos, &inLen, - (inSize == 0 ? CODER_FINISH_END : CODER_FINISH_ANY), &status); - inPos += inLen; - outPos += outLen; - InSize += inLen; - OutSize += outLen; - DecodeRes = res; - bool finished = ((inLen == 0 && outLen == 0) || res != SZ_OK); - if (outStream) - { - if (outPos == kOutBufSize || finished) - { - if (outPos != 0) - { - RINOK(WriteStream(outStream, xzu.OutBuf, outPos)); - outPos = 0; - } - } - } - else - outPos = 0; - - if (progress) - { - RINOK(progress->SetRatioInfo(&InSize, &OutSize)); - } - - if (finished) - { - PhySize = InSize; - NumStreams = xzu.p.numStartedStreams; - if (NumStreams > 0) - IsArc = true; - NumBlocks = xzu.p.numTotalBlocks; - UnpackSize_Defined = true; - NumStreams_Defined = true; - NumBlocks_Defined = true; - - UInt64 extraSize = XzUnpacker_GetExtraSize(&xzu.p); - - if (res == SZ_OK) - { - if (status == CODER_STATUS_NEEDS_MORE_INPUT) - { - extraSize = 0; - if (!XzUnpacker_IsStreamWasFinished(&xzu.p)) - { - // finished at padding bytes, but padding is not aligned for 4 - UnexpectedEnd = true; - res = SZ_ERROR_DATA; - } - } - else // status == CODER_STATUS_NOT_FINISHED - res = SZ_ERROR_DATA; - } - else if (res == SZ_ERROR_NO_ARCHIVE) - { - if (InSize == extraSize) - IsArc = false; - else - { - if (extraSize != 0 || inPos != inSize) - { - DataAfterEnd = true; - res = SZ_OK; - } - } - } - - DecodeRes = res; - PhySize -= extraSize; - - switch (res) - { - case SZ_OK: break; - case SZ_ERROR_NO_ARCHIVE: IsArc = false; break; - case SZ_ERROR_ARCHIVE: HeadersError = true; break; - case SZ_ERROR_UNSUPPORTED: Unsupported = true; break; - case SZ_ERROR_CRC: CrcError = true; break; - case SZ_ERROR_DATA: DataError = true; break; - default: DataError = true; break; - } - - break; - } - } - - 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) @@ -733,7 +575,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, else _needSeekToStart = true; - CDecoder decoder; + NCompress::NXz::CDecoder decoder; RINOK(Decode2(_seqStream, realOutStream, decoder, lpsRef)); Int32 opRes = decoder.Get_Extract_OperationResult(); @@ -755,11 +597,13 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt { COM_TRY_BEGIN - CSeqOutStreamWrap seqOutStream(outStream); if (numItems == 0) { - SRes res = Xz_EncodeEmpty(&seqOutStream.p); + CSeqOutStreamWrap seqOutStream; + + seqOutStream.Init(outStream); + SRes res = Xz_EncodeEmpty(&seqOutStream.vt); return SResToHRESULT(res); } @@ -795,34 +639,36 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt RINOK(updateCallback->SetTotal(size)); } - CLzma2EncProps lzma2Props; - Lzma2EncProps_Init(&lzma2Props); + NCompress::NXz::CEncoder *encoderSpec = new NCompress::NXz::CEncoder; + CMyComPtr<ICompressCoder> encoder = encoderSpec; + CLzma2EncProps &lzma2Props = encoderSpec->_lzma2Props; lzma2Props.lzmaProps.level = GetLevel(); CMyComPtr<ISequentialInStream> fileInStream; RINOK(updateCallback->GetStream(0, &fileInStream)); - CSeqInStreamWrap seqInStream(fileInStream); - { NCOM::CPropVariant prop = (UInt64)size; - RINOK(NCompress::NLzma2::SetLzma2Prop(NCoderPropID::kReduceSize, prop, lzma2Props)); + RINOK(encoderSpec->SetCoderProp(NCoderPropID::kReduceSize, prop)); } FOR_VECTOR (i, _methods) { COneMethodInfo &m = _methods[i]; - SetGlobalLevelAndThreads(m + + /* + SetGlobalLevelTo(m); #ifndef _7ZIP_ST - , _numThreads + CMultiMethodProps::SetMethodThreads(m, _numThreads); #endif - ); + */ + { FOR_VECTOR (j, m.Props) { const CProp &prop = m.Props[j]; - RINOK(NCompress::NLzma2::SetLzma2Prop(prop.Id, prop.Value, lzma2Props)); + RINOK(encoderSpec->SetCoderProp(prop.Id, prop.Value)); } } } @@ -835,11 +681,12 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); - CCompressProgressWrap progressWrap(progress); - CXzProps xzProps; - CXzFilterProps filter; + CXzProps &xzProps = encoderSpec->xzProps; + CXzFilterProps &filter = encoderSpec->filter; + XzProps_Init(&xzProps); XzFilterProps_Init(&filter); + xzProps.lzma2Props = &lzma2Props; xzProps.filterProps = (_filterId != 0 ? &filter : NULL); switch (_crcSize) @@ -869,10 +716,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (!deltaDefined) return E_INVALIDARG; } - SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &xzProps, &progressWrap.p); - if (res == SZ_OK) - return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); - return SResToHRESULT(res); + + return encoderSpec->Code(fileInStream, outStream, NULL, NULL, progress); } if (indexInArchive != 0) @@ -901,6 +746,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt COM_TRY_END } + STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) { COM_TRY_BEGIN diff --git a/CPP/7zip/Archive/XzHandler.h b/CPP/7zip/Archive/XzHandler.h index 4a59e356..24e8eeb4 100644 --- a/CPP/7zip/Archive/XzHandler.h +++ b/CPP/7zip/Archive/XzHandler.h @@ -3,63 +3,9 @@ #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/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp index 06fbe22f..dd83f87f 100644 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp @@ -17,6 +17,7 @@ #include "../../Compress/LzmaEncoder.h" #include "../../Compress/PpmdZip.h" +#include "../../Compress/XzEncoder.h" #include "../Common/InStreamWithCRC.h" @@ -26,8 +27,8 @@ namespace NArchive { namespace NZip { -static const CMethodId kMethodId_ZipBase = 0x040100; -static const CMethodId kMethodId_BZip2 = 0x040202; +using namespace NFileHeader; + static const UInt32 kLzmaPropsSize = 5; static const UInt32 kLzmaHeaderSize = 4 + kLzmaPropsSize; @@ -37,10 +38,11 @@ class CLzmaEncoder: public ICompressSetCoderProperties, public CMyUnknownImp { +public: NCompress::NLzma::CEncoder *EncoderSpec; CMyComPtr<ICompressCoder> Encoder; Byte Header[kLzmaHeaderSize]; -public: + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); @@ -81,7 +83,8 @@ CAddCommon::CAddCommon(const CCompressionMethodMode &options): _options(options), _copyCoderSpec(NULL), _cryptoStreamSpec(NULL), - _buf(NULL) + _buf(NULL), + _isLzmaEos(false) {} CAddCommon::~CAddCommon() @@ -114,49 +117,100 @@ HRESULT CAddCommon::CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultC } } + +HRESULT CAddCommon::Set_Pre_CompressionResult(bool seqMode, UInt64 unpackSize, CCompressingResult &opRes) const +{ + // We use Zip64, if unPackSize size is larger than 0xF8000000 to support + // cases when compressed size can be about 3% larger than uncompressed size + + const UInt32 kUnpackZip64Limit = 0xF8000000; + + opRes.UnpackSize = unpackSize; + opRes.PackSize = (UInt64)1 << 60; // we use big value to force Zip64 mode. + + if (unpackSize < kUnpackZip64Limit) + opRes.PackSize = (UInt32)0xFFFFFFFF - 1; // it will not use Zip64 for that size + + if (opRes.PackSize < unpackSize) + opRes.PackSize = unpackSize; + + Byte method = _options.MethodSequence[0]; + + if (method == NCompressionMethod::kStore && !_options.PasswordIsDefined) + opRes.PackSize = unpackSize; + + opRes.CRC = 0; + + opRes.LzmaEos = false; + + opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default; + opRes.FileTimeWasUsed = false; + + if (_options.PasswordIsDefined) + { + opRes.ExtractVersion = NCompressionMethod::kExtractVersion_ZipCrypto; + if (_options.IsAesMode) + opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Aes; + else + { + if (seqMode) + opRes.FileTimeWasUsed = true; + } + } + + opRes.Method = method; + Byte ver = 0; + + switch (method) + { + case NCompressionMethod::kStore: break; + case NCompressionMethod::kDeflate: ver = NCompressionMethod::kExtractVersion_Deflate; break; + case NCompressionMethod::kDeflate64: ver = NCompressionMethod::kExtractVersion_Deflate64; break; + case NCompressionMethod::kXz : ver = NCompressionMethod::kExtractVersion_Xz; break; + case NCompressionMethod::kPPMd : ver = NCompressionMethod::kExtractVersion_PPMd; break; + case NCompressionMethod::kBZip2: ver = NCompressionMethod::kExtractVersion_BZip2; break; + case NCompressionMethod::kLZMA : + { + ver = NCompressionMethod::kExtractVersion_LZMA; + const COneMethodInfo *oneMethodMain = &_options._methods[0]; + opRes.LzmaEos = oneMethodMain->Get_Lzma_Eos(); + break; + } + } + if (opRes.ExtractVersion < ver) + opRes.ExtractVersion = ver; + + return S_OK; +} + + HRESULT CAddCommon::Compress( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, IOutStream *outStream, - UInt32 /* fileTime */, + bool seqMode, UInt32 fileTime, ICompressProgressInfo *progress, CCompressingResult &opRes) { + opRes.LzmaEos = false; + if (!inStream) { // We can create empty stream here. But it was already implemented in caller code in 9.33+ return E_INVALIDARG; } - // CSequentialInStreamWithCRC *inSecCrcStreamSpec = NULL; - CInStreamWithCRC *inCrcStreamSpec = NULL; - CMyComPtr<ISequentialInStream> inCrcStream; - { - CMyComPtr<IInStream> inStream2; - + CSequentialInStreamWithCRC *inSecCrcStreamSpec = new CSequentialInStreamWithCRC; + CMyComPtr<ISequentialInStream> inCrcStream = inSecCrcStreamSpec; + + CMyComPtr<IInStream> inStream2; + if (!seqMode) inStream->QueryInterface(IID_IInStream, (void **)&inStream2); - if (inStream2) - { - inCrcStreamSpec = new CInStreamWithCRC; - inCrcStream = inCrcStreamSpec; - inCrcStreamSpec->SetStream(inStream2); - inCrcStreamSpec->Init(); - } - 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(); - */ - } - } + inSecCrcStreamSpec->SetStream(inStream); + inSecCrcStreamSpec->Init(); unsigned numTestMethods = _options.MethodSequence.Size(); - if (numTestMethods > 1 && !inCrcStreamSpec) + if (seqMode || (numTestMethods > 1 && !inStream2)) numTestMethods = 1; UInt32 crc = 0; @@ -164,20 +218,24 @@ HRESULT CAddCommon::Compress( Byte method = 0; CFilterCoder::C_OutStream_Releaser outStreamReleaser; - opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default; + opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default; opRes.FileTimeWasUsed = false; for (unsigned i = 0; i < numTestMethods; i++) { - opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default; - if (inCrcStreamSpec) - RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL)); + opRes.LzmaEos = false; + opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default; + if (inStream2 && i != 0) + { + inSecCrcStreamSpec->Init(); + RINOK(inStream2->Seek(0, STREAM_SEEK_SET, NULL)); + } RINOK(outStream->SetSize(0)); RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL)); if (_options.PasswordIsDefined) { - opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_ZipCrypto; + opRes.ExtractVersion = NCompressionMethod::kExtractVersion_ZipCrypto; if (!_cryptoStream) { @@ -187,7 +245,7 @@ HRESULT CAddCommon::Compress( if (_options.IsAesMode) { - opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Aes; + opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Aes; if (!_cryptoStreamSpec->Filter) { _cryptoStreamSpec->Filter = _filterAesSpec = new NCrypto::NWzAes::CEncoder; @@ -206,23 +264,22 @@ HRESULT CAddCommon::Compress( UInt32 check; - // if (inCrcStreamSpec) + if (inStream2) { if (!crc_IsCalculated) { RINOK(CalcStreamCRC(inStream, crc)); crc_IsCalculated = true; - RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(inStream2->Seek(0, STREAM_SEEK_SET, NULL)); + inSecCrcStreamSpec->Init(); } check = (crc >> 16); } - /* else { opRes.FileTimeWasUsed = true; check = (fileTime & 0xFFFF); } - */ RINOK(_filterSpec->WriteHeader_Check16(outStream, (UInt16)check)); } @@ -236,7 +293,7 @@ HRESULT CAddCommon::Compress( switch (method) { - case NFileHeader::NCompressionMethod::kStored: + case NCompressionMethod::kStore: { if (_copyCoderSpec == NULL) { @@ -256,15 +313,22 @@ HRESULT CAddCommon::Compress( { if (!_compressEncoder) { - if (method == NFileHeader::NCompressionMethod::kLZMA) + CLzmaEncoder *_lzmaEncoder = NULL; + if (method == NCompressionMethod::kLZMA) { - _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_LZMA; - CLzmaEncoder *_lzmaEncoder = new CLzmaEncoder(); + _compressExtractVersion = NCompressionMethod::kExtractVersion_LZMA; + _lzmaEncoder = new CLzmaEncoder(); _compressEncoder = _lzmaEncoder; } - else if (method == NFileHeader::NCompressionMethod::kPPMd) + else if (method == NCompressionMethod::kXz) + { + _compressExtractVersion = NCompressionMethod::kExtractVersion_Xz; + NCompress::NXz::CEncoder *encoder = new NCompress::NXz::CEncoder(); + _compressEncoder = encoder; + } + else if (method == NCompressionMethod::kPPMd) { - _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_PPMd; + _compressExtractVersion = NCompressionMethod::kExtractVersion_PPMd; NCompress::NPpmdZip::CEncoder *encoder = new NCompress::NPpmdZip::CEncoder(); _compressEncoder = encoder; } @@ -273,14 +337,14 @@ HRESULT CAddCommon::Compress( CMethodId methodId; switch (method) { - case NFileHeader::NCompressionMethod::kBZip2: + case NCompressionMethod::kBZip2: methodId = kMethodId_BZip2; - _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_BZip2; + _compressExtractVersion = NCompressionMethod::kExtractVersion_BZip2; break; default: - _compressExtractVersion = ((method == NFileHeader::NCompressionMethod::kDeflated64) ? - NFileHeader::NCompressionMethod::kExtractVersion_Deflate64 : - NFileHeader::NCompressionMethod::kExtractVersion_Deflate); + _compressExtractVersion = ((method == NCompressionMethod::kDeflate64) ? + NCompressionMethod::kExtractVersion_Deflate64 : + NCompressionMethod::kExtractVersion_Deflate); methodId = kMethodId_ZipBase + method; break; } @@ -290,11 +354,11 @@ HRESULT CAddCommon::Compress( if (!_compressEncoder) return E_NOTIMPL; - if (method == NFileHeader::NCompressionMethod::kDeflated || - method == NFileHeader::NCompressionMethod::kDeflated64) + if (method == NCompressionMethod::kDeflate || + method == NCompressionMethod::kDeflate64) { } - else if (method == NFileHeader::NCompressionMethod::kBZip2) + else if (method == NCompressionMethod::kBZip2) { } } @@ -303,11 +367,22 @@ HRESULT CAddCommon::Compress( _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProps); if (setCoderProps) { - RINOK(_options.MethodInfo.SetCoderProps(setCoderProps, - _options._dataSizeReduceDefined ? &_options._dataSizeReduce : NULL)); + if (!_options._methods.IsEmpty()) + { + COneMethodInfo *oneMethodMain = &_options._methods[0]; + + RINOK(oneMethodMain->SetCoderProps(setCoderProps, + _options._dataSizeReduceDefined ? &_options._dataSizeReduce : NULL)); + } } } + if (method == NCompressionMethod::kLZMA) + _isLzmaEos = _lzmaEncoder->EncoderSpec->IsWriteEndMark(); } + + if (method == NCompressionMethod::kLZMA) + opRes.LzmaEos = _isLzmaEos; + CMyComPtr<ISequentialOutStream> outStreamNew; if (_options.PasswordIsDefined) outStreamNew = _cryptoStream; @@ -332,18 +407,10 @@ HRESULT CAddCommon::Compress( RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize)); - // if (inCrcStreamSpec) - { - opRes.CRC = inCrcStreamSpec->GetCRC(); - opRes.UnpackSize = inCrcStreamSpec->GetSize(); - } - /* - else { opRes.CRC = inSecCrcStreamSpec->GetCRC(); opRes.UnpackSize = inSecCrcStreamSpec->GetSize(); } - */ if (_options.PasswordIsDefined) { diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.h b/CPP/7zip/Archive/Zip/ZipAddCommon.h index 1e0c3bfa..ea5f8180 100644 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.h +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.h @@ -27,6 +27,7 @@ struct CCompressingResult UInt16 Method; Byte ExtractVersion; bool FileTimeWasUsed; + bool LzmaEos; }; class CAddCommon @@ -37,6 +38,7 @@ class CAddCommon CMyComPtr<ICompressCoder> _compressEncoder; Byte _compressExtractVersion; + bool _isLzmaEos; CFilterCoder *_cryptoStreamSpec; CMyComPtr<ISequentialOutStream> _cryptoStream; @@ -50,11 +52,14 @@ class CAddCommon public: CAddCommon(const CCompressionMethodMode &options); ~CAddCommon(); + + HRESULT Set_Pre_CompressionResult(bool seqMode, UInt64 unpackSize, CCompressingResult &opRes) const; + HRESULT Compress( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, IOutStream *outStream, - UInt32 fileTime, - ICompressProgressInfo *progress, CCompressingResult &operationResult); + bool seqMode, UInt32 fileTime, + ICompressProgressInfo *progress, CCompressingResult &opRes); }; }} diff --git a/CPP/7zip/Archive/Zip/ZipCompressionMode.h b/CPP/7zip/Archive/Zip/ZipCompressionMode.h index 86548d95..1125f6ed 100644 --- a/CPP/7zip/Archive/Zip/ZipCompressionMode.h +++ b/CPP/7zip/Archive/Zip/ZipCompressionMode.h @@ -14,26 +14,18 @@ namespace NArchive { namespace NZip { -struct CBaseProps -{ - CMethodProps MethodInfo; - Int32 Level; +const CMethodId kMethodId_ZipBase = 0x040100; +const CMethodId kMethodId_BZip2 = 0x040202; - #ifndef _7ZIP_ST - UInt32 NumThreads; - bool NumThreadsWasChanged; - #endif +struct CBaseProps: public CMultiMethodProps +{ bool IsAesMode; Byte AesKeyMode; void Init() { - MethodInfo.Clear(); - Level = -1; - #ifndef _7ZIP_ST - NumThreads = NWindows::NSystem::GetNumberOfProcessors();; - NumThreadsWasChanged = false; - #endif + CMultiMethodProps::Init(); + IsAesMode = false; AesKeyMode = 3; } diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp index 75034de0..75fad760 100644 --- a/CPP/7zip/Archive/Zip/ZipHandler.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp @@ -3,10 +3,10 @@ #include "StdAfx.h" #include "../../../Common/ComTry.h" -#include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantUtils.h" #include "../../../Windows/TimeUtils.h" #include "../../IPassword.h" @@ -22,6 +22,7 @@ #include "../../Compress/ImplodeDecoder.h" #include "../../Compress/PpmdZip.h" #include "../../Compress/ShrinkDecoder.h" +#include "../../Compress/XzDecoder.h" #include "../../Crypto/WzAes.h" #include "../../Crypto/ZipCrypto.h" @@ -30,7 +31,6 @@ #include "../Common/ItemNameUtils.h" #include "../Common/OutStreamWithCRC.h" -#include "../XzHandler.h" #include "ZipHandler.h" @@ -39,9 +39,6 @@ using namespace NWindows; namespace NArchive { namespace NZip { -static const CMethodId kMethodId_ZipBase = 0x040100; -static const CMethodId kMethodId_BZip2 = 0x040202; - static const char * const kHostOS[] = { "FAT" @@ -66,24 +63,57 @@ static const char * const kHostOS[] = , "OS/X" }; -static const char * const kMethods[] = + +const char * const kMethodNames1[kNumMethodNames1] = { "Store" , "Shrink" - , "Reduced1" - , "Reduced2" - , "Reduced3" - , "Reduced4" + , "Reduce1" + , "Reduce2" + , "Reduce3" + , "Reduce4" , "Implode" - , "Tokenizing" + , NULL // "Tokenize" , "Deflate" , "Deflate64" , "PKImploding" + , NULL + , "BZip2" + , NULL + , "LZMA" +}; + + +const char * const kMethodNames2[kNumMethodNames2] = +{ + "xz" + , "Jpeg" + , "WavPack" + , "PPMd" + , "WzAES" }; -static const char *kMethod_AES = "AES"; -static const char *kMethod_ZipCrypto = "ZipCrypto"; -static const char *kMethod_StrongCrypto = "StrongCrypto"; +#define kMethod_AES "AES" +#define kMethod_ZipCrypto "ZipCrypto" +#define kMethod_StrongCrypto "StrongCrypto" + +static const char * const kDeflateLevels[4] = +{ + "Normal" + , "Maximum" + , "Fast" + , "Fastest" +}; + + +static const CUInt32PCharPair g_HeaderCharacts[] = +{ + { 0, "Encrypt" }, + { 3, "Descriptor" }, + // { 5, "Patched" }, + { 6, kMethod_StrongCrypto }, + { 11, "UTF8" } +}; struct CIdToNamePair { @@ -91,15 +121,6 @@ struct CIdToNamePair const char *Name; }; -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" } -}; static const CIdToNamePair k_StrongCryptoPairs[] = { @@ -116,7 +137,7 @@ static const CIdToNamePair k_StrongCryptoPairs[] = { NStrongCrypto_AlgId::kRC4, "RC4" } }; -const char *FindNameForId(const CIdToNamePair *pairs, unsigned num, unsigned id) +static const char *FindNameForId(const CIdToNamePair *pairs, unsigned num, unsigned id) { for (unsigned i = 0; i < num; i++) { @@ -127,6 +148,7 @@ const char *FindNameForId(const CIdToNamePair *pairs, unsigned num, unsigned id) return NULL; } + static const Byte kProps[] = { kpidPath, @@ -142,9 +164,11 @@ static const Byte kProps[] = kpidComment, kpidCRC, kpidMethod, + kpidCharacts, kpidHostOS, kpidUnpackVer, - kpidVolumeIndex + kpidVolumeIndex, + kpidOffset }; static const Byte kArcProps[] = @@ -152,6 +176,7 @@ static const Byte kArcProps[] = kpidEmbeddedStubSize, kpidBit64, kpidComment, + kpidCharacts, kpidTotalPhySize, kpidIsVolume, kpidVolumeIndex, @@ -193,11 +218,34 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) break; } - case kpidTotalPhySize: if (m_Archive.IsMultiVol) prop = m_Archive.Vols.GetTotalSize(); break; + case kpidTotalPhySize: if (m_Archive.IsMultiVol) prop = m_Archive.Vols.TotalBytesSize; break; case kpidVolumeIndex: if (m_Archive.IsMultiVol) prop = (UInt32)m_Archive.Vols.StartVolIndex; break; case kpidIsVolume: if (m_Archive.IsMultiVol) prop = true; break; case kpidNumVolumes: if (m_Archive.IsMultiVol) prop = (UInt32)m_Archive.Vols.Streams.Size(); break; + case kpidCharacts: + { + AString s; + + if (m_Archive.LocalsWereRead) + { + s.Add_OptSpaced("Local"); + + if (m_Archive.LocalsCenterMerged) + s.Add_OptSpaced("Central"); + } + + if (m_Archive.IsZip64) + s.Add_OptSpaced("Zip64"); + + if (m_Archive.ExtraMinorError) + s.Add_OptSpaced("Minor_Extra_ERROR"); + + if (!s.IsEmpty()) + prop = s; + break; + } + case kpidWarningFlags: { UInt32 v = 0; @@ -208,12 +256,23 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) break; } + case kpidWarning: + { + AString s; + if (m_Archive.Overflow32bit) + s.Add_OptSpaced("32-bit overflow in headers"); + if (m_Archive.Cd_NumEntries_Overflow_16bit) + s.Add_OptSpaced("16-bit overflow for number of files in headers"); + if (!s.IsEmpty()) + prop = s; + break; + } + case kpidError: { if (!m_Archive.Vols.MissingName.IsEmpty()) { - UString s; - s.SetFromAscii("Missing volume : "); + UString s("Missing volume : "); s += m_Archive.Vols.MissingName; prop = s; } @@ -273,13 +332,19 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { UString res; item.GetUnicodeString(res, item.Name, false, _forceCodePage, _specifiedCodePage); - NItemName::ConvertToOSName2(res); + NItemName::ReplaceToOsSlashes_Remove_TailSlash(res); prop = res; break; } case kpidIsDir: prop = item.IsDir(); break; - case kpidSize: prop = item.Size; break; + case kpidSize: + { + if (item.FromCentral || !item.FromLocal || !item.HasDescriptor() || item.DescriptorWasRead) + prop = item.Size; + break; + } + case kpidPackSize: prop = item.PackSize; break; case kpidTimeType: @@ -299,17 +364,36 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidCTime: { - FILETIME ft; - if (extra.GetNtfsTime(NFileHeader::NNtfsExtra::kCTime, ft)) - prop = ft; + FILETIME utc; + bool defined = true; + if (!extra.GetNtfsTime(NFileHeader::NNtfsExtra::kCTime, utc)) + { + UInt32 unixTime = 0; + if (extra.GetUnixTime(true, NFileHeader::NUnixTime::kCTime, unixTime)) + NTime::UnixTimeToFileTime(unixTime, utc); + else + defined = false; + } + if (defined) + prop = utc; break; } case kpidATime: { - FILETIME ft; - if (extra.GetNtfsTime(NFileHeader::NNtfsExtra::kATime, ft)) - prop = ft; + FILETIME utc; + bool defined = true; + if (!extra.GetNtfsTime(NFileHeader::NNtfsExtra::kATime, utc)) + { + UInt32 unixTime = 0; + if (extra.GetUnixTime(true, NFileHeader::NUnixTime::kATime, unixTime)) + NTime::UnixTimeToFileTime(unixTime, utc); + else + defined = false; + } + if (defined) + prop = utc; + break; } @@ -375,10 +459,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val CWzAesExtra aesField; if (extra.GetWzAes(aesField)) { - char s[16]; - s[0] = '-'; - ConvertUInt32ToString(((unsigned)aesField.Strength + 1) * 64 , s + 1); - m += s; + m += '-'; + m.Add_UInt32(((unsigned)aesField.Strength + 1) * 64); id = aesField.Method; } } @@ -394,10 +476,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val else { m += kMethod_StrongCrypto; - char temp[16]; - temp[0] = ':'; - ConvertUInt32ToString(f.AlgId, temp + 1); - m += temp; + m += ':'; + m.Add_UInt32(f.AlgId); } if (f.CertificateIsUsed()) m += "-Cert"; @@ -411,41 +491,96 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } { - char temp[16]; const char *s = NULL; - if (id < ARRAY_SIZE(kMethods)) - s = kMethods[id]; + if (id < kNumMethodNames1) + s = kMethodNames1[id]; else { - s = FindNameForId(k_MethodIdNamePairs, ARRAY_SIZE(k_MethodIdNamePairs), id); - if (!s) + int id2 = (int)id - (int)kMethodNames2Start; + if (id2 >= 0 && id2 < kNumMethodNames2) + s = kMethodNames2[id2]; + } + if (s) + m += s; + else + m.Add_UInt32(id); + } + { + unsigned level = item.GetDeflateLevel(); + if (level != 0) + { + if (id == NFileHeader::NCompressionMethod::kLZMA) + { + if (level & 1) + m += ":eos"; + level &= ~1; + } + else if (id == NFileHeader::NCompressionMethod::kDeflate) { - ConvertUInt32ToString(id, temp); - s = temp; + m += ':'; + m += kDeflateLevels[level]; + level = 0; + } + + if (level != 0) + { + m += ":v"; + m.Add_UInt32(level); } } - m += s; - if (id == NFileHeader::NCompressionMethod::kLZMA && item.IsLzmaEOS()) - m += ":EOS"; } prop = m; break; } - case kpidHostOS: + case kpidCharacts: { - Byte hostOS = item.GetHostOS(); - char temp[16]; - const char *s = NULL; - if (hostOS < ARRAY_SIZE(kHostOS)) - s = kHostOS[hostOS]; - else + AString s; + + if (item.FromLocal) + { + s.Add_OptSpaced("Local"); + + item.LocalExtra.PrintInfo(s); + + if (item.FromCentral) + { + s.Add_OptSpaced(":"); + s.Add_OptSpaced("Central"); + } + } + + if (item.FromCentral) { - ConvertUInt32ToString(hostOS, temp); - s = temp; + item.CentralExtra.PrintInfo(s); } - prop = s; + + UInt32 flags = item.Flags; + flags &= ~(6); // we don't need compression related bits here. + + if (flags != 0) + { + AString s2 = FlagsToString(g_HeaderCharacts, ARRAY_SIZE(g_HeaderCharacts), flags); + if (!s2.IsEmpty()) + { + s.Add_OptSpaced(":"); + s.Add_OptSpaced(s2); + } + } + + if (!item.FromCentral && item.FromLocal && item.HasDescriptor() && !item.DescriptorWasRead) + s.Add_OptSpaced("Descriptor_ERROR"); + + if (!s.IsEmpty()) + prop = s; + break; + } + + case kpidHostOS: + { + const Byte hostOS = item.GetHostOS(); + TYPE_TO_PROP(kHostOS, hostOS, prop); break; } @@ -456,6 +591,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidVolumeIndex: prop = item.Disk; break; + + case kpidOffset: + prop = item.LocalHeaderPos; + break; } prop.Detach(value); @@ -475,7 +614,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, if (res != S_OK) { m_Items.Clear(); - m_Archive.ClearRefs(); + m_Archive.ClearRefs(); // we don't want to clear error flags } return res; } @@ -493,16 +632,24 @@ STDMETHODIMP CHandler::Close() class CLzmaDecoder: public ICompressCoder, + public ICompressSetFinishMode, + public ICompressGetInStreamProcessedSize, public CMyUnknownImp { +public: NCompress::NLzma::CDecoder *DecoderSpec; CMyComPtr<ICompressCoder> Decoder; -public: - CLzmaDecoder(); + + MY_UNKNOWN_IMP2( + ICompressSetFinishMode, + ICompressGetInStreamProcessedSize) + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetFinishMode)(UInt32 finishMode); + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); - MY_UNKNOWN_IMP + CLzmaDecoder(); }; CLzmaDecoder::CLzmaDecoder() @@ -511,44 +658,45 @@ CLzmaDecoder::CLzmaDecoder() Decoder = DecoderSpec; } +static const unsigned kZipLzmaPropsSize = 4 + LZMA_PROPS_SIZE; + HRESULT CLzmaDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { - Byte buf[9]; - RINOK(ReadStream_FALSE(inStream, buf, 9)); - if (buf[2] != 5 || buf[3] != 0) + Byte buf[kZipLzmaPropsSize]; + RINOK(ReadStream_FALSE(inStream, buf, kZipLzmaPropsSize)); + if (buf[2] != LZMA_PROPS_SIZE || buf[3] != 0) return E_NOTIMPL; - RINOK(DecoderSpec->SetDecoderProperties2(buf + 4, 5)); - return Decoder->Code(inStream, outStream, NULL, outSize, progress); + RINOK(DecoderSpec->SetDecoderProperties2(buf + 4, LZMA_PROPS_SIZE)); + UInt64 inSize2 = 0; + if (inSize) + { + inSize2 = *inSize; + if (inSize2 < kZipLzmaPropsSize) + return S_FALSE; + inSize2 -= kZipLzmaPropsSize; + } + return Decoder->Code(inStream, outStream, inSize ? &inSize2 : NULL, outSize, progress); } - -class CXzDecoder: - public ICompressCoder, - public CMyUnknownImp +STDMETHODIMP CLzmaDecoder::SetFinishMode(UInt32 finishMode) { - NArchive::NXz::CDecoder _decoder; -public: - - STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); - - MY_UNKNOWN_IMP -}; + DecoderSpec->FinishStream = (finishMode != 0); + return S_OK; +} -HRESULT CXzDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) +STDMETHODIMP CLzmaDecoder::GetInStreamProcessedSize(UInt64 *value) { - 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; + *value = DecoderSpec->GetInputProcessedSize() + kZipLzmaPropsSize; return S_OK; } + + + + + struct CMethodItem { unsigned ZipMethod; @@ -572,12 +720,15 @@ class CZipDecoder CMyComPtr<ICryptoGetTextPassword> getTextPassword; CObjectVector<CMethodItem> methodItems; + CLzmaDecoder *lzmaDecoderSpec; public: CZipDecoder(): _zipCryptoDecoderSpec(0), _pkAesDecoderSpec(0), _wzAesDecoderSpec(0), - filterStreamSpec(0) {} + filterStreamSpec(0), + lzmaDecoderSpec(0) + {} HRESULT Decode( DECL_EXTERNAL_CODECS_LOC_VARS @@ -592,19 +743,18 @@ public: }; -static HRESULT SkipStreamData(ISequentialInStream *stream, UInt64 size) +static HRESULT SkipStreamData(ISequentialInStream *stream, bool &thereAreData) { + thereAreData = false; const size_t kBufSize = 1 << 12; Byte buf[kBufSize]; for (;;) { + size_t size = kBufSize; + RINOK(ReadStream(stream, buf, &size)); if (size == 0) return S_OK; - size_t curSize = kBufSize; - if (curSize > size) - curSize = (size_t)size; - RINOK(ReadStream_FALSE(stream, buf, curSize)); - size -= curSize; + thereAreData = true; } } @@ -620,12 +770,15 @@ HRESULT CZipDecoder::Decode( #endif Int32 &res) { - res = NExtract::NOperationResult::kDataError; + res = NExtract::NOperationResult::kHeadersError; + CFilterCoder::C_InStream_Releaser inStreamReleaser; + CFilterCoder::C_Filter_Releaser filterReleaser; bool needCRC = true; bool wzAesMode = false; bool pkAesMode = false; + unsigned id = item.Method; if (item.IsEncrypted()) @@ -633,27 +786,23 @@ HRESULT CZipDecoder::Decode( if (item.IsStrongEncrypted()) { CStrongCryptoExtra f; - if (item.CentralExtra.GetStrongCrypto(f)) - { - pkAesMode = true; - } - if (!pkAesMode) + if (!item.CentralExtra.GetStrongCrypto(f)) { res = NExtract::NOperationResult::kUnsupportedMethod; return S_OK; } + pkAesMode = true; } - if (!pkAesMode && id == NFileHeader::NCompressionMethod::kWzAES) + else if (id == NFileHeader::NCompressionMethod::kWzAES) { CWzAesExtra aesField; - if (item.GetMainExtra().GetWzAes(aesField)) - { - wzAesMode = true; - needCRC = aesField.NeedCrc(); - } + if (!item.GetMainExtra().GetWzAes(aesField)) + return S_OK; + wzAesMode = true; + needCRC = aesField.NeedCrc(); } } - + COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; outStreamSpec->SetStream(realOutStream); @@ -681,6 +830,9 @@ HRESULT CZipDecoder::Decode( limitedStreamSpec->SetStream(packStream); limitedStreamSpec->Init(packSize); } + + + res = NExtract::NOperationResult::kDataError; CMyComPtr<ICompressFilter> cryptoFilter; @@ -725,6 +877,8 @@ HRESULT CZipDecoder::Decode( CMyComPtr<ICryptoSetPassword> cryptoSetPassword; RINOK(cryptoFilter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword)); + if (!cryptoSetPassword) + return E_FAIL; if (!getTextPassword) extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword); @@ -736,39 +890,35 @@ HRESULT CZipDecoder::Decode( AString charPassword; if (password) { + UnicodeStringToMultiByte2(charPassword, (const wchar_t *)password, CP_ACP); + /* if (wzAesMode || pkAesMode) { - charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_ACP); - /* - for (unsigned i = 0;; i++) - { - wchar_t c = password[i]; - if (c == 0) - break; - if (c >= 0x80) - { - res = NExtract::NOperationResult::kDataError; - return S_OK; - } - charPassword += (char)c; - } - */ } else { - /* pkzip25 / WinZip / Windows probably use ANSI for some files - We use OEM for compatibility with previous versions of 7-Zip? */ - charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP); + // PASSWORD encoding for ZipCrypto: + // pkzip25 / WinZip / Windows probably use ANSI + // 7-Zip < 4.43 creates ZIP archives with OEM encoding in password + // 7-Zip >= 4.43 creates ZIP archives only with ASCII characters in password + // 7-Zip < 17.00 uses CP_OEMCP for password decoding + // 7-Zip >= 17.00 uses CP_ACP for password decoding } + */ } HRESULT result = cryptoSetPassword->CryptoSetPassword( (const Byte *)(const char *)charPassword, charPassword.Len()); if (result != S_OK) + { + res = NExtract::NOperationResult::kWrongPassword; return S_OK; + } } else { - RINOK(cryptoSetPassword->CryptoSetPassword(0, 0)); + res = NExtract::NOperationResult::kWrongPassword; + return S_OK; + // RINOK(cryptoSetPassword->CryptoSetPassword(NULL, 0)); } } @@ -781,16 +931,19 @@ HRESULT CZipDecoder::Decode( { CMethodItem mi; mi.ZipMethod = id; - if (id == NFileHeader::NCompressionMethod::kStored) + if (id == NFileHeader::NCompressionMethod::kStore) mi.Coder = new NCompress::CCopyCoder; - else if (id == NFileHeader::NCompressionMethod::kShrunk) + else if (id == NFileHeader::NCompressionMethod::kShrink) mi.Coder = new NCompress::NShrink::CDecoder; - else if (id == NFileHeader::NCompressionMethod::kImploded) + else if (id == NFileHeader::NCompressionMethod::kImplode) mi.Coder = new NCompress::NImplode::NDecoder::CCoder; else if (id == NFileHeader::NCompressionMethod::kLZMA) - mi.Coder = new CLzmaDecoder; + { + lzmaDecoderSpec = new CLzmaDecoder; + mi.Coder = lzmaDecoderSpec; + } else if (id == NFileHeader::NCompressionMethod::kXz) - mi.Coder = new CXzDecoder; + mi.Coder = new NCompress::NXz::CComDecoder; else if (id == NFileHeader::NCompressionMethod::kPPMd) mi.Coder = new NCompress::NPpmdZip::CDecoder(true); else @@ -810,7 +963,7 @@ HRESULT CZipDecoder::Decode( RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS szMethodID, false, mi.Coder)); - if (mi.Coder == 0) + if (!mi.Coder) { res = NExtract::NOperationResult::kUnsupportedMethod; return S_OK; @@ -842,9 +995,17 @@ HRESULT CZipDecoder::Decode( } #endif + CMyComPtr<ISequentialInStream> inStreamNew; + + bool isFullStreamExpected = (!item.HasDescriptor() || item.PackSize != 0); + bool needReminderCheck = false; + + bool dataAfterEnd = false; + bool truncatedError = false; + bool lzmaEosError = false; + { HRESULT result = S_OK; - CMyComPtr<ISequentialInStream> inStreamNew; if (item.IsEncrypted()) { if (!filterStream) @@ -853,6 +1014,7 @@ HRESULT CZipDecoder::Decode( filterStream = filterStreamSpec; } + filterReleaser.FilterCoder = filterStreamSpec; filterStreamSpec->Filter = cryptoFilter; if (wzAesMode) @@ -869,6 +1031,7 @@ HRESULT CZipDecoder::Decode( } else if (pkAesMode) { + isFullStreamExpected = false; result =_pkAesDecoderSpec->ReadHeader(inStream, item.Crc, item.Size); if (result == S_OK) { @@ -926,7 +1089,70 @@ HRESULT CZipDecoder::Decode( inStreamNew = inStream; if (result == S_OK) - result = coder->Code(inStreamNew, outStream, NULL, &item.Size, compressProgress); + { + CMyComPtr<ICompressSetFinishMode> setFinishMode; + coder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode); + if (setFinishMode) + { + RINOK(setFinishMode->SetFinishMode(BoolToInt(true))); + } + + const UInt64 coderPackSize = limitedStreamSpec->GetRem(); + + bool useUnpackLimit = (id == 0 + || !item.HasDescriptor() + || item.Size >= ((UInt64)1 << 32) + || item.LocalExtra.IsZip64 + || item.CentralExtra.IsZip64 + ); + + result = coder->Code(inStreamNew, outStream, + isFullStreamExpected ? &coderPackSize : NULL, + // NULL, + useUnpackLimit ? &item.Size : NULL, + compressProgress); + + if (result == S_OK) + { + CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize; + coder->QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize); + if (getInStreamProcessedSize && setFinishMode) + { + UInt64 processed; + RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&processed)); + if (processed != (UInt64)(Int64)-1) + { + if (pkAesMode) + { + const UInt32 padSize = _pkAesDecoderSpec->GetPadSize((UInt32)processed); + if (processed + padSize > coderPackSize) + truncatedError = true; + else + { + if (processed + padSize < coderPackSize) + dataAfterEnd = true; + // also here we can check PKCS7 padding data from reminder (it can be inside stream buffer in coder). + } + } + else + { + if (processed < coderPackSize) + { + if (isFullStreamExpected) + dataAfterEnd = true; + } + else if (processed > coderPackSize) + truncatedError = true; + needReminderCheck = isFullStreamExpected; + } + } + } + } + + if (result == S_OK && id == NFileHeader::NCompressionMethod::kLZMA) + if (!lzmaDecoderSpec->DecoderSpec->CheckFinishStatus(item.IsLzmaEOS())) + lzmaEosError = true; + } if (result == S_FALSE) return S_OK; @@ -947,19 +1173,40 @@ HRESULT CZipDecoder::Decode( if (wzAesMode) { - const UInt64 rem = limitedStreamSpec->GetRem(); - if (rem != 0) - if (SkipStreamData(inStream, rem) != S_OK) - authOk = false; + bool thereAreData = false; + if (SkipStreamData(inStreamNew, thereAreData) != S_OK) + authOk = false; + if (needReminderCheck && thereAreData) + dataAfterEnd = true; + limitedStreamSpec->Init(NCrypto::NWzAes::kMacSize); if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK) authOk = false; } - - res = ((crcOK && authOk) ? - NExtract::NOperationResult::kOK : - NExtract::NOperationResult::kCRCError); + + res = NExtract::NOperationResult::kCRCError; + + if (crcOK && authOk) + { + res = NExtract::NOperationResult::kOK; + + if (dataAfterEnd) + res = NExtract::NOperationResult::kDataAfterEnd; + else if (truncatedError) + res = NExtract::NOperationResult::kUnexpectedEnd; + else if (lzmaEosError) + res = NExtract::NOperationResult::kHeadersError; + + // CheckDescriptor() supports only data descriptor with signature and + // it doesn't support "old" pkzip's data descriptor without signature. + // So we disable that check. + /* + if (item.HasDescriptor() && archive.CheckDescriptor(item) != S_OK) + res = NExtract::NOperationResult::kHeadersError; + */ + } + return S_OK; } @@ -1026,11 +1273,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnavailable)); continue; } + + bool headersError = false; if (!item.FromLocal) { bool isAvail = true; - HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item, isAvail); + HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item, isAvail, headersError); if (res == S_FALSE) { if (item.IsDir() || realOutStream || testMode) @@ -1069,12 +1318,16 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, m_Archive, item, realOutStream, extractCallback, progress, #ifndef _7ZIP_ST - _props.NumThreads, + _props._numThreads, #endif res); + RINOK(hres); realOutStream.Release(); + if (res == NExtract::NOperationResult::kOK && headersError) + res = NExtract::NOperationResult::kHeadersError; + RINOK(extractCallback->SetOperationResult(res)) } diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h index c2a362a7..53e6a460 100644 --- a/CPP/7zip/Archive/Zip/ZipHandler.h +++ b/CPP/7zip/Archive/Zip/ZipHandler.h @@ -9,12 +9,20 @@ #include "../../Common/CreateCoder.h" -#include "ZipIn.h" #include "ZipCompressionMode.h" +#include "ZipIn.h" namespace NArchive { namespace NZip { +const unsigned kNumMethodNames1 = NFileHeader::NCompressionMethod::kLZMA + 1; +const unsigned kMethodNames2Start = NFileHeader::NCompressionMethod::kXz; +const unsigned kNumMethodNames2 = NFileHeader::NCompressionMethod::kWzAES + 1 - kMethodNames2Start; + +extern const char * const kMethodNames1[kNumMethodNames1]; +extern const char * const kMethodNames2[kNumMethodNames2]; + + class CHandler: public IInArchive, public IOutArchive, diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp index 8a8de511..8ecf7942 100644 --- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp @@ -46,6 +46,30 @@ static bool IsSimpleAsciiString(const wchar_t *s) } } + +static int FindZipMethod(const char *s, const char * const *names, unsigned num) +{ + for (unsigned i = 0; i < num; i++) + { + const char *name = names[i]; + if (name && StringsAreEqualNoCase_Ascii(s, name)) + return i; + } + return -1; +} + +static int FindZipMethod(const char *s) +{ + int k = FindZipMethod(s, kMethodNames1, kNumMethodNames1); + if (k >= 0) + return k; + k = FindZipMethod(s, kMethodNames2, kNumMethodNames2); + if (k >= 0) + return kMethodNames2Start + k; + return -1; +} + + #define COM_TRY_BEGIN2 try { #define COM_TRY_END2 } \ catch(const CSystemException &e) { return e.ErrorCode; } \ @@ -63,6 +87,7 @@ static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propI return S_OK; } + STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *callback) { @@ -75,31 +100,46 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt } CObjectVector<CUpdateItem> updateItems; + updateItems.ClearAndReserve(numItems); + bool thereAreAesUpdates = false; UInt64 largestSize = 0; bool largestSizeDefined = false; + UString name; + CUpdateItem ui; + for (UInt32 i = 0; i < numItems; i++) { - CUpdateItem ui; Int32 newData; Int32 newProps; - UInt32 indexInArchive; + UInt32 indexInArc; + if (!callback) return E_FAIL; - RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive)); + + RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArc)); + + name.Empty(); + ui.Clear(); + ui.NewProps = IntToBool(newProps); ui.NewData = IntToBool(newData); - ui.IndexInArc = indexInArchive; + ui.IndexInArc = indexInArc; ui.IndexInClient = i; - bool existInArchive = (indexInArchive != (UInt32)(Int32)-1); - if (existInArchive && newData) - if (m_Items[indexInArchive].IsAesEncrypted()) + + bool existInArchive = (indexInArc != (UInt32)(Int32)-1); + if (existInArchive) + { + const CItemEx &inputItem = m_Items[indexInArc]; + if (inputItem.IsAesEncrypted()) thereAreAesUpdates = true; + if (!IntToBool(newProps)) + ui.IsDir = inputItem.IsDir(); + } if (IntToBool(newProps)) { - UString name; { NCOM::CPropVariant prop; RINOK(callback->GetProperty(i, kpidAttrib, &prop)); @@ -115,12 +155,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt NCOM::CPropVariant prop; RINOK(callback->GetProperty(i, kpidPath, &prop)); if (prop.vt == VT_EMPTY) - name.Empty(); + { + // name.Empty(); + } else if (prop.vt != VT_BSTR) return E_INVALIDARG; else name = prop.bstrVal; } + { NCOM::CPropVariant prop; RINOK(callback->GetProperty(i, kpidIsDir, &prop)); @@ -153,7 +196,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt FileTimeToDosTime(localFileTime, ui.Time); } - name = NItemName::MakeLegalName(name); + NItemName::ReplaceSlashes_OsToUnix(name); + bool needSlash = ui.IsDir; const wchar_t kSlash = L'/'; if (!name.IsEmpty()) @@ -188,11 +232,37 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (ui.Name.Len() >= (1 << 16)) return E_INVALIDARG; - ui.IndexInClient = i; + { + NCOM::CPropVariant prop; + RINOK(callback->GetProperty(i, kpidComment, &prop)); + if (prop.vt == VT_EMPTY) + { + // ui.Comment.Free(); + } + else if (prop.vt != VT_BSTR) + return E_INVALIDARG; + else + { + UString s = prop.bstrVal; + AString a; + if (ui.IsUtf8) + ConvertUnicodeToUTF8(s, a); + else + { + bool defaultCharWasUsed; + a = UnicodeStringToMultiByte(s, codePage, '_', defaultCharWasUsed); + } + if (a.Len() >= (1 << 16)) + return E_INVALIDARG; + ui.Comment.CopyFrom((const Byte *)(const char *)a, a.Len()); + } + } + + /* if (existInArchive) { - const CItemEx &itemInfo = m_Items[indexInArchive]; + const CItemEx &itemInfo = m_Items[indexInArc]; // ui.Commented = itemInfo.IsCommented(); ui.Commented = false; if (ui.Commented) @@ -205,6 +275,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.Commented = false; */ } + + if (IntToBool(newData)) { UInt64 size = 0; @@ -220,12 +292,12 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt largestSizeDefined = true; } ui.Size = size; - - // ui.Size -= ui.Size / 2; } + updateItems.Add(ui); } + CMyComPtr<ICryptoGetTextPassword2> getTextPassword; { CMyComPtr<IArchiveUpdateCallback> udateCallBack2(callback); @@ -261,16 +333,52 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt } } - Byte mainMethod; - if (m_MainMethod < 0) - mainMethod = (Byte)(((_props.Level == 0) ? - NFileHeader::NCompressionMethod::kStored : - NFileHeader::NCompressionMethod::kDeflated)); + + int mainMethod = m_MainMethod; + + if (mainMethod < 0) + { + if (!_props._methods.IsEmpty()) + { + const AString &methodName = _props._methods.Front().MethodName; + if (!methodName.IsEmpty()) + { + mainMethod = FindZipMethod(methodName); + if (mainMethod < 0) + { + CMethodId methodId; + UInt32 numStreams; + if (!FindMethod(EXTERNAL_CODECS_VARS methodName, methodId, numStreams)) + return E_NOTIMPL; + if (numStreams != 1) + return E_NOTIMPL; + if (methodId == kMethodId_BZip2) + mainMethod = NFileHeader::NCompressionMethod::kBZip2; + else + { + if (methodId < kMethodId_ZipBase) + return E_NOTIMPL; + methodId -= kMethodId_ZipBase; + if (methodId > 0xFF) + return E_NOTIMPL; + mainMethod = (int)methodId; + } + } + } + } + } + + if (mainMethod < 0) + mainMethod = (Byte)(((_props.GetLevel() == 0) ? + NFileHeader::NCompressionMethod::kStore : + NFileHeader::NCompressionMethod::kDeflate)); else - mainMethod = (Byte)m_MainMethod; - options.MethodSequence.Add(mainMethod); - if (mainMethod != NFileHeader::NCompressionMethod::kStored) - options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStored); + mainMethod = (Byte)mainMethod; + + options.MethodSequence.Add((Byte)mainMethod); + + if (mainMethod != NFileHeader::NCompressionMethod::kStore) + options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStore); return Update( EXTERNAL_CODECS_VARS @@ -281,28 +389,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt COM_TRY_END2 } -struct CMethodIndexToName -{ - unsigned Method; - const char *Name; -}; -static const CMethodIndexToName k_SupportedMethods[] = -{ - { NFileHeader::NCompressionMethod::kStored, "copy" }, - { NFileHeader::NCompressionMethod::kDeflated, "deflate" }, - { NFileHeader::NCompressionMethod::kDeflated64, "deflate64" }, - { NFileHeader::NCompressionMethod::kBZip2, "bzip2" }, - { NFileHeader::NCompressionMethod::kLZMA, "lzma" }, - { NFileHeader::NCompressionMethod::kPPMd, "ppmd" } -}; STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) { InitMethodProps(); - #ifndef _7ZIP_ST - const UInt32 numProcessors = _props.NumThreads; - #endif for (UInt32 i = 0; i < numProps; i++) { @@ -313,82 +404,27 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR const PROPVARIANT &prop = values[i]; - if (name[0] == L'x') - { - UInt32 level = 9; - RINOK(ParsePropToUInt32(name.Ptr(1), prop, level)); - _props.Level = level; - _props.MethodInfo.AddProp_Level(level); - } - else if (name == L"m") - { - if (prop.vt == VT_BSTR) - { - UString m = prop.bstrVal, m2; - m.MakeLower_Ascii(); - int colonPos = m.Find(L':'); - if (colonPos >= 0) - { - m2 = m.Ptr(colonPos + 1); - m.DeleteFrom(colonPos); - } - unsigned k; - for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++) - { - const CMethodIndexToName &pair = k_SupportedMethods[k]; - if (m.IsEqualTo(pair.Name)) - { - if (!m2.IsEmpty()) - { - RINOK(_props.MethodInfo.ParseParamsFromString(m2)); - } - m_MainMethod = pair.Method; - break; - } - } - if (k == ARRAY_SIZE(k_SupportedMethods)) - return E_INVALIDARG; - } - else if (prop.vt == VT_UI4) - { - unsigned k; - for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++) - { - unsigned method = k_SupportedMethods[k].Method; - if (prop.ulVal == method) - { - m_MainMethod = method; - break; - } - } - if (k == ARRAY_SIZE(k_SupportedMethods)) - return E_INVALIDARG; - } - else - return E_INVALIDARG; - } - else if (name.IsPrefixedBy(L"em")) + if (name.IsEqualTo_Ascii_NoCase("em")) { if (prop.vt != VT_BSTR) return E_INVALIDARG; { - UString m = prop.bstrVal; - m.MakeLower_Ascii(); - if (m.IsPrefixedBy(L"aes")) + const wchar_t *m = prop.bstrVal; + if (IsString1PrefixedByString2_NoCase_Ascii(m, "aes")) { - m.DeleteFrontal(3); - if (m == L"128") + m += 3; + if (StringsAreEqual_Ascii(m, "128")) _props.AesKeyMode = 1; - else if (m == L"192") + else if (StringsAreEqual_Ascii(m, "192")) _props.AesKeyMode = 2; - else if (m == L"256" || m.IsEmpty()) + else if (StringsAreEqual_Ascii(m, "256") || m[0] == 0) _props.AesKeyMode = 3; else return E_INVALIDARG; _props.IsAesMode = true; m_ForceAesMode = true; } - else if (m == L"zipcrypto") + else if (StringsAreEqualNoCase_Ascii(m, "ZipCrypto")) { _props.IsAesMode = false; m_ForceAesMode = true; @@ -397,13 +433,6 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR return E_INVALIDARG; } } - else if (name.IsPrefixedBy(L"mt")) - { - #ifndef _7ZIP_ST - RINOK(ParseMtProp(name.Ptr(2), prop, numProcessors, _props.NumThreads)); - _props.NumThreadsWasChanged = true; - #endif - } else if (name.IsEqualTo("tc")) { RINOK(PROPVARIANT_to_bool(prop, m_WriteNtfsTimeExtra)); @@ -433,9 +462,39 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR } else { - RINOK(_props.MethodInfo.ParseParamsFromPROPVARIANT(name, prop)); + if (name.IsEqualTo_Ascii_NoCase("m") && prop.vt == VT_UI4) + { + UInt32 id = prop.ulVal; + if (id > 0xFF) + return E_INVALIDARG; + m_MainMethod = id; + } + else + { + RINOK(_props.SetProperty(name, prop)); + } + // RINOK(_props.MethodInfo.ParseParamsFromPROPVARIANT(name, prop)); } } + + _props._methods.DeleteFrontal(_props.GetNumEmptyMethods()); + if (_props._methods.Size() > 1) + return E_INVALIDARG; + if (_props._methods.Size() == 1) + { + const AString &methodName = _props._methods[0].MethodName; + + if (!methodName.IsEmpty()) + { + const char *end; + UInt32 id = ConvertStringToUInt32(methodName, &end); + if (*end == 0 && id <= 0xFF) + m_MainMethod = id; + else if (methodName.IsEqualTo_Ascii_NoCase("Copy")) // it's alias for "Store" + m_MainMethod = 0; + } + } + return S_OK; } diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h index fead0192..61b4ea4b 100644 --- a/CPP/7zip/Archive/Zip/ZipHeader.h +++ b/CPP/7zip/Archive/Zip/ZipHeader.h @@ -23,7 +23,8 @@ namespace NSignature } const unsigned kLocalHeaderSize = 4 + 26; // including signature -const unsigned kDataDescriptorSize = 4 + 12; // including signature +const unsigned kDataDescriptorSize32 = 4 + 4 + 4 * 2; // including signature +const unsigned kDataDescriptorSize64 = 4 + 4 + 8 * 2; // including signature const unsigned kCentralHeaderSize = 4 + 42; // including signature const unsigned kEcdSize = 22; // including signature @@ -37,28 +38,30 @@ namespace NFileHeader { enum EType { - kStored = 0, - kShrunk = 1, - kReduced1 = 2, - kReduced2 = 3, - kReduced3 = 4, - kReduced4 = 5, - kImploded = 6, - kReservedTokenizing = 7, // reserved for tokenizing - kDeflated = 8, - kDeflated64 = 9, + kStore = 0, + kShrink = 1, + kReduce1 = 2, + kReduce2 = 3, + kReduce3 = 4, + kReduce4 = 5, + kImplode = 6, + kTokenize = 7, + kDeflate = 8, + kDeflate64 = 9, kPKImploding = 10, kBZip2 = 12, + kLZMA = 14, + kTerse = 18, kLz77 = 19, - kXz = 0x5F, - kJpeg = 0x60, - kWavPack = 0x61, - kPPMd = 0x62, - kWzAES = 0x63 + kXz = 95, + kJpeg = 96, + kWavPack = 97, + kPPMd = 98, + kWzAES = 99 }; const Byte kMadeByProgramVersion = 63; @@ -73,6 +76,7 @@ namespace NFileHeader const Byte kExtractVersion_Aes = 51; const Byte kExtractVersion_LZMA = 63; const Byte kExtractVersion_PPMd = 63; + const Byte kExtractVersion_Xz = 20; // test it } namespace NExtraID @@ -83,6 +87,7 @@ namespace NFileHeader kNTFS = 0x0A, kStrongEncrypt = 0x17, kUnixTime = 0x5455, + kUnixExtra = 0x5855, kIzUnicodeComment = 0x6375, kIzUnicodeName = 0x7075, kWzAES = 0x9901 @@ -110,6 +115,15 @@ namespace NFileHeader }; } + namespace NUnixExtra + { + enum + { + kATime = 0, + kMTime + }; + } + namespace NFlags { const unsigned kEncrypted = 1 << 0; @@ -121,10 +135,12 @@ namespace NFileHeader const unsigned kImplodeDictionarySizeMask = 1 << 1; const unsigned kImplodeLiteralsOnMask = 1 << 2; + /* const unsigned kDeflateTypeBitStart = 1; const unsigned kNumDeflateTypeBits = 2; const unsigned kNumDeflateTypes = (1 << kNumDeflateTypeBits); const unsigned kDeflateTypeMask = (1 << kNumDeflateTypeBits) - 1; + */ } namespace NHostOS diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index 6361dc5c..09443a61 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -6,6 +6,7 @@ #include "../../../Common/DynamicBuffer.h" #include "../../../Common/IntToString.h" +#include "../../../Common/MyException.h" #include "../../../Common/StringToInt.h" #include "../../../Windows/PropVariant.h" @@ -27,6 +28,19 @@ namespace NArchive { namespace NZip { +// (kBufferSize >= kDataDescriptorSize64 + 4) + +static const size_t kSeqBufferSize = (size_t)1 << 14; + +/* + if (not defined ZIP_SELF_CHECK) : it reads CD and if error in first pass CD reading, it reads LOCALS-CD-MODE + if ( defined ZIP_SELF_CHECK) : it always reads CD and LOCALS-CD-MODE + use ZIP_SELF_CHECK to check LOCALS-CD-MODE for any zip archive +*/ + +// #define ZIP_SELF_CHECK + + struct CEcd { UInt16 ThisDisk; @@ -66,6 +80,7 @@ void CEcd::Parse(const Byte *p) void CCdInfo::ParseEcd32(const Byte *p) { + IsFromEcd64 = false; // (p) includes signature p += 4; G16(0, ThisDisk); @@ -79,6 +94,7 @@ void CCdInfo::ParseEcd32(const Byte *p) void CCdInfo::ParseEcd64e(const Byte *p) { + IsFromEcd64 = true; // (p) exclude signature G16(0, VersionMade); G16(2, VersionNeedExtract); @@ -106,9 +122,14 @@ struct CLocator G64(4, Ecd64Offset); G32(12, NumDisks); } -}; + bool IsEmptyArc() const + { + return Ecd64Disk == 0 && NumDisks == 0 && Ecd64Offset == 0; + } +}; + void CInArchive::ClearRefs() @@ -123,27 +144,174 @@ void CInArchive::ClearRefs() void CInArchive::Close() { - _processedCnt = 0; - IsArc = false; + _cnt = 0; + DisableBufMode(); + IsArcOpen = false; - IsMultiVol = false; - UseDisk_in_SingleVol = false; - EcdVolIndex = 0; + + IsArc = false; + IsZip64 = false; + HeadersError = false; HeadersWarning = false; ExtraMinorError = false; UnexpectedEnd = false; + LocalsWereRead = false; + LocalsCenterMerged = false; NoCentralDir = false; - IsZip64 = false; + Overflow32bit = false; + Cd_NumEntries_Overflow_16bit = false; + MarkerIsFound = false; + MarkerIsSafe = false; + + IsMultiVol = false; + UseDisk_in_SingleVol = false; + EcdVolIndex = 0; + ArcInfo.Clear(); + ClearRefs(); } -HRESULT CInArchive::Seek(UInt64 offset) + +HRESULT CInArchive::Seek_SavePos(UInt64 offset) +{ + // InitBuf(); + // if (!Stream) return S_FALSE; + return Stream->Seek(offset, STREAM_SEEK_SET, &_streamPos); +} + +HRESULT CInArchive::SeekToVol(int volIndex, UInt64 offset) +{ + if (volIndex != Vols.StreamIndex) + { + InitBuf(); + if (IsMultiVol && volIndex >= 0) + { + if ((unsigned)volIndex >= Vols.Streams.Size()) + return S_FALSE; + if (!Vols.Streams[volIndex].Stream) + return S_FALSE; + Stream = Vols.Streams[volIndex].Stream; + } + else if (volIndex == -2) + { + if (!Vols.ZipStream) + return S_FALSE; + Stream = Vols.ZipStream; + } + else + Stream = StartStream; + Vols.StreamIndex = volIndex; + } + else + { + if (offset <= _streamPos) + { + const UInt64 back = _streamPos - offset; + if (back <= _bufCached) + { + _bufPos = _bufCached - (size_t)back; + return S_OK; + } + } + InitBuf(); + } + return Seek_SavePos(offset); +} + + +// ---------- ReadFromCache ---------- +// reads from cache and from Stream +// move to next volume can be allowed if (CanStartNewVol) and only before first byte reading + +HRESULT CInArchive::ReadFromCache(Byte *data, unsigned size, unsigned &processed) { - return Stream->Seek(offset, STREAM_SEEK_SET, NULL); + HRESULT result = S_OK; + processed = 0; + + for (;;) + { + if (size == 0) + return S_OK; + + const size_t avail = GetAvail(); + + if (avail != 0) + { + unsigned cur = size; + if (cur > avail) + cur = (unsigned)avail; + memcpy(data, (const Byte *)Buffer + _bufPos, cur); + + data += cur; + size -= cur; + processed += cur; + + _bufPos += cur; + _cnt += cur; + + CanStartNewVol = false; + + continue; + } + + InitBuf(); + + if (_inBufMode) + { + UInt32 cur = 0; + result = Stream->Read(Buffer, (UInt32)Buffer.Size(), &cur); + _bufPos = 0; + _bufCached = cur; + _streamPos += cur; + if (cur != 0) + CanStartNewVol = false; + if (result != S_OK) + break; + if (cur != 0) + continue; + } + else + { + UInt32 cur = 0; + result = Stream->Read(data, size, &cur); + data += cur; + size -= cur; + processed += cur; + _streamPos += cur; + _cnt += cur; + if (cur != 0) + { + CanStartNewVol = false; + break; + } + if (result != S_OK) + break; + } + + if ( !IsMultiVol + || !CanStartNewVol + || Vols.StreamIndex < 0 + || (unsigned)Vols.StreamIndex + 1 >= Vols.Streams.Size()) + break; + + const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex + 1]; + if (!s.Stream) + break; + result = s.SeekToStart(); + if (result != S_OK) + break; + Vols.StreamIndex++; + _streamPos = 0; + // Vols.NeedSeek = false; + + Stream = s.Stream; + } + + return result; } @@ -168,18 +336,33 @@ API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size) if (p[0] != 'P') return k_IsArc_Res_NO; - UInt32 value = Get32(p); + UInt32 sig = Get32(p); - if (value == NSignature::kNoSpan - || value == NSignature::kSpan) + if (sig == NSignature::kNoSpan || sig == NSignature::kSpan) { p += 4; size -= 4; } - value = Get32(p); + sig = Get32(p); - if (value == NSignature::kEcd) + if (sig == NSignature::kEcd64) + { + if (size < kEcd64_FullSize) + return k_IsArc_Res_NEED_MORE; + + const UInt64 recordSize = Get64(p + 4); + if ( recordSize < kEcd64_MainSize + || recordSize > kEcd64_MainSize + (1 << 20)) + return k_IsArc_Res_NO; + CCdInfo cdInfo; + cdInfo.ParseEcd64e(p + 12); + if (!cdInfo.IsEmptyArc()) + return k_IsArc_Res_NO; + return k_IsArc_Res_YES; // k_IsArc_Res_YES_2; + } + + if (sig == NSignature::kEcd) { if (size < kEcdSize) return k_IsArc_Res_NEED_MORE; @@ -190,8 +373,8 @@ API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size) return k_IsArc_Res_NO; return k_IsArc_Res_YES; // k_IsArc_Res_YES_2; } - - if (value != NSignature::kLocalFileHeader) + + if (sig != NSignature::kLocalFileHeader) return k_IsArc_Res_NO; if (size < kLocalHeaderSize) @@ -240,8 +423,17 @@ API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size) const Byte *p2 = p + kLocalHeaderSize; for (size_t i = 0; i < rem; i++) if (p2[i] == 0) + { + // we support some "bad" zip archives that contain zeros after name + for (size_t k = i + 1; k < rem; k++) + if (p2[k] != 0) + return k_IsArc_Res_NO; + break; + /* if (i != nameSize - 1) return k_IsArc_Res_NO; + */ + } } if (size < extraOffset) @@ -288,398 +480,562 @@ static UInt32 IsArc_Zip_2(const Byte *p, size_t size, bool isFinal) } + +MY_NO_INLINE +static const Byte *FindPK(const Byte *p, const Byte *limit) +{ + for (;;) + { + for (;;) + { + Byte b0 = p[0]; + if (p >= limit) + return p; + p++; + if (b0 == 0x50) + break; + } + if (p[0] == 0x4B) + return p - 1; + } +} + -HRESULT CInArchive::FindMarker(IInStream *stream, const UInt64 *searchLimit) +/* +---------- FindMarker ---------- +returns: + S_OK: + ArcInfo.MarkerVolIndex : volume of marker + ArcInfo.MarkerPos : Pos of first signature + ArcInfo.MarkerPos2 : Pos of main signature (local item signature in most cases) + _streamPos : stream pos + _cnt : The number of virtal Bytes after start of search to offset after signature + _signature : main signature + + S_FALSE: can't find marker, or there is some non-zip data after marker + + Error code: stream reading error. +*/ + +HRESULT CInArchive::FindMarker(const UInt64 *searchLimit) { - ArcInfo.MarkerPos = m_Position; - ArcInfo.MarkerPos2 = m_Position; + ArcInfo.MarkerPos = GetVirtStreamPos(); + ArcInfo.MarkerPos2 = ArcInfo.MarkerPos; + ArcInfo.MarkerVolIndex = Vols.StreamIndex; + + _cnt = 0; + + CanStartNewVol = false; if (searchLimit && *searchLimit == 0) { Byte startBuf[kMarkerSize]; - { - size_t processed = kMarkerSize; - RINOK(ReadStream(stream, startBuf, &processed)); - m_Position += processed; - if (processed != kMarkerSize) - return S_FALSE; - } + unsigned processed; + RINOK(ReadFromCache(startBuf, kMarkerSize, processed)); + if (processed != kMarkerSize) + return S_FALSE; - m_Signature = Get32(startBuf); + UInt32 marker = Get32(startBuf); + _signature = marker; - if (m_Signature != NSignature::kEcd && - m_Signature != NSignature::kLocalFileHeader) + if ( marker == NSignature::kNoSpan + || marker == NSignature::kSpan) { - if (m_Signature != NSignature::kNoSpan) - { - if (m_Signature != NSignature::kSpan) - return S_FALSE; - if (m_Position != 4) // we don't support multivol archives with sfx stub - return S_FALSE; - ArcInfo.IsSpanMode = true; - } - size_t processed = kMarkerSize; - RINOK(ReadStream(stream, startBuf, &processed)); - m_Position += processed; + RINOK(ReadFromCache(startBuf, kMarkerSize, processed)); if (processed != kMarkerSize) return S_FALSE; - m_Signature = Get32(startBuf); - if (m_Signature != NSignature::kEcd && - m_Signature != NSignature::kLocalFileHeader) - return S_FALSE; - ArcInfo.MarkerPos2 += 4; + _signature = Get32(startBuf); } + + if ( _signature != NSignature::kEcd + && _signature != NSignature::kEcd64 + && _signature != NSignature::kLocalFileHeader) + return S_FALSE; + + ArcInfo.MarkerPos2 = GetVirtStreamPos() - 4; + ArcInfo.IsSpanMode = (marker == NSignature::kSpan); // we use weak test in case of (*searchLimit == 0) // since error will be detected later in Open function - return S_OK; // maybe we need to search backward. + return S_OK; } - const size_t kBufSize = (size_t)1 << 18; // must be larger than kCheckSize const size_t kCheckSize = (size_t)1 << 16; // must be smaller than kBufSize - CByteArr buffer(kBufSize); - - size_t numBytesInBuffer = 0; - UInt64 curScanPos = 0; + const size_t kBufSize = (size_t)1 << 17; // must be larger than kCheckSize + + if (Buffer.Size() < kBufSize) + { + InitBuf(); + Buffer.AllocAtLeast(kBufSize); + if (!Buffer.IsAllocated()) + return E_OUTOFMEMORY; + } + + _inBufMode = true; + + UInt64 progressPrev = 0; for (;;) { - size_t numReadBytes = kBufSize - numBytesInBuffer; - RINOK(ReadStream(stream, buffer + numBytesInBuffer, &numReadBytes)); - m_Position += numReadBytes; - numBytesInBuffer += numReadBytes; - const bool isFinished = (numBytesInBuffer != kBufSize); + RINOK(LookAhead(kBufSize)); - size_t limit = numBytesInBuffer;; + const size_t avail = GetAvail(); + + size_t limitPos; + const bool isFinished = (avail != kBufSize); if (isFinished) { - if (limit == 0) - break; - limit--; + const unsigned kMinAllowed = 4; + if (avail <= kMinAllowed) + { + if ( !IsMultiVol + || Vols.StreamIndex < 0 + || (unsigned)Vols.StreamIndex + 1 >= Vols.Streams.Size()) + break; + + SkipLookahed(avail); + + const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex + 1]; + if (!s.Stream) + break; + + RINOK(s.SeekToStart()); + + InitBuf(); + Vols.StreamIndex++; + _streamPos = 0; + Stream = s.Stream; + continue; + } + limitPos = avail - kMinAllowed; } else - limit -= kCheckSize; + limitPos = (avail - kCheckSize); - if (searchLimit && curScanPos + limit > *searchLimit) - limit = (size_t)(*searchLimit - curScanPos + 1); + // we don't check at (limitPos) for good fast aligned operations - if (limit < 1) + if (searchLimit) + { + if (_cnt > *searchLimit) + break; + UInt64 rem = *searchLimit - _cnt; + if (limitPos > rem) + limitPos = (size_t)rem + 1; + } + + if (limitPos == 0) break; - const Byte *buf = buffer; - for (size_t pos = 0; pos < limit; pos++) + const Byte * const pStart = Buffer + _bufPos; + const Byte * p = pStart; + const Byte * const limit = pStart + limitPos; + + for (;; p++) { - if (buf[pos] != 0x50) - continue; - if (buf[pos + 1] != 0x4B) - continue; - size_t rem = numBytesInBuffer - pos; - UInt32 res = IsArc_Zip_2(buf + pos, rem, isFinished); + p = FindPK(p, limit); + if (p >= limit) + break; + const size_t rem = pStart + avail - p; + UInt32 res = IsArc_Zip_2(p, rem, isFinished); if (res != k_IsArc_Res_NO) { if (rem < kMarkerSize) return S_FALSE; - m_Signature = Get32(buf + pos); - ArcInfo.MarkerPos += curScanPos + pos; + _signature = Get32(p); + SkipLookahed(p - pStart); + ArcInfo.MarkerVolIndex = Vols.StreamIndex; + ArcInfo.MarkerPos = GetVirtStreamPos(); ArcInfo.MarkerPos2 = ArcInfo.MarkerPos; - if (m_Signature == NSignature::kNoSpan - || m_Signature == NSignature::kSpan) + SkipLookahed(4); + if ( _signature == NSignature::kNoSpan + || _signature == NSignature::kSpan) { - m_Signature = Get32(buf + pos + 4); + if (rem < kMarkerSize * 2) + return S_FALSE; + ArcInfo.IsSpanMode = (_signature == NSignature::kSpan); + _signature = Get32(p + 4); ArcInfo.MarkerPos2 += 4; + SkipLookahed(4); } - m_Position = ArcInfo.MarkerPos2 + kMarkerSize; return S_OK; } } - if (isFinished) + if (!IsMultiVol && isFinished) break; - curScanPos += limit; - numBytesInBuffer -= limit; - memmove(buffer, buffer + limit, numBytesInBuffer); + SkipLookahed(p - pStart); + + if (Callback && (_cnt - progressPrev) >= ((UInt32)1 << 23)) + { + progressPrev = _cnt; + // const UInt64 numFiles64 = 0; + RINOK(Callback->SetCompleted(NULL, &_cnt)); + } } return S_FALSE; } -HRESULT CInArchive::IncreaseRealPosition(Int64 addValue, bool &isFinished) +/* +---------- IncreaseRealPosition ---------- +moves virtual offset in virtual stream. +changing to new volumes is allowed +*/ + +HRESULT CInArchive::IncreaseRealPosition(UInt64 offset, bool &isFinished) { isFinished = false; + + for (;;) + { + const size_t avail = GetAvail(); + + if (offset <= avail) + { + _bufPos += (size_t)offset; + _cnt += offset; + return S_OK; + } + + _cnt += avail; + offset -= avail; + + _bufCached = 0; + _bufPos = 0; + + if (!_inBufMode) + break; + + CanStartNewVol = true; + LookAhead(1); + + if (GetAvail() == 0) + return S_OK; + } + if (!IsMultiVol) - return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position); + { + _cnt += offset; + return Stream->Seek(offset, STREAM_SEEK_CUR, &_streamPos); + } for (;;) { - if (addValue == 0) + if (offset == 0) return S_OK; - if (addValue > 0) + + if (Vols.StreamIndex < 0) + return S_FALSE; + if ((unsigned)Vols.StreamIndex >= Vols.Streams.Size()) { - if (Vols.StreamIndex < 0) - return S_FALSE; - if ((unsigned)Vols.StreamIndex >= Vols.Streams.Size()) + isFinished = true; + return S_OK; + } + { + const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex]; + if (!s.Stream) { isFinished = true; return S_OK; } + if (_streamPos > s.Size) + return S_FALSE; + const UInt64 rem = s.Size - _streamPos; + if ((UInt64)offset <= rem) { - const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex]; - if (!s.Stream) - { - isFinished = true; - return S_OK; - } - if (m_Position > s.Size) - return S_FALSE; - UInt64 rem = s.Size - m_Position; - if ((UInt64)addValue <= rem) - return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position); - RINOK(Stream->Seek(s.Size, STREAM_SEEK_SET, &m_Position)); - addValue -= rem; - Stream = NULL; - Vols.StreamIndex++; - if ((unsigned)Vols.StreamIndex >= Vols.Streams.Size()) - { - isFinished = true; - return S_OK; - } - } - const CVols::CSubStreamInfo &s2 = Vols.Streams[Vols.StreamIndex]; - if (!s2.Stream) - { - isFinished = true; - return S_OK; + _cnt += offset; + return Stream->Seek(offset, STREAM_SEEK_CUR, &_streamPos); } - Stream = s2.Stream; - m_Position = 0; - RINOK(Stream->Seek(0, STREAM_SEEK_SET, &m_Position)); + RINOK(Seek_SavePos(s.Size)); + offset -= rem; + _cnt += rem; } - else + + Stream = NULL; + _streamPos = 0; + Vols.StreamIndex++; + if ((unsigned)Vols.StreamIndex >= Vols.Streams.Size()) { - if (!Stream) - return S_FALSE; - { - if (m_Position >= (UInt64)(-addValue)) - return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position); - addValue += m_Position; - RINOK(Stream->Seek(0, STREAM_SEEK_SET, &m_Position)); - m_Position = 0; - Stream = NULL; - if (--Vols.StreamIndex < 0) - return S_FALSE; - } - const CVols::CSubStreamInfo &s2 = Vols.Streams[Vols.StreamIndex]; - if (!s2.Stream) - return S_FALSE; - Stream = s2.Stream; - m_Position = s2.Size; - RINOK(Stream->Seek(s2.Size, STREAM_SEEK_SET, &m_Position)); + isFinished = true; + return S_OK; + } + const CVols::CSubStreamInfo &s2 = Vols.Streams[Vols.StreamIndex]; + if (!s2.Stream) + { + isFinished = true; + return S_OK; } + Stream = s2.Stream; + RINOK(Seek_SavePos(0)); } } -class CUnexpectEnd {}; +/* +---------- LookAhead ---------- +Reads data to buffer, if required. -HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize) -{ - size_t realProcessedSize = size; - HRESULT result = S_OK; - if (_inBufMode) - { - try { realProcessedSize = _inBuffer.ReadBytes((Byte *)data, size); } - catch (const CInBufferException &e) { return e.ErrorCode; } - } - else - result = ReadStream(Stream, data, &realProcessedSize); - if (processedSize) - *processedSize = (UInt32)realProcessedSize; - m_Position += realProcessedSize; - return result; -} +It can read from volumes as long as Buffer.Size(). +But it moves to new volume, only if it's required to provide minRequired bytes in buffer. -void CInArchive::SafeReadBytes(void *data, unsigned size) -{ - size_t processed = size; - - HRESULT result = S_OK; +in: + (minRequired <= Buffer.Size()) - if (!_inBufMode) - result = ReadStream(Stream, data, &processed); - else +return: + S_OK : if (GetAvail() < minRequired) after function return, it's end of stream(s) data, or no new volume stream. + Error codes: IInStream::Read() error or IInStream::Seek() error for multivol +*/ + +HRESULT CInArchive::LookAhead(size_t minRequired) +{ + for (;;) { - for (;;) + const size_t avail = GetAvail(); + + if (minRequired <= avail) + return S_OK; + + if (_bufPos != 0) { - processed = _inBuffer.ReadBytes((Byte *)data, size); - if (processed != 0 - || IsMultiVol - || !CanStartNewVol - || Vols.StreamIndex < 0 - || (unsigned)Vols.StreamIndex >= Vols.Streams.Size()) - break; - Vols.StreamIndex++; - const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex]; - if (!s.Stream) - break; - // if (Vols.NeedSeek) - { - result = s.Stream->Seek(0, STREAM_SEEK_SET, NULL); - m_Position = 0; - if (result != S_OK) - break; - Vols.NeedSeek = false; - } - _inBuffer.SetStream(s.Stream); - _inBuffer.Init(); + if (avail != 0) + memmove(Buffer, Buffer + _bufPos, avail); + _bufPos = 0; + _bufCached = avail; } - CanStartNewVol = false; + + const size_t pos = _bufCached; + UInt32 processed = 0; + HRESULT res = Stream->Read(Buffer + pos, (UInt32)(Buffer.Size() - pos), &processed); + _streamPos += processed; + _bufCached += processed; + + if (res != S_OK) + return res; + + if (processed != 0) + continue; + + if ( !IsMultiVol + || !CanStartNewVol + || Vols.StreamIndex < 0 + || (unsigned)Vols.StreamIndex + 1 >= Vols.Streams.Size()) + return S_OK; + + const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex + 1]; + if (!s.Stream) + return S_OK; + + RINOK(s.SeekToStart()); + + Vols.StreamIndex++; + _streamPos = 0; + Stream = s.Stream; + // Vols.NeedSeek = false; } +} + + +class CUnexpectEnd {}; + + +/* +---------- SafeRead ---------- + +reads data of exact size from stream(s) - m_Position += processed; - _processedCnt += processed; +in: + _inBufMode + if (CanStartNewVol) it can go to next volume before first byte reading, if there is end of volume data. +in, out: + _streamPos : position in Stream + Stream + Vols : if (IsMultiVol) + _cnt + +out: + (CanStartNewVol == false), if some data was read + +return: + S_OK : success reading of requested data + +exceptions: + CSystemException() - stream reading error + CUnexpectEnd() : could not read data of requested size +*/ + +void CInArchive::SafeRead(Byte *data, unsigned size) +{ + unsigned processed; + HRESULT result = ReadFromCache(data, size, processed); if (result != S_OK) throw CSystemException(result); - - if (processed != size) + if (size != processed) throw CUnexpectEnd(); } void CInArchive::ReadBuffer(CByteBuffer &buffer, unsigned size) { buffer.Alloc(size); - if (size > 0) - SafeReadBytes(buffer, size); + if (size != 0) + SafeRead(buffer, size); } -Byte CInArchive::ReadByte() +// Byte CInArchive::ReadByte () { Byte b; SafeRead(&b, 1); return b; } +// UInt16 CInArchive::ReadUInt16() { Byte buf[2]; SafeRead(buf, 2); return Get16(buf); } +UInt32 CInArchive::ReadUInt32() { Byte buf[4]; SafeRead(buf, 4); return Get32(buf); } +UInt64 CInArchive::ReadUInt64() { Byte buf[8]; SafeRead(buf, 8); return Get64(buf); } + +void CInArchive::ReadSignature() { - Byte b; - SafeReadBytes(&b, 1); - return b; + CanStartNewVol = true; + _signature = ReadUInt32(); + // CanStartNewVol = false; // it's already changed in SafeRead } -UInt16 CInArchive::ReadUInt16() { Byte buf[2]; SafeReadBytes(buf, 2); return Get16(buf); } -UInt32 CInArchive::ReadUInt32() { Byte buf[4]; SafeReadBytes(buf, 4); return Get32(buf); } -UInt64 CInArchive::ReadUInt64() { Byte buf[8]; SafeReadBytes(buf, 8); return Get64(buf); } -// we use Skip() inside headers only, so no need for stream change in multivol. +// we Skip() inside headers only, so no need for stream change in multivol. -void CInArchive::Skip(unsigned num) +void CInArchive::Skip(size_t num) { - if (_inBufMode) - { - size_t skip = _inBuffer.Skip(num); - m_Position += skip; - _processedCnt += skip; - if (skip != num) - throw CUnexpectEnd(); - } - else + while (num != 0) { - for (unsigned i = 0; i < num; i++) - ReadByte(); + const unsigned kBufSize = (size_t)1 << 10; + Byte buf[kBufSize]; + unsigned step = kBufSize; + if (step > num) + step = (unsigned)num; + SafeRead(buf, step); + num -= step; } } -void CInArchive::Skip64(UInt64 num) +/* +HRESULT CInArchive::Callback_Completed(unsigned numFiles) +{ + const UInt64 numFiles64 = numFiles; + return Callback->SetCompleted(&numFiles64, &_cnt); +} +*/ + +HRESULT CInArchive::Skip64(UInt64 num, unsigned numFiles) { - for (UInt64 i = 0; i < num; i++) - ReadByte(); + if (num == 0) + return S_OK; + + for (;;) + { + size_t step = (size_t)1 << 24; + if (step > num) + step = (size_t)num; + Skip(step); + num -= step; + if (num == 0) + return S_OK; + if (Callback) + { + const UInt64 numFiles64 = numFiles; + RINOK(Callback->SetCompleted(&numFiles64, &_cnt)); + } + } } -void CInArchive::ReadFileName(unsigned size, AString &s) +bool CInArchive::ReadFileName(unsigned size, AString &s) { if (size == 0) { s.Empty(); - return; + return true; + } + char *p = s.GetBuf(size); + SafeRead((Byte *)p, size); + unsigned i = size; + do + { + if (p[i - 1] != 0) + break; } - SafeReadBytes(s.GetBuf(size), size); + while (--i); s.ReleaseBuf_CalcLen(size); + return s.Len() == i; } -bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extraBlock, - UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber) +#define ZIP64_IS_32_MAX(n) ((n) == 0xFFFFFFFF) +#define ZIP64_IS_16_MAX(n) ((n) == 0xFFFF) + + +bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extra, + UInt64 &unpackSize, UInt64 &packSize, UInt64 &localOffset, UInt32 &disk) { - extraBlock.Clear(); + extra.Clear(); - UInt32 remain = extraSize; - - while (remain >= 4) + while (extraSize >= 4) { CExtraSubBlock subBlock; - subBlock.ID = ReadUInt16(); - unsigned dataSize = ReadUInt16(); - remain -= 4; - if (dataSize > remain) // it's bug + const UInt32 pair = ReadUInt32(); + subBlock.ID = (pair & 0xFFFF); + unsigned size = (unsigned)(pair >> 16); + + extraSize -= 4; + + if (size > extraSize) { + // it's error in extra HeadersWarning = true; - Skip(remain); + extra.Error = true; + Skip(extraSize); return false; } + + extraSize -= size; + if (subBlock.ID == NFileHeader::NExtraID::kZip64) { - if (unpackSize == 0xFFFFFFFF) - { - if (dataSize < 8) - { - HeadersWarning = true; - Skip(remain); - return false; - } - unpackSize = ReadUInt64(); - remain -= 8; - dataSize -= 8; - } - if (packSize == 0xFFFFFFFF) - { - if (dataSize < 8) - break; - packSize = ReadUInt64(); - remain -= 8; - dataSize -= 8; - } - if (localHeaderOffset == 0xFFFFFFFF) - { - if (dataSize < 8) - break; - localHeaderOffset = ReadUInt64(); - remain -= 8; - dataSize -= 8; - } - if (diskStartNumber == 0xFFFF) + extra.IsZip64 = true; + bool isOK = true; + + if (ZIP64_IS_32_MAX(unpackSize)) + if (size < 8) isOK = false; else { size -= 8; unpackSize = ReadUInt64(); } + + if (isOK && ZIP64_IS_32_MAX(packSize)) + if (size < 8) isOK = false; else { size -= 8; packSize = ReadUInt64(); } + + if (isOK && ZIP64_IS_32_MAX(localOffset)) + if (size < 8) isOK = false; else { size -= 8; localOffset = ReadUInt64(); } + + if (isOK && ZIP64_IS_16_MAX(disk)) + if (size < 4) isOK = false; else { size -= 4; disk = ReadUInt32(); } + + if (!isOK || size != 0) { - if (dataSize < 4) - break; - diskStartNumber = ReadUInt32(); - remain -= 4; - dataSize -= 4; + HeadersWarning = true; + extra.Error = true; + extra.IsZip64_Error = true; + Skip(size); } - Skip(dataSize); } else { - ReadBuffer(subBlock.Data, dataSize); - extraBlock.SubBlocks.Add(subBlock); + ReadBuffer(subBlock.Data, size); + extra.SubBlocks.Add(subBlock); } - remain -= dataSize; } - if (remain != 0) + if (extraSize != 0) { ExtraMinorError = true; + extra.MinorError = true; // 7-Zip before 9.31 created incorrect WsAES Extra in folder's local headers. // so we don't return false, but just set warning flag // return false; + Skip(extraSize); } - - Skip(remain); + return true; } @@ -691,7 +1047,7 @@ bool CInArchive::ReadLocalItem(CItemEx &item) item.Disk = Vols.StreamIndex; const unsigned kPureHeaderSize = kLocalHeaderSize - 4; Byte p[kPureHeaderSize]; - SafeReadBytes(p, kPureHeaderSize); + SafeRead(p, kPureHeaderSize); { unsigned i; for (i = 0; i < kPureHeaderSize && p[i] == 0; i++); @@ -709,8 +1065,9 @@ bool CInArchive::ReadLocalItem(CItemEx &item) G32(18, item.Size); const unsigned nameSize = Get16(p + 22); const unsigned extraSize = Get16(p + 24); - ReadFileName(nameSize, item.Name); + bool isOkName = ReadFileName(nameSize, item.Name); item.LocalFullHeaderSize = kLocalHeaderSize + (UInt32)nameSize + extraSize; + item.DescriptorWasRead = false; /* if (item.IsDir()) @@ -719,10 +1076,9 @@ bool CInArchive::ReadLocalItem(CItemEx &item) if (extraSize > 0) { - UInt64 localHeaderOffset = 0; - UInt32 diskStartNumber = 0; - if (!ReadExtra(extraSize, item.LocalExtra, item.Size, item.PackSize, - localHeaderOffset, diskStartNumber)) + UInt64 localOffset = 0; + UInt32 disk = 0; + if (!ReadExtra(extraSize, item.LocalExtra, item.Size, item.PackSize, localOffset, disk)) { /* 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. @@ -739,8 +1095,8 @@ bool CInArchive::ReadLocalItem(CItemEx &item) if (item.Name.Len() != nameSize) { - // we support "bad" archives with null-terminated name. - if (item.Name.Len() + 1 != nameSize) + // we support some "bad" zip archives that contain zeros after name + if (!isOkName) return false; HeadersWarning = true; } @@ -758,11 +1114,11 @@ static bool FlagsAreSame(const CItem &i1, const CItem &i2) UInt32 mask = 0xFFFF; switch (i1.Method) { - case NFileHeader::NCompressionMethod::kDeflated: + case NFileHeader::NCompressionMethod::kDeflate: mask = 0x7FF9; break; default: - if (i1.Method <= NFileHeader::NCompressionMethod::kImploded) + if (i1.Method <= NFileHeader::NCompressionMethod::kImplode) mask = 0x7FFF; } @@ -805,9 +1161,9 @@ static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem) return false; if (!localItem.HasDescriptor()) { - if (cdItem.Crc != localItem.Crc || - cdItem.PackSize != localItem.PackSize || - cdItem.Size != localItem.Size) + if (cdItem.PackSize != localItem.PackSize + || cdItem.Size != localItem.Size + || cdItem.Crc != localItem.Crc && cdItem.Crc != 0) // some program writes 0 to crc field in central directory return false; } /* pkzip 2.50 creates incorrect archives. It uses @@ -833,7 +1189,8 @@ static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem) // pkzip 2.50 uses DOS encoding in central dir and WIN encoding in local header. // so we ignore that error if (hostOs != NFileHeader::NHostOS::kFAT - || cdItem.MadeByVersion.Version != 25) + || cdItem.MadeByVersion.Version < 25 + || cdItem.MadeByVersion.Version > 40) return false; } } @@ -847,9 +1204,13 @@ static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem) } -HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail) +HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail, bool &headersError) { + InitBuf(); + _inBufMode = false; + isAvail = true; + headersError = false; if (item.FromLocal) return S_OK; try @@ -863,15 +1224,13 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail) isAvail = false; return S_FALSE; } - IInStream *str2 = Vols.Streams[item.Disk].Stream; - if (!str2) + Stream = Vols.Streams[item.Disk].Stream; + Vols.StreamIndex = item.Disk; + if (!Stream) { isAvail = false; return S_FALSE; } - RINOK(str2->Seek(offset, STREAM_SEEK_SET, NULL)); - Stream = str2; - Vols.StreamIndex = item.Disk; } else { @@ -888,9 +1247,16 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail) isAvail = false; return S_FALSE; } - RINOK(Seek(offset)); } + RINOK(Seek_SavePos(offset)); + + /* + // we can check buf mode + InitBuf(); + _inBufMode = true; + Buffer.AllocAtLeast(1 << 10); + */ CItemEx localItem; if (ReadUInt32() != NSignature::kLocalFileHeader) @@ -900,6 +1266,11 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail) return S_FALSE; item.LocalFullHeaderSize = localItem.LocalFullHeaderSize; item.LocalExtra = localItem.LocalExtra; + if (item.Crc != localItem.Crc && !localItem.HasDescriptor()) + { + item.Crc = localItem.Crc; + headersError = true; + } item.FromLocal = true; } catch(...) { return S_FALSE; } @@ -907,53 +1278,202 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail) } -HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item) +/* +---------- FindDescriptor ---------- + +in: + _streamPos : position in Stream + Stream : + Vols : if (IsMultiVol) + +action: + searches descriptor in input stream(s). + sets + item.DescriptorWasRead = true; + item.Size + item.PackSize + item.Crc + if descriptor was found + +out: + S_OK: + if ( item.DescriptorWasRead) : if descriptor was found + if (!item.DescriptorWasRead) : if descriptor was not found : unexpected end of stream(s) + + S_FALSE: if no items or there is just one item with strange properies that doesn't look like real archive. + + another error code: Callback error. + +exceptions : + CSystemException() : stream reading error +*/ + +HRESULT CInArchive::FindDescriptor(CItemEx &item, unsigned numFiles) { - const unsigned kBufSize = (1 << 12); - Byte buf[kBufSize]; + // const size_t kBufSize = (size_t)1 << 5; // don't increase it too much. It reads data look ahead. + + // Buffer.Alloc(kBufSize); + // Byte *buf = Buffer; - UInt32 numBytesInBuffer = 0; - UInt32 packedSize = 0; + UInt64 packedSize = 0; + UInt64 progressPrev = _cnt; + for (;;) { - UInt32 processedSize; - RINOK(ReadBytes(buf + numBytesInBuffer, kBufSize - numBytesInBuffer, &processedSize)); - numBytesInBuffer += processedSize; - if (numBytesInBuffer < kDataDescriptorSize) - return S_FALSE; + /* appnote specification claims that we must use 64-bit descriptor, if there is zip64 extra. + But some old third-party xps archives used 64-bit descriptor without zip64 extra. */ + // unsigned descriptorSize = kDataDescriptorSize64 + kNextSignatureSize; + + // const unsigned kNextSignatureSize = 0; // we can disable check for next signatuire + const unsigned kNextSignatureSize = 4; // we check also for signature for next File headear + + const unsigned descriptorSize4 = item.GetDescriptorSize() + kNextSignatureSize; + + if (descriptorSize4 > Buffer.Size()) return E_FAIL; + + // size_t processedSize; + CanStartNewVol = true; + RINOK(LookAhead(descriptorSize4)); + const size_t avail = GetAvail(); + + if (avail < descriptorSize4) + { + // we write to packSize all these available bytes. + // later it's simpler to work with such value than with 0 + if (item.PackSize == 0) + item.PackSize = packedSize + avail; + return S_OK; + } + + const Byte * const pStart = Buffer + _bufPos; + const Byte * p = pStart; + const Byte * const limit = pStart + (avail - descriptorSize4); - UInt32 i; - for (i = 0; i <= numBytesInBuffer - kDataDescriptorSize; i++) + for (; p <= limit; p++) { // descriptor signature field is Info-ZIP's extension to pkware Zip specification. // New ZIP specification also allows descriptorSignature. - if (buf[i] != 0x50) + + p = FindPK(p, limit + 1); + if (p > limit) + break; + + /* + if (*p != 0x50) + continue; + */ + + if (Get32(p) != NSignature::kDataDescriptor) continue; - // !!!! It must be fixed for Zip64 archives - if (Get32(buf + i) == NSignature::kDataDescriptor) + + // we check next signatuire after descriptor + // maybe we need check only 2 bytes "PK" instead of 4 bytes, if some another type of header is possible after descriptor + const UInt32 sig = Get32(p + descriptorSize4 - kNextSignatureSize); + if ( sig != NSignature::kLocalFileHeader + && sig != NSignature::kCentralFileHeader) + continue; + + const UInt64 packSizeCur = packedSize + (p - pStart); + if (descriptorSize4 == kDataDescriptorSize64 + kNextSignatureSize) // if (item.LocalExtra.IsZip64) { - UInt32 descriptorPackSize = Get32(buf + i + 8); - if (descriptorPackSize == packedSize + i) - { - item.Crc = Get32(buf + i + 4); - item.PackSize = descriptorPackSize; - item.Size = Get32(buf + i + 12); - bool isFinished; - return IncreaseRealPosition((Int64)(Int32)(0 - (numBytesInBuffer - i - kDataDescriptorSize)), isFinished); - } + const UInt64 descriptorPackSize = Get64(p + 8); + if (descriptorPackSize != packSizeCur) + continue; + item.Size = Get64(p + 16); } + else + { + const UInt32 descriptorPackSize = Get32(p + 8); + if (descriptorPackSize != (UInt32)packSizeCur) + continue; + item.Size = Get32(p + 12); + // that item.Size can be truncated to 32-bit value here + } + // We write calculated 64-bit packSize, even if descriptor64 was not used + item.PackSize = packSizeCur; + + item.DescriptorWasRead = true; + item.Crc = Get32(p + 4); + + const size_t skip = (p - pStart) + descriptorSize4 - kNextSignatureSize; + + SkipLookahed(skip); + + return S_OK; } - packedSize += i; - unsigned j; - for (j = 0; i < numBytesInBuffer; i++, j++) - buf[j] = buf[i]; - numBytesInBuffer = j; + const size_t skip = (p - pStart); + SkipLookahed(skip); + + packedSize += skip; + + if (Callback) + if (_cnt - progressPrev >= ((UInt32)1 << 22)) + { + progressPrev = _cnt; + const UInt64 numFiles64 = numFiles; + RINOK(Callback->SetCompleted(&numFiles64, &_cnt)); + } } } +HRESULT CInArchive::CheckDescriptor(const CItemEx &item) +{ + if (!item.HasDescriptor()) + return S_OK; + + // pkzip's version without descriptor signature is not supported + + bool isFinished = false; + RINOK(IncreaseRealPosition(item.PackSize, isFinished)); + if (isFinished) + return S_FALSE; + + /* + if (!IsMultiVol) + { + RINOK(Seek_SavePos(ArcInfo.Base + item.GetDataPosition() + item.PackSize)); + } + */ + + Byte buf[kDataDescriptorSize64]; + try + { + CanStartNewVol = true; + SafeRead(buf, item.GetDescriptorSize()); + } + catch (const CSystemException &e) { return e.ErrorCode; } + // catch (const CUnexpectEnd &) + catch(...) + { + return S_FALSE; + } + // RINOK(ReadStream_FALSE(Stream, buf, item.GetDescriptorSize())); + + if (Get32(buf) != NSignature::kDataDescriptor) + return S_FALSE; + UInt32 crc = Get32(buf + 4); + UInt64 packSize, unpackSize; + + if (item.LocalExtra.IsZip64) + { + packSize = Get64(buf + 8); + unpackSize = Get64(buf + 16); + } + else + { + packSize = Get32(buf + 8); + unpackSize = Get32(buf + 12); + } + + if (crc != item.Crc || item.PackSize != packSize || item.Size != unpackSize) + return S_FALSE; + return S_OK; +} + + HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item) { if (item.FromLocal) @@ -961,32 +1481,12 @@ HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item) try { bool isAvail = true; - RINOK(ReadLocalItemAfterCdItem(item, isAvail)); + bool headersError = false; + RINOK(ReadLocalItemAfterCdItem(item, isAvail, headersError)); + if (headersError) + return S_FALSE; if (item.HasDescriptor()) - { - // pkzip's version without descriptor is not supported - RINOK(Seek(ArcInfo.Base + item.GetDataPosition() + item.PackSize)); - if (ReadUInt32() != NSignature::kDataDescriptor) - return S_FALSE; - UInt32 crc = ReadUInt32(); - UInt64 packSize, unpackSize; - - /* - if (IsZip64) - { - packSize = ReadUInt64(); - unpackSize = ReadUInt64(); - } - else - */ - { - packSize = ReadUInt32(); - unpackSize = ReadUInt32(); - } - - if (crc != item.Crc || item.PackSize != packSize || item.Size != unpackSize) - return S_FALSE; - } + return CheckDescriptor(item); } catch(...) { return S_FALSE; } return S_OK; @@ -997,7 +1497,7 @@ HRESULT CInArchive::ReadCdItem(CItemEx &item) { item.FromCentral = true; Byte p[kCentralHeaderSize - 4]; - SafeReadBytes(p, kCentralHeaderSize - 4); + SafeRead(p, kCentralHeaderSize - 4); item.MadeByVersion.Version = p[0]; item.MadeByVersion.HostOS = p[1]; @@ -1036,15 +1536,19 @@ HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo) { if (offset >= ((UInt64)1 << 63)) return S_FALSE; - RINOK(Seek(offset)); Byte buf[kEcd64_FullSize]; - RINOK(ReadStream_FALSE(Stream, buf, kEcd64_FullSize)); + RINOK(SeekToVol(Vols.StreamIndex, offset)); + unsigned processed = 0; + ReadFromCache(buf, kEcd64_FullSize, processed); + + if (processed != kEcd64_FullSize) + return S_FALSE; if (Get32(buf) != NSignature::kEcd64) return S_FALSE; UInt64 mainSize = Get64(buf + 4); - if (mainSize < kEcd64_MainSize || mainSize > ((UInt64)1 << 32)) + if (mainSize < kEcd64_MainSize || mainSize > ((UInt64)1 << 40)) return S_FALSE; cdInfo.ParseEcd64e(buf + 12); return S_OK; @@ -1057,27 +1561,49 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode) UInt64 endPos; + // There are no useful data in cache in most cases here. + // So here we don't use cache data from previous operations . + + InitBuf(); RINOK(Stream->Seek(0, STREAM_SEEK_END, &endPos)); + _streamPos = endPos; + + // const UInt32 kBufSizeMax2 = ((UInt32)1 << 16) + kEcdSize + kEcd64Locator_Size + kEcd64_FullSize; + const size_t kBufSizeMax = ((size_t)1 << 17); // must be larger than kBufSizeMax2 - const UInt32 kBufSizeMax = ((UInt32)1 << 16) + kEcdSize + kEcd64Locator_Size + kEcd64_FullSize; - const UInt32 bufSize = (endPos < kBufSizeMax) ? (UInt32)endPos : kBufSizeMax; + const size_t bufSize = (endPos < kBufSizeMax) ? (size_t)endPos : kBufSizeMax; if (bufSize < kEcdSize) return S_FALSE; - CByteArr byteBuffer(bufSize); + // CByteArr byteBuffer(bufSize); + + if (Buffer.Size() < kBufSizeMax) + { + // InitBuf(); + Buffer.AllocAtLeast(kBufSizeMax); + if (!Buffer.IsAllocated()) + return E_OUTOFMEMORY; + } - const UInt64 startPos = endPos - bufSize; - RINOK(Stream->Seek(startPos, STREAM_SEEK_SET, &m_Position)); - if (m_Position != startPos) + RINOK(Seek_SavePos(endPos - bufSize)); + + size_t processed = bufSize; + HRESULT res = ReadStream(Stream, Buffer, &processed); + _streamPos += processed; + _bufCached = processed; + _bufPos = 0; + _cnt += processed; + if (res != S_OK) + return res; + if (processed != bufSize) return S_FALSE; + - RINOK(ReadStream_FALSE(Stream, byteBuffer, bufSize)); - - for (UInt32 i = bufSize - kEcdSize + 1;;) + for (size_t i = bufSize - kEcdSize + 1;;) { if (i == 0) return S_FALSE; - const Byte *buf = byteBuffer; + const Byte *buf = Buffer; for (;;) { @@ -1095,24 +1621,26 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode) if (i >= kEcd64Locator_Size) { - const Byte *locatorPtr = buf + i - kEcd64Locator_Size; - if (Get32(locatorPtr) == NSignature::kEcd64Locator) + const size_t locatorIndex = i - kEcd64Locator_Size; + if (Get32(buf + locatorIndex) == NSignature::kEcd64Locator) { CLocator locator; - locator.Parse(locatorPtr + 4); - if ((cdInfo.ThisDisk == locator.NumDisks - 1 || cdInfo.ThisDisk == 0xFFFF) + locator.Parse(buf + locatorIndex + 4); + if ((cdInfo.ThisDisk == locator.NumDisks - 1 || ZIP64_IS_16_MAX(cdInfo.ThisDisk)) && locator.Ecd64Disk < locator.NumDisks) { - if (locator.Ecd64Disk != cdInfo.ThisDisk && cdInfo.ThisDisk != 0xFFFF) + if (locator.Ecd64Disk != cdInfo.ThisDisk && !ZIP64_IS_16_MAX(cdInfo.ThisDisk)) return E_NOTIMPL; // Most of the zip64 use fixed size Zip64 ECD // we try relative backward reading. UInt64 absEcd64 = endPos - bufSize + i - (kEcd64Locator_Size + kEcd64_FullSize); + + if (locatorIndex >= kEcd64_FullSize) if (checkOffsetMode || absEcd64 == locator.Ecd64Offset) { - const Byte *ecd64 = locatorPtr - kEcd64_FullSize; + const Byte *ecd64 = buf + locatorIndex - kEcd64_FullSize; if (Get32(ecd64) == NSignature::kEcd64) { UInt64 mainEcd64Size = Get64(ecd64 + 4); @@ -1193,42 +1721,25 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdIn { items.Clear(); - ISequentialInStream *stream; - - if (!IsMultiVol) - { - stream = this->StartStream; - Vols.StreamIndex = -1; - RINOK(this->StartStream->Seek(cdOffset, STREAM_SEEK_SET, &m_Position)); - if (m_Position != cdOffset) - return S_FALSE; - } - else - { - if (cdInfo.CdDisk >= Vols.Streams.Size()) - return S_FALSE; - IInStream *str2 = Vols.Streams[cdInfo.CdDisk].Stream; - if (!str2) - return S_FALSE; - RINOK(str2->Seek(cdOffset, STREAM_SEEK_SET, NULL)); - stream = str2; - Vols.NeedSeek = false; - Vols.StreamIndex = cdInfo.CdDisk; - m_Position = cdOffset; - } + RINOK(SeekToVol(IsMultiVol ? cdInfo.CdDisk : -1, cdOffset)); - _inBuffer.SetStream(stream); - - _inBuffer.Init(); _inBufMode = true; + _cnt = 0; - _processedCnt = 0; + if (Callback) + { + RINOK(Callback->SetTotal(&cdInfo.NumEntries, IsMultiVol ? &Vols.TotalBytesSize : NULL)); + } + UInt64 numFileExpected = cdInfo.NumEntries; + const UInt64 *totalFilesPtr = &numFileExpected; + bool isCorrect_NumEntries = (cdInfo.IsFromEcd64 || numFileExpected >= ((UInt32)1 << 16)); - while (_processedCnt < cdSize) + while (_cnt < cdSize) { CanStartNewVol = true; if (ReadUInt32() != NSignature::kCentralFileHeader) return S_FALSE; + CanStartNewVol = false; { CItemEx cdItem; RINOK(ReadCdItem(cdItem)); @@ -1237,13 +1748,24 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdIn if (Callback && (items.Size() & 0xFFF) == 0) { const UInt64 numFiles = items.Size(); - RINOK(Callback->SetCompleted(&numFiles, NULL)); + + if (numFiles > numFileExpected && totalFilesPtr) + { + if (isCorrect_NumEntries) + totalFilesPtr = NULL; + else + while (numFiles > numFileExpected) + numFileExpected += (UInt32)1 << 16; + RINOK(Callback->SetTotal(totalFilesPtr, NULL)); + } + + RINOK(Callback->SetCompleted(&numFiles, &_cnt)); } } CanStartNewVol = true; - return (_processedCnt == cdSize) ? S_OK : S_FALSE; + return (_cnt == cdSize) ? S_OK : S_FALSE; } @@ -1275,11 +1797,12 @@ HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 cdOffset = cdInfo.Offset; cdDisk = cdInfo.CdDisk; - if (Callback) + if (!IsMultiVol) { - RINOK(Callback->SetTotal(&cdInfo.NumEntries, NULL)); + if (cdInfo.ThisDisk != cdInfo.CdDisk) + return S_FALSE; } - + const UInt64 base = (IsMultiVol ? 0 : ArcInfo.Base); res = TryReadCd(items, cdInfo, base + cdOffset, cdSize); @@ -1323,47 +1846,83 @@ static bool IsStrangeItem(const CItem &item) } + +/* + ---------- ReadLocals ---------- + +in: + (_signature == NSignature::kLocalFileHeader) + VirtStreamPos : after _signature : position in Stream + Stream : + Vols : if (IsMultiVol) + (_inBufMode == false) + +action: + it parses local items. + + if ( IsMultiVol) it writes absolute offsets to CItemEx::LocalHeaderPos + if (!IsMultiVol) it writes relative (from ArcInfo.Base) offsets to CItemEx::LocalHeaderPos + later we can correct CItemEx::LocalHeaderPos values, if + some new value for ArcInfo.Base will be detected +out: + S_OK: + (_signature != NSignature::kLocalFileHeade) + _streamPos : after _signature + + S_FALSE: if no items or there is just one item with strange properies that doesn't look like real archive. + + another error code: stream reading error or Callback error. + + CUnexpectEnd() exception : it's not fatal exception here. + It means that reading was interrupted by unexpected end of input stream, + but some CItemEx items were parsed OK. + We can stop further archive parsing. + But we can use all filled CItemEx items. +*/ + HRESULT CInArchive::ReadLocals(CObjectVector<CItemEx> &items) { items.Clear(); + + UInt64 progressPrev = _cnt; - while (m_Signature == NSignature::kLocalFileHeader) + if (Callback) + { + RINOK(Callback->SetTotal(NULL, IsMultiVol ? &Vols.TotalBytesSize : NULL)); + } + + while (_signature == NSignature::kLocalFileHeader) { CItemEx item; - item.LocalHeaderPos = m_Position - 4; - if (!IsMultiVol) - item.LocalHeaderPos -= ArcInfo.MarkerPos; - // we write ralative LocalHeaderPos here. Later we can correct it to real Base. + item.LocalHeaderPos = GetVirtStreamPos() - 4; + if (!IsMultiVol) + item.LocalHeaderPos -= ArcInfo.Base; try { ReadLocalItem(item); item.FromLocal = true; bool isFinished = false; - + if (item.HasDescriptor()) - ReadLocalItemDescriptor(item); + { + RINOK(FindDescriptor(item, items.Size())); + isFinished = !item.DescriptorWasRead; + } else { - /* - if (IsMultiVol) - { - const int kStep = 10000; - RINOK(IncreaseRealPosition(-kStep, isFinished)); - RINOK(IncreaseRealPosition(item.PackSize + kStep, isFinished)); - } - else - */ + if (item.PackSize >= ((UInt64)1 << 62)) + throw CUnexpectEnd(); RINOK(IncreaseRealPosition(item.PackSize, isFinished)); } - + items.Add(item); if (isFinished) throw CUnexpectEnd(); - - m_Signature = ReadUInt32(); + + ReadSignature(); } catch (CUnexpectEnd &) { @@ -1372,17 +1931,18 @@ HRESULT CInArchive::ReadLocals(CObjectVector<CItemEx> &items) throw; } - if (Callback && (items.Size() & 0xFF) == 0) + + if (Callback) + if ((items.Size() & 0xFF) == 0 + || _cnt - progressPrev >= ((UInt32)1 << 22)) { + progressPrev = _cnt; const UInt64 numFiles = items.Size(); - UInt64 numBytes = 0; - // if (!sMultiVol) - numBytes = item.LocalHeaderPos; - RINOK(Callback->SetCompleted(&numFiles, &numBytes)); + RINOK(Callback->SetCompleted(&numFiles, &_cnt)); } } - if (items.Size() == 1 && m_Signature != NSignature::kCentralFileHeader) + if (items.Size() == 1 && _signature != NSignature::kCentralFileHeader) if (IsStrangeItem(items[0])) return S_FALSE; @@ -1402,26 +1962,22 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback) name = prop.bstrVal; } - UString base = name; int dotPos = name.ReverseFind_Dot(); - if (dotPos < 0) return S_OK; - - base.DeleteFrom(dotPos + 1); - const UString ext = name.Ptr(dotPos + 1); + name.DeleteFrom(dotPos + 1); + StartVolIndex = (Int32)(-1); if (ext.IsEmpty()) return S_OK; - else { wchar_t c = ext[0]; IsUpperCase = (c >= 'A' && c <= 'Z'); if (ext.IsEqualTo_Ascii_NoCase("zip")) { - BaseName = base; + BaseName = name; StartIsZ = true; StartIsZip = true; return S_OK; @@ -1429,8 +1985,13 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback) else if (ext.IsEqualTo_Ascii_NoCase("exe")) { StartIsExe = true; - BaseName = base; + BaseName = name; StartVolIndex = 0; + /* sfx-zip can use both arc.exe and arc.zip + We can open arc.zip, if it was requesed to open arc.exe. + But it's possible that arc.exe and arc.zip are not parts of same archive. + So we can disable such operation */ + return S_FALSE; // don't open arc.zip instead of arc.exe } else if (ext[0] == 'z' || ext[0] == 'Z') { @@ -1441,7 +2002,7 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback) if (*end != 0 || volNum < 1 || volNum > ((UInt32)1 << 30)) return S_OK; StartVolIndex = volNum - 1; - BaseName = base; + BaseName = name; StartIsZ = true; } else @@ -1449,9 +2010,11 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback) } UString volName = BaseName; - volName.AddAscii(IsUpperCase ? "ZIP" : "zip"); - HRESULT result = volCallback->GetStream(volName, &ZipStream); - if (result == S_FALSE || !ZipStream) + volName += (IsUpperCase ? "ZIP" : "zip"); + + HRESULT res = volCallback->GetStream(volName, &ZipStream); + + if (res == S_FALSE || !ZipStream) { if (MissingName.IsEmpty()) { @@ -1461,7 +2024,7 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback) return S_OK; } - return result; + return res; } @@ -1493,24 +2056,30 @@ HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback, { UString volName = Vols.BaseName; { - volName += (wchar_t)(Vols.IsUpperCase ? 'Z' : 'z'); + volName += (char)(Vols.IsUpperCase ? 'Z' : 'z'); + unsigned v = i + 1; + if (v < 10) + volName += '0'; + volName.Add_UInt32(v); + } + + HRESULT res = volCallback->GetStream(volName, &stream); + if (res != S_OK && res != S_FALSE) + return res; + if (res == S_FALSE || !stream) + { + if (i == 0) { - char s[32]; - ConvertUInt32ToString(i + 1, s); - unsigned len = (unsigned)strlen(s); - while (len < 2) - { - volName += (wchar_t)'0'; - len++; - } - volName.AddAscii(s); + UString volName_exe = Vols.BaseName; + volName_exe += (Vols.IsUpperCase ? "EXE" : "exe"); + + HRESULT res2 = volCallback->GetStream(volName_exe, &stream); + if (res2 != S_OK && res2 != S_FALSE) + return res2; + res = res2; } } - - HRESULT result = volCallback->GetStream(volName, &stream); - if (result != S_OK && result != S_FALSE) - return result; - if (result == S_FALSE || !stream) + if (res == S_FALSE || !stream) { if (Vols.MissingName.IsEmpty()) Vols.MissingName = volName; @@ -1524,7 +2093,6 @@ HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback, } UInt64 size; - UInt64 pos; RINOK(stream->Seek(0, STREAM_SEEK_CUR, &pos)); RINOK(stream->Seek(0, STREAM_SEEK_END, &size)); @@ -1535,6 +2103,8 @@ HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback, CVols::CSubStreamInfo &ss = Vols.Streams[i]; Vols.NumVols++; + Vols.TotalBytesSize += size; + ss.Stream = stream; ss.Size = size; @@ -1559,11 +2129,11 @@ HRESULT CInArchive::ReadVols() RINOK(Vols.ParseArcName(volCallback)); - int startZIndex = Vols.StartVolIndex; + // const int startZIndex = Vols.StartVolIndex; if (!Vols.StartIsZ) { - // if (!Vols.StartIsExe) + if (!Vols.StartIsExe) return S_OK; } @@ -1573,35 +2143,46 @@ HRESULT CInArchive::ReadVols() if (Vols.StartIsZip) Vols.ZipStream = StartStream; - // bool cdOK = false; - if (Vols.ZipStream) { Stream = Vols.ZipStream; + + if (Vols.StartIsZip) + Vols.StreamIndex = -1; + else + { + Vols.StreamIndex = -2; + InitBuf(); + } + HRESULT res = FindCd(true); + CCdInfo &ecd = Vols.ecd; if (res == S_OK) { zipDisk = ecd.ThisDisk; Vols.ecd_wasRead = true; + + // if is not multivol or bad multivol, we return to main single stream code if (ecd.ThisDisk == 0 || ecd.ThisDisk >= ((UInt32)1 << 30) || ecd.ThisDisk < ecd.CdDisk) return S_OK; + cdDisk = ecd.CdDisk; if (Vols.StartVolIndex < 0) Vols.StartVolIndex = ecd.ThisDisk; + else if ((UInt32)Vols.StartVolIndex >= ecd.ThisDisk) + return S_OK; + // Vols.StartVolIndex = ecd.ThisDisk; // Vols.EndVolIndex = ecd.ThisDisk; unsigned numMissingVols; - if (cdDisk == zipDisk) - { - // cdOK = true; - } - else + if (cdDisk != zipDisk) { + // get volumes required for cd. RINOK(ReadVols2(volCallback, cdDisk, zipDisk, zipDisk, 0, numMissingVols)); - if (numMissingVols == 0) + if (numMissingVols != 0) { // cdOK = false; } @@ -1611,25 +2192,50 @@ HRESULT CInArchive::ReadVols() return res; } - if (Vols.Streams.Size() > 0) - IsMultiVol = true; - if (Vols.StartVolIndex < 0) + { + // is not mutivol; return S_OK; + } + /* + if (!Vols.Streams.IsEmpty()) + IsMultiVol = true; + */ + unsigned numMissingVols; if (cdDisk != 0) { - RINOK(ReadVols2(volCallback, 0, cdDisk < 0 ? -1 : cdDisk, zipDisk, 1 << 10, numMissingVols)); + // get volumes that were no requested still + const unsigned kNumMissingVolsMax = 1 << 12; + RINOK(ReadVols2(volCallback, 0, cdDisk < 0 ? -1 : cdDisk, zipDisk, kNumMissingVolsMax, numMissingVols)); + } + + // if (Vols.StartVolIndex >= 0) + { + if (Vols.Streams.IsEmpty()) + if (Vols.StartVolIndex > (1 << 20)) + return S_OK; + if ((unsigned)Vols.StartVolIndex >= Vols.Streams.Size() + || !Vols.Streams[Vols.StartVolIndex].Stream) + { + // we get volumes starting from StartVolIndex, if they we not requested before know the volume index (if FindCd() was ok) + RINOK(ReadVols2(volCallback, Vols.StartVolIndex, zipDisk, zipDisk, 0, numMissingVols)); + } } if (Vols.ZipStream) { + // if there is no another volumes and volumeIndex is too big, we don't use multivol mode if (Vols.Streams.IsEmpty()) if (zipDisk > (1 << 10)) return S_OK; - RINOK(ReadVols2(volCallback, zipDisk, zipDisk + 1, zipDisk, 0, numMissingVols)); + if (zipDisk >= 0) + { + // we create item in Streams for ZipStream, if we know the volume index (if FindCd() was ok) + RINOK(ReadVols2(volCallback, zipDisk, zipDisk + 1, zipDisk, 0, numMissingVols)); + } } if (!Vols.Streams.IsEmpty()) @@ -1639,11 +2245,14 @@ HRESULT CInArchive::ReadVols() if (cdDisk) IsMultiVol = true; */ + const int startZIndex = Vols.StartVolIndex; if (startZIndex >= 0) { - if (Vols.Streams.Size() >= (unsigned)startZIndex) + // if all volumes before start volume are OK, we can start parsing from 0 + // if there are missing volumes before startZIndex, we start parsing in current startZIndex + if ((unsigned)startZIndex < Vols.Streams.Size()) { - for (unsigned i = 0; i < (unsigned)startZIndex; i++) + for (unsigned i = 0; i <= (unsigned)startZIndex; i++) if (!Vols.Streams[i].Stream) { Vols.StartParsingVol = startZIndex; @@ -1658,10 +2267,6 @@ HRESULT CInArchive::ReadVols() - - - - HRESULT CVols::Read(void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) @@ -1680,7 +2285,7 @@ HRESULT CVols::Read(void *data, UInt32 size, UInt32 *processedSize) return S_FALSE; if (NeedSeek) { - RINOK(s.Stream->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(s.SeekToStart()); NeedSeek = false; } UInt32 realProcessedSize = 0; @@ -1704,47 +2309,112 @@ STDMETHODIMP CVolStream::Read(void *data, UInt32 size, UInt32 *processedSize) -#define COPY_ECD_ITEM_16(n) if (!isZip64 || ecd. n != 0xFFFF) ecd64. n = ecd. n; -#define COPY_ECD_ITEM_32(n) if (!isZip64 || ecd. n != 0xFFFFFFFF) ecd64. n = ecd. n; +#define COPY_ECD_ITEM_16(n) if (!isZip64 || !ZIP64_IS_16_MAX(ecd. n)) cdInfo. n = ecd. n; +#define COPY_ECD_ITEM_32(n) if (!isZip64 || !ZIP64_IS_32_MAX(ecd. n)) cdInfo. n = ecd. n; -HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items) +HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items) { + if (Buffer.Size() < kSeqBufferSize) + { + InitBuf(); + Buffer.AllocAtLeast(kSeqBufferSize); + if (!Buffer.IsAllocated()) + return E_OUTOFMEMORY; + } + + _inBufMode = false; + HRESULT res = S_OK; bool localsWereRead = false; - UInt64 cdSize = 0, cdRelatOffset = 0, cdAbsOffset = 0; + + /* we try to open archive with the following modes: + 1) CD-MODE : fast mode : we read backward ECD and CD, compare CD items with first Local item. + 2) LOCALS-CD-MODE : slow mode, if CD-MODE fails : we sequentially read all Locals and then CD. + Then we read sequentially ECD64, Locator, ECD again at the end. + + - in LOCALS-CD-MODE we use use the following + variables (with real cd properties) to set Base archive offset + and check real cd properties with values from ECD/ECD64. + */ + + UInt64 cdSize = 0; + UInt64 cdRelatOffset = 0; UInt32 cdDisk = 0; - if (!_inBuffer.Create(1 << 15)) - return E_OUTOFMEMORY; + UInt64 cdAbsOffset = 0; // absolute cd offset, for LOCALS-CD-MODE only. - if (!MarkerIsFound) + if (!MarkerIsFound || !MarkerIsSafe) { IsArc = true; res = ReadCd(items, cdDisk, cdRelatOffset, cdSize); if (res == S_OK) - m_Signature = ReadUInt32(); + ReadSignature(); + else if (res != S_FALSE) + return res; } else { - // m_Signature must be kLocalFileHeader or kEcd - // m_Position points to next byte after signature - RINOK(Stream->Seek(m_Position, STREAM_SEEK_SET, NULL)); + // _signature must be kLocalFileHeader or kEcd or kEcd64 + + SeekToVol(ArcInfo.MarkerVolIndex, ArcInfo.MarkerPos2 + 4); + + CanStartNewVol = false; + + if (_signature == NSignature::kEcd64) + { + // UInt64 ecd64Offset = GetVirtStreamPos() - 4; + IsZip64 = true; - _inBuffer.SetStream(Stream); + { + const UInt64 recordSize = ReadUInt64(); + if (recordSize < kEcd64_MainSize) + return S_FALSE; + if (recordSize >= ((UInt64)1 << 62)) + return S_FALSE; + + { + const unsigned kBufSize = kEcd64_MainSize; + Byte buf[kBufSize]; + SafeRead(buf, kBufSize); + CCdInfo cdInfo; + cdInfo.ParseEcd64e(buf); + if (!cdInfo.IsEmptyArc()) + return S_FALSE; + } + + RINOK(Skip64(recordSize - kEcd64_MainSize, 0)); + } + + ReadSignature(); + if (_signature != NSignature::kEcd64Locator) + return S_FALSE; - bool needReadCd = true; + { + const unsigned kBufSize = 16; + Byte buf[kBufSize]; + SafeRead(buf, kBufSize); + CLocator locator; + locator.Parse(buf); + if (!locator.IsEmptyArc()) + return S_FALSE; + } - if (m_Signature == NSignature::kEcd) + ReadSignature(); + if (_signature != NSignature::kEcd) + return S_FALSE; + } + + if (_signature == NSignature::kEcd) { // It must be empty archive or backware archive // we don't support backware archive still const unsigned kBufSize = kEcdSize - 4; Byte buf[kBufSize]; - SafeReadBytes(buf, kBufSize); + SafeRead(buf, kBufSize); CEcd ecd; ecd.Parse(buf); // if (ecd.cdSize != 0) @@ -1753,15 +2423,15 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items) return S_FALSE; ArcInfo.Base = ArcInfo.MarkerPos; - needReadCd = false; IsArc = true; // check it: we need more tests? - RINOK(Stream->Seek(ArcInfo.MarkerPos2 + 4, STREAM_SEEK_SET, &m_Position)); - } - if (needReadCd) + RINOK(SeekToVol(ArcInfo.MarkerVolIndex, ArcInfo.MarkerPos2)); + ReadSignature(); + } + else { CItemEx firstItem; - // try + try { try { @@ -1776,9 +2446,10 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items) IsArc = true; res = ReadCd(items, cdDisk, cdRelatOffset, cdSize); if (res == S_OK) - m_Signature = ReadUInt32(); + ReadSignature(); } - // catch() { res = S_FALSE; } + catch(CUnexpectEnd &) { res = S_FALSE; } + if (res != S_FALSE && res != S_OK) return res; @@ -1812,52 +2483,93 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items) CObjectVector<CItemEx> cdItems; - bool needSetBase = false; + bool needSetBase = false; // we set needSetBase only for LOCALS_CD_MODE unsigned numCdItems = items.Size(); - if (res == S_FALSE) + #ifdef ZIP_SELF_CHECK + res = S_FALSE; // if uncommented, it uses additional LOCALS-CD-MODE mode to check the code + #endif + + if (res != S_OK) { + // ---------- LOCALS-CD-MODE ---------- // CD doesn't match firstItem, - // so we clear items and read Locals. + // so we clear items and read Locals and CD. + items.Clear(); localsWereRead = true; + + // we can use any mode: with buffer and without buffer + // without buffer : skips packed data : fast for big files : slow for small files + // with buffer : reads packed data : slow for big files : fast for small files + _inBufMode = false; - ArcInfo.Base = ArcInfo.MarkerPos; + // _inBufMode = true; - if (IsMultiVol) + InitBuf(); + + ArcInfo.Base = 0; + + if (!MarkerIsFound) { - Vols.StreamIndex = Vols.StartParsingVol; - if (Vols.StartParsingVol >= (int)Vols.Streams.Size()) + if (!IsMultiVol) return S_FALSE; - Stream = Vols.Streams[Vols.StartParsingVol].Stream; - if (!Stream) + if (Vols.StartParsingVol != 0) return S_FALSE; + // if (StartParsingVol == 0) and we didn't find marker, we use default zero marker. + // so we suppose that there is no sfx stub + RINOK(SeekToVol(0, ArcInfo.MarkerPos2)); } + else + { + if (ArcInfo.MarkerPos != 0) + { + /* + If multi-vol or there is (No)Span-marker at start of stream, we set (Base) as 0. + In another caes: + (No)Span-marker is supposed as false positive. So we set (Base) as main marker (MarkerPos2). + The (Base) can be corrected later after ECD reading. + But sfx volume with stub and (No)Span-marker in (!IsMultiVol) mode will have incorrect (Base) here. + */ + ArcInfo.Base = ArcInfo.MarkerPos2; + } + + RINOK(SeekToVol(ArcInfo.MarkerVolIndex, ArcInfo.MarkerPos2)); + } + + _cnt = 0; - RINOK(Stream->Seek(ArcInfo.MarkerPos2, STREAM_SEEK_SET, &m_Position)); - m_Signature = ReadUInt32(); + ReadSignature(); + LocalsWereRead = true; + RINOK(ReadLocals(items)); - if (m_Signature != NSignature::kCentralFileHeader) + if (_signature != NSignature::kCentralFileHeader) { - // if (!UnexpectedEnd) - m_Position -= 4; + // GetVirtStreamPos() - 4 + if (items.IsEmpty()) + return S_FALSE; NoCentralDir = true; HeadersError = true; return S_OK; } _inBufMode = true; - _inBuffer.Init(); - - cdAbsOffset = m_Position - 4; + + cdAbsOffset = GetVirtStreamPos() - 4; cdDisk = Vols.StreamIndex; + #ifdef ZIP_SELF_CHECK + if (!IsMultiVol && _cnt != GetVirtStreamPos() - ArcInfo.MarkerPos2) + return E_FAIL; + #endif + + const UInt64 processedCnt_start = _cnt; + for (;;) { CItemEx cdItem; - CanStartNewVol = true; RINOK(ReadCdItem(cdItem)); @@ -1865,17 +2577,29 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items) if (Callback && (cdItems.Size() & 0xFFF) == 0) { const UInt64 numFiles = items.Size(); - RINOK(Callback->SetCompleted(&numFiles, NULL)); + const UInt64 numBytes = _cnt; + RINOK(Callback->SetCompleted(&numFiles, &numBytes)); } - CanStartNewVol = true; - m_Signature = ReadUInt32(); - if (m_Signature != NSignature::kCentralFileHeader) + ReadSignature(); + if (_signature != NSignature::kCentralFileHeader) break; } - cdSize = (m_Position - 4) - cdAbsOffset; + cdSize = _cnt - processedCnt_start; + + #ifdef ZIP_SELF_CHECK + if (!IsMultiVol) + { + if (_cnt != GetVirtStreamPos() - ArcInfo.MarkerPos2) + return E_FAIL; + if (cdSize != (GetVirtStreamPos() - 4) - cdAbsOffset) + return E_FAIL; + } + #endif + needSetBase = true; numCdItems = cdItems.Size(); + cdRelatOffset = cdAbsOffset - ArcInfo.Base; if (!cdItems.IsEmpty()) { @@ -1886,13 +2610,13 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items) - CCdInfo ecd64; + CCdInfo cdInfo; CLocator locator; bool isZip64 = false; - const UInt64 ecd64AbsOffset = m_Position - 4; + const UInt64 ecd64AbsOffset = GetVirtStreamPos() - 4; int ecd64Disk = -1; - if (m_Signature == NSignature::kEcd64) + if (_signature == NSignature::kEcd64) { ecd64Disk = Vols.StreamIndex; @@ -1900,26 +2624,27 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items) { const UInt64 recordSize = ReadUInt64(); - if (recordSize < kEcd64_MainSize) + if (recordSize < kEcd64_MainSize + || recordSize >= ((UInt64)1 << 62)) { HeadersError = true; return S_OK; } - + { const unsigned kBufSize = kEcd64_MainSize; Byte buf[kBufSize]; - SafeReadBytes(buf, kBufSize); - ecd64.ParseEcd64e(buf); + SafeRead(buf, kBufSize); + cdInfo.ParseEcd64e(buf); } - Skip64(recordSize - kEcd64_MainSize); + RINOK(Skip64(recordSize - kEcd64_MainSize, items.Size())); } - m_Signature = ReadUInt32(); + ReadSignature(); - if (m_Signature != NSignature::kEcd64Locator) + if (_signature != NSignature::kEcd64Locator) { HeadersError = true; return S_OK; @@ -1928,28 +2653,30 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items) { const unsigned kBufSize = 16; Byte buf[kBufSize]; - SafeReadBytes(buf, kBufSize); + SafeRead(buf, kBufSize); locator.Parse(buf); } - m_Signature = ReadUInt32(); + ReadSignature(); } - if (m_Signature != NSignature::kEcd) + if (_signature != NSignature::kEcd) { HeadersError = true; return S_OK; } + CanStartNewVol = false; + // ---------- ECD ---------- CEcd ecd; { const unsigned kBufSize = kEcdSize - 4; Byte buf[kBufSize]; - SafeReadBytes(buf, kBufSize); + SafeRead(buf, kBufSize); ecd.Parse(buf); } @@ -1960,34 +2687,103 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items) COPY_ECD_ITEM_32(Size); COPY_ECD_ITEM_32(Offset); + bool cdOK = true; + + if ((UInt32)cdInfo.Size != (UInt32)cdSize) + { + // return S_FALSE; + cdOK = false; + } + + if (isZip64) + { + if (cdInfo.NumEntries != numCdItems + || cdInfo.Size != cdSize) + { + cdOK = false; + } + } + + if (IsMultiVol) { - if (cdDisk != (int)ecd64.CdDisk) + if (cdDisk != (int)cdInfo.CdDisk) HeadersError = true; } - else if (needSetBase) + else if (needSetBase && cdOK) { + const UInt64 oldBase = ArcInfo.Base; + // localsWereRead == true + // ArcInfo.Base == ArcInfo.MarkerPos2 + // cdRelatOffset == (cdAbsOffset - ArcInfo.Base) + if (isZip64) { if (ecd64Disk == Vols.StartVolIndex) { - ArcInfo.Base = ecd64AbsOffset - locator.Ecd64Offset; - // cdRelatOffset = ecd64.Offset; - needSetBase = false; + const Int64 newBase = (Int64)ecd64AbsOffset - locator.Ecd64Offset; + if (newBase <= (Int64)ecd64AbsOffset) + { + if (!localsWereRead || newBase <= (Int64)ArcInfo.MarkerPos2) + { + ArcInfo.Base = newBase; + cdRelatOffset = cdAbsOffset - newBase; + } + else + cdOK = false; + } } } - else + else if (numCdItems != 0) // we can't use ecd.Offset in empty archive? { if ((int)cdDisk == Vols.StartVolIndex) { - ArcInfo.Base = cdAbsOffset - ecd64.Offset; - cdRelatOffset = ecd64.Offset; - needSetBase = false; + const Int64 newBase = (Int64)cdAbsOffset - cdInfo.Offset; + if (newBase <= (Int64)cdAbsOffset) + { + if (!localsWereRead || newBase <= (Int64)ArcInfo.MarkerPos2) + { + // cd can be more accurate, when it points before Locals + // so we change Base and cdRelatOffset + ArcInfo.Base = newBase; + cdRelatOffset = cdInfo.Offset; + } + else + { + // const UInt64 delta = ((UInt64)cdRelatOffset - cdInfo.Offset); + const UInt64 delta = ((UInt64)(newBase - ArcInfo.Base)); + if ((UInt32)delta == 0) + { + // we set Overflow32bit mode, only if there is (x<<32) offset + // between real_CD_offset_from_MarkerPos and CD_Offset_in_ECD. + // Base and cdRelatOffset unchanged + Overflow32bit = true; + } + else + cdOK = false; + } + } + else + cdOK = false; + } + } + // cdRelatOffset = cdAbsOffset - ArcInfo.Base; + + if (localsWereRead) + { + const UInt64 delta = oldBase - ArcInfo.Base; + if (delta != 0) + { + FOR_VECTOR (i, items) + items[i].LocalHeaderPos += delta; } } } - EcdVolIndex = ecd64.ThisDisk; + if (!cdOK) + HeadersError = true; + + EcdVolIndex = cdInfo.ThisDisk; if (!IsMultiVol) { @@ -1997,54 +2793,80 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items) Vols.MissingZip = false; } - UseDisk_in_SingleVol = true; - if (localsWereRead) { - if ((UInt64)ArcInfo.Base != ArcInfo.MarkerPos) - { - const UInt64 delta = ArcInfo.MarkerPos - ArcInfo.Base; - FOR_VECTOR (i, items) - items[i].LocalHeaderPos += delta; - } - if (EcdVolIndex != 0) { FOR_VECTOR (i, items) items[i].Disk = EcdVolIndex; } } + + UseDisk_in_SingleVol = true; } if (isZip64) { - if (ecd64.ThisDisk == 0 && ecd64AbsOffset != ArcInfo.Base + locator.Ecd64Offset - // || ecd64.NumEntries_in_ThisDisk != numCdItems - || ecd64.NumEntries != numCdItems - || ecd64.Size != cdSize - || (ecd64.Offset != cdRelatOffset && !items.IsEmpty())) + if (cdInfo.ThisDisk == 0 && ecd64AbsOffset != ArcInfo.Base + locator.Ecd64Offset + // || cdInfo.NumEntries_in_ThisDisk != numCdItems + || cdInfo.NumEntries != numCdItems + || cdInfo.Size != cdSize + || (cdInfo.Offset != cdRelatOffset && !items.IsEmpty())) { HeadersError = true; return S_OK; } } - // ---------- merge Central Directory Items ---------- - - if (!cdItems.IsEmpty()) + if (cdOK && !cdItems.IsEmpty()) { - CObjectVector<CItemEx> items2; + // ---------- merge Central Directory Items ---------- + + CRecordVector<unsigned> items2; + + int nextLocalIndex = 0; + + LocalsCenterMerged = true; FOR_VECTOR (i, cdItems) { + if (Callback) + if ((i & 0x3FFF) == 0) + { + const UInt64 numFiles64 = items.Size() + items2.Size(); + RINOK(Callback->SetCompleted(&numFiles64, &_cnt)); + } + const CItemEx &cdItem = cdItems[i]; - int index = FindItem(items, cdItem); + + int index = -1; + + if (nextLocalIndex != -1) + { + if ((unsigned)nextLocalIndex < items.Size()) + { + CItemEx &item = items[nextLocalIndex]; + if (item.Disk == cdItem.Disk && + (item.LocalHeaderPos == cdItem.LocalHeaderPos + || Overflow32bit && (UInt32)item.LocalHeaderPos == cdItem.LocalHeaderPos)) + index = nextLocalIndex++; + else + nextLocalIndex = -1; + } + } + + if (index == -1) + index = FindItem(items, cdItem); + + // index = -1; + if (index == -1) { - items2.Add(cdItem); + items2.Add(i); HeadersError = true; continue; } + CItemEx &item = items[index]; if (item.Name != cdItem.Name // || item.Name.Len() != cdItem.Name.Len() @@ -2067,10 +2889,10 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items) item.FromCentral = cdItem.FromCentral; } - items += items2; + FOR_VECTOR (k, items2) + items.Add(cdItems[items2[k]]); } - if (ecd.NumEntries < ecd.NumEntries_in_ThisDisk) HeadersError = true; @@ -2083,35 +2905,56 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items) } } - if (ecd.NumEntries > items.Size()) - HeadersError = true; - if (isZip64) { - if (ecd64.NumEntries != items.Size()) + if (cdInfo.NumEntries != items.Size() + || ecd.NumEntries != items.Size() && ecd.NumEntries != 0xFFFF) HeadersError = true; } else { // old 7-zip could store 32-bit number of CD items to 16-bit field. - /* - if ((UInt16)ecd64.NumEntries == (UInt16)items.Size()) + // if (ecd.NumEntries != items.Size()) + if (ecd.NumEntries > items.Size()) HeadersError = true; - */ + + if (cdInfo.NumEntries != numCdItems) + { + if ((UInt16)cdInfo.NumEntries != (UInt16)numCdItems) + HeadersError = true; + else + Cd_NumEntries_Overflow_16bit = true; + } } ReadBuffer(ArcInfo.Comment, ecd.CommentSize); + _inBufMode = false; - _inBuffer.Free(); - if ((UInt16)ecd64.NumEntries != (UInt16)numCdItems - || (UInt32)ecd64.Size != (UInt32)cdSize - || ((UInt32)ecd64.Offset != (UInt32)cdRelatOffset && !items.IsEmpty())) + // DisableBufMode(); + // Buffer.Free(); + /* we can't clear buf varibles. we need them to calculate PhySize of archive */ + + if ((UInt16)cdInfo.NumEntries != (UInt16)numCdItems + || (UInt32)cdInfo.Size != (UInt32)cdSize + || ((UInt32)cdInfo.Offset != (UInt32)cdRelatOffset && !items.IsEmpty())) { // return S_FALSE; HeadersError = true; } - + + #ifdef ZIP_SELF_CHECK + if (localsWereRead) + { + const UInt64 endPos = ArcInfo.MarkerPos2 + _cnt; + if (endPos != (IsMultiVol ? Vols.TotalBytesSize : ArcInfo.FileEndPos)) + { + // there are some data after the end of archive or error in code; + return E_FAIL; + } + } + #endif + // printf("\nOpen OK"); return S_OK; } @@ -2121,40 +2964,47 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items) HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit, IArchiveOpenCallback *callback, CObjectVector<CItemEx> &items) { - _inBufMode = false; items.Clear(); Close(); - ArcInfo.Clear(); UInt64 startPos; RINOK(stream->Seek(0, STREAM_SEEK_CUR, &startPos)); RINOK(stream->Seek(0, STREAM_SEEK_END, &ArcInfo.FileEndPos)); - m_Position = ArcInfo.FileEndPos; + _streamPos = ArcInfo.FileEndPos; StartStream = stream; + Stream = stream; Callback = callback; + + DisableBufMode(); bool volWasRequested = false; if (callback && (startPos == 0 || !searchLimit || *searchLimit != 0)) { + // we try to read volumes only if it's first call (offset == 0) or scan is allowed. volWasRequested = true; RINOK(ReadVols()); } - if (IsMultiVol && Vols.StartVolIndex != 0) + if (IsMultiVol && Vols.StartParsingVol == 0 && (unsigned)Vols.StartParsingVol < Vols.Streams.Size()) { - Stream = Vols.Streams[0].Stream; - if (Stream) + // only StartParsingVol = 0 is safe search. + RINOK(SeekToVol(0, 0)); + // if (Stream) { - m_Position = 0; - RINOK(Stream->Seek(0, STREAM_SEEK_SET, NULL)); - UInt64 limit = 0; - HRESULT res = FindMarker(Stream, &limit); + // UInt64 limit = 1 << 22; // for sfx + UInt64 limit = 0; // without sfx + + HRESULT res = FindMarker(&limit); + if (res == S_OK) + { MarkerIsFound = true; + MarkerIsSafe = true; + } else if (res != S_FALSE) return res; } @@ -2162,56 +3012,93 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit, else { // printf("\nOpen offset = %u\n", (unsigned)startPos); - RINOK(stream->Seek(startPos, STREAM_SEEK_SET, NULL)); - m_Position = startPos; - HRESULT res = FindMarker(stream, searchLimit); - UInt64 curPos = m_Position; + if (IsMultiVol && (unsigned)Vols.StartParsingVol < Vols.Streams.Size() && Vols.Streams[Vols.StartParsingVol].Stream) + { + RINOK(SeekToVol(Vols.StartParsingVol, Vols.StreamIndex == Vols.StartVolIndex ? startPos : 0)); + } + else + { + RINOK(SeekToVol(-1, startPos)); + } + + // UInt64 limit = 1 << 22; + // HRESULT res = FindMarker(&limit); + + HRESULT res = FindMarker(searchLimit); + + // const UInt64 curPos = GetVirtStreamPos(); + const UInt64 curPos = ArcInfo.MarkerPos2 + 4; + if (res == S_OK) MarkerIsFound = true; - else + else if (!IsMultiVol) { - // if (res != S_FALSE) + /* + // if (startPos != 0), probably CD copuld be already tested with another call with (startPos == 0). + // so we don't want to try to open CD again in that ase. + if (startPos != 0) + return res; + // we can try to open CD, if there is no Marker and (startPos == 0). + // is it OK to open such files as ZIP, or big number of false positive, when CD can be find in end of file ? + */ return res; } - - MarkerIsFound = true; if (ArcInfo.IsSpanMode && !volWasRequested) { RINOK(ReadVols()); + if (IsMultiVol && MarkerIsFound && ArcInfo.MarkerVolIndex < 0) + ArcInfo.MarkerVolIndex = Vols.StartVolIndex; } + + MarkerIsSafe = !IsMultiVol + || (ArcInfo.MarkerVolIndex == 0 && ArcInfo.MarkerPos == 0) + ; - if (IsMultiVol && (unsigned)Vols.StartVolIndex < Vols.Streams.Size()) + + if (IsMultiVol) { - Stream = Vols.Streams[Vols.StartVolIndex].Stream; - if (!Stream) - IsMultiVol = false; - else + if ((unsigned)Vols.StartVolIndex < Vols.Streams.Size()) { - RINOK(Stream->Seek(curPos, STREAM_SEEK_SET, NULL)); - m_Position = curPos; + Stream = Vols.Streams[Vols.StartVolIndex].Stream; + if (Stream) + { + RINOK(Seek_SavePos(curPos)); + } + else + IsMultiVol = false; } + else + IsMultiVol = false; } - else - IsMultiVol = false; if (!IsMultiVol) { - RINOK(stream->Seek(curPos, STREAM_SEEK_SET, NULL)); - m_Position = curPos; + if (Vols.StreamIndex != -1) + { + Stream = StartStream; + Vols.StreamIndex = -1; + InitBuf(); + RINOK(Seek_SavePos(curPos)); + } + + ArcInfo.MarkerVolIndex = -1; StreamRef = stream; Stream = stream; } } + if (!IsMultiVol) + Vols.ClearRefs(); + { HRESULT res; try { - res = ReadHeaders2(items); + res = ReadHeaders(items); } - catch (const CInBufferException &e) { res = e.ErrorCode; } + catch (const CSystemException &e) { res = e.ErrorCode; } catch (const CUnexpectEnd &) { if (items.IsEmpty()) @@ -2221,7 +3108,7 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit, } catch (...) { - _inBufMode = false; + DisableBufMode(); throw; } @@ -2229,16 +3116,17 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit, { ArcInfo.FinishPos = ArcInfo.FileEndPos; if ((unsigned)Vols.StreamIndex < Vols.Streams.Size()) - if (m_Position < Vols.Streams[Vols.StreamIndex].Size) + if (GetVirtStreamPos() < Vols.Streams[Vols.StreamIndex].Size) ArcInfo.ThereIsTail = true; } else { - ArcInfo.FinishPos = m_Position; - ArcInfo.ThereIsTail = (ArcInfo.FileEndPos > m_Position); + ArcInfo.FinishPos = GetVirtStreamPos(); + ArcInfo.ThereIsTail = (ArcInfo.FileEndPos > ArcInfo.FinishPos); } - _inBufMode = false; + DisableBufMode(); + IsArcOpen = true; if (!IsMultiVol) Vols.Streams.Clear(); diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h index 9b0afe28..a312c36a 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.h +++ b/CPP/7zip/Archive/Zip/ZipIn.h @@ -3,12 +3,11 @@ #ifndef __ZIP_IN_H #define __ZIP_IN_H +#include "../../../Common/MyBuffer2.h" #include "../../../Common/MyCom.h" #include "../../IStream.h" -#include "../../Common/InBuffer.h" - #include "ZipHeader.h" #include "ZipItem.h" @@ -22,8 +21,12 @@ class CItemEx: public CItem public: UInt32 LocalFullHeaderSize; // including Name and Extra + bool DescriptorWasRead; + + CItemEx(): DescriptorWasRead(false) {} + UInt64 GetLocalFullSize() const - { return LocalFullHeaderSize + PackSize + (HasDescriptor() ? kDataDescriptorSize : 0); } + { return LocalFullHeaderSize + GetPackSizeWithDescriptor(); } UInt64 GetDataPosition() const { return LocalHeaderPos + LocalFullHeaderSize; } }; @@ -52,6 +55,10 @@ struct CInArchiveInfo UInt64 FirstItemRelatOffset; /* Relative offset of first local (read from cd) (relative to Base). = 0 in most archives = size of stub for some SFXs */ + + + int MarkerVolIndex; + bool CdWasRead; bool IsSpanMode; bool ThereIsTail; @@ -68,6 +75,7 @@ struct CInArchiveInfo FinishPos(0), FileEndPos(0), FirstItemRelatOffset(0), + MarkerVolIndex(-1), CdWasRead(false), IsSpanMode(false), ThereIsTail(false) @@ -82,6 +90,7 @@ struct CInArchiveInfo MarkerPos2 = 0; FinishPos = 0; FileEndPos = 0; + MarkerVolIndex = -1; ThereIsTail = false; FirstItemRelatOffset = 0; @@ -96,6 +105,10 @@ struct CInArchiveInfo struct CCdInfo { + bool IsFromEcd64; + + UInt16 CommentSize; + // 64 UInt16 VersionMade; UInt16 VersionNeedExtract; @@ -108,39 +121,55 @@ struct CCdInfo UInt64 Size; UInt64 Offset; - UInt16 CommentSize; - - CCdInfo() { memset(this, 0, sizeof(*this)); } + CCdInfo() { memset(this, 0, sizeof(*this)); IsFromEcd64 = false; } void ParseEcd32(const Byte *p); // (p) includes signature void ParseEcd64e(const Byte *p); // (p) exclude signature + + bool IsEmptyArc() const + { + return ThisDisk == 0 + && CdDisk == 0 + && NumEntries_in_ThisDisk == 0 + && NumEntries == 0 + && Size == 0 + && Offset == 0 // test it + ; + } }; -class CVols +struct CVols { -public: - struct CSubStreamInfo { CMyComPtr<IInStream> Stream; UInt64 Size; + HRESULT SeekToStart() const { return Stream->Seek(0, STREAM_SEEK_SET, NULL); } + CSubStreamInfo(): Size(0) {} }; CObjectVector<CSubStreamInfo> Streams; - int StreamIndex; + + int StreamIndex; // -1 for StartStream + // -2 for ZipStream at multivol detection code + // >=0 volume index in multivol + bool NeedSeek; - CMyComPtr<IInStream> ZipStream; - bool StartIsExe; // is .exe bool StartIsZ; // is .zip or .zNN bool StartIsZip; // is .zip bool IsUpperCase; bool MissingZip; - Int32 StartVolIndex; // = (NN - 1), if StartStream is .zNN + + bool ecd_wasRead; + + Int32 StartVolIndex; // -1, if unknown vol index + // = (NN - 1), if StartStream is .zNN + // = 0, if start vol is exe Int32 StartParsingVol; // if we need local parsing, we must use that stream unsigned NumVols; @@ -148,19 +177,27 @@ public: int EndVolIndex; // index of last volume (ecd volume), // -1, if is not multivol - UString BaseName; // including '.' - + UString BaseName; // name of archive including '.' UString MissingName; + CMyComPtr<IInStream> ZipStream; + CCdInfo ecd; - bool ecd_wasRead; + + UInt64 TotalBytesSize; // for MultiVol only + + void ClearRefs() + { + Streams.Clear(); + ZipStream.Release(); + TotalBytesSize = 0; + } void Clear() { StreamIndex = -1; NeedSeek = false; - StartIsExe = false; StartIsZ = false; StartIsZip = false; @@ -177,21 +214,12 @@ public: MissingZip = false; ecd_wasRead = false; - Streams.Clear(); - ZipStream.Release(); + ClearRefs(); } HRESULT ParseArcName(IArchiveOpenVolumeCallback *volCallback); HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); - - UInt64 GetTotalSize() const - { - UInt64 total = 0; - FOR_VECTOR (i, Streams) - total += Streams[i].Size; - return total; - } }; @@ -210,44 +238,69 @@ public: class CInArchive { - CInBuffer _inBuffer; + CMidBuffer Buffer; + size_t _bufPos; + size_t _bufCached; + + UInt64 _streamPos; + UInt64 _cnt; + + size_t GetAvail() const { return _bufCached - _bufPos; } + + void InitBuf() { _bufPos = 0; _bufCached = 0; } + void DisableBufMode() { InitBuf(); _inBufMode = false; } + + void SkipLookahed(size_t skip) + { + _bufPos += skip; + _cnt += skip; + } + + UInt64 GetVirtStreamPos() { return _streamPos - _bufCached + _bufPos; } + bool _inBufMode; - UInt32 m_Signature; - UInt64 m_Position; - UInt64 _processedCnt; - + bool IsArcOpen; bool CanStartNewVol; + UInt32 _signature; + CMyComPtr<IInStream> StreamRef; IInStream *Stream; IInStream *StartStream; + IArchiveOpenCallback *Callback; - bool IsArcOpen; + HRESULT Seek_SavePos(UInt64 offset); + HRESULT SeekToVol(int volIndex, UInt64 offset); + + HRESULT ReadFromCache(Byte *data, unsigned size, unsigned &processed); HRESULT ReadVols2(IArchiveOpenVolumeCallback *volCallback, unsigned start, int lastDisk, int zipDisk, unsigned numMissingVolsMax, unsigned &numMissingVols); HRESULT ReadVols(); - HRESULT Seek(UInt64 offset); - HRESULT FindMarker(IInStream *stream, const UInt64 *searchLimit); - HRESULT IncreaseRealPosition(Int64 addValue, bool &isFinished); + HRESULT FindMarker(const UInt64 *searchLimit); + HRESULT IncreaseRealPosition(UInt64 addValue, bool &isFinished); - HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize); - void SafeReadBytes(void *data, unsigned size); + HRESULT LookAhead(size_t minRequiredInBuffer); + void SafeRead(Byte *data, unsigned size); void ReadBuffer(CByteBuffer &buffer, unsigned size); - Byte ReadByte(); - UInt16 ReadUInt16(); + // Byte ReadByte(); + // UInt16 ReadUInt16(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); - void Skip(unsigned num); - void Skip64(UInt64 num); - void ReadFileName(unsigned nameSize, AString &dest); - bool ReadExtra(unsigned extraSize, CExtraBlock &extraBlock, - UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber); + void ReadSignature(); + + void Skip(size_t num); + HRESULT Skip64(UInt64 num, unsigned numFiles); + + bool ReadFileName(unsigned nameSize, AString &dest); + + bool ReadExtra(unsigned extraSize, CExtraBlock &extra, + UInt64 &unpackSize, UInt64 &packSize, UInt64 &localOffset, UInt32 &disk); bool ReadLocalItem(CItemEx &item); - HRESULT ReadLocalItemDescriptor(CItemEx &item); + HRESULT FindDescriptor(CItemEx &item, unsigned numFiles); HRESULT ReadCdItem(CItemEx &item); HRESULT TryEcd64(UInt64 offset, CCdInfo &cdInfo); HRESULT FindCd(bool checkOffsetMode); @@ -255,21 +308,28 @@ class CInArchive HRESULT ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 &cdOffset, UInt64 &cdSize); HRESULT ReadLocals(CObjectVector<CItemEx> &localItems); - HRESULT ReadHeaders2(CObjectVector<CItemEx> &items); + HRESULT ReadHeaders(CObjectVector<CItemEx> &items); HRESULT GetVolStream(unsigned vol, UInt64 pos, CMyComPtr<ISequentialInStream> &stream); + public: CInArchiveInfo ArcInfo; bool IsArc; bool IsZip64; + bool HeadersError; bool HeadersWarning; bool ExtraMinorError; bool UnexpectedEnd; + bool LocalsWereRead; + bool LocalsCenterMerged; bool NoCentralDir; + bool Overflow32bit; // = true, if zip without Zip64 extension support and it has some fields values truncated to 32-bits. + bool Cd_NumEntries_Overflow_16bit; // = true, if no Zip64 and 16-bit ecd:NumEntries was overflowed. bool MarkerIsFound; + bool MarkerIsSafe; bool IsMultiVol; bool UseDisk_in_SingleVol; @@ -277,9 +337,7 @@ public: CVols Vols; - IArchiveOpenCallback *Callback; - - CInArchive(): Stream(NULL), Callback(NULL), IsArcOpen(false) {} + CInArchive(): Stream(NULL), StartStream(NULL), Callback(NULL), IsArcOpen(false) {} UInt64 GetPhySize() const { @@ -301,7 +359,6 @@ public: void ClearRefs(); void Close(); HRESULT Open(IInStream *stream, const UInt64 *searchLimit, IArchiveOpenCallback *callback, CObjectVector<CItemEx> &items); - HRESULT ReadHeaders(CObjectVector<CItemEx> &items); bool IsOpen() const { return IsArcOpen; } @@ -329,7 +386,8 @@ public: } - HRESULT ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail); + HRESULT CheckDescriptor(const CItemEx &item); + HRESULT ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail, bool &headersError); HRESULT ReadLocalItemAfterCdItemFull(CItemEx &item); HRESULT GetItemStream(const CItemEx &item, bool seekPackData, CMyComPtr<ISequentialInStream> &stream); diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp index e732df7c..4fc59f79 100644 --- a/CPP/7zip/Archive/Zip/ZipItem.cpp +++ b/CPP/7zip/Archive/Zip/ZipItem.cpp @@ -5,9 +5,12 @@ #include "../../../../C/CpuArch.h" #include "../../../../C/7zCrc.h" +#include "../../../Common/IntToString.h" #include "../../../Common/MyLinux.h" #include "../../../Common/StringConvert.h" +#include "../../../Windows/PropVariantUtils.h" + #include "../Common/ItemNameUtils.h" #include "ZipItem.h" @@ -17,6 +20,62 @@ namespace NZip { using namespace NFileHeader; +static const CUInt32PCharPair g_ExtraTypes[] = +{ + { NExtraID::kZip64, "Zip64" }, + { NExtraID::kNTFS, "NTFS" }, + { NExtraID::kStrongEncrypt, "StrongCrypto" }, + { NExtraID::kUnixTime, "UT" }, + { NExtraID::kUnixExtra, "UX" }, + { NExtraID::kIzUnicodeComment, "uc" }, + { NExtraID::kIzUnicodeName, "up" }, + { NExtraID::kWzAES, "WzAES" } +}; + +void CExtraSubBlock::PrintInfo(AString &s) const +{ + for (unsigned i = 0; i < ARRAY_SIZE(g_ExtraTypes); i++) + { + const CUInt32PCharPair &pair = g_ExtraTypes[i]; + if (pair.Value == ID) + { + s += pair.Name; + return; + } + } + { + char sz[32]; + sz[0] = '0'; + sz[1] = 'x'; + ConvertUInt32ToHex(ID, sz + 2); + s += sz; + } +} + + +void CExtraBlock::PrintInfo(AString &s) const +{ + if (Error) + s.Add_OptSpaced("Extra_ERROR"); + + if (MinorError) + s.Add_OptSpaced("Minor_Extra_ERROR"); + + if (IsZip64 || IsZip64_Error) + { + s.Add_OptSpaced("Zip64"); + if (IsZip64_Error) + s += "_ERROR"; + } + + FOR_VECTOR (i, SubBlocks) + { + s.Add_Space_if_NotEmpty(); + SubBlocks[i].PrintInfo(s); + } +} + + bool CExtraSubBlock::ExtractNtfsTime(unsigned index, FILETIME &ft) const { ft.dwHighDateTime = ft.dwLowDateTime = 0; @@ -83,6 +142,19 @@ bool CExtraSubBlock::ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res } +bool CExtraSubBlock::ExtractUnixExtraTime(unsigned index, UInt32 &res) const +{ + res = 0; + const size_t size = Data.Size(); + unsigned offset = index * 4; + if (ID != NExtraID::kUnixExtra || size < offset + 4) + return false; + const Byte *p = (const Byte *)Data + offset; + res = GetUi32(p); + return true; +} + + bool CExtraBlock::GetNtfsTime(unsigned index, FILETIME &ft) const { FOR_VECTOR (i, SubBlocks) @@ -96,11 +168,29 @@ bool CExtraBlock::GetNtfsTime(unsigned index, FILETIME &ft) const bool CExtraBlock::GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const { - FOR_VECTOR (i, SubBlocks) { - const CExtraSubBlock &sb = SubBlocks[i]; - if (sb.ID == NFileHeader::NExtraID::kUnixTime) - return sb.ExtractUnixTime(isCentral, index, res); + FOR_VECTOR (i, SubBlocks) + { + const CExtraSubBlock &sb = SubBlocks[i]; + if (sb.ID == NFileHeader::NExtraID::kUnixTime) + return sb.ExtractUnixTime(isCentral, index, res); + } + } + + switch (index) + { + case NUnixTime::kMTime: index = NUnixExtra::kMTime; break; + case NUnixTime::kATime: index = NUnixExtra::kATime; break; + default: return false; + } + + { + FOR_VECTOR (i, SubBlocks) + { + const CExtraSubBlock &sb = SubBlocks[i]; + if (sb.ID == NFileHeader::NExtraID::kUnixExtra) + return sb.ExtractUnixExtraTime(index, res); + } } return false; } diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h index c134ec79..0cf9bd09 100644 --- a/CPP/7zip/Archive/Zip/ZipItem.h +++ b/CPP/7zip/Archive/Zip/ZipItem.h @@ -22,11 +22,12 @@ struct CVersion struct CExtraSubBlock { - UInt16 ID; + UInt32 ID; CByteBuffer Data; bool ExtractNtfsTime(unsigned index, FILETIME &ft) const; bool ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const; + bool ExtractUnixExtraTime(unsigned index, UInt32 &res) const; bool ExtractIzUnicode(UInt32 crc, AString &name) const { @@ -44,6 +45,8 @@ struct CExtraSubBlock return false; return CheckUTF8(name, false); } + + void PrintInfo(AString &s) const; }; const unsigned k_WzAesExtra_Size = 7; @@ -129,11 +132,22 @@ struct CStrongCryptoExtra bool CertificateIsUsed() const { return (Flags > 0x0001); } }; + struct CExtraBlock { CObjectVector<CExtraSubBlock> SubBlocks; + bool Error; + bool MinorError; + bool IsZip64; + bool IsZip64_Error; - void Clear() { SubBlocks.Clear(); } + CExtraBlock(): Error(false), MinorError(false), IsZip64(false), IsZip64_Error(false) {} + + void Clear() + { + SubBlocks.Clear(); + IsZip64 = false; + } size_t GetSize() const { @@ -176,6 +190,8 @@ struct CExtraBlock bool GetNtfsTime(unsigned index, FILETIME &ft) const; bool GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const; + void PrintInfo(AString &s) const; + void RemoveUnknownSubBlocks() { for (unsigned i = SubBlocks.Size(); i != 0;) @@ -206,12 +222,19 @@ public: CExtraBlock LocalExtra; + unsigned GetDescriptorSize() const { return LocalExtra.IsZip64 ? kDataDescriptorSize64 : kDataDescriptorSize32; } + + UInt64 GetPackSizeWithDescriptor() const + { return PackSize + (HasDescriptor() ? GetDescriptorSize() : 0); } + 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 IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; } bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; } + + unsigned GetDeflateLevel() const { return (Flags >> 1) & 3; } bool IsDir() const; diff --git a/CPP/7zip/Archive/Zip/ZipOut.cpp b/CPP/7zip/Archive/Zip/ZipOut.cpp index 2a1ba2c4..1fdc24f8 100644 --- a/CPP/7zip/Archive/Zip/ZipOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipOut.cpp @@ -21,48 +21,20 @@ HRESULT COutArchive::Create(IOutStream *outStream) return m_Stream->Seek(0, STREAM_SEEK_CUR, &m_Base); } -void COutArchive::MoveCurPos(UInt64 distanceToMove) -{ - m_CurPos += distanceToMove; // test overflow -} - -void COutArchive::SeekToRelatPos(UInt64 offset) +void COutArchive::SeekToCurPos() { - HRESULT res = m_Stream->Seek(m_Base + offset, STREAM_SEEK_SET, NULL); + HRESULT res = m_Stream->Seek(m_Base + m_CurPos, STREAM_SEEK_SET, NULL); if (res != S_OK) throw CSystemException(res); } -void COutArchive::PrepareWriteCompressedDataZip64(unsigned fileNameLen, bool isZip64, bool aesEncryption) -{ - m_IsZip64 = isZip64; - m_ExtraSize = isZip64 ? (4 + 8 + 8) : 0; - if (aesEncryption) - m_ExtraSize += 4 + k_WzAesExtra_Size; - m_LocalFileHeaderSize = kLocalHeaderSize + fileNameLen + m_ExtraSize; -} - -void COutArchive::PrepareWriteCompressedData(unsigned fileNameLen, UInt64 unPackSize, bool aesEncryption) -{ - // We use Zip64, if unPackSize size is larger than 0xF8000000 to support - // cases when compressed size can be about 3% larger than uncompressed size - - PrepareWriteCompressedDataZip64(fileNameLen, unPackSize >= (UInt32)0xF8000000, aesEncryption); -} - #define DOES_NEED_ZIP64(v) (v >= (UInt32)0xFFFFFFFF) +// #define DOES_NEED_ZIP64(v) (v >= 0) -void COutArchive::PrepareWriteCompressedData2(unsigned fileNameLen, UInt64 unPackSize, UInt64 packSize, bool aesEncryption) -{ - bool isZip64 = - DOES_NEED_ZIP64(unPackSize) || - DOES_NEED_ZIP64(packSize); - PrepareWriteCompressedDataZip64(fileNameLen, isZip64, aesEncryption); -} -void COutArchive::WriteBytes(const void *buffer, UInt32 size) +void COutArchive::WriteBytes(const void *data, size_t size) { - m_OutBuffer.WriteBytes(buffer, size); + m_OutBuffer.WriteBytes(data, size); m_CurPos += size; } @@ -74,11 +46,8 @@ void COutArchive::Write8(Byte b) void COutArchive::Write16(UInt16 val) { - for (int i = 0; i < 2; i++) - { - Write8((Byte)val); - val >>= 8; - } + Write8((Byte)val); + Write8((Byte)(val >> 8)); } void COutArchive::Write32(UInt32 val) @@ -101,15 +70,12 @@ void COutArchive::Write64(UInt64 val) void COutArchive::WriteExtra(const CExtraBlock &extra) { - if (extra.SubBlocks.Size() != 0) + FOR_VECTOR (i, extra.SubBlocks) { - FOR_VECTOR (i, extra.SubBlocks) - { - const CExtraSubBlock &subBlock = extra.SubBlocks[i]; - Write16(subBlock.ID); - Write16((UInt16)subBlock.Data.Size()); - WriteBytes(subBlock.Data, (UInt32)subBlock.Data.Size()); - } + const CExtraSubBlock &subBlock = extra.SubBlocks[i]; + Write16((UInt16)subBlock.ID); + Write16((UInt16)subBlock.Data.Size()); + WriteBytes(subBlock.Data, (UInt16)subBlock.Data.Size()); } } @@ -125,40 +91,65 @@ void COutArchive::WriteCommonItemInfo(const CLocalItem &item, bool isZip64) Write16(item.Flags); Write16(item.Method); Write32(item.Time); - Write32(item.Crc); } + #define WRITE_32_VAL_SPEC(__v, __isZip64) Write32((__isZip64) ? 0xFFFFFFFF : (UInt32)(__v)); -void COutArchive::WriteLocalHeader(const CLocalItem &item) + +void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck) { - SeekToCurPos(); + m_LocalHeaderPos = m_CurPos; + item.LocalHeaderPos = m_CurPos; - bool isZip64 = m_IsZip64 || + bool isZip64 = DOES_NEED_ZIP64(item.PackSize) || DOES_NEED_ZIP64(item.Size); - + + if (needCheck && m_IsZip64) + isZip64 = true; + + const UInt32 localExtraSize = (UInt32)((isZip64 ? (4 + 8 + 8): 0) + item.LocalExtra.GetSize()); + if ((UInt16)localExtraSize != localExtraSize) + throw CSystemException(E_FAIL); + if (needCheck && m_ExtraSize != localExtraSize) + throw CSystemException(E_FAIL); + + m_IsZip64 = isZip64; + m_ExtraSize = localExtraSize; + + item.LocalExtra.IsZip64 = isZip64; + Write32(NSignature::kLocalFileHeader); + WriteCommonItemInfo(item, isZip64); + + Write32(item.HasDescriptor() ? 0 : item.Crc); - WRITE_32_VAL_SPEC(item.PackSize, isZip64); - WRITE_32_VAL_SPEC(item.Size, isZip64); - - Write16((UInt16)item.Name.Len()); + UInt64 packSize = item.PackSize; + UInt64 size = item.Size; + + if (item.HasDescriptor()) { - UInt16 localExtraSize = (UInt16)((isZip64 ? (4 + 8 + 8): 0) + item.LocalExtra.GetSize()); - if (localExtraSize != m_ExtraSize) - throw CSystemException(E_FAIL); + packSize = 0; + size = 0; } - Write16((UInt16)m_ExtraSize); - WriteBytes((const char *)item.Name, item.Name.Len()); + + WRITE_32_VAL_SPEC(packSize, isZip64); + WRITE_32_VAL_SPEC(size, isZip64); + + Write16((UInt16)item.Name.Len()); + + Write16((UInt16)localExtraSize); + + WriteBytes((const char *)item.Name, (UInt16)item.Name.Len()); if (isZip64) { Write16(NFileHeader::NExtraID::kZip64); Write16(8 + 8); - Write64(item.Size); - Write64(item.PackSize); + Write64(size); + Write64(packSize); } WriteExtra(item.LocalExtra); @@ -166,10 +157,57 @@ void COutArchive::WriteLocalHeader(const CLocalItem &item) // Why don't we write NTFS timestamps to local header? // Probably we want to reduce size of archive? + const UInt32 localFileHeaderSize = (UInt32)(m_CurPos - m_LocalHeaderPos); + if (needCheck && m_LocalFileHeaderSize != localFileHeaderSize) + throw CSystemException(E_FAIL); + m_LocalFileHeaderSize = localFileHeaderSize; + m_OutBuffer.FlushWithCheck(); - MoveCurPos(item.PackSize); } + +void COutArchive::WriteLocalHeader_Replace(CItemOut &item) +{ + m_CurPos = m_LocalHeaderPos + m_LocalFileHeaderSize + item.PackSize; + + if (item.HasDescriptor()) + { + WriteDescriptor(item); + m_OutBuffer.FlushWithCheck(); + } + + const UInt64 nextPos = m_CurPos; + m_CurPos = m_LocalHeaderPos; + SeekToCurPos(); + WriteLocalHeader(item, true); + m_CurPos = nextPos; + SeekToCurPos(); +} + + +void COutArchive::WriteDescriptor(const CItemOut &item) +{ + Byte buf[kDataDescriptorSize64]; + SetUi32(buf, NSignature::kDataDescriptor); + SetUi32(buf + 4, item.Crc); + unsigned descriptorSize; + if (m_IsZip64) + { + SetUi64(buf + 8, item.PackSize); + SetUi64(buf + 16, item.Size); + descriptorSize = kDataDescriptorSize64; + } + else + { + SetUi32(buf + 8, (UInt32)item.PackSize); + SetUi32(buf + 12, (UInt32)item.Size); + descriptorSize = kDataDescriptorSize32; + } + WriteBytes(buf, descriptorSize); +} + + + void COutArchive::WriteCentralHeader(const CItemOut &item) { bool isUnPack64 = DOES_NEED_ZIP64(item.Size); @@ -182,6 +220,7 @@ void COutArchive::WriteCentralHeader(const CItemOut &item) Write8(item.MadeByVersion.HostOS); WriteCommonItemInfo(item, isZip64); + Write32(item.Crc); WRITE_32_VAL_SPEC(item.PackSize, isPack64); WRITE_32_VAL_SPEC(item.Size, isUnPack64); @@ -196,7 +235,10 @@ void COutArchive::WriteCentralHeader(const CItemOut &item) item.CentralExtra.GetSize()); Write16(centralExtraSize); // test it; - Write16((UInt16)item.Comment.Size()); + + const UInt16 commentSize = (UInt16)item.Comment.Size(); + + Write16(commentSize); Write16(0); // DiskNumberStart; Write16(item.InternalAttrib); Write32(item.ExternalAttrib); @@ -228,14 +270,12 @@ void COutArchive::WriteCentralHeader(const CItemOut &item) } WriteExtra(item.CentralExtra); - if (item.Comment.Size() > 0) - WriteBytes(item.Comment, (UInt32)item.Comment.Size()); + if (commentSize != 0) + WriteBytes(item.Comment, commentSize); } void COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment) { - SeekToCurPos(); - UInt64 cdOffset = GetCurPos(); FOR_VECTOR (i, items) WriteCentralHeader(items[i]); @@ -252,6 +292,11 @@ void COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const CB { Write32(NSignature::kEcd64); Write64(kEcd64_MainSize); + + // to test extra block: + // const UInt32 extraSize = 1 << 26; + // Write64(kEcd64_MainSize + extraSize); + Write16(45); // made by version Write16(45); // extract version Write32(0); // ThisDiskNumber = 0; @@ -261,6 +306,8 @@ void COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const CB Write64((UInt64)cdSize); Write64((UInt64)cdOffset); + // for (UInt32 iii = 0; iii < extraSize; iii++) Write8(1); + Write32(NSignature::kEcd64Locator); Write32(0); // number of the disk with the start of the zip64 end of central directory Write64(cd64EndOffset); @@ -276,37 +323,23 @@ void COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const CB WRITE_32_VAL_SPEC(cdSize, cdSize64); WRITE_32_VAL_SPEC(cdOffset, cdOffset64); - UInt32 commentSize = (UInt32)(comment ? comment->Size() : 0); + const UInt16 commentSize = (UInt16)(comment ? comment->Size() : 0); Write16((UInt16)commentSize); - if (commentSize > 0) + if (commentSize != 0) WriteBytes((const Byte *)*comment, commentSize); m_OutBuffer.FlushWithCheck(); } -void COutArchive::CreateStreamForCompressing(IOutStream **outStream) +void COutArchive::CreateStreamForCompressing(CMyComPtr<IOutStream> &outStream) { COffsetOutStream *streamSpec = new COffsetOutStream; - CMyComPtr<IOutStream> tempStream(streamSpec); - streamSpec->Init(m_Stream, m_Base + m_CurPos + m_LocalFileHeaderSize); - *outStream = tempStream.Detach(); -} - -/* -void COutArchive::SeekToPackedDataPosition() -{ - SeekTo(m_BasePosition + m_LocalFileHeaderSize); -} -*/ - -void COutArchive::SeekToCurPos() -{ - SeekToRelatPos(m_CurPos); + outStream = streamSpec; + streamSpec->Init(m_Stream, m_Base + m_CurPos); } -void COutArchive::CreateStreamForCopying(ISequentialOutStream **outStream) +void COutArchive::CreateStreamForCopying(CMyComPtr<ISequentialOutStream> &outStream) { - CMyComPtr<ISequentialOutStream> tempStream(m_Stream); - *outStream = tempStream.Detach(); + outStream = m_Stream; } }} diff --git a/CPP/7zip/Archive/Zip/ZipOut.h b/CPP/7zip/Archive/Zip/ZipOut.h index 056d0d09..0a0ac0c8 100644 --- a/CPP/7zip/Archive/Zip/ZipOut.h +++ b/CPP/7zip/Archive/Zip/ZipOut.h @@ -5,7 +5,6 @@ #include "../../../Common/MyCom.h" -#include "../../IStream.h" #include "../../Common/OutBuffer.h" #include "ZipItem.h" @@ -13,8 +12,6 @@ namespace NArchive { namespace NZip { -// can throw CSystemException and COutBufferException - class CItemOut: public CItem { public: @@ -28,21 +25,23 @@ public: CItemOut(): NtfsTimeIsDefined(false) {} }; + +// COutArchive can throw CSystemException and COutBufferException + class COutArchive { - CMyComPtr<IOutStream> m_Stream; COutBuffer m_OutBuffer; + CMyComPtr<IOutStream> m_Stream; - UInt64 m_Base; // Base of arc (offset in output Stream) + UInt64 m_Base; // Base of archive (offset in output Stream) UInt64 m_CurPos; // Curent position in archive (relative from m_Base) + UInt64 m_LocalHeaderPos; // LocalHeaderPos (relative from m_Base) for last WriteLocalHeader() call UInt32 m_LocalFileHeaderSize; UInt32 m_ExtraSize; bool m_IsZip64; - void SeekToRelatPos(UInt64 offset); - - void WriteBytes(const void *buffer, UInt32 size); + void WriteBytes(const void *data, size_t size); void Write8(Byte b); void Write16(UInt16 val); void Write32(UInt32 val); @@ -57,30 +56,26 @@ class COutArchive void WriteCommonItemInfo(const CLocalItem &item, bool isZip64); void WriteCentralHeader(const CItemOut &item); - void PrepareWriteCompressedDataZip64(unsigned fileNameLen, bool isZip64, bool aesEncryption); - + void SeekToCurPos(); public: HRESULT Create(IOutStream *outStream); - void MoveCurPos(UInt64 distanceToMove); UInt64 GetCurPos() const { return m_CurPos; } - void SeekToCurPos(); - - void PrepareWriteCompressedData(unsigned fileNameLen, UInt64 unPackSize, bool aesEncryption); - void PrepareWriteCompressedData2(unsigned fileNameLen, UInt64 unPackSize, UInt64 packSize, bool aesEncryption); - void WriteLocalHeader(const CLocalItem &item); - - void WriteLocalHeader_And_SeekToNextFile(const CLocalItem &item) + void MoveCurPos(UInt64 distanceToMove) { - WriteLocalHeader(item); - SeekToCurPos(); + m_CurPos += distanceToMove; } + void WriteLocalHeader(CItemOut &item, bool needCheck = false); + void WriteLocalHeader_Replace(CItemOut &item); + + void WriteDescriptor(const CItemOut &item); + void WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment); - void CreateStreamForCompressing(IOutStream **outStream); - void CreateStreamForCopying(ISequentialOutStream **outStream); + void CreateStreamForCompressing(CMyComPtr<IOutStream> &outStream); + void CreateStreamForCopying(CMyComPtr<ISequentialOutStream> &outStream); }; }} diff --git a/CPP/7zip/Archive/Zip/ZipRegister.cpp b/CPP/7zip/Archive/Zip/ZipRegister.cpp index 6674189f..e6929f1b 100644 --- a/CPP/7zip/Archive/Zip/ZipRegister.cpp +++ b/CPP/7zip/Archive/Zip/ZipRegister.cpp @@ -10,13 +10,14 @@ namespace NArchive { namespace NZip { static const Byte k_Signature[] = { - 4, 0x50, 0x4B, 0x03, 0x04, - 4, 0x50, 0x4B, 0x05, 0x06, - 6, 0x50, 0x4B, 0x07, 0x08, 0x50, 0x4B, - 6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B }; + 4, 0x50, 0x4B, 0x03, 0x04, // Local + 4, 0x50, 0x4B, 0x05, 0x06, // Ecd + 4, 0x50, 0x4B, 0x06, 0x06, // Ecd64 + 6, 0x50, 0x4B, 0x07, 0x08, 0x50, 0x4B, // Span / Descriptor + 6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B }; // NoSpan REGISTER_ARC_IO( - "zip", "zip z01 zipx jar xpi odt ods docx xlsx epub", 0, 1, + "zip", "zip z01 zipx jar xpi odt ods docx xlsx epub ipa apk appx", 0, 1, k_Signature, 0, NArcInfoFlags::kFindSignature | diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp index bc50c1d7..81f48a2a 100644 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -42,32 +42,38 @@ static const Byte kHostOS = static const Byte kMadeByHostOS = kHostOS; static const Byte kExtractHostOS = kHostOS; -static const Byte kMethodForDirectory = NFileHeader::NCompressionMethod::kStored; +static const Byte kMethodForDirectory = NFileHeader::NCompressionMethod::kStore; -static HRESULT CopyBlockToArchive(ISequentialInStream *inStream, UInt64 size, - COutArchive &outArchive, ICompressProgressInfo *progress) + +static void AddAesExtra(CItem &item, Byte aesKeyMode, UInt16 method) { - CMyComPtr<ISequentialOutStream> outStream; - outArchive.CreateStreamForCopying(&outStream); - return NCompress::CopyStream_ExactSize(inStream, outStream, size, progress); + CWzAesExtra wzAesField; + wzAesField.Strength = aesKeyMode; + wzAesField.Method = method; + item.Method = NFileHeader::NCompressionMethod::kWzAES; + item.Crc = 0; + CExtraSubBlock sb; + wzAesField.SetSubBlock(sb); + item.LocalExtra.SubBlocks.Add(sb); + item.CentralExtra.SubBlocks.Add(sb); } + static void SetFileHeader( - COutArchive &archive, const CCompressionMethodMode &options, const CUpdateItem &ui, // bool isSeqMode, CItemOut &item) { item.Size = ui.Size; - bool isDir; + bool isDir = ui.IsDir; item.ClearFlags(); if (ui.NewProps) { - isDir = ui.IsDir; item.Name = ui.Name; + item.Comment = ui.Comment; item.SetUtf8(ui.IsUtf8); item.ExternalAttrib = ui.Attrib; item.Time = ui.Time; @@ -76,10 +82,11 @@ static void SetFileHeader( item.Ntfs_CTime = ui.Ntfs_CTime; item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined; } + /* else isDir = item.IsDir(); + */ - item.LocalHeaderPos = archive.GetCurPos(); item.MadeByVersion.HostOS = kMadeByHostOS; item.MadeByVersion.Version = NFileHeader::NCompressionMethod::kMadeByProgramVersion; @@ -97,14 +104,32 @@ static void SetFileHeader( item.Size = 0; item.Crc = 0; } + + item.LocalExtra.Clear(); + item.CentralExtra.Clear(); + + if (isDir) + { + item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir; + item.Method = kMethodForDirectory; + item.PackSize = 0; + item.Size = 0; + item.Crc = 0; + } + else if (options.IsRealAesMode()) + AddAesExtra(item, options.AesKeyMode, (Byte)(options.MethodSequence.IsEmpty() ? 8 : options.MethodSequence[0])); } +// we call SetItemInfoFromCompressingResult() after SetFileHeader() + static void SetItemInfoFromCompressingResult(const CCompressingResult &compressingResult, bool isAesMode, Byte aesKeyMode, CItem &item) { item.ExtractVersion.Version = compressingResult.ExtractVersion; item.Method = compressingResult.Method; + if (compressingResult.Method == NFileHeader::NCompressionMethod::kLZMA && compressingResult.LzmaEos) + item.Flags |= NFileHeader::NFlags::kLzmaEOS; item.Crc = compressingResult.CRC; item.Size = compressingResult.UnpackSize; item.PackSize = compressingResult.PackSize; @@ -113,17 +138,7 @@ static void SetItemInfoFromCompressingResult(const CCompressingResult &compressi item.CentralExtra.Clear(); if (isAesMode) - { - CWzAesExtra wzAesField; - wzAesField.Strength = aesKeyMode; - wzAesField.Method = compressingResult.Method; - item.Method = NFileHeader::NCompressionMethod::kWzAES; - item.Crc = 0; - CExtraSubBlock sb; - wzAesField.SetSubBlock(sb); - item.LocalExtra.SubBlocks.Add(sb); - item.CentralExtra.SubBlocks.Add(sb); - } + AddAesExtra(item, aesKeyMode, compressingResult.Method); } @@ -151,6 +166,7 @@ struct CThreadInfo HRESULT Result; CCompressingResult CompressingResult; + bool SeqMode; bool IsFree; UInt32 UpdateIndex; UInt32 FileTime; @@ -160,6 +176,7 @@ struct CThreadInfo ProgressSpec(0), OutStreamSpec(0), Coder(options), + SeqMode(false), FileTime(0) {} @@ -193,7 +210,7 @@ void CThreadInfo::WaitAndCode() Result = Coder.Compress( EXTERNAL_CODECS_LOC_VARS - InStream, OutStream, FileTime, Progress, CompressingResult); + InStream, OutStream, SeqMode, FileTime, Progress, CompressingResult); if (Result == S_OK && Progress) Result = Progress->SetRatioInfo(&CompressingResult.UnpackSize, &CompressingResult.PackSize); @@ -342,6 +359,8 @@ static HRESULT UpdateItemOldData( NUpdateNotifyOp::kReplicate)) } + UInt64 rangeSize; + if (ui.NewProps) { if (item.HasDescriptor()) @@ -349,14 +368,11 @@ static HRESULT UpdateItemOldData( // use old name size. - CMyComPtr<ISequentialInStream> packStream; - RINOK(inArchive->GetItemStream(itemEx, true, packStream)); - if (!packStream) - return E_NOTIMPL; - // we keep ExternalAttrib and some another properties from old archive // item.ExternalAttrib = ui.Attrib; + // if we don't change Comment, we keep Comment from OldProperties + item.Comment = ui.Comment; item.Name = ui.Name; item.SetUtf8(ui.IsUtf8); item.Time = ui.Time; @@ -367,46 +383,37 @@ static HRESULT UpdateItemOldData( item.CentralExtra.RemoveUnknownSubBlocks(); item.LocalExtra.RemoveUnknownSubBlocks(); - item.LocalHeaderPos = archive.GetCurPos(); - archive.PrepareWriteCompressedData2(item.Name.Len(), item.Size, item.PackSize, item.LocalExtra.HasWzAes()); archive.WriteLocalHeader(item); - - RINOK(CopyBlockToArchive(packStream, itemEx.PackSize, archive, progress)); - - complexity += itemEx.PackSize; + rangeSize = item.GetPackSizeWithDescriptor(); } else { - CMyComPtr<ISequentialInStream> packStream; - RINOK(inArchive->GetItemStream(itemEx, false, packStream)); - if (!packStream) - return E_NOTIMPL; - - // set new header position item.LocalHeaderPos = archive.GetCurPos(); - - const UInt64 rangeSize = itemEx.GetLocalFullSize(); - - RINOK(CopyBlockToArchive(packStream, rangeSize, archive, progress)); - - complexity += rangeSize; - archive.MoveCurPos(rangeSize); + rangeSize = itemEx.GetLocalFullSize(); } - return S_OK; + CMyComPtr<ISequentialInStream> packStream; + + RINOK(inArchive->GetItemStream(itemEx, ui.NewProps, packStream)); + if (!packStream) + return E_NOTIMPL; + + complexity += rangeSize; + + CMyComPtr<ISequentialOutStream> outStream; + archive.CreateStreamForCopying(outStream); + HRESULT res = NCompress::CopyStream_ExactSize(packStream, outStream, rangeSize, progress); + archive.MoveCurPos(rangeSize); + return res; } static void WriteDirHeader(COutArchive &archive, const CCompressionMethodMode *options, const CUpdateItem &ui, CItemOut &item) { - SetFileHeader(archive, *options, ui, item); - archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size, - // options->IsRealAesMode() - false // fixed 9.31 - ); - archive.WriteLocalHeader_And_SeekToNextFile(item); + SetFileHeader(*options, ui, item); + archive.WriteLocalHeader(item); } @@ -490,6 +497,8 @@ static HRESULT Update2St( if (!ui.NewProps || !ui.NewData) { + // Note: for (ui.NewProps && !ui.NewData) it copies Props from old archive, + // But we will rewrite all important properties later. But we can keep some properties like Comment itemEx = inputItems[ui.IndexInArc]; if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK) return E_NOTIMPL; @@ -498,7 +507,8 @@ static HRESULT Update2St( if (ui.NewData) { - bool isDir = ((ui.NewProps) ? ui.IsDir : item.IsDir()); + // bool isDir = ((ui.NewProps) ? ui.IsDir : item.IsDir()); + bool isDir = ui.IsDir; if (isDir) { WriteDirHeader(archive, options, ui, item); @@ -517,28 +527,39 @@ static HRESULT Update2St( if (!fileInStream) return E_INVALIDARG; - // bool isSeqMode = false; - /* + bool seqMode; { CMyComPtr<IInStream> inStream2; fileInStream->QueryInterface(IID_IInStream, (void **)&inStream2); - isSeqMode = (inStream2 == NULL); + seqMode = (inStream2 == NULL); } - */ + // seqMode = true; // to test seqMode UpdatePropsFromStream(ui, fileInStream, updateCallback, totalComplexity); - SetFileHeader(archive, *options, ui, item); + SetFileHeader(*options, ui, item); + + item.SetDescriptorMode(seqMode); // file Size can be 64-bit !!! - archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size, options->IsRealAesMode()); + CCompressingResult compressingResult; + + RINOK(compressor.Set_Pre_CompressionResult( + seqMode, + ui.Size, + compressingResult)); + + SetItemInfoFromCompressingResult(compressingResult, options->IsRealAesMode(), options->AesKeyMode, item); + + archive.WriteLocalHeader(item); + CMyComPtr<IOutStream> outStream; - archive.CreateStreamForCompressing(&outStream); + archive.CreateStreamForCompressing(outStream); RINOK(compressor.Compress( EXTERNAL_CODECS_LOC_VARS fileInStream, outStream, - ui.Time, + seqMode, ui.Time, progress, compressingResult)); if (compressingResult.FileTimeWasUsed) @@ -551,7 +572,9 @@ static HRESULT Update2St( } SetItemInfoFromCompressingResult(compressingResult, options->IsRealAesMode(), options->AesKeyMode, item); - archive.WriteLocalHeader_And_SeekToNextFile(item); + + archive.WriteLocalHeader_Replace(item); + RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); unpackSizeTotal += item.Size; packSizeTotal += item.PackSize; @@ -561,7 +584,9 @@ static HRESULT Update2St( { UInt64 complexity = 0; lps->SendRatio = false; + RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, opCallback, complexity)); + lps->SendRatio = true; lps->ProgressOffset += complexity; } @@ -591,6 +616,7 @@ static HRESULT Update2( CMyComPtr<IArchiveUpdateCallbackFile> opCallback; updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback); + bool unknownComplexity = false; UInt64 complexity = 0; UInt64 numFilesToCompress = 0; UInt64 numBytesToCompress = 0; @@ -602,7 +628,10 @@ static HRESULT Update2( const CUpdateItem &ui = updateItems[i]; if (ui.NewData) { - complexity += ui.Size; + if (ui.Size == (UInt64)(Int64)-1) + unknownComplexity = true; + else + complexity += ui.Size; numBytesToCompress += ui.Size; numFilesToCompress++; /* @@ -625,19 +654,49 @@ static HRESULT Update2( if (comment) complexity += comment->Size(); complexity++; // end of central - updateCallback->SetTotal(complexity); + + if (!unknownComplexity) + updateCallback->SetTotal(complexity); UInt64 totalComplexity = complexity; - CAddCommon compressor(options); + CCompressionMethodMode options2 = options; + + if (options2._methods.IsEmpty()) + { + // we need method item, if default method was used + options2._methods.AddNew(); + } + + CAddCommon compressor(options2); complexity = 0; - CCompressionMethodMode options2 = options; + const Byte method = options.MethodSequence.Front(); + + COneMethodInfo *oneMethodMain = NULL; + if (!options2._methods.IsEmpty()) + oneMethodMain = &options2._methods[0]; + + { + FOR_VECTOR (mi, options2._methods) + { + options2.SetGlobalLevelTo(options2._methods[mi]); + } + } + + if (oneMethodMain) + { + // appnote recommends to use EOS marker for LZMA. + if (method == NFileHeader::NCompressionMethod::kLZMA) + oneMethodMain->AddProp_EndMarker_if_NotFound(true); + } + #ifndef _7ZIP_ST - UInt32 numThreads = options.NumThreads; + UInt32 numThreads = options._numThreads; + const UInt32 kNumMaxThreads = 64; if (numThreads > kNumMaxThreads) numThreads = kNumMaxThreads; @@ -646,7 +705,6 @@ static HRESULT Update2( if (numThreads < 1) numThreads = 1; - const size_t kMemPerThread = (1 << 25); const size_t kBlockSize = 1 << 16; @@ -655,44 +713,69 @@ static HRESULT Update2( if (numFilesToCompress <= 1) mtMode = false; - Byte method = options.MethodSequence.Front(); - if (!mtMode) { - if (options2.MethodInfo.FindProp(NCoderPropID::kNumThreads) < 0) + FOR_VECTOR (mi, options2._methods) { - // fixed for 9.31. bzip2 default is just one thread. - if (options2.NumThreadsWasChanged || method == NFileHeader::NCompressionMethod::kBZip2) - options2.MethodInfo.AddProp_NumThreads(numThreads); + COneMethodInfo &onem = options2._methods[mi]; + + if (onem.FindProp(NCoderPropID::kNumThreads) < 0) + { + // fixed for 9.31. bzip2 default is just one thread. + onem.AddProp_NumThreads(numThreads); + } } } else { - if (method == NFileHeader::NCompressionMethod::kStored && !options.PasswordIsDefined) + if (method == NFileHeader::NCompressionMethod::kStore && !options.PasswordIsDefined) numThreads = 1; + + if (oneMethodMain) + { + if (method == NFileHeader::NCompressionMethod::kBZip2) { bool fixedNumber; - UInt32 numBZip2Threads = options2.MethodInfo.Get_BZip2_NumThreads(fixedNumber); + UInt32 numBZip2Threads = oneMethodMain->Get_BZip2_NumThreads(fixedNumber); if (!fixedNumber) { - UInt64 averageSize = numBytesToCompress / numFilesToCompress; - UInt32 blockSize = options2.MethodInfo.Get_BZip2_BlockSize(); - UInt64 averageNumberOfBlocks = averageSize / blockSize + 1; + const UInt64 averageSize = numBytesToCompress / numFilesToCompress; + const UInt32 blockSize = oneMethodMain->Get_BZip2_BlockSize(); + const UInt64 averageNumberOfBlocks = averageSize / blockSize + 1; numBZip2Threads = 32; - if (averageNumberOfBlocks < numBZip2Threads) + if (numBZip2Threads > averageNumberOfBlocks) numBZip2Threads = (UInt32)averageNumberOfBlocks; - options2.MethodInfo.AddProp_NumThreads(numBZip2Threads); + oneMethodMain->AddProp_NumThreads(numBZip2Threads); } numThreads /= numBZip2Threads; } - if (method == NFileHeader::NCompressionMethod::kLZMA) + + if (method == NFileHeader::NCompressionMethod::kXz) { bool fixedNumber; + UInt32 numLzma2Threads = oneMethodMain->Get_Lzma2_NumThreads(fixedNumber); + if (!fixedNumber) + { + const UInt64 averageSize = numBytesToCompress / numFilesToCompress; + const UInt64 blockSize = oneMethodMain->Get_Lzma2_BlockSize(); + const UInt64 averageNumberOfBlocks = averageSize / blockSize + 1; + numLzma2Threads = 2; + if (numLzma2Threads > averageNumberOfBlocks) + numLzma2Threads = (UInt32)averageNumberOfBlocks; + oneMethodMain->AddProp_NumThreads(numLzma2Threads); + } + numThreads /= numLzma2Threads; + } + + if (method == NFileHeader::NCompressionMethod::kLZMA) + { // we suppose that default LZMA is 2 thread. So we don't change it - UInt32 numLZMAThreads = options2.MethodInfo.Get_Lzma_NumThreads(fixedNumber); + UInt32 numLZMAThreads = oneMethodMain->Get_Lzma_NumThreads(); numThreads /= numLZMAThreads; } + } + if (numThreads > numFilesToCompress) numThreads = (UInt32)numFilesToCompress; if (numThreads <= 1) @@ -747,6 +830,7 @@ static HRESULT Update2( threadInfo.ProgressSpec = new CMtCompressProgress(); threadInfo.Progress = threadInfo.ProgressSpec; threadInfo.ProgressSpec->Init(&mtCompressProgressMixer, (int)i); + threadInfo.SeqMode = false; // fix it ! threadInfo.FileTime = 0; // fix it ! RINOK(threadInfo.CreateThread()); } @@ -777,7 +861,9 @@ static HRESULT Update2( if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK) return E_NOTIMPL; (CItem &)item = itemEx; - if (item.IsDir()) + if (item.IsDir() != ui.IsDir) + return E_NOTIMPL; + if (ui.IsDir) continue; } @@ -849,7 +935,8 @@ static HRESULT Update2( if (ui.NewData) { - bool isDir = ((ui.NewProps) ? ui.IsDir : item.IsDir()); + // bool isDir = ((ui.NewProps) ? ui.IsDir : item.IsDir()); + bool isDir = ui.IsDir; if (isDir) { @@ -857,39 +944,51 @@ static HRESULT Update2( } else { - if (lastRealStreamItemIndex < (int)itemIndex) - { - lastRealStreamItemIndex = itemIndex; - SetFileHeader(archive, options, ui, item); - // file Size can be 64-bit !!! - archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size, options.IsRealAesMode()); - } - CMemBlocks2 &memRef = refs.Refs[itemIndex]; if (memRef.Defined) { - CMyComPtr<IOutStream> outStream; - archive.CreateStreamForCompressing(&outStream); - memRef.WriteToStream(memManager.GetBlockSize(), outStream); - SetFileHeader(archive, options, ui, item); + if (lastRealStreamItemIndex < (int)itemIndex) + lastRealStreamItemIndex = itemIndex; + + SetFileHeader(options, ui, item); // the BUG was fixed in 9.26: // SetItemInfoFromCompressingResult must be after SetFileHeader // to write correct Size. SetItemInfoFromCompressingResult(memRef.CompressingResult, options.IsRealAesMode(), options.AesKeyMode, item); - archive.WriteLocalHeader_And_SeekToNextFile(item); + archive.WriteLocalHeader(item); // RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + CMyComPtr<ISequentialOutStream> outStream; + archive.CreateStreamForCopying(outStream); + memRef.WriteToStream(memManager.GetBlockSize(), outStream); + archive.MoveCurPos(item.PackSize); memRef.FreeOpt(&memManager); } else { + if (lastRealStreamItemIndex < (int)itemIndex) + { + lastRealStreamItemIndex = itemIndex; + SetFileHeader(options, ui, item); + + CCompressingResult compressingResult; + RINOK(compressor.Set_Pre_CompressionResult( + false, // seqMode + ui.Size, + compressingResult)); + SetItemInfoFromCompressingResult(compressingResult, options.IsRealAesMode(), options.AesKeyMode, item); + + // file Size can be 64-bit !!! + archive.WriteLocalHeader(item); + } + { CThreadInfo &thread = threads.Threads[threadIndices.Front()]; if (!thread.OutStreamSpec->WasUnlockEventSent()) { CMyComPtr<IOutStream> outStream; - archive.CreateStreamForCompressing(&outStream); + archive.CreateStreamForCompressing(outStream); thread.OutStreamSpec->SetOutStream(outStream); thread.OutStreamSpec->SetRealStreamMode(); } @@ -918,10 +1017,10 @@ static HRESULT Update2( { RINOK(threadInfo.OutStreamSpec->WriteToRealStream()); threadInfo.OutStreamSpec->ReleaseOutStream(); - SetFileHeader(archive, options, ui, item); + SetFileHeader(options, ui, item); SetItemInfoFromCompressingResult(threadInfo.CompressingResult, options.IsRealAesMode(), options.AesKeyMode, item); - archive.WriteLocalHeader_And_SeekToNextFile(item); + archive.WriteLocalHeader_Replace(item); } else { diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.h b/CPP/7zip/Archive/Zip/ZipUpdate.h index 15cbf69d..d5fda855 100644 --- a/CPP/7zip/Archive/Zip/ZipUpdate.h +++ b/CPP/7zip/Archive/Zip/ZipUpdate.h @@ -14,6 +14,7 @@ namespace NArchive { namespace NZip { +/* struct CUpdateRange { UInt64 Position; @@ -22,6 +23,7 @@ struct CUpdateRange // CUpdateRange() {}; CUpdateRange(UInt64 position, UInt64 size): Position(position), Size(size) {}; }; +*/ struct CUpdateItem { @@ -36,12 +38,23 @@ struct CUpdateItem UInt32 Time; UInt64 Size; AString Name; + CByteBuffer Comment; // bool Commented; // CUpdateRange CommentRange; FILETIME Ntfs_MTime; FILETIME Ntfs_ATime; FILETIME Ntfs_CTime; + void Clear() + { + IsDir = false; + NtfsTimeIsDefined = false; + IsUtf8 = false; + Size = 0; + Name.Empty(); + Comment.Free(); + } + CUpdateItem(): NtfsTimeIsDefined(false), IsUtf8(false), Size(0) {} }; diff --git a/CPP/7zip/Asm.mak b/CPP/7zip/Asm.mak index 4f77dddf..c4073e89 100644 --- a/CPP/7zip/Asm.mak +++ b/CPP/7zip/Asm.mak @@ -2,7 +2,7 @@ !IF "$(CPU)" == "ARM" $(ASM_OBJS): ../../../../Asm/Arm/$(*B).asm $(COMPL_ASM) -!ELSEIF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS" +!ELSEIF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS" && "$(CPU)" != "ARM64" $(ASM_OBJS): ../../../../Asm/x86/$(*B).asm $(COMPL_ASM) !ENDIF diff --git a/CPP/7zip/Bundles/Alone/Alone.dsp b/CPP/7zip/Bundles/Alone/Alone.dsp index b16ab914..f959e4a1 100644 --- a/CPP/7zip/Bundles/Alone/Alone.dsp +++ b/CPP/7zip/Bundles/Alone/Alone.dsp @@ -410,6 +410,10 @@ SOURCE=..\..\..\Common\Wildcard.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\XzCrc64Init.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\XzCrc64Reg.cpp # End Source File # End Group @@ -514,6 +518,14 @@ SOURCE=..\..\..\Windows\PropVariantConv.h # End Source File # Begin Source File +SOURCE=..\..\..\Windows\PropVariantUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantUtils.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File @@ -903,14 +915,6 @@ SOURCE=..\..\Compress\ImplodeDecoder.cpp SOURCE=..\..\Compress\ImplodeDecoder.h # End Source File -# Begin Source File - -SOURCE=..\..\Compress\ImplodeHuffmanDecoder.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\Compress\ImplodeHuffmanDecoder.h -# End Source File # End Group # Begin Group "LZMA" @@ -1232,6 +1236,22 @@ SOURCE=..\..\Compress\LzOutWindow.cpp SOURCE=..\..\Compress\LzOutWindow.h # End Source File +# Begin Source File + +SOURCE=..\..\Compress\XzDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\XzDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\XzEncoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\XzEncoder.h +# End Source File # End Group # Begin Group "Archive" diff --git a/CPP/7zip/Bundles/Alone/makefile b/CPP/7zip/Bundles/Alone/makefile index 91ecfce4..8e9d59a6 100644 --- a/CPP/7zip/Bundles/Alone/makefile +++ b/CPP/7zip/Bundles/Alone/makefile @@ -22,6 +22,7 @@ COMMON_OBJS = \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ + $O\XzCrc64Init.obj \ $O\XzCrc64Reg.obj \ $O\Sha1Reg.obj \ $O\Sha256Reg.obj \ @@ -38,6 +39,7 @@ WIN_OBJS = \ $O\MemoryLock.obj \ $O\PropVariant.obj \ $O\PropVariantConv.obj \ + $O\PropVariantUtils.obj \ $O\Synchronization.obj \ $O\System.obj \ $O\TimeUtils.obj \ @@ -151,7 +153,6 @@ COMPRESS_OBJS = \ $O\DeflateRegister.obj \ $O\DeltaFilter.obj \ $O\ImplodeDecoder.obj \ - $O\ImplodeHuffmanDecoder.obj \ $O\Lzma2Decoder.obj \ $O\Lzma2Encoder.obj \ $O\Lzma2Register.obj \ @@ -166,6 +167,8 @@ COMPRESS_OBJS = \ $O\PpmdZip.obj \ $O\QuantumDecoder.obj \ $O\ShrinkDecoder.obj \ + $O\XzDecoder.obj \ + $O\XzEncoder.obj \ $O\ZDecoder.obj \ CRYPTO_OBJS = \ diff --git a/CPP/7zip/Bundles/Alone7z/Alone.dsp b/CPP/7zip/Bundles/Alone7z/Alone.dsp index d220b198..334b6635 100644 --- a/CPP/7zip/Bundles/Alone7z/Alone.dsp +++ b/CPP/7zip/Bundles/Alone7z/Alone.dsp @@ -406,6 +406,10 @@ SOURCE=..\..\..\Common\Wildcard.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\XzCrc64Init.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\XzCrc64Reg.cpp # End Source File # End Group @@ -804,6 +808,22 @@ SOURCE=..\..\Compress\LzmaEncoder.h SOURCE=..\..\Compress\LzmaRegister.cpp # End Source File +# Begin Source File + +SOURCE=..\..\Compress\XzDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\XzDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\XzEncoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\XzEncoder.h +# End Source File # End Group # Begin Group "Archive" diff --git a/CPP/7zip/Bundles/Alone7z/makefile b/CPP/7zip/Bundles/Alone7z/makefile index 15c51f91..d8335818 100644 --- a/CPP/7zip/Bundles/Alone7z/makefile +++ b/CPP/7zip/Bundles/Alone7z/makefile @@ -22,6 +22,7 @@ COMMON_OBJS = \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ + $O\XzCrc64Init.obj \ $O\XzCrc64Reg.obj \ WIN_OBJS = \ @@ -109,6 +110,8 @@ COMPRESS_OBJS = \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ + $O\XzDecoder.obj \ + $O\XzEncoder.obj \ CRYPTO_OBJS = \ $O\7zAes.obj \ diff --git a/CPP/7zip/Bundles/Fm/FM.dsp b/CPP/7zip/Bundles/Fm/FM.dsp index eb1aa103..7ebf37ef 100644 --- a/CPP/7zip/Bundles/Fm/FM.dsp +++ b/CPP/7zip/Bundles/Fm/FM.dsp @@ -995,6 +995,24 @@ SOURCE=..\..\..\..\C\LzFindMt.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Lzma2Dec.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Dec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Enc.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Enc.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\LzmaDec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File @@ -1013,6 +1031,15 @@ SOURCE=..\..\..\..\C\LzmaEnc.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\MtCoder.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\MtCoder.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Sha256.c !IF "$(CFG)" == "FM - Win32 Release" @@ -1911,6 +1938,26 @@ SOURCE=..\..\Compress\CopyRegister.cpp # End Source File # Begin Source File +SOURCE=..\..\Compress\Lzma2Decoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Decoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Encoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Encoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Register.cpp +# End Source File +# Begin Source File + SOURCE=..\..\Compress\LzmaDecoder.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/Bundles/Format7zF/Arc.mak b/CPP/7zip/Bundles/Format7zF/Arc.mak index 44bd023b..97f6596e 100644 --- a/CPP/7zip/Bundles/Format7zF/Arc.mak +++ b/CPP/7zip/Bundles/Format7zF/Arc.mak @@ -14,6 +14,7 @@ COMMON_OBJS = \ $O\StringToInt.obj \ $O\UTFConvert.obj \ $O\Wildcard.obj \ + $O\XzCrc64Init.obj \ $O\XzCrc64Reg.obj \ WIN_OBJS = \ @@ -197,7 +198,6 @@ COMPRESS_OBJS = \ $O\DeflateRegister.obj \ $O\DeltaFilter.obj \ $O\ImplodeDecoder.obj \ - $O\ImplodeHuffmanDecoder.obj \ $O\LzhDecoder.obj \ $O\Lzma2Decoder.obj \ $O\Lzma2Encoder.obj \ @@ -220,10 +220,13 @@ COMPRESS_OBJS = \ $O\Rar5Decoder.obj \ $O\RarCodecsRegister.obj \ $O\ShrinkDecoder.obj \ + $O\XpressDecoder.obj \ + $O\XzDecoder.obj \ + $O\XzEncoder.obj \ $O\ZlibDecoder.obj \ $O\ZlibEncoder.obj \ $O\ZDecoder.obj \ - $O\XPressDecoder.obj \ + CRYPTO_OBJS = \ $O\7zAes.obj \ diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp index 69d4f3a0..f2a8fcc8 100644 --- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp +++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp @@ -271,6 +271,10 @@ SOURCE=..\..\..\Common\MyBuffer.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\MyBuffer2.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File @@ -383,6 +387,10 @@ SOURCE=..\..\..\Common\Wildcard.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\XzCrc64Init.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\XzCrc64Reg.cpp # End Source File # End Group @@ -419,6 +427,16 @@ SOURCE=..\..\Compress\BitmEncoder.h # Begin Source File SOURCE=..\..\Compress\Rar1Decoder.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 @@ -427,6 +445,16 @@ SOURCE=..\..\Compress\Rar1Decoder.h # Begin Source File SOURCE=..\..\Compress\Rar2Decoder.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 @@ -453,6 +481,16 @@ SOURCE=..\..\Compress\Rar3Decoder.h # Begin Source File SOURCE=..\..\Compress\Rar3Vm.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 @@ -479,6 +517,16 @@ SOURCE=..\..\Compress\Rar5Decoder.h # Begin Source File SOURCE=..\..\Compress\RarCodecsRegister.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + # End Source File # End Group # Begin Group "BZip2 Compress" @@ -491,6 +539,16 @@ SOURCE=..\..\Compress\BZip2Const.h # Begin Source File SOURCE=..\..\Compress\BZip2Crc.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 @@ -499,6 +557,16 @@ SOURCE=..\..\Compress\BZip2Crc.h # Begin Source File SOURCE=..\..\Compress\BZip2Decoder.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 @@ -507,6 +575,16 @@ SOURCE=..\..\Compress\BZip2Decoder.h # Begin Source File SOURCE=..\..\Compress\BZip2Encoder.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 @@ -515,6 +593,16 @@ SOURCE=..\..\Compress\BZip2Encoder.h # Begin Source File SOURCE=..\..\Compress\BZip2Register.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 @@ -527,6 +615,16 @@ SOURCE=..\..\Compress\Mtf8.h # Begin Source File SOURCE=..\..\Compress\Deflate64Register.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 @@ -535,6 +633,16 @@ SOURCE=..\..\Compress\DeflateConst.h # Begin Source File SOURCE=..\..\Compress\DeflateDecoder.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 @@ -543,6 +651,16 @@ SOURCE=..\..\Compress\DeflateDecoder.h # Begin Source File SOURCE=..\..\Compress\DeflateEncoder.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 @@ -551,26 +669,48 @@ SOURCE=..\..\Compress\DeflateEncoder.h # Begin Source File SOURCE=..\..\Compress\DeflateRegister.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\ImplodeDecoder.cpp -# End Source File -# Begin Source File -SOURCE=..\..\Compress\ImplodeDecoder.h -# End Source File -# Begin Source File +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF -SOURCE=..\..\Compress\ImplodeHuffmanDecoder.cpp # End Source File # Begin Source File -SOURCE=..\..\Compress\ImplodeHuffmanDecoder.h +SOURCE=..\..\Compress\ImplodeDecoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\PpmdZip.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 @@ -579,6 +719,16 @@ SOURCE=..\..\Compress\PpmdZip.h # Begin Source File SOURCE=..\..\Compress\ShrinkDecoder.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 @@ -587,6 +737,16 @@ SOURCE=..\..\Compress\ShrinkDecoder.h # Begin Source File SOURCE=..\..\Compress\ZlibDecoder.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 @@ -595,6 +755,16 @@ SOURCE=..\..\Compress\ZlibDecoder.h # Begin Source File SOURCE=..\..\Compress\ZlibEncoder.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 @@ -843,6 +1013,22 @@ SOURCE=..\..\Compress\XpressDecoder.h # End Source File # Begin Source File +SOURCE=..\..\Compress\XzDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\XzDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\XzEncoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\XzEncoder.h +# End Source File +# Begin Source File + SOURCE=..\..\Compress\ZDecoder.cpp # End Source File # Begin Source File @@ -1300,6 +1486,10 @@ SOURCE=..\..\..\..\C\XzIn.c # End Group # Begin Source File +SOURCE=..\..\..\..\C\7zBuf.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\7zBuf2.c # SUBTRACT CPP /YX /Yc /Yu # End Source File diff --git a/CPP/7zip/Bundles/Format7zF/resource.rc b/CPP/7zip/Bundles/Format7zF/resource.rc index 1caf7301..705814f5 100644 --- a/CPP/7zip/Bundles/Format7zF/resource.rc +++ b/CPP/7zip/Bundles/Format7zF/resource.rc @@ -1,6 +1,6 @@ #include "../../MyVersionInfo.rc" -MY_VERSION_INFO_DLL("7z Plugin", "7z") +MY_VERSION_INFO_DLL("7z Plugin" , "7z") 0 ICON "../../Archive/Icons/7z.ico" diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp index 178753e5..62d3a84c 100644 --- a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp +++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp @@ -4,6 +4,8 @@ #include <stdio.h> +#include "../../../../C/CpuArch.h" + #if (defined(_WIN32) || defined(OS2) || defined(MSDOS)) && !defined(UNDER_CE) #include <fcntl.h> #include <io.h> @@ -39,14 +41,16 @@ #include "../../UI/Console/BenchCon.h" #include "../../UI/Console/ConsoleClose.h" +bool g_LargePagesMode = false; + using namespace NCommandLineParser; static const unsigned kDictSizeLog = 24; -static const char *kCopyrightString = "\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n\n"; +#define kCopyrightString "\nLZMA " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n" -static const char *kHelpString = - "Usage: LZMA <command> [inputFile] [outputFile] [<switches>...]\n" +static const char * const kHelpString = + "Usage: lzma <command> [inputFile] [outputFile] [<switches>...]\n" "\n" "<command>\n" " e : Encode file\n" @@ -67,9 +71,9 @@ static const char *kHelpString = " -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"; +static const char * const kCantAllocate = "Can not allocate memory"; +static const char * const kReadError = "Read error"; +static const char * const kWriteError = "Write error"; namespace NKey { @@ -117,6 +121,21 @@ static const CSwitchForm kSwitchForms[] = }; +static void Convert_UString_to_AString(const UString &s, AString &temp) +{ + int codePage = CP_OEMCP; + /* + int g_CodePage = -1; + int codePage = g_CodePage; + if (codePage == -1) + codePage = CP_OEMCP; + if (codePage == CP_UTF8) + ConvertUnicodeToUTF8(s, temp); + else + */ + UnicodeStringToMultiByte2(temp, s, (UINT)codePage); +} + static void PrintErr(const char *s) { fputs(s, stderr); @@ -135,10 +154,12 @@ static void PrintError(const char *s) PrintErr_LF(s); } -static void PrintError2(const char *s1, const wchar_t *s2) +static void PrintError2(const char *s1, const UString &s2) { PrintError(s1); - PrintErr_LF(GetOemString(s2)); + AString a; + Convert_UString_to_AString(s2, a); + PrintErr_LF(a); } static void PrintError_int(const char *s, int code) @@ -208,7 +229,7 @@ public: #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 = +static const char * const kBackSpaces = BACK_STR " " BACK_STR; @@ -298,7 +319,7 @@ static int Error_HRESULT(const char *s, HRESULT res) static void AddProp(CObjectVector<CProperty> &props2, const char *name, const wchar_t *val) { CProperty &prop = props2.AddNew(); - prop.Name.SetFromAscii(name); + prop.Name = name; prop.Value = val; } @@ -322,10 +343,10 @@ static int main2(int numArgs, const char *args[]) for (int i = 1; i < numArgs; i++) commandStrings.Add(MultiByteToUnicodeString(args[i])); - CParser parser(ARRAY_SIZE(kSwitchForms)); + CParser parser; try { - if (!parser.ParseStrings(kSwitchForms, commandStrings)) + if (!parser.ParseStrings(kSwitchForms, ARRAY_SIZE(kSwitchForms), commandStrings)) { PrintError2(parser.ErrorMessage, parser.ErrorLine); return 1; @@ -376,7 +397,7 @@ static int main2(int numArgs, const char *args[]) AddProp(props2, "x", s); } - UString mf = L"BT4"; + UString mf ("BT4"); if (parser[NKey::kMatchFinder].ThereIs) mf = parser[NKey::kMatchFinder].PostStrings[0]; diff --git a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp index d828922f..3209a01c 100644 --- a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp +++ b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../../C/CpuArch.h" + #include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" @@ -37,8 +39,8 @@ HINSTANCE g_hInstance = 0; int g_CodePage = -1; extern CStdOutStream *g_StdStream; -static const char *kCopyrightString = -"\n7-Zip SFX " MY_VERSION_COPYRIGHT_DATE "\n"; +static const char * const kCopyrightString = +"\n7-Zip SFX " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n"; static const int kNumSwitches = 6; @@ -65,7 +67,6 @@ enum EEnum } /* static const char kRecursedIDChar = 'R'; -static const wchar_t *kRecursedPostCharSet = L"0-"; namespace NRecursedPostCharIndex { enum EEnum @@ -101,10 +102,10 @@ static const NRecursedType::EEnum kCommandRecursedDefault[kNumCommandForms] = // static const bool kTestExtractRecursedDefault = true; // static const bool kAddRecursedDefault = false; -static const wchar_t *kUniversalWildcard = L"*"; +static const char * const kUniversalWildcard = "*"; static const int kCommandIndex = 0; -static const char *kHelpString = +static const char * const kHelpString = "\nUsage: 7zSFX [<command>] [<switches>...] [<file_name>...]\n" "\n" "<Commands>\n" @@ -121,16 +122,16 @@ static const char *kHelpString = // --------------------------- // exception messages -static const char *kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError -// static const char *kIncorrectListFile = "Incorrect wildcard in listfile"; -static const char *kIncorrectWildcardInCommandLine = "Incorrect wildcard in command line"; +static const char * const kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError +// static const char * const kIncorrectListFile = "Incorrect wildcard in listfile"; +static const char * const kIncorrectWildcardInCommandLine = "Incorrect wildcard in command line"; // static const CSysString kFileIsNotArchiveMessageBefore = "File \""; // static const CSysString kFileIsNotArchiveMessageAfter = "\" is not archive"; -// static const char *kProcessArchiveMessage = " archive: "; +// static const char * const kProcessArchiveMessage = " archive: "; -static const char *kCantFindSFX = " cannot find sfx"; +static const char * const kCantFindSFX = " cannot find sfx"; namespace NCommandType { @@ -280,13 +281,16 @@ int Main2( #endif - commandStrings.Delete(0); + #ifndef UNDER_CE + if (commandStrings.Size() > 0) + commandStrings.Delete(0); + #endif - NCommandLineParser::CParser parser(kNumSwitches); + NCommandLineParser::CParser parser; try { - if (!parser.ParseStrings(kSwitchForms, commandStrings)) + if (!parser.ParseStrings(kSwitchForms, kNumSwitches, commandStrings)) { g_StdOut << "Command line error:" << endl << parser.ErrorMessage << endl @@ -331,7 +335,7 @@ int Main2( { if (nonSwitchStrings.Size() == curCommandIndex) - AddCommandLineWildcardToCensor(wildcardCensor, kUniversalWildcard, true, recursedType); + AddCommandLineWildcardToCensor(wildcardCensor, (UString)kUniversalWildcard, true, recursedType); for (; curCommandIndex < nonSwitchStrings.Size(); curCommandIndex++) { const UString &s = nonSwitchStrings[curCommandIndex]; diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp index 79330630..00e3ba53 100644 --- a/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp +++ b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp @@ -15,9 +15,9 @@ using namespace NWindows; using namespace NFile; using namespace NDir; -static LPCWSTR kCantDeleteFile = L"Can not delete output file"; -static LPCWSTR kCantOpenFile = L"Can not open output file"; -static LPCWSTR kUnsupportedMethod = L"Unsupported Method"; +static LPCSTR const kCantDeleteFile = "Can not delete output file"; +static LPCSTR const kCantOpenFile = "Can not open output file"; +static LPCSTR const kUnsupportedMethod = "Unsupported Method"; void CExtractCallbackImp::Init(IInArchive *archiveHandler, const FString &directoryPath, diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp index b1592993..e510e5c8 100644 --- a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp +++ b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp @@ -18,8 +18,8 @@ using namespace NWindows; using namespace NFile; using namespace NDir; -static LPCWSTR kCantFindArchive = L"Can not find archive file"; -static LPCWSTR kCantOpenArchive = L"Can not open the file as archive"; +static LPCSTR const kCantFindArchive = "Can not find archive file"; +static LPCSTR const kCantOpenArchive = "Can not open the file as archive"; struct CThreadExtracting { @@ -73,7 +73,7 @@ struct CThreadExtracting return; } - ExtractCallbackSpec->Init(ArchiveLink.GetArchive(), dirPath, L"Default", fi.MTime, 0); + ExtractCallbackSpec->Init(ArchiveLink.GetArchive(), dirPath, (UString)"Default", fi.MTime, 0); Result = ArchiveLink.GetArchive()->Extract(0, (UInt32)(Int32)-1 , BoolToInt(false), ExtractCallback); } diff --git a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp index aef2e196..0c302332 100644 --- a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp +++ b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp @@ -33,7 +33,7 @@ using namespace NDir; HINSTANCE g_hInstance; -static CFSTR kTempDirPrefix = FTEXT("7zS"); +static CFSTR const kTempDirPrefix = FTEXT("7zS"); #define _SHELL_EXECUTE @@ -169,7 +169,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, return 1; } - UString dirPrefix = L"." WSTRING_PATH_SEPARATOR; + UString dirPrefix ("." STRING_PATH_SEPARATOR); UString appLaunched; bool showProgress = true; if (!config.IsEmpty()) @@ -181,12 +181,12 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, ShowErrorMessage(L"Config failed"); return 1; } - UString friendlyName = GetTextConfigValue(pairs, L"Title"); - UString installPrompt = GetTextConfigValue(pairs, L"BeginPrompt"); - UString progress = GetTextConfigValue(pairs, L"Progress"); + UString friendlyName = GetTextConfigValue(pairs, "Title"); + UString installPrompt = GetTextConfigValue(pairs, "BeginPrompt"); + UString progress = GetTextConfigValue(pairs, "Progress"); if (progress.IsEqualTo_Ascii_NoCase("no")) showProgress = false; - int index = FindTextConfigItem(pairs, L"Directory"); + int index = FindTextConfigItem(pairs, "Directory"); if (index >= 0) dirPrefix = pairs[index].String; if (!installPrompt.IsEmpty() && !assumeYes) @@ -195,11 +195,11 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, MB_ICONQUESTION) != IDYES) return 0; } - appLaunched = GetTextConfigValue(pairs, L"RunProgram"); + appLaunched = GetTextConfigValue(pairs, "RunProgram"); #ifdef _SHELL_EXECUTE - executeFile = GetTextConfigValue(pairs, L"ExecuteFile"); - executeParameters = GetTextConfigValue(pairs, L"ExecuteParameters"); + executeFile = GetTextConfigValue(pairs, "ExecuteFile"); + executeParameters = GetTextConfigValue(pairs, "ExecuteParameters"); #endif } @@ -260,7 +260,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, #ifdef _SHELL_EXECUTE if (!executeFile.IsEmpty()) { - CSysString filePath = GetSystemString(executeFile); + CSysString filePath (GetSystemString(executeFile)); SHELLEXECUTEINFO execInfo; execInfo.cbSize = sizeof(execInfo); execInfo.fMask = SEE_MASK_NOCLOSEPROCESS @@ -278,7 +278,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, executeParameters += switches; } - CSysString parametersSys = GetSystemString(executeParameters); + CSysString parametersSys (GetSystemString(executeParameters)); if (parametersSys.IsEmpty()) execInfo.lpParameters = NULL; else @@ -337,7 +337,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, PROCESS_INFORMATION processInformation; - CSysString appLaunchedSys = GetSystemString(dirPrefix + appLaunched); + CSysString appLaunchedSys (GetSystemString(dirPrefix + appLaunched)); BOOL createResult = CreateProcess(NULL, (LPTSTR)(LPCTSTR)appLaunchedSys, NULL, NULL, FALSE, 0, NULL, NULL /*tempDir.GetPath() */, diff --git a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp index db7acfef..3c77356e 100644 --- a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp +++ b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp @@ -65,7 +65,7 @@ static DWORD GetDllVersion(LPCTSTR dllName) bool g_LVN_ITEMACTIVATE_Support = true; -static const wchar_t *kUnknownExceptionMessage = L"ERROR: Unknown Error!"; +static const wchar_t * const kUnknownExceptionMessage = L"ERROR: Unknown Error!"; void ErrorMessageForHRESULT(HRESULT res) { diff --git a/CPP/7zip/Common/CWrappers.cpp b/CPP/7zip/Common/CWrappers.cpp index a77b67e8..d85aa238 100644 --- a/CPP/7zip/Common/CWrappers.cpp +++ b/CPP/7zip/Common/CWrappers.cpp @@ -8,43 +8,61 @@ #include "StreamUtils.h" +SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) throw() +{ + switch (res) + { + case S_OK: return SZ_OK; + case E_OUTOFMEMORY: return SZ_ERROR_MEM; + case E_INVALIDARG: return SZ_ERROR_PARAM; + case E_ABORT: return SZ_ERROR_PROGRESS; + case S_FALSE: return SZ_ERROR_DATA; + case E_NOTIMPL: return SZ_ERROR_UNSUPPORTED; + } + return defaultRes; +} + + +HRESULT SResToHRESULT(SRes res) throw() +{ + switch (res) + { + case SZ_OK: return S_OK; + case SZ_ERROR_MEM: return E_OUTOFMEMORY; + case SZ_ERROR_PARAM: return E_INVALIDARG; + case SZ_ERROR_PROGRESS: return E_ABORT; + case SZ_ERROR_DATA: return S_FALSE; + case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; + // case SZ_ERROR_READ: return E_NOTIMPL; + } + return E_FAIL; +} + + #define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1) #define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x) -static SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize) throw() + +static SRes CompressProgress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize) throw() { - CCompressProgressWrap *p = (CCompressProgressWrap *)pp; + CCompressProgressWrap *p = CONTAINER_FROM_VTBL(pp, CCompressProgressWrap, vt); p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize)); - return (SRes)p->Res; + return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS); } -CCompressProgressWrap::CCompressProgressWrap(ICompressProgressInfo *progress) throw() +void CCompressProgressWrap::Init(ICompressProgressInfo *progress) throw() { - p.Progress = CompressProgress; + vt.Progress = CompressProgress; Progress = progress; Res = SZ_OK; } static const UInt32 kStreamStepSize = (UInt32)1 << 31; -SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) +static SRes MyRead(const ISeqInStream *pp, void *data, size_t *size) throw() { - switch (res) - { - case S_OK: return SZ_OK; - case E_OUTOFMEMORY: return SZ_ERROR_MEM; - case E_INVALIDARG: return SZ_ERROR_PARAM; - case E_ABORT: return SZ_ERROR_PROGRESS; - case S_FALSE: return SZ_ERROR_DATA; - case E_NOTIMPL: return SZ_ERROR_UNSUPPORTED; - } - return defaultRes; -} - -static SRes MyRead(void *object, void *data, size_t *size) throw() -{ - CSeqInStreamWrap *p = (CSeqInStreamWrap *)object; + CSeqInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeqInStreamWrap, vt); UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); p->Res = (p->Stream->Read(data, curSize, &curSize)); *size = curSize; @@ -54,9 +72,9 @@ static SRes MyRead(void *object, void *data, size_t *size) throw() return HRESULT_To_SRes(p->Res, SZ_ERROR_READ); } -static size_t MyWrite(void *object, const void *data, size_t size) throw() +static size_t MyWrite(const ISeqOutStream *pp, const void *data, size_t size) throw() { - CSeqOutStreamWrap *p = (CSeqOutStreamWrap *)object; + CSeqOutStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeqOutStreamWrap, vt); if (p->Stream) { p->Res = WriteStream(p->Stream, data, size); @@ -69,47 +87,36 @@ static size_t MyWrite(void *object, const void *data, size_t size) throw() return size; } -CSeqInStreamWrap::CSeqInStreamWrap(ISequentialInStream *stream) throw() + +void CSeqInStreamWrap::Init(ISequentialInStream *stream) throw() { - p.Read = MyRead; + vt.Read = MyRead; Stream = stream; Processed = 0; + Res = S_OK; } -CSeqOutStreamWrap::CSeqOutStreamWrap(ISequentialOutStream *stream) throw() +void CSeqOutStreamWrap::Init(ISequentialOutStream *stream) throw() { - p.Write = MyWrite; + vt.Write = MyWrite; Stream = stream; Res = SZ_OK; Processed = 0; } -HRESULT SResToHRESULT(SRes res) throw() -{ - switch (res) - { - case SZ_OK: return S_OK; - case SZ_ERROR_MEM: return E_OUTOFMEMORY; - case SZ_ERROR_PARAM: return E_INVALIDARG; - case SZ_ERROR_PROGRESS: return E_ABORT; - case SZ_ERROR_DATA: return S_FALSE; - case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; - } - return E_FAIL; -} -static SRes InStreamWrap_Read(void *pp, void *data, size_t *size) throw() +static SRes InStreamWrap_Read(const ISeekInStream *pp, void *data, size_t *size) throw() { - CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp; + CSeekInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeekInStreamWrap, vt); UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); p->Res = p->Stream->Read(data, curSize, &curSize); *size = curSize; return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ; } -static SRes InStreamWrap_Seek(void *pp, Int64 *offset, ESzSeek origin) throw() +static SRes InStreamWrap_Seek(const ISeekInStream *pp, Int64 *offset, ESzSeek origin) throw() { - CSeekInStreamWrap *p = (CSeekInStreamWrap *)pp; + CSeekInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeekInStreamWrap, vt); UInt32 moveMethod; switch (origin) { @@ -124,11 +131,11 @@ static SRes InStreamWrap_Seek(void *pp, Int64 *offset, ESzSeek origin) throw() return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ; } -CSeekInStreamWrap::CSeekInStreamWrap(IInStream *stream) throw() +void CSeekInStreamWrap::Init(IInStream *stream) throw() { Stream = stream; - p.Read = InStreamWrap_Read; - p.Seek = InStreamWrap_Seek; + vt.Read = InStreamWrap_Read; + vt.Seek = InStreamWrap_Seek; Res = S_OK; } @@ -168,9 +175,9 @@ Byte CByteInBufWrap::ReadByteFromNewBlock() throw() return 0; } -static Byte Wrap_ReadByte(void *pp) throw() +static Byte Wrap_ReadByte(const IByteIn *pp) throw() { - CByteInBufWrap *p = (CByteInBufWrap *)pp; + CByteInBufWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CByteInBufWrap, vt); if (p->Cur != p->Lim) return *p->Cur++; return p->ReadByteFromNewBlock(); @@ -178,7 +185,7 @@ static Byte Wrap_ReadByte(void *pp) throw() CByteInBufWrap::CByteInBufWrap(): Buf(0) { - p.Read = Wrap_ReadByte; + vt.Read = Wrap_ReadByte; } @@ -214,9 +221,9 @@ HRESULT CByteOutBufWrap::Flush() throw() return Res; } -static void Wrap_WriteByte(void *pp, Byte b) throw() +static void Wrap_WriteByte(const IByteOut *pp, Byte b) throw() { - CByteOutBufWrap *p = (CByteOutBufWrap *)pp; + CByteOutBufWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CByteOutBufWrap, vt); Byte *dest = p->Cur; *dest = b; p->Cur = ++dest; @@ -226,5 +233,5 @@ static void Wrap_WriteByte(void *pp, Byte b) throw() CByteOutBufWrap::CByteOutBufWrap() throw(): Buf(0) { - p.Write = Wrap_WriteByte; + vt.Write = Wrap_WriteByte; } diff --git a/CPP/7zip/Common/CWrappers.h b/CPP/7zip/Common/CWrappers.h index acadc170..e5c890d8 100644 --- a/CPP/7zip/Common/CWrappers.h +++ b/CPP/7zip/Common/CWrappers.h @@ -6,49 +6,54 @@ #include "../ICoder.h" #include "../../Common/MyCom.h" +SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) throw(); +HRESULT SResToHRESULT(SRes res) throw(); + struct CCompressProgressWrap { - ICompressProgress p; + ICompressProgress vt; ICompressProgressInfo *Progress; HRESULT Res; - CCompressProgressWrap(ICompressProgressInfo *progress) throw(); + void Init(ICompressProgressInfo *progress) throw(); }; + struct CSeqInStreamWrap { - ISeqInStream p; + ISeqInStream vt; ISequentialInStream *Stream; HRESULT Res; UInt64 Processed; - CSeqInStreamWrap(ISequentialInStream *stream) throw(); + void Init(ISequentialInStream *stream) throw(); }; + struct CSeekInStreamWrap { - ISeekInStream p; + ISeekInStream vt; IInStream *Stream; HRESULT Res; - CSeekInStreamWrap(IInStream *stream) throw(); + void Init(IInStream *stream) throw(); }; + struct CSeqOutStreamWrap { - ISeqOutStream p; + ISeqOutStream vt; ISequentialOutStream *Stream; HRESULT Res; UInt64 Processed; - CSeqOutStreamWrap(ISequentialOutStream *stream) throw(); + void Init(ISequentialOutStream *stream) throw(); }; -HRESULT SResToHRESULT(SRes res) throw(); struct CByteInBufWrap { - IByteIn p; + IByteIn vt; const Byte *Cur; const Byte *Lim; Byte *Buf; @@ -79,9 +84,10 @@ struct CByteInBufWrap } }; + struct CByteOutBufWrap { - IByteOut p; + IByteOut vt; Byte *Cur; const Byte *Lim; Byte *Buf; diff --git a/CPP/7zip/Common/FilePathAutoRename.cpp b/CPP/7zip/Common/FilePathAutoRename.cpp index d186e599..0904e696 100644 --- a/CPP/7zip/Common/FilePathAutoRename.cpp +++ b/CPP/7zip/Common/FilePathAutoRename.cpp @@ -2,9 +2,6 @@ #include "StdAfx.h" -#include "../../Common/Defs.h" -#include "../../Common/IntToString.h" - #include "../../Windows/FileFind.h" #include "FilePathAutoRename.h" @@ -14,10 +11,8 @@ using namespace NWindows; static bool MakeAutoName(const FString &name, const FString &extension, UInt32 value, FString &path) { - char temp[16]; - ConvertUInt32ToString(value, temp); path = name; - path.AddAscii(temp); + path.Add_UInt32(value); path += extension; return NFile::NFind::DoesFileOrDirExist(path); } @@ -34,7 +29,7 @@ bool AutoRenamePath(FString &path) name.DeleteFrom(dotPos); extension = path.Ptr(dotPos); } - name += FTEXT('_'); + name += '_'; FString temp; diff --git a/CPP/7zip/Common/FilterCoder.h b/CPP/7zip/Common/FilterCoder.h index 224ff2ca..85963f59 100644 --- a/CPP/7zip/Common/FilterCoder.h +++ b/CPP/7zip/Common/FilterCoder.h @@ -153,6 +153,15 @@ public: ~C_OutStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); } }; + class C_Filter_Releaser + { + public: + CFilterCoder *FilterCoder; + C_Filter_Releaser(): FilterCoder(NULL) {} + ~C_Filter_Releaser() { if (FilterCoder) FilterCoder->Filter.Release(); } + }; + + MY_QUERYINTERFACE_BEGIN2(ICompressCoder) MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize) diff --git a/CPP/7zip/Common/InBuffer.h b/CPP/7zip/Common/InBuffer.h index 4b8662bb..4b9c2c32 100644 --- a/CPP/7zip/Common/InBuffer.h +++ b/CPP/7zip/Common/InBuffer.h @@ -59,7 +59,8 @@ public: } void Init() throw(); - + + MY_FORCE_INLINE bool ReadByte(Byte &b) { if (_buf >= _bufLim) @@ -68,6 +69,7 @@ public: return true; } + MY_FORCE_INLINE Byte ReadByte() { if (_buf >= _bufLim) diff --git a/CPP/7zip/Common/InOutTempBuffer.cpp b/CPP/7zip/Common/InOutTempBuffer.cpp index 85d6a1aa..7523f3a3 100644 --- a/CPP/7zip/Common/InOutTempBuffer.cpp +++ b/CPP/7zip/Common/InOutTempBuffer.cpp @@ -15,7 +15,7 @@ using namespace NDir; static const size_t kTempBufSize = (1 << 20); -static CFSTR kTempFilePrefixString = FTEXT("7zt"); +#define kTempFilePrefixString FTEXT("7zt") CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { } diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp index 09f7b29c..ef6f2e3f 100644 --- a/CPP/7zip/Common/MethodProps.cpp +++ b/CPP/7zip/Common/MethodProps.cpp @@ -8,9 +8,9 @@ using namespace NWindows; -bool StringToBool(const UString &s, bool &res) +bool StringToBool(const wchar_t *s, bool &res) { - if (s.IsEmpty() || (s[0] == '+' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "ON")) + if (s[0] == 0 || (s[0] == '+' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "ON")) { res = true; return true; @@ -95,7 +95,7 @@ static HRESULT StringToDictSize(const UString &s, NCOM::CPropVariant &destProp) { const wchar_t *end; UInt32 number = ConvertStringToUInt32(s, &end); - unsigned numDigits = (unsigned)(end - s); + unsigned numDigits = (unsigned)(end - s.Ptr()); if (numDigits == 0 || s.Len() > numDigits + 1) return E_INVALIDARG; @@ -144,17 +144,29 @@ static HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, NCOM::CPropVaria return S_OK; } if (prop.vt == VT_BSTR) - return StringToDictSize(prop.bstrVal, destProp); + { + UString s; + s = prop.bstrVal; + return StringToDictSize(s, destProp); + } return E_INVALIDARG; } -void CProps::AddProp32(PROPID propid, UInt32 level) +void CProps::AddProp32(PROPID propid, UInt32 val) { CProp &prop = Props.AddNew(); prop.IsOptional = true; prop.Id = propid; - prop.Value = (UInt32)level; + prop.Value = (UInt32)val; +} + +void CProps::AddPropBool(PROPID propid, bool val) +{ + CProp &prop = Props.AddNew(); + prop.IsOptional = true; + prop.Id = propid; + prop.Value = val; } class CCoderProps @@ -454,5 +466,7 @@ HRESULT COneMethodInfo::ParseMethodFromPROPVARIANT(const UString &realName, cons // -m{N}=method if (value.vt != VT_BSTR) return E_INVALIDARG; - return ParseMethodFromString(value.bstrVal); + UString s; + s = value.bstrVal; + return ParseMethodFromString(s); } diff --git a/CPP/7zip/Common/MethodProps.h b/CPP/7zip/Common/MethodProps.h index 765e425d..b634a04e 100644 --- a/CPP/7zip/Common/MethodProps.h +++ b/CPP/7zip/Common/MethodProps.h @@ -5,11 +5,13 @@ #include "../../Common/MyString.h" +#include "../../Windows/Defs.h" + #include "../../Windows/PropVariant.h" #include "../ICoder.h" -bool StringToBool(const UString &s, bool &res); +bool StringToBool(const wchar_t *s, bool &res); HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest); unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number); HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); @@ -38,7 +40,9 @@ struct CProps return false; } - void AddProp32(PROPID propid, UInt32 level); + void AddProp32(PROPID propid, UInt32 val); + + void AddPropBool(PROPID propid, bool val); void AddProp_Ascii(PROPID propid, const char *s) { @@ -99,6 +103,18 @@ public: return level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)); } + bool Get_Lzma_Eos() const + { + int i = FindProp(NCoderPropID::kEndMarker); + if (i >= 0) + { + const NWindows::NCOM::CPropVariant &val = Props[i].Value; + if (val.vt == VT_BOOL) + return VARIANT_BOOLToBool(val.boolVal); + } + return false; + } + bool Are_Lzma_Model_Props_Defined() const { if (FindProp(NCoderPropID::kPosStateBits) >= 0) return true; @@ -107,18 +123,52 @@ public: return false; } - UInt32 Get_Lzma_NumThreads(bool &fixedNumber) const + UInt32 Get_Lzma_NumThreads() const + { + if (Get_Lzma_Algo() == 0) + return 1; + int numThreads = Get_NumThreads(); + if (numThreads >= 0) + return numThreads < 2 ? 1 : 2; + return 2; + } + + UInt32 Get_Lzma2_NumThreads(bool &fixedNumber) const { fixedNumber = false; int numThreads = Get_NumThreads(); if (numThreads >= 0) { fixedNumber = true; - return numThreads < 2 ? 1 : 2; + if (numThreads < 1) return 1; + const unsigned kNumLzma2ThreadsMax = 32; + if (numThreads > kNumLzma2ThreadsMax) return kNumLzma2ThreadsMax; + return numThreads; } - return Get_Lzma_Algo() == 0 ? 1 : 2; + return 1; } + UInt64 Get_Lzma2_BlockSize() const + { + int i = FindProp(NCoderPropID::kBlockSize); + if (i >= 0) + { + const NWindows::NCOM::CPropVariant &val = Props[i].Value; + if (val.vt == VT_UI4) return val.ulVal; + if (val.vt == VT_UI8) return val.uhVal.QuadPart; + } + + UInt32 dictSize = Get_Lzma_DicSize(); + UInt64 blockSize = (UInt64)dictSize << 2; + const UInt32 kMinSize = (UInt32)1 << 20; + const UInt32 kMaxSize = (UInt32)1 << 28; + if (blockSize < kMinSize) blockSize = kMinSize; + if (blockSize > kMaxSize) blockSize = kMaxSize; + if (blockSize < dictSize) blockSize = dictSize; + return blockSize; + } + + UInt32 Get_BZip2_NumThreads(bool &fixedNumber) const { fixedNumber = false; @@ -127,7 +177,8 @@ public: { fixedNumber = true; if (numThreads < 1) return 1; - if (numThreads > 64) return 64; + const unsigned kNumBZip2ThreadsMax = 64; + if (numThreads > kNumBZip2ThreadsMax) return kNumBZip2ThreadsMax; return numThreads; } return 1; @@ -170,6 +221,12 @@ public: AddProp32(NCoderPropID::kNumThreads, numThreads); } + void AddProp_EndMarker_if_NotFound(bool eos) + { + if (FindProp(NCoderPropID::kEndMarker) < 0) + AddPropBool(NCoderPropID::kEndMarker, eos); + } + HRESULT ParseParamsFromString(const UString &srcString); HRESULT ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value); }; diff --git a/CPP/7zip/Common/OutBuffer.h b/CPP/7zip/Common/OutBuffer.h index 3bdfb87c..d7ca9f6a 100644 --- a/CPP/7zip/Common/OutBuffer.h +++ b/CPP/7zip/Common/OutBuffer.h @@ -47,8 +47,11 @@ public: void WriteByte(Byte b) { - _buf[_pos++] = b; - if (_pos == _limitPos) + UInt32 pos = _pos; + _buf[pos] = b; + pos++; + _pos = pos; + if (pos == _limitPos) FlushWithCheck(); } void WriteBytes(const void *data, size_t size) diff --git a/CPP/7zip/Compress/BZip2Crc.cpp b/CPP/7zip/Compress/BZip2Crc.cpp index 4e4741f4..bf8e540f 100644 --- a/CPP/7zip/Compress/BZip2Crc.cpp +++ b/CPP/7zip/Compress/BZip2Crc.cpp @@ -13,8 +13,8 @@ void CBZip2Crc::InitTable() for (UInt32 i = 0; i < 256; i++) { UInt32 r = (i << 24); - for (int j = 8; j > 0; j--) - r = (r & 0x80000000) ? ((r << 1) ^ kBZip2CrcPoly) : (r << 1); + for (unsigned j = 0; j < 8; j++) + r = (r << 1) ^ (kBZip2CrcPoly & ((UInt32)0 - (r >> 31))); Table[i] = r; } } diff --git a/CPP/7zip/Compress/BZip2Decoder.cpp b/CPP/7zip/Compress/BZip2Decoder.cpp index 56f1b02f..62fa26d0 100644 --- a/CPP/7zip/Compress/BZip2Decoder.cpp +++ b/CPP/7zip/Compress/BZip2Decoder.cpp @@ -2,20 +2,47 @@ #include "StdAfx.h" +// #include "CopyCoder.h" + +/* +#include <stdio.h> +#include "../../../C/CpuTicks.h" +*/ +#define TICKS_START +#define TICKS_UPDATE(n) + + +/* +#define PRIN(s) printf(s "\n"); fflush(stdout); +#define PRIN_VAL(s, val) printf(s " = %u \n", val); fflush(stdout); +*/ + +#define PRIN(s) +#define PRIN_VAL(s, val) + +#define PRIN_MT(s) PRIN(" " s) + #include "../../../C/Alloc.h" +#include "../Common/StreamUtils.h" + #include "BZip2Decoder.h" -#include "Mtf8.h" + namespace NCompress { namespace NBZip2 { -#undef NO_INLINE -#define NO_INLINE - -static const UInt32 kNumThreadsMax = 4; +// #undef NO_INLINE +#define NO_INLINE MY_NO_INLINE + +#define BZIP2_BYTE_MODE + + +static const UInt32 kInBufSize = (UInt32)1 << 17; +static const size_t kOutBufSize = (size_t)1 << 20; + +static const UInt32 kProgressStep = (UInt32)1 << 16; -static const UInt32 kBufferSize = (1 << 17); static const UInt16 kRandNums[512] = { 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, @@ -72,923 +99,1643 @@ static const UInt16 kRandNums[512] = { 936, 638 }; -bool CState::Alloc() + + +enum EState +{ + STATE_STREAM_SIGNATURE, + STATE_BLOCK_SIGNATURE, + + STATE_BLOCK_START, + STATE_ORIG_BITS, + STATE_IN_USE, + STATE_IN_USE2, + STATE_NUM_TABLES, + STATE_NUM_SELECTORS, + STATE_SELECTORS, + STATE_LEVELS, + + STATE_BLOCK_SYMBOLS, + + STATE_STREAM_FINISHED +}; + + +#define UPDATE_VAL_2(val) { \ + val |= (UInt32)(*_buf) << (24 - _numBits); \ + _numBits += 8; \ + _buf++; \ +} + +#define UPDATE_VAL UPDATE_VAL_2(VAL) + +#define READ_BITS(res, num) { \ + while (_numBits < num) { \ + if (_buf == _lim) return SZ_OK; \ + UPDATE_VAL_2(_value) } \ + res = _value >> (32 - num); \ + _value <<= num; \ + _numBits -= num; \ +} + +#define READ_BITS_8(res, num) { \ + if (_numBits < num) { \ + if (_buf == _lim) return SZ_OK; \ + UPDATE_VAL_2(_value) } \ + res = _value >> (32 - num); \ + _value <<= num; \ + _numBits -= num; \ +} + +#define READ_BIT(res) READ_BITS_8(res, 1) + + + +#define VAL _value2 +#define BLOCK_SIZE blockSize2 +#define RUN_COUNTER runCounter2 + +#define LOAD_LOCAL \ + UInt32 VAL = this->_value; \ + UInt32 BLOCK_SIZE = this->blockSize; \ + UInt32 RUN_COUNTER = this->runCounter; \ + +#define SAVE_LOCAL \ + this->_value = VAL; \ + this->blockSize = BLOCK_SIZE; \ + this->runCounter = RUN_COUNTER; \ + + + +SRes CBitDecoder::ReadByte(int &b) +{ + b = -1; + READ_BITS_8(b, 8); + return SZ_OK; +} + + +NO_INLINE +SRes CBase::ReadStreamSignature2() { - if (!Counters) - Counters = (UInt32 *)::BigAlloc((256 + kBlockSizeMax) * sizeof(UInt32)); - return (Counters != 0); + for (;;) + { + unsigned b; + READ_BITS_8(b, 8); + + if ( state2 == 0 && b != kArSig0 + || state2 == 1 && b != kArSig1 + || state2 == 2 && b != kArSig2 + || state2 == 3 && (b <= kArSig3 || b > kArSig3 + kBlockSizeMultMax)) + return SZ_ERROR_DATA; + state2++; + + if (state2 == 4) + { + blockSizeMax = (UInt32)(b - kArSig3) * kBlockSizeStep; + CombinedCrc.Init(); + state = STATE_BLOCK_SIGNATURE; + state2 = 0; + return SZ_OK; + } + } } -void CState::Free() + +bool IsEndSig(const Byte *p) throw() { - ::BigFree(Counters); - Counters = 0; + return + p[0] == kFinSig0 && + p[1] == kFinSig1 && + p[2] == kFinSig2 && + p[3] == kFinSig3 && + p[4] == kFinSig4 && + p[5] == kFinSig5; } -Byte CDecoder::ReadByte() { return (Byte)Base.ReadBits(8); } +bool IsBlockSig(const Byte *p) throw() +{ + return + p[0] == kBlockSig0 && + p[1] == kBlockSig1 && + p[2] == kBlockSig2 && + p[3] == kBlockSig3 && + p[4] == kBlockSig4 && + p[5] == kBlockSig5; +} -UInt32 CBase::ReadBits(unsigned numBits) { return BitDecoder.ReadBits(numBits); } -unsigned CBase::ReadBit() { return (unsigned)BitDecoder.ReadBits(1); } -HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps *props) +NO_INLINE +SRes CBase::ReadBlockSignature2() { - NumBlocks++; + while (state2 < 10) + { + unsigned b; + READ_BITS_8(b, 8); + temp[state2] = (Byte)b; + state2++; + } - if (props->randMode) - props->randMode = ReadBit() ? true : false; - props->origPtr = ReadBits(kNumOrigBits); + crc = 0; + for (unsigned i = 0; i < 4; i++) + { + crc <<= 8; + crc |= temp[6 + i]; + } + + if (IsBlockSig(temp)) + { + if (!IsBz) + NumStreams++; + NumBlocks++; + IsBz = true; + CombinedCrc.Update(crc); + state = STATE_BLOCK_START; + return SZ_OK; + } - // in original code it compares OrigPtr to (UInt32)(10 + blockSizeMax)) : why ? - if (props->origPtr >= blockSizeMax) - return S_FALSE; + if (!IsEndSig(temp)) + return SZ_ERROR_DATA; + + if (!IsBz) + NumStreams++; + IsBz = true; - CMtf8Decoder mtf; - mtf.StartInit(); + if (_value != 0) + MinorError = true; + + AlignToByte(); + + state = STATE_STREAM_FINISHED; + if (crc != CombinedCrc.GetDigest()) + { + StreamCrcError = true; + return SZ_ERROR_DATA; + } + return SZ_OK; +} + + +NO_INLINE +SRes CBase::ReadBlock2() +{ + if (state != STATE_BLOCK_SYMBOLS) { + PRIN("ReadBlock2") + + if (state == STATE_BLOCK_START) + { + if (Props.randMode) + { + READ_BIT(Props.randMode); + } + state = STATE_ORIG_BITS; + // g_Tick = GetCpuTicks(); + } + + if (state == STATE_ORIG_BITS) + { + READ_BITS(Props.origPtr, kNumOrigBits); + if (Props.origPtr >= blockSizeMax) + return SZ_ERROR_DATA; + state = STATE_IN_USE; + } - unsigned numInUse = 0; - { - Byte inUse16[16]; - unsigned i; - for (i = 0; i < 16; i++) - inUse16[i] = (Byte)ReadBit(); - for (i = 0; i < 256; i++) - if (inUse16[i >> 4]) + // why original code compares origPtr to (UInt32)(10 + blockSizeMax)) ? + + if (state == STATE_IN_USE) + { + READ_BITS(state2, 16); + state = STATE_IN_USE2; + state3 = 0; + numInUse = 0; + mtf.StartInit(); + } + + if (state == STATE_IN_USE2) + { + for (; state3 < 256; state3++) + if (state2 & ((UInt32)0x8000 >> (state3 >> 4))) { - if (ReadBit()) - mtf.Add(numInUse++, (Byte)i); + unsigned b; + READ_BIT(b); + if (b) + mtf.Add(numInUse++, (Byte)state3); } if (numInUse == 0) - return S_FALSE; - // mtf.Init(numInUse); + return SZ_ERROR_DATA; + state = STATE_NUM_TABLES; } - unsigned alphaSize = numInUse + 2; - unsigned numTables = ReadBits(kNumTablesBits); - if (numTables < kNumTablesMin || numTables > kNumTablesMax) - return S_FALSE; - UInt32 numSelectors = ReadBits(kNumSelectorsBits); - if (numSelectors < 1 || numSelectors > kNumSelectorsMax) - return S_FALSE; - + if (state == STATE_NUM_TABLES) { - Byte mtfPos[kNumTablesMax]; - unsigned t = 0; - do - mtfPos[t] = (Byte)t; - while (++t < numTables); - UInt32 i = 0; - do - { - unsigned j = 0; - while (ReadBit()) - if (++j >= numTables) - return S_FALSE; - Byte tmp = mtfPos[j]; - for (;j > 0; j--) - mtfPos[j] = mtfPos[j - 1]; - m_Selectors[i] = mtfPos[0] = tmp; - } - while (++i < numSelectors); + READ_BITS_8(numTables, kNumTablesBits); + state = STATE_NUM_SELECTORS; + if (numTables < kNumTablesMin || numTables > kNumTablesMax) + return SZ_ERROR_DATA; + } + + if (state == STATE_NUM_SELECTORS) + { + READ_BITS(numSelectors, kNumSelectorsBits); + state = STATE_SELECTORS; + state2 = 0x543210; + state3 = 0; + state4 = 0; + if (numSelectors == 0 || numSelectors > kNumSelectorsMax) + return SZ_ERROR_DATA; } - unsigned t = 0; - do + if (state == STATE_SELECTORS) { - Byte lens[kMaxAlphaSize]; - unsigned len = (unsigned)ReadBits(kNumLevelsBits); - unsigned i; - for (i = 0; i < alphaSize; i++) + const unsigned kMtfBits = 4; + const UInt32 kMtfMask = (1 << kMtfBits) - 1; + do { for (;;) { - if (len < 1 || len > kMaxHuffmanLen) - return S_FALSE; - if (!ReadBit()) + unsigned b; + READ_BIT(b); + if (!b) break; - len++; - len -= (ReadBit() << 1); + if (++state4 >= numTables) + return SZ_ERROR_DATA; } - lens[i] = (Byte)len; + UInt32 tmp = (state2 >> (kMtfBits * state4)) & kMtfMask; + UInt32 mask = ((UInt32)1 << ((state4 + 1) * kMtfBits)) - 1; + state4 = 0; + state2 = ((state2 << kMtfBits) & mask) | (state2 & ~mask) | tmp; + selectors[state3] = (Byte)tmp; } - for (; i < kMaxAlphaSize; i++) - lens[i] = 0; - if (!m_HuffmanDecoders[t].Build(lens)) - return S_FALSE; + while (++state3 < numSelectors); + + state = STATE_LEVELS; + state2 = 0; + state3 = 0; } - while (++t < numTables); + if (state == STATE_LEVELS) { - for (unsigned i = 0; i < 256; i++) - charCounters[i] = 0; + do + { + if (state3 == 0) + { + READ_BITS_8(state3, kNumLevelsBits); + state4 = 0; + state5 = 0; + } + const unsigned alphaSize = numInUse + 2; + for (; state4 < alphaSize; state4++) + { + for (;;) + { + if (state3 < 1 || state3 > kMaxHuffmanLen) + return SZ_ERROR_DATA; + + if (state5 == 0) + { + unsigned b; + READ_BIT(b); + if (!b) + break; + } + + state5 = 1; + unsigned b; + READ_BIT(b); + + state5 = 0; + state3++; + state3 -= (b << 1); + } + lens[state4] = (Byte)state3; + state5 = 0; + } + /* + for (unsigned i = state4; i < kMaxAlphaSize; i++) + lens[i] = 0; + */ + if (!huffs[state2].BuildFull(lens, state4)) + return SZ_ERROR_DATA; + state3 = 0; + } + while (++state2 < numTables); + + { + UInt32 *counters = this->Counters; + for (unsigned i = 0; i < 256; i++) + counters[i] = 0; + } + + state = STATE_BLOCK_SYMBOLS; + + groupIndex = 0; + groupSize = kGroupSize; + runPower = 0; + runCounter = 0; + blockSize = 0; } - UInt32 blockSize = 0; + if (state != STATE_BLOCK_SYMBOLS) + return SZ_ERROR_DATA; + + // g_Ticks[3] += GetCpuTicks() - g_Tick; + + } + { - UInt32 groupIndex = 0; - UInt32 groupSize = 0; - CHuffmanDecoder *huffmanDecoder = 0; - unsigned runPower = 0; - UInt32 runCounter = 0; - + LOAD_LOCAL + const CHuffmanDecoder *huff = &huffs[selectors[groupIndex]]; + for (;;) { if (groupSize == 0) { - if (groupIndex >= numSelectors) - return S_FALSE; + if (++groupIndex >= numSelectors) + return SZ_ERROR_DATA; + huff = &huffs[selectors[groupIndex]]; groupSize = kGroupSize; - huffmanDecoder = &m_HuffmanDecoders[m_Selectors[groupIndex++]]; } + + if (_numBits <= 8 && + _buf != _lim) { UPDATE_VAL + if (_buf != _lim) { UPDATE_VAL + if (_buf != _lim) { UPDATE_VAL }}} + + UInt32 sym; + UInt32 val = VAL >> (32 - kMaxHuffmanLen); + if (val >= huff->_limits[kNumTableBits]) + { + if (_numBits <= kMaxHuffmanLen && _buf != _lim) { UPDATE_VAL + if (_numBits <= kMaxHuffmanLen && _buf != _lim) { UPDATE_VAL }} + + val = VAL >> (32 - kMaxHuffmanLen); + unsigned len; + for (len = kNumTableBits + 1; val >= huff->_limits[len]; len++); + /* + if (len > kNumBitsMax) + return SZ_ERROR_DATA; + */ + if (_numBits < len) + { + SAVE_LOCAL + return SZ_OK; + } + sym = huff->_symbols[huff->_poses[len] + ((val - huff->_limits[(size_t)len - 1]) >> (kNumBitsMax - len))]; + VAL <<= len; + _numBits -= len; + } + else + { + sym = huff->_lens[val >> (kMaxHuffmanLen - kNumTableBits)]; + unsigned len = (sym & NHuffman::kPairLenMask); + sym >>= NHuffman::kNumPairLenBits; + if (_numBits < len) + { + SAVE_LOCAL + return SZ_OK; + } + VAL <<= len; + _numBits -= len; + } + groupSize--; - - if (BitDecoder.ExtraBitsWereRead_Fast()) - break; - UInt32 nextSym = huffmanDecoder->Decode(&BitDecoder); - - if (nextSym < 2) + if (sym < 2) { - runCounter += ((UInt32)(nextSym + 1) << runPower++); - if (blockSizeMax - blockSize < runCounter) - return S_FALSE; + RUN_COUNTER += ((UInt32)(sym + 1) << runPower); + runPower++; + if (blockSizeMax - BLOCK_SIZE < RUN_COUNTER) + return SZ_ERROR_DATA; continue; } - if (runCounter != 0) + + UInt32 *counters = this->Counters; + if (RUN_COUNTER != 0) { - UInt32 b = (UInt32)mtf.GetHead(); - charCounters[b] += runCounter; - do - charCounters[256 + blockSize++] = b; - while (--runCounter != 0); + UInt32 b = (UInt32)(mtf.Buf[0] & 0xFF); + counters[b] += RUN_COUNTER; runPower = 0; + #ifdef BZIP2_BYTE_MODE + Byte *dest = (Byte *)(&counters[256 + kBlockSizeMax]) + BLOCK_SIZE; + const Byte *limit = dest + RUN_COUNTER; + BLOCK_SIZE += RUN_COUNTER; + RUN_COUNTER = 0; + do + { + dest[0] = (Byte)b; + dest[1] = (Byte)b; + dest[2] = (Byte)b; + dest[3] = (Byte)b; + dest += 4; + } + while (dest < limit); + #else + UInt32 *dest = &counters[256 + BLOCK_SIZE]; + const UInt32 *limit = dest + RUN_COUNTER; + BLOCK_SIZE += RUN_COUNTER; + RUN_COUNTER = 0; + do + { + dest[0] = b; + dest[1] = b; + dest[2] = b; + dest[3] = b; + dest += 4; + } + while (dest < limit); + #endif } - if (nextSym <= (UInt32)numInUse) + + sym -= 1; + if (sym < numInUse) { - UInt32 b = (UInt32)mtf.GetAndMove((unsigned)nextSym - 1); - if (blockSize >= blockSizeMax) - return S_FALSE; - charCounters[b]++; - charCounters[256 + blockSize++] = b; + if (BLOCK_SIZE >= blockSizeMax) + return SZ_ERROR_DATA; + + // UInt32 b = (UInt32)mtf.GetAndMove((unsigned)sym); + + const unsigned lim = sym >> MTF_MOVS; + const unsigned pos = (sym & MTF_MASK) << 3; + CMtfVar next = mtf.Buf[lim]; + CMtfVar prev = (next >> pos) & 0xFF; + + #ifdef BZIP2_BYTE_MODE + ((Byte *)(counters + 256 + kBlockSizeMax))[BLOCK_SIZE++] = (Byte)prev; + #else + (counters + 256)[BLOCK_SIZE++] = (UInt32)prev; + #endif + counters[prev]++; + + CMtfVar *m = mtf.Buf; + CMtfVar *mLim = m + lim; + if (lim != 0) + { + do + { + CMtfVar n0 = *m; + *m = (n0 << 8) | prev; + prev = (n0 >> (MTF_MASK << 3)); + } + while (++m != mLim); + } + + CMtfVar mask = (((CMtfVar)0x100 << pos) - 1); + *mLim = (next & ~mask) | (((next << 8) | prev) & mask); + continue; } - else if (nextSym == (UInt32)numInUse + 1) - break; - else - return S_FALSE; + + if (sym != numInUse) + return SZ_ERROR_DATA; + break; } - if (BitDecoder.ExtraBitsWereRead()) - return S_FALSE; + // we write additional item that will be read in DecodeBlock1 for prefetching + #ifdef BZIP2_BYTE_MODE + ((Byte *)(Counters + 256 + kBlockSizeMax))[BLOCK_SIZE] = 0; + #else + (counters + 256)[BLOCK_SIZE] = 0; + #endif + + SAVE_LOCAL + Props.blockSize = blockSize; + state = STATE_BLOCK_SIGNATURE; + state2 = 0; + + PRIN_VAL("origPtr", Props.origPtr); + PRIN_VAL("blockSize", Props.blockSize); + + return (Props.origPtr < Props.blockSize) ? SZ_OK : SZ_ERROR_DATA; } - props->blockSize = blockSize; - return (props->origPtr < props->blockSize) ? S_OK : S_FALSE; } -static void NO_INLINE DecodeBlock1(UInt32 *charCounters, UInt32 blockSize) + +NO_INLINE +static void DecodeBlock1(UInt32 *counters, UInt32 blockSize) { { UInt32 sum = 0; for (UInt32 i = 0; i < 256; i++) { - sum += charCounters[i]; - charCounters[i] = sum - charCounters[i]; + const UInt32 v = counters[i]; + counters[i] = sum; + sum += v; } } - UInt32 *tt = charCounters + 256; + UInt32 *tt = counters + 256; // Compute the T^(-1) vector - UInt32 i = 0; - do - tt[charCounters[tt[i] & 0xFF]++] |= (i << 8); - while (++i < blockSize); + + // blockSize--; + + #ifdef BZIP2_BYTE_MODE + + unsigned c = ((const Byte *)(tt + kBlockSizeMax))[0]; + + for (UInt32 i = 0; i < blockSize; i++) + { + unsigned c1 = c; + const UInt32 pos = counters[c]; + c = ((const Byte *)(tt + kBlockSizeMax))[(size_t)i + 1]; + counters[c1] = pos + 1; + tt[pos] = (i << 8) | ((const Byte *)(tt + kBlockSizeMax))[pos]; + } + + /* + // last iteration without next character prefetching + { + const UInt32 pos = counters[c]; + counters[c] = pos + 1; + tt[pos] = (blockSize << 8) | ((const Byte *)(tt + kBlockSizeMax))[pos]; + } + */ + + #else + + unsigned c = (unsigned)(tt[0] & 0xFF); + + for (UInt32 i = 0; i < blockSize; i++) + { + unsigned c1 = c; + const UInt32 pos = counters[c]; + c = (unsigned)(tt[(size_t)i + 1] & 0xFF); + counters[c1] = pos + 1; + tt[pos] |= (i << 8); + } + + /* + { + const UInt32 pos = counters[c]; + counters[c] = pos + 1; + tt[pos] |= (blockSize << 8); + } + */ + + #endif + + + /* + for (UInt32 i = 0; i < blockSize; i++) + { + #ifdef BZIP2_BYTE_MODE + const unsigned c = ((const Byte *)(tt + kBlockSizeMax))[i]; + const UInt32 pos = counters[c]++; + tt[pos] = (i << 8) | ((const Byte *)(tt + kBlockSizeMax))[pos]; + #else + const unsigned c = (unsigned)(tt[i] & 0xFF); + const UInt32 pos = counters[c]++; + tt[pos] |= (i << 8); + #endif + } + */ } -static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32 OrigPtr, COutBuffer &m_OutStream) + +void CSpecState::Init(UInt32 origPtr, unsigned randMode) throw() { - CBZip2Crc crc; + _tPos = _tt[_tt[origPtr] >> 8]; + _prevByte = (unsigned)(_tPos & 0xFF); + _reps = 0; + _randIndex = 0; + _randToGo = -1; + if (randMode) + { + _randIndex = 1; + _randToGo = kRandNums[0] - 2; + } + _crc.Init(); +} - // it's for speed optimization: prefetch & prevByte_init; - UInt32 tPos = tt[tt[OrigPtr] >> 8]; - unsigned prevByte = (unsigned)(tPos & 0xFF); - - unsigned numReps = 0; - do + +NO_INLINE +Byte * CSpecState::Decode(Byte *data, size_t size) throw() +{ + if (size == 0) + return data; + + unsigned prevByte = _prevByte; + int reps = _reps; + CBZip2Crc crc = _crc; + const Byte *lim = data + size; + + while (reps > 0) + { + reps--; + *data++ = (Byte)prevByte; + crc.UpdateByte(prevByte); + if (data == lim) + break; + } + + UInt32 tPos = _tPos; + UInt32 blockSize = _blockSize; + const UInt32 *tt = _tt; + + if (data != lim && blockSize) + + for (;;) { unsigned b = (unsigned)(tPos & 0xFF); tPos = tt[tPos >> 8]; - - if (numReps == kRleModeRepSize) + blockSize--; + + if (_randToGo >= 0) { - for (; b > 0; b--) + if (_randToGo == 0) { - crc.UpdateByte(prevByte); - m_OutStream.WriteByte((Byte)prevByte); + b ^= 1; + _randToGo = kRandNums[_randIndex]; + _randIndex++; + _randIndex &= 0x1FF; } - numReps = 0; - continue; + _randToGo--; } - if (b != prevByte) - numReps = 0; - numReps++; - prevByte = b; - crc.UpdateByte(b); - m_OutStream.WriteByte((Byte)b); - - /* - prevByte = b; - crc.UpdateByte(b); - m_OutStream.WriteByte((Byte)b); - for (; --blockSize != 0;) - { - b = (unsigned)(tPos & 0xFF); - tPos = tt[tPos >> 8]; - crc.UpdateByte(b); - m_OutStream.WriteByte((Byte)b); + + if (reps != -(int)kRleModeRepSize) + { if (b != prevByte) - { - prevByte = b; - continue; - } - if (--blockSize == 0) - break; - - b = (unsigned)(tPos & 0xFF); - tPos = tt[tPos >> 8]; + reps = 0; + reps--; + prevByte = b; + *data++ = (Byte)b; crc.UpdateByte(b); - m_OutStream.WriteByte((Byte)b); - if (b != prevByte) - { - prevByte = b; - continue; - } - if (--blockSize == 0) + if (data == lim || blockSize == 0) + break; + continue; + } + + reps = b; + while (reps) + { + reps--; + *data++ = (Byte)prevByte; + crc.UpdateByte(prevByte); + if (data == lim) break; - - b = (unsigned)(tPos & 0xFF); - tPos = tt[tPos >> 8]; - crc.UpdateByte(b); - m_OutStream.WriteByte((Byte)b); - if (b != prevByte) - { - prevByte = b; - continue; - } - --blockSize; - break; } + if (data == lim) + break; if (blockSize == 0) break; + } - b = (unsigned)(tPos & 0xFF); + if (blockSize == 1 && reps == -(int)kRleModeRepSize) + { + unsigned b = (unsigned)(tPos & 0xFF); tPos = tt[tPos >> 8]; - - for (; b > 0; b--) + blockSize--; + + if (_randToGo >= 0) { - crc.UpdateByte(prevByte); - m_OutStream.WriteByte((Byte)prevByte); + if (_randToGo == 0) + { + b ^= 1; + _randToGo = kRandNums[_randIndex]; + _randIndex++; + _randIndex &= 0x1FF; + } + _randToGo--; } - */ + + reps = b; } - while (--blockSize != 0); - return crc.GetDigest(); + + _tPos = tPos; + _prevByte = prevByte; + _reps = reps; + _crc = crc; + _blockSize = blockSize; + + return data; } -static UInt32 NO_INLINE DecodeBlock2Rand(const UInt32 *tt, UInt32 blockSize, UInt32 OrigPtr, COutBuffer &m_OutStream) + +HRESULT CDecoder::Flush() { - CBZip2Crc crc; - - UInt32 randIndex = 1; - UInt32 randToGo = kRandNums[0] - 2; - - unsigned numReps = 0; + if (_writeRes == S_OK) + { + _writeRes = WriteStream(_outStream, _outBuf, _outPos); + _outWritten += _outPos; + _outPos = 0; + } + return _writeRes; +} - // it's for speed optimization: prefetch & prevByte_init; - UInt32 tPos = tt[tt[OrigPtr] >> 8]; - unsigned prevByte = (unsigned)(tPos & 0xFF); - - do + +NO_INLINE +HRESULT CDecoder::DecodeBlock(const CBlockProps &props) +{ + _calcedBlockCrc = 0; + _blockFinished = false; + + CSpecState block; + + block._blockSize = props.blockSize; + block._tt = _counters + 256; + + block.Init(props.origPtr, props.randMode); + + for (;;) { - unsigned b = (unsigned)(tPos & 0xFF); - tPos = tt[tPos >> 8]; + Byte *data = _outBuf + _outPos; + size_t size = kOutBufSize - _outPos; + if (_outSizeDefined) { - if (randToGo == 0) + const UInt64 rem = _outSize - _outPosTotal; + if (size >= rem) { - b ^= 1; - randToGo = kRandNums[randIndex++]; - randIndex &= 0x1FF; + size = (size_t)rem; + if (size == 0) + return FinishMode ? S_FALSE : S_OK; } - randToGo--; + } + + TICKS_START + const size_t processed = block.Decode(data, size) - data; + TICKS_UPDATE(2) + + _outPosTotal += processed; + _outPos += processed; + + if (processed >= size) + { + RINOK(Flush()); } - if (numReps == kRleModeRepSize) + if (block.Finished()) { - for (; b > 0; b--) - { - crc.UpdateByte(prevByte); - m_OutStream.WriteByte((Byte)prevByte); - } - numReps = 0; - continue; + _blockFinished = true; + _calcedBlockCrc = block._crc.GetDigest(); + return S_OK; } - if (b != prevByte) - numReps = 0; - numReps++; - prevByte = b; - crc.UpdateByte(b); - m_OutStream.WriteByte((Byte)b); } - while (--blockSize != 0); - return crc.GetDigest(); } -static UInt32 NO_INLINE DecodeBlock(const CBlockProps &props, UInt32 *tt, COutBuffer &m_OutStream) -{ - if (props.randMode) - return DecodeBlock2Rand(tt, props.blockSize, props.origPtr, m_OutStream); - else - return DecodeBlock2 (tt, props.blockSize, props.origPtr, m_OutStream); -} -CDecoder::CDecoder() +CDecoder::CDecoder(): + _inBuf(NULL), + _outBuf(NULL), + _counters(NULL), + FinishMode(false), + _outSizeDefined(false) { #ifndef _7ZIP_ST - m_States = 0; - m_NumThreadsPrev = 0; - NumThreads = 1; + MtMode = false; + NeedWaitScout = false; + // ScoutRes = S_OK; #endif - _needInStreamInit = true; } -#ifndef _7ZIP_ST CDecoder::~CDecoder() { - Free(); -} - -#define RINOK_THREAD(x) { WRes __result_ = (x); if (__result_ != 0) return __result_; } + PRIN("\n~CDecoder()"); -HRESULT CDecoder::Create() -{ - RINOK_THREAD(CanProcessEvent.CreateIfNotCreated()); - RINOK_THREAD(CanStartWaitingEvent.CreateIfNotCreated()); - if (m_States != 0 && m_NumThreadsPrev == NumThreads) - return S_OK; - Free(); - MtMode = (NumThreads > 1); - m_NumThreadsPrev = NumThreads; - try - { - m_States = new CState[NumThreads]; - if (!m_States) - return E_OUTOFMEMORY; - } - catch(...) { return E_OUTOFMEMORY; } - for (UInt32 t = 0; t < NumThreads; t++) + #ifndef _7ZIP_ST + + if (Thread.IsCreated()) { - CState &ti = m_States[t]; - ti.Decoder = this; - if (MtMode) - { - HRESULT res = ti.Create(); - if (res != S_OK) - { - NumThreads = t; - Free(); - return res; - } - } + WaitScout(); + + _block.StopScout = true; + + PRIN("\nScoutEvent.Set()"); + ScoutEvent.Set(); + + PRIN("\nThread.Wait()()"); + Thread.Wait(); + PRIN("\n after Thread.Wait()()"); + Thread.Close(); + + // if (ScoutRes != S_OK) throw ScoutRes; } - return S_OK; + + #endif + + BigFree(_counters); + MidFree(_outBuf); + MidFree(_inBuf); } -void CDecoder::Free() + +HRESULT CDecoder::ReadInput() { - if (!m_States) - return; - CloseThreads = true; - CanProcessEvent.Set(); - for (UInt32 t = 0; t < NumThreads; t++) - { - CState &s = m_States[t]; - if (MtMode) - s.Thread.Wait(); - s.Free(); - } - delete []m_States; - m_States = 0; + if (Base._buf != Base._lim || _inputFinished || _inputRes != S_OK) + return _inputRes; + + _inProcessed += (Base._buf - _inBuf); + Base._buf = _inBuf; + Base._lim = _inBuf; + UInt32 size = 0; + _inputRes = Base.InStream->Read(_inBuf, kInBufSize, &size); + _inputFinished = (size == 0); + Base._lim = _inBuf + size; + return _inputRes; } -#endif -bool IsEndSig(const Byte *p) throw() +void CDecoder::StartNewStream() { - return - p[0] == kFinSig0 && - p[1] == kFinSig1 && - p[2] == kFinSig2 && - p[3] == kFinSig3 && - p[4] == kFinSig4 && - p[5] == kFinSig5; + Base.state = STATE_STREAM_SIGNATURE; + Base.state2 = 0; + Base.IsBz = false; } -bool IsBlockSig(const Byte *p) throw() + +HRESULT CDecoder::ReadStreamSignature() { - return - p[0] == kBlockSig0 && - p[1] == kBlockSig1 && - p[2] == kBlockSig2 && - p[3] == kBlockSig3 && - p[4] == kBlockSig4 && - p[5] == kBlockSig5; + for (;;) + { + RINOK(ReadInput()); + SRes res = Base.ReadStreamSignature2(); + if (res != SZ_OK) + return S_FALSE; + if (Base.state == STATE_BLOCK_SIGNATURE) + return S_OK; + if (_inputFinished) + { + Base.NeedMoreInput = true; + return S_FALSE; + } + } } -HRESULT CDecoder::ReadSignature(UInt32 &crc) -{ - BzWasFinished = false; - crc = 0; - Byte s[10]; - unsigned i; - for (i = 0; i < 10; i++) - s[i] = ReadByte(); +HRESULT CDecoder::StartRead() +{ + StartNewStream(); + return ReadStreamSignature(); +} - if (Base.BitDecoder.ExtraBitsWereRead()) - return S_FALSE; - UInt32 v = 0; - for (i = 0; i < 4; i++) +HRESULT CDecoder::ReadBlockSignature() +{ + for (;;) { - v <<= 8; - v |= s[6 + i]; + RINOK(ReadInput()); + + SRes res = Base.ReadBlockSignature2(); + + if (Base.state == STATE_STREAM_FINISHED) + Base.FinishedPackSize = GetInputProcessedSize(); + if (res != SZ_OK) + return S_FALSE; + if (Base.state != STATE_BLOCK_SIGNATURE) + return S_OK; + if (_inputFinished) + { + Base.NeedMoreInput = true; + return S_FALSE; + } } +} - crc = v; - if (IsBlockSig(s)) +HRESULT CDecoder::ReadBlock() +{ + for (;;) { - IsBz = true; - CombinedCrc.Update(crc); - return S_OK; - } + RINOK(ReadInput()); - if (!IsEndSig(s)) - return S_FALSE; + SRes res = Base.ReadBlock2(); - IsBz = true; - BzWasFinished = true; - if (crc != CombinedCrc.GetDigest()) - { - CrcError = true; - return S_FALSE; + if (res != SZ_OK) + return S_FALSE; + if (Base.state == STATE_BLOCK_SIGNATURE) + return S_OK; + if (_inputFinished) + { + Base.NeedMoreInput = true; + return S_FALSE; + } } - return S_OK; } -HRESULT CDecoder::DecodeFile(ICompressProgressInfo *progress) + + +HRESULT CDecoder::DecodeStreams(ICompressProgressInfo *progress) { - Progress = progress; - #ifndef _7ZIP_ST - RINOK(Create()); - for (UInt32 t = 0; t < NumThreads; t++) { - CState &s = m_States[t]; - if (!s.Alloc()) - return E_OUTOFMEMORY; - if (MtMode) - { - RINOK(s.StreamWasFinishedEvent.Reset()); - RINOK(s.WaitingWasStartedEvent.Reset()); - RINOK(s.CanWriteEvent.Reset()); - } + #ifndef _7ZIP_ST + _block.StopScout = false; + #endif } - #else - if (!m_States[0].Alloc()) - return E_OUTOFMEMORY; - #endif - IsBz = false; + RINOK(StartRead()); - /* - if (Base.BitDecoder.ExtraBitsWereRead()) - return E_FAIL; - */ + UInt64 inPrev = 0; + UInt64 outPrev = 0; - Byte s[4]; - unsigned i; - for (i = 0; i < 4; i++) - s[i] = ReadByte(); - if (Base.BitDecoder.ExtraBitsWereRead()) - return S_FALSE; + { + #ifndef _7ZIP_ST + CWaitScout_Releaser waitScout_Releaser(this); - if (s[0] != kArSig0 || - s[1] != kArSig1 || - s[2] != kArSig2 || - s[3] <= kArSig3 || - s[3] > kArSig3 + kBlockSizeMultMax) - return S_FALSE; + bool useMt = false; + #endif - UInt32 dicSize = (UInt32)(s[3] - kArSig3) * kBlockSizeStep; + bool wasFinished = false; + + UInt32 crc = 0; + UInt32 nextCrc = 0; + HRESULT nextRes = S_OK; + + UInt64 packPos = 0; + + CBlockProps props; + + props.blockSize = 0; - CombinedCrc.Init(); - #ifndef _7ZIP_ST - if (MtMode) - { - NextBlockIndex = 0; - StreamWasFinished1 = StreamWasFinished2 = false; - CloseThreads = false; - CanStartWaitingEvent.Reset(); - m_States[0].CanWriteEvent.Set(); - BlockSizeMax = dicSize; - Result1 = Result2 = S_OK; - CanProcessEvent.Set(); - UInt32 t; - for (t = 0; t < NumThreads; t++) - m_States[t].StreamWasFinishedEvent.Lock(); - CanProcessEvent.Reset(); - CanStartWaitingEvent.Set(); - for (t = 0; t < NumThreads; t++) - m_States[t].WaitingWasStartedEvent.Lock(); - CanStartWaitingEvent.Reset(); - RINOK(Result2); - RINOK(Result1); - } - else - #endif - { - CState &state = m_States[0]; for (;;) { - RINOK(SetRatioProgress(Base.BitDecoder.GetProcessedSize())); - UInt32 crc; - RINOK(ReadSignature(crc)); - if (BzWasFinished) - return S_OK; - - CBlockProps props; - props.randMode = true; - RINOK(Base.ReadBlock(state.Counters, dicSize, &props)); - DecodeBlock1(state.Counters, props.blockSize); - if (DecodeBlock(props, state.Counters + 256, m_OutStream) != crc) + if (progress) + { + const UInt64 outCur = GetOutProcessedSize(); + if (packPos - inPrev >= kProgressStep || outCur - outPrev >= kProgressStep) + { + RINOK(progress->SetRatioInfo(&packPos, &outCur)); + inPrev = packPos; + outPrev = outCur; + } + } + + if (props.blockSize == 0) + if (wasFinished || nextRes != S_OK) + return nextRes; + + if ( + #ifndef _7ZIP_ST + !useMt && + #endif + !wasFinished && Base.state == STATE_BLOCK_SIGNATURE) + { + nextRes = ReadBlockSignature(); + nextCrc = Base.crc; + packPos = GetInputProcessedSize(); + + wasFinished = true; + + if (nextRes != S_OK) + continue; + + if (Base.state == STATE_STREAM_FINISHED) + { + if (!Base.DecodeAllStreams) + { + wasFinished = true; + continue; + } + + nextRes = StartRead(); + + if (Base.NeedMoreInput) + { + if (Base.state2 == 0) + Base.NeedMoreInput = false; + wasFinished = true; + nextRes = S_OK; + continue; + } + + if (nextRes != S_OK) + continue; + + wasFinished = false; + continue; + } + + wasFinished = false; + + #ifndef _7ZIP_ST + if (MtMode) + if (props.blockSize != 0) + { + // we start multithreading, if next block is big enough. + const UInt32 k_Mt_BlockSize_Threshold = (1 << 12); // (1 << 13) + if (props.blockSize > k_Mt_BlockSize_Threshold) + { + if (!Thread.IsCreated()) + { + PRIN("=== MT_MODE"); + RINOK(CreateThread()); + } + useMt = true; + } + } + #endif + } + + if (props.blockSize == 0) { - CrcError = true; + crc = nextCrc; + + #ifndef _7ZIP_ST + if (useMt) + { + PRIN("DecoderEvent.Lock()"); + RINOK(DecoderEvent.Lock()); + NeedWaitScout = false; + PRIN("-- DecoderEvent.Lock()"); + props = _block.Props; + nextCrc = _block.NextCrc; + if (_block.Crc_Defined) + crc = _block.Crc; + packPos = _block.PackPos; + wasFinished = _block.WasFinished; + RINOK(_block.Res); + } + else + #endif + { + if (Base.state != STATE_BLOCK_START) + return E_FAIL; + + TICKS_START + Base.Props.randMode = 1; + RINOK(ReadBlock()); + TICKS_UPDATE(0) + + props = Base.Props; + continue; + } + } + + if (props.blockSize != 0) + { + TICKS_START + DecodeBlock1(_counters, props.blockSize); + TICKS_UPDATE(1) + } + + #ifndef _7ZIP_ST + if (useMt && !wasFinished) + { + /* + if (props.blockSize == 0) + { + // this codes switches back to single-threadMode + useMt = false; + PRIN("=== ST_MODE"); + continue; + } + */ + + PRIN("ScoutEvent.Set()"); + RINOK(ScoutEvent.Set()); + NeedWaitScout = true; + } + #endif + + if (props.blockSize == 0) + continue; + + RINOK(DecodeBlock(props)); + + if (!_blockFinished) + return nextRes; + + props.blockSize = 0; + if (_calcedBlockCrc != crc) + { + BlockCrcError = true; return S_FALSE; } } } - return SetRatioProgress(Base.BitDecoder.GetProcessedSize()); } -HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, - ICompressProgressInfo *progress) -{ - IsBz = false; - BzWasFinished = false; - CrcError = false; - try + + +bool CDecoder::CreateInputBufer() +{ + if (!_inBuf) { + _inBuf = (Byte *)MidAlloc(kInBufSize); + if (!_inBuf) + return false; + } + if (!_counters) + { + _counters = (UInt32 *)::BigAlloc((256 + kBlockSizeMax) * sizeof(UInt32) + #ifdef BZIP2_BYTE_MODE + + kBlockSizeMax + #endif + + 256); + if (!_counters) + return false; + Base.Counters = _counters; + } + return true; +} - if (!Base.BitDecoder.Create(kBufferSize)) - return E_OUTOFMEMORY; - if (!m_OutStream.Create(kBufferSize)) - return E_OUTOFMEMORY; - if (inStream) - Base.BitDecoder.SetStream(inStream); +void CDecoder::InitOutSize(const UInt64 *outSize) +{ + _outPosTotal = 0; + + _outSizeDefined = false; + _outSize = 0; + if (outSize) + { + _outSize = *outSize; + _outSizeDefined = true; + } + + BlockCrcError = false; + + Base.InitNumStreams2(); +} - CDecoderFlusher flusher(this); - if (_needInStreamInit) +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + /* { - Base.BitDecoder.Init(); - _needInStreamInit = false; + RINOK(SetInStream(inStream)); + RINOK(SetOutStreamSize(outSize)); + + RINOK(CopyStream(this, outStream, progress)); + return ReleaseInStream(); } - _inStart = Base.BitDecoder.GetProcessedSize(); + */ + + InitOutSize(outSize); - Base.BitDecoder.AlignToByte(); + _inputFinished = false; + _inputRes = S_OK; + _writeRes = S_OK; - m_OutStream.SetStream(outStream); - m_OutStream.Init(); + try { - RINOK(DecodeFile(progress)); - flusher.NeedFlush = false; - return Flush(); + if (!CreateInputBufer()) + return E_OUTOFMEMORY; + if (!_outBuf) + { + _outBuf = (Byte *)MidAlloc(kOutBufSize); + if (!_outBuf) + return E_OUTOFMEMORY; } - catch(const CInBufferException &e) { return e.ErrorCode; } - catch(const COutBufferException &e) { return e.ErrorCode; } - catch(...) { return E_FAIL; } -} -STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) -{ - _needInStreamInit = true; - return CodeReal(inStream, outStream, progress); -} + Base.InStream = inStream; + + InitInputBuffer(); + + _outStream = outStream; + _outWritten = 0; + _outPos = 0; -HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, ICompressProgressInfo *progress) -{ - return CodeReal(NULL, outStream, progress); + HRESULT res = DecodeStreams(progress); + + Flush(); + + Base.InStream = NULL; + _outStream = NULL; + + /* + if (res == S_OK) + if (FinishMode && inSize && *inSize != GetInputProcessedSize()) + res = S_FALSE; + */ + + if (res != S_OK) + return res; + + } catch(...) { return E_FAIL; } + + return _writeRes; } -STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) + +STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode) { - Base.InStreamRef = inStream; - Base.BitDecoder.SetStream(inStream); + FinishMode = (finishMode != 0); return S_OK; } -STDMETHODIMP CDecoder::ReleaseInStream() + +STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { - Base.InStreamRef.Release(); + *value = GetInputProcessedSize(); return S_OK; } + #ifndef _7ZIP_ST -static THREAD_FUNC_DECL MFThread(void *p) { ((CState *)p)->ThreadFunc(); return 0; } +#define RINOK_THREAD(x) { WRes __result_ = (x); if (__result_ != 0) return __result_; } -HRESULT CState::Create() -{ - RINOK_THREAD(StreamWasFinishedEvent.CreateIfNotCreated()); - RINOK_THREAD(WaitingWasStartedEvent.CreateIfNotCreated()); - RINOK_THREAD(CanWriteEvent.CreateIfNotCreated()); - RINOK_THREAD(Thread.Create(MFThread, this)); - return S_OK; -} +static THREAD_FUNC_DECL RunScout2(void *p) { ((CDecoder *)p)->RunScout(); return 0; } -void CState::FinishStream() +HRESULT CDecoder::CreateThread() { - Decoder->StreamWasFinished1 = true; - StreamWasFinishedEvent.Set(); - Decoder->CS.Leave(); - Decoder->CanStartWaitingEvent.Lock(); - WaitingWasStartedEvent.Set(); + RINOK_THREAD(DecoderEvent.CreateIfNotCreated()); + RINOK_THREAD(ScoutEvent.CreateIfNotCreated()); + RINOK_THREAD(Thread.Create(RunScout2, this)); + return S_OK; } -void CState::ThreadFunc() +void CDecoder::RunScout() { for (;;) { - Decoder->CanProcessEvent.Lock(); - Decoder->CS.Enter(); - if (Decoder->CloseThreads) { - Decoder->CS.Leave(); - return; - } - if (Decoder->StreamWasFinished1) - { - FinishStream(); - continue; - } - HRESULT res = S_OK; - - UInt32 blockIndex = Decoder->NextBlockIndex; - UInt32 nextBlockIndex = blockIndex + 1; - if (nextBlockIndex == Decoder->NumThreads) - nextBlockIndex = 0; - Decoder->NextBlockIndex = nextBlockIndex; - UInt32 crc; - UInt64 packSize = 0; - CBlockProps props; - - try - { - res = Decoder->ReadSignature(crc); - if (res != S_OK) - { - Decoder->Result1 = res; - FinishStream(); - continue; - } - if (Decoder->BzWasFinished) - { - Decoder->Result1 = res; - FinishStream(); - continue; - } - - props.randMode = true; - res = Decoder->Base.ReadBlock(Counters, Decoder->BlockSizeMax, &props); - if (res != S_OK) + PRIN_MT("ScoutEvent.Lock()"); + WRes wres = ScoutEvent.Lock(); + PRIN_MT("-- ScoutEvent.Lock()"); + if (wres != 0) { - Decoder->Result1 = res; - FinishStream(); - continue; + // ScoutRes = wres; + return; } - packSize = Decoder->Base.BitDecoder.GetProcessedSize(); } - catch(const CInBufferException &e) { res = e.ErrorCode; if (res == S_OK) res = E_FAIL; } - catch(...) { res = E_FAIL; } - if (res != S_OK) + + CBlock &block = _block; + + if (block.StopScout) { - Decoder->Result1 = res; - FinishStream(); - continue; + // ScoutRes = S_OK; + return; } - Decoder->CS.Leave(); + block.Res = S_OK; + block.WasFinished = false; - DecodeBlock1(Counters, props.blockSize); + HRESULT res = S_OK; - bool needFinish = true; try { - Decoder->m_States[blockIndex].CanWriteEvent.Lock(); - needFinish = Decoder->StreamWasFinished2; - if (!needFinish) + UInt64 packPos = GetInputProcessedSize(); + + block.Props.blockSize = 0; + block.Crc_Defined = false; + // block.NextCrc_Defined = false; + block.NextCrc = 0; + + for (;;) { - if (DecodeBlock(props, Counters + 256, Decoder->m_OutStream) == crc) - res = Decoder->SetRatioProgress(packSize); - else - res = S_FALSE; + if (Base.state == STATE_BLOCK_SIGNATURE) + { + res = ReadBlockSignature(); + + if (res != S_OK) + break; + + if (block.Props.blockSize == 0) + { + block.Crc = Base.crc; + block.Crc_Defined = true; + } + else + { + block.NextCrc = Base.crc; + // block.NextCrc_Defined = true; + } + + continue; + } + + if (Base.state == STATE_BLOCK_START) + { + if (block.Props.blockSize != 0) + break; + + Base.Props.randMode = 1; + + res = ReadBlock(); + + PRIN_MT("-- Base.ReadBlock"); + if (res != S_OK) + break; + block.Props = Base.Props; + continue; + } + + if (Base.state == STATE_STREAM_FINISHED) + { + if (!Base.DecodeAllStreams) + { + block.WasFinished = true; + break; + } + + res = StartRead(); + + if (Base.NeedMoreInput) + { + if (Base.state2 == 0) + Base.NeedMoreInput = false; + block.WasFinished = true; + res = S_OK; + break; + } + + if (res != S_OK) + break; + + if (GetInputProcessedSize() - packPos > 0) // kProgressStep + break; + continue; + } + + // throw 1; + res = E_FAIL; + break; } } - catch(const COutBufferException &e) { res = e.ErrorCode; if (res == S_OK) res = E_FAIL; } - catch(...) { res = E_FAIL; } + + catch (...) { res = E_FAIL; } + if (res != S_OK) { - Decoder->Result2 = res; - Decoder->StreamWasFinished2 = true; + PRIN_MT("error"); + block.Res = res; + block.WasFinished = true; } - Decoder->m_States[nextBlockIndex].CanWriteEvent.Set(); - if (res != S_OK || needFinish) + + block.PackPos = GetInputProcessedSize(); + PRIN_MT("DecoderEvent.Set()"); + WRes wres = DecoderEvent.Set(); + if (wres != 0) { - StreamWasFinishedEvent.Set(); - Decoder->CanStartWaitingEvent.Lock(); - WaitingWasStartedEvent.Set(); + // ScoutRes = wres; + return; } } } + STDMETHODIMP CDecoder::SetNumberOfThreads(UInt32 numThreads) { - NumThreads = numThreads; - if (NumThreads < 1) - NumThreads = 1; - if (NumThreads > kNumThreadsMax) - NumThreads = kNumThreadsMax; + MtMode = (numThreads > 1); + + #ifndef BZIP2_BYTE_MODE + MtMode = false; + #endif + + // MtMode = false; return S_OK; } #endif -HRESULT CDecoder::SetRatioProgress(UInt64 packSize) -{ - if (!Progress) - return S_OK; - packSize -= _inStart; - UInt64 unpackSize = m_OutStream.GetProcessedSize(); - return Progress->SetRatioInfo(&packSize, &unpackSize); -} -// ---------- NSIS ---------- +#ifndef NO_READ_FROM_CODER -enum -{ - NSIS_STATE_INIT, - NSIS_STATE_NEW_BLOCK, - NSIS_STATE_DATA, - NSIS_STATE_FINISHED, - NSIS_STATE_ERROR -}; -STDMETHODIMP CNsisDecoder::SetInStream(ISequentialInStream *inStream) +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { Base.InStreamRef = inStream; - Base.BitDecoder.SetStream(inStream); + Base.InStream = inStream; return S_OK; } -STDMETHODIMP CNsisDecoder::ReleaseInStream() + + +STDMETHODIMP CDecoder::ReleaseInStream() { Base.InStreamRef.Release(); + Base.InStream = NULL; return S_OK; } -STDMETHODIMP CNsisDecoder::SetOutStreamSize(const UInt64 * /* outSize */) + + +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { - _nsisState = NSIS_STATE_INIT; + InitOutSize(outSize); + + if (!CreateInputBufer()) + return E_OUTOFMEMORY; + + InitInputBuffer(); + + StartNewStream(); + + _blockFinished = true; + + ErrorResult = S_OK; + + _inputFinished = false; + _inputRes = S_OK; + return S_OK; } -STDMETHODIMP CNsisDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) -{ - try { + +STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ *processedSize = 0; - if (_nsisState == NSIS_STATE_FINISHED) - return S_OK; - if (_nsisState == NSIS_STATE_ERROR) - return S_FALSE; - if (size == 0) - return S_OK; - CState &state = m_State; + try { - if (_nsisState == NSIS_STATE_INIT) - { - if (!Base.BitDecoder.Create(kBufferSize)) - return E_OUTOFMEMORY; - if (!state.Alloc()) - return E_OUTOFMEMORY; - Base.BitDecoder.Init(); - _nsisState = NSIS_STATE_NEW_BLOCK; - } + if (ErrorResult != S_OK) + return ErrorResult; - if (_nsisState == NSIS_STATE_NEW_BLOCK) + for (;;) { - Byte b = (Byte)Base.ReadBits(8); - if (b == kFinSig0) + if (Base.state == STATE_STREAM_FINISHED) + { + if (!Base.DecodeAllStreams) + return ErrorResult; + StartNewStream(); + continue; + } + + if (Base.state == STATE_STREAM_SIGNATURE) { - _nsisState = NSIS_STATE_FINISHED; + ErrorResult = ReadStreamSignature(); + + if (Base.NeedMoreInput) + if (Base.state2 == 0 && Base.NumStreams != 0) + { + Base.NeedMoreInput = false; + ErrorResult = S_OK; + return S_OK; + } + if (ErrorResult != S_OK) + return ErrorResult; + continue; + } + + if (_blockFinished && Base.state == STATE_BLOCK_SIGNATURE) + { + ErrorResult = ReadBlockSignature(); + + if (ErrorResult != S_OK) + return ErrorResult; + + continue; + } + + if (_outSizeDefined) + { + const UInt64 rem = _outSize - _outPosTotal; + if (size >= rem) + size = (UInt32)rem; + } + if (size == 0) return S_OK; + + if (_blockFinished) + { + if (Base.state != STATE_BLOCK_START) + { + ErrorResult = E_FAIL; + return ErrorResult; + } + + Base.Props.randMode = 1; + ErrorResult = ReadBlock(); + + if (ErrorResult != S_OK) + return ErrorResult; + + DecodeBlock1(_counters, Base.Props.blockSize); + + _spec._blockSize = Base.Props.blockSize; + _spec._tt = _counters + 256; + _spec.Init(Base.Props.origPtr, Base.Props.randMode); + + _blockFinished = false; } - if (b != kBlockSig0) + { - _nsisState = NSIS_STATE_ERROR; - return S_FALSE; + Byte *ptr = _spec.Decode((Byte *)data, size); + + const UInt32 processed = (UInt32)(ptr - (Byte *)data); + data = ptr; + size -= processed; + (*processedSize) += processed; + _outPosTotal += processed; + + if (_spec.Finished()) + { + _blockFinished = true; + if (Base.crc != _spec._crc.GetDigest()) + { + BlockCrcError = true; + ErrorResult = S_FALSE; + return ErrorResult; + } + } } - CBlockProps props; - props.randMode = false; - RINOK(Base.ReadBlock(state.Counters, 9 * kBlockSizeStep, &props)); - _blockSize = props.blockSize; - DecodeBlock1(state.Counters, props.blockSize); - const UInt32 *tt = state.Counters + 256; - _tPos = tt[tt[props.origPtr] >> 8]; - _prevByte = (unsigned)(_tPos & 0xFF); - _numReps = 0; - _repRem = 0; - _nsisState = NSIS_STATE_DATA; } - UInt32 tPos = _tPos; - unsigned prevByte = _prevByte; - unsigned numReps = _numReps; - UInt32 blockSize = _blockSize; - const UInt32 *tt = state.Counters + 256; + } catch(...) { ErrorResult = S_FALSE; return S_FALSE; } +} - while (_repRem) - { - _repRem--; - *(Byte *)data = (Byte)prevByte; - data = (Byte *)data + 1; - (*processedSize)++; - if (--size == 0) - return S_OK; - } - if (blockSize == 0) - { - _nsisState = NSIS_STATE_NEW_BLOCK; + +// ---------- NSIS ---------- + +STDMETHODIMP CNsisDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + *processedSize = 0; + + try { + + if (ErrorResult != S_OK) + return ErrorResult; + + if (Base.state == STATE_STREAM_FINISHED) return S_OK; + + if (Base.state == STATE_STREAM_SIGNATURE) + { + Base.blockSizeMax = 9 * kBlockSizeStep; + Base.state = STATE_BLOCK_SIGNATURE; + // Base.state2 = 0; } - do + for (;;) { - unsigned b = (unsigned)(tPos & 0xFF); - tPos = tt[tPos >> 8]; - blockSize--; + if (_blockFinished && Base.state == STATE_BLOCK_SIGNATURE) + { + ErrorResult = ReadInput(); + if (ErrorResult != S_OK) + return ErrorResult; + + int b; + Base.ReadByte(b); + if (b < 0) + { + ErrorResult = S_FALSE; + return ErrorResult; + } + + if (b == kFinSig0) + { + /* + if (!Base.AreRemainByteBitsEmpty()) + ErrorResult = S_FALSE; + */ + Base.state = STATE_STREAM_FINISHED; + return ErrorResult; + } + + if (b != kBlockSig0) + { + ErrorResult = S_FALSE; + return ErrorResult; + } + + Base.state = STATE_BLOCK_START; + } + + if (_outSizeDefined) + { + const UInt64 rem = _outSize - _outPosTotal; + if (size >= rem) + size = (UInt32)rem; + } + if (size == 0) + return S_OK; - if (numReps == kRleModeRepSize) + if (_blockFinished) { - numReps = 0; - while (b) + if (Base.state != STATE_BLOCK_START) { - b--; - *(Byte *)data = (Byte)prevByte; - data = (Byte *)data + 1; - (*processedSize)++; - if (--size == 0) - break; + ErrorResult = E_FAIL; + return ErrorResult; } - _repRem = b; - continue; + + Base.Props.randMode = 0; + ErrorResult = ReadBlock(); + + if (ErrorResult != S_OK) + return ErrorResult; + + DecodeBlock1(_counters, Base.Props.blockSize); + + _spec._blockSize = Base.Props.blockSize; + _spec._tt = _counters + 256; + _spec.Init(Base.Props.origPtr, Base.Props.randMode); + + _blockFinished = false; + } + + { + Byte *ptr = _spec.Decode((Byte *)data, size); + + const UInt32 processed = (UInt32)(ptr - (Byte *)data); + data = ptr; + size -= processed; + (*processedSize) += processed; + _outPosTotal += processed; + + if (_spec.Finished()) + _blockFinished = true; } - if (b != prevByte) - numReps = 0; - numReps++; - prevByte = b; - *(Byte *)data = (Byte)b; - data = (Byte *)data + 1; - (*processedSize)++; - size--; } - while (size && blockSize); - _tPos = tPos; - _prevByte = prevByte; - _numReps = numReps; - _blockSize = blockSize; - return S_OK; - } - catch(const CInBufferException &e) { return e.ErrorCode; } - catch(...) { return S_FALSE; } + } catch(...) { ErrorResult = S_FALSE; return S_FALSE; } } +#endif + }} diff --git a/CPP/7zip/Compress/BZip2Decoder.h b/CPP/7zip/Compress/BZip2Decoder.h index 8703d572..68aa7094 100644 --- a/CPP/7zip/Compress/BZip2Decoder.h +++ b/CPP/7zip/Compress/BZip2Decoder.h @@ -5,6 +5,9 @@ #include "../../Common/MyCom.h" +// #define NO_READ_FROM_CODER +// #define _7ZIP_ST + #ifndef _7ZIP_ST #include "../../Windows/Synchronization.h" #include "../../Windows/Thread.h" @@ -12,13 +15,10 @@ #include "../ICoder.h" -#include "../Common/InBuffer.h" -#include "../Common/OutBuffer.h" - -#include "BitmDecoder.h" #include "BZip2Const.h" #include "BZip2Crc.h" #include "HuffmanDecoder.h" +#include "Mtf8.h" namespace NCompress { namespace NBZip2 { @@ -26,154 +26,311 @@ namespace NBZip2 { bool IsEndSig(const Byte *p) throw(); bool IsBlockSig(const Byte *p) throw(); -typedef NCompress::NHuffman::CDecoder<kMaxHuffmanLen, kMaxAlphaSize> CHuffmanDecoder; +const unsigned kNumTableBits = 9; +const unsigned kNumBitsMax = kMaxHuffmanLen; -class CDecoder; +typedef NHuffman::CDecoder<kMaxHuffmanLen, kMaxAlphaSize, kNumTableBits> CHuffmanDecoder; -struct CState -{ - UInt32 *Counters; - #ifndef _7ZIP_ST - - CDecoder *Decoder; - NWindows::CThread Thread; - bool m_OptimizeNumTables; +struct CBlockProps +{ + UInt32 blockSize; + UInt32 origPtr; + unsigned randMode; + + CBlockProps(): blockSize(0), origPtr(0), randMode(0) {} +}; - NWindows::NSynchronization::CAutoResetEvent StreamWasFinishedEvent; - NWindows::NSynchronization::CAutoResetEvent WaitingWasStartedEvent; - // it's not member of this thread. We just need one event per thread - NWindows::NSynchronization::CAutoResetEvent CanWriteEvent; +struct CBitDecoder +{ + unsigned _numBits; + UInt32 _value; + const Byte *_buf; + const Byte *_lim; - Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. + void InitBitDecoder() + { + _numBits = 0; + _value = 0; + } - HRESULT Create(); - void FinishStream(); - void ThreadFunc(); + void AlignToByte() + { + unsigned bits = _numBits & 7; + _numBits -= bits; + _value <<= bits; + } - #endif + /* + bool AreRemainByteBitsEmpty() const + { + unsigned bits = _numBits & 7; + if (bits != 0) + return (_value >> (32 - bits)) == 0; + return true; + } + */ - CState(): Counters(0) {} - ~CState() { Free(); } - bool Alloc(); - void Free(); + SRes ReadByte(int &b); }; -struct CBlockProps + +struct CBase: public CBitDecoder { + unsigned numInUse; + UInt32 groupIndex; + UInt32 groupSize; + unsigned runPower; + UInt32 runCounter; UInt32 blockSize; - UInt32 origPtr; - bool randMode; - - CBlockProps(): blockSize(0), origPtr(0), randMode(false) {} -}; -struct CBase -{ - CMyComPtr<ISequentialInStream> InStreamRef; - NBitm::CDecoder<CInBuffer> BitDecoder; + UInt32 *Counters; + UInt32 blockSizeMax; + + unsigned state; + unsigned state2; + unsigned state3; + unsigned state4; + unsigned state5; + unsigned numTables; + UInt32 numSelectors; + + CBlockProps Props; private: - Byte m_Selectors[kNumSelectorsMax]; - CHuffmanDecoder m_HuffmanDecoders[kNumTablesMax]; + CMtf8Decoder mtf; + Byte selectors[kNumSelectorsMax]; + CHuffmanDecoder huffs[kNumTablesMax]; + + Byte lens[kMaxAlphaSize]; + + Byte temp[10]; public: + UInt32 crc; + CBZip2CombinedCrc CombinedCrc; + + bool IsBz; + bool StreamCrcError; + bool MinorError; + bool NeedMoreInput; + + bool DecodeAllStreams; + + UInt64 NumStreams; UInt64 NumBlocks; + UInt64 FinishedPackSize; - CBase(): NumBlocks(0) {} - UInt32 ReadBits(unsigned numBits); - unsigned ReadBit(); - void InitNumBlocks() { NumBlocks = 0; } + ISequentialInStream *InStream; - /* - ReadBlock() props->randMode: - in: need read randMode bit, - out: randMode status - */ - HRESULT ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps *props); + #ifndef NO_READ_FROM_CODER + CMyComPtr<ISequentialInStream> InStreamRef; + #endif + + CBase(): + StreamCrcError(false), + MinorError(false), + NeedMoreInput(false), + + DecodeAllStreams(false), + + NumStreams(0), + NumBlocks(0), + FinishedPackSize(0) + {} + + void InitNumStreams2() + { + StreamCrcError = false; + MinorError = false; + NeedMoreInput = 0; + NumStreams = 0; + NumBlocks = 0; + FinishedPackSize = 0; + } + + SRes ReadStreamSignature2(); + SRes ReadBlockSignature2(); + + /* ReadBlock2() : Props->randMode: + in: need read randMode bit + out: randMode status */ + SRes ReadBlock2(); +}; + + +class CSpecState +{ + UInt32 _tPos; + unsigned _prevByte; + int _reps; + +public: + CBZip2Crc _crc; + UInt32 _blockSize; + UInt32 *_tt; + + int _randToGo; + unsigned _randIndex; + + void Init(UInt32 origPtr, unsigned randMode) throw(); + + bool Finished() const { return _reps <= 0 && _blockSize == 0; } + + Byte *Decode(Byte *data, size_t size) throw(); }; + + + class CDecoder : public ICompressCoder, + public ICompressSetFinishMode, + public ICompressGetInStreamProcessedSize, + + #ifndef NO_READ_FROM_CODER + public ICompressSetInStream, + public ICompressSetOutStreamSize, + public ISequentialInStream, + #endif + #ifndef _7ZIP_ST public ICompressSetCoderMt, #endif + public CMyUnknownImp { + Byte *_outBuf; + size_t _outPos; + UInt64 _outWritten; + ISequentialOutStream *_outStream; + HRESULT _writeRes; + +protected: + HRESULT ErrorResult; // for ISequentialInStream::Read mode only + public: - COutBuffer m_OutStream; - Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. - CBase Base; + UInt32 _calcedBlockCrc; + bool _blockFinished; + bool BlockCrcError; - UInt64 _inStart; + bool FinishMode; + bool _outSizeDefined; + UInt64 _outSize; + UInt64 _outPosTotal; -private: + CSpecState _spec; + UInt32 *_counters; - bool _needInStreamInit; + #ifndef _7ZIP_ST - Byte ReadByte(); + struct CBlock + { + bool StopScout; + + bool WasFinished; + bool Crc_Defined; + // bool NextCrc_Defined; + + UInt32 Crc; + UInt32 NextCrc; + HRESULT Res; + UInt64 PackPos; + + CBlockProps Props; + }; + + CBlock _block; + + bool NeedWaitScout; + bool MtMode; - HRESULT DecodeFile(ICompressProgressInfo *progress); - HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress); + NWindows::CThread Thread; + NWindows::NSynchronization::CAutoResetEvent DecoderEvent; + NWindows::NSynchronization::CAutoResetEvent ScoutEvent; + // HRESULT ScoutRes; - class CDecoderFlusher + Byte MtPad[1 << 7]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. + + + void RunScout(); + + void WaitScout() { - CDecoder *_decoder; - public: - bool NeedFlush; - CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {} - ~CDecoderFlusher() + if (NeedWaitScout) { - if (NeedFlush) - _decoder->Flush(); + DecoderEvent.Lock(); + NeedWaitScout = false; } + } + + class CWaitScout_Releaser + { + CDecoder *_decoder; + public: + CWaitScout_Releaser(CDecoder *decoder): _decoder(decoder) {} + ~CWaitScout_Releaser() { _decoder->WaitScout(); } }; -public: - CBZip2CombinedCrc CombinedCrc; - ICompressProgressInfo *Progress; + HRESULT CreateThread(); - #ifndef _7ZIP_ST - CState *m_States; - UInt32 m_NumThreadsPrev; + #endif - NWindows::NSynchronization::CManualResetEvent CanProcessEvent; - NWindows::NSynchronization::CCriticalSection CS; - UInt32 NumThreads; - bool MtMode; - UInt32 NextBlockIndex; - bool CloseThreads; - bool StreamWasFinished1; - bool StreamWasFinished2; - NWindows::NSynchronization::CManualResetEvent CanStartWaitingEvent; + Byte *_inBuf; + UInt64 _inProcessed; + bool _inputFinished; + HRESULT _inputRes; - HRESULT Result1; - HRESULT Result2; + CBase Base; - UInt32 BlockSizeMax; + bool GetCrcError() const { return BlockCrcError || Base.StreamCrcError; } - ~CDecoder(); - HRESULT Create(); - void Free(); + void InitOutSize(const UInt64 *outSize); + + bool CreateInputBufer(); - #else - CState m_States[1]; - #endif + void InitInputBuffer() + { + _inProcessed = 0; + Base._buf = _inBuf; + Base._lim = _inBuf; + Base.InitBitDecoder(); + } - 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. + UInt64 GetInputProcessedSize() const + { + // for NSIS case : we need also look the number of bits in bitDecoder + return _inProcessed + (Base._buf - _inBuf); + } - CDecoder(); + UInt64 GetOutProcessedSize() const { return _outWritten + _outPos; } + + HRESULT ReadInput(); - HRESULT SetRatioProgress(UInt64 packSize); - HRESULT ReadSignature(UInt32 &crc); + void StartNewStream(); + + HRESULT ReadStreamSignature(); + HRESULT StartRead(); - HRESULT Flush() { return m_OutStream.Flush(); } + HRESULT ReadBlockSignature(); + HRESULT ReadBlock(); + + HRESULT Flush(); + HRESULT DecodeBlock(const CBlockProps &props); + HRESULT DecodeStreams(ICompressProgressInfo *progress); MY_QUERYINTERFACE_BEGIN2(ICompressCoder) + MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode) + MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize) + + #ifndef NO_READ_FROM_CODER + MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) + MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize) + MY_QUERYINTERFACE_ENTRY(ISequentialInStream) + #endif + #ifndef _7ZIP_ST MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt) #endif @@ -185,54 +342,41 @@ public: STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetFinishMode)(UInt32 finishMode); + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); + + UInt64 GetNumStreams() const { return Base.NumStreams; } + UInt64 GetNumBlocks() const { return Base.NumBlocks; } + + #ifndef NO_READ_FROM_CODER + STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - HRESULT CodeResume(ISequentialOutStream *outStream, ICompressProgressInfo *progress); - - UInt64 GetStreamSize() const { return Base.BitDecoder.GetStreamSize(); } - UInt64 GetInputProcessedSize() const { return Base.BitDecoder.GetProcessedSize(); } + #endif - void InitNumBlocks() { Base.InitNumBlocks(); } - UInt64 GetNumBlocks() const { return Base.NumBlocks; } - #ifndef _7ZIP_ST STDMETHOD(SetNumberOfThreads)(UInt32 numThreads); #endif + + CDecoder(); + ~CDecoder(); }; -class CNsisDecoder : - public ISequentialInStream, - public ICompressSetInStream, - public ICompressSetOutStreamSize, - public CMyUnknownImp -{ - CBase Base; - CState m_State; - - int _nsisState; - UInt32 _tPos; - unsigned _prevByte; - unsigned _repRem; - unsigned _numReps; - UInt32 _blockSize; +#ifndef NO_READ_FROM_CODER +class CNsisDecoder : public CDecoder +{ public: - - MY_QUERYINTERFACE_BEGIN2(ISequentialInStream) - MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) - MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize) - MY_QUERYINTERFACE_END - MY_ADDREF_RELEASE - STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(SetInStream)(ISequentialInStream *inStream); - STDMETHOD(ReleaseInStream)(); - STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); }; +#endif + }} #endif diff --git a/CPP/7zip/Compress/BZip2Encoder.cpp b/CPP/7zip/Compress/BZip2Encoder.cpp index e2225134..c9f9c664 100644 --- a/CPP/7zip/Compress/BZip2Encoder.cpp +++ b/CPP/7zip/Compress/BZip2Encoder.cpp @@ -337,7 +337,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) } else mtfs[mtfArraySize++] = (Byte)(pos + 1); - symbolCounts[pos + 1]++; + symbolCounts[(size_t)pos + 1]++; } } while (++i < blockSize); @@ -357,7 +357,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) mtfs[mtfArraySize++] = 0xFF; mtfs[mtfArraySize++] = (Byte)(alphaSize - 256); } - symbolCounts[alphaSize - 1]++; + symbolCounts[(size_t)alphaSize - 1]++; } UInt32 numSymbols = 0; @@ -412,7 +412,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) if (ge > gs + 1 && t != numTables && t != 1 && (((numTables - t) & 1) == 1)) aFreq -= symbolCounts[--ge]; - Byte *lens = Lens[t - 1]; + Byte *lens = Lens[(size_t)t - 1]; unsigned i = 0; do lens[i] = (Byte)((i >= gs && i < ge) ? 0 : 1); @@ -507,7 +507,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) WriteBit2(1); WriteBit2(0); for (; pos > 0; pos--) - mtfSel[pos] = mtfSel[pos - 1]; + mtfSel[pos] = mtfSel[(size_t)pos - 1]; mtfSel[0] = sel; } while (++i < numSelectors); @@ -634,10 +634,13 @@ void CThreadInfo::EncodeBlock2(const Byte *block, UInt32 blockSize, UInt32 numPa UInt32 endPos = 0; if (numPasses > 1 && blockSize >= (1 << 10)) { - UInt32 blockSize0 = blockSize / 2; - for (;(block[blockSize0] == block[blockSize0 - 1] || - block[blockSize0 - 1] == block[blockSize0 - 2]) && - blockSize0 < blockSize; blockSize0++); + UInt32 blockSize0 = blockSize / 2; // ???? + + for (; (block[blockSize0] == block[(size_t)blockSize0 - 1] + || block[(size_t)blockSize0 - 1] == block[(size_t)blockSize0 - 2]) + && blockSize0 < blockSize; + blockSize0++); + if (blockSize0 < blockSize) { EncodeBlock2(block, blockSize0, numPasses - 1); diff --git a/CPP/7zip/Compress/Bcj2Coder.cpp b/CPP/7zip/Compress/Bcj2Coder.cpp index 96150c5f..4906e78c 100644 --- a/CPP/7zip/Compress/Bcj2Coder.cpp +++ b/CPP/7zip/Compress/Bcj2Coder.cpp @@ -463,10 +463,10 @@ HRESULT CDecoder::Code(ISequentialInStream * const *inStreams, const UInt64 * co if (progress) { - UInt64 outSize2 = outSizeProcessed + (dec.dest - _bufs[BCJ2_NUM_STREAMS]); + const UInt64 outSize2 = outSizeProcessed + (dec.dest - _bufs[BCJ2_NUM_STREAMS]); if (outSize2 - prevProgress >= (1 << 22)) { - UInt64 inSize2 = outSize2 + _inStreamsProcessed[BCJ2_STREAM_RC] - (dec.lims[BCJ2_STREAM_RC] - dec.bufs[BCJ2_STREAM_RC]); + const UInt64 inSize2 = outSize2 + _inStreamsProcessed[BCJ2_STREAM_RC] - (dec.lims[BCJ2_STREAM_RC] - dec.bufs[BCJ2_STREAM_RC]); RINOK(progress->SetRatioInfo(&inSize2, &outSize2)); prevProgress = outSize2; } @@ -655,4 +655,12 @@ STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) return res; } + +STDMETHODIMP CDecoder::GetInStreamProcessedSize2(UInt32 streamIndex, UInt64 *value) +{ + const size_t rem = dec.lims[streamIndex] - dec.bufs[streamIndex] + _extraReadSizes[streamIndex]; + *value = _inStreamsProcessed[streamIndex] - rem; + return S_OK; +} + }} diff --git a/CPP/7zip/Compress/Bcj2Coder.h b/CPP/7zip/Compress/Bcj2Coder.h index 381b9f54..ca6a1e4e 100644 --- a/CPP/7zip/Compress/Bcj2Coder.h +++ b/CPP/7zip/Compress/Bcj2Coder.h @@ -62,6 +62,7 @@ public: class CDecoder: public ICompressCoder2, public ICompressSetFinishMode, + public ICompressGetInStreamProcessedSize2, public ICompressSetInStream2, public ISequentialInStream, public ICompressSetOutStreamSize, @@ -84,9 +85,10 @@ class CDecoder: // HRESULT ReadSpec(); public: - MY_UNKNOWN_IMP6( + MY_UNKNOWN_IMP7( ICompressCoder2, ICompressSetFinishMode, + ICompressGetInStreamProcessedSize2, ICompressSetInStream2, ISequentialInStream, ICompressSetOutStreamSize, @@ -98,6 +100,7 @@ public: ICompressProgressInfo *progress); STDMETHOD(SetFinishMode)(UInt32 finishMode); + STDMETHOD(GetInStreamProcessedSize2)(UInt32 streamIndex, UInt64 *value); STDMETHOD(SetInStream2)(UInt32 streamIndex, ISequentialInStream *inStream); STDMETHOD(ReleaseInStream2)(UInt32 streamIndex); diff --git a/CPP/7zip/Compress/BitlDecoder.h b/CPP/7zip/Compress/BitlDecoder.h index 41e22fe7..f3b8248f 100644 --- a/CPP/7zip/Compress/BitlDecoder.h +++ b/CPP/7zip/Compress/BitlDecoder.h @@ -42,13 +42,15 @@ public: UInt64 GetProcessedSize() const { return _stream.GetProcessedSize() - ((kNumBigValueBits - _bitPos) >> 3); } bool ThereAreDataInBitsBuffer() const { return this->_bitPos != kNumBigValueBits; } - + + MY_FORCE_INLINE void Normalize() { for (; _bitPos >= 8; _bitPos -= 8) _value = ((UInt32)_stream.ReadByte() << (kNumBigValueBits - _bitPos)) | _value; } + MY_FORCE_INLINE UInt32 ReadBits(unsigned numBits) { Normalize(); @@ -88,7 +90,8 @@ public: CBaseDecoder<TInByte>::Init(); _normalValue = 0; } - + + MY_FORCE_INLINE void Normalize() { for (; this->_bitPos >= 8; this->_bitPos -= 8) @@ -99,18 +102,21 @@ public: } } + MY_FORCE_INLINE UInt32 GetValue(unsigned numBits) { Normalize(); return ((this->_value >> (8 - this->_bitPos)) & kMask) >> (kNumValueBits - numBits); } - + + MY_FORCE_INLINE void MovePos(unsigned numBits) { this->_bitPos += numBits; _normalValue >>= numBits; } + MY_FORCE_INLINE UInt32 ReadBits(unsigned numBits) { Normalize(); @@ -120,9 +126,11 @@ public: } void AlignToByte() { MovePos((32 - this->_bitPos) & 7); } - + + MY_FORCE_INLINE Byte ReadDirectByte() { return this->_stream.ReadByte(); } - + + MY_FORCE_INLINE Byte ReadAlignedByte() { if (this->_bitPos == kNumBigValueBits) diff --git a/CPP/7zip/Compress/BitmDecoder.h b/CPP/7zip/Compress/BitmDecoder.h index 9b1c540e..9ce41bd1 100644 --- a/CPP/7zip/Compress/BitmDecoder.h +++ b/CPP/7zip/Compress/BitmDecoder.h @@ -46,25 +46,29 @@ public: { return (_stream.NumExtraBytes > 4); } - + + MY_FORCE_INLINE void Normalize() { for (; _bitPos >= 8; _bitPos -= 8) _value = (_value << 8) | _stream.ReadByte(); } + MY_FORCE_INLINE UInt32 GetValue(unsigned numBits) const { // return (_value << _bitPos) >> (kNumBigValueBits - numBits); return ((_value >> (8 - _bitPos)) & kMask) >> (kNumValueBits - numBits); } - + + MY_FORCE_INLINE void MovePos(unsigned numBits) { _bitPos += numBits; Normalize(); } - + + MY_FORCE_INLINE UInt32 ReadBits(unsigned numBits) { UInt32 res = GetValue(numBits); @@ -87,6 +91,7 @@ public: void AlignToByte() { MovePos((kNumBigValueBits - _bitPos) & 7); } + MY_FORCE_INLINE UInt32 ReadAlignBits() { return ReadBits((kNumBigValueBits - _bitPos) & 7); } }; diff --git a/CPP/7zip/Compress/CopyCoder.cpp b/CPP/7zip/Compress/CopyCoder.cpp index ac6ab2e7..d8487ad5 100644 --- a/CPP/7zip/Compress/CopyCoder.cpp +++ b/CPP/7zip/Compress/CopyCoder.cpp @@ -15,6 +15,11 @@ CCopyCoder::~CCopyCoder() ::MidFree(_buf); } +STDMETHODIMP CCopyCoder::SetFinishMode(UInt32 /* finishMode */) +{ + return S_OK; +} + STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, diff --git a/CPP/7zip/Compress/CopyCoder.h b/CPP/7zip/Compress/CopyCoder.h index a21c0988..a9d0b6db 100644 --- a/CPP/7zip/Compress/CopyCoder.h +++ b/CPP/7zip/Compress/CopyCoder.h @@ -13,6 +13,7 @@ class CCopyCoder: public ICompressCoder, public ICompressSetInStream, public ISequentialInStream, + public ICompressSetFinishMode, public ICompressGetInStreamProcessedSize, public CMyUnknownImp { @@ -24,10 +25,11 @@ public: CCopyCoder(): _buf(0), TotalSize(0) {}; ~CCopyCoder(); - MY_UNKNOWN_IMP4( + MY_UNKNOWN_IMP5( ICompressCoder, ICompressSetInStream, ISequentialInStream, + ICompressSetFinishMode, ICompressGetInStreamProcessedSize) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, @@ -35,6 +37,7 @@ public: STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(SetFinishMode)(UInt32 finishMode); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); }; diff --git a/CPP/7zip/Compress/DeflateDecoder.cpp b/CPP/7zip/Compress/DeflateDecoder.cpp index 60c9aea6..88ab1f91 100644 --- a/CPP/7zip/Compress/DeflateDecoder.cpp +++ b/CPP/7zip/Compress/DeflateDecoder.cpp @@ -14,6 +14,8 @@ CCoder::CCoder(bool deflate64Mode): _keepHistory(false), _needFinishInput(false), _needInitInStream(true), + _outSizeDefined(false), + _outStartPos(0), ZlibMode(false) {} UInt32 CCoder::ReadBits(unsigned numBits) @@ -50,7 +52,7 @@ bool CCoder::DecodeLevels(Byte *levels, unsigned numSymbols) return false; numBits = 2; num = 0; - symbol = levels[i - 1]; + symbol = levels[(size_t)i - 1]; } else { @@ -145,10 +147,28 @@ bool CCoder::ReadTables(void) return m_DistDecoder.Build(levels.distLevels); } -HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream) + +HRESULT CCoder::InitInStream(bool needInit) +{ + if (needInit) + { + // for HDD-Windows: + // (1 << 15) - best for reading only prefetch + // (1 << 22) - best for real reading / writing + if (!m_InBitStream.Create(1 << 20)) + return E_OUTOFMEMORY; + m_InBitStream.Init(); + _needInitInStream = false; + } + return S_OK; +} + + +HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream, UInt32 inputProgressLimit) { if (_remainLen == kLenIdFinished) return S_OK; + if (_remainLen == kLenIdNeedInit) { if (!_keepHistory) @@ -156,6 +176,7 @@ HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream) return E_OUTOFMEMORY; RINOK(InitInStream(_needInitInStream)); m_OutWindowStream.Init(_keepHistory); + m_FinalBlock = false; _remainLen = 0; _needReadTable = true; @@ -169,6 +190,10 @@ HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream) curSize--; } + UInt64 inputStart = 0; + if (inputProgressLimit != 0) + inputStart = m_InBitStream.GetProcessedSize(); + while (curSize > 0 || finishInputStream) { if (m_InBitStream.ExtraBitsWereRead()) @@ -181,6 +206,11 @@ HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream) _remainLen = kLenIdFinished; break; } + + if (inputProgressLimit != 0) + if (m_InBitStream.GetProcessedSize() - inputStart >= inputProgressLimit) + return S_OK; + if (!ReadTables()) return S_FALSE; if (m_InBitStream.ExtraBitsWereRead()) @@ -284,31 +314,34 @@ HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream) #define DEFLATE_TRY_BEGIN try { #define DEFLATE_TRY_END(res) } \ - catch(const CInBufferException &e) { res = e.ErrorCode; } \ - catch(const CLzOutWindowException &e) { res = e.ErrorCode; } \ + catch(const CSystemException &e) { res = e.ErrorCode; } \ catch(...) { res = S_FALSE; } + // catch(const CInBufferException &e) { res = e.ErrorCode; } + // catch(const CLzOutWindowException &e) { res = e.ErrorCode; } + #endif -HRESULT CCoder::CodeReal(ISequentialOutStream *outStream, - const UInt64 *outSize, ICompressProgressInfo *progress) +HRESULT CCoder::CodeReal(ISequentialOutStream *outStream, ICompressProgressInfo *progress) { HRESULT res; + DEFLATE_TRY_BEGIN + m_OutWindowStream.SetStream(outStream); CCoderReleaser flusher(this); const UInt64 inStart = _needInitInStream ? 0 : m_InBitStream.GetProcessedSize(); - const UInt64 start = m_OutWindowStream.GetProcessedSize(); for (;;) { - UInt32 curSize = 1 << 18; + const UInt32 kInputProgressLimit = 1 << 21; + UInt32 curSize = 1 << 20; bool finishInputStream = false; - if (outSize) + if (_outSizeDefined) { - const UInt64 rem = *outSize - (m_OutWindowStream.GetProcessedSize() - start); + const UInt64 rem = _outSize - GetOutProcessedCur(); if (curSize >= rem) { curSize = (UInt32)rem; @@ -318,13 +351,16 @@ HRESULT CCoder::CodeReal(ISequentialOutStream *outStream, } if (!finishInputStream && curSize == 0) break; - RINOK(CodeSpec(curSize, finishInputStream)); + + RINOK(CodeSpec(curSize, finishInputStream, progress ? kInputProgressLimit : 0)); + if (_remainLen == kLenIdFinished) break; + if (progress) { const UInt64 inSize = m_InBitStream.GetProcessedSize() - inStart; - const UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start; + const UInt64 nowPos64 = GetOutProcessedCur(); RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); } } @@ -340,20 +376,36 @@ HRESULT CCoder::CodeReal(ISequentialOutStream *outStream, res = Flush(); if (res == S_OK && _remainLen != kLenIdNeedInit && InputEofError()) return S_FALSE; + DEFLATE_TRY_END(res) + return res; } + HRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { SetInStream(inStream); SetOutStreamSize(outSize); - HRESULT res = CodeReal(outStream, outSize, progress); + HRESULT res = CodeReal(outStream, progress); ReleaseInStream(); + /* + if (res == S_OK) + if (_needFinishInput && inSize && *inSize != m_InBitStream.GetProcessedSize()) + res = S_FALSE; + */ return res; } + +STDMETHODIMP CCoder::SetFinishMode(UInt32 finishMode) +{ + Set_NeedFinishInput(finishMode != 0); + return S_OK; +} + + STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value) { if (!value) @@ -362,6 +414,7 @@ STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value) return S_OK; } + STDMETHODIMP CCoder::SetInStream(ISequentialInStream *inStream) { m_InStreamRef = inStream; @@ -369,49 +422,88 @@ STDMETHODIMP CCoder::SetInStream(ISequentialInStream *inStream) return S_OK; } + STDMETHODIMP CCoder::ReleaseInStream() { m_InStreamRef.Release(); return S_OK; } -STDMETHODIMP CCoder::SetOutStreamSize(const UInt64 * /* outSize */) + +void CCoder::SetOutStreamSizeResume(const UInt64 *outSize) { + _outSizeDefined = (outSize != NULL); + _outSize = 0; + if (_outSizeDefined) + _outSize = *outSize; + + m_OutWindowStream.Init(_keepHistory); + _outStartPos = m_OutWindowStream.GetProcessedSize(); + _remainLen = kLenIdNeedInit; +} + + +STDMETHODIMP CCoder::SetOutStreamSize(const UInt64 *outSize) +{ _needInitInStream = true; - m_OutWindowStream.Init(_keepHistory); + SetOutStreamSizeResume(outSize); return S_OK; } + #ifndef NO_READ_FROM_CODER STDMETHODIMP CCoder::Read(void *data, UInt32 size, UInt32 *processedSize) { HRESULT res; - DEFLATE_TRY_BEGIN + if (processedSize) *processedSize = 0; - const UInt64 startPos = m_OutWindowStream.GetProcessedSize(); - m_OutWindowStream.SetMemStream((Byte *)data); - res = CodeSpec(size, false); - if (res == S_OK) + const UInt64 outPos = GetOutProcessedCur(); + + bool finishInputStream = false; + if (_outSizeDefined) { - res = Flush(); - if (processedSize) - *processedSize = (UInt32)(m_OutWindowStream.GetProcessedSize() - startPos); + const UInt64 rem = _outSize - outPos; + if (size >= rem) + { + size = (UInt32)rem; + if (ZlibMode || _needFinishInput) + finishInputStream = true; + } } + if (!finishInputStream && size == 0) + return S_OK; + + DEFLATE_TRY_BEGIN + + m_OutWindowStream.SetMemStream((Byte *)data); + + res = CodeSpec(size, finishInputStream); + DEFLATE_TRY_END(res) + + { + HRESULT res2 = Flush(); + if (res2 != S_OK) + res = res2; + } + + if (processedSize) + *processedSize = (UInt32)(GetOutProcessedCur() - outPos); + m_OutWindowStream.SetMemStream(NULL); return res; } #endif -STDMETHODIMP CCoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress) + +HRESULT CCoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress) { - _remainLen = kLenIdNeedInit; - m_OutWindowStream.Init(_keepHistory); - return CodeReal(outStream, outSize, progress); + SetOutStreamSizeResume(outSize); + return CodeReal(outStream, progress); } }}} diff --git a/CPP/7zip/Compress/DeflateDecoder.h b/CPP/7zip/Compress/DeflateDecoder.h index 09f84eb4..0a724247 100644 --- a/CPP/7zip/Compress/DeflateDecoder.h +++ b/CPP/7zip/Compress/DeflateDecoder.h @@ -23,6 +23,7 @@ const int kLenIdNeedInit = -2; class CCoder: public ICompressCoder, + public ICompressSetFinishMode, public ICompressGetInStreamProcessedSize, #ifndef NO_READ_FROM_CODER public ICompressSetInStream, @@ -54,6 +55,13 @@ class CCoder: Int32 _remainLen; UInt32 _rep0; + bool _outSizeDefined; + UInt64 _outSize; + UInt64 _outStartPos; + + void SetOutStreamSizeResume(const UInt64 *outSize); + UInt64 GetOutProcessedCur() const { return m_OutWindowStream.GetProcessedSize() - _outStartPos; } + UInt32 ReadBits(unsigned numBits); bool DecodeLevels(Byte *levels, unsigned numSymbols); @@ -74,7 +82,7 @@ class CCoder: }; friend class CCoderReleaser; - HRESULT CodeSpec(UInt32 curSize, bool finishInputStream); + HRESULT CodeSpec(UInt32 curSize, bool finishInputStream, UInt32 inputProgressLimit = 0); public: bool ZlibMode; Byte ZlibFooter[4]; @@ -90,26 +98,28 @@ public: bool IsFinished() const { return _remainLen == kLenIdFinished;; } bool IsFinalBlock() const { return m_FinalBlock; } - HRESULT CodeReal(ISequentialOutStream *outStream, - const UInt64 *outSize, ICompressProgressInfo *progress); + HRESULT CodeReal(ISequentialOutStream *outStream, ICompressProgressInfo *progress); + + MY_QUERYINTERFACE_BEGIN2(ICompressCoder) + MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode) + MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize) #ifndef NO_READ_FROM_CODER - MY_UNKNOWN_IMP5( - ICompressCoder, - ICompressGetInStreamProcessedSize, - ICompressSetInStream, - ICompressSetOutStreamSize, - ISequentialInStream - ) - #else - MY_UNKNOWN_IMP2( - ICompressCoder, - 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(SetFinishMode)(UInt32 finishMode); + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); + STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); @@ -118,19 +128,9 @@ public: STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); #endif - STDMETHOD(CodeResume)(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress); + HRESULT CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress); - HRESULT InitInStream(bool needInit) - { - if (!m_InBitStream.Create(1 << 17)) - return E_OUTOFMEMORY; - if (needInit) - { - m_InBitStream.Init(); - _needInitInStream = false; - } - return S_OK; - } + HRESULT InitInStream(bool needInit); void AlignToByte() { m_InBitStream.AlignToByte(); } Byte ReadAlignedByte(); @@ -143,9 +143,6 @@ public: UInt64 GetStreamSize() const { return m_InBitStream.GetStreamSize(); } UInt64 GetInputProcessedSize() const { return m_InBitStream.GetProcessedSize(); } - - // IGetInStreamProcessedSize - STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); }; class CCOMCoder : public CCoder { public: CCOMCoder(): CCoder(false) {} }; diff --git a/CPP/7zip/Compress/DeflateEncoder.cpp b/CPP/7zip/Compress/DeflateEncoder.cpp index 538e7b5e..7cf59cc0 100644 --- a/CPP/7zip/Compress/DeflateEncoder.cpp +++ b/CPP/7zip/Compress/DeflateEncoder.cpp @@ -7,6 +7,8 @@ #include "../../Common/ComTry.h" +#include "../Common/CWrappers.h" + #include "DeflateEncoder.h" #undef NO_INLINE @@ -262,19 +264,19 @@ NO_INLINE void CCoder::GetMatches() UInt32 i; for (i = 0; i < numPairs; i += 2) { - m_MatchDistances[i + 1] = (UInt16)distanceTmp[i]; - m_MatchDistances[i + 2] = (UInt16)distanceTmp[i + 1]; + m_MatchDistances[(size_t)i + 1] = (UInt16)distanceTmp[i]; + m_MatchDistances[(size_t)i + 2] = (UInt16)distanceTmp[(size_t)i + 1]; } - UInt32 len = distanceTmp[numPairs - 2]; + UInt32 len = distanceTmp[(size_t)numPairs - 2]; if (len == m_NumFastBytes && m_NumFastBytes != m_MatchMaxLen) { UInt32 numAvail = Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) + 1; const Byte *pby = Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) - 1; - const Byte *pby2 = pby - (distanceTmp[numPairs - 1] + 1); + const Byte *pby2 = pby - (distanceTmp[(size_t)numPairs - 1] + 1); if (numAvail > m_MatchMaxLen) numAvail = m_MatchMaxLen; for (; len < numAvail && pby[len] == pby2[len]; len++); - m_MatchDistances[i - 1] = (UInt16)len; + m_MatchDistances[(size_t)i - 1] = (UInt16)len; } } if (m_IsMultiPass) @@ -337,11 +339,11 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes) if (numDistancePairs == 0) return 1; const UInt16 *matchDistances = m_MatchDistances + 1; - lenEnd = matchDistances[numDistancePairs - 2]; + lenEnd = matchDistances[(size_t)numDistancePairs - 2]; if (lenEnd > m_NumFastBytes) { - backRes = matchDistances[numDistancePairs - 1]; + backRes = matchDistances[(size_t)numDistancePairs - 1]; MovePos(lenEnd - 1); return lenEnd; } @@ -356,10 +358,10 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes) for (UInt32 i = kMatchMinLen; i <= lenEnd; i++) { - UInt32 distance = matchDistances[offs + 1]; + UInt32 distance = matchDistances[(size_t)offs + 1]; m_Optimum[i].PosPrev = 0; m_Optimum[i].BackPrev = (UInt16)distance; - m_Optimum[i].Price = m_LenPrices[i - kMatchMinLen] + m_PosPrices[GetPosSlot(distance)]; + m_Optimum[i].Price = m_LenPrices[(size_t)i - kMatchMinLen] + m_PosPrices[GetPosSlot(distance)]; if (i == matchDistances[offs]) offs += 2; } @@ -378,11 +380,11 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes) UInt32 newLen = 0; if (numDistancePairs != 0) { - newLen = matchDistances[numDistancePairs - 2]; + newLen = matchDistances[(size_t)numDistancePairs - 2]; if (newLen > m_NumFastBytes) { UInt32 len = Backward(backRes, cur); - m_Optimum[cur].BackPrev = matchDistances[numDistancePairs - 1]; + m_Optimum[cur].BackPrev = matchDistances[(size_t)numDistancePairs - 1]; m_OptimumEndIndex = cur + newLen; m_Optimum[cur].PosPrev = (UInt16)m_OptimumEndIndex; MovePos(newLen - 1); @@ -392,7 +394,7 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes) UInt32 curPrice = m_Optimum[cur].Price; { const UInt32 curAnd1Price = curPrice + m_LiteralPrices[*(Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) + cur - m_AdditionalOffset)]; - COptimal &optimum = m_Optimum[cur + 1]; + COptimal &optimum = m_Optimum[(size_t)cur + 1]; if (curAnd1Price < optimum.Price) { optimum.Price = curAnd1Price; @@ -404,11 +406,11 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes) while (lenEnd < cur + newLen) m_Optimum[++lenEnd].Price = kIfinityPrice; UInt32 offs = 0; - UInt32 distance = matchDistances[offs + 1]; + UInt32 distance = matchDistances[(size_t)offs + 1]; curPrice += m_PosPrices[GetPosSlot(distance)]; for (UInt32 lenTest = kMatchMinLen; ; lenTest++) { - UInt32 curAndLenPrice = curPrice + m_LenPrices[lenTest - kMatchMinLen]; + UInt32 curAndLenPrice = curPrice + m_LenPrices[(size_t)lenTest - kMatchMinLen]; COptimal &optimum = m_Optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { @@ -422,7 +424,7 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes) if (offs == numDistancePairs) break; curPrice -= m_PosPrices[GetPosSlot(distance)]; - distance = matchDistances[offs + 1]; + distance = matchDistances[(size_t)offs + 1]; curPrice += m_PosPrices[GetPosSlot(distance)]; } } @@ -435,7 +437,7 @@ UInt32 CCoder::GetOptimalFast(UInt32 &backRes) UInt32 numDistancePairs = m_MatchDistances[0]; if (numDistancePairs == 0) return 1; - UInt32 lenMain = m_MatchDistances[numDistancePairs - 1]; + UInt32 lenMain = m_MatchDistances[(size_t)numDistancePairs - 1]; backRes = m_MatchDistances[numDistancePairs]; MovePos(lenMain - 1); return lenMain; @@ -470,7 +472,7 @@ NO_INLINE void CCoder::LevelTableDummy(const Byte *levels, unsigned numLevels, U for (unsigned n = 0; n < numLevels; n++) { unsigned curLen = nextLen; - nextLen = (n < numLevels - 1) ? levels[n + 1] : 0xFF; + nextLen = (n < numLevels - 1) ? levels[(size_t)n + 1] : 0xFF; count++; if (count < maxCount && curLen == nextLen) continue; @@ -537,7 +539,7 @@ NO_INLINE void CCoder::LevelTableCode(const Byte *levels, unsigned numLevels, co for (unsigned n = 0; n < numLevels; n++) { unsigned curLen = nextLen; - nextLen = (n < numLevels - 1) ? levels[n + 1] : 0xFF; + nextLen = (n < numLevels - 1) ? levels[(size_t)n + 1] : 0xFF; count++; if (count < maxCount && curLen == nextLen) continue; @@ -642,7 +644,7 @@ NO_INLINE void CCoder::TryBlock() { UInt32 newLen = len - kMatchMinLen; codeValue.Len = (UInt16)newLen; - mainFreqs[kSymbolMatch + g_LenSlots[newLen]]++; + mainFreqs[kSymbolMatch + (size_t)g_LenSlots[newLen]]++; codeValue.Pos = (UInt16)pos; distFreqs[GetPosSlot(pos)]++; } @@ -675,7 +677,7 @@ NO_INLINE void CCoder::SetPrices(const CLevels &levels) for (i = 0; i < m_NumLenCombinations; i++) { UInt32 slot = g_LenSlots[i]; - Byte price = levels.litLenLevels[kSymbolMatch + slot]; + Byte price = levels.litLenLevels[kSymbolMatch + (size_t)slot]; m_LenPrices[i] = (Byte)(((price != 0) ? price : kNoLenStatPrice) + m_LenDirectBits[slot]); } @@ -780,11 +782,11 @@ NO_INLINE UInt32 CCoder::TryDynBlock(unsigned tableIndex, UInt32 numPasses) (CLevels &)t = m_NewLevels; m_NumLitLenLevels = kMainTableSize; - while (m_NumLitLenLevels > kNumLitLenCodesMin && m_NewLevels.litLenLevels[m_NumLitLenLevels - 1] == 0) + while (m_NumLitLenLevels > kNumLitLenCodesMin && m_NewLevels.litLenLevels[(size_t)m_NumLitLenLevels - 1] == 0) m_NumLitLenLevels--; m_NumDistLevels = kDistTableSize64; - while (m_NumDistLevels > kNumDistCodesMin && m_NewLevels.distLevels[m_NumDistLevels - 1] == 0) + while (m_NumDistLevels > kNumDistCodesMin && m_NewLevels.distLevels[(size_t)m_NumDistLevels - 1] == 0) m_NumDistLevels--; UInt32 levelFreqs[kLevelTableSize]; @@ -923,14 +925,6 @@ void CCoder::CodeBlock(unsigned tableIndex, bool finalBlock) } } -SRes Read(void *object, void *data, size_t *size) -{ - const UInt32 kStepSize = (UInt32)1 << 31; - UInt32 curSize = ((*size < kStepSize) ? (UInt32)*size : kStepSize); - HRESULT res = ((CSeqInStream *)object)->RealStream->Read(data, curSize, &curSize); - *size = curSize; - return (SRes)res; -} HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */ , const UInt64 * /* outSize */ , ICompressProgressInfo *progress) @@ -944,9 +938,11 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *ou UInt64 nowPos = 0; - _seqInStream.RealStream = inStream; - _seqInStream.SeqInStream.Read = Read; - _lzInWindow.stream = &_seqInStream.SeqInStream; + CSeqInStreamWrap _seqInStream; + + _seqInStream.Init(inStream); + + _lzInWindow.stream = &_seqInStream.vt; MatchFinder_Init(&_lzInWindow); m_OutStream.SetStream(outStream); @@ -974,7 +970,7 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *ou } while (Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) != 0); if (_lzInWindow.result != SZ_OK) - return _lzInWindow.result; + return SResToHRESULT(_lzInWindow.result); return m_OutStream.Flush(); } diff --git a/CPP/7zip/Compress/DeflateEncoder.h b/CPP/7zip/Compress/DeflateEncoder.h index 6c4ae4fc..94d250ec 100644 --- a/CPP/7zip/Compress/DeflateEncoder.h +++ b/CPP/7zip/Compress/DeflateEncoder.h @@ -46,11 +46,6 @@ struct CTables: public CLevels void InitStructures(); }; -typedef struct _CSeqInStream -{ - ISeqInStream SeqInStream; - ISequentialInStream *RealStream; -} CSeqInStream; struct CEncProps { @@ -76,8 +71,6 @@ class CCoder CMatchFinder _lzInWindow; CBitlEncoder m_OutStream; - CSeqInStream _seqInStream; - public: CCodeValue *m_Values; diff --git a/CPP/7zip/Compress/HuffmanDecoder.h b/CPP/7zip/Compress/HuffmanDecoder.h index 04364c14..f0529876 100644 --- a/CPP/7zip/Compress/HuffmanDecoder.h +++ b/CPP/7zip/Compress/HuffmanDecoder.h @@ -8,45 +8,52 @@ namespace NCompress { namespace NHuffman { +const unsigned kNumPairLenBits = 4; +const unsigned kPairLenMask = (1 << kNumPairLenBits) - 1; + template <unsigned kNumBitsMax, UInt32 m_NumSymbols, unsigned kNumTableBits = 9> class CDecoder { +public: UInt32 _limits[kNumBitsMax + 2]; UInt32 _poses[kNumBitsMax + 1]; UInt16 _lens[1 << kNumTableBits]; UInt16 _symbols[m_NumSymbols]; -public: bool Build(const Byte *lens) throw() { - UInt32 lenCounts[kNumBitsMax + 1]; - UInt32 tmpPoses[kNumBitsMax + 1]; + UInt32 counts[kNumBitsMax + 1]; unsigned i; for (i = 0; i <= kNumBitsMax; i++) - lenCounts[i] = 0; + counts[i] = 0; UInt32 sym; for (sym = 0; sym < m_NumSymbols; sym++) - lenCounts[lens[sym]]++; + counts[lens[sym]]++; - lenCounts[0] = 0; - _poses[0] = 0; + const UInt32 kMaxValue = (UInt32)1 << kNumBitsMax; + _limits[0] = 0; + UInt32 startPos = 0; - const UInt32 kMaxValue = (UInt32)1 << kNumBitsMax; + UInt32 sum = 0; for (i = 1; i <= kNumBitsMax; i++) { - startPos += lenCounts[i] << (kNumBitsMax - i); + const UInt32 cnt = counts[i]; + startPos += cnt << (kNumBitsMax - i); if (startPos > kMaxValue) return false; _limits[i] = startPos; - _poses[i] = _poses[i - 1] + lenCounts[i - 1]; - tmpPoses[i] = _poses[i]; + counts[i] = sum; + _poses[i] = sum; + sum += cnt; } + counts[0] = sum; + _poses[0] = sum; _limits[kNumBitsMax + 1] = kMaxValue; for (sym = 0; sym < m_NumSymbols; sym++) @@ -55,16 +62,15 @@ public: if (len == 0) continue; - unsigned offset = tmpPoses[len]; + unsigned offset = counts[len]++; _symbols[offset] = (UInt16)sym; - tmpPoses[len] = offset + 1; if (len <= kNumTableBits) { offset -= _poses[len]; UInt32 num = (UInt32)1 << (kNumTableBits - len); - UInt16 val = (UInt16)((sym << 4) | len); - UInt16 *dest = _lens + (_limits[len - 1] >> (kNumBitsMax - kNumTableBits)) + (offset << (kNumTableBits - len)); + UInt16 val = (UInt16)((sym << kNumPairLenBits) | len); + UInt16 *dest = _lens + (_limits[(size_t)len - 1] >> (kNumBitsMax - kNumTableBits)) + (offset << (kNumTableBits - len)); for (UInt32 k = 0; k < num; k++) dest[k] = val; } @@ -73,36 +79,41 @@ public: return true; } + bool BuildFull(const Byte *lens, UInt32 numSymbols = m_NumSymbols) throw() { - UInt32 lenCounts[kNumBitsMax + 1]; - UInt32 tmpPoses[kNumBitsMax + 1]; + UInt32 counts[kNumBitsMax + 1]; unsigned i; for (i = 0; i <= kNumBitsMax; i++) - lenCounts[i] = 0; + counts[i] = 0; UInt32 sym; for (sym = 0; sym < numSymbols; sym++) - lenCounts[lens[sym]]++; + counts[lens[sym]]++; - lenCounts[0] = 0; - _poses[0] = 0; + const UInt32 kMaxValue = (UInt32)1 << kNumBitsMax; + _limits[0] = 0; + UInt32 startPos = 0; - const UInt32 kMaxValue = (UInt32)1 << kNumBitsMax; + UInt32 sum = 0; for (i = 1; i <= kNumBitsMax; i++) { - startPos += lenCounts[i] << (kNumBitsMax - i); + const UInt32 cnt = counts[i]; + startPos += cnt << (kNumBitsMax - i); if (startPos > kMaxValue) return false; _limits[i] = startPos; - _poses[i] = _poses[i - 1] + lenCounts[i - 1]; - tmpPoses[i] = _poses[i]; + counts[i] = sum; + _poses[i] = sum; + sum += cnt; } + counts[0] = sum; + _poses[0] = sum; _limits[kNumBitsMax + 1] = kMaxValue; for (sym = 0; sym < numSymbols; sym++) @@ -111,16 +122,15 @@ public: if (len == 0) continue; - unsigned offset = tmpPoses[len]; + unsigned offset = counts[len]++; _symbols[offset] = (UInt16)sym; - tmpPoses[len] = offset + 1; if (len <= kNumTableBits) { offset -= _poses[len]; UInt32 num = (UInt32)1 << (kNumTableBits - len); - UInt16 val = (UInt16)((sym << 4) | len); - UInt16 *dest = _lens + (_limits[len - 1] >> (kNumBitsMax - kNumTableBits)) + (offset << (kNumTableBits - len)); + UInt16 val = (UInt16)((sym << kNumPairLenBits) | len); + UInt16 *dest = _lens + (_limits[(size_t)len - 1] >> (kNumBitsMax - kNumTableBits)) + (offset << (kNumTableBits - len)); for (UInt32 k = 0; k < num; k++) dest[k] = val; } @@ -129,16 +139,18 @@ public: return startPos == kMaxValue; } + template <class TBitDecoder> - UInt32 Decode(TBitDecoder *bitStream) const throw() + MY_FORCE_INLINE + UInt32 Decode(TBitDecoder *bitStream) const { UInt32 val = bitStream->GetValue(kNumBitsMax); if (val < _limits[kNumTableBits]) { UInt32 pair = _lens[val >> (kNumBitsMax - kNumTableBits)]; - bitStream->MovePos((unsigned)(pair & 0xF)); - return pair >> 4; + bitStream->MovePos((unsigned)(pair & kPairLenMask)); + return pair >> kNumPairLenBits; } unsigned numBits; @@ -148,27 +160,29 @@ public: return 0xFFFFFFFF; bitStream->MovePos(numBits); - UInt32 index = _poses[numBits] + ((val - _limits[numBits - 1]) >> (kNumBitsMax - numBits)); + UInt32 index = _poses[numBits] + ((val - _limits[(size_t)numBits - 1]) >> (kNumBitsMax - numBits)); return _symbols[index]; } + template <class TBitDecoder> - UInt32 DecodeFull(TBitDecoder *bitStream) const throw() + MY_FORCE_INLINE + UInt32 DecodeFull(TBitDecoder *bitStream) const { UInt32 val = bitStream->GetValue(kNumBitsMax); if (val < _limits[kNumTableBits]) { UInt32 pair = _lens[val >> (kNumBitsMax - kNumTableBits)]; - bitStream->MovePos((unsigned)(pair & 0xF)); - return pair >> 4; + bitStream->MovePos((unsigned)(pair & kPairLenMask)); + return pair >> kNumPairLenBits; } unsigned numBits; for (numBits = kNumTableBits + 1; val >= _limits[numBits]; numBits++); bitStream->MovePos(numBits); - UInt32 index = _poses[numBits] + ((val - _limits[numBits - 1]) >> (kNumBitsMax - numBits)); + UInt32 index = _poses[numBits] + ((val - _limits[(size_t)numBits - 1]) >> (kNumBitsMax - numBits)); return _symbols[index]; } }; @@ -185,50 +199,54 @@ public: { const unsigned kNumBitsMax = 7; - UInt32 lenCounts[kNumBitsMax + 1]; - UInt32 tmpPoses[kNumBitsMax + 1]; + UInt32 counts[kNumBitsMax + 1]; UInt32 _poses[kNumBitsMax + 1]; UInt32 _limits[kNumBitsMax + 1]; unsigned i; for (i = 0; i <= kNumBitsMax; i++) - lenCounts[i] = 0; + counts[i] = 0; UInt32 sym; for (sym = 0; sym < m_NumSymbols; sym++) - lenCounts[lens[sym]]++; + counts[lens[sym]]++; - lenCounts[0] = 0; - _poses[0] = 0; + const UInt32 kMaxValue = (UInt32)1 << kNumBitsMax; + _limits[0] = 0; + UInt32 startPos = 0; - const UInt32 kMaxValue = (UInt32)1 << kNumBitsMax; + UInt32 sum = 0; for (i = 1; i <= kNumBitsMax; i++) { - startPos += lenCounts[i] << (kNumBitsMax - i); + const UInt32 cnt = counts[i]; + startPos += cnt << (kNumBitsMax - i); if (startPos > kMaxValue) return false; _limits[i] = startPos; - _poses[i] = _poses[i - 1] + lenCounts[i - 1]; - tmpPoses[i] = _poses[i]; + counts[i] = sum; + _poses[i] = sum; + sum += cnt; } + counts[0] = sum; + _poses[0] = sum; + for (sym = 0; sym < m_NumSymbols; sym++) { unsigned len = lens[sym]; if (len == 0) continue; - unsigned offset = tmpPoses[len]; - tmpPoses[len] = offset + 1; + unsigned offset = counts[len]++; { offset -= _poses[len]; UInt32 num = (UInt32)1 << (kNumBitsMax - len); Byte val = (Byte)((sym << 3) | len); - Byte *dest = _lens + (_limits[len - 1]) + (offset << (kNumBitsMax - len)); + Byte *dest = _lens + (_limits[(size_t)len - 1]) + (offset << (kNumBitsMax - len)); for (UInt32 k = 0; k < num; k++) dest[k] = val; } @@ -246,7 +264,7 @@ public: } template <class TBitDecoder> - UInt32 Decode(TBitDecoder *bitStream) const throw() + UInt32 Decode(TBitDecoder *bitStream) const { UInt32 val = bitStream->GetValue(7); UInt32 pair = _lens[val]; diff --git a/CPP/7zip/Compress/ImplodeDecoder.cpp b/CPP/7zip/Compress/ImplodeDecoder.cpp index e1d68a43..736c832e 100644 --- a/CPP/7zip/Compress/ImplodeDecoder.cpp +++ b/CPP/7zip/Compress/ImplodeDecoder.cpp @@ -10,214 +10,248 @@ namespace NCompress { namespace NImplode { namespace NDecoder { -class CException +bool CHuffmanDecoder::Build(const Byte *lens, unsigned numSymbols) throw() { -public: - enum ECauseType - { - kData - } m_Cause; - CException(ECauseType cause): m_Cause(cause) {} -}; + unsigned counts[kNumHuffmanBits + 1]; + + unsigned i; + for (i = 0; i <= kNumHuffmanBits; i++) + counts[i] = 0; + + unsigned sym; + for (sym = 0; sym < numSymbols; sym++) + counts[lens[sym]]++; -static const int kNumDistanceLowDirectBitsForBigDict = 7; -static const int kNumDistanceLowDirectBitsForSmallDict = 6; + const UInt32 kMaxValue = (UInt32)1 << kNumHuffmanBits; + + // _limits[0] = kMaxValue; -static const int kNumBitsInByte = 8; + UInt32 startPos = kMaxValue; + UInt32 sum = 0; -// static const int kLevelStructuresNumberFieldSize = kNumBitsInByte; -static const int kLevelStructuresNumberAdditionalValue = 1; + for (i = 1; i <= kNumHuffmanBits; i++) + { + const UInt32 cnt = counts[i]; + const UInt32 range = cnt << (kNumHuffmanBits - i); + if (startPos < range) + return false; + startPos -= range; + _limits[i] = startPos; + _poses[i] = sum; + sum += cnt; + counts[i] = sum; + } -static const int kNumLevelStructureLevelBits = 4; -static const int kLevelStructureLevelAdditionalValue = 1; + // counts[0] += sum; -static const int kNumLevelStructureRepNumberBits = 4; -static const int kLevelStructureRepNumberAdditionalValue = 1; + if (startPos != 0) + return false; + for (sym = 0; sym < numSymbols; sym++) + { + unsigned len = lens[sym]; + if (len != 0) + _symbols[--counts[len]] = (Byte)sym; + } -static const int kLiteralTableSize = (1 << kNumBitsInByte); -static const int kDistanceTableSize = 64; -static const int kLengthTableSize = 64; + return true; +} -static const UInt32 kHistorySize = - (1 << MyMax(kNumDistanceLowDirectBitsForBigDict, - kNumDistanceLowDirectBitsForSmallDict)) * - kDistanceTableSize; // = 8 KB; -static const int kNumAdditionalLengthBits = 8; +UInt32 CHuffmanDecoder::Decode(CInBit *inStream) const throw() +{ + UInt32 val = inStream->GetValue(kNumHuffmanBits); + unsigned numBits; + for (numBits = 1; val < _limits[numBits]; numBits++); + UInt32 sym = _symbols[_poses[numBits] + ((val - _limits[numBits]) >> (kNumHuffmanBits - numBits))]; + inStream->MovePos(numBits); + return sym; +} -static const UInt32 kMatchMinLenWhenLiteralsOn = 3; -static const UInt32 kMatchMinLenWhenLiteralsOff = 2; -static const UInt32 kMatchMinLenMax = MyMax(kMatchMinLenWhenLiteralsOn, - kMatchMinLenWhenLiteralsOff); // 3 -// static const UInt32 kMatchMaxLenMax = kMatchMinLenMax + (kLengthTableSize - 1) + (1 << kNumAdditionalLengthBits) - 1; // or 2 +static const unsigned kNumLenDirectBits = 8; -enum -{ - kMatchId = 0, - kLiteralId = 1 -}; +static const unsigned kNumDistDirectBitsSmall = 6; +static const unsigned kNumDistDirectBitsBig = 7; +static const unsigned kLitTableSize = (1 << 8); +static const unsigned kDistTableSize = 64; +static const unsigned kLenTableSize = 64; -CCoder::CCoder(): - m_LiteralDecoder(kLiteralTableSize), - m_LengthDecoder(kLengthTableSize), - m_DistanceDecoder(kDistanceTableSize) -{ -} +static const UInt32 kHistorySize = (1 << kNumDistDirectBitsBig) * kDistTableSize; // 8 KB -/* -void CCoder::ReleaseStreams() -{ - m_OutWindowStream.ReleaseStream(); - m_InBitStream.ReleaseStream(); -} -*/ -bool CCoder::ReadLevelItems(NImplode::NHuffman::CDecoder &decoder, - Byte *levels, int numLevelItems) -{ - int numCodedStructures = m_InBitStream.ReadBits(kNumBitsInByte) + - kLevelStructuresNumberAdditionalValue; - int currentIndex = 0; - for (int i = 0; i < numCodedStructures; i++) - { - int level = m_InBitStream.ReadBits(kNumLevelStructureLevelBits) + - kLevelStructureLevelAdditionalValue; - int rep = m_InBitStream.ReadBits(kNumLevelStructureRepNumberBits) + - kLevelStructureRepNumberAdditionalValue; - if (currentIndex + rep > numLevelItems) - throw CException(CException::kData); - for (int j = 0; j < rep; j++) - levels[currentIndex++] = (Byte)level; - } - if (currentIndex != numLevelItems) - return false; - return decoder.SetCodeLengths(levels); -} +CCoder::CCoder(): + _fullStreamMode(false), + _flags(0) +{} -bool CCoder::ReadTables(void) +bool CCoder::BuildHuff(CHuffmanDecoder &decoder, unsigned numSymbols) { - if (m_LiteralsOn) + Byte levels[kMaxHuffTableSize]; + unsigned numRecords = (unsigned)_inBitStream.ReadAlignedByte() + 1; + unsigned index = 0; + do { - Byte literalLevels[kLiteralTableSize]; - if (!ReadLevelItems(m_LiteralDecoder, literalLevels, kLiteralTableSize)) + unsigned b = (unsigned)_inBitStream.ReadAlignedByte(); + Byte level = (Byte)((b & 0xF) + 1); + unsigned rep = ((unsigned)b >> 4) + 1; + if (index + rep > numSymbols) return false; + for (unsigned j = 0; j < rep; j++) + levels[index++] = level; } + while (--numRecords); - Byte lengthLevels[kLengthTableSize]; - if (!ReadLevelItems(m_LengthDecoder, lengthLevels, kLengthTableSize)) + if (index != numSymbols) return false; - - Byte distanceLevels[kDistanceTableSize]; - return ReadLevelItems(m_DistanceDecoder, distanceLevels, kDistanceTableSize); + return decoder.Build(levels, numSymbols); } -/* -class CCoderReleaser -{ - CCoder *m_Coder; -public: - CCoderReleaser(CCoder *coder): m_Coder(coder) {} - ~CCoderReleaser() { m_Coder->ReleaseStreams(); } -}; -*/ HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { - if (!m_InBitStream.Create(1 << 20)) + if (!_inBitStream.Create(1 << 18)) return E_OUTOFMEMORY; - if (!m_OutWindowStream.Create(kHistorySize)) + if (!_outWindowStream.Create(kHistorySize << 1)) // 16 KB return E_OUTOFMEMORY; - if (outSize == NULL) + if (!outSize) return E_INVALIDARG; - UInt64 pos = 0, unPackSize = *outSize; - m_OutWindowStream.SetStream(outStream); - m_OutWindowStream.Init(false); - m_InBitStream.SetStream(inStream); - m_InBitStream.Init(); - // CCoderReleaser coderReleaser(this); - - if (!ReadTables()) + _outWindowStream.SetStream(outStream); + _outWindowStream.Init(false); + _inBitStream.SetStream(inStream); + _inBitStream.Init(); + + const unsigned numDistDirectBits = (_flags & 2) ? + kNumDistDirectBitsBig: + kNumDistDirectBitsSmall; + const bool literalsOn = ((_flags & 4) != 0); + const UInt32 minMatchLen = (literalsOn ? 3 : 2); + + if (literalsOn) + if (!BuildHuff(_litDecoder, kLitTableSize)) + return S_FALSE; + if (!BuildHuff(_lenDecoder, kLenTableSize)) return S_FALSE; - + if (!BuildHuff(_distDecoder, kDistTableSize)) + return S_FALSE; + + UInt64 prevProgress = 0; + bool moreOut = false; + UInt64 pos = 0, unPackSize = *outSize; + while (pos < unPackSize) { - if (progress != NULL && pos % (1 << 16) == 0) + if (progress && (pos - prevProgress) >= (1 << 18)) { - UInt64 packSize = m_InBitStream.GetProcessedSize(); + const UInt64 packSize = _inBitStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(&packSize, &pos)); + prevProgress = pos; } - if (m_InBitStream.ReadBits(1) == kMatchId) // match + + if (_inBitStream.ReadBits(1) != 0) { - UInt32 lowDistBits = m_InBitStream.ReadBits(m_NumDistanceLowDirectBits); - UInt32 distance = m_DistanceDecoder.DecodeSymbol(&m_InBitStream); - if (distance >= kDistanceTableSize) - return S_FALSE; - distance = (distance << m_NumDistanceLowDirectBits) + lowDistBits; - UInt32 lengthSymbol = m_LengthDecoder.DecodeSymbol(&m_InBitStream); - if (lengthSymbol >= kLengthTableSize) - return S_FALSE; - UInt32 length = lengthSymbol + m_MinMatchLength; - if (lengthSymbol == kLengthTableSize - 1) // special symbol = 63 - length += m_InBitStream.ReadBits(kNumAdditionalLengthBits); - while (distance >= pos && length > 0) + Byte b; + if (literalsOn) { - m_OutWindowStream.PutByte(0); - pos++; - length--; + UInt32 sym = _litDecoder.Decode(&_inBitStream); + // if (sym >= kLitTableSize) break; + b = (Byte)sym; } - if (length > 0) - m_OutWindowStream.CopyBlock(distance, length); - pos += length; + else + b = (Byte)_inBitStream.ReadBits(8); + _outWindowStream.PutByte(b); + pos++; } else { - Byte b; - if (m_LiteralsOn) + UInt32 lowDistBits = _inBitStream.ReadBits(numDistDirectBits); + UInt32 dist = _distDecoder.Decode(&_inBitStream); + // if (dist >= kDistTableSize) break; + dist = (dist << numDistDirectBits) + lowDistBits; + UInt32 len = _lenDecoder.Decode(&_inBitStream); + // if (len >= kLenTableSize) break; + if (len == kLenTableSize - 1) + len += _inBitStream.ReadBits(kNumLenDirectBits); + len += minMatchLen; + { - UInt32 temp = m_LiteralDecoder.DecodeSymbol(&m_InBitStream); - if (temp >= kLiteralTableSize) - return S_FALSE; - b = (Byte)temp; + const UInt64 limit = unPackSize - pos; + if (len > limit) + { + moreOut = true; + len = (UInt32)limit; + } + } + + while (dist >= pos && len != 0) + { + _outWindowStream.PutByte(0); + pos++; + len--; + } + + if (len != 0) + { + _outWindowStream.CopyBlock(dist, len); + pos += len; } - else - b = (Byte)m_InBitStream.ReadBits(kNumBitsInByte); - m_OutWindowStream.PutByte(b); - pos++; } } - if (pos > unPackSize) - return S_FALSE; - return m_OutWindowStream.Flush(); + + HRESULT res = _outWindowStream.Flush(); + + if (res == S_OK) + { + if (_fullStreamMode) + { + if (moreOut) + res = S_FALSE; + if (inSize && *inSize != _inBitStream.GetProcessedSize()) + res = S_FALSE; + } + if (pos != unPackSize) + res = S_FALSE; + } + + return res; } + 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 CLzOutWindowException &e) { return e.ErrorCode; } + // catch(const CInBufferException &e) { return e.ErrorCode; } + // catch(const CLzOutWindowException &e) { return e.ErrorCode; } + catch(const CSystemException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } + STDMETHODIMP CCoder::SetDecoderProperties2(const Byte *data, UInt32 size) { - if (size < 1) - return E_INVALIDARG; - Byte flag = data[0]; - m_BigDictionaryOn = ((flag & 2) != 0); - m_NumDistanceLowDirectBits = m_BigDictionaryOn ? - kNumDistanceLowDirectBitsForBigDict: - kNumDistanceLowDirectBitsForSmallDict; - m_LiteralsOn = ((flag & 4) != 0); - m_MinMatchLength = m_LiteralsOn ? - kMatchMinLenWhenLiteralsOn : - kMatchMinLenWhenLiteralsOff; + if (size == 0) + return E_NOTIMPL; + _flags = data[0]; + return S_OK; +} + + +STDMETHODIMP CCoder::SetFinishMode(UInt32 finishMode) +{ + _fullStreamMode = (finishMode != 0); + return S_OK; +} + + +STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value) +{ + *value = _inBitStream.GetProcessedSize(); return S_OK; } diff --git a/CPP/7zip/Compress/ImplodeDecoder.h b/CPP/7zip/Compress/ImplodeDecoder.h index 5876ecac..a73c143c 100644 --- a/CPP/7zip/Compress/ImplodeDecoder.h +++ b/CPP/7zip/Compress/ImplodeDecoder.h @@ -7,48 +7,65 @@ #include "../ICoder.h" -#include "ImplodeHuffmanDecoder.h" +#include "../Common/InBuffer.h" + +#include "BitlDecoder.h" #include "LzOutWindow.h" namespace NCompress { namespace NImplode { namespace NDecoder { +typedef NBitl::CDecoder<CInBuffer> CInBit; + +const unsigned kNumHuffmanBits = 16; +const unsigned kMaxHuffTableSize = 1 << 8; + +class CHuffmanDecoder +{ + UInt32 _limits[kNumHuffmanBits + 1]; + UInt32 _poses[kNumHuffmanBits + 1]; + Byte _symbols[kMaxHuffTableSize]; +public: + bool Build(const Byte *lens, unsigned numSymbols) throw(); + UInt32 Decode(CInBit *inStream) const throw(); +}; + + class CCoder: public ICompressCoder, public ICompressSetDecoderProperties2, + public ICompressSetFinishMode, + public ICompressGetInStreamProcessedSize, public CMyUnknownImp { - CLzOutWindow m_OutWindowStream; - NBitl::CDecoder<CInBuffer> m_InBitStream; + CLzOutWindow _outWindowStream; + CInBit _inBitStream; - NImplode::NHuffman::CDecoder m_LiteralDecoder; - NImplode::NHuffman::CDecoder m_LengthDecoder; - NImplode::NHuffman::CDecoder m_DistanceDecoder; + CHuffmanDecoder _litDecoder; + CHuffmanDecoder _lenDecoder; + CHuffmanDecoder _distDecoder; - bool m_BigDictionaryOn; - bool m_LiteralsOn; + Byte _flags; + bool _fullStreamMode; - int m_NumDistanceLowDirectBits; - UInt32 m_MinMatchLength; - - bool ReadLevelItems(NImplode::NHuffman::CDecoder &table, Byte *levels, int numLevelItems); - bool ReadTables(); - void DeCodeLevelTable(Byte *newLevels, int numLevels); -public: - CCoder(); - - MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) - - // void ReleaseStreams(); - + bool BuildHuff(CHuffmanDecoder &table, unsigned numSymbols); HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); +public: + MY_UNKNOWN_IMP3( + ICompressSetDecoderProperties2, + ICompressSetFinishMode, + ICompressGetInStreamProcessedSize) + 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); + + CCoder(); }; }}} diff --git a/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp b/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp index d385d7b1..7d31bb94 100644 --- a/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp +++ b/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp @@ -1,89 +1,3 @@ // ImplodeHuffmanDecoder.cpp #include "StdAfx.h" - -#include "ImplodeHuffmanDecoder.h" - -namespace NCompress { -namespace NImplode { -namespace NHuffman { - -CDecoder::CDecoder(UInt32 numSymbols): - m_NumSymbols(numSymbols) -{ - m_Symbols = new UInt32[m_NumSymbols]; -} - -CDecoder::~CDecoder() -{ - delete []m_Symbols; -} - -bool CDecoder::SetCodeLengths(const Byte *codeLengths) -{ - // 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; - for (symbolIndex = 0; symbolIndex < m_NumSymbols; symbolIndex++) - lenCounts[codeLengths[symbolIndex]]++; - // lenCounts[0] = 0; - - // tmpPositions[0] = m_Positions[0] = m_Limitits[0] = 0; - m_Limitits[kNumBitsInLongestCode + 1] = 0; - m_Positions[kNumBitsInLongestCode + 1] = 0; - lenCounts[kNumBitsInLongestCode + 1] = 0; - - - UInt32 startPos = 0; - static const UInt32 kMaxValue = (1 << kNumBitsInLongestCode); - - for (i = kNumBitsInLongestCode; i > 0; i--) - { - startPos += lenCounts[i] << (kNumBitsInLongestCode - i); - if (startPos > kMaxValue) - return false; - m_Limitits[i] = startPos; - m_Positions[i] = m_Positions[i + 1] + lenCounts[i + 1]; - tmpPositions[i] = m_Positions[i] + lenCounts[i]; - - } - - // if _ZIP_MODE do not throw exception for trees containing only one node - // #ifndef _ZIP_MODE - if (startPos != kMaxValue) - return false; - // #endif - - for (symbolIndex = 0; symbolIndex < m_NumSymbols; symbolIndex++) - if (codeLengths[symbolIndex] != 0) - m_Symbols[--tmpPositions[codeLengths[symbolIndex]]] = symbolIndex; - return true; -} - -UInt32 CDecoder::DecodeSymbol(CInBit *inStream) -{ - UInt32 numBits = 0; - UInt32 value = inStream->GetValue(kNumBitsInLongestCode); - unsigned i; - for (i = kNumBitsInLongestCode; i > 0; i--) - { - if (value < m_Limitits[i]) - { - numBits = i; - break; - } - } - if (i == 0) - return 0xFFFFFFFF; - inStream->MovePos(numBits); - UInt32 index = m_Positions[numBits] + - ((value - m_Limitits[numBits + 1]) >> (kNumBitsInLongestCode - numBits)); - if (index >= m_NumSymbols) - return 0xFFFFFFFF; - return m_Symbols[index]; -} - -}}} diff --git a/CPP/7zip/Compress/ImplodeHuffmanDecoder.h b/CPP/7zip/Compress/ImplodeHuffmanDecoder.h index 691a8e93..ea25211a 100644 --- a/CPP/7zip/Compress/ImplodeHuffmanDecoder.h +++ b/CPP/7zip/Compress/ImplodeHuffmanDecoder.h @@ -3,32 +3,4 @@ #ifndef __IMPLODE_HUFFMAN_DECODER_H #define __IMPLODE_HUFFMAN_DECODER_H -#include "../Common/InBuffer.h" - -#include "BitlDecoder.h" - -namespace NCompress { -namespace NImplode { -namespace NHuffman { - -const unsigned kNumBitsInLongestCode = 16; - -typedef NBitl::CDecoder<CInBuffer> CInBit; - -class CDecoder -{ - UInt32 m_Limitits[kNumBitsInLongestCode + 2]; // m_Limitits[i] = value limit for symbols with length = i - UInt32 m_Positions[kNumBitsInLongestCode + 2]; // m_Positions[i] = index in m_Symbols[] of first symbol with length = i - UInt32 m_NumSymbols; // number of symbols in m_Symbols - UInt32 *m_Symbols; // symbols: at first with len=1 then 2, ... 15. -public: - CDecoder(UInt32 numSymbols); - ~CDecoder(); - - bool SetCodeLengths(const Byte *codeLengths); - UInt32 DecodeSymbol(CInBit *inStream); -}; - -}}} - #endif diff --git a/CPP/7zip/Compress/Lzma2Decoder.cpp b/CPP/7zip/Compress/Lzma2Decoder.cpp index 1a378bbe..98af203d 100644 --- a/CPP/7zip/Compress/Lzma2Decoder.cpp +++ b/CPP/7zip/Compress/Lzma2Decoder.cpp @@ -15,7 +15,7 @@ static HRESULT SResToHRESULT(SRes res) case SZ_OK: return S_OK; case SZ_ERROR_MEM: return E_OUTOFMEMORY; case SZ_ERROR_PARAM: return E_INVALIDARG; - // case SZ_ERROR_PROGRESS: return E_ABORT; + case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; case SZ_ERROR_DATA: return S_FALSE; } return E_FAIL; @@ -26,30 +26,31 @@ namespace NLzma2 { CDecoder::CDecoder(): _inBuf(NULL), - _inBufSize(0), - _inBufSizeNew(1 << 20), - _outStepSize(1 << 22), + _finishMode(false), _outSizeDefined(false), - _finishMode(false) + _outStep(1 << 22), + _inBufSize(0), + _inBufSizeNew(1 << 20) { Lzma2Dec_Construct(&_state); } -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); MidFree(_inBuf); } +STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSizeNew = size; return S_OK; } +STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outStep = size; return S_OK; } + STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size) { if (size != 1) return E_NOTIMPL; RINOK(SResToHRESULT(Lzma2Dec_Allocate(&_state, prop[0], &g_Alloc))); + if (!_inBuf || _inBufSize != _inBufSizeNew) { MidFree(_inBuf); @@ -63,9 +64,6 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size) return S_OK; } -STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _inSizeProcessed; return S_OK; } -STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; } -STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; } STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { @@ -73,191 +71,197 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) _outSize = 0; if (_outSizeDefined) _outSize = *outSize; + _inPos = _inLim = 0; + _inProcessed = 0; + _outProcessed = 0; Lzma2Dec_Init(&_state); - - _inPos = _inSize = 0; - _inSizeProcessed = _outSizeProcessed = 0; + return S_OK; } + STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode) { _finishMode = (finishMode != 0); return S_OK; } -STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, - ISequentialOutStream *outStream, const UInt64 *inSize, - const UInt64 *outSize, ICompressProgressInfo *progress) + +STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) +{ + *value = _inProcessed; + return S_OK; +} + + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { 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; + HRESULT readRes = S_OK; for (;;) { - if (_inPos == _inSize) + if (_inPos == _inLim && readRes == S_OK) { - _inPos = _inSize = 0; - hres = inStream->Read(_inBuf, _inBufSize, &_inSize); - if (hres != S_OK) - break; + _inPos = _inLim = 0; + readRes = inStream->Read(_inBuf, _inBufSize, &_inLim); + } + + const SizeT dicPos = _state.decoder.dicPos; + SizeT size; + { + SizeT next = _state.decoder.dicBufSize; + if (next - wrPos > _outStep) + next = wrPos + _outStep; + size = next - dicPos; } - SizeT dicPos = _state.decoder.dicPos; - SizeT curSize = next - dicPos; - ELzmaFinishMode finishMode = LZMA_FINISH_ANY; if (_outSizeDefined) { - const UInt64 rem = _outSize - _outSizeProcessed; - if (curSize >= rem) + const UInt64 rem = _outSize - _outProcessed; + if (size >= rem) { - curSize = (SizeT)rem; + size = (SizeT)rem; if (_finishMode) finishMode = LZMA_FINISH_END; } } - SizeT inSizeProcessed = _inSize - _inPos; + SizeT inProcessed = _inLim - _inPos; ELzmaStatus status; - SRes res = Lzma2Dec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status); + + SRes res = Lzma2Dec_DecodeToDic(&_state, dicPos + size, _inBuf + _inPos, &inProcessed, finishMode, &status); - _inPos += (UInt32)inSizeProcessed; - _inSizeProcessed += inSizeProcessed; - SizeT outSizeProcessed = _state.decoder.dicPos - dicPos; - _outSizeProcessed += outSizeProcessed; + + _inPos += (UInt32)inProcessed; + _inProcessed += inProcessed; + const SizeT outProcessed = _state.decoder.dicPos - dicPos; + _outProcessed += outProcessed; + + + bool outFinished = (_outSizeDefined && _outProcessed >= _outSize); - bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0 - || status == LZMA_STATUS_FINISHED_WITH_MARK); - bool outFinished = (_outSizeDefined && _outSizeProcessed >= _outSize); + bool needStop = (res != 0 + || (inProcessed == 0 && outProcessed == 0) + || status == LZMA_STATUS_FINISHED_WITH_MARK + || (!_finishMode && outFinished)); - if (res != 0 - || _state.decoder.dicPos >= next - || finished - || outFinished) + if (needStop || outProcessed >= size) { 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 (finished) + if (needStop) { + if (res != 0) + return S_FALSE; + 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; + if (_finishMode) + { + if (inSize && *inSize != _inProcessed) + return S_FALSE; + if (_outSizeDefined && _outSize != _outProcessed) + return S_FALSE; + } + return readRes; } - return (finishMode == LZMA_FINISH_END) ? S_FALSE : S_OK; - } - if (outFinished && finishMode == LZMA_FINISH_ANY) - return S_OK; + if (!_finishMode && outFinished) + return readRes; + + return S_FALSE; + } } if (progress) { - RINOK(progress->SetRatioInfo(&_inSizeProcessed, &_outSizeProcessed)); + RINOK(progress->SetRatioInfo(&_inProcessed, &_outProcessed)); } } - - 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::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; } +STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; } + + STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { - UInt32 totalProcessed = 0; - if (processedSize) *processedSize = 0; - for (;;) + ELzmaFinishMode finishMode = LZMA_FINISH_ANY; + if (_outSizeDefined) { - if (_inPos == _inSize) + const UInt64 rem = _outSize - _outProcessed; + if (size >= rem) { - _inPos = _inSize = 0; - RINOK(_inStream->Read(_inBuf, _inBufSize, &_inSize)); + size = (UInt32)rem; + if (_finishMode) + finishMode = LZMA_FINISH_END; } + } + + HRESULT readRes = S_OK; + + for (;;) + { + if (_inPos == _inLim && readRes == S_OK) { - ELzmaFinishMode finishMode = LZMA_FINISH_ANY; - if (_outSizeDefined) - { - const UInt64 rem = _outSize - _outSizeProcessed; - if (rem <= size) - { - size = (UInt32)rem; - if (_finishMode) - finishMode = LZMA_FINISH_END; - } - } + _inPos = _inLim = 0; + readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim); + } + + SizeT inProcessed = _inLim - _inPos; + SizeT outProcessed = size; + ELzmaStatus status; - SizeT outProcessed = size; - SizeT inProcessed = _inSize - _inPos; - - ELzmaStatus status; - SRes res = Lzma2Dec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, - _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 = 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; - } + SRes res = Lzma2Dec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, + _inBuf + _inPos, &inProcessed, finishMode, &status); + + + _inPos += (UInt32)inProcessed; + _inProcessed += inProcessed; + _outProcessed += outProcessed; + size -= (UInt32)outProcessed; + data = (Byte *)data + outProcessed; + if (processedSize) + *processedSize += (UInt32)outProcessed; + + if (res != 0) + return S_FALSE; + + /* + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + return readRes; + + if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT) + { + if (_finishMode && _outSizeDefined && _outProcessed >= _outSize) + return S_FALSE; + return readRes; } + */ + + if (inProcessed == 0 && outProcessed == 0) + return readRes; } } diff --git a/CPP/7zip/Compress/Lzma2Decoder.h b/CPP/7zip/Compress/Lzma2Decoder.h index a87912fb..440914e7 100644 --- a/CPP/7zip/Compress/Lzma2Decoder.h +++ b/CPP/7zip/Compress/Lzma2Decoder.h @@ -6,7 +6,6 @@ #include "../../../C/Lzma2Dec.h" #include "../../Common/MyCom.h" - #include "../ICoder.h" namespace NCompress { @@ -25,25 +24,23 @@ class CDecoder: #endif public CMyUnknownImp { - CMyComPtr<ISequentialInStream> _inStream; Byte *_inBuf; UInt32 _inPos; - UInt32 _inSize; + UInt32 _inLim; bool _finishMode; bool _outSizeDefined; UInt64 _outSize; - - UInt64 _inSizeProcessed; - UInt64 _outSizeProcessed; + UInt64 _inProcessed; + UInt64 _outProcessed; + UInt32 _outStep; UInt32 _inBufSize; UInt32 _inBufSizeNew; - UInt32 _outStepSize; CLzma2Dec _state; -public: +public: MY_QUERYINTERFACE_BEGIN2(ICompressCoder) MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2) MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode) @@ -59,28 +56,27 @@ 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(GetInStreamProcessedSize)(UInt64 *value); - + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size); STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size); + #ifndef NO_READ_FROM_CODER + +private: + CMyComPtr<ISequentialInStream> _inStream; +public: + STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); - - STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); - - #ifndef NO_READ_FROM_CODER STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + #endif CDecoder(); virtual ~CDecoder(); - }; }} diff --git a/CPP/7zip/Compress/Lzma2Encoder.cpp b/CPP/7zip/Compress/Lzma2Encoder.cpp index 06a11f10..9b3258cd 100644 --- a/CPP/7zip/Compress/Lzma2Encoder.cpp +++ b/CPP/7zip/Compress/Lzma2Encoder.cpp @@ -82,11 +82,15 @@ STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) { - CSeqInStreamWrap inWrap(inStream); - CSeqOutStreamWrap outWrap(outStream); - CCompressProgressWrap progressWrap(progress); + CSeqInStreamWrap inWrap; + CSeqOutStreamWrap outWrap; + CCompressProgressWrap progressWrap; + + inWrap.Init(inStream); + outWrap.Init(outStream); + progressWrap.Init(progress); - SRes res = Lzma2Enc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL); + SRes res = Lzma2Enc_Encode(_encoder, &outWrap.vt, &inWrap.vt, progress ? &progressWrap.vt : NULL); if (res == SZ_ERROR_READ && inWrap.Res != S_OK) return inWrap.Res; if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK) diff --git a/CPP/7zip/Compress/LzmaDecoder.cpp b/CPP/7zip/Compress/LzmaDecoder.cpp index 9002678a..2fbe0589 100644 --- a/CPP/7zip/Compress/LzmaDecoder.cpp +++ b/CPP/7zip/Compress/LzmaDecoder.cpp @@ -24,14 +24,19 @@ static HRESULT SResToHRESULT(SRes res) namespace NCompress { namespace NLzma { -CDecoder::CDecoder(): _inBuf(0), _propsWereSet(false), _outSizeDefined(false), - _inBufSize(1 << 20), - _outBufSize(1 << 22), +CDecoder::CDecoder(): + _inBuf(NULL), + _lzmaStatus(LZMA_STATUS_NOT_SPECIFIED), FinishStream(false), - NeedMoreInput(false) + _propsWereSet(false), + _outSizeDefined(false), + _outStep(1 << 22), + _inBufSize(0), + _inBufSizeNew(1 << 20) { - _inSizeProcessed = 0; - _inPos = _inSize = 0; + _inProcessed = 0; + _inPos = _inLim = 0; + LzmaDec_Construct(&_state); } @@ -41,22 +46,24 @@ CDecoder::~CDecoder() MyFree(_inBuf); } -STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; } -STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; } +STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSizeNew = size; return S_OK; } +STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outStep = size; return S_OK; } HRESULT CDecoder::CreateInputBuffer() { - if (_inBuf == 0 || _inBufSize != _inBufSizeAllocated) + if (!_inBuf || _inBufSizeNew != _inBufSize) { MyFree(_inBuf); - _inBuf = (Byte *)MyAlloc(_inBufSize); - if (_inBuf == 0) + _inBufSize = 0; + _inBuf = (Byte *)MyAlloc(_inBufSizeNew); + if (!_inBuf) return E_OUTOFMEMORY; - _inBufSizeAllocated = _inBufSize; + _inBufSize = _inBufSizeNew; } return S_OK; } + STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size) { RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_Alloc))); @@ -64,203 +71,266 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size) return CreateInputBuffer(); } + void CDecoder::SetOutStreamSizeResume(const UInt64 *outSize) { _outSizeDefined = (outSize != NULL); + _outSize = 0; if (_outSizeDefined) _outSize = *outSize; - _outSizeProcessed = 0; - _wrPos = 0; + _outProcessed = 0; + _lzmaStatus = LZMA_STATUS_NOT_SPECIFIED; + LzmaDec_Init(&_state); } + STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { - _inSizeProcessed = 0; - _inPos = _inSize = 0; - NeedMoreInput = false; + _inProcessed = 0; + _inPos = _inLim = 0; SetOutStreamSizeResume(outSize); return S_OK; } + STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode) { FinishStream = (finishMode != 0); return S_OK; } + +STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) +{ + *value = _inProcessed; + return S_OK; +} + + HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) { - if (_inBuf == 0 || !_propsWereSet) + if (!_inBuf || !_propsWereSet) return S_FALSE; + + const UInt64 startInProgress = _inProcessed; + SizeT wrPos = _state.dicPos; + HRESULT readRes = S_OK; - UInt64 startInProgress = _inSizeProcessed; - - SizeT next = (_state.dicBufSize - _state.dicPos < _outBufSize) ? _state.dicBufSize : (_state.dicPos + _outBufSize); for (;;) { - if (_inPos == _inSize) + if (_inPos == _inLim && readRes == S_OK) { - _inPos = _inSize = 0; - RINOK(inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize)); + _inPos = _inLim = 0; + readRes = inStream->Read(_inBuf, _inBufSize, &_inLim); + } + + const SizeT dicPos = _state.dicPos; + SizeT size; + { + SizeT next = _state.dicBufSize; + if (next - wrPos > _outStep) + next = wrPos + _outStep; + size = next - dicPos; } - SizeT dicPos = _state.dicPos; - SizeT curSize = next - dicPos; - ELzmaFinishMode finishMode = LZMA_FINISH_ANY; if (_outSizeDefined) { - const UInt64 rem = _outSize - _outSizeProcessed; - if (rem <= curSize) + const UInt64 rem = _outSize - _outProcessed; + if (size >= rem) { - curSize = (SizeT)rem; + size = (SizeT)rem; if (FinishStream) finishMode = LZMA_FINISH_END; } } - SizeT inSizeProcessed = _inSize - _inPos; + SizeT inProcessed = _inLim - _inPos; ELzmaStatus status; - SRes res = LzmaDec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status); + + SRes res = LzmaDec_DecodeToDic(&_state, dicPos + size, _inBuf + _inPos, &inProcessed, finishMode, &status); + + _lzmaStatus = status; + _inPos += (UInt32)inProcessed; + _inProcessed += inProcessed; + const SizeT outProcessed = _state.dicPos - dicPos; + _outProcessed += outProcessed; - _inPos += (UInt32)inSizeProcessed; - _inSizeProcessed += inSizeProcessed; - SizeT outSizeProcessed = _state.dicPos - dicPos; - _outSizeProcessed += outSizeProcessed; + // we check for LZMA_STATUS_NEEDS_MORE_INPUT to allow RangeCoder initialization, if (_outSizeDefined && _outSize == 0) + bool outFinished = (_outSizeDefined && _outProcessed >= _outSize); - bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0); - bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize); + bool needStop = (res != 0 + || (inProcessed == 0 && outProcessed == 0) + || status == LZMA_STATUS_FINISHED_WITH_MARK + || (outFinished && status != LZMA_STATUS_NEEDS_MORE_INPUT)); - if (res != 0 || _state.dicPos == next || finished || stopDecoding) + if (needStop || outProcessed >= size) { - HRESULT res2 = WriteStream(outStream, _state.dic + _wrPos, _state.dicPos - _wrPos); + HRESULT res2 = WriteStream(outStream, _state.dic + wrPos, _state.dicPos - wrPos); - _wrPos = _state.dicPos; if (_state.dicPos == _state.dicBufSize) - { _state.dicPos = 0; - _wrPos = 0; - } - next = (_state.dicBufSize - _state.dicPos < _outBufSize) ? _state.dicBufSize : (_state.dicPos + _outBufSize); - - if (res != 0) - return S_FALSE; + wrPos = _state.dicPos; + RINOK(res2); - if (stopDecoding) + + if (needStop) { - if (status == LZMA_STATUS_NEEDS_MORE_INPUT) - NeedMoreInput = true; - if (FinishStream && - status != LZMA_STATUS_FINISHED_WITH_MARK && - status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) + if (res != 0) return S_FALSE; - return S_OK; - } - if (finished) - { - if (status == LZMA_STATUS_NEEDS_MORE_INPUT) - NeedMoreInput = true; - return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE); + + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + { + if (FinishStream) + if (_outSizeDefined && _outSize != _outProcessed) + return S_FALSE; + return readRes; + } + + if (outFinished && status != LZMA_STATUS_NEEDS_MORE_INPUT) + if (!FinishStream || status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) + return readRes; + + return S_FALSE; } } + if (progress) { - UInt64 inSize = _inSizeProcessed - startInProgress; - RINOK(progress->SetRatioInfo(&inSize, &_outSizeProcessed)); + const UInt64 inSize = _inProcessed - startInProgress; + RINOK(progress->SetRatioInfo(&inSize, &_outProcessed)); } } } + STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { - if (_inBuf == 0) + if (!_inBuf) return E_INVALIDARG; SetOutStreamSize(outSize); - return CodeSpec(inStream, outStream, progress); + HRESULT res = CodeSpec(inStream, outStream, progress); + if (res == S_OK) + if (FinishStream && inSize && *inSize != _inProcessed) + res = S_FALSE; + return res; } + #ifndef NO_READ_FROM_CODER STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; } STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; } + STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) *processedSize = 0; - do + + ELzmaFinishMode finishMode = LZMA_FINISH_ANY; + if (_outSizeDefined) { - if (_inPos == _inSize) + const UInt64 rem = _outSize - _outProcessed; + if (size >= rem) { - _inPos = _inSize = 0; - RINOK(_inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize)); + size = (UInt32)rem; + if (FinishStream) + finishMode = LZMA_FINISH_END; } + } + + HRESULT readRes = S_OK; + + for (;;) + { + if (_inPos == _inLim && readRes == S_OK) { - SizeT inProcessed = _inSize - _inPos; + _inPos = _inLim = 0; + readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim); + } - if (_outSizeDefined) - { - const UInt64 rem = _outSize - _outSizeProcessed; - if (rem < size) - size = (UInt32)rem; - } + SizeT inProcessed = _inLim - _inPos; + SizeT outProcessed = size; + ELzmaStatus status; + + SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, + _inBuf + _inPos, &inProcessed, finishMode, &status); + + _lzmaStatus = status; + _inPos += (UInt32)inProcessed; + _inProcessed += inProcessed; + _outProcessed += outProcessed; + size -= (UInt32)outProcessed; + data = (Byte *)data + outProcessed; + if (processedSize) + *processedSize += (UInt32)outProcessed; + + if (res != 0) + return S_FALSE; + + /* + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + return readRes; - SizeT outProcessed = size; - ELzmaStatus status; - SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, - _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status); - _inPos += (UInt32)inProcessed; - _inSizeProcessed += inProcessed; - _outSizeProcessed += outProcessed; - size -= (UInt32)outProcessed; - data = (Byte *)data + outProcessed; - if (processedSize) - *processedSize += (UInt32)outProcessed; - RINOK(SResToHRESULT(res)); - if (inProcessed == 0 && outProcessed == 0) - return S_OK; + if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT) + { + if (FinishStream + && _outSizeDefined && _outProcessed >= _outSize + && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) + return S_FALSE; + return readRes; } + */ + + if (inProcessed == 0 && outProcessed == 0) + return readRes; } - while (size != 0); - return S_OK; } + HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress) { SetOutStreamSizeResume(outSize); return CodeSpec(_inStream, outStream, progress); } + HRESULT CDecoder::ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize) { RINOK(CreateInputBuffer()); + if (processedSize) *processedSize = 0; - while (size > 0) + + HRESULT readRes = S_OK; + + while (size != 0) { - if (_inPos == _inSize) + if (_inPos == _inLim) { - _inPos = _inSize = 0; - RINOK(_inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize)); - if (_inSize == 0) + _inPos = _inLim = 0; + if (readRes == S_OK) + readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim); + if (_inLim == 0) break; } - { - UInt32 curSize = _inSize - _inPos; - if (curSize > size) - curSize = size; - memcpy(data, _inBuf + _inPos, curSize); - _inPos += curSize; - _inSizeProcessed += curSize; - size -= curSize; - data = (Byte *)data + curSize; - if (processedSize) - *processedSize += curSize; - } + + UInt32 cur = _inLim - _inPos; + if (cur > size) + cur = size; + memcpy(data, _inBuf + _inPos, cur); + _inPos += cur; + _inProcessed += cur; + size -= cur; + data = (Byte *)data + cur; + if (processedSize) + *processedSize += cur; } - return S_OK; + + return readRes; } #endif diff --git a/CPP/7zip/Compress/LzmaDecoder.h b/CPP/7zip/Compress/LzmaDecoder.h index f1f839a4..e73925ed 100644 --- a/CPP/7zip/Compress/LzmaDecoder.h +++ b/CPP/7zip/Compress/LzmaDecoder.h @@ -15,6 +15,7 @@ class CDecoder: public ICompressCoder, public ICompressSetDecoderProperties2, public ICompressSetFinishMode, + public ICompressGetInStreamProcessedSize, public ICompressSetBufSize, #ifndef NO_READ_FROM_CODER public ICompressSetInStream, @@ -23,21 +24,26 @@ class CDecoder: #endif public CMyUnknownImp { - CMyComPtr<ISequentialInStream> _inStream; Byte *_inBuf; UInt32 _inPos; - UInt32 _inSize; + UInt32 _inLim; + CLzmaDec _state; + ELzmaStatus _lzmaStatus; + +public: + bool FinishStream; // set it before decoding, if you need to decode full LZMA stream + +private: bool _propsWereSet; bool _outSizeDefined; UInt64 _outSize; - UInt64 _inSizeProcessed; - UInt64 _outSizeProcessed; + UInt64 _inProcessed; + UInt64 _outProcessed; - UInt32 _inBufSizeAllocated; + UInt32 _outStep; UInt32 _inBufSize; - UInt32 _outBufSize; - SizeT _wrPos; + UInt32 _inBufSizeNew; HRESULT CreateInputBuffer(); HRESULT CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress); @@ -47,6 +53,7 @@ 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_QUERYINTERFACE_ENTRY(ICompressSetInStream) @@ -60,11 +67,16 @@ public: const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); STDMETHOD(SetFinishMode)(UInt32 finishMode); + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size); STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size); #ifndef NO_READ_FROM_CODER + +private: + CMyComPtr<ISequentialInStream> _inStream; +public: STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); @@ -72,18 +84,24 @@ public: HRESULT CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress); HRESULT ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize); - UInt64 GetInputProcessedSize() const { return _inSizeProcessed; } - + #endif - bool FinishStream; // set it before decoding, if you need to decode full LZMA stream - - bool NeedMoreInput; // it's set by decoder, if it needs more input data to decode stream + UInt64 GetInputProcessedSize() const { return _inProcessed; } CDecoder(); virtual ~CDecoder(); - UInt64 GetOutputProcessedSize() const { return _outSizeProcessed; } + UInt64 GetOutputProcessedSize() const { return _outProcessed; } + + bool NeedsMoreInput() const { return _lzmaStatus == LZMA_STATUS_NEEDS_MORE_INPUT; } + + bool CheckFinishStatus(bool withEndMark) const + { + return _lzmaStatus == (withEndMark ? + LZMA_STATUS_FINISHED_WITH_MARK : + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK); + } }; }} diff --git a/CPP/7zip/Compress/LzmaEncoder.cpp b/CPP/7zip/Compress/LzmaEncoder.cpp index 0a7e294d..38966f6f 100644 --- a/CPP/7zip/Compress/LzmaEncoder.cpp +++ b/CPP/7zip/Compress/LzmaEncoder.cpp @@ -134,11 +134,16 @@ STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) { - CSeqInStreamWrap inWrap(inStream); - CSeqOutStreamWrap outWrap(outStream); - CCompressProgressWrap progressWrap(progress); + CSeqInStreamWrap inWrap; + CSeqOutStreamWrap outWrap; + CCompressProgressWrap progressWrap; + + inWrap.Init(inStream); + outWrap.Init(outStream); + progressWrap.Init(progress); + + SRes res = LzmaEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt, progress ? &progressWrap.vt : NULL, &g_Alloc, &g_BigAlloc); - SRes res = LzmaEnc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL, &g_Alloc, &g_BigAlloc); _inputProcessed = inWrap.Processed; if (res == SZ_ERROR_READ && inWrap.Res != S_OK) return inWrap.Res; diff --git a/CPP/7zip/Compress/LzmaEncoder.h b/CPP/7zip/Compress/LzmaEncoder.h index f919ac2c..3d472d67 100644 --- a/CPP/7zip/Compress/LzmaEncoder.h +++ b/CPP/7zip/Compress/LzmaEncoder.h @@ -30,7 +30,9 @@ public: CEncoder(); virtual ~CEncoder(); + UInt64 GetInputProcessedSize() const { return _inputProcessed; } + bool IsWriteEndMark() const { return LzmaEnc_IsWriteEndMark(_encoder) != 0; } }; }} diff --git a/CPP/7zip/Compress/LzmsDecoder.cpp b/CPP/7zip/Compress/LzmsDecoder.cpp index 0e823446..02a7f5dc 100644 --- a/CPP/7zip/Compress/LzmsDecoder.cpp +++ b/CPP/7zip/Compress/LzmsDecoder.cpp @@ -114,8 +114,8 @@ static void x86_Filter(Byte *data, UInt32 size, Int32 *history) size -= 16; const unsigned kSave = 6; - const Byte savedByte = data[size + kSave]; - data[size + kSave] = 0xE8; + const Byte savedByte = data[(size_t)size + kSave]; + data[(size_t)size + kSave] = 0xE8; Int32 last_x86_pos = -k_x86_TransOffset - 1; // first byte is ignored @@ -215,7 +215,7 @@ static void x86_Filter(Byte *data, UInt32 size, Int32 *history) *target = i; } - data[size + kSave] = savedByte; + data[(size_t)size + kSave] = savedByte; } diff --git a/CPP/7zip/Compress/LzxDecoder.cpp b/CPP/7zip/Compress/LzxDecoder.cpp index 55231ce5..a7bba903 100644 --- a/CPP/7zip/Compress/LzxDecoder.cpp +++ b/CPP/7zip/Compress/LzxDecoder.cpp @@ -27,8 +27,8 @@ static void x86_Filter(Byte *data, UInt32 size, UInt32 processedSize, UInt32 tra return; size -= kResidue; - Byte save = data[size + 4]; - data[size + 4] = 0xE8; + Byte save = data[(size_t)size + 4]; + data[(size_t)size + 4] = 0xE8; for (UInt32 i = 0;;) { @@ -57,7 +57,7 @@ static void x86_Filter(Byte *data, UInt32 size, UInt32 processedSize, UInt32 tra } } - data[size + 4] = save; + data[(size_t)size + 4] = save; } diff --git a/CPP/7zip/Compress/Mtf8.h b/CPP/7zip/Compress/Mtf8.h index 5d49fe44..50a84cee 100644 --- a/CPP/7zip/Compress/Mtf8.h +++ b/CPP/7zip/Compress/Mtf8.h @@ -11,11 +11,11 @@ struct CMtf8Encoder { Byte Buf[256]; - unsigned FindAndMove(Byte v) + unsigned FindAndMove(Byte v) throw() { - unsigned pos; + size_t pos; for (pos = 0; Buf[pos] != v; pos++); - unsigned resPos = pos; + unsigned resPos = (unsigned)pos; for (; pos >= 8; pos -= 8) { Buf[pos] = Buf[pos - 1]; @@ -39,9 +39,10 @@ struct CMtf8Decoder { Byte Buf[256]; - void Init(int) {}; + void StartInit() { memset(Buf, 0, sizeof(Buf)); } + void Add(unsigned pos, Byte val) { Buf[pos] = val; } Byte GetHead() const { return Buf[0]; } - Byte GetAndMove(int pos) + Byte GetAndMove(unsigned pos) { Byte res = Buf[pos]; for (; pos >= 8; pos -= 8) @@ -64,11 +65,11 @@ struct CMtf8Decoder */ #ifdef MY_CPU_64BIT -typedef UInt64 CMtfVar; -#define MTF_MOVS 3 + typedef UInt64 CMtfVar; + #define MTF_MOVS 3 #else -typedef UInt32 CMtfVar; -#define MTF_MOVS 2 + typedef UInt32 CMtfVar; + #define MTF_MOVS 2 #endif #define MTF_MASK ((1 << MTF_MOVS) - 1) @@ -81,13 +82,18 @@ struct CMtf8Decoder void StartInit() { memset(Buf, 0, sizeof(Buf)); } void Add(unsigned pos, Byte val) { Buf[pos >> MTF_MOVS] |= ((CMtfVar)val << ((pos & MTF_MASK) << 3)); } Byte GetHead() const { return (Byte)Buf[0]; } - Byte GetAndMove(unsigned pos) + + MY_FORCE_INLINE + Byte GetAndMove(unsigned pos) throw() { UInt32 lim = ((UInt32)pos >> MTF_MOVS); pos = (pos & MTF_MASK) << 3; CMtfVar prev = (Buf[lim] >> pos) & 0xFF; UInt32 i = 0; + + + /* if ((lim & 1) != 0) { CMtfVar next = Buf[0]; @@ -104,6 +110,16 @@ struct CMtf8Decoder Buf[i + 1] = (n1 << 8) | (n0 >> (MTF_MASK << 3)); prev = (n1 >> (MTF_MASK << 3)); } + */ + + for (; i < lim; i++) + { + CMtfVar n0 = Buf[i]; + Buf[i ] = (n0 << 8) | prev; + prev = (n0 >> (MTF_MASK << 3)); + } + + CMtfVar next = Buf[i]; CMtfVar mask = (((CMtfVar)0x100 << pos) - 1); Buf[i] = (next & ~mask) | (((next << 8) | prev) & mask); @@ -117,7 +133,7 @@ class CMtf8Decoder { Byte SmallBuffer[kSmallSize]; int SmallSize; - Byte Counts[16]; + int Counts[16]; int Size; public: Byte Buf[256]; @@ -140,6 +156,11 @@ public: } } + void Add(unsigned pos, Byte val) + { + Buf[pos] = val; + } + Byte GetAndMove(int pos) { if (pos < SmallSize) diff --git a/CPP/7zip/Compress/PpmdDecoder.cpp b/CPP/7zip/Compress/PpmdDecoder.cpp index c868730e..ed0e9e29 100644 --- a/CPP/7zip/Compress/PpmdDecoder.cpp +++ b/CPP/7zip/Compress/PpmdDecoder.cpp @@ -75,7 +75,7 @@ HRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size) int sym = 0; for (i = 0; i != size; i++) { - sym = Ppmd7_DecodeSymbol(&_ppmd, &_rangeDec.p); + sym = Ppmd7_DecodeSymbol(&_ppmd, &_rangeDec.vt); if (_inStream.Extra || sym < 0) break; memStream[i] = (Byte)sym; @@ -134,6 +134,13 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) return S_OK; } + +STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) +{ + *value = _inStream.GetProcessed(); + return S_OK; +} + #ifndef NO_READ_FROM_CODER STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) diff --git a/CPP/7zip/Compress/PpmdDecoder.h b/CPP/7zip/Compress/PpmdDecoder.h index 8ebcd700..2b6213c0 100644 --- a/CPP/7zip/Compress/PpmdDecoder.h +++ b/CPP/7zip/Compress/PpmdDecoder.h @@ -18,6 +18,7 @@ namespace NPpmd { class CDecoder : public ICompressCoder, public ICompressSetDecoderProperties2, + public ICompressGetInStreamProcessedSize, #ifndef NO_READ_FROM_CODER public ICompressSetInStream, public ICompressSetOutStreamSize, @@ -42,19 +43,26 @@ public: #ifndef NO_READ_FROM_CODER CMyComPtr<ISequentialInStream> InSeqStream; - MY_UNKNOWN_IMP4( - ICompressSetDecoderProperties2, - ICompressSetInStream, - ICompressSetOutStreamSize, - ISequentialInStream) - #else - MY_UNKNOWN_IMP1( - ICompressSetDecoderProperties2) #endif + MY_QUERYINTERFACE_BEGIN2(ICompressCoder) + MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2) + // MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode) + MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize) + #ifndef NO_READ_FROM_CODER + 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(SetDecoderProperties2)(const Byte *data, UInt32 size); + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); #ifndef NO_READ_FROM_CODER @@ -66,7 +74,7 @@ public: CDecoder(): _outBuf(NULL), _outSizeDefined(false) { Ppmd7z_RangeDec_CreateVTable(&_rangeDec); - _rangeDec.Stream = &_inStream.p; + _rangeDec.Stream = &_inStream.vt; Ppmd7_Construct(&_ppmd); } diff --git a/CPP/7zip/Compress/PpmdEncoder.cpp b/CPP/7zip/Compress/PpmdEncoder.cpp index 00ea9668..34e6d361 100644 --- a/CPP/7zip/Compress/PpmdEncoder.cpp +++ b/CPP/7zip/Compress/PpmdEncoder.cpp @@ -43,7 +43,7 @@ CEncoder::CEncoder(): _inBuf(NULL) { _props.Normalize(-1); - _rangeEnc.Stream = &_outStream.p; + _rangeEnc.Stream = &_outStream.vt; Ppmd7_Construct(&_ppmd); } diff --git a/CPP/7zip/Compress/PpmdZip.cpp b/CPP/7zip/Compress/PpmdZip.cpp index 24dd32f2..d9ce218a 100644 --- a/CPP/7zip/Compress/PpmdZip.cpp +++ b/CPP/7zip/Compress/PpmdZip.cpp @@ -15,7 +15,7 @@ namespace NPpmdZip { CDecoder::CDecoder(bool fullFileMode): _fullFileMode(fullFileMode) { - _ppmd.Stream.In = &_inStream.p; + _ppmd.Stream.In = &_inStream.vt; Ppmd8_Construct(&_ppmd); } @@ -25,7 +25,7 @@ CDecoder::~CDecoder() } STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { if (!_outStream.Alloc()) return E_OUTOFMEMORY; @@ -64,15 +64,21 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream bool wasFinished = false; UInt64 processedSize = 0; - while (!outSize || processedSize < *outSize) + + for (;;) { size_t size = kBufSize; - if (outSize != NULL) + if (outSize) { const UInt64 rem = *outSize - processedSize; if (size > rem) + { size = (size_t)rem; + if (size == 0) + break; + } } + Byte *data = _outStream.Buf; size_t i = 0; int sym = 0; @@ -84,6 +90,7 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream data[i] = (Byte)sym; } while (++i != size); + processedSize += i; RINOK(WriteStream(outStream, _outStream.Buf, i)); @@ -99,13 +106,16 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream wasFinished = true; break; } + if (progress) { - UInt64 inSize = _inStream.GetProcessed(); - RINOK(progress->SetRatioInfo(&inSize, &processedSize)); + const UInt64 inProccessed = _inStream.GetProcessed(); + RINOK(progress->SetRatioInfo(&inProccessed, &processedSize)); } } + RINOK(_inStream.Res); + if (_fullFileMode) { if (!wasFinished) @@ -117,11 +127,29 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream } if (!Ppmd8_RangeDec_IsFinishedOK(&_ppmd)) return S_FALSE; + + if (inSize && *inSize != _inStream.GetProcessed()) + return S_FALSE; } + + return S_OK; +} + + +STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode) +{ + _fullFileMode = (finishMode != 0); + return S_OK; +} + +STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) +{ + *value = _inStream.GetProcessed(); return S_OK; } + // ---------- Encoder ---------- void CEncProps::Normalize(int level) @@ -206,7 +234,7 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIA CEncoder::CEncoder() { _props.Normalize(-1); - _ppmd.Stream.Out = &_outStream.p; + _ppmd.Stream.Out = &_outStream.vt; Ppmd8_Construct(&_ppmd); } @@ -248,10 +276,10 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream RINOK(_outStream.Res); } processed += size; - if (progress != NULL) + if (progress) { - UInt64 outSize = _outStream.GetProcessed(); - RINOK(progress->SetRatioInfo(&processed, &outSize)); + const UInt64 outProccessed = _outStream.GetProcessed(); + RINOK(progress->SetRatioInfo(&processed, &outProccessed)); } } } diff --git a/CPP/7zip/Compress/PpmdZip.h b/CPP/7zip/Compress/PpmdZip.h index e15a060d..b8c7aae0 100644 --- a/CPP/7zip/Compress/PpmdZip.h +++ b/CPP/7zip/Compress/PpmdZip.h @@ -31,8 +31,11 @@ struct CBuf } }; + class CDecoder : public ICompressCoder, + public ICompressSetFinishMode, + public ICompressGetInStreamProcessedSize, public CMyUnknownImp { CByteInBufWrap _inStream; @@ -40,13 +43,20 @@ class CDecoder : CPpmd8 _ppmd; bool _fullFileMode; public: - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP2( + ICompressSetFinishMode, + ICompressGetInStreamProcessedSize) + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetFinishMode)(UInt32 finishMode); + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); + CDecoder(bool fullFileMode); ~CDecoder(); }; + struct CEncProps { UInt32 MemSizeMB; diff --git a/CPP/7zip/Compress/QuantumDecoder.cpp b/CPP/7zip/Compress/QuantumDecoder.cpp index 2adb9053..64e35bf2 100644 --- a/CPP/7zip/Compress/QuantumDecoder.cpp +++ b/CPP/7zip/Compress/QuantumDecoder.cpp @@ -37,7 +37,7 @@ unsigned CModelDecoder::Decode(CRangeDecoder *rc) unsigned i; for (i = 1; Freqs[i] > threshold; i++); - rc->Decode(Freqs[i], Freqs[i - 1], Freqs[0]); + rc->Decode(Freqs[i], Freqs[(size_t)i - 1], Freqs[0]); unsigned res = Vals[--i]; do @@ -50,7 +50,7 @@ unsigned CModelDecoder::Decode(CRangeDecoder *rc) { ReorderCount = kReorderCount; for (i = 0; i < NumItems; i++) - Freqs[i] = (UInt16)(((Freqs[i] - Freqs[i + 1]) + 1) >> 1); + Freqs[i] = (UInt16)(((Freqs[i] - Freqs[(size_t)i + 1]) + 1) >> 1); for (i = 0; i < NumItems - 1; i++) for (unsigned j = i + 1; j < NumItems; j++) if (Freqs[i] < Freqs[j]) @@ -64,7 +64,7 @@ unsigned CModelDecoder::Decode(CRangeDecoder *rc) } do - Freqs[i] = (UInt16)(Freqs[i] + Freqs[i + 1]); + Freqs[i] = (UInt16)(Freqs[i] + Freqs[(size_t)i + 1]); while (i--); } else @@ -73,8 +73,8 @@ unsigned CModelDecoder::Decode(CRangeDecoder *rc) do { Freqs[i] >>= 1; - if (Freqs[i] <= Freqs[i + 1]) - Freqs[i] = (UInt16)(Freqs[i + 1] + 1); + if (Freqs[i] <= Freqs[(size_t)i + 1]) + Freqs[i] = (UInt16)(Freqs[(size_t)i + 1] + 1); } while (i--); } diff --git a/CPP/7zip/Compress/Rar1Decoder.cpp b/CPP/7zip/Compress/Rar1Decoder.cpp index 1aaedcc1..0a552506 100644 --- a/CPP/7zip/Compress/Rar1Decoder.cpp +++ b/CPP/7zip/Compress/Rar1Decoder.cpp @@ -57,7 +57,7 @@ UInt32 CDecoder::DecodeNum(const UInt32 *posTab) UInt32 num = m_InBitStream.GetValue(12); for (;;) { - UInt32 cur = (posTab[startPos + 1] - posTab[startPos]) << (12 - startPos); + UInt32 cur = (posTab[(size_t)startPos + 1] - posTab[startPos]) << (12 - startPos); if (num < cur) break; startPos++; @@ -149,7 +149,7 @@ HRESULT CDecoder::ShortLZ() PlaceA[dist]--; UInt32 lastDistance = ChSetA[(unsigned)distancePlace]; PlaceA[lastDistance]++; - ChSetA[(unsigned)distancePlace + 1] = lastDistance; + ChSetA[(size_t)(unsigned)distancePlace + 1] = lastDistance; ChSetA[(unsigned)distancePlace] = dist; } len += 2; diff --git a/CPP/7zip/Compress/Rar2Decoder.cpp b/CPP/7zip/Compress/Rar2Decoder.cpp index db67433a..e906deef 100644 --- a/CPP/7zip/Compress/Rar2Decoder.cpp +++ b/CPP/7zip/Compress/Rar2Decoder.cpp @@ -104,7 +104,8 @@ bool CDecoder::ReadTables(void) m_TablesOK = false; Byte levelLevels[kLevelTableSize]; - Byte newLevels[kMaxTableSize]; + Byte lens[kMaxTableSize]; + m_AudioMode = (ReadBits(1) == 1); if (ReadBits(1) == 0) @@ -134,16 +135,29 @@ bool CDecoder::ReadTables(void) UInt32 sym = m_LevelDecoder.Decode(&m_InBitStream); if (sym < kTableDirectLevels) { - newLevels[i] = (Byte)((sym + m_LastLevels[i]) & kLevelMask); + lens[i] = (Byte)((sym + m_LastLevels[i]) & kLevelMask); i++; } else { if (sym == kTableLevelRepNumber) { - unsigned t = ReadBits(2) + 3; - for (unsigned reps = t; reps > 0 && i < numLevels; reps--, i++) - newLevels[i] = newLevels[i - 1]; + unsigned num = ReadBits(2) + 3; + if (i == 0) + { + // return false; + continue; // original unRAR + } + num += i; + if (num > numLevels) + { + // return false; + num = numLevels; // original unRAR + } + Byte v = lens[(size_t)i - 1]; + do + lens[i++] = v; + while (i < num); } else { @@ -154,8 +168,15 @@ bool CDecoder::ReadTables(void) num = ReadBits(7) + 11; else return false; - for (; num > 0 && i < numLevels; num--) - newLevels[i++] = 0; + num += i; + if (num > numLevels) + { + // return false; + num = numLevels; // original unRAR + } + do + lens[i++] = 0; + while (i < num); } } } @@ -163,16 +184,16 @@ bool CDecoder::ReadTables(void) if (m_AudioMode) for (i = 0; i < m_NumChannels; i++) { - RIF(m_MMDecoders[i].Build(&newLevels[i * kMMTableSize])); + RIF(m_MMDecoders[i].Build(&lens[i * kMMTableSize])); } else { - RIF(m_MainDecoder.Build(&newLevels[0])); - RIF(m_DistDecoder.Build(&newLevels[kMainTableSize])); - RIF(m_LenDecoder.Build(&newLevels[kMainTableSize + kDistTableSize])); + RIF(m_MainDecoder.Build(&lens[0])); + RIF(m_DistDecoder.Build(&lens[kMainTableSize])); + RIF(m_LenDecoder.Build(&lens[kMainTableSize + kDistTableSize])); } - memcpy(m_LastLevels, newLevels, kMaxTableSize); + memcpy(m_LastLevels, lens, kMaxTableSize); m_TablesOK = true; @@ -220,13 +241,11 @@ public: bool CDecoder::DecodeMm(UInt32 pos) { - while (pos-- > 0) + while (pos-- != 0) { UInt32 symbol = m_MMDecoders[m_MmFilter.CurrentChannel].Decode(&m_InBitStream); - if (symbol == 256) - return true; - if (symbol >= kMMTableSize) - return false; + if (symbol >= 256) + return symbol == 256; /* Byte byPredict = m_Predictor.Predict(); Byte byReal = (Byte)(byPredict - (Byte)symbol); @@ -254,6 +273,8 @@ bool CDecoder::DecodeLz(Int32 pos) } else if (sym >= kMatchNumber) { + if (sym >= kMainTableSize) + return false; sym -= kMatchNumber; length = kNormalMatchMinLen + UInt32(kLenStart[sym]) + m_InBitStream.ReadBits(kLenDirectBits[sym]); @@ -302,10 +323,9 @@ bool CDecoder::DecodeLz(Int32 pos) m_InBitStream.ReadBits(kLen2DistDirectBits[sym]); length = 2; } - else if (sym == kReadTableNumber) + else // (sym == kReadTableNumber) return true; - else - return false; + m_RepDists[m_RepDistPtr++ & 3] = distance; m_LastLength = length; if (!m_OutWindowStream.CopyBlock(distance, length)) diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp index 3bf25132..a4f23524 100644 --- a/CPP/7zip/Compress/Rar3Decoder.cpp +++ b/CPP/7zip/Compress/Rar3Decoder.cpp @@ -44,15 +44,17 @@ static const UInt32 kVmCodeSizeMax = 1 << 16; extern "C" { -static UInt32 Range_GetThreshold(void *pp, UInt32 total) +#define GET_RangeDecoder CRangeDecoder *p = CONTAINER_FROM_VTBL_CLS(pp, CRangeDecoder, vt); + +static UInt32 Range_GetThreshold(const IPpmd7_RangeDec *pp, UInt32 total) { - CRangeDecoder *p = (CRangeDecoder *)pp; + GET_RangeDecoder; return p->Code / (p->Range /= total); } -static void Range_Decode(void *pp, UInt32 start, UInt32 size) +static void Range_Decode(const IPpmd7_RangeDec *pp, UInt32 start, UInt32 size) { - CRangeDecoder *p = (CRangeDecoder *)pp; + GET_RangeDecoder; start *= p->Range; p->Low += start; p->Code -= start; @@ -60,28 +62,28 @@ static void Range_Decode(void *pp, UInt32 start, UInt32 size) p->Normalize(); } -static UInt32 Range_DecodeBit(void *pp, UInt32 size0) +static UInt32 Range_DecodeBit(const IPpmd7_RangeDec *pp, UInt32 size0) { - CRangeDecoder *p = (CRangeDecoder *)pp; + GET_RangeDecoder; if (p->Code / (p->Range >>= 14) < size0) { - Range_Decode(p, 0, size0); + Range_Decode(&p->vt, 0, size0); return 0; } else { - Range_Decode(p, size0, (1 << 14) - size0); + Range_Decode(&p->vt, size0, (1 << 14) - size0); return 1; } } } -CRangeDecoder::CRangeDecoder() +CRangeDecoder::CRangeDecoder() throw() { - s.GetThreshold = Range_GetThreshold; - s.Decode = Range_Decode; - s.DecodeBit = Range_DecodeBit; + vt.GetThreshold = Range_GetThreshold; + vt.Decode = Range_Decode; + vt.DecodeBit = Range_DecodeBit; } CDecoder::CDecoder(): @@ -445,7 +447,7 @@ HRESULT CDecoder::InitPPM() return S_OK; } -int CDecoder::DecodePpmSymbol() { return Ppmd7_DecodeSymbol(&_ppmd, &m_InBitStream.s); } +int CDecoder::DecodePpmSymbol() { return Ppmd7_DecodeSymbol(&_ppmd, &m_InBitStream.vt); } HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing) { @@ -545,6 +547,9 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing) return InitPPM(); } + TablesRead = false; + TablesOK = false; + _lzMode = true; PrevAlignBits = 0; PrevAlignCount = 0; @@ -597,7 +602,7 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing) if (i == 0) return S_FALSE; for (; num > 0 && i < kTablesSizesSum; num--, i++) - newLevels[i] = newLevels[i - 1]; + newLevels[i] = newLevels[(size_t)i - 1]; } else { @@ -606,6 +611,7 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing) } } } + TablesRead = true; // original code has check here: @@ -623,6 +629,9 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing) RIF(m_LenDecoder.Build(&newLevels[kMainTableSize + kDistTableSize + kAlignTableSize])); memcpy(m_LastLevels, newLevels, kTablesSizesSum); + + TablesOK = true; + return S_OK; } @@ -641,16 +650,15 @@ public: HRESULT CDecoder::ReadEndOfBlock(bool &keepDecompressing) { - if (ReadBits(1) != 0) + if (ReadBits(1) == 0) { - // old file - TablesRead = false; - return ReadTables(keepDecompressing); + // new file + keepDecompressing = false; + TablesRead = (ReadBits(1) == 0); + return S_OK; } - // new file - keepDecompressing = false; - TablesRead = (ReadBits(1) == 0); - return S_OK; + TablesRead = false; + return ReadTables(keepDecompressing); } UInt32 kDistStart[kDistTableSize]; @@ -807,10 +815,12 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing) return S_OK; } + HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) { _writtenFileSize = 0; _unsupportedFilter = false; + if (!m_IsSolid) { _lzSize = 0; @@ -825,6 +835,7 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) PpmError = true; InitFilters(); } + if (!m_IsSolid || !TablesRead) { bool keepDecompressing; @@ -838,6 +849,8 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress) bool keepDecompressing; if (_lzMode) { + if (!TablesOK) + return S_FALSE; RINOK(DecodeLZ(keepDecompressing)) } else diff --git a/CPP/7zip/Compress/Rar3Decoder.h b/CPP/7zip/Compress/Rar3Decoder.h index c130cec6..f2a9e345 100644 --- a/CPP/7zip/Compress/Rar3Decoder.h +++ b/CPP/7zip/Compress/Rar3Decoder.h @@ -102,7 +102,7 @@ const UInt32 kBot = (1 << 15); struct CRangeDecoder { - IPpmd7_RangeDec s; + IPpmd7_RangeDec vt; UInt32 Range; UInt32 Code; UInt32 Low; @@ -130,7 +130,7 @@ public: } } - CRangeDecoder(); + CRangeDecoder() throw(); }; struct CFilter: public NVm::CProgram @@ -200,6 +200,7 @@ class CDecoder: UInt32 PrevAlignCount; bool TablesRead; + bool TablesOK; CPpmd7 _ppmd; int PpmEscChar; diff --git a/CPP/7zip/Compress/Rar3Vm.cpp b/CPP/7zip/Compress/Rar3Vm.cpp index 5dca9eab..84e44a8e 100644 --- a/CPP/7zip/Compress/Rar3Vm.cpp +++ b/CPP/7zip/Compress/Rar3Vm.cpp @@ -891,53 +891,47 @@ static void E8E9Decode(Byte *data, UInt32 dataSize, UInt32 fileOffset, bool e9) } } -static inline UInt32 ItaniumGetOpType(const Byte *data, unsigned bitPos) -{ - return (data[bitPos >> 3] >> (bitPos & 7)) & 0xF; -} - -static const Byte kCmdMasks[16] = {4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0}; static void ItaniumDecode(Byte *data, UInt32 dataSize, UInt32 fileOffset) { - UInt32 curPos = 0; + if (dataSize <= 21) + return; fileOffset >>= 4; - while (curPos < dataSize - 21) + dataSize -= 21; + dataSize += 15; + dataSize >>= 4; + dataSize += fileOffset; + do { - int b = (data[0] & 0x1F) - 0x10; - if (b >= 0) + unsigned m = ((UInt32)0x334B0000 >> (data[0] & 0x1E)) & 3; + if (m) { - Byte cmdMask = kCmdMasks[b]; - if (cmdMask != 0) - for (unsigned i = 0; i < 3; i++) - if (cmdMask & (1 << i)) - { - unsigned startPos = i * 41 + 18; - if (ItaniumGetOpType(data, startPos + 24) == 5) - { - const UInt32 kMask = 0xFFFFF; - Byte *p = data + (startPos >> 3); - UInt32 bitField = ((UInt32)p[0]) | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16); - unsigned inBit = (startPos & 7); - UInt32 offset = (bitField >> inBit) & kMask; - UInt32 andMask = ~(kMask << inBit); - bitField = ((offset - fileOffset) & kMask) << inBit; - for (unsigned j = 0; j < 3; j++) - { - p[j] &= andMask; - p[j] |= bitField; - andMask >>= 8; - bitField >>= 8; - } - } - } + m++; + do + { + Byte *p = data + ((size_t)m * 5 - 8); + if (((p[3] >> m) & 15) == 5) + { + const UInt32 kMask = 0xFFFFF; + // UInt32 raw = ((UInt32)p[0]) | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16); + UInt32 raw = GetUi32(p); + UInt32 v = raw >> m; + v -= fileOffset; + v &= kMask; + raw &= ~(kMask << m); + raw |= (v << m); + // p[0] = (Byte)raw; p[1] = (Byte)(raw >> 8); p[2] = (Byte)(raw >> 16); + SetUi32(p, raw); + } + } + while (++m <= 4); } data += 16; - curPos += 16; - fileOffset++; } + while (++fileOffset != dataSize); } + static void DeltaDecode(Byte *data, UInt32 dataSize, UInt32 numChannels) { UInt32 srcPos = 0; diff --git a/CPP/7zip/Compress/Rar5Decoder.cpp b/CPP/7zip/Compress/Rar5Decoder.cpp index fdd65a11..6b6e80d1 100644 --- a/CPP/7zip/Compress/Rar5Decoder.cpp +++ b/CPP/7zip/Compress/Rar5Decoder.cpp @@ -448,7 +448,7 @@ HRESULT CDecoder::ReadTables(CBitDecoder &_bitStream) // return S_FALSE; continue; // original unRAR } - Byte v = lens[i - 1]; + Byte v = lens[(size_t)i - 1]; do lens[i++] = v; while (i < num); @@ -475,7 +475,7 @@ HRESULT CDecoder::ReadTables(CBitDecoder &_bitStream) _useAlignBits = false; // _useAlignBits = true; for (i = 0; i < kAlignTableSize; i++) - if (lens[kMainTableSize + kDistTableSize + i] != kNumAlignBits) + if (lens[kMainTableSize + kDistTableSize + (size_t)i] != kNumAlignBits) { _useAlignBits = true; break; diff --git a/CPP/7zip/Compress/Rar5Decoder.h b/CPP/7zip/Compress/Rar5Decoder.h index b0a4dd12..c37cb0e0 100644 --- a/CPP/7zip/Compress/Rar5Decoder.h +++ b/CPP/7zip/Compress/Rar5Decoder.h @@ -5,10 +5,9 @@ #ifndef __COMPRESS_RAR5_DECODER_H #define __COMPRESS_RAR5_DECODER_H -#include "../../../C/Alloc.h" #include "../../../C/CpuArch.h" -#include "../../Common/MyBuffer.h" +#include "../../Common/MyBuffer2.h" #include "../../Common/MyCom.h" #include "../../Common/MyException.h" #include "../../Common/MyVector.h" @@ -20,35 +19,6 @@ namespace NCompress { namespace NRar5 { -class CMidBuffer -{ - Byte *_data; - size_t _size; - - CLASS_NO_COPY(CMidBuffer) - -public: - CMidBuffer(): _data(NULL), _size(0) {}; - ~CMidBuffer() { ::MidFree(_data); } - - bool IsAllocated() const { return _data != NULL; } - operator Byte *() { return _data; } - operator const Byte *() const { return _data; } - size_t Size() const { return _size; } - - void AllocAtLeast(size_t size) - { - if (size > _size) - { - const size_t kMinSize = (1 << 16); - if (size < kMinSize) - size = kMinSize; - ::MidFree(_data); - _data = (Byte *)::MidAlloc(size); - _size = size; - } - } -}; /* struct CInBufferException: public CSystemException diff --git a/CPP/7zip/Compress/ShrinkDecoder.cpp b/CPP/7zip/Compress/ShrinkDecoder.cpp index 80b7e67c..bd7c2461 100644 --- a/CPP/7zip/Compress/ShrinkDecoder.cpp +++ b/CPP/7zip/Compress/ShrinkDecoder.cpp @@ -1,10 +1,7 @@ // ShrinkDecoder.cpp - #include "StdAfx.h" -#include <stdio.h> - #include "../../../C/Alloc.h" #include "../Common/InBuffer.h" @@ -20,18 +17,19 @@ static const UInt32 kBufferSize = (1 << 18); static const unsigned kNumMinBits = 9; HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { NBitl::CBaseDecoder<CInBuffer> inBuffer; COutBuffer outBuffer; if (!inBuffer.Create(kBufferSize)) return E_OUTOFMEMORY; + if (!outBuffer.Create(kBufferSize)) + return E_OUTOFMEMORY; + inBuffer.SetStream(inStream); inBuffer.Init(); - if (!outBuffer.Create(kBufferSize)) - return E_OUTOFMEMORY; outBuffer.SetStream(outStream); outBuffer.Init(); @@ -45,31 +43,69 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * _suffixes[i] = 0; } - UInt64 prevPos = 0; + UInt64 prevPos = 0, inPrev = 0; unsigned numBits = kNumMinBits; unsigned head = 257; int lastSym = -1; Byte lastChar2 = 0; + bool moreOut = false; + + HRESULT res = S_FALSE; for (;;) { + _inProcessed = inBuffer.GetProcessedSize(); + const UInt64 nowPos = outBuffer.GetProcessedSize(); + + bool eofCheck = false; + + if (outSize && nowPos >= *outSize) + { + if (!_fullStreamMode || moreOut) + { + res = S_OK; + break; + } + eofCheck = true; + // Is specSym(=256) allowed after end of stream + // Do we need to read it here + } + + if (progress) + { + if (nowPos - prevPos >= (1 << 18) + || _inProcessed - inPrev >= (1 << 20)) + { + prevPos = nowPos; + inPrev = _inProcessed; + RINOK(progress->SetRatioInfo(&_inProcessed, &nowPos)); + } + } + UInt32 sym = inBuffer.ReadBits(numBits); - + if (inBuffer.ExtraBitsWereRead()) + { + res = S_OK; break; + } if (sym == 256) { sym = inBuffer.ReadBits(numBits); + + if (inBuffer.ExtraBitsWereRead()) + break; + if (sym == 1) { if (numBits >= kNumMaxBits) - return S_FALSE; + break; numBits++; continue; } if (sym != 2) - return S_FALSE; + break; { unsigned i; for (i = 257; i < kNumItems; i++) @@ -90,6 +126,14 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * } } + if (eofCheck) + { + // It's can be error case. + // That error can be detected later in (*inSize != _inProcessed) check. + res = S_OK; + break; + } + bool needPrev = false; if (head < kNumItems && lastSym >= 0) { @@ -101,7 +145,8 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * { // we need to fix the code for that case // _parents[head] is not allowed to link to itself - return E_NOTIMPL; + res = E_NOTIMPL; + break; } needPrev = true; _parents[head] = (UInt16)lastSym; @@ -111,7 +156,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * } if (_parents[sym] == kNumItems) - return S_FALSE; + break; lastSym = sym; unsigned cur = sym; @@ -127,34 +172,64 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * lastChar2 = (Byte)cur; if (needPrev) - _suffixes[head - 1] = (Byte)cur; + _suffixes[(size_t)head - 1] = (Byte)cur; + + if (outSize) + { + const UInt64 limit = *outSize - nowPos; + if (i > limit) + { + moreOut = true; + i = (unsigned)limit; + } + } do outBuffer.WriteByte(_stack[--i]); while (i); - - if (progress) + } + + RINOK(outBuffer.Flush()); + + if (res == S_OK) + if (_fullStreamMode) { + if (moreOut) + res = S_FALSE; const UInt64 nowPos = outBuffer.GetProcessedSize(); - if (nowPos - prevPos >= (1 << 18)) - { - prevPos = nowPos; - const UInt64 packSize = inBuffer.GetProcessedSize(); - RINOK(progress->SetRatioInfo(&packSize, &nowPos)); - } + if (outSize && *outSize != nowPos) + res = S_FALSE; + if (inSize && *inSize != _inProcessed) + res = S_FALSE; } - } - return outBuffer.Flush(); + return res; } -STDMETHODIMP CDecoder ::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + +STDMETHODIMP CDecoder::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 COutBufferException &e) { return e.ErrorCode; } + // catch(const CInBufferException &e) { return e.ErrorCode; } + // catch(const COutBufferException &e) { return e.ErrorCode; } + catch(const CSystemException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } + +STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode) +{ + _fullStreamMode = (finishMode != 0); + return S_OK; +} + + +STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) +{ + *value = _inProcessed; + return S_OK; +} + + }} diff --git a/CPP/7zip/Compress/ShrinkDecoder.h b/CPP/7zip/Compress/ShrinkDecoder.h index 42e5eee7..2f01596a 100644 --- a/CPP/7zip/Compress/ShrinkDecoder.h +++ b/CPP/7zip/Compress/ShrinkDecoder.h @@ -15,20 +15,29 @@ const unsigned kNumItems = 1 << kNumMaxBits; class CDecoder : public ICompressCoder, + public ICompressSetFinishMode, + public ICompressGetInStreamProcessedSize, public CMyUnknownImp { + UInt64 _inProcessed; + bool _fullStreamMode; + UInt16 _parents[kNumItems]; Byte _suffixes[kNumItems]; Byte _stack[kNumItems]; -public: - MY_UNKNOWN_IMP - HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); - + +public: + MY_UNKNOWN_IMP2( + ICompressSetFinishMode, + ICompressGetInStreamProcessedSize) + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetFinishMode)(UInt32 finishMode); + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); }; }} diff --git a/CPP/7zip/Compress/XpressDecoder.cpp b/CPP/7zip/Compress/XpressDecoder.cpp index a4d45335..a38d9418 100644 --- a/CPP/7zip/Compress/XpressDecoder.cpp +++ b/CPP/7zip/Compress/XpressDecoder.cpp @@ -49,8 +49,8 @@ HRESULT Decode(const Byte *in, size_t inSize, Byte *out, size_t outSize) for (unsigned i = 0; i < kNumSyms / 2; i++) { Byte b = in[i]; - levels[i * 2] = (Byte)(b & 0xF); - levels[i * 2 + 1] = (Byte)(b >> 4); + levels[(size_t)i * 2] = (Byte)(b & 0xF); + levels[(size_t)i * 2 + 1] = (Byte)(b >> 4); } if (!huff.BuildFull(levels)) return S_FALSE; diff --git a/CPP/7zip/Compress/XzDecoder.cpp b/CPP/7zip/Compress/XzDecoder.cpp new file mode 100644 index 00000000..e7ee6046 --- /dev/null +++ b/CPP/7zip/Compress/XzDecoder.cpp @@ -0,0 +1,260 @@ +// XzDecoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../Common/StreamUtils.h" + +#include "../Archive/IArchive.h" + +#include "XzDecoder.h" + +using namespace NArchive; + +namespace NCompress { +namespace NXz { + + +void CStatInfo::Clear() +{ + InSize = 0; + OutSize = 0; + PhySize = 0; + + 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; +} + + +CXzUnpackerCPP::CXzUnpackerCPP(): InBuf(0), OutBuf(0) +{ + XzUnpacker_Construct(&p, &g_Alloc); +} + +CXzUnpackerCPP::~CXzUnpackerCPP() +{ + XzUnpacker_Free(&p); + MidFree(InBuf); + MidFree(OutBuf); +} + + + +HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, + const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *progress) +{ + const size_t kInBufSize = (size_t)1 << 20; + const size_t kOutBufSize = (size_t)1 << 21; + + Clear(); + DecodeRes = SZ_OK; + + XzUnpacker_Init(&xzu.p); + + if (!xzu.InBuf) + { + xzu.InBuf = (Byte *)MidAlloc(kInBufSize); + if (!xzu.InBuf) + return E_OUTOFMEMORY; + } + if (!xzu.OutBuf) + { + xzu.OutBuf = (Byte *)MidAlloc(kOutBufSize); + if (!xzu.OutBuf) + return E_OUTOFMEMORY; + } + + UInt32 inSize = 0; + UInt32 inPos = 0; + SizeT outPos = 0; + + HRESULT readRes = S_OK; + + for (;;) + { + if (inPos == inSize && readRes == S_OK) + { + inPos = inSize = 0; + readRes = seqInStream->Read(xzu.InBuf, kInBufSize, &inSize); + } + + SizeT inLen = inSize - inPos; + SizeT outLen = kOutBufSize - outPos; + ECoderFinishMode finishMode = CODER_FINISH_ANY; + if (inSize == 0) + finishMode = CODER_FINISH_END; + + if (outSizeLimit) + { + const UInt64 rem = *outSizeLimit - OutSize; + if (outLen >= rem) + { + outLen = (SizeT)rem; + if (finishStream) + finishMode = CODER_FINISH_END; + } + } + + ECoderStatus status; + + const SizeT outLenRequested = outLen; + + SRes res = XzUnpacker_Code(&xzu.p, + xzu.OutBuf + outPos, &outLen, + xzu.InBuf + inPos, &inLen, + finishMode, &status); + + DecodeRes = res; + + inPos += (UInt32)inLen; + outPos += outLen; + + InSize += inLen; + OutSize += outLen; + + bool finished = ((inLen == 0 && outLen == 0) || res != SZ_OK); + + if (outLen >= outLenRequested || finished) + { + if (outStream && outPos != 0) + { + RINOK(WriteStream(outStream, xzu.OutBuf, outPos)); + } + outPos = 0; + } + + if (progress) + { + RINOK(progress->SetRatioInfo(&InSize, &OutSize)); + } + + if (!finished) + continue; + + { + PhySize = InSize; + NumStreams = xzu.p.numStartedStreams; + if (NumStreams > 0) + IsArc = true; + NumBlocks = xzu.p.numTotalBlocks; + + UnpackSize_Defined = true; + NumStreams_Defined = true; + NumBlocks_Defined = true; + + UInt64 extraSize = XzUnpacker_GetExtraSize(&xzu.p); + + if (res == SZ_OK) + { + if (status == CODER_STATUS_NEEDS_MORE_INPUT) + { + extraSize = 0; + if (!XzUnpacker_IsStreamWasFinished(&xzu.p)) + { + // finished at padding bytes, but padding is not aligned for 4 + UnexpectedEnd = true; + res = SZ_ERROR_DATA; + } + } + else // status == CODER_STATUS_NOT_FINISHED + res = SZ_ERROR_DATA; + } + else if (res == SZ_ERROR_NO_ARCHIVE) + { + if (InSize == extraSize) + IsArc = false; + else + { + if (extraSize != 0 || inPos != inSize) + { + DataAfterEnd = true; + res = SZ_OK; + } + } + } + + DecodeRes = res; + PhySize -= extraSize; + + switch (res) + { + case SZ_OK: break; + case SZ_ERROR_NO_ARCHIVE: IsArc = false; break; + case SZ_ERROR_ARCHIVE: HeadersError = true; break; + case SZ_ERROR_UNSUPPORTED: Unsupported = true; break; + case SZ_ERROR_CRC: CrcError = true; break; + case SZ_ERROR_DATA: DataError = true; break; + default: DataError = true; break; + } + + return readRes; + } + } +} + + +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; +} + + + +HRESULT CComDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + RINOK(_decoder.Decode(inStream, outStream, outSize, _finishStream, progress)); + Int32 opRes = _decoder.Get_Extract_OperationResult(); + if (opRes == NArchive::NExtract::NOperationResult::kUnsupportedMethod) + return E_NOTIMPL; + if (opRes != NArchive::NExtract::NOperationResult::kOK) + return S_FALSE; + return S_OK; +} + +STDMETHODIMP CComDecoder::SetFinishMode(UInt32 finishMode) +{ + _finishStream = (finishMode != 0); + return S_OK; +} + +STDMETHODIMP CComDecoder::GetInStreamProcessedSize(UInt64 *value) +{ + *value = _decoder.InSize; + return S_OK; +} + +}} diff --git a/CPP/7zip/Compress/XzDecoder.h b/CPP/7zip/Compress/XzDecoder.h new file mode 100644 index 00000000..00609412 --- /dev/null +++ b/CPP/7zip/Compress/XzDecoder.h @@ -0,0 +1,95 @@ +// XzDecoder.h + +#ifndef __XZ_DECODER_H +#define __XZ_DECODER_H + +#include "../../Common/MyCom.h" +#include "../ICoder.h" + +#include "../../../C/Xz.h" + + +// #include "../../Archive/XzHandler.h" + +namespace NCompress { +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, + const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *compressProgress); + Int32 Get_Extract_OperationResult() const; +}; + + +class CComDecoder: + public ICompressCoder, + public ICompressSetFinishMode, + public ICompressGetInStreamProcessedSize, + public CMyUnknownImp +{ + CDecoder _decoder; + bool _finishStream; + +public: + MY_UNKNOWN_IMP2( + ICompressSetFinishMode, + ICompressGetInStreamProcessedSize) + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetFinishMode)(UInt32 finishMode); + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); + + CComDecoder(): _finishStream(false) {} +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/XzEncoder.cpp b/CPP/7zip/Compress/XzEncoder.cpp new file mode 100644 index 00000000..27194597 --- /dev/null +++ b/CPP/7zip/Compress/XzEncoder.cpp @@ -0,0 +1,190 @@ +// XzEncoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../Common/CWrappers.h" +#include "../Common/StreamUtils.h" + +#include "XzEncoder.h" + +namespace NCompress { + +namespace NLzma2 { + +HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props); + +} + +namespace NXz { + +extern "C" { + +static void *SzBigAlloc(ISzAllocPtr, size_t size) { return BigAlloc(size); } +static void SzBigFree(ISzAllocPtr, void *address) { BigFree(address); } +static const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; + +static void *SzAlloc(ISzAllocPtr, size_t size) { return MyAlloc(size); } +static void SzFree(ISzAllocPtr, void *address) { MyFree(address); } +static const ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +} + +void CEncoder::InitCoderProps() +{ + Lzma2EncProps_Init(&_lzma2Props); + XzProps_Init(&xzProps); + XzFilterProps_Init(&filter); + + xzProps.lzma2Props = &_lzma2Props; + // xzProps.filterProps = (_filterId != 0 ? &filter : NULL); + xzProps.filterProps = NULL; +} + +CEncoder::CEncoder() +{ + InitCoderProps(); +} + +CEncoder::~CEncoder() +{ +} + + +HRESULT CEncoder::SetCoderProp(PROPID propID, const PROPVARIANT &prop) +{ + return NLzma2::SetLzma2Prop(propID, prop, _lzma2Props); +} + +STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, + const PROPVARIANT *coderProps, UInt32 numProps) +{ + Lzma2EncProps_Init(&_lzma2Props); + + for (UInt32 i = 0; i < numProps; i++) + { + RINOK(SetCoderProp(propIDs[i], coderProps[i])); + } + return S_OK; + // return SResToHRESULT(Lzma2Enc_SetProps(_encoder, &lzma2Props)); +} + + + +STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, + ICompressProgressInfo *progress) +{ + CSeqOutStreamWrap seqOutStream; + + seqOutStream.Init(outStream); + + // if (IntToBool(newData)) + { + /* + UInt64 size; + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(0, kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + size = prop.uhVal.QuadPart; + RINOK(updateCallback->SetTotal(size)); + } + */ + + /* + CLzma2EncProps lzma2Props; + Lzma2EncProps_Init(&lzma2Props); + + lzma2Props.lzmaProps.level = GetLevel(); + */ + + CSeqInStreamWrap seqInStream; + + seqInStream.Init(inStream); + + + /* + { + NCOM::CPropVariant prop = (UInt64)size; + RINOK(NCompress::NLzma2::SetLzma2Prop(NCoderPropID::kReduceSize, prop, lzma2Props)); + } + + FOR_VECTOR (i, _methods) + { + COneMethodInfo &m = _methods[i]; + SetGlobalLevelAndThreads(m + #ifndef _7ZIP_ST + , _numThreads + #endif + ); + { + FOR_VECTOR (j, m.Props) + { + const CProp &prop = m.Props[j]; + RINOK(NCompress::NLzma2::SetLzma2Prop(prop.Id, prop.Value, lzma2Props)); + } + } + } + + #ifndef _7ZIP_ST + lzma2Props.numTotalThreads = _numThreads; + #endif + + */ + + CCompressProgressWrap progressWrap; + + progressWrap.Init(progress); + + xzProps.checkId = XZ_CHECK_CRC32; + // xzProps.checkId = XZ_CHECK_CRC64; + /* + CXzProps xzProps; + CXzFilterProps filter; + XzProps_Init(&xzProps); + XzFilterProps_Init(&filter); + xzProps.lzma2Props = &_lzma2Props; + */ + /* + xzProps.filterProps = (_filterId != 0 ? &filter : NULL); + switch (_crcSize) + { + case 0: xzProps.checkId = XZ_CHECK_NO; break; + case 4: xzProps.checkId = XZ_CHECK_CRC32; break; + case 8: xzProps.checkId = XZ_CHECK_CRC64; break; + case 32: xzProps.checkId = XZ_CHECK_SHA256; break; + default: return E_INVALIDARG; + } + filter.id = _filterId; + if (_filterId == XZ_ID_Delta) + { + bool deltaDefined = false; + FOR_VECTOR (j, _filterMethod.Props) + { + const CProp &prop = _filterMethod.Props[j]; + if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4) + { + UInt32 delta = (UInt32)prop.Value.ulVal; + if (delta < 1 || delta > 256) + return E_INVALIDARG; + filter.delta = delta; + deltaDefined = true; + } + } + if (!deltaDefined) + return E_INVALIDARG; + } + */ + SRes res = Xz_Encode(&seqOutStream.vt, &seqInStream.vt, &xzProps, progress ? &progressWrap.vt : NULL); + /* + if (res == SZ_OK) + return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); + */ + return SResToHRESULT(res); + } +} + +}} diff --git a/CPP/7zip/Compress/XzEncoder.h b/CPP/7zip/Compress/XzEncoder.h new file mode 100644 index 00000000..0e166ad3 --- /dev/null +++ b/CPP/7zip/Compress/XzEncoder.h @@ -0,0 +1,44 @@ +// XzEncoder.h + +#ifndef __XZ_ENCODER_H +#define __XZ_ENCODER_H + +#include "../../../C/XzEnc.h" + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +namespace NCompress { +namespace NXz { + + +class CEncoder: + public ICompressCoder, + public ICompressSetCoderProperties, + public CMyUnknownImp +{ + // CXzEncHandle _encoder; +public: + CLzma2EncProps _lzma2Props; + + CXzProps xzProps; + CXzFilterProps filter; + + MY_UNKNOWN_IMP2(ICompressCoder, ICompressSetCoderProperties) + + void InitCoderProps(); + + HRESULT SetCoderProp(PROPID propID, const PROPVARIANT &prop); + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + + CEncoder(); + virtual ~CEncoder(); +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/ZDecoder.cpp b/CPP/7zip/Compress/ZDecoder.cpp index 7308bc0b..06eab00e 100644 --- a/CPP/7zip/Compress/ZDecoder.cpp +++ b/CPP/7zip/Compress/ZDecoder.cpp @@ -100,7 +100,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * } } unsigned bytePos = bitPos >> 3; - UInt32 symbol = buf[bytePos] | ((UInt32)buf[bytePos + 1] << 8) | ((UInt32)buf[bytePos + 2] << 16); + UInt32 symbol = buf[bytePos] | ((UInt32)buf[(size_t)bytePos + 1] << 8) | ((UInt32)buf[(size_t)bytePos + 2] << 16); symbol >>= (bitPos & 7); symbol &= (1 << numBits) - 1; bitPos += numBits; @@ -129,7 +129,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * _stack[i++] = (Byte)cur; if (needPrev) { - _suffixes[head - 1] = (Byte)cur; + _suffixes[(size_t)head - 1] = (Byte)cur; if (symbol == head - 1) _stack[0] = (Byte)cur; } diff --git a/CPP/7zip/Crc.mak b/CPP/7zip/Crc.mak index f2b0874c..2e0b92ef 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" || "$(CPU)" == "ARM" +!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS" || "$(CPU)" == "ARM" || "$(CPU)" == "ARM64" C_OBJS = $(C_OBJS) \ !ELSE ASM_OBJS = $(ASM_OBJS) \ diff --git a/CPP/7zip/Crc64.mak b/CPP/7zip/Crc64.mak index 57301c22..1228a014 100644 --- a/CPP/7zip/Crc64.mak +++ b/CPP/7zip/Crc64.mak @@ -1,6 +1,6 @@ C_OBJS = $(C_OBJS) \ $O\XzCrc64.obj -!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS" || "$(CPU)" == "ARM" +!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS" || "$(CPU)" == "ARM" || "$(CPU)" == "ARM64" C_OBJS = $(C_OBJS) \ !ELSE ASM_OBJS = $(ASM_OBJS) \ diff --git a/CPP/7zip/Crypto/MyAes.h b/CPP/7zip/Crypto/MyAes.h index 84c21de3..182411db 100644 --- a/CPP/7zip/Crypto/MyAes.h +++ b/CPP/7zip/Crypto/MyAes.h @@ -30,6 +30,8 @@ class CAesCbcCoder: public: CAesCbcCoder(bool encodeMode, unsigned keySize); + virtual ~CAesCbcCoder() {}; // we need virtual destructor for derived classes + MY_UNKNOWN_IMP3(ICompressFilter, ICryptoProperties, ICompressSetCoderProperties) INTERFACE_ICompressFilter(;) diff --git a/CPP/7zip/Crypto/Rar20Crypto.cpp b/CPP/7zip/Crypto/Rar20Crypto.cpp index 346d969e..878dfc5c 100644 --- a/CPP/7zip/Crypto/Rar20Crypto.cpp +++ b/CPP/7zip/Crypto/Rar20Crypto.cpp @@ -68,7 +68,7 @@ void CData::SetPassword(const Byte *data, unsigned size) for (unsigned i = 0; i < size; i += 2) { unsigned n1 = (Byte)g_CrcTable[(psw[i] - j) & 0xFF]; - unsigned n2 = (Byte)g_CrcTable[(psw[i + 1] + j) & 0xFF]; + unsigned n2 = (Byte)g_CrcTable[(psw[(size_t)i + 1] + j) & 0xFF]; for (unsigned k = 1; (n1 & 0xFF) != n2; n1++, k++) Swap(SubstTable[n1 & 0xFF], SubstTable[(n1 + i + k) & 0xFF]); } diff --git a/CPP/7zip/Crypto/Rar20Crypto.h b/CPP/7zip/Crypto/Rar20Crypto.h index b3033700..6d1d0f5d 100644 --- a/CPP/7zip/Crypto/Rar20Crypto.h +++ b/CPP/7zip/Crypto/Rar20Crypto.h @@ -20,10 +20,10 @@ class CData UInt32 SubstLong(UInt32 t) const { - return (UInt32)SubstTable[(unsigned)t & 255] - | ((UInt32)SubstTable[(unsigned)(t >> 8) & 255] << 8) + 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); + | ((UInt32)SubstTable[(unsigned)(t >> 24) ] << 24); } void UpdateKeys(const Byte *data); void CryptBlock(Byte *buf, bool encrypt); diff --git a/CPP/7zip/Crypto/WzAes.h b/CPP/7zip/Crypto/WzAes.h index 41f9949e..3b22bc16 100644 --- a/CPP/7zip/Crypto/WzAes.h +++ b/CPP/7zip/Crypto/WzAes.h @@ -105,6 +105,8 @@ public: _key.KeySizeMode = (EKeySizeMode)mode; return true; } + + virtual ~CBaseCoder() {} }; class CEncoder: diff --git a/CPP/7zip/Crypto/ZipCrypto.h b/CPP/7zip/Crypto/ZipCrypto.h index b23d4216..acc0b031 100644 --- a/CPP/7zip/Crypto/ZipCrypto.h +++ b/CPP/7zip/Crypto/ZipCrypto.h @@ -50,6 +50,8 @@ public: MY_UNKNOWN_IMP1(ICryptoSetPassword) STDMETHOD(Init)(); STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); + + virtual ~CCipher() {} }; class CEncoder: public CCipher diff --git a/CPP/7zip/Crypto/ZipStrong.cpp b/CPP/7zip/Crypto/ZipStrong.cpp index 6d73a34b..2a923bf5 100644 --- a/CPP/7zip/Crypto/ZipStrong.cpp +++ b/CPP/7zip/Crypto/ZipStrong.cpp @@ -15,10 +15,14 @@ namespace NZipStrong { static const UInt16 kAES128 = 0x660E; -// DeriveKey* function is similar to CryptDeriveKey() from Windows. -// But MSDN tells that we need such scheme only if -// "the required key length is longer than the hash value" -// but ZipStrong uses it always. +/* + DeriveKey() function is similar to CryptDeriveKey() from Windows. + New version of MSDN contains the following condition in CryptDeriveKey() description: + "If the hash is not a member of the SHA-2 family and the required key is for either 3DES or AES". + Now we support ZipStrong for AES only. And it uses SHA1. + Our DeriveKey() code is equal to CryptDeriveKey() in Windows for such conditions: (SHA1 + AES). + if (method != AES && method != 3DES), probably we need another code. +*/ static void DeriveKey2(const Byte *digest, Byte c, Byte *dest) { @@ -116,7 +120,7 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK) if ((flags & 0x4000) != 0) { - // Use 3DES + // Use 3DES for rd data return E_NOTIMPL; } @@ -135,17 +139,21 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK) if (rdSize + 16 > _remSize) return E_NOTIMPL; + const unsigned kPadSize = kAesPadAllign; // is equal to blockSize of cipher for rd + /* if (cert) { - // how to filter rd, if ((rdSize & 0xF) != 0) ? if ((rdSize & 0x7) != 0) return E_NOTIMPL; } else */ { - if ((rdSize & 0xF) != 0) + // PKCS7 padding + if (rdSize < kPadSize) + return E_NOTIMPL; + if ((rdSize & (kPadSize - 1)) != 0) return E_NOTIMPL; } @@ -198,13 +206,18 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK) RINOK(SetInitVector(_iv, 16)); RINOK(Init()); Filter(p, rdSize); + + rdSize -= kPadSize; + for (unsigned i = 0; i < kPadSize; i++) + if (p[(size_t)rdSize + i] != kPadSize) + return S_OK; // passwOK = false; } Byte fileKey[32]; NSha1::CContext sha; sha.Init(); sha.Update(_iv, _ivSize); - sha.Update(p, rdSize - 16); // we don't use last 16 bytes (PAD bytes) + sha.Update(p, rdSize); DeriveKey(sha, fileKey); RINOK(SetKey(fileKey, _key.KeySize)); diff --git a/CPP/7zip/Crypto/ZipStrong.h b/CPP/7zip/Crypto/ZipStrong.h index c5809e7b..8e3c74e2 100644 --- a/CPP/7zip/Crypto/ZipStrong.h +++ b/CPP/7zip/Crypto/ZipStrong.h @@ -42,6 +42,8 @@ public: STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); }; +const unsigned kAesPadAllign = AES_BLOCK_SIZE; + class CDecoder: public CBaseCoder { UInt32 _ivSize; @@ -51,6 +53,12 @@ public: MY_UNKNOWN_IMP1(ICryptoSetPassword) HRESULT ReadHeader(ISequentialInStream *inStream, UInt32 crc, UInt64 unpackSize); HRESULT Init_and_CheckPassword(bool &passwOK); + UInt32 GetPadSize(UInt32 packSize32) const + { + // Padding is to align to blockSize of cipher. + // Change it, if is not AES + return kAesPadAllign - (packSize32 & (kAesPadAllign - 1)); + } }; }} diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt index 7edab6ea..a3360a86 100644 --- a/CPP/7zip/Guid.txt +++ b/CPP/7zip/Guid.txt @@ -47,6 +47,7 @@ 24 ICompressGetInStreamProcessedSize 25 ICompressSetCoderMt 26 ICompressSetFinishMode + 27 ICompressGetInStreamProcessedSize2 30 ICompressGetSubStreamSize 31 ICompressSetInStream diff --git a/CPP/7zip/ICoder.h b/CPP/7zip/ICoder.h index 75db9399..28f5f6d8 100644 --- a/CPP/7zip/ICoder.h +++ b/CPP/7zip/ICoder.h @@ -170,6 +170,11 @@ CODER_INTERFACE(ICompressSetFinishMode, 0x26) 1 : full decoding. The stream must be finished at the end of decoding. */ }; +CODER_INTERFACE(ICompressGetInStreamProcessedSize2, 0x27) +{ + STDMETHOD(GetInStreamProcessedSize2)(UInt32 streamIndex, UInt64 *value) PURE; +}; + CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) { diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp index a9021ef9..9b841ce2 100644 --- a/CPP/7zip/UI/Agent/Agent.cpp +++ b/CPP/7zip/UI/Agent/Agent.cpp @@ -523,6 +523,21 @@ static const wchar_t *GetExtension(const wchar_t *name) } } + +int CAgentFolder::CompareItems3(UInt32 index1, UInt32 index2, PROPID propID) +{ + NCOM::CPropVariant prop1, prop2; + // Name must be first property + GetProperty(index1, propID, &prop1); + GetProperty(index2, propID, &prop2); + if (prop1.vt != prop2.vt) + return MyCompare(prop1.vt, prop2.vt); + if (prop1.vt == VT_BSTR) + return MyStringCompareNoCase(prop1.bstrVal, prop2.bstrVal); + return prop1.Compare(prop2); +} + + int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw) { unsigned realIndex1, realIndex2; @@ -651,21 +666,10 @@ int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int if (propIsRaw) return CompareRawProps(_agentSpec->_archiveLink.GetArchiveGetRawProps(), arcIndex1, arcIndex2, propID); - NCOM::CPropVariant prop1, prop2; - // Name must be first property - GetProperty(index1, propID, &prop1); - GetProperty(index2, propID, &prop2); - if (prop1.vt != prop2.vt) - { - return MyCompare(prop1.vt, prop2.vt); - } - if (prop1.vt == VT_BSTR) - { - return _wcsicmp(prop1.bstrVal, prop2.bstrVal); - } - return prop1.Compare(prop2); + return CompareItems3(index1, index2, propID); } + STDMETHODIMP_(Int32) CAgentFolder::CompareItems(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw) { try { @@ -811,23 +815,12 @@ STDMETHODIMP_(Int32) CAgentFolder::CompareItems(UInt32 index1, UInt32 index2, PR return CompareRawProps(_agentSpec->_archiveLink.GetArchiveGetRawProps(), arcIndex1, arcIndex2, propID); } - NCOM::CPropVariant prop1, prop2; - // Name must be first property - GetProperty(index1, propID, &prop1); - GetProperty(index2, propID, &prop2); - if (prop1.vt != prop2.vt) - { - return MyCompare(prop1.vt, prop2.vt); - } - if (prop1.vt == VT_BSTR) - { - return _wcsicmp(prop1.bstrVal, prop2.bstrVal); - } - return prop1.Compare(prop2); + return CompareItems3(index1, index2, propID); } catch(...) { return 0; } } + HRESULT CAgentFolder::BindToFolder_Internal(unsigned proxyDirIndex, IFolderFolder **resultFolder) { /* @@ -1246,7 +1239,7 @@ STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) 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 kpidType: prop = UString("7-Zip.") + _agentSpec->ArchiveType; break; case kpidCRC: if (dir.CrcIsDefined) prop = dir.Crc; break; } @@ -1262,7 +1255,7 @@ STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) 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 kpidType: prop = UString("7-Zip.") + _agentSpec->ArchiveType; break; case kpidCRC: if (dir.CrcIsDefined) prop = dir.Crc; break; } } @@ -1582,9 +1575,9 @@ STDMETHODIMP CAgent::Open( if (Read_ShowDeleted()) { COptionalOpenProperties &optPair = optProps.AddNew(); - optPair.FormatName = L"ntfs"; - // optPair.Props.AddNew().Name = L"LS"; - optPair.Props.AddNew().Name = L"LD"; + optPair.FormatName = "ntfs"; + // optPair.Props.AddNew().Name = "LS"; + optPair.Props.AddNew().Name = "LD"; } */ diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h index 9d70c7a1..ae4026d6 100644 --- a/CPP/7zip/UI/Agent/Agent.h +++ b/CPP/7zip/UI/Agent/Agent.h @@ -43,7 +43,8 @@ enum AGENT_OP AGENT_OP_Delete, AGENT_OP_CreateFolder, AGENT_OP_Rename, - AGENT_OP_CopyFromFile + AGENT_OP_CopyFromFile, + AGENT_OP_Comment }; class CAgentFolder: @@ -101,6 +102,7 @@ public: STDMETHOD(GetFolderArcProps)(IFolderArcProps **object); STDMETHOD_(Int32, CompareItems)(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw); + int CompareItems3(UInt32 index1, UInt32 index2, PROPID propID); int CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw); // IArchiveFolder @@ -205,6 +207,10 @@ public: const UInt32 *indices, UInt32 numItems, const wchar_t *newItemName, IFolderArchiveUpdateCallback *updateCallback100); + HRESULT CommentItem(ISequentialOutStream *outArchiveStream, + const UInt32 *indices, UInt32 numItems, const wchar_t *newItemName, + IFolderArchiveUpdateCallback *updateCallback100); + HRESULT UpdateOneFile(ISequentialOutStream *outArchiveStream, const UInt32 *indices, UInt32 numItems, const wchar_t *diskFilePath, IFolderArchiveUpdateCallback *updateCallback100); @@ -262,7 +268,7 @@ public: UString GetTypeOfArc(const CArc &arc) const { if (arc.FormatIndex < 0) - return L"Parser"; + return UString("Parser"); return g_CodecsObj->GetFormatNamePtr(arc.FormatIndex); } @@ -277,12 +283,12 @@ public: if (arc.ErrorInfo.ErrorFormatIndex >= 0) { if (arc.ErrorInfo.ErrorFormatIndex == arc.FormatIndex) - s2.AddAscii("Warning: The archive is open with offset"); + s2 += "Warning: The archive is open with offset"; else { - s2.AddAscii("Can not open the file as ["); + s2 += "Can not open the file as ["; s2 += g_CodecsObj->GetFormatNamePtr(arc.ErrorInfo.ErrorFormatIndex); - s2.AddAscii("] archive"); + s2 += "] archive"; } } @@ -290,16 +296,16 @@ public: { if (!s2.IsEmpty()) s2.Add_LF(); - s2.AddAscii("\n["); + s2 += "\n["; s2 += GetTypeOfArc(arc); - s2.AddAscii("]: "); + s2 += "]: "; s2 += arc.ErrorInfo.ErrorMessage; } if (!s2.IsEmpty()) { if (!s.IsEmpty()) - s.AddAscii("--------------------\n"); + s += "--------------------\n"; s += arc.Path; s.Add_LF(); s += s2; diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp index 1302d8c7..40876d76 100644 --- a/CPP/7zip/UI/Agent/AgentOut.cpp +++ b/CPP/7zip/UI/Agent/AgentOut.cpp @@ -589,6 +589,55 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream, return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback); } + +HRESULT CAgent::CommentItem(ISequentialOutStream *outArchiveStream, + const UInt32 *indices, UInt32 numItems, const wchar_t *newItemName, + IFolderArchiveUpdateCallback *updateCallback100) +{ + if (!CanUpdate()) + return E_NOTIMPL; + if (numItems != 1) + return E_INVALIDARG; + if (!_archiveLink.IsOpen) + return E_FAIL; + + CRecordVector<CUpdatePair2> updatePairs; + CUpdateCallbackAgent updateCallbackAgent; + updateCallbackAgent.SetCallback(updateCallback100); + CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; + CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec); + + const int mainRealIndex = _agentFolder->GetRealIndex(indices[0]); + + if (mainRealIndex < 0) + return E_NOTIMPL; + + UInt32 numItemsInArchive; + RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive)); + + UString newName = newItemName; + + for (UInt32 i = 0; i < numItemsInArchive; i++) + { + CUpdatePair2 up2; + up2.SetAs_NoChangeArcItem(i); + if ((int)i == mainRealIndex) + up2.NewProps = true; + updatePairs.Add(up2); + } + + updateCallbackSpec->Callback = &updateCallbackAgent; + updateCallbackSpec->UpdatePairs = &updatePairs; + updateCallbackSpec->CommentIndex = mainRealIndex; + updateCallbackSpec->Comment = &newName; + + SetInArchiveInterfaces(this, updateCallbackSpec); + + return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback); +} + + + HRESULT CAgent::UpdateOneFile(ISequentialOutStream *outArchiveStream, const UInt32 *indices, UInt32 numItems, const wchar_t *diskFilePath, IFolderArchiveUpdateCallback *updateCallback100) diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp index eb07efd8..7f550f75 100644 --- a/CPP/7zip/UI/Agent/AgentProxy.cpp +++ b/CPP/7zip/UI/Agent/AgentProxy.cpp @@ -316,7 +316,7 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) if (numLevels <= kLevelLimit) { if (numLevels == kLevelLimit) - name.SetFromAscii("[LONG_PATH]"); + name = "[LONG_PATH]"; else name.SetFrom(s + namePos, j - namePos); curItem = AddDir(curItem, -1, name); @@ -569,7 +569,7 @@ HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress) { // Dirs[1] - for alt streams of root dir CProxyDir2 &dir = Dirs.AddNew(); - dir.PathPrefix = L':'; + dir.PathPrefix = ':'; } Files.Alloc(numItems); diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp index 325d6426..ecbfe58b 100644 --- a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp @@ -30,9 +30,11 @@ void CAgentFolder::GetPathParts(UStringVector &pathParts, bool &isAltStreamFolde static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path) { NFind::CFileInfo fileInfo; - FString pathPrefix = path + FCHAR_PATH_SEPARATOR; + FString pathPrefix = path; + pathPrefix.Add_PathSepar(); { - NFind::CEnumerator enumerator(pathPrefix + FCHAR_ANY_MASK); + NFind::CEnumerator enumerator; + enumerator.SetDirPrefix(pathPrefix); while (enumerator.Next(fileInfo)) { if (fileInfo.IsDir()) @@ -112,6 +114,9 @@ HRESULT CAgentFolder::CommonUpdateOperation( case AGENT_OP_Rename: result = _agentSpec->RenameItem(tailStream, indices, numItems, newItemName, updateCallback100); break; + case AGENT_OP_Comment: + result = _agentSpec->CommentItem(tailStream, indices, numItems, newItemName, updateCallback100); + break; case AGENT_OP_CopyFromFile: result = _agentSpec->UpdateOneFile(tailStream, indices, numItems, newItemName, updateCallback100); break; @@ -274,7 +279,7 @@ HRESULT CAgentFolder::CommonUpdateOperation( { if (updateCallback100) { - UString s2 = L"Error: "; + UString s2 ("Error: "); s2 += s; RINOK(updateCallback100->UpdateErrorMessage(s2)); return E_FAIL; @@ -304,13 +309,9 @@ STDMETHODIMP CAgentFolder::CopyFrom(Int32 moveMode, STDMETHODIMP CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPath, IProgress *progress) { COM_TRY_BEGIN - CUIntVector indices; - indices.Add(destIndex); - { - return CommonUpdateOperation(AGENT_OP_CopyFromFile, false, itemPath, - &NUpdateArchive::k_ActionSet_Add, - &indices.Front(), indices.Size(), progress); - } + return CommonUpdateOperation(AGENT_OP_CopyFromFile, false, itemPath, + &NUpdateArchive::k_ActionSet_Add, + &destIndex, 1, progress); COM_TRY_END } @@ -347,10 +348,8 @@ STDMETHODIMP CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress STDMETHODIMP CAgentFolder::Rename(UInt32 index, const wchar_t *newName, IProgress *progress) { COM_TRY_BEGIN - CUIntVector indices; - indices.Add(index); return CommonUpdateOperation(AGENT_OP_Rename, false, newName, NULL, - &indices.Front(), indices.Size(), progress); + &index, 1, progress); COM_TRY_END } @@ -359,8 +358,16 @@ STDMETHODIMP CAgentFolder::CreateFile(const wchar_t * /* name */, IProgress * /* return E_NOTIMPL; } -STDMETHODIMP CAgentFolder::SetProperty(UInt32 /* index */, PROPID /* propID */, - const PROPVARIANT * /* value */, IProgress * /* progress */) +STDMETHODIMP CAgentFolder::SetProperty(UInt32 index, PROPID propID, + const PROPVARIANT *value, IProgress *progress) { - return E_NOTIMPL; + COM_TRY_BEGIN + if (propID != kpidComment || value->vt != VT_BSTR) + return E_NOTIMPL; + if (!_agentSpec || !_agentSpec->GetTypeOfArc(_agentSpec->GetArc()).IsEqualTo_Ascii_NoCase("zip")) + return E_NOTIMPL; + + return CommonUpdateOperation(AGENT_OP_Comment, false, value->bstrVal, NULL, + &index, 1, progress); + COM_TRY_END } diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp index e2813c80..d450eefe 100644 --- a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp +++ b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp @@ -22,10 +22,10 @@ void CUpdateCallbackAgent::SetCallback(IFolderArchiveUpdateCallback *callback) } } -HRESULT CUpdateCallbackAgent::SetNumItems(UInt64 numItems) +HRESULT CUpdateCallbackAgent::SetNumItems(const CArcToDoStat &stat) { if (Callback) - return Callback->SetNumFiles(numItems); + return Callback->SetNumFiles(stat.Get_NumDataItems_Total()); return S_OK; } @@ -82,9 +82,9 @@ HRESULT CUpdateCallbackAgent::OpenFileError(const FString &path, DWORD systemErr if (Callback) { - UString s = L"WARNING: "; + UString s ("WARNING: "); s += NError::MyFormatMessage(systemError); - s += L": "; + s += ": "; s += fs2us(path); RINOK(Callback->UpdateErrorMessage(s)); return S_FALSE; @@ -106,9 +106,9 @@ HRESULT CUpdateCallbackAgent::ReadingFileError(const FString &path, DWORD system } else if (Callback) { - UString s = L"ERROR: "; + UString s ("ERROR: "); s += NError::MyFormatMessage(systemError); - s += L": "; + s += ": "; s += fs2us(path); RINOK(Callback->UpdateErrorMessage(s)); } diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp index 55650cfa..1eb3909c 100644 --- a/CPP/7zip/UI/Client7z/Client7z.cpp +++ b/CPP/7zip/UI/Client7z/Client7z.cpp @@ -49,21 +49,35 @@ using namespace NDir; #define kDllName "7z.dll" -static const char *kCopyrightString = "\n7-Zip " MY_VERSION -" (" kDllName " client) " -MY_COPYRIGHT " " MY_DATE "\n"; - -static const char *kHelpString = -"Usage: Client7z.exe [a | l | x ] archive.7z [fileName ...]\n" +static const char * const kCopyrightString = + "\n" + "7-Zip" + " (" kDllName " client)" + " " MY_VERSION + " : " MY_COPYRIGHT_DATE + "\n"; + +static const char * const kHelpString = +"Usage: 7zcl.exe [a | l | x] archive.7z [fileName ...]\n" "Examples:\n" -" Client7z.exe a archive.7z f1.txt f2.txt : compress two files to archive.7z\n" -" Client7z.exe l archive.7z : List contents of archive.7z\n" -" Client7z.exe x archive.7z : eXtract files from archive.7z\n"; +" 7zcl.exe a archive.7z f1.txt f2.txt : compress two files to archive.7z\n" +" 7zcl.exe l archive.7z : List contents of archive.7z\n" +" 7zcl.exe x archive.7z : eXtract files from archive.7z\n"; -static AString FStringToConsoleString(const FString &s) +static void Convert_UString_to_AString(const UString &s, AString &temp) { - return GetOemString(fs2us(s)); + int codePage = CP_OEMCP; + /* + int g_CodePage = -1; + int codePage = g_CodePage; + if (codePage == -1) + codePage = CP_OEMCP; + if (codePage == CP_UTF8) + ConvertUnicodeToUTF8(s, temp); + else + */ + UnicodeStringToMultiByte2(temp, s, (UINT)codePage); } static FString CmdStringToFString(const char *s) @@ -71,42 +85,54 @@ static FString CmdStringToFString(const char *s) return us2fs(GetUnicodeString(s)); } -static void PrintString(const UString &s) +static void Print(const char *s) +{ + fputs(s, stdout); +} + +static void Print(const AString &s) { - printf("%s", (LPCSTR)GetOemString(s)); + Print(s.Ptr()); } -static void PrintString(const AString &s) +static void Print(const UString &s) { - printf("%s", (LPCSTR)s); + AString as; + Convert_UString_to_AString(s, as); + Print(as); +} + +static void Print(const wchar_t *s) +{ + Print(UString(s)); } static void PrintNewLine() { - PrintString("\n"); + Print("\n"); } -static void PrintStringLn(const AString &s) +static void PrintStringLn(const char *s) { - PrintString(s); + Print(s); PrintNewLine(); } -static void PrintError(const char *message, const FString &name) +static void PrintError(const char *message) { - printf("Error: %s", (LPCSTR)message); + Print("Error: "); PrintNewLine(); - PrintString(FStringToConsoleString(name)); + Print(message); PrintNewLine(); } -static void PrintError(const AString &s) +static void PrintError(const char *message, const FString &name) { - PrintNewLine(); - PrintString(s); - PrintNewLine(); + PrintError(message); + Print(name); } + static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; @@ -126,7 +152,7 @@ static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &resu } -static const wchar_t *kEmptyFileAlias = L"[Content]"; +static const wchar_t * const kEmptyFileAlias = L"[Content]"; ////////////////////////////////////////////////////////////// @@ -176,21 +202,25 @@ STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password) } + +static const char * const kIncorrectCommand = "incorrect command"; + ////////////////////////////////////////////////////////////// // Archive Extracting callback class -static const char *kTestingString = "Testing "; -static const char *kExtractingString = "Extracting "; -static const char *kSkippingString = "Skipping "; +static const char * const kTestingString = "Testing "; +static const char * const kExtractingString = "Extracting "; +static const char * const kSkippingString = "Skipping "; + +static const char * const kUnsupportedMethod = "Unsupported Method"; +static const char * const kCRCFailed = "CRC Failed"; +static const char * const kDataError = "Data Error"; +static const char * const kUnavailableData = "Unavailable data"; +static const char * const kUnexpectedEnd = "Unexpected end of data"; +static const char * const kDataAfterEnd = "There are some data after the end of the payload data"; +static const char * const kIsNotArc = "Is not archive"; +static const char * const kHeadersError = "Headers Error"; -static const char *kUnsupportedMethod = "Unsupported Method"; -static const char *kCRCFailed = "CRC Failed"; -static const char *kDataError = "Data Error"; -static const char *kUnavailableData = "Unavailable data"; -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"; class CArchiveExtractCallback: public IArchiveExtractCallback, @@ -380,11 +410,11 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) }; switch (askExtractMode) { - case NArchive::NExtract::NAskMode::kExtract: PrintString(kExtractingString); break; - case NArchive::NExtract::NAskMode::kTest: PrintString(kTestingString); break; - case NArchive::NExtract::NAskMode::kSkip: PrintString(kSkippingString); break; + case NArchive::NExtract::NAskMode::kExtract: Print(kExtractingString); break; + case NArchive::NExtract::NAskMode::kTest: Print(kTestingString); break; + case NArchive::NExtract::NAskMode::kSkip: Print(kSkippingString); break; }; - PrintString(_filePath); + Print(_filePath); return S_OK; } @@ -397,7 +427,7 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) default: { NumErrors++; - PrintString(" : "); + Print(" : "); const char *s = NULL; switch (operationResult) { @@ -428,15 +458,15 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) } if (s) { - PrintString("Error : "); - PrintString(s); + Print("Error : "); + Print(s); } else { char temp[16]; ConvertUInt32ToString(operationResult, temp); - PrintString("Error #"); - PrintString(temp); + Print("Error #"); + Print(temp); } } } @@ -602,10 +632,10 @@ HRESULT CArchiveUpdateCallback::Finilize() static void GetStream2(const wchar_t *name) { - PrintString("Compressing "); + Print("Compressing "); if (name[0] == 0) name = kEmptyFileAlias; - PrintString(name); + Print(name); } STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) @@ -631,7 +661,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream { PrintNewLine(); PrintError("WARNING: can't open file"); - // PrintString(NError::MyFormatMessageW(systemError)); + // Print(NError::MyFormatMessageW(systemError)); return S_FALSE; } // return sysError; @@ -665,7 +695,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOu while (res.Len() < 2) res.InsertAtFront(L'0'); UString fileName = VolName; - fileName += L'.'; + fileName += '.'; fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; @@ -704,11 +734,18 @@ int MY_CDECL main(int numArgs, const char *args[]) PrintStringLn(kCopyrightString); - if (numArgs < 3) + if (numArgs < 2) { PrintStringLn(kHelpString); + return 0; + } + + if (numArgs < 3) + { + PrintError(kIncorrectCommand); return 1; } + NDLL::CLibrary lib; if (!lib.Load(NDLL::GetModuleDirPrefix() + FTEXT(kDllName))) @@ -726,10 +763,10 @@ int MY_CDECL main(int numArgs, const char *args[]) char c; { - AString command = args[1]; + AString command (args[1]); if (command.Len() != 1) { - PrintError("incorrect command"); + PrintError(kIncorrectCommand); return 1; } c = (char)MyCharLower_Ascii(command[0]); @@ -742,7 +779,7 @@ int MY_CDECL main(int numArgs, const char *args[]) // create archive command if (numArgs < 4) { - PrintStringLn(kHelpString); + PrintError(kIncorrectCommand); return 1; } CObjectVector<CDirItem> dirItems; @@ -839,7 +876,7 @@ int MY_CDECL main(int numArgs, const char *args[]) { if (numArgs != 3) { - PrintStringLn(kHelpString); + PrintError(kIncorrectCommand); return 1; } @@ -851,7 +888,7 @@ int MY_CDECL main(int numArgs, const char *args[]) listCommand = false; else { - PrintError("incorrect command"); + PrintError(kIncorrectCommand); return 1; } @@ -899,17 +936,17 @@ int MY_CDECL main(int numArgs, const char *args[]) archive->GetProperty(i, kpidSize, &prop); char s[32]; ConvertPropVariantToShortString(prop, s); - PrintString(s); - PrintString(" "); + Print(s); + Print(" "); } { // Get name of file NCOM::CPropVariant prop; archive->GetProperty(i, kpidPath, &prop); if (prop.vt == VT_BSTR) - PrintString(prop.bstrVal); + Print(prop.bstrVal); else if (prop.vt != VT_EMPTY) - PrintString("ERROR!"); + Print("ERROR!"); } PrintNewLine(); } @@ -919,10 +956,10 @@ int MY_CDECL main(int numArgs, const char *args[]) // Extract command CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec); - extractCallbackSpec->Init(archive, FTEXT("")); // second parameter is output folder path + extractCallbackSpec->Init(archive, FString()); // second parameter is output folder path extractCallbackSpec->PasswordIsDefined = false; // extractCallbackSpec->PasswordIsDefined = true; - // extractCallbackSpec->Password = L"1"; + // extractCallbackSpec->Password = "1"; /* const wchar_t *names[] = diff --git a/CPP/7zip/UI/Client7z/Client7z.dsp b/CPP/7zip/UI/Client7z/Client7z.dsp index 8ad7fb13..b412c8e9 100644 --- a/CPP/7zip/UI/Client7z/Client7z.dsp +++ b/CPP/7zip/UI/Client7z/Client7z.dsp @@ -66,7 +66,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" /Yu"stdafx.h" /FD /GZ /c -# ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MDd /W4 /WX /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe diff --git a/CPP/7zip/UI/Client7z/resource.rc b/CPP/7zip/UI/Client7z/resource.rc index a09bb044..462df6fa 100644 --- a/CPP/7zip/UI/Client7z/resource.rc +++ b/CPP/7zip/UI/Client7z/resource.rc @@ -1,3 +1,3 @@ #include "../../MyVersionInfo.rc" -MY_VERSION_INFO_APP("7-Zip client", "7zcl") +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 832ec66d..ad21bc88 100644 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp @@ -29,6 +29,7 @@ #include "UpdateAction.h" extern bool g_CaseSensitive; +extern bool g_PathTrailReplaceMode; #ifdef UNDER_CE @@ -61,10 +62,10 @@ static bool StringToUInt32(const wchar_t *s, UInt32 &v) CArcCmdLineException::CArcCmdLineException(const char *a, const wchar_t *u) { - (*this) += MultiByteToUnicodeString(a); + (*this) += a; if (u) { - this->Add_LF(); + Add_LF(); (*this) += u; } } @@ -133,10 +134,13 @@ enum Enum kHardLinks, kSymLinks, kNtSecurity, + kAltStreams, kReplaceColonForAltStream, kWriteToAltStreamIfColon, + kNameTrailReplace, + kDeleteAfterCompressing, kSetArcMTime @@ -149,11 +153,11 @@ enum Enum static const wchar_t kRecursedIDChar = 'r'; -static const char *kRecursedPostCharSet = "0-"; +static const char * const kRecursedPostCharSet = "0-"; -static const char *k_ArcNameMode_PostCharSet = "sea"; +static const char * const k_ArcNameMode_PostCharSet = "sea"; -static const char *k_Stream_PostCharSet = "012"; +static const char * const k_Stream_PostCharSet = "012"; static inline const EArcNameMode ParseArcNameMode(int postCharIndex) { @@ -180,7 +184,7 @@ static const char kFileListID = '@'; static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be -static const char *kOverwritePostCharSet = "asut"; +static const char * const kOverwritePostCharSet = "asut"; static const NExtract::NOverwriteMode::EEnum k_OverwriteModes[] = { @@ -251,10 +255,13 @@ static const CSwitchForm kSwitchForms[] = { "snh", NSwitchType::kMinus }, { "snl", NSwitchType::kMinus }, { "sni" }, + { "sns", NSwitchType::kMinus }, { "snr" }, { "snc" }, + { "snt", NSwitchType::kMinus }, + { "sdel" }, { "stl" } @@ -263,17 +270,17 @@ static const CSwitchForm kSwitchForms[] = #endif }; -static const wchar_t *kUniversalWildcard = L"*"; +static const char * const kUniversalWildcard = "*"; 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 *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 stream"; -static const char *kEmptyFilePath = "Empty file path"; -static const char *kCannotFindArchive = "Cannot find archive"; +// static const char * const kUserErrorMessage = "Incorrect command line"; +static const char * const kCannotFindListFile = "Cannot find listfile"; +static const char * const kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch."; +static const char * const kTerminalOutError = "I won't write compressed data to a terminal"; +static const char * const kSameTerminalError = "I won't write data and program's messages to same stream"; +static const char * const kEmptyFilePath = "Empty file path"; +static const char * const kCannotFindArchive = "Cannot find archive"; bool CArcCommand::IsFromExtractGroup() const { @@ -328,7 +335,7 @@ static const char *g_Commands = "audtexlbih"; static bool ParseArchiveCommand(const UString &commandString, CArcCommand &command) { - UString s = commandString; + UString s (commandString); s.MakeLower_Ascii(); if (s.Len() == 1) { @@ -386,9 +393,9 @@ static void AddRenamePair(CObjectVector<CRenamePair> *renamePairs, val += pair.NewName; val.Add_LF(); if (type == NRecursedType::kRecursed) - val.AddAscii("-r"); + val += "-r"; else if (type == NRecursedType::kWildcardOnlyRecursed) - val.AddAscii("-r0"); + val += "-r0"; throw CArcCmdLineException("Unsupported rename command:", val); } } @@ -422,23 +429,28 @@ static void AddToCensorFromNonSwitchesStrings( CObjectVector<CRenamePair> *renamePairs, unsigned startIndex, NWildcard::CCensor &censor, - const UStringVector &nonSwitchStrings, NRecursedType::EEnum type, + const UStringVector &nonSwitchStrings, + int stopSwitchIndex, + NRecursedType::EEnum type, bool wildcardMatching, bool thereAreSwitchIncludes, Int32 codePage) { if ((renamePairs || nonSwitchStrings.Size() == startIndex) && !thereAreSwitchIncludes) - AddNameToCensor(censor, kUniversalWildcard, true, type, + AddNameToCensor(censor, UString(kUniversalWildcard), true, type, true // wildcardMatching ); int oldIndex = -1; + if (stopSwitchIndex < 0) + stopSwitchIndex = nonSwitchStrings.Size(); + for (unsigned i = startIndex; i < nonSwitchStrings.Size(); i++) { const UString &s = nonSwitchStrings[i]; if (s.IsEmpty()) throw CArcCmdLineException(kEmptyFilePath); - if (s[0] == kFileListID) + if (i < (unsigned)stopSwitchIndex && s[0] == kFileListID) AddToCensorFromListFile(renamePairs, censor, s.Ptr(1), true, type, wildcardMatching, codePage); else if (renamePairs) { @@ -477,7 +489,7 @@ struct CEventSetEnd } }; -const char *k_IncorrectMapCommand = "Incorrect Map command"; +static const char * const k_IncorrectMapCommand = "Incorrect Map command"; static const char *ParseMapWithPaths( NWildcard::CCensor &censor, @@ -485,7 +497,7 @@ static const char *ParseMapWithPaths( NRecursedType::EEnum commonRecursedType, bool wildcardMatching) { - UString s = s2; + UString s (s2); int pos = s.Find(L':'); if (pos < 0) return k_IncorrectMapCommand; @@ -577,7 +589,7 @@ static void AddSwitchWildcardsToCensor( break; } - UString tail = name.Ptr(pos + 1); + const UString tail = name.Ptr(pos + 1); if (name[pos] == kImmediateNameID) AddNameToCensor(censor, tail, include, recursedType, wildcardMatching); @@ -610,7 +622,7 @@ static void ConvertToLongName(const UString &prefix, UString &name) if (name.IsEmpty() || DoesNameContainWildcard(name)) return; NFind::CFileInfo fi; - const FString path = us2fs(prefix + name); + const FString path (us2fs(prefix + name)); #ifndef UNDER_CE if (NFile::NName::IsDevicePath(path)) return; @@ -693,11 +705,11 @@ static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i) } */ -static const wchar_t *kUpdatePairStateIDSet = L"pqrxyzw"; +static const char * const kUpdatePairStateIDSet = "pqrxyzw"; static const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1}; static const unsigned kNumUpdatePairActions = 4; -static const char *kUpdateIgnoreItselfPostStringID = "-"; +static const char * const kUpdateIgnoreItselfPostStringID = "-"; static const wchar_t kUpdateNewArchivePostCharID = '!'; @@ -707,8 +719,8 @@ static bool ParseUpdateCommandString2(const UString &command, for (unsigned i = 0; i < command.Len();) { wchar_t c = MyCharLower_Ascii(command[i]); - int statePos = FindCharPosInString(kUpdatePairStateIDSet, c); - if (statePos < 0) + int statePos = FindCharPosInString(kUpdatePairStateIDSet, (char)c); + if (c > 0x7F || statePos < 0) { postString = command.Ptr(i); return true; @@ -849,7 +861,6 @@ static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &pr } } -CArcCmdLineParser::CArcCmdLineParser(): parser(ARRAY_SIZE(kSwitchForms)) {} static inline void SetStreamMode(const CSwitchResult &sw, unsigned &res) { @@ -857,10 +868,11 @@ static inline void SetStreamMode(const CSwitchResult &sw, unsigned &res) res = sw.PostCharIndex; } + void CArcCmdLineParser::Parse1(const UStringVector &commandStrings, CArcCmdLineOptions &options) { - if (!parser.ParseStrings(kSwitchForms, commandStrings)) + if (!parser.ParseStrings(kSwitchForms, ARRAY_SIZE(kSwitchForms), commandStrings)) throw CArcCmdLineException(parser.ErrorMessage, parser.ErrorLine); options.IsInTerminal = MY_IS_TERMINAL(stdin); @@ -965,7 +977,7 @@ static Int32 FindCharset(const NCommandLineParser::CParser &parser, unsigned key if (!parser[keyIndex].ThereIs) return defaultVal; - UString name = parser[keyIndex].PostStrings.Back(); + UString name (parser[keyIndex].PostStrings.Back()); UInt32 v; if (StringToUInt32(name, v)) if (v < ((UInt32)1 << 16)) @@ -1051,7 +1063,7 @@ static void SetBoolPair(NCommandLineParser::CParser &parser, unsigned switchID, void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) { const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; - unsigned numNonSwitchStrings = nonSwitchStrings.Size(); + const unsigned numNonSwitchStrings = nonSwitchStrings.Size(); if (numNonSwitchStrings < kMinNonSwitchWords) throw CArcCmdLineException("The command must be specified"); @@ -1082,6 +1094,9 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) } } + if (parser[NKey::kNameTrailReplace].ThereIs) + g_PathTrailReplaceMode = !parser[NKey::kNameTrailReplace].WithMinus; + NRecursedType::EEnum recursedType; if (parser[NKey::kRecursed].ThereIs) recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex); @@ -1138,7 +1153,8 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) AddToCensorFromNonSwitchesStrings(isRename ? &options.UpdateOptions.RenamePairs : NULL, curCommandIndex, options.Censor, - nonSwitchStrings, recursedType, wildcardMatching, + nonSwitchStrings, parser.StopSwitchIndex, + recursedType, wildcardMatching, thereAreSwitchIncludes, codePage); options.YesToAll = parser[NKey::kYes].ThereIs; diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.h b/CPP/7zip/UI/Common/ArchiveCommandLine.h index a345505c..1c96601a 100644 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.h +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.h @@ -130,7 +130,6 @@ class CArcCmdLineParser { NCommandLineParser::CParser parser; public: - CArcCmdLineParser(); void Parse1(const UStringVector &commandStrings, CArcCmdLineOptions &options); void Parse2(CArcCmdLineOptions &options); }; diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp index bc116c93..8d645a29 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp @@ -5,7 +5,12 @@ #undef sprintf #undef printf +// #include <stdio.h> +// #include "../../../../C/CpuTicks.h" + #include "../../../../C/Alloc.h" +#include "../../../../C/CpuArch.h" + #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" @@ -36,10 +41,14 @@ using namespace NWindows; using namespace NFile; using namespace NDir; -static const char *kCantAutoRename = "Can not create file with auto name"; -static const char *kCantRenameFile = "Can not rename existing file"; -static const char *kCantDeleteOutputFile = "Can not delete output file"; -static const char *kCantDeleteOutputDir = "Can not delete output folder"; +static const char * const kCantAutoRename = "Can not create file with auto name"; +static const char * const kCantRenameFile = "Can not rename existing file"; +static const char * const kCantDeleteOutputFile = "Can not delete output file"; +static const char * const kCantDeleteOutputDir = "Can not delete output folder"; +static const char * const kCantCreateHardLink = "Can not create hard link"; +static const char * const kCantCreateSymLink = "Can not create symbolic link"; +static const char * const kCantOpenOutFile = "Can not open output file"; +static const char * const kCantSetFileLen = "Can not set length for output file"; #ifndef _SFX @@ -381,14 +390,13 @@ HRESULT CArchiveExtractCallback::GetUnpackSize() static void AddPathToMessage(UString &s, const FString &path) { - s.AddAscii(" : "); + s += " : "; s += fs2us(path); } HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path) { - UString s; - s.AddAscii(message); + UString s (message); AddPathToMessage(s, path); return _extractCallback2->MessageError(s); } @@ -396,11 +404,10 @@ HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FSt HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path) { DWORD errorCode = GetLastError(); - UString s; - s.AddAscii(message); + UString s (message); if (errorCode != 0) { - s.AddAscii(" : "); + s += " : "; s += NError::MyFormatMessage(errorCode); } AddPathToMessage(s, path); @@ -409,8 +416,7 @@ HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *mes HRESULT CArchiveExtractCallback::SendMessageError2(const char *message, const FString &path1, const FString &path2) { - UString s; - s.AddAscii(message); + UString s (message); AddPathToMessage(s, path1); AddPathToMessage(s, path2); return _extractCallback2->MessageError(s); @@ -440,7 +446,7 @@ STDMETHODIMP CGetProp::GetProp(PROPID propID, PROPVARIANT *value) static UString GetDirPrefixOf(const UString &src) { - UString s = src; + UString s (src); if (!s.IsEmpty()) { if (IsPathSepar(s.Back())) @@ -514,7 +520,7 @@ bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcIte if (pathParts2.IsEmpty()) pathParts2.AddNew(); UString &back = pathParts2.Back(); - back += L':'; + back += ':'; back += item.AltStreamName; bool include2; @@ -541,7 +547,7 @@ bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem static FString MakePath_from_2_Parts(const FString &prefix, const FString &path) { - FString s = prefix; + FString s (prefix); #if defined(_WIN32) && !defined(UNDER_CE) if (!path.IsEmpty() && path[0] == ':' && !prefix.IsEmpty() && IsPathSepar(prefix.Back())) { @@ -596,6 +602,7 @@ HRESULT CArchiveExtractCallback::MyCopyFile(ISequentialOutStream *outStream) #endif */ + STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { COM_TRY_BEGIN @@ -616,6 +623,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre _curSize = 0; _curSizeDefined = false; + _fileLengthWasSet = false; _index = index; _diskFilePath.Empty(); @@ -928,13 +936,13 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre } GetProp_Spec->Arc = _arc; GetProp_Spec->IndexInArc = index; - UString name = MakePathFromParts(pathParts); + UString name (MakePathFromParts(pathParts)); #ifdef SUPPORT_ALT_STREAMS if (_item.IsAltStream) { if (!pathParts.IsEmpty() || (!_removePartsForAltStreams && _pathMode != NExtract::NPathMode::kNoPathsAlt)) - name += L':'; + name += ':'; name += _item.AltStreamName; } #endif @@ -986,7 +994,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) if (_item.IsAltStream) { - UString s = _item.AltStreamName; + UString s (_item.AltStreamName); Correct_AltStream_Name(s); bool needColon = true; @@ -1002,13 +1010,13 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) UString &name = pathParts.Back(); if (needColon) - name += (wchar_t)(_ntOptions.ReplaceColonForAltStream ? L'_' : L':'); + name += (char)(_ntOptions.ReplaceColonForAltStream ? '_' : ':'); name += s; } #endif - UString processedPath = MakePathFromParts(pathParts); + UString processedPath (MakePathFromParts(pathParts)); if (!isAnti) { @@ -1035,7 +1043,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) } - FString fullProcessedPath = us2fs(processedPath); + FString fullProcessedPath (us2fs(processedPath)); if (_pathMode != NExtract::NPathMode::kAbsPaths || !NName::IsAbsolutePath(processedPath)) { @@ -1051,8 +1059,8 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) { const CIndexToPathPair &pair = _renamedFiles[renIndex]; fullProcessedPath = pair.Path; - fullProcessedPath += (FChar)':'; - UString s = _item.AltStreamName; + fullProcessedPath += ':'; + UString s (_item.AltStreamName); Correct_AltStream_Name(s); fullProcessedPath += us2fs(s); } @@ -1086,7 +1094,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) case NExtract::NOverwriteMode::kAsk: { int slashPos = fullProcessedPath.ReverseFind_PathSepar(); - FString realFullProcessedPath = fullProcessedPath.Left(slashPos + 1) + fileInfo.Name; + FString realFullProcessedPath (fullProcessedPath.Left(slashPos + 1) + fileInfo.Name); Int32 overwriteResult; RINOK(_extractCallback2->AskOverwrite( @@ -1119,7 +1127,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) } else if (_overwriteMode == NExtract::NOverwriteMode::kRenameExisting) { - FString existPath = fullProcessedPath; + FString existPath (fullProcessedPath); if (!AutoRenamePath(existPath)) { RINOK(SendMessageError(kCantAutoRename, fullProcessedPath)); @@ -1165,7 +1173,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) int colonPos = NName::FindAltStreamColon(fullProcessedPath); if (colonPos >= 0 && fullProcessedPath[(unsigned)colonPos + 1] != 0) { - FString parentFsPath = fullProcessedPath; + FString parentFsPath (fullProcessedPath); parentFsPath.DeleteFrom(colonPos); NFind::CFileInfo parentFi; if (parentFi.Find(parentFsPath)) @@ -1222,7 +1230,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) { if (!MyCreateHardLink(fullProcessedPath, existPath)) { - RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, existPath)); + RINOK(SendMessageError2(kCantCreateHardLink, fullProcessedPath, existPath)); // return S_OK; } } @@ -1270,7 +1278,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) else if (!NFile::NIO::SetReparseData(fullProcessedPath, _item.IsDir, data, (DWORD)data.Size())) { - RINOK(SendMessageError_with_LastError("Can not create symbolic link", fullProcessedPath)); + RINOK(SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath)); } } } @@ -1304,7 +1312,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) { if (!MyCreateHardLink(fullProcessedPath, hl)) { - RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, hl)); + RINOK(SendMessageError2(kCantCreateHardLink, fullProcessedPath, hl)); return S_OK; } needWriteFile = false; @@ -1323,11 +1331,24 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) { // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) { - RINOK(SendMessageError_with_LastError("Can not open output file", fullProcessedPath)); + RINOK(SendMessageError_with_LastError(kCantOpenOutFile, fullProcessedPath)); return S_OK; } } + if (_ntOptions.PreAllocateOutFile && !_isSplit && _curSizeDefined && _curSize > (1 << 12)) + { + // UInt64 ticks = GetCpuTicks(); + bool res = _outFileStreamSpec->File.SetLength(_curSize); + _fileLengthWasSet = res; + _outFileStreamSpec->File.SeekToBegin(); + // ticks = GetCpuTicks() - ticks; + // printf("\nticks = %10d\n", (unsigned)ticks); + if (!res) + { + RINOK(SendMessageError_with_LastError(kCantSetFileLen, fullProcessedPath)); + } + } #ifdef SUPPORT_ALT_STREAMS if (isRenamed && !_item.IsAltStream) @@ -1456,14 +1477,24 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes) if (_outFileStream) { + HRESULT hres = S_OK; _outFileStreamSpec->SetTime( (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL, (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL, (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL)); - _curSize = _outFileStreamSpec->ProcessedSize; + const UInt64 processedSize = _outFileStreamSpec->ProcessedSize; + if (_fileLengthWasSet && _curSize > processedSize) + { + bool res = _outFileStreamSpec->File.SetLength(processedSize); + _fileLengthWasSet = res; + if (!res) + hres = SendMessageError_with_LastError(kCantSetFileLen, us2fs(_item.Path)); + } + _curSize = processedSize; _curSizeDefined = true; RINOK(_outFileStreamSpec->Close()); _outFileStream.Release(); + RINOK(hres); } #ifdef _USE_SECURITY_CODE @@ -1525,23 +1556,19 @@ STDMETHODIMP CArchiveExtractCallback::ReportExtractResult(UInt32 indexType, UInt if (_folderArchiveExtractCallback2) { bool isEncrypted = false; - wchar_t temp[16]; - UString s2; - const wchar_t *s = NULL; + UString s; if (indexType == NArchive::NEventIndexType::kInArcIndex && index != (UInt32)(Int32)-1) { CReadArcItem item; RINOK(_arc->GetItem(index, item)); - s2 = item.Path; - s = s2; + s = item.Path; RINOK(Archive_GetItemBoolProp(_arc->Archive, index, kpidEncrypted, isEncrypted)); } else { - temp[0] = '#'; - ConvertUInt32ToString(index, temp + 1); - s = temp; + s = '#'; + s.Add_UInt32(index); // if (indexType == NArchive::NEventIndexType::kBlockIndex) {} } diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h index 7d4155fe..058ddbcf 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h @@ -57,6 +57,8 @@ struct CExtractNtOptions bool ReplaceColonForAltStream; bool WriteToAltStreamIfColon; + bool PreAllocateOutFile; + CExtractNtOptions(): ReplaceColonForAltStream(false), WriteToAltStreamIfColon(false) @@ -64,6 +66,13 @@ struct CExtractNtOptions SymLinks.Val = true; HardLinks.Val = true; AltStreams.Val = true; + + PreAllocateOutFile = + #ifdef _WIN32 + true; + #else + false; + #endif } }; @@ -201,6 +210,7 @@ class CArchiveExtractCallback: UInt32 _index; UInt64 _curSize; bool _curSizeDefined; + bool _fileLengthWasSet; COutFileStream *_outFileStreamSpec; CMyComPtr<ISequentialOutStream> _outFileStream; diff --git a/CPP/7zip/UI/Common/ArchiveName.cpp b/CPP/7zip/UI/Common/ArchiveName.cpp index 06d2ab80..a3a44ce2 100644 --- a/CPP/7zip/UI/Common/ArchiveName.cpp +++ b/CPP/7zip/UI/Common/ArchiveName.cpp @@ -29,7 +29,7 @@ UString CreateArchiveName(const NFind::CFileInfo &fi, bool keepName) static FString CreateArchiveName2(const FString &path, bool fromPrev, bool keepName) { - FString resultName = FTEXT("Archive"); + FString resultName ("Archive"); if (fromPrev) { FString dirPrefix; diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp index ecbacbc9..70d4ffd6 100644 --- a/CPP/7zip/UI/Common/Bench.cpp +++ b/CPP/7zip/UI/Common/Bench.cpp @@ -32,8 +32,6 @@ #include "../../../../C/Alloc.h" #include "../../../../C/CpuArch.h" -#include "../../../Windows/System.h" - #ifndef _7ZIP_ST #include "../../../Windows/Synchronization.h" #include "../../../Windows/Thread.h" @@ -1200,10 +1198,9 @@ static HRESULT MethodBench( if (oldLzmaBenchMode && methodId == k_LZMA) { - bool fixedNumber; - UInt32 numLzmaThreads = method.Get_Lzma_NumThreads(fixedNumber); - if (!fixedNumber && numThreads == 1) + if (numThreads == 1 && method.Get_NumThreads() < 0) method.AddProp_NumThreads(1); + const UInt32 numLzmaThreads = method.Get_Lzma_NumThreads(); if (numThreads > 1 && numLzmaThreads > 1) { numEncoderThreads = numThreads / 2; @@ -1858,6 +1855,37 @@ static void PrintTotals(IBenchPrintCallback &f, bool showFreq, UInt64 cpuFreq, c PrintResults(f, res.Usage / numIterations2, res.RPU / numIterations2, res.Rating / numIterations2, showFreq, cpuFreq); } + +static void PrintHex(AString &s, UInt64 v) +{ + char temp[32]; + ConvertUInt64ToHex(v, temp); + s += temp; +} + +AString GetProcessThreadsInfo(const NSystem::CProcessAffinity &ti) +{ + AString s; + // s.Add_UInt32(ti.numProcessThreads); + if (ti.processAffinityMask != ti.systemAffinityMask) + { + // if (ti.numProcessThreads != ti.numSysThreads) + { + s += " / "; + s.Add_UInt32(ti.GetNumSystemThreads()); + } + s += " : "; + PrintHex(s, ti.processAffinityMask); + s += " / "; + PrintHex(s, ti.systemAffinityMask); + } + return s; +} + + +extern bool g_LargePagesMode; + + static void PrintRequirements(IBenchPrintCallback &f, const char *sizeString, bool size_Defined, UInt64 size, const char *threadsString, UInt32 numThreads) { @@ -1867,12 +1895,16 @@ static void PrintRequirements(IBenchPrintCallback &f, const char *sizeString, PrintNumber(f, (size >> 20), 6); else f.Print(" ?"); - f.Print(" MB, # "); + f.Print(" MB"); + if (g_LargePagesMode) + f.Print(" LP"); + f.Print(", # "); f.Print(threadsString); PrintNumber(f, numThreads, 3); - f.NewLine(); } + + struct CBenchCallbackToPrint: public IBenchCallback { CBenchProps BenchProps; @@ -1930,7 +1962,7 @@ HRESULT CBenchCallbackToPrint::SetEncodeResult(const CBenchInfo &info, bool fina return S_OK; } -static const char *kSep = " | "; +static const char * const kSep = " | "; HRESULT CBenchCallbackToPrint::SetDecodeResult(const CBenchInfo &info, bool final) { @@ -2147,7 +2179,7 @@ static HRESULT CrcBench( numThreads = 1; #endif - AString methodName = method.MethodName; + const AString &methodName = method.MethodName; // methodName.RemoveChar(L'-'); CMethodId hashID; if (!FindHashMethod( @@ -2410,6 +2442,240 @@ static void x86cpuid_to_String(const Cx86cpuid &c, AString &s) #endif + +static const char * const k_PROCESSOR_ARCHITECTURE[] = +{ + "x86" // "INTEL" + , "MIPS" + , "ALPHA" + , "PPC" + , "SHX" + , "ARM" + , "IA64" + , "ALPHA64" + , "MSIL" + , "x64" // "AMD64" + , "IA32_ON_WIN64" + , "NEUTRAL" + , "ARM64" + , "ARM32_ON_WIN64" +}; + +#define MY__PROCESSOR_ARCHITECTURE_INTEL 0 +#define MY__PROCESSOR_ARCHITECTURE_AMD64 9 + + +#define MY__PROCESSOR_INTEL_PENTIUM 586 +#define MY__PROCESSOR_AMD_X8664 8664 + +/* +static const CUInt32PCharPair k_PROCESSOR[] = +{ + { 2200, "IA64" }, + { 8664, "x64" } +}; + +#define PROCESSOR_INTEL_386 386 +#define PROCESSOR_INTEL_486 486 +#define PROCESSOR_INTEL_PENTIUM 586 +#define PROCESSOR_INTEL_860 860 +#define PROCESSOR_INTEL_IA64 2200 +#define PROCESSOR_AMD_X8664 8664 +#define PROCESSOR_MIPS_R2000 2000 +#define PROCESSOR_MIPS_R3000 3000 +#define PROCESSOR_MIPS_R4000 4000 +#define PROCESSOR_ALPHA_21064 21064 +#define PROCESSOR_PPC_601 601 +#define PROCESSOR_PPC_603 603 +#define PROCESSOR_PPC_604 604 +#define PROCESSOR_PPC_620 620 +#define PROCESSOR_HITACHI_SH3 10003 +#define PROCESSOR_HITACHI_SH3E 10004 +#define PROCESSOR_HITACHI_SH4 10005 +#define PROCESSOR_MOTOROLA_821 821 +#define PROCESSOR_SHx_SH3 103 +#define PROCESSOR_SHx_SH4 104 +#define PROCESSOR_STRONGARM 2577 // 0xA11 +#define PROCESSOR_ARM720 1824 // 0x720 +#define PROCESSOR_ARM820 2080 // 0x820 +#define PROCESSOR_ARM920 2336 // 0x920 +#define PROCESSOR_ARM_7TDMI 70001 +#define PROCESSOR_OPTIL 18767 // 0x494f +*/ + +#ifdef _WIN32 + +static const char * const k_PF[] = +{ + "FP_ERRATA" + , "FP_EMU" + , "CMPXCHG" + , "MMX" + , "PPC_MOVEMEM_64BIT" + , "ALPHA_BYTE" + , "SSE" + , "3DNOW" + , "RDTSC" + , "PAE" + , "SSE2" + , "SSE_DAZ" + , "NX" + , "SSE3" + , "CMPXCHG16B" + , "CMP8XCHG16" + , "CHANNELS" + , "XSAVE" + , "ARM_VFP_32" + , "ARM_NEON" + , "L2AT" + , "VIRT_FIRMWARE" + , "RDWRFSGSBASE" + , "FASTFAIL" + , "ARM_DIVIDE" + , "ARM_64BIT_LOADSTORE_ATOMIC" + , "ARM_EXTERNAL_CACHE" + , "ARM_FMAC" + , "RDRAND" + , "ARM_V8" + , "ARM_V8_CRYPTO" + , "ARM_V8_CRC32" + , "RDTSCP" +}; + +#endif + + +static void PrintSize(AString &s, UInt64 ptr) +{ + UInt64 v = ptr; + UInt64 t = v >> 40; + UInt64 g = v >> 30; + UInt64 m = v >> 20; + UInt64 k = v >> 10; + UInt32 d = (UInt32)v; + char c = 0; + if (t >= 1000) { d = (UInt32)t; c = 'T'; } + else if (g >= 1000) { d = (UInt32)g; c = 'G'; } + else if (m >= 1000) { d = (UInt32)m; c = 'M'; } + else if (k >= 10) { d = (UInt32)k; c = 'K'; } + + s.Add_UInt32(d); + // s += ' '; + if (c) + s += c; + + + // PrintHex(s, (DWORD_PTR)v); +} + + +static void PrintPage(AString &s, UInt32 v) +{ + if ((v & 0x3FF) == 0) + { + s.Add_UInt32(v >> 10); + s += "K"; + } + else + s.Add_UInt32(v >> 10); +} + +static AString TypeToString2(const char * const table[], unsigned num, UInt32 value) +{ + char sz[16]; + const char *p = NULL; + if (value < num) + p = table[value]; + if (!p) + { + ConvertUInt32ToString(value, sz); + p = sz; + } + return (AString)p; +} + +#ifdef _WIN32 + +static void SysInfo_To_String(AString &s, const SYSTEM_INFO &si) +{ + s += TypeToString2(k_PROCESSOR_ARCHITECTURE, ARRAY_SIZE(k_PROCESSOR_ARCHITECTURE), si.wProcessorArchitecture); + + if (!( si.wProcessorArchitecture == MY__PROCESSOR_ARCHITECTURE_INTEL && si.dwProcessorType == MY__PROCESSOR_INTEL_PENTIUM + || si.wProcessorArchitecture == MY__PROCESSOR_ARCHITECTURE_AMD64 && si.dwProcessorType == MY__PROCESSOR_AMD_X8664)) + { + s += " "; + // s += TypePairToString(k_PROCESSOR, ARRAY_SIZE(k_PROCESSOR), si.dwProcessorType); + s.Add_UInt32(si.dwProcessorType); + } + s += " "; + PrintHex(s, si.wProcessorLevel); + s += "."; + PrintHex(s, si.wProcessorRevision); + if (si.dwActiveProcessorMask + 1 != ((UInt64)1 << si.dwNumberOfProcessors)) + { + s += " act:"; + PrintHex(s, si.dwActiveProcessorMask); + } + s += " cpus:"; + s.Add_UInt32(si.dwNumberOfProcessors); + if (si.dwPageSize != 1 << 12) + { + s += " page:"; + PrintPage(s, si.dwPageSize); + } + if (si.dwAllocationGranularity != 1 << 16) + { + s += " gran:"; + PrintPage(s, si.dwAllocationGranularity); + } + s += " "; + + DWORD_PTR minAdd = (DWORD_PTR)si.lpMinimumApplicationAddress; + if (minAdd != (1 << 16)) + { + PrintSize(s, minAdd); + s += "-"; + } + PrintSize(s, (UInt64)(DWORD_PTR)si.lpMaximumApplicationAddress + 1); +} + +#ifndef _WIN64 +typedef VOID (WINAPI *Func_GetNativeSystemInfo)(LPSYSTEM_INFO lpSystemInfo); +#endif + +#endif + +void GetSysInfo(AString &s1, AString &s2) +{ + s1.Empty(); + s2.Empty(); + + #ifdef _WIN32 + SYSTEM_INFO si; + GetSystemInfo(&si); + { + SysInfo_To_String(s1, si); + // s += " : "; + } + + #if !defined(_WIN64) && !defined(UNDER_CE) + Func_GetNativeSystemInfo fn_GetNativeSystemInfo = (Func_GetNativeSystemInfo)GetProcAddress( + GetModuleHandleA("kernel32.dll"), "GetNativeSystemInfo"); + if (fn_GetNativeSystemInfo) + { + SYSTEM_INFO si2; + fn_GetNativeSystemInfo(&si2); + // if (memcmp(&si, &si2, sizeof(si)) != 0) + { + // s += " - "; + SysInfo_To_String(s2, si2); + } + } + #endif + #endif +} + + void GetCpuName(AString &s) { s.Empty(); @@ -2419,31 +2685,53 @@ void GetCpuName(AString &s) Cx86cpuid cpuid; if (x86cpuid_CheckAndRead(&cpuid)) { - x86cpuid_to_String(cpuid, s); + AString s2; + x86cpuid_to_String(cpuid, s2); + s += s2; return; } #ifdef MY_CPU_AMD64 - s = "x64"; + s += "x64"; #else - s = "x86"; + s += "x86"; #endif } #else #ifdef MY_CPU_LE - s = "LE"; + s += "LE"; #elif defined(MY_CPU_BE) - s = "BE"; + s += "BE"; #endif #endif } +void GetCpuFeatures(AString &s) +{ + s.Empty(); + + #ifdef _WIN32 + const unsigned kNumFeatures_Extra = 32; // we check also for unknown features + const unsigned kNumFeatures = ARRAY_SIZE(k_PF) + kNumFeatures_Extra; + for (unsigned i = 0; i < kNumFeatures; i++) + { + if (IsProcessorFeaturePresent(i)) + { + s.Add_Space_if_NotEmpty(); + s += TypeToString2(k_PF, ARRAY_SIZE(k_PF), i); + } + } + #endif +} + + HRESULT Bench( DECL_EXTERNAL_CODECS_LOC_VARS IBenchPrintCallback *printCallback, IBenchCallback *benchCallback, + // IBenchFreqCallback *freqCallback, const CObjectVector<CProperty> &props, UInt32 numIterations, bool multiDict) @@ -2454,8 +2742,16 @@ HRESULT Bench( UInt32 numCPUs = 1; UInt64 ramSize = (UInt64)(sizeof(size_t)) << 29; + NSystem::CProcessAffinity threadsInfo; + threadsInfo.InitST(); + #ifndef _7ZIP_ST - numCPUs = NSystem::GetNumberOfProcessors(); + + if (threadsInfo.Get() && threadsInfo.processAffinityMask != 0) + numCPUs = threadsInfo.GetNumProcessThreads(); + else + numCPUs = NSystem::GetNumberOfProcessors(); + #endif bool ramSize_Defined = NSystem::GetRamSize(ramSize); @@ -2477,7 +2773,7 @@ HRESULT Bench( for (i = 0; i < props.Size(); i++) { const CProperty &property = props[i]; - UString name = property.Name; + UString name (property.Name); name.MakeLower_Ascii(); if (name.IsEqualTo("file")) @@ -2504,7 +2800,6 @@ HRESULT Bench( if (printCallback) { printCallback->Print("file size ="); - // printCallback->Print(GetOemString(property.Value)); PrintNumber(*printCallback, len, 0); printCallback->NewLine(); } @@ -2523,14 +2818,14 @@ HRESULT Bench( if (name.IsEqualTo("time")) { - RINOK(ParsePropToUInt32(L"", propVariant, testTime)); + RINOK(ParsePropToUInt32(UString(), propVariant, testTime)); continue; } if (name.IsEqualTo("freq")) { UInt32 freq32 = 0; - RINOK(ParsePropToUInt32(L"", propVariant, freq32)); + RINOK(ParsePropToUInt32(UString(), propVariant, freq32)); if (freq32 == 0) return E_INVALIDARG; specifiedFreq = (UInt64)freq32 * 1000000; @@ -2548,19 +2843,12 @@ HRESULT Bench( if (name.IsPrefixedBy_Ascii_NoCase("mt")) { UString s = name.Ptr(2); - if (s == L"*") + if (s.IsEqualTo("*") + || s.IsEmpty() && propVariant.vt == VT_BSTR && StringsAreEqual_Ascii(propVariant.bstrVal, "*")) { multiThreadTests = true; continue; } - if (s.IsEmpty() && propVariant.vt == VT_BSTR) - { - if (wcscmp(propVariant.bstrVal, L"*") == 0) - { - multiThreadTests = true; - continue; - } - } #ifndef _7ZIP_ST RINOK(ParseMtProp(s, propVariant, numCPUs, numThreadsSpecified)); #endif @@ -2573,10 +2861,38 @@ HRESULT Bench( if (printCallback) { - AString s; - GetCpuName(s); - printCallback->Print(s); - printCallback->NewLine(); + { + AString s1, s2; + GetSysInfo(s1, s2); + if (!s1.IsEmpty() || !s2.IsEmpty()) + { + printCallback->Print(s1); + if (s1 != s2 && !s2.IsEmpty()) + { + printCallback->Print(" - "); + printCallback->Print(s2); + } + printCallback->NewLine(); + } + } + { + AString s; + GetCpuFeatures(s); + if (!s.IsEmpty()) + { + printCallback->Print(s); + printCallback->NewLine(); + } + } + { + AString s; + GetCpuName(s); + if (!s.IsEmpty()) + { + printCallback->Print(s); + printCallback->NewLine(); + } + } } if (printCallback) @@ -2586,7 +2902,7 @@ HRESULT Bench( UInt64 complexInCommands = kComplexInCommands; - if (printCallback /* || benchCallback */) + if (printCallback /* || freqCallback */) { UInt64 numMilCommands = 1 << 6; if (specifiedFreq != 0) @@ -2623,8 +2939,8 @@ HRESULT Bench( } } /* - if (benchCallback) - benchCallback->AddCpuFreq(mipsVal); + if (freqCallback) + freqCallback->AddCpuFreq(mipsVal); */ if (jj >= 3) @@ -2643,6 +2959,8 @@ HRESULT Bench( printCallback->NewLine(); printCallback->NewLine(); PrintRequirements(*printCallback, "size: ", ramSize_Defined, ramSize, "CPU hardware threads:", numCPUs); + printCallback->Print(GetProcessThreadsInfo(threadsInfo)); + printCallback->NewLine(); } if (numThreadsSpecified < 1 || numThreadsSpecified > kNumThreadsMax) @@ -2669,7 +2987,7 @@ HRESULT Bench( kOldLzmaDictBits, printCallback, benchCallback, &benchProps); } - AString methodName = method.MethodName; + AString methodName (method.MethodName); if (methodName.IsEqualTo_Ascii_NoCase("CRC")) methodName = "crc32"; method.MethodName = methodName; @@ -2691,7 +3009,7 @@ HRESULT Bench( for (unsigned i = 0; i < ARRAY_SIZE(g_Hash); i++) { const CBenchHash &h = g_Hash[i]; - AString s = h.Name; + AString s (h.Name); AString hProp; int propPos = s.Find(':'); if (propPos >= 0) @@ -2852,6 +3170,7 @@ HRESULT Bench( } PrintRequirements(f, "usage:", true, GetBenchMemoryUsage(numThreads, dict, totalBenchMode), "Benchmark threads: ", numThreads); + f.NewLine(); f.NewLine(); @@ -3000,7 +3319,6 @@ HRESULT Bench( for (unsigned i = 0; i < ARRAY_SIZE(g_Bench); i++) { const CBenchMethod &h = g_Bench[i]; - AString s = h.Name; if (AreSameMethodNames(h.Name, methodName)) { callback.BenchProps.EncComplex = h.EncComplex; @@ -3040,7 +3358,7 @@ HRESULT Bench( // method2 can have two different dictionary size properties. // And last property is main. NCOM::CPropVariant propVariant = (UInt32)pow; - RINOK(method2.ParseMethodFromPROPVARIANT(L"d", propVariant)); + RINOK(method2.ParseMethodFromPROPVARIANT((UString)"d", propVariant)); } size_t uncompressedDataSize; diff --git a/CPP/7zip/UI/Common/Bench.h b/CPP/7zip/UI/Common/Bench.h index 841250ef..ec51faee 100644 --- a/CPP/7zip/UI/Common/Bench.h +++ b/CPP/7zip/UI/Common/Bench.h @@ -3,6 +3,8 @@ #ifndef __7ZIP_BENCH_H #define __7ZIP_BENCH_H +#include "../../../Windows/System.h" + #include "../../Common/CreateCoder.h" #include "../../UI/Common/Property.h" @@ -43,13 +45,28 @@ struct IBenchPrintCallback virtual HRESULT CheckBreak() = 0; }; +/* +struct IBenchFreqCallback +{ + virtual void AddCpuFreq(UInt64 freq) = 0; +}; +*/ + HRESULT Bench( DECL_EXTERNAL_CODECS_LOC_VARS IBenchPrintCallback *printCallback, IBenchCallback *benchCallback, + // IBenchFreqCallback *freqCallback, const CObjectVector<CProperty> &props, UInt32 numIterations, bool multiDict ); +AString GetProcessThreadsInfo(const NWindows::NSystem::CProcessAffinity &ti); + +void GetSysInfo(AString &s1, AString &s2); +void GetCpuName(AString &s); +void GetCpuFeatures(AString &s); + + #endif diff --git a/CPP/7zip/UI/Common/CompressCall.cpp b/CPP/7zip/UI/Common/CompressCall.cpp index 37da9d1a..6439dfb9 100644 --- a/CPP/7zip/UI/Common/CompressCall.cpp +++ b/CPP/7zip/UI/Common/CompressCall.cpp @@ -30,24 +30,24 @@ using namespace NWindows; #define MY_TRY_FINISH_VOID } \ catch(...) { ErrorMessageHRESULT(E_FAIL); } -static const char *k7zGui = "7zG.exe"; +#define 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-"; +#define kShowDialogSwitch " -ad" +#define kEmailSwitch " -seml." +#define kIncludeSwitch " -i" +#define kArchiveTypeSwitch " -t" +#define kArcIncludeSwitches " -an -ai" +#define kHashIncludeSwitches " -i" +#define kStopSwitchParsing " --" +#define kLargePagesDisable " -slp-" extern HWND g_HWND; UString GetQuotedString(const UString &s) { - UString s2 = L'\"'; + UString s2 ('\"'); s2 += s; - s2 += L'\"'; + s2 += '\"'; return s2; } @@ -73,7 +73,7 @@ static HRESULT Call7zGui(const UString ¶ms, NSynchronization::CBaseEvent *event) { UString imageName = fs2us(NWindows::NDLL::GetModuleDirPrefix()); - imageName.AddAscii(k7zGui); + imageName += k7zGui; CProcess process; WRes res = process.Create(imageName, params, NULL); // curDir); @@ -95,7 +95,7 @@ static HRESULT Call7zGui(const UString ¶ms, static void AddLagePagesSwitch(UString ¶ms) { if (!ReadLockMemoryEnable()) - params.AddAscii(kLargePagesDisable); + params += kLargePagesDisable; } class CRandNameGenerator @@ -105,10 +105,8 @@ public: CRandNameGenerator() { _random.Init(); } void GenerateName(UString &s, const char *prefix) { - s.AddAscii(prefix); - char temp[16]; - ConvertUInt32ToString((UInt32)(unsigned)_random.Generate(), temp); - s.AddAscii(temp); + s += prefix; + s.Add_UInt32((UInt32)(unsigned)_random.Generate()); } }; @@ -150,14 +148,14 @@ static HRESULT CreateMap(const UStringVector &names, event.Close(); } - params += L'#'; + params += '#'; params += mappingName; - params += L':'; + params += ':'; char temp[32]; ConvertUInt64ToString(totalSize, temp); - params.AddAscii(temp); + params += temp; - params += L':'; + params += ':'; params += eventName; LPVOID data = fileMapping.Map(FILE_MAP_WRITE, 0, totalSize); @@ -187,36 +185,36 @@ HRESULT CompressFiles( bool email, bool showDialog, bool waitFinish) { MY_TRY_BEGIN - UString params = L'a'; + UString params ('a'); CFileMapping fileMapping; NSynchronization::CManualResetEvent event; - params.AddAscii(kIncludeSwitch); + params += kIncludeSwitch; RINOK(CreateMap(names, fileMapping, event, params)); if (!arcType.IsEmpty()) { - params.AddAscii(kArchiveTypeSwitch); + params += kArchiveTypeSwitch; params += arcType; } if (email) - params.AddAscii(kEmailSwitch); + params += kEmailSwitch; if (showDialog) - params.AddAscii(kShowDialogSwitch); + params += kShowDialogSwitch; AddLagePagesSwitch(params); if (arcName.IsEmpty()) - params.AddAscii(" -an"); + params += " -an"; if (addExtension) - params.AddAscii(" -saa"); + params += " -saa"; else - params.AddAscii(" -sae"); + params += " -sae"; - params.AddAscii(kStopSwitchParsing); + params += kStopSwitchParsing; params.Add_Space(); if (!arcName.IsEmpty()) @@ -237,7 +235,7 @@ HRESULT CompressFiles( static void ExtractGroupCommand(const UStringVector &arcPaths, UString ¶ms, bool isHash) { AddLagePagesSwitch(params); - params.AddAscii(isHash ? kHashIncludeSwitches : kArcIncludeSwitches); + params += (isHash ? kHashIncludeSwitches : kArcIncludeSwitches); CFileMapping fileMapping; NSynchronization::CManualResetEvent event; HRESULT result = CreateMap(arcPaths, fileMapping, event, params); @@ -250,16 +248,16 @@ static void ExtractGroupCommand(const UStringVector &arcPaths, UString ¶ms, void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup) { MY_TRY_BEGIN - UString params = L'x'; + UString params ('x'); if (!outFolder.IsEmpty()) { - params.AddAscii(" -o"); + params += " -o"; params += GetQuotedString(outFolder); } if (elimDup) - params.AddAscii(" -spe"); + params += " -spe"; if (showDialog) - params.AddAscii(kShowDialogSwitch); + params += kShowDialogSwitch; ExtractGroupCommand(arcPaths, params, false); MY_TRY_FINISH_VOID } @@ -267,7 +265,7 @@ void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bo void TestArchives(const UStringVector &arcPaths) { MY_TRY_BEGIN - UString params = L't'; + UString params ('t'); ExtractGroupCommand(arcPaths, params, false); MY_TRY_FINISH_VOID } @@ -275,10 +273,10 @@ void TestArchives(const UStringVector &arcPaths) void CalcChecksum(const UStringVector &paths, const UString &methodName) { MY_TRY_BEGIN - UString params = L'h'; + UString params ('h'); if (!methodName.IsEmpty()) { - params.AddAscii(" -scrc"); + params += " -scrc"; params += methodName; } ExtractGroupCommand(paths, params, true); @@ -288,7 +286,10 @@ void CalcChecksum(const UStringVector &paths, const UString &methodName) void Benchmark(bool totalMode) { MY_TRY_BEGIN - HRESULT result = Call7zGui(totalMode ? L"b -mm=*" : L"b", false, NULL); + UString params ('b'); + if (totalMode) + params += " -mm=*"; + HRESULT result = Call7zGui(params, 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 b3421e5a..fb67ed12 100644 --- a/CPP/7zip/UI/Common/CompressCall2.cpp +++ b/CPP/7zip/UI/Common/CompressCall2.cpp @@ -59,9 +59,9 @@ static void ThrowException_if_Error(HRESULT res) UString GetQuotedString(const UString &s) { - UString s2 = L'\"'; + UString s2 ('\"'); s2 += s; - s2 += L'\"'; + s2 += '\"'; return s2; } @@ -145,6 +145,7 @@ HRESULT CompressFiles( return S_OK; } + static HRESULT ExtractGroupCommand(const UStringVector &arcPaths, bool showDialog, const UString &outFolder, bool testMode, bool elimDup = false) { @@ -192,10 +193,14 @@ static HRESULT ExtractGroupCommand(const UStringVector &arcPaths, censor.AddPathsToCensor(NWildcard::k_RelatPath); bool messageWasDisplayed = false; + + ecs->MultiArcMode = (arcPathsSorted.Size() > 1); + result = ExtractGUI(codecs, formatIndices, CIntVector(), arcPathsSorted, arcFullPathsSorted, censor.Pairs.Front().Head, eo, NULL, showDialog, messageWasDisplayed, ecs, g_HWND); + if (result != S_OK) { if (result != E_ABORT && messageWasDisplayed) @@ -260,8 +265,8 @@ void Benchmark(bool totalMode) if (totalMode) { CProperty prop; - prop.Name = L"m"; - prop.Value = L"*"; + prop.Name = "m"; + prop.Value = "*"; props.Add(prop); } result = Benchmark(EXTERNAL_CODECS_VARS_L props, g_HWND); diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h index 4286b4e8..67e492d8 100644 --- a/CPP/7zip/UI/Common/DirItem.h +++ b/CPP/7zip/UI/Common/DirItem.h @@ -20,9 +20,18 @@ struct CDirItemsStat UInt64 AltStreamsSize; UInt64 NumErrors; - // UInt64 GetTotalItems() const { return NumDirs + NumFiles + NumAltStreams; } + UInt64 Get_NumItems() const { return NumDirs + NumFiles + NumAltStreams; } + UInt64 Get_NumDataItems() const { return NumFiles + NumAltStreams; } UInt64 GetTotalBytes() const { return FilesSize + AltStreamsSize; } + + bool IsEmpty() const { return + 0 == NumDirs + && 0 == NumFiles + && 0 == NumAltStreams + && 0 == FilesSize + && 0 == AltStreamsSize + && 0 == NumErrors; } CDirItemsStat(): NumDirs(0), diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp index 3ebf25aa..28887614 100644 --- a/CPP/7zip/UI/Common/EnumDirItems.cpp +++ b/CPP/7zip/UI/Common/EnumDirItems.cpp @@ -213,7 +213,8 @@ HRESULT CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phy { RINOK(ScanProgress(phyPrefix)); - NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK); + NFind::CEnumerator enumerator; + enumerator.SetDirPrefix(phyPrefix); for (unsigned ttt = 0; ; ttt++) { NFind::CFileInfo fi; @@ -570,7 +571,7 @@ static HRESULT EnumerateDirItems( #endif */ - fullPath = FCHAR_PATH_SEPARATOR; + fullPath = CHAR_PATH_SEPARATOR; } #if defined(_WIN32) && !defined(UNDER_CE) else if (item.IsDriveItem()) @@ -682,7 +683,7 @@ static HRESULT EnumerateDirItems( { { if (nextNode.Name.IsEmpty()) - fullPath = FCHAR_PATH_SEPARATOR; + fullPath = CHAR_PATH_SEPARATOR; #ifdef _WIN32 else if (NWildcard::IsDriveColonName(nextNode.Name)) fullPath.Add_PathSepar(); @@ -773,7 +774,9 @@ static HRESULT EnumerateDirItems( #endif #endif - NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK); + NFind::CEnumerator enumerator; + enumerator.SetDirPrefix(phyPrefix); + for (unsigned ttt = 0; ; ttt++) { NFind::CFileInfo fi; diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp index 3da0aadb..e92c988e 100644 --- a/CPP/7zip/UI/Common/Extract.cpp +++ b/CPP/7zip/UI/Common/Extract.cpp @@ -51,7 +51,7 @@ static HRESULT DecompressArchive( replaceName = arc0.DefaultName; } - outDir.Replace(FSTRING_ANY_MASK, us2fs(Get_Correct_FsFile_Name(replaceName))); + outDir.Replace(FString("*"), us2fs(Get_Correct_FsFile_Name(replaceName))); bool elimIsPossible = false; UString elimPrefix; // only pure name without dir delimiter @@ -156,7 +156,7 @@ static HRESULT DecompressArchive( #endif if (outDir.IsEmpty()) - outDir = FTEXT(".") FSTRING_PATH_SEPARATOR; + outDir = "." STRING_PATH_SEPARATOR; /* #ifdef _WIN32 else if (NName::IsAltPathPrefix(outDir)) {} @@ -167,7 +167,7 @@ static HRESULT DecompressArchive( HRESULT res = ::GetLastError(); if (res == S_OK) res = E_FAIL; - errorMessage.SetFromAscii("Can not create output directory: "); + errorMessage = "Can not create output directory: "; errorMessage += fs2us(outDir); return res; } diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp index 39e67b7f..e92badec 100644 --- a/CPP/7zip/UI/Common/ExtractingFilePath.cpp +++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp @@ -8,6 +8,15 @@ #include "ExtractingFilePath.h" +bool g_PathTrailReplaceMode = + #ifdef _WIN32 + true + #else + false + #endif + ; + + static void ReplaceIncorrectChars(UString &s) { { @@ -26,17 +35,42 @@ static void ReplaceIncorrectChars(UString &s) } } - #ifdef _WIN32 + if (g_PathTrailReplaceMode) { - for (unsigned i = s.Len(); i != 0;) + /* + // if (g_PathTrailReplaceMode == 1) { - wchar_t c = s[--i]; - if (c != '.' && c != ' ') - break; - s.ReplaceOneCharAtPos(i, '_'); + if (!s.IsEmpty()) + { + wchar_t c = s.Back(); + if (c == '.' || c == ' ') + { + // s += (wchar_t)(0x9c); // STRING TERMINATOR + s += (wchar_t)'_'; + } + } + } + else + */ + { + unsigned i; + for (i = s.Len(); i != 0;) + { + wchar_t c = s[i - 1]; + if (c != '.' && c != ' ') + break; + i--; + s.ReplaceOneCharAtPos(i, '_'); + // s.ReplaceOneCharAtPos(i, (c == ' ' ? (wchar_t)(0x2423) : (wchar_t)0x00B7)); + } + /* + if (g_PathTrailReplaceMode > 1 && i != s.Len()) + { + s.DeleteFrom(i); + } + */ } } - #endif } #ifdef _WIN32 @@ -61,7 +95,7 @@ void Correct_AltStream_Name(UString &s) s.ReplaceOneCharAtPos(i, '_'); } if (s.IsEmpty()) - s = L'_'; + s = '_'; } static const unsigned g_ReservedWithNum_Index = 4; @@ -120,8 +154,8 @@ static void Correct_PathPart(UString &s) #endif } -// static const wchar_t *k_EmptyReplaceName = L"[]"; -static const wchar_t k_EmptyReplaceName = L'_'; +// static const char * const k_EmptyReplaceName = "[]"; +static const char k_EmptyReplaceName = '_'; UString Get_Correct_FsFile_Name(const UString &name) { @@ -176,11 +210,11 @@ void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir) if (isDrive) { // we convert "c:name" to "c:\name", if absIsAllowed path. - const UString &ds = parts[i - 1]; - if (ds.Len() != 2) + UString &ds = parts[i - 1]; + if (ds.Len() > 2) { - UString s = ds.Ptr(2); - parts.Insert(i, s); + parts.Insert(i, ds.Ptr(2)); + ds.DeleteFrom(2); } } #endif @@ -214,7 +248,7 @@ void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir) if (!isDir) { if (parts.IsEmpty()) - parts.Add(k_EmptyReplaceName); + parts.Add((UString)k_EmptyReplaceName); else { UString &s = parts.Back(); diff --git a/CPP/7zip/UI/Common/HashCalc.cpp b/CPP/7zip/UI/Common/HashCalc.cpp index 60a747d5..46a69de1 100644 --- a/CPP/7zip/UI/Common/HashCalc.cpp +++ b/CPP/7zip/UI/Common/HashCalc.cpp @@ -30,17 +30,13 @@ public: ~CHashMidBuf() { ::MidFree(_data); } }; -static const char *k_DefaultHashMethod = "CRC32"; +static const char * const k_DefaultHashMethod = "CRC32"; HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &hashMethods) { UStringVector names = hashMethods; if (names.IsEmpty()) - { - UString s; - s.SetFromAscii(k_DefaultHashMethod); - names.Add(s); - } + names.Add(UString(k_DefaultHashMethod)); CRecordVector<CMethodId> ids; CObjectVector<COneMethodInfo> methods; diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp index 5435499b..f1334613 100644 --- a/CPP/7zip/UI/Common/LoadCodecs.cpp +++ b/CPP/7zip/UI/Common/LoadCodecs.cpp @@ -81,7 +81,7 @@ using namespace NFile; #define kFormatsFolderName FTEXT("Formats") -static CFSTR kMainDll = +static CFSTR const kMainDll = // #ifdef _WIN32 FTEXT("7z.dll"); // #else @@ -91,9 +91,9 @@ static CFSTR kMainDll = #ifdef _WIN32 -static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip"); -static LPCWSTR kProgramPathValue = L"Path"; -static LPCWSTR kProgramPath2Value = L"Path" +static LPCTSTR const kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip"); +static LPCWSTR const kProgramPathValue = L"Path"; +static LPCWSTR const kProgramPath2Value = L"Path" #ifdef _WIN64 L"64"; #else @@ -516,12 +516,11 @@ HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loaded } lib.CreateObject = (Func_CreateObject)lib.Lib.GetProc("CreateObject"); - if (lib.CreateObject) { unsigned startSize = Codecs.Size() + Hashers.Size(); res = LoadCodecs(); used = (startSize != Codecs.Size() + Hashers.Size()); - if (res == S_OK) + if (res == S_OK && lib.CreateObject) { startSize = Formats.Size(); res = LoadFormats(); @@ -539,7 +538,8 @@ HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loaded HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPrefix) { - NFile::NFind::CEnumerator enumerator(folderPrefix + FCHAR_ANY_MASK); + NFile::NFind::CEnumerator enumerator; + enumerator.SetDirPrefix(folderPrefix); NFile::NFind::CFileInfo fi; while (enumerator.Next(fi)) { @@ -595,7 +595,7 @@ HRESULT CCodecs::Load() const CArcInfo &arc = *g_Arcs[i]; CArcInfoEx item; - item.Name.SetFromAscii(arc.Name); + item.Name = arc.Name; item.CreateInArchive = arc.CreateInArchive; item.IsArcFunc = arc.IsArc; item.Flags = arc.Flags; @@ -603,9 +603,9 @@ HRESULT CCodecs::Load() { UString e, ae; if (arc.Ext) - e.SetFromAscii(arc.Ext); + e = arc.Ext; if (arc.AddExt) - ae.SetFromAscii(arc.AddExt); + ae = arc.AddExt; item.AddExts(e, ae); } @@ -866,7 +866,8 @@ STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder) const CCodecLib &lib = Libs[ci.LibIndex]; if (lib.CreateDecoder) return lib.CreateDecoder(ci.CodecIndex, iid, (void **)coder); - return lib.CreateObject(&ci.Decoder, iid, (void **)coder); + if (lib.CreateObject) + return lib.CreateObject(&ci.Decoder, iid, (void **)coder); } return S_OK; #else @@ -888,7 +889,8 @@ STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder) const CCodecLib &lib = Libs[ci.LibIndex]; if (lib.CreateEncoder) return lib.CreateEncoder(ci.CodecIndex, iid, (void **)coder); - return lib.CreateObject(&ci.Encoder, iid, (void **)coder); + if (lib.CreateObject) + return lib.CreateObject(&ci.Encoder, iid, (void **)coder); } return S_OK; #else diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp index bf3b982e..69817179 100644 --- a/CPP/7zip/UI/Common/OpenArchive.cpp +++ b/CPP/7zip/UI/Common/OpenArchive.cpp @@ -330,17 +330,17 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { case kpidPath: { - wchar_t sz[32]; + char sz[32]; ConvertUInt32ToString(index + 1, sz); - UString s = sz; + UString s(sz); if (!item.Name.IsEmpty()) { - s += L'.'; + s += '.'; s += item.Name; } if (!item.Extension.IsEmpty()) { - s += L'.'; + s += '.'; s += item.Extension; } prop = s; break; @@ -583,7 +583,7 @@ HRESULT CArc::GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &pa { { UString &s2 = parts[parts.Size() - 2]; - s2 += L':'; + s2 += ':'; s2 += parts.Back(); } parts.DeleteBack(); @@ -733,7 +733,7 @@ HRESULT CArc::GetDefaultItemPath(UInt32 index, UString &result) const RINOK(Archive->GetProperty(index, kpidExtension, &prop)); if (prop.vt == VT_BSTR) { - result += L'.'; + result += '.'; result += prop.bstrVal; } else if (prop.vt != VT_EMPTY) @@ -1020,10 +1020,11 @@ static void MakeCheckOrder(CCodecs *codecs, #ifdef UNDER_CE static const unsigned kNumHashBytes = 1; - #define HASH_VAL(buf, pos) ((buf)[pos]) + #define HASH_VAL(buf) ((buf)[0]) #else static const unsigned kNumHashBytes = 2; - #define HASH_VAL(buf, pos) ((buf)[pos] | ((UInt32)(buf)[pos + 1] << 8)) + // #define HASH_VAL(buf) ((buf)[0] | ((UInt32)(buf)[1] << 8)) + #define HASH_VAL(buf) GetUi16(buf) #endif @@ -2317,7 +2318,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) continue; } thereAreHandlersForSearch = true; - UInt32 v = HASH_VAL(sig, 0); + UInt32 v = HASH_VAL(sig); unsigned sigIndex = arc2sig[(unsigned)index] + k; prevs[sigIndex] = hash[v]; hash[v] = (Byte)sigIndex; @@ -2440,6 +2441,9 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) } } + if (bytesInBuf <= (size_t)posInBuf) + break; + bool useOffsetCallback = false; if (openCallback_Offset) { @@ -2489,17 +2493,19 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) scanSize++; const Byte *buf = byteBuffer + (size_t)posInBuf; + const Byte *bufLimit = buf + scanSize; size_t ppp = 0; if (!needCheckStartOpen) { - for (; ppp < scanSize && hash[HASH_VAL(buf, ppp)] == 0xFF; ppp++); + for (; buf < bufLimit && hash[HASH_VAL(buf)] == 0xFF; buf++); + ppp = buf - (byteBuffer + (size_t)posInBuf); pos += ppp; - if (ppp == scanSize) + if (buf == bufLimit) continue; } - UInt32 v = HASH_VAL(buf, ppp); + UInt32 v = HASH_VAL(buf); bool nextNeedCheckStartOpen = true; unsigned i = hash[v]; unsigned indexOfDifficult = 0; @@ -2539,7 +2545,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op) const CByteBuffer &sig = ai.Signatures[sigIndex]; if (ppp + sig.Size() > availSize - || !TestSignature(buf + ppp, sig, sig.Size())) + || !TestSignature(buf, sig, sig.Size())) continue; // printf("\nSignature OK: %10S %8x %5d", (const wchar_t *)ai.Name, (int)pos, (int)(pos - prevPos)); // prevPos = pos; @@ -2946,10 +2952,10 @@ HRESULT CArc::OpenStream(const COpenOptions &op) #ifdef _SFX #ifdef _WIN32 - static const char *k_ExeExt = ".exe"; + #define k_ExeExt ".exe" static const unsigned k_ExeExt_Len = 4; #else - static const char *k_ExeExt = ""; + #define k_ExeExt "" static const unsigned k_ExeExt_Len = 0; #endif @@ -3012,10 +3018,10 @@ HRESULT CArc::OpenStreamOrFile(COpenOptions &op) if (ai.IsSplit()) continue; UString path3 = path2; - path3 += L'.'; + path3 += '.'; path3 += ai.GetMainExt(); // "7z" for SFX. Path = path3; - Path.AddAscii(".001"); + Path += ".001"; bool isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path)); if (!isOk) { diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp index dccc08b1..4d0e98db 100644 --- a/CPP/7zip/UI/Common/PropIDUtils.cpp +++ b/CPP/7zip/UI/Common/PropIDUtils.cpp @@ -83,18 +83,17 @@ void ConvertWinAttribToString(char *s, UInt32 wa) throw() } } -void ConvertPropertyToShortString(char *dest, const PROPVARIANT &prop, PROPID propID, bool full) throw() +void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &prop, PROPID propID, int level) throw() { *dest = 0; if (prop.vt == VT_FILETIME) { - FILETIME localFileTime; - if ((prop.filetime.dwHighDateTime == 0 && - prop.filetime.dwLowDateTime == 0) || - !::FileTimeToLocalFileTime(&prop.filetime, &localFileTime)) + const FILETIME &ft = prop.filetime; + if ((ft.dwHighDateTime == 0 && + ft.dwLowDateTime == 0)) return; - ConvertFileTimeToString(localFileTime, dest, true, full); + ConvertUtcFileTimeToString(prop.filetime, dest, level); return; } @@ -158,7 +157,7 @@ void ConvertPropertyToShortString(char *dest, const PROPVARIANT &prop, PROPID pr ConvertPropVariantToShortString(prop, dest); } -void ConvertPropertyToString(UString &dest, const PROPVARIANT &prop, PROPID propID, bool full) +void ConvertPropertyToString2(UString &dest, const PROPVARIANT &prop, PROPID propID, int level) { if (prop.vt == VT_BSTR) { @@ -166,8 +165,8 @@ void ConvertPropertyToString(UString &dest, const PROPVARIANT &prop, PROPID prop return; } char temp[64]; - ConvertPropertyToShortString(temp, prop, propID, full); - dest.SetFromAscii(temp); + ConvertPropertyToShortString2(temp, prop, propID, level); + dest = temp; } static inline unsigned GetHex(unsigned v) @@ -349,13 +348,9 @@ static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize) } } - char sz[16]; s += "S-1-"; if (p[2] == 0 && p[3] == 0) - { - ConvertUInt32ToString(authority, sz); - s += sz; - } + s.Add_UInt32(authority); else { s += "0x"; @@ -365,8 +360,7 @@ static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize) for (UInt32 i = 0; i < num; i++) { s += '-'; - ConvertUInt32ToString(Get32(p + 8 + i * 4), sz); - s += sz; + s.Add_UInt32(Get32(p + 8 + i * 4)); } } @@ -536,11 +530,11 @@ bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s) if (attr.Parse(data, size)) { if (!attr.IsSymLink()) - s.AddAscii("Junction: "); + s += "Junction: "; s += attr.GetPath(); if (!attr.IsOkNamePair()) { - s.AddAscii(" : "); + s += " : "; s += attr.PrintName; } return true; @@ -557,7 +551,7 @@ bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s) char hex[16]; ConvertUInt32ToHex8Digits(tag, hex); - s.AddAscii(hex); + s += hex; s.Add_Space(); data += 8; @@ -565,8 +559,8 @@ bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s) for (UInt32 i = 0; i < len; i++) { unsigned b = ((const Byte *)data)[i]; - s += (wchar_t)GetHex((b >> 4) & 0xF); - s += (wchar_t)GetHex(b & 0xF); + s += (char)GetHex((b >> 4) & 0xF); + s += (char)GetHex(b & 0xF); } return true; } diff --git a/CPP/7zip/UI/Common/PropIDUtils.h b/CPP/7zip/UI/Common/PropIDUtils.h index 1dea321e..915bfc28 100644 --- a/CPP/7zip/UI/Common/PropIDUtils.h +++ b/CPP/7zip/UI/Common/PropIDUtils.h @@ -6,8 +6,8 @@ #include "../../../Common/MyString.h" // provide at least 64 bytes for buffer including zero-end -void ConvertPropertyToShortString(char *dest, const PROPVARIANT &propVariant, PROPID propID, bool full = true) throw(); -void ConvertPropertyToString(UString &dest, const PROPVARIANT &propVariant, PROPID propID, bool full = true); +void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0) throw(); +void ConvertPropertyToString2(UString &dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0); bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s); void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s); diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp index 0db4a87f..78f68f35 100644 --- a/CPP/7zip/UI/Common/Update.cpp +++ b/CPP/7zip/UI/Common/Update.cpp @@ -4,7 +4,6 @@ #include "Update.h" -#include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #include "../../../Windows/DLL.h" @@ -30,16 +29,19 @@ #include "TempFiles.h" #include "UpdateCallback.h" -static const char *kUpdateIsNotSupoorted = +static const char * const kUpdateIsNotSupoorted = "update operations are not supported for this archive"; +static const char * const kUpdateIsNotSupoorted_MultiVol = + "Updating for multivolume archives is not implemented"; + using namespace NWindows; using namespace NCOM; using namespace NFile; using namespace NDir; using namespace NName; -static CFSTR kTempFolderPrefix = FTEXT("7zE"); +static CFSTR const kTempFolderPrefix = FTEXT("7zE"); void CUpdateErrorInfo::SetFromLastError(const char *message) @@ -60,7 +62,8 @@ static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path) NFind::CFileInfo fileInfo; FString pathPrefix = path + FCHAR_PATH_SEPARATOR; { - NFind::CEnumerator enumerator(pathPrefix + FCHAR_ANY_MASK); + NFind::CEnumerator enumerator; + enumerator.SetDirPrefix(pathPrefix); while (enumerator.Next(fileInfo)) { if (fileInfo.IsDir()) @@ -156,7 +159,7 @@ bool COutMultiVolStream::SetMTime(const FILETIME *mTime) STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { - if (processedSize != NULL) + if (processedSize) *processedSize = 0; while (size > 0) { @@ -164,9 +167,8 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr { CAltStreamInfo altStream; - FChar temp[16]; - ConvertUInt32ToString(_streamIndex + 1, temp); - FString name = temp; + FString name; + name.Add_UInt32(_streamIndex + 1); while (name.Len() < 3) name.InsertAtFront(FTEXT('0')); name.Insert(0, Prefix); @@ -218,7 +220,7 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr _length = _absPos; if (_offsetPos > altStream.RealSize) altStream.RealSize = _offsetPos; - if (processedSize != NULL) + if (processedSize) *processedSize += realProcessed; if (altStream.Pos == volSize) { @@ -243,7 +245,7 @@ STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *n case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; - if (newPosition != NULL) + if (newPosition) *newPosition = _absPos; _streamIndex = 0; return S_OK; @@ -316,7 +318,7 @@ UString CArchivePath::GetFinalPath() const UString path = GetPathWithoutExt(); if (!BaseExtension.IsEmpty()) { - path += L'.'; + path += '.'; path += BaseExtension; } return path; @@ -327,7 +329,7 @@ UString CArchivePath::GetFinalVolPath() const UString path = GetPathWithoutExt(); if (!BaseExtension.IsEmpty()) { - path += L'.'; + path += '.'; path += VolExtension; } return path; @@ -339,17 +341,17 @@ FString CArchivePath::GetTempPath() const path += us2fs(Name); if (!BaseExtension.IsEmpty()) { - path += FTEXT('.'); + path += '.'; path += us2fs(BaseExtension); } - path.AddAscii(".tmp"); + path += ".tmp"; path += TempPostfix; return path; } -static const wchar_t *kDefaultArcType = L"7z"; -static const wchar_t *kDefaultArcExt = L"7z"; -static const char *kSFXExtension = +static const char * const kDefaultArcType = "7z"; +static const char * const kDefaultArcExt = "7z"; +static const char * const kSFXExtension = #ifdef _WIN32 "exe"; #else @@ -398,7 +400,7 @@ bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath) } UString ext = typeExt; if (SfxMode) - ext.SetFromAscii(kSFXExtension); + ext = kSFXExtension; ArchivePath.BaseExtension = ext; ArchivePath.VolExtension = typeExt; ArchivePath.ParseFromPath(arcPath, ArcNameMode); @@ -412,19 +414,43 @@ bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath) return true; } + struct CUpdateProduceCallbackImp: public IUpdateProduceCallback { const CObjectVector<CArcItem> *_arcItems; IUpdateCallbackUI *_callback; + CDirItemsStat *_stat; + + CUpdateProduceCallbackImp( + const CObjectVector<CArcItem> *a, + CDirItemsStat *stat, + IUpdateCallbackUI *callback): + _arcItems(a), + _stat(stat), + _callback(callback) {} - CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a, - IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {} virtual HRESULT ShowDeleteFile(unsigned arcIndex); }; + HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(unsigned arcIndex) { const CArcItem &ai = (*_arcItems)[arcIndex]; + { + CDirItemsStat &stat = *_stat; + if (ai.IsDir) + stat.NumDirs++; + else if (ai.IsAltStream) + { + stat.NumAltStreams++; + stat.AltStreamsSize += ai.Size; + } + else + { + stat.NumFiles++; + stat.FilesSize += ai.Size; + } + } return _callback->ShowDeleteFile(ai.Name, ai.IsDir); } @@ -562,6 +588,8 @@ static HRESULT Compress( UStringVector newNames; + CArcToDoStat stat2; + if (options.RenamePairs.Size() != 0) { FOR_VECTOR (i, arcItems) @@ -595,7 +623,7 @@ static HRESULT Compress( if (rp.GetNewPath(false, mainName, dest)) { needRename = true; - dest += L':'; + dest += ':'; dest += ai.Name.Ptr(colonPos + 1); break; } @@ -620,17 +648,51 @@ static HRESULT Compress( { CRecordVector<CUpdatePair> updatePairs; GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!! - CUpdateProduceCallbackImp upCallback(&arcItems, callback); + CUpdateProduceCallbackImp upCallback(&arcItems, &stat2.DeleteData, callback); UpdateProduce(updatePairs, actionSet, updatePairs2, isUpdatingItself ? &upCallback : NULL); } { - UInt32 numItems = 0; FOR_VECTOR (i, updatePairs2) - if (updatePairs2[i].NewData) - numItems++; - RINOK(callback->SetNumItems(numItems)); + { + const CUpdatePair2 &up = updatePairs2[i]; + if (up.NewData) + { + CDirItemsStat &stat = stat2.NewData; + const CDirItem &di = dirItems.Items[up.DirIndex]; + if (di.IsDir()) + stat.NumDirs++; + else if (di.IsAltStream) + { + stat.NumAltStreams++; + stat.AltStreamsSize += di.Size; + } + else + { + stat.NumFiles++; + stat.FilesSize += di.Size; + } + } + else if (up.ArcIndex >= 0) + { + CDirItemsStat &stat = stat2.OldData; + const CArcItem &ai = arcItems[up.ArcIndex]; + if (ai.IsDir) + stat.NumDirs++; + else if (ai.IsAltStream) + { + stat.NumAltStreams++; + stat.AltStreamsSize += ai.Size; + } + else + { + stat.NumFiles++; + stat.FilesSize += ai.Size; + } + } + } + RINOK(callback->SetNumItems(stat2)); } CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; @@ -698,9 +760,8 @@ static HRESULT Compress( { if (i > 0) { - FChar s[16]; - ConvertUInt32ToString(i, s); - archivePath.TempPostfix = s; + archivePath.TempPostfix.Empty(); + archivePath.TempPostfix.Add_UInt32(i); } realPath = archivePath.GetTempPath(); } @@ -734,7 +795,7 @@ static HRESULT Compress( outStream = outSeekStream; volStreamSpec->Sizes = options.VolumesSizes; volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath()); - volStreamSpec->Prefix += FTEXT('.'); + volStreamSpec->Prefix += '.'; volStreamSpec->TempFiles = &tempFiles; volStreamSpec->Init(); @@ -742,7 +803,7 @@ static HRESULT Compress( updateCallbackSpec->VolumesSizes = volumesSizes; updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name; if (!archivePath.VolExtension.IsEmpty()) - updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension; + updateCallbackSpec->VolExt = UString('.') + archivePath.VolExtension; */ } @@ -1025,7 +1086,7 @@ HRESULT UpdateArchive( if (options.SfxMode) { CProperty property; - property.Name.SetFromAscii("rsfx"); + property.Name = "rsfx"; options.MethodMode.Properties.Add(property); if (options.SfxModule.IsEmpty()) { @@ -1058,7 +1119,15 @@ HRESULT UpdateArchive( !options.SetArcPath(codecs, cmdArcPath2)) return E_NOTIMPL; } - const UString arcPath = options.ArchivePath.GetFinalPath(); + + UString arcPath = options.ArchivePath.GetFinalPath(); + + if (!options.VolumesSizes.IsEmpty()) + { + arcPath = options.ArchivePath.GetFinalVolPath(); + arcPath += '.'; + arcPath += "001"; + } if (cmdArcPath2.IsEmpty()) { @@ -1085,7 +1154,12 @@ HRESULT UpdateArchive( if (fi.IsDevice) return E_NOTIMPL; if (options.VolumesSizes.Size() > 0) + { + errorInfo.FileNames.Add(us2fs(arcPath)); + errorInfo.SystemError = (DWORD)E_NOTIMPL; + errorInfo.Message = kUpdateIsNotSupoorted_MultiVol; return E_NOTIMPL; + } CObjectVector<COpenType> types2; // change it. if (options.MethodMode.Type_Defined) @@ -1122,7 +1196,7 @@ HRESULT UpdateArchive( if (arcLink.VolumePaths.Size() > 1) { errorInfo.SystemError = (DWORD)E_NOTIMPL; - errorInfo.Message = "Updating for multivolume archives is not implemented"; + errorInfo.Message = kUpdateIsNotSupoorted_MultiVol; return E_NOTIMPL; } @@ -1147,7 +1221,7 @@ HRESULT UpdateArchive( if (options.MethodMode.Type.FormatIndex < 0) { - options.MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArcType); + options.MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveType((UString)kDefaultArcType); if (options.MethodMode.Type.FormatIndex < 0) return E_NOTIMPL; } @@ -1218,7 +1292,7 @@ HRESULT UpdateArchive( { NFind::CFileInfo fi; FString prefix = us2fs(censor.Pairs[0].Prefix); - prefix += FTEXT('.'); + prefix += '.'; // UString prefix = censor.Pairs[0].Prefix; /* if (prefix.Back() == WCHAR_PATH_SEPARATOR) @@ -1353,7 +1427,7 @@ HRESULT UpdateArchive( if (options.StdOutMode) { - name.SetFromAscii("stdout"); + name = "stdout"; isUpdating = thereIsInArchive; } else @@ -1461,10 +1535,10 @@ HRESULT UpdateArchive( for (i = 0; i < fullPaths.Size(); i++) { - UString arcPath2 = fs2us(fullPaths[i]); - UString fileName = ExtractFileNameFromPath(arcPath2); - AString path = GetAnsiString(arcPath2); - AString name = GetAnsiString(fileName); + const UString arcPath2 = fs2us(fullPaths[i]); + const UString fileName = ExtractFileNameFromPath(arcPath2); + const AString path (GetAnsiString(arcPath2)); + const AString name (GetAnsiString(fileName)); // Warning!!! MAPISendDocuments function changes Current directory // fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0); @@ -1479,7 +1553,7 @@ HRESULT UpdateArchive( m.nFileCount = 1; m.lpFiles = &f; - const AString addr = GetAnsiString(options.EMailAddress); + const AString addr (GetAnsiString(options.EMailAddress)); MapiRecipDesc rec; if (!addr.IsEmpty()) { diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp index 5499f2a1..ae3c4831 100644 --- a/CPP/7zip/UI/Common/UpdateCallback.cpp +++ b/CPP/7zip/UI/Common/UpdateCallback.cpp @@ -51,6 +51,8 @@ CArchiveUpdateCallback::CArchiveUpdateCallback(): ArcItems(NULL), UpdatePairs(NULL), NewNames(NULL), + CommentIndex(-1), + Comment(NULL), ShareForWrite(false), StdInMode(false), @@ -300,7 +302,7 @@ static UString GetRelativePath(const UString &to, const UString &from) unsigned k; for (k = i + 1; k < partsFrom.Size(); k++) - s += L".." WSTRING_PATH_SEPARATOR; + s += ".." STRING_PATH_SEPARATOR; for (k = i; k < partsTo.Size(); k++) { @@ -396,6 +398,11 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR } else if (propID == kpidPath && up.NewNameIndex >= 0) prop = (*NewNames)[up.NewNameIndex]; + else if (propID == kpidComment + && CommentIndex >= 0 + && (unsigned)CommentIndex == index + && Comment) + prop = *Comment; else if (propID == kpidShortName && up.NewNameIndex >= 0 && up.IsMainRenameItem) { // we can generate new ShortName here; @@ -690,13 +697,13 @@ STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { COM_TRY_BEGIN - FChar temp[16]; + char temp[16]; ConvertUInt32ToString(index + 1, temp); - FString res = temp; + FString res (temp); while (res.Len() < 2) res.InsertAtFront(FTEXT('0')); FString fileName = VolName; - fileName += FTEXT('.'); + fileName += '.'; fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; diff --git a/CPP/7zip/UI/Common/UpdateCallback.h b/CPP/7zip/UI/Common/UpdateCallback.h index 4ff4a7eb..87a114b1 100644 --- a/CPP/7zip/UI/Common/UpdateCallback.h +++ b/CPP/7zip/UI/Common/UpdateCallback.h @@ -15,6 +15,18 @@ #include "OpenArchive.h" +struct CArcToDoStat +{ + CDirItemsStat NewData; + CDirItemsStat OldData; + CDirItemsStat DeleteData; + + UInt64 Get_NumDataItems_Total() const + { + return NewData.Get_NumDataItems() + OldData.Get_NumDataItems(); + } +}; + #define INTERFACE_IUpdateCallbackUI(x) \ virtual HRESULT WriteSfx(const wchar_t *name, UInt64 size) x; \ virtual HRESULT SetTotal(UInt64 size) x; \ @@ -22,7 +34,7 @@ virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \ virtual HRESULT CheckBreak() x; \ /* virtual HRESULT Finalize() x; */ \ - virtual HRESULT SetNumItems(UInt64 numItems) x; \ + virtual HRESULT SetNumItems(const CArcToDoStat &stat) 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; \ @@ -120,6 +132,8 @@ public: const CObjectVector<CArcItem> *ArcItems; const CRecordVector<CUpdatePair2> *UpdatePairs; const UStringVector *NewNames; + int CommentIndex; + const UString *Comment; bool ShareForWrite; bool StdInMode; diff --git a/CPP/7zip/UI/Common/UpdatePair.cpp b/CPP/7zip/UI/Common/UpdatePair.cpp index e2115197..82876c1d 100644 --- a/CPP/7zip/UI/Common/UpdatePair.cpp +++ b/CPP/7zip/UI/Common/UpdatePair.cpp @@ -38,14 +38,13 @@ static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time throw 4191618; } -static const char *k_Duplicate_inArc_Message = "Duplicate filename in archive:"; -static const char *k_Duplicate_inDir_Message = "Duplicate filename on disk:"; -static const char *k_NotCensoredCollision_Message = "Internal file name collision (file on disk, file in archive):"; +static const char * const k_Duplicate_inArc_Message = "Duplicate filename in archive:"; +static const char * const k_Duplicate_inDir_Message = "Duplicate filename on disk:"; +static const char * const k_NotCensoredCollision_Message = "Internal file name collision (file on disk, file in archive):"; static void ThrowError(const char *message, const UString &s1, const UString &s2) { - UString m; - m.SetFromAscii(message); + UString m (message); 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 e6eabcf1..d5052f13 100644 --- a/CPP/7zip/UI/Common/UpdateProduce.cpp +++ b/CPP/7zip/UI/Common/UpdateProduce.cpp @@ -6,7 +6,7 @@ using namespace NUpdateArchive; -static const char *kUpdateActionSetCollision = "Internal collision in update action set"; +static const char * const kUpdateActionSetCollision = "Internal collision in update action set"; void UpdateProduce( const CRecordVector<CUpdatePair> &updatePairs, diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp index a0e692d0..558a159c 100644 --- a/CPP/7zip/UI/Common/ZipRegistry.cpp +++ b/CPP/7zip/UI/Common/ZipRegistry.cpp @@ -16,9 +16,9 @@ using namespace NRegistry; static NSynchronization::CCriticalSection g_CS; #define CS_LOCK NSynchronization::CCriticalSectionLock lock(g_CS); -static const TCHAR *kCuPrefix = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR); +static LPCTSTR const kCuPrefix = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR); -static CSysString GetKeyPath(const CSysString &path) { return kCuPrefix + path; } +static CSysString GetKeyPath(LPCTSTR path) { return kCuPrefix + (CSysString)path; } static LONG OpenMainKey(CKey &key, LPCTSTR keyName) { @@ -51,16 +51,16 @@ static void Key_Get_BoolPair_true(CKey &key, LPCTSTR name, CBoolPair &b) namespace NExtract { -static const TCHAR *kKeyName = TEXT("Extraction"); +static LPCTSTR const kKeyName = TEXT("Extraction"); -static const TCHAR *kExtractMode = TEXT("ExtractMode"); -static const TCHAR *kOverwriteMode = TEXT("OverwriteMode"); -static const TCHAR *kShowPassword = TEXT("ShowPassword"); -static const TCHAR *kPathHistory = TEXT("PathHistory"); -static const TCHAR *kSplitDest = TEXT("SplitDest"); -static const TCHAR *kElimDup = TEXT("ElimDup"); -// static const TCHAR *kAltStreams = TEXT("AltStreams"); -static const TCHAR *kNtSecur = TEXT("Security"); +static LPCTSTR const kExtractMode = TEXT("ExtractMode"); +static LPCTSTR const kOverwriteMode = TEXT("OverwriteMode"); +static LPCTSTR const kShowPassword = TEXT("ShowPassword"); +static LPCTSTR const kPathHistory = TEXT("PathHistory"); +static LPCTSTR const kSplitDest = TEXT("SplitDest"); +static LPCTSTR const kElimDup = TEXT("ElimDup"); +// static LPCTSTR const kAltStreams = TEXT("AltStreams"); +static LPCTSTR const kNtSecur = TEXT("Security"); void CInfo::Save() const { @@ -144,30 +144,30 @@ bool Read_ShowPassword() namespace NCompression { -static const TCHAR *kKeyName = TEXT("Compression"); +static LPCTSTR const kKeyName = TEXT("Compression"); -static const TCHAR *kArcHistory = TEXT("ArcHistory"); -static const WCHAR *kArchiver = L"Archiver"; -static const TCHAR *kShowPassword = TEXT("ShowPassword"); -static const TCHAR *kEncryptHeaders = TEXT("EncryptHeaders"); +static LPCTSTR const kArcHistory = TEXT("ArcHistory"); +static LPCWSTR const kArchiver = L"Archiver"; +static LPCTSTR const kShowPassword = TEXT("ShowPassword"); +static LPCTSTR const kEncryptHeaders = TEXT("EncryptHeaders"); -static const TCHAR *kOptionsKeyName = TEXT("Options"); +static LPCTSTR const kOptionsKeyName = TEXT("Options"); -static const TCHAR *kLevel = TEXT("Level"); -static const TCHAR *kDictionary = TEXT("Dictionary"); -static const TCHAR *kOrder = TEXT("Order"); -static const TCHAR *kBlockSize = TEXT("BlockSize"); -static const TCHAR *kNumThreads = TEXT("NumThreads"); -static const WCHAR *kMethod = L"Method"; -static const WCHAR *kOptions = L"Options"; -static const WCHAR *kEncryptionMethod = L"EncryptionMethod"; +static LPCTSTR const kLevel = TEXT("Level"); +static LPCTSTR const kDictionary = TEXT("Dictionary"); +static LPCTSTR const kOrder = TEXT("Order"); +static LPCTSTR const kBlockSize = TEXT("BlockSize"); +static LPCTSTR const kNumThreads = TEXT("NumThreads"); +static LPCWSTR const kMethod = L"Method"; +static LPCWSTR const kOptions = L"Options"; +static LPCWSTR const kEncryptionMethod = L"EncryptionMethod"; -static const TCHAR *kNtSecur = TEXT("Security"); -static const TCHAR *kAltStreams = TEXT("AltStreams"); -static const TCHAR *kHardLinks = TEXT("HardLinks"); -static const TCHAR *kSymLinks = TEXT("SymLinks"); +static LPCTSTR const kNtSecur = TEXT("Security"); +static LPCTSTR const kAltStreams = TEXT("AltStreams"); +static LPCTSTR const kHardLinks = TEXT("HardLinks"); +static LPCTSTR const kSymLinks = TEXT("SymLinks"); -static void SetRegString(CKey &key, const WCHAR *name, const UString &value) +static void SetRegString(CKey &key, LPCWSTR name, const UString &value) { if (value.IsEmpty()) key.DeleteValue(name); @@ -175,7 +175,7 @@ static void SetRegString(CKey &key, const WCHAR *name, const UString &value) key.SetValue(name, value); } -static void SetRegUInt32(CKey &key, const TCHAR *name, UInt32 value) +static void SetRegUInt32(CKey &key, LPCTSTR name, UInt32 value) { if (value == (UInt32)(Int32)-1) key.DeleteValue(name); @@ -183,13 +183,13 @@ static void SetRegUInt32(CKey &key, const TCHAR *name, UInt32 value) key.SetValue(name, value); } -static void GetRegString(CKey &key, const WCHAR *name, UString &value) +static void GetRegString(CKey &key, LPCWSTR name, UString &value) { if (key.QueryValue(name, value) != ERROR_SUCCESS) value.Empty(); } -static void GetRegUInt32(CKey &key, const TCHAR *name, UInt32 &value) +static void GetRegUInt32(CKey &key, LPCTSTR name, UInt32 &value) { if (key.QueryValue(name, value) != ERROR_SUCCESS) value = (UInt32)(Int32)-1; @@ -300,13 +300,13 @@ void CInfo::Load() } -static const TCHAR *kOptionsInfoKeyName = TEXT("Options"); +static LPCTSTR const kOptionsInfoKeyName = TEXT("Options"); namespace NWorkDir { -static const TCHAR *kWorkDirType = TEXT("WorkDirType"); -static const WCHAR *kWorkDirPath = L"WorkDirPath"; -static const TCHAR *kTempRemovableOnly = TEXT("TempRemovableOnly"); +static LPCTSTR const kWorkDirType = TEXT("WorkDirType"); +static LPCWSTR const kWorkDirPath = L"WorkDirPath"; +static LPCTSTR const kTempRemovableOnly = TEXT("TempRemovableOnly"); void CInfo::Save()const @@ -352,10 +352,10 @@ void CInfo::Load() } -static const TCHAR *kCascadedMenu = TEXT("CascadedMenu"); -static const TCHAR *kContextMenu = TEXT("ContextMenu"); -static const TCHAR *kMenuIcons = TEXT("MenuIcons"); -static const TCHAR *kElimDup = TEXT("ElimDupExtract"); +static LPCTSTR const kCascadedMenu = TEXT("CascadedMenu"); +static LPCTSTR const kContextMenu = TEXT("ContextMenu"); +static LPCTSTR const kMenuIcons = TEXT("MenuIcons"); +static LPCTSTR const kElimDup = TEXT("ElimDupExtract"); void CContextMenuInfo::Save() const { diff --git a/CPP/7zip/UI/Console/Console.dsp b/CPP/7zip/UI/Console/Console.dsp index 84ee4a6f..4145d726 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 /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 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" /FAcs /Yu"StdAfx.h" /FD /GF /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp index 8dac7fbc..68a7a85f 100644 --- a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp +++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp @@ -32,7 +32,7 @@ static HRESULT CheckBreak2() return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK; } -static const char *kError = "ERROR: "; +static const char * const kError = "ERROR: "; void CExtractScanConsole::StartScanning() @@ -138,33 +138,33 @@ static NSynchronization::CCriticalSection g_CriticalSection; #endif -static const char *kTestString = "T"; -static const char *kExtractString = "-"; -static const char *kSkipString = "."; +static const char * const kTestString = "T"; +static const char * const kExtractString = "-"; +static const char * const 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 * const kCantAutoRename = "can not create file with auto name\n"; +// static const char * const kCantRenameFile = "can not rename existing file\n"; +// static const char * const kCantDeleteOutputFile = "can not delete output file "; -static const char *kMemoryExceptionMessage = "Can't allocate required memory!"; +static const char * const kMemoryExceptionMessage = "Can't allocate required memory!"; -static const char *kExtracting = "Extracting archive: "; -static const char *kTesting = "Testing archive: "; +static const char * const kExtracting = "Extracting archive: "; +static const char * const kTesting = "Testing archive: "; -static const char *kEverythingIsOk = "Everything is Ok"; -static const char *kNoFiles = "No files to process"; +static const char * const kEverythingIsOk = "Everything is Ok"; +static const char * const kNoFiles = "No files to process"; -static const char *kUnsupportedMethod = "Unsupported Method"; -static const char *kCrcFailed = "CRC Failed"; -static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?"; -static const char *kDataError = "Data Error"; -static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?"; -static const char *kUnavailableData = "Unavailable data"; -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 * const kUnsupportedMethod = "Unsupported Method"; +static const char * const kCrcFailed = "CRC Failed"; +static const char * const kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?"; +static const char * const kDataError = "Data Error"; +static const char * const kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?"; +static const char * const kUnavailableData = "Unavailable data"; +static const char * const kUnexpectedEnd = "Unexpected end of data"; +static const char * const kDataAfterEnd = "There are some data after the end of the payload data"; +static const char * const kIsNotArc = "Is not archive"; +static const char * const kHeadersError = "Headers Error"; +static const char * const kWrongPassword = "Wrong password"; static const char * const k_ErrorFlagsMessages[] = { @@ -206,7 +206,7 @@ STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *completeValue) return CheckBreak2(); } -static const char *kTab = " "; +static const char * const kTab = " "; static void PrintFileInfo(CStdOutStream *_so, const wchar_t *path, const FILETIME *ft, const UInt64 *size) { @@ -220,10 +220,8 @@ static void PrintFileInfo(CStdOutStream *_so, const wchar_t *path, const FILETIM if (ft) { char temp[64]; - FILETIME locTime; - if (FileTimeToLocalFileTime(ft, &locTime)) - if (ConvertFileTimeToString(locTime, temp, true, true)) - *_so << kTab << "Modified: " << temp << endl; + if (ConvertUtcFileTimeToString(*ft, temp, kTimestampPrintLevel_SEC)) + *_so << kTab << "Modified: " << temp << endl; } } @@ -256,6 +254,8 @@ STDMETHODIMP CExtractCallbackConsole::AskOverwrite( case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break; case NUserAnswerMode::kYes: *answer = NOverwriteAnswer::kYes; break; case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break; + case NUserAnswerMode::kEof: return E_ABORT; + case NUserAnswerMode::kError: return E_FAIL; default: return E_FAIL; } @@ -388,10 +388,8 @@ void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest) dest += s; else { - char temp[16]; - ConvertUInt32ToString(opRes, temp); dest += "Error #"; - dest += temp; + dest.Add_UInt32(opRes); } } @@ -524,22 +522,22 @@ void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags) void Add_Messsage_Pre_ArcType(UString &s, const char *pre, const wchar_t *arcType) { s.Add_LF(); - s.AddAscii(pre); - s.AddAscii(" as ["); + s += pre; + s += " as ["; s += arcType; - s.AddAscii("] archive"); + s += "] archive"; } void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc) { const CArcErrorInfo &er = arc.ErrorInfo; - UString s = L"WARNING:\n"; + UString s ("WARNING:\n"); s += arc.Path; if (arc.FormatIndex == er.ErrorFormatIndex) { s.Add_LF(); - s.AddAscii("The archive is open with offset"); + s += "The archive is open with offset"; } else { diff --git a/CPP/7zip/UI/Console/HashCon.cpp b/CPP/7zip/UI/Console/HashCon.cpp index 6a82daf2..8ff90753 100644 --- a/CPP/7zip/UI/Console/HashCon.cpp +++ b/CPP/7zip/UI/Console/HashCon.cpp @@ -7,9 +7,9 @@ #include "ConsoleClose.h" #include "HashCon.h" -static const wchar_t *kEmptyFileAlias = L"[Content]"; +static const char * const kEmptyFileAlias = "[Content]"; -static const char *kScanningMessage = "Scanning"; +static const char * const kScanningMessage = "Scanning"; static HRESULT CheckBreak2() { @@ -168,7 +168,7 @@ HRESULT CHashCallbackConsole::BeforeFirstFile(const CHashBundle &hb) if (PrintSize) { _s.Add_Space(); - const AString s2 = "Size"; + const AString s2 ("Size"); AddSpaces_if_Positive(_s, (int)kSizeField_Len - (int)s2.Len()); _s += s2; } diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp index 62e813b2..57d1d1bc 100644 --- a/CPP/7zip/UI/Console/List.cpp +++ b/CPP/7zip/UI/Console/List.cpp @@ -128,14 +128,14 @@ static const char * const kPropIdToName[] = static const char kEmptyAttribChar = '.'; -static const char *kListing = "Listing archive: "; +static const char * const kListing = "Listing archive: "; -static const char *kString_Files = "files"; -static const char *kString_Dirs = "folders"; -static const char *kString_AltStreams = "alternate streams"; -static const char *kString_Streams = "streams"; +static const char * const kString_Files = "files"; +static const char * const kString_Dirs = "folders"; +static const char * const kString_AltStreams = "alternate streams"; +static const char * const kString_Streams = "streams"; -static const char *kError = "ERROR: "; +static const char * const kError = "ERROR: "; static void GetAttribString(UInt32 wa, bool isDir, bool allAttribs, char *s) { @@ -417,9 +417,8 @@ static void GetPropName(PROPID propID, const wchar_t *name, AString &nameA, UStr nameU = name; else { - char s[16]; - ConvertUInt32ToString(propID, s); - nameA = s; + nameA.Empty(); + nameA.Add_UInt32(propID); } } @@ -429,7 +428,7 @@ void CFieldPrinter::AddProp(const wchar_t *name, PROPID propID, bool isRawProp) f.PropID = propID; f.IsRawProp = isRawProp; GetPropName(propID, name, f.NameA, f.NameU); - f.NameU.AddAscii(" = "); + f.NameU += " = "; if (!f.NameA.IsEmpty()) f.NameA += " = "; else @@ -499,10 +498,7 @@ static void PrintTime(char *dest, const FILETIME *ft) *dest = 0; if (ft->dwLowDateTime == 0 && ft->dwHighDateTime == 0) return; - FILETIME locTime; - if (!FileTimeToLocalFileTime(ft, &locTime)) - throw 20121211; - ConvertFileTimeToString(locTime, dest, true, true); + ConvertUtcFileTimeToString(*ft, dest, kTimestampPrintLevel_SEC); } #ifndef _SFX @@ -686,7 +682,7 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st) else { char s[64]; - ConvertPropertyToShortString(s, prop, f.PropID); + ConvertPropertyToShortString2(s, prop, f.PropID); if (techMode) g_StdOut << s; else @@ -828,7 +824,7 @@ static void PrintPropPair(CStdOutStream &so, const char *name, const wchar_t *va static void PrintPropertyPair2(CStdOutStream &so, PROPID propID, const wchar_t *name, const CPropVariant &prop) { UString s; - ConvertPropertyToString(s, prop, propID); + ConvertPropertyToString2(s, prop, propID); if (!s.IsEmpty()) { AString nameA; diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp index 50652555..8a077d47 100644 --- a/CPP/7zip/UI/Console/Main.cpp +++ b/CPP/7zip/UI/Console/Main.cpp @@ -64,6 +64,8 @@ using namespace NCommandLineParser; HINSTANCE g_hInstance = 0; #endif +bool g_LargePagesMode = false; + extern CStdOutStream *g_StdStream; extern CStdOutStream *g_ErrStream; @@ -73,24 +75,19 @@ extern const CCodecInfo *g_Codecs[]; extern unsigned g_NumHashers; extern const CHasherInfo *g_Hashers[]; -static const char *kCopyrightString = "\n7-Zip" -#ifndef EXTERNAL_CODECS -#ifdef PROG_VARIANT_R -" (r)" -#else -" (a)" -#endif -#endif - -#ifdef MY_CPU_64BIT -" [64]" -#elif defined MY_CPU_32BIT -" [32]" -#endif +static const char * const kCopyrightString = "\n7-Zip" + #ifndef EXTERNAL_CODECS + #ifdef PROG_VARIANT_R + " (r)" + #else + " (a)" + #endif + #endif -" " MY_VERSION_COPYRIGHT_DATE "\n\n"; + " " MY_VERSION_CPU + " : " MY_COPYRIGHT_DATE "\n\n"; -static const char *kHelpString = +static const char * const kHelpString = "Usage: 7z" #ifndef EXTERNAL_CODECS #ifdef PROG_VARIANT_R @@ -128,6 +125,7 @@ static const char *kHelpString = " -i[r[-|0]]{@listfile|!wildcard} : Include filenames\n" " -m{Parameters} : set compression Method\n" " -mmt[N] : set number of CPU threads\n" + " -mx[N] : set compression level: -mx1 (fastest) ... -mx9 (ultra)\n" " -o{Directory} : set Output directory\n" #ifndef _NO_CRYPTO " -p{Password} : set Password\n" @@ -166,13 +164,13 @@ static const char *kHelpString = // --------------------------- // exception messages -static const char *kEverythingIsOk = "Everything is Ok"; -static const char *kUserErrorMessage = "Incorrect command line"; -static const char *kNoFormats = "7-Zip cannot find the code that works with archives."; -static const char *kUnsupportedArcTypeMessage = "Unsupported archive type"; -// static const char *kUnsupportedUpdateArcType = "Can't create archive for that type"; +static const char * const kEverythingIsOk = "Everything is Ok"; +static const char * const kUserErrorMessage = "Incorrect command line"; +static const char * const kNoFormats = "7-Zip cannot find the code that works with archives."; +static const char * const kUnsupportedArcTypeMessage = "Unsupported archive type"; +// static const char * const kUnsupportedUpdateArcType = "Can't create archive for that type"; -static CFSTR kDefaultSfxModule = FTEXT("7zCon.sfx"); +#define kDefaultSfxModule "7zCon.sfx" static void ShowMessageAndThrowException(LPCSTR message, NExitCode::EEnum code) { @@ -204,9 +202,9 @@ static void ShowCopyrightAndHelp(CStdOutStream *so, bool needHelp) } -static void PrintStringRight(CStdOutStream &so, const AString &s, unsigned size) +static void PrintStringRight(CStdOutStream &so, const char *s, unsigned size) { - unsigned len = s.Len(); + unsigned len = MyStringLen(s); for (unsigned i = len; i < size; i++) so << ' '; so << s; @@ -279,7 +277,7 @@ static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback, UString message; if (!errorInfo.Message.IsEmpty()) { - message.AddAscii(errorInfo.Message); + message += errorInfo.Message.Ptr(); message.Add_LF(); } { @@ -389,6 +387,7 @@ static void PrintMemUsage(const char *s, UInt64 val) EXTERN_C_BEGIN typedef BOOL (WINAPI *Func_GetProcessMemoryInfo)(HANDLE Process, PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb); +typedef BOOL (WINAPI *Func_QueryProcessCycleTime)(HANDLE Process, PULONG64 CycleTime); EXTERN_C_END #endif @@ -415,6 +414,8 @@ static void PrintStat() PROCESS_MEMORY_COUNTERS m; memset(&m, 0, sizeof(m)); BOOL memDefined = FALSE; + BOOL cycleDefined = FALSE; + ULONG64 cycleTime = 0; { /* NT 4.0: GetProcessMemoryInfo() in Psapi.dll Win7: new function K32GetProcessMemoryInfo() in kernel32.dll @@ -425,8 +426,9 @@ static void PrintStat() // memDefined = GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m)); */ + HMODULE kern = ::GetModuleHandleW(L"kernel32.dll"); Func_GetProcessMemoryInfo my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo) - ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "K32GetProcessMemoryInfo"); + ::GetProcAddress(kern, "K32GetProcessMemoryInfo"); if (!my_GetProcessMemoryInfo) { HMODULE lib = LoadLibraryW(L"Psapi.dll"); @@ -436,6 +438,11 @@ static void PrintStat() if (my_GetProcessMemoryInfo) memDefined = my_GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m)); // FreeLibrary(lib); + + Func_QueryProcessCycleTime my_QueryProcessCycleTime = (Func_QueryProcessCycleTime) + ::GetProcAddress(kern, "QueryProcessCycleTime"); + if (my_QueryProcessCycleTime) + cycleDefined = my_QueryProcessCycleTime(GetCurrentProcess(), &cycleTime); } #endif @@ -448,6 +455,16 @@ static void PrintStat() UInt64 totalTime = curTime - creationTime; PrintTime("Kernel ", kernelTime, totalTime); + + #ifndef UNDER_CE + if (cycleDefined) + { + *g_StdStream << " "; + PrintNum(cycleTime / 1000000, 22); + *g_StdStream << " MCycles"; + } + #endif + PrintTime("User ", userTime, totalTime); PrintTime("Process", kernelTime + userTime, totalTime); @@ -470,6 +487,7 @@ static void PrintHexId(CStdOutStream &so, UInt64 id) PrintStringRight(so, s, 8); } + int Main2( #ifndef _WIN32 int numArgs, char *args[] @@ -488,14 +506,17 @@ int Main2( GetArguments(numArgs, args, commandStrings); #endif - if (commandStrings.Size() == 1) + #ifndef UNDER_CE + if (commandStrings.Size() > 0) + commandStrings.Delete(0); + #endif + + if (commandStrings.Size() == 0) { ShowCopyrightAndHelp(g_StdStream, true); return 0; } - commandStrings.Delete(0); - CArcCmdLineOptions options; CArcCmdLineParser parser; @@ -527,8 +548,11 @@ int Main2( if (options.LargePages) { SetLargePageSize(); + g_LargePagesMode = #if defined(_WIN32) && !defined(UNDER_CE) - NSecurity::EnablePrivilege_LockMemory(); + NSecurity::EnablePrivilege_LockMemory(); + #else + true; #endif } #endif @@ -579,7 +603,7 @@ int Main2( #ifdef EXTERNAL_CODECS if (!codecs->MainDll_ErrorPath.IsEmpty()) { - UString s = L"Can't load module "; + UString s ("Can't load module: "); s += fs2us(codecs->MainDll_ErrorPath); throw s; } @@ -639,7 +663,7 @@ int Main2( so << endl << "Formats:" << endl; - const char *kArcFlags = "KSNFMGOPBELH"; + const char * const kArcFlags = "KSNFMGOPBELH"; const unsigned kNumArcFlags = (unsigned)strlen(kArcFlags); for (i = 0; i < codecs->Formats.Size(); i++) @@ -673,9 +697,9 @@ int Main2( s += ext.Ext; if (!ext.AddExt.IsEmpty()) { - s += L" ("; + s += " ("; s += ext.AddExt; - s += L')'; + s += ')'; } } diff --git a/CPP/7zip/UI/Console/MainAr.cpp b/CPP/7zip/UI/Console/MainAr.cpp index d30a96e4..68e5fe97 100644 --- a/CPP/7zip/UI/Console/MainAr.cpp +++ b/CPP/7zip/UI/Console/MainAr.cpp @@ -24,12 +24,12 @@ extern int Main2( #endif ); -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 #"; +static const char * const kException_CmdLine_Error_Message = "Command Line Error:"; +static const char * const kExceptionErrorMessage = "ERROR:"; +static const char * const kUserBreakMessage = "Break signaled"; +static const char * const kMemoryExceptionMessage = "ERROR: Can't allocate required memory!"; +static const char * const kUnknownExceptionMessage = "Unknown Error"; +static const char * const kInternalExceptionMessage = "\n\nInternal Error #"; static void FlushStreams() { diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.cpp b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp index 9d25a729..a074fa1f 100644 --- a/CPP/7zip/UI/Console/OpenCallbackConsole.cpp +++ b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp @@ -32,13 +32,17 @@ HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *files, const UInt64 *b if (bytes) { - _totalBytesDefined = true; - // _totalBytes = *bytes; + // _totalBytesDefined = true; + _totalBytes = *bytes; if (!files) _percent.Total = *bytes; } else - _totalBytesDefined = false; + { + // _totalBytesDefined = false; + if (!files) + _percent.Total = _totalBytes; + } } return CheckBreak2(); @@ -83,7 +87,7 @@ HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password) if (!PasswordIsDefined) { ClosePercents(); - Password = GetPassword(_so); + RINOK(GetPassword_HRESULT(_so, Password)); PasswordIsDefined = true; } return StringToBstr(Password, password); diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.h b/CPP/7zip/UI/Console/OpenCallbackConsole.h index 0dd4e1d1..64c1dad3 100644 --- a/CPP/7zip/UI/Console/OpenCallbackConsole.h +++ b/CPP/7zip/UI/Console/OpenCallbackConsole.h @@ -18,9 +18,9 @@ protected: CStdOutStream *_se; bool _totalFilesDefined; - bool _totalBytesDefined; + // bool _totalBytesDefined; // UInt64 _totalFiles; - // UInt64 _totalBytes; + UInt64 _totalBytes; bool NeedPercents() const { return _percent._so != NULL; } @@ -36,7 +36,8 @@ public: COpenCallbackConsole(): _totalFilesDefined(false), - _totalBytesDefined(false), + // _totalBytesDefined(false), + _totalBytes(0), MultiArcMode(false) #ifndef _NO_CRYPTO diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp index f4f2d102..efac98e3 100644 --- a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp +++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp @@ -23,15 +23,15 @@ static NSynchronization::CCriticalSection g_CriticalSection; #define MT_LOCK #endif -static const wchar_t *kEmptyFileAlias = L"[Content]"; +static const wchar_t * const kEmptyFileAlias = L"[Content]"; -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 * const kOpenArchiveMessage = "Open archive: "; +static const char * const kCreatingArchiveMessage = "Creating archive: "; +static const char * const kUpdatingArchiveMessage = "Updating archive: "; +static const char * const kScanningMessage = "Scanning the drive:"; -static const char *kError = "ERROR: "; -static const char *kWarning = "WARNING: "; +static const char * const kError = "ERROR: "; +static const char * const kWarning = "WARNING: "; static HRESULT CheckBreak2() { @@ -259,7 +259,7 @@ HRESULT CUpdateCallbackConsole::FinishScanning(const CDirItemsStat &st) return S_OK; } -static const char *k_StdOut_ArcName = "StdOut"; +static const char * const k_StdOut_ArcName = "StdOut"; HRESULT CUpdateCallbackConsole::StartOpenArchive(const wchar_t *name) { @@ -316,7 +316,7 @@ HRESULT CUpdateCallbackConsole::WriteSfx(const wchar_t *name, UInt64 size) { *_so << "Write SFX: "; *_so << name; - AString s = " : "; + AString s (" : "); PrintSize_bytes_Smart(s, size); *_so << s << endl; } @@ -398,14 +398,31 @@ HRESULT CUpdateCallbackConsole::Finalize() } */ -HRESULT CUpdateCallbackConsole::SetNumItems(UInt64 numItems) + +void static PrintToDoStat(CStdOutStream *_so, const CDirItemsStat &stat, const char *name) +{ + AString s; + Print_DirItemsStat(s, stat); + *_so << name << ": " << s << endl; +} + +HRESULT CUpdateCallbackConsole::SetNumItems(const CArcToDoStat &stat) { if (_so) { ClosePercents_for_so(); - AString s; - PrintPropPair(s, "Items to compress", numItems); - *_so << s << endl << endl; + if (!stat.DeleteData.IsEmpty()) + { + *_so << endl; + PrintToDoStat(_so, stat.DeleteData, "Delete data from archive"); + } + if (!stat.OldData.IsEmpty()) + PrintToDoStat(_so, stat.OldData, "Keep old data in archive"); + // if (!stat.NewData.IsEmpty()) + { + PrintToDoStat(_so, stat.NewData, "Add new data to archive"); + } + *_so << endl; } return S_OK; } @@ -622,7 +639,7 @@ HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, { if (AskPassword) { - Password = GetPassword(_so); + RINOK(GetPassword_HRESULT(_so, Password)); PasswordIsDefined = true; } } @@ -649,7 +666,7 @@ HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password) if (!PasswordIsDefined) { { - Password = GetPassword(_so); + RINOK(GetPassword_HRESULT(_so, Password)) PasswordIsDefined = true; } } diff --git a/CPP/7zip/UI/Console/UserInputUtils.cpp b/CPP/7zip/UI/Console/UserInputUtils.cpp index c7f830ff..0e2d7ac1 100644 --- a/CPP/7zip/UI/Console/UserInputUtils.cpp +++ b/CPP/7zip/UI/Console/UserInputUtils.cpp @@ -14,8 +14,8 @@ static const char kNoAll = 's'; static const char kAutoRenameAll = 'u'; static const char kQuit = 'q'; -static const char *kFirstQuestionMessage = "? "; -static const char *kHelpQuestionMessage = +static const char * const kFirstQuestionMessage = "? "; +static const char * const kHelpQuestionMessage = "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? "; // return true if pressed Quite; @@ -31,9 +31,16 @@ NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream) *outStream << kHelpQuestionMessage; outStream->Flush(); } - AString scannedString = g_StdIn.ScanStringUntilNewLine(); + AString scannedString; + if (!g_StdIn.ScanAStringUntilNewLine(scannedString)) + return NUserAnswerMode::kError; + if (g_StdIn.Error()) + return NUserAnswerMode::kError; scannedString.Trim(); - if (!scannedString.IsEmpty()) + if (scannedString.IsEmpty() && g_StdIn.Eof()) + return NUserAnswerMode::kEof; + + if (scannedString.Len() == 1) switch (::MyCharLower_Ascii(scannedString[0])) { case kYes: return NUserAnswerMode::kYes; @@ -52,7 +59,7 @@ NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream) #endif #endif -UString GetPassword(CStdOutStream *outStream) +static bool GetPassword(CStdOutStream *outStream, UString &psw) { if (outStream) { @@ -72,19 +79,32 @@ UString GetPassword(CStdOutStream *outStream) if (console != INVALID_HANDLE_VALUE && console != 0) if (GetConsoleMode(console, &mode)) wasChanged = (SetConsoleMode(console, mode & ~ENABLE_ECHO_INPUT) != 0); - UString res = g_StdIn.ScanUStringUntilNewLine(); + bool res = g_StdIn.ScanUStringUntilNewLine(psw); if (wasChanged) SetConsoleMode(console, mode); + + #else + + bool res = g_StdIn.ScanUStringUntilNewLine(psw); + + #endif + if (outStream) { *outStream << endl; outStream->Flush(); } + return res; - - #else - - return g_StdIn.ScanUStringUntilNewLine(); - - #endif +} + +HRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw) +{ + if (!GetPassword(outStream, psw)) + return E_INVALIDARG; + if (g_StdIn.Error()) + return E_FAIL; + if (g_StdIn.Eof() && psw.IsEmpty()) + return E_ABORT; + return S_OK; } diff --git a/CPP/7zip/UI/Console/UserInputUtils.h b/CPP/7zip/UI/Console/UserInputUtils.h index 16f04580..256feafe 100644 --- a/CPP/7zip/UI/Console/UserInputUtils.h +++ b/CPP/7zip/UI/Console/UserInputUtils.h @@ -14,11 +14,14 @@ enum EEnum kYesAll, kNoAll, kAutoRenameAll, - kQuit + kQuit, + kEof, + kError }; } NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream); -UString GetPassword(CStdOutStream *outStream); +// bool GetPassword(CStdOutStream *outStream, UString &psw); +HRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw); #endif diff --git a/CPP/7zip/UI/Console/resource.rc b/CPP/7zip/UI/Console/resource.rc index 6e09bb96..2f7ef073 100644 --- a/CPP/7zip/UI/Console/resource.rc +++ b/CPP/7zip/UI/Console/resource.rc @@ -1,3 +1,3 @@ #include "../../MyVersionInfo.rc" -MY_VERSION_INFO_APP("7-Zip Console", "7z") +MY_VERSION_INFO_APP("7-Zip Console" , "7z") diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp index 62ad0aa9..21de12a5 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp @@ -129,27 +129,16 @@ HRESULT CZipContextMenu::InitContextMenu(const wchar_t * /* folder */, const wch ///////////////////////////// // IContextMenu -static LPCWSTR kMainVerb = L"SevenZip"; -static LPCWSTR kOpenCascadedVerb = L"SevenZip.OpenWithType."; -static LPCWSTR kCheckSumCascadedVerb = L"SevenZip.Checksum"; +static LPCSTR const kMainVerb = "SevenZip"; +static LPCSTR const kOpenCascadedVerb = "SevenZip.OpenWithType."; +static LPCSTR const kCheckSumCascadedVerb = "SevenZip.Checksum"; -/* -static LPCTSTR kOpenVerb = TEXT("SevenOpen"); -static LPCTSTR kExtractVerb = TEXT("SevenExtract"); -static LPCTSTR kExtractHereVerb = TEXT("SevenExtractHere"); -static LPCTSTR kExtractToVerb = TEXT("SevenExtractTo"); -static LPCTSTR kTestVerb = TEXT("SevenTest"); -static LPCTSTR kCompressVerb = TEXT("SevenCompress"); -static LPCTSTR kCompressToVerb = TEXT("SevenCompressTo"); -static LPCTSTR kCompressEmailVerb = TEXT("SevenCompressEmail"); -static LPCTSTR kCompressToEmailVerb = TEXT("SevenCompressToEmail"); -*/ struct CContextMenuCommand { UInt32 flag; CZipContextMenu::ECommandInternalID CommandInternalID; - LPCWSTR Verb; + LPCSTR Verb; UINT ResourceID; }; @@ -158,67 +147,67 @@ static const CContextMenuCommand g_Commands[] = { NContextMenuFlags::kOpen, CZipContextMenu::kOpen, - L"Open", + "Open", IDS_CONTEXT_OPEN }, { NContextMenuFlags::kExtract, CZipContextMenu::kExtract, - L"Extract", + "Extract", IDS_CONTEXT_EXTRACT }, { NContextMenuFlags::kExtractHere, CZipContextMenu::kExtractHere, - L"ExtractHere", + "ExtractHere", IDS_CONTEXT_EXTRACT_HERE }, { NContextMenuFlags::kExtractTo, CZipContextMenu::kExtractTo, - L"ExtractTo", + "ExtractTo", IDS_CONTEXT_EXTRACT_TO }, { NContextMenuFlags::kTest, CZipContextMenu::kTest, - L"Test", + "Test", IDS_CONTEXT_TEST }, { NContextMenuFlags::kCompress, CZipContextMenu::kCompress, - L"Compress", + "Compress", IDS_CONTEXT_COMPRESS }, { NContextMenuFlags::kCompressEmail, CZipContextMenu::kCompressEmail, - L"CompressEmail", + "CompressEmail", IDS_CONTEXT_COMPRESS_EMAIL }, { NContextMenuFlags::kCompressTo7z, CZipContextMenu::kCompressTo7z, - L"CompressTo7z", + "CompressTo7z", IDS_CONTEXT_COMPRESS_TO }, { NContextMenuFlags::kCompressTo7zEmail, CZipContextMenu::kCompressTo7zEmail, - L"CompressTo7zEmail", + "CompressTo7zEmail", IDS_CONTEXT_COMPRESS_TO_EMAIL }, { NContextMenuFlags::kCompressToZip, CZipContextMenu::kCompressToZip, - L"CompressToZip", + "CompressToZip", IDS_CONTEXT_COMPRESS_TO }, { NContextMenuFlags::kCompressToZipEmail, CZipContextMenu::kCompressToZipEmail, - L"CompressToZipEmail", + "CompressToZipEmail", IDS_CONTEXT_COMPRESS_TO_EMAIL } }; @@ -226,17 +215,17 @@ static const CContextMenuCommand g_Commands[] = struct CHashCommand { CZipContextMenu::ECommandInternalID CommandInternalID; - LPCWSTR UserName; - LPCWSTR MethodName; + LPCSTR UserName; + LPCSTR MethodName; }; static const CHashCommand g_HashCommands[] = { - { CZipContextMenu::kHash_CRC32, L"CRC-32", L"CRC32" }, - { CZipContextMenu::kHash_CRC64, L"CRC-64", L"CRC64" }, - { CZipContextMenu::kHash_SHA1, L"SHA-1", L"SHA1" }, - { CZipContextMenu::kHash_SHA256, L"SHA-256", L"SHA256" }, - { CZipContextMenu::kHash_All, L"*", L"*" } + { CZipContextMenu::kHash_CRC32, "CRC-32", "CRC32" }, + { CZipContextMenu::kHash_CRC64, "CRC-64", "CRC64" }, + { CZipContextMenu::kHash_SHA1, "SHA-1", "SHA1" }, + { CZipContextMenu::kHash_SHA256, "SHA-256", "SHA256" }, + { CZipContextMenu::kHash_All, "*", "*" } }; static int FindCommand(CZipContextMenu::ECommandInternalID &id) @@ -255,7 +244,8 @@ bool CZipContextMenu::FillCommand(ECommandInternalID id, UString &mainString, CC return false; const CContextMenuCommand &command = g_Commands[i]; commandMapItem.CommandInternalID = command.CommandInternalID; - commandMapItem.Verb = (UString)kMainVerb + (UString)command.Verb; + commandMapItem.Verb = kMainVerb; + commandMapItem.Verb += command.Verb; // LangString(command.ResourceHelpID, command.LangID + 1, commandMapItem.HelpString); LangString(command.ResourceID, mainString); return true; @@ -341,7 +331,7 @@ static void MyFormatNew_ReducedName(UString &s, const UString &name) s = MyFormatNew(s, GetQuotedReducedString(name)); } -static const char *kExtractExludeExtensions = +static const char * const kExtractExludeExtensions = " 3gp" " aac ans ape asc asm asp aspx avi awk" " bas bat bmp" @@ -353,7 +343,7 @@ static const char *kExtractExludeExtensions = " h hpp hta htm html hxx" " ico idl inc ini inl" " java jpeg jpg js" - " la log" + " la lnk log" " mak manifest wmv mov mp3 mp4 mpe mpeg mpg m4a" " ofr ogg" " pac pas pdf php php3 php4 php5 phptml pl pm png ps py pyo" @@ -366,7 +356,7 @@ static const char *kExtractExludeExtensions = " "; /* -static const char *kNoOpenAsExtensions = +static const char * const kNoOpenAsExtensions = " 7z arj bz2 cab chm cpio flv gz lha lzh lzma rar swm tar tbz2 tgz wim xar xz z zip "; */ @@ -419,7 +409,7 @@ static bool DoNeedExtract(const FString &name) } // we must use diferent Verbs for Popup subMenu. -void CZipContextMenu::AddMapItem_ForSubMenu(const wchar_t *verb) +void CZipContextMenu::AddMapItem_ForSubMenu(const char *verb) { CCommandMapItem commandMapItem; commandMapItem.CommandInternalID = kCommandNULL; @@ -498,9 +488,9 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, fi0.Name = us2fs(fileName.Ptr(NName::kDevicePathPrefixSize)); // change it 4 - must be constant folderPrefix = #ifdef UNDER_CE - FTEXT("\\"); + "\\"; #else - FTEXT("C:\\"); + "C:\\"; #endif } else @@ -555,9 +545,11 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, FillCommand(kOpen, mainString, commandMapItem); else { - mainString.SetFromAscii(kOpenTypes[i]); + mainString = kOpenTypes[i]; commandMapItem.CommandInternalID = kOpen; - commandMapItem.Verb = (UString)kMainVerb + L".Open." + mainString; + commandMapItem.Verb = kMainVerb; + commandMapItem.Verb += ".Open."; + commandMapItem.Verb += mainString; commandMapItem.HelpString = mainString; commandMapItem.ArcType = mainString; } @@ -599,7 +591,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (_dropMode) baseFolder = _dropPath; - UString specFolder = L'*'; + UString specFolder ('*'); if (_fileNames.Size() == 1) specFolder = GetSubFolderNameForExtract(fs2us(fi0.Name)); specFolder.Add_PathSepar(); @@ -653,8 +645,10 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, else arcName = CreateArchiveName(fileName, _fileNames.Size() > 1, false); - UString arcName7z = arcName + L".7z"; - UString arcNameZip = arcName + L".zip"; + UString arcName7z = arcName; + arcName7z += ".7z"; + UString arcNameZip = arcName; + arcNameZip += ".zip"; // Compress if ((contextMenuFlags & NContextMenuFlags::kCompress) != 0) @@ -694,7 +688,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, else commandMapItem.Folder = fs2us(folderPrefix); commandMapItem.ArcName = arcName7z; - commandMapItem.ArcType.SetFromAscii("7z"); + commandMapItem.ArcType = "7z"; MyFormatNew_ReducedName(s, arcName7z); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); @@ -708,7 +702,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UString s; FillCommand(kCompressTo7zEmail, s, commandMapItem); commandMapItem.ArcName = arcName7z; - commandMapItem.ArcType.SetFromAscii("7z"); + commandMapItem.ArcType = "7z"; MyFormatNew_ReducedName(s, arcName7z); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); @@ -727,7 +721,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, else commandMapItem.Folder = fs2us(folderPrefix); commandMapItem.ArcName = arcNameZip; - commandMapItem.ArcType.SetFromAscii("zip"); + commandMapItem.ArcType = "zip"; MyFormatNew_ReducedName(s, arcNameZip); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); @@ -741,7 +735,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UString s; FillCommand(kCompressToZipEmail, s, commandMapItem); commandMapItem.ArcName = arcNameZip; - commandMapItem.ArcType.SetFromAscii("zip"); + commandMapItem.ArcType = "zip"; MyFormatNew_ReducedName(s, arcNameZip); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); @@ -763,7 +757,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, mi.fMask |= MIIM_CHECKMARKS; mi.wID = currentCommandID++; mi.hSubMenu = popupMenu.Detach(); - mi.StringValue.SetFromAscii("7-Zip"); // LangString(IDS_CONTEXT_POPUP_CAPTION); + mi.StringValue = "7-Zip"; // LangString(IDS_CONTEXT_POPUP_CAPTION); mi.hbmpUnchecked = bitmap; CMenu menu; @@ -799,7 +793,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, mi.fMask |= MIIM_CHECKMARKS; mi.wID = currentCommandID++; mi.hSubMenu = subMenu; - mi.StringValue.SetFromAscii("CRC SHA"); + mi.StringValue = "CRC SHA"; mi.hbmpUnchecked = bitmap; CMenu menu; @@ -814,9 +808,10 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, const CHashCommand &hc = g_HashCommands[i]; CCommandMapItem commandMapItem; commandMapItem.CommandInternalID = hc.CommandInternalID; - commandMapItem.Verb = (UString)kCheckSumCascadedVerb + (UString)hc.MethodName; + commandMapItem.Verb = kCheckSumCascadedVerb; + commandMapItem.Verb += hc.MethodName; // commandMapItem.HelpString = hc.Name; - MyInsertMenu(subMenu, subIndex_CRC++, currentCommandID++, hc.UserName, bitmap); + MyInsertMenu(subMenu, subIndex_CRC++, currentCommandID++, (UString)hc.UserName, bitmap); _commandMap.Add(commandMapItem); } @@ -881,7 +876,7 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo) params = GetQuotedString(_fileNames[0]); if (!commandMapItem.ArcType.IsEmpty()) { - params += L" -t"; + params += " -t"; params += commandMapItem.ArcType; } MyCreateProcess(Get7zFmPath(), params); @@ -935,7 +930,7 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo) const CHashCommand &hc = g_HashCommands[i]; if (hc.CommandInternalID == cmdID) { - CalcChecksum(_fileNames, hc.MethodName); + CalcChecksum(_fileNames, (UString)hc.MethodName); break; } } diff --git a/CPP/7zip/UI/Explorer/ContextMenu.h b/CPP/7zip/UI/Explorer/ContextMenu.h index 53bf18de..3a0eacc8 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.h +++ b/CPP/7zip/UI/Explorer/ContextMenu.h @@ -79,7 +79,7 @@ private: HRESULT GetFileNames(LPDATAOBJECT dataObject, UStringVector &fileNames); int FindVerb(const UString &verb); bool FillCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &commandMapItem); - void AddMapItem_ForSubMenu(const wchar_t *ver); + void AddMapItem_ForSubMenu(const char *ver); }; #endif diff --git a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp index d02af9ef..c38d7257 100644 --- a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp +++ b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp @@ -25,11 +25,11 @@ #include "ContextMenu.h" -static LPCTSTR k_ShellExtName = TEXT("7-Zip Shell Extension"); -static LPCTSTR k_Approved = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"); +static LPCTSTR const k_ShellExtName = TEXT("7-Zip Shell Extension"); +static LPCTSTR const k_Approved = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"); // {23170F69-40C1-278A-1000-000100020000} -static LPCTSTR k_Clsid = TEXT("{23170F69-40C1-278A-1000-000100020000}"); +static LPCTSTR const k_Clsid = TEXT("{23170F69-40C1-278A-1000-000100020000}"); DEFINE_GUID(CLSID_CZipContextMenu, k_7zip_GUID_Data1, @@ -155,9 +155,8 @@ static BOOL RegisterServer() return FALSE; const UString modulePathU = fs2us(modulePath); - CSysString clsidString = k_Clsid; - CSysString s = TEXT("CLSID\\"); - s += clsidString; + CSysString s ("CLSID\\"); + s += k_Clsid; { NRegistry::CKey key; @@ -177,7 +176,7 @@ static BOOL RegisterServer() { NRegistry::CKey key; if (key.Create(HKEY_LOCAL_MACHINE, k_Approved, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE) == NOERROR) - key.SetValue(clsidString, k_ShellExtName); + key.SetValue(k_Clsid, k_ShellExtName); } return TRUE; @@ -190,13 +189,10 @@ STDAPI DllRegisterServer(void) static BOOL UnregisterServer() { - const CSysString clsidString = k_Clsid; - CSysString s = TEXT("CLSID\\"); - s += clsidString; - CSysString s2 = s; - s2.AddAscii("\\InprocServer32"); + CSysString s ("CLSID\\"); + s += k_Clsid; - RegDeleteKey(HKEY_CLASSES_ROOT, s2); + RegDeleteKey(HKEY_CLASSES_ROOT, s + TEXT("\\InprocServer32")); RegDeleteKey(HKEY_CLASSES_ROOT, s); #if !defined(_WIN64) && !defined(UNDER_CE) @@ -206,7 +202,7 @@ static BOOL UnregisterServer() HKEY hKey; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, k_Approved, 0, KEY_SET_VALUE, &hKey) == NOERROR) { - RegDeleteValue(hKey, clsidString); + RegDeleteValue(hKey, k_Clsid); RegCloseKey(hKey); } } diff --git a/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp b/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp index d83aa76e..c9d7910f 100644 --- a/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp @@ -17,21 +17,23 @@ using namespace NRegistry; // CLISID (and Approved ?) items are separated for 32-bit and 64-bit code. // shellex items shared by 32-bit and 64-bit code? -static LPCTSTR k_Clsid = TEXT("{23170F69-40C1-278A-1000-000100020000}"); -static LPCTSTR k_ShellExtName = TEXT("7-Zip Shell Extension"); +#define k_Clsid_A "{23170F69-40C1-278A-1000-000100020000}" -static LPCTSTR k_Approved = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"); -static LPCTSTR k_Inproc = TEXT("InprocServer32"); +static LPCTSTR const k_Clsid = TEXT(k_Clsid_A); +static LPCTSTR const k_ShellExtName = TEXT("7-Zip Shell Extension"); -static LPCTSTR k_KeyPostfix_ContextMenu = TEXT("\\shellex\\ContextMenuHandlers\\7-Zip"); -static LPCTSTR k_KeyPostfix_DragDrop = TEXT("\\shellex\\DragDropHandlers\\7-Zip"); +static LPCTSTR const k_Approved = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"); +static LPCTSTR const k_Inproc = TEXT("InprocServer32"); -static LPCTSTR k_KeyName_File = TEXT("*"); -static LPCTSTR k_KeyName_Folder = TEXT("Folder"); -static LPCTSTR k_KeyName_Directory = TEXT("Directory"); -static LPCTSTR k_KeyName_Drive = TEXT("Drive"); +static LPCSTR const k_KeyPostfix_ContextMenu = "\\shellex\\ContextMenuHandlers\\7-Zip"; +static LPCSTR const k_KeyPostfix_DragDrop = "\\shellex\\DragDropHandlers\\7-Zip"; -static LPCTSTR const k_shellex_Prefixes[] = +static LPCSTR const k_KeyName_File = "*"; +static LPCSTR const k_KeyName_Folder = "Folder"; +static LPCSTR const k_KeyName_Directory = "Directory"; +static LPCSTR const k_KeyName_Drive = "Drive"; + +static LPCSTR const k_shellex_Prefixes[] = { k_KeyName_File, k_KeyName_Folder, @@ -95,32 +97,32 @@ static LONG MyRegistry_DeleteKey_HKCR(LPCTSTR name, UInt32 wow) // static NSynchronization::CCriticalSection g_CS; -static CSysString Get_ContextMenuHandler_KeyName(const CSysString &keyName) - { return (keyName + k_KeyPostfix_ContextMenu); } +static AString Get_ContextMenuHandler_KeyName(LPCSTR keyName) + { return (AString)keyName + k_KeyPostfix_ContextMenu; } /* -static CSysString Get_DragDropHandler_KeyName(const CSysString &keyName) - { return (keyName + k_KeyPostfix_DragDrop); } +static CSysString Get_DragDropHandler_KeyName(LPCTSTR keyName) + { return (AString)keyName + k_KeyPostfix_DragDrop); } */ -static bool CheckHandlerCommon(const CSysString &keyName, UInt32 wow) +static bool CheckHandlerCommon(const AString &keyName, UInt32 wow) { CKey key; - if (key.Open(HKEY_CLASSES_ROOT, keyName, KEY_READ | wow) != ERROR_SUCCESS) + if (key.Open(HKEY_CLASSES_ROOT, (CSysString)keyName, KEY_READ | wow) != ERROR_SUCCESS) return false; CSysString value; if (key.QueryValue(NULL, value) != ERROR_SUCCESS) return false; - return StringsAreEqualNoCase_Ascii(value, k_Clsid); + return StringsAreEqualNoCase_Ascii(value, k_Clsid_A); } bool CheckContextMenuHandler(const UString &path, UInt32 wow) { // NSynchronization::CCriticalSectionLock lock(g_CS); - CSysString s = TEXT("CLSID\\"); - s += k_Clsid; - s.AddAscii("\\InprocServer32"); + CSysString s ("CLSID\\"); + s += k_Clsid_A; + s += "\\InprocServer32"; { NRegistry::CKey key; @@ -160,8 +162,8 @@ LONG SetContextMenuHandler(bool setMode, const UString &path, UInt32 wow) LONG res; { - CSysString s = TEXT("CLSID\\"); - s += k_Clsid; + CSysString s ("CLSID\\"); + s += k_Clsid_A; if (setMode) { @@ -189,8 +191,8 @@ LONG SetContextMenuHandler(bool setMode, const UString &path, UInt32 wow) } else { - CSysString s2 = s; - s2.AddAscii("\\InprocServer32"); + CSysString s2 (s); + s2 += "\\InprocServer32"; MyRegistry_DeleteKey_HKCR(s2, wow); res = MyRegistry_DeleteKey_HKCR(s, wow); @@ -203,7 +205,7 @@ LONG SetContextMenuHandler(bool setMode, const UString &path, UInt32 wow) { for (unsigned k = 0; k < ARRAY_SIZE(k_shellex_Prefixes); k++) { - CSysString s = k_shellex_Prefixes[k]; + CSysString s (k_shellex_Prefixes[k]); s += (i == 0 ? k_KeyPostfix_ContextMenu : k_KeyPostfix_DragDrop); if (k_shellex_Statuses[i][k]) { diff --git a/CPP/7zip/UI/Far/ExtractEngine.cpp b/CPP/7zip/UI/Far/ExtractEngine.cpp index c21655fd..04bad724 100644 --- a/CPP/7zip/UI/Far/ExtractEngine.cpp +++ b/CPP/7zip/UI/Far/ExtractEngine.cpp @@ -6,7 +6,6 @@ #include "../../../Windows/Synchronization.h" #endif -#include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #include "ExtractEngine.h" @@ -128,9 +127,9 @@ STDMETHODIMP CExtractCallbackImp::AskOverwrite( return CheckBreak2(); } -static const char *kTestString = "Testing"; -static const char *kExtractString = "Extracting"; -static const char *kSkipString = "Skipping"; +static const char * const kTestString = "Testing"; +static const char * const kExtractString = "Extracting"; +static const char * const kSkipString = "Skipping"; STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, Int32 /* isFolder */, Int32 askExtractMode, const UInt64 * /* position */) { @@ -161,7 +160,7 @@ STDMETHODIMP CExtractCallbackImp::MessageError(const wchar_t *message) { MT_LOCK - AString s = UnicodeStringToMultiByte(message, CP_OEMCP); + AString s (UnicodeStringToMultiByte(message, CP_OEMCP)); if (g_StartupInfo.ShowErrorMessage((const char *)s) == -1) return E_ABORT; @@ -198,7 +197,7 @@ void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &s) if (messageID != 0) { s = g_StartupInfo.GetMsgString(messageID); - s.Replace(" '%s'", ""); + s.Replace((AString)" '%s'", AString()); } else if (opRes == NArchive::NExtract::NOperationResult::kUnavailable) s = "Unavailable data"; @@ -212,10 +211,8 @@ void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &s) s = "kHeaders Error"; else { - char temp[16]; - ConvertUInt32ToString(opRes, temp); s = "Error #"; - s += temp; + s.Add_UInt32(opRes); } } } diff --git a/CPP/7zip/UI/Far/Far.cpp b/CPP/7zip/UI/Far/Far.cpp index 7c0876dd..cec4af52 100644 --- a/CPP/7zip/UI/Far/Far.cpp +++ b/CPP/7zip/UI/Far/Far.cpp @@ -25,10 +25,10 @@ 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"); -static const char *kHelpTopicConfig = "Config"; +static const char * const kCommandPrefix = "7-zip"; +static const char * const kRegisrtryMainKeyName = NULL; // "" +static LPCTSTR const kRegisrtryValueNameEnabled = TEXT("UsedByDefault3"); +static const char * const kHelpTopicConfig = "Config"; static bool kPluginEnabledDefault = true; HINSTANCE g_hInstance; @@ -67,7 +67,7 @@ static struct COptions bool Enabled; } g_Options; -static const TCHAR *kPliginNameForRegestry = TEXT("7-ZIP"); +static const char * const kPliginNameForRegistry = "7-ZIP"; EXTERN_C void WINAPI ExitFAR() { @@ -84,7 +84,7 @@ EXTERN_C void WINAPI ExitFAR() EXTERN_C void WINAPI SetStartupInfo(const PluginStartupInfo *info) { MY_TRY_BEGIN; - g_StartupInfo.Init(*info, kPliginNameForRegestry); + g_StartupInfo.Init(*info, kPliginNameForRegistry); g_Options.Enabled = g_StartupInfo.QueryRegKeyValue( HKEY_CURRENT_USER, kRegisrtryMainKeyName, kRegisrtryValueNameEnabled, kPluginEnabledDefault); @@ -299,8 +299,7 @@ HRESULT GetPassword(UString &password) if (g_StartupInfo.ShowDialog(76, 6, NULL, dialogItems, kNumItems) < 0) return E_ABORT; - AString oemPassword = dialogItems[2].Data; - password = MultiByteToUnicodeString(oemPassword, CP_OEMCP); + password = MultiByteToUnicodeString(dialogItems[2].Data, CP_OEMCP); return S_OK; } @@ -449,7 +448,7 @@ EXTERN_C HANDLE WINAPI OpenPlugin(int openFrom, INT_PTR item) if (openFrom == OPEN_COMMANDLINE) { - AString fileName = (const char *)item; + AString fileName ((const char *)item); if (fileName.IsEmpty()) return INVALID_HANDLE_VALUE; if (fileName.Len() >= 2 @@ -522,9 +521,9 @@ EXTERN_C int WINAPI GetFindData(HANDLE plugin, struct PluginPanelItem **panelIte EXTERN_C void WINAPI FreeFindData(HANDLE plugin, struct PluginPanelItem *panelItems, int itemsNumber) { - MY_TRY_BEGIN; + // MY_TRY_BEGIN; ((CPlugin *)plugin)->FreeFindData(panelItems, itemsNumber); - MY_TRY_END1("FreeFindData"); + // MY_TRY_END1("FreeFindData"); } EXTERN_C int WINAPI GetFiles(HANDLE plugin, struct PluginPanelItem *panelItems, diff --git a/CPP/7zip/UI/Far/FarUtils.cpp b/CPP/7zip/UI/Far/FarUtils.cpp index cc058ef9..ddca3cab 100644 --- a/CPP/7zip/UI/Far/FarUtils.cpp +++ b/CPP/7zip/UI/Far/FarUtils.cpp @@ -2,7 +2,7 @@ #include "StdAfx.h" -#include "../../../Common/IntToString.h" +// #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #ifndef UNDER_CE @@ -19,13 +19,15 @@ namespace NFar { CStartupInfo g_StartupInfo; +const char kRegistryKeyDelimiter = '\\'; + void CStartupInfo::Init(const PluginStartupInfo &pluginStartupInfo, - const CSysString &pluginNameForRegestry) + const char *pluginNameForRegistry) { m_Data = pluginStartupInfo; - m_RegistryPath = GetSystemString(pluginStartupInfo.RootKey); - m_RegistryPath += TEXT('\\'); - m_RegistryPath += pluginNameForRegestry; + m_RegistryPath = pluginStartupInfo.RootKey; + m_RegistryPath += kRegistryKeyDelimiter; + m_RegistryPath += pluginNameForRegistry; } const char *CStartupInfo::GetMsgString(int messageId) @@ -114,7 +116,7 @@ static void SplitString(const AString &src, AStringVector &destStrings) int CStartupInfo::ShowErrorMessage(const char *message) { AStringVector strings; - SplitString(message, strings); + SplitString((AString)message, strings); const unsigned kNumStringsMax = 20; const char *items[kNumStringsMax + 1]; unsigned pos = 0; @@ -209,28 +211,31 @@ void CStartupInfo::RestoreScreen(HANDLE handle) m_Data.RestoreScreen(handle); } -const TCHAR kRegestryKeyDelimiter = TEXT('\''); - -CSysString CStartupInfo::GetFullKeyName(const CSysString &keyName) const +CSysString CStartupInfo::GetFullKeyName(const char *keyName) const { - return (keyName.IsEmpty()) ? m_RegistryPath: - (m_RegistryPath + kRegestryKeyDelimiter + keyName); + AString s = m_RegistryPath; + if (keyName && *keyName) + { + s += kRegistryKeyDelimiter; + s += keyName; + } + return (CSysString)s; } LONG CStartupInfo::CreateRegKey(HKEY parentKey, - const CSysString &keyName, NRegistry::CKey &destKey) const + const char *keyName, NRegistry::CKey &destKey) const { return destKey.Create(parentKey, GetFullKeyName(keyName)); } LONG CStartupInfo::OpenRegKey(HKEY parentKey, - const CSysString &keyName, NRegistry::CKey &destKey) const + const char *keyName, NRegistry::CKey &destKey) const { return destKey.Open(parentKey, GetFullKeyName(keyName)); } -void CStartupInfo::SetRegKeyValue(HKEY parentKey, const CSysString &keyName, +void CStartupInfo::SetRegKeyValue(HKEY parentKey, const char *keyName, LPCTSTR valueName, LPCTSTR value) const { NRegistry::CKey regKey; @@ -238,7 +243,7 @@ void CStartupInfo::SetRegKeyValue(HKEY parentKey, const CSysString &keyName, regKey.SetValue(valueName, value); } -void CStartupInfo::SetRegKeyValue(HKEY parentKey, const CSysString &keyName, +void CStartupInfo::SetRegKeyValue(HKEY parentKey, const char *keyName, LPCTSTR valueName, UInt32 value) const { NRegistry::CKey regKey; @@ -246,7 +251,7 @@ void CStartupInfo::SetRegKeyValue(HKEY parentKey, const CSysString &keyName, regKey.SetValue(valueName, value); } -void CStartupInfo::SetRegKeyValue(HKEY parentKey, const CSysString &keyName, +void CStartupInfo::SetRegKeyValue(HKEY parentKey, const char *keyName, LPCTSTR valueName, bool value) const { NRegistry::CKey regKey; @@ -254,7 +259,7 @@ void CStartupInfo::SetRegKeyValue(HKEY parentKey, const CSysString &keyName, regKey.SetValue(valueName, value); } -CSysString CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyName, +CSysString CStartupInfo::QueryRegKeyValue(HKEY parentKey, const char *keyName, LPCTSTR valueName, const CSysString &valueDefault) const { NRegistry::CKey regKey; @@ -268,7 +273,7 @@ CSysString CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyN return value; } -UInt32 CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyName, +UInt32 CStartupInfo::QueryRegKeyValue(HKEY parentKey, const char *keyName, LPCTSTR valueName, UInt32 valueDefault) const { NRegistry::CKey regKey; @@ -282,7 +287,7 @@ UInt32 CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyName, return value; } -bool CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyName, +bool CStartupInfo::QueryRegKeyValue(HKEY parentKey, const char *keyName, LPCTSTR valueName, bool valueDefault) const { NRegistry::CKey regKey; @@ -390,7 +395,7 @@ int CStartupInfo::Menu( unsigned int flags, const char *title, const char *helpTopic, - const CSysStringVector &items, + const AStringVector &items, int selectedItem) { CRecordVector<FarMenuItem> farMenuItems; @@ -400,8 +405,8 @@ int CStartupInfo::Menu( item.Checked = 0; item.Separator = 0; item.Selected = ((int)i == selectedItem); - CSysString reducedString = items[i].Left(ARRAY_SIZE(item.Text) - 1); - MyStringCopy(item.Text, (const char *)GetOemString(reducedString)); + const AString reducedString (items[i].Left(ARRAY_SIZE(item.Text) - 1)); + MyStringCopy(item.Text, reducedString); farMenuItems.Add(item); } return Menu(flags, title, helpTopic, &farMenuItems.Front(), farMenuItems.Size()); @@ -434,11 +439,9 @@ void CScreenRestorer::Restore() int PrintErrorMessage(const char *message, unsigned code) { - AString s = message; + AString s (message); s += " #"; - char temp[16]; - ConvertUInt32ToString((UInt32)code, temp); - s += temp; + s.Add_UInt32((UInt32)code); return g_StartupInfo.ShowErrorMessage(s); } @@ -479,10 +482,10 @@ int ShowLastErrorMessage() 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); + const UString s = NError::MyFormatMessage(errorCode); + return g_StartupInfo.ShowErrorMessage2( + UnicodeStringToMultiByte(s, CP_OEMCP), + UnicodeStringToMultiByte(name, CP_OEMCP)); } diff --git a/CPP/7zip/UI/Far/FarUtils.h b/CPP/7zip/UI/Far/FarUtils.h index 5617c6c8..38f64f98 100644 --- a/CPP/7zip/UI/Far/FarUtils.h +++ b/CPP/7zip/UI/Far/FarUtils.h @@ -47,17 +47,17 @@ struct CInitDialogItem class CStartupInfo { PluginStartupInfo m_Data; - CSysString m_RegistryPath; + AString m_RegistryPath; - CSysString GetFullKeyName(const CSysString &keyName) const; + CSysString GetFullKeyName(const char *keyName) const; LONG CreateRegKey(HKEY parentKey, - const CSysString &keyName, NWindows::NRegistry::CKey &destKey) const; + const char *keyName, NWindows::NRegistry::CKey &destKey) const; LONG OpenRegKey(HKEY parentKey, - const CSysString &keyName, NWindows::NRegistry::CKey &destKey) const; + const char *keyName, NWindows::NRegistry::CKey &destKey) const; public: void Init(const PluginStartupInfo &pluginStartupInfo, - const CSysString &pluginNameForRegestry); + const char *pluginNameForRegistry); const char *GetMsgString(int messageId); int ShowMessage(unsigned int flags, const char *helpTopic, @@ -82,20 +82,20 @@ public: HANDLE SaveScreen(); void RestoreScreen(HANDLE handle); - void SetRegKeyValue(HKEY parentKey, const CSysString &keyName, + void SetRegKeyValue(HKEY parentKey, const char *keyName, const LPCTSTR valueName, LPCTSTR value) const; - void SetRegKeyValue(HKEY hRoot, const CSysString &keyName, + void SetRegKeyValue(HKEY hRoot, const char *keyName, const LPCTSTR valueName, UInt32 value) const; - void SetRegKeyValue(HKEY hRoot, const CSysString &keyName, + void SetRegKeyValue(HKEY hRoot, const char *keyName, const LPCTSTR valueName, bool value) const; - CSysString QueryRegKeyValue(HKEY parentKey, const CSysString &keyName, + CSysString QueryRegKeyValue(HKEY parentKey, const char *keyName, LPCTSTR valueName, const CSysString &valueDefault) const; - UInt32 QueryRegKeyValue(HKEY parentKey, const CSysString &keyName, + UInt32 QueryRegKeyValue(HKEY parentKey, const char *keyName, LPCTSTR valueName, UInt32 valueDefault) const; - bool QueryRegKeyValue(HKEY parentKey, const CSysString &keyName, + bool QueryRegKeyValue(HKEY parentKey, const char *keyName, LPCTSTR valueName, bool valueDefault) const; bool Control(HANDLE plugin, int command, void *param); @@ -131,7 +131,7 @@ public: unsigned int flags, const char *title, const char *helpTopic, - const CSysStringVector &items, + const AStringVector &items, int selectedItem); int Editor(const char *fileName, const char *title, diff --git a/CPP/7zip/UI/Far/OverwriteDialogFar.cpp b/CPP/7zip/UI/Far/OverwriteDialogFar.cpp index e950f695..1171453e 100644 --- a/CPP/7zip/UI/Far/OverwriteDialogFar.cpp +++ b/CPP/7zip/UI/Far/OverwriteDialogFar.cpp @@ -43,23 +43,31 @@ void SetFileInfoStrings(const CFileInfo &fileInfo, fileInfoStrings.Size = ""; } - FILETIME localFileTime; fileInfoStrings.Time.Empty(); if (fileInfo.TimeIsDefined) { - if (!FileTimeToLocalFileTime(&fileInfo.Time, &localFileTime)) - throw 4190402; char timeString[32]; - ConvertFileTimeToString(localFileTime, timeString); + ConvertUtcFileTimeToString(fileInfo.Time, timeString); fileInfoStrings.Time = g_StartupInfo.GetMsgString(NMessageID::kOverwriteModifiedOn); fileInfoStrings.Time += ' '; fileInfoStrings.Time += timeString; } } +static void ReduceString2(UString &s, unsigned size) +{ + if (!s.IsEmpty() && s.Back() == ' ') + { + // s += (wchar_t)(0x2423); + s.InsertAtFront(L'\"'); + s += L'\"'; + } + ReduceString(s, size); +} + NResult::EEnum Execute(const CFileInfo &oldFileInfo, const CFileInfo &newFileInfo) { - const int kYSize = 20; + const int kYSize = 22; const int kXSize = 76; CFileInfoStrings oldFileInfoStrings; @@ -68,17 +76,30 @@ NResult::EEnum Execute(const CFileInfo &oldFileInfo, const CFileInfo &newFileInf SetFileInfoStrings(oldFileInfo, oldFileInfoStrings); SetFileInfoStrings(newFileInfo, newFileInfoStrings); - UString oldName2 = oldFileInfo.Name; - UString newName2 = newFileInfo.Name; + const UString &oldName2 = oldFileInfo.Name; + const UString &newName2 = newFileInfo.Name; + + int slashPos = oldName2.ReverseFind_PathSepar(); + UString pref1 = oldName2.Left(slashPos + 1); + UString name1 = oldName2.Ptr(slashPos + 1); + + slashPos = newName2.ReverseFind_PathSepar(); + UString pref2 = newName2.Left(slashPos + 1); + UString name2 = newName2.Ptr(slashPos + 1); + const unsigned kNameOffset = 2; { const unsigned maxNameLen = kXSize - 9 - 2; - ReduceString(oldName2, maxNameLen); - ReduceString(newName2, maxNameLen); + ReduceString(pref1, maxNameLen); + ReduceString(pref2, maxNameLen); + ReduceString2(name1, maxNameLen - kNameOffset); + ReduceString2(name2, maxNameLen - kNameOffset); } - AString oldName = UnicodeStringToMultiByte(oldName2); - AString newName = UnicodeStringToMultiByte(newName2); + AString pref1A (UnicodeStringToMultiByte(pref1, CP_OEMCP)); + AString pref2A (UnicodeStringToMultiByte(pref2, CP_OEMCP)); + AString name1A (UnicodeStringToMultiByte(name1, CP_OEMCP)); + AString name2A (UnicodeStringToMultiByte(name2, CP_OEMCP)); struct CInitDialogItem initItems[]={ { DI_DOUBLEBOX, 3, 1, kXSize - 4, kYSize - 2, false, false, 0, false, NMessageID::kOverwriteTitle, NULL, NULL }, @@ -88,15 +109,17 @@ NResult::EEnum Execute(const CFileInfo &oldFileInfo, const CFileInfo &newFileInf { DI_TEXT, 5, 4, 0, 0, false, false, 0, false, NMessageID::kOverwriteMessageWouldYouLike, NULL, NULL }, - { DI_TEXT, 7, 6, 0, 0, false, false, 0, false, -1, oldName, NULL }, - { DI_TEXT, 7, 7, 0, 0, false, false, 0, false, -1, oldFileInfoStrings.Size, NULL }, - { DI_TEXT, 7, 8, 0, 0, false, false, 0, false, -1, oldFileInfoStrings.Time, NULL }, + { DI_TEXT, 7, 6, 0, 0, false, false, 0, false, -1, pref1A, NULL }, + { DI_TEXT, 7 + kNameOffset, 7, 0, 0, false, false, 0, false, -1, name1A, NULL }, + { DI_TEXT, 7, 8, 0, 0, false, false, 0, false, -1, oldFileInfoStrings.Size, NULL }, + { DI_TEXT, 7, 9, 0, 0, false, false, 0, false, -1, oldFileInfoStrings.Time, NULL }, - { DI_TEXT, 5, 10, 0, 0, false, false, 0, false, NMessageID::kOverwriteMessageWithtTisOne, NULL, NULL }, + { DI_TEXT, 5, 11, 0, 0, false, false, 0, false, NMessageID::kOverwriteMessageWithtTisOne, NULL, NULL }, - { DI_TEXT, 7, 12, 0, 0, false, false, 0, false, -1, newName, NULL }, - { DI_TEXT, 7, 13, 0, 0, false, false, 0, false, -1, newFileInfoStrings.Size, NULL }, - { DI_TEXT, 7, 14, 0, 0, false, false, 0, false, -1, newFileInfoStrings.Time, NULL }, + { DI_TEXT, 7, 13, 0, 0, false, false, 0, false, -1, pref2A, NULL }, + { DI_TEXT, 7 + kNameOffset, 14, 0, 0, false, false, 0, false, -1, name2A, NULL }, + { DI_TEXT, 7, 15, 0, 0, false, false, 0, false, -1, newFileInfoStrings.Size, NULL }, + { DI_TEXT, 7, 16, 0, 0, false, false, 0, false, -1, newFileInfoStrings.Time, NULL }, { DI_TEXT, 3, kYSize - 5, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL }, diff --git a/CPP/7zip/UI/Far/Plugin.cpp b/CPP/7zip/UI/Far/Plugin.cpp index 607cdfe3..72f81ac9 100644 --- a/CPP/7zip/UI/Far/Plugin.cpp +++ b/CPP/7zip/UI/Far/Plugin.cpp @@ -30,7 +30,8 @@ int CompareFileNames_ForFolderList(const wchar_t *s1, const wchar_t *s2) CPlugin::CPlugin(const FString &fileName, CAgent *agent, UString archiveTypeName): _agent(agent), m_FileName(fileName), - _archiveTypeName(archiveTypeName) + _archiveTypeName(archiveTypeName), + PasswordIsDefined(false) { m_ArchiveHandler = agent; if (!m_FileInfo.Find(m_FileName)) @@ -82,7 +83,7 @@ void CPlugin::ReadPluginPanelItem(PluginPanelItem &panelItem, UInt32 itemIndex) if (prop.vt != VT_BSTR) throw 272340; - AString oemString = UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP); + AString oemString (UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP)); if (oemString == "..") oemString = kDotsReplaceString; @@ -193,7 +194,7 @@ void CPlugin::EnterToDirectory(const UString &dirName) CMyComPtr<IFolderFolder> newFolder; UString s = dirName; if (dirName == kDotsReplaceStringU) - s = L".."; + s = ".."; _folder->BindToFolder(s, &newFolder); if (!newFolder) if (dirName.IsEmpty()) @@ -281,7 +282,7 @@ void CPlugin::SetCurrentDirVar() } } -static const char *kPluginFormatName = "7-ZIP"; +static const char * const kPluginFormatName = "7-ZIP"; static int FindPropNameID(PROPID propID) @@ -371,17 +372,17 @@ static AString GetNameOfProp(PROPID propID, const wchar_t *name) { int farID = FindPropNameID(propID); if (farID >= 0) - return g_StartupInfo.GetMsgString(farID); + return (AString)g_StartupInfo.GetMsgString(farID); if (name) - return UnicodeStringToMultiByte((const wchar_t *)name, CP_OEMCP); + return UnicodeStringToMultiByte(name, CP_OEMCP); char s[16]; ConvertUInt32ToString(propID, s); - return s; + return (AString)s; } static AString GetNameOfProp2(PROPID propID, const wchar_t *name) { - AString s = GetNameOfProp(propID, name); + AString s (GetNameOfProp(propID, name)); if (s.Len() > (kInfoPanelLineSize - 1)) s.DeleteFrom(kInfoPanelLineSize - 1); return s; @@ -403,14 +404,14 @@ static AString ConvertSizeToString(UInt64 value) } while (i > 0) s[--pos] = s[--i]; - return s + pos; + return (AString)(s + pos); } static AString PropToString(const NCOM::CPropVariant &prop, PROPID propID) { if (prop.vt == VT_BSTR) { - AString s = UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP); + AString s (UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP)); s.Replace((char)0xA, ' '); s.Replace((char)0xD, ' '); return s; @@ -419,7 +420,7 @@ static AString PropToString(const NCOM::CPropVariant &prop, PROPID propID) { int messageID = VARIANT_BOOLToBool(prop.boolVal) ? NMessageID::kYes : NMessageID::kNo; - return g_StartupInfo.GetMsgString(messageID); + return (AString)g_StartupInfo.GetMsgString(messageID); } if (prop.vt != VT_EMPTY) { @@ -441,8 +442,8 @@ static AString PropToString(const NCOM::CPropVariant &prop, PROPID propID) } { char sz[64]; - ConvertPropertyToShortString(sz, prop, propID); - return sz; + ConvertPropertyToShortString2(sz, prop, propID); + return (AString)sz; } } return AString(); @@ -450,7 +451,7 @@ static AString PropToString(const NCOM::CPropVariant &prop, PROPID propID) static AString PropToString2(const NCOM::CPropVariant &prop, PROPID propID) { - AString s = PropToString(prop, propID); + AString s (PropToString(prop, propID)); if (s.Len() > (kInfoPanelLineSize - 1)) s.DeleteFrom(kInfoPanelLineSize - 1); return s; @@ -461,7 +462,7 @@ static void AddPropertyString(InfoPanelLine *lines, int &numItems, PROPID propID { if (prop.vt != VT_EMPTY) { - AString val = PropToString2(prop, propID); + AString val (PropToString2(prop, propID)); if (!val.IsEmpty()) { InfoPanelLine &item = lines[numItems++]; @@ -504,9 +505,9 @@ void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info) name = fs2us(fileName); } - m_PannelTitle = L' '; + m_PannelTitle = ' '; m_PannelTitle += _archiveTypeName; - m_PannelTitle += L':'; + m_PannelTitle += ':'; m_PannelTitle += name; m_PannelTitle.Add_Space(); if (!m_CurrentDir.IsEmpty()) @@ -748,8 +749,7 @@ HRESULT CPlugin::ShowAttributesWindow() NCOM::CPropVariant prop; RINOK(_folder->GetProperty(itemIndex, property.ID, &prop)); - AString s = PropToString(prop, property.ID); - values.Add(s); + values.Add(PropToString(prop, property.ID)); { const CInitDialogItem idi = @@ -803,10 +803,8 @@ HRESULT CPlugin::ShowAttributesWindow() const UInt32 kMaxDataSize = 64; if (dataSize > kMaxDataSize) { - char temp[64]; s += "data:"; - ConvertUInt32ToString(dataSize, temp); - s += temp; + s.Add_UInt32(dataSize); } else { diff --git a/CPP/7zip/UI/Far/PluginDelete.cpp b/CPP/7zip/UI/Far/PluginDelete.cpp index e1a103ac..95584341 100644 --- a/CPP/7zip/UI/Far/PluginDelete.cpp +++ b/CPP/7zip/UI/Far/PluginDelete.cpp @@ -84,6 +84,8 @@ int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode) CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec); updateCallbackSpec->Init(/* m_ArchiveHandler, */ progressBoxPointer); + updateCallbackSpec->PasswordIsDefined = PasswordIsDefined; + updateCallbackSpec->Password = Password; /* outArchive->SetFolder(_folder); diff --git a/CPP/7zip/UI/Far/PluginRead.cpp b/CPP/7zip/UI/Far/PluginRead.cpp index 433e8140..9df4a09f 100644 --- a/CPP/7zip/UI/Far/PluginRead.cpp +++ b/CPP/7zip/UI/Far/PluginRead.cpp @@ -21,11 +21,11 @@ using namespace NFile; using namespace NDir; using namespace NFar; -static const char *kHelpTopicExtrFromSevenZip = "Extract"; +static const char * const kHelpTopicExtrFromSevenZip = "Extract"; -static const char kDirDelimiter = '\\'; +static const char kDirDelimiter = CHAR_PATH_SEPARATOR; -static const char *kExractPathHistoryName = "7-ZipExtractPath"; +static const char * const kExractPathHistoryName = "7-ZipExtractPath"; HRESULT CPlugin::ExtractFiles( bool decompressAllItems, @@ -95,7 +95,7 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa return NFileOperationReturnCode::kError; } - AString destPath = destPathLoc; + AString destPath (destPathLoc); UString destPathU = GetUnicodeString(destPath, CP_OEMCP); NName::NormalizeDirPathPrefix(destPathU); destPath = UnicodeStringToMultiByte(destPathU, CP_OEMCP); @@ -127,7 +127,7 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa const int kXMid = kXSize / 2; - AString oemPassword = UnicodeStringToMultiByte(password, CP_OEMCP); + AString oemPassword (UnicodeStringToMultiByte(password, CP_OEMCP)); struct CInitDialogItem initItems[]={ { DI_DOUBLEBOX, 3, 1, kXSize - 4, kYSize - 2, false, false, 0, false, NMessageID::kExtractTitle, NULL, NULL }, @@ -196,7 +196,7 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa if (destPathU.IsEmpty()) { #ifdef UNDER_CE - destPathU = L"\\"; + destPathU = "\\"; #else FString destPathF = us2fs(destPathU); if (!GetCurrentDir(destPathF)) diff --git a/CPP/7zip/UI/Far/PluginWrite.cpp b/CPP/7zip/UI/Far/PluginWrite.cpp index b22577af..ec0f119b 100644 --- a/CPP/7zip/UI/Far/PluginWrite.cpp +++ b/CPP/7zip/UI/Far/PluginWrite.cpp @@ -27,9 +27,9 @@ using namespace NFar; using namespace NUpdateArchive; -static const char *kHelpTopic = "Update"; +static const char * const kHelpTopic = "Update"; -static const char *kArchiveHistoryKeyName = "7-ZipArcName"; +static const char * const kArchiveHistoryKeyName = "7-ZipArcName"; static const UInt32 g_MethodMap[] = { 0, 1, 3, 5, 7, 9 }; @@ -38,13 +38,18 @@ static HRESULT SetOutProperties(IOutFolderArchive *outArchive, UInt32 method) CMyComPtr<ISetProperties> setProperties; if (outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties) == S_OK) { + /* UStringVector realNames; - realNames.Add(UString(L"x")); + realNames.Add(UString("x")); NCOM::CPropVariant value = (UInt32)method; CRecordVector<const wchar_t *> names; FOR_VECTOR (i, realNames) names.Add(realNames[i]); RINOK(setProperties->SetProperties(&names.Front(), &value, names.Size())); + */ + NCOM::CPropVariant value = (UInt32)method; + const wchar_t *name = L"x"; + RINOK(setProperties->SetProperties(&name, &value, 1)); } return S_OK; } @@ -219,6 +224,8 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles( CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec ); updateCallbackSpec->Init(/* m_ArchiveHandler, */ progressBoxPointer); + updateCallbackSpec->PasswordIsDefined = PasswordIsDefined; + updateCallbackSpec->Password = Password; if (SetOutProperties(outArchive, compressionInfo.Level) != S_OK) return NFileOperationReturnCode::kError; @@ -287,7 +294,7 @@ struct CParsedPath UString MergePath() const; }; -static const wchar_t kDirDelimiter = WCHAR_PATH_SEPARATOR; +static const char kDirDelimiter = CHAR_PATH_SEPARATOR; static const wchar_t kDiskDelimiter = L':'; namespace NPathType @@ -322,7 +329,7 @@ void CParsedPath::ParsePath(const UString &path) case NPathType::kUNC: { // the bug was fixed: - curPos = path.Find(kDirDelimiter, 2); + curPos = path.Find((wchar_t)kDirDelimiter, 2); if (curPos < 0) curPos = path.Len(); else @@ -355,7 +362,7 @@ static void SetArcName(UString &arcName, const CArcInfoEx &arcInfo) if (dotPos > slashPos + 1) arcName.DeleteFrom(dotPos); } - arcName += L'.'; + arcName += '.'; arcName += arcInfo.GetMainExt(); } @@ -444,7 +451,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) for (;;) { - AString archiveNameA = UnicodeStringToMultiByte(arcName, CP_OEMCP); + AString archiveNameA (UnicodeStringToMultiByte(arcName, CP_OEMCP)); const int kYSize = 16; const int kXMid = 38; @@ -456,7 +463,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) char updateAddToArchiveString[512]; { const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex]; - const AString s = UnicodeStringToMultiByte(arcInfo.Name, CP_OEMCP); + const AString s (UnicodeStringToMultiByte(arcInfo.Name, CP_OEMCP)); sprintf(updateAddToArchiveString, g_StartupInfo.GetMsgString(NMessageID::kUpdateAddToArchive), (const char *)s); } @@ -530,14 +537,14 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) if (askCode == kSelectarchiverButtonIndex) { CIntVector indices; - CSysStringVector archiverNames; + AStringVector archiverNames; FOR_VECTOR (k, codecs->Formats) { const CArcInfoEx &arc = codecs->Formats[k]; if (arc.UpdateEnabled) { indices.Add(k); - archiverNames.Add(GetSystemString(arc.Name, CP_OEMCP)); + archiverNames.Add(GetOemString(arc.Name)); } } @@ -704,7 +711,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) } -static const char *k_CreateFolder_History = "NewFolder"; // we use default FAR folder name +static const char * const k_CreateFolder_History = "NewFolder"; // we use default FAR folder name HRESULT CPlugin::CreateFolder() { @@ -720,7 +727,7 @@ HRESULT CPlugin::CreateFolder() const int kYSize = 8; const int kPathIndex = 2; - AString destPath = "New Folder"; + AString destPath ("New Folder"); const struct CInitDialogItem initItems[]={ { DI_DOUBLEBOX, 3, 1, kXSize - 4, kYSize - 2, false, false, 0, false, @@ -773,6 +780,8 @@ HRESULT CPlugin::CreateFolder() CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec); updateCallbackSpec->Init(/* m_ArchiveHandler, */ progressBoxPointer); + updateCallbackSpec->PasswordIsDefined = PasswordIsDefined; + updateCallbackSpec->Password = Password; HRESULT result; { @@ -797,7 +806,7 @@ HRESULT CPlugin::CreateFolder() if (g_StartupInfo.ControlGetActivePanelInfo(panelInfo)) { - AString destPath = GetOemString(destPathU); + const AString destPath (GetOemString(destPathU)); for (int i = 0; i < panelInfo.ItemsNumber; i++) { diff --git a/CPP/7zip/UI/Far/ProgressBox.cpp b/CPP/7zip/UI/Far/ProgressBox.cpp index 75467864..6efb132a 100644 --- a/CPP/7zip/UI/Far/ProgressBox.cpp +++ b/CPP/7zip/UI/Far/ProgressBox.cpp @@ -18,7 +18,7 @@ void CPercentPrinterState::ClearCurState() FileName.Empty(); } -void CProgressBox::Init(const AString &title) +void CProgressBox::Init(const char *title) { _title = title; _wasPrinted = false; @@ -218,14 +218,13 @@ void CProgressBox::Print() unsigned filled = 0; if (total != (UInt64)(Int64)-1 && total != 0) filled = (unsigned)(cur * numChars / total); + if (filled > numChars) + filled = numChars; unsigned i = 0; - if (filled < numChars) - { - for (i = 0; i < filled; i++) - _perc += '='; - } + for (i = 0; i < filled; i++) + _perc += (char)(Byte)0xDB; // '='; for (; i < numChars; i++) - _perc += '.'; + _perc += (char)(Byte)0xB0; // '.'; } _perc.Add_Space(); diff --git a/CPP/7zip/UI/Far/ProgressBox.h b/CPP/7zip/UI/Far/ProgressBox.h index 83731b38..54bdb4f1 100644 --- a/CPP/7zip/UI/Far/ProgressBox.h +++ b/CPP/7zip/UI/Far/ProgressBox.h @@ -76,7 +76,7 @@ public: MaxLen(60) {} - void Init(const AString &title); + void Init(const char *title); void Print(); }; diff --git a/CPP/7zip/UI/Far/UpdateCallbackFar.cpp b/CPP/7zip/UI/Far/UpdateCallbackFar.cpp index 18d1a2c9..3f0f206b 100644 --- a/CPP/7zip/UI/Far/UpdateCallbackFar.cpp +++ b/CPP/7zip/UI/Far/UpdateCallbackFar.cpp @@ -62,6 +62,20 @@ STDMETHODIMP CUpdateCallback100Imp::SetNumFiles(UInt64 numFiles) return CheckBreak2(); } + +STDMETHODIMP CUpdateCallback100Imp::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */) +{ + return S_OK; +} + +STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */) +{ + MT_LOCK + return CheckBreak2(); +} + + + STDMETHODIMP CUpdateCallback100Imp::SetTotal(UInt64 size) { MT_LOCK @@ -203,10 +217,21 @@ STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password) MT_LOCK *password = NULL; - if (!m_PasswordIsDefined) + if (!PasswordIsDefined) { - RINOK(GetPassword(m_Password)); - m_PasswordIsDefined = true; + RINOK(GetPassword(Password)); + PasswordIsDefined = true; } - return StringToBstr(m_Password, password); + return StringToBstr(Password, password); +} + +STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) +{ + MT_LOCK + + *password = NULL; + *passwordIsDefined = BoolToInt(PasswordIsDefined); + if (!PasswordIsDefined) + return S_OK; + return StringToBstr(Password, password); } diff --git a/CPP/7zip/UI/Far/UpdateCallbackFar.h b/CPP/7zip/UI/Far/UpdateCallbackFar.h index a2328669..d2c2c8ed 100644 --- a/CPP/7zip/UI/Far/UpdateCallbackFar.h +++ b/CPP/7zip/UI/Far/UpdateCallbackFar.h @@ -15,35 +15,45 @@ class CUpdateCallback100Imp: public IFolderArchiveUpdateCallback, public IFolderArchiveUpdateCallback2, public IFolderScanProgress, + public ICryptoGetTextPassword2, public ICryptoGetTextPassword, + public IArchiveOpenCallback, public CMyUnknownImp { // CMyComPtr<IInFolderArchive> _archiveHandler; CProgressBox *_percent; UInt64 _total; - bool m_PasswordIsDefined; - UString m_Password; public: - MY_UNKNOWN_IMP4( + + bool PasswordIsDefined; + UString Password; + + MY_UNKNOWN_IMP6( IFolderArchiveUpdateCallback, IFolderArchiveUpdateCallback2, IFolderScanProgress, - ICryptoGetTextPassword) + ICryptoGetTextPassword2, + ICryptoGetTextPassword, + IArchiveOpenCallback + ) INTERFACE_IProgress(;) INTERFACE_IFolderArchiveUpdateCallback(;) INTERFACE_IFolderArchiveUpdateCallback2(;) INTERFACE_IFolderScanProgress(;) + INTERFACE_IArchiveOpenCallback(;) STDMETHOD(CryptoGetTextPassword)(BSTR *password); + STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); CUpdateCallback100Imp(): _total(0) {} void Init(/* IInFolderArchive *archiveHandler, */ CProgressBox *progressBox) { // _archiveHandler = archiveHandler; _percent = progressBox; - m_PasswordIsDefined = false; + PasswordIsDefined = false; + Password.Empty(); } }; diff --git a/CPP/7zip/UI/FileManager/AboutDialog.cpp b/CPP/7zip/UI/FileManager/AboutDialog.cpp index 35e67753..a644474b 100644 --- a/CPP/7zip/UI/FileManager/AboutDialog.cpp +++ b/CPP/7zip/UI/FileManager/AboutDialog.cpp @@ -17,8 +17,8 @@ static const UInt32 kLangIDs[] = IDT_ABOUT_INFO }; -static LPCTSTR kHomePageURL = TEXT("http://www.7-zip.org/"); -static LPCWSTR kHelpTopic = L"start.htm"; +#define kHomePageURL TEXT("http://www.7-zip.org/") +#define kHelpTopic "start.htm" #define LLL_(quote) L##quote #define LLL(quote) LLL_(quote) @@ -26,14 +26,7 @@ static LPCWSTR kHelpTopic = L"start.htm"; bool CAboutDialog::OnInit() { LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); - UString s = L"7-Zip " LLL(MY_VERSION); - #ifdef MY_CPU_64BIT - s += L" ["; - AddLangString(s, IDS_PROP_BIT64); - s += L']'; - #endif - - SetItemText(IDT_ABOUT_VERSION, s); + SetItemText(IDT_ABOUT_VERSION, UString("7-Zip " MY_VERSION_CPU)); SetItemText(IDT_ABOUT_DATE, LLL(MY_DATE)); LangSetWindowText(*this, IDD_ABOUT); @@ -43,7 +36,7 @@ bool CAboutDialog::OnInit() void CAboutDialog::OnHelp() { - ShowHelpWindow(NULL, kHelpTopic); + ShowHelpWindow(kHelpTopic); } bool CAboutDialog::OnButtonClicked(int buttonID, HWND buttonHWND) diff --git a/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp b/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp index c209bf35..b7fbb235 100644 --- a/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp +++ b/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp @@ -274,7 +274,7 @@ STDMETHODIMP CAltStreamsFolder::BindToFolder(const wchar_t * /* name */, IFolder return E_INVALIDARG; } -static const CFSTR kSuperPrefix = FTEXT("\\\\?\\"); +// static CFSTR const kSuperPrefix = FTEXT("\\\\?\\"); STDMETHODIMP CAltStreamsFolder::BindToParentFolder(IFolderFolder **resultFolder) { @@ -408,7 +408,7 @@ static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback, const wchar_t *message, const FString &fileName) { UString s = message; - s += L" : "; + s += " : "; s += fs2us(fileName); return callback->ShowMessage(s); } @@ -417,7 +417,7 @@ static HRESULT SendMessageError(IFolderArchiveUpdateCallback *callback, const wchar_t *message, const FString &fileName) { UString s = message; - s += L" : "; + s += " : "; s += fs2us(fileName); return callback->UpdateErrorMessage(s); } @@ -629,7 +629,7 @@ static HRESULT CopyStream( if (IntToBool(writeAskResult)) { RINOK(callback->SetCurrentFilePath(fs2us(srcPath))); - FString destPathNew = us2fs((LPCOLESTR)destPathResult); + FString destPathNew (us2fs((LPCOLESTR)destPathResult)); RINOK(state.MyCopyFile(srcPath, destPathNew)); if (state.ErrorFileIndex >= 0) { @@ -712,7 +712,7 @@ STDMETHODIMP CAltStreamsFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UI } */ - FString destPath = us2fs(path); + FString destPath (us2fs(path)); if (destPath.IsEmpty() /* && !ExtractToStreamCallback */) return E_INVALIDARG; diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp index 6d5662de..dfc75b69 100644 --- a/CPP/7zip/UI/FileManager/App.cpp +++ b/CPP/7zip/UI/FileManager/App.cpp @@ -23,6 +23,7 @@ #include "FormatUtils.h" #include "IFolder.h" #include "LangUtils.h" +#include "MyLoadMenu.h" #include "RegistryUtils.h" #include "ViewSettings.h" @@ -37,7 +38,7 @@ using namespace NName; extern DWORD g_ComCtl32Version; extern HINSTANCE g_hInstance; -static CFSTR kTempDirPrefix = FTEXT("7zE"); +#define kTempDirPrefix FTEXT("7zE") void CPanelCallbackImp::OnTab() { @@ -281,9 +282,6 @@ void CApp::SaveToolbarChanges() } -void MyLoadMenu(); - - HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool needOpenArc, bool &archiveIsOpened, bool &encrypted) { _window.Attach(hwnd); @@ -460,7 +458,7 @@ static void AddSizeValue(UString &s, UInt64 size) static void AddValuePair1(UString &s, UINT resourceID, UInt64 size) { AddLangString(s, resourceID); - s += L": "; + s += ": "; AddSizeValue(s, size); s.Add_LF(); } @@ -470,14 +468,14 @@ void AddValuePair2(UString &s, UINT resourceID, UInt64 num, UInt64 size) if (num == 0) return; AddLangString(s, resourceID); - s += L": "; + s += ": "; s += ConvertSizeToString(num); if (size != (UInt64)(Int64)-1) { - s += L" ( "; + s += " ( "; AddSizeValue(s, size); - s += L" )"; + s += " )"; } s.Add_LF(); } @@ -529,14 +527,18 @@ UString CPanel::GetItemsInfoString(const CRecordVector<UInt32> &indices) for (i = 0; i < indices.Size() && (int)i < (int)kCopyDialog_NumInfoLines - 6; i++) { - info += L"\n "; + info.Add_LF(); + info += " "; int index = indices[i]; info += GetItemRelPath(index); if (IsItem_Folder(index)) info.Add_PathSepar(); } if (i != indices.Size()) - info += L"\n ..."; + { + info.Add_LF(); + info += " ..."; + } return info; } @@ -697,7 +699,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) else { if (indices.Size() == 1 && - !destPath.IsEmpty() && destPath.Back() != WCHAR_PATH_SEPARATOR) + !destPath.IsEmpty() && !IS_PATH_SEPAR(destPath.Back())) { int pos = destPath.ReverseFind_PathSepar(); if (pos < 0) @@ -810,7 +812,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) // srcPanel.InvalidateList(NULL, true); if (result != E_ABORT) - srcPanel.MessageBoxError(result, L"Error"); + srcPanel.MessageBoxError(result); // return; } @@ -862,12 +864,24 @@ void CApp::OnSetSubFolder(int srcPanelIndex) { if (srcPanel._folder->BindToParentFolder(&newFolder) != S_OK) return; + if (!newFolder) + { + const UString parentPrefix = srcPanel.GetParentDirPrefix(); + bool archiveIsOpened, encrypted; + destPanel.BindToPath(parentPrefix, UString(), archiveIsOpened, encrypted); + destPanel.RefreshListCtrl(); + return; + } } else { if (srcPanel._folder->BindToFolder(realIndex, &newFolder) != S_OK) return; } + + if (!newFolder) + return; + destPanel.CloseOpenFolders(); destPanel.SetNewFolder(newFolder); destPanel.RefreshListCtrl(); @@ -927,7 +941,7 @@ void CApp::RefreshTitle(bool always) { UString path = GetFocusedPanel()._currentFolderPrefix; if (path.IsEmpty()) - path = L"7-Zip"; // LangString(IDS_APP_TITLE); + path = "7-Zip"; // LangString(IDS_APP_TITLE); if (!always && path == PrevTitle) return; PrevTitle = path; diff --git a/CPP/7zip/UI/FileManager/App.h b/CPP/7zip/UI/FileManager/App.h index 9cc1066b..fa8eeaa7 100644 --- a/CPP/7zip/UI/FileManager/App.h +++ b/CPP/7zip/UI/FileManager/App.h @@ -195,7 +195,7 @@ public: void MoveTo() { OnCopy(true, false, GetFocusedPanelIndex()); } void Delete(bool toRecycleBin) { GetFocusedPanel().DeleteItems(toRecycleBin); } HRESULT CalculateCrc2(const UString &methodName); - void CalculateCrc(const UString &methodName); + void CalculateCrc(const char *methodName); void DiffFiles(); void Split(); void Combine(); @@ -259,7 +259,23 @@ public: void SetListSettings(); HRESULT SwitchOnOffOnePanel(); + CIntVector _timestampLevels; + bool GetFlatMode() { return Panels[LastFocusedPanel].GetFlatMode(); } + + int GetTimestampLevel() const { return Panels[LastFocusedPanel]._timestampLevel; } + void SetTimestampLevel(int level) + { + unsigned i; + for (i = 0; i < kNumPanelsMax; i++) + { + CPanel &panel = Panels[i]; + panel._timestampLevel = level; + if (panel.PanelCreated) + panel.RedrawListItems(); + } + } + // bool Get_ShowNtfsStrems_Mode() { return Panels[LastFocusedPanel].Get_ShowNtfsStrems_Mode(); } void ChangeFlatMode() { Panels[LastFocusedPanel].ChangeFlatMode(); } diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp index 066ac219..d8f9ebe8 100644 --- a/CPP/7zip/UI/FileManager/BrowseDialog.cpp +++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp @@ -209,7 +209,7 @@ bool CBrowseDialog::OnInit() if (!FilterDescription.IsEmpty()) s = FilterDescription; else if (ShowAllFiles) - s = L"*.*"; + s = "*.*"; else { FOR_VECTOR (i, Filters) @@ -468,11 +468,11 @@ bool CBrowseDialog::GetParentPath(const UString &path, UString &parentPrefix, US if (_topDirPrefix == path) return false; UString s = path; - if (s.Back() == WCHAR_PATH_SEPARATOR) + if (IS_PATH_SEPAR(s.Back())) s.DeleteBack(); if (s.IsEmpty()) return false; - if (s.Back() == WCHAR_PATH_SEPARATOR) + if (IS_PATH_SEPAR(s.Back())) return false; int pos = s.ReverseFind_PathSepar(); parentPrefix.SetFrom(s, pos + 1); @@ -531,7 +531,7 @@ HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selected #ifndef UNDER_CE bool isDrive = false; - if (pathPrefix.IsEmpty() || pathPrefix == kSuperPathPrefix) + if (pathPrefix.IsEmpty() || pathPrefix.IsEqualTo(kSuperPathPrefix)) { isDrive = true; FStringVector drives; @@ -551,7 +551,8 @@ HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selected else #endif { - CEnumerator enumerator(us2fs(pathPrefix + L'*')); + CEnumerator enumerator; + enumerator.SetDirPrefix(us2fs(pathPrefix)); for (;;) { bool found; @@ -596,7 +597,7 @@ HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selected if (_showDots && _topDirPrefix != DirPrefix) { item.iItem = index; - const UString itemName = L".."; + const UString itemName (".."); if (selectedName.IsEmpty()) cursorIndex = index; item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; @@ -642,16 +643,14 @@ HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selected _list.InsertItem(&item); wchar_t s[32]; { - FILETIME ft; s[0] = 0; - if (FileTimeToLocalFileTime(&fi.MTime, &ft)) - ConvertFileTimeToString(ft, s, + ConvertUtcFileTimeToString(fi.MTime, s, #ifndef UNDER_CE - true + kTimestampPrintLevel_MIN #else - false + kTimestampPrintLevel_DAY #endif - , false); + ); _list.SetSubItem(index, subItem++, s); } { @@ -780,8 +779,10 @@ void CBrowseDialog::OnItemEnter() */ return; } - UString s = DirPrefix + fs2us(file.Name) + WCHAR_PATH_SEPARATOR; - HRESULT res = Reload(s, L""); + UString s = DirPrefix; + s += fs2us(file.Name); + s.Add_PathSepar(); + HRESULT res = Reload(s, UString()); if (res != S_OK) MessageBox_HResError(*this, res, s); SetPathEditText(); @@ -853,17 +854,17 @@ bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path, #else // maybe we must use GetLastError in WinCE. DWORD errorCode = CommDlgExtendedError(); - const wchar_t *errorMessage = NULL; + const char *errorMessage = NULL; switch (errorCode) { case 0: return false; // cancel or close obn dialog - case FNERR_INVALIDFILENAME: errorMessage = L"Invalid File Name"; break; - default: errorMessage = L"Open Dialog Error"; + case FNERR_INVALIDFILENAME: errorMessage = "Invalid File Name"; break; + default: errorMessage = "Open Dialog Error"; } if (!errorMessage) return false; { - UString s = errorMessage; + UString s (errorMessage); s.Add_LF(); s += path; MessageBox_Error_Global(owner, s); diff --git a/CPP/7zip/UI/FileManager/EditPage.cpp b/CPP/7zip/UI/FileManager/EditPage.cpp index b88c0f68..0108904d 100644 --- a/CPP/7zip/UI/FileManager/EditPage.cpp +++ b/CPP/7zip/UI/FileManager/EditPage.cpp @@ -23,7 +23,7 @@ static const UInt32 kLangIDs_Colon[] = IDT_EDIT_VIEWER }; -static LPCWSTR kEditTopic = L"FM/options.htm#editor"; +#define kEditTopic "FM/options.htm#editor" bool CEditPage::OnInit() { @@ -76,17 +76,38 @@ LONG CEditPage::OnApply() void CEditPage::OnNotifyHelp() { - ShowHelpWindow(NULL, kEditTopic); + ShowHelpWindow(kEditTopic); } +void SplitCmdLineSmart(const UString &cmd, UString &prg, UString ¶ms); + static void Edit_BrowseForFile(NWindows::NControl::CEdit &edit, HWND hwnd) { - UString path; - edit.GetText(path); + UString cmd; + edit.GetText(cmd); + + UString param; + UString prg; + + SplitCmdLineSmart(cmd, prg, param); + UString resPath; - if (MyBrowseForFile(hwnd, 0, path, NULL, L"*.exe", resPath)) + + if (MyBrowseForFile(hwnd, 0, prg, NULL, L"*.exe", resPath)) { - edit.SetText(resPath); + resPath.Trim(); + cmd = resPath; + /* + if (!param.IsEmpty() && !resPath.IsEmpty()) + { + cmd.InsertAtFront(L'\"'); + cmd += L'\"'; + cmd.Add_Space(); + cmd += param; + } + */ + + edit.SetText(cmd); // Changed(); } } diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp index 7d61d14d..343bb0f8 100644 --- a/CPP/7zip/UI/FileManager/ExtractCallback.cpp +++ b/CPP/7zip/UI/FileManager/ExtractCallback.cpp @@ -335,20 +335,18 @@ void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileNam s += msg; else { - char temp[16]; - ConvertUInt32ToString(opRes, temp); - s.AddAscii("Error #"); - s.AddAscii(temp); + s += "Error #"; + s.Add_UInt32(opRes); } if (encrypted && opRes != NArchive::NExtract::NOperationResult::kWrongPassword) { - // s.AddAscii(" : "); + // s += " : "; // AddLangString(s, IDS_EXTRACT_MSG_ENCRYPTED); - s.AddAscii(" : "); + s += " : "; AddLangString(s, IDS_EXTRACT_MSG_WRONG_PSW_GUESS); } - s.AddAscii(" : "); + s += " : "; s += fileName; } } @@ -466,7 +464,7 @@ UString GetOpenArcErrorMessage(UInt32 errorFlags) continue; if (f == kpv_ErrorFlags_EncryptedHeadersError) { - m.AddAscii(" : "); + m += " : "; AddLangString(m, IDS_EXTRACT_MSG_WRONG_PSW_GUESS); } if (!s.IsEmpty()) @@ -483,7 +481,7 @@ UString GetOpenArcErrorMessage(UInt32 errorFlags) ConvertUInt32ToHex(errorFlags, sz + 2); if (!s.IsEmpty()) s.Add_LF(); - s.AddAscii(sz); + s += sz; } return s; @@ -503,7 +501,7 @@ static void ErrorInfo_Print(UString &s, const CArcErrorInfo &er) if (warningFlags != 0) { s += GetNameOfProperty(kpidWarningFlags, L"Warnings"); - s.AddAscii(":"); + s += ":"; s.Add_LF(); AddNewLineString(s, GetOpenArcErrorMessage(warningFlags)); } @@ -511,7 +509,7 @@ static void ErrorInfo_Print(UString &s, const CArcErrorInfo &er) if (!er.WarningMessage.IsEmpty()) { s += GetNameOfProperty(kpidWarning, L"Warning"); - s.AddAscii(": "); + s += ": "; s += er.WarningMessage; s.Add_LF(); } @@ -519,9 +517,9 @@ static void ErrorInfo_Print(UString &s, const CArcErrorInfo &er) static UString GetBracedType(const wchar_t *type) { - UString s = L'['; + UString s ('['); s += type; - s += L']'; + s += ']'; return s; } @@ -1009,7 +1007,7 @@ HRESULT CVirtFileSystem::FlushToDisk(bool closeLast) { _outFileStream.Release(); return E_FAIL; - // MessageBoxMyError(UString(L"Can't create file ") + fs2us(tempFilePath)); + // MessageBoxMyError(UString("Can't create file ") + fs2us(tempFilePath)); } _fileIsOpen = true; RINOK(WriteStream(_outFileStream, file.Data, (size_t)file.Size)); diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp index ce39011e..fe5ae671 100644 --- a/CPP/7zip/UI/FileManager/FM.cpp +++ b/CPP/7zip/UI/FileManager/FM.cpp @@ -8,7 +8,6 @@ #include "../../../../C/Alloc.h" -#include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" @@ -43,16 +42,21 @@ using namespace NFind; #define MENU_HEIGHT 26 bool g_RAM_Size_Defined; +bool g_LargePagesMode = false; +bool g_OpenArchive = false; + +static bool g_Maximized = false; + UInt64 g_RAM_Size; #ifdef _WIN32 HINSTANCE g_hInstance; #endif + HWND g_HWND; -bool g_OpenArchive = false; + static UString g_MainPath; static UString g_ArcFormat; -static bool g_Maximized = false; // HRESULT LoadGlobalCodecs(); void FreeGlobalCodecs(); @@ -166,7 +170,7 @@ CApp g_App; LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); -const wchar_t *kWindowClass = L"FM"; +static const wchar_t * const kWindowClass = L"FM"; #ifdef UNDER_CE #define WS_OVERLAPPEDWINDOW ( \ @@ -185,7 +189,7 @@ static BOOL InitInstance(int nCmdShow) // LoadString(hInstance, IDS_CLASS, windowClass, MAX_LOADSTRING); - UString title = L"7-Zip"; // LangString(IDS_APP_TITLE, 0x03000000); + UString title ("7-Zip"); // LangString(IDS_APP_TITLE, 0x03000000); /* //If it is already running, then focus on the window @@ -379,7 +383,7 @@ static void SetMemoryLock() NSecurity::AddLockMemoryPrivilege(); if (ReadLockMemoryEnable()) - NSecurity::EnablePrivilege_LockMemory(); + g_LargePagesMode = NSecurity::EnablePrivilege_LockMemory(); } bool g_SymLink_Supported = false; @@ -426,8 +430,13 @@ static void ErrorMessage(const wchar_t *s) MessageBoxW(0, s, L"7-Zip", MB_ICONERROR); } +static void ErrorMessage(const char *s) +{ + ErrorMessage(GetUnicodeString(s)); +} + -#define NT_CHECK_FAIL_ACTION ErrorMessage(L"Unsupported Windows version"); return 1; +#define NT_CHECK_FAIL_ACTION ErrorMessage("Unsupported Windows version"); return 1; static int WINAPI WinMain2(int nCmdShow) { @@ -667,7 +676,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, } catch(const AString &s) { - ErrorMessage(GetUnicodeString(s)); + ErrorMessage(s.Ptr()); return 1; } catch(const wchar_t *s) @@ -677,19 +686,19 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, } catch(const char *s) { - ErrorMessage(GetUnicodeString(s)); + ErrorMessage(s); return 1; } catch(int v) { - wchar_t s[32]; - ConvertUInt32ToString(v, s); - ErrorMessage(UString(L"Error: ") + s); + AString e ("Error: "); + e.Add_UInt32(v); + ErrorMessage(e); return 1; } catch(...) { - ErrorMessage(L"Unknown error"); + ErrorMessage("Unknown error"); return 1; } } @@ -844,7 +853,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) if (needOpenFile && !archiveIsOpened || res != S_OK) { - UString m = L"Error"; + UString m ("Error"); if (res == S_FALSE || res == S_OK) { m = MyFormatNew(encrypted ? diff --git a/CPP/7zip/UI/FileManager/FM.dsp b/CPP/7zip/UI/FileManager/FM.dsp index f18e5441..3b2fb2e3 100644 --- a/CPP/7zip/UI/FileManager/FM.dsp +++ b/CPP/7zip/UI/FileManager/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" /FAs /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" /D "SUPPORT_DEVICE_FILE" /FAcs /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" diff --git a/CPP/7zip/UI/FileManager/FSDrives.cpp b/CPP/7zip/UI/FileManager/FSDrives.cpp index dd4ba724..208cea4e 100644 --- a/CPP/7zip/UI/FileManager/FSDrives.cpp +++ b/CPP/7zip/UI/FileManager/FSDrives.cpp @@ -28,12 +28,14 @@ using namespace NWindows; using namespace NFile; using namespace NFind; -static const CFSTR kVolPrefix = FTEXT("\\\\.\\"); -static const CFSTR kSuperPrefix = FTEXT("\\\\?\\"); +static const char * const kVolPrefix = "\\\\.\\"; +static const char * const kSuperPrefix = "\\\\?\\"; FString CDriveInfo::GetDeviceFileIoName() const { - return kVolPrefix + Name; + FString f (kVolPrefix); + f += Name; + return f; } struct CPhysTempBuffer @@ -179,11 +181,10 @@ STDMETHODIMP CFSDrives::LoadItems() // we must use IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS for (unsigned n = 0; n < 16; n++) // why 16 ? { - FChar temp[16]; - ConvertUInt32ToString(n, temp); - FString name = FTEXT("PhysicalDrive"); - name += temp; - FString fullPath = kVolPrefix; + FString name ("PhysicalDrive"); + name.Add_UInt32(n); + + FString fullPath (kVolPrefix); fullPath += name; CFileInfo fi; @@ -336,7 +337,7 @@ STDMETHODIMP CFSDrives::GetSystemIconIndex(UInt32 index, Int32 *iconIndex) void CFSDrives::AddExt(FString &s, unsigned index) const { - s += FTEXT('.'); + s += '.'; const CDriveInfo &di = _drives[index]; const char *ext; if (di.DriveType == DRIVE_CDROM) @@ -347,7 +348,7 @@ void CFSDrives::AddExt(FString &s, unsigned index) const ext = "fat"; else ext = "img"; - s.AddAscii(ext); + s += ext; } HRESULT CFSDrives::GetFileSize(unsigned index, UInt64 &fileSize) const diff --git a/CPP/7zip/UI/FileManager/FSFolder.cpp b/CPP/7zip/UI/FileManager/FSFolder.cpp index e46afb9e..94cd04cb 100644 --- a/CPP/7zip/UI/FileManager/FSFolder.cpp +++ b/CPP/7zip/UI/FileManager/FSFolder.cpp @@ -73,6 +73,8 @@ HRESULT CFSFolder::Init(const FString &path /* , IFolderFolder *parentFolder */) // _parentFolder = parentFolder; _path = path; + #ifdef _WIN32 + _findChangeNotification.FindFirst(_path, false, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME @@ -85,17 +87,24 @@ HRESULT CFSFolder::Init(const FString &path /* , IFolderFolder *parentFolder */) | FILE_NOTIFY_CHANGE_SECURITY */ ); + if (!_findChangeNotification.IsHandleAllocated()) { DWORD lastError = GetLastError(); CFindFile findFile; CFileInfo fi; - if (!findFile.FindFirst(_path + FCHAR_ANY_MASK, fi)) + FString path2 = _path; + path2 += '*'; // CHAR_ANY_MASK; + if (!findFile.FindFirst(path2, fi)) return lastError; } + + #endif + return S_OK; } + HRESULT CFsFolderStat::Enumerate() { if (Progress) @@ -103,9 +112,9 @@ HRESULT CFsFolderStat::Enumerate() RINOK(Progress->SetCompleted(NULL)); } Path.Add_PathSepar(); - unsigned len = Path.Len(); - Path += FCHAR_ANY_MASK; - CEnumerator enumerator(Path); + const unsigned len = Path.Len(); + CEnumerator enumerator; + enumerator.SetDirPrefix(Path); CFileInfo fi; while (enumerator.Next(fi)) { @@ -164,7 +173,8 @@ HRESULT CFSFolder::LoadSubItems(int dirItem, const FString &relPrefix) { unsigned startIndex = Folders.Size(); { - CEnumerator enumerator(_path + relPrefix + FCHAR_ANY_MASK); + CEnumerator enumerator; + enumerator.SetDirPrefix(_path + relPrefix); CDirItem fi; fi.FolderStat_Defined = false; fi.NumFolders = 0; @@ -267,7 +277,7 @@ STDMETHODIMP CFSFolder::LoadItems() return S_OK; } -static CFSTR kDescriptionFileName = FTEXT("descript.ion"); +static CFSTR const kDescriptionFileName = FTEXT("descript.ion"); bool CFSFolder::LoadComments() { @@ -389,6 +399,7 @@ bool CFSFolder::ReadFileInfo(CDirItem &di) { di.FileInfo_WasRequested = true; BY_HANDLE_FILE_INFORMATION info; + memset(&info, 0, sizeof(info)); // for vc6-O2 if (!NIO::CFileBase::GetFileInformation(_path + GetRelPath(di), &info)) return false; di.NumLinks = info.nNumberOfLinks; @@ -744,8 +755,6 @@ STDMETHODIMP CFSFolder::BindToFolder(const wchar_t *name, IFolderFolder **result return BindToFolderSpec(us2fs(name), resultFolder); } -static const CFSTR kSuperPrefix = FTEXT("\\\\?\\"); - STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder) { *resultFolder = 0; @@ -759,43 +768,39 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder) */ if (_path.IsEmpty()) return E_INVALIDARG; - int pos = _path.ReverseFind_PathSepar(); - if (pos < 0 || pos != (int)_path.Len() - 1) - return E_FAIL; - FString parentPath = _path.Left(pos); - pos = parentPath.ReverseFind_PathSepar(); - if (pos < 0) + + #ifndef UNDER_CE + + if (IsDriveRootPath_SuperAllowed(_path)) { - #ifdef UNDER_CE - *resultFolder = 0; - #else CFSDrives *drivesFolderSpec = new CFSDrives; CMyComPtr<IFolderFolder> drivesFolder = drivesFolderSpec; - drivesFolderSpec->Init(); + drivesFolderSpec->Init(false, IsSuperPath(_path)); *resultFolder = drivesFolder.Detach(); - #endif return S_OK; } - /* + int pos = _path.ReverseFind_PathSepar(); + if (pos < 0 || pos != (int)_path.Len() - 1) + return E_FAIL; + FString parentPath = _path.Left(pos); + pos = parentPath.ReverseFind_PathSepar(); parentPath.DeleteFrom(pos + 1); - - if (parentPath == kSuperPrefix) + + if (NName::IsDrivePath_SuperAllowed(parentPath)) { - #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; + CFSFolder *parentFolderSpec = new CFSFolder; + CMyComPtr<IFolderFolder> parentFolder = parentFolderSpec; + if (parentFolderSpec->Init(parentPath) == S_OK) + { + *resultFolder = parentFolder.Detach(); + return S_OK; + } } - + + /* FString parentPathReduced = parentPath.Left(pos); - #ifndef UNDER_CE pos = parentPathReduced.ReverseFind_PathSepar(); if (pos == 1) { @@ -807,13 +812,10 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder) *resultFolder = netFolder.Detach(); return S_OK; } - #endif - - CFSFolder *parentFolderSpec = new CFSFolder; - CMyComPtr<IFolderFolder> parentFolder = parentFolderSpec; - RINOK(parentFolderSpec->Init(parentPath, 0)); - *resultFolder = parentFolder.Detach(); */ + + #endif + return S_OK; } @@ -844,24 +846,22 @@ STDMETHODIMP CFSFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value) STDMETHODIMP CFSFolder::WasChanged(Int32 *wasChanged) { bool wasChangedMain = false; + + #ifdef _WIN32 + for (;;) { if (!_findChangeNotification.IsHandleAllocated()) - { - *wasChanged = BoolToInt(false); - return S_OK; - } - + break; DWORD waitResult = ::WaitForSingleObject(_findChangeNotification, 0); - bool wasChangedLoc = (waitResult == WAIT_OBJECT_0); - if (wasChangedLoc) - { - _findChangeNotification.FindNext(); - wasChangedMain = true; - } - else + if (waitResult != WAIT_OBJECT_0) break; + _findChangeNotification.FindNext(); + wasChangedMain = true; } + + #endif + *wasChanged = BoolToInt(wasChangedMain); return S_OK; } diff --git a/CPP/7zip/UI/FileManager/FSFolder.h b/CPP/7zip/UI/FileManager/FSFolder.h index 057ba14c..4cbace52 100644 --- a/CPP/7zip/UI/FileManager/FSFolder.h +++ b/CPP/7zip/UI/FileManager/FSFolder.h @@ -142,7 +142,9 @@ private: // bool _scanAltStreams; bool _flatMode; + #ifdef _WIN32 NWindows::NFile::NFind::CFindChangeNotification _findChangeNotification; + #endif HRESULT GetItemsFullSize(const UInt32 *indices, UInt32 numItems, CFsFolderStat &stat); @@ -161,7 +163,7 @@ private: public: HRESULT Init(const FString &path /* , IFolderFolder *parentFolder */); #if !defined(_WIN32) || defined(UNDER_CE) - HRESULT InitToRoot() { return Init(FSTRING_PATH_SEPARATOR /* , NULL */); } + HRESULT InitToRoot() { return Init((FString) FSTRING_PATH_SEPARATOR /* , NULL */); } #endif CFSFolder() : _flatMode(false) diff --git a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp index c91deb07..fa728b47 100644 --- a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp +++ b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp @@ -75,7 +75,7 @@ HRESULT CCopyStateIO::MyCopyFile(CFSTR inPath, CFSTR outPath) } if (written != num) { - ErrorMessage = L"Write error"; + ErrorMessage = "Write error"; return S_OK; } CurrentSize += num; @@ -357,7 +357,7 @@ static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback, const wchar_t *message, const FString &fileName) { UString s = message; - s += L" : "; + s += " : "; s += fs2us(fileName); return callback->ShowMessage(s); } @@ -514,7 +514,8 @@ static HRESULT CopyFolder( return E_ABORT; } - CEnumerator enumerator(CombinePath(srcPath, FSTRING_ANY_MASK)); + CEnumerator enumerator; + enumerator.SetDirPrefix(CombinePath(srcPath, FString())); for (;;) { diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp index dc46ff5b..4e964628 100644 --- a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp +++ b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp @@ -68,7 +68,7 @@ static void SplitNameToPureNameAndExtension(const FString &fullName, else { pureName.SetFrom(fullName, index); - extensionDelimiter = FTEXT('.'); + extensionDelimiter = '.'; extension = fullName.Ptr(index + 1); } } @@ -151,7 +151,7 @@ HRESULT OpenFileFolderPlugin( UString progressTitle = LangString(IDS_OPENNING); t.OpenCallbackSpec->ProgressDialog.MainWindow = parentWindow; - t.OpenCallbackSpec->ProgressDialog.MainTitle = L"7-Zip"; // LangString(IDS_APP_TITLE); + t.OpenCallbackSpec->ProgressDialog.MainTitle = "7-Zip"; // LangString(IDS_APP_TITLE); t.OpenCallbackSpec->ProgressDialog.MainAddTitle = progressTitle + L' '; t.OpenCallbackSpec->ProgressDialog.WaitMode = true; diff --git a/CPP/7zip/UI/FileManager/FoldersPage.cpp b/CPP/7zip/UI/FileManager/FoldersPage.cpp index 42662153..d019bab8 100644 --- a/CPP/7zip/UI/FileManager/FoldersPage.cpp +++ b/CPP/7zip/UI/FileManager/FoldersPage.cpp @@ -27,6 +27,8 @@ static const int kWorkModeButtons[] = IDR_FOLDERS_WORK_SPECIFIED }; +#define kFoldersTopic "fm/options.htm#folders" + static const unsigned kNumWorkModeButtons = ARRAY_SIZE(kWorkModeButtons); bool CFoldersPage::OnInit() @@ -158,9 +160,7 @@ LONG CFoldersPage::OnApply() return PSNRET_NOERROR; } -static LPCWSTR kFoldersTopic = L"fm/options.htm#folders"; - void CFoldersPage::OnNotifyHelp() { - ShowHelpWindow(NULL, kFoldersTopic); + ShowHelpWindow(kFoldersTopic); } diff --git a/CPP/7zip/UI/FileManager/HelpUtils.cpp b/CPP/7zip/UI/FileManager/HelpUtils.cpp index bae2365e..c0f57990 100644 --- a/CPP/7zip/UI/FileManager/HelpUtils.cpp +++ b/CPP/7zip/UI/FileManager/HelpUtils.cpp @@ -6,7 +6,7 @@ #if defined(UNDER_CE) || !defined(_WIN32) -void ShowHelpWindow(HWND, LPCWSTR) +void ShowHelpWindow(LPCSTR) { } @@ -18,12 +18,15 @@ void ShowHelpWindow(HWND, LPCWSTR) #include "../../../Windows/DLL.h" -static LPCWSTR kHelpFileName = L"7-zip.chm::/"; +#define kHelpFileName "7-zip.chm::/" -void ShowHelpWindow(HWND hwnd, LPCWSTR topicFile) +void ShowHelpWindow(LPCSTR topicFile) { FString path = NWindows::NDLL::GetModuleDirPrefix(); - HtmlHelp(hwnd, GetSystemString(fs2us(path) + kHelpFileName + topicFile), HH_DISPLAY_TOPIC, 0); + path += kHelpFileName; + path += topicFile; + // HWND hwnd = NULL; + HtmlHelp(NULL, GetSystemString(fs2us(path)), HH_DISPLAY_TOPIC, 0); } #endif diff --git a/CPP/7zip/UI/FileManager/HelpUtils.h b/CPP/7zip/UI/FileManager/HelpUtils.h index 52b1418a..90c5f7d1 100644 --- a/CPP/7zip/UI/FileManager/HelpUtils.h +++ b/CPP/7zip/UI/FileManager/HelpUtils.h @@ -5,6 +5,6 @@ #include "../../../Common/MyString.h" -void ShowHelpWindow(HWND hwnd, LPCWSTR topicFile); +void ShowHelpWindow(LPCSTR topicFile); #endif diff --git a/CPP/7zip/UI/FileManager/LangPage.cpp b/CPP/7zip/UI/FileManager/LangPage.cpp index cb1bbaab..47e7894c 100644 --- a/CPP/7zip/UI/FileManager/LangPage.cpp +++ b/CPP/7zip/UI/FileManager/LangPage.cpp @@ -20,13 +20,13 @@ static const UInt32 kLangIDs[] = IDT_LANG_LANG }; -static LPCWSTR kLangTopic = L"fm/options.htm#language"; +#define kLangTopic "fm/options.htm#language" static void NativeLangString(UString &dest, const wchar_t *s) { - dest += L" ("; + dest += " ("; dest += s; - dest += L')'; + dest += ')'; } bool LangOpen(CLang &lang, CFSTR fileName); @@ -45,7 +45,8 @@ bool CLangPage::OnInit() _langCombo.SetCurSel(0); const FString dirPrefix = GetLangDirPrefix(); - NFile::NFind::CEnumerator enumerator(dirPrefix + FTEXT("*.txt")); + NFile::NFind::CEnumerator enumerator; + enumerator.SetDirPrefix(dirPrefix); NFile::NFind::CFileInfo fi; CLang lang; UString error; @@ -54,12 +55,15 @@ bool CLangPage::OnInit() { if (fi.IsDir()) continue; - const int kExtSize = 4; + const unsigned kExtSize = 4; if (fi.Name.Len() < kExtSize) continue; - unsigned pos = fi.Name.Len() - kExtSize; + const unsigned pos = fi.Name.Len() - kExtSize; if (!StringsAreEqualNoCase_Ascii(fi.Name.Ptr(pos), ".txt")) + { + // if (!StringsAreEqualNoCase_Ascii(fi.Name.Ptr(pos), ".ttt")) continue; + } if (!LangOpen(lang, dirPrefix + fi.Name)) { @@ -101,7 +105,7 @@ LONG CLangPage::OnApply() void CLangPage::OnNotifyHelp() { - ShowHelpWindow(NULL, kLangTopic); + ShowHelpWindow(kLangTopic); } bool CLangPage::OnCommand(int code, int itemID, LPARAM param) diff --git a/CPP/7zip/UI/FileManager/LangUtils.cpp b/CPP/7zip/UI/FileManager/LangUtils.cpp index 761319b5..94e9ecba 100644 --- a/CPP/7zip/UI/FileManager/LangUtils.cpp +++ b/CPP/7zip/UI/FileManager/LangUtils.cpp @@ -25,7 +25,7 @@ static NSynchronization::CCriticalSection g_CriticalSection; bool LangOpen(CLang &lang, CFSTR fileName) { - return lang.Open(fileName, L"7-Zip"); + return lang.Open(fileName, "7-Zip"); } FString GetLangDirPrefix() @@ -94,7 +94,7 @@ void LangSetDlgItems_Colon(HWND dialog, const UInt32 *ids, unsigned numItems) { CWindow window(GetDlgItem(dialog, id)); UString s2 = s; - s2 += L':'; + s2 += ':'; window.SetText(s2); } } @@ -139,7 +139,7 @@ void LangString_OnlyFromLangFile(UInt32 langID, UString &dest) dest = s; } -static const char *kLangs = +static const char * const kLangs = "ar.bg.ca.zh.-tw.-cn.cs.da.de.el.en.es.fi.fr.he.hu.is." "it.ja.ko.nl.no.=nb.=nn.pl.pt.-br.rm.ro.ru.sr.=hr.-spl.-spc.sk.sq.sv.th.tr." "ur.id.uk.be.sl.et.lv.lt.tg.fa.vi.hy.az.eu.hsb.mk." @@ -153,7 +153,7 @@ static const char *kLangs = // ".gd." ; -static void FindShortNames(UInt32 primeLang, UStringVector &names) +static void FindShortNames(UInt32 primeLang, AStringVector &names) { UInt32 index = 0; for (const char *p = kLangs; *p != 0;) @@ -167,7 +167,7 @@ static void FindShortNames(UInt32 primeLang, UStringVector &names) { if (index > primeLang) break; - UString s; + AString s; if (isSub) { if (p[0] == '-') @@ -176,7 +176,7 @@ static void FindShortNames(UInt32 primeLang, UStringVector &names) p++; } while (p != p2) - s += (wchar_t)(Byte)*p++; + s += (char)(Byte)*p++; names.Add(s); } p = p2 + 1; @@ -195,7 +195,7 @@ static struct CC1Lang UString s; char ttt[32]; ConvertUInt32ToHex(i, ttt); - s.AddAscii(ttt); + s += ttt; UStringVector names; FindShortNames(i, names); @@ -238,18 +238,21 @@ static void OpenDefaultLang() WORD primLang = (WORD)(PRIMARYLANGID(langID)); WORD subLang = (WORD)(SUBLANGID(langID)); { - UStringVector names; + AStringVector names; FindShortNames(primLang, names); - const FString dirPrefix = GetLangDirPrefix(); + const FString dirPrefix (GetLangDirPrefix()); for (unsigned i = 0; i < 2; i++) { unsigned index = (i == 0 ? subLang : 0); if (index < names.Size()) { - const UString &name = names[index]; + const AString &name = names[index]; if (!name.IsEmpty()) { - if (LangOpen(g_Lang, dirPrefix + us2fs(name) + FTEXT(".txt"))) + FString path (dirPrefix); + path += name; + path += ".txt"; + if (LangOpen(g_Lang, path)) { g_LangID = name; return; @@ -280,7 +283,7 @@ void ReloadLang() if (s.Find(FCHAR_PATH_SEPARATOR) < 0) { if (s.Find(FTEXT('.')) < 0) - s += FTEXT(".txt"); + s += ".txt"; s.Insert(0, GetLangDirPrefix()); } LangOpen(g_Lang, s); diff --git a/CPP/7zip/UI/FileManager/LinkDialog.cpp b/CPP/7zip/UI/FileManager/LinkDialog.cpp index 2ef2da5b..ba21c0c7 100644 --- a/CPP/7zip/UI/FileManager/LinkDialog.cpp +++ b/CPP/7zip/UI/FileManager/LinkDialog.cpp @@ -108,11 +108,11 @@ bool CLinkDialog::OnInit() UString s = attr.PrintName; if (!attr.IsOkNamePair()) { - s += L" : "; + s += " : "; s += attr.SubsName; } if (!res) - s = L"ERROR: " + s; + s.Insert(0, L"ERROR: "); SetItemText(IDT_LINK_PATH_TO_CUR, s); @@ -214,7 +214,7 @@ void CLinkDialog::OnButton_SetPath(bool to) _pathToCombo : _pathFromCombo; combo.GetText(currentPath); - // UString title = L"Specify a location for output folder"; + // UString title = "Specify a location for output folder"; UString title = LangString(IDS_SET_FOLDER); UString resultPath; diff --git a/CPP/7zip/UI/FileManager/MenuPage.cpp b/CPP/7zip/UI/FileManager/MenuPage.cpp index 8852ce35..4067ad75 100644 --- a/CPP/7zip/UI/FileManager/MenuPage.cpp +++ b/CPP/7zip/UI/FileManager/MenuPage.cpp @@ -35,7 +35,7 @@ static const UInt32 kLangIDs[] = IDT_SYSTEM_CONTEXT_MENU_ITEMS }; -static LPCWSTR kSystemTopic = L"fm/options.htm#sevenZip"; +#define kMenuTopic "fm/options.htm#sevenZip" struct CContextMenuItem { @@ -71,6 +71,13 @@ static const CContextMenuItem kMenuItems[] = extern bool g_Is_Wow64; #endif +#ifndef KEY_WOW64_64KEY + #define KEY_WOW64_64KEY (0x0100) +#endif + +#ifndef KEY_WOW64_32KEY + #define KEY_WOW64_32KEY (0x0200) +#endif bool CMenuPage::OnInit() { @@ -95,14 +102,14 @@ bool CMenuPage::OnInit() } UString bit64 = LangString(IDS_PROP_BIT64); if (bit64.IsEmpty()) - bit64.SetFromAscii("64-bit"); + bit64 = "64-bit"; #ifdef _WIN64 bit64.Replace(L"64", L"32"); #endif s.Add_Space(); - s += L'('; + s += '('; s += bit64; - s += L')'; + s += ')'; SetItemText(IDX_SYSTEM_INTEGRATE_TO_MENU_2, s); } @@ -136,7 +143,7 @@ bool CMenuPage::OnInit() FString &path = dll.Path; path = prefix; - path.AddAscii(d == 0 ? "7-zip.dll" : + path += (d == 0 ? "7-zip.dll" : #ifdef _WIN64 "7-zip32.dll" #else @@ -180,10 +187,10 @@ bool CMenuPage::OnInit() UString s = LangString(menuItem.ControlID); if (menuItem.Flag == kCRC) - s.SetFromAscii("CRC SHA"); + s = "CRC SHA"; if (menuItem.Flag == kOpenAs || menuItem.Flag == kCRC) - s.AddAscii(" >"); + s += " >"; switch (menuItem.ControlID) { @@ -200,11 +207,11 @@ bool CMenuPage::OnInit() { case kCompressTo7z: case kCompressTo7zEmail: - s2.AddAscii(".7z"); + s2 += (".7z"); break; case kCompressToZip: case kCompressToZipEmail: - s2.AddAscii(".zip"); + s2 += (".zip"); break; } s = MyFormatNew(s, s2); @@ -286,7 +293,7 @@ LONG CMenuPage::OnApply() void CMenuPage::OnNotifyHelp() { - ShowHelpWindow(NULL, kSystemTopic); + ShowHelpWindow(kMenuTopic); } bool CMenuPage::OnButtonClicked(int buttonID, HWND buttonHWND) diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp index d3031f5a..50104950 100644 --- a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp +++ b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp @@ -3,6 +3,7 @@ #include "StdAfx.h" #include "../../../Windows/Menu.h" +#include "../../../Windows/TimeUtils.h" #include "../../../Windows/Control/Dialog.h" #include "../../PropID.h" @@ -22,10 +23,12 @@ using namespace NWindows; static const UINT kOpenBookmarkMenuID = 830; static const UINT kSetBookmarkMenuID = 810; +static const UINT kMenuID_Time_Parent = 760; +static const UINT kMenuID_Time = 761; extern HINSTANCE g_hInstance; -static LPCWSTR kFMHelpTopic = L"FM/index.htm"; +#define kFMHelpTopic "FM/index.htm" extern void OptionsDialog(HWND hwndOwner, HINSTANCE hInstance); @@ -115,10 +118,12 @@ static UINT Get_fMask_for_FType_and_String() 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) { CMenu menu; menu.Attach(menuLoc); + for (int i = 0;; i++) { CMenuItem item; @@ -137,7 +142,12 @@ static void MyChangeMenu(HMENU menuLoc, int level, int menuIndex) { MyChangeMenu(item.hSubMenu, level + 1, i); if (level == 1 && menuIndex == kMenuIndex_View) - langID = kToolbarsLangID; + { + if (item.wID == kMenuID_Time_Parent || item.StringValue.IsPrefixedBy_Ascii_NoCase("20")) + continue; + else + langID = kToolbarsLangID; + } else if (level == 0 && i < ARRAY_SIZE(kTopMenuLangIDs)) langID = kTopMenuLangIDs[i]; else @@ -168,7 +178,18 @@ static void MyChangeMenu(HMENU menuLoc, int level, int menuIndex) int tabPos = newString.Find(L"\t"); if (tabPos >= 0) newString.DeleteFrom(tabPos); - newString += (langID == IDM_OPEN_INSIDE_ONE ? L" *" : L" #"); + newString += (langID == IDM_OPEN_INSIDE_ONE ? " *" : " #"); + } + else if (langID == IDM_BENCHMARK2) + { + LangString_OnlyFromLangFile(IDM_BENCHMARK, newString); + if (newString.IsEmpty()) + continue; + newString.Replace(L"&", L""); + int tabPos = newString.Find(L"\t"); + if (tabPos >= 0) + newString.DeleteFrom(tabPos); + newString += " 2"; } else LangString_OnlyFromLangFile(langID, newString); @@ -245,6 +266,8 @@ void MyLoadMenu() ::DestroyMenu(oldMenu); /* BOOL b = */ g_App._commandBar.InsertMenubar(g_hInstance, IDM_MENU, 0); baseMenu = g_App._commandBar.GetMenu(0); + // if (startInit) + // SetIdsForSubMenes(baseMenu, 0, 0); if (!g_LangID.IsEmpty()) MyChangeMenu(baseMenu, 0, 0); g_App._commandBar.DrawMenuBar(0); @@ -256,6 +279,8 @@ void MyLoadMenu() ::SetMenu(hWnd, ::LoadMenu(g_hInstance, MAKEINTRESOURCE(IDM_MENU))); ::DestroyMenu(oldMenu); baseMenu = ::GetMenu(hWnd); + // if (startInit) + // SetIdsForSubMenes(baseMenu, 0, 0); if (!g_LangID.IsEmpty()) MyChangeMenu(baseMenu, 0, 0); ::DrawMenuBar(hWnd); @@ -277,8 +302,10 @@ void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position) ::GetMenu(g_HWND) #endif ; + if (::GetSubMenu(mainMenu, position) != hMenu) return; + if (position == kMenuIndex_File) { CMenu menu; @@ -316,6 +343,72 @@ void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position) menu.CheckItemByID(IDM_VIEW_AUTO_REFRESH, g_App.Get_AutoRefresh_Mode()); // menu.CheckItemByID(IDM_VIEW_SHOW_STREAMS, g_App.Get_ShowNtfsStrems_Mode()); // menu.CheckItemByID(IDM_VIEW_SHOW_DELETED, g_App.ShowDeletedFiles); + + for (int i = 0;; i++) + { + CMenuItem item; + item.fMask = Get_fMask_for_String() | MIIM_SUBMENU | MIIM_ID; + item.fType = MFT_STRING; + if (!menu.GetItem(i, true, item)) + break; + if (item.hSubMenu && (item.wID == kMenuID_Time_Parent + || item.StringValue.IsPrefixedBy_Ascii_NoCase("20") + )) + { + FILETIME ft; + NTime::GetCurUtcFileTime(ft); + + { + wchar_t s[64]; + s[0] = 0; + if (ConvertUtcFileTimeToString(ft, s, kTimestampPrintLevel_DAY)) + item.StringValue = s; + } + + item.fMask = Get_fMask_for_String() | MIIM_ID; + item.fType = MFT_STRING; + item.wID = kMenuID_Time_Parent; + menu.SetItem(i, true, item); + + CMenu subMenu; + subMenu.Attach(menu.GetSubMenu(i)); + subMenu.RemoveAllItems(); + + const int k_TimeLevels[] = + { + kTimestampPrintLevel_DAY, + kTimestampPrintLevel_MIN, + kTimestampPrintLevel_SEC, + // 1,2,3,4,5,6, + kTimestampPrintLevel_NTFS + }; + + unsigned last = kMenuID_Time; + unsigned selectedCommand = 0; + g_App._timestampLevels.Clear(); + unsigned id = kMenuID_Time; + + for (unsigned k = 0; k < ARRAY_SIZE(k_TimeLevels); k++) + { + wchar_t s[64]; + s[0] = 0; + int timestampLevel = k_TimeLevels[k]; + if (ConvertUtcFileTimeToString(ft, s, timestampLevel)) + { + if (subMenu.AppendItem(MF_STRING, id, s)) + { + last = id; + g_App._timestampLevels.Add(timestampLevel); + if (g_App.GetTimestampLevel() == timestampLevel) + selectedCommand = id; + id++; + } + } + } + if (selectedCommand != 0) + menu.CheckRadioItem(kMenuID_Time, last, selectedCommand, MF_BYCOMMAND); + } + } } else if (position == kMenuIndex_Bookmarks) { @@ -331,9 +424,9 @@ void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position) { UString s = LangString(IDS_BOOKMARK); s.Add_Space(); - wchar_t c = (wchar_t)(L'0' + i); + char c = (char)(L'0' + i); s += c; - s.AddAscii("\tAlt+Shift+"); + s += "\tAlt+Shift+"; s += c; subMenu.AppendItem(MF_STRING, kSetBookmarkMenuID + i, s); } @@ -351,9 +444,9 @@ void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position) s.Insert(kFirstPartSize, L" ... "); } if (s.IsEmpty()) - s = L'-'; - s.AddAscii("\tAlt+"); - s += (wchar_t)(L'0' + i); + s = '-'; + s += "\tAlt+"; + s += (char)('0' + i); menu.AppendItem(MF_STRING, kOpenBookmarkMenuID + i, s); } } @@ -398,6 +491,15 @@ void CFileMenu::Load(HMENU hMenu, unsigned startPos) if (item.wID == IDM_OPEN_INSIDE_ONE || item.wID == IDM_OPEN_INSIDE_PARSER) { // We use diff as "super mode" marker for additional commands. + /* + if (diffPath.IsEmpty()) + continue; + */ + } + + if (item.wID == IDM_BENCHMARK2) + { + // We use diff as "super mode" marker for additional commands. if (diffPath.IsEmpty()) continue; } @@ -473,11 +575,11 @@ bool ExecuteFileCommand(int id) case IDM_MOVE_TO: g_App.MoveTo(); break; case IDM_DELETE: g_App.Delete(!IsKeyDown(VK_SHIFT)); break; - case IDM_HASH_ALL: g_App.CalculateCrc(L"*"); break; - case IDM_CRC32: g_App.CalculateCrc(L"CRC32"); break; - case IDM_CRC64: g_App.CalculateCrc(L"CRC64"); break; - case IDM_SHA1: g_App.CalculateCrc(L"SHA1"); break; - case IDM_SHA256: g_App.CalculateCrc(L"SHA256"); break; + case IDM_HASH_ALL: g_App.CalculateCrc("*"); break; + case IDM_CRC32: g_App.CalculateCrc("CRC32"); break; + case IDM_CRC64: g_App.CalculateCrc("CRC64"); break; + case IDM_SHA1: g_App.CalculateCrc("SHA1"); break; + case IDM_SHA256: g_App.CalculateCrc("SHA256"); break; case IDM_DIFF: g_App.DiffFiles(); break; case IDM_SPLIT: g_App.Split(); break; @@ -614,7 +716,7 @@ bool OnMenuCommand(HWND hWnd, int id) // Help case IDM_HELP_CONTENTS: - ShowHelpWindow(NULL, kFMHelpTopic); + ShowHelpWindow(kFMHelpTopic); break; case IDM_ABOUT: { @@ -634,6 +736,12 @@ bool OnMenuCommand(HWND hWnd, int id) g_App.SetBookmark(id - kSetBookmarkMenuID); return true; } + else if (id >= kMenuID_Time && (unsigned)id <= kMenuID_Time + g_App._timestampLevels.Size()) + { + unsigned index = id - kMenuID_Time; + g_App.SetTimestampLevel(g_App._timestampLevels[index]); + return true; + } return false; } } diff --git a/CPP/7zip/UI/FileManager/NetFolder.cpp b/CPP/7zip/UI/FileManager/NetFolder.cpp index 112f8c06..a941e73d 100644 --- a/CPP/7zip/UI/FileManager/NetFolder.cpp +++ b/CPP/7zip/UI/FileManager/NetFolder.cpp @@ -232,7 +232,7 @@ STDMETHODIMP CNetFolder::BindToParentFolder(IFolderFolder **resultFolder) CNetFolder *netFolder = new CNetFolder; CMyComPtr<IFolderFolder> subFolder = netFolder; - netFolder->Init(&resourceParent, 0, WCHAR_PATH_SEPARATOR); + netFolder->Init(&resourceParent, 0, WSTRING_PATH_SEPARATOR); *resultFolder = subFolder.Detach(); } return S_OK; diff --git a/CPP/7zip/UI/FileManager/OpenCallback.cpp b/CPP/7zip/UI/FileManager/OpenCallback.cpp index 331b171b..bf7abfb7 100644 --- a/CPP/7zip/UI/FileManager/OpenCallback.cpp +++ b/CPP/7zip/UI/FileManager/OpenCallback.cpp @@ -22,10 +22,10 @@ STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 *numFiles, const UInt64 RINOK(ProgressDialog.Sync.CheckStop()); { // NSynchronization::CCriticalSectionLock lock(_criticalSection); - if (numFiles) + ProgressDialog.Sync.Set_NumFilesTotal(numFiles ? *numFiles : (UInt64)(Int64)-1); + // if (numFiles) { - ProgressDialog.Sync.Set_NumFilesTotal(*numFiles); - ProgressDialog.Sync.Set_BytesProgressMode(false); + ProgressDialog.Sync.Set_BytesProgressMode(numFiles == NULL); } if (numBytes) ProgressDialog.Sync.Set_NumBytesTotal(*numBytes); diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp index c6feb902..1c029132 100644 --- a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp +++ b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp @@ -40,6 +40,12 @@ void COverwriteDialog::ReduceString(UString &s) s.Delete(size / 2, s.Len() - size); s.Insert(size / 2, L" ... "); } + if (!s.IsEmpty() && s.Back() == ' ') + { + // s += (wchar_t)(0x2423); + s.InsertAtFront(L'\"'); + s += L'\"'; + } } void COverwriteDialog::SetFileInfoControl(int textID, int iconID, @@ -66,13 +72,10 @@ void COverwriteDialog::SetFileInfoControl(int textID, int iconID, if (fileInfo.TimeIsDefined) { - FILETIME localFileTime; - if (!FileTimeToLocalFileTime(&fileInfo.Time, &localFileTime)) - throw 4190402; AddLangString(s, IDS_PROP_MTIME); - s += L": "; - wchar_t t[32]; - ConvertFileTimeToString(localFileTime, t); + s += ": "; + char t[32]; + ConvertUtcFileTimeToString(fileInfo.Time, t); s += t; } diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp index 5e3ec8ef..6a067acb 100644 --- a/CPP/7zip/UI/FileManager/Panel.cpp +++ b/CPP/7zip/UI/FileManager/Panel.cpp @@ -68,7 +68,7 @@ HWND CPanel::GetParent() return (h == 0) ? _mainWindow : h; } -static LPCWSTR kClassName = L"7-Zip::Panel"; +#define kClassName L"7-Zip::Panel" HRESULT CPanel::Create(HWND mainWindow, HWND parentWindow, UINT id, @@ -933,7 +933,7 @@ void CPanel::ExtractArchives() if (indices.Size() == 1) outFolder += GetSubFolderNameForExtract2(GetItemRelPath(indices[0])); else - outFolder += L'*'; + outFolder += '*'; outFolder.Add_PathSepar(); ::ExtractArchives(paths, outFolder @@ -947,9 +947,9 @@ static void AddValuePair(UINT resourceID, UInt64 value, UString &s) { AddLangString(s, resourceID); char sz[32]; - s += L": "; + s += ": "; ConvertUInt64ToString(value, sz); - s.AddAsciiStr(sz); + s += sz; s.Add_LF(); } */ @@ -999,11 +999,11 @@ static void AddSizePair(UInt32 langID, UInt64 value, UString &s) AddLangString(s, langID); s += L' '; ConvertUInt64ToString(value, sz); - s.AddAsciiStr(sz); + s += sz; ConvertUInt64ToString(value >> 20, sz); - s.AddAsciiStr(" ("); - s.AddAsciiStr(sz); - s.AddAsciiStr(" MB)"); + s += " ("; + s += sz; + s += " MB)"; s.Add_LF(); } */ @@ -1051,11 +1051,10 @@ void CPanel::TestArchives() extracter.Indices = indices; UString title = LangString(IDS_PROGRESS_TESTING); - UString progressWindowTitle = L"7-Zip"; // LangString(IDS_APP_TITLE); extracter.ProgressDialog.CompressingMode = false; extracter.ProgressDialog.MainWindow = GetParent(); - extracter.ProgressDialog.MainTitle = progressWindowTitle; + extracter.ProgressDialog.MainTitle = "7-Zip"; // LangString(IDS_APP_TITLE); extracter.ProgressDialog.MainAddTitle = title + L' '; extracter.ExtractCallbackSpec->OverwriteMode = NExtract::NOverwriteMode::kAskBefore; diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h index 0110ee9d..6402ec2c 100644 --- a/CPP/7zip/UI/FileManager/Panel.h +++ b/CPP/7zip/UI/FileManager/Panel.h @@ -17,6 +17,7 @@ #include "../../../Windows/FileFind.h" #include "../../../Windows/FileName.h" #include "../../../Windows/Handle.h" +#include "../../../Windows/PropVariantConv.h" #include "../../../Windows/Synchronization.h" #include "../../../Windows/Control/ComboBox.h" @@ -373,6 +374,16 @@ public: // CUIntVector _realIndices; bool _enableItemChangeNotify; bool _mySelectMode; + + int _timestampLevel; + + + void RedrawListItems() + { + _listView.RedrawAllItems(); + } + + CBoolVector _selectedStatusVector; CSelectedState _selectedState; @@ -466,6 +477,7 @@ public: UString GetItemRelPath(int itemIndex) const; UString GetItemRelPath2(int itemIndex) const; UString GetItemFullPath(int itemIndex) const; + UInt64 GetItem_UInt64Prop(int itemIndex, PROPID propID) const; UInt64 GetItemSize(int itemIndex) const; //////////////////////// @@ -487,6 +499,7 @@ public: void CloseOpenFolders(); void OpenRootFolder(); + UString GetParentDirPrefix() const; HRESULT Create(HWND mainWindow, HWND parentWindow, UINT id, @@ -526,7 +539,9 @@ public: _thereAreDeletedItems(false), _markDeletedItems(true), _enableItemChangeNotify(true), - _dontShowMode(false) + _dontShowMode(false), + + _timestampLevel(kTimestampPrintLevel_MIN) {} void SetExtendedStyle() diff --git a/CPP/7zip/UI/FileManager/PanelCopy.cpp b/CPP/7zip/UI/FileManager/PanelCopy.cpp index fb418963..a64b4a90 100644 --- a/CPP/7zip/UI/FileManager/PanelCopy.cpp +++ b/CPP/7zip/UI/FileManager/PanelCopy.cpp @@ -183,7 +183,7 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind title = LangString(titleID); } - UString progressWindowTitle = L"7-Zip"; // LangString(IDS_APP_TITLE); + UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE); extracter.ProgressDialog.MainWindow = GetParent(); extracter.ProgressDialog.MainTitle = progressWindowTitle; @@ -248,9 +248,12 @@ struct CThreadUpdate } }; + HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStringVector &filePaths, bool showErrorMessages, UStringVector *messages) { + // CDisableNotify disableNotify(*this); + HRESULT res; if (!_folderOperations) res = E_NOINTERFACE; @@ -265,7 +268,7 @@ HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStri updater.UpdateCallbackSpec->ProgressDialog = &updater.ProgressDialog; UString title = LangString(IDS_COPYING); - UString progressWindowTitle = L"7-Zip"; // LangString(IDS_APP_TITLE); + UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE); updater.ProgressDialog.MainWindow = GetParent(); updater.ProgressDialog.MainTitle = progressWindowTitle; @@ -321,10 +324,10 @@ void CPanel::CopyFromNoAsk(const UStringVector &filePaths) CSelectedState srcSelState; SaveSelectedState(srcSelState); - HRESULT result = CopyFrom(false, L"", filePaths, true, 0); - CDisableNotify disableNotify(*this); + HRESULT result = CopyFrom(false, L"", filePaths, true, 0); + if (result != S_OK) { disableNotify.Restore(); @@ -345,9 +348,9 @@ void CPanel::CopyFromAsk(const UStringVector &filePaths) { UString title = LangString(IDS_CONFIRM_FILE_COPY); UString message = LangString(IDS_WANT_TO_COPY_FILES); - message += L"\n\'"; + message += "\n\'"; message += _currentFolderPrefix; - message += L"\' ?"; + message += "\' ?"; int res = ::MessageBoxW(*(this), message, title, MB_YESNOCANCEL | MB_ICONQUESTION); if (res != IDYES) return; diff --git a/CPP/7zip/UI/FileManager/PanelCrc.cpp b/CPP/7zip/UI/FileManager/PanelCrc.cpp index c9697e8b..8500a9a5 100644 --- a/CPP/7zip/UI/FileManager/PanelCrc.cpp +++ b/CPP/7zip/UI/FileManager/PanelCrc.cpp @@ -128,14 +128,15 @@ DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &r FString s = resPath; s.Add_PathSepar(); Prefixes.Add(s); - s += FCHAR_ANY_MASK; - Enumerators.Add(NFind::CEnumerator(BasePrefix + s)); + Enumerators.AddNew().SetDirPrefix(BasePrefix + s); } filled = true; return S_OK; } + + class CThreadCrc: public CProgressThreadVirt { HRESULT ProcessVirt(); @@ -364,7 +365,7 @@ HRESULT CApp::CalculateCrc2(const UString &methodName) UString title = LangString(IDS_CHECKSUM_CALCULATING); t.ProgressDialog.MainWindow = _window; - t.ProgressDialog.MainTitle = L"7-Zip"; // LangString(IDS_APP_TITLE); + t.ProgressDialog.MainTitle = "7-Zip"; // LangString(IDS_APP_TITLE); t.ProgressDialog.MainAddTitle = title; t.ProgressDialog.MainAddTitle.Add_Space(); @@ -374,9 +375,9 @@ HRESULT CApp::CalculateCrc2(const UString &methodName) return S_OK; } -void CApp::CalculateCrc(const UString &methodName) +void CApp::CalculateCrc(const char *methodName) { - HRESULT res = CalculateCrc2(methodName); + HRESULT res = CalculateCrc2(UString(methodName)); if (res != S_OK && res != E_ABORT) { unsigned srcPanelIndex = GetFocusedPanelIndex(); diff --git a/CPP/7zip/UI/FileManager/PanelDrag.cpp b/CPP/7zip/UI/FileManager/PanelDrag.cpp index ff16f24e..bdfccbb3 100644 --- a/CPP/7zip/UI/FileManager/PanelDrag.cpp +++ b/CPP/7zip/UI/FileManager/PanelDrag.cpp @@ -31,8 +31,9 @@ using namespace NDir; extern bool g_IsNT; #endif -static CFSTR kTempDirPrefix = FTEXT("7zE"); -static LPCTSTR kSvenZipSetFolderFormat = TEXT("7-Zip::SetTargetFolder"); +#define kTempDirPrefix FTEXT("7zE") + +static LPCTSTR const kSvenZipSetFolderFormat = TEXT("7-Zip::SetTargetFolder"); //////////////////////////////////////////////////////// @@ -619,7 +620,10 @@ bool CDropTarget::IsItSameDrive() const return false; } else if (m_Panel->IsFSDrivesFolder() && m_SelectionIndex >= 0) - drive = m_SubFolderName + WCHAR_PATH_SEPARATOR; + { + drive = m_SubFolderName; + drive.Add_PathSepar(); + } else return false; diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp index 5a59d056..fad29cf1 100644 --- a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp +++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp @@ -67,6 +67,12 @@ void CPanel::SetToRootFolder() rootFolderSpec->Init(); } + +static bool DoesNameContainWildcard_SkipRoot(const UString &path) +{ + return DoesNameContainWildcard(path.Ptr(NName::GetRootPrefixSize(path))); +} + HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bool &archiveIsOpened, bool &encrypted) { UString path = fullPath; @@ -178,11 +184,11 @@ HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bo else if (fileInfo.IsDir()) { #ifdef _WIN32 - if (DoesNameContainWildcard(sysPath)) + if (DoesNameContainWildcard_SkipRoot(sysPath)) { FString dirPrefix, fileName; NDir::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName); - if (DoesNameContainWildcard(dirPrefix)) + if (DoesNameContainWildcard_SkipRoot(fs2us(dirPrefix))) return E_INVALIDARG; sysPath = fs2us(dirPrefix + fileInfo.Name); } @@ -200,10 +206,10 @@ HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bo HRESULT res = S_OK; #ifdef _WIN32 - if (DoesNameContainWildcard(dirPrefix)) + if (DoesNameContainWildcard_SkipRoot(fs2us(dirPrefix))) return E_INVALIDARG; - if (DoesNameContainWildcard(fileName)) + if (DoesNameContainWildcard(fs2us(fileName))) res = S_FALSE; else #endif @@ -281,7 +287,17 @@ HRESULT CPanel::BindToPathAndRefresh(const UString &path) CDisableTimerProcessing disableTimerProcessing(*this); CDisableNotify disableNotify(*this); bool archiveIsOpened, encrypted; - HRESULT res = BindToPath(path, UString(), archiveIsOpened, encrypted); + UString s = path; + + #ifdef _WIN32 + if (!s.IsEmpty() && s[0] == '\"' && s.Back() == '\"') + { + s.DeleteBack(); + s.Delete(0); + } + #endif + + HRESULT res = BindToPath(s, UString(), archiveIsOpened, encrypted); RefreshListCtrl(UString(), -1, true, UStringVector()); return res; } @@ -349,14 +365,14 @@ void CPanel::LoadFullPathAndShow() #else 1 #endif - && path.Back() == WCHAR_PATH_SEPARATOR) + && IS_PATH_SEPAR(path.Back())) path.DeleteBack(); DWORD attrib = FILE_ATTRIBUTE_DIRECTORY; // GetRealIconIndex is slow for direct DVD/UDF path. So we use dummy path if (path.IsPrefixedBy(L"\\\\.\\")) - path = L"_TestFolder_"; + path = "_TestFolder_"; else { CFileInfo fi; @@ -456,7 +472,7 @@ void CPanel::AddComboBoxItem(const UString &name, int iconIndex, int indent, boo UString s; iconIndex = iconIndex; for (int i = 0; i < indent; i++) - s += L" "; + s += " "; _headerComboBox.AddString(s + name); #else @@ -631,6 +647,30 @@ void CPanel::FoldersHistory() BindToPathAndRefresh(selectString); } + +UString CPanel::GetParentDirPrefix() const +{ + UString s; + if (!_currentFolderPrefix.IsEmpty()) + { + wchar_t c = _currentFolderPrefix.Back(); + if (IS_PATH_SEPAR(c) || c == ':') + { + s = _currentFolderPrefix; + s.DeleteBack(); + if (s != L"\\\\." && + s != L"\\\\?") + { + int pos = s.ReverseFind_PathSepar(); + if (pos >= 0) + s.DeleteFrom(pos + 1); + } + } + } + return s; +} + + void CPanel::OpenParentFolder() { LoadFullPath(); // Maybe we don't need it ?? @@ -641,12 +681,12 @@ void CPanel::OpenParentFolder() if (!_currentFolderPrefix.IsEmpty()) { wchar_t c = _currentFolderPrefix.Back(); - if (c == WCHAR_PATH_SEPARATOR || c == ':') + if (IS_PATH_SEPAR(c) || c == ':') { focusedName = _currentFolderPrefix; focusedName.DeleteBack(); /* - if (c == ':' && !focusedName.IsEmpty() && focusedName.Back() == WCHAR_PATH_SEPARATOR) + if (c == ':' && !focusedName.IsEmpty() && IS_PATH_SEPAR(focusedName.Back())) { focusedName.DeleteBack(); } @@ -825,7 +865,7 @@ void CPanel::OpenAltStreams() path.DeleteBack(); } - path += L':'; + path += ':'; BindToPathAndRefresh(path); #endif } diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp index cfbc5770..795e74b7 100644 --- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp +++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp @@ -46,7 +46,7 @@ extern UInt64 g_RAM_Size; extern bool g_IsNT; #endif -static CFSTR kTempDirPrefix = FTEXT("7zO"); +#define kTempDirPrefix FTEXT("7zO") // #define SHOW_DEBUG_INFO @@ -534,23 +534,23 @@ HRESULT CPanel::OpenAsArc(IInStream *inStream, UString s2; if (!values[3].IsEmpty()) { - s2 = L"Can not open the file as [" + values[3] + L"] archive"; + s2 = "Can not open the file as [" + values[3] + "] archive"; if (level2 != 0) - s2 += L"\nThe file is open as [" + values[2] + L"] archive"; + s2 += "\nThe file is open as [" + values[2] + "] archive"; } if (!values[0].IsEmpty()) { if (!s2.IsEmpty()) s2.Add_LF(); - s2 += L"["; + s2 += "["; s2 += values[2]; - s2 += L"] Error: "; + s2 += "] Error: "; s2 += values[0]; } if (!s2.IsEmpty()) { if (!s.IsEmpty()) - s += L"--------------------\n"; + s += "--------------------\n"; s += values[1]; s.Add_LF(); s += s2; @@ -587,7 +587,7 @@ HRESULT CPanel::OpenAsArc_Msg(IInStream *inStream, if (showErrorMessage && encrypted) { - UString message = L"Error"; + UString message("Error"); if (res == S_FALSE) { message = MyFormatNew( @@ -663,11 +663,15 @@ HRESULT CPanel::OpenParentArchiveFolder() } -static const char *kStartExtensions = +static const char * const kExeExtensions = + " exe bat ps1 com" + " "; + +static const char * const kStartExtensions = #ifdef UNDER_CE " cab" #endif - " exe bat com" + " exe bat ps1 com" " chm" " msi doc xls ppt pps wps wpt wks xlr wdb vsd pub" @@ -718,6 +722,51 @@ static bool DoItemAlwaysStart(const UString &name) UString GetQuotedString(const UString &s); + +void SplitCmdLineSmart(const UString &cmd, UString &prg, UString ¶ms) +{ + params.Empty(); + prg = cmd; + prg.Trim(); + if (prg.Len() >= 2 && prg[0] == L'"') + { + int pos = prg.Find(L'"', 1); + if (pos >= 0) + { + if ((unsigned)pos + 1 == prg.Len() || prg[pos + 1] == ' ') + { + params = prg.Ptr(pos + 1); + params.Trim(); + prg.DeleteFrom(pos); + prg.DeleteFrontal(1); + } + } + } +} + + +static WRes StartAppWithParams(const UString &cmd, const UStringVector ¶mVector, CProcess &process) +{ + UString param; + UString prg; + + SplitCmdLineSmart(cmd, prg, param); + + param.Trim(); + + // int pos = params.Find(L"%1"); + + FOR_VECTOR (i, paramVector) + { + if (!param.IsEmpty() && param.Back() != ' ') + param.Add_Space(); + param += GetQuotedString(paramVector[i]); + } + + return process.Create(prg, param, NULL); +} + + static HRESULT StartEditApplication(const UString &path, bool useEditor, HWND window, CProcess &process) { UString command; @@ -725,7 +774,7 @@ static HRESULT StartEditApplication(const UString &path, bool useEditor, HWND wi if (command.IsEmpty()) { #ifdef UNDER_CE - command = L"\\Windows\\"; + command = "\\Windows\\"; #else FString winDir; if (!GetWindowsDir(winDir)) @@ -733,15 +782,19 @@ static HRESULT StartEditApplication(const UString &path, bool useEditor, HWND wi NName::NormalizeDirPathPrefix(winDir); command = fs2us(winDir); #endif - command += L"notepad.exe"; + command += "notepad.exe"; } - HRESULT res = process.Create(command, GetQuotedString(path), NULL); + UStringVector params; + params.Add(path); + + HRESULT res = StartAppWithParams(command, params, process); if (res != SZ_OK) ::MessageBoxW(window, LangString(IDS_CANNOT_START_EDITOR), L"7-Zip", MB_OK | MB_ICONSTOP); return res; } + void CApp::DiffFiles() { const CPanel &panel = GetFocusedPanel(); @@ -779,16 +832,21 @@ void CApp::DiffFiles() if (command.IsEmpty()) return; - UString param = GetQuotedString(path1); - param.Add_Space(); - param += GetQuotedString(path2); + UStringVector params; + params.Add(path1); + params.Add(path2); - HRESULT res = MyCreateProcess(command, param); + HRESULT res; + { + CProcess process; + res = StartAppWithParams(command, params, process); + } if (res == SZ_OK) return; ::MessageBoxW(_window, LangString(IDS_CANNOT_START_EDITOR), L"7-Zip", MB_OK | MB_ICONSTOP); } + #ifndef _UNICODE typedef BOOL (WINAPI * ShellExecuteExWP)(LPSHELLEXECUTEINFOW lpExecInfo); #endif @@ -802,7 +860,7 @@ static HRESULT StartApplication(const UString &dir, const UString &path, HWND wi int dot = path2.ReverseFind_Dot(); int separ = path2.ReverseFind_PathSepar(); if (dot < 0 || dot < separ) - path2 += L'.'; + path2 += '.'; } #endif @@ -841,8 +899,8 @@ static HRESULT StartApplication(const UString &dir, const UString &path, HWND wi ; execInfo.hwnd = NULL; execInfo.lpVerb = NULL; - const CSysString sysPath = GetSystemString(path2); - const CSysString sysDir = GetSystemString(dir); + const CSysString sysPath (GetSystemString(path2)); + const CSysString sysDir (GetSystemString(dir)); execInfo.lpFile = sysPath; execInfo.lpParameters = NULL; execInfo.lpDirectory = @@ -896,27 +954,36 @@ void CPanel::EditItem(int index, bool useEditor) StartEditApplication(GetItemFullPath(index), useEditor, (HWND)*this, process); } + void CPanel::OpenFolderExternal(int index) { - UString fsPrefix = GetFsPath(); - UString name; + UString prefix = GetFsPath(); + UString path = prefix; + if (index == kParentIndex) { - int pos = fsPrefix.ReverseFind_PathSepar(); - if (pos >= 0 && pos == (int)fsPrefix.Len() - 1) - { - UString s = fsPrefix.Left(pos); - pos = s.ReverseFind_PathSepar(); - if (pos >= 0) - fsPrefix.SetFrom(s, pos + 1); - } - name = fsPrefix; + if (prefix.IsEmpty()) + return; + const wchar_t c = prefix.Back(); + if (!IS_PATH_SEPAR(c) && c != ':') + return; + prefix.DeleteBack(); + int pos = prefix.ReverseFind_PathSepar(); + if (pos < 0) + return; + prefix.DeleteFrom(pos + 1); + path = prefix; } else - name = fsPrefix + GetItemRelPath(index) + WCHAR_PATH_SEPARATOR; - StartApplicationDontWait(fsPrefix, name, (HWND)*this); + { + path += GetItemRelPath(index); + path.Add_PathSepar(); + } + + StartApplicationDontWait(prefix, path, (HWND)*this); } + bool CPanel::IsVirus_Message(const UString &name) { UString name2; @@ -928,12 +995,12 @@ bool CPanel::IsVirus_Message(const UString &name) if (name2.Find(cRLO) >= 0) { - UString badString = cRLO; + const UString badString(cRLO); name2.Replace(badString, L"[RLO]"); isVirus = true; } { - const wchar_t *kVirusSpaces = L" "; + const wchar_t * const kVirusSpaces = L" "; // const unsigned kNumSpaces = strlen(kVirusSpaces); for (;;) { @@ -945,6 +1012,27 @@ bool CPanel::IsVirus_Message(const UString &name) name2.Replace(kVirusSpaces, L" "); } } + + #ifdef _WIN32 + { + unsigned i; + for (i = name2.Len(); i != 0;) + { + wchar_t c = name2[i - 1]; + if (c != '.' && c != ' ') + break; + i--; + name2.ReplaceOneCharAtPos(i, '_'); + } + if (i != name2.Len()) + { + UString name3 = name2; + name3.DeleteFrom(i); + if (FindExt(kExeExtensions, name3)) + isVirus = true; + } + } + #endif if (!isVirus) return false; @@ -983,8 +1071,9 @@ void CPanel::OpenItem(int index, bool tryInternal, bool tryExternal, const wchar CDisableTimerProcessing disableTimerProcessing(*this); UString name = GetItemRelPath2(index); - if (IsVirus_Message(name)) - return; + if (tryExternal) + if (IsVirus_Message(name)) + return; if (!_parentFolders.IsEmpty()) { @@ -1330,7 +1419,7 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param) #if defined(_WIN32) && !defined(UNDER_CE) -static const FChar *k_ZoneId_StreamName = FTEXT(":Zone.Identifier"); +static const FChar * const k_ZoneId_StreamName = FTEXT(":Zone.Identifier"); #endif @@ -1443,7 +1532,7 @@ HRESULT CBufSeqOutStream_WithFile::FlushToFile() { outFileStream.Release(); return E_FAIL; - // MessageBoxMyError(UString(L"Can't create file ") + fs2us(tempFilePath)); + // MessageBoxMyError(UString("Can't create file ") + fs2us(tempFilePath)); } } while (_fileWritePos != _pos) @@ -1494,8 +1583,9 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo const UString name = GetItemName(index); const UString relPath = GetItemRelPath(index); - if (IsVirus_Message(name)) - return; + if (tryExternal) + if (IsVirus_Message(name)) + return; if (!_folderOperations) { diff --git a/CPP/7zip/UI/FileManager/PanelItems.cpp b/CPP/7zip/UI/FileManager/PanelItems.cpp index 55981d6d..2f32a143 100644 --- a/CPP/7zip/UI/FileManager/PanelItems.cpp +++ b/CPP/7zip/UI/FileManager/PanelItems.cpp @@ -532,7 +532,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool if (showDots) { - UString itemName = L".."; + UString itemName (".."); item.iItem = listViewItemCount; if (itemName == focusedName) cursorIndex = item.iItem; @@ -587,7 +587,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool unsigned prefixLen = 0; _folderGetItemName->GetItemPrefix(i, &prefix, &prefixLen); if (prefix) - relPath += prefix; + relPath = prefix; } if (!prefix) { @@ -595,7 +595,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool if (_folder->GetProperty(i, kpidPrefix, &prop) != S_OK) throw 2723400; if (prop.vt == VT_BSTR) - relPath += prop.bstrVal; + relPath.SetFromBstr(prop.bstrVal); } } relPath += name; @@ -637,7 +637,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool if (j < finish) { correctedName.Empty(); - correctedName = L"virus"; + correctedName = "virus"; int pos = 0; for (;;) { @@ -648,7 +648,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool break; } correctedName += itemName.Mid(pos, posNew - pos); - correctedName += L" ... "; + correctedName += " ... "; pos = posNew; while (itemName[++pos] == ' '); } @@ -664,19 +664,6 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool LPSTR_TEXTCALLBACKW can be 2-3 times faster for loading in this loop. */ } - UInt32 attrib = 0; - // for (int yyy = 0; yyy < 6000000; yyy++) { - NCOM::CPropVariant prop; - RINOK(_folder->GetProperty(i, kpidAttrib, &prop)); - if (prop.vt == VT_UI4) - { - // char s[256]; sprintf(s, "attrib = %7x", attrib); OutputDebugStringA(s); - attrib = prop.ulVal; - } - else if (IsItem_Folder(i)) - attrib |= FILE_ATTRIBUTE_DIRECTORY; - // } - bool defined = false; if (folderGetSystemIconIndex) @@ -684,8 +671,19 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool folderGetSystemIconIndex->GetSystemIconIndex(i, &item.iImage); defined = (item.iImage > 0); } + if (!defined) { + UInt32 attrib = 0; + { + NCOM::CPropVariant prop; + RINOK(_folder->GetProperty(i, kpidAttrib, &prop)); + if (prop.vt == VT_UI4) + attrib = prop.ulVal; + } + if (IsItem_Folder(i)) + attrib |= FILE_ATTRIBUTE_DIRECTORY; + if (_currentFolderPrefix.IsEmpty()) { int iconIndexTemp; @@ -993,7 +991,7 @@ void CPanel::GetItemName(int itemIndex, UString &s) const { if (itemIndex == kParentIndex) { - s = L".."; + s = ".."; return; } NCOM::CPropVariant prop; @@ -1073,14 +1071,12 @@ bool CPanel::IsItem_AltStream(int itemIndex) const return GetItem_BoolProp(itemIndex, kpidIsAltStream); } -UInt64 CPanel::GetItemSize(int itemIndex) const +UInt64 CPanel::GetItem_UInt64Prop(int itemIndex, PROPID propID) const { if (itemIndex == kParentIndex) return 0; - if (_folderGetItemName) - return _folderGetItemName->GetItemSize(itemIndex); NCOM::CPropVariant prop; - if (_folder->GetProperty(itemIndex, kpidSize, &prop) != S_OK) + if (_folder->GetProperty(itemIndex, propID, &prop) != S_OK) throw 2723400; UInt64 val = 0; if (ConvertPropVariantToUInt64(prop, val)) @@ -1088,6 +1084,14 @@ UInt64 CPanel::GetItemSize(int itemIndex) const return 0; } +UInt64 CPanel::GetItemSize(int itemIndex) const +{ + if (itemIndex == kParentIndex) + return 0; + if (_folderGetItemName) + return _folderGetItemName->GetItemSize(itemIndex); + return GetItem_UInt64Prop(itemIndex, kpidSize); +} void CPanel::SaveListViewInfo() { diff --git a/CPP/7zip/UI/FileManager/PanelKey.cpp b/CPP/7zip/UI/FileManager/PanelKey.cpp index 26aa0b2f..5603251f 100644 --- a/CPP/7zip/UI/FileManager/PanelKey.cpp +++ b/CPP/7zip/UI/FileManager/PanelKey.cpp @@ -10,7 +10,7 @@ using namespace NWindows; -// static LPCWSTR kHelpTopic = L"FM/index.htm"; +// #define kHelpTopic "FM/index.htm" struct CVKeyPropIDPair { diff --git a/CPP/7zip/UI/FileManager/PanelListNotify.cpp b/CPP/7zip/UI/FileManager/PanelListNotify.cpp index cc84f712..d7785d12 100644 --- a/CPP/7zip/UI/FileManager/PanelListNotify.cpp +++ b/CPP/7zip/UI/FileManager/PanelListNotify.cpp @@ -19,6 +19,18 @@ using namespace NWindows; +/* Unicode characters for space: +0x009C STRING TERMINATOR +0x00B7 Middle dot +0x237D Shouldered open box +0x2420 Symbol for space +0x2422 Blank symbol +0x2423 Open box +*/ + +#define SPACE_REPLACE_CHAR (wchar_t)(0x2423) +#define SPACE_TERMINATOR_CHAR (wchar_t)(0x9C) + #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); @@ -42,7 +54,7 @@ static void ConvertSizeToString(UInt64 val, wchar_t *s) throw() { if (i != 0) { - *s++ = temp[i - 1]; + *s++ = temp[(size_t)i - 1]; if (i == 2) *s++ = temp[0]; } @@ -62,9 +74,9 @@ static void ConvertSizeToString(UInt64 val, wchar_t *s) throw() do { s[0] = ' '; - s[1] = temp[i - 1]; - s[2] = temp[i - 2]; - s[3] = temp[i - 3]; + s[1] = temp[(size_t)i - 1]; + s[2] = temp[(size_t)i - 2]; + s[3] = temp[(size_t)i - 3]; s += 4; } while (i -= 3); @@ -337,17 +349,17 @@ LRESULT CPanel::SetItemText(LVITEMW &item) { if (c != 0x202E) // RLO continue; - text[dest - 1] = '_'; + text[(size_t)dest - 1] = '_'; continue; } - if (name[i + 1] != ' ') + if (name[i] != ' ') continue; - unsigned t = 2; + unsigned t = 1; for (; name[i + t] == ' '; t++); - - if (t >= 4 && dest + 4 <= limit) + + if (t >= 4 && dest + 4 < limit) { text[dest++] = '.'; text[dest++] = '.'; @@ -356,6 +368,20 @@ LRESULT CPanel::SetItemText(LVITEMW &item) i += t; } } + + if (dest == 0) + text[dest++]= '_'; + + #ifdef _WIN32 + else if (text[(size_t)dest - 1] == ' ') + { + if (dest < limit) + text[dest++] = SPACE_TERMINATOR_CHAR; + else + text[dest - 1] = SPACE_REPLACE_CHAR; + } + #endif + text[dest] = 0; // OutputDebugStringW(text); return 0; @@ -392,7 +418,7 @@ LRESULT CPanel::SetItemText(LVITEMW &item) if (res != S_OK) { MyStringCopy(text, L"Error: "); - // s = UString(L"Error: ") + HResultToMessage(res); + // s = UString("Error: ") + HResultToMessage(res); } else if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && IsSizeProp(propID)) { @@ -418,7 +444,7 @@ LRESULT CPanel::SetItemText(LVITEMW &item) else { char temp[64]; - ConvertPropertyToShortString(temp, prop, propID, false); + ConvertPropertyToShortString2(temp, prop, propID, _timestampLevel); unsigned i; unsigned limit = item.cchTextMax - 1; for (i = 0; i < limit; i++) @@ -712,7 +738,7 @@ void CPanel::Refresh_StatusBar() { char dateString2[32]; dateString2[0] = 0; - ConvertPropertyToShortString(dateString2, prop, kpidMTime, false); + ConvertPropertyToShortString2(dateString2, prop, kpidMTime); for (unsigned i = 0;; i++) { char c = dateString2[i]; diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp index c5b07825..b3f3a6b6 100644 --- a/CPP/7zip/UI/FileManager/PanelMenu.cpp +++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp @@ -14,6 +14,7 @@ #include "../Explorer/ContextMenu.h" #include "App.h" +#include "FormatUtils.h" #include "LangUtils.h" #include "MyLoadMenu.h" #include "PropertyName.h" @@ -49,9 +50,9 @@ void CPanel::InvokeSystemCommand(const char *command) contextMenu->InvokeCommand(&ci); } -static const char *kSeparator = "----------------------------\n"; -static const char *kSeparatorSmall = "----\n"; -static const char *kPropValueSeparator = ": "; +static const char * const kSeparator = "----------------------------\n"; +static const char * const kSeparatorSmall = "----\n"; +static const char * const kPropValueSeparator = ": "; extern UString ConvertSizeToString(UInt64 value) throw(); bool IsSizeProp(UINT propID) throw(); @@ -82,12 +83,12 @@ static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR, val = ConvertSizeToString(v); } else - ConvertPropertyToString(val, prop, propID); + ConvertPropertyToString2(val, prop, propID); if (!val.IsEmpty()) { s += GetNameOfProperty(propID, nameBSTR); - s.AddAscii(kPropValueSeparator); + s += kPropValueSeparator; /* if (propID == kpidComment) s.Add_LF(); @@ -98,6 +99,14 @@ static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR, } } + +static void AddPropertyString(PROPID propID, UInt64 val, UString &s) +{ + NCOM::CPropVariant prop = val; + AddPropertyString(propID, NULL, prop, s); +} + + static inline char GetHex(Byte value) { return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); @@ -132,10 +141,11 @@ void CPanel::Properties() CRecordVector<UInt32> operatedIndices; GetOperatedItemIndices(operatedIndices); + if (operatedIndices.Size() == 1) { UInt32 index = operatedIndices[0]; - // message += L"Item:\n"; + // message += "Item:\n"); UInt32 numProps; if (_folder->GetNumberOfProperties(&numProps) == S_OK) { @@ -182,10 +192,8 @@ void CPanel::Properties() const UInt32 kMaxDataSize = 64; if (dataSize > kMaxDataSize) { - char temp[64]; s += "data:"; - ConvertUInt32ToString(dataSize, temp); - s += temp; + s.Add_UInt32(dataSize); } else { @@ -198,15 +206,53 @@ void CPanel::Properties() } } message += GetNameOfProperty(propID, name); - message.AddAscii(kPropValueSeparator); - message.AddAscii(s); + message += kPropValueSeparator; + message += s.Ptr(); message.Add_LF(); } } } - message.AddAscii(kSeparator); + message += kSeparator; + } + else if (operatedIndices.Size() >= 1) + { + UInt64 packSize = 0; + UInt64 unpackSize = 0; + UInt64 numFiles = 0; + UInt64 numDirs = 0; + + FOR_VECTOR (i, operatedIndices) + { + const UInt32 index = operatedIndices[i]; + unpackSize += GetItemSize(index); + packSize += GetItem_UInt64Prop(index, kpidPackSize); + if (IsItem_Folder(index)) + { + numDirs++; + numDirs += GetItem_UInt64Prop(index, kpidNumSubDirs); + numFiles += GetItem_UInt64Prop(index, kpidNumSubFiles);; + } + else + numFiles++; + } + { + wchar_t temp[32]; + ConvertUInt32ToString(operatedIndices.Size(), temp); + message += MyFormatNew(g_App.LangString_N_SELECTED_ITEMS, temp); + message.Add_LF(); + } + + if (numDirs != 0) + AddPropertyString(kpidNumSubDirs, numDirs, message); + if (numFiles != 0) + AddPropertyString(kpidNumSubFiles, numFiles, message); + AddPropertyString(kpidSize, unpackSize, message); + AddPropertyString(kpidPackSize, packSize, message); + + message += kSeparator; } + /* AddLangString(message, IDS_PROP_FILE_TYPE); @@ -263,7 +309,7 @@ void CPanel::Properties() { const int kNumSpecProps = ARRAY_SIZE(kSpecProps); - message.AddAscii(kSeparator); + message += kSeparator; for (Int32 i = -(int)kNumSpecProps; i < (Int32)numProps; i++) { @@ -288,7 +334,7 @@ void CPanel::Properties() UInt32 numProps; if (getProps->GetArcNumProps2(level, &numProps) == S_OK) { - message.AddAscii(kSeparatorSmall); + message += kSeparatorSmall; for (Int32 i = 0; i < (Int32)numProps; i++) { CMyComBSTR name; @@ -331,8 +377,8 @@ void CPanel::EditCopy() GetSelectedItemsIndices(indices); FOR_VECTOR (i, indices) { - if (i > 0) - s += L"\xD\n"; + if (i != 0) + s += "\xD\n"; s += GetItemName(indices[i]); } ClipboardSetText(_mainWindow, s); @@ -755,7 +801,7 @@ bool CPanel::InvokePluginCommand(int id, commandInfo.hwnd = GetParent(); commandInfo.lpVerb = (LPCSTR)(MAKEINTRESOURCE(offset)); commandInfo.lpParameters = NULL; - CSysString currentFolderSys = GetSystemString(_currentFolderPrefix); + const CSysString currentFolderSys (GetSystemString(_currentFolderPrefix)); commandInfo.lpDirectory = (LPCSTR)(LPCTSTR)(currentFolderSys); commandInfo.nShow = SW_SHOW; diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp index 3331a4cf..3d852cdc 100644 --- a/CPP/7zip/UI/FileManager/PanelOperations.cpp +++ b/CPP/7zip/UI/FileManager/PanelOperations.cpp @@ -96,7 +96,7 @@ HRESULT CThreadFolderOperations::DoOperation(CPanel &panel, const UString &progr ProgressDialog.MainWindow = panel._mainWindow; // panel.GetParent() - ProgressDialog.MainTitle = L"7-Zip"; // LangString(IDS_APP_TITLE); + ProgressDialog.MainTitle = "7-Zip"; // LangString(IDS_APP_TITLE); ProgressDialog.MainAddTitle = progressTitle + L' '; RINOK(Create(progressTitle, ProgressDialog.MainWindow)); @@ -138,7 +138,7 @@ void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin)) CDynamicBuffer<CHAR> buffer; FOR_VECTOR (i, indices) { - const AString path = GetSystemString(GetItemFullPath(indices[i])); + const AString path (GetSystemString(GetItemFullPath(indices[i]))); buffer.AddData(path, path.Len() + 1); } *buffer.GetCurPtrAndGrow(1) = 0; @@ -502,7 +502,7 @@ void CPanel::ChangeComment() UString name = GetItemRelPath2(realIndex); CComboDialog dlg; dlg.Title = name; - dlg.Title += L" : "; + dlg.Title += " : "; AddLangString(dlg.Title, IDS_COMMENT); dlg.Value = comment; LangString(IDS_COMMENT2, dlg.Static); diff --git a/CPP/7zip/UI/FileManager/PanelSelect.cpp b/CPP/7zip/UI/FileManager/PanelSelect.cpp index 72cb4838..268b64af 100644 --- a/CPP/7zip/UI/FileManager/PanelSelect.cpp +++ b/CPP/7zip/UI/FileManager/PanelSelect.cpp @@ -156,7 +156,7 @@ void CPanel::SelectSpec(bool selectMode) CComboDialog dlg; LangString(selectMode ? IDS_SELECT : IDS_DESELECT, dlg.Title ); LangString(IDS_SELECT_MASK, dlg.Static); - dlg.Value = L'*'; + dlg.Value = '*'; if (dlg.Create(GetParent()) != IDOK) return; const UString &mask = dlg.Value; @@ -192,7 +192,7 @@ void CPanel::SelectByType(bool selectMode) } else { - UString mask = L'*'; + UString mask ('*'); mask += name.Ptr(pos); FOR_VECTOR (i, _selectedStatusVector) if (IsItem_Folder(i) == isItemFolder && DoesWildcardMatchName(mask, GetItemName(i))) diff --git a/CPP/7zip/UI/FileManager/PanelSort.cpp b/CPP/7zip/UI/FileManager/PanelSort.cpp index 59b785b8..4adfc39f 100644 --- a/CPP/7zip/UI/FileManager/PanelSort.cpp +++ b/CPP/7zip/UI/FileManager/PanelSort.cpp @@ -176,17 +176,13 @@ int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) panel->_folder->GetProperty((UInt32)lParam1, propID, &prop1); panel->_folder->GetProperty((UInt32)lParam2, propID, &prop2); if (prop1.vt != prop2.vt) - { return MyCompare(prop1.vt, prop2.vt); - } if (prop1.vt == VT_BSTR) - { - return _wcsicmp(prop1.bstrVal, prop2.bstrVal); - } + return MyStringCompareNoCase(prop1.bstrVal, prop2.bstrVal); return prop1.Compare(prop2); - // return 0; } + int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) { if (lpData == 0) return 0; diff --git a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp index 7aaa97b1..604448e8 100644 --- a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp +++ b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp @@ -24,21 +24,21 @@ using namespace NWindows; using namespace NFile; using namespace NDir; -static const wchar_t *g_Message_FileWriteError = L"File write error"; +static const char * const g_Message_FileWriteError = "File write error"; struct CVolSeqName { UString UnchangedPart; UString ChangedPart; - CVolSeqName(): ChangedPart(L"000") {}; + CVolSeqName(): ChangedPart("000") {}; void SetNumDigits(UInt64 numVolumes) { - ChangedPart = L"000"; + ChangedPart = "000"; while (numVolumes > 999) { numVolumes /= 10; - ChangedPart += L'0'; + ChangedPart += '0'; } } @@ -131,7 +131,7 @@ HRESULT CThreadSplit::ProcessVirt() if (curVolSize == 0) { FString name = VolBasePath; - name += FTEXT('.'); + name += '.'; name += us2fs(seqName.GetNextName()); sync.Set_FilePath(fs2us(name)); sync.Set_NumFilesCur(numFiles++); @@ -236,7 +236,7 @@ void CApp::Split() CProgressDialog &progressDialog = spliter.ProgressDialog; - UString progressWindowTitle = L"7-Zip"; // LangString(IDS_APP_TITLE, 0x03000000); + UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE, 0x03000000); UString title = LangString(IDS_SPLITTING); progressDialog.ShowCompressionInfo = false; @@ -340,7 +340,7 @@ extern void AddValuePair2(UString &s, UINT resourceID, UInt64 num, UInt64 size); static void AddInfoFileName(UString &dest, const UString &name) { - dest += L"\n "; + dest += "\n "; dest += name; } @@ -450,7 +450,7 @@ void CApp::Combine() outName.DeleteBack(); } if (outName.IsEmpty()) - outName = L"file"; + outName = "file"; NFind::CFileInfo fileInfo; UString destFilePath = path + outName; @@ -464,7 +464,7 @@ void CApp::Combine() CProgressDialog &progressDialog = combiner.ProgressDialog; progressDialog.ShowCompressionInfo = false; - UString progressWindowTitle = L"7-Zip"; // LangString(IDS_APP_TITLE, 0x03000000); + UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE, 0x03000000); UString title = LangString(IDS_COMBINING); progressDialog.MainWindow = _window; diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.cpp b/CPP/7zip/UI/FileManager/ProgressDialog.cpp index 65201a9e..1bf115ad 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog.cpp +++ b/CPP/7zip/UI/FileManager/ProgressDialog.cpp @@ -120,7 +120,7 @@ bool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */) wchar_t s[64]; ConvertUInt64ToString(percentValue, s); UString title = s; - title += L"% "; + title += "% "; SetText(title + _title); #ifndef _SFX AddToTitle(title + MainAddTitle); diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp index 8c38b81a..762f2492 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp @@ -217,7 +217,7 @@ void CProgressSync::AddError_Message_Name(const wchar_t *message, const wchar_t UString s; if (name && *name != 0) s += name; - if (message && *message != 0 ) + if (message && *message != 0) { if (!s.IsEmpty()) s.Add_LF(); @@ -232,7 +232,7 @@ void CProgressSync::AddError_Code_Name(DWORD systemError, const wchar_t *name) { UString s = NError::MyFormatMessage(systemError); if (systemError == 0) - s = L"Error"; + s = "Error"; AddError_Message_Name(s, name); } @@ -828,8 +828,8 @@ void CProgressDialog::UpdateStatInfo(bool showAll) ConvertUInt64ToString(completedFiles, s); if (IS_DEFINED_VAL(totalFiles)) { - wcscat(s, L" / "); - ConvertUInt64ToString(totalFiles, s + wcslen(s)); + MyStringCat(s, L" / "); + ConvertUInt64ToString(totalFiles, s + MyStringLen(s)); } if (_filesStr_Prev != s) { @@ -862,7 +862,7 @@ void CProgressDialog::UpdateStatInfo(bool showAll) { _ratio_Prev = ratio; ConvertUInt64ToString(ratio, s); - wcscat(s, L"%"); + MyStringCat(s, L"%"); SetItemText(IDT_PROGRESS_RATIO_VAL, s); } } @@ -986,7 +986,7 @@ bool CProgressDialog::OnExternalCloseMessage() { MessagesDisplayed = true; if (fm.ErrorMessage.Title.IsEmpty()) - fm.ErrorMessage.Title = L"7-Zip"; + fm.ErrorMessage.Title = "7-Zip"; MessageBoxW(*this, fm.ErrorMessage.Message, fm.ErrorMessage.Title, MB_ICONERROR); } else if (!thereAreMessages) @@ -995,7 +995,7 @@ bool CProgressDialog::OnExternalCloseMessage() if (!fm.OkMessage.Message.IsEmpty()) { if (fm.OkMessage.Title.IsEmpty()) - fm.OkMessage.Title = L"7-Zip"; + fm.OkMessage.Title = "7-Zip"; MessageBoxW(*this, fm.OkMessage.Message, fm.OkMessage.Title, MB_OK); } } @@ -1050,8 +1050,8 @@ void CProgressDialog::SetTitleText() { char temp[32]; ConvertUInt64ToString(_prevPercentValue, temp); - s.AddAscii(temp); - s += L'%'; + s += temp; + s += '%'; } if (!_foreground) { @@ -1273,12 +1273,10 @@ void CProgressThreadVirt::Process() catch(const char *s) { m = GetUnicodeString(s); } catch(int v) { - wchar_t s[16]; - ConvertUInt32ToString(v, s); - m = L"Error #"; - m += s; + m = "Error #"; + m.Add_UInt32(v); } - catch(...) { m = L"Error"; } + catch(...) { m = "Error"; } if (Result != E_ABORT) { if (m.IsEmpty() && Result != S_OK) diff --git a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp index 93ba40c2..e48dbb44 100644 --- a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp +++ b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp @@ -17,14 +17,14 @@ namespace NRegistryAssoc { // static NSynchronization::CCriticalSection g_CriticalSection; -static const TCHAR *kClasses = TEXT("Software\\Classes\\"); -// static const TCHAR *kShellNewKeyName = TEXT("ShellNew"); -// static const TCHAR *kShellNewDataValueName = TEXT("Data"); -static const TCHAR *kDefaultIconKeyName = TEXT("DefaultIcon"); -static const TCHAR *kShellKeyName = TEXT("shell"); -static const TCHAR *kOpenKeyName = TEXT("open"); -static const TCHAR *kCommandKeyName = TEXT("command"); -static const TCHAR *k7zipPrefix = TEXT("7-Zip."); +static const TCHAR * const kClasses = TEXT("Software\\Classes\\"); +// static const TCHAR * const kShellNewKeyName = TEXT("ShellNew"); +// static const TCHAR * const kShellNewDataValueName = TEXT("Data"); +static const TCHAR * const kDefaultIconKeyName = TEXT("DefaultIcon"); +static const TCHAR * const kShellKeyName = TEXT("shell"); +static const TCHAR * const kOpenKeyName = TEXT("open"); +static const TCHAR * const kCommandKeyName = TEXT("command"); +static const char * const k7zipPrefix = "7-Zip."; static CSysString GetExtProgramKeyName(const CSysString &ext) { @@ -59,7 +59,8 @@ bool CShellExtInfo::ReadFromRegistry(HKEY hkey, const CSysString &ext) } { CKey iconKey; - if (iconKey.Open(hkey, GetFullKeyPath(hkey, ProgramKey + CSysString(TEXT(CHAR_PATH_SEPARATOR)) + kDefaultIconKeyName), KEY_READ) == ERROR_SUCCESS) + + if (iconKey.Open(hkey, GetFullKeyPath(hkey, ProgramKey + CSysString(CHAR_PATH_SEPARATOR) + kDefaultIconKeyName), KEY_READ) == ERROR_SUCCESS) { UString value; if (iconKey.QueryValue(NULL, value) == ERROR_SUCCESS) @@ -86,7 +87,7 @@ bool CShellExtInfo::ReadFromRegistry(HKEY hkey, const CSysString &ext) bool CShellExtInfo::IsIt7Zip() const { - return IsString1PrefixedByString2_NoCase(GetUnicodeString(ProgramKey), GetUnicodeString(k7zipPrefix)); + return ProgramKey.IsPrefixedBy_Ascii_NoCase(k7zipPrefix); } LONG DeleteShellExtensionInfo(HKEY hkey, const CSysString &ext) @@ -114,9 +115,9 @@ LONG AddShellExtensionInfo(HKEY hkey, // NSynchronization::CCriticalSectionLock lock(g_CriticalSection); CSysString programKeyName; { - CSysString ext2 = ext; + CSysString ext2 (ext); if (iconIndex < 0) - ext2 = TEXT("*"); + ext2 = "*"; programKeyName = GetExtProgramKeyName(ext2); } { @@ -142,10 +143,8 @@ LONG AddShellExtensionInfo(HKEY hkey, iconIndex = 0; // if (iconIndex >= 0) { - iconPathFull += L','; - wchar_t s[16]; - ConvertUInt32ToString((UInt32)iconIndex, s); - iconPathFull += s; + iconPathFull += ','; + iconPathFull.Add_UInt32((UInt32)iconIndex); } iconKey.Create(programKey, kDefaultIconKeyName); iconKey.SetValue(NULL, iconPathFull); diff --git a/CPP/7zip/UI/FileManager/RegistryPlugins.cpp b/CPP/7zip/UI/FileManager/RegistryPlugins.cpp index ad70db80..a0753ca6 100644 --- a/CPP/7zip/UI/FileManager/RegistryPlugins.cpp +++ b/CPP/7zip/UI/FileManager/RegistryPlugins.cpp @@ -13,12 +13,12 @@ using namespace NWindows; using namespace NFile; /* -static const TCHAR *kLMBasePath = TEXT("Software\\7-Zip\\FM"); +static LPCTSTR const kLMBasePath = TEXT("Software\\7-Zip\\FM"); -static const TCHAR *kPluginsKeyName = TEXT("Plugins"); -static const TCHAR *kPluginsOpenClassIDValue = TEXT("CLSID"); -static const TCHAR *kPluginsOptionsClassIDValue = TEXT("Options"); -static const TCHAR *kPluginsTypeValue = TEXT("Type"); +static LPCTSTR const kPluginsKeyName = TEXT("Plugins"); +static LPCTSTR const kPluginsOpenClassIDValue = TEXT("CLSID"); +static LPCTSTR const kPluginsOptionsClassIDValue = TEXT("Options"); +static LPCTSTR const kPluginsTypeValue = TEXT("Type"); static CSysString GetFileFolderPluginsKeyName() { @@ -101,8 +101,10 @@ void ReadPluginInfoList(CObjectVector<CPluginInfo> &plugins) if (::ReadPluginInfo(pluginInfo, false)) plugins.Add(pluginInfo); } - FString folderPath = baseFolderPrefix + FTEXT("Plugins") FSTRING_PATH_SEPARATOR; - NFind::CEnumerator enumerator(folderPath + FCHAR_ANY_MASK); + FString folderPath = baseFolderPrefix; + folderPath += "Plugins" STRING_PATH_SEPARATOR; + NFind::CEnumerator enumerator; + enumerator.SetDirPrefix(folderPath); NFind::CFileInfo fileInfo; while (enumerator.Next(fileInfo)) { @@ -127,7 +129,7 @@ void ReadFileFolderPluginInfoList(CObjectVector<CPluginInfo> &plugins) CPluginInfo p; // p.FilePath.Empty(); p.Type = kPluginTypeFF; - p.Name = L"7-Zip"; + p.Name = "7-Zip"; // p.ClassID = CLSID_CAgentArchiveHandler; p.ClassIDDefined = true; // p.OptionsClassID; diff --git a/CPP/7zip/UI/FileManager/RegistryUtils.cpp b/CPP/7zip/UI/FileManager/RegistryUtils.cpp index 9cc76c36..91b69a21 100644 --- a/CPP/7zip/UI/FileManager/RegistryUtils.cpp +++ b/CPP/7zip/UI/FileManager/RegistryUtils.cpp @@ -13,31 +13,31 @@ using namespace NRegistry; #define REG_PATH_7Z TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") -static const TCHAR *kCUBasePath = REG_PATH_7Z; -static const TCHAR *kCU_FMPath = REG_PATH_7Z TEXT(STRING_PATH_SEPARATOR) TEXT("FM"); -// static const TCHAR *kLM_Path = REG_PATH_7Z TEXT(STRING_PATH_SEPARATOR) TEXT("FM"); +static LPCTSTR const kCUBasePath = REG_PATH_7Z; +static LPCTSTR const kCU_FMPath = REG_PATH_7Z TEXT(STRING_PATH_SEPARATOR) TEXT("FM"); +// static LPCTSTR const kLM_Path = REG_PATH_7Z TEXT(STRING_PATH_SEPARATOR) TEXT("FM"); -static const WCHAR *kLangValueName = L"Lang"; +static LPCWSTR const kLangValueName = L"Lang"; -static const WCHAR *kViewer = L"Viewer"; -static const WCHAR *kEditor = L"Editor"; -static const WCHAR *kDiff = L"Diff"; +static LPCWSTR const kViewer = L"Viewer"; +static LPCWSTR const kEditor = L"Editor"; +static LPCWSTR const kDiff = L"Diff"; -static const TCHAR *kShowDots = TEXT("ShowDots"); -static const TCHAR *kShowRealFileIcons = TEXT("ShowRealFileIcons"); -static const TCHAR *kFullRow = TEXT("FullRow"); -static const TCHAR *kShowGrid = TEXT("ShowGrid"); -static const TCHAR *kSingleClick = TEXT("SingleClick"); -static const TCHAR *kAlternativeSelection = TEXT("AlternativeSelection"); -// static const TCHAR *kUnderline = TEXT("Underline"); +static LPCTSTR const kShowDots = TEXT("ShowDots"); +static LPCTSTR const kShowRealFileIcons = TEXT("ShowRealFileIcons"); +static LPCTSTR const kFullRow = TEXT("FullRow"); +static LPCTSTR const kShowGrid = TEXT("ShowGrid"); +static LPCTSTR const kSingleClick = TEXT("SingleClick"); +static LPCTSTR const kAlternativeSelection = TEXT("AlternativeSelection"); +// static LPCTSTR const kUnderline = TEXT("Underline"); -static const TCHAR *kShowSystemMenu = TEXT("ShowSystemMenu"); +static LPCTSTR const kShowSystemMenu = TEXT("ShowSystemMenu"); -// static const TCHAR *kLockMemoryAdd = TEXT("LockMemoryAdd"); -static const TCHAR *kLargePages = TEXT("LargePages"); +// static LPCTSTR const kLockMemoryAdd = TEXT("LockMemoryAdd"); +static LPCTSTR const kLargePages = TEXT("LargePages"); -static const TCHAR *kFlatViewName = TEXT("FlatViewArc"); -// static const TCHAR *kShowDeletedFiles = TEXT("ShowDeleted"); +static LPCTSTR const kFlatViewName = TEXT("FlatViewArc"); +// static LPCTSTR const kShowDeletedFiles = TEXT("ShowDeleted"); static void SaveCuString(LPCTSTR keyPath, LPCWSTR valuePath, LPCWSTR value) { @@ -63,21 +63,21 @@ void ReadRegEditor(bool useEditor, UString &path) { ReadCuString(kCU_FMPath, use void SaveRegDiff(const UString &path) { SaveCuString(kCU_FMPath, kDiff, path); } void ReadRegDiff(UString &path) { ReadCuString(kCU_FMPath, kDiff, path); } -static void Save7ZipOption(const TCHAR *value, bool enabled) +static void Save7ZipOption(LPCTSTR value, bool enabled) { CKey key; key.Create(HKEY_CURRENT_USER, kCUBasePath); key.SetValue(value, enabled); } -static void SaveOption(const TCHAR *value, bool enabled) +static void SaveOption(LPCTSTR value, bool enabled) { CKey key; key.Create(HKEY_CURRENT_USER, kCU_FMPath); key.SetValue(value, enabled); } -static bool Read7ZipOption(const TCHAR *value, bool defaultValue) +static bool Read7ZipOption(LPCTSTR value, bool defaultValue) { CKey key; if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) == ERROR_SUCCESS) @@ -89,7 +89,7 @@ static bool Read7ZipOption(const TCHAR *value, bool defaultValue) return defaultValue; } -static void ReadOption(CKey &key, const TCHAR *value, bool &dest) +static void ReadOption(CKey &key, LPCTSTR value, bool &dest) { bool enabled = false; if (key.QueryValue(value, enabled) == ERROR_SUCCESS) @@ -97,14 +97,14 @@ static void ReadOption(CKey &key, const TCHAR *value, bool &dest) } /* -static void SaveLmOption(const TCHAR *value, bool enabled) +static void SaveLmOption(LPCTSTR value, bool enabled) { CKey key; key.Create(HKEY_LOCAL_MACHINE, kLM_Path); key.SetValue(value, enabled); } -static bool ReadLmOption(const TCHAR *value, bool defaultValue) +static bool ReadLmOption(LPCTSTR value, bool defaultValue) { CKey key; if (key.Open(HKEY_LOCAL_MACHINE, kLM_Path, KEY_READ) == ERROR_SUCCESS) diff --git a/CPP/7zip/UI/FileManager/RootFolder.cpp b/CPP/7zip/UI/FileManager/RootFolder.cpp index b9629263..643f1066 100644 --- a/CPP/7zip/UI/FileManager/RootFolder.cpp +++ b/CPP/7zip/UI/FileManager/RootFolder.cpp @@ -79,7 +79,7 @@ enum }; #ifdef USE_WIN_PATHS -static const wchar_t *kVolPrefix = L"\\\\."; +static const char * const kVolPrefix = "\\\\."; #endif void CRootFolder::Init() @@ -194,7 +194,7 @@ static bool AreEqualNames(const UString &path, const wchar_t *name) unsigned len = MyStringLen(name); if (len > path.Len() || len + 1 < path.Len()) return false; - if (len + 1 == path.Len() && path[len] != WCHAR_PATH_SEPARATOR) + if (len + 1 == path.Len() && !IS_PATH_SEPAR(path[len])) return false; return path.IsPrefixedBy(name); } @@ -244,13 +244,13 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu CMyComPtr<IFolderFolder> subFolder; #ifdef USE_WIN_PATHS - if (name2.IsPrefixedBy(kVolPrefix)) + if (name2.IsPrefixedBy_Ascii_NoCase(kVolPrefix)) { CFSDrives *folderSpec = new CFSDrives; subFolder = folderSpec; folderSpec->Init(true); } - else if (name2 == NFile::NName::kSuperPathPrefix) + else if (name2.IsEqualTo(NFile::NName::kSuperPathPrefix)) { CFSDrives *folderSpec = new CFSDrives; subFolder = folderSpec; @@ -272,7 +272,7 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu if (fsFolderSpec->Init(us2fs(name2)) != S_OK) { #ifdef USE_WIN_PATHS - if (name2[0] == WCHAR_PATH_SEPARATOR) + if (IS_PATH_SEPAR(name2[0])) { CNetFolder *netFolderSpec = new CNetFolder; subFolder = netFolderSpec; diff --git a/CPP/7zip/UI/FileManager/SettingsPage.cpp b/CPP/7zip/UI/FileManager/SettingsPage.cpp index 07121b28..bdd62f71 100644 --- a/CPP/7zip/UI/FileManager/SettingsPage.cpp +++ b/CPP/7zip/UI/FileManager/SettingsPage.cpp @@ -29,7 +29,7 @@ static const UInt32 kLangIDs[] = IDX_SETTINGS_LARGE_PAGES }; -static LPCWSTR kEditTopic = L"FM/options.htm#settings"; +#define kSettingsTopic "FM/options.htm#settings" extern bool IsLargePageSupported(); @@ -108,7 +108,7 @@ LONG CSettingsPage::OnApply() void CSettingsPage::OnNotifyHelp() { - ShowHelpWindow(NULL, kEditTopic); // change it + ShowHelpWindow(kSettingsTopic); } bool CSettingsPage::OnButtonClicked(int buttonID, HWND buttonHWND) diff --git a/CPP/7zip/UI/FileManager/SplitDialog.cpp b/CPP/7zip/UI/FileManager/SplitDialog.cpp index 455874ef..0c9fdd17 100644 --- a/CPP/7zip/UI/FileManager/SplitDialog.cpp +++ b/CPP/7zip/UI/FileManager/SplitDialog.cpp @@ -90,7 +90,7 @@ void CSplitDialog::OnButtonSetPath() { UString currentPath; _pathCombo.GetText(currentPath); - // UString title = L"Specify a location for output folder"; + // UString title = "Specify a location for output folder"; UString title = LangString(IDS_SET_FOLDER); UString resultPath; diff --git a/CPP/7zip/UI/FileManager/SplitUtils.cpp b/CPP/7zip/UI/FileManager/SplitUtils.cpp index b0172a9f..4b6235b3 100644 --- a/CPP/7zip/UI/FileManager/SplitUtils.cpp +++ b/CPP/7zip/UI/FileManager/SplitUtils.cpp @@ -57,16 +57,25 @@ bool ParseVolumeSizes(const UString &s, CRecordVector<UInt64> &values) return true; } + +static const char * const k_Sizes[] = +{ + "10M" + , "100M" + , "1000M" + , "650M - CD" + , "700M - CD" + , "4092M - FAT" + , "4480M - DVD" // 4489 MiB limit + , "8128M - DVD DL" // 8147 MiB limit + , "23040M - BD" // 23866 MiB limit + // , "1457664 - 3.5\" floppy" +}; + void AddVolumeItems(NWindows::NControl::CComboBox &combo) { - combo.AddString(TEXT("10M")); - combo.AddString(TEXT("650M - CD")); - combo.AddString(TEXT("700M - CD")); - combo.AddString(TEXT("4092M - FAT")); - combo.AddString(TEXT("4480M - DVD")); // 4489 MiB limit - combo.AddString(TEXT("8128M - DVD DL")); // 8147 MiB limit - combo.AddString(TEXT("23040M - BD")); // 23866 MiB limit - combo.AddString(TEXT("1457664 - 3.5\" floppy")); + for (unsigned i = 0; i < ARRAY_SIZE(k_Sizes); i++) + combo.AddString(CSysString(k_Sizes[i])); } UInt64 GetNumberOfVolumes(UInt64 size, const CRecordVector<UInt64> &volSizes) diff --git a/CPP/7zip/UI/FileManager/StringUtils.cpp b/CPP/7zip/UI/FileManager/StringUtils.cpp index 7c814f7f..04783992 100644 --- a/CPP/7zip/UI/FileManager/StringUtils.cpp +++ b/CPP/7zip/UI/FileManager/StringUtils.cpp @@ -12,9 +12,9 @@ void SplitStringToTwoStrings(const UString &src, UString &dest1, UString &dest2) for (unsigned i = 0; i < src.Len(); i++) { const wchar_t c = src[i]; - if (c == L'\"') + if (c == '\"') quoteMode = !quoteMode; - else if (c == L' ' && !quoteMode) + else if (c == ' ' && !quoteMode) { dest2 = src.Ptr(i + 1); return; @@ -34,7 +34,7 @@ void SplitString(const UString &srcString, UStringVector &destStrings) for (unsigned i = 0; i < len; i++) { wchar_t c = srcString[i]; - if (c == L' ') + if (c == ' ') { if (!s.IsEmpty()) { diff --git a/CPP/7zip/UI/FileManager/SystemPage.cpp b/CPP/7zip/UI/FileManager/SystemPage.cpp index 5214a55c..819443ee 100644 --- a/CPP/7zip/UI/FileManager/SystemPage.cpp +++ b/CPP/7zip/UI/FileManager/SystemPage.cpp @@ -30,7 +30,7 @@ static const UInt32 kLangIDs[] = IDT_SYSTEM_ASSOCIATE }; -static LPCWSTR kSystemTopic = L"FM/options.htm#system"; +#define kSystemTopic "FM/options.htm#system" CSysString CModifiedExtInfo::GetString() const { @@ -165,7 +165,7 @@ bool CSystemPage::OnInit() UString s; #if NUM_EXT_GROUPS == 1 - s.SetFromAscii("Program"); + s = "Program"; #else #ifndef UNDER_CE const unsigned kSize = 256; @@ -190,7 +190,7 @@ bool CSystemPage::OnInit() if (!res) #endif - s.SetFromAscii("Current User"); + s = "Current User"; #endif LV_COLUMNW ci; @@ -257,9 +257,9 @@ bool CSystemPage::OnInit() static UString GetProgramCommand() { - UString s = L"\""; + UString s ('\"'); s += fs2us(NDLL::GetModuleDirPrefix()); - s.AddAscii("7zFM.exe\" \"%1\""); + s += "7zFM.exe\" \"%1\""; return s; } @@ -291,7 +291,7 @@ LONG CSystemPage::OnApply() if (mi.State == kExtState_7Zip) { UString title = extInfo.Ext; - title.AddAscii(" Archive"); + title += " Archive"; const CPluginToIcon &plug = extInfo.Plugins[0]; res2 = NRegistryAssoc::AddShellExtensionInfo(key, GetSystemString(extInfo.Ext), title, command, plug.IconPath, plug.IconIndex); @@ -327,7 +327,7 @@ LONG CSystemPage::OnApply() void CSystemPage::OnNotifyHelp() { - ShowHelpWindow(NULL, kSystemTopic); + ShowHelpWindow(kSystemTopic); } diff --git a/CPP/7zip/UI/FileManager/TextPairs.cpp b/CPP/7zip/UI/FileManager/TextPairs.cpp index 0fac2506..d4002b45 100644 --- a/CPP/7zip/UI/FileManager/TextPairs.cpp +++ b/CPP/7zip/UI/FileManager/TextPairs.cpp @@ -178,13 +178,13 @@ void CPairsStorage::SaveToString(UString &text) const const CTextPair &pair = Pairs[i]; bool multiWord = (pair.ID.Find(L' ') >= 0); if (multiWord) - text += L'\"'; + text += '\"'; text += pair.ID; if (multiWord) - text += L'\"'; - text += L' '; + text += '\"'; + text += ' '; text += pair.Value; - text += L'\x0D'; + text += '\x0D'; text.Add_LF(); } } diff --git a/CPP/7zip/UI/FileManager/ViewSettings.cpp b/CPP/7zip/UI/FileManager/ViewSettings.cpp index 9292d120..af61efcd 100644 --- a/CPP/7zip/UI/FileManager/ViewSettings.cpp +++ b/CPP/7zip/UI/FileManager/ViewSettings.cpp @@ -17,18 +17,19 @@ using namespace NRegistry; #define REG_PATH_FM TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR) TEXT("FM") -static const TCHAR *kCUBasePath = REG_PATH_FM; -static const TCHAR *kCulumnsKeyName = REG_PATH_FM TEXT(STRING_PATH_SEPARATOR) TEXT("Columns"); +static LPCTSTR const kCUBasePath = REG_PATH_FM; +static LPCTSTR const kCulumnsKeyName = REG_PATH_FM TEXT(STRING_PATH_SEPARATOR) TEXT("Columns"); -static const TCHAR *kPositionValueName = TEXT("Position"); -static const TCHAR *kPanelsInfoValueName = TEXT("Panels"); -static const TCHAR *kToolbars = TEXT("Toolbars"); +static LPCTSTR const kPositionValueName = TEXT("Position"); +static LPCTSTR const kPanelsInfoValueName = TEXT("Panels"); +static LPCTSTR const kToolbars = TEXT("Toolbars"); -static const WCHAR *kPanelPathValueName = L"PanelPath"; -static const TCHAR *kListMode = TEXT("ListMode"); -static const TCHAR *kFolderHistoryValueName = TEXT("FolderHistory"); -static const TCHAR *kFastFoldersValueName = TEXT("FolderShortcuts"); -static const TCHAR *kCopyHistoryValueName = TEXT("CopyHistory"); +static LPCWSTR const kPanelPathValueName = L"PanelPath"; + +static LPCTSTR const kListMode = TEXT("ListMode"); +static LPCTSTR const kFolderHistoryValueName = TEXT("FolderHistory"); +static LPCTSTR const kFastFoldersValueName = TEXT("FolderShortcuts"); +static LPCTSTR const kCopyHistoryValueName = TEXT("CopyHistory"); static NSynchronization::CCriticalSection g_CS; @@ -246,9 +247,9 @@ void CListMode::Read() static UString GetPanelPathName(UInt32 panelIndex) { - WCHAR s[16]; - ConvertUInt32ToString(panelIndex, s); - return (UString)kPanelPathValueName + s; + UString s (kPanelPathValueName); + s.Add_UInt32(panelIndex); + return s; } void SavePanelPath(UInt32 panel, const UString &path) diff --git a/CPP/7zip/UI/FileManager/resource.h b/CPP/7zip/UI/FileManager/resource.h index b7ca17f1..bb0d7752 100644 --- a/CPP/7zip/UI/FileManager/resource.h +++ b/CPP/7zip/UI/FileManager/resource.h @@ -85,6 +85,8 @@ #define IDM_VIEW_TOOLBARS_LARGE_BUTTONS 752 #define IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT 753 +#define IDM_VIEW_TIME 761 + #define IDS_BOOKMARK 801 #define IDM_OPTIONS 900 diff --git a/CPP/7zip/UI/FileManager/resource.rc b/CPP/7zip/UI/FileManager/resource.rc index 7db5d3a1..a166129b 100644 --- a/CPP/7zip/UI/FileManager/resource.rc +++ b/CPP/7zip/UI/FileManager/resource.rc @@ -83,6 +83,12 @@ BEGIN MENUITEM SEPARATOR MENUITEM "Flat View", IDM_VIEW_FLAT_VIEW MENUITEM "&2 Panels\tF9", IDM_VIEW_TWO_PANELS + + POPUP "2017" + BEGIN + MENUITEM "Time", IDM_VIEW_TIME + END + POPUP "Toolbars" BEGIN MENUITEM "Archive Toolbar", IDM_VIEW_ARCHIVE_TOOLBAR @@ -112,9 +118,10 @@ BEGIN POPUP "&Tools" BEGIN MENUITEM "&Options...", IDM_OPTIONS + MENUITEM SEPARATOR MENUITEM "&Benchmark", IDM_BENCHMARK #ifdef UNDER_CE - MENUITEM "&Benchmark2", IDM_BENCHMARK2 + MENUITEM "Benchmark 2", IDM_BENCHMARK2 #endif #ifndef UNDER_CE END diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp index 4fba3dc3..59dc78b3 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp @@ -23,9 +23,7 @@ using namespace NWindows; -void GetCpuName(AString &s); - -static LPCWSTR kHelpTopic = L"fm/benchmark.htm"; +#define kHelpTopic "fm/benchmark.htm" static const UINT_PTR kTimerID = 4; static const UINT kTimerElapse = 1000; @@ -66,10 +64,10 @@ static const UInt32 kLangIDs_Colon[] = #endif -static const LPCTSTR kProcessingString = TEXT("..."); -static const LPCTSTR kMB = TEXT(" MB"); -static const LPCTSTR kMIPS = TEXT(" MIPS"); -static const LPCTSTR kKBs = TEXT(" KB/s"); +static LPCTSTR const kProcessingString = TEXT("..."); +static LPCTSTR const kMB = TEXT(" MB"); +static LPCTSTR const kMIPS = TEXT(" MIPS"); +static LPCTSTR const kKBs = TEXT(" KB/s"); static const unsigned kMinDicLogSize = #ifdef UNDER_CE @@ -119,35 +117,67 @@ bool CBenchmarkDialog::OnInit() _consoleEdit.SendMsg(WM_SETFONT, (WPARAM)_font._font, TRUE); } + UInt32 numCPUs = 1; + { - TCHAR s[40]; - s[0] = '/'; - s[1] = ' '; - ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2); + UString s ("/ "); + + NSystem::CProcessAffinity threadsInfo; + threadsInfo.InitST(); + + #ifndef _7ZIP_ST + + if (threadsInfo.Get() && threadsInfo.processAffinityMask != 0) + numCPUs = threadsInfo.GetNumProcessThreads(); + else + numCPUs = NSystem::GetNumberOfProcessors(); + + #endif + + s.Add_UInt32(numCPUs); + s += GetProcessThreadsInfo(threadsInfo); SetItemText(IDT_BENCH_HARDWARE_THREADS, s); } { UString s; { - AString cpuName; - GetCpuName(cpuName); - s.SetFromAscii(cpuName); + AString s1, s2; + GetSysInfo(s1, s2); + s = s1; + SetItemText(IDT_BENCH_SYS1, s); + if (s1 != s2 && !s2.IsEmpty()) + { + s = s2; + SetItemText(IDT_BENCH_SYS2, s); + } + } + /* + { + GetVersionString(s); + SetItemText(IDT_BENCH_SYSTEM, s); + } + */ + { + AString s2; + GetCpuName(s2); + s = s2; SetItemText(IDT_BENCH_CPU, s); } + /* + { + AString s2; + GetCpuFeatures(s2); + s = s2; + SetItemText(IDT_BENCH_CPU_FEATURE, s); + } + */ - s.SetFromAscii("7-Zip " MY_VERSION " [" - #ifdef MY_CPU_64BIT - "64-bit" - #elif defined MY_CPU_32BIT - "32-bit" - #endif - "]"); + s = "7-Zip " MY_VERSION_CPU; SetItemText(IDT_BENCH_VER, s); } - UInt32 numCPUs = NSystem::GetNumberOfProcessors(); if (numCPUs < 1) numCPUs = 1; numCPUs = MyMin(numCPUs, (UInt32)(1 << 8)); @@ -178,8 +208,8 @@ bool CBenchmarkDialog::OnInit() m_Dictionary.Attach(GetItem(IDC_BENCH_DICTIONARY)); cur = 0; - UInt64 ramSize = (UInt64)(sizeof(size_t)) << 29; - bool ramSize_Defined = NSystem::GetRamSize(ramSize); + ramSize = (UInt64)(sizeof(size_t)) << 29; + ramSize_Defined = NSystem::GetRamSize(ramSize); #ifdef UNDER_CE const UInt32 kNormalizedCeSize = (16 << 20); @@ -208,10 +238,10 @@ bool CBenchmarkDialog::OnInit() for (unsigned i = kMinDicLogSize; i <= 30; i++) for (unsigned j = 0; j < 2; j++) { - UInt32 dict = (1 << i) + (j << (i - 1)); + UInt32 dict = ((UInt32)1 << i) + ((UInt32)j << (i - 1)); if (dict > kMaxDicSize) continue; - TCHAR s[16]; + TCHAR s[32]; ConvertUInt32ToString((dict >> 20), s); lstrcat(s, kMB); int index = (int)m_Dictionary.AddString(s); @@ -276,15 +306,43 @@ UInt32 CBenchmarkDialog::GetNumberOfThreads() return (UInt32)m_NumThreads.GetItemData_of_CurSel(); } + +void CBenchmarkDialog::SetItemText_Number(int itemID, UInt64 val, LPCTSTR post) +{ + TCHAR s[64]; + ConvertUInt64ToString(val, s); + if (post) + lstrcat(s, post); + SetItemText(itemID, s); +} + +static void PrintSize_MB(UString &s, UInt64 size) +{ + char temp[32]; + ConvertUInt64ToString((size + (1 << 20) - 1) >> 20, temp); + s += temp; + s += kMB; +} + +extern bool g_LargePagesMode; + UInt32 CBenchmarkDialog::OnChangeDictionary() { - UInt32 dict = (UInt32)m_Dictionary.GetItemData_of_CurSel(); - UInt64 memUsage = GetBenchMemoryUsage(GetNumberOfThreads(), dict); - memUsage = (memUsage + (1 << 20) - 1) >> 20; - TCHAR s[40]; - ConvertUInt64ToString(memUsage, s); - lstrcat(s, kMB); + const UInt32 dict = (UInt32)m_Dictionary.GetItemData_of_CurSel(); + const UInt64 memUsage = GetBenchMemoryUsage(GetNumberOfThreads(), dict); + + UString s; + PrintSize_MB(s, memUsage); + if (ramSize_Defined) + { + s += " / "; + PrintSize_MB(s, ramSize); + } + if (g_LargePagesMode) + s += " LP"; + SetItemText(IDT_BENCH_MEMORY_VAL, s); + return dict; } @@ -311,6 +369,9 @@ static const UInt32 g_IDs[] = IDT_BENCH_TOTAL_USAGE_VAL, IDT_BENCH_TOTAL_RATING_VAL, IDT_BENCH_TOTAL_RPU_VAL + + // IDT_BENCH_FREQ_CUR, + // IDT_BENCH_FREQ_RES }; void CBenchmarkDialog::OnChangeSettings() @@ -342,7 +403,7 @@ void CBenchmarkDialog::OnStopButton() void CBenchmarkDialog::OnHelp() { - ShowHelpWindow(NULL, kHelpTopic); + ShowHelpWindow(kHelpTopic); } void CBenchmarkDialog::OnCancel() @@ -368,18 +429,12 @@ void CBenchmarkDialog::PrintTime() void CBenchmarkDialog::PrintRating(UInt64 rating, UINT controlID) { - TCHAR s[40]; - ConvertUInt64ToString(rating / 1000000, s); - lstrcat(s, kMIPS); - SetItemText(controlID, s); + SetItemText_Number(controlID, rating / 1000000, kMIPS); } void CBenchmarkDialog::PrintUsage(UInt64 usage, UINT controlID) { - TCHAR s[40]; - ConvertUInt64ToString((usage + 5000) / 10000, s); - lstrcat(s, TEXT("%")); - SetItemText(controlID, s); + SetItemText_Number(controlID, (usage + 5000) / 10000, TEXT("%")); } void CBenchmarkDialog::PrintResults( @@ -391,12 +446,9 @@ void CBenchmarkDialog::PrintResults( if (info.GlobalTime == 0) return; - TCHAR s[40]; { - UInt64 speed = info.UnpackSize * info.NumIterations * info.GlobalFreq / info.GlobalTime; - ConvertUInt64ToString(speed / 1024, s); - lstrcat(s, kKBs); - SetItemText(speedID, s); + const UInt64 speed = info.UnpackSize * info.NumIterations * info.GlobalFreq / info.GlobalTime; + SetItemText_Number(speedID, speed >> 10, kKBs); } UInt64 rating; if (decompressMode) @@ -419,25 +471,36 @@ bool CBenchmarkDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */) } if (printTime) PrintTime(); - NWindows::NSynchronization::CCriticalSectionLock lock(Sync.CS); if (TotalMode) { - if (Sync.TextWasChanged) + bool wasChanged = false; { - _consoleEdit.SetText(GetSystemString(Sync.Text)); - Sync.TextWasChanged = false; + NWindows::NSynchronization::CCriticalSectionLock lock(Sync.CS); + + if (Sync.TextWasChanged) + { + wasChanged = true; + Bench2Text += Sync.Text; + Sync.Text.Empty(); + Sync.TextWasChanged = false; + } } + if (wasChanged) + _consoleEdit.SetText(Bench2Text); return true; } - TCHAR s[40]; - ConvertUInt64ToString((Sync.ProcessedSize >> 20), s); - lstrcat(s, kMB); - SetItemText(IDT_BENCH_SIZE_VAL, s); + SetItemText_Number(IDT_BENCH_SIZE_VAL, (Sync.ProcessedSize >> 20), kMB); - ConvertUInt64ToString(Sync.NumPasses, s); - SetItemText(IDT_BENCH_PASSES_VAL, s); + SetItemText_Number(IDT_BENCH_PASSES_VAL, Sync.NumPasses); + + /* + if (Sync.FirstPath) + SetItemText_Number(IDT_BENCH_FREQ_CUR, Sync.Freq, TEXT(" MHz")); + else + SetItemText_Number(IDT_BENCH_FREQ_RES, Sync.Freq, TEXT(" MHz")); + */ /* if (Sync.FreqWasChanged) @@ -549,7 +612,7 @@ struct CThreadBenchmark struct CBenchCallback: public IBenchCallback { UInt32 dictionarySize; - CProgressSyncInfo *Sync; + CBenchProgressSync *Sync; // void AddCpuFreq(UInt64 cpuFreq); HRESULT SetFreq(bool showFreq, UInt64 cpuFreq); @@ -613,7 +676,8 @@ HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final) struct CBenchCallback2: public IBenchPrintCallback { - CProgressSyncInfo *Sync; + CBenchProgressSync *Sync; + bool TotalMode; void Print(const char *s); void NewLine(); @@ -622,9 +686,12 @@ struct CBenchCallback2: public IBenchPrintCallback void CBenchCallback2::Print(const char *s) { - NSynchronization::CCriticalSectionLock lock(Sync->CS); - Sync->Text += s; - Sync->TextWasChanged = true; + if (TotalMode) + { + NSynchronization::CCriticalSectionLock lock(Sync->CS); + Sync->Text += s; + Sync->TextWasChanged = true; + } } void CBenchCallback2::NewLine() @@ -640,9 +707,27 @@ HRESULT CBenchCallback2::CheckBreak() } + +/* +struct CFreqCallback: public IBenchFreqCallback +{ + CBenchProgressSync *Sync; + + virtual void AddCpuFreq(UInt64 freq); +}; + +void CFreqCallback::AddCpuFreq(UInt64 freq) +{ + NSynchronization::CCriticalSectionLock lock(Sync->CS); + Sync->Freq = freq; +} +*/ + + + HRESULT CThreadBenchmark::Process() { - CProgressSyncInfo &sync = BenchmarkDialog->Sync; + CBenchProgressSync &sync = BenchmarkDialog->Sync; sync.WaitCreating(); try { @@ -665,13 +750,20 @@ HRESULT CThreadBenchmark::Process() sync.Init(); dictionarySize = sync.DictionarySize; numThreads = sync.NumThreads; + /* + if (sync.CompressingInfo.GlobalTime != 0) + sync.FirstPath = false; + */ } CBenchCallback callback; callback.dictionarySize = dictionarySize; callback.Sync = &sync; CBenchCallback2 callback2; + callback2.TotalMode = BenchmarkDialog->TotalMode; callback2.Sync = &sync; + // CFreqCallback freqCallback; + // freqCallback.Sync = &sync; HRESULT result; try @@ -685,26 +777,25 @@ HRESULT CThreadBenchmark::Process() { { CProperty prop; - prop.Name = L"mt"; - wchar_t s[16]; - ConvertUInt32ToString(numThreads, s); - prop.Value = s; + prop.Name = "mt"; + prop.Value.Add_UInt32(numThreads); props.Add(prop); } { CProperty prop; - prop.Name = L'd'; - wchar_t s[16]; - ConvertUInt32ToString(dictionarySize, s); - prop.Name += s; - prop.Name += L'b'; + prop.Name = 'd'; + prop.Name.Add_UInt32(dictionarySize); + prop.Name += 'b'; props.Add(prop); } } + result = Bench(EXTERNAL_CODECS_LOC_VARS BenchmarkDialog->TotalMode ? &callback2 : NULL, BenchmarkDialog->TotalMode ? NULL : &callback, + // &freqCallback, props, 1, false); + if (BenchmarkDialog->TotalMode) { sync.Stop(); @@ -725,9 +816,9 @@ HRESULT CThreadBenchmark::Process() } UString message; if (result == S_FALSE) - message = L"Decoding error"; + message = "Decoding error"; else if (result == CLASS_E_CLASSNOTAVAILABLE) - message = L"Can't find 7z.dll"; + message = "Can't find 7z.dll"; else message = HResultToMessage(result); BenchmarkDialog->MessageBoxError(message); @@ -820,7 +911,13 @@ HRESULT Benchmark( RINOK(method.ParseMethodFromPROPVARIANT(name, propVariant)); } - // bool totalBenchMode = (method.MethodName == L"*"); + if (bd.TotalMode) + { + // bd.Bench2Text.Empty(); + bd.Bench2Text = "7-Zip " MY_VERSION_CPU; + bd.Bench2Text += (char)0xD; + bd.Bench2Text.Add_LF(); + } { UInt32 dict; diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.h b/CPP/7zip/UI/GUI/BenchmarkDialog.h index 0d88d217..1bad8ea9 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.h +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.h @@ -29,7 +29,7 @@ struct CBenchInfo2 : public CBenchInfo } }; -class CProgressSyncInfo +class CBenchProgressSync { public: bool Stopped; @@ -51,10 +51,12 @@ public: AString Text; bool TextWasChanged; + // bool FirstPath; + // UInt64 Freq; // UString Freq; // bool FreqWasChanged; - CProgressSyncInfo() + CBenchProgressSync() { if (_startEvent.Create() != S_OK) throw 3986437; @@ -74,6 +76,8 @@ public: NumPasses = 0; + // FirstPath = true; + // Freq = 0; // Freq.SetFromAscii("MHz: "); // FreqWasChanged = true; @@ -135,6 +139,9 @@ class CBenchmarkDialog: UInt32 _startTime; CMyFont _font; + UInt64 ramSize; + bool ramSize_Defined; + bool OnSize(WPARAM /* wParam */, int xSize, int ySize); bool OnTimer(WPARAM timerID, LPARAM callback); virtual bool OnInit(); @@ -156,11 +163,16 @@ class CBenchmarkDialog: UInt32 GetNumberOfThreads(); UInt32 OnChangeDictionary(); void OnChangeSettings(); + + void SetItemText_Number(int itemID, UInt64 val, LPCTSTR post = NULL); + public: - CProgressSyncInfo Sync; + CBenchProgressSync Sync; bool TotalMode; CObjectVector<CProperty> Props; + CSysString Bench2Text; + CBenchmarkDialog(): _timer(0), TotalMode(false) {} INT_PTR Create(HWND wndParent = 0) { diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.rc b/CPP/7zip/UI/GUI/BenchmarkDialog.rc index cae9097b..f1d37cab 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.rc +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.rc @@ -16,7 +16,7 @@ #define gSpace 24 #define g0xs 90 -#define g1xs 44 +#define g1xs 48 #define g1x (m + g0xs) #define gc2x (g1x + g1xs + m) #define gc2xs 80 @@ -27,12 +27,15 @@ #define sSpeed 60 #define sUsage 60 #define sRpu 60 +#define sFreq 34 #define xRating (xs - m - m - sRating) #define xRpu (xRating - sRpu) #define xUsage (xRpu - sUsage) #define xSpeed (xUsage - sSpeed) +#define xFreq (xUsage - sFreq) + #define sLabel (xUsage - g4x) #define sTotalRating (sUsage + sRpu + sRating + m + m) #define xTotalRating (xs - m - sTotalRating) @@ -51,6 +54,8 @@ #define GROUP_Y2_SIZE 32 #endif +#define g7xs bx1 - m - g0xs - g1xs - m + IDD_BENCH DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE | WS_MINIMIZEBOX CAPTION "Benchmark" MY_FONT @@ -64,12 +69,12 @@ BEGIN LTEXT "&Dictionary size:", IDT_BENCH_DICTIONARY, m, m + 1, g0xs, 8 COMBOBOX IDC_BENCH_DICTIONARY, g1x, m, g1xs, 140, MY_COMBO - LTEXT "Memory usage:", IDT_BENCH_MEMORY, gc2x, m + 1, gc2xs, 8 - LTEXT "", IDT_BENCH_MEMORY_VAL, gc2x + gc2xs, m + 1, 40, 8 + LTEXT "Memory usage:", IDT_BENCH_MEMORY, gc2x, m - 2, g7xs, 8 + LTEXT "", IDT_BENCH_MEMORY_VAL, gc2x, m + 8, g7xs, 8 - LTEXT "&Number of CPU threads:", IDT_BENCH_NUM_THREADS, m, 28, g0xs, 8 - COMBOBOX IDC_BENCH_NUM_THREADS, g1x, 27, g1xs, 140, MY_COMBO - LTEXT "", IDT_BENCH_HARDWARE_THREADS, gc2x, 28, 40, 8 + LTEXT "&Number of CPU threads:", IDT_BENCH_NUM_THREADS, m, 30, g0xs, 8 + COMBOBOX IDC_BENCH_NUM_THREADS, g1x, 29, g1xs, 140, MY_COMBO + LTEXT "", IDT_BENCH_HARDWARE_THREADS, gc2x, 32, g7xs, 8 RTEXT "CPU Usage", IDT_BENCH_USAGE_LABEL, xUsage, 54, sUsage, 8 RTEXT "Speed", IDT_BENCH_SPEED, xSpeed, 54, sSpeed, 8 @@ -111,7 +116,17 @@ BEGIN 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 + + RTEXT "", IDT_BENCH_VER, m + xc - 80, 216, 80, 8 + + LTEXT "", IDT_BENCH_CPU_FEATURE, m, 212, xc - 80, 26 + LTEXT "", IDT_BENCH_SYS1, m, 238, xc - 140, 8 + LTEXT "", IDT_BENCH_SYS2, m, 248, xc - 140, 8 + + // LTEXT "", IDT_BENCH_SYSTEM, m, 232, xc - 80, 8 + // LTEXT "", IDT_BENCH_FREQ_RES, m, 242, 80, 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 a632d764..8ee4f681 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialogRes.h +++ b/CPP/7zip/UI/GUI/BenchmarkDialogRes.h @@ -11,6 +11,9 @@ #define IDT_BENCH_VER 105 #define IDT_BENCH_CPU 106 +#define IDT_BENCH_SYS1 107 +#define IDT_BENCH_SYS2 108 +#define IDT_BENCH_CPU_FEATURE 109 #define IDT_BENCH_COMPRESS_SPEED1 110 #define IDT_BENCH_COMPRESS_SPEED2 111 @@ -39,6 +42,9 @@ #define IDT_BENCH_PASSES_VAL 142 +// #define IDT_BENCH_FREQ_CUR 150 +// #define IDT_BENCH_FREQ_RES 151 + #define IDB_STOP 442 #define IDB_RESTART 443 diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp index 14a9d31c..57f7c30a 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.cpp +++ b/CPP/7zip/UI/GUI/CompressDialog.cpp @@ -80,8 +80,9 @@ using namespace NDir; static const unsigned kHistorySize = 20; -static LPCWSTR kExeExt = L".exe"; -static LPCWSTR k7zFormat = L"7z"; +static LPCSTR const kExeExt = ".exe"; + +#define k7zFormat "7z" static const UInt32 g_Levels[] = { @@ -109,16 +110,16 @@ enum EMethodID kPPMdZip }; -static const LPCWSTR kMethodsNames[] = +static LPCSTR const kMethodsNames[] = { - L"Copy", - L"LZMA", - L"LZMA2", - L"PPMd", - L"BZip2", - L"Deflate", - L"Deflate64", - L"PPMd" + "Copy" + , "LZMA" + , "LZMA2" + , "PPMd" + , "BZip2" + , "Deflate" + , "Deflate64" + , "PPMd" }; static const EMethodID g_7zMethods[] = @@ -169,10 +170,10 @@ static const EMethodID g_SwfcMethods[] = struct CFormatInfo { - LPCWSTR Name; + LPCSTR Name; UInt32 LevelsMask; - const EMethodID *MathodIDs; unsigned NumMethods; + const EMethodID *MathodIDs; bool Filter; bool Solid; bool MultiThread; @@ -182,12 +183,12 @@ struct CFormatInfo bool EncryptFileNames; }; -#define METHODS_PAIR(x) x, ARRAY_SIZE(x) +#define METHODS_PAIR(x) ARRAY_SIZE(x), x static const CFormatInfo g_Formats[] = { { - L"", + "", (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), 0, 0, false, false, false, false, false, false @@ -199,43 +200,43 @@ static const CFormatInfo g_Formats[] = true, true, true, true, true, true }, { - L"Zip", + "Zip", (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), METHODS_PAIR(g_ZipMethods), false, false, true, false, true, false }, { - L"GZip", + "GZip", (1 << 1) | (1 << 5) | (1 << 7) | (1 << 9), METHODS_PAIR(g_GZipMethods), false, false, false, false, false, false }, { - L"BZip2", + "BZip2", (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), METHODS_PAIR(g_BZip2Methods), false, false, true, false, false, false }, { - L"xz", + "xz", (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), METHODS_PAIR(g_XzMethods), false, false, true, false, false, false }, { - L"Swfc", + "Swfc", (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), METHODS_PAIR(g_SwfcMethods), false, false, true, false, false, false }, { - L"Tar", + "Tar", (1 << 0), 0, 0, false, false, false, false, false, false }, { - L"wim", + "wim", (1 << 0), 0, 0, false, false, false, false, false, false @@ -383,6 +384,8 @@ bool CCompressDialog::OnInit() } } + CheckButton(IDX_COMPRESS_SFX, Info.SFXMode); + { UString fileName; SetArcPathFields(Info.ArcPath, fileName, true); @@ -408,7 +411,6 @@ bool CCompressDialog::OnInit() ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2); SetItemText(IDT_COMPRESS_HARDWARE_THREADS, s); - CheckButton(IDX_COMPRESS_SFX, Info.SFXMode); CheckButton(IDX_COMPRESS_SHARED, Info.OpenShareForWrite); CheckButton(IDX_COMPRESS_DEL, Info.DeleteAfterCompressing); @@ -580,7 +582,7 @@ void CCompressDialog::OnButtonSFX() if (dotPos >= 0) { UString ext = fileName.Ptr(dotPos); - if (ext.IsEqualTo_NoCase(kExeExt)) + if (ext.IsEqualTo_Ascii_NoCase(kExeExt)) { fileName.DeleteFrom(dotPos); m_ArchivePath.SetText(fileName); @@ -639,7 +641,7 @@ bool CCompressDialog::SetArcPathFields(const UString &path, UString &name, bool return res; } -static const wchar_t *k_IncorrectPathMessage = L"Incorrect archive path"; +static const wchar_t * const k_IncorrectPathMessage = L"Incorrect archive path"; void CCompressDialog::OnButtonSetArchive() { @@ -652,7 +654,7 @@ void CCompressDialog::OnButtonSetArchive() UString title = LangString(IDS_COMPRESS_SET_ARCHIVE_BROWSE); UString filterDescription = LangString(IDS_OPEN_TYPE_ALL_FILES); - filterDescription += L" (*.*)"; + filterDescription += " (*.*)"; UString resPath; CurrentDirWasChanged = true; if (!MyBrowseForFile(*this, title, @@ -812,11 +814,11 @@ void CCompressDialog::OnOK() CModalDialog::OnOK(); } -static LPCWSTR kHelpTopic = L"fm/plugins/7-zip/add.htm"; +#define kHelpTopic "fm/plugins/7-zip/add.htm" void CCompressDialog::OnHelp() { - ShowHelpWindow(NULL, kHelpTopic); + ShowHelpWindow(kHelpTopic); } bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam) @@ -917,7 +919,10 @@ void CCompressDialog::SetArchiveName2(bool prevWasSFX) if (prevWasSFX) prevExtension = kExeExt; else - prevExtension = UString(L'.') + prevArchiverInfo.GetMainExt(); + { + prevExtension += '.'; + prevExtension += prevArchiverInfo.GetMainExt(); + } const unsigned prevExtensionLen = prevExtension.Len(); if (fileName.Len() >= prevExtensionLen) if (StringsAreEqualNoCase(fileName.RightPtr(prevExtensionLen), prevExtension)) @@ -954,7 +959,7 @@ void CCompressDialog::SetArchiveName(const UString &name) fileName += kExeExt; else { - fileName += L'.'; + fileName += '.'; fileName += ai.GetMainExt(); } m_ArchivePath.SetText(fileName); @@ -987,7 +992,7 @@ int CCompressDialog::GetStaticFormatIndex() { const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; for (unsigned i = 0; i < ARRAY_SIZE(g_Formats); i++) - if (ai.Name.IsEqualTo_NoCase(g_Formats[i].Name)) + if (ai.Name.IsEqualTo_Ascii_NoCase(g_Formats[i].Name)) return i; return 0; // -1; } @@ -1035,6 +1040,13 @@ void CCompressDialog::SetLevel() SetMethod(); } + +static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s) +{ + return cb.AddString((CSysString)s); +} + + void CCompressDialog::SetMethod(int keepMethodId) { m_Method.ResetContent(); @@ -1063,8 +1075,8 @@ void CCompressDialog::SetMethod(int keepMethodId) if (isSfx) if (!IsMethodSupportedBySfx(methodID)) continue; - const LPCWSTR method = kMethodsNames[methodID]; - int itemIndex = (int)m_Method.AddString(GetSystemString(method)); + const char *method = kMethodsNames[methodID]; + int itemIndex = (int)ComboBox_AddStringAscii(m_Method, method); m_Method.SetItemData(itemIndex, methodID); if (keepMethodId == methodID) { @@ -1072,7 +1084,7 @@ void CCompressDialog::SetMethod(int keepMethodId) weUseSameMethod = true; continue; } - if ((defaultMethod.IsEqualTo_NoCase(method) || m == 0) && !weUseSameMethod) + if ((defaultMethod.IsEqualTo_Ascii_NoCase(method) || m == 0) && !weUseSameMethod) m_Method.SetCurSel(itemIndex); } @@ -1095,7 +1107,7 @@ void CCompressDialog::SetEncryptionMethod() const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; if (ai.Name.IsEqualTo_Ascii_NoCase("7z")) { - _encryptionMethod.AddString(TEXT("AES-256")); + ComboBox_AddStringAscii(_encryptionMethod, "AES-256"); _encryptionMethod.SetCurSel(0); } else if (ai.Name.IsEqualTo_Ascii_NoCase("zip")) @@ -1107,8 +1119,8 @@ void CCompressDialog::SetEncryptionMethod() const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; encryptionMethod = fo.EncryptionMethod; } - _encryptionMethod.AddString(TEXT("ZipCrypto")); - _encryptionMethod.AddString(TEXT("AES-256")); + ComboBox_AddStringAscii(_encryptionMethod, "ZipCrypto"); + ComboBox_AddStringAscii(_encryptionMethod, "AES-256"); _encryptionMethod.SetCurSel(encryptionMethod.IsPrefixedBy_Ascii_NoCase("aes") ? 1 : 0); } } @@ -1122,21 +1134,22 @@ int CCompressDialog::GetMethodID() UString CCompressDialog::GetMethodSpec() { - if (m_Method.GetCount() <= 1) - return UString(); - return kMethodsNames[GetMethodID()]; + UString s; + if (m_Method.GetCount() > 1) + s = kMethodsNames[GetMethodID()]; + return s; } UString CCompressDialog::GetEncryptionMethodSpec() { - if (_encryptionMethod.GetCount() <= 1) - return UString(); - if (_encryptionMethod.GetCurSel() <= 0) - return UString(); - UString result; - _encryptionMethod.GetText(result); - result.RemoveChar(L'-'); - return result; + UString s; + if (_encryptionMethod.GetCount() > 1 + && _encryptionMethod.GetCurSel() > 0) + { + _encryptionMethod.GetText(s); + s.RemoveChar(L'-'); + } + return s; } void CCompressDialog::AddDictionarySize(UInt32 size) diff --git a/CPP/7zip/UI/GUI/ExtractDialog.cpp b/CPP/7zip/UI/GUI/ExtractDialog.cpp index af47fc2d..b36a4943 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.AddAscii(" : "); + s += " : "; s += ArcPath; } SetText(s); @@ -409,10 +409,10 @@ void CExtractDialog::OnOK() } #ifndef NO_REGISTRY -static LPCWSTR kHelpTopic = L"fm/plugins/7-zip/extract.htm"; +#define kHelpTopic "fm/plugins/7-zip/extract.htm" void CExtractDialog::OnHelp() { - ShowHelpWindow(NULL, kHelpTopic); + ShowHelpWindow(kHelpTopic); CModalDialog::OnHelp(); } #endif diff --git a/CPP/7zip/UI/GUI/ExtractGUI.cpp b/CPP/7zip/UI/GUI/ExtractGUI.cpp index 7fb843a1..5071d1f0 100644 --- a/CPP/7zip/UI/GUI/ExtractGUI.cpp +++ b/CPP/7zip/UI/GUI/ExtractGUI.cpp @@ -34,7 +34,7 @@ using namespace NWindows; using namespace NFile; using namespace NDir; -static const wchar_t *kIncorrectOutDir = L"Incorrect output directory path"; +static const wchar_t * const kIncorrectOutDir = L"Incorrect output directory path"; #ifndef _SFX @@ -42,28 +42,31 @@ static void AddValuePair(UString &s, UINT resourceID, UInt64 value, bool addColo { AddLangString(s, resourceID); if (addColon) - s += L':'; + s += ':'; s.Add_Space(); char sz[32]; ConvertUInt64ToString(value, sz); - s.AddAscii(sz); + s += sz; s.Add_LF(); } static void AddSizePair(UString &s, UINT resourceID, UInt64 value) { - wchar_t sz[32]; - AddLangString(s, resourceID); - s += L": "; - ConvertUInt64ToString(value, sz); - s += MyFormatNew(IDS_FILE_SIZE, sz); + { + wchar_t sz[32]; + AddLangString(s, resourceID); + s += ": "; + ConvertUInt64ToString(value, sz); + s += MyFormatNew(IDS_FILE_SIZE, sz); + } // s += sz; if (value >= (1 << 20)) { + char sz[32]; ConvertUInt64ToString(value >> 20, sz); - s += L" ("; + s += " ("; s += sz; - s += L" MB)"; + s += " MB)"; } s.Add_LF(); } diff --git a/CPP/7zip/UI/GUI/GUI.cpp b/CPP/7zip/UI/GUI/GUI.cpp index 489fc721..2a2ef883 100644 --- a/CPP/7zip/UI/GUI/GUI.cpp +++ b/CPP/7zip/UI/GUI/GUI.cpp @@ -11,7 +11,6 @@ #include "../../../Common/MyInitGuid.h" #include "../../../Common/CommandLineParser.h" -#include "../../../Common/IntToString.h" #include "../../../Common/MyException.h" #include "../../../Common/StringConvert.h" @@ -37,8 +36,8 @@ using namespace NWindows; HINSTANCE g_hInstance; -#ifndef _UNICODE -#endif + +bool g_LargePagesMode = false; #ifndef UNDER_CE @@ -74,12 +73,17 @@ static void ErrorMessage(LPCWSTR message) MessageBoxW(NULL, message, L"7-Zip", MB_ICONERROR | MB_OK); } +static void ErrorMessage(const char *s) +{ + ErrorMessage(GetUnicodeString(s)); +} + static void ErrorLangMessage(UINT resourceID) { ErrorMessage(LangString(resourceID)); } -static const char *kNoFormats = "7-Zip cannot find the code that works with archives."; +static const char * const kNoFormats = "7-Zip cannot find the code that works with archives."; static int ShowMemErrorMessage() { @@ -126,7 +130,10 @@ static int Main2() NSecurity::EnablePrivilege_SymLink(); #ifdef _7ZIP_LARGE_PAGES if (options.LargePages) - NSecurity::EnablePrivilege_LockMemory(); + { + SetLargePageSize(); + g_LargePagesMode = NSecurity::EnablePrivilege_LockMemory(); + } #endif #endif @@ -146,7 +153,7 @@ static int Main2() #ifdef EXTERNAL_CODECS if (!codecs->MainDll_ErrorPath.IsEmpty()) { - UString s = L"7-Zip cannot load module "; + UString s ("7-Zip cannot load module: "); s += fs2us(codecs->MainDll_ErrorPath); throw s; } @@ -350,7 +357,7 @@ static int Main2() return 0; } -#define NT_CHECK_FAIL_ACTION ErrorMessage(L"Unsupported Windows version"); return NExitCode::kFatalError; +#define NT_CHECK_FAIL_ACTION ErrorMessage("Unsupported Windows version"); return NExitCode::kFatalError; int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, #ifdef UNDER_CE @@ -361,9 +368,9 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, /* lpCmdLine */, int /* nCmdShow */) { g_hInstance = hInstance; + #ifdef _WIN32 NT_CHECK - SetLargePageSize(); #endif InitCommonControls(); @@ -407,7 +414,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, } catch(const AString &s) { - ErrorMessage(GetUnicodeString(s)); + ErrorMessage(s); return NExitCode::kFatalError; } catch(const wchar_t *s) @@ -417,19 +424,19 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, } catch(const char *s) { - ErrorMessage(GetUnicodeString(s)); + ErrorMessage(s); return NExitCode::kFatalError; } catch(int v) { - wchar_t s[32]; - ConvertUInt32ToString(v, s); - ErrorMessage(UString(L"Error: ") + s); + AString e ("Error: "); + e.Add_UInt32(v); + ErrorMessage(e); return NExitCode::kFatalError; } catch(...) { - ErrorMessage(L"Unknown error"); + ErrorMessage("Unknown error"); return NExitCode::kFatalError; } } diff --git a/CPP/7zip/UI/GUI/GUI.dsp b/CPP/7zip/UI/GUI/GUI.dsp index 63cdb2fd..9a171d93 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 /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 CPP /nologo /Gr /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /FAcs /Yu"stdafx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -835,10 +835,6 @@ SOURCE=..\..\..\..\C\Threads.h # PROP Default_Filter "" # Begin Source File -SOURCE=..\..\..\Common\Buffer.h -# End Source File -# Begin Source File - SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File @@ -875,6 +871,10 @@ SOURCE=..\..\..\Common\ListFileUtils.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\MyBuffer.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/UI/GUI/HashGUI.cpp b/CPP/7zip/UI/GUI/HashGUI.cpp index 03d65156..cc93f07e 100644 --- a/CPP/7zip/UI/GUI/HashGUI.cpp +++ b/CPP/7zip/UI/GUI/HashGUI.cpp @@ -47,25 +47,30 @@ public: static void AddValuePair(UString &s, UINT resourceID, UInt64 value) { AddLangString(s, resourceID); - s.AddAscii(": "); + s += ": "; char sz[32]; ConvertUInt64ToString(value, sz); - s.AddAscii(sz); + s += sz; s.Add_LF(); } static void AddSizeValuePair(UString &s, UINT resourceID, UInt64 value) { AddLangString(s, resourceID); - s.AddAscii(": "); - wchar_t sz[32]; - ConvertUInt64ToString(value, sz); - s += MyFormatNew(IDS_FILE_SIZE, sz); - ConvertUInt64ToString(value >> 20, sz); - s.AddAscii(" ("); - s += sz; - s.AddAscii(" MB)"); - s.Add_LF(); + s += ": "; + { + wchar_t sz[32]; + ConvertUInt64ToString(value, sz); + s += MyFormatNew(IDS_FILE_SIZE, sz); + } + { + char sz[32]; + ConvertUInt64ToString(value >> 20, sz); + s += " ("; + s += sz; + s += " MB)"; + s.Add_LF(); + } } HRESULT CHashCallbackGUI::StartScanning() @@ -155,15 +160,14 @@ static void AddHashString(UString &s, const CHasherState &h, unsigned digestInde s.Add_Space(); char temp[k_HashCalc_DigestSize_Max * 2 + 4]; AddHashHexToString(temp, h.Digests[digestIndex], h.DigestSize); - s.AddAscii(temp); + s += temp; s.Add_LF(); } static void AddHashResString(UString &s, const CHasherState &h, unsigned digestIndex, UInt32 resID) { UString s2 = LangString(resID); - UString name; - name.SetFromAscii(h.Name); + UString name (h.Name); s2.Replace(L"CRC", name); AddHashString(s, h, digestIndex, s2); } @@ -179,7 +183,7 @@ void AddHashBundleRes(UString &s, const CHashBundle &hb, const UString &firstFil if (hb.NumFiles == 1 && hb.NumDirs == 0 && !firstFileName.IsEmpty()) { AddLangString(s, IDS_PROP_NAME); - s.AddAscii(": "); + s += ": "; s += firstFileName; s.Add_LF(); } @@ -210,7 +214,7 @@ void AddHashBundleRes(UString &s, const CHashBundle &hb, const UString &firstFil const CHasherState &h = hb.Hashers[i]; if (hb.NumFiles == 1 && hb.NumDirs == 0) { - s.AddAscii(h.Name); + s += h.Name; AddHashString(s, h, k_HashCalc_Index_DataSum, L":"); } else @@ -268,7 +272,7 @@ HRESULT HashCalcGUI( const UString title = LangString(IDS_CHECKSUM_CALCULATING); - t.ProgressDialog.MainTitle = L"7-Zip"; // LangString(IDS_APP_TITLE); + t.ProgressDialog.MainTitle = "7-Zip"; // LangString(IDS_APP_TITLE); t.ProgressDialog.MainAddTitle = title; t.ProgressDialog.MainAddTitle.Add_Space(); diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp index 0723b223..33852e3b 100644 --- a/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp +++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp @@ -97,9 +97,9 @@ HRESULT CUpdateCallbackGUI::Finalize() } */ -HRESULT CUpdateCallbackGUI::SetNumItems(UInt64 numItems) +HRESULT CUpdateCallbackGUI::SetNumItems(const CArcToDoStat &stat) { - ProgressDialog->Sync.Set_NumFilesTotal(numItems); + ProgressDialog->Sync.Set_NumFilesTotal(stat.Get_NumDataItems_Total()); return S_OK; } diff --git a/CPP/7zip/UI/GUI/UpdateGUI.cpp b/CPP/7zip/UI/GUI/UpdateGUI.cpp index 53864f72..261b1e2b 100644 --- a/CPP/7zip/UI/GUI/UpdateGUI.cpp +++ b/CPP/7zip/UI/GUI/UpdateGUI.cpp @@ -28,8 +28,8 @@ using namespace NWindows; using namespace NFile; using namespace NDir; -static CFSTR kDefaultSfxModule = FTEXT("7z.sfx"); -static const wchar_t *kSFXExtension = L"exe"; +static const char * const kDefaultSfxModule = "7z.sfx"; +static const char * const kSFXExtension = "exe"; extern void AddMessageToString(UString &dest, const UString &src); @@ -54,14 +54,14 @@ HRESULT CThreadUpdating::ProcessVirt() HRESULT res = UpdateArchive(codecs, *formatIndices, *cmdArcPath, *WildcardCensor, *Options, ei, UpdateCallbackGUI, UpdateCallbackGUI, needSetPath); - FinalMessage.ErrorMessage.Message.SetFromAscii(ei.Message); + FinalMessage.ErrorMessage.Message = ei.Message.Ptr(); ErrorPaths = ei.FileNames; if (ei.SystemError != S_OK && ei.SystemError != E_FAIL && ei.SystemError != E_ABORT) return ei.SystemError; return res; } -static void AddProp(CObjectVector<CProperty> &properties, const UString &name, const UString &value) +static void AddProp(CObjectVector<CProperty> &properties, const char *name, const UString &value) { CProperty prop; prop.Name = name; @@ -69,16 +69,16 @@ static void AddProp(CObjectVector<CProperty> &properties, const UString &name, c properties.Add(prop); } -static void AddProp(CObjectVector<CProperty> &properties, const UString &name, UInt32 value) +static void AddProp(CObjectVector<CProperty> &properties, const char *name, UInt32 value) { - wchar_t tmp[32]; + char tmp[32]; ConvertUInt64ToString(value, tmp); - AddProp(properties, name, tmp); + AddProp(properties, name, UString(tmp)); } -static void AddProp(CObjectVector<CProperty> &properties, const UString &name, bool value) +static void AddProp(CObjectVector<CProperty> &properties, const char *name, bool value) { - AddProp(properties, name, value ? UString(L"on"): UString(L"off")); + AddProp(properties, name, UString(value ? "on": "off")); } static bool IsThereMethodOverride(bool is7z, const UString &propertiesString) @@ -128,12 +128,12 @@ static void ParseAndAddPropertires(CObjectVector<CProperty> &properties, static UString GetNumInBytesString(UInt64 v) { - wchar_t s[32]; + char s[32]; ConvertUInt64ToString(v, s); - size_t len = wcslen(s); - s[len++] = L'B'; - s[len] = L'\0'; - return s; + size_t len = MyStringLen(s); + s[len++] = 'B'; + s[len] = '\0'; + return UString(s); } static void SetOutProperties( @@ -152,44 +152,38 @@ static void SetOutProperties( bool /* sfxMode */) { if (level != (UInt32)(Int32)-1) - AddProp(properties, L"x", (UInt32)level); + AddProp(properties, "x", (UInt32)level); if (setMethod) { if (!method.IsEmpty()) - AddProp(properties, is7z ? L"0": L"m", method); + AddProp(properties, is7z ? "0": "m", method); if (dictionary != (UInt32)(Int32)-1) { - UString name; + AString name; if (is7z) - name = L"0"; - if (orderMode) - name += L"mem"; - else - name += L"d"; + name = "0"; + name += (orderMode ? "mem" : "d"); AddProp(properties, name, GetNumInBytesString(dictionary)); } if (order != (UInt32)(Int32)-1) { - UString name; + AString name; if (is7z) - name = L"0"; - if (orderMode) - name += L"o"; - else - name += L"fb"; + name = "0"; + name += (orderMode ? "o" : "fb"); AddProp(properties, name, (UInt32)order); } } if (!encryptionMethod.IsEmpty()) - AddProp(properties, L"em", encryptionMethod); + AddProp(properties, "em", encryptionMethod); if (encryptHeadersIsAllowed) - AddProp(properties, L"he", encryptHeaders); + AddProp(properties, "he", encryptHeaders); if (solidIsSpecified) - AddProp(properties, L"s", GetNumInBytesString(solidBlockSize)); + AddProp(properties, "s", GetNumInBytesString(solidBlockSize)); if (multiThreadIsAllowed) - AddProp(properties, L"mt", numThreads); + AddProp(properties, "mt", numThreads); } struct C_UpdateMode_ToAction_Pair @@ -453,8 +447,8 @@ HRESULT UpdateGUI( } if (options.SfxMode && options.SfxModule.IsEmpty()) { - FString folder = NWindows::NDLL::GetModuleDirPrefix(); - options.SfxModule = folder + kDefaultSfxModule; + options.SfxModule = NWindows::NDLL::GetModuleDirPrefix(); + options.SfxModule += kDefaultSfxModule; } CThreadUpdating tu; diff --git a/CPP/Build.mak b/CPP/Build.mak index ef0ed0c4..39ebe0aa 100644 --- a/CPP/Build.mak +++ b/CPP/Build.mak @@ -53,15 +53,22 @@ CFLAGS = $(CFLAGS) -MD !ENDIF !IFDEF NEW_COMPILER -CFLAGS = $(CFLAGS) -GS- -Zc:forScope +CFLAGS = $(CFLAGS) -GS- -Zc:forScope -Zc:wchar_t !IFNDEF UNDER_CE CFLAGS = $(CFLAGS) -MP2 +!IFNDEF CPU +# CFLAGS = $(CFLAGS) -arch:IA32 +!ENDIF !ENDIF !ELSE CFLAGS = $(CFLAGS) !ENDIF +!IF "$(CPU)" == "AMD64" +CFLAGS_O1 = $(CFLAGS) -O1 +!ELSE CFLAGS_O1 = $(CFLAGS) -O1 +!ENDIF CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:REF -OPT:ICF @@ -72,15 +79,27 @@ LFLAGS = $(LFLAGS) /LARGEADDRESSAWARE !IFDEF DEF_FILE LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE) +!ELSE +LFLAGS = $(LFLAGS) /FIXED +# /BASE:0x400000 !ENDIF -MY_SUB_SYS_VER=6.0 + +# !IF "$(CPU)" == "AMD64" + +!IFDEF SUB_SYS_VER + +MY_SUB_SYS_VER=5.02 + !IFDEF MY_CONSOLE -# LFLAGS = $(LFLAGS) /SUBSYSTEM:console,$(MY_SUB_SYS_VER) +LFLAGS = $(LFLAGS) /SUBSYSTEM:console,$(MY_SUB_SYS_VER) !ELSE -# LFLAGS = $(LFLAGS) /SUBSYSTEM:windows,$(MY_SUB_SYS_VER) +LFLAGS = $(LFLAGS) /SUBSYSTEM:windows,$(MY_SUB_SYS_VER) !ENDIF +!ENDIF + + PROGPATH = $O\$(PROG) COMPL_O1 = $(CC) $(CFLAGS_O1) $** diff --git a/CPP/Common/ComTry.h b/CPP/Common/ComTry.h index fb4ef045..297c407b 100644 --- a/CPP/Common/ComTry.h +++ b/CPP/Common/ComTry.h @@ -10,7 +10,11 @@ #define COM_TRY_BEGIN try { #define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; } - // catch(const CNewException &) { return E_OUTOFMEMORY; } +/* +#define COM_TRY_END } \ + catch(const CNewException &) { return E_OUTOFMEMORY; } \ + catch(...) { return HRESULT_FROM_WIN32(ERROR_NOACCESS); } \ +*/ // catch(const CSystemException &e) { return e.ErrorCode; } // catch(...) { return E_FAIL; } diff --git a/CPP/Common/CommandLineParser.cpp b/CPP/Common/CommandLineParser.cpp index 1c7f2654..145f3435 100644 --- a/CPP/Common/CommandLineParser.cpp +++ b/CPP/Common/CommandLineParser.cpp @@ -4,20 +4,6 @@ #include "CommandLineParser.h" -static bool IsString1PrefixedByString2_NoCase(const wchar_t *u, const char *a) -{ - for (;;) - { - char c = *a; - if (c == 0) - return true; - if ((unsigned char)MyCharLower_Ascii(c) != MyCharLower_Ascii(*u)) - return false; - a++; - u++; - } -} - namespace NCommandLineParser { bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2) @@ -44,7 +30,7 @@ bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2) void SplitCommandLine(const UString &s, UStringVector &parts) { - UString sTemp = s; + UString sTemp (s); sTemp.Trim(); parts.Clear(); for (;;) @@ -59,18 +45,17 @@ void SplitCommandLine(const UString &s, UStringVector &parts) } -static const char *kStopSwitchParsing = "--"; +static const char * const kStopSwitchParsing = "--"; static bool inline IsItSwitchChar(wchar_t c) { return (c == '-'); } -CParser::CParser(unsigned numSwitches): - _numSwitches(numSwitches), - _switches(0) +CParser::CParser(): + _switches(NULL), + StopSwitchIndex(-1) { - _switches = new CSwitchResult[numSwitches]; } CParser::~CParser() @@ -81,7 +66,7 @@ CParser::~CParser() // if (s) contains switch then function updates switch structures // out: true, if (s) is a switch -bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) +bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches) { if (s.IsEmpty() || !IsItSwitchChar(s[0])) return false; @@ -90,13 +75,13 @@ bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) unsigned switchIndex = 0; int maxLen = -1; - for (unsigned i = 0; i < _numSwitches; i++) + for (unsigned i = 0; i < numSwitches; i++) { - const char *key = switchForms[i].Key; + const char * const key = switchForms[i].Key; unsigned switchLen = MyStringLen(key); if ((int)switchLen <= maxLen || pos + switchLen > s.Len()) continue; - if (IsString1PrefixedByString2_NoCase((const wchar_t *)s + pos, key)) + if (IsString1PrefixedByString2_NoCase_Ascii((const wchar_t *)s + pos, key)) { switchIndex = i; maxLen = switchLen; @@ -161,8 +146,10 @@ bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) break; case NSwitchType::kString: - sw.PostStrings.Add((const wchar_t *)s + pos); + { + sw.PostStrings.Add(s.Ptr(pos)); return true; + } } if (pos != s.Len()) @@ -173,23 +160,30 @@ bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) return true; } -bool CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings) + +bool CParser::ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings) { + StopSwitchIndex = -1; + ErrorMessage.Empty(); ErrorLine.Empty(); - bool stopSwitch = false; + NonSwitchStrings.Clear(); + delete []_switches; + _switches = NULL; + _switches = new CSwitchResult[numSwitches]; + FOR_VECTOR (i, commandStrings) { const UString &s = commandStrings[i]; - if (!stopSwitch) + if (StopSwitchIndex < 0) { if (s.IsEqualTo(kStopSwitchParsing)) { - stopSwitch = true; + StopSwitchIndex = NonSwitchStrings.Size(); continue; } if (!s.IsEmpty() && IsItSwitchChar(s[0])) { - if (ParseString(s, switchForms)) + if (ParseString(s, switchForms, numSwitches)) continue; ErrorLine = s; return false; diff --git a/CPP/Common/CommandLineParser.h b/CPP/Common/CommandLineParser.h index c9fd2956..1dbdd4ea 100644 --- a/CPP/Common/CommandLineParser.h +++ b/CPP/Common/CommandLineParser.h @@ -43,19 +43,19 @@ struct CSwitchResult class CParser { - unsigned _numSwitches; CSwitchResult *_switches; - bool ParseString(const UString &s, const CSwitchForm *switchForms); + bool ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches); public: UStringVector NonSwitchStrings; + int StopSwitchIndex; // NonSwitchStrings[StopSwitchIndex+] are after "--" AString ErrorMessage; UString ErrorLine; - CParser(unsigned numSwitches); + CParser(); ~CParser(); - bool ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings); - const CSwitchResult& operator[](size_t index) const { return _switches[index]; } + bool ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings); + const CSwitchResult& operator[](unsigned index) const { return _switches[index]; } }; } diff --git a/CPP/Common/Common.h b/CPP/Common/Common.h index 9dd30f4b..5430a92d 100644 --- a/CPP/Common/Common.h +++ b/CPP/Common/Common.h @@ -3,11 +3,41 @@ #ifndef __COMMON_COMMON_H #define __COMMON_COMMON_H +/* +This file is included to all cpp files in 7-Zip. +Each folder contains StdAfx.h file that includes "Common.h". +So 7-Zip includes "Common.h" in both modes: + with precompiled StdAfx.h +and + without precompiled StdAfx.h + +If you use 7-Zip code, you must include "Common.h" before other h files of 7-zip. +If you don't need some things that are used in 7-Zip, +you can change this h file or h files included in this file. +*/ + +// compiler pragmas to disable some warnings #include "../../C/Compiler.h" +// it's <windows.h> or code that defines windows things, if it's not _WIN32 #include "MyWindows.h" + +// NewHandler.h and NewHandler.cpp redefine operator new() to throw exceptions, if compiled with old MSVC compilers #include "NewHandler.h" -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[1])) + + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + + +/* There is BUG in MSVC 6.0 compiler for operator new[]: + It doesn't check overflow, when it calculates size in bytes for allocated array. + So we can use MY_ARRAY_NEW macro instead of new[] operator. */ + +#if defined(_MSC_VER) && (_MSC_VER == 1200) && !defined(_WIN64) + #define MY_ARRAY_NEW(p, T, size) p = new T[(size > (unsigned)0xFFFFFFFF / sizeof(T)) ? (unsigned)0xFFFFFFFF / sizeof(T) : size]; +#else + #define MY_ARRAY_NEW(p, T, size) p = new T[size]; +#endif #endif diff --git a/CPP/Common/DynLimBuf.h b/CPP/Common/DynLimBuf.h index 93aa144f..e80a7e7c 100644 --- a/CPP/Common/DynLimBuf.h +++ b/CPP/Common/DynLimBuf.h @@ -27,6 +27,7 @@ public: ~CDynLimBuf() { MyFree(_chars); } size_t Len() const { return _pos; } + bool IsError() const { return _error; } void Empty() { _pos = 0; _error = false; } operator const Byte *() const { return _chars; } diff --git a/CPP/Common/IntToString.cpp b/CPP/Common/IntToString.cpp index ed217c72..05b1c148 100644 --- a/CPP/Common/IntToString.cpp +++ b/CPP/Common/IntToString.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../C/CpuArch.h" + #include "IntToString.h" #define CONVERT_INT_TO_STR(charType, tempSize) \ @@ -46,6 +48,12 @@ void ConvertUInt64ToOct(UInt64 val, char *s) throw() while (i); } + +#define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))))) + +static inline char GetHexChar(unsigned t) { return GET_HEX_CHAR(t); } + + void ConvertUInt32ToHex(UInt32 val, char *s) throw() { UInt32 v = val; @@ -59,13 +67,14 @@ void ConvertUInt32ToHex(UInt32 val, char *s) throw() s[i] = 0; do { - unsigned t = (unsigned)((val & 0xF)); + unsigned t = (unsigned)(val & 0xF); val >>= 4; - s[--i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + s[--i] = GET_HEX_CHAR(t); } while (i); } + void ConvertUInt64ToHex(UInt64 val, char *s) throw() { UInt64 v = val; @@ -79,9 +88,9 @@ void ConvertUInt64ToHex(UInt64 val, char *s) throw() s[i] = 0; do { - unsigned t = (unsigned)((val & 0xF)); + unsigned t = (unsigned)(val & 0xF); val >>= 4; - s[--i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + s[--i] = GET_HEX_CHAR(t); } while (i); } @@ -93,7 +102,7 @@ void ConvertUInt32ToHex8Digits(UInt32 val, char *s) throw() { unsigned t = val & 0xF; val >>= 4; - s[i] = (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))); + s[i] = GET_HEX_CHAR(t);; } } @@ -144,3 +153,41 @@ void ConvertInt64ToString(Int64 val, wchar_t *s) throw() } ConvertUInt64ToString(val, s); } + + +static void ConvertByteToHex2Digits(unsigned v, char *s) throw() +{ + s[0] = GetHexChar(v >> 4); + s[1] = GetHexChar(v & 0xF); +} + +static void ConvertUInt16ToHex4Digits(UInt32 val, char *s) throw() +{ + ConvertByteToHex2Digits(val >> 8, s); + ConvertByteToHex2Digits(val & 0xFF, s + 2); +} + +char *RawLeGuidToString(const Byte *g, char *s) throw() +{ + ConvertUInt32ToHex8Digits(GetUi32(g ), s); s += 8; *s++ = '-'; + ConvertUInt16ToHex4Digits(GetUi16(g + 4), s); s += 4; *s++ = '-'; + ConvertUInt16ToHex4Digits(GetUi16(g + 6), s); s += 4; *s++ = '-'; + for (unsigned i = 0; i < 8; i++) + { + if (i == 2) + *s++ = '-'; + ConvertByteToHex2Digits(g[8 + i], s); + s += 2; + } + *s = 0; + return s; +} + +char *RawLeGuidToString_Braced(const Byte *g, char *s) throw() +{ + *s++ = '{'; + s = RawLeGuidToString(g, s); + *s++ = '}'; + *s = 0; + return s; +} diff --git a/CPP/Common/IntToString.h b/CPP/Common/IntToString.h index 69605ab7..d4110d1d 100644 --- a/CPP/Common/IntToString.h +++ b/CPP/Common/IntToString.h @@ -21,4 +21,8 @@ void ConvertUInt32ToHex8Digits(UInt32 value, char *s) throw(); void ConvertInt64ToString(Int64 value, char *s) throw(); void ConvertInt64ToString(Int64 value, wchar_t *s) throw(); +// use RawLeGuid only for RAW bytes that contain stored GUID as Little-endian. +char *RawLeGuidToString(const Byte *guid, char *s) throw(); +char *RawLeGuidToString_Braced(const Byte *guid, char *s) throw(); + #endif diff --git a/CPP/Common/Lang.cpp b/CPP/Common/Lang.cpp index 8c525cf7..e959ba48 100644 --- a/CPP/Common/Lang.cpp +++ b/CPP/Common/Lang.cpp @@ -10,13 +10,13 @@ void CLang::Clear() throw() { - delete []_text; - _text = 0; _ids.Clear(); _offsets.Clear(); + delete []_text; + _text = 0; } -static const wchar_t *kLangSignature = L";!@Lang2@!UTF-8!"; +static const char * const kLangSignature = ";!@Lang2@!UTF-8!"; bool CLang::OpenFromString(const AString &s2) { @@ -29,9 +29,9 @@ bool CLang::OpenFromString(const AString &s2) if (s[0] == 0xFEFF) i++; - for (const wchar_t *p = kLangSignature;; i++) + for (const char *p = kLangSignature;; i++) { - wchar_t c = *p++; + Byte c = *p++; if (c == 0) break; if (s[i] != c) @@ -109,7 +109,7 @@ bool CLang::OpenFromString(const AString &s2) return true; } -bool CLang::Open(CFSTR fileName, const wchar_t *id) +bool CLang::Open(CFSTR fileName, const char *id) { Clear(); NWindows::NFile::NIO::CInFile file; @@ -146,7 +146,7 @@ bool CLang::Open(CFSTR fileName, const wchar_t *id) if (OpenFromString(s)) { const wchar_t *name = Get(0); - if (name && wcscmp(name, id) == 0) + if (name && StringsAreEqual_Ascii(name, id)) return true; } diff --git a/CPP/Common/Lang.h b/CPP/Common/Lang.h index 22e42574..cc66677d 100644 --- a/CPP/Common/Lang.h +++ b/CPP/Common/Lang.h @@ -15,7 +15,7 @@ class CLang public: CLang(): _text(0) {} ~CLang() { Clear(); } - bool Open(CFSTR fileName, const wchar_t *id); + bool Open(CFSTR fileName, const char *id); void Clear() throw(); const wchar_t *Get(UInt32 id) const throw(); }; diff --git a/CPP/Common/ListFileUtils.cpp b/CPP/Common/ListFileUtils.cpp index 3bf4ec29..9112003b 100644 --- a/CPP/Common/ListFileUtils.cpp +++ b/CPP/Common/ListFileUtils.cpp @@ -52,7 +52,7 @@ bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage if (codePage == MY__CP_UTF16) for (unsigned i = 0; i < num; i++) { - wchar_t c = GetUi16(buf + i * 2); + wchar_t c = GetUi16(buf + (size_t)i * 2); if (c == 0) return false; p[i] = c; @@ -60,7 +60,7 @@ bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage else for (unsigned i = 0; i < num; i++) { - wchar_t c = (wchar_t)GetBe16(buf + i * 2); + wchar_t c = (wchar_t)GetBe16(buf + (size_t)i * 2); if (c == 0) return false; p[i] = c; @@ -104,7 +104,7 @@ bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage wchar_t c = u[i]; if (c == kGoodBOM || c == kBadBOM) return false; - if (c == L'\n' || c == 0xD) + if (c == '\n' || c == 0xD) { AddName(strings, s); s.Empty(); diff --git a/CPP/Common/MyBuffer.h b/CPP/Common/MyBuffer.h index d0378057..5d4e3475 100644 --- a/CPP/Common/MyBuffer.h +++ b/CPP/Common/MyBuffer.h @@ -5,6 +5,9 @@ #include "Defs.h" +/* 7-Zip now uses CBuffer only as CByteBuffer. + So there is no need to use MY_ARRAY_NEW macro in CBuffer code. */ + template <class T> class CBuffer { T *_items; @@ -119,7 +122,7 @@ bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2) } -typedef CBuffer<char> CCharBuffer; +// typedef CBuffer<char> CCharBuffer; // typedef CBuffer<wchar_t> CWCharBuffer; typedef CBuffer<unsigned char> CByteBuffer; @@ -129,7 +132,7 @@ template <class T> class CObjArray protected: T *_items; private: - // we disable constructors + // we disable copy CObjArray(const CObjArray &buffer); void operator=(const CObjArray &buffer); public: @@ -138,7 +141,14 @@ public: delete []_items; _items = 0; } - CObjArray(size_t size): _items(0) { if (size != 0) _items = new T[size]; } + CObjArray(size_t size): _items(0) + { + if (size != 0) + { + MY_ARRAY_NEW(_items, T, size) + // _items = new T[size]; + } + } CObjArray(): _items(0) {}; ~CObjArray() { delete []_items; } @@ -149,7 +159,8 @@ public: { delete []_items; _items = 0; - _items = new T[newSize]; + MY_ARRAY_NEW(_items, T, newSize) + // _items = new T[newSize]; } }; @@ -164,6 +175,7 @@ template <class T> class CObjArray2 T *_items; unsigned _size; + // we disable copy CObjArray2(const CObjArray2 &buffer); void operator=(const CObjArray2 &buffer); public: @@ -216,7 +228,10 @@ public: return; T *newBuffer = NULL; if (size != 0) - newBuffer = new T[size]; + { + MY_ARRAY_NEW(newBuffer, T, size) + // newBuffer = new T[size]; + } delete []_items; _items = newBuffer; _size = size; diff --git a/CPP/Common/MyBuffer2.h b/CPP/Common/MyBuffer2.h new file mode 100644 index 00000000..ba98d137 --- /dev/null +++ b/CPP/Common/MyBuffer2.h @@ -0,0 +1,45 @@ +// Common/MyBuffer2.h + +#ifndef __COMMON_MY_BUFFER2_H +#define __COMMON_MY_BUFFER2_H + +#include "../../C/Alloc.h" + +#include "Defs.h" + +class CMidBuffer +{ + Byte *_data; + size_t _size; + + CLASS_NO_COPY(CMidBuffer) + +public: + CMidBuffer(): _data(NULL), _size(0) {}; + ~CMidBuffer() { ::MidFree(_data); } + + void Free() { ::MidFree(_data); _data = NULL; _size = 0; } + + bool IsAllocated() const { return _data != NULL; } + operator Byte *() { return _data; } + operator const Byte *() const { return _data; } + size_t Size() const { return _size; } + + void AllocAtLeast(size_t size) + { + if (!_data || size > _size) + { + const size_t kMinSize = (size_t)1 << 16; + if (size < kMinSize) + size = kMinSize; + ::MidFree(_data); + _size = 0; + _data = 0; + _data = (Byte *)::MidAlloc(size); + if (_data) + _size = size; + } + } +}; + +#endif diff --git a/CPP/Common/MyCom.h b/CPP/Common/MyCom.h index 7c725c91..031921d3 100644 --- a/CPP/Common/MyCom.h +++ b/CPP/Common/MyCom.h @@ -4,7 +4,6 @@ #define __MY_COM_H #include "MyWindows.h" -#include "NewHandler.h" #ifndef RINOK #define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; } @@ -158,7 +157,20 @@ private: } }; -////////////////////////////////////////////////////////// + + +/* + If CMyUnknownImp doesn't use virtual destructor, the code size is smaller. + But if some class_1 derived from CMyUnknownImp + uses MY_ADDREF_RELEASE and IUnknown::Release() + and some another class_2 is derived from class_1, + then class_1 must use virtual destructor: + virtual ~class_1(); + In that case, class_1::Release() calls correct destructor of class_2. + + Also you can use virtual ~CMyUnknownImp(), if you want to disable warning + "class has virtual functions, but destructor is not virtual". +*/ class CMyUnknownImp { @@ -166,9 +178,12 @@ public: ULONG __m_RefCount; CMyUnknownImp(): __m_RefCount(0) {} - // virtual ~CMyUnknownImp() {}; + // virtual + ~CMyUnknownImp() {} }; + + #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ (REFGUID iid, void **outObject) throw() { *outObject = NULL; diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp index a2d4cc4e..e2ec8a68 100644 --- a/CPP/Common/MyString.cpp +++ b/CPP/Common/MyString.cpp @@ -8,6 +8,8 @@ #include <ctype.h> #endif +#include "IntToString.h" + #if !defined(_UNICODE) || !defined(USE_UNICODE_FSTRING) #include "StringConvert.h" #endif @@ -28,6 +30,10 @@ inline const char* MyStringGetNextCharPointer(const char *p) throw() } */ +#define MY_STRING_NEW_char(_size_) MY_STRING_NEW(char, _size_) +#define MY_STRING_NEW_wchar_t(_size_) MY_STRING_NEW(wchar_t, _size_) + + int FindCharPosInString(const char *s, char c) throw() { for (const char *p = s;; p++) @@ -52,7 +58,18 @@ int FindCharPosInString(const wchar_t *s, wchar_t c) throw() } /* -void MyStringUpper_Ascii(wchar_t *s) +void MyStringUpper_Ascii(char *s) throw() +{ + for (;;) + { + char c = *s; + if (c == 0) + return; + *s++ = MyCharUpper_Ascii(c); + } +} + +void MyStringUpper_Ascii(wchar_t *s) throw() { for (;;) { @@ -282,6 +299,26 @@ bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw() } } +bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw() +{ + for (;;) + { + unsigned char c2 = (unsigned char)(*s2++); if (c2 == 0) return true; + wchar_t c1 = *s1++; if (c1 != c2) return false; + } +} + +bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *s1, const char *s2) throw() +{ + for (;;) + { + char c2 = *s2++; if (c2 == 0) return true; + wchar_t c1 = *s1++; + if (c1 != (unsigned char)c2 && MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)) + return false; + } +} + bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw() { for (;;) @@ -345,8 +382,8 @@ void AString::ReAlloc(unsigned newLimit) { if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130220; // MY_STRING_REALLOC(_chars, char, newLimit + 1, _len + 1); - char *newBuf = MY_STRING_NEW(char, newLimit + 1); - memcpy(newBuf, _chars, (size_t)(_len + 1)); \ + char *newBuf = MY_STRING_NEW_char(newLimit + 1); + memcpy(newBuf, _chars, (size_t)(_len + 1)); MY_STRING_DELETE(_chars); _chars = newBuf; _limit = newLimit; @@ -356,7 +393,7 @@ void AString::ReAlloc2(unsigned newLimit) { if (newLimit >= k_Alloc_Len_Limit) throw 20130220; // MY_STRING_REALLOC(_chars, char, newLimit + 1, 0); - char *newBuf = MY_STRING_NEW(char, newLimit + 1); + char *newBuf = MY_STRING_NEW_char(newLimit + 1); newBuf[0] = 0; MY_STRING_DELETE(_chars); _chars = newBuf; @@ -366,7 +403,7 @@ void AString::ReAlloc2(unsigned newLimit) void AString::SetStartLen(unsigned len) { _chars = 0; - _chars = MY_STRING_NEW(char, len + 1); + _chars = MY_STRING_NEW_char(len + 1); _len = len; _limit = len; } @@ -393,7 +430,6 @@ void AString::Grow(unsigned n) ReAlloc(next - 1); } -/* AString::AString(unsigned num, const char *s) { unsigned len = MyStringLen(s); @@ -403,7 +439,6 @@ AString::AString(unsigned num, const char *s) memcpy(_chars, s, num); _chars[num] = 0; } -*/ AString::AString(unsigned num, const AString &s) { @@ -421,7 +456,7 @@ AString::AString(const AString &s, char c) unsigned len = s.Len(); memcpy(chars, s, len); chars[len] = c; - chars[len + 1] = 0; + chars[(size_t)len + 1] = 0; } AString::AString(const char *s1, unsigned num1, const char *s2, unsigned num2) @@ -436,20 +471,23 @@ AString operator+(const AString &s1, const AString &s2) { return AString(s1, s1. AString operator+(const AString &s1, const char *s2) { return AString(s1, s1.Len(), s2, MyStringLen(s2)); } AString operator+(const char *s1, const AString &s2) { return AString(s1, MyStringLen(s1), s2, s2.Len()); } +static const unsigned kStartStringCapacity = 4; + AString::AString() { _chars = 0; - _chars = MY_STRING_NEW(char, 4); + _chars = MY_STRING_NEW_char(kStartStringCapacity); _len = 0; - _limit = 4 - 1; + _limit = kStartStringCapacity - 1; _chars[0] = 0; } AString::AString(char c) { SetStartLen(1); - _chars[0] = c; - _chars[1] = 0; + char *chars = _chars; + chars[0] = c; + chars[1] = 0; } AString::AString(const char *s) @@ -468,14 +506,15 @@ AString &AString::operator=(char c) { if (1 > _limit) { - char *newBuf = MY_STRING_NEW(char, 1 + 1); + char *newBuf = MY_STRING_NEW_char(1 + 1); MY_STRING_DELETE(_chars); _chars = newBuf; _limit = 1; } _len = 1; - _chars[0] = c; - _chars[1] = 0; + char *chars = _chars; + chars[0] = c; + chars[1] = 0; return *this; } @@ -484,7 +523,7 @@ AString &AString::operator=(const char *s) unsigned len = MyStringLen(s); if (len > _limit) { - char *newBuf = MY_STRING_NEW(char, len + 1); + char *newBuf = MY_STRING_NEW_char(len + 1); MY_STRING_DELETE(_chars); _chars = newBuf; _limit = len; @@ -501,7 +540,7 @@ AString &AString::operator=(const AString &s) unsigned len = s._len; if (len > _limit) { - char *newBuf = MY_STRING_NEW(char, len + 1); + char *newBuf = MY_STRING_NEW_char(len + 1); MY_STRING_DELETE(_chars); _chars = newBuf; _limit = len; @@ -526,7 +565,7 @@ void AString::SetFromWStr_if_Ascii(const wchar_t *s) } if (len > _limit) { - char *newBuf = MY_STRING_NEW(char, len + 1); + char *newBuf = MY_STRING_NEW_char(len + 1); MY_STRING_DELETE(_chars); _chars = newBuf; _limit = len; @@ -550,7 +589,7 @@ void AString::SetFromBstr_if_Ascii(BSTR s) } if (len > _limit) { - char *newBuf = MY_STRING_NEW(char, len + 1); + char *newBuf = MY_STRING_NEW_char(len + 1); MY_STRING_DELETE(_chars); _chars = newBuf; _limit = len; @@ -577,6 +616,12 @@ AString &AString::operator+=(const char *s) return *this; } +void AString::Add_OptSpaced(const char *s) +{ + Add_Space_if_NotEmpty(); + (*this) += s; +} + AString &AString::operator+=(const AString &s) { Grow(s._len); @@ -585,11 +630,18 @@ AString &AString::operator+=(const AString &s) return *this; } +void AString::Add_UInt32(UInt32 v) +{ + char sz[16]; + ConvertUInt32ToString(v, sz); + (*this) += sz; +} + void AString::SetFrom(const char *s, unsigned len) // no check { if (len > _limit) { - char *newBuf = MY_STRING_NEW(char, len + 1); + char *newBuf = MY_STRING_NEW_char(len + 1); MY_STRING_DELETE(_chars); _chars = newBuf; _limit = len; @@ -694,7 +746,7 @@ void AString::TrimRight() throw() unsigned i; for (i = _len; i != 0; i--) { - char c = p[i - 1]; + char c = p[(size_t)i - 1]; if (c != ' ' && c != '\n' && c != '\t') break; } @@ -780,12 +832,13 @@ void AString::Replace(char oldChar, char newChar) throw() return; // 0; // unsigned number = 0; int pos = 0; + char *chars = _chars; while ((unsigned)pos < _len) { pos = Find(oldChar, pos); if (pos < 0) break; - _chars[(unsigned)pos] = newChar; + chars[(unsigned)pos] = newChar; pos++; // number++; } @@ -895,7 +948,7 @@ void UString::ReAlloc(unsigned newLimit) { if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130221; // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, _len + 1); - wchar_t *newBuf = MY_STRING_NEW(wchar_t, newLimit + 1); + wchar_t *newBuf = MY_STRING_NEW_wchar_t(newLimit + 1); wmemcpy(newBuf, _chars, _len + 1); MY_STRING_DELETE(_chars); _chars = newBuf; @@ -906,7 +959,7 @@ void UString::ReAlloc2(unsigned newLimit) { if (newLimit >= k_Alloc_Len_Limit) throw 20130221; // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0); - wchar_t *newBuf = MY_STRING_NEW(wchar_t, newLimit + 1); + wchar_t *newBuf = MY_STRING_NEW_wchar_t(newLimit + 1); newBuf[0] = 0; MY_STRING_DELETE(_chars); _chars = newBuf; @@ -916,7 +969,7 @@ void UString::ReAlloc2(unsigned newLimit) void UString::SetStartLen(unsigned len) { _chars = 0; - _chars = MY_STRING_NEW(wchar_t, len + 1); + _chars = MY_STRING_NEW_wchar_t(len + 1); _len = len; _limit = len; } @@ -971,7 +1024,7 @@ UString::UString(const UString &s, wchar_t c) unsigned len = s.Len(); wmemcpy(chars, s, len); chars[len] = c; - chars[len + 1] = 0; + chars[(size_t)len + 1] = 0; } UString::UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2) @@ -989,17 +1042,26 @@ UString operator+(const wchar_t *s1, const UString &s2) { return UString(s1, MyS UString::UString() { _chars = 0; - _chars = MY_STRING_NEW(wchar_t, 4); + _chars = MY_STRING_NEW_wchar_t(kStartStringCapacity); _len = 0; - _limit = 4 - 1; + _limit = kStartStringCapacity - 1; _chars[0] = 0; } UString::UString(wchar_t c) { SetStartLen(1); - _chars[0] = c; - _chars[1] = 0; + wchar_t *chars = _chars; + chars[0] = c; + chars[1] = 0; +} + +UString::UString(char c) +{ + SetStartLen(1); + wchar_t *chars = _chars; + chars[0] = (unsigned char)c; + chars[1] = 0; } UString::UString(const wchar_t *s) @@ -1009,6 +1071,16 @@ UString::UString(const wchar_t *s) wmemcpy(_chars, s, len + 1); } +UString::UString(const char *s) +{ + unsigned len = MyStringLen(s); + SetStartLen(len); + wchar_t *chars = _chars; + for (unsigned i = 0; i < len; i++) + chars[i] = (unsigned char)s[i]; + chars[len] = 0; +} + UString::UString(const UString &s) { SetStartLen(s._len); @@ -1019,14 +1091,15 @@ UString &UString::operator=(wchar_t c) { if (1 > _limit) { - wchar_t *newBuf = MY_STRING_NEW(wchar_t, 1 + 1); + wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1); MY_STRING_DELETE(_chars); _chars = newBuf; _limit = 1; } _len = 1; - _chars[0] = c; - _chars[1] = 0; + wchar_t *chars = _chars; + chars[0] = c; + chars[1] = 0; return *this; } @@ -1035,7 +1108,7 @@ UString &UString::operator=(const wchar_t *s) unsigned len = MyStringLen(s); if (len > _limit) { - wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1); + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); MY_STRING_DELETE(_chars); _chars = newBuf; _limit = len; @@ -1052,7 +1125,7 @@ UString &UString::operator=(const UString &s) unsigned len = s._len; if (len > _limit) { - wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1); + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); MY_STRING_DELETE(_chars); _chars = newBuf; _limit = len; @@ -1062,12 +1135,27 @@ UString &UString::operator=(const UString &s) return *this; } +void UString::SetFrom(const wchar_t *s, unsigned len) // no check +{ + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + if (len != 0) + wmemcpy(_chars, s, len); + _chars[len] = 0; + _len = len; +} + void UString::SetFromBstr(BSTR s) { unsigned len = ::SysStringLen(s); if (len > _limit) { - wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1); + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); MY_STRING_DELETE(_chars); _chars = newBuf; _limit = len; @@ -1077,6 +1165,24 @@ void UString::SetFromBstr(BSTR s) wmemcpy(_chars, s, len + 1); } +UString &UString::operator=(const char *s) +{ + unsigned len = MyStringLen(s); + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + wchar_t *chars = _chars; + for (unsigned i = 0; i < len; i++) + chars[i] = (unsigned char)s[i]; + chars[len] = 0; + _len = len; + return *this; +} + void UString::Add_Space() { operator+=(L' '); } void UString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); } @@ -1108,39 +1214,7 @@ UString &UString::operator+=(const UString &s) return *this; } -void UString::SetFrom(const wchar_t *s, unsigned len) // no check -{ - if (len > _limit) - { - wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1); - MY_STRING_DELETE(_chars); - _chars = newBuf; - _limit = len; - } - if (len != 0) - wmemcpy(_chars, s, len); - _chars[len] = 0; - _len = len; -} - -void UString::SetFromAscii(const char *s) -{ - unsigned len = MyStringLen(s); - if (len > _limit) - { - wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1); - MY_STRING_DELETE(_chars); - _chars = newBuf; - _limit = len; - } - wchar_t *chars = _chars; - for (unsigned i = 0; i < len; i++) - chars[i] = (unsigned char)s[i]; - chars[len] = 0; - _len = len; -} - -void UString::AddAscii(const char *s) +UString &UString::operator+=(const char *s) { unsigned len = MyStringLen(s); Grow(len); @@ -1149,9 +1223,17 @@ void UString::AddAscii(const char *s) chars[i] = (unsigned char)s[i]; chars[len] = 0; _len += len; + return *this; } +void UString::Add_UInt32(UInt32 v) +{ + char sz[16]; + ConvertUInt32ToString(v, sz); + (*this) += sz; +} + int UString::Find(const wchar_t *s, unsigned startIndex) const throw() { @@ -1238,7 +1320,7 @@ void UString::TrimRight() throw() unsigned i; for (i = _len; i != 0; i--) { - wchar_t c = p[i - 1]; + wchar_t c = p[(size_t)i - 1]; if (c != ' ' && c != '\n' && c != '\t') break; } @@ -1324,12 +1406,13 @@ void UString::Replace(wchar_t oldChar, wchar_t newChar) throw() return; // 0; // unsigned number = 0; int pos = 0; + wchar_t *chars = _chars; while ((unsigned)pos < _len) { pos = Find(oldChar, pos); if (pos < 0) break; - _chars[(unsigned)pos] = newChar; + chars[(unsigned)pos] = newChar; pos++; // number++; } @@ -1392,13 +1475,13 @@ void UString2::ReAlloc2(unsigned newLimit) { if (newLimit >= k_Alloc_Len_Limit) throw 20130221; // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0); - _chars = MY_STRING_NEW(wchar_t, newLimit + 1); + _chars = MY_STRING_NEW_wchar_t(newLimit + 1); } void UString2::SetStartLen(unsigned len) { _chars = 0; - _chars = MY_STRING_NEW(wchar_t, len + 1); + _chars = MY_STRING_NEW_wchar_t(len + 1); _len = len; } @@ -1407,8 +1490,9 @@ void UString2::SetStartLen(unsigned len) UString2::UString2(wchar_t c) { SetStartLen(1); - _chars[0] = c; - _chars[1] = 0; + wchar_t *chars = _chars; + chars[0] = c; + chars[1] = 0; } */ @@ -1433,14 +1517,15 @@ UString2 &UString2::operator=(wchar_t c) { if (1 > _len) { - wchar_t *newBuf = MY_STRING_NEW(wchar_t, 1 + 1); + wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1); if (_chars) MY_STRING_DELETE(_chars); _chars = newBuf; } _len = 1; - _chars[0] = c; - _chars[1] = 0; + wchar_t *chars = _chars; + chars[0] = c; + chars[1] = 0; return *this; } */ @@ -1450,7 +1535,7 @@ UString2 &UString2::operator=(const wchar_t *s) unsigned len = MyStringLen(s); if (len > _len) { - wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1); + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); if (_chars) MY_STRING_DELETE(_chars); _chars = newBuf; @@ -1465,7 +1550,7 @@ void UString2::SetFromAscii(const char *s) unsigned len = MyStringLen(s); if (len > _len) { - wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1); + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); if (_chars) MY_STRING_DELETE(_chars); _chars = newBuf; @@ -1484,7 +1569,7 @@ UString2 &UString2::operator=(const UString2 &s) unsigned len = s._len; if (len > _len) { - wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1); + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); if (_chars) MY_STRING_DELETE(_chars); _chars = newBuf; @@ -1542,6 +1627,11 @@ AString fs2fas(CFSTR s) return UnicodeStringToMultiByte(s, GetCurrentCodePage()); } +FString fas2fs(const char *s) +{ + return MultiByteToUnicodeString(s, GetCurrentCodePage()); +} + FString fas2fs(const AString &s) { return MultiByteToUnicodeString(s, GetCurrentCodePage()); @@ -1551,9 +1641,14 @@ FString fas2fs(const AString &s) #else +UString fs2us(const FChar *s) +{ + return MultiByteToUnicodeString(s, GetCurrentCodePage()); +} + UString fs2us(const FString &s) { - return MultiByteToUnicodeString((AString)s, GetCurrentCodePage()); + return MultiByteToUnicodeString(s, GetCurrentCodePage()); } FString us2fs(const wchar_t *s) diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h index 02308555..1c7357e4 100644 --- a/CPP/Common/MyString.h +++ b/CPP/Common/MyString.h @@ -14,6 +14,26 @@ #include "MyTypes.h" #include "MyVector.h" + +#ifdef _MSC_VER + #ifdef _NATIVE_WCHAR_T_DEFINED + #define MY_NATIVE_WCHAR_T_DEFINED + #endif +#else + #define MY_NATIVE_WCHAR_T_DEFINED +#endif + +/* + native support for wchar_t: + _MSC_VER == 1600 : /Zc:wchar_t is not supported + _MSC_VER == 1310 (VS2003) + ? _MSC_VER == 1400 (VS2005) : wchar_t <- unsigned short + /Zc:wchar_t : wchar_t <- __wchar_t, _WCHAR_T_DEFINED and _NATIVE_WCHAR_T_DEFINED + _MSC_VER > 1400 (VS2008+) + /Zc:wchar_t[-] + /Zc:wchar_t is on by default +*/ + #ifdef _WIN32 #define IS_PATH_SEPAR(c) ((c) == '\\' || (c) == '/') #else @@ -60,6 +80,12 @@ inline void MyStringCopy(wchar_t *dest, const wchar_t *src) while ((*dest++ = *src++) != 0); } +inline void MyStringCat(wchar_t *dest, const wchar_t *src) +{ + MyStringCopy(dest + MyStringLen(dest), src); +} + + /* inline wchar_t *MyWcpCpy(wchar_t *dest, const wchar_t *src) { @@ -88,13 +114,15 @@ int FindCharPosInString(const wchar_t *s, wchar_t c) throw(); #define STRING_UNICODE_THROW throw() #endif -/* + inline char MyCharUpper_Ascii(char c) { if (c >= 'a' && c <= 'z') - return (char)(c - 0x20); + return (char)((unsigned char)c - 0x20); return c; } + +/* inline wchar_t MyCharUpper_Ascii(wchar_t c) { if (c >= 'a' && c <= 'z') @@ -158,6 +186,7 @@ inline wchar_t MyCharLower(wchar_t c) throw() // char *MyStringUpper(char *s) throw(); // char *MyStringLower(char *s) throw(); +// void MyStringUpper_Ascii(char *s) throw(); // void MyStringUpper_Ascii(wchar_t *s) throw(); void MyStringLower_Ascii(char *s) throw(); void MyStringLower_Ascii(wchar_t *s) throw(); @@ -168,8 +197,11 @@ bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw(); bool IsString1PrefixedByString2(const char *s1, const char *s2) throw(); bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw(); +bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw(); +bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *u, const char *a) throw(); bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw(); +#define MyStringCompare(s1, s2) wcscmp(s1, s2) int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw(); // int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw(); @@ -183,6 +215,33 @@ bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw(); #define MY_STRING_DELETE(_p_) delete []_p_; // #define MY_STRING_DELETE(_p_) my_delete(_p_); + +#define FORBID_STRING_OPS_2(cls, t) \ + void Find(t) const; \ + void Find(t, unsigned startIndex) const; \ + void ReverseFind(t) const; \ + void InsertAtFront(t); \ + void RemoveChar(t); \ + void Replace(t, t); \ + +#define FORBID_STRING_OPS(cls, t) \ + explicit cls(t); \ + explicit cls(const t *); \ + cls &operator=(t); \ + cls &operator=(const t *); \ + cls &operator+=(t); \ + cls &operator+=(const t *); \ + FORBID_STRING_OPS_2(cls, t); \ + +/* + cls &operator+(t); \ + cls &operator+(const t *); \ +*/ + +#define FORBID_STRING_OPS_AString(t) FORBID_STRING_OPS(AString, t) +#define FORBID_STRING_OPS_UString(t) FORBID_STRING_OPS(UString, t) +#define FORBID_STRING_OPS_UString2(t) FORBID_STRING_OPS(UString2, t) + class AString { char *_chars; @@ -202,7 +261,7 @@ class AString void Grow_1(); void Grow(unsigned n); - // AString(unsigned num, const char *s); + AString(unsigned num, const char *s); AString(unsigned num, const AString &s); AString(const AString &s, char c); // it's for String + char AString(const char *s1, unsigned num1, const char *s2, unsigned num2); @@ -215,20 +274,24 @@ class AString friend AString operator+(const char *s1, const AString &s2); // ---------- forbidden functions ---------- - AString &operator+=(wchar_t c); - AString &operator=(wchar_t c); - AString(wchar_t c); - void Find(wchar_t c) const; - void Find(wchar_t c, unsigned startIndex) const; - void ReverseFind(wchar_t c) const; - void InsertAtFront(wchar_t c); - void RemoveChar(wchar_t ch); - void Replace(wchar_t oldChar, wchar_t newChar); + + #ifdef MY_NATIVE_WCHAR_T_DEFINED + FORBID_STRING_OPS_AString(wchar_t) + #endif + + FORBID_STRING_OPS_AString(signed char) + FORBID_STRING_OPS_AString(unsigned char) + FORBID_STRING_OPS_AString(short) + FORBID_STRING_OPS_AString(unsigned short) + FORBID_STRING_OPS_AString(int) + FORBID_STRING_OPS_AString(unsigned) + FORBID_STRING_OPS_AString(long) + FORBID_STRING_OPS_AString(unsigned long) public: - AString(); - AString(char c); - AString(const char *s); + explicit AString(); + explicit AString(char c); + explicit AString(const char *s); AString(const AString &s); ~AString() { MY_STRING_DELETE(_chars); } @@ -240,7 +303,7 @@ public: const char *Ptr() const { return _chars; } const char *Ptr(unsigned pos) const { return _chars + pos; } const char *RightPtr(unsigned num) const { return _chars + _len - num; } - char Back() const { return _chars[_len - 1]; } + char Back() const { return _chars[(size_t)_len - 1]; } void ReplaceOneCharAtPos(unsigned pos, char c) { _chars[pos] = c; } @@ -292,16 +355,17 @@ public: void Add_Space(); void Add_Space_if_NotEmpty(); + void Add_OptSpaced(const char *s); void Add_LF(); void Add_PathSepar() { operator+=(CHAR_PATH_SEPARATOR); } AString &operator+=(const char *s); AString &operator+=(const AString &s); - void AddAscii(const char *s) { operator+=(s); } + + void Add_UInt32(UInt32 v); void SetFrom(const char *s, unsigned len); // no check void SetFrom_CalcLen(const char *s, unsigned len); - // void SetFromAscii(const char *s) { operator+=(s); } AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); } AString Left(unsigned count) const { return AString(count, *this); } @@ -444,28 +508,27 @@ class UString // ---------- forbidden functions ---------- - UString &operator+=(char c); - UString &operator+=(unsigned char c); - UString &operator=(char c); - UString &operator=(unsigned char c); - UString(char c); - UString(unsigned char c); - void Find(char c) const; - void Find(unsigned char c) const; - void Find(char c, unsigned startIndex) const; - void Find(unsigned char c, unsigned startIndex) const; - void ReverseFind(char c) const; - void ReverseFind(unsigned char c) const; - void InsertAtFront(char c); - void InsertAtFront(unsigned char c); - void RemoveChar(char ch); - void RemoveChar(unsigned char ch); - void Replace(char oldChar, char newChar); - void Replace(unsigned char oldChar, unsigned char newChar); + FORBID_STRING_OPS_UString(signed char) + FORBID_STRING_OPS_UString(unsigned char) + FORBID_STRING_OPS_UString(short) + + #ifdef MY_NATIVE_WCHAR_T_DEFINED + FORBID_STRING_OPS_UString(unsigned short) + #endif + + FORBID_STRING_OPS_UString(int) + FORBID_STRING_OPS_UString(unsigned) + FORBID_STRING_OPS_UString(long) + FORBID_STRING_OPS_UString(unsigned long) + + FORBID_STRING_OPS_2(UString, char) public: UString(); - UString(wchar_t c); + explicit UString(wchar_t c); + explicit UString(char c); + explicit UString(const char *s); + // UString(const AString &s); UString(const wchar_t *s); UString(const UString &s); ~UString() { MY_STRING_DELETE(_chars); } @@ -478,7 +541,7 @@ public: const wchar_t *Ptr() const { return _chars; } const wchar_t *Ptr(unsigned pos) const { return _chars + pos; } const wchar_t *RightPtr(unsigned num) const { return _chars + _len - num; } - wchar_t Back() const { return _chars[_len - 1]; } + wchar_t Back() const { return _chars[(size_t)_len - 1]; } void ReplaceOneCharAtPos(unsigned pos, wchar_t c) { _chars[pos] = c; } @@ -508,9 +571,13 @@ public: } UString &operator=(wchar_t c); + UString &operator=(char c) { return (*this)=((wchar_t)c); } UString &operator=(const wchar_t *s); UString &operator=(const UString &s); + void SetFrom(const wchar_t *s, unsigned len); // no check void SetFromBstr(BSTR s); + UString &operator=(const char *s); + UString &operator=(const AString &s) { return operator=(s.Ptr()); } UString &operator+=(wchar_t c) { @@ -524,6 +591,8 @@ public: return *this; } + UString &operator+=(char c) { return (*this)+=((wchar_t)(unsigned char)c); } + void Add_Space(); void Add_Space_if_NotEmpty(); void Add_LF(); @@ -531,11 +600,10 @@ public: UString &operator+=(const wchar_t *s); UString &operator+=(const UString &s); + UString &operator+=(const char *s); + UString &operator+=(const AString &s) { return operator+=(s.Ptr()); } - void SetFrom(const wchar_t *s, unsigned len); // no check - - void SetFromAscii(const char *s); - void AddAscii(const char *s); + void Add_UInt32(UInt32 v); UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); } UString Left(unsigned count) const { return UString(count, *this); } @@ -630,6 +698,12 @@ void operator==(const UString &s1, wchar_t c2); void operator+(wchar_t c, const UString &s); // this function can be OK, but we don't use it +void operator+(const AString &s1, const UString &s2); +void operator+(const UString &s1, const AString &s2); + +void operator+(const UString &s1, const char *s2); +void operator+(const char *s1, const UString &s2); + void operator+(const UString &s, char c); void operator+(const UString &s, unsigned char c); void operator+(char c, const UString &s); @@ -662,15 +736,16 @@ class UString2 // ---------- forbidden functions ---------- - UString2 &operator=(char c); - UString2 &operator=(unsigned char c); + FORBID_STRING_OPS_UString2(char) + FORBID_STRING_OPS_UString2(signed char) + FORBID_STRING_OPS_UString2(unsigned char) + FORBID_STRING_OPS_UString2(short) + UString2 &operator=(wchar_t c); - UString2(char c); - UString2(unsigned char c); + UString2(wchar_t c); public: UString2(): _chars(NULL), _len(0) {} - // UString2(wchar_t c); UString2(const wchar_t *s); UString2(const UString2 &s); ~UString2() { if (_chars) MY_STRING_DELETE(_chars); } @@ -682,6 +757,8 @@ public: // operator const wchar_t *() const { return _chars; } const wchar_t *GetRawPtr() const { return _chars; } + int Compare(const wchar_t *s) const { return wcscmp(_chars, s); } + wchar_t *GetBuf(unsigned minLen) { if (!_chars || minLen > _len) @@ -754,6 +831,7 @@ typedef CObjectVector<CSysString> CSysStringVector; #define fs2us(_x_) (_x_) #define us2fs(_x_) (_x_) + FString fas2fs(const char *s); FString fas2fs(const AString &s); AString fs2fas(const FChar *s); @@ -764,6 +842,7 @@ typedef CObjectVector<CSysString> CSysStringVector; typedef char FChar; typedef AString FString; + UString fs2us(const FChar *s); UString fs2us(const FString &s); FString us2fs(const wchar_t *s); #define fas2fs(_x_) (_x_) @@ -775,8 +854,10 @@ typedef CObjectVector<CSysString> CSysStringVector; #define FCHAR_PATH_SEPARATOR FTEXT(CHAR_PATH_SEPARATOR) #define FSTRING_PATH_SEPARATOR FTEXT(STRING_PATH_SEPARATOR) -#define FCHAR_ANY_MASK FTEXT('*') -#define FSTRING_ANY_MASK FTEXT("*") + +// #define FCHAR_ANY_MASK FTEXT('*') +// #define FSTRING_ANY_MASK FTEXT("*") + typedef const FChar *CFSTR; typedef CObjectVector<FString> FStringVector; diff --git a/CPP/Common/MyVector.h b/CPP/Common/MyVector.h index 14f7b11a..61dabbd1 100644 --- a/CPP/Common/MyVector.h +++ b/CPP/Common/MyVector.h @@ -22,7 +22,9 @@ class CRecordVector if (_size == _capacity) { unsigned newCapacity = _capacity + (_capacity >> 2) + 1; - T *p = new T[newCapacity]; + T *p; + MY_ARRAY_NEW(p, T, newCapacity); + // p = new T[newCapacity]; if (_size != 0) memcpy(p, _items, (size_t)_size * sizeof(T)); delete []_items; @@ -54,7 +56,8 @@ public: { if (size != 0) { - _items = new T[size]; + MY_ARRAY_NEW(_items, T, size) + // _items = new T[size]; _capacity = size; } } @@ -63,7 +66,9 @@ public: { if (newCapacity > _capacity) { - T *p = new T[newCapacity]; + T *p; + MY_ARRAY_NEW(p, T, newCapacity); + // p = new T[newCapacity]; if (_size != 0) memcpy(p, _items, (size_t)_size * sizeof(T)); delete []_items; @@ -80,7 +85,8 @@ public: delete []_items; _items = NULL; _capacity = 0; - _items = new T[newCapacity]; + MY_ARRAY_NEW(_items, T, newCapacity) + // _items = new T[newCapacity]; _capacity = newCapacity; } } @@ -95,7 +101,9 @@ public: { if (newSize > _capacity) { - T *p = new T[newSize]; + T *p; + MY_ARRAY_NEW(p, T, newSize) + // p = new T[newSize]; if (_size != 0) memcpy(p, _items, (size_t)_size * sizeof(T)); delete []_items; @@ -230,8 +238,8 @@ public: T& operator[](unsigned index) { return _items[index]; } const T& Front() const { return _items[0]; } T& Front() { return _items[0]; } - const T& Back() const { return _items[_size - 1]; } - T& Back() { return _items[_size - 1]; } + const T& Back() const { return _items[(size_t)_size - 1]; } + T& Back() { return _items[(size_t)_size - 1]; } /* void Swap(unsigned i, unsigned j) @@ -370,7 +378,7 @@ public: unsigned s = (k << 1); if (s > size) break; - if (s < size && p[s + 1].Compare(p[s]) > 0) + if (s < size && p[(size_t)s + 1].Compare(p[s]) > 0) s++; if (temp.Compare(p[s]) >= 0) break; @@ -453,8 +461,8 @@ public: T& operator[](unsigned index) { return *((T *)_v[index]); } const T& Front() const { return operator[](0); } T& Front() { return operator[](0); } - const T& Back() const { return operator[](_v.Size() - 1); } - T& Back() { return operator[](_v.Size() - 1); } + const T& Back() const { return *(T *)_v.Back(); } + T& Back() { return *(T *)_v.Back(); } void MoveToFront(unsigned index) { _v.MoveToFront(index); } @@ -521,7 +529,7 @@ public: void DeleteBack() { - delete (T *)_v[_v.Size() - 1]; + delete (T *)_v.Back(); _v.DeleteBack(); } diff --git a/CPP/Common/MyWindows.h b/CPP/Common/MyWindows.h index 139a4e8b..a8db9e65 100644 --- a/CPP/Common/MyWindows.h +++ b/CPP/Common/MyWindows.h @@ -44,6 +44,16 @@ typedef UINT32 ULONG; #undef DWORD typedef UINT32 DWORD; +typedef long BOOL; + +#ifndef FALSE + #define FALSE 0 + #define TRUE 1 +#endif + +// typedef size_t ULONG_PTR; +typedef size_t DWORD_PTR; + typedef Int64 LONGLONG; typedef UInt64 ULONGLONG; diff --git a/CPP/Common/MyXml.cpp b/CPP/Common/MyXml.cpp index a177e4a2..f34a745e 100644 --- a/CPP/Common/MyXml.cpp +++ b/CPP/Common/MyXml.cpp @@ -20,7 +20,7 @@ static bool IsSpaceChar(char c) #define SKIP_SPACES(s) while (IsSpaceChar(*s)) s++; -int CXmlItem::FindProp(const AString &propName) const throw() +int CXmlItem::FindProp(const char *propName) const throw() { FOR_VECTOR (i, Props) if (Props[i].Name == propName) @@ -28,7 +28,7 @@ int CXmlItem::FindProp(const AString &propName) const throw() return -1; } -AString CXmlItem::GetPropVal(const AString &propName) const +AString CXmlItem::GetPropVal(const char *propName) const { int index = FindProp(propName); if (index >= 0) @@ -36,12 +36,12 @@ AString CXmlItem::GetPropVal(const AString &propName) const return AString(); } -bool CXmlItem::IsTagged(const AString &tag) const throw() +bool CXmlItem::IsTagged(const char *tag) const throw() { return (IsTag && Name == tag); } -int CXmlItem::FindSubTag(const AString &tag) const throw() +int CXmlItem::FindSubTag(const char *tag) const throw() { FOR_VECTOR (i, SubItems) if (SubItems[i].IsTagged(tag)) @@ -71,7 +71,7 @@ const AString * CXmlItem::GetSubStringPtr() const throw() return NULL; } -AString CXmlItem::GetSubStringForTag(const AString &tag) const +AString CXmlItem::GetSubStringForTag(const char *tag) const { int index = FindSubTag(tag); if (index >= 0) diff --git a/CPP/Common/MyXml.h b/CPP/Common/MyXml.h index 0e4b21d4..00b7113a 100644 --- a/CPP/Common/MyXml.h +++ b/CPP/Common/MyXml.h @@ -21,13 +21,13 @@ public: const char * ParseItem(const char *s, int numAllowedLevels); - bool IsTagged(const AString &tag) const throw(); - int FindProp(const AString &propName) const throw(); - AString GetPropVal(const AString &propName) const; + bool IsTagged(const char *tag) const throw(); + int FindProp(const char *propName) const throw(); + AString GetPropVal(const char *propName) const; AString GetSubString() const; const AString * GetSubStringPtr() const throw(); - int FindSubTag(const AString &tag) const throw(); - AString GetSubStringForTag(const AString &tag) const; + int FindSubTag(const char *tag) const throw(); + AString GetSubStringForTag(const char *tag) const; void AppendTo(AString &s) const; }; diff --git a/CPP/Common/NewHandler.cpp b/CPP/Common/NewHandler.cpp index 522c2a75..7e5b1d45 100644 --- a/CPP/Common/NewHandler.cpp +++ b/CPP/Common/NewHandler.cpp @@ -10,7 +10,7 @@ #ifndef DEBUG_MEMORY_LEAK -#ifdef _WIN32 +#ifdef _7ZIP_REDEFINE_OPERATOR_NEW /* void * my_new(size_t size) diff --git a/CPP/Common/NewHandler.h b/CPP/Common/NewHandler.h index dcad5688..aedeca64 100644 --- a/CPP/Common/NewHandler.h +++ b/CPP/Common/NewHandler.h @@ -4,28 +4,29 @@ #define __COMMON_NEW_HANDLER_H /* -This file must be included before any code that uses operators "delete" or "new". -Also you must compile and link "NewHandler.cpp", if you use MSVC 6.0. -The operator "new" in MSVC 6.0 doesn't throw exception "bad_alloc". -So we define another version of operator "new" that throws "CNewException" on failure. +NewHandler.h and NewHandler.cpp allows to solve problem with compilers that +don't throw exception in operator new(). -If you use compiler that throws exception in "new" operator (GCC or new version of MSVC), -you can compile without "NewHandler.cpp". So standard exception "bad_alloc" will be used. +This file must be included before any code that uses operators new() or delete() +and you must compile and link "NewHandler.cpp", if you use some old MSVC compiler. -It's still allowed to use redefined version of operator "new" from "NewHandler.cpp" -with any compiler. 7-Zip's code can work with "bad_alloc" and "CNewException" exceptions. -But if you use some additional code (outside of 7-Zip's code), you must check -that redefined version of operator "new" (that throws CNewException) is not -problem for your code. +The operator new() in some MSVC versions doesn't throw exception std::bad_alloc. +MSVC 6.0 (_MSC_VER == 1200) doesn't throw exception. +The code produced by some another MSVC compilers also can be linked +to library that doesn't throw exception. +We suppose that code compiled with VS2015+ (_MSC_VER >= 1900) throws exception std::bad_alloc. +For older _MSC_VER versions we redefine operator new() and operator delete(). +Our version of operator new() throws CNewException() exception on failure. -Also we declare delete(void *p) throw() that creates smaller code. +It's still allowed to use redefined version of operator new() from "NewHandler.cpp" +with any compiler. 7-Zip's code can work with std::bad_alloc and CNewException() exceptions. +But if you use some additional code (outside of 7-Zip's code), you must check +that redefined version of operator new() is not problem for your code. */ #include <stddef.h> -class CNewException {}; - -#ifdef WIN32 +#ifdef _WIN32 // We can compile my_new and my_delete with _fastcall /* void * my_new(size_t size); @@ -34,7 +35,19 @@ void my_delete(void *p) throw(); */ #endif -#ifdef _WIN32 + +#if defined(_MSC_VER) && (_MSC_VER < 1900) + // If you want to use default operator new(), you can disable the following line + #define _7ZIP_REDEFINE_OPERATOR_NEW +#endif + + +#ifdef _7ZIP_REDEFINE_OPERATOR_NEW + +// std::bad_alloc can require additional DLL dependency. +// So we don't define CNewException as std::bad_alloc here. + +class CNewException {}; void * #ifdef _MSC_VER @@ -48,6 +61,12 @@ __cdecl #endif operator delete(void *p) throw(); +#else + +#include <new> + +#define CNewException std::bad_alloc + #endif /* diff --git a/CPP/Common/StdInStream.cpp b/CPP/Common/StdInStream.cpp index c35747bb..422a96e5 100644 --- a/CPP/Common/StdInStream.cpp +++ b/CPP/Common/StdInStream.cpp @@ -8,13 +8,11 @@ #include "StringConvert.h" #include "UTFConvert.h" -static const char kNewLineChar = '\n'; +// #define kEOFMessage "Unexpected end of input stream" +// #define kReadErrorMessage "Error reading input stream" +// #define kIllegalCharMessage "Illegal zero character in input stream" -static const char *kEOFMessage = "Unexpected end of input stream"; -static const char *kReadErrorMessage ="Error reading input stream"; -static const char *kIllegalCharMessage = "Illegal character in input stream"; - -static LPCTSTR kFileOpenMode = TEXT("r"); +#define kFileOpenMode TEXT("r") extern int g_CodePage; @@ -36,59 +34,56 @@ bool CStdInStream::Close() throw() return !_streamIsOpen; } -AString CStdInStream::ScanStringUntilNewLine(bool allowEOF) +bool CStdInStream::ScanAStringUntilNewLine(AString &s) { - AString s; + s.Empty(); for (;;) { int intChar = GetChar(); if (intChar == EOF) - { - if (allowEOF) - break; - throw kEOFMessage; - } + return true; char c = (char)intChar; if (c == 0) - throw kIllegalCharMessage; - if (c == kNewLineChar) - break; + return false; + if (c == '\n') + return true; s += c; } - return s; } -UString CStdInStream::ScanUStringUntilNewLine() +bool CStdInStream::ScanUStringUntilNewLine(UString &dest) { - AString s = ScanStringUntilNewLine(true); + dest.Empty(); + AString s; + bool res = ScanAStringUntilNewLine(s); int codePage = g_CodePage; if (codePage == -1) codePage = CP_OEMCP; - UString dest; if (codePage == CP_UTF8) ConvertUTF8ToUnicode(s, dest); else - dest = MultiByteToUnicodeString(s, (UINT)codePage); - return dest; + MultiByteToUnicodeString2(dest, s, (UINT)codePage); + return res; } -void CStdInStream::ReadToString(AString &resultString) +/* +bool CStdInStream::ReadToString(AString &resultString) { resultString.Empty(); - int c; - while ((c = GetChar()) != EOF) - resultString += (char)c; -} - -bool CStdInStream::Eof() throw() -{ - return (feof(_stream) != 0); + for (;;) + { + int intChar = GetChar(); + if (intChar == EOF) + return !Error(); + char c = (char)intChar; + if (c == 0) + return false; + resultString += c; + } } +*/ int CStdInStream::GetChar() { - int c = fgetc(_stream); // getc() doesn't work in BeOS? - if (c == EOF && !Eof()) - throw kReadErrorMessage; - return c; + return fgetc(_stream); // getc() doesn't work in BeOS? } diff --git a/CPP/Common/StdInStream.h b/CPP/Common/StdInStream.h index 6d9ed670..698ebec1 100644 --- a/CPP/Common/StdInStream.h +++ b/CPP/Common/StdInStream.h @@ -20,11 +20,16 @@ public: bool Open(LPCTSTR fileName) throw(); bool Close() throw(); - AString ScanStringUntilNewLine(bool allowEOF = false); - void ReadToString(AString &resultString); - UString ScanUStringUntilNewLine(); + // returns: + // false, if ZERO character in stream + // true, if EOF or '\n' + bool ScanAStringUntilNewLine(AString &s); + bool ScanUStringUntilNewLine(UString &s); + // bool ReadToString(AString &resultString); + + bool Eof() const throw() { return (feof(_stream) != 0); } + bool Error() const throw() { return (ferror(_stream) != 0); } - bool Eof() throw(); int GetChar(); }; diff --git a/CPP/Common/StdOutStream.cpp b/CPP/Common/StdOutStream.cpp index 6aed31a3..19e0329f 100644 --- a/CPP/Common/StdOutStream.cpp +++ b/CPP/Common/StdOutStream.cpp @@ -9,9 +9,7 @@ #include "StringConvert.h" #include "UTFConvert.h" -static const char kNewLineChar = '\n'; - -static const char *kFileOpenMode = "wt"; +#define kFileOpenMode "wt" extern int g_CodePage; @@ -44,7 +42,7 @@ bool CStdOutStream::Flush() throw() CStdOutStream & endl(CStdOutStream & outStream) throw() { - return outStream << kNewLineChar; + return outStream << '\n'; } CStdOutStream & CStdOutStream::operator<<(const wchar_t *s) diff --git a/CPP/Common/StringConvert.cpp b/CPP/Common/StringConvert.cpp index 30d95aa7..2a73d688 100644 --- a/CPP/Common/StringConvert.cpp +++ b/CPP/Common/StringConvert.cpp @@ -291,6 +291,12 @@ UString MultiByteToUnicodeString(const AString &src, UINT codePage) return dest; } +UString MultiByteToUnicodeString(const char *src, UINT codePage) +{ + return MultiByteToUnicodeString(AString(src), codePage); +} + + void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage) { bool defaultCharWasUsed; diff --git a/CPP/Common/StringConvert.h b/CPP/Common/StringConvert.h index 92401245..25fe503f 100644 --- a/CPP/Common/StringConvert.h +++ b/CPP/Common/StringConvert.h @@ -6,72 +6,83 @@ #include "MyString.h" #include "MyWindows.h" -UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP); +UString MultiByteToUnicodeString(const AString &src, UINT codePage = CP_ACP); +UString MultiByteToUnicodeString(const char *src, UINT codePage = CP_ACP); // optimized versions that work faster for ASCII strings -void MultiByteToUnicodeString2(UString &dest, const AString &srcString, UINT codePage = CP_ACP); +void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage = CP_ACP); // void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed); -void UnicodeStringToMultiByte2(AString &dest, const UString &srcString, UINT codePage); - -AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage, char defaultChar, bool &defaultCharWasUsed); -AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP); - -inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString) - { return unicodeString; } -inline const UString& GetUnicodeString(const UString &unicodeString) - { return unicodeString; } -inline UString GetUnicodeString(const AString &ansiString) - { return MultiByteToUnicodeString(ansiString); } -inline UString GetUnicodeString(const AString &multiByteString, UINT codePage) - { return MultiByteToUnicodeString(multiByteString, codePage); } -inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT) - { return unicodeString; } -inline const UString& GetUnicodeString(const UString &unicodeString, UINT) - { return unicodeString; } - -inline const char* GetAnsiString(const char* ansiString) - { return ansiString; } -inline const AString& GetAnsiString(const AString &ansiString) - { return ansiString; } -inline AString GetAnsiString(const UString &unicodeString) - { return UnicodeStringToMultiByte(unicodeString); } - -inline const char* GetOemString(const char* oemString) - { return oemString; } -inline const AString& GetOemString(const AString &oemString) - { return oemString; } -inline AString GetOemString(const UString &unicodeString) - { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); } +void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage); +AString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed); +AString UnicodeStringToMultiByte(const UString &src, UINT codePage = CP_ACP); + +inline const wchar_t* GetUnicodeString(const wchar_t *u) { return u; } +inline const UString& GetUnicodeString(const UString &u) { return u; } + +inline UString GetUnicodeString(const AString &a) { return MultiByteToUnicodeString(a); } +inline UString GetUnicodeString(const char *a) { return MultiByteToUnicodeString(a); } + +inline UString GetUnicodeString(const AString &a, UINT codePage) + { return MultiByteToUnicodeString(a, codePage); } +inline UString GetUnicodeString(const char *a, UINT codePage) + { return MultiByteToUnicodeString(a, codePage); } + +inline const wchar_t* GetUnicodeString(const wchar_t *u, UINT) { return u; } +inline const UString& GetUnicodeString(const UString &u, UINT) { return u; } + +inline const char* GetAnsiString(const char *a) { return a; } +inline const AString& GetAnsiString(const AString &a) { return a; } + +inline AString GetAnsiString(const wchar_t *u) { return UnicodeStringToMultiByte(UString(u)); } +inline AString GetAnsiString(const UString &u) { return UnicodeStringToMultiByte(u); } + +/* +inline const char* GetOemString(const char* oem) + { return oem; } +inline const AString& GetOemString(const AString &oem) + { return oem; } +*/ +const char* GetOemString(const char* oem); +const AString& GetOemString(const AString &oem); +inline AString GetOemString(const UString &u) + { return UnicodeStringToMultiByte(u, CP_OEMCP); } #ifdef _UNICODE - inline const wchar_t* GetSystemString(const wchar_t* unicodeString) - { return unicodeString;} - inline const UString& GetSystemString(const UString &unicodeString) - { return unicodeString;} - inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT /* codePage */) - { return unicodeString;} - inline const UString& GetSystemString(const UString &unicodeString, UINT /* codePage */) - { return unicodeString;} - inline UString GetSystemString(const AString &multiByteString, UINT codePage) - { return MultiByteToUnicodeString(multiByteString, codePage);} - inline UString GetSystemString(const AString &multiByteString) - { return MultiByteToUnicodeString(multiByteString);} + inline const wchar_t* GetSystemString(const wchar_t *u) { return u;} + inline const UString& GetSystemString(const UString &u) { return u;} + inline const wchar_t* GetSystemString(const wchar_t *u, UINT /* codePage */) { return u;} + inline const UString& GetSystemString(const UString &u, UINT /* codePage */) { return u;} + + inline UString GetSystemString(const AString &a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); } + inline UString GetSystemString(const char *a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); } + inline UString GetSystemString(const AString &a) { return MultiByteToUnicodeString(a); } + inline UString GetSystemString(const char *a) { return MultiByteToUnicodeString(a); } #else - inline const char* GetSystemString(const char *ansiString) - { return ansiString; } - inline const AString& GetSystemString(const AString &multiByteString, UINT) - { return multiByteString; } - inline const char * GetSystemString(const char *multiByteString, UINT) - { return multiByteString; } - inline AString GetSystemString(const UString &unicodeString) - { return UnicodeStringToMultiByte(unicodeString); } - inline AString GetSystemString(const UString &unicodeString, UINT codePage) - { return UnicodeStringToMultiByte(unicodeString, codePage); } + inline const char* GetSystemString(const char *a) { return a; } + inline const AString& GetSystemString(const AString &a) { return a; } + inline const char* GetSystemString(const char *a, UINT) { return a; } + inline const AString& GetSystemString(const AString &a, UINT) { return a; } + + inline AString GetSystemString(const wchar_t *u) { return UnicodeStringToMultiByte(UString(u)); } + inline AString GetSystemString(const UString &u) { return UnicodeStringToMultiByte(u); } + inline AString GetSystemString(const UString &u, UINT codePage) { return UnicodeStringToMultiByte(u, codePage); } + + + + /* + inline AString GetSystemString(const wchar_t *u) + { + UString s; + s = u; + return UnicodeStringToMultiByte(s); + } + */ + #endif #ifndef UNDER_CE -AString SystemStringToOemString(const CSysString &srcString); +AString SystemStringToOemString(const CSysString &src); #endif #endif diff --git a/CPP/Common/TextConfig.cpp b/CPP/Common/TextConfig.cpp index 9ae4074b..1428aab5 100644 --- a/CPP/Common/TextConfig.cpp +++ b/CPP/Common/TextConfig.cpp @@ -61,7 +61,7 @@ bool GetTextConfig(const AString &s, CObjectVector<CTextConfigPair> &pairs) break; CTextConfigPair pair; unsigned finishPos; - AString temp = GetIDString(((const char *)s) + pos, finishPos); + const AString temp (GetIDString(((const char *)s) + pos, finishPos)); if (!ConvertUTF8ToUnicode(temp, pair.ID)) return false; if (finishPos == 0) @@ -107,15 +107,15 @@ bool GetTextConfig(const AString &s, CObjectVector<CTextConfigPair> &pairs) return true; } -int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const UString &id) throw() +int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const char *id) throw() { FOR_VECTOR (i, pairs) - if (pairs[i].ID == id) + if (pairs[i].ID.IsEqualTo(id)) return i; return -1; } -UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const UString &id) +UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const char *id) { int index = FindTextConfigItem(pairs, id); if (index < 0) diff --git a/CPP/Common/TextConfig.h b/CPP/Common/TextConfig.h index 0129ad96..cc7ce412 100644 --- a/CPP/Common/TextConfig.h +++ b/CPP/Common/TextConfig.h @@ -13,7 +13,7 @@ struct CTextConfigPair bool GetTextConfig(const AString &text, CObjectVector<CTextConfigPair> &pairs); -int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const UString &id) throw(); -UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const UString &id); +int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const char *id) throw(); +UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const char *id); #endif diff --git a/CPP/Common/Wildcard.cpp b/CPP/Common/Wildcard.cpp index 5e6ddfc6..a7199170 100644 --- a/CPP/Common/Wildcard.cpp +++ b/CPP/Common/Wildcard.cpp @@ -22,16 +22,18 @@ bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2) int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW { if (g_CaseSensitive) - return wcscmp(s1, s2); + return MyStringCompare(s1, s2); return MyStringCompareNoCase(s1, s2); } #ifndef USE_UNICODE_FSTRING int CompareFileNames(const char *s1, const char *s2) { + const UString u1 = fs2us(s1); + const UString u2 = fs2us(s2); if (g_CaseSensitive) - return wcscmp(fs2us(s1), fs2us(s2)); - return MyStringCompareNoCase(fs2us(s1), fs2us(s2)); + return MyStringCompare(u1, u2); + return MyStringCompareNoCase(u1, u2); } #endif @@ -120,24 +122,16 @@ void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &na name = p; } +/* UString ExtractDirPrefixFromPath(const UString &path) { - const wchar_t *start = path; - const wchar_t *p = start + path.Len(); - for (; p != start; p--) - if (IsPathSepar(*(p - 1))) - break; - return path.Left((unsigned)(p - start)); + return path.Left(path.ReverseFind_PathSepar() + 1)); } +*/ UString ExtractFileNameFromPath(const UString &path) { - const wchar_t *start = path; - const wchar_t *p = start + path.Len(); - for (; p != start; p--) - if (IsPathSepar(*(p - 1))) - break; - return p; + return UString(path.Ptr(path.ReverseFind_PathSepar() + 1)); } @@ -425,7 +419,7 @@ void CCensorNode::AddItem2(bool include, const UString &path, bool recursive, bo return; bool forFile = true; bool forFolder = true; - UString path2 = path; + UString path2 (path); if (IsPathSepar(path.Back())) { path2.DeleteBack(); @@ -612,7 +606,7 @@ void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &pat { // we create universal item, if we skip all parts as prefix (like \ or L:\ ) pathParts.Clear(); - pathParts.Add(L"*"); + pathParts.Add(UString("*")); forFile = true; wildcardMatching = true; recursive = false; diff --git a/CPP/Common/Wildcard.h b/CPP/Common/Wildcard.h index 512687d1..93f53c0f 100644 --- a/CPP/Common/Wildcard.h +++ b/CPP/Common/Wildcard.h @@ -139,7 +139,7 @@ public: } void AddPreItem_Wildcard() { - AddPreItem(true, L"*", false, true); + AddPreItem(true, UString("*"), false, true); } }; diff --git a/CPP/Common/XzCrc64Init.cpp b/CPP/Common/XzCrc64Init.cpp new file mode 100644 index 00000000..5cb8e674 --- /dev/null +++ b/CPP/Common/XzCrc64Init.cpp @@ -0,0 +1,7 @@ +// XzCrc64Init.cpp + +#include "StdAfx.h" + +#include "../../C/XzCrc64.h" + +static struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit; diff --git a/CPP/Windows/Clipboard.cpp b/CPP/Windows/Clipboard.cpp index e0996930..bc7e201d 100644 --- a/CPP/Windows/Clipboard.cpp +++ b/CPP/Windows/Clipboard.cpp @@ -117,7 +117,7 @@ bool ClipboardSetText(HWND owner, const UString &s) bool res; res = ClipboardSetData(CF_UNICODETEXT, (const wchar_t *)s, (s.Len() + 1) * sizeof(wchar_t)); #ifndef _UNICODE - AString a = UnicodeStringToMultiByte(s, CP_ACP); + AString a (UnicodeStringToMultiByte(s, CP_ACP)); if (ClipboardSetData(CF_TEXT, (const char *)a, (a.Len() + 1) * sizeof(char))) res = true; a = UnicodeStringToMultiByte(s, CP_OEMCP); diff --git a/CPP/Windows/Control/PropertyPage.cpp b/CPP/Windows/Control/PropertyPage.cpp index bbac74ad..ce8696d4 100644 --- a/CPP/Windows/Control/PropertyPage.cpp +++ b/CPP/Windows/Control/PropertyPage.cpp @@ -115,7 +115,7 @@ INT_PTR MyPropertySheet(const CObjectVector<CPageInfo> &pagesInfo, HWND hwndPare sheet.dwFlags = PSH_PROPSHEETPAGE; sheet.hwndParent = hwndParent; sheet.hInstance = g_hInstance; - AString titleA = GetSystemString(title); + AString titleA (GetSystemString(title)); sheet.pszCaption = titleA; sheet.nPages = pagesInfo.Size(); sheet.nStartPage = 0; diff --git a/CPP/Windows/DLL.cpp b/CPP/Windows/DLL.cpp index a71a8017..d7f38375 100644 --- a/CPP/Windows/DLL.cpp +++ b/CPP/Windows/DLL.cpp @@ -97,12 +97,11 @@ FString GetModuleDirPrefix() { int pos = s.ReverseFind_PathSepar(); if (pos >= 0) - { s.DeleteFrom(pos + 1); - return s; - } } - return FTEXT(".") FSTRING_PATH_SEPARATOR; + if (s.IsEmpty()) + s = "." STRING_PATH_SEPARATOR; + return s; } #endif diff --git a/CPP/Windows/ErrorMsg.cpp b/CPP/Windows/ErrorMsg.cpp index c9de4a6c..b86c0b39 100644 --- a/CPP/Windows/ErrorMsg.cpp +++ b/CPP/Windows/ErrorMsg.cpp @@ -53,8 +53,8 @@ UString MyFormatMessage(DWORD errorCode) s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); } s[8] = 0; - m.AddAscii("Error #"); - m.AddAscii(s); + m += "Error #"; + m += s; } else if (m.Len() >= 2 && m[m.Len() - 1] == 0x0A diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp index da71b710..a7164b6b 100644 --- a/CPP/Windows/FileDir.cpp +++ b/CPP/Windows/FileDir.cpp @@ -345,7 +345,7 @@ bool CreateComplexDir(CFSTR _path) #endif - FString path = _path; + FString path (_path); int pos = path.ReverseFind_PathSepar(); if (pos >= 0 && (unsigned)pos == path.Len() - 1) @@ -355,7 +355,7 @@ bool CreateComplexDir(CFSTR _path) path.DeleteBack(); } - const FString path2 = path; + const FString path2 (path); pos = path.Len(); for (;;) @@ -452,11 +452,11 @@ bool RemoveDirWithSubItems(const FString &path) if (needRemoveSubItems) { - FString s = path; + FString s (path); s.Add_PathSepar(); - unsigned prefixSize = s.Len(); - s += FCHAR_ANY_MASK; - NFind::CEnumerator enumerator(s); + const unsigned prefixSize = s.Len(); + NFind::CEnumerator enumerator; + enumerator.SetDirPrefix(s); NFind::CFileInfo fi; while (enumerator.Next(fi)) { @@ -580,18 +580,18 @@ static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COu path = prefix; if (addRandom) { - FChar s[16]; - UInt32 value = d; + char s[16]; + UInt32 val = d; unsigned k; for (k = 0; k < 8; k++) { - unsigned t = value & 0xF; - value >>= 4; - s[k] = (FChar)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + unsigned t = val & 0xF; + val >>= 4; + s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); } s[k] = '\0'; if (outFile) - path += FChar('.'); + path += '.'; path += s; UInt32 step = GetTickCount() + 2; if (step == 0) @@ -600,7 +600,7 @@ static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COu } addRandom = true; if (outFile) - path += FTEXT(".tmp"); + path += ".tmp"; if (NFind::DoesFileOrDirExist(path)) { SetLastError(ERROR_ALREADY_EXISTS); diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp index 05196f92..b9692b81 100644 --- a/CPP/Windows/FileFind.cpp +++ b/CPP/Windows/FileFind.cpp @@ -227,7 +227,7 @@ bool CStreamInfo::IsMainStream() const throw() UString CStreamInfo::GetReducedName() const { // remove ":$DATA" postfix, but keep postfix, if Name is "::$DATA" - UString s = Name; + UString s (Name); if (s.Len() > 6 + 1 && StringsAreEqualNoCase_Ascii(s.RightPtr(6), ":$DATA")) s.DeleteFrom(s.Len() - 6); return s; @@ -453,7 +453,7 @@ bool CFileInfo::Find(CFSTR path) if (colonPos >= 0 && path[(unsigned)colonPos + 1] != 0) { UString streamName = fs2us(path + (unsigned)colonPos); - FString filePath = path; + FString filePath (path); filePath.DeleteFrom(colonPos); /* we allow both cases: name:stream @@ -462,7 +462,7 @@ bool CFileInfo::Find(CFSTR path) const unsigned kPostfixSize = 6; if (streamName.Len() <= kPostfixSize || !StringsAreEqualNoCase_Ascii(streamName.RightPtr(kPostfixSize), ":$DATA")) - streamName += L":$DATA"; + streamName += ":$DATA"; bool isOk = true; @@ -559,9 +559,9 @@ bool CFileInfo::Find(CFSTR path) { if (NName::FindSepar(path + prefixSize) < 0) { - FString s = path; + FString s (path); s.Add_PathSepar(); - s += FCHAR_ANY_MASK; + s += '*'; // CHAR_ANY_MASK bool isOK = false; if (finder.FindFirst(s, *this)) @@ -618,6 +618,12 @@ bool DoesFileOrDirExist(CFSTR name) } +void CEnumerator::SetDirPrefix(const FString &dirPrefix) +{ + _wildcard = dirPrefix; + _wildcard += '*'; +} + bool CEnumerator::NextAny(CFileInfo &fi) { if (_findFile.IsHandleAllocated()) diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h index 615c2dfe..bfb29206 100644 --- a/CPP/Windows/FileFind.h +++ b/CPP/Windows/FileFind.h @@ -134,7 +134,7 @@ class CEnumerator bool NextAny(CFileInfo &fileInfo); public: - CEnumerator(const FString &wildcard): _wildcard(wildcard) {} + void SetDirPrefix(const FString &dirPrefix); bool Next(CFileInfo &fileInfo); bool Next(CFileInfo &fileInfo, bool &found); }; diff --git a/CPP/Windows/FileLink.cpp b/CPP/Windows/FileLink.cpp index 25d49ac3..9e706ead 100644 --- a/CPP/Windows/FileLink.cpp +++ b/CPP/Windows/FileLink.cpp @@ -74,7 +74,7 @@ static const UInt32 kReparseFlags_Microsoft = ((UInt32)1 << 31); #define Set16(p, v) SetUi16(p, v) #define Set32(p, v) SetUi32(p, v) -static const wchar_t *k_LinkPrefix = L"\\??\\"; +static const wchar_t * const k_LinkPrefix = L"\\??\\"; static const unsigned k_LinkPrefix_Size = 4; static const bool IsLinkPrefix(const wchar_t *s) @@ -83,7 +83,7 @@ static const bool IsLinkPrefix(const wchar_t *s) } /* -static const wchar_t *k_VolumePrefix = L"Volume{"; +static const wchar_t * const k_VolumePrefix = L"Volume{"; static const bool IsVolumeName(const wchar_t *s) { return IsString1PrefixedByString2(s, k_VolumePrefix); @@ -332,7 +332,7 @@ bool CReparseAttr::IsVolume() const UString CReparseAttr::GetPath() const { - UString s = SubsName; + UString s (SubsName); if (IsLinkPrefix(s)) { s.ReplaceOneCharAtPos(1, '\\'); @@ -376,7 +376,7 @@ bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMA static bool CreatePrefixDirOfFile(CFSTR path) { - FString path2 = path; + FString path2 (path); int pos = path2.ReverseFind_PathSepar(); if (pos < 0) return true; diff --git a/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp index 908ed53f..2d0b50d5 100644 --- a/CPP/Windows/FileName.cpp +++ b/CPP/Windows/FileName.cpp @@ -87,8 +87,8 @@ bool IsAltPathPrefix(CFSTR s) throw() #if defined(_WIN32) && !defined(UNDER_CE) -const wchar_t *kSuperPathPrefix = L"\\\\?\\"; -static const wchar_t *kSuperUncPrefix = L"\\\\?\\UNC\\"; +const char * const kSuperPathPrefix = "\\\\?\\"; +static const char * const kSuperUncPrefix = "\\\\?\\UNC\\"; #define IS_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '.' && IS_SEPAR((s)[3])) #define IS_SUPER_PREFIX(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '?' && IS_SEPAR((s)[3])) @@ -109,7 +109,7 @@ bool IsDevicePath(CFSTR s) throw() /* // actually we don't know the way to open device file in WinCE. unsigned len = MyStringLen(s); - if (len < 5 || len > 5 || memcmp(s, FTEXT("DSK"), 3 * sizeof(FChar)) != 0) + if (len < 5 || len > 5 || !IsString1PrefixedByString2(s, "DSK")) return false; if (s[4] != ':') return false; @@ -123,7 +123,7 @@ bool IsDevicePath(CFSTR s) throw() unsigned len = MyStringLen(s); if (len == 6 && s[5] == ':') return true; - if (len < 18 || len > 22 || memcmp(s + kDevicePathPrefixSize, FTEXT("PhysicalDrive"), 13 * sizeof(FChar)) != 0) + if (len < 18 || len > 22 || !IsString1PrefixedByString2(s + kDevicePathPrefixSize, "PhysicalDrive")) return false; for (unsigned i = 17; i < len; i++) if (s[i] < '0' || s[i] > '9') @@ -191,14 +191,12 @@ bool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); } bool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); } #endif // USE_UNICODE_FSTRING -/* -bool IsDrivePath_SuperAllowed(CFSTR s) +bool IsDrivePath_SuperAllowed(CFSTR s) throw() { if (IsSuperPath(s)) s += kSuperPathPrefixSize; return IsDrivePath(s); } -*/ bool IsDriveRootPath_SuperAllowed(CFSTR s) throw() { @@ -212,7 +210,7 @@ bool IsAbsolutePath(const wchar_t *s) throw() return IS_SEPAR(s[0]) || IsDrivePath2(s); } -int FindAltStreamColon(CFSTR path) +int FindAltStreamColon(CFSTR path) throw() { unsigned i = 0; if (IsDrivePath2(path)) @@ -274,7 +272,7 @@ static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s) return kSuperPathPrefixSize + pos + 1; } -unsigned GetRootPrefixSize(CFSTR s) +unsigned GetRootPrefixSize(CFSTR s) throw() { if (IS_DEVICE_PATH(s)) return kDevicePathPrefixSize; @@ -285,7 +283,7 @@ unsigned GetRootPrefixSize(CFSTR s) #endif // USE_UNICODE_FSTRING -static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) +static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw() { // Network path: we look "server\path\" as root prefix int pos = FindSepar(s); @@ -297,7 +295,7 @@ static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) return pos + pos2 + 2; } -static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) +static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw() { if (IsDrivePath(s)) return kDrivePrefixSize; @@ -309,7 +307,7 @@ static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) return (size == 0) ? 0 : 2 + size; } -static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) +static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw() { if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) { @@ -628,7 +626,7 @@ static bool GetSuperPathBase(CFSTR s, UString &res) unsigned fixedSizeStart = 0; unsigned fixedSize = 0; - const wchar_t *superMarker = NULL; + const char *superMarker = NULL; if (IsSuperPath(curDir)) { fixedSize = GetRootPrefixSize_Of_SuperPath(curDir); diff --git a/CPP/Windows/FileName.h b/CPP/Windows/FileName.h index 6f9b6e03..2c9c56db 100644 --- a/CPP/Windows/FileName.h +++ b/CPP/Windows/FileName.h @@ -23,7 +23,7 @@ bool IsAltPathPrefix(CFSTR s) throw(); /* name: */ #if defined(_WIN32) && !defined(UNDER_CE) -extern const wchar_t *kSuperPathPrefix; /* \\?\ */ +extern const char * const kSuperPathPrefix; /* \\?\ */ const unsigned kDevicePathPrefixSize = 4; const unsigned kSuperPathPrefixSize = 4; const unsigned kSuperUncPathPrefixSize = kSuperPathPrefixSize + 4; @@ -42,7 +42,7 @@ unsigned GetNetworkServerPrefixSize(CFSTR s) throw(); bool IsNetworkShareRootPath(CFSTR s) throw(); /* \\?\UNC\SERVER\share or \\SERVER\share or with slash */ -// bool IsDrivePath_SuperAllowed(CFSTR s) throw(); // first chars are drive chars like "a:\" or "\\?\a:\" +bool IsDrivePath_SuperAllowed(CFSTR s) throw(); // first chars are drive chars like "a:\" or "\\?\a:\" bool IsDriveRootPath_SuperAllowed(CFSTR s) throw(); // exact drive root path "a:\" or "\\?\a:\" bool IsDrivePath2(const wchar_t *s) throw(); // first 2 chars are drive chars like "a:" @@ -71,7 +71,7 @@ unsigned GetRootPrefixSize(CFSTR s) throw(); #endif -int FindAltStreamColon(CFSTR path); +int FindAltStreamColon(CFSTR path) throw(); #endif // _WIN32 diff --git a/CPP/Windows/Net.cpp b/CPP/Windows/Net.cpp index 47079f37..14d06d6e 100644 --- a/CPP/Windows/Net.cpp +++ b/CPP/Windows/Net.cpp @@ -364,8 +364,8 @@ DWORD AddConnection2(const CResourceW &resource, LPCWSTR password, LPCWSTR userN } CResource resourceA; ConvertResourceWToResource(resource, resourceA); - CSysString passwordA = GetSystemString(password); - CSysString userNameA = GetSystemString(userName); + const CSysString passwordA (GetSystemString(password)); + const CSysString userNameA (GetSystemString(userName)); return AddConnection2(resourceA, password ? (LPCTSTR)passwordA: 0, userName ? (LPCTSTR)userNameA: 0, diff --git a/CPP/Windows/ProcessUtils.cpp b/CPP/Windows/ProcessUtils.cpp index 9b833e54..f7878d51 100644 --- a/CPP/Windows/ProcessUtils.cpp +++ b/CPP/Windows/ProcessUtils.cpp @@ -15,9 +15,9 @@ namespace NWindows { #ifndef UNDER_CE static UString GetQuotedString(const UString &s) { - UString s2 = L'\"'; + UString s2 ('\"'); s2 += s; - s2 += L'\"'; + s2 += '\"'; return s2; } #endif diff --git a/CPP/Windows/PropVariant.cpp b/CPP/Windows/PropVariant.cpp index e95cbd2b..c4ad3acb 100644 --- a/CPP/Windows/PropVariant.cpp +++ b/CPP/Windows/PropVariant.cpp @@ -91,7 +91,7 @@ CPropVariant& CPropVariant::operator=(BSTR bstrSrc) return *this; } -static const char *kMemException = "out of memory"; +static const char * const kMemException = "out of memory"; CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) { diff --git a/CPP/Windows/PropVariant.h b/CPP/Windows/PropVariant.h index 3610d6a8..58e8a0c6 100644 --- a/CPP/Windows/PropVariant.h +++ b/CPP/Windows/PropVariant.h @@ -80,6 +80,8 @@ public: CPropVariant& operator=(const UString &s); CPropVariant& operator=(const UString2 &s); CPropVariant& operator=(const char *s); + CPropVariant& operator=(const AString &s) + { return (*this)=(const char *)s; } CPropVariant& operator=(bool bSrc) throw(); CPropVariant& operator=(Byte value) throw(); diff --git a/CPP/Windows/PropVariantConv.cpp b/CPP/Windows/PropVariantConv.cpp index fe86f936..65aa9f7e 100644 --- a/CPP/Windows/PropVariantConv.cpp +++ b/CPP/Windows/PropVariantConv.cpp @@ -9,21 +9,24 @@ #define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; } -bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds) throw() +bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw() { + *s = 0; + FILETIME ft; + if (!FileTimeToLocalFileTime(&utc, &ft)) + return false; + SYSTEMTIME st; if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) - { - *s = 0; return false; - } - unsigned val = st.wYear; - if (val >= 10000) - { - *s++ = (char)('0' + val / 10000); - val %= 10000; - } + { + unsigned val = st.wYear; + if (val >= 10000) + { + *s++ = (char)('0' + val / 10000); + val %= 10000; + } s[3] = (char)('0' + val % 10); val /= 10; s[2] = (char)('0' + val % 10); val /= 10; s[1] = (char)('0' + val % 10); @@ -32,40 +35,66 @@ bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool } UINT_TO_STR_2('-', st.wMonth); UINT_TO_STR_2('-', st.wDay); - if (includeTime) + + if (level > kTimestampPrintLevel_DAY) { UINT_TO_STR_2(' ', st.wHour); UINT_TO_STR_2(':', st.wMinute); - if (includeSeconds) + + if (level >= kTimestampPrintLevel_SEC) { UINT_TO_STR_2(':', st.wSecond); - /* - *s++ = '.'; - unsigned val = st.wMilliseconds; - s[2] = (char)('0' + val % 10); val /= 10; - s[1] = (char)('0' + val % 10); - s[0] = (char)('0' + val / 10); - s += 3; - */ + + if (level > kTimestampPrintLevel_SEC) + { + *s++ = '.'; + /* + { + unsigned val = st.wMilliseconds; + s[2] = (char)('0' + val % 10); val /= 10; + s[1] = (char)('0' + val % 10); + s[0] = (char)('0' + val / 10); + s += 3; + } + *s++ = ' '; + */ + + { + unsigned numDigits = 7; + UInt32 val = (UInt32)((((UInt64)ft.dwHighDateTime << 32) + ft.dwLowDateTime) % 10000000); + for (unsigned i = numDigits; i != 0;) + { + i--; + s[i] = (char)('0' + val % 10); val /= 10; + } + if (numDigits > (unsigned)level) + numDigits = (unsigned)level; + s += numDigits; + } + } } } + *s = 0; return true; } -void ConvertFileTimeToString(const FILETIME &ft, wchar_t *dest, bool includeTime, bool includeSeconds) throw() + +bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *dest, int level) throw() { char s[32]; - ConvertFileTimeToString(ft, s, includeTime, includeSeconds); + bool res = ConvertUtcFileTimeToString(ft, s, level); for (unsigned i = 0;; i++) { unsigned char c = s[i]; dest[i] = c; if (c == 0) - return; + break; } + return res; } + void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw() { *dest = 0; @@ -77,7 +106,7 @@ void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw( case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; - case VT_FILETIME: ConvertFileTimeToString(prop.filetime, dest, true, true); return; + case VT_FILETIME: ConvertUtcFileTimeToString(prop.filetime, dest); return; // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; @@ -98,7 +127,7 @@ void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) thr case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; - case VT_FILETIME: ConvertFileTimeToString(prop.filetime, dest, true, true); return; + case VT_FILETIME: ConvertUtcFileTimeToString(prop.filetime, dest); return; // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; diff --git a/CPP/Windows/PropVariantConv.h b/CPP/Windows/PropVariantConv.h index 5d26357f..390e0b89 100644 --- a/CPP/Windows/PropVariantConv.h +++ b/CPP/Windows/PropVariantConv.h @@ -6,8 +6,15 @@ #include "../Common/MyTypes.h" // provide at least 32 bytes for buffer including zero-end -bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true) throw(); -void ConvertFileTimeToString(const FILETIME &ft, wchar_t *s, bool includeTime = true, bool includeSeconds = true) throw(); + +#define kTimestampPrintLevel_DAY -3 +// #define kTimestampPrintLevel_HOUR -2 +#define kTimestampPrintLevel_MIN -1 +#define kTimestampPrintLevel_SEC 0 +#define kTimestampPrintLevel_NTFS 7 + +bool ConvertUtcFileTimeToString(const FILETIME &ft, char *s, int level = kTimestampPrintLevel_SEC) throw(); +bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw(); // provide at least 32 bytes for buffer including zero-end // don't send VT_BSTR to these functions diff --git a/CPP/Windows/PropVariantUtils.cpp b/CPP/Windows/PropVariantUtils.cpp index 7149616b..fab556a5 100644 --- a/CPP/Windows/PropVariantUtils.cpp +++ b/CPP/Windows/PropVariantUtils.cpp @@ -8,27 +8,32 @@ using namespace NWindows; -static AString GetHex(UInt32 v) +static void AddHex(AString &s, UInt32 v) { char sz[16]; sz[0] = '0'; sz[1] = 'x'; ConvertUInt32ToHex(v, sz + 2); - return sz; + s += sz; } + AString TypePairToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 value) { - AString s; + char sz[16]; + const char *p = NULL; for (unsigned i = 0; i < num; i++) { - const CUInt32PCharPair &p = pairs[i]; - if (p.Value == value) - s = p.Name; + const CUInt32PCharPair &pair = pairs[i]; + if (pair.Value == value) + p = pair.Name; } - if (s.IsEmpty()) - s = GetHex(value); - return s; + if (!p) + { + ConvertUInt32ToString(value, sz); + p = sz; + } + return (AString)p; } void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NCOM::CPropVariant &prop) @@ -39,14 +44,30 @@ void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NCOM: AString TypeToString(const char * const table[], unsigned num, UInt32 value) { + char sz[16]; + const char *p = NULL; if (value < num) - return table[value]; - return GetHex(value); + p = table[value]; + if (!p) + { + ConvertUInt32ToString(value, sz); + p = sz; + } + return (AString)p; } -void TypeToProp(const char * const table[], unsigned num, UInt32 value, NCOM::CPropVariant &prop) +void TypeToProp(const char * const table[], unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop) { - prop = TypeToString(table, num, value); + char sz[16]; + const char *p = NULL; + if (value < num) + p = table[value]; + if (!p) + { + ConvertUInt32ToString(value, sz); + p = sz; + } + prop = p; } @@ -59,20 +80,17 @@ AString FlagsToString(const char * const *names, unsigned num, UInt32 flags) if ((flags & flag) != 0) { const char *name = names[i]; - if (name != 0 && name[0] != 0) + if (name && name[0] != 0) { - if (!s.IsEmpty()) - s += ' '; - s += name; + s.Add_OptSpaced(name); flags &= ~flag; } } } if (flags != 0) { - if (!s.IsEmpty()) - s += ' '; - s += GetHex(flags); + s.Add_Space_if_NotEmpty(); + AddHex(s, flags); } return s; } @@ -87,23 +105,23 @@ AString FlagsToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags) if ((flags & flag) != 0) { if (p.Name[0] != 0) - { - if (!s.IsEmpty()) - s += ' '; - s += p.Name; - } + s.Add_OptSpaced(p.Name); } flags &= ~flag; } if (flags != 0) { - if (!s.IsEmpty()) - s += ' '; - s += GetHex(flags); + s.Add_Space_if_NotEmpty(); + AddHex(s, flags); } return s; } +void FlagsToProp(const char * const *names, unsigned num, UInt32 flags, NCOM::CPropVariant &prop) +{ + prop = FlagsToString(names, num, flags); +} + void FlagsToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags, NCOM::CPropVariant &prop) { prop = FlagsToString(pairs, num, flags); @@ -120,24 +138,18 @@ AString Flags64ToString(const CUInt32PCharPair *pairs, unsigned num, UInt64 flag if ((flags & flag) != 0) { if (p.Name[0] != 0) - { - if (!s.IsEmpty()) - s += ' '; - s += p.Name; - } + s.Add_OptSpaced(p.Name); } flags &= ~flag; } if (flags != 0) { - if (!s.IsEmpty()) - s += ' '; { char sz[32]; sz[0] = '0'; sz[1] = 'x'; ConvertUInt64ToHex(flags, sz + 2); - s += sz; + s.Add_OptSpaced(sz); } } return s; diff --git a/CPP/Windows/PropVariantUtils.h b/CPP/Windows/PropVariantUtils.h index 64dfd5a1..3dd8295f 100644 --- a/CPP/Windows/PropVariantUtils.h +++ b/CPP/Windows/PropVariantUtils.h @@ -18,6 +18,7 @@ void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NWind AString FlagsToString(const char * const *names, unsigned num, UInt32 flags); AString FlagsToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags); +void FlagsToProp(const char * const *names, unsigned num, UInt32 flags, NWindows::NCOM::CPropVariant &prop); void FlagsToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags, NWindows::NCOM::CPropVariant &prop); AString TypeToString(const char * const table[], unsigned num, UInt32 value); diff --git a/CPP/Windows/Shell.cpp b/CPP/Windows/Shell.cpp index 8e82c14a..382d774f 100644 --- a/CPP/Windows/Shell.cpp +++ b/CPP/Windows/Shell.cpp @@ -153,8 +153,8 @@ bool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */, MessageBoxW(0, L"yes", L"", 0); */ /* - UString s = L"all files"; - s += L" (*.*)"; + UString s = "all files"; + s += " (*.*)"; return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true); */ return false; diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp index 59cb7c0b..cc33169a 100644 --- a/CPP/Windows/System.cpp +++ b/CPP/Windows/System.cpp @@ -11,12 +11,42 @@ namespace NWindows { namespace NSystem { +UInt32 CountAffinity(DWORD_PTR mask) +{ + UInt32 num = 0; + for (unsigned i = 0; i < sizeof(mask) * 8; i++) + num += (UInt32)((mask >> i) & 1); + return num; +} + #ifdef _WIN32 +BOOL CProcessAffinity::Get() +{ + #ifndef UNDER_CE + return GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask); + #else + return FALSE; + #endif +} + + UInt32 GetNumberOfProcessors() { + // We need to know how many threads we can use. + // By default the process is assigned to one group. + // So we get the number of logical processors (threads) + // assigned to current process in the current group. + // Group size can be smaller than total number logical processors, for exammple, 2x36 + + CProcessAffinity pa; + + if (pa.Get() && pa.processAffinityMask != 0) + return pa.GetNumProcessThreads(); + SYSTEM_INFO systemInfo; GetSystemInfo(&systemInfo); + // the number of logical processors in the current group return (UInt32)systemInfo.dwNumberOfProcessors; } diff --git a/CPP/Windows/System.h b/CPP/Windows/System.h index 910bc7fd..519e0444 100644 --- a/CPP/Windows/System.h +++ b/CPP/Windows/System.h @@ -8,6 +8,29 @@ namespace NWindows { namespace NSystem { +UInt32 CountAffinity(DWORD_PTR mask); + +struct CProcessAffinity +{ + // UInt32 numProcessThreads; + // UInt32 numSysThreads; + DWORD_PTR processAffinityMask; + DWORD_PTR systemAffinityMask; + + void InitST() + { + // numProcessThreads = 1; + // numSysThreads = 1; + processAffinityMask = 1; + systemAffinityMask = 1; + } + + UInt32 GetNumProcessThreads() const { return CountAffinity(processAffinityMask); } + UInt32 GetNumSystemThreads() const { return CountAffinity(systemAffinityMask); } + + BOOL Get(); +}; + UInt32 GetNumberOfProcessors(); bool GetRamSize(UInt64 &size); // returns false, if unknown ram size diff --git a/CPP/Windows/TimeUtils.cpp b/CPP/Windows/TimeUtils.cpp index 7ef44d9c..d288f121 100644 --- a/CPP/Windows/TimeUtils.cpp +++ b/CPP/Windows/TimeUtils.cpp @@ -115,16 +115,26 @@ bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw() return true; } +UInt64 UnixTimeToFileTime64(UInt32 unixTime) throw() +{ + return (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond; +} + void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft) throw() { - UInt64 v = (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond; + UInt64 v = UnixTimeToFileTime64(unixTime); ft.dwLowDateTime = (DWORD)v; ft.dwHighDateTime = (DWORD)(v >> 32); } +UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw() +{ + return (UInt64)(kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond; +} + bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) throw() { - if (unixTime > kNumSecondsInFileTime - kUnixTimeOffset) + if (unixTime > (Int64)(kNumSecondsInFileTime - kUnixTimeOffset)) { ft.dwLowDateTime = ft.dwHighDateTime = (UInt32)(Int32)-1; return false; @@ -144,7 +154,7 @@ bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) throw() Int64 FileTimeToUnixTime64(const FILETIME &ft) throw() { UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; - return (Int64)(winTime / kNumTimeQuantumsInSecond) - kUnixTimeOffset; + return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset; } bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) throw() diff --git a/CPP/Windows/TimeUtils.h b/CPP/Windows/TimeUtils.h index d3033ede..d1d8c150 100644 --- a/CPP/Windows/TimeUtils.h +++ b/CPP/Windows/TimeUtils.h @@ -11,10 +11,18 @@ namespace NTime { bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) throw(); bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) throw(); + +// UInt32 Unix Time : for dates 1970-2106 +UInt64 UnixTimeToFileTime64(UInt32 unixTime) throw(); void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) throw(); + +// Int64 Unix Time : negative values for dates before 1970 +UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw(); bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &fileTime) throw(); + bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) throw(); Int64 FileTimeToUnixTime64(const FILETIME &ft) throw(); + bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw(); void GetCurUtcFileTime(FILETIME &ft) throw(); |