aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/Archive/Chm/ChmHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--CPP/7zip/Archive/Chm/ChmHandler.cpp106
1 files changed, 48 insertions, 58 deletions
diff --git a/CPP/7zip/Archive/Chm/ChmHandler.cpp b/CPP/7zip/Archive/Chm/ChmHandler.cpp
index 38e2543..93c3a85 100644
--- a/CPP/7zip/Archive/Chm/ChmHandler.cpp
+++ b/CPP/7zip/Archive/Chm/ChmHandler.cpp
@@ -2,6 +2,7 @@
2 2
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5#include "../../../Common/AutoPtr.h"
5#include "../../../Common/ComTry.h" 6#include "../../../Common/ComTry.h"
6#include "../../../Common/StringConvert.h" 7#include "../../../Common/StringConvert.h"
7#include "../../../Common/UTFConvert.h" 8#include "../../../Common/UTFConvert.h"
@@ -414,21 +415,18 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
414 m_Database.Indices.Size()); 415 m_Database.Indices.Size());
415 if (numItems == 0) 416 if (numItems == 0)
416 return S_OK; 417 return S_OK;
417 bool testMode = (testModeSpec != 0); 418 const bool testMode = (testModeSpec != 0);
418 419
419 UInt64 currentTotalSize = 0; 420 UInt64 currentTotalSize = 0;
420 421
421 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; 422 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
422 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
423 UInt32 i;
424
425 CLocalProgress *lps = new CLocalProgress;
426 CMyComPtr<ICompressProgressInfo> progress = lps;
427 lps->Init(extractCallback, false); 423 lps->Init(extractCallback, false);
428 424
429 CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; 425 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
430 CMyComPtr<ISequentialInStream> inStream(streamSpec); 426 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
431 streamSpec->SetStream(m_Stream); 427 inStream->SetStream(m_Stream);
428
429 UInt32 i;
432 430
433 if (m_Database.LowLevel) 431 if (m_Database.LowLevel)
434 { 432 {
@@ -441,7 +439,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
441 for (i = 0; i < numItems; i++) 439 for (i = 0; i < numItems; i++)
442 totalSize += m_Database.Items[allFilesMode ? i : indices[i]].Size; 440 totalSize += m_Database.Items[allFilesMode ? i : indices[i]].Size;
443 441
444 extractCallback->SetTotal(totalSize); 442 RINOK(extractCallback->SetTotal(totalSize))
445 443
446 for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) 444 for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
447 { 445 {
@@ -465,7 +463,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
465 continue; 463 continue;
466 if (!testMode) 464 if (!testMode)
467 { 465 {
468 UInt32 size = m_Database.NewFormatString.Len(); 466 const unsigned size = m_Database.NewFormatString.Len();
469 RINOK(WriteStream(realOutStream, (const char *)m_Database.NewFormatString, size)) 467 RINOK(WriteStream(realOutStream, (const char *)m_Database.NewFormatString, size))
470 } 468 }
471 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) 469 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
@@ -492,18 +490,18 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
492 } 490 }
493 491
494 RINOK(InStream_SeekSet(m_Stream, m_Database.ContentOffset + item.Offset)) 492 RINOK(InStream_SeekSet(m_Stream, m_Database.ContentOffset + item.Offset))
495 streamSpec->Init(item.Size); 493 inStream->Init(item.Size);
496 494
497 RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)) 495 RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
498 realOutStream.Release(); 496 realOutStream.Release();
499 RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ? 497 RINOK(extractCallback->SetOperationResult((copyCoder->TotalSize == item.Size) ?
500 NExtract::NOperationResult::kOK: 498 NExtract::NOperationResult::kOK:
501 NExtract::NOperationResult::kDataError)) 499 NExtract::NOperationResult::kDataError))
502 } 500 }
503 return S_OK; 501 return S_OK;
504 } 502 }
505 503
506 UInt64 lastFolderIndex = ((UInt64)0 - 1); 504 UInt64 lastFolderIndex = (UInt64)0 - 1;
507 505
508 for (i = 0; i < numItems; i++) 506 for (i = 0; i < numItems; i++)
509 { 507 {
@@ -536,10 +534,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
536 534
537 RINOK(extractCallback->SetTotal(currentTotalSize)) 535 RINOK(extractCallback->SetTotal(currentTotalSize))
538 536
539 NCompress::NLzx::CDecoder *lzxDecoderSpec = NULL; 537 CMyUniquePtr<NCompress::NLzx::CDecoder> lzxDecoder;
540 CMyComPtr<IUnknown> lzxDecoder; 538 CMyComPtr2_Create<ISequentialOutStream, CChmFolderOutStream> chmFolderOutStream;
541 CChmFolderOutStream *chmFolderOutStream = NULL;
542 CMyComPtr<ISequentialOutStream> outStream;
543 539
544 currentTotalSize = 0; 540 currentTotalSize = 0;
545 541
@@ -558,7 +554,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
558 i++; 554 i++;
559 const CItem &item = m_Database.Items[m_Database.Indices[index]]; 555 const CItem &item = m_Database.Items[m_Database.Indices[index]];
560 const UInt64 sectionIndex = item.Section; 556 const UInt64 sectionIndex = item.Section;
561 Int32 askMode= testMode ? 557 const Int32 askMode= testMode ?
562 NExtract::NAskMode::kTest : 558 NExtract::NAskMode::kTest :
563 NExtract::NAskMode::kExtract; 559 NExtract::NAskMode::kExtract;
564 560
@@ -586,9 +582,9 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
586 if (!testMode && item.Size != 0) 582 if (!testMode && item.Size != 0)
587 { 583 {
588 RINOK(InStream_SeekSet(m_Stream, m_Database.ContentOffset + item.Offset)) 584 RINOK(InStream_SeekSet(m_Stream, m_Database.ContentOffset + item.Offset))
589 streamSpec->Init(item.Size); 585 inStream->Init(item.Size);
590 RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)) 586 RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
591 if (copyCoderSpec->TotalSize != item.Size) 587 if (copyCoder->TotalSize != item.Size)
592 opRes = NExtract::NOperationResult::kDataError; 588 opRes = NExtract::NOperationResult::kDataError;
593 } 589 }
594 realOutStream.Release(); 590 realOutStream.Release();
@@ -624,24 +620,14 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
624 620
625 const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo; 621 const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;
626 622
627 if (!chmFolderOutStream)
628 {
629 chmFolderOutStream = new CChmFolderOutStream;
630 outStream = chmFolderOutStream;
631 }
632
633 chmFolderOutStream->Init(&m_Database, extractCallback, testMode); 623 chmFolderOutStream->Init(&m_Database, extractCallback, testMode);
634 624
635 if (!lzxDecoderSpec) 625 lzxDecoder.Create_if_Empty();
636 {
637 lzxDecoderSpec = new NCompress::NLzx::CDecoder;
638 lzxDecoder = lzxDecoderSpec;
639 }
640 626
641 UInt64 folderIndex = m_Database.GetFolder(index); 627 UInt64 folderIndex = m_Database.GetFolder(index);
642 628
643 const UInt64 compressedPos = m_Database.ContentOffset + section.Offset; 629 const UInt64 compressedPos = m_Database.ContentOffset + section.Offset;
644 RINOK(lzxDecoderSpec->SetParams_and_Alloc(lzxInfo.GetNumDictBits())) 630 RINOK(lzxDecoder->Set_DictBits_and_Alloc(lzxInfo.GetNumDictBits()))
645 631
646 const CItem *lastItem = &item; 632 const CItem *lastItem = &item;
647 extractStatuses.Clear(); 633 extractStatuses.Clear();
@@ -651,12 +637,12 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
651 { 637 {
652 RINOK(extractCallback->SetCompleted(&currentTotalSize)) 638 RINOK(extractCallback->SetCompleted(&currentTotalSize))
653 639
654 UInt64 startPos = lzxInfo.GetFolderPos(folderIndex); 640 const UInt64 startPos = lzxInfo.GetFolderPos(folderIndex);
655 UInt64 finishPos = lastItem->Offset + lastItem->Size; 641 UInt64 finishPos = lastItem->Offset + lastItem->Size;
656 UInt64 limitFolderIndex = lzxInfo.GetFolder(finishPos); 642 const UInt64 limitFolderIndex = lzxInfo.GetFolder(finishPos);
657 643
658 lastFolderIndex = m_Database.GetLastFolder(index); 644 lastFolderIndex = m_Database.GetLastFolder(index);
659 UInt64 folderSize = lzxInfo.GetFolderSize(); 645 const UInt64 folderSize = lzxInfo.GetFolderSize();
660 UInt64 unPackSize = folderSize; 646 UInt64 unPackSize = folderSize;
661 647
662 if (extractStatuses.IsEmpty()) 648 if (extractStatuses.IsEmpty())
@@ -697,9 +683,9 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
697 683
698 try 684 try
699 { 685 {
700 UInt64 startBlock = lzxInfo.GetBlockIndexFromFolderIndex(folderIndex); 686 const UInt64 startBlock = lzxInfo.GetBlockIndexFromFolderIndex(folderIndex);
701 const CResetTable &rt = lzxInfo.ResetTable; 687 const CResetTable &rt = lzxInfo.ResetTable;
702 UInt32 numBlocks = (UInt32)rt.GetNumBlocks(unPackSize); 688 const UInt32 numBlocks = (UInt32)rt.GetNumBlocks(unPackSize);
703 689
704 for (UInt32 b = 0; b < numBlocks; b++) 690 for (UInt32 b = 0; b < numBlocks; b++)
705 { 691 {
@@ -708,33 +694,37 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
708 UInt64 bCur = startBlock + b; 694 UInt64 bCur = startBlock + b;
709 if (bCur >= rt.ResetOffsets.Size()) 695 if (bCur >= rt.ResetOffsets.Size())
710 return E_FAIL; 696 return E_FAIL;
711 UInt64 offset = rt.ResetOffsets[(unsigned)bCur]; 697 const UInt64 offset = rt.ResetOffsets[(unsigned)bCur];
712 UInt64 compressedSize; 698 UInt64 compressedSize;
713 rt.GetCompressedSizeOfBlock(bCur, compressedSize); 699 rt.GetCompressedSizeOfBlock(bCur, compressedSize);
714 700
715 // chm writes full blocks. So we don't need to use reduced size for last block 701 // chm writes full blocks. So we don't need to use reduced size for last block
716 702
717 RINOK(InStream_SeekSet(m_Stream, compressedPos + offset)) 703 RINOK(InStream_SeekSet(m_Stream, compressedPos + offset))
718 streamSpec->SetStream(m_Stream); 704 inStream->Init(compressedSize);
719 streamSpec->Init(compressedSize);
720 705
721 lzxDecoderSpec->SetKeepHistory(b > 0); 706 lzxDecoder->Set_KeepHistory(b > 0);
722 707
723 size_t compressedSizeT = (size_t)compressedSize; 708 HRESULT res = S_FALSE;
724 if (compressedSizeT != compressedSize) 709 if (compressedSize <= (1u << 30))
725 throw 2;
726 packBuf.AllocAtLeast(compressedSizeT);
727
728 HRESULT res = ReadStream_FALSE(inStream, packBuf, compressedSizeT);
729
730 if (res == S_OK)
731 { 710 {
732 lzxDecoderSpec->KeepHistoryForNext = true; 711 const unsigned kAdditionalInputSize = 32;
733 res = lzxDecoderSpec->Code(packBuf, compressedSizeT, kBlockSize); // rt.BlockSize; 712 const size_t compressedSizeT = (size_t)compressedSize;
713 const size_t allocSize = compressedSizeT + kAdditionalInputSize;
714 if (allocSize <= compressedSize)
715 throw 2;
716 packBuf.AllocAtLeast(allocSize);
717 res = ReadStream_FALSE(inStream, packBuf, compressedSizeT);
734 if (res == S_OK) 718 if (res == S_OK)
735 res = WriteStream(chmFolderOutStream, 719 {
736 lzxDecoderSpec->GetUnpackData(), 720 memset(packBuf + compressedSizeT, 0xff, kAdditionalInputSize);
737 lzxDecoderSpec->GetUnpackSize()); 721 lzxDecoder->Set_KeepHistoryForNext(true);
722 res = lzxDecoder->Code_WithExceedReadWrite(packBuf, compressedSizeT, kBlockSize); // rt.BlockSize;
723 if (res == S_OK)
724 res = WriteStream(chmFolderOutStream,
725 lzxDecoder->GetUnpackData(),
726 lzxDecoder->GetUnpackSize());
727 }
738 } 728 }
739 729
740 if (res != S_OK) 730 if (res != S_OK)