diff options
Diffstat (limited to '')
-rw-r--r-- | CPP/7zip/Archive/Chm/ChmHandler.cpp | 106 |
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(¤tTotalSize)) | 638 | RINOK(extractCallback->SetCompleted(¤tTotalSize)) |
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) |