diff options
Diffstat (limited to 'CPP/7zip/Archive/Cab/CabHandler.cpp')
-rw-r--r-- | CPP/7zip/Archive/Cab/CabHandler.cpp | 99 |
1 files changed, 65 insertions, 34 deletions
diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp index 22bc93a0..4235ec34 100644 --- a/CPP/7zip/Archive/Cab/CabHandler.cpp +++ b/CPP/7zip/Archive/Cab/CabHandler.cpp @@ -71,7 +71,7 @@ static const Byte kArcProps[] = IMP_IInArchive_Props IMP_IInArchive_ArcProps -static const char *kMethods[] = +static const char * const kMethods[] = { "None" , "MSZip" @@ -124,17 +124,19 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) } } } + AString s; + for (unsigned i = 0; i < kNumMethodsMax; i++) { if ((mask & (1 << i)) == 0) continue; - if (!s.IsEmpty()) - s += ' '; + s.Add_Space_if_NotEmpty(); char temp[kMethodNameBufSize]; SetMethodName(temp, i, params[i == NHeader::NMethod::kQuantum ? 0 : 1]); s += temp; } + prop = s; break; } @@ -466,8 +468,8 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, return result; if (!_errorMessage.IsEmpty()) - _errorMessage += L"\n"; - _errorMessage += L"Can't open volume: "; + _errorMessage.Add_LF(); + _errorMessage.AddAscii("Can't open volume: "); _errorMessage += fullName; if (prevChecked) @@ -528,7 +530,7 @@ private: Byte *TempBuf; UInt32 TempBufSize; - int NumIdenticalFiles; + unsigned NumIdenticalFiles; bool TempBufMode; UInt32 m_BufStartFolderOffset; @@ -619,8 +621,9 @@ HRESULT CFolderOutStream::OpenFile() { const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex]; const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; - int numExtractItems = 0; + unsigned numExtractItems = 0; unsigned curIndex; + for (curIndex = m_CurrentIndex; curIndex < m_ExtractStatuses->Size(); curIndex++) { const CMvItem &mvItem2 = m_Database->Items[m_StartIndex + curIndex]; @@ -632,10 +635,12 @@ HRESULT CFolderOutStream::OpenFile() if (!m_TestMode && (*m_ExtractStatuses)[curIndex]) numExtractItems++; } + NumIdenticalFiles = (curIndex - m_CurrentIndex); if (NumIdenticalFiles == 0) NumIdenticalFiles = 1; TempBufMode = false; + if (numExtractItems > 1) { if (!TempBuf || item.Size > TempBufSize) @@ -699,7 +704,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe { COM_TRY_BEGIN UInt32 realProcessed = 0; - if (processedSize != NULL) + if (processedSize) *processedSize = 0; while (size != 0) { @@ -707,7 +712,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe { UInt32 numBytesToWrite = MyMin(m_RemainFileSize, size); HRESULT res = S_OK; - if (numBytesToWrite > 0) + if (numBytesToWrite != 0) { if (!isOK) m_IsOk = false; @@ -721,7 +726,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe memcpy(TempBuf + (m_PosInFolder - m_BufStartFolderOffset), data, numBytesToWrite); } realProcessed += numBytesToWrite; - if (processedSize != NULL) + if (processedSize) *processedSize = realProcessed; data = (const void *)((const Byte *)data + numBytesToWrite); size -= numBytesToWrite; @@ -773,7 +778,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe { UInt32 numBytesToWrite = MyMin(fileOffset - (UInt32)m_PosInFolder, size); realProcessed += numBytesToWrite; - if (processedSize != NULL) + if (processedSize) *processedSize = realProcessed; data = (const void *)((const Byte *)data + numBytesToWrite); size -= numBytesToWrite; @@ -799,24 +804,24 @@ STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *proc HRESULT CFolderOutStream::FlushCorrupted() { - const UInt32 kBufferSize = (1 << 10); - Byte buffer[kBufferSize]; - for (int i = 0; i < kBufferSize; i++) - buffer[i] = 0; + const unsigned kBufSize = (1 << 10); + Byte buf[kBufSize]; + for (unsigned i = 0; i < kBufSize; i++) + buf[i] = 0; for (;;) { UInt64 remain = GetRemain(); if (remain == 0) return S_OK; - UInt32 size = (UInt32)MyMin(remain, (UInt64)kBufferSize); + UInt32 size = (remain < kBufSize ? (UInt32)remain : (UInt32)kBufSize); UInt32 processedSizeLocal = 0; - RINOK(Write2(buffer, size, &processedSizeLocal, false)); + RINOK(Write2(buf, size, &processedSizeLocal, false)); } } HRESULT CFolderOutStream::Unsupported() { - while(m_CurrentIndex < m_ExtractStatuses->Size()) + while (m_CurrentIndex < m_ExtractStatuses->Size()) { HRESULT result = OpenFile(); if (result != S_FALSE && result != S_OK) @@ -844,9 +849,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UInt32 i; int lastFolder = -2; UInt64 lastFolderSize = 0; - for(i = 0; i < numItems; i++) + + for (i = 0; i < numItems; i++) { - int index = allFilesMode ? i : indices[i]; + unsigned index = allFilesMode ? i : indices[i]; const CMvItem &mvItem = m_Database.Items[index]; const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; if (item.IsDir()) @@ -857,6 +863,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, lastFolder = folderIndex; lastFolderSize = item.GetEndOffset(); } + totalUnPacked += lastFolderSize; extractCallback->SetTotal(totalUnPacked); @@ -887,9 +894,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, return E_OUTOFMEMORY; CRecordVector<bool> extractStatuses; - for(i = 0; i < numItems;) + + for (i = 0; i < numItems;) { - int index = allFilesMode ? i : indices[i]; + unsigned index = allFilesMode ? i : indices[i]; const CMvItem &mvItem = m_Database.Items[index]; const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex]; @@ -909,7 +917,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); continue; } + int folderIndex = m_Database.GetFolderIndex(&mvItem); + if (folderIndex < 0) { // If we need previous archive @@ -923,17 +933,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError)); continue; } - int startIndex2 = m_Database.FolderStartFileIndex[folderIndex]; - int startIndex = startIndex2; + + unsigned startIndex2 = m_Database.FolderStartFileIndex[folderIndex]; + unsigned startIndex = startIndex2; extractStatuses.Clear(); for (; startIndex < index; startIndex++) extractStatuses.Add(false); extractStatuses.Add(true); startIndex++; UInt64 curUnpack = item.GetEndOffset(); + for (; i < numItems; i++) { - int indexNext = allFilesMode ? i : indices[i]; + unsigned indexNext = allFilesMode ? i : indices[i]; const CMvItem &mvItem = m_Database.Items[indexNext]; const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; if (item.IsDir()) @@ -963,6 +975,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, cabBlockInStreamSpec->MsZip = false; HRESULT res = S_OK; + switch (folder.GetMethod()) { case NHeader::NMethod::kNone: @@ -1009,7 +1022,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, int locFolderIndex = item.GetFolderIndex(db.Folders.Size()); bool keepHistory = false; bool keepInputBuffer = false; - for (UInt32 f = 0; cabFolderOutStream->GetRemain() != 0;) + + for (UInt32 bl = 0; cabFolderOutStream->GetRemain() != 0;) { if (volIndex >= m_Database.Volumes.Size()) { @@ -1019,19 +1033,32 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, const CDatabaseEx &db = m_Database.Volumes[volIndex]; const CFolder &folder = db.Folders[locFolderIndex]; - if (f == 0) + + if (bl == 0) { cabBlockInStreamSpec->ReservedSize = db.ArcInfo.GetDataBlockReserveSize(); RINOK(db.Stream->Seek(db.StartPosition + folder.DataStart, STREAM_SEEK_SET, NULL)); } - if (f == folder.NumDataBlocks) + + if (bl == folder.NumDataBlocks) { - volIndex++; - locFolderIndex = 0; - f = 0; - continue; + /* + CFolder::NumDataBlocks (CFFOLDER::cCFData in CAB specification) is 16-bit. + But there are some big CAB archives from MS that contain more + than (0xFFFF) CFDATA blocks in folder. + Old cab extracting software can show error (or ask next volume) + but cab extracting library in new Windows ignores this error. + 15.00 : We also try to ignore such error, if archive is not multi-volume. + */ + if (m_Database.Volumes.Size() > 1) + { + volIndex++; + locFolderIndex = 0; + bl = 0; + continue; + } } - f++; + bl++; if (!keepInputBuffer) cabBlockInStreamSpec->InitForNewBlock(); @@ -1059,7 +1086,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, unpackRemain = kBlockSizeMax; if (unpackRemain > unpackSize) unpackRemain = unpackSize; - + switch (folder.GetMethod()) { case NHeader::NMethod::kNone: @@ -1092,14 +1119,17 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, res = quantumDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL); break; } + if (res != S_OK) { if (res != S_FALSE) RINOK(res); break; } + keepHistory = true; } + if (res == S_OK) { RINOK(cabFolderOutStream->WriteEmptyFiles()); @@ -1111,6 +1141,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } totalUnPacked += curUnpack; } + return S_OK; COM_TRY_END } |