From d66cf2fcf3cc3667f76f1ea50e8360f1c2813753 Mon Sep 17 00:00:00 2001 From: Igor Pavlov Date: Wed, 21 Sep 2005 00:00:00 +0000 Subject: [PATCH] 4.27 beta --- 7zip/Archive/7z/7z.dsp | 8 + 7zip/Archive/7z/7zDecode.cpp | 8 +- 7zip/Archive/7z/7zExtract.cpp | 8 +- 7zip/Archive/7z/7zFolderInStream.cpp | 22 +- 7zip/Archive/7z/7zFolderInStream.h | 1 - 7zip/Archive/7z/7zFolderOutStream.cpp | 9 +- 7zip/Archive/7z/7zFolderOutStream.h | 1 - 7zip/Archive/7z/7zHandler.h | 4 +- 7zip/Archive/7z/7zIn.cpp | 11 +- 7zip/Archive/7z/7zOut.cpp | 11 +- 7zip/Archive/7z/7zSpecStream.cpp | 10 - 7zip/Archive/7z/7zSpecStream.h | 1 - 7zip/Archive/7z/7zUpdate.cpp | 116 +- 7zip/Archive/7z/7zUpdate.h | 2 +- 7zip/Archive/7z/makefile | 1 + 7zip/Archive/7z_C/makefile.gcc | 50 + 7zip/Archive/Arj/Arj.dsp | 24 +- 7zip/Archive/Arj/ArjHandler.cpp | 4 +- 7zip/Archive/Arj/ArjIn.cpp | 6 +- 7zip/Archive/Arj/DllExports.cpp | 4 +- 7zip/Archive/Arj/makefile | 6 +- 7zip/Archive/BZip2/BZip2.dsp | 8 + 7zip/Archive/BZip2/BZip2Handler.cpp | 6 +- 7zip/Archive/BZip2/DllExports.cpp | 4 +- 7zip/Archive/BZip2/makefile | 1 + 7zip/Archive/Cab/Cab.dsp | 174 ++- 7zip/Archive/Cab/CabBlockInStream.cpp | 194 +++ 7zip/Archive/Cab/CabBlockInStream.h | 56 + 7zip/Archive/Cab/CabCopyDecoder.cpp | 73 -- 7zip/Archive/Cab/CabCopyDecoder.h | 41 - 7zip/Archive/Cab/CabHandler.cpp | 802 ++++++++----- 7zip/Archive/Cab/CabHandler.h | 5 +- 7zip/Archive/Cab/CabHeader.h | 79 +- 7zip/Archive/Cab/CabIn.cpp | 346 ++++-- 7zip/Archive/Cab/CabIn.h | 133 ++- 7zip/Archive/Cab/CabInBuffer.cpp | 175 --- 7zip/Archive/Cab/CabInBuffer.h | 66 -- 7zip/Archive/Cab/CabItem.h | 54 +- 7zip/Archive/Cab/DllExports.cpp | 6 +- 7zip/Archive/Cab/LZXBitDecoder.h | 111 -- 7zip/Archive/Cab/LZXConst.h | 110 -- 7zip/Archive/Cab/LZXDecoder.cpp | 310 ----- 7zip/Archive/Cab/LZXDecoder.h | 95 -- 7zip/Archive/Cab/LZXExtConst.h | 30 - 7zip/Archive/Cab/MSZipConst.h | 92 -- 7zip/Archive/Cab/MSZipDecoder.cpp | 268 ----- 7zip/Archive/Cab/MSZipDecoder.h | 85 -- 7zip/Archive/Cab/MSZipExtConst.h | 20 - 7zip/Archive/Cab/makefile | 24 +- 7zip/Archive/Chm/Chm.dsp | 337 ++++++ 7zip/Archive/Chm/Chm.dsw | 29 + 7zip/Archive/Chm/ChmHandler.cpp | 729 ++++++++++++ 7zip/Archive/Chm/ChmHandler.h | 46 + 7zip/Archive/Chm/ChmHeader.cpp | 24 + 7zip/Archive/Chm/ChmHeader.h | 28 + 7zip/Archive/Chm/ChmIn.cpp | 924 +++++++++++++++ 7zip/Archive/Chm/ChmIn.h | 242 ++++ 7zip/Archive/Chm/DllExports.cpp | 77 ++ 7zip/Archive/Chm/StdAfx.cpp | 3 + 7zip/Archive/Chm/StdAfx.h | 8 + 7zip/Archive/Chm/makefile | 68 ++ 7zip/Archive/Chm/resource.rc | 3 + 7zip/Archive/Common/DummyOutStream.cpp | 10 - 7zip/Archive/Common/DummyOutStream.h | 1 - 7zip/Archive/Common/FilterCoder.cpp | 26 +- 7zip/Archive/Common/FilterCoder.h | 2 - 7zip/Archive/Common/InStreamWithCRC.cpp | 24 - 7zip/Archive/Common/InStreamWithCRC.h | 2 - 7zip/Archive/Common/MultiStream.cpp | 16 +- 7zip/Archive/Common/MultiStream.h | 2 - 7zip/Archive/Common/OutStreamWithCRC.cpp | 20 +- 7zip/Archive/Common/OutStreamWithCRC.h | 1 - 7zip/Archive/Cpio/makefile | 2 + 7zip/Archive/Deb/Deb.dsp | 16 + 7zip/Archive/Deb/DebIn.cpp | 84 +- 7zip/Archive/Deb/DllExports.cpp | 4 +- 7zip/Archive/Deb/makefile | 2 + 7zip/Archive/GZip/DllExports.cpp | 4 +- 7zip/Archive/GZip/GZip.dsp | 8 + 7zip/Archive/GZip/GZipHandler.cpp | 8 +- 7zip/Archive/GZip/GZipIn.cpp | 4 +- 7zip/Archive/GZip/GZipOut.cpp | 3 +- 7zip/Archive/GZip/makefile | 1 + 7zip/Archive/IArchive.h | 94 +- 7zip/Archive/Lzh/DllExports.cpp | 4 +- 7zip/Archive/Lzh/Lzh.dsp | 16 + 7zip/Archive/Lzh/LzhIn.cpp | 6 +- 7zip/Archive/Lzh/LzhItem.h | 7 + 7zip/Archive/Lzh/LzhOutStreamWithCRC.cpp | 23 +- 7zip/Archive/Lzh/LzhOutStreamWithCRC.h | 1 - 7zip/Archive/Lzh/makefile | 2 + 7zip/Archive/RPM/DllExports.cpp | 4 +- 7zip/Archive/RPM/Rpm.dsp | 8 + 7zip/Archive/RPM/RpmIn.cpp | 6 +- 7zip/Archive/RPM/makefile | 1 + 7zip/Archive/Rar/DllExports.cpp | 4 +- 7zip/Archive/Rar/Rar.dsp | 16 + 7zip/Archive/Rar/RarHandler.cpp | 7 +- 7zip/Archive/Rar/RarHeader.h | 13 + 7zip/Archive/Rar/RarIn.cpp | 56 +- 7zip/Archive/Rar/RarIn.h | 3 +- 7zip/Archive/Rar/RarVolumeInStream.cpp | 8 +- 7zip/Archive/Rar/RarVolumeInStream.h | 1 - 7zip/Archive/Rar/makefile | 2 + 7zip/Archive/Split/DllExports.cpp | 4 +- 7zip/Archive/Split/Split.dsp | 10 +- 7zip/Archive/Split/makefile | 1 + 7zip/Archive/Tar/DllExports.cpp | 4 +- 7zip/Archive/Tar/Tar.dsp | 16 + 7zip/Archive/Tar/TarHeader.cpp | 2 +- 7zip/Archive/Tar/TarHeader.h | 4 +- 7zip/Archive/Tar/TarIn.cpp | 74 +- 7zip/Archive/Tar/TarItem.h | 8 + 7zip/Archive/Tar/TarOut.cpp | 14 +- 7zip/Archive/Tar/makefile | 2 + 7zip/Archive/Z/DllExports.cpp | 8 +- 7zip/Archive/Z/Z.dsp | 8 + 7zip/Archive/Z/ZHandler.cpp | 3 +- 7zip/Archive/Z/makefile | 1 + 7zip/Archive/Zip/Zip.dsp | 8 + 7zip/Archive/Zip/ZipHandler.cpp | 3 + 7zip/Archive/Zip/ZipHeader.h | 3 +- 7zip/Archive/Zip/ZipIn.cpp | 9 +- 7zip/Archive/Zip/ZipOut.cpp | 3 +- 7zip/Archive/Zip/makefile | 1 + 7zip/Archive/cpio/CpioIn.cpp | 53 +- 7zip/Archive/cpio/DllExports.cpp | 4 +- 7zip/Archive/cpio/cpio.dsp | 16 + 7zip/Archive/makefile | 1 + 7zip/Bundles/Alone/Alone.dsp | 8 + 7zip/Bundles/Alone/makefile | 1 + 7zip/Bundles/Format7z/Format7z.dsp | 12 +- 7zip/Bundles/Format7z/makefile | 1 + 7zip/Bundles/Format7zExtract/Format7z.dsp | 12 +- 7zip/Bundles/Format7zExtract/makefile | 1 + 7zip/Bundles/SFXCon/SFXCon.dsp | 8 + 7zip/Bundles/SFXCon/makefile | 1 + 7zip/Bundles/SFXSetup/SFXSetup.dsp | 8 + 7zip/Bundles/SFXSetup/makefile | 1 + 7zip/Bundles/SFXWin/SFXWin.dsp | 8 + 7zip/Bundles/SFXWin/makefile | 1 + 7zip/Common/FileStreams.cpp | 29 +- 7zip/Common/FileStreams.h | 4 - 7zip/Common/InBuffer.cpp | 9 +- 7zip/Common/InBuffer.h | 10 +- 7zip/Common/InOutTempBuffer.cpp | 35 +- 7zip/Common/InOutTempBuffer.h | 2 - 7zip/Common/LSBFDecoder.h | 16 +- 7zip/Common/LimitedStreams.cpp | 14 +- 7zip/Common/LimitedStreams.h | 1 - 7zip/Common/LockedStream.cpp | 21 +- 7zip/Common/LockedStream.h | 2 - 7zip/Common/MSBFDecoder.h | 5 +- 7zip/Common/OffsetStream.cpp | 8 +- 7zip/Common/OffsetStream.h | 1 - 7zip/Common/OutBuffer.cpp | 77 +- 7zip/Common/OutBuffer.h | 30 +- 7zip/Common/StreamBinder.cpp | 38 +- 7zip/Common/StreamBinder.h | 6 +- 7zip/Common/StreamObjects.cpp | 100 +- 7zip/Common/StreamObjects.h | 66 +- 7zip/Common/StreamUtils.cpp | 44 + 7zip/Common/StreamUtils.h | 11 + .../Arj/{Decoder1.cpp => ArjDecoder1.cpp} | 2 +- .../Arj/{Decoder1.h => ArjDecoder1.h} | 0 .../Arj/{Decoder2.cpp => ArjDecoder2.cpp} | 2 +- .../Arj/{Decoder2.h => ArjDecoder2.h} | 0 7zip/Compress/BZip2/BZip2CRC.cpp | 2 +- 7zip/Compress/BZip2/BZip2Decoder.cpp | 20 +- 7zip/Compress/Branch/x86_2.cpp | 15 +- 7zip/Compress/Copy/Copy.dsp | 12 + 7zip/Compress/Copy/CopyCoder.cpp | 5 +- 7zip/Compress/Copy/makefile | 6 + 7zip/Compress/Deflate/DeflateDecoder.cpp | 408 ++++--- 7zip/Compress/Deflate/DeflateDecoder.h | 88 +- 7zip/Compress/Huffman/HuffmanDecoder.h | 125 +- 7zip/Compress/Implode/ImplodeDecoder.cpp | 48 +- 7zip/Compress/Implode/ImplodeDecoder.h | 5 +- .../Implode/ImplodeHuffmanDecoder.cpp | 11 +- 7zip/Compress/Implode/ImplodeHuffmanDecoder.h | 3 +- 7zip/Compress/LZ/LZInWindow.cpp | 2 +- 7zip/Compress/LZ/LZOutWindow.cpp | 74 +- 7zip/Compress/LZ/LZOutWindow.h | 47 +- 7zip/Compress/LZMA/LZMA.dsp | 8 + 7zip/Compress/LZMA/LZMADecoder.cpp | 162 ++- 7zip/Compress/LZMA/LZMADecoder.h | 23 +- 7zip/Compress/LZMA/LZMAEncoder.cpp | 3 +- 7zip/Compress/LZMA/makefile | 1 + 7zip/Compress/LZMA_Alone/AloneLZMA.dsp | 8 + 7zip/Compress/LZMA_Alone/LzmaAlone.cpp | 27 +- 7zip/Compress/LZMA_Alone/LzmaBench.cpp | 20 - 7zip/Compress/LZMA_Alone/LzmaRam.cpp | 14 - 7zip/Compress/LZMA_Alone/makefile | 7 +- 7zip/Compress/LZMA_C/LzmaDecodeSize.c | 31 +- 7zip/Compress/LZMA_C/LzmaTest.c | 10 +- 7zip/Compress/Lzx/Lzx.h | 61 + .../Lzx/Lzx86Converter.cpp} | 63 +- .../Lzx/Lzx86Converter.h} | 37 +- 7zip/Compress/Lzx/LzxDecoder.cpp | 382 ++++++ 7zip/Compress/Lzx/LzxDecoder.h | 181 +++ 7zip/Compress/Lzx/StdAfx.h | 8 + 7zip/Compress/PPMD/PPMD.dsp | 8 + 7zip/Compress/PPMD/PPMDContext.h | 153 ++- 7zip/Compress/PPMD/PPMDDecode.h | 12 +- 7zip/Compress/PPMD/PPMDDecoder.cpp | 166 ++- 7zip/Compress/PPMD/PPMDDecoder.h | 35 +- 7zip/Compress/PPMD/PPMDEncode.h | 12 +- 7zip/Compress/PPMD/PPMDEncoder.cpp | 99 +- 7zip/Compress/PPMD/PPMDEncoder.h | 31 +- 7zip/Compress/PPMD/PPMDSubAlloc.h | 151 ++- 7zip/Compress/PPMD/PPMDType.h | 6 - 7zip/Compress/PPMD/makefile | 1 + 7zip/Compress/Quantum/QuantumDecoder.cpp | 174 +++ 7zip/Compress/Quantum/QuantumDecoder.h | 287 +++++ 7zip/Compress/Rar20/DllExports.cpp | 66 ++ 7zip/Compress/Rar20/Rar20Const.h | 65 + 7zip/Compress/Rar20/Rar20Decoder.cpp | 319 +++++ 7zip/Compress/Rar20/Rar20Decoder.h | 95 ++ 7zip/Compress/Rar20/Rar20ExtConst.h | 21 + 7zip/Compress/Rar20/Rar20Multimedia.cpp | 128 ++ 7zip/Compress/Rar20/Rar20Multimedia.h | 43 + 7zip/Compress/Rar20/StdAfx.cpp | 3 + 7zip/Compress/Rar20/StdAfx.h | 8 + 7zip/Compress/Rar29/DllExports.cpp | 105 ++ 7zip/Compress/Rar29/Original/archive.hpp | 128 ++ 7zip/Compress/Rar29/Original/array.hpp | 121 ++ 7zip/Compress/Rar29/Original/cmddata.hpp | 56 + 7zip/Compress/Rar29/Original/coder.cpp | 47 + 7zip/Compress/Rar29/Original/coder.hpp | 24 + 7zip/Compress/Rar29/Original/compress.hpp | 36 + 7zip/Compress/Rar29/Original/consio.hpp | 42 + 7zip/Compress/Rar29/Original/crc.cpp | 61 + 7zip/Compress/Rar29/Original/crc.hpp | 10 + 7zip/Compress/Rar29/Original/crypt.hpp | 60 + 7zip/Compress/Rar29/Original/encname.hpp | 20 + 7zip/Compress/Rar29/Original/errhnd.cpp | 356 ++++++ 7zip/Compress/Rar29/Original/errhnd.hpp | 61 + 7zip/Compress/Rar29/Original/extinfo.hpp | 8 + 7zip/Compress/Rar29/Original/extract.hpp | 40 + 7zip/Compress/Rar29/Original/filcreat.hpp | 12 + 7zip/Compress/Rar29/Original/file.hpp | 100 ++ 7zip/Compress/Rar29/Original/filefn.hpp | 39 + 7zip/Compress/Rar29/Original/filestr.hpp | 8 + 7zip/Compress/Rar29/Original/find.hpp | 48 + 7zip/Compress/Rar29/Original/getbits.cpp | 24 + 7zip/Compress/Rar29/Original/getbits.hpp | 37 + 7zip/Compress/Rar29/Original/global.hpp | 14 + 7zip/Compress/Rar29/Original/headers.hpp | 304 +++++ 7zip/Compress/Rar29/Original/int64.cpp | 274 +++++ 7zip/Compress/Rar29/Original/int64.hpp | 86 ++ 7zip/Compress/Rar29/Original/isnt.hpp | 6 + 7zip/Compress/Rar29/Original/list.hpp | 6 + 7zip/Compress/Rar29/Original/loclang.hpp | 340 ++++++ 7zip/Compress/Rar29/Original/log.hpp | 18 + 7zip/Compress/Rar29/Original/match.hpp | 16 + 7zip/Compress/Rar29/Original/model.cpp | 600 ++++++++++ 7zip/Compress/Rar29/Original/model.hpp | 126 ++ 7zip/Compress/Rar29/Original/options.hpp | 129 ++ 7zip/Compress/Rar29/Original/os.hpp | 235 ++++ 7zip/Compress/Rar29/Original/pathfn.hpp | 44 + 7zip/Compress/Rar29/Original/rar.hpp | 80 ++ 7zip/Compress/Rar29/Original/rardefs.hpp | 21 + 7zip/Compress/Rar29/Original/rarfn.hpp | 7 + 7zip/Compress/Rar29/Original/rarlang.hpp | 10 + 7zip/Compress/Rar29/Original/raros.hpp | 41 + 7zip/Compress/Rar29/Original/rartypes.hpp | 21 + 7zip/Compress/Rar29/Original/rarvm.cpp | 1050 +++++++++++++++++ 7zip/Compress/Rar29/Original/rarvm.hpp | 110 ++ 7zip/Compress/Rar29/Original/rarvmtbl.cpp | 53 + 7zip/Compress/Rar29/Original/rawread.hpp | 32 + 7zip/Compress/Rar29/Original/rdwrfn.cpp | 306 +++++ 7zip/Compress/Rar29/Original/rdwrfn.hpp | 104 ++ 7zip/Compress/Rar29/Original/recvol.hpp | 16 + 7zip/Compress/Rar29/Original/resource.cpp | 12 + 7zip/Compress/Rar29/Original/resource.hpp | 14 + 7zip/Compress/Rar29/Original/rijndael.hpp | 37 + 7zip/Compress/Rar29/Original/rs.hpp | 32 + 7zip/Compress/Rar29/Original/savepos.hpp | 15 + 7zip/Compress/Rar29/Original/scantree.hpp | 52 + 7zip/Compress/Rar29/Original/sha1.hpp | 16 + 7zip/Compress/Rar29/Original/smallfn.cpp | 17 + 7zip/Compress/Rar29/Original/smallfn.hpp | 7 + 7zip/Compress/Rar29/Original/strfn.hpp | 24 + 7zip/Compress/Rar29/Original/strlist.hpp | 39 + 7zip/Compress/Rar29/Original/suballoc.cpp | 241 ++++ 7zip/Compress/Rar29/Original/suballoc.hpp | 81 ++ 7zip/Compress/Rar29/Original/system.cpp | 79 ++ 7zip/Compress/Rar29/Original/system.hpp | 10 + 7zip/Compress/Rar29/Original/timefn.hpp | 57 + 7zip/Compress/Rar29/Original/ulinks.hpp | 9 + 7zip/Compress/Rar29/Original/unicode.hpp | 82 ++ 7zip/Compress/Rar29/Original/unpack.cpp | 939 +++++++++++++++ 7zip/Compress/Rar29/Original/unpack.hpp | 205 ++++ 7zip/Compress/Rar29/Original/unpack15.cpp | 507 ++++++++ 7zip/Compress/Rar29/Original/version.hpp | 6 + 7zip/Compress/Rar29/Original/volume.hpp | 11 + 7zip/Compress/Rar29/Rar29.dsp | 415 +++++++ 7zip/Compress/Rar29/Rar29.dsw | 29 + 7zip/Compress/Rar29/Rar29Decoder.cpp | 153 +++ 7zip/Compress/Rar29/Rar29Decoder.h | 97 ++ 7zip/Compress/Rar29/StdAfx.cpp | 3 + 7zip/Compress/Rar29/StdAfx.h | 8 + 7zip/Compress/Rar29/makefile | 62 + 7zip/Compress/Rar29/resource.rc | 3 + 7zip/Crypto/7zAES/7zAES.cpp | 5 +- 7zip/Crypto/7zAES/7zAES.dsp | 8 + 7zip/Crypto/7zAES/makefile | 1 + 7zip/Crypto/RarAES/RarAES.cpp | 22 +- 7zip/Crypto/RarAES/RarAES.h | 3 + 7zip/Crypto/RarAES/sha1.cpp | 35 +- 7zip/Crypto/RarAES/sha1.h | 11 +- 7zip/Crypto/Zip/ZipCipher.cpp | 6 +- 7zip/FileManager/App.cpp | 3 +- 7zip/FileManager/App.h | 4 +- 7zip/FileManager/FSFolder.cpp | 34 + 7zip/FileManager/FSFolder.h | 4 + 7zip/FileManager/IFolder.h | 239 ++-- 7zip/FileManager/MyLoadMenu.cpp | 5 +- 7zip/FileManager/OptionsDialog.cpp | 3 + 7zip/FileManager/Panel.cpp | 2 +- 7zip/FileManager/Panel.h | 13 +- 7zip/FileManager/PanelFolderChange.cpp | 8 +- 7zip/FileManager/PanelItems.cpp | 75 +- 7zip/FileManager/PanelKey.cpp | 3 +- 7zip/FileManager/PanelListNotify.cpp | 11 +- 7zip/FileManager/PanelMenu.cpp | 3 +- 7zip/FileManager/PanelOperations.cpp | 70 +- 7zip/FileManager/PanelSelect.cpp | 21 + .../BenchmarkDialog/BenchmarkDialog.cpp | 18 - 7zip/FileManager/StringUtils.cpp | 3 +- 7zip/FileManager/TextPairs.cpp | 18 +- 7zip/FileManager/resource.h | 1 + 7zip/FileManager/resource.rc | 1 + 7zip/Guid.txt | 152 +++ 7zip/ICoder.h | 110 +- 7zip/IPassword.h | 34 +- 7zip/IProgress.h | 1 - 7zip/IStream.h | 91 +- 7zip/MyVersion.h | 8 +- 7zip/UI/Agent/AgentOut.cpp | 5 +- 7zip/UI/Agent/AgentProxy.cpp | 3 +- 7zip/UI/Agent/ArchiveFolderOpen.cpp | 11 +- 7zip/UI/Client7z/Client7z.cpp | 4 +- 7zip/UI/Common/ArchiveCommandLine.cpp | 2 +- 7zip/UI/Common/ArchiveCommandLine.h | 2 +- 7zip/UI/Common/ArchiverInfo.cpp | 36 +- 7zip/UI/Common/ArchiverInfo.h | 23 +- 7zip/UI/Common/EnumDirItems.cpp | 7 +- 7zip/UI/Common/Extract.h | 1 - 7zip/UI/Common/OpenArchive.cpp | 7 +- 7zip/UI/Common/SortUtils.cpp | 21 +- 7zip/UI/Common/Update.cpp | 9 +- 7zip/UI/Console/Console.dsp | 8 + 7zip/UI/Console/Main.cpp | 4 +- 7zip/UI/Console/makefile | 1 + 7zip/UI/Explorer/ContextMenu.cpp | 11 +- 7zip/UI/Explorer/Explorer.dsp | 8 + 7zip/UI/Explorer/makefile | 1 + 7zip/UI/Far/Far.dsp | 8 + 7zip/UI/Far/Messages.h | 1 + 7zip/UI/Far/PluginRead.cpp | 63 +- 7zip/UI/Far/PluginWrite.cpp | 2 +- 7zip/UI/Far/makefile | 1 + 7zip/UI/GUI/CompressDialog.cpp | 29 +- 7zip/UI/GUI/GUI.dsp | 8 + 7zip/UI/GUI/makefile | 1 + Build.mak | 3 +- Common/Buffer.h | 2 + Common/Copy of StringConvert.cpp | 93 -- Common/Copy of StringConvert.h | 71 -- Common/Copy of UTFConvert.cpp | 91 -- Common/Copy of UTFConvert.h | 11 - Common/MyCom.h | 4 +- Common/MyGuidDef.h | 8 +- Common/MyWindows.h | 1 - Common/String.h | 4 +- Common/StringConvert.h | 8 +- Common/StringToInt.cpp | 19 + Common/StringToInt.h | 1 + Common/Vector.h | 64 +- DOC/7zFormat.txt | 4 +- DOC/7zip.nsi | 73 +- DOC/Methods.txt | 11 +- DOC/history.txt | 8 + DOC/lzma.txt | 4 +- DOC/readme.txt | 62 +- DOC/unRarLicense.txt | 41 + Windows/Control/ListView.h | 4 +- Windows/FileIO.cpp | 61 +- Windows/FileIO.h | 2 + Windows/PropVariant.cpp | 4 +- Windows/PropVariant.h | 4 +- Windows/PropVariantConversions.cpp | 3 - 393 files changed, 17345 insertions(+), 4743 deletions(-) create mode 100755 7zip/Archive/7z_C/makefile.gcc create mode 100755 7zip/Archive/Cab/CabBlockInStream.cpp create mode 100755 7zip/Archive/Cab/CabBlockInStream.h delete mode 100755 7zip/Archive/Cab/CabCopyDecoder.cpp delete mode 100755 7zip/Archive/Cab/CabCopyDecoder.h delete mode 100755 7zip/Archive/Cab/CabInBuffer.cpp delete mode 100755 7zip/Archive/Cab/CabInBuffer.h delete mode 100755 7zip/Archive/Cab/LZXBitDecoder.h delete mode 100755 7zip/Archive/Cab/LZXConst.h delete mode 100755 7zip/Archive/Cab/LZXDecoder.cpp delete mode 100755 7zip/Archive/Cab/LZXDecoder.h delete mode 100755 7zip/Archive/Cab/LZXExtConst.h delete mode 100755 7zip/Archive/Cab/MSZipConst.h delete mode 100755 7zip/Archive/Cab/MSZipDecoder.cpp delete mode 100755 7zip/Archive/Cab/MSZipDecoder.h delete mode 100755 7zip/Archive/Cab/MSZipExtConst.h create mode 100755 7zip/Archive/Chm/Chm.dsp create mode 100755 7zip/Archive/Chm/Chm.dsw create mode 100755 7zip/Archive/Chm/ChmHandler.cpp create mode 100755 7zip/Archive/Chm/ChmHandler.h create mode 100755 7zip/Archive/Chm/ChmHeader.cpp create mode 100755 7zip/Archive/Chm/ChmHeader.h create mode 100755 7zip/Archive/Chm/ChmIn.cpp create mode 100755 7zip/Archive/Chm/ChmIn.h create mode 100755 7zip/Archive/Chm/DllExports.cpp create mode 100755 7zip/Archive/Chm/StdAfx.cpp create mode 100755 7zip/Archive/Chm/StdAfx.h create mode 100755 7zip/Archive/Chm/makefile create mode 100755 7zip/Archive/Chm/resource.rc create mode 100755 7zip/Common/StreamUtils.cpp create mode 100755 7zip/Common/StreamUtils.h rename 7zip/Compress/Arj/{Decoder1.cpp => ArjDecoder1.cpp} (99%) rename 7zip/Compress/Arj/{Decoder1.h => ArjDecoder1.h} (100%) rename 7zip/Compress/Arj/{Decoder2.cpp => ArjDecoder2.cpp} (98%) rename 7zip/Compress/Arj/{Decoder2.h => ArjDecoder2.h} (100%) create mode 100755 7zip/Compress/Lzx/Lzx.h rename 7zip/{Archive/Cab/LZXi86Converter.cpp => Compress/Lzx/Lzx86Converter.cpp} (53%) rename 7zip/{Archive/Cab/LZXi86Converter.h => Compress/Lzx/Lzx86Converter.h} (57%) create mode 100755 7zip/Compress/Lzx/LzxDecoder.cpp create mode 100755 7zip/Compress/Lzx/LzxDecoder.h create mode 100755 7zip/Compress/Lzx/StdAfx.h create mode 100755 7zip/Compress/Quantum/QuantumDecoder.cpp create mode 100755 7zip/Compress/Quantum/QuantumDecoder.h create mode 100755 7zip/Compress/Rar20/DllExports.cpp create mode 100755 7zip/Compress/Rar20/Rar20Const.h create mode 100755 7zip/Compress/Rar20/Rar20Decoder.cpp create mode 100755 7zip/Compress/Rar20/Rar20Decoder.h create mode 100755 7zip/Compress/Rar20/Rar20ExtConst.h create mode 100755 7zip/Compress/Rar20/Rar20Multimedia.cpp create mode 100755 7zip/Compress/Rar20/Rar20Multimedia.h create mode 100755 7zip/Compress/Rar20/StdAfx.cpp create mode 100755 7zip/Compress/Rar20/StdAfx.h create mode 100755 7zip/Compress/Rar29/DllExports.cpp create mode 100755 7zip/Compress/Rar29/Original/archive.hpp create mode 100755 7zip/Compress/Rar29/Original/array.hpp create mode 100755 7zip/Compress/Rar29/Original/cmddata.hpp create mode 100755 7zip/Compress/Rar29/Original/coder.cpp create mode 100755 7zip/Compress/Rar29/Original/coder.hpp create mode 100755 7zip/Compress/Rar29/Original/compress.hpp create mode 100755 7zip/Compress/Rar29/Original/consio.hpp create mode 100755 7zip/Compress/Rar29/Original/crc.cpp create mode 100755 7zip/Compress/Rar29/Original/crc.hpp create mode 100755 7zip/Compress/Rar29/Original/crypt.hpp create mode 100755 7zip/Compress/Rar29/Original/encname.hpp create mode 100755 7zip/Compress/Rar29/Original/errhnd.cpp create mode 100755 7zip/Compress/Rar29/Original/errhnd.hpp create mode 100755 7zip/Compress/Rar29/Original/extinfo.hpp create mode 100755 7zip/Compress/Rar29/Original/extract.hpp create mode 100755 7zip/Compress/Rar29/Original/filcreat.hpp create mode 100755 7zip/Compress/Rar29/Original/file.hpp create mode 100755 7zip/Compress/Rar29/Original/filefn.hpp create mode 100755 7zip/Compress/Rar29/Original/filestr.hpp create mode 100755 7zip/Compress/Rar29/Original/find.hpp create mode 100755 7zip/Compress/Rar29/Original/getbits.cpp create mode 100755 7zip/Compress/Rar29/Original/getbits.hpp create mode 100755 7zip/Compress/Rar29/Original/global.hpp create mode 100755 7zip/Compress/Rar29/Original/headers.hpp create mode 100755 7zip/Compress/Rar29/Original/int64.cpp create mode 100755 7zip/Compress/Rar29/Original/int64.hpp create mode 100755 7zip/Compress/Rar29/Original/isnt.hpp create mode 100755 7zip/Compress/Rar29/Original/list.hpp create mode 100755 7zip/Compress/Rar29/Original/loclang.hpp create mode 100755 7zip/Compress/Rar29/Original/log.hpp create mode 100755 7zip/Compress/Rar29/Original/match.hpp create mode 100755 7zip/Compress/Rar29/Original/model.cpp create mode 100755 7zip/Compress/Rar29/Original/model.hpp create mode 100755 7zip/Compress/Rar29/Original/options.hpp create mode 100755 7zip/Compress/Rar29/Original/os.hpp create mode 100755 7zip/Compress/Rar29/Original/pathfn.hpp create mode 100755 7zip/Compress/Rar29/Original/rar.hpp create mode 100755 7zip/Compress/Rar29/Original/rardefs.hpp create mode 100755 7zip/Compress/Rar29/Original/rarfn.hpp create mode 100755 7zip/Compress/Rar29/Original/rarlang.hpp create mode 100755 7zip/Compress/Rar29/Original/raros.hpp create mode 100755 7zip/Compress/Rar29/Original/rartypes.hpp create mode 100755 7zip/Compress/Rar29/Original/rarvm.cpp create mode 100755 7zip/Compress/Rar29/Original/rarvm.hpp create mode 100755 7zip/Compress/Rar29/Original/rarvmtbl.cpp create mode 100755 7zip/Compress/Rar29/Original/rawread.hpp create mode 100755 7zip/Compress/Rar29/Original/rdwrfn.cpp create mode 100755 7zip/Compress/Rar29/Original/rdwrfn.hpp create mode 100755 7zip/Compress/Rar29/Original/recvol.hpp create mode 100755 7zip/Compress/Rar29/Original/resource.cpp create mode 100755 7zip/Compress/Rar29/Original/resource.hpp create mode 100755 7zip/Compress/Rar29/Original/rijndael.hpp create mode 100755 7zip/Compress/Rar29/Original/rs.hpp create mode 100755 7zip/Compress/Rar29/Original/savepos.hpp create mode 100755 7zip/Compress/Rar29/Original/scantree.hpp create mode 100755 7zip/Compress/Rar29/Original/sha1.hpp create mode 100755 7zip/Compress/Rar29/Original/smallfn.cpp create mode 100755 7zip/Compress/Rar29/Original/smallfn.hpp create mode 100755 7zip/Compress/Rar29/Original/strfn.hpp create mode 100755 7zip/Compress/Rar29/Original/strlist.hpp create mode 100755 7zip/Compress/Rar29/Original/suballoc.cpp create mode 100755 7zip/Compress/Rar29/Original/suballoc.hpp create mode 100755 7zip/Compress/Rar29/Original/system.cpp create mode 100755 7zip/Compress/Rar29/Original/system.hpp create mode 100755 7zip/Compress/Rar29/Original/timefn.hpp create mode 100755 7zip/Compress/Rar29/Original/ulinks.hpp create mode 100755 7zip/Compress/Rar29/Original/unicode.hpp create mode 100755 7zip/Compress/Rar29/Original/unpack.cpp create mode 100755 7zip/Compress/Rar29/Original/unpack.hpp create mode 100755 7zip/Compress/Rar29/Original/unpack15.cpp create mode 100755 7zip/Compress/Rar29/Original/version.hpp create mode 100755 7zip/Compress/Rar29/Original/volume.hpp create mode 100755 7zip/Compress/Rar29/Rar29.dsp create mode 100755 7zip/Compress/Rar29/Rar29.dsw create mode 100755 7zip/Compress/Rar29/Rar29Decoder.cpp create mode 100755 7zip/Compress/Rar29/Rar29Decoder.h create mode 100755 7zip/Compress/Rar29/StdAfx.cpp create mode 100755 7zip/Compress/Rar29/StdAfx.h create mode 100755 7zip/Compress/Rar29/makefile create mode 100755 7zip/Compress/Rar29/resource.rc create mode 100755 7zip/Guid.txt delete mode 100755 Common/Copy of StringConvert.cpp delete mode 100755 Common/Copy of StringConvert.h delete mode 100755 Common/Copy of UTFConvert.cpp delete mode 100755 Common/Copy of UTFConvert.h create mode 100755 DOC/unRarLicense.txt diff --git a/7zip/Archive/7z/7z.dsp b/7zip/Archive/7z/7z.dsp index 2e05281d..83e48cef 100755 --- a/7zip/Archive/7z/7z.dsp +++ b/7zip/Archive/7z/7z.dsp @@ -496,6 +496,14 @@ SOURCE=..\..\Common\StreamObjects.cpp SOURCE=..\..\Common\StreamObjects.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # Begin Group "Windows" diff --git a/7zip/Archive/7z/7zDecode.cpp b/7zip/Archive/7z/7zDecode.cpp index e6dbeefd..2deffc12 100755 --- a/7zip/Archive/7z/7zDecode.cpp +++ b/7zip/Archive/7z/7zDecode.cpp @@ -1,4 +1,4 @@ -// Decode.cpp +// 7zDecode.cpp #include "StdAfx.h" @@ -136,10 +136,10 @@ static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2) CDecoder::CDecoder(bool multiThread) { - _multiThread = true; - #ifdef _ST_MODE - _multiThread = multiThread; + #ifndef _ST_MODE + multiThread = true; #endif + _multiThread = multiThread; _bindInfoExPrevIsDefinded = false; #ifndef EXCLUDE_COM LoadMethodMap(); diff --git a/7zip/Archive/7z/7zExtract.cpp b/7zip/Archive/7z/7zExtract.cpp index 1fcccfd7..bf827dc0 100755 --- a/7zip/Archive/7z/7zExtract.cpp +++ b/7zip/Archive/7z/7zExtract.cpp @@ -142,7 +142,13 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, extractCallback->SetTotal(importantTotalUnPacked); - CDecoder decoder(true); + CDecoder decoder( + #ifdef _ST_MODE + false + #else + true + #endif + ); // CDecoder1 decoder; UInt64 currentImportantTotalUnPacked = 0; diff --git a/7zip/Archive/7z/7zFolderInStream.cpp b/7zip/Archive/7z/7zFolderInStream.cpp index 91b39fa9..1b3e2a06 100755 --- a/7zip/Archive/7z/7zFolderInStream.cpp +++ b/7zip/Archive/7z/7zFolderInStream.cpp @@ -79,7 +79,7 @@ HRESULT CFolderInStream::CloseStream() return S_OK; } -STDMETHODIMP CFolderInStream::ReadPart(void *data, UInt32 size, UInt32 *processedSize) +STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; while ((_fileIndex < _numFiles || _fileIsOpen) && size > 0) @@ -87,7 +87,7 @@ STDMETHODIMP CFolderInStream::ReadPart(void *data, UInt32 size, UInt32 *processe if (_fileIsOpen) { UInt32 localProcessedSize; - RINOK(_inStreamWithHash->ReadPart( + RINOK(_inStreamWithHash->Read( ((Byte *)data) + realProcessedSize, size, &localProcessedSize)); if (localProcessedSize == 0) { @@ -109,24 +109,6 @@ STDMETHODIMP CFolderInStream::ReadPart(void *data, UInt32 size, UInt32 *processe return S_OK; } -STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) -{ - UInt32 realProcessedSize = 0; - while (size > 0) - { - UInt32 localProcessedSize; - RINOK(ReadPart(((Byte *)data) + realProcessedSize, size, &localProcessedSize)); - if (localProcessedSize == 0) - break; - size -= localProcessedSize; - realProcessedSize += localProcessedSize; - } - if (processedSize != 0) - *processedSize = realProcessedSize; - return S_OK; -} - - STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) { *value = 0; diff --git a/7zip/Archive/7z/7zFolderInStream.h b/7zip/Archive/7z/7zFolderInStream.h index 12a2ac07..9a720c8b 100755 --- a/7zip/Archive/7z/7zFolderInStream.h +++ b/7zip/Archive/7z/7zFolderInStream.h @@ -26,7 +26,6 @@ public: CFolderInStream(); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); private: diff --git a/7zip/Archive/7z/7zFolderOutStream.cpp b/7zip/Archive/7z/7zFolderOutStream.cpp index c09271f5..bb770ccc 100755 --- a/7zip/Archive/7z/7zFolderOutStream.cpp +++ b/7zip/Archive/7z/7zFolderOutStream.cpp @@ -91,7 +91,8 @@ STDMETHODIMP CFolderOutStream::Write(const void *data, UInt64(size - realProcessedSize)); UInt32 processedSizeLocal; - RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize, numBytesToWrite, &processedSizeLocal)); + RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize, + numBytesToWrite, &processedSizeLocal)); _filePos += processedSizeLocal; realProcessedSize += processedSizeLocal; @@ -130,12 +131,6 @@ STDMETHODIMP CFolderOutStream::Write(const void *data, return S_OK; } -STDMETHODIMP CFolderOutStream::WritePart(const void *data, - UInt32 size, UInt32 *processedSize) -{ - return Write(data, size, processedSize); -} - HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult) { while(_currentIndex < _extractStatuses->Size()) diff --git a/7zip/Archive/7z/7zFolderOutStream.h b/7zip/Archive/7z/7zFolderOutStream.h index 9153070e..c132c79a 100755 --- a/7zip/Archive/7z/7zFolderOutStream.h +++ b/7zip/Archive/7z/7zFolderOutStream.h @@ -22,7 +22,6 @@ public: CFolderOutStream(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); private: COutStreamWithCRC *_outStreamWithHashSpec; diff --git a/7zip/Archive/7z/7zHandler.h b/7zip/Archive/7z/7zHandler.h index 7966b86c..b7a53b20 100755 --- a/7zip/Archive/7z/7zHandler.h +++ b/7zip/Archive/7z/7zHandler.h @@ -50,9 +50,9 @@ struct COneMethodInfo }; #endif -// {23170F69-40C1-278A-1000-000110050000} +// {23170F69-40C1-278A-1000-000110070000} DEFINE_GUID(CLSID_CFormat7z, - 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x05, 0x00, 0x00); + 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00); class CHandler: public IInArchive, diff --git a/7zip/Archive/7z/7zIn.cpp b/7zip/Archive/7z/7zIn.cpp index 93a72c75..c35a77ce 100755 --- a/7zip/Archive/7z/7zIn.cpp +++ b/7zip/Archive/7z/7zIn.cpp @@ -6,6 +6,7 @@ #include "7zMethods.h" #include "7zDecode.h" #include "../../Common/StreamObjects.h" +#include "../../Common/StreamUtils.h" #include "../../../Common/CRC.h" namespace NArchive { @@ -69,7 +70,7 @@ HRESULT CInArchive::ReadDirect(IInStream *stream, void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; - HRESULT result = stream->Read(data, size, &realProcessedSize); + HRESULT result = ReadStream(stream, data, size, &realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; _position += realProcessedSize; @@ -850,7 +851,13 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(UInt64 baseOffset, // database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader; CNum packIndex = 0; - CDecoder decoder(false); + CDecoder decoder( + #ifdef _ST_MODE + false + #else + true + #endif + ); UInt64 dataStartPos = baseOffset + dataOffset; for(int i = 0; i < folders.Size(); i++) { diff --git a/7zip/Archive/7z/7zOut.cpp b/7zip/Archive/7z/7zOut.cpp index b2ba2db3..116cb0cc 100755 --- a/7zip/Archive/7z/7zOut.cpp +++ b/7zip/Archive/7z/7zOut.cpp @@ -11,10 +11,10 @@ static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t { while (size > 0) { - UInt32 curSize = (UInt32)(MyMin(size, (size_t)0xFFFFFFFF)); + UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF); UInt32 processedSize; - RINOK(stream->WritePart(data, curSize, &processedSize)); - if(processedSize == 0 || processedSize > curSize) + RINOK(stream->Write(data, curSize, &processedSize)); + if(processedSize == 0) return E_FAIL; data = (const void *)((const Byte *)data + processedSize); size -= processedSize; @@ -111,7 +111,10 @@ HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker) { SeqStream.QueryInterface(IID_IOutStream, &Stream); if (!Stream) - endMarker = true; + { + return E_NOTIMPL; + // endMarker = true; + } } #ifdef _7Z_VOL if (endMarker) diff --git a/7zip/Archive/7z/7zSpecStream.cpp b/7zip/Archive/7z/7zSpecStream.cpp index fb42d98c..80d303a4 100755 --- a/7zip/Archive/7z/7zSpecStream.cpp +++ b/7zip/Archive/7z/7zSpecStream.cpp @@ -14,16 +14,6 @@ STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 return result; } -STDMETHODIMP CSequentialInStreamSizeCount2::ReadPart(void *data, UInt32 size, UInt32 *processedSize) -{ - UInt32 realProcessedSize; - HRESULT result = _stream->ReadPart(data, size, &realProcessedSize); - _size += realProcessedSize; - if (processedSize != 0) - *processedSize = realProcessedSize; - return result; -} - STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize( UInt64 subStream, UInt64 *value) { diff --git a/7zip/Archive/7z/7zSpecStream.h b/7zip/Archive/7z/7zSpecStream.h index 7d3cf538..0253c421 100755 --- a/7zip/Archive/7z/7zSpecStream.h +++ b/7zip/Archive/7z/7zSpecStream.h @@ -28,7 +28,6 @@ public: MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); }; diff --git a/7zip/Archive/7z/7zUpdate.cpp b/7zip/Archive/7z/7zUpdate.cpp index 5722aba4..e5d82764 100755 --- a/7zip/Archive/7z/7zUpdate.cpp +++ b/7zip/Archive/7z/7zUpdate.cpp @@ -89,11 +89,13 @@ UString CUpdateItem::GetExtension() const return Name.Mid(GetExtensionPos()); } +/* struct CFolderRef { const CArchiveDatabaseEx *Database; int FolderIndex; }; +*/ #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } @@ -159,31 +161,31 @@ static int CompareFiles(const CFileItem &f1, const CFileItem &f2) return MyStringCollateNoCase(f1.Name, f2.Name); } -static int __cdecl CompareFolderRefs(const void *p1, const void *p2) +static int CompareFolderRefs(const int *p1, const int *p2, void *param) { - const CFolderRef &a1 = *((const CFolderRef *)p1); - const CFolderRef &a2 = *((const CFolderRef *)p2); - const CArchiveDatabaseEx &d1 = *a1.Database; - const CArchiveDatabaseEx &d2 = *a2.Database; + int i1 = *p1; + int i2 = *p2; + const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param; RINOZ(CompareFolders( - d1.Folders[a1.FolderIndex], - d2.Folders[a2.FolderIndex])); + db.Folders[i1], + db.Folders[i2])); RINOZ(MyCompare( - d1.NumUnPackStreamsVector[a1.FolderIndex], - d2.NumUnPackStreamsVector[a2.FolderIndex])); - if (d1.NumUnPackStreamsVector[a1.FolderIndex] == 0) + db.NumUnPackStreamsVector[i1], + db.NumUnPackStreamsVector[i2])); + if (db.NumUnPackStreamsVector[i1] == 0) return 0; return CompareFiles( - d1.Files[d1.FolderStartFileIndex[a1.FolderIndex]], - d2.Files[d2.FolderStartFileIndex[a2.FolderIndex]]); + db.Files[db.FolderStartFileIndex[i1]], + db.Files[db.FolderStartFileIndex[i2]]); } //////////////////////////////////////////////////////////// -static int __cdecl CompareEmptyItems(const void *p1, const void *p2) +static int CompareEmptyItems(const int *p1, const int *p2, void *param) { - const CUpdateItem &u1 = **((CUpdateItem **)p1); - const CUpdateItem &u2 = **((CUpdateItem **)p2); + const CObjectVector &updateItems = *(const CObjectVector *)param; + const CUpdateItem &u1 = updateItems[*p1]; + const CUpdateItem &u2 = updateItems[*p2]; if (u1.IsDirectory != u2.IsDirectory) { if (u1.IsDirectory) @@ -234,10 +236,10 @@ struct CRefItem } }; -static int __cdecl CompareUpdateItems(const void *p1, const void *p2) +static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param) { - const CRefItem &a1 = *((CRefItem *)p1); - const CRefItem &a2 = *((CRefItem *)p2); + const CRefItem &a1 = *p1; + const CRefItem &a2 = *p2; const CUpdateItem &u1 = *a1.UpdateItem; const CUpdateItem &u2 = *a2.UpdateItem; int n; @@ -455,7 +457,7 @@ static void FromUpdateItemToFileItem(const CUpdateItem &updateItem, static HRESULT Update2( IInStream *inStream, const CArchiveDatabaseEx *database, - CObjectVector &updateItems, + const CObjectVector &updateItems, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) @@ -496,38 +498,32 @@ static HRESULT Update2( fileIndexToUpdateIndexMap[index] = i; } - CRecordVector folderRefs; + CRecordVector folderRefs; if (database != 0) { - for(i = 0; i < database->Folders.Size(); i++) - { - CNum indexInFolder = 0; - CNum numCopyItems = 0; - CNum numUnPackStreams = database->NumUnPackStreamsVector[i]; - for (CNum fileIndex = database->FolderStartFileIndex[i]; - indexInFolder < numUnPackStreams; fileIndex++) + for(i = 0; i < database->Folders.Size(); i++) { - if (database->Files[fileIndex].HasStream) + CNum indexInFolder = 0; + CNum numCopyItems = 0; + CNum numUnPackStreams = database->NumUnPackStreamsVector[i]; + for (CNum fileIndex = database->FolderStartFileIndex[i]; + indexInFolder < numUnPackStreams; fileIndex++) { - indexInFolder++; - int updateIndex = fileIndexToUpdateIndexMap[fileIndex]; - if (updateIndex >= 0) - if (!updateItems[updateIndex].NewData) - numCopyItems++; + if (database->Files[fileIndex].HasStream) + { + indexInFolder++; + int updateIndex = fileIndexToUpdateIndexMap[fileIndex]; + if (updateIndex >= 0) + if (!updateItems[updateIndex].NewData) + numCopyItems++; + } } + if (numCopyItems != numUnPackStreams && numCopyItems != 0) + return E_NOTIMPL; // It needs repacking !!! + if (numCopyItems > 0) + folderRefs.Add(i); } - if (numCopyItems != numUnPackStreams && numCopyItems != 0) - return E_NOTIMPL; // It needs repacking !!! - if (numCopyItems > 0) - { - CFolderRef folderRef; - folderRef.Database = database; - folderRef.FolderIndex = i; - folderRefs.Add(folderRef); - } - } - qsort(&folderRefs.Front(), folderRefs.Size(), sizeof(folderRefs[0]), - CompareFolderRefs); + folderRefs.Sort(CompareFolderRefs, (void *)database); } CArchiveDatabase newDatabase; @@ -535,7 +531,7 @@ static HRESULT Update2( ///////////////////////////////////////// // Write Empty Files & Folders - CRecordVector emptyRefs; + CRecordVector emptyRefs; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &updateItem = updateItems[i]; @@ -548,13 +544,12 @@ static HRESULT Update2( if (updateItem.IndexInArchive != -1) if (database->Files[updateItem.IndexInArchive].HasStream) continue; - emptyRefs.Add(&updateItem); + emptyRefs.Add(i); } - qsort(&emptyRefs.Front(), emptyRefs.Size(), sizeof(emptyRefs[0]), - CompareEmptyItems); + emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems); for(i = 0; i < emptyRefs.Size(); i++) { - const CUpdateItem &updateItem = *emptyRefs[i]; + const CUpdateItem &updateItem = updateItems[emptyRefs[i]]; CFileItem file; if (updateItem.NewProperties) FromUpdateItemToFileItem(updateItem, file); @@ -566,11 +561,11 @@ static HRESULT Update2( //////////////////////////// COutArchive archive; - archive.Create(seqOutStream, false); + RINOK(archive.Create(seqOutStream, false)); RINOK(archive.SkeepPrefixArchiveHeader()); UInt64 complexity = 0; for(i = 0; i < folderRefs.Size(); i++) - complexity += database->GetFolderFullPackSize(folderRefs[i].FolderIndex); + complexity += database->GetFolderFullPackSize(folderRefs[i]); for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &updateItem = updateItems[i]; @@ -586,7 +581,7 @@ static HRESULT Update2( for(i = 0; i < folderRefs.Size(); i++) { - int folderIndex = folderRefs[i].FolderIndex; + int folderIndex = folderRefs[i]; RINOK(WriteRange(inStream, archive.SeqStream, database->GetFolderStreamPos(folderIndex, 0), @@ -652,7 +647,7 @@ static HRESULT Update2( for (i = 0; i < numFiles; i++) refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], numSolidFiles > 1)); - qsort(&refItems.Front(), refItems.Size(), sizeof(refItems[0]), CompareUpdateItems); + refItems.Sort(CompareUpdateItems, 0); CRecordVector indices; indices.Reserve(numFiles); @@ -862,7 +857,7 @@ HRESULT UpdateVolume( RINOK(volumeCallback->GetVolumeStream(volumeIndex, &volumeStream)); COutArchive archive; - archive.Create(volumeStream, true); + RINOK(archive.Create(volumeStream, true)); RINOK(archive.SkeepPrefixArchiveHeader()); CSequentialInStreamWithCRC *inCrcStreamSpec = new CSequentialInStreamWithCRC; @@ -914,7 +909,6 @@ public: HRESULT Flush(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); }; HRESULT COutVolumeStream::Flush() @@ -943,7 +937,7 @@ STDMETHODIMP COutVolumeStream::Write(const void *data, UInt32 size, UInt32 *proc RINOK(VolumeCallback->GetVolumeStream(_volIndex, &_volumeStream)); _volIndex++; _curPos = 0; - _archive.Create(_volumeStream, true); + RINOK(_archive.Create(_volumeStream, true)); RINOK(_archive.SkeepPrefixArchiveHeader()); _crc.Init(); continue; @@ -959,7 +953,7 @@ STDMETHODIMP COutVolumeStream::Write(const void *data, UInt32 size, UInt32 *proc if(processedSize != NULL) *processedSize += realProcessed; _curPos += realProcessed; - if (realProcessed != curSize) + if (realProcessed != curSize && realProcessed == 0) return E_FAIL; if (_curPos == pureSize) { @@ -969,16 +963,12 @@ STDMETHODIMP COutVolumeStream::Write(const void *data, UInt32 size, UInt32 *proc return S_OK; } -STDMETHODIMP COutVolumeStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize) -{ - return Write(data, size, processedSize); -} #endif HRESULT Update( IInStream *inStream, const CArchiveDatabaseEx *database, - CObjectVector &updateItems, + const CObjectVector &updateItems, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) diff --git a/7zip/Archive/7z/7zUpdate.h b/7zip/Archive/7z/7zUpdate.h index ab6cff4f..7567864a 100755 --- a/7zip/Archive/7z/7zUpdate.h +++ b/7zip/Archive/7z/7zUpdate.h @@ -60,7 +60,7 @@ struct CUpdateOptions HRESULT Update( IInStream *inStream, const CArchiveDatabaseEx *database, - CObjectVector &updateItems, + const CObjectVector &updateItems, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options); diff --git a/7zip/Archive/7z/makefile b/7zip/Archive/7z/makefile index 5c58e960..97bbbaaf 100755 --- a/7zip/Archive/7z/makefile +++ b/7zip/Archive/7z/makefile @@ -48,6 +48,7 @@ WIN_OBJS = \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ + $O\StreamUtils.obj \ AR_COMMON_OBJS = \ $O\CodecsPath.obj \ diff --git a/7zip/Archive/7z_C/makefile.gcc b/7zip/Archive/7z_C/makefile.gcc new file mode 100755 index 00000000..21b7df47 --- /dev/null +++ b/7zip/Archive/7z_C/makefile.gcc @@ -0,0 +1,50 @@ +PROG = 7zDec +CXX = g++ +LIB = +RM = rm -f +CFLAGS = -c -O2 -Wall + +OBJS = 7zAlloc.o 7zBuffer.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o 7zMethodID.o LzmaDecode.o + +all: $(PROG) + +$(PROG): $(OBJS) + $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) + +7zAlloc.o: 7zAlloc.c + $(CXX) $(CFLAGS) 7zAlloc.c + +7zBuffer.o: 7zBuffer.c + $(CXX) $(CFLAGS) 7zBuffer.c + +7zCrc.o: 7zCrc.c + $(CXX) $(CFLAGS) 7zCrc.c + +7zDecode.o: 7zDecode.c + $(CXX) $(CFLAGS) 7zDecode.c + +7zExtract.o: 7zExtract.c + $(CXX) $(CFLAGS) 7zExtract.c + +7zHeader.o: 7zHeader.c + $(CXX) $(CFLAGS) 7zHeader.c + +7zIn.o: 7zIn.c + $(CXX) $(CFLAGS) 7zIn.c + +7zItem.o: 7zItem.c + $(CXX) $(CFLAGS) 7zItem.c + +7zMain.o: 7zMain.c + $(CXX) $(CFLAGS) 7zMain.c + +7zMethodID.o: 7zMethodID.c + $(CXX) $(CFLAGS) 7zMethodID.c + +LzmaDecode.o: ../../Compress/LZMA_C/LzmaDecode.c + $(CXX) $(CFLAGS) ../../Compress/LZMA_C/LzmaDecode.c + + +clean: + -$(RM) $(PROG) $(OBJS) + diff --git a/7zip/Archive/Arj/Arj.dsp b/7zip/Archive/Arj/Arj.dsp index 0963ce38..3bc6fa91 100755 --- a/7zip/Archive/Arj/Arj.dsp +++ b/7zip/Archive/Arj/Arj.dsp @@ -213,19 +213,19 @@ SOURCE=.\ArjItem.h # PROP Default_Filter "" # Begin Source File -SOURCE=..\..\Compress\Arj\Decoder1.cpp +SOURCE=..\..\Compress\Arj\ArjDecoder1.cpp # End Source File # Begin Source File -SOURCE=..\..\Compress\Arj\Decoder1.h +SOURCE=..\..\Compress\Arj\ArjDecoder1.h # End Source File # Begin Source File -SOURCE=..\..\Compress\Arj\Decoder2.cpp +SOURCE=..\..\Compress\Arj\ArjDecoder2.cpp # End Source File # Begin Source File -SOURCE=..\..\Compress\Arj\Decoder2.h +SOURCE=..\..\Compress\Arj\ArjDecoder2.h # End Source File # End Group # Begin Group "LZ" @@ -278,12 +278,28 @@ SOURCE=..\..\Common\MSBFDecoder.h # End Source File # Begin Source File +SOURCE=..\..\Common\OutBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # Begin Group "Archive Common" diff --git a/7zip/Archive/Arj/ArjHandler.cpp b/7zip/Archive/Arj/ArjHandler.cpp index 7701da3b..ab75493f 100755 --- a/7zip/Archive/Arj/ArjHandler.cpp +++ b/7zip/Archive/Arj/ArjHandler.cpp @@ -19,8 +19,8 @@ #include "../../Common/LimitedStreams.h" #include "../../Compress/Copy/CopyCoder.h" -#include "../../Compress/Arj/Decoder1.h" -#include "../../Compress/Arj/Decoder2.h" +#include "../../Compress/Arj/ArjDecoder1.h" +#include "../../Compress/Arj/ArjDecoder2.h" #include "../Common/ItemNameUtils.h" #include "../Common/OutStreamWithCRC.h" diff --git a/7zip/Archive/Arj/ArjIn.cpp b/7zip/Archive/Arj/ArjIn.cpp index c019055c..03346824 100755 --- a/7zip/Archive/Arj/ArjIn.cpp +++ b/7zip/Archive/Arj/ArjIn.cpp @@ -6,6 +6,8 @@ #include "Common/Buffer.h" #include "Common/CRC.h" +#include "../../Common/StreamUtils.h" + #include "ArjIn.h" namespace NArchive { @@ -14,7 +16,7 @@ namespace NArj { HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; - HRESULT result = _stream->Read(data, size, &realProcessedSize); + HRESULT result = ReadStream(_stream, data, size, &realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; IncreasePositionValue(realProcessedSize); @@ -162,7 +164,7 @@ bool CInArchive::ReadBlock() { _blockPos = 0; _blockSize = SafeReadUInt16(); - if (_blockSize == 0) + if (_blockSize == 0 || _blockSize > kMaxBlockSize) return false; SafeReadBytes(_block, _blockSize); UInt32 crcFromFile = SafeReadUInt32(); diff --git a/7zip/Archive/Arj/DllExports.cpp b/7zip/Archive/Arj/DllExports.cpp index abedc1f7..202fbe0d 100755 --- a/7zip/Archive/Arj/DllExports.cpp +++ b/7zip/Archive/Arj/DllExports.cpp @@ -8,9 +8,9 @@ #include "../../ICoder.h" #include "ArjHandler.h" -// {23170F69-40C1-278A-1000-0001100A0000} +// {23170F69-40C1-278A-1000-000110040000} DEFINE_GUID(CLSID_CArjHandler, - 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x0A, 0x00, 0x00); + 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x04, 0x00, 0x00); extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) diff --git a/7zip/Archive/Arj/makefile b/7zip/Archive/Arj/makefile index d45975b4..2609998b 100755 --- a/7zip/Archive/Arj/makefile +++ b/7zip/Archive/Arj/makefile @@ -22,15 +22,17 @@ WIN_OBJS = \ 7ZIP_COMMON_OBJS = \ $O\InBuffer.obj \ $O\LimitedStreams.obj \ + $O\OutBuffer.obj \ $O\ProgressUtils.obj \ + $O\StreamUtils.obj \ AR_COMMON_OBJS = \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ COMPRESS_ARJ_OBJS = \ - $O\Decoder1.obj \ - $O\Decoder2.obj \ + $O\ArjDecoder1.obj \ + $O\ArjDecoder2.obj \ OBJS = \ $O\StdAfx.obj \ diff --git a/7zip/Archive/BZip2/BZip2.dsp b/7zip/Archive/BZip2/BZip2.dsp index 0e28884f..ccae8d3b 100755 --- a/7zip/Archive/BZip2/BZip2.dsp +++ b/7zip/Archive/BZip2/BZip2.dsp @@ -256,6 +256,14 @@ SOURCE=..\..\Common\ProgressUtils.cpp SOURCE=..\..\Common\ProgressUtils.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # Begin Source File diff --git a/7zip/Archive/BZip2/BZip2Handler.cpp b/7zip/Archive/BZip2/BZip2Handler.cpp index 97ea155c..88e5da1f 100755 --- a/7zip/Archive/BZip2/BZip2Handler.cpp +++ b/7zip/Archive/BZip2/BZip2Handler.cpp @@ -7,7 +7,7 @@ #include "Common/Defs.h" #include "../../Common/ProgressUtils.h" -// #include "Interface/EnumStatProp.h" +#include "../../Common/StreamUtils.h" #include "Windows/PropVariant.h" #include "Windows/Defs.h" @@ -111,7 +111,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const int kSignatureSize = 3; Byte buffer[kSignatureSize]; UInt32 processedSize; - RINOK(stream->Read(buffer, kSignatureSize, &processedSize)); + RINOK(ReadStream(stream, buffer, kSignatureSize, &processedSize)); if (processedSize != kSignatureSize) return S_FALSE; if (buffer[0] != 'B' || buffer[1] != 'Z' || buffer[2] != 'h') @@ -221,7 +221,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, const int kSignatureSize = 3; Byte buffer[kSignatureSize]; UInt32 processedSize; - RINOK(_stream->Read(buffer, kSignatureSize, &processedSize)); + RINOK(ReadStream(_stream, buffer, kSignatureSize, &processedSize)); if (processedSize < kSignatureSize) { if (firstItem) diff --git a/7zip/Archive/BZip2/DllExports.cpp b/7zip/Archive/BZip2/DllExports.cpp index 52e9cca4..932a75bb 100755 --- a/7zip/Archive/BZip2/DllExports.cpp +++ b/7zip/Archive/BZip2/DllExports.cpp @@ -16,9 +16,9 @@ DEFINE_GUID(CLSID_CCompressBZip2Encoder, DEFINE_GUID(CLSID_CCompressBZip2Decoder, 0x23170F69, 0x40C1, 0x278B, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00); -// {23170F69-40C1-278A-1000-000110070000} +// {23170F69-40C1-278A-1000-000110020000} DEFINE_GUID(CLSID_CBZip2Handler, -0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00); +0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x02, 0x00, 0x00); HINSTANCE g_hInstance; diff --git a/7zip/Archive/BZip2/makefile b/7zip/Archive/BZip2/makefile index 936abdcc..85095122 100755 --- a/7zip/Archive/BZip2/makefile +++ b/7zip/Archive/BZip2/makefile @@ -22,6 +22,7 @@ WIN_OBJS = \ 7ZIP_COMMON_OBJS = \ $O\ProgressUtils.obj \ + $O\StreamUtils.obj \ AR_COMMON_OBJS = \ $O\CodecsPath.obj \ diff --git a/7zip/Archive/Cab/Cab.dsp b/7zip/Archive/Cab/Cab.dsp index f96be2e0..565661f6 100755 --- a/7zip/Archive/Cab/Cab.dsp +++ b/7zip/Archive/Cab/Cab.dsp @@ -43,7 +43,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CAB_EXPORTS" /YX /FD /c -# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CAB_EXPORTS" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CAB_EXPORTS" /FAs /Yu"StdAfx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" @@ -70,7 +70,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CAB_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CAB_EXPORTS" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CAB_EXPORTS" /FAcs /Yu"StdAfx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" @@ -190,11 +190,11 @@ SOURCE=..\..\..\Windows\PropVariant.h # PROP Default_Filter "" # Begin Source File -SOURCE=.\CabCopyDecoder.cpp +SOURCE=.\CabBlockInStream.cpp # End Source File # Begin Source File -SOURCE=.\CabCopyDecoder.h +SOURCE=.\CabBlockInStream.h # End Source File # Begin Source File @@ -222,60 +222,8 @@ SOURCE=.\CabIn.h # End Source File # Begin Source File -SOURCE=.\CabInBuffer.cpp -# End Source File -# Begin Source File - -SOURCE=.\CabInBuffer.h -# End Source File -# Begin Source File - SOURCE=.\CabItem.h # End Source File -# Begin Source File - -SOURCE=.\LZXBitDecoder.h -# End Source File -# Begin Source File - -SOURCE=.\LZXConst.h -# End Source File -# Begin Source File - -SOURCE=.\LZXDecoder.cpp -# End Source File -# Begin Source File - -SOURCE=.\LZXDecoder.h -# End Source File -# Begin Source File - -SOURCE=.\LZXExtConst.h -# End Source File -# Begin Source File - -SOURCE=.\LZXi86Converter.cpp -# End Source File -# Begin Source File - -SOURCE=.\LZXi86Converter.h -# End Source File -# Begin Source File - -SOURCE=.\MSZipConst.h -# End Source File -# Begin Source File - -SOURCE=.\MSZipDecoder.cpp -# End Source File -# Begin Source File - -SOURCE=.\MSZipDecoder.h -# End Source File -# Begin Source File - -SOURCE=.\MSZipExtConst.h -# End Source File # End Group # Begin Group "7zip Common" @@ -298,6 +246,10 @@ SOURCE=..\..\Common\LSBFDecoder.h # End Source File # Begin Source File +SOURCE=..\..\Common\MSBFDecoder.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File @@ -306,11 +258,11 @@ SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File -SOURCE=..\..\Common\ProgressUtils.cpp +SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File -SOURCE=..\..\Common\ProgressUtils.h +SOURCE=..\..\Common\StreamUtils.h # End Source File # End Group # Begin Group "Compress" @@ -328,6 +280,112 @@ SOURCE=..\..\Compress\LZ\LZOutWindow.cpp SOURCE=..\..\Compress\LZ\LZOutWindow.h # End Source File # End Group +# Begin Group "Lzx" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Lzx\Lzx.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzx\Lzx86Converter.cpp + +!IF "$(CFG)" == "Cab - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Cab - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzx\Lzx86Converter.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzx\LzxDecoder.cpp + +!IF "$(CFG)" == "Cab - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Cab - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzx\LzxDecoder.h +# End Source File +# End Group +# Begin Group "Deflate" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Deflate\DeflateConst.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Deflate\DeflateDecoder.cpp + +!IF "$(CFG)" == "Cab - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Cab - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Deflate\DeflateDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Deflate\DeflateExtConst.h +# End Source File +# End Group +# Begin Group "Copy" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Copy\CopyCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Copy\CopyCoder.h +# End Source File +# End Group +# Begin Group "Quantum" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Quantum\QuantumDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Quantum\QuantumDecoder.h +# End Source File +# End Group +# Begin Group "Huffman" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Huffman\HuffmanDecoder.h +# End Source File +# End Group # End Group # Begin Source File diff --git a/7zip/Archive/Cab/CabBlockInStream.cpp b/7zip/Archive/Cab/CabBlockInStream.cpp new file mode 100755 index 00000000..b775c105 --- /dev/null +++ b/7zip/Archive/Cab/CabBlockInStream.cpp @@ -0,0 +1,194 @@ +// CabBlockInStream.cpp + +#include "StdAfx.h" + +#include "Common/Alloc.h" +#include "Common/Defs.h" + +#include "../../Common/StreamUtils.h" + +#include "CabBlockInStream.h" + +namespace NArchive { +namespace NCab { + +static const UInt32 kBlockSize = (1 << 16); + +bool CCabBlockInStream::Create() +{ + if (!_buffer) + _buffer = (Byte *)::MyAlloc(kBlockSize); + return (_buffer != 0); +} + +CCabBlockInStream::~CCabBlockInStream() +{ + MyFree(_buffer); +} + +class CCheckSum2 +{ + UInt32 m_Value; + int m_Pos; + Byte m_Hist[4]; +public: + CCheckSum2(): m_Value(0){}; + void Init() { m_Value = 0; m_Pos = 0; } + void Update(const void *data, UInt32 size); + void FinishDataUpdate() + { + for (int i = 0; i < m_Pos; i++) + m_Value ^= ((UInt32)(m_Hist[i])) << (8 * (m_Pos - i - 1)); + } + void UpdateUInt32(UInt32 v) { m_Value ^= v; } + UInt32 GetResult() const { return m_Value; } +}; + +void CCheckSum2::Update(const void *data, UInt32 size) +{ + UInt32 checkSum = m_Value; + const Byte *dataPointer = (const Byte *)data; + + while (size != 0 && m_Pos != 0) + { + m_Hist[m_Pos] = *dataPointer++; + m_Pos = (m_Pos + 1) & 3; + size--; + if (m_Pos == 0) + for (int i = 0; i < 4; i++) + checkSum ^= ((UInt32)m_Hist[i]) << (8 * i); + } + + int numWords = size / 4; + + while (numWords-- != 0) + { + UInt32 temp = *dataPointer++; + temp |= ((UInt32)(*dataPointer++)) << 8; + temp |= ((UInt32)(*dataPointer++)) << 16; + temp |= ((UInt32)(*dataPointer++)) << 24; + checkSum ^= temp; + } + m_Value = checkSum; + + size &= 3; + + while (size != 0) + { + m_Hist[m_Pos] = *dataPointer++; + m_Pos = (m_Pos + 1) & 3; + size--; + } +} + +static const UInt32 kDataBlockHeaderSize = 8; + +class CTempCabInBuffer2 +{ +public: + Byte Buffer[kDataBlockHeaderSize]; + UInt32 Pos; + Byte ReadByte() + { + return Buffer[Pos++]; + } + UInt32 ReadUInt32() + { + UInt32 value = 0; + for (int i = 0; i < 4; i++) + value |= (((UInt32)ReadByte()) << (8 * i)); + return value; + } + UInt16 ReadUInt16() + { + UInt16 value = 0; + for (int i = 0; i < 2; i++) + value |= (((UInt16)ReadByte()) << (8 * i)); + return value; + } +}; + +HRESULT CCabBlockInStream::PreRead(UInt32 &packSize, UInt32 &unpackSize) +{ + CTempCabInBuffer2 inBuffer; + inBuffer.Pos = 0; + UInt32 processedSizeLoc; + RINOK(ReadStream(_stream, inBuffer.Buffer, kDataBlockHeaderSize, &processedSizeLoc)) + if (processedSizeLoc != kDataBlockHeaderSize) + return S_FALSE; // bad block + + UInt32 checkSum = inBuffer.ReadUInt32(); + packSize = inBuffer.ReadUInt16(); + unpackSize = inBuffer.ReadUInt16(); + if (ReservedSize != 0) + { + RINOK(ReadStream(_stream, _buffer, ReservedSize, &processedSizeLoc)); + if(ReservedSize != processedSizeLoc) + return S_FALSE; // bad block; + } + _pos = 0; + CCheckSum2 checkSumCalc; + checkSumCalc.Init(); + UInt32 packSize2 = packSize; + if (MsZip && _size == 0) + { + if (packSize < 2) + return S_FALSE; // bad block; + Byte sig[2]; + RINOK(ReadStream(_stream, sig, 2, &processedSizeLoc)); + if(processedSizeLoc != 2) + return S_FALSE; + if (sig[0] != 0x43 || sig[1] != 0x4B) + return S_FALSE; + packSize2 -= 2; + checkSumCalc.Update(sig, 2); + } + + if (kBlockSize - _size < packSize2) + return S_FALSE; + + UInt32 curSize = packSize2; + if (curSize != 0) + { + RINOK(ReadStream(_stream, _buffer + _size, curSize, &processedSizeLoc)); + checkSumCalc.Update(_buffer + _size, processedSizeLoc); + _size += processedSizeLoc; + if (processedSizeLoc != curSize) + return S_FALSE; + } + TotalPackSize = _size; + + checkSumCalc.FinishDataUpdate(); + + bool dataError; + if (checkSum == 0) + dataError = false; + else + { + checkSumCalc.UpdateUInt32(packSize | (((UInt32)unpackSize) << 16)); + dataError = (checkSumCalc.GetResult() != checkSum); + } + DataError |= dataError; + return dataError ? S_FALSE : S_OK; +} + +STDMETHODIMP CCabBlockInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != 0) + *processedSize = 0; + if (size == 0) + return S_OK; + if (_size != 0) + { + size = MyMin(_size, size); + memmove(data, _buffer + _pos, size); + _pos += size; + _size -= size; + if (processedSize != 0) + *processedSize = size; + return S_OK; + } + return S_OK; // no blocks data +} + +}} diff --git a/7zip/Archive/Cab/CabBlockInStream.h b/7zip/Archive/Cab/CabBlockInStream.h new file mode 100755 index 00000000..46e15222 --- /dev/null +++ b/7zip/Archive/Cab/CabBlockInStream.h @@ -0,0 +1,56 @@ +// CabBlockInStream.cpp + +#ifndef __CABBLOCKINSTREAM_H +#define __CABBLOCKINSTREAM_H + +#include "Common/MyCom.h" +#include "../../IStream.h" + +namespace NArchive { +namespace NCab { + +class CCabBlockInStream: + public ISequentialInStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + Byte *_buffer; + UInt32 _pos; + UInt32 _size; + int _align; + +public: + UInt32 TotalPackSize; + UInt32 ReservedSize; + bool DataError; + bool MsZip; + + CCabBlockInStream(): _buffer(0), ReservedSize(0), MsZip(false), DataError(false), _align(0), TotalPackSize(0) {} + ~CCabBlockInStream(); + bool Create(); + void SetStream(ISequentialInStream *stream) { _stream = stream; } + + void InitForNewFolder() + { + _align = 0; + TotalPackSize = 0; + } + + void InitForNewBlock() + { + _size = 0; + _align = (_align + (int)TotalPackSize) & 1; + } + + int GetAlign() const { return _align; } + + MY_UNKNOWN_IMP + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + + HRESULT PreRead(UInt32 &packSize, UInt32 &unpackSize); +}; + +}} + +#endif diff --git a/7zip/Archive/Cab/CabCopyDecoder.cpp b/7zip/Archive/Cab/CabCopyDecoder.cpp deleted file mode 100755 index 541d4d93..00000000 --- a/7zip/Archive/Cab/CabCopyDecoder.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// CabCopyDecoder.cpp - -#include "StdAfx.h" - -#include "CabCopyDecoder.h" -#include "Common/Defs.h" -#include "Windows/Defs.h" - -namespace NArchive { -namespace NCab { - -static const UInt32 kBufferSize = 1 << 17; - -void CCopyDecoder::ReleaseStreams() -{ - m_InStream.ReleaseStream(); - m_OutStream.ReleaseStream(); -} - -class CCopyDecoderFlusher -{ - CCopyDecoder *m_Decoder; -public: - CCopyDecoderFlusher(CCopyDecoder *decoder): m_Decoder(decoder) {} - ~CCopyDecoderFlusher() - { - m_Decoder->Flush(); - m_Decoder->ReleaseStreams(); - } -}; - -STDMETHODIMP CCopyDecoder::Code(ISequentialInStream *inStream, - ISequentialOutStream *outStream, - const UInt64 *inSize, const UInt64 *outSize, - ICompressProgressInfo *progress) -{ - if (outSize == NULL) - return E_INVALIDARG; - UInt64 size = *outSize; - - if (!m_OutStream.Create(1 << 20)) - return E_OUTOFMEMORY; - if (!m_InStream.Create(1 << 20)) - return E_OUTOFMEMORY; - - m_InStream.SetStream(inStream); - m_InStream.Init(m_ReservedSize, m_NumInDataBlocks); - m_OutStream.SetStream(outStream); - m_OutStream.Init(); - CCopyDecoderFlusher decoderFlusher(this); - - UInt64 nowPos64 = 0; - while(nowPos64 < size) - { - UInt32 blockSize; - bool dataAreCorrect; - RINOK(m_InStream.ReadBlock(blockSize, dataAreCorrect)); - if (!dataAreCorrect) - { - throw 123456; - } - for (UInt32 i = 0; i < blockSize; i++) - m_OutStream.WriteByte(m_InStream.ReadByte()); - nowPos64 += blockSize; - if (progress != NULL) - { - RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64)); - } - } - return S_OK; -} - -}} diff --git a/7zip/Archive/Cab/CabCopyDecoder.h b/7zip/Archive/Cab/CabCopyDecoder.h deleted file mode 100755 index 21545d39..00000000 --- a/7zip/Archive/Cab/CabCopyDecoder.h +++ /dev/null @@ -1,41 +0,0 @@ -// CabCopyDecoder.h - -#ifndef __ARCHIVE_CAB_COPY_DECODER_H -#define __ARCHIVE_CAB_COPY_DECODER_H - -#include "Common/MyCom.h" -#include "../../ICoder.h" -#include "../../Common/OutBuffer.h" -#include "CabInBuffer.h" - -namespace NArchive { -namespace NCab { - -class CCopyDecoder: - public ICompressCoder, - public CMyUnknownImp -{ - CInBuffer m_InStream; - COutBuffer m_OutStream; - Byte m_ReservedSize; - UInt32 m_NumInDataBlocks; -public: - MY_UNKNOWN_IMP - STDMETHOD(Code)(ISequentialInStream *inStream, - ISequentialOutStream *outStream, - const UInt64 *inSize, const UInt64 *outSize, - ICompressProgressInfo *progress); - - void ReleaseStreams(); - HRESULT Flush() { return m_OutStream.Flush(); } - void SetParams(Byte reservedSize, UInt32 numInDataBlocks) - { - m_ReservedSize = reservedSize; - m_NumInDataBlocks = numInDataBlocks; - } - -}; - -}} - -#endif \ No newline at end of file diff --git a/7zip/Archive/Cab/CabHandler.cpp b/7zip/Archive/Cab/CabHandler.cpp index 669de218..c3dd061f 100755 --- a/7zip/Archive/Cab/CabHandler.cpp +++ b/7zip/Archive/Cab/CabHandler.cpp @@ -1,9 +1,10 @@ -// Cab/Handler.cpp +// CabHandler.cpp #include "StdAfx.h" #include "Common/StringConvert.h" #include "Common/Defs.h" +#include "Common/Alloc.h" #include "Common/UTFConvert.h" #include "Common/ComTry.h" #include "Common/IntToString.h" @@ -11,32 +12,45 @@ #include "Windows/PropVariant.h" #include "Windows/Time.h" -#include "CabCopyDecoder.h" -#include "LZXDecoder.h" -#include "MSZipDecoder.h" - #include "CabHandler.h" +#include "CabBlockInStream.h" -#include "../../Common/ProgressUtils.h" +#include "../../Compress/Copy/CopyCoder.h" +#include "../../Compress/Deflate/DeflateDecoder.h" +#include "../../Compress/Lzx/LzxDecoder.h" +#include "../../Compress/Quantum/QuantumDecoder.h" using namespace NWindows; -using namespace NTime; namespace NArchive { namespace NCab { +// #define _CAB_DETAILS + +#ifdef _CAB_DETAILS +enum +{ + kpidBlockReal = kpidUserDefined, + kpidOffset, + kpidVolume, +}; +#endif + STATPROPSTG kProperties[] = { { NULL, kpidPath, VT_BSTR}, - { NULL, kpidIsFolder, VT_BOOL}, + // { NULL, kpidIsFolder, VT_BOOL}, { NULL, kpidSize, VT_UI8}, { NULL, kpidLastWriteTime, VT_FILETIME}, { NULL, kpidAttributes, VT_UI4}, - { NULL, kpidMethod, VT_BSTR}, - // { NULL, kpidDictionarySize, VT_UI4}, - - { NULL, kpidBlock, VT_UI4} + { NULL, kpidBlock, VT_I4} + #ifdef _CAB_DETAILS + , + { L"BlockReal", kpidBlockReal, VT_UI4}, + { L"Offset", kpidOffset, VT_UI4}, + { L"Volume", kpidVolume, VT_UI4} + #endif }; static const int kNumProperties = sizeof(kProperties) / sizeof(kProperties[0]); @@ -72,7 +86,10 @@ STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, const STATPROPSTG &srcItem = kProperties[index]; *propID = srcItem.propid; *varType = srcItem.vt; - *name = 0; + if (srcItem.lpwstrName == 0) + *name = 0; + else + *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } @@ -92,31 +109,35 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va { COM_TRY_BEGIN NWindows::NCOM::CPropVariant propVariant; - const CItem &fileInfo = m_Files[index]; + + const CMvItem &mvItem = m_Database.Items[index]; + const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex]; + int itemIndex = mvItem.ItemIndex; + const CItem &item = db.Items[itemIndex]; switch(propID) { case kpidPath: - if (fileInfo.IsNameUTF()) + if (item.IsNameUTF()) { UString unicodeName; - if (!ConvertUTF8ToUnicode(fileInfo.Name, unicodeName)) + if (!ConvertUTF8ToUnicode(item.Name, unicodeName)) propVariant = L""; else propVariant = unicodeName; } else - propVariant = MultiByteToUnicodeString(fileInfo.Name, CP_ACP); + propVariant = MultiByteToUnicodeString(item.Name, CP_ACP); break; case kpidIsFolder: - propVariant = fileInfo.IsDirectory(); + propVariant = item.IsDirectory(); break; case kpidSize: - propVariant = fileInfo.UnPackSize; + propVariant = item.Size; break; case kpidLastWriteTime: { FILETIME localFileTime, utcFileTime; - if (DosTimeToFileTime(fileInfo.Time, localFileTime)) + if (NTime::DosTimeToFileTime(item.Time, localFileTime)) { if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime)) utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; @@ -127,21 +148,17 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va break; } case kpidAttributes: - propVariant = fileInfo.GetWinAttributes(); + propVariant = item.GetWinAttributes(); break; case kpidMethod: { - UInt16 realFolderIndex = NHeader::NFolderIndex::GetRealFolderIndex( - m_Folders.Size(), fileInfo.FolderIndex); - const NHeader::CFolder &folder = m_Folders[realFolderIndex]; - UString method; + UInt16 realFolderIndex = item.GetFolderIndex(db.Folders.Size()); + const CFolder &folder = db.Folders[realFolderIndex]; int methodIndex = folder.GetCompressionMethod(); - if (methodIndex < kNumMethods) - method = kMethods[methodIndex]; - else - method = kUnknownMethod; - if (methodIndex == NHeader::NCompressionMethodMajor::kLZX) + UString method = (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod; + if (methodIndex == NHeader::NCompressionMethodMajor::kLZX || + methodIndex == NHeader::NCompressionMethodMajor::kQuantum) { method += L":"; wchar_t temp[32]; @@ -152,14 +169,29 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va break; } case kpidBlock: - propVariant = UInt32(fileInfo.FolderIndex); + propVariant = (Int32)m_Database.GetFolderIndex(&mvItem); break; + + #ifdef _CAB_DETAILS + + case kpidBlockReal: + propVariant = UInt32(item.FolderIndex); + break; + case kpidOffset: + propVariant = (UInt32)item.Offset; + break; + case kpidVolume: + propVariant = (UInt32)mvItem.VolumeIndex; + break; + + #endif } propVariant.Detach(value); return S_OK; COM_TRY_END } +/* class CPropgressImp: public CProgressVirt { CMyComPtr m_OpenArchiveCallback; @@ -183,36 +215,113 @@ STDMETHODIMP CPropgressImp::SetCompleted(const UInt64 *numFiles) return m_OpenArchiveCallback->SetCompleted(numFiles, NULL); return S_OK; } +*/ STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN - m_Stream.Release(); - // try + Close(); + HRESULT res; + CInArchive archive; + CMyComPtr openVolumeCallback; { - CInArchive archive; - m_Files.Clear(); - CPropgressImp progressImp; - progressImp.Init(openArchiveCallback); - RINOK(archive.Open(inStream, maxCheckStartPosition, - m_ArchiveInfo, m_Folders, m_Files, &progressImp)); - m_Stream = inStream; + CMyComPtr openArchiveCallbackWrap = openArchiveCallback; + openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback); + } + + CMyComPtr nextStream = inStream; + bool prevChecked = false; + UInt64 numItems = 0; + try + { + while(nextStream != 0) + { + CDatabaseEx db; + db.Stream = nextStream; + res = archive.Open(maxCheckStartPosition, db); + if (res == S_OK) + { + if (!m_Database.Volumes.IsEmpty()) + { + const CDatabaseEx &dbPrev = m_Database.Volumes[prevChecked ? m_Database.Volumes.Size() - 1 : 0]; + if (dbPrev.ArchiveInfo.SetID != db.ArchiveInfo.SetID || + dbPrev.ArchiveInfo.CabinetNumber + (prevChecked ? 1: - 1) != + db.ArchiveInfo.CabinetNumber) + res = S_FALSE; + } + } + if (res == S_OK) + m_Database.Volumes.Insert(prevChecked ? m_Database.Volumes.Size() : 0, db); + else if (res != S_FALSE) + return res; + else + { + if (m_Database.Volumes.IsEmpty()) + return S_FALSE; + if (prevChecked) + break; + prevChecked = true; + } + + numItems += db.Items.Size(); + RINOK(openArchiveCallback->SetCompleted(&numItems, NULL)); + + nextStream = 0; + while(true) + { + const COtherArchive *otherArchive = 0; + if (!prevChecked) + { + const CInArchiveInfo &ai = m_Database.Volumes.Front().ArchiveInfo; + if (ai.IsTherePrev()) + otherArchive = &ai.PreviousArchive; + else + prevChecked = true; + } + if (otherArchive == 0) + { + const CInArchiveInfo &ai = m_Database.Volumes.Back().ArchiveInfo; + if (ai.IsThereNext()) + otherArchive = &ai.NextArchive; + } + if (!otherArchive) + break; + const UString fullName = MultiByteToUnicodeString(otherArchive->FileName, CP_ACP); + HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream); + if (result == S_OK) + break; + if (result != S_FALSE) + return result; + if (prevChecked) + break; + prevChecked = true; + } + } + if (res == S_OK) + { + m_Database.FillSortAndShrink(); + if (!m_Database.Check()) + res = S_FALSE; + } } - /* catch(...) { - return S_FALSE; + res = S_FALSE; + } + if (res != S_OK) + { + Close(); + return res; } - */ COM_TRY_END return S_OK; } STDMETHODIMP CHandler::Close() { - m_Stream.Release(); + m_Database.Clear(); return S_OK; } @@ -224,405 +333,472 @@ public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); private: - const CObjectVector *m_Folders; - const CObjectVector *m_Files; - const CRecordVector *m_FileIndexes; + const CMvDatabaseEx *m_Database; const CRecordVector *m_ExtractStatuses; int m_StartIndex; int m_CurrentIndex; - int m_NumFiles; - UInt64 m_CurrentDataPos; CMyComPtr m_ExtractCallback; bool m_TestMode; - bool m_FileIsOpen; - CMyComPtr realOutStream; - UInt64 m_FilePos; + CMyComPtr m_RealOutStream; - HRESULT OpenFile(int indexIndex, ISequentialOutStream **realOutStream); - HRESULT WriteEmptyFiles(); - UInt64 m_StartImportantTotalUnPacked; + bool m_IsOk; + bool m_FileIsOpen; + UInt64 m_RemainFileSize; + UInt64 m_FolderSize; + UInt64 m_PosInFolder; + + HRESULT OpenFile(); + HRESULT Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK); public: + HRESULT WriteEmptyFiles(); + void Init( - const CObjectVector *folders, - const CObjectVector *files, - const CRecordVector *fileIndices, + const CMvDatabaseEx *database, const CRecordVector *extractStatuses, int startIndex, - int numFiles, + UInt64 folderSize, IArchiveExtractCallback *extractCallback, - UInt64 startImportantTotalUnPacked, bool testMode); HRESULT FlushCorrupted(); HRESULT Unsupported(); + + UInt64 GetRemain() const { return m_FolderSize - m_PosInFolder; } + UInt64 GetPosInFolder() const { return m_PosInFolder; } }; void CCabFolderOutStream::Init( - const CObjectVector *folders, - const CObjectVector *files, - const CRecordVector *fileIndices, + const CMvDatabaseEx *database, const CRecordVector *extractStatuses, int startIndex, - int numFiles, + UInt64 folderSize, IArchiveExtractCallback *extractCallback, - UInt64 startImportantTotalUnPacked, bool testMode) { - m_Folders = folders; - m_Files = files; - m_FileIndexes = fileIndices; + m_Database = database; m_ExtractStatuses = extractStatuses; m_StartIndex = startIndex; - m_NumFiles = numFiles; + m_FolderSize = folderSize; + m_ExtractCallback = extractCallback; - m_StartImportantTotalUnPacked = startImportantTotalUnPacked; m_TestMode = testMode; m_CurrentIndex = 0; + m_PosInFolder = 0; m_FileIsOpen = false; + m_IsOk = true; } -HRESULT CCabFolderOutStream::OpenFile(int indexIndex, ISequentialOutStream **realOutStream) +HRESULT CCabFolderOutStream::OpenFile() { - // RINOK(m_ExtractCallback->SetCompleted(&m_StartImportantTotalUnPacked)); - - int fullIndex = m_StartIndex + indexIndex; - - Int32 askMode; - if((*m_ExtractStatuses)[fullIndex]) - askMode = m_TestMode ? - NArchive::NExtract::NAskMode::kTest : - NArchive::NExtract::NAskMode::kExtract; - else + Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? (m_TestMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract) : + NExtract::NAskMode::kSkip; + RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode)); + if (!m_RealOutStream && !m_TestMode) askMode = NArchive::NExtract::NAskMode::kSkip; - - int index = (*m_FileIndexes)[fullIndex]; - const CItem &fileInfo = (*m_Files)[index]; - UInt16 realFolderIndex = NHeader::NFolderIndex::GetRealFolderIndex( - m_Folders->Size(), fileInfo.FolderIndex); - - RINOK(m_ExtractCallback->GetStream(index, realOutStream, askMode)); - - UInt64 currentUnPackSize = fileInfo.UnPackSize; - - bool mustBeProcessedAnywhere = (indexIndex < m_NumFiles - 1); - - if (realOutStream || mustBeProcessedAnywhere) - { - if (!realOutStream && !m_TestMode) - askMode = NArchive::NExtract::NAskMode::kSkip; - RINOK(m_ExtractCallback->PrepareOperation(askMode)); - return S_OK; - } - else - return S_FALSE; + return m_ExtractCallback->PrepareOperation(askMode); } - HRESULT CCabFolderOutStream::WriteEmptyFiles() { - for(;m_CurrentIndex < m_NumFiles; m_CurrentIndex++) + if (m_FileIsOpen) + return S_OK; + for(;m_CurrentIndex < m_ExtractStatuses->Size(); m_CurrentIndex++) { - int index = (*m_FileIndexes)[m_StartIndex + m_CurrentIndex]; - const CItem &fileInfo = (*m_Files)[index]; - if (fileInfo.UnPackSize != 0) + const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex]; + const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; + UInt64 fileSize = item.Size; + if (fileSize != 0) return S_OK; - realOutStream.Release(); - HRESULT result = OpenFile(m_CurrentIndex, &realOutStream); - realOutStream.Release(); - if (result == S_FALSE) - { - } - else if (result == S_OK) - { - RINOK(m_ExtractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); - } - else - return result; + HRESULT result = OpenFile(); + m_RealOutStream.Release(); + RINOK(result); + RINOK(m_ExtractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); } return S_OK; } -STDMETHODIMP CCabFolderOutStream::Write(const void *data, - UInt32 size, UInt32 *processedSize) +// This is Write function +HRESULT CCabFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK) { - UInt32 processedSizeReal = 0; - while(m_CurrentIndex < m_NumFiles) + UInt32 realProcessed = 0; + if (processedSize != NULL) + *processedSize = 0; + while(size != 0) { if (m_FileIsOpen) { - int index = (*m_FileIndexes)[m_StartIndex + m_CurrentIndex]; - const CItem &fileInfo = (*m_Files)[index]; - UInt64 fileSize = fileInfo.UnPackSize; - - UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - m_FilePos, - UInt64(size - processedSizeReal)); - - UInt32 processedSizeLocal; - if (!realOutStream) + UInt32 numBytesToWrite = (UInt32)MyMin(m_RemainFileSize, (UInt64)(size)); + HRESULT res = S_OK; + if (numBytesToWrite > 0) { - processedSizeLocal = numBytesToWrite; + if (!isOK) + m_IsOk = false; + if (m_RealOutStream) + { + UInt32 processedSizeLocal = 0; + res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal); + numBytesToWrite = processedSizeLocal; + } } - else + realProcessed += numBytesToWrite; + if (processedSize != NULL) + *processedSize = realProcessed; + data = (const void *)((const Byte *)data + numBytesToWrite); + size -= numBytesToWrite; + m_RemainFileSize -= numBytesToWrite; + m_PosInFolder += numBytesToWrite; + if (res != S_OK) + return res; + if (m_RemainFileSize == 0) { - RINOK(realOutStream->Write((const Byte *)data + processedSizeReal, numBytesToWrite, &processedSizeLocal)); - } - m_FilePos += processedSizeLocal; - processedSizeReal += processedSizeLocal; - if (m_FilePos == fileInfo.UnPackSize) - { - realOutStream.Release(); - RINOK(m_ExtractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + m_RealOutStream.Release(); + RINOK(m_ExtractCallback->SetOperationResult( + m_IsOk ? + NArchive::NExtract::NOperationResult::kOK: + NArchive::NExtract::NOperationResult::kDataError)); m_FileIsOpen = false; - m_CurrentIndex++; - } - if (processedSizeReal == size) - { - RINOK(WriteEmptyFiles()); - if (processedSize != NULL) - *processedSize = processedSizeReal; - return S_OK; } + if (realProcessed > 0) + break; // with this break this function works as Write-Part } else { - HRESULT result = OpenFile(m_CurrentIndex, &realOutStream); - if (result != S_FALSE && result != S_OK) - return result; - m_FileIsOpen = true; - m_FilePos = 0; + if (m_CurrentIndex >= m_ExtractStatuses->Size()) + return E_FAIL; + + const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex]; + const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; + + m_RemainFileSize = item.Size; + + UInt32 fileOffset = item.Offset; + if (fileOffset < m_PosInFolder) + return E_FAIL; + if (fileOffset > m_PosInFolder) + { + UInt32 numBytesToWrite = (UInt32)MyMin((UInt64)fileOffset - m_PosInFolder, UInt64(size)); + realProcessed += numBytesToWrite; + if (processedSize != NULL) + *processedSize = realProcessed; + data = (const void *)((const Byte *)data + numBytesToWrite); + size -= numBytesToWrite; + m_PosInFolder += numBytesToWrite; + } + if (fileOffset == m_PosInFolder) + { + RINOK(OpenFile()); + m_FileIsOpen = true; + m_CurrentIndex++; + m_IsOk = true; + } } } - if (processedSize != NULL) - *processedSize = size; - return S_OK; + return WriteEmptyFiles(); +} + +STDMETHODIMP CCabFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + return Write2(data, size, processedSize, true); } HRESULT CCabFolderOutStream::FlushCorrupted() { - // UInt32 processedSizeReal = 0; - while(m_CurrentIndex < m_NumFiles) + const UInt32 kBufferSize = (1 << 10); + Byte buffer[kBufferSize]; + for (int i = 0; i < kBufferSize; i++) + buffer[i] = 0; + while(true) { - if (m_FileIsOpen) - { - int index = (*m_FileIndexes)[m_StartIndex + m_CurrentIndex]; - const CItem &fileInfo = (*m_Files)[index]; - UInt64 fileSize = fileInfo.UnPackSize; - - realOutStream.Release(); - RINOK(m_ExtractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kCRCError)); - m_FileIsOpen = false; - m_CurrentIndex++; - } - else - { - HRESULT result = OpenFile(m_CurrentIndex, &realOutStream); - if (result != S_FALSE && result != S_OK) - return result; - m_FileIsOpen = true; - } + UInt64 remain = GetRemain(); + if (remain == 0) + return S_OK; + UInt32 size = (UInt32)MyMin(remain, (UInt64)kBufferSize); + UInt32 processedSizeLocal = 0; + RINOK(Write2(buffer, size, &processedSizeLocal, false)); } - return S_OK; } HRESULT CCabFolderOutStream::Unsupported() { - while(m_CurrentIndex < m_NumFiles) + while(m_CurrentIndex < m_ExtractStatuses->Size()) { - HRESULT result = OpenFile(m_CurrentIndex, &realOutStream); + HRESULT result = OpenFile(); if (result != S_FALSE && result != S_OK) return result; - realOutStream.Release(); + m_RealOutStream.Release(); RINOK(m_ExtractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); m_CurrentIndex++; } return S_OK; } -STDMETHODIMP CCabFolderOutStream::WritePart(const void *data, - UInt32 size, UInt32 *processedSize) -{ - return Write(data, size, processedSize); -} - STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 _aTestMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == UInt32(-1)); + bool allFilesMode = (numItems == (UInt32)(-1)); if (allFilesMode) - numItems = m_Files.Size(); + numItems = m_Database.Items.Size(); if(numItems == 0) return S_OK; bool testMode = (_aTestMode != 0); - UInt64 censoredTotalUnPacked = 0, importantTotalUnPacked = 0; + UInt64 totalUnPacked = 0; int lastIndex = 0; - CRecordVector folderIndexes; - CRecordVector importantIndices; - CRecordVector extractStatuses; UInt32 i; + int lastFolder = -2; + UInt64 lastFolderSize = 0; for(i = 0; i < numItems; i++) { int index = allFilesMode ? i : indices[i]; - const CItem &fileInfo = m_Files[index]; - censoredTotalUnPacked += fileInfo.UnPackSize; - - int folderIndex = fileInfo.FolderIndex; - if (folderIndexes.IsEmpty()) - folderIndexes.Add(folderIndex); - else - { - if (folderIndex != folderIndexes.Back()) - folderIndexes.Add(folderIndex); - } - - int j; - for(j = index - 1; j >= lastIndex; j--) - if(m_Files[j].FolderIndex != folderIndex) - break; - for(j++; j <= index; j++) - { - const CItem &fileInfo = m_Files[j]; - importantTotalUnPacked += fileInfo.UnPackSize; - importantIndices.Add(j); - extractStatuses.Add(j == index); - } - lastIndex = index + 1; + const CMvItem &mvItem = m_Database.Items[index]; + const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; + if (item.IsDirectory()) + continue; + int folderIndex = m_Database.GetFolderIndex(&mvItem); + if (folderIndex != lastFolder) + totalUnPacked += lastFolderSize; + lastFolder = folderIndex; + lastFolderSize = item.GetEndOffset(); } + totalUnPacked += lastFolderSize; - extractCallback->SetTotal(importantTotalUnPacked); - UInt64 currentImportantTotalUnPacked = 0; - UInt64 currentImportantTotalPacked = 0; + extractCallback->SetTotal(totalUnPacked); - CCopyDecoder *storeDecoderSpec = NULL; - CMyComPtr storeDecoder; + totalUnPacked = 0; - NMSZip::CDecoder *msZipDecoderSpec = NULL; - CMyComPtr msZipDecoder; + NCompress::CCopyCoder *copyCoderSpec = NULL; + CMyComPtr copyCoder; - NLZX::CDecoder *lzxDecoderSpec = NULL; + NCompress::NDeflate::NDecoder::CCOMCoder *deflateDecoderSpec = NULL; + CMyComPtr deflateDecoder; + + NCompress::NLzx::CDecoder *lzxDecoderSpec = NULL; CMyComPtr lzxDecoder; + NCompress::NQuantum::CDecoder *quantumDecoderSpec = NULL; + CMyComPtr quantumDecoder; - int curImportantIndexIndex = 0; - UInt64 totalFolderUnPacked; - for(i = 0; i < (UInt32)folderIndexes.Size(); i++, currentImportantTotalUnPacked += totalFolderUnPacked) + CCabBlockInStream *cabBlockInStreamSpec = new CCabBlockInStream(); + CMyComPtr cabBlockInStream = cabBlockInStreamSpec; + if (!cabBlockInStreamSpec->Create()) + return E_OUTOFMEMORY; + + CRecordVector extractStatuses; + for(i = 0; i < numItems;) { - int folderIndex = folderIndexes[i]; - UInt16 realFolderIndex = NHeader::NFolderIndex::GetRealFolderIndex( - m_Folders.Size(), folderIndex); + int index = allFilesMode ? i : indices[i]; - RINOK(extractCallback->SetCompleted(¤tImportantTotalUnPacked)); - totalFolderUnPacked = 0; - int j; - for (j = curImportantIndexIndex; j < importantIndices.Size(); j++) + const CMvItem &mvItem = m_Database.Items[index]; + const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex]; + int itemIndex = mvItem.ItemIndex; + const CItem &item = db.Items[itemIndex]; + + i++; + if (item.IsDirectory()) { - const CItem &fileInfo = m_Files[importantIndices[j]]; - if (fileInfo.FolderIndex != folderIndex) - break; - totalFolderUnPacked += fileInfo.UnPackSize; + Int32 askMode= testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + CMyComPtr realOutStream; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + RINOK(extractCallback->PrepareOperation(askMode)); + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + continue; } + int folderIndex = m_Database.GetFolderIndex(&mvItem); + if (folderIndex < 0) + { + // If we need previous archive + Int32 askMode= testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + CMyComPtr realOutStream; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + RINOK(extractCallback->PrepareOperation(askMode)); + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kDataError)); + continue; + } + int startIndex2 = m_Database.FolderStartFileIndex[folderIndex]; + int 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]; + const CMvItem &mvItem = m_Database.Items[indexNext]; + const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; + if (item.IsDirectory()) + continue; + int newFolderIndex = m_Database.GetFolderIndex(&mvItem); + + if (newFolderIndex != folderIndex) + break; + for (; startIndex < indexNext; startIndex++) + extractStatuses.Add(false); + extractStatuses.Add(true); + startIndex++; + curUnpack = item.GetEndOffset(); + } + + RINOK(extractCallback->SetCompleted(&totalUnPacked)); - CCabFolderOutStream *cabFolderOutStream = new CCabFolderOutStream; + CCabFolderOutStream *cabFolderOutStream = new CCabFolderOutStream; CMyComPtr outStream(cabFolderOutStream); - const NHeader::CFolder &folder = m_Folders[realFolderIndex]; + const CFolder &folder = db.Folders[item.GetFolderIndex(db.Folders.Size())]; - cabFolderOutStream->Init(&m_Folders, &m_Files, &importantIndices, - &extractStatuses, curImportantIndexIndex, j - curImportantIndexIndex, - extractCallback, currentImportantTotalUnPacked, - folder.GetCompressionMethod() == NHeader::NCompressionMethodMajor::kQuantum? - true: testMode); - - curImportantIndexIndex = j; - - UInt64 pos = folder.DataStart; // test it (+ archiveStart) - RINOK(m_Stream->Seek(pos, STREAM_SEEK_SET, NULL)); - - CLocalProgress *localProgressSpec = new CLocalProgress; - CMyComPtr progress = localProgressSpec; - localProgressSpec->Init(extractCallback, false); - - CLocalCompressProgressInfo *localCompressProgressSpec = - new CLocalCompressProgressInfo; - CMyComPtr compressProgress = localCompressProgressSpec; - localCompressProgressSpec->Init(progress, - NULL, ¤tImportantTotalUnPacked); - - Byte reservedSize = m_ArchiveInfo.ReserveBlockPresent() ? - m_ArchiveInfo.PerDataSizes.PerDatablockAreaSize : 0; + cabFolderOutStream->Init(&m_Database, &extractStatuses, startIndex2, + curUnpack, extractCallback, testMode); + cabBlockInStreamSpec->MsZip = false; switch(folder.GetCompressionMethod()) { case NHeader::NCompressionMethodMajor::kNone: - { - if(storeDecoderSpec == NULL) + if(copyCoderSpec == NULL) { - storeDecoderSpec = new CCopyDecoder; - storeDecoder = storeDecoderSpec; - } - try - { - storeDecoderSpec->SetParams(reservedSize, folder.NumDataBlocks); - RINOK(storeDecoder->Code(m_Stream, outStream, - NULL, &totalFolderUnPacked, compressProgress)); - } - catch(...) - { - RINOK(cabFolderOutStream->FlushCorrupted()); - continue; + copyCoderSpec = new NCompress::CCopyCoder; + copyCoder = copyCoderSpec; } break; - } case NHeader::NCompressionMethodMajor::kMSZip: - { - if(lzxDecoderSpec == NULL) + if(deflateDecoderSpec == NULL) { - msZipDecoderSpec = new NMSZip::CDecoder; - msZipDecoder = msZipDecoderSpec; - } - try - { - msZipDecoderSpec->SetParams(reservedSize, folder.NumDataBlocks); - RINOK(msZipDecoder->Code(m_Stream, outStream, - NULL, &totalFolderUnPacked, compressProgress)); - } - catch(...) - { - RINOK(cabFolderOutStream->FlushCorrupted()); - continue; + deflateDecoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder; + deflateDecoder = deflateDecoderSpec; } + cabBlockInStreamSpec->MsZip = true; break; - } case NHeader::NCompressionMethodMajor::kLZX: - { if(lzxDecoderSpec == NULL) { - lzxDecoderSpec = new NLZX::CDecoder; + lzxDecoderSpec = new NCompress::NLzx::CDecoder; lzxDecoder = lzxDecoderSpec; } - try + RINOK(lzxDecoderSpec->SetParams(folder.CompressionTypeMinor)); + break; + case NHeader::NCompressionMethodMajor::kQuantum: + if(quantumDecoderSpec == NULL) { - lzxDecoderSpec->SetParams(reservedSize, folder.NumDataBlocks, - folder.CompressionTypeMinor); - RINOK(lzxDecoder->Code(m_Stream, outStream, - NULL, &totalFolderUnPacked, compressProgress)); + quantumDecoderSpec = new NCompress::NQuantum::CDecoder; + quantumDecoder = quantumDecoderSpec; } - catch(...) + quantumDecoderSpec->SetParams(folder.CompressionTypeMinor); + break; + default: + { + RINOK(cabFolderOutStream->Unsupported()); + totalUnPacked += curUnpack; + continue; + } + } + + cabBlockInStreamSpec->InitForNewFolder(); + + HRESULT res = S_OK; + + { + int volIndex = mvItem.VolumeIndex; + int locFolderIndex = item.GetFolderIndex(db.Folders.Size()); + bool keepHistory = false; + bool keepInputBuffer = false; + for (UInt32 f = 0; cabFolderOutStream->GetRemain() != 0;) + { + if (volIndex >= m_Database.Volumes.Size()) { - RINOK(cabFolderOutStream->FlushCorrupted()); + res = S_FALSE; + break; + } + + const CDatabaseEx &db = m_Database.Volumes[volIndex]; + const CFolder &folder = db.Folders[locFolderIndex]; + if (f == 0) + { + cabBlockInStreamSpec->SetStream(db.Stream); + cabBlockInStreamSpec->ReservedSize = db.ArchiveInfo.GetDataBlockReserveSize(); + RINOK(db.Stream->Seek(db.StartPosition + folder.DataStart, STREAM_SEEK_SET, NULL)); + } + if (f == folder.NumDataBlocks) + { + volIndex++; + locFolderIndex = 0; + f = 0; continue; } - break; + f++; + + cabBlockInStreamSpec->DataError = false; + + if (!keepInputBuffer) + cabBlockInStreamSpec->InitForNewBlock(); + + UInt32 packSize, unpackSize; + res = cabBlockInStreamSpec->PreRead(packSize, unpackSize); + if (res == S_FALSE) + break; + RINOK(res); + keepInputBuffer = (unpackSize == 0); + if (keepInputBuffer) + continue; + + + UInt64 totalUnPacked2 = totalUnPacked + cabFolderOutStream->GetPosInFolder(); + RINOK(extractCallback->SetCompleted(&totalUnPacked2)); + UInt64 unpackRemain = cabFolderOutStream->GetRemain(); + + const UInt32 kBlockSizeMax = (1 << 15); + if (unpackRemain > kBlockSizeMax) + unpackRemain = kBlockSizeMax; + if (unpackRemain > unpackSize) + unpackRemain = unpackSize; + + switch(folder.GetCompressionMethod()) + { + case NHeader::NCompressionMethodMajor::kNone: + res = copyCoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL); + break; + case NHeader::NCompressionMethodMajor::kMSZip: + deflateDecoderSpec->SetKeepHistory(keepHistory); + res = deflateDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL); + break; + case NHeader::NCompressionMethodMajor::kLZX: + lzxDecoderSpec->SetKeepHistory(keepHistory, cabBlockInStreamSpec->GetAlign()); + res = lzxDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL); + break; + case NHeader::NCompressionMethodMajor::kQuantum: + quantumDecoderSpec->SetKeepHistory(keepHistory); + 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()); } - default: - RINOK(cabFolderOutStream->Unsupported()); - // return E_FAIL; } + if (res != S_OK || cabFolderOutStream->GetRemain() != 0) + { + RINOK(cabFolderOutStream->FlushCorrupted()); + } + totalUnPacked += curUnpack; } return S_OK; COM_TRY_END @@ -631,9 +807,9 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { COM_TRY_BEGIN - *numItems = m_Files.Size(); + *numItems = m_Database.Items.Size(); return S_OK; COM_TRY_END } -}} \ No newline at end of file +}} diff --git a/7zip/Archive/Cab/CabHandler.h b/7zip/Archive/Cab/CabHandler.h index 584dadf8..2c14d468 100755 --- a/7zip/Archive/Cab/CabHandler.h +++ b/7zip/Archive/Cab/CabHandler.h @@ -37,10 +37,7 @@ public: BSTR *name, PROPID *propID, VARTYPE *varType); private: - CObjectVector m_Folders; - CObjectVector m_Files; - CInArchiveInfo m_ArchiveInfo; - CMyComPtr m_Stream; + CMvDatabaseEx m_Database; }; }} diff --git a/7zip/Archive/Cab/CabHeader.h b/7zip/Archive/Cab/CabHeader.h index 2eac96bf..5c122743 100755 --- a/7zip/Archive/Cab/CabHeader.h +++ b/7zip/Archive/Cab/CabHeader.h @@ -9,53 +9,15 @@ namespace NArchive { namespace NCab { namespace NHeader{ -namespace NArchive { - +namespace NArchive +{ extern UInt32 kSignature; - namespace NFlags { const int kPrevCabinet = 0x0001; const int kNextCabinet = 0x0002; const int kReservePresent = 0x0004; } - - const UInt32 kArchiveHeaderSize = 36; - /* - struct CBlock - { - UInt32 Signature; // cabinet file signature - UInt32 Reserved1; // reserved - UInt32 Size; // size of this cabinet file in bytes - UInt32 Reserved2; // reserved - UInt32 FileOffset; // offset of the first CFFILE entry - UInt32 Reserved3; // reserved - Byte VersionMinor; // cabinet file format version, minor - Byte VersionMajor; // cabinet file format version, major - UInt16 NumFolders; // number of CFFOLDER entries in this cabinet - UInt16 NumFiles; // number of CFFILE entries in this cabinet - UInt16 Flags; // cabinet file option indicators - UInt16 SetID; // must be the same for all cabinets in a set - UInt16 CabinetNumber; // number of this cabinet file in a set - }; - */ - - const UInt32 kPerDataSizesHeaderSize = 4; - - struct CPerDataSizes - { - UInt16 PerCabinetAreaSize; // (optional) size of per-cabinet reserved area - Byte PerFolderAreaSize; // (optional) size of per-folder reserved area - Byte PerDatablockAreaSize; // (optional) size of per-datablock reserved area - }; - - /* - Byte abReserve[]; // (optional) per-cabinet reserved area - Byte szCabinetPrev[]; // (optional) name of previous cabinet file - Byte szDiskPrev[]; // (optional) name of previous disk - Byte szCabinetNext[]; // (optional) name of next cabinet file - Byte szDiskNext[]; // (optional) name of next disk - */ } namespace NCompressionMethodMajor @@ -66,17 +28,6 @@ namespace NCompressionMethodMajor const Byte kLZX = 3; } -const UInt32 kFolderHeaderSize = 8; -struct CFolder -{ - UInt32 DataStart; // offset of the first CFDATA block in this folder - UInt16 NumDataBlocks; // number of CFDATA blocks in this folder - Byte CompressionTypeMajor; - Byte CompressionTypeMinor; - // Byte abReserve[]; // (optional) per-folder reserved area - Byte GetCompressionMethod() const { return CompressionTypeMajor & 0xF; } -}; - const int kFileNameIsUTFAttributeMask = 0x80; namespace NFolderIndex @@ -84,34 +35,8 @@ namespace NFolderIndex const int kContinuedFromPrev = 0xFFFD; const int kContinuedToNext = 0xFFFE; const int kContinuedPrevAndNext = 0xFFFF; - inline UInt16 GetRealFolderIndex(UInt16 aNumFolders, UInt16 aFolderIndex) - { - switch(aFolderIndex) - { - case kContinuedFromPrev: - return 0; - case kContinuedToNext: - case kContinuedPrevAndNext: - return aNumFolders - 1; - default: - return aFolderIndex; - } - } } -const UInt32 kFileHeaderSize = 16; -/* -struct CFile -{ - UInt32 UnPackSize; // uncompressed size of this file in bytes - UInt32 UnPackOffset; // uncompressed offset of this file in the folder - UInt16 FolderIndex; // index into the CFFOLDER area - UInt16 PureDate; - UInt16 PureTime; // Time - UInt16 Attributes; // attribute flags for this file - Byte szName[]; // name of this file -}; -*/ }}} #endif diff --git a/7zip/Archive/Cab/CabIn.cpp b/7zip/Archive/Cab/CabIn.cpp index a9d40726..1d47502c 100755 --- a/7zip/Archive/Cab/CabIn.cpp +++ b/7zip/Archive/Cab/CabIn.cpp @@ -6,7 +6,8 @@ #include "Common/MyCom.h" #include "CabIn.h" #include "Windows/Defs.h" -#include "../../Common/InBuffer.h" + +#include "../../Common/StreamUtils.h" namespace NArchive{ namespace NCab{ @@ -14,7 +15,7 @@ namespace NCab{ static HRESULT ReadBytes(IInStream *inStream, void *data, UInt32 size) { UInt32 realProcessedSize; - RINOK(inStream->Read(data, size, &realProcessedSize)); + RINOK(ReadStream(inStream, data, size, &realProcessedSize)); if(realProcessedSize != size) return S_FALSE; return S_OK; @@ -23,7 +24,7 @@ static HRESULT ReadBytes(IInStream *inStream, void *data, UInt32 size) static HRESULT SafeRead(IInStream *inStream, void *data, UInt32 size) { UInt32 realProcessedSize; - RINOK(inStream->Read(data, size, &realProcessedSize)); + RINOK(ReadStream(inStream, data, size, &realProcessedSize)); if(realProcessedSize != size) throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive); return S_OK; @@ -37,25 +38,12 @@ static void SafeInByteRead(::CInBuffer &inBuffer, void *data, UInt32 size) throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive); } -static void SafeReadName(::CInBuffer &inBuffer, AString &name) -{ - name.Empty(); - while(true) - { - Byte b; - if (!inBuffer.ReadByte(b)) - throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive); - if (b == 0) - return; - name += char(b); - } -} - Byte CInArchive::ReadByte() { - if (_blockPos >= _blockSize) - throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive); - return _block[_blockPos++]; + Byte b; + if (!inBuffer.ReadByte(b)) + throw CInArchiveException(CInArchiveException::kUnsupported); + return b; } UInt16 CInArchive::ReadUInt16() @@ -80,20 +68,38 @@ UInt32 CInArchive::ReadUInt32() return value; } -HRESULT CInArchive::Open(IInStream *inStream, - const UInt64 *searchHeaderSizeLimit, - CInArchiveInfo &inArchiveInfo, - CObjectVector &folders, - CObjectVector &files, - CProgressVirt *progressVirt) +AString CInArchive::SafeReadName() { - UInt64 startPosition; - RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &startPosition)); + AString name; + while(true) + { + Byte b = ReadByte(); + if (b == 0) + return name; + name += (char)b; + } +} - // NHeader::NArchive::CBlock archiveHeader; +void CInArchive::ReadOtherArchive(COtherArchive &oa) +{ + oa.FileName = SafeReadName(); + oa.DiskName = SafeReadName(); +} + +void CInArchive::Skeep(size_t size) +{ + while (size-- != 0) + ReadByte(); +} + +HRESULT CInArchive::Open2(IInStream *inStream, + const UInt64 *searchHeaderSizeLimit, + CDatabase &database) +{ + database.Clear(); + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &database.StartPosition)); { - ::CInBuffer inBuffer; if (!inBuffer.Create(1 << 17)) return E_OUTOFMEMORY; inBuffer.SetStream(inStream); @@ -117,141 +123,219 @@ HRESULT CInArchive::Open(IInStream *inStream, return S_FALSE; } } - startPosition += inBuffer.GetProcessedSize() - kSignatureSize; + database.StartPosition += inBuffer.GetProcessedSize() - kSignatureSize; } - RINOK(inStream->Seek(startPosition, STREAM_SEEK_SET, NULL)); - RINOK(ReadBytes(inStream, _block, NHeader::NArchive::kArchiveHeaderSize)); - _blockSize = NHeader::NArchive::kArchiveHeaderSize; - _blockPos = 0; + CInArchiveInfo &archiveInfo = database.ArchiveInfo; - ReadUInt32(); // Signature; // cabinet file signature - // if (archiveHeader.Signature != NHeader::NArchive::kSignature) - // return S_FALSE; + archiveInfo.Size = ReadUInt32(); // size of this cabinet file in bytes + if (ReadUInt32() != 0) + return S_FALSE; + archiveInfo.FileHeadersOffset = ReadUInt32(); // offset of the first CFFILE entry + if (ReadUInt32() != 0) + return S_FALSE; - UInt32 reserved1 = ReadUInt32(); - UInt32 size = ReadUInt32(); // size of this cabinet file in bytes - UInt32 reserved2 = ReadUInt32(); - UInt32 fileOffset = ReadUInt32(); // offset of the first CFFILE entry - UInt32 reserved3 = ReadUInt32(); + archiveInfo.VersionMinor = ReadByte(); // cabinet file format version, minor + archiveInfo.VersionMajor = ReadByte(); // cabinet file format version, major + archiveInfo.NumFolders = ReadUInt16(); // number of CFFOLDER entries in this cabinet + archiveInfo.NumFiles = ReadUInt16(); // number of CFFILE entries in this cabinet + archiveInfo.Flags = ReadUInt16(); // number of CFFILE entries in this cabinet + archiveInfo.SetID = ReadUInt16(); // must be the same for all cabinets in a set + archiveInfo.CabinetNumber = ReadUInt16(); // number of this cabinet file in a set - inArchiveInfo.VersionMinor = ReadByte(); // cabinet file format version, minor - inArchiveInfo.VersionMajor = ReadByte(); // cabinet file format version, major - inArchiveInfo.NumFolders = ReadUInt16(); // number of CFFOLDER entries in this cabinet - inArchiveInfo.NumFiles = ReadUInt16(); // number of CFFILE entries in this cabinet - inArchiveInfo.Flags = ReadUInt16(); // number of CFFILE entries in this cabinet - UInt16 setID = ReadUInt16(); // must be the same for all cabinets in a set - UInt16 cabinetNumber = ReadUInt16(); // number of this cabinet file in a set - - if (reserved1 != 0 || reserved2 != 0 || reserved3 != 0) - throw CInArchiveException(CInArchiveException::kUnsupported); - - if (inArchiveInfo.ReserveBlockPresent()) + if (archiveInfo.ReserveBlockPresent()) { - RINOK(SafeRead(inStream, _block, NHeader::NArchive::kPerDataSizesHeaderSize)); - _blockSize = NHeader::NArchive::kPerDataSizesHeaderSize; - _blockPos = 0; + archiveInfo.PerCabinetAreaSize = ReadUInt16(); // (optional) size of per-cabinet reserved area + archiveInfo.PerFolderAreaSize = ReadByte(); // (optional) size of per-folder reserved area + archiveInfo.PerDataBlockAreaSize = ReadByte(); // (optional) size of per-datablock reserved area - inArchiveInfo.PerDataSizes.PerCabinetAreaSize = ReadUInt16(); // (optional) size of per-cabinet reserved area - inArchiveInfo.PerDataSizes.PerFolderAreaSize = ReadByte(); // (optional) size of per-folder reserved area - inArchiveInfo.PerDataSizes.PerDatablockAreaSize = ReadByte(); // (optional) size of per-datablock reserved area - RINOK(inStream->Seek(inArchiveInfo.PerDataSizes.PerCabinetAreaSize, - STREAM_SEEK_CUR, NULL)); + Skeep(archiveInfo.PerCabinetAreaSize); } { - UInt64 foldersStartPosition; - RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &foldersStartPosition)); - ::CInBuffer inBuffer; - if (!inBuffer.Create(1 << 17)) - return E_OUTOFMEMORY; - inBuffer.SetStream(inStream); - inBuffer.Init(); - if ((inArchiveInfo.Flags & NHeader::NArchive::NFlags::kPrevCabinet) != 0) - { - SafeReadName(inBuffer, inArchiveInfo.PreviousCabinetName); - SafeReadName(inBuffer, inArchiveInfo.PreviousDiskName); - } - if ((inArchiveInfo.Flags & NHeader::NArchive::NFlags::kNextCabinet) != 0) - { - SafeReadName(inBuffer, inArchiveInfo.NextCabinetName); - SafeReadName(inBuffer, inArchiveInfo.NextDiskName); - } - foldersStartPosition += inBuffer.GetProcessedSize(); - RINOK(inStream->Seek(foldersStartPosition, STREAM_SEEK_SET, NULL)); + if (archiveInfo.IsTherePrev()) + ReadOtherArchive(archiveInfo.PreviousArchive); + if (archiveInfo.IsThereNext()) + ReadOtherArchive(archiveInfo.NextArchive); } - if (progressVirt != NULL) - { - UInt64 numFiles = inArchiveInfo.NumFiles; - RINOK(progressVirt->SetTotal(&numFiles)); - } - folders.Clear(); int i; - for(i = 0; i < inArchiveInfo.NumFolders; i++) + for(i = 0; i < archiveInfo.NumFolders; i++) { - if (progressVirt != NULL) - { - UInt64 numFiles = 0; - RINOK(progressVirt->SetCompleted(&numFiles)); - } - NHeader::CFolder folder; - RINOK(SafeRead(inStream, _block, NHeader::kFolderHeaderSize)); - _blockSize = NHeader::kFolderHeaderSize; - _blockPos = 0; + CFolder folder; folder.DataStart = ReadUInt32(); folder.NumDataBlocks = ReadUInt16(); folder.CompressionTypeMajor = ReadByte(); folder.CompressionTypeMinor = ReadByte(); - if (inArchiveInfo.ReserveBlockPresent()) - { - RINOK(inStream->Seek( - inArchiveInfo.PerDataSizes.PerFolderAreaSize, STREAM_SEEK_CUR, NULL)); - } - folder.DataStart += (UInt32)startPosition; - folders.Add(folder); + Skeep(archiveInfo.PerFolderAreaSize); + database.Folders.Add(folder); } - RINOK(inStream->Seek(startPosition + fileOffset, - STREAM_SEEK_SET, NULL)); + RINOK(inStream->Seek(database.StartPosition + archiveInfo.FileHeadersOffset, STREAM_SEEK_SET, NULL)); - ::CInBuffer inBuffer; - if (!inBuffer.Create(1 << 17)) - return E_OUTOFMEMORY; inBuffer.SetStream(inStream); inBuffer.Init(); - files.Clear(); - if (progressVirt != NULL) + for(i = 0; i < archiveInfo.NumFiles; i++) { - UInt64 numFiles = files.Size(); - RINOK(progressVirt->SetCompleted(&numFiles)); - } - for(i = 0; i < inArchiveInfo.NumFiles; i++) - { - SafeInByteRead(inBuffer, _block, NHeader::kFileHeaderSize); - _blockSize = NHeader::kFileHeaderSize; - _blockPos = 0; CItem item; - item.UnPackSize = ReadUInt32(); - item.UnPackOffset = ReadUInt32(); + item.Size = ReadUInt32(); + item.Offset = ReadUInt32(); item.FolderIndex = ReadUInt16(); - if (item.FolderIndex > inArchiveInfo.NumFolders) - return S_FALSE; UInt16 pureDate = ReadUInt16(); UInt16 pureTime = ReadUInt16(); item.Time = ((UInt32(pureDate) << 16)) | pureTime; item.Attributes = ReadUInt16(); - SafeReadName(inBuffer, item.Name); - files.Add(item); - if (progressVirt != NULL) - { - UInt64 numFiles = files.Size(); - RINOK(progressVirt->SetCompleted(&numFiles)); - } + item.Name = SafeReadName(); + int folderIndex = item.GetFolderIndex(database.Folders.Size()); + if (folderIndex >= database.Folders.Size()) + return S_FALSE; + database.Items.Add(item); } return S_OK; } +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + +HRESULT CInArchive::Open( + const UInt64 *searchHeaderSizeLimit, + CDatabaseEx &database) +{ + return Open2(database.Stream, searchHeaderSizeLimit, database); +} + + +static int CompareMvItems2(const CMvItem *p1, const CMvItem *p2) +{ + RINOZ(MyCompare(p1->VolumeIndex, p2->VolumeIndex)); + return MyCompare(p1->ItemIndex, p2->ItemIndex); +} + +static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param) +{ + const CMvDatabaseEx &mvDb = *(const CMvDatabaseEx *)param; + const CDatabaseEx &db1 = mvDb.Volumes[p1->VolumeIndex]; + const CDatabaseEx &db2 = mvDb.Volumes[p2->VolumeIndex]; + const CItem &item1 = db1.Items[p1->ItemIndex]; + const CItem &item2 = db2.Items[p2->ItemIndex];; + bool isDir1 = item1.IsDirectory(); + bool isDir2 = item2.IsDirectory(); + if (isDir1 && !isDir2) + return -1; + if (isDir2 && !isDir1) + return 1; + int f1 = mvDb.GetFolderIndex(p1); + int f2 = mvDb.GetFolderIndex(p2); + RINOZ(MyCompare(f1, f2)); + RINOZ(MyCompare(item1.Offset, item2.Offset)); + RINOZ(MyCompare(item1.Size, item2.Size)); + return CompareMvItems2(p1, p2); +} + +bool CMvDatabaseEx::AreItemsEqual(int i1, int i2) +{ + const CMvItem *p1 = &Items[i1]; + const CMvItem *p2 = &Items[i2]; + const CDatabaseEx &db1 = Volumes[p1->VolumeIndex]; + const CDatabaseEx &db2 = Volumes[p2->VolumeIndex]; + const CItem &item1 = db1.Items[p1->ItemIndex]; + const CItem &item2 = db2.Items[p2->ItemIndex];; + int f1 = GetFolderIndex(p1); + int f2 = GetFolderIndex(p2); + if (f1 != f2) + return false; + if (item1.Offset != item2.Offset) + return false; + if (item1.Size != item2.Size) + return false; + + return true; +} + +void CMvDatabaseEx::FillSortAndShrink() +{ + Items.Clear(); + StartFolderOfVol.Clear(); + FolderStartFileIndex.Clear(); + int offset = 0; + for (int v = 0; v < Volumes.Size(); v++) + { + const CDatabaseEx &db = Volumes[v]; + int curOffset = offset; + if (db.IsTherePrevFolder()) + curOffset--; + StartFolderOfVol.Add(curOffset); + offset += db.GetNumberOfNewFolders(); + + CMvItem mvItem; + mvItem.VolumeIndex = v; + for (int i = 0 ; i < db.Items.Size(); i++) + { + mvItem.ItemIndex = i; + Items.Add(mvItem); + } + } + + Items.Sort(CompareMvItems, (void *)this); + int j = 1; + int i; + for (i = 1; i < Items.Size(); i++) + if (!AreItemsEqual(i, i -1)) + Items[j++] = Items[i]; + Items.DeleteFrom(j); + + for (i = 0; i < Items.Size(); i++) + { + const CMvItem &mvItem = Items[i]; + int folderIndex = GetFolderIndex(&mvItem); + if (folderIndex >= FolderStartFileIndex.Size()) + FolderStartFileIndex.Add(i); + } +} + +bool CMvDatabaseEx::Check() +{ + for (int v = 1; v < Volumes.Size(); v++) + { + const CDatabaseEx &db1 = Volumes[v]; + if (db1.IsTherePrevFolder()) + { + const CDatabaseEx &db0 = Volumes[v - 1]; + if (db0.Folders.IsEmpty() || db1.Folders.IsEmpty()) + return false; + const CFolder &f0 = db0.Folders.Back(); + const CFolder &f1 = db1.Folders.Front(); + if (f0.CompressionTypeMajor != f1.CompressionTypeMajor || + f0.CompressionTypeMinor != f1.CompressionTypeMinor) + return false; + } + } + UInt64 maxPos = 0; + int prevFolder = -2; + for(int i = 0; i < Items.Size(); i++) + { + const CMvItem &mvItem = Items[i]; + int fIndex = GetFolderIndex(&mvItem); + if (fIndex >= FolderStartFileIndex.Size()) + return false; + const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; + if (item.IsDirectory()) + continue; + int folderIndex = GetFolderIndex(&mvItem); + if (folderIndex != prevFolder) + { + prevFolder = folderIndex; + maxPos = 0; + continue; + } + if (item.Offset < maxPos) + return false; + maxPos = item.GetEndOffset(); + if (maxPos < item.Offset) + return false; + } + return true; +} + }} diff --git a/7zip/Archive/Cab/CabIn.h b/7zip/Archive/Cab/CabIn.h index 82a9ea0d..4e817e94 100755 --- a/7zip/Archive/Cab/CabIn.h +++ b/7zip/Archive/Cab/CabIn.h @@ -4,6 +4,7 @@ #define __ARCHIVE_CAB_IN_H #include "../../IStream.h" +#include "../../Common/InBuffer.h" #include "CabHeader.h" #include "CabItem.h" @@ -22,10 +23,14 @@ public: CInArchiveException(CCauseType cause) : Cause(cause) {} }; -class CInArchiveInfo +struct COtherArchive +{ + AString FileName; + AString DiskName; +}; + +struct CArchiveInfo { -public: - UInt32 Size; /* size of this cabinet file in bytes */ Byte VersionMinor; /* cabinet file format version, minor */ Byte VersionMajor; /* cabinet file format version, major */ UInt16 NumFolders; /* number of CFFOLDER entries in this cabinet */ @@ -35,39 +40,125 @@ public: UInt16 CabinetNumber; /* number of this cabinet file in a set */ bool ReserveBlockPresent() const { return (Flags & NHeader::NArchive::NFlags::kReservePresent) != 0; } - NHeader::NArchive::CPerDataSizes PerDataSizes; - AString PreviousCabinetName; - AString PreviousDiskName; - AString NextCabinetName; - AString NextDiskName; + bool IsTherePrev() const { return (Flags & NHeader::NArchive::NFlags::kPrevCabinet) != 0; } + bool IsThereNext() const { return (Flags & NHeader::NArchive::NFlags::kNextCabinet) != 0; } + + UInt16 PerCabinetAreaSize; // (optional) size of per-cabinet reserved area + Byte PerFolderAreaSize; // (optional) size of per-folder reserved area + Byte PerDataBlockAreaSize; // (optional) size of per-datablock reserved area + + Byte GetDataBlockReserveSize() const { return (Byte)(ReserveBlockPresent() ? PerDataBlockAreaSize : 0); } + + COtherArchive PreviousArchive; + COtherArchive NextArchive; + + CArchiveInfo() + { + Clear(); + } + + void Clear() + { + PerCabinetAreaSize = 0; + PerFolderAreaSize = 0; + PerDataBlockAreaSize = 0; + } }; -class CProgressVirt +struct CInArchiveInfo: public CArchiveInfo +{ + UInt32 Size; /* size of this cabinet file in bytes */ + UInt32 FileHeadersOffset; //offset of the first CFFILE entry +}; + + +class CDatabase { public: - STDMETHOD(SetTotal)(const UInt64 *numFiles) PURE; - STDMETHOD(SetCompleted)(const UInt64 *numFiles) PURE; + UInt64 StartPosition; + CInArchiveInfo ArchiveInfo; + CObjectVector Folders; + CObjectVector Items; + void Clear() + { + ArchiveInfo.Clear(); + Folders.Clear(); + Items.Clear(); + } + bool IsTherePrevFolder() const + { + for (int i = 0; i < Items.Size(); i++) + if (Items[i].ContinuedFromPrev()) + return true; + return false; + } + int GetNumberOfNewFolders() const + { + int res = Folders.Size(); + if (IsTherePrevFolder()) + res--; + return res; + } + UInt32 GetFileOffset(int index) const { return Items[index].Offset; } + UInt32 GetFileSize(int index) const { return Items[index].Size; } }; -const UInt32 kMaxBlockSize = NHeader::NArchive::kArchiveHeaderSize; +class CDatabaseEx: public CDatabase +{ +public: + CMyComPtr Stream; +}; + +struct CMvItem +{ + int VolumeIndex; + int ItemIndex; +}; + +class CMvDatabaseEx +{ + bool AreItemsEqual(int i1, int i2); +public: + CObjectVector Volumes; + CRecordVector Items; + CRecordVector StartFolderOfVol; + CRecordVector FolderStartFileIndex; + int GetFolderIndex(const CMvItem *mvi) const + { + const CDatabaseEx &db = Volumes[mvi->VolumeIndex]; + return StartFolderOfVol[mvi->VolumeIndex] + + db.Items[mvi->ItemIndex].GetFolderIndex(db.Folders.Size()); + } + void Clear() + { + Volumes.Clear(); + Items.Clear(); + StartFolderOfVol.Clear(); + FolderStartFileIndex.Clear(); + } + void FillSortAndShrink(); + bool Check(); +}; class CInArchive { - UInt16 _blockSize; - Byte _block[kMaxBlockSize]; - UInt32 _blockPos; + CInBuffer inBuffer; Byte ReadByte(); UInt16 ReadUInt16(); UInt32 ReadUInt32(); -public: - HRESULT Open(IInStream *inStream, + AString SafeReadName(); + void Skeep(size_t size); + void ReadOtherArchive(COtherArchive &oa); + + HRESULT Open2(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, - CInArchiveInfo &inArchiveInfo, - CObjectVector &folders, - CObjectVector &files, - CProgressVirt *progressVirt); + CDatabase &database); +public: + HRESULT Open( + const UInt64 *searchHeaderSizeLimit, + CDatabaseEx &database); }; }} diff --git a/7zip/Archive/Cab/CabInBuffer.cpp b/7zip/Archive/Cab/CabInBuffer.cpp deleted file mode 100755 index c429033c..00000000 --- a/7zip/Archive/Cab/CabInBuffer.cpp +++ /dev/null @@ -1,175 +0,0 @@ -// Archive/CabInBuffer.cpp - -#include "StdAfx.h" - -#include "../../../Common/Alloc.h" -#include "../../../Common/MyCom.h" -#include "../../../Windows/Defs.h" -#include "CabInBuffer.h" - -namespace NArchive { -namespace NCab { - -static const UInt32 kDataBlockHeaderSize = 8; -/* -struct CDataBlockHeader -{ - UInt32 CheckSum; // checksum of this CFDATA entry - UInt16 PackSize; // number of compressed bytes in this block - UInt16 UnPackSize; // number of uncompressed bytes in this block - // Byte abReserve[]; // (optional) per-datablock reserved area - // Byte ab[cbData]; // compressed data bytes -}; -*/ - -class CTempCabInBuffer -{ -public: - Byte *Buffer; - UInt32 Size; - UInt32 Pos; - Byte ReadByte() - { - if (Pos >= Size) - throw "overflow"; - return Buffer[Pos++]; - } - UInt32 ReadUInt32() - { - UInt32 value = 0; - for (int i = 0; i < 4; i++) - value |= (((UInt32)ReadByte()) << (8 * i)); - return value; - } - UInt16 ReadUInt16() - { - UInt16 value = 0; - for (int i = 0; i < 2; i++) - value |= (((UInt16)ReadByte()) << (8 * i)); - return value; - } -}; - -bool CInBuffer::Create(UInt32 bufferSize) -{ - const UInt32 kMinBlockSize = 1; - if (bufferSize < kMinBlockSize) - bufferSize = kMinBlockSize; - if (m_Buffer != 0 && m_BufferSize == bufferSize) - return true; - Free(); - m_BufferSize = bufferSize; - m_Buffer = (Byte *)::BigAlloc(bufferSize); - return (m_Buffer != 0); -} - -void CInBuffer::Free() -{ - BigFree(m_Buffer); - m_Buffer = 0; -} - -void CInBuffer::Init(Byte reservedSize, UInt32 numBlocks) -{ - m_ReservedSize = reservedSize; - m_NumBlocks = numBlocks; - m_CurrentBlockIndex = 0; - m_ProcessedSize = 0; - m_Pos = 0; - m_NumReadBytesInBuffer = 0; -} - -class CCheckSum -{ - UInt32 m_Value; -public: - CCheckSum(): m_Value(0){}; - void Init() { m_Value = 0; } - void Update(const void *data, UInt32 size); - void UpdateUInt32(UInt32 v) { m_Value ^= v; } - UInt32 GetResult() const { return m_Value; } -}; - -void CCheckSum::Update(const void *data, UInt32 size) -{ - UInt32 checkSum = m_Value; - const Byte *dataPointer = (const Byte *)data; - int numUINT32Words = size / 4; // Number of ULONGs - - UInt32 temp; - while (numUINT32Words-- > 0) - { - temp = *dataPointer++; - temp |= (((UInt32)(*dataPointer++)) << 8); - temp |= (((UInt32)(*dataPointer++)) << 16); - temp |= (((UInt32)(*dataPointer++)) << 24); - checkSum ^= temp; - } - - temp = 0; - int rem = (size & 3); - if (rem >= 3) - temp |= (((UInt32)(*dataPointer++)) << 16); - if (rem >= 2) - temp |= (((UInt32)(*dataPointer++)) << 8); - if (rem >= 1) - temp |= *dataPointer++; - checkSum ^= temp; - m_Value = checkSum; -} - -HRESULT CInBuffer::ReadBlock(UInt32 &uncompressedSize, bool &dataAreCorrect) -{ - if (m_CurrentBlockIndex >= m_NumBlocks) - throw "there is no more data blocks"; - - m_ProcessedSize += m_NumReadBytesInBuffer; - - Byte buffer[kDataBlockHeaderSize]; - UInt32 numProcessedBytes; - RINOK(m_Stream->Read(buffer, kDataBlockHeaderSize, &numProcessedBytes)); - if (numProcessedBytes != kDataBlockHeaderSize) - throw "bad block"; - - CTempCabInBuffer inBuffer; - inBuffer.Size = kDataBlockHeaderSize; - inBuffer.Buffer = (Byte *)buffer; - inBuffer.Pos = 0; - - UInt32 checkSum = inBuffer.ReadUInt32(); // checksum of this CFDATA entry - UInt16 packSize = inBuffer.ReadUInt16(); // number of compressed bytes in this block - UInt16 unPackSize = inBuffer.ReadUInt16(); // number of uncompressed bytes in this block - - if (m_ReservedSize != 0) - { - Byte reservedArea[256]; - RINOK(m_Stream->Read(reservedArea, m_ReservedSize, &numProcessedBytes)); - if (numProcessedBytes != m_ReservedSize) - throw "bad block"; - } - - RINOK(m_Stream->Read(m_Buffer, packSize, &m_NumReadBytesInBuffer)); - if (m_NumReadBytesInBuffer != packSize) - throw "bad block"; - - // Cab specification: - // checkSum: May be set to zero if the checksum is not supplied. - // but seems it's stupid rule. - if (checkSum == 0) - dataAreCorrect = true; - else - { - CCheckSum checkSumCalc; - checkSumCalc.Update(m_Buffer, packSize); - checkSumCalc.UpdateUInt32(packSize | (((UInt32)unPackSize) << 16)); - dataAreCorrect = (checkSumCalc.GetResult() == checkSum); - } - - m_Pos = 0; - uncompressedSize = unPackSize; - - m_CurrentBlockIndex++; - return S_OK; -} - -}} diff --git a/7zip/Archive/Cab/CabInBuffer.h b/7zip/Archive/Cab/CabInBuffer.h deleted file mode 100755 index 1b94f77f..00000000 --- a/7zip/Archive/Cab/CabInBuffer.h +++ /dev/null @@ -1,66 +0,0 @@ -// Archive/CabInBuffer.h - -#ifndef __ARCHIVE_CAB_INBUFFER_H -#define __ARCHIVE_CAB_INBUFFER_H - -#include "../../IStream.h" -#include "../../../Common/MyCom.h" - -namespace NArchive { -namespace NCab { - -class CInBuffer -{ - UInt64 m_ProcessedSize; - UInt32 m_Pos; - UInt32 m_NumReadBytesInBuffer; - Byte *m_Buffer; - CMyComPtr m_Stream; - UInt32 m_BufferSize; - - UInt32 m_NumBlocks; - UInt32 m_CurrentBlockIndex; - UInt32 m_ReservedSize; - -public: - CInBuffer(): m_Buffer(0) {} - ~CInBuffer() { Free(); } - bool Create(UInt32 bufferSize); - void Free(); - - void SetStream(ISequentialInStream *inStream) { m_Stream = inStream; } - void ReleaseStream() { m_Stream.Release(); } - - void Init(Byte reservedSize, UInt32 numBlocks); - void Init() {} - - bool ReadByte(Byte &b) - { - if(m_Pos >= m_NumReadBytesInBuffer) - return false; - b = m_Buffer[m_Pos++]; - return true; - } - Byte ReadByte() - { - if(m_Pos >= m_NumReadBytesInBuffer) - return 0; - return m_Buffer[m_Pos++]; - } - /* - void ReadBytes(void *data, UInt32 size, UInt32 &aProcessedSize) - { - Byte *aDataPointer = (Byte *)data; - for(int i = 0; i < size; i++) - if (!ReadByte(aDataPointer[i])) - break; - aProcessedSize = i; - } - */ - HRESULT ReadBlock(UInt32 &uncompressedSize, bool &dataAreCorrect); - UInt64 GetProcessedSize() const { return m_ProcessedSize + m_Pos; } -}; - -}} - -#endif diff --git a/7zip/Archive/Cab/CabItem.h b/7zip/Archive/Cab/CabItem.h index b1ebeb60..d8b56325 100755 --- a/7zip/Archive/Cab/CabItem.h +++ b/7zip/Archive/Cab/CabItem.h @@ -1,7 +1,7 @@ -// Archive/Cab/ItemInfo.h +// Archive/CabItem.h -#ifndef __ARCHIVE_RAR_ITEMINFO_H -#define __ARCHIVE_RAR_ITEMINFO_H +#ifndef __ARCHIVE_CAB_ITEM_H +#define __ARCHIVE_CAB_ITEM_H #include "Common/Types.h" #include "Common/String.h" @@ -10,23 +10,53 @@ namespace NArchive { namespace NCab { +struct CFolder +{ + UInt32 DataStart; // offset of the first CFDATA block in this folder + UInt16 NumDataBlocks; // number of CFDATA blocks in this folder + Byte CompressionTypeMajor; + Byte CompressionTypeMinor; + Byte GetCompressionMethod() const { return (Byte)(CompressionTypeMajor & 0xF); } +}; + class CItem { public: - UInt16 Flags; - UInt64 UnPackSize; - UInt32 UnPackOffset; - UInt16 FolderIndex; + AString Name; + UInt32 Offset; + UInt32 Size; UInt32 Time; - UInt16 Attributes; - UInt32 GetWinAttributes() const { return Attributes & (Attributes & ~NHeader::kFileNameIsUTFAttributeMask); } + UInt16 FolderIndex; + UInt16 Flags; + UInt16 Attributes; + UInt64 GetEndOffset() const { return (UInt64)Offset + Size; } + UInt32 GetWinAttributes() const { return (Attributes & ~NHeader::kFileNameIsUTFAttributeMask); } bool IsNameUTF() const { return (Attributes & NHeader::kFileNameIsUTFAttributeMask) != 0; } bool IsDirectory() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; } - AString Name; + + bool ContinuedFromPrev() const + { + return + (FolderIndex == NHeader::NFolderIndex::kContinuedFromPrev) || + (FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext); + } + bool ContinuedToNext() const + { + return + (FolderIndex == NHeader::NFolderIndex::kContinuedToNext) || + (FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext); + } + + int GetFolderIndex(int numFolders) const + { + if (ContinuedFromPrev()) + return 0; + if (ContinuedToNext()) + return (numFolders - 1); + return FolderIndex; + } }; }} #endif - - diff --git a/7zip/Archive/Cab/DllExports.cpp b/7zip/Archive/Cab/DllExports.cpp index b92504fd..fa17f10b 100755 --- a/7zip/Archive/Cab/DllExports.cpp +++ b/7zip/Archive/Cab/DllExports.cpp @@ -8,12 +8,12 @@ #include "CabHandler.h" #include "../../ICoder.h" -// {23170F69-40C1-278A-1000-000110060000} +// {23170F69-40C1-278A-1000-000110080000} DEFINE_GUID(CLSID_CCabHandler, - 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x06, 0x00, 0x00); + 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0x00); extern "C" -BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) +BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) { return TRUE; } diff --git a/7zip/Archive/Cab/LZXBitDecoder.h b/7zip/Archive/Cab/LZXBitDecoder.h deleted file mode 100755 index 51737135..00000000 --- a/7zip/Archive/Cab/LZXBitDecoder.h +++ /dev/null @@ -1,111 +0,0 @@ -// Archive/Cab/LZXBitDecoder.h - -#ifndef __ARCHIVE_CAB_LZXBITDECODER_H -#define __ARCHIVE_CAB_LZXBITDECODER_H - -#include "CabInBuffer.h" - -namespace NArchive { -namespace NCab { -namespace NLZX { -namespace NBitStream { - -const int kNumBigValueBits = 8 * 4; - -const int kNumValueBits = 17; -const int kBitDecoderValueMask = (1 << kNumValueBits) - 1; - -class CDecoder -{ -protected: - CInBuffer m_Stream; - UInt32 m_BitPos; - UInt32 m_Value; -public: - bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); } - void SetStream(ISequentialInStream *s) { m_Stream.SetStream(s); } - void ReleaseStream() { m_Stream.ReleaseStream(); } - void Init(Byte reservedSize, UInt32 numBlocks) - { - m_Stream.Init(reservedSize, numBlocks); - } - UInt64 GetProcessedSize() const - { return m_Stream.GetProcessedSize() - (kNumBigValueBits - m_BitPos) / 8; } - UInt32 GetBitPosition() const - { return UInt32(m_Stream.GetProcessedSize() * 8 - (kNumBigValueBits - m_BitPos)); } - - void Init() - { - m_BitPos = kNumBigValueBits; - Normalize(); - } - - void Normalize() - { - for (;m_BitPos >= 16; m_BitPos -= 16) - { - Byte b0 = m_Stream.ReadByte(); - Byte b1 = m_Stream.ReadByte(); - m_Value = (m_Value << 8) | b1; - m_Value = (m_Value << 8) | b0; - } - } - - UInt32 GetValue(UInt32 numBits) - { - return ((m_Value >> ((32 - kNumValueBits) - m_BitPos)) & kBitDecoderValueMask) >> - (kNumValueBits - numBits); - } - - void MovePos(UInt32 numBits) - { - m_BitPos += numBits; - Normalize(); - } - - UInt32 ReadBits(UInt32 numBits) - { - UInt32 res = GetValue(numBits); - MovePos(numBits); - return res; - } - UInt32 ReadBitsBig(UInt32 numBits) - { - UInt32 numBits0 = numBits / 2; - UInt32 numBits1 = numBits - numBits0; - UInt32 res = ReadBits(numBits0) << numBits1; - return res + ReadBits(numBits1); - } - - Byte DirectReadByte() - { - if (m_BitPos == kNumBigValueBits) - return m_Stream.ReadByte(); - Byte res; - switch(m_BitPos) - { - case 0: - res = Byte(m_Value >> 16); - break; - case 8: - res = Byte(m_Value >> 24); - break; - case 16: - res = Byte(m_Value); - break; - case 24: - res = Byte(m_Value >> 8); - break; - } - m_BitPos += 8; - return res; - } - - HRESULT ReadBlock(UInt32 &uncompressedSize, bool &dataAreCorrect) - { return m_Stream.ReadBlock(uncompressedSize, dataAreCorrect); } -}; - - -}}}} - -#endif diff --git a/7zip/Archive/Cab/LZXConst.h b/7zip/Archive/Cab/LZXConst.h deleted file mode 100755 index f4648024..00000000 --- a/7zip/Archive/Cab/LZXConst.h +++ /dev/null @@ -1,110 +0,0 @@ -// Archive/Cab/LZXConst.h - -#ifndef __ARCHIVE_CAB_LZXCONST_H -#define __ARCHIVE_CAB_LZXCONST_H - -#include "LZXExtConst.h" - -namespace NArchive { -namespace NCab { -namespace NLZX { - -namespace NBlockType -{ - const int kNumBits = 3; - enum EEnum - { - kVerbatim = 1, - kAligned = 2, - kUncompressed = 3 - }; -} - -const int kUncompressedBlockSizeNumBits = 24; - -const UInt32 kLevelTableSize = 20; - -const UInt32 kNumBitsForPreTreeLevel = 4; - -const int kLevelSymbolZeros = 17; -const int kLevelSymbolZerosBig = 18; -const int kLevelSymbolSame = 19; - -const int kLevelSymbolZerosStartValue = 4; -const int kLevelSymbolZerosNumBits = 4; - -const int kLevelSymbolZerosBigStartValue = kLevelSymbolZerosStartValue + - (1 << kLevelSymbolZerosNumBits); -const int kLevelSymbolZerosBigNumBits = 5; - -const int kNumBitsForAlignLevel = 3; - -const int kLevelSymbolSameNumBits = 1; -const int kLevelSymbolSameStartValue = 4; - -// const UInt32 kMainTableSize = 256 + kNumPosLenSlots + 1; - -/* -const UInt32 kLenTableSize = 28; - -const UInt32 kLenTableStart = kMainTableSize; -const UInt32 kAlignTableStart = kLenTableStart + kLenTableSize; - -const UInt32 kHeapTablesSizesSum = kMainTableSize + kLenTableSize + kAlignTableSize; - - -const UInt32 kMaxTableSize = kHeapTablesSizesSum; - -const UInt32 kTableDirectLevels = 16; -const UInt32 kTableLevelRepNumber = kTableDirectLevels; -const UInt32 kTableLevel0Number = kTableLevelRepNumber + 1; -const UInt32 kTableLevel0Number2 = kTableLevel0Number + 1; - -const UInt32 kLevelMask = 0xF; - -const UInt32 kPosLenNumber = 256; -const UInt32 kReadTableNumber = 256 + kNumPosLenSlots; - -//const UInt32 kMatchNumber = kReadTableNumber + 1; - -const Byte kLenStart[kLenTableSize] = - {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224}; -const Byte kLenDirectBits[kLenTableSize] = - {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5}; -*/ - -const UInt32 kDistStart[] = -{ 0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024, - 1536,2048,3072,4096,6144,8192,12288,16384,24576,32768,49152,65536,98304,131072,196608, - 0x40000, - 0x60000, - 0x80000, - 0xA0000, - 0xC0000, - 0xE0000, - - 0x100000, - 0x120000, - 0x140000, - 0x160000, - 0x180000, - 0x1A0000, - 0x1C0000, - 0x1E0000 -}; -const Byte kDistDirectBits[] = -{ - 0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16, - 17, 17, 17, 17, 17, 17, - 17, 17,17, 17, 17, 17, 17, 17 -}; - -/* -const Byte kLevelDirectBits[kLevelTableSize] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7}; - -const UInt32 kDistLimit2 = 0x101 - 1; -*/ - -}}} - -#endif diff --git a/7zip/Archive/Cab/LZXDecoder.cpp b/7zip/Archive/Cab/LZXDecoder.cpp deleted file mode 100755 index 49f87ed7..00000000 --- a/7zip/Archive/Cab/LZXDecoder.cpp +++ /dev/null @@ -1,310 +0,0 @@ -// Archive/Cab/LZXDecoder.cpp - -#include "StdAfx.h" - -#include "LZXDecoder.h" - -#include "Common/Defs.h" -#include "Windows/Defs.h" - -namespace NArchive { -namespace NCab { -namespace NLZX { - -static const UInt32 kHistorySize = (1 << 21); - -CDecoder::CDecoder() -{ - m_i86TranslationOutStreamSpec = new Ci86TranslationOutStream; - m_i86TranslationOutStream = m_i86TranslationOutStreamSpec; -} - -void CDecoder::ReleaseStreams() -{ - m_OutWindowStream.ReleaseStream(); - m_InBitStream.ReleaseStream(); - m_i86TranslationOutStreamSpec->ReleaseStream(); -} - -STDMETHODIMP CDecoder::Flush() -{ - RINOK(m_OutWindowStream.Flush()); - return m_i86TranslationOutStreamSpec->Flush(); -} - -void CDecoder::ReadTable(Byte *lastLevels, Byte *newLevels, UInt32 numSymbols) -{ - Byte levelLevels[kLevelTableSize]; - UInt32 i; - for (i = 0; i < kLevelTableSize; i++) - levelLevels[i] = Byte(m_InBitStream.ReadBits(kNumBitsForPreTreeLevel)); - m_LevelDecoder.SetCodeLengths(levelLevels); - for (i = 0; i < numSymbols;) - { - UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream); - if (number <= kNumHuffmanBits) - newLevels[i++] = Byte((17 + lastLevels[i] - number) % (kNumHuffmanBits + 1)); - else if (number == kLevelSymbolZeros || number == kLevelSymbolZerosBig) - { - int num; - if (number == kLevelSymbolZeros) - num = kLevelSymbolZerosStartValue + - m_InBitStream.ReadBits(kLevelSymbolZerosNumBits); - else - num = kLevelSymbolZerosBigStartValue + - m_InBitStream.ReadBits(kLevelSymbolZerosBigNumBits); - for (;num > 0 && i < numSymbols; num--, i++) - newLevels[i] = 0; - } - else if (number == kLevelSymbolSame) - { - int num = kLevelSymbolSameStartValue + m_InBitStream.ReadBits(kLevelSymbolSameNumBits); - UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream); - if (number > kNumHuffmanBits) - throw "bad data"; - Byte symbol = Byte((17 + lastLevels[i] - number) % (kNumHuffmanBits + 1)); - for (; num > 0 && i < numSymbols; num--, i++) - newLevels[i] = symbol; - } - else - throw "bad data"; - } - - memmove(lastLevels, newLevels, numSymbols); -} - -void CDecoder::ReadTables(void) -{ - int blockType = m_InBitStream.ReadBits(NBlockType::kNumBits); - - if (blockType != NBlockType::kVerbatim && blockType != NBlockType::kAligned && - blockType != NBlockType::kUncompressed) - throw "bad data"; - - m_UnCompressedBlockSize = m_InBitStream.ReadBitsBig(kUncompressedBlockSizeNumBits); - - if (blockType == NBlockType::kUncompressed) - { - m_UncompressedBlock = true; - UInt32 bitPos = m_InBitStream.GetBitPosition() % 16; - m_InBitStream.ReadBits(16 - bitPos); - for (int i = 0; i < kNumRepDistances; i++) - { - m_RepDistances[i] = 0; - for (int j = 0; j < 4; j++) - m_RepDistances[i] |= (m_InBitStream.DirectReadByte()) << (8 * j); - m_RepDistances[i]--; - } - return; - } - - m_UncompressedBlock = false; - - m_AlignIsUsed = (blockType == NBlockType::kAligned); - - Byte newLevels[kMaxTableSize]; - - if (m_AlignIsUsed) - { - for(int i = 0; i < kAlignTableSize; i++) - newLevels[i] = m_InBitStream.ReadBits(kNumBitsForAlignLevel); - m_AlignDecoder.SetCodeLengths(newLevels); - } - - ReadTable(m_LastByteLevels, newLevels, 256); - ReadTable(m_LastPosLenLevels, newLevels + 256, m_NumPosLenSlots); - for (int i = m_NumPosLenSlots; i < kNumPosSlotLenSlotSymbols; i++) - newLevels[256 + i] = 0; - m_MainDecoder.SetCodeLengths(newLevels); - - ReadTable(m_LastLenLevels, newLevels, kNumLenSymbols); - m_LenDecoder.SetCodeLengths(newLevels); - -} - -class CDecoderFlusher -{ - CDecoder *m_Decoder; -public: - CDecoderFlusher(CDecoder *decoder): m_Decoder(decoder) {} - ~CDecoderFlusher() - { - m_Decoder->Flush(); - m_Decoder->ReleaseStreams(); - } -}; - - -void CDecoder::ClearPrevLeveles() -{ - memset(m_LastByteLevels, 0, 256); - memset(m_LastPosLenLevels, 0, kNumPosSlotLenSlotSymbols); - memset(m_LastLenLevels, 0, kNumLenSymbols); -}; - - -STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, - ISequentialOutStream *outStream, - const UInt64 *inSize, const UInt64 *outSize, - ICompressProgressInfo *progress) -{ - if (outSize == NULL) - return E_INVALIDARG; - UInt64 size = *outSize; - - if (!m_OutWindowStream.Create(kHistorySize)) - return E_OUTOFMEMORY; - if (!m_InBitStream.Create(1 << 20)) - return E_OUTOFMEMORY; - - m_OutWindowStream.SetStream(m_i86TranslationOutStream); - m_OutWindowStream.Init(); - - m_InBitStream.SetStream(inStream); - m_InBitStream.Init(m_ReservedSize, m_NumInDataBlocks); - - CDecoderFlusher flusher(this); - - UInt32 uncompressedCFDataBlockSize; - bool dataAreCorrect; - RINOK(m_InBitStream.ReadBlock(uncompressedCFDataBlockSize, dataAreCorrect)); - if (!dataAreCorrect) - { - throw "Data Error"; - } - UInt32 uncompressedCFDataCurrentValue = 0; - m_InBitStream.Init(); - - ClearPrevLeveles(); - - if (m_InBitStream.ReadBits(1) == 0) - m_i86TranslationOutStreamSpec->Init(outStream, false, 0); - else - { - UInt32 i86TranslationSize = m_InBitStream.ReadBits(16) << 16; - i86TranslationSize |= m_InBitStream.ReadBits(16); - m_i86TranslationOutStreamSpec->Init(outStream, true , i86TranslationSize); - } - - for(int i = 0 ; i < kNumRepDistances; i++) - m_RepDistances[i] = 0; - - UInt64 nowPos64 = 0; - while(nowPos64 < size) - { - if (uncompressedCFDataCurrentValue == uncompressedCFDataBlockSize) - { - bool dataAreCorrect; - RINOK(m_InBitStream.ReadBlock(uncompressedCFDataBlockSize, dataAreCorrect)); - if (!dataAreCorrect) - { - throw "Data Error"; - } - m_InBitStream.Init(); - uncompressedCFDataCurrentValue = 0; - } - ReadTables(); - UInt32 nowPos = 0; - UInt32 next = (UInt32)MyMin((UInt64)m_UnCompressedBlockSize, size - nowPos64); - if (m_UncompressedBlock) - { - while(nowPos < next) - { - m_OutWindowStream.PutByte(m_InBitStream.DirectReadByte()); - nowPos++; - uncompressedCFDataCurrentValue++; - if (uncompressedCFDataCurrentValue == uncompressedCFDataBlockSize) - { - bool dataAreCorrect; - RINOK(m_InBitStream.ReadBlock(uncompressedCFDataBlockSize, dataAreCorrect)); - if (!dataAreCorrect) - { - throw "Data Error"; - } - // m_InBitStream.Init(); - uncompressedCFDataCurrentValue = 0; - continue; - } - } - int bitPos = m_InBitStream.GetBitPosition() % 16; - if (bitPos == 8) - m_InBitStream.DirectReadByte(); - m_InBitStream.Normalize(); - } - else for (;nowPos < next;) - { - if (uncompressedCFDataCurrentValue == uncompressedCFDataBlockSize) - { - bool dataAreCorrect; - RINOK(m_InBitStream.ReadBlock(uncompressedCFDataBlockSize, dataAreCorrect)); - if (!dataAreCorrect) - { - throw "Data Error"; - } - m_InBitStream.Init(); - uncompressedCFDataCurrentValue = 0; - } - UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream); - if (number < 256) - { - m_OutWindowStream.PutByte(Byte(number)); - nowPos++; - uncompressedCFDataCurrentValue++; - // continue; - } - else if (number < 256 + m_NumPosLenSlots) - { - UInt32 posLenSlot = number - 256; - UInt32 posSlot = posLenSlot / kNumLenSlots; - UInt32 lenSlot = posLenSlot % kNumLenSlots; - UInt32 length = 2 + lenSlot; - if (lenSlot == kNumLenSlots - 1) - length += m_LenDecoder.DecodeSymbol(&m_InBitStream); - - if (posSlot < kNumRepDistances) - { - UInt32 distance = m_RepDistances[posSlot]; - m_OutWindowStream.CopyBlock(distance, length); - if (posSlot != 0) - { - m_RepDistances[posSlot] = m_RepDistances[0]; - m_RepDistances[0] = distance; - } - } - else - { - UInt32 pos = kDistStart[posSlot]; - UInt32 posDirectBits = kDistDirectBits[posSlot]; - if (m_AlignIsUsed && posDirectBits >= kNumAlignBits) - { - pos += (m_InBitStream.ReadBits(posDirectBits - kNumAlignBits) << kNumAlignBits); - pos += m_AlignDecoder.DecodeSymbol(&m_InBitStream); - } - else - pos += m_InBitStream.ReadBits(posDirectBits); - UInt32 distance = pos - kNumRepDistances; - if (distance >= nowPos64 + nowPos) - throw 777123; - m_OutWindowStream.CopyBlock(distance, length); - m_RepDistances[2] = m_RepDistances[1]; - m_RepDistances[1] = m_RepDistances[0]; - m_RepDistances[0] = distance; - } - nowPos += length; - uncompressedCFDataCurrentValue += length; - } - else - throw 98112823; - } - if (progress != NULL) - { - UInt64 inSize = m_InBitStream.GetProcessedSize(); - UInt64 outSize = nowPos64 + nowPos; - RINOK(progress->SetRatioInfo(&inSize, &outSize)); - } - nowPos64 += nowPos; - } - return S_OK; -} - -}}} diff --git a/7zip/Archive/Cab/LZXDecoder.h b/7zip/Archive/Cab/LZXDecoder.h deleted file mode 100755 index 257de7b9..00000000 --- a/7zip/Archive/Cab/LZXDecoder.h +++ /dev/null @@ -1,95 +0,0 @@ -// Archive/Cab/LZXDecoder.h - -#ifndef __ARCHIVE_CAB_LZXDECODER_H -#define __ARCHIVE_CAB_LZXDECODER_H - -#include "../../ICoder.h" - -#include "../../Compress/Huffman/HuffmanDecoder.h" -#include "../../Compress/LZ/LZOutWindow.h" - -#include "LZXExtConst.h" -#include "LZXBitDecoder.h" - -#include "LZXi86Converter.h" -#include "LZXConst.h" - -namespace NArchive { -namespace NCab { -namespace NLZX { - -const int kMainTableSize = 256 + kNumPosSlotLenSlotSymbols; - -class CDecoder : - public ICompressCoder, - public CMyUnknownImp -{ - CLZOutWindow m_OutWindowStream; - NBitStream::CDecoder m_InBitStream; - - NCompress::NHuffman::CDecoder m_MainDecoder; - NCompress::NHuffman::CDecoder m_LenDecoder; - NCompress::NHuffman::CDecoder m_AlignDecoder; - NCompress::NHuffman::CDecoder m_LevelDecoder; - - UInt32 m_RepDistances[kNumRepDistances]; - - Byte m_LastByteLevels[256]; - Byte m_LastPosLenLevels[kNumPosSlotLenSlotSymbols]; - Byte m_LastLenLevels[kNumLenSymbols]; - - UInt32 m_DictionarySizePowerOf2; - UInt32 m_NumPosSlots; - UInt32 m_NumPosLenSlots; - - // bool m_i86PreprocessingUsed; - // UInt32 m_i86TranslationSize; - - bool m_UncompressedBlock; - bool m_AlignIsUsed; - - UInt32 m_UnCompressedBlockSize; - - Ci86TranslationOutStream *m_i86TranslationOutStreamSpec; - CMyComPtr m_i86TranslationOutStream; - - Byte m_ReservedSize; - UInt32 m_NumInDataBlocks; - - void ReadTable(Byte *lastLevels, Byte *newLevels, UInt32 numSymbols); - void ReadTables(); - void ClearPrevLeveles(); - -public: - CDecoder(); - - MY_UNKNOWN_IMP - - void ReleaseStreams(); - STDMETHOD(Flush)(); - - // ICompressCoder interface - STDMETHOD(Code)(ISequentialInStream *inStream, - ISequentialOutStream *outStream, - const UInt64 *inSize, const UInt64 *outSize, - ICompressProgressInfo *progress); - - void SetParams(Byte reservedSize, UInt32 numInDataBlocks, - UInt32 dictionarySizePowerOf2) - { - m_ReservedSize = reservedSize; - m_NumInDataBlocks = numInDataBlocks; - m_DictionarySizePowerOf2 = dictionarySizePowerOf2; - if (dictionarySizePowerOf2 < 20) - m_NumPosSlots = 30 + (dictionarySizePowerOf2 - 15) * 2; - else if (dictionarySizePowerOf2 == 20) - m_NumPosSlots = 42; - else - m_NumPosSlots = 50; - m_NumPosLenSlots = m_NumPosSlots * kNumLenSlots; - } -}; - -}}} - -#endif \ No newline at end of file diff --git a/7zip/Archive/Cab/LZXExtConst.h b/7zip/Archive/Cab/LZXExtConst.h deleted file mode 100755 index df2ef6cf..00000000 --- a/7zip/Archive/Cab/LZXExtConst.h +++ /dev/null @@ -1,30 +0,0 @@ -// Archive/Cab/LZXExtConst.h - -#ifndef __ARCHIVE_CAB_LZXEXTCONST_H -#define __ARCHIVE_CAB_LZXEXTCONST_H - -namespace NArchive { -namespace NCab { -namespace NLZX { - -const UInt32 kNumRepDistances = 3; - -const UInt32 kNumLenSlots = 8; -const UInt32 kMatchMinLen = 2; -const UInt32 kNumLenSymbols = 249; -const UInt32 kMatchMaxLen = kMatchMinLen + (kNumLenSlots - 1) + kNumLenSymbols - 1; - -const Byte kNumAlignBits = 3; -const UInt32 kAlignTableSize = 1 << kNumAlignBits; - -const UInt32 kNumHuffmanBits = 16; - -const int kNumPosSlotSymbols = 50; -const int kNumPosSlotLenSlotSymbols = kNumPosSlotSymbols * kNumLenSlots; - -const int kMaxTableSize = 256 + kNumPosSlotLenSlotSymbols; - - -}}} - -#endif diff --git a/7zip/Archive/Cab/MSZipConst.h b/7zip/Archive/Cab/MSZipConst.h deleted file mode 100755 index f2dfda86..00000000 --- a/7zip/Archive/Cab/MSZipConst.h +++ /dev/null @@ -1,92 +0,0 @@ -// MSZipConst.h - -#ifndef __MSZIP_CONST_H -#define __MSZIP_CONST_H - -#include "MSZipExtConst.h" - -namespace NArchive { -namespace NCab { -namespace NMSZip { - -const UInt32 kLenTableSize = 29; - -const UInt32 kStaticDistTableSize = 32; -const UInt32 kStaticLenTableSize = 31; - -const UInt32 kReadTableNumber = 0x100; -const UInt32 kMatchNumber = kReadTableNumber + 1; - -const UInt32 kMainTableSize = kMatchNumber + kLenTableSize; //298; -const UInt32 kStaticMainTableSize = kMatchNumber + kStaticLenTableSize; //298; - -const UInt32 kDistTableStart = kMainTableSize; - -const UInt32 kHeapTablesSizesSum = kMainTableSize + kDistTableSize; - -const UInt32 kLevelTableSize = 19; - -const UInt32 kMaxTableSize = kHeapTablesSizesSum; // test it -const UInt32 kStaticMaxTableSize = kStaticMainTableSize + kStaticDistTableSize; - -const UInt32 kTableDirectLevels = 16; -const UInt32 kTableLevelRepNumber = kTableDirectLevels; -const UInt32 kTableLevel0Number = kTableLevelRepNumber + 1; -const UInt32 kTableLevel0Number2 = kTableLevel0Number + 1; - -const UInt32 kLevelMask = 0xF; - -const Byte kLenStart[kLenTableSize] = {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224, 255}; -const Byte kLenDirectBits[kLenTableSize] = {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; - - -const UInt32 kDistStart[kDistTableSize] = {0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576}; -const Byte kDistDirectBits[kDistTableSize] = {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; - -const Byte kLevelDirectBits[kLevelTableSize] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7}; - -const Byte kCodeLengthAlphabetOrder[kLevelTableSize] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - -const UInt32 kMatchMinLen = 3; -const UInt32 kMatchMaxLen = kNumLenCombinations + kMatchMinLen - 1; //255 + 2; test it - -const int kFinalBlockFieldSize = 1; - -namespace NFinalBlockField -{ -enum -{ - kNotFinalBlock = 0, - kFinalBlock = 1 -}; -} - -const int kBlockTypeFieldSize = 2; - -namespace NBlockType -{ - enum - { - kStored = 0, - kFixedHuffman = 1, - kDynamicHuffman = 2, - kReserved = 3 - }; -} - -const UInt32 kDeflateNumberOfLengthCodesFieldSize = 5; -const UInt32 kDeflateNumberOfDistanceCodesFieldSize = 5; -const UInt32 kDeflateNumberOfLevelCodesFieldSize = 4; - -const UInt32 kDeflateNumberOfLitLenCodesMin = 257; - -const UInt32 kDeflateNumberOfDistanceCodesMin = 1; -const UInt32 kDeflateNumberOfLevelCodesMin = 4; - -const UInt32 kDeflateLevelCodeFieldSize = 3; - -const UInt32 kDeflateStoredBlockLengthFieldSizeSize = 16; - -}}} - -#endif \ No newline at end of file diff --git a/7zip/Archive/Cab/MSZipDecoder.cpp b/7zip/Archive/Cab/MSZipDecoder.cpp deleted file mode 100755 index 9e004bf9..00000000 --- a/7zip/Archive/Cab/MSZipDecoder.cpp +++ /dev/null @@ -1,268 +0,0 @@ -// Archive/Cab/MSZipDecoder.cpp - -#include "StdAfx.h" - -#include "MSZipDecoder.h" - -#include "Windows/Defs.h" - -namespace NArchive { -namespace NCab { -namespace NMSZip { - -CDecoder::CDecoder(){} - -HRESULT CDecoder::Flush() -{ - return m_OutWindowStream.Flush(); -} - -void CDecoder::ReleaseStreams() -{ - m_OutWindowStream.ReleaseStream(); - m_InBitStream.ReleaseStream(); -} - -void CDecoder::DeCodeLevelTable(Byte *newLevels, int numLevels) -{ - int i = 0; - while (i < numLevels) - { - UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream); - if (number < kTableDirectLevels) - newLevels[i++] = Byte(number); - else - { - if (number == kTableLevelRepNumber) - { - int t = m_InBitStream.ReadBits(2) + 3; - for (int reps = t; reps > 0 && i < numLevels ; reps--, i++) - newLevels[i] = newLevels[i - 1]; - } - else - { - int num; - if (number == kTableLevel0Number) - num = m_InBitStream.ReadBits(3) + 3; - else - num = m_InBitStream.ReadBits(7) + 11; - for (;num > 0 && i < numLevels; num--) - newLevels[i++] = 0; - } - } - } -} - -void CDecoder::ReadTables(void) -{ - if(m_FinalBlock) // test it - throw CDecoderException(CDecoderException::kData); - - m_FinalBlock = (m_InBitStream.ReadBits(kFinalBlockFieldSize) == NFinalBlockField::kFinalBlock); - - int blockType = m_InBitStream.ReadBits(kBlockTypeFieldSize); - - switch(blockType) - { - case NBlockType::kStored: - { - m_StoredMode = true; - UInt32 currentBitPosition = m_InBitStream.GetBitPosition(); - UInt32 numBitsForAlign = currentBitPosition > 0 ? (8 - currentBitPosition): 0; - if (numBitsForAlign > 0) - m_InBitStream.ReadBits(numBitsForAlign); - m_StoredBlockSize = m_InBitStream.ReadBits(kDeflateStoredBlockLengthFieldSizeSize); - WORD onesComplementReverse = ~WORD(m_InBitStream.ReadBits(kDeflateStoredBlockLengthFieldSizeSize)); - if (m_StoredBlockSize != onesComplementReverse) - throw CDecoderException(CDecoderException::kData); - break; - } - case NBlockType::kFixedHuffman: - case NBlockType::kDynamicHuffman: - { - m_StoredMode = false; - Byte litLenLevels[kStaticMainTableSize]; - Byte distLevels[kStaticDistTableSize]; - if (blockType == NBlockType::kFixedHuffman) - { - int i; - - // Leteral / length levels - for (i = 0; i < 144; i++) - litLenLevels[i] = 8; - for (; i < 256; i++) - litLenLevels[i] = 9; - for (; i < 280; i++) - litLenLevels[i] = 7; - for (; i < 288; i++) /* make a complete, but wrong code set */ - litLenLevels[i] = 8; - - // Distance levels - for (i = 0; i < kStaticDistTableSize; i++) // test it: infozip only use kDistTableSize - distLevels[i] = 5; - } - else // in case when (blockType == kDeflateBlockTypeFixedHuffman) - { - int numLitLenLevels = m_InBitStream.ReadBits(kDeflateNumberOfLengthCodesFieldSize) + - kDeflateNumberOfLitLenCodesMin; - int numDistLevels = m_InBitStream.ReadBits(kDeflateNumberOfDistanceCodesFieldSize) + - kDeflateNumberOfDistanceCodesMin; - int numLevelCodes = m_InBitStream.ReadBits(kDeflateNumberOfLevelCodesFieldSize) + - kDeflateNumberOfLevelCodesMin; - - int numLevels; - numLevels = kHeapTablesSizesSum; - - Byte levelLevels[kLevelTableSize]; - int i; - for (i = 0; i < kLevelTableSize; i++) - { - int position = kCodeLengthAlphabetOrder[i]; - if(i < numLevelCodes) - levelLevels[position] = Byte(m_InBitStream.ReadBits(kDeflateLevelCodeFieldSize)); - else - levelLevels[position] = 0; - } - - try - { - m_LevelDecoder.SetCodeLengths(levelLevels); - } - catch(...) - { - throw CDecoderException(CDecoderException::kData); - } - - Byte tmpLevels[kStaticMaxTableSize]; - DeCodeLevelTable(tmpLevels, numLitLenLevels + numDistLevels); - - memmove(litLenLevels, tmpLevels, numLitLenLevels); - memset(litLenLevels + numLitLenLevels, 0, - kStaticMainTableSize - numLitLenLevels); - - memmove(distLevels, tmpLevels + numLitLenLevels, numDistLevels); - memset(distLevels + numDistLevels, 0, kStaticDistTableSize - numDistLevels); - } - try - { - m_MainDecoder.SetCodeLengths(litLenLevels); - m_DistDecoder.SetCodeLengths(distLevels); - } - catch(...) - { - throw CDecoderException(CDecoderException::kData); - } - break; - } - default: - throw CDecoderException(CDecoderException::kData); - } -} - -class CCoderReleaser -{ - CDecoder *m_Coder; -public: - CCoderReleaser(CDecoder *aCoder): m_Coder(aCoder) {} - ~CCoderReleaser() - { - m_Coder->Flush(); - m_Coder->ReleaseStreams(); - } -}; - -STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, - ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, - ICompressProgressInfo *progress) -{ - if (outSize == NULL) - return E_INVALIDARG; - UInt64 size = *outSize; - - if (!m_OutWindowStream.Create(kHistorySize)) - return E_OUTOFMEMORY; - if (!m_InBitStream.Create(1 << 20)) - return E_OUTOFMEMORY; - - m_OutWindowStream.SetStream(outStream); - m_OutWindowStream.Init(false); - - m_InBitStream.SetStream(inStream); - m_InBitStream.InitMain(m_ReservedSize, m_NumInDataBlocks); - CCoderReleaser coderReleaser(this); - - UInt64 nowPos = 0; - while(nowPos < size) - { - if (progress != NULL) - { - UInt64 packSize = m_InBitStream.GetProcessedSize(); - RINOK(progress->SetRatioInfo(&packSize, &nowPos)); - } - UInt32 uncompressedCFDataBlockSize; - bool dataAreCorrect; - RINOK(m_InBitStream.ReadBlock(uncompressedCFDataBlockSize, dataAreCorrect)); - if (!dataAreCorrect) - { - throw "Data Error"; - } - m_InBitStream.Init(); - if (m_InBitStream.ReadBits(8) != 0x43) - throw CDecoderException(CDecoderException::kData); - if (m_InBitStream.ReadBits(8) != 0x4B) - throw CDecoderException(CDecoderException::kData); - UInt32 uncompressedCFDataCurrentValue = 0; - m_FinalBlock = false; - while (uncompressedCFDataCurrentValue < uncompressedCFDataBlockSize) - { - ReadTables(); - if(m_StoredMode) - { - for (UInt32 i = 0; i < m_StoredBlockSize; i++) - m_OutWindowStream.PutByte(Byte(m_InBitStream.ReadBits(8))); - nowPos += m_StoredBlockSize; - uncompressedCFDataCurrentValue += m_StoredBlockSize; - continue; - } - while(true) - { - UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream); - - if (number < 256) - { - m_OutWindowStream.PutByte(Byte(number)); - nowPos++; - uncompressedCFDataCurrentValue++; - continue; - } - else if (number >= kMatchNumber) - { - number -= kMatchNumber; - UInt32 length = UInt32(kLenStart[number]) + kMatchMinLen; - UInt32 numBits; - if ((numBits = kLenDirectBits[number]) > 0) - length += m_InBitStream.ReadBits(numBits); - - number = m_DistDecoder.DecodeSymbol(&m_InBitStream); - UInt32 distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]); - /* - if (distance >= nowPos) - throw "data error"; - */ - m_OutWindowStream.CopyBlock(distance, length); - nowPos += length; - uncompressedCFDataCurrentValue += length; - } - else if (number == kReadTableNumber) - { - break; - } - else - throw CDecoderException(CDecoderException::kData); - } - } - } - return S_OK; -} - -}}} diff --git a/7zip/Archive/Cab/MSZipDecoder.h b/7zip/Archive/Cab/MSZipDecoder.h deleted file mode 100755 index f83a5ab7..00000000 --- a/7zip/Archive/Cab/MSZipDecoder.h +++ /dev/null @@ -1,85 +0,0 @@ -// Archive/Cab/MSZipDecoder.h - -#ifndef __ARCHIVE_CAB_DECODER_H -#define __ARCHIVE_CAB_DECODER_H - -#include "Common/MyCom.h" -#include "../../ICoder.h" -#include "../../Common/LSBFDecoder.h" -#include "../../Compress/Huffman/HuffmanDecoder.h" -#include "../../Compress/LZ/LZOutWindow.h" - -#include "CabInBuffer.h" -#include "MSZipExtConst.h" -#include "MSZipConst.h" - -namespace NArchive { -namespace NCab { -namespace NMSZip { - -class CDecoderException -{ -public: - enum ECauseType - { - kData - } m_Cause; - CDecoderException(ECauseType aCause): m_Cause(aCause) {} -}; - -class CMSZipBitDecoder: public NStream::NLSBF::CDecoder -{ -public: - void InitMain(Byte reservedSize, UInt32 aNumBlocks) - { - m_Stream.Init(reservedSize, aNumBlocks); - Init(); - } - HRESULT ReadBlock(UInt32 &uncompressedSize, bool &dataAreCorrect) - { - return m_Stream.ReadBlock(uncompressedSize, dataAreCorrect); - } -}; - -class CDecoder : - public ICompressCoder, - public CMyUnknownImp -{ - CLZOutWindow m_OutWindowStream; - CMSZipBitDecoder m_InBitStream; - NCompress::NHuffman::CDecoder m_MainDecoder; - NCompress::NHuffman::CDecoder m_DistDecoder; - NCompress::NHuffman::CDecoder m_LevelDecoder; - - bool m_FinalBlock; - bool m_StoredMode; - UInt32 m_StoredBlockSize; - - Byte m_ReservedSize; - UInt32 m_NumInDataBlocks; - - void DeCodeLevelTable(Byte *newLevels, int numLevels); - void ReadTables(); -public: - CDecoder(); - - MY_UNKNOWN_IMP - - HRESULT Flush(); - void ReleaseStreams(); - - STDMETHOD(Code)(ISequentialInStream *inStream, - ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, - ICompressProgressInfo *progress); - - void SetParams(Byte reservedSize, UInt32 numInDataBlocks) - { - m_ReservedSize = reservedSize; - m_NumInDataBlocks = numInDataBlocks; - } - -}; - -}}} - -#endif \ No newline at end of file diff --git a/7zip/Archive/Cab/MSZipExtConst.h b/7zip/Archive/Cab/MSZipExtConst.h deleted file mode 100755 index f51eebb8..00000000 --- a/7zip/Archive/Cab/MSZipExtConst.h +++ /dev/null @@ -1,20 +0,0 @@ -// DeflateExtConst.h - -#ifndef __DEFLATEEXTCONST_H -#define __DEFLATEEXTCONST_H - -#include "Common/Types.h" - -namespace NArchive { -namespace NCab { -namespace NMSZip { - - const UInt32 kDistTableSize = 30; - const UInt32 kHistorySize = 0x8000; - const UInt32 kNumLenCombinations = 256; - - const UInt32 kNumHuffmanBits = 15; - -}}} - -#endif diff --git a/7zip/Archive/Cab/makefile b/7zip/Archive/Cab/makefile index ab635c5d..672afed3 100755 --- a/7zip/Archive/Cab/makefile +++ b/7zip/Archive/Cab/makefile @@ -5,14 +5,10 @@ LIBS = $(LIBS) oleaut32.lib user32.lib CAB_OBJS = \ $O\DllExports.obj \ - $O\CabCopyDecoder.obj \ + $O\CabBlockInStream.obj \ $O\CabHandler.obj \ $O\CabHeader.obj \ $O\CabIn.obj \ - $O\CabInBuffer.obj \ - $O\LZXDecoder.obj \ - $O\LZXi86Converter.obj \ - $O\MSZipDecoder.obj \ COMMON_OBJS = \ $O\Alloc.obj \ @@ -32,6 +28,11 @@ WIN_OBJS = \ $O\LSBFDecoder.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ + $O\StreamUtils.obj \ + +COMPRESS_LZX_OBJS = \ + $O\LzxDecoder.obj \ + $O\Lzx86Converter.obj \ OBJS = \ $O\StdAfx.obj \ @@ -39,7 +40,11 @@ OBJS = \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ + $(COMPRESS_LZX_OBJS) \ + $O\DeflateDecoder.obj \ + $O\QuantumDecoder.obj \ $O\LZOutWindow.obj \ + $O\CopyCoder.obj \ $O\resource.res !include "../../../Build.mak" @@ -52,5 +57,14 @@ $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) +$(COMPRESS_LZX_OBJS): ../../Compress/Lzx/$(*B).cpp + $(COMPL_O2) +$O\DeflateDecoder.obj: ../../Compress/Deflate/$(*B).cpp + $(COMPL_O2) +$O\QuantumDecoder.obj: ../../Compress/Quantum/$(*B).cpp + $(COMPL) $O\LZOutWindow.obj: ../../Compress/LZ/$(*B).cpp $(COMPL) +$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp + $(COMPL) + diff --git a/7zip/Archive/Chm/Chm.dsp b/7zip/Archive/Chm/Chm.dsp new file mode 100755 index 00000000..7e0b7c66 --- /dev/null +++ b/7zip/Archive/Chm/Chm.dsp @@ -0,0 +1,337 @@ +# Microsoft Developer Studio Project File - Name="Chm" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=Chm - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Chm.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Chm.mak" CFG="Chm - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Chm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Chm - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Chm - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CHM_EXPORTS" /YX /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CHM_EXPORTS" /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" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-Zip\Formats\chm.dll" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "Chm - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CHM_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../../" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CHM_EXPORTS" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-Zip\Formats\chm.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "Chm - Win32 Release" +# Name "Chm - Win32 Debug" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Archive.def +# End Source File +# Begin Source File + +SOURCE=.\DllExports.cpp +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"StdAfx.h" +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "Engine" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\ChmHandler.cpp +# End Source File +# Begin Source File + +SOURCE=.\ChmHandler.h +# End Source File +# Begin Source File + +SOURCE=.\ChmHeader.cpp +# End Source File +# Begin Source File + +SOURCE=.\ChmHeader.h +# End Source File +# Begin Source File + +SOURCE=.\ChmIn.cpp +# End Source File +# Begin Source File + +SOURCE=.\ChmIn.h +# End Source File +# End Group +# Begin Group "7zip Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Common\InBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\InBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LimitedStreams.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LimitedStreams.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File +# End Group +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Common\Alloc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Alloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Buffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\String.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\String.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\UTFConvert.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\UTFConvert.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Vector.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Vector.h +# End Source File +# End Group +# Begin Group "Windows" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.h +# End Source File +# End Group +# Begin Group "Archive Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Common\ItemNameUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ItemNameUtils.h +# End Source File +# End Group +# Begin Group "Compress" + +# PROP Default_Filter "" +# Begin Group "LZ" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\LZ\LZOutWindow.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LZ\LZOutWindow.h +# End Source File +# End Group +# Begin Group "Lzx" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Lzx\Lzx.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzx\Lzx86Converter.cpp + +!IF "$(CFG)" == "Chm - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Chm - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzx\Lzx86Converter.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzx\LzxDecoder.cpp + +!IF "$(CFG)" == "Chm - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Chm - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzx\LzxDecoder.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\Compress\Copy\CopyCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Copy\CopyCoder.h +# End Source File +# End Group +# End Target +# End Project diff --git a/7zip/Archive/Chm/Chm.dsw b/7zip/Archive/Chm/Chm.dsw new file mode 100755 index 00000000..58cb09b2 --- /dev/null +++ b/7zip/Archive/Chm/Chm.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Chm"=.\Chm.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/7zip/Archive/Chm/ChmHandler.cpp b/7zip/Archive/Chm/ChmHandler.cpp new file mode 100755 index 00000000..3f2d3cc7 --- /dev/null +++ b/7zip/Archive/Chm/ChmHandler.cpp @@ -0,0 +1,729 @@ +// Chm/Handler.cpp + +#include "StdAfx.h" + +#include "Common/StringConvert.h" +#include "Common/Defs.h" +#include "Common/UTFConvert.h" +#include "Common/ComTry.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../../Common/LimitedStreams.h" +#include "../../Common/StreamUtils.h" +#include "../../Common/ProgressUtils.h" + +#include "../../Compress/Copy/CopyCoder.h" +#include "../../Compress/Lzx/LzxDecoder.h" + +#include "../Common/ItemNameUtils.h" + +#include "ChmHandler.h" + + +using namespace NWindows; +using namespace NTime; + +namespace NArchive { +namespace NChm { + +// #define _CHM_DETAILS + +#ifdef _CHM_DETAILS + +enum +{ + kpidSection = kpidUserDefined, + kpidOffset +}; + +#endif + +STATPROPSTG kProperties[] = +{ + { NULL, kpidPath, VT_BSTR}, + // { NULL, kpidIsFolder, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidBlock, VT_UI4} + + #ifdef _CHM_DETAILS + , + { L"Section", kpidSection, VT_UI4}, + { L"Offset", kpidOffset, VT_UI4} + #endif +}; + +static const int kNumProperties = sizeof(kProperties) / sizeof(kProperties[0]); + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + value->vt = VT_EMPTY; + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) +{ + *numProperties = sizeof(kProperties) / sizeof(kProperties[0]); + return S_OK; +} + +STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, + BSTR *name, PROPID *propID, VARTYPE *varType) +{ + if(index >= sizeof(kProperties) / sizeof(kProperties[0])) + return E_INVALIDARG; + const STATPROPSTG &srcItem = kProperties[index]; + *propID = srcItem.propid; + *varType = srcItem.vt; + if (srcItem.lpwstrName == 0) + *name = 0; + else + *name = ::SysAllocString(srcItem.lpwstrName); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) +{ + *numProperties = 0; + return S_OK; +} + +STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index, + BSTR *name, PROPID *propID, VARTYPE *varType) +{ + return E_INVALIDARG; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant propVariant; + if (m_Database.NewFormat) + { + switch(propID) + { + case kpidSize: + propVariant = (UInt64)m_Database.NewFormatString.Length(); + break; + } + propVariant.Detach(value); + return S_OK; + } + int entryIndex; + if (m_Database.LowLevel) + entryIndex = index; + else + entryIndex = m_Database.Indices[index]; + const CItem &item = m_Database.Items[entryIndex]; + switch(propID) + { + case kpidPath: + { + UString us; + if (ConvertUTF8ToUnicode(item.Name, us)) + { + if (!m_Database.LowLevel) + { + if (us.Length() > 1) + if (us[0] == L'/') + us.Delete(0); + } + propVariant = NItemName::GetOSName2(us); + } + break; + } + case kpidIsFolder: + propVariant = item.IsDirectory(); + break; + case kpidSize: + propVariant = item.Size; + break; + case kpidMethod: + { + if (!item.IsDirectory()) + if (item.Section == 0) + propVariant = L"Copy"; + else if (item.Section < m_Database.Sections.Size()) + propVariant = m_Database.Sections[(size_t)item.Section].GetMethodName(); + break; + } + case kpidBlock: + if (m_Database.LowLevel) + propVariant = item.Section; + else if (item.Section != 0) + propVariant = m_Database.GetFolder(index); + break; + + #ifdef _CHM_DETAILS + + case kpidSection: + propVariant = (UInt32)item.Section; + break; + case kpidOffset: + propVariant = (UInt32)item.Offset; + break; + + #endif + } + propVariant.Detach(value); + return S_OK; + COM_TRY_END +} + +class CPropgressImp: public CProgressVirt +{ + CMyComPtr m_OpenArchiveCallback; +public: + STDMETHOD(SetTotal)(const UInt64 *numFiles); + STDMETHOD(SetCompleted)(const UInt64 *numFiles); + void Init(IArchiveOpenCallback *openArchiveCallback) + { m_OpenArchiveCallback = openArchiveCallback; } +}; + +STDMETHODIMP CPropgressImp::SetTotal(const UInt64 *numFiles) +{ + if (m_OpenArchiveCallback) + return m_OpenArchiveCallback->SetCompleted(numFiles, NULL); + return S_OK; +} + +STDMETHODIMP CPropgressImp::SetCompleted(const UInt64 *numFiles) +{ + if (m_OpenArchiveCallback) + return m_OpenArchiveCallback->SetCompleted(numFiles, NULL); + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, + const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback *openArchiveCallback) +{ + COM_TRY_BEGIN + m_Stream.Release(); + try + { + CInArchive archive; + CPropgressImp progressImp; + progressImp.Init(openArchiveCallback); + RINOK(archive.Open(inStream, maxCheckStartPosition, m_Database)); + /* + if (m_Database.LowLevel) + return S_FALSE; + */ + m_Stream = inStream; + } + catch(...) + { + return S_FALSE; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + m_Stream.Release(); + return S_OK; +} + +class CChmFolderOutStream: + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + + HRESULT Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK); + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + + UInt64 m_FolderSize; + UInt64 m_PosInFolder; + UInt64 m_PosInSection; + const CRecordVector *m_ExtractStatuses; + int m_StartIndex; + int m_CurrentIndex; + int m_NumFiles; + +private: + const CFilesDatabase *m_Database; + CMyComPtr m_ExtractCallback; + bool m_TestMode; + + bool m_IsOk; + bool m_FileIsOpen; + UInt64 m_RemainFileSize; + CMyComPtr m_RealOutStream; + + HRESULT OpenFile(); + HRESULT WriteEmptyFiles(); +public: + void Init( + const CFilesDatabase *database, + IArchiveExtractCallback *extractCallback, + bool testMode); + HRESULT FlushCorrupted(); +}; + +void CChmFolderOutStream::Init( + const CFilesDatabase *database, + IArchiveExtractCallback *extractCallback, + bool testMode) +{ + m_Database = database; + m_ExtractCallback = extractCallback; + m_TestMode = testMode; + + m_CurrentIndex = 0; + m_FileIsOpen = false; +} + +HRESULT CChmFolderOutStream::OpenFile() +{ + Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? (m_TestMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract) : + NExtract::NAskMode::kSkip; + m_RealOutStream.Release(); + RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode)); + if (!m_RealOutStream && !m_TestMode) + askMode = NArchive::NExtract::NAskMode::kSkip; + return m_ExtractCallback->PrepareOperation(askMode); +} + +HRESULT CChmFolderOutStream::WriteEmptyFiles() +{ + if (m_FileIsOpen) + return S_OK; + for(;m_CurrentIndex < m_NumFiles; m_CurrentIndex++) + { + UInt64 fileSize = m_Database->GetFileSize(m_StartIndex + m_CurrentIndex); + if (fileSize != 0) + return S_OK; + HRESULT result = OpenFile(); + m_RealOutStream.Release(); + RINOK(result); + RINOK(m_ExtractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + } + return S_OK; +} + +// This is WritePart function +HRESULT CChmFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK) +{ + UInt32 realProcessed = 0; + if (processedSize != NULL) + *processedSize = 0; + while(size != 0) + { + if (m_FileIsOpen) + { + UInt32 numBytesToWrite = (UInt32)MyMin(m_RemainFileSize, (UInt64)(size)); + HRESULT res = S_OK; + if (numBytesToWrite > 0) + { + if (!isOK) + m_IsOk = false; + if (m_RealOutStream) + { + UInt32 processedSizeLocal = 0; + res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal); + numBytesToWrite = processedSizeLocal; + } + } + realProcessed += numBytesToWrite; + if (processedSize != NULL) + *processedSize = realProcessed; + data = (const void *)((const Byte *)data + numBytesToWrite); + size -= numBytesToWrite; + m_RemainFileSize -= numBytesToWrite; + m_PosInSection += numBytesToWrite; + m_PosInFolder += numBytesToWrite; + if (res != S_OK) + return res; + if (m_RemainFileSize == 0) + { + m_RealOutStream.Release(); + RINOK(m_ExtractCallback->SetOperationResult( + m_IsOk ? + NArchive::NExtract::NOperationResult::kOK: + NArchive::NExtract::NOperationResult::kDataError)); + m_FileIsOpen = false; + } + if (realProcessed > 0) + break; // with this break this function works as write part + } + else + { + if (m_CurrentIndex >= m_NumFiles) + return E_FAIL; + int fullIndex = m_StartIndex + m_CurrentIndex; + m_RemainFileSize = m_Database->GetFileSize(fullIndex); + UInt64 fileOffset = m_Database->GetFileOffset(fullIndex); + if (fileOffset < m_PosInSection) + return E_FAIL; + if (fileOffset > m_PosInSection) + { + UInt32 numBytesToWrite = (UInt32)MyMin(fileOffset - m_PosInSection, UInt64(size)); + realProcessed += numBytesToWrite; + if (processedSize != NULL) + *processedSize = realProcessed; + data = (const void *)((const Byte *)data + numBytesToWrite); + size -= numBytesToWrite; + m_PosInSection += numBytesToWrite; + m_PosInFolder += numBytesToWrite; + } + if (fileOffset == m_PosInSection) + { + RINOK(OpenFile()); + m_FileIsOpen = true; + m_CurrentIndex++; + m_IsOk = true; + } + } + } + return WriteEmptyFiles(); +} + +STDMETHODIMP CChmFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + return Write2(data, size, processedSize, true); +} + +HRESULT CChmFolderOutStream::FlushCorrupted() +{ + const UInt32 kBufferSize = (1 << 10); + Byte buffer[kBufferSize]; + for (int i = 0; i < kBufferSize; i++) + buffer[i] = 0; + while(m_PosInFolder < m_FolderSize) + { + UInt32 size = (UInt32)MyMin(m_FolderSize - m_PosInFolder, (UInt64)kBufferSize); + UInt32 processedSizeLocal = 0; + RINOK(Write2(buffer, size, &processedSizeLocal, false)); + } + return S_OK; +} + + +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, + Int32 _aTestMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == UInt32(-1)); + + if (allFilesMode) + numItems = m_Database.NewFormat ? 1: + (m_Database.LowLevel ? + m_Database.Items.Size(): + m_Database.Indices.Size()); + if(numItems == 0) + return S_OK; + bool testMode = (_aTestMode != 0); + + UInt64 currentTotalSize = 0; + + CMyComPtr copyCoder; + UInt32 i; + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + + if (m_Database.LowLevel) + { + UInt64 currentItemSize = 0; + UInt64 totalSize = 0; + if (m_Database.NewFormat) + totalSize = m_Database.NewFormatString.Length(); + else + for(i = 0; i < numItems; i++) + totalSize += m_Database.Items[allFilesMode ? i : indices[i]].Size; + extractCallback->SetTotal(totalSize); + + for(i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + { + RINOK(extractCallback->SetCompleted(¤tTotalSize)); + CMyComPtr realOutStream; + Int32 askMode; + askMode = testMode ? NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + if (m_Database.NewFormat) + { + if (index != 0) + return E_FAIL; + if(!testMode && (!realOutStream)) + continue; + if (!testMode) + { + UInt32 size = m_Database.NewFormatString.Length(); + RINOK(WriteStream(realOutStream, (const char *)m_Database.NewFormatString, size, 0)); + } + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + continue; + } + const CItem &item = m_Database.Items[index]; + + currentItemSize = item.Size; + + if(!testMode && (!realOutStream)) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + if (item.Section != 0) + { + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); + continue; + } + + if (testMode) + { + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + continue; + } + + RINOK(m_Stream->Seek(m_Database.ContentOffset + item.Offset, STREAM_SEEK_SET, NULL)); + streamSpec->Init(m_Stream, item.Size); + + CLocalProgress *localProgressSpec = new CLocalProgress; + CMyComPtr progress = localProgressSpec; + localProgressSpec->Init(extractCallback, false); + + CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo; + CMyComPtr compressProgress = localCompressProgressSpec; + localCompressProgressSpec->Init(progress, ¤tTotalSize, ¤tTotalSize); + + if(!copyCoder) + copyCoder = new NCompress::CCopyCoder; + RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, compressProgress)); + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + } + return S_OK; + } + + UInt64 lastFolderIndex = ((UInt64)0 - 1); + for(i = 0; i < numItems; i++) + { + UInt32 index = allFilesMode ? i : indices[i]; + int entryIndex = m_Database.Indices[index]; + const CItem &item = m_Database.Items[entryIndex]; + UInt64 sectionIndex = item.Section; + if (item.IsDirectory() || item.Size == 0) + continue; + if (sectionIndex == 0) + { + currentTotalSize += item.Size; + continue; + } + const CSectionInfo §ion = m_Database.Sections[(size_t)item.Section]; + if (section.IsLzx()) + { + const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo; + UInt64 folderIndex = m_Database.GetFolder(index); + if (lastFolderIndex == folderIndex) + folderIndex++; + lastFolderIndex = m_Database.GetLastFolder(index); + for (; folderIndex <= lastFolderIndex; folderIndex++) + currentTotalSize += lzxInfo.GetFolderSize(); + } + } + + RINOK(extractCallback->SetTotal(currentTotalSize)); + + NCompress::NLzx::CDecoder *lzxDecoderSpec = 0; + CMyComPtr lzxDecoder; + CChmFolderOutStream *chmFolderOutStream = 0; + CMyComPtr outStream; + + currentTotalSize = 0; + + CRecordVector extractStatuses; + for(i = 0; i < numItems;) + { + RINOK(extractCallback->SetCompleted(¤tTotalSize)); + UInt32 index = allFilesMode ? i : indices[i]; + i++; + int entryIndex = m_Database.Indices[index]; + const CItem &item = m_Database.Items[entryIndex]; + UInt64 sectionIndex = item.Section; + Int32 askMode= testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + if (item.IsDirectory()) + { + CMyComPtr realOutStream; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + RINOK(extractCallback->PrepareOperation(askMode)); + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + continue; + } + + CLocalProgress *localProgressSpec = new CLocalProgress; + CMyComPtr progress = localProgressSpec; + localProgressSpec->Init(extractCallback, false); + + CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo; + CMyComPtr compressProgress = localCompressProgressSpec; + localCompressProgressSpec->Init(progress, NULL, ¤tTotalSize); + + if (item.Size == 0 || sectionIndex == 0) + { + CMyComPtr realOutStream; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + if(!testMode && (!realOutStream)) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + if (!testMode && item.Size != 0) + { + RINOK(m_Stream->Seek(m_Database.ContentOffset + item.Offset, STREAM_SEEK_SET, NULL)); + streamSpec->Init(m_Stream, item.Size); + if(!copyCoder) + copyCoder = new NCompress::CCopyCoder; + RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, compressProgress)); + } + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + currentTotalSize += item.Size; + continue; + } + + const CSectionInfo §ion = m_Database.Sections[(size_t)sectionIndex]; + + if (!section.IsLzx()) + { + CMyComPtr realOutStream; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + if(!testMode && (!realOutStream)) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); + continue; + } + + const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo; + + if (chmFolderOutStream == 0) + { + chmFolderOutStream = new CChmFolderOutStream; + outStream = chmFolderOutStream; + } + + chmFolderOutStream->Init(&m_Database, extractCallback, testMode); + + if(lzxDecoderSpec == NULL) + { + lzxDecoderSpec = new NCompress::NLzx::CDecoder; + lzxDecoder = lzxDecoderSpec; + } + + UInt64 folderIndex = m_Database.GetFolder(index); + + UInt64 compressedPos = m_Database.ContentOffset + section.Offset; + UInt32 numDictBits = lzxInfo.GetNumDictBits(); + RINOK(lzxDecoderSpec->SetParams(numDictBits)); + + const CItem *lastItem = &item; + extractStatuses.Clear(); + extractStatuses.Add(true); + + for (;true; folderIndex++) + { + RINOK(extractCallback->SetCompleted(¤tTotalSize)); + + UInt64 startPos = lzxInfo.GetFolderPos(folderIndex); + UInt64 finishPos = lastItem->Offset + lastItem->Size; + UInt64 limitFolderIndex = lzxInfo.GetFolder(finishPos); + + lastFolderIndex = m_Database.GetLastFolder(index); + UInt64 folderSize = lzxInfo.GetFolderSize(); + UInt64 unPackSize = folderSize; + if (extractStatuses.IsEmpty()) + chmFolderOutStream->m_StartIndex = index + 1; + else + chmFolderOutStream->m_StartIndex = index; + if (limitFolderIndex == folderIndex) + { + for(; i < numItems; i++) + { + UInt32 nextIndex = allFilesMode ? i : indices[i]; + int entryIndex = m_Database.Indices[nextIndex]; + const CItem &nextItem = m_Database.Items[entryIndex]; + if (nextItem.Section != sectionIndex) + break; + UInt64 nextFolderIndex = m_Database.GetFolder(nextIndex); + if (nextFolderIndex != folderIndex) + break; + for (index++; index < nextIndex; index++) + extractStatuses.Add(false); + extractStatuses.Add(true); + index = nextIndex; + lastItem = &nextItem; + if (nextItem.Size != 0) + finishPos = nextItem.Offset + nextItem.Size; + lastFolderIndex = m_Database.GetLastFolder(index); + } + } + unPackSize = MyMin(finishPos - startPos, unPackSize); + + chmFolderOutStream->m_FolderSize = folderSize; + chmFolderOutStream->m_PosInFolder = 0; + chmFolderOutStream->m_PosInSection = startPos; + chmFolderOutStream->m_ExtractStatuses = &extractStatuses; + chmFolderOutStream->m_NumFiles = extractStatuses.Size(); + chmFolderOutStream->m_CurrentIndex = 0; + try + { + UInt64 startBlock = lzxInfo.GetBlockIndexFromFolderIndex(folderIndex); + const CResetTable &rt = lzxInfo.ResetTable; + UInt32 numBlocks = (UInt32)rt.GetNumBlocks(unPackSize); + for (UInt32 b = 0; b < numBlocks; b++) + { + UInt64 completedSize = currentTotalSize + chmFolderOutStream->m_PosInSection - startPos; + RINOK(extractCallback->SetCompleted(&completedSize)); + UInt64 bCur = startBlock + b; + if (bCur >= rt.ResetOffsets.Size()) + return E_FAIL; + UInt64 startOffset = rt.ResetOffsets[(int)startBlock]; + UInt64 offset = rt.ResetOffsets[(int)bCur]; + UInt64 compressedSize; + rt.GetCompressedSizeOfBlock(bCur, compressedSize); + UInt64 rem = finishPos - chmFolderOutStream->m_PosInSection; + if (rem > rt.BlockSize) + rem = rt.BlockSize; + const UInt64 *offsets = (const UInt64 *)&rt.ResetOffsets.Front(); + RINOK(m_Stream->Seek(compressedPos + offset, STREAM_SEEK_SET, NULL)); + streamSpec->Init(m_Stream, compressedSize); + lzxDecoderSpec->SetKeepHistory(b > 0, (int)((offset - startOffset) & 1)); + RINOK(lzxDecoder->Code(inStream, outStream, NULL, &rem, NULL)); + } + } + catch(...) + { + RINOK(chmFolderOutStream->FlushCorrupted()); + } + currentTotalSize += folderSize; + if (folderIndex == lastFolderIndex) + break; + extractStatuses.Clear(); + } + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + COM_TRY_BEGIN + *numItems = m_Database.NewFormat ? 1: + (m_Database.LowLevel ? + m_Database.Items.Size(): + m_Database.Indices.Size()); + return S_OK; + COM_TRY_END +} + +}} diff --git a/7zip/Archive/Chm/ChmHandler.h b/7zip/Archive/Chm/ChmHandler.h new file mode 100755 index 00000000..54f01b84 --- /dev/null +++ b/7zip/Archive/Chm/ChmHandler.h @@ -0,0 +1,46 @@ +// ChmHandler.h + +#ifndef __ARCHIVE_CHM_HANDLER_H +#define __ARCHIVE_CHM_HANDLER_H + +#include "Common/MyCom.h" +#include "../IArchive.h" +#include "ChmIn.h" + +namespace NArchive { +namespace NChm { + +class CHandler: + public IInArchive, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + + STDMETHOD(Open)(IInStream *stream, + const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback *openArchiveCallback); + STDMETHOD(Close)(); + STDMETHOD(GetNumberOfItems)(UInt32 *numItems); + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); + STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback); + + STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value); + + STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties); + STDMETHOD(GetPropertyInfo)(UInt32 index, + BSTR *name, PROPID *propID, VARTYPE *varType); + + STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties); + STDMETHOD(GetArchivePropertyInfo)(UInt32 index, + BSTR *name, PROPID *propID, VARTYPE *varType); + +private: + CFilesDatabase m_Database; + CMyComPtr m_Stream; +}; + +}} + +#endif \ No newline at end of file diff --git a/7zip/Archive/Chm/ChmHeader.cpp b/7zip/Archive/Chm/ChmHeader.cpp new file mode 100755 index 00000000..4d485b6c --- /dev/null +++ b/7zip/Archive/Chm/ChmHeader.cpp @@ -0,0 +1,24 @@ +// Archive/Chm/Header.h + +#include "StdAfx.h" + +#include "ChmHeader.h" + +namespace NArchive{ +namespace NChm{ +namespace NHeader{ + +UInt32 kItsfSignature = 0x46535449 + 1; +UInt32 kItolSignature = 0x4C4F5449 + 1; +static class CSignatureInitializer +{ +public: + CSignatureInitializer() + { + kItsfSignature--; + kItolSignature--; + } +}g_SignatureInitializer; + + +}}} diff --git a/7zip/Archive/Chm/ChmHeader.h b/7zip/Archive/Chm/ChmHeader.h new file mode 100755 index 00000000..9f1bd42b --- /dev/null +++ b/7zip/Archive/Chm/ChmHeader.h @@ -0,0 +1,28 @@ +// Archive/Chm/Header.h + +#ifndef __ARCHIVE_CHM_HEADER_H +#define __ARCHIVE_CHM_HEADER_H + +#include "Common/Types.h" + +namespace NArchive { +namespace NChm { +namespace NHeader{ + +const UInt32 kItspSignature = 0x50535449; +const UInt32 kPmglSignature = 0x4C474D50; +const UInt32 kLzxcSignature = 0x43585A4C; + +const UInt32 kIfcmSignature = 0x4D434649; +const UInt32 kAollSignature = 0x4C4C4F41; +const UInt32 kCaolSignature = 0x4C4F4143; + +extern UInt32 kItsfSignature; + +extern UInt32 kItolSignature; +const UInt32 kItlsSignature = 0x534C5449; +UInt64 inline GetHxsSignature() { return ((UInt64)kItlsSignature << 32) | kItolSignature; } + +}}} + +#endif diff --git a/7zip/Archive/Chm/ChmIn.cpp b/7zip/Archive/Chm/ChmIn.cpp new file mode 100755 index 00000000..79e934ad --- /dev/null +++ b/7zip/Archive/Chm/ChmIn.cpp @@ -0,0 +1,924 @@ +// Archive/ChmIn.cpp + +#include "StdAfx.h" + +#include "Common/StringConvert.h" +#include "Common/MyCom.h" +#include "Common/UTFConvert.h" +#include "Common/IntToString.h" +#include "Windows/Defs.h" + +#include "../../Common/LimitedStreams.h" +#include "ChmIn.h" + +namespace NArchive{ +namespace NChm{ + +// 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 bool AreGuidsEqual(REFGUID g1, REFGUID 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; +} + +static char GetHex(Byte value) +{ + return (value < 10) ? ('0' + value) : ('A' + (value - 10)); +} + +static void PrintByte(Byte b, AString &s) +{ + s += GetHex(b >> 4); + 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; +} + +bool CMethodInfo::IsLzx() const +{ + if (AreGuidsEqual(Guid, kChmLzxGuid)) + return true; + return AreGuidsEqual(Guid, kHelp2LzxGuid); +} + +bool CMethodInfo::IsDes() const +{ + return AreGuidsEqual(Guid, kDesGuid); +} + +UString CMethodInfo::GetName() const +{ + UString s; + if (IsLzx()) + { + s = L"LZX:"; + UInt32 numDictBits = LzxInfo.GetNumDictBits(); + wchar_t temp[32]; + ConvertUInt64ToString(numDictBits, temp); + s += temp; + } + else + { + AString s2; + if (IsDes()) + s2 = "DES"; + else + { + s2 = GetGuidString(); + if (ControlData.GetCapacity() > 0) + { + s2 += ":"; + for (size_t i = 0; i < ControlData.GetCapacity(); i++) + PrintByte(ControlData[i], s2); + } + } + ConvertUTF8ToUnicode(s2, s); + } + return s; +} + +bool CSectionInfo::IsLzx() const +{ + if (Methods.Size() != 1) + return false; + return Methods[0].IsLzx(); +} + +UString CSectionInfo::GetMethodName() const +{ + UString s; + if (!IsLzx()) + { + UString temp; + if (ConvertUTF8ToUnicode(Name, temp)) + s += temp; + s += L": "; + } + for (int i = 0; i < Methods.Size(); i++) + { + if (i != 0) + s += L" "; + s += Methods[i].GetName(); + } + return s; +} + +Byte CInArchive::ReadByte() +{ + Byte b; + if (!_inBuffer.ReadByte(b)) + throw 1; + return b; +} + +void CInArchive::Skeep(size_t size) +{ + while (size-- != 0) + ReadByte(); +} + +void CInArchive::ReadBytes(Byte *data, UInt32 size) +{ + for (UInt32 i = 0; i < size; i++) + data[i] = ReadByte(); +} + +UInt16 CInArchive::ReadUInt16() +{ + UInt16 value = 0; + for (int i = 0; i < 2; i++) + value |= ((UInt16)(ReadByte()) << (8 * i)); + return value; +} + +UInt32 CInArchive::ReadUInt32() +{ + UInt32 value = 0; + for (int i = 0; i < 4; i++) + value |= ((UInt32)(ReadByte()) << (8 * i)); + return value; +} + +UInt64 CInArchive::ReadUInt64() +{ + UInt64 value = 0; + for (int i = 0; i < 8; i++) + value |= ((UInt64)(ReadByte()) << (8 * i)); + return value; +} + +UInt64 CInArchive::ReadEncInt() +{ + UInt64 val = 0;; + for (int i = 0; i < 10; i++) + { + Byte b = ReadByte(); + val |= (b & 0x7F); + if (b < 0x80) + return val; + val <<= 7; + } + throw 1; +} + +void CInArchive::ReadGUID(GUID &g) +{ + g.Data1 = ReadUInt32(); + g.Data2 = ReadUInt16(); + g.Data3 = ReadUInt16(); + ReadBytes(g.Data4, 8); +} + +void CInArchive::ReadString(int size, AString &s) +{ + s.Empty(); + while(size-- != 0) + { + char c = (char)ReadByte(); + if (c == 0) + { + Skeep(size); + return; + } + s += c; + } +} + +void CInArchive::ReadUString(int size, UString &s) +{ + s.Empty(); + while(size-- != 0) + { + wchar_t c = ReadUInt16(); + if (c == 0) + { + Skeep(2 * size); + return; + } + s += c; + } +} + +HRESULT CInArchive::ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size) +{ + RINOK(inStream->Seek(pos, STREAM_SEEK_SET, NULL)); + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr limitedStream(streamSpec); + streamSpec->Init(inStream, size); + _inBuffer.SetStream(limitedStream); + _inBuffer.Init(); + return S_OK; +} + +HRESULT CInArchive::ReadDirEntry(CDatabase &database) +{ + CItem item; + UInt64 nameLength = ReadEncInt(); + if (nameLength == 0 || nameLength >= 0x10000000) + return S_FALSE; + ReadString((int)nameLength, item.Name); + item.Section = ReadEncInt(); + item.Offset = ReadEncInt(); + item.Size = ReadEncInt(); + database.Items.Add(item); + return S_OK; +} + +HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database) +{ + UInt32 headerSize = ReadUInt32(); + if (headerSize != 0x60) + return S_FALSE; + UInt32 unknown1 = ReadUInt32(); + if (unknown1 != 0 && unknown1 != 1) // it's 0 in one .sll file + return S_FALSE; + UInt32 timeStamp = ReadUInt32(); + // Considered as a big-endian DWORD, it appears to contain seconds (MSB) and + // fractional seconds (second byte). + // 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; + ReadGUID(g); // {7C01FD10-7BAA-11D0-9E0C-00A0-C922-E6EC} + ReadGUID(g); // {7C01FD11-7BAA-11D0-9E0C-00A0-C922-E6EC} + const int kNumSections = 2; + UInt64 sectionOffsets[kNumSections]; + UInt64 sectionSizes[kNumSections]; + int i; + for (i = 0; i < kNumSections; i++) + { + sectionOffsets[i] = ReadUInt64(); + sectionSizes[i] = ReadUInt64(); + } + // if (chmVersion == 3) + database.ContentOffset = ReadUInt64(); + /* + else + database.ContentOffset = _startPosition + 0x58 + */ + + /* + // Section 0 + ReadChunk(inStream, sectionOffsets[0], sectionSizes[0]); + if (sectionSizes[0] != 0x18) + return S_FALSE; + ReadUInt32(); // unknown: 01FE + ReadUInt32(); // unknown: 0 + UInt64 fileSize = ReadUInt64(); + ReadUInt32(); // unknown: 0 + ReadUInt32(); // unknown: 0 + */ + + // Section 1: The Directory Listing + ReadChunk(inStream, sectionOffsets[1], sectionSizes[1]); + if (ReadUInt32() != NHeader::kItspSignature) + return S_FALSE; + if (ReadUInt32() != 1) // version + return S_FALSE; + UInt32 dirHeaderSize = ReadUInt32(); + ReadUInt32(); // 0x0A (unknown) + UInt32 dirChunkSize = ReadUInt32(); // $1000 + if (dirChunkSize < 32) + return S_FALSE; + UInt32 density = ReadUInt32(); // "Density" of quickref section, usually 2. + UInt32 depth = ReadUInt32(); // Depth of the index tree: 1 there is no index, + // 2 if there is one level of PMGI chunks. + + UInt32 chunkNumber = ReadUInt32(); // Chunk number of root index chunk, -1 if there is none + // (though at least one file has 0 despite there being no + // index chunk, probably a bug.) + UInt32 firstPmglChunkNumber = ReadUInt32(); // Chunk number of first PMGL (listing) chunk + UInt32 lastPmglChunkNumber = ReadUInt32(); // Chunk number of last PMGL (listing) chunk + ReadUInt32(); // -1 (unknown) + UInt32 numDirChunks = ReadUInt32(); // Number of directory chunks (total) + UInt32 windowsLangId = ReadUInt32(); + ReadGUID(g); // {5D02926A-212E-11D0-9DF9-00A0C922E6EC} + ReadUInt32(); // 0x54 (This is the length again) + ReadUInt32(); // -1 (unknown) + ReadUInt32(); // -1 (unknown) + ReadUInt32(); // -1 (unknown) + + for (UInt32 ci = 0; ci < numDirChunks; ci++) + { + UInt64 chunkPos = _inBuffer.GetProcessedSize(); + if (ReadUInt32() == NHeader::kPmglSignature) + { + // The quickref area is written backwards from the end of the chunk. + // One quickref entry exists for every n entries in the file, where n + // is calculated as 1 + (1 << quickref density). So for density = 2, n = 5. + + UInt32 quickrefLength = ReadUInt32(); // Length of free space and/or quickref area at end of directory chunk + if (quickrefLength > dirChunkSize || quickrefLength < 2) + return S_FALSE; + ReadUInt32(); // Always 0 + ReadUInt32(); // Chunk number of previous listing chunk when reading + // directory in sequence (-1 if this is the first listing chunk) + ReadUInt32(); // Chunk number of next listing chunk when reading + // directory in sequence (-1 if this is the last listing chunk) + int numItems = 0; + while (true) + { + UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos; + UInt32 offsetLimit = dirChunkSize - quickrefLength; + if (offset > offsetLimit) + return S_FALSE; + if (offset == offsetLimit) + break; + RINOK(ReadDirEntry(database)); + numItems++; + } + Skeep(quickrefLength - 2); + if (ReadUInt16() != numItems) + return S_FALSE; + } + else + Skeep(dirChunkSize - 4); + } + return S_OK; +} + +HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database) +{ + if (ReadUInt32() != 1) // version + return S_FALSE; + if (ReadUInt32() != 0x28) // Location of header section table + return S_FALSE; + UInt32 numHeaderSections = ReadUInt32(); + const int kNumHeaderSectionsMax = 5; + if (numHeaderSections != kNumHeaderSectionsMax) + return S_FALSE; + ReadUInt32(); // Length of post-header table + GUID g; + ReadGUID(g); // {0A9007C1-4076-11D3-8789-0000F8105754} + + // header section table + UInt64 sectionOffsets[kNumHeaderSectionsMax]; + UInt64 sectionSizes[kNumHeaderSectionsMax]; + UInt32 i; + for (i = 0; i < numHeaderSections; i++) + { + sectionOffsets[i] = ReadUInt64(); + sectionSizes[i] = ReadUInt64(); + } + + // Post-Header + ReadUInt32(); // 2 + ReadUInt32(); // 0x98: offset to CAOL from beginning of post-header) + // ----- Directory information + ReadUInt64(); // Chunk number of top-level AOLI chunk in directory, or -1 + ReadUInt64(); // Chunk number of first AOLL chunk in directory + ReadUInt64(); // Chunk number of last AOLL chunk in directory + ReadUInt64(); // 0 (unknown) + ReadUInt32(); // $2000 (Directory chunk size of directory) + ReadUInt32(); // Quickref density for main directory, usually 2 + ReadUInt32(); // 0 (unknown) + ReadUInt32(); // Depth of main directory index tree + // 1 there is no index, 2 if there is one level of AOLI chunks. + ReadUInt64(); // 0 (unknown) + UInt64 numDirEntries = ReadUInt64(); // Number of directory entries + // ----- Directory Index Information + ReadUInt64(); // -1 (unknown, probably chunk number of top-level AOLI in directory index) + ReadUInt64(); // Chunk number of first AOLL chunk in directory index + ReadUInt64(); // Chunk number of last AOLL chunk in directory index + ReadUInt64(); // 0 (unknown) + ReadUInt32(); // $200 (Directory chunk size of directory index) + ReadUInt32(); // Quickref density for directory index, usually 2 + ReadUInt32(); // 0 (unknown) + ReadUInt32(); // Depth of directory index index tree. + ReadUInt64(); // Possibly flags -- sometimes 1, sometimes 0. + ReadUInt64(); // Number of directory index entries (same as number of AOLL + // chunks in main directory) + + // (The obvious guess for the following two fields, which recur in a number + // of places, is they are maximum sizes for the directory and directory index. + // However, I have seen no direct evidence that this is the case.) + + ReadUInt32(); // $100000 (Same as field following chunk size in directory) + ReadUInt32(); // $20000 (Same as field following chunk size in directory index) + + ReadUInt64(); // 0 (unknown) + if (ReadUInt32() != NHeader::kCaolSignature) + return S_FALSE; + if (ReadUInt32() != 2) // (Most likely a version number) + return S_FALSE; + UInt32 caolLength = ReadUInt32(); // $50 (Length of the CAOL section, which includes the ITSF section) + if (caolLength >= 0x2C) + { + UInt32 c7 = ReadUInt16(); // Unknown. Remains the same when identical files are built. + // Does not appear to be a checksum. Many files have + // 'HH' (HTML Help?) here, indicating this may be a compiler ID + // field. But at least one ITOL/ITLS compiler does not set this + // field to a constant value. + ReadUInt16(); // 0 (Unknown. Possibly part of 00A4 field) + ReadUInt32(); // Unknown. Two values have been seen -- $43ED, and 0. + ReadUInt32(); // $2000 (Directory chunk size of directory) + ReadUInt32(); // $200 (Directory chunk size of directory index) + ReadUInt32(); // $100000 (Same as field following chunk size in directory) + ReadUInt32(); // $20000 (Same as field following chunk size in directory index) + ReadUInt32(); // 0 (unknown) + ReadUInt32(); // 0 (Unknown) + if (caolLength == 0x2C) + { + database.ContentOffset = 0; + database.NewFormat = true; + } + else if (caolLength == 0x50) + { + ReadUInt32(); // 0 (Unknown) + if (ReadUInt32() != NHeader::kItsfSignature) + return S_FALSE; + if (ReadUInt32() != 4) // $4 (Version number -- CHM uses 3) + return S_FALSE; + if (ReadUInt32() != 0x20) // $20 (length of ITSF) + return S_FALSE; + UInt32 unknown = ReadUInt32(); + if (unknown != 0 && unknown != 1) // = 0 for some HxW files, 1 in other cases; + return S_FALSE; + database.ContentOffset = _startPosition + ReadUInt64(); + UInt32 timeStamp = ReadUInt32(); + // A timestamp of some sort. + // Considered as a big-endian DWORD, it appears to contain + // seconds (MSB) and fractional seconds (second byte). + // 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(); // BE? + } + else + return S_FALSE; + } + + /* + // Section 0 + ReadChunk(inStream, _startPosition + sectionOffsets[0], sectionSizes[0]); + if (sectionSizes[0] != 0x18) + return S_FALSE; + ReadUInt32(); // unknown: 01FE + ReadUInt32(); // unknown: 0 + UInt64 fileSize = ReadUInt64(); + ReadUInt32(); // unknown: 0 + ReadUInt32(); // unknown: 0 + */ + + // Section 1: The Directory Listing + ReadChunk(inStream, _startPosition + sectionOffsets[1], sectionSizes[1]); + if (ReadUInt32() != NHeader::kIfcmSignature) + return S_FALSE; + if (ReadUInt32() != 1) // (probably a version number) + return S_FALSE; + UInt32 dirChunkSize = ReadUInt32(); // $2000 + if (dirChunkSize < 64) + return S_FALSE; + ReadUInt32(); // $100000 (unknown) + ReadUInt32(); // -1 (unknown) + ReadUInt32(); // -1 (unknown) + UInt32 numDirChunks = ReadUInt32(); + ReadUInt32(); // 0 (unknown, probably high word of above) + + for (UInt32 ci = 0; ci < numDirChunks; ci++) + { + UInt64 chunkPos = _inBuffer.GetProcessedSize(); + if (ReadUInt32() == NHeader::kAollSignature) + { + UInt32 quickrefLength = ReadUInt32(); // Length of quickref area at end of directory chunk + if (quickrefLength > dirChunkSize || quickrefLength < 2) + return S_FALSE; + ReadUInt64(); // Directory chunk number + // This must match physical position in file, that is + // the chunk size times the chunk number must be the + // offset from the end of the directory header. + ReadUInt64(); // Chunk number of previous listing chunk when reading + // directory in sequence (-1 if first listing chunk) + ReadUInt64(); // Chunk number of next listing chunk when reading + // directory in sequence (-1 if last listing chunk) + ReadUInt64(); // Number of first listing entry in this chunk + ReadUInt32(); // 1 (unknown -- other values have also been seen here) + ReadUInt32(); // 0 (unknown) + + int numItems = 0; + while (true) + { + UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos; + UInt32 offsetLimit = dirChunkSize - quickrefLength; + if (offset > offsetLimit) + return S_FALSE; + if (offset == offsetLimit) + break; + if (database.NewFormat) + { + UInt16 nameLength = ReadUInt16(); + if (nameLength == 0) + return S_FALSE; + UString name; + ReadUString((int)nameLength, name); + AString s; + ConvertUnicodeToUTF8(name, s); + Byte b = ReadByte(); + s += ' '; + PrintByte(b, s); + s += ' '; + UInt64 len = ReadEncInt(); + // then number of items ? + // then length ? + // then some data (binary encoding?) + while (len-- != 0) + { + b = ReadByte(); + PrintByte(b, s); + } + database.NewFormatString += s; + database.NewFormatString += "\r\n"; + } + else + { + RINOK(ReadDirEntry(database)); + } + numItems++; + } + Skeep(quickrefLength - 2); + if (ReadUInt16() != numItems) + return S_FALSE; + if (numItems > numDirEntries) + return S_FALSE; + numDirEntries -= numItems; + } + else + Skeep(dirChunkSize - 4); + } + return numDirEntries == 0 ? S_OK : S_FALSE; +} + +HRESULT CInArchive::DecompressStream(IInStream *inStream, const CDatabase &database, const AString &name) +{ + int index = database.FindItem(name); + if (index < 0) + return S_FALSE; + const CItem &item = database.Items[index]; + _chunkSize = item.Size; + return ReadChunk(inStream, database.ContentOffset + item.Offset, item.Size); +} + + +#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"; + +static AString GetSectionPrefix(const AString &name) +{ + return AString(kStorage) + name + AString("/"); +} + +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + +static int CompareFiles(const int *p1, const int *p2, void *param) +{ + const CObjectVector &items = *(const CObjectVector *)param; + const CItem &item1 = items[*p1]; + const CItem &item2 = items[*p2]; + bool isDir1 = item1.IsDirectory(); + bool isDir2 = item2.IsDirectory(); + if (isDir1 && !isDir2) + return -1; + if (isDir2) + { + if (isDir1) + return MyCompare(*p1, *p2); + return 1; + } + RINOZ(MyCompare(item1.Section, item2.Section)); + RINOZ(MyCompare(item1.Offset, item2.Offset)); + RINOZ(MyCompare(item1.Size, item2.Size)); + return MyCompare(*p1, *p2); +} + +void CFilesDatabase::SetIndices() +{ + for (int i = 0; i < Items.Size(); i++) + { + const CItem &item = Items[i]; + if (item.IsUserItem() && item.Name.Length() != 1) + Indices.Add(i); + } +} + +void CFilesDatabase::Sort() +{ + Indices.Sort(CompareFiles, (void *)&Items); +} + +bool CFilesDatabase::Check() +{ + UInt64 maxPos = 0; + UInt64 prevSection = 0; + for(int i = 0; i < Indices.Size(); i++) + { + const CItem &item = Items[Indices[i]]; + if (item.Section == 0 || item.IsDirectory()) + continue; + if (item.Section != prevSection) + { + prevSection = item.Section; + maxPos = 0; + continue; + } + if (item.Offset < maxPos) + return false; + maxPos = item.Offset + item.Size; + if (maxPos < item.Offset) + return false; + } + return true; +} + +HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database) +{ + { + // The NameList file + RINOK(DecompressStream(inStream, database, kNameList)); + UInt16 length = ReadUInt16(); + UInt16 numSections = ReadUInt16(); + for (int i = 0; i < numSections; i++) + { + CSectionInfo section; + UInt16 nameLength = ReadUInt16(); + UString name; + ReadUString(nameLength, name); + if (ReadUInt16() != 0) + return S_FALSE; + if (!ConvertUnicodeToUTF8(name, section.Name)) + return S_FALSE; + database.Sections.Add(section); + } + } + + int i; + for (i = 1; i < database.Sections.Size(); i++) + { + CSectionInfo §ion = database.Sections[i]; + AString sectionPrefix = GetSectionPrefix(section.Name); + { + // Content + int index = database.FindItem(sectionPrefix + kContent); + if (index < 0) + return S_FALSE; + const CItem &item = database.Items[index]; + section.Offset = item.Offset; + section.CompressedSize = item.Size; + } + AString transformPrefix = sectionPrefix + kTransform; + if (database.Help2Format) + { + // Transform List + RINOK(DecompressStream(inStream, database, transformPrefix + kTransformList)); + if ((_chunkSize & 0xF) != 0) + return S_FALSE; + int numGuids = (int)(_chunkSize / 0x10); + if (numGuids < 1) + return S_FALSE; + for (int i = 0; i < numGuids; i++) + { + CMethodInfo method; + ReadGUID(method.Guid); + section.Methods.Add(method); + } + } + else + { + CMethodInfo method; + method.Guid = kChmLzxGuid; + section.Methods.Add(method); + } + + { + // Control Data + RINOK(DecompressStream(inStream, database, sectionPrefix + kControlData)); + for (int mi = 0; mi < section.Methods.Size(); mi++) + { + CMethodInfo &method = section.Methods[mi]; + UInt32 numDWORDS = ReadUInt32(); + if (method.IsLzx()) + { + if (numDWORDS < 5) + return S_FALSE; + if (ReadUInt32() != NHeader::kLzxcSignature) + return S_FALSE; + CLzxInfo &li = method.LzxInfo; + li.Version = ReadUInt32(); + if (li.Version != 2 && li.Version != 3) + return S_FALSE; + li.ResetInterval = ReadUInt32(); + li.WindowSize = ReadUInt32(); + li.CacheSize = ReadUInt32(); + if (li.ResetInterval != 2 && li.ResetInterval != 4) + return S_FALSE; + if (li.WindowSize != 2 && li.WindowSize != 4) + return S_FALSE; + numDWORDS -= 5; + while (numDWORDS-- != 0) + ReadUInt32(); + } + else + { + UInt32 numBytes = numDWORDS * 4; + method.ControlData.SetCapacity(numBytes); + ReadBytes(method.ControlData, numBytes); + } + } + } + + { + // SpanInfo + RINOK(DecompressStream(inStream, database, sectionPrefix + kSpanInfo)); + section.UncompressedSize = ReadUInt64(); + } + + // read ResetTable for LZX + for (int mi = 0; mi < section.Methods.Size(); mi++) + { + CMethodInfo &method = section.Methods[mi]; + if (method.IsLzx()) + { + // ResetTable; + RINOK(DecompressStream(inStream, database, transformPrefix + + method.GetGuidString() + kResetTable)); + CResetTable &rt = method.LzxInfo.ResetTable; + if (_chunkSize < 4) + { + if (_chunkSize != 0) + return S_FALSE; + // ResetTable is empty in .chw files + if (section.UncompressedSize != 0) + return S_FALSE; + rt.UncompressedSize = 0; + rt.CompressedSize = 0; + rt.BlockSize = 0; + } + else + { + UInt32 ver = ReadUInt32(); // 2 unknown (possibly a version number) + if (ver != 2 && ver != 3) + return S_FALSE; + UInt32 numEntries = ReadUInt32(); + if (ReadUInt32() != 8) // Size of table entry (bytes) + return S_FALSE; + if (ReadUInt32() != 0x28) // Length of table header + return S_FALSE; + rt.UncompressedSize = ReadUInt64(); + rt.CompressedSize = ReadUInt64(); + rt.BlockSize = ReadUInt64(); // 0x8000 block size for locations below + if (rt.BlockSize != 0x8000) + return S_FALSE; + rt.ResetOffsets.Reserve(numEntries); + for (UInt32 i = 0; i < numEntries; i++) + rt.ResetOffsets.Add(ReadUInt64()); + } + } + } + } + + database.SetIndices(); + database.Sort(); + return database.Check() ? S_OK : S_FALSE; +} + +HRESULT CInArchive::Open2(IInStream *inStream, + const UInt64 *searchHeaderSizeLimit, + CFilesDatabase &database) +{ + database.Clear(); + + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_startPosition)); + + database.Help2Format = false; + const UInt32 chmVersion = 3; + { + if (!_inBuffer.Create(1 << 14)) + return E_OUTOFMEMORY; + _inBuffer.SetStream(inStream); + _inBuffer.Init(); + UInt64 value = 0; + const int kSignatureSize = 8; + UInt64 hxsSignature = NHeader::GetHxsSignature(); + UInt64 chmSignature = ((UInt64)chmVersion << 32)| NHeader::kItsfSignature; + while(true) + { + Byte b; + if (!_inBuffer.ReadByte(b)) + return S_FALSE; + value >>= 8; + value |= ((UInt64)b) << ((kSignatureSize - 1) * 8); + if (_inBuffer.GetProcessedSize() >= kSignatureSize) + { + if (value == chmSignature) + break; + if (value == hxsSignature) + { + database.Help2Format = true; + break; + } + if (searchHeaderSizeLimit != NULL) + if (_inBuffer.GetProcessedSize() > (*searchHeaderSizeLimit)) + return S_FALSE; + } + } + _startPosition += _inBuffer.GetProcessedSize() - kSignatureSize; + } + + if (database.Help2Format) + { + RINOK(OpenHelp2(inStream, database)); + if (database.NewFormat) + return S_OK; + } + else + { + RINOK(OpenChm(inStream, database)); + } + + #ifndef CHM_LOW + try + { + HRESULT res = OpenHighLevel(inStream, database); + if (res == S_FALSE) + { + database.HighLevelClear(); + return S_OK; + } + RINOK(res); + database.LowLevel = false; + } + catch(...) + { + return S_OK; + } + #endif + return S_OK; +} + +HRESULT CInArchive::Open(IInStream *inStream, + const UInt64 *searchHeaderSizeLimit, + CFilesDatabase &database) +{ + try + { + HRESULT res = Open2(inStream, searchHeaderSizeLimit, database); + _inBuffer.ReleaseStream(); + return res; + } + catch(...) + { + _inBuffer.ReleaseStream(); + throw; + } +} + +}} diff --git a/7zip/Archive/Chm/ChmIn.h b/7zip/Archive/Chm/ChmIn.h new file mode 100755 index 00000000..d2ddb378 --- /dev/null +++ b/7zip/Archive/Chm/ChmIn.h @@ -0,0 +1,242 @@ +// Archive/ChmIn.h + +#ifndef __ARCHIVE_CHM_IN_H +#define __ARCHIVE_CHM_IN_H + +#include "Common/String.h" +#include "Common/Buffer.h" +#include "../../IStream.h" +#include "../../Common/InBuffer.h" +#include "ChmHeader.h" + +namespace NArchive { +namespace NChm { + +struct CItem +{ + UInt64 Section; + UInt64 Offset; + UInt64 Size; + AString Name; + + bool IsFormatRelatedItem() const + { + if (Name.Length() < 2) + return false; + return Name[0] == ':' && Name[1] == ':'; + } + + bool IsUserItem() const + { + if (Name.Length() < 2) + return false; + return Name[0] == '/'; + } + + bool IsDirectory() const + { + if (Name.Length() == 0) + return false; + return (Name[Name.Length() - 1] == '/'); + } +}; + +struct CDatabase +{ + UInt64 ContentOffset; + CObjectVector Items; + AString NewFormatString; + bool Help2Format; + bool NewFormat; + + int FindItem(const AString &name) const + { + for (int i = 0; i < Items.Size(); i++) + if (Items[i].Name == name) + return i; + return -1; + } + + void Clear() + { + NewFormat = false; + NewFormatString.Empty(); + Help2Format = false; + Items.Clear(); + } +}; + +struct CResetTable +{ + UInt64 UncompressedSize; + UInt64 CompressedSize; + UInt64 BlockSize; + CRecordVector ResetOffsets; + bool GetCompressedSizeOfBlocks(UInt64 blockIndex, UInt32 numBlocks, UInt64 &size) const + { + if (blockIndex >= ResetOffsets.Size()) + return false; + UInt64 startPos = ResetOffsets[(size_t)blockIndex]; + if (blockIndex + numBlocks >= ResetOffsets.Size()) + size = CompressedSize - startPos; + else + size = ResetOffsets[(size_t)blockIndex + numBlocks] - startPos; + return true; + } + bool GetCompressedSizeOfBlock(UInt64 blockIndex, UInt64 &size) const + { + return GetCompressedSizeOfBlocks(blockIndex, 1, size); + } + UInt64 GetNumBlocks(UInt64 size) const + { + return (size + BlockSize - 1) / BlockSize; + } +}; + +struct CLzxInfo +{ + UInt32 Version; + UInt32 ResetInterval; + UInt32 WindowSize; + UInt32 CacheSize; + CResetTable ResetTable; + + UInt32 GetNumDictBits() const + { + if (Version == 2 || Version == 3) + { + for (int i = 0; i <= 31; i++) + if (((UInt32)1 << i) >= WindowSize) + return 15 + i; + } + return 0; + } + + UInt64 GetFolderSize() const { return ResetTable.BlockSize * ResetInterval; }; + UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); }; + UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); }; + UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex * ResetInterval; }; + bool GetOffsetOfFolder(UInt64 folderIndex, UInt64 &offset) const + { + UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex); + if (blockIndex >= ResetTable.ResetOffsets.Size()) + return false; + offset = ResetTable.ResetOffsets[(size_t)blockIndex]; + return true; + } + bool GetCompressedSizeOfFolder(UInt64 folderIndex, UInt64 &size) const + { + UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex); + return ResetTable.GetCompressedSizeOfBlocks(blockIndex, ResetInterval, size); + } +}; + +struct CMethodInfo +{ + GUID Guid; + CByteBuffer ControlData; + CLzxInfo LzxInfo; + bool IsLzx() const; + bool IsDes() const; + AString GetGuidString() const; + UString GetName() const; +}; + +struct CSectionInfo +{ + UInt64 Offset; + UInt64 CompressedSize; + UInt64 UncompressedSize; + + AString Name; + CObjectVector Methods; + + bool IsLzx() const; + UString GetMethodName() const; +}; + +class CFilesDatabase: public CDatabase +{ +public: + bool LowLevel; + CRecordVector Indices; + CObjectVector Sections; + + UInt64 GetFileSize(int fileIndex) const { return Items[Indices[fileIndex]].Size; } + UInt64 GetFileOffset(int fileIndex) const { return Items[Indices[fileIndex]].Offset; } + + UInt64 GetFolder(int fileIndex) const + { + const CItem &item = Items[Indices[fileIndex]]; + const CSectionInfo §ion = Sections[(size_t)item.Section]; + if (section.IsLzx()) + return section.Methods[0].LzxInfo.GetFolder(item.Offset); + return 0; + } + + UInt64 GetLastFolder(int fileIndex) const + { + const CItem &item = Items[Indices[fileIndex]]; + const CSectionInfo §ion = Sections[(size_t)item.Section]; + if (section.IsLzx()) + return section.Methods[0].LzxInfo.GetFolder(item.Offset + item.Size - 1); + return 0; + } + + void HighLevelClear() + { + LowLevel = true; + Indices.Clear(); + Sections.Clear(); + } + + void Clear() + { + CDatabase::Clear(); + HighLevelClear(); + } + void SetIndices(); + void Sort(); + bool Check(); +}; + +class CProgressVirt +{ +public: + STDMETHOD(SetTotal)(const UInt64 *numFiles) PURE; + STDMETHOD(SetCompleted)(const UInt64 *numFiles) PURE; +}; + +class CInArchive +{ + UInt64 _startPosition; + ::CInBuffer _inBuffer; + UInt64 _chunkSize; + + Byte ReadByte(); + void ReadBytes(Byte *data, UInt32 size); + void Skeep(size_t size); + UInt16 ReadUInt16(); + UInt32 ReadUInt32(); + UInt64 ReadUInt64(); + UInt64 ReadEncInt(); + void ReadString(int size, AString &s); + void ReadUString(int size, UString &s); + void ReadGUID(GUID &g); + + HRESULT ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size); + + HRESULT ReadDirEntry(CDatabase &database); + HRESULT DecompressStream(IInStream *inStream, const CDatabase &database, const AString &name); + +public: + HRESULT OpenChm(IInStream *inStream, CDatabase &database); + HRESULT OpenHelp2(IInStream *inStream, CDatabase &database); + HRESULT OpenHighLevel(IInStream *inStream, CFilesDatabase &database); + HRESULT Open2(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database); + HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database); +}; + +}} + +#endif diff --git a/7zip/Archive/Chm/DllExports.cpp b/7zip/Archive/Chm/DllExports.cpp new file mode 100755 index 00000000..edc87a8c --- /dev/null +++ b/7zip/Archive/Chm/DllExports.cpp @@ -0,0 +1,77 @@ +// DLLExports.cpp + +#include "StdAfx.h" + +#include "Common/MyInitGuid.h" +#include "Common/ComTry.h" +#include "Windows/PropVariant.h" +#include "ChmHandler.h" +#include "../../ICoder.h" + +// {23170F69-40C1-278A-1000-000110E90000} +DEFINE_GUID(CLSID_CChmHandler, + 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xE9, 0x00, 0x00); + +extern "C" +BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) +{ + return TRUE; +} + +STDAPI CreateObject( + const GUID *classID, + const GUID *interfaceID, + void **outObject) +{ + COM_TRY_BEGIN + *outObject = 0; + if (*classID != CLSID_CChmHandler) + return CLASS_E_CLASSNOTAVAILABLE; + if (*interfaceID != IID_IInArchive) + return E_NOINTERFACE; + CMyComPtr inArchive = (IInArchive *)new NArchive::NChm::CHandler; + *outObject = inArchive.Detach(); + COM_TRY_END + return S_OK; +} + +STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant propVariant; + switch(propID) + { + case NArchive::kName: + propVariant = L"Chm"; + break; + case NArchive::kClassID: + { + if ((value->bstrVal = ::SysAllocStringByteLen( + (const char *)&CLSID_CChmHandler, sizeof(GUID))) != 0) + value->vt = VT_BSTR; + return S_OK; + } + case NArchive::kExtension: + propVariant = L"chm chi chq chw hxs hxi hxr hxq hxw lit"; + break; + case NArchive::kUpdate: + propVariant = false; + break; + case NArchive::kKeepName: + propVariant = false; + break; + case NArchive::kStartSignature: + { + const char sig[] = { 'I', 'T', 'S', 'F' }; + if ((value->bstrVal = ::SysAllocStringByteLen(sig, 4)) != 0) + value->vt = VT_BSTR; + return S_OK; + } + case NArchive::kAssociate: + { + propVariant = false; + break; + } + } + propVariant.Detach(value); + return S_OK; +} diff --git a/7zip/Archive/Chm/StdAfx.cpp b/7zip/Archive/Chm/StdAfx.cpp new file mode 100755 index 00000000..d0feea85 --- /dev/null +++ b/7zip/Archive/Chm/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/7zip/Archive/Chm/StdAfx.h b/7zip/Archive/Chm/StdAfx.h new file mode 100755 index 00000000..e7fb6986 --- /dev/null +++ b/7zip/Archive/Chm/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" + +#endif diff --git a/7zip/Archive/Chm/makefile b/7zip/Archive/Chm/makefile new file mode 100755 index 00000000..4adce2f5 --- /dev/null +++ b/7zip/Archive/Chm/makefile @@ -0,0 +1,68 @@ +PROG = chm.dll +DEF_FILE = ../Archive.def +CFLAGS = $(CFLAGS) -I ../../../ +LIBS = $(LIBS) oleaut32.lib user32.lib + +CHM_OBJS = \ + $O\DllExports.obj \ + $O\ChmHandler.obj \ + $O\ChmHeader.obj \ + $O\ChmIn.obj \ + +COMMON_OBJS = \ + $O\Alloc.obj \ + $O\IntToString.obj \ + $O\NewHandler.obj \ + $O\String.obj \ + $O\StringConvert.obj \ + $O\UTFConvert.obj \ + $O\Vector.obj \ + +WIN_OBJS = \ + $O\PropVariant.obj \ + +7ZIP_COMMON_OBJS = \ + $O\InBuffer.obj \ + $O\LimitedStreams.obj \ + $O\OutBuffer.obj \ + $O\ProgressUtils.obj \ + $O\StreamUtils.obj \ + +AR_COMMON_OBJS = \ + $O\ItemNameUtils.obj \ + +COMPRESS_LZX_OBJS = \ + $O\LzxDecoder.obj \ + $O\Lzx86Converter.obj \ + +OBJS = \ + $O\StdAfx.obj \ + $(CHM_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_COMMON_OBJS) \ + $(COMPRESS_LZX_OBJS) \ + $O\LZOutWindow.obj \ + $O\CopyCoder.obj \ + $O\resource.res + +!include "../../../Build.mak" + +$(CHM_OBJS): $(*B).cpp + $(COMPL) +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../Common/$(*B).cpp + $(COMPL) +$(COMPRESS_LZX_OBJS): ../../Compress/Lzx/$(*B).cpp + $(COMPL_O2) +$O\LZOutWindow.obj: ../../Compress/LZ/$(*B).cpp + $(COMPL) +$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp + $(COMPL) + diff --git a/7zip/Archive/Chm/resource.rc b/7zip/Archive/Chm/resource.rc new file mode 100755 index 00000000..fc93ae4f --- /dev/null +++ b/7zip/Archive/Chm/resource.rc @@ -0,0 +1,3 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_DLL("Chm Plugin", "chm") diff --git a/7zip/Archive/Common/DummyOutStream.cpp b/7zip/Archive/Common/DummyOutStream.cpp index f188ac05..b1d49913 100755 --- a/7zip/Archive/Common/DummyOutStream.cpp +++ b/7zip/Archive/Common/DummyOutStream.cpp @@ -18,13 +18,3 @@ STDMETHODIMP CDummyOutStream::Write(const void *data, *processedSize = size; return S_OK; } - -STDMETHODIMP CDummyOutStream::WritePart(const void *data, - UInt32 size, UInt32 *processedSize) -{ - if(m_Stream) - return m_Stream->WritePart(data, size, processedSize); - if(processedSize != NULL) - *processedSize = size; - return S_OK; -} diff --git a/7zip/Archive/Common/DummyOutStream.h b/7zip/Archive/Common/DummyOutStream.h index 2e66cd3d..51690787 100755 --- a/7zip/Archive/Common/DummyOutStream.h +++ b/7zip/Archive/Common/DummyOutStream.h @@ -14,7 +14,6 @@ public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); private: CMyComPtr m_Stream; public: diff --git a/7zip/Archive/Common/FilterCoder.cpp b/7zip/Archive/Common/FilterCoder.cpp index 3a7a95b6..1ad0f5de 100755 --- a/7zip/Archive/Common/FilterCoder.cpp +++ b/7zip/Archive/Common/FilterCoder.cpp @@ -5,6 +5,7 @@ #include "FilterCoder.h" #include "../../../Common/Alloc.h" #include "../../../Common/Defs.h" +#include "../../Common/StreamUtils.h" static const int kBufferSize = 1 << 17; @@ -27,7 +28,7 @@ HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 siz size = (UInt32)remSize; } UInt32 processedSize = 0; - RINOK(outStream->Write(_buffer, size, &processedSize)); + RINOK(WriteStream(outStream, _buffer, size, &processedSize)); if (size != processedSize) return E_FAIL; _nowPos64 += processedSize; @@ -47,8 +48,10 @@ STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, while(NeedMore()) { UInt32 processedSize; - UInt32 size = kBufferSize - bufferPos; - RINOK(inStream->Read(_buffer + bufferPos, size, &processedSize)); + + // Change it: It can be optimized using ReadPart + RINOK(ReadStream(inStream, _buffer + bufferPos, kBufferSize - bufferPos, &processedSize)); + UInt32 endPos = bufferPos + processedSize; bufferPos = Filter->Filter(_buffer, endPos); @@ -131,11 +134,6 @@ STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processe return S_OK; } -STDMETHODIMP CFilterCoder::WritePart(const void *data, UInt32 size, UInt32 *processedSize) -{ - return Write(data, size, processedSize); -} - STDMETHODIMP CFilterCoder::Flush() { if (_bufferPos != 0) @@ -149,7 +147,7 @@ STDMETHODIMP CFilterCoder::Flush() return E_FAIL; } UInt32 processedSize; - RINOK(_outStream->Write(_buffer, _bufferPos, &processedSize)); + RINOK(WriteStream(_outStream, _buffer, _bufferPos, &processedSize)); if (_bufferPos != processedSize) return E_FAIL; _bufferPos = 0; @@ -189,7 +187,7 @@ STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) data = (void *)((Byte *)data + sizeTemp); size -= sizeTemp; processedSizeTotal += sizeTemp; - continue; + break; } int i; for (i = 0; _convertedPosEnd + i < _bufferPos; i++) @@ -198,7 +196,8 @@ STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) _convertedPosBegin = _convertedPosEnd = 0; UInt32 processedSizeTemp; UInt32 size0 = kBufferSize - _bufferPos; - RINOK(_inStream->Read(_buffer + _bufferPos, size0, &processedSizeTemp)); + // Optimize it: + RINOK(ReadStream(_inStream, _buffer + _bufferPos, size0, &processedSizeTemp)); _bufferPos = _bufferPos + processedSizeTemp; _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); if (_convertedPosEnd == 0) @@ -217,11 +216,6 @@ STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) return S_OK; } -STDMETHODIMP CFilterCoder::ReadPart(void *data, UInt32 size, UInt32 *processedSize) -{ - return Read(data, size, processedSize); -} - // #endif // _ST_MODE #ifndef _NO_CRYPTO diff --git a/7zip/Archive/Common/FilterCoder.h b/7zip/Archive/Common/FilterCoder.h index a37e7715..4db7f28a 100755 --- a/7zip/Archive/Common/FilterCoder.h +++ b/7zip/Archive/Common/FilterCoder.h @@ -94,11 +94,9 @@ public: STDMETHOD(ReleaseInStream)(); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \ - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); \ STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Flush)(); // #endif diff --git a/7zip/Archive/Common/InStreamWithCRC.cpp b/7zip/Archive/Common/InStreamWithCRC.cpp index e1b98383..86151b9d 100755 --- a/7zip/Archive/Common/InStreamWithCRC.cpp +++ b/7zip/Archive/Common/InStreamWithCRC.cpp @@ -16,18 +16,6 @@ STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, return result; } -STDMETHODIMP CSequentialInStreamWithCRC::ReadPart(void *data, - UInt32 size, UInt32 *processedSize) -{ - UInt32 realProcessedSize; - HRESULT result = _stream->ReadPart(data, size, &realProcessedSize); - _size += realProcessedSize; - _crc.Update(data, realProcessedSize); - if(processedSize != NULL) - *processedSize = realProcessedSize; - return result; -} - STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { @@ -40,18 +28,6 @@ STDMETHODIMP CInStreamWithCRC::Read(void *data, return result; } -STDMETHODIMP CInStreamWithCRC::ReadPart(void *data, - UInt32 size, UInt32 *processedSize) -{ - UInt32 realProcessedSize; - HRESULT result = _stream->ReadPart(data, size, &realProcessedSize); - _size += realProcessedSize; - _crc.Update(data, realProcessedSize); - if(processedSize != NULL) - *processedSize = realProcessedSize; - return result; -} - STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { diff --git a/7zip/Archive/Common/InStreamWithCRC.h b/7zip/Archive/Common/InStreamWithCRC.h index 112af5d0..9628a6f2 100755 --- a/7zip/Archive/Common/InStreamWithCRC.h +++ b/7zip/Archive/Common/InStreamWithCRC.h @@ -15,7 +15,6 @@ public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); private: CMyComPtr _stream; UInt64 _size; @@ -40,7 +39,6 @@ public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); private: CMyComPtr _stream; diff --git a/7zip/Archive/Common/MultiStream.cpp b/7zip/Archive/Common/MultiStream.cpp index cdcb8886..7ef4f155 100755 --- a/7zip/Archive/Common/MultiStream.cpp +++ b/7zip/Archive/Common/MultiStream.cpp @@ -28,17 +28,11 @@ STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) _pos += realProcessed; _seekPos += realProcessed; RINOK(result); - if (realProcessed == 0) - break; + break; } return S_OK; } -STDMETHODIMP CMultiStream::ReadPart(void *data, UInt32 size, UInt32 *processedSize) -{ - return Read(data, size, processedSize); -} - STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { @@ -113,7 +107,6 @@ public: HRESULT Flush(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); }; HRESULT COutVolumeStream::Flush() @@ -179,17 +172,12 @@ STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *proce _streamIndex++; _offsetPos = 0; } - if (realProcessed != curSize) + if (realProcessed != curSize && realProcessed == 0) return E_FAIL; } return S_OK; } -STDMETHODIMP COutMultiStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize) -{ - return Write(data, size, processedSize); -} - STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) diff --git a/7zip/Archive/Common/MultiStream.h b/7zip/Archive/Common/MultiStream.h index b6e2abc5..5a7cc687 100755 --- a/7zip/Archive/Common/MultiStream.h +++ b/7zip/Archive/Common/MultiStream.h @@ -36,7 +36,6 @@ public: MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; @@ -70,7 +69,6 @@ public: MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; */ diff --git a/7zip/Archive/Common/OutStreamWithCRC.cpp b/7zip/Archive/Common/OutStreamWithCRC.cpp index ae832eef..4fbce564 100755 --- a/7zip/Archive/Common/OutStreamWithCRC.cpp +++ b/7zip/Archive/Common/OutStreamWithCRC.cpp @@ -7,8 +7,8 @@ STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) { - HRESULT result; UInt32 realProcessedSize; + HRESULT result; if(!_stream) { realProcessedSize = size; @@ -21,21 +21,3 @@ STDMETHODIMP COutStreamWithCRC::Write(const void *data, *processedSize = realProcessedSize; return result; } - -STDMETHODIMP COutStreamWithCRC::WritePart(const void *data, - UInt32 size, UInt32 *processedSize) -{ - UInt32 realProcessedSize; - HRESULT result; - if(!_stream) - { - realProcessedSize = size; - result = S_OK; - } - else - result = _stream->WritePart(data, size, &realProcessedSize); - _crc.Update(data, realProcessedSize); - if(processedSize != NULL) - *processedSize = realProcessedSize; - return result; -} diff --git a/7zip/Archive/Common/OutStreamWithCRC.h b/7zip/Archive/Common/OutStreamWithCRC.h index 2668885c..23c69e04 100755 --- a/7zip/Archive/Common/OutStreamWithCRC.h +++ b/7zip/Archive/Common/OutStreamWithCRC.h @@ -15,7 +15,6 @@ public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); private: CCRC _crc; CMyComPtr _stream; diff --git a/7zip/Archive/Cpio/makefile b/7zip/Archive/Cpio/makefile index 6c5fb3f4..d7760281 100755 --- a/7zip/Archive/Cpio/makefile +++ b/7zip/Archive/Cpio/makefile @@ -14,6 +14,7 @@ COMMON_OBJS = \ $O\NewHandler.obj \ $O\String.obj \ $O\StringConvert.obj \ + $O\StringToInt.obj \ $O\Vector.obj \ WIN_OBJS = \ @@ -22,6 +23,7 @@ WIN_OBJS = \ 7ZIP_COMMON_OBJS = \ $O\LimitedStreams.obj \ $O\ProgressUtils.obj \ + $O\StreamUtils.obj \ AR_COMMON_OBJS = \ $O\ItemNameUtils.obj \ diff --git a/7zip/Archive/Deb/Deb.dsp b/7zip/Archive/Deb/Deb.dsp index 42f354a7..56689305 100755 --- a/7zip/Archive/Deb/Deb.dsp +++ b/7zip/Archive/Deb/Deb.dsp @@ -154,6 +154,14 @@ SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\StringToInt.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringToInt.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\Vector.cpp # End Source File # Begin Source File @@ -248,6 +256,14 @@ SOURCE=..\..\Common\ProgressUtils.cpp SOURCE=..\..\Common\ProgressUtils.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # End Target # End Project diff --git a/7zip/Archive/Deb/DebIn.cpp b/7zip/Archive/Deb/DebIn.cpp index 55f1e034..4900517b 100755 --- a/7zip/Archive/Deb/DebIn.cpp +++ b/7zip/Archive/Deb/DebIn.cpp @@ -5,8 +5,11 @@ #include "DebIn.h" #include "DebHeader.h" +#include "Common/StringToInt.h" #include "Windows/Defs.h" +#include "../../Common/StreamUtils.h" + namespace NArchive { namespace NDeb { @@ -14,7 +17,7 @@ using namespace NHeader; HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize) { - RINOK(m_Stream->Read(data, size, &processedSize)); + RINOK(ReadStream(m_Stream, data, size, &processedSize)); m_Position += processedSize; return S_OK; } @@ -24,7 +27,7 @@ HRESULT CInArchive::Open(IInStream *inStream) RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position)); char signature[kSignatureLen]; UInt32 processedSize; - RINOK(inStream->Read(signature, kSignatureLen, &processedSize)); + RINOK(ReadStream(inStream, signature, kSignatureLen, &processedSize)); m_Position += processedSize; if (processedSize != kSignatureLen) return S_FALSE; @@ -34,40 +37,50 @@ HRESULT CInArchive::Open(IInStream *inStream) return S_OK; } -static bool CheckString(const char *srcString, int numChars, int radix) +static bool OctalToNumber(const char *s, int size, UInt64 &res) { - for(int i = 0; i < numChars; i++) - { - char c = srcString[i]; - if (c == 0) - return true; - if (c >= '0' && c <= '0' + radix - 1) - continue; - if (c != ' ') - return false; - } - return true; + char sz[32]; + strncpy(sz, s, size); + sz[size] = 0; + const char *end; + int i; + for (i = 0; sz[i] == ' '; i++); + res = ConvertOctStringToUInt64(sz + i, &end); + return (*end == ' ' || *end == 0); } -static bool CheckOctalString(const char *srcString, int numChars) - { return CheckString(srcString, numChars, 8); } -static bool CheckDecimalString(const char *srcString, int numChars) - { return CheckString(srcString, numChars, 10); } -#define ReturnIfBadOctal(x, y) { if (!CheckOctalString((x), (y))) return S_FALSE; } -#define ReturnIfBadDecimal(x, y) { if (!CheckDecimalString((x), (y))) return S_FALSE; } - -static UInt32 StringToNumber(const char *srcString, int numChars, int radix) +static bool OctalToNumber32(const char *s, int size, UInt32 &res) { - AString modString; - for (int i = 0; i < numChars; i++) - modString += srcString[i]; - char *endPtr; - return strtoul(modString, &endPtr, radix); + UInt64 res64; + if (!OctalToNumber(s, size, res64)) + return false; + res = (UInt32)res64; + return (res64 <= 0xFFFFFFFF); } -static UInt32 OctalToNumber(const char *srcString, int numChars) - { return StringToNumber(srcString, numChars, 8); } -static UInt32 DecimalToNumber(const char *srcString, int numChars) - { return StringToNumber(srcString, numChars, 10); } + +static bool DecimalToNumber(const char *s, int size, UInt64 &res) +{ + char sz[32]; + strncpy(sz, s, size); + sz[size] = 0; + const char *end; + int i; + for (i = 0; sz[i] == ' '; i++); + res = ConvertStringToUInt64(sz + i, &end); + return (*end == ' ' || *end == 0); +} + +static bool DecimalToNumber32(const char *s, int size, UInt32 &res) +{ + UInt64 res64; + if (!DecimalToNumber(s, size, res64)) + return false; + res = (UInt32)res64; + return (res64 <= 0xFFFFFFFF); +} + +#define RIF(x) { if (!(x)) return S_FALSE; } + HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item) { @@ -93,18 +106,15 @@ HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item) if (((Byte)item.Name[i]) < 0x20) return S_FALSE; - ReturnIfBadDecimal(cur, kTimeSize); - item.ModificationTime = DecimalToNumber(cur, kTimeSize); + RIF(DecimalToNumber32(cur, kTimeSize, item.ModificationTime)); cur += kTimeSize; cur += 6 + 6; - ReturnIfBadOctal(cur, kModeSize); - item.Mode = OctalToNumber(cur, kModeSize); + RIF(OctalToNumber32(cur, kModeSize, item.Mode)); cur += kModeSize; - ReturnIfBadDecimal(cur, kSizeSize); - item.Size = DecimalToNumber(cur, kSizeSize); + RIF(DecimalToNumber(cur, kSizeSize, item.Size)); cur += kSizeSize; filled = true; diff --git a/7zip/Archive/Deb/DllExports.cpp b/7zip/Archive/Deb/DllExports.cpp index 66bf7c38..cb314000 100755 --- a/7zip/Archive/Deb/DllExports.cpp +++ b/7zip/Archive/Deb/DllExports.cpp @@ -8,9 +8,9 @@ #include "DebHandler.h" #include "../../ICoder.h" -// {23170F69-40C1-278A-1000-0001100C0000} +// {23170F69-40C1-278A-1000-000110EC0000} DEFINE_GUID(CLSID_CDebHandler, - 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x0C, 0x00, 0x00); + 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEC, 0x00, 0x00); extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) diff --git a/7zip/Archive/Deb/makefile b/7zip/Archive/Deb/makefile index 8cff91a2..a74f33de 100755 --- a/7zip/Archive/Deb/makefile +++ b/7zip/Archive/Deb/makefile @@ -14,6 +14,7 @@ COMMON_OBJS = \ $O\NewHandler.obj \ $O\String.obj \ $O\StringConvert.obj \ + $O\StringToInt.obj \ $O\Vector.obj \ WIN_OBJS = \ @@ -22,6 +23,7 @@ WIN_OBJS = \ 7ZIP_COMMON_OBJS = \ $O\LimitedStreams.obj \ $O\ProgressUtils.obj \ + $O\StreamUtils.obj \ AR_COMMON_OBJS = \ $O\ItemNameUtils.obj \ diff --git a/7zip/Archive/GZip/DllExports.cpp b/7zip/Archive/GZip/DllExports.cpp index 4a0aca73..2b32f16b 100755 --- a/7zip/Archive/GZip/DllExports.cpp +++ b/7zip/Archive/GZip/DllExports.cpp @@ -8,9 +8,9 @@ #include "../../ICoder.h" #include "GZipHandler.h" -// {23170F69-40C1-278A-1000-000110030000} +// {23170F69-40C1-278A-1000-000110EF0000} DEFINE_GUID(CLSID_CGZipHandler, -0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x03, 0x00, 0x00); +0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEF, 0x00, 0x00); // {23170F69-40C1-278B-0401-080000000100} DEFINE_GUID(CLSID_CCompressDeflateEncoder, diff --git a/7zip/Archive/GZip/GZip.dsp b/7zip/Archive/GZip/GZip.dsp index aa880e63..4507e833 100755 --- a/7zip/Archive/GZip/GZip.dsp +++ b/7zip/Archive/GZip/GZip.dsp @@ -264,6 +264,14 @@ SOURCE=..\..\Common\ProgressUtils.cpp SOURCE=..\..\Common\ProgressUtils.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # Begin Group "Archive Common" diff --git a/7zip/Archive/GZip/GZipHandler.cpp b/7zip/Archive/GZip/GZipHandler.cpp index f3d0d065..e234e96d 100755 --- a/7zip/Archive/GZip/GZipHandler.cpp +++ b/7zip/Archive/GZip/GZipHandler.cpp @@ -58,12 +58,14 @@ static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]); static const wchar_t *kUnknownOS = L"Unknown"; +/* enum // PropID { - // kpidExtraIsPresent = kpidUserDefined, - // kpidExtraFlags, - // kpidIsText + kpidExtraIsPresent = kpidUserDefined, + kpidExtraFlags, + kpidIsText }; +*/ STATPROPSTG kProperties[] = { diff --git a/7zip/Archive/GZip/GZipIn.cpp b/7zip/Archive/GZip/GZipIn.cpp index 69270fb1..d36ce5d0 100755 --- a/7zip/Archive/GZip/GZipIn.cpp +++ b/7zip/Archive/GZip/GZipIn.cpp @@ -8,13 +8,15 @@ #include "Common/MyCom.h" #include "Windows/Defs.h" +#include "../../Common/StreamUtils.h" + namespace NArchive { namespace NGZip { HRESULT CInArchive::ReadBytes(ISequentialInStream *inStream, void *data, UInt32 size) { UInt32 realProcessedSize; - RINOK(inStream->Read(data, size, &realProcessedSize)); + RINOK(ReadStream(inStream, data, size, &realProcessedSize)); m_Position += realProcessedSize; if(realProcessedSize != size) return S_FALSE; diff --git a/7zip/Archive/GZip/GZipOut.cpp b/7zip/Archive/GZip/GZipOut.cpp index e88ede19..99b08319 100755 --- a/7zip/Archive/GZip/GZipOut.cpp +++ b/7zip/Archive/GZip/GZipOut.cpp @@ -5,6 +5,7 @@ #include "GZipOut.h" #include "Common/CRC.h" #include "Windows/Defs.h" +#include "../../Common/StreamUtils.h" namespace NArchive { namespace NGZip { @@ -12,7 +13,7 @@ namespace NGZip { HRESULT COutArchive::WriteBytes(const void *buffer, UInt32 size) { UInt32 processedSize; - RINOK(m_Stream->Write(buffer, size, &processedSize)); + RINOK(WriteStream(m_Stream, buffer, size, &processedSize)); if(processedSize != size) return E_FAIL; return S_OK; diff --git a/7zip/Archive/GZip/makefile b/7zip/Archive/GZip/makefile index 3c1c94a5..06d8908d 100755 --- a/7zip/Archive/GZip/makefile +++ b/7zip/Archive/GZip/makefile @@ -26,6 +26,7 @@ WIN_OBJS = \ 7ZIP_COMMON_OBJS = \ $O\ProgressUtils.obj \ + $O\StreamUtils.obj \ AR_COMMON_OBJS = \ $O\CodecsPath.obj \ diff --git a/7zip/Archive/IArchive.h b/7zip/Archive/IArchive.h index 9c74b1bf..d6cbe804 100755 --- a/7zip/Archive/IArchive.h +++ b/7zip/Archive/IArchive.h @@ -7,6 +7,14 @@ #include "../IProgress.h" #include "../PropID.h" +// MIDL_INTERFACE("23170F69-40C1-278A-0000-000600xx0000") +#define ARCHIVE_INTERFACE_SUB(i, base, x) \ +DEFINE_GUID(IID_ ## i, \ +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x06, 0x00, x, 0x00, 0x00); \ +struct i: public base + +#define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x) + namespace NFileTimeType { enum EEnum @@ -29,6 +37,7 @@ namespace NArchive kKeepName, kStartSignature, kFinishSignature, + kAssociate }; namespace NExtract @@ -66,24 +75,15 @@ namespace NArchive } } -// {23170F69-40C1-278A-0000-000100010000} -DEFINE_GUID(IID_IArchiveOpenCallback, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000100010000") -IArchiveOpenCallback: public IUnknown +ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10) { -public: STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) PURE; STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) PURE; }; -// {23170F69-40C1-278A-0000-000100090000} -DEFINE_GUID(IID_IArchiveExtractCallback, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000100090000") -IArchiveExtractCallback: public IProgress + +ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20) { -public: STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) PURE; // GetStream OUT: S_OK - OK, S_FALSE - skeep this file @@ -92,36 +92,27 @@ public: }; -// {23170F69-40C1-278A-0000-0001000D0000} -DEFINE_GUID(IID_IArchiveOpenVolumeCallback, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0D, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-0001000D0000") -IArchiveOpenVolumeCallback: public IUnknown +ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30) { -public: STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) PURE; STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) PURE; }; -// {23170F69-40C1-278A-0000-0001000D0100} -DEFINE_GUID(IID_IArchiveOpenSetSubArchiveName, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0D, 0x01, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-0001000D0100") -IArchiveOpenSetSubArchiveName: public IUnknown +ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40) +{ + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE; +}; + + +ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50) { -public: STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE; }; -// {23170F69-40C1-278A-0000-000100080000} -DEFINE_GUID(IID_IInArchive, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000100080000") -IInArchive: public IUnknown +ARCHIVE_INTERFACE(IInArchive, 0x60) { -public: STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) PURE; STDMETHOD(Close)() PURE; @@ -129,6 +120,9 @@ public: STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) PURE; + // indices must be sorted + // numItems = 0xFFFFFFFF means all files + // testMode != 0 means "test files operation" STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) PURE; @@ -141,25 +135,9 @@ public: BSTR *name, PROPID *propID, VARTYPE *varType) PURE; }; -// {23170F69-40C1-278A-0000-000100080100} -DEFINE_GUID(IID_IInArchiveGetStream, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x01, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000100080100") -IInArchiveGetStream: public IUnknown -{ -public: - STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE; -}; - -// {23170F69-40C1-278A-0000-000100040000} -DEFINE_GUID(IID_IArchiveUpdateCallback, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000100040000") -IArchiveUpdateCallback: public IProgress +ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80) { -public: - // STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator) PURE; STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, // 1 - new data, 0 - old data Int32 *newProperties, // 1 - new properties, 0 - old properties @@ -170,33 +148,23 @@ public: STDMETHOD(SetOperationResult)(Int32 operationResult) PURE; }; -// {23170F69-40C1-278A-0000-000100040002} -DEFINE_GUID(IID_IArchiveUpdateCallback2, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x02); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000100040002") -IArchiveUpdateCallback2: public IArchiveUpdateCallback + +ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82) { -public: STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) PURE; STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) PURE; }; -// {23170F69-40C1-278A-0000-000100020000} -DEFINE_GUID(IID_IOutArchive, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000100020000") -IOutArchive: public IUnknown + +ARCHIVE_INTERFACE(IOutArchive, 0xA0) { STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) PURE; STDMETHOD(GetFileTimeType)(UInt32 *type) PURE; }; -// {23170F69-40C1-278A-0000-000100030000} -DEFINE_GUID(IID_ISetProperties, -0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00); -MIDL_INTERFACE("23170F69-40C1-278A-0000-000100030000") -ISetProperties: public IUnknown + +ARCHIVE_INTERFACE(ISetProperties, 0x03) { STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE; }; diff --git a/7zip/Archive/Lzh/DllExports.cpp b/7zip/Archive/Lzh/DllExports.cpp index 567d4bf8..ee5006f3 100755 --- a/7zip/Archive/Lzh/DllExports.cpp +++ b/7zip/Archive/Lzh/DllExports.cpp @@ -8,9 +8,9 @@ #include "../../ICoder.h" #include "LzhHandler.h" -// {23170F69-40C1-278A-1000-0001100E0000} +// {23170F69-40C1-278A-1000-000110060000} DEFINE_GUID(CLSID_CLzhHandler, - 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x0E, 0x00, 0x00); + 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x06, 0x00, 0x00); extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) diff --git a/7zip/Archive/Lzh/Lzh.dsp b/7zip/Archive/Lzh/Lzh.dsp index 9f5b21b0..ad00699c 100755 --- a/7zip/Archive/Lzh/Lzh.dsp +++ b/7zip/Archive/Lzh/Lzh.dsp @@ -290,12 +290,28 @@ SOURCE=..\..\Common\MSBFDecoder.h # End Source File # Begin Source File +SOURCE=..\..\Common\OutBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.h +# End Source File +# Begin Source File + SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # Begin Group "Archive Common" diff --git a/7zip/Archive/Lzh/LzhIn.cpp b/7zip/Archive/Lzh/LzhIn.cpp index f9b5daff..5344ef13 100755 --- a/7zip/Archive/Lzh/LzhIn.cpp +++ b/7zip/Archive/Lzh/LzhIn.cpp @@ -1,4 +1,4 @@ -/ Archive/arj/InEngine.cpp +// Archive/arj/InEngine.cpp #include "StdAfx.h" @@ -6,6 +6,8 @@ #include "Common/Buffer.h" #include "Common/CRC.h" +#include "../../Common/StreamUtils.h" + #include "LzhIn.h" namespace NArchive { @@ -13,7 +15,7 @@ namespace NLzh { HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize) { - RINOK(m_Stream->Read(data, size, &processedSize)); + RINOK(ReadStream(m_Stream, data, size, &processedSize)); m_Position += processedSize; return S_OK; } diff --git a/7zip/Archive/Lzh/LzhItem.h b/7zip/Archive/Lzh/LzhItem.h index 36ccb672..b9b5f914 100755 --- a/7zip/Archive/Lzh/LzhItem.h +++ b/7zip/Archive/Lzh/LzhItem.h @@ -115,7 +115,14 @@ public: { int index = FindExt(kExtIdUnixTime); if (index < 0) + { + if (Level == 2) + { + value = ModifiedTime; + return true; + } return false; + } const Byte *data = (const Byte *)(Extensions[index].Data); value = data[0] | ((UInt32)data[1] << 8) | diff --git a/7zip/Archive/Lzh/LzhOutStreamWithCRC.cpp b/7zip/Archive/Lzh/LzhOutStreamWithCRC.cpp index ddefec88..2281a884 100755 --- a/7zip/Archive/Lzh/LzhOutStreamWithCRC.cpp +++ b/7zip/Archive/Lzh/LzhOutStreamWithCRC.cpp @@ -7,11 +7,10 @@ namespace NArchive { namespace NLzh { -STDMETHODIMP COutStreamWithCRC::Write(const void *data, - UInt32 size, UInt32 *processedSize) +STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) { - HRESULT result; UInt32 realProcessedSize; + HRESULT result; if(!_stream) { realProcessedSize = size; @@ -25,22 +24,4 @@ STDMETHODIMP COutStreamWithCRC::Write(const void *data, return result; } -STDMETHODIMP COutStreamWithCRC::WritePart(const void *data, - UInt32 size, UInt32 *processedSize) -{ - UInt32 realProcessedSize; - HRESULT result; - if(!_stream) - { - realProcessedSize = size; - result = S_OK; - } - else - result = _stream->WritePart(data, size, &realProcessedSize); - _crc.Update(data, realProcessedSize); - if(processedSize != NULL) - *processedSize = realProcessedSize; - return result; -} - }} diff --git a/7zip/Archive/Lzh/LzhOutStreamWithCRC.h b/7zip/Archive/Lzh/LzhOutStreamWithCRC.h index fc5fc1c9..31b536b7 100755 --- a/7zip/Archive/Lzh/LzhOutStreamWithCRC.h +++ b/7zip/Archive/Lzh/LzhOutStreamWithCRC.h @@ -18,7 +18,6 @@ public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); private: CCRC _crc; CMyComPtr _stream; diff --git a/7zip/Archive/Lzh/makefile b/7zip/Archive/Lzh/makefile index caa61334..6f8fd2a0 100755 --- a/7zip/Archive/Lzh/makefile +++ b/7zip/Archive/Lzh/makefile @@ -23,7 +23,9 @@ WIN_OBJS = \ 7ZIP_COMMON_OBJS = \ $O\InBuffer.obj \ $O\LimitedStreams.obj \ + $O\OutBuffer.obj \ $O\ProgressUtils.obj \ + $O\StreamUtils.obj \ AR_COMMON_OBJS = \ $O\ItemNameUtils.obj \ diff --git a/7zip/Archive/RPM/DllExports.cpp b/7zip/Archive/RPM/DllExports.cpp index d712abfe..2319857c 100755 --- a/7zip/Archive/RPM/DllExports.cpp +++ b/7zip/Archive/RPM/DllExports.cpp @@ -8,9 +8,9 @@ #include "../../ICoder.h" #include "RpmHandler.h" -// {23170F69-40C1-278A-1000-000110090000} +// {23170F69-40C1-278A-1000-000110EB0000} DEFINE_GUID(CLSID_CRpmHandler, - 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x09, 0x00, 0x00); + 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEB, 0x00, 0x00); extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) diff --git a/7zip/Archive/RPM/Rpm.dsp b/7zip/Archive/RPM/Rpm.dsp index e0a828b3..085fe137 100755 --- a/7zip/Archive/RPM/Rpm.dsp +++ b/7zip/Archive/RPM/Rpm.dsp @@ -140,6 +140,14 @@ SOURCE=..\..\Common\ProgressUtils.cpp SOURCE=..\..\Common\ProgressUtils.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # Begin Group "Compress" diff --git a/7zip/Archive/RPM/RpmIn.cpp b/7zip/Archive/RPM/RpmIn.cpp index 9b48a0ae..03373d9c 100755 --- a/7zip/Archive/RPM/RpmIn.cpp +++ b/7zip/Archive/RPM/RpmIn.cpp @@ -9,6 +9,8 @@ #include "Windows/Defs.h" #include "Common/MyCom.h" +#include "../../Common/StreamUtils.h" + namespace NArchive { namespace NRpm { @@ -31,7 +33,7 @@ static HRESULT RedSigHeaderSig(IInStream *inStream, CSigHeaderSig &h) char dat[kCSigHeaderSigSize]; char *cur = dat; UInt32 processedSize; - RINOK(inStream->Read(dat, kCSigHeaderSigSize, &processedSize)); + RINOK(ReadStream(inStream, dat, kCSigHeaderSigSize, &processedSize)); if (kCSigHeaderSigSize != processedSize) return S_FALSE; memmove(h.Magic, cur, 4); @@ -50,7 +52,7 @@ HRESULT OpenArchive(IInStream *inStream) char *cur = leadData; CLead lead; UInt32 processedSize; - RINOK(inStream->Read(leadData, kLeadSize, &processedSize)); + RINOK(ReadStream(inStream, leadData, kLeadSize, &processedSize)); if (kLeadSize != processedSize) return S_FALSE; memmove(lead.Magic, cur, 4); diff --git a/7zip/Archive/RPM/makefile b/7zip/Archive/RPM/makefile index 310c09a8..afda1289 100755 --- a/7zip/Archive/RPM/makefile +++ b/7zip/Archive/RPM/makefile @@ -17,6 +17,7 @@ WIN_OBJS = \ 7ZIP_COMMON_OBJS = \ $O\ProgressUtils.obj \ + $O\StreamUtils.obj \ OBJS = \ $O\StdAfx.obj \ diff --git a/7zip/Archive/Rar/DllExports.cpp b/7zip/Archive/Rar/DllExports.cpp index 7e24047c..0df1ac47 100755 --- a/7zip/Archive/Rar/DllExports.cpp +++ b/7zip/Archive/Rar/DllExports.cpp @@ -46,9 +46,9 @@ DEFINE_GUID(CLSID_CCryptoRar29Decoder, 0x23170F69, 0x40C1, 0x278B, 0x06, 0xF1, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00); */ -// {23170F69-40C1-278A-1000-000110020000} +// {23170F69-40C1-278A-1000-000110030000} DEFINE_GUID(CLSID_CRarHandler, - 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x02, 0x00, 0x00); + 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x03, 0x00, 0x00); extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) diff --git a/7zip/Archive/Rar/Rar.dsp b/7zip/Archive/Rar/Rar.dsp index 9fe9b840..9aee468e 100755 --- a/7zip/Archive/Rar/Rar.dsp +++ b/7zip/Archive/Rar/Rar.dsp @@ -178,6 +178,14 @@ SOURCE=..\..\..\Common\Types.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\UTFConvert.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\UTFConvert.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\Vector.cpp # End Source File # Begin Source File @@ -400,6 +408,14 @@ SOURCE=..\..\Common\StreamObjects.cpp SOURCE=..\..\Common\StreamObjects.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # Begin Group "7z" diff --git a/7zip/Archive/Rar/RarHandler.cpp b/7zip/Archive/Rar/RarHandler.cpp index d38b65a4..56187156 100755 --- a/7zip/Archive/Rar/RarHandler.cpp +++ b/7zip/Archive/Rar/RarHandler.cpp @@ -186,7 +186,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va switch(propID) { case kpidPath: - if (item.HasUnicodeName()) + if (item.HasUnicodeName() && !item.UnicodeName.IsEmpty()) propVariant = item.UnicodeName; else propVariant = (const wchar_t *)MultiByteToUnicodeString(item.Name, CP_OEMCP); @@ -615,6 +615,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec; CMyComPtr rar20CryptoDecoder; + NCrypto::NRar29::CDecoder *rar29CryptoDecoderSpec; CMyComPtr rar29CryptoDecoder; CFolderInStream *folderInStreamSpec = NULL; @@ -727,9 +728,11 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, { if (!rar29CryptoDecoder) { - rar29CryptoDecoder = new NCrypto::NRar29::CDecoder; + rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder; + rar29CryptoDecoder = rar29CryptoDecoderSpec; // RINOK(rar29CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar29Decoder)); } + rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36); CMyComPtr cryptoProperties; RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &cryptoProperties)); diff --git a/7zip/Archive/Rar/RarHeader.h b/7zip/Archive/Rar/RarHeader.h index f7e6f711..832a21c0 100755 --- a/7zip/Archive/Rar/RarHeader.h +++ b/7zip/Archive/Rar/RarHeader.h @@ -42,7 +42,10 @@ namespace NArchive const UInt16 kRecovery = 0x40; const UInt16 kBlockEncryption = 0x80; const UInt16 kFirstVolume = 0x100; // (set only by RAR 3.0 and later) + const UInt16 kEncryptVer = 0x200; // RAR 3.6 there is EncryptVer Byte in End of MainHeader + const int kHeaderSizeMin = 7; + struct CBlock { UInt16 CRC; @@ -53,9 +56,19 @@ namespace NArchive UInt32 Reserved2; // UInt16 GetRealCRC() const; }; + const int kArchiveHeaderSize = 13; const int kBlockHeadersAreEncrypted = 0x80; + + struct CHeader360: public CBlock + { + Byte EncryptVersion; + bool IsEncrypted() const { return (Flags & NHeader::NArchive::kBlockEncryption) != 0; } + bool IsThereEncryptVer() const { return (Flags & NHeader::NArchive::kEncryptVer) != 0; } + bool IsEncryptOld() const { return (!IsThereEncryptVer() || EncryptVersion < 36); } + UInt32 GetBaseSize() const { return kArchiveHeaderSize + (IsEncryptOld() ? 0 : 1); } + }; } namespace NFile diff --git a/7zip/Archive/Rar/RarIn.cpp b/7zip/Archive/Rar/RarIn.cpp index f6a4891f..36d8b824 100755 --- a/7zip/Archive/Rar/RarIn.cpp +++ b/7zip/Archive/Rar/RarIn.cpp @@ -4,9 +4,11 @@ #include "Common/StringConvert.h" #include "Common/CRC.h" +#include "Common/UTFConvert.h" #include "RarIn.h" #include "../../Common/LimitedStreams.h" +#include "../../Common/StreamUtils.h" namespace NArchive { namespace NRar { @@ -115,7 +117,7 @@ bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size) return (i == size); } UInt32 processedSize; - m_Stream->Read(data, size, &processedSize); + ReadStream(m_Stream, data, size, &processedSize); return (processedSize == size); } @@ -128,7 +130,7 @@ void CInArchive::ReadBytesAndTestResult(void *data, UInt32 size) HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; - HRESULT result = m_Stream->Read(data, size, &realProcessedSize); + HRESULT result = ReadStream(m_Stream, data, size, &realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; AddToSeekValue(realProcessedSize); @@ -155,6 +157,7 @@ bool CInArchive::ReadMarkerAndArchiveHeader(const UInt64 *searchHeaderSizeLimit) m_ArchiveHeader.Size = ReadUInt16(); m_ArchiveHeader.Reserved1 = ReadUInt16(); m_ArchiveHeader.Reserved2 = ReadUInt32(); + m_ArchiveHeader.EncryptVersion = 0; CCRC crc; crc.UpdateByte(m_ArchiveHeader.Type); @@ -163,6 +166,14 @@ bool CInArchive::ReadMarkerAndArchiveHeader(const UInt64 *searchHeaderSizeLimit) crc.UpdateUInt16(m_ArchiveHeader.Reserved1); crc.UpdateUInt32(m_ArchiveHeader.Reserved2); + if (m_ArchiveHeader.IsThereEncryptVer() && m_ArchiveHeader.Size > NHeader::NArchive::kArchiveHeaderSize) + { + ReadBytes(&m_ArchiveHeader.EncryptVersion, 1, &processedSize); + if (processedSize != 1) + return false; + crc.UpdateByte(m_ArchiveHeader.EncryptVersion); + } + UInt32 u = crc.GetDigest(); if(m_ArchiveHeader.CRC != (crc.GetDigest() & 0xFFFF)) ThrowExceptionWithCode(CInArchiveException::kArchiveHeaderCRCError); @@ -177,7 +188,7 @@ void CInArchive::SkipArchiveComment() { if (!m_SeekOnArchiveComment) return; - AddToSeekValue(m_ArchiveHeader.Size - NHeader::NArchive::kArchiveHeaderSize); + AddToSeekValue(m_ArchiveHeader.Size - m_ArchiveHeader.GetBaseSize()); m_SeekOnArchiveComment = false; } @@ -256,15 +267,18 @@ void CInArchive::ReadName(CItemEx &item, int nameSize) buffer[mainLen] = '\0'; item.Name = buffer; - int unicodeNameSizeMax = MyMin(nameSize, (0x400)); - _unicodeNameBuffer.EnsureCapacity(unicodeNameSizeMax + 1); - - if((m_BlockHeader.Flags & NHeader::NFile::kUnicodeName) != 0 && - mainLen < nameSize) + if(item.HasUnicodeName()) { - DecodeUnicodeFileName(buffer, (const Byte *)buffer + mainLen + 1, - nameSize - (mainLen + 1), _unicodeNameBuffer, unicodeNameSizeMax); - item.UnicodeName = _unicodeNameBuffer; + if(mainLen < nameSize) + { + int unicodeNameSizeMax = MyMin(nameSize, (0x400)); + _unicodeNameBuffer.EnsureCapacity(unicodeNameSizeMax + 1); + DecodeUnicodeFileName(buffer, (const Byte *)buffer + mainLen + 1, + nameSize - (mainLen + 1), _unicodeNameBuffer, unicodeNameSizeMax); + item.UnicodeName = _unicodeNameBuffer; + } + else if (!ConvertUTF8ToUnicode(item.Name, item.UnicodeName)) + item.UnicodeName.Empty(); } } else @@ -398,6 +412,8 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa m_RarAESSpec = new NCrypto::NRar29::CDecoder; m_RarAES = m_RarAESSpec; } + m_RarAESSpec->SetRar350Mode(m_ArchiveHeader.IsEncryptOld()); + // Salt const UInt32 kSaltSize = 8; Byte salt[kSaltSize]; @@ -410,9 +426,17 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa RINOK(getTextPassword->CryptoGetTextPassword(&password)) UString unicodePassword(password); - RINOK(m_RarAESSpec->CryptoSetPassword( - (const Byte *)(const wchar_t *)unicodePassword, - unicodePassword.Length() * 2)); + CByteBuffer buffer; + const UInt32 sizeInBytes = unicodePassword.Length() * 2; + buffer.SetCapacity(sizeInBytes); + for (int i = 0; i < unicodePassword.Length(); i++) + { + wchar_t c = unicodePassword[i]; + ((Byte *)buffer)[i * 2] = (Byte)c; + ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); + } + + RINOK(m_RarAESSpec->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); const UInt32 kDecryptedBufferSize = (1 << 12); if (m_DecryptedData.GetCapacity() == 0) @@ -420,7 +444,7 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa m_DecryptedData.SetCapacity(kDecryptedBufferSize); } RINOK(m_RarAES->Init()); - RINOK(m_Stream->Read((Byte *)m_DecryptedData, kDecryptedBufferSize, &m_DecryptedDataSize)); + RINOK(ReadStream(m_Stream, (Byte *)m_DecryptedData, kDecryptedBufferSize, &m_DecryptedDataSize)); m_DecryptedDataSize = m_RarAES->Filter((Byte *)m_DecryptedData, m_DecryptedDataSize); m_CryptoMode = true; @@ -486,7 +510,7 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa void CInArchive::DirectGetBytes(void *data, UInt32 size) { - m_Stream->Read(data, size, NULL); + ReadStream(m_Stream, data, size, NULL); } bool CInArchive::SeekInArchive(UInt64 position) diff --git a/7zip/Archive/Rar/RarIn.h b/7zip/Archive/Rar/RarIn.h index c370733a..22262a74 100755 --- a/7zip/Archive/Rar/RarIn.h +++ b/7zip/Archive/Rar/RarIn.h @@ -41,6 +41,7 @@ public: bool IsCommented() const { return (Flags & NHeader::NArchive::kComment) != 0; } bool IsVolume() const { return (Flags & NHeader::NArchive::kVolume) != 0; } bool HaveNewVolumeName() const { return (Flags & NHeader::NArchive::kNewVolName) != 0; } + bool IsEncrypted() const { return (Flags & NHeader::NArchive::kBlockEncryption) != 0; } }; class CInArchive @@ -51,7 +52,7 @@ class CInArchive UInt64 m_Position; UInt64 m_ArchiveStartPosition; - NHeader::NArchive::CBlock m_ArchiveHeader; + NHeader::NArchive::CHeader360 m_ArchiveHeader; CDynamicBuffer m_NameBuffer; CDynamicBuffer _unicodeNameBuffer; bool m_SeekOnArchiveComment; diff --git a/7zip/Archive/Rar/RarVolumeInStream.cpp b/7zip/Archive/Rar/RarVolumeInStream.cpp index 5a185707..32078e6d 100755 --- a/7zip/Archive/Rar/RarVolumeInStream.cpp +++ b/7zip/Archive/Rar/RarVolumeInStream.cpp @@ -64,6 +64,7 @@ STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSiz } realProcessedSize += localProcessedSize; size -= localProcessedSize; + break; } else { @@ -75,9 +76,4 @@ STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSiz return S_OK; } -STDMETHODIMP CFolderInStream::ReadPart(void *data, UInt32 size, UInt32 *processedSize) -{ - return Read(data, size, processedSize); -} - -}} \ No newline at end of file +}} diff --git a/7zip/Archive/Rar/RarVolumeInStream.h b/7zip/Archive/Rar/RarVolumeInStream.h index 53156306..4c9a9e96 100755 --- a/7zip/Archive/Rar/RarVolumeInStream.h +++ b/7zip/Archive/Rar/RarVolumeInStream.h @@ -25,7 +25,6 @@ public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); private: CObjectVector *_archives; diff --git a/7zip/Archive/Rar/makefile b/7zip/Archive/Rar/makefile index 0799edf3..42942f74 100755 --- a/7zip/Archive/Rar/makefile +++ b/7zip/Archive/Rar/makefile @@ -18,6 +18,7 @@ COMMON_OBJS = \ $O\NewHandler.obj \ $O\String.obj \ $O\StringConvert.obj \ + $O\UTFConvert.obj \ $O\Vector.obj \ WIN_OBJS = \ @@ -29,6 +30,7 @@ WIN_OBJS = \ $O\LimitedStreams.obj \ $O\ProgressUtils.obj \ $O\StreamObjects.obj \ + $O\StreamUtils.obj \ AR_COMMON_OBJS = \ $O\CodecsPath.obj \ diff --git a/7zip/Archive/Split/DllExports.cpp b/7zip/Archive/Split/DllExports.cpp index d8ea97c7..f9e8a83b 100755 --- a/7zip/Archive/Split/DllExports.cpp +++ b/7zip/Archive/Split/DllExports.cpp @@ -8,9 +8,9 @@ #include "SplitHandler.h" #include "../../ICoder.h" -// {23170F69-40C1-278A-1000-0001100B0000} +// {23170F69-40C1-278A-1000-000110EA0000} DEFINE_GUID(CLSID_CSplitHandler, - 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x0B, 0x00, 0x00); + 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEA, 0x00, 0x00); extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) diff --git a/7zip/Archive/Split/Split.dsp b/7zip/Archive/Split/Split.dsp index 5758e3b3..d6229d98 100755 --- a/7zip/Archive/Split/Split.dsp +++ b/7zip/Archive/Split/Split.dsp @@ -204,6 +204,14 @@ SOURCE=..\..\Common\ProgressUtils.cpp SOURCE=..\..\Common\ProgressUtils.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # Begin Group "Interface" @@ -223,7 +231,7 @@ SOURCE=.\SplitHandler.h # End Source File # Begin Source File -SOURCE=.\SplitHanlerOut.cpp +SOURCE=.\SplitHandlerOut.cpp # End Source File # End Target # End Project diff --git a/7zip/Archive/Split/makefile b/7zip/Archive/Split/makefile index a821b2f8..650c750b 100755 --- a/7zip/Archive/Split/makefile +++ b/7zip/Archive/Split/makefile @@ -20,6 +20,7 @@ WIN_OBJS = \ 7ZIP_COMMON_OBJS = \ $O\ProgressUtils.obj \ + $O\StreamUtils.obj \ AR_COMMON_OBJS = \ $O\MultiStream.obj \ diff --git a/7zip/Archive/Tar/DllExports.cpp b/7zip/Archive/Tar/DllExports.cpp index 7f4f5c04..9d80a651 100755 --- a/7zip/Archive/Tar/DllExports.cpp +++ b/7zip/Archive/Tar/DllExports.cpp @@ -8,9 +8,9 @@ #include "../../ICoder.h" #include "TarHandler.h" -// {23170F69-40C1-278A-1000-000110040000} +// {23170F69-40C1-278A-1000-000110EE0000} DEFINE_GUID(CLSID_CTarHandler, - 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x04, 0x00, 0x00); + 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEE, 0x00, 0x00); extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) diff --git a/7zip/Archive/Tar/Tar.dsp b/7zip/Archive/Tar/Tar.dsp index bba8ab2b..c01e7383 100755 --- a/7zip/Archive/Tar/Tar.dsp +++ b/7zip/Archive/Tar/Tar.dsp @@ -162,6 +162,14 @@ SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\StringToInt.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringToInt.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\Vector.cpp # End Source File # Begin Source File @@ -276,6 +284,14 @@ SOURCE=..\..\Common\ProgressUtils.cpp SOURCE=..\..\Common\ProgressUtils.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # End Target # End Project diff --git a/7zip/Archive/Tar/TarHeader.cpp b/7zip/Archive/Tar/TarHeader.cpp index 9bf408c0..41fb2137 100755 --- a/7zip/Archive/Tar/TarHeader.cpp +++ b/7zip/Archive/Tar/TarHeader.cpp @@ -16,7 +16,7 @@ namespace NFileHeader { // The magic field is filled with this if uname and gname are valid. namespace NMagic { - const char *kUsTar = "ustar "; // 7 chars and a null + 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"; // 7 chars and a null } diff --git a/7zip/Archive/Tar/TarHeader.h b/7zip/Archive/Tar/TarHeader.h index c32092ca..1436293f 100755 --- a/7zip/Archive/Tar/TarHeader.h +++ b/7zip/Archive/Tar/TarHeader.h @@ -14,6 +14,7 @@ namespace NFileHeader const int kNameSize = 100; const int kUserNameSize = 32; const int kGroupNameSize = 32; + const int kPrefixSize = 155; /* struct CHeader @@ -32,6 +33,7 @@ namespace NFileHeader char GroupName[kGroupNameSize]; char DeviceMajor[8]; char DeviceMinor[8]; + char Prefix[155]; }; union CRecord { @@ -84,7 +86,7 @@ namespace NFileHeader // The magic field is filled with this if uname and gname are valid. namespace NMagic { - extern const char *kUsTar; // = "ustar "; // 7 chars and a null + extern const char *kUsTar; // = "ustar"; // 5 chars extern const char *kGNUTar; // = "GNUtar "; // 7 chars and a null extern const char *kEmpty; // = "GNUtar "; // 7 chars and a null } diff --git a/7zip/Archive/Tar/TarIn.cpp b/7zip/Archive/Tar/TarIn.cpp index f9bfacd6..fad27587 100755 --- a/7zip/Archive/Tar/TarIn.cpp +++ b/7zip/Archive/Tar/TarIn.cpp @@ -5,14 +5,17 @@ #include "TarIn.h" #include "TarHeader.h" +#include "Common/StringToInt.h" #include "Windows/Defs.h" +#include "../../Common/StreamUtils.h" + namespace NArchive { namespace NTar { HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize) { - RINOK(m_Stream->Read(data, size, &processedSize)); + RINOK(ReadStream(m_Stream, data, size, &processedSize)); m_Position += processedSize; return S_OK; } @@ -24,28 +27,28 @@ HRESULT CInArchive::Open(IInStream *inStream) return S_OK; } -static UInt32 OctalToNumber(const char *srcString) +static bool OctalToNumber(const char *srcString, int size, UInt64 &res) { - char *endPtr; - return(strtoul(srcString, &endPtr, 8)); + char sz[32]; + strncpy(sz, srcString, size); + sz[size] = 0; + const char *end; + int i; + for (i = 0; sz[i] == ' '; i++); + res = ConvertOctStringToUInt64(sz + i, &end); + return (*end == ' ' || *end == 0); } -static bool CheckOctalString(const char *srcString, int numChars) +static bool OctalToNumber32(const char *srcString, int size, UInt32 &res) { - for(int i = 0; i < numChars; i++) - { - char c = srcString[i]; - if (c == 0) - return true; - if (c >= '0' && c <= '7') - continue; - if (c != ' ') - return false; - } - return true; + UInt64 res64; + if (!OctalToNumber(srcString, size, res64)) + return false; + res = (UInt32)res64; + return (res64 <= 0xFFFFFFFF); } -#define ReturnIfBadOctal(x, y) { if (!CheckOctalString((x), (y))) return S_FALSE; } +#define RIF(x) { if (!(x)) return S_FALSE; } static bool IsRecordLast(const char *record) { @@ -57,9 +60,9 @@ static bool IsRecordLast(const char *record) static void ReadString(const char *s, int size, AString &result) { - if (size > NFileHeader::kNameSize) + if (size > NFileHeader::kRecordSize) size = NFileHeader::kNameSize; - char tempString[NFileHeader::kNameSize + 1]; + char tempString[NFileHeader::kRecordSize + 1]; strncpy(tempString, s, size); tempString[size] = '\0'; result = tempString; @@ -114,28 +117,23 @@ HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item) item.Name += c; } - ReturnIfBadOctal(cur, 8); - item.Mode = OctalToNumber(cur); + RIF(OctalToNumber32(cur, 8, item.Mode)); cur += 8; - ReturnIfBadOctal(cur, 8); - item.UID = OctalToNumber(cur); + RIF(OctalToNumber32(cur, 8, item.UID)); cur += 8; - ReturnIfBadOctal(cur, 8); - item.GID = OctalToNumber(cur); + RIF(OctalToNumber32(cur, 8, item.GID)); cur += 8; - ReturnIfBadOctal(cur, 12); - item.Size = OctalToNumber(cur); + RIF(OctalToNumber(cur, 12, item.Size)); cur += 12; - ReturnIfBadOctal(cur, 12); - item.ModificationTime = OctalToNumber(cur); + RIF(OctalToNumber32(cur, 12, item.ModificationTime)); cur += 12; - ReturnIfBadOctal(cur, 8); - UInt32 checkSum = OctalToNumber(cur); + UInt32 checkSum; + RIF(OctalToNumber32(cur, 8, checkSum)); memmove(cur, NFileHeader::kCheckSumBlanks, 8); cur += 8; @@ -153,17 +151,19 @@ HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item) ReadString(cur, NFileHeader::kUserNameSize, item.GroupName); cur += NFileHeader::kUserNameSize; - ReturnIfBadOctal(cur, 8); item.DeviceMajorDefined = (cur[0] != 0); - if (item.DeviceMajorDefined) - item.DeviceMajor = OctalToNumber(cur); + RIF(OctalToNumber32(cur, 8, item.DeviceMajor)); + cur += 8; - ReturnIfBadOctal(cur, 8); item.DeviceMinorDefined = (cur[0] != 0); - if (item.DeviceMinorDefined) - item.DeviceMinor = OctalToNumber(cur); + RIF(OctalToNumber32(cur, 8, item.DeviceMinor)); cur += 8; + AString prefix; + ReadString(cur, NFileHeader::kPrefixSize, prefix); + cur += NFileHeader::kPrefixSize; + if (!prefix.IsEmpty() && item.IsMagic()) + item.Name = prefix + AString('/') + item.Name; if (item.LinkFlag == NFileHeader::NLinkFlag::kLink) item.Size = 0; diff --git a/7zip/Archive/Tar/TarItem.h b/7zip/Archive/Tar/TarItem.h index 7637b537..71fff7ba 100755 --- a/7zip/Archive/Tar/TarItem.h +++ b/7zip/Archive/Tar/TarItem.h @@ -45,6 +45,14 @@ public: } return false; } + + bool IsMagic() const + { + for (int i = 0; i < 5; i++) + if (Magic[i] != NFileHeader::NMagic::kUsTar[i]) + return false; + return true; + } }; class CItemEx: public CItem diff --git a/7zip/Archive/Tar/TarOut.cpp b/7zip/Archive/Tar/TarOut.cpp index 45c7ef1d..28146c34 100755 --- a/7zip/Archive/Tar/TarOut.cpp +++ b/7zip/Archive/Tar/TarOut.cpp @@ -7,6 +7,7 @@ #include "Common/IntToString.h" #include "Windows/Defs.h" +#include "../../Common/StreamUtils.h" namespace NArchive { namespace NTar { @@ -14,7 +15,7 @@ namespace NTar { HRESULT COutArchive::WriteBytes(const void *buffer, UInt32 size) { UInt32 processedSize; - RINOK(m_Stream->Write(buffer, size, &processedSize)); + RINOK(WriteStream(m_Stream, buffer, size, &processedSize)); if(processedSize != size) return E_FAIL; return S_OK; @@ -165,10 +166,15 @@ HRESULT COutArchive::FillDataResidual(UInt64 dataSize) HRESULT COutArchive::WriteFinishHeader() { - char record[NFileHeader::kRecordSize]; - for (int i = 0; i < NFileHeader::kRecordSize; i++) + Byte record[NFileHeader::kRecordSize]; + int i; + for (i = 0; i < NFileHeader::kRecordSize; i++) record[i] = 0; - return WriteBytes(record, NFileHeader::kRecordSize); + for (i = 0; i < 2; i++) + { + RINOK(WriteBytes(record, NFileHeader::kRecordSize)); + } + return S_OK; } }} diff --git a/7zip/Archive/Tar/makefile b/7zip/Archive/Tar/makefile index b9670b28..f892c303 100755 --- a/7zip/Archive/Tar/makefile +++ b/7zip/Archive/Tar/makefile @@ -18,6 +18,7 @@ COMMON_OBJS = \ $O\NewHandler.obj \ $O\String.obj \ $O\StringConvert.obj \ + $O\StringToInt.obj \ $O\Vector.obj \ WIN_OBJS = \ @@ -26,6 +27,7 @@ WIN_OBJS = \ 7ZIP_COMMON_OBJS = \ $O\LimitedStreams.obj \ $O\ProgressUtils.obj \ + $O\StreamUtils.obj \ AR_COMMON_OBJS = \ $O\ItemNameUtils.obj \ diff --git a/7zip/Archive/Z/DllExports.cpp b/7zip/Archive/Z/DllExports.cpp index 7d4e0d23..d96cd303 100755 --- a/7zip/Archive/Z/DllExports.cpp +++ b/7zip/Archive/Z/DllExports.cpp @@ -8,13 +8,9 @@ #include "ZHandler.h" #include "../../ICoder.h" -// {23170F69-40C1-278B-0402-050000000000} -DEFINE_GUID(CLSID_CCompressZDecoder, -0x23170F69, 0x40C1, 0x278B, 0x04, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00); - -// {23170F69-40C1-278A-1000-0001100D0000} +// {23170F69-40C1-278A-1000-000110050000} DEFINE_GUID(CLSID_CZHandler, -0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x0D, 0x00, 0x00); +0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x05, 0x00, 0x00); HINSTANCE g_hInstance; diff --git a/7zip/Archive/Z/Z.dsp b/7zip/Archive/Z/Z.dsp index 56873229..e1f72522 100755 --- a/7zip/Archive/Z/Z.dsp +++ b/7zip/Archive/Z/Z.dsp @@ -220,6 +220,14 @@ SOURCE=..\..\Common\ProgressUtils.cpp SOURCE=..\..\Common\ProgressUtils.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # Begin Source File diff --git a/7zip/Archive/Z/ZHandler.cpp b/7zip/Archive/Z/ZHandler.cpp index e7b13a75..5787273b 100755 --- a/7zip/Archive/Z/ZHandler.cpp +++ b/7zip/Archive/Z/ZHandler.cpp @@ -8,6 +8,7 @@ #include "../../Common/ProgressUtils.h" #include "../../Compress/Z/ZDecoder.h" +#include "../../Common/StreamUtils.h" #include "Windows/PropVariant.h" #include "Windows/Defs.h" @@ -98,7 +99,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_streamStartPosition)); Byte buffer[kSignatureSize]; UInt32 processedSize; - RINOK(stream->Read(buffer, kSignatureSize, &processedSize)); + RINOK(ReadStream(stream, buffer, kSignatureSize, &processedSize)); if (processedSize != kSignatureSize) return S_FALSE; if (buffer[0] != 0x1F || buffer[1] != 0x9D) diff --git a/7zip/Archive/Z/makefile b/7zip/Archive/Z/makefile index fbd9d6ad..aff4fc42 100755 --- a/7zip/Archive/Z/makefile +++ b/7zip/Archive/Z/makefile @@ -18,6 +18,7 @@ WIN_OBJS = \ $O\InBuffer.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ + $O\StreamUtils.obj \ AR_COMMON_OBJS = \ $O\DummyOutStream.obj \ diff --git a/7zip/Archive/Zip/Zip.dsp b/7zip/Archive/Zip/Zip.dsp index 7a5ebdbf..44852ec1 100755 --- a/7zip/Archive/Zip/Zip.dsp +++ b/7zip/Archive/Zip/Zip.dsp @@ -320,6 +320,14 @@ SOURCE=..\..\Common\StreamObjects.cpp SOURCE=..\..\Common\StreamObjects.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # Begin Group "Engine" diff --git a/7zip/Archive/Zip/ZipHandler.cpp b/7zip/Archive/Zip/ZipHandler.cpp index 922a69c7..00a61f57 100755 --- a/7zip/Archive/Zip/ZipHandler.cpp +++ b/7zip/Archive/Zip/ZipHandler.cpp @@ -148,6 +148,7 @@ const wchar_t *kMethods[] = const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]); const wchar_t *kUnknownMethod = L"Unknown"; +const wchar_t *kPPMdMethod = L"PPMd"; CHandler::CHandler(): m_ArchiveIsOpen(false) @@ -258,6 +259,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID aPropID, PROPVARIANT *a UString method; if (item.CompressionMethod < kNumMethods) method = kMethods[item.CompressionMethod]; + else if (item.CompressionMethod == NFileHeader::NCompressionMethod::kWinZipPPMd) + method = kPPMdMethod; else method = kUnknownMethod; propVariant = method; diff --git a/7zip/Archive/Zip/ZipHeader.h b/7zip/Archive/Zip/ZipHeader.h index e6d1288a..7d023715 100755 --- a/7zip/Archive/Zip/ZipHeader.h +++ b/7zip/Archive/Zip/ZipHeader.h @@ -67,7 +67,8 @@ namespace NFileHeader kDeflated64 = 9, kPKImploding = 10, - kBZip2 = 12 + kBZip2 = 12, + kWinZipPPMd = 0x62 }; const int kNumCompressionMethods = 11; const Byte kMadeByProgramVersion = 20; diff --git a/7zip/Archive/Zip/ZipIn.cpp b/7zip/Archive/Zip/ZipIn.cpp index 4b4481ed..59f1e0ae 100755 --- a/7zip/Archive/Zip/ZipIn.cpp +++ b/7zip/Archive/Zip/ZipIn.cpp @@ -7,6 +7,7 @@ #include "Common/StringConvert.h" #include "Common/DynamicBuffer.h" #include "../../Common/LimitedStreams.h" +#include "../../Common/StreamUtils.h" namespace NArchive { namespace NZip { @@ -87,13 +88,10 @@ bool CInArchive::FindAndReadMarker(const UInt64 *searchHeaderSizeLimit) } } -////////////////////////////////////// -// Read Operations - HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; - HRESULT result = m_Stream->Read(data, size, &realProcessedSize); + HRESULT result = ReadStream(m_Stream, data, size, &realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; m_Position += realProcessedSize; @@ -158,9 +156,6 @@ UInt64 CInArchive::ReadUInt64() return value; } -////////////////////////////////// -// Read headers - bool CInArchive::ReadUInt32(UInt32 &value) { value = 0; diff --git a/7zip/Archive/Zip/ZipOut.cpp b/7zip/Archive/Zip/ZipOut.cpp index 7e46d6ca..6e4e7335 100755 --- a/7zip/Archive/Zip/ZipOut.cpp +++ b/7zip/Archive/Zip/ZipOut.cpp @@ -6,6 +6,7 @@ #include "Common/StringConvert.h" #include "Common/CRC.h" #include "../../Common/OffsetStream.h" +#include "../../Common/StreamUtils.h" namespace NArchive { namespace NZip { @@ -46,7 +47,7 @@ void COutArchive::PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPa void COutArchive::WriteBytes(const void *buffer, UInt32 size) { UInt32 processedSize; - if(m_Stream->Write(buffer, size, &processedSize) != S_OK) + if(WriteStream(m_Stream, buffer, size, &processedSize) != S_OK) throw 0; if(processedSize != size) throw 0; diff --git a/7zip/Archive/Zip/makefile b/7zip/Archive/Zip/makefile index 22d59801..4d59fb0c 100755 --- a/7zip/Archive/Zip/makefile +++ b/7zip/Archive/Zip/makefile @@ -38,6 +38,7 @@ WIN_OBJS = \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamObjects.obj \ + $O\StreamUtils.obj \ AR_COMMON_OBJS = \ $O\CodecsPath.obj \ diff --git a/7zip/Archive/cpio/CpioIn.cpp b/7zip/Archive/cpio/CpioIn.cpp index ce2ab023..32b9f77d 100755 --- a/7zip/Archive/cpio/CpioIn.cpp +++ b/7zip/Archive/cpio/CpioIn.cpp @@ -4,8 +4,11 @@ #include "CpioIn.h" +#include "Common/StringToInt.h" #include "Windows/Defs.h" +#include "../../Common/StreamUtils.h" + #include "CpioHeader.h" namespace NArchive { @@ -13,7 +16,7 @@ namespace NCpio { HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize) { - RINOK(m_Stream->Read(data, size, &processedSize)); + RINOK(ReadStream(m_Stream, data, size, &processedSize)); m_Position += processedSize; return S_OK; } @@ -75,24 +78,37 @@ bool CInArchive::ReadNumber(UInt32 &resultValue) return true; } -bool CInArchive::ReadOctNumber(int size, UInt32 &resultValue) +static bool OctalToNumber(const char *s, UInt64 &res) { - char s[32]; - int i; - for (i = 0; i < size && i < 32; i++) - s[i] = char(ReadByte()); - s[i] = 0; - char *endPtr; - resultValue = strtoul(s, &endPtr, 8); - return true; + const char *end; + res = ConvertOctStringToUInt64(s, &end); + return (*end == ' ' || *end == 0); } -#define GetFromHex(y) { if (!ReadNumber(y)) return E_FAIL; } -#define GetFromOct6(y) { if (!ReadOctNumber(6, y)) return E_FAIL; } -#define GetFromOct11(y) { if (!ReadOctNumber(11, y)) return E_FAIL; } +static bool OctalToNumber32(const char *s, UInt32 &res) +{ + UInt64 res64; + if (!OctalToNumber(s, res64)) + return false; + res = (UInt32)res64; + return (res64 <= 0xFFFFFFFF); +} -static unsigned short ConvertValue( - unsigned short value, bool convert) +bool CInArchive::ReadOctNumber(int size, UInt32 &resultValue) +{ + char sz[32 + 4]; + int i; + for (i = 0; i < size && i < 32; i++) + sz[i] = (char)ReadByte(); + sz[i] = 0; + return OctalToNumber32(sz, resultValue); +} + +#define GetFromHex(y) { if (!ReadNumber(y)) return S_FALSE; } +#define GetFromOct6(y) { if (!ReadOctNumber(6, y)) return S_FALSE; } +#define GetFromOct11(y) { if (!ReadOctNumber(11, y)) return S_FALSE; } + +static unsigned short ConvertValue(unsigned short value, bool convert) { if (!convert) return value; @@ -109,13 +125,6 @@ static UInt32 GetAlignedSize(UInt32 size, UInt32 align) HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) { - /* - union - { - NFileHeader::CRecord record; - NFileHeader::CRecord2 record2; - }; - */ filled = false; UInt32 processedSize; diff --git a/7zip/Archive/cpio/DllExports.cpp b/7zip/Archive/cpio/DllExports.cpp index a72058a5..32473235 100755 --- a/7zip/Archive/cpio/DllExports.cpp +++ b/7zip/Archive/cpio/DllExports.cpp @@ -8,9 +8,9 @@ #include "CpioHandler.h" #include "../../ICoder.h" -// {23170F69-40C1-278A-1000-000110080000} +// {23170F69-40C1-278A-1000-000110ED0000} DEFINE_GUID(CLSID_CCpioHandler, - 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0x00); + 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xED, 0x00, 0x00); extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) diff --git a/7zip/Archive/cpio/cpio.dsp b/7zip/Archive/cpio/cpio.dsp index 5f555d9b..f30c3e63 100755 --- a/7zip/Archive/cpio/cpio.dsp +++ b/7zip/Archive/cpio/cpio.dsp @@ -150,6 +150,14 @@ SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File +SOURCE=..\..\..\Common\StringToInt.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringToInt.h +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\Vector.cpp # End Source File # Begin Source File @@ -244,6 +252,14 @@ SOURCE=..\..\Common\ProgressUtils.cpp SOURCE=..\..\Common\ProgressUtils.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # End Target # End Project diff --git a/7zip/Archive/makefile b/7zip/Archive/makefile index a5858144..24df1961 100755 --- a/7zip/Archive/makefile +++ b/7zip/Archive/makefile @@ -3,6 +3,7 @@ DIRS = \ Arj\~ \ BZip2\~ \ Cab\~ \ + Chm\~ \ Cpio\~ \ Deb\~ \ GZip\~ \ diff --git a/7zip/Bundles/Alone/Alone.dsp b/7zip/Bundles/Alone/Alone.dsp index 9cb637bc..bcb415a9 100755 --- a/7zip/Bundles/Alone/Alone.dsp +++ b/7zip/Bundles/Alone/Alone.dsp @@ -635,6 +635,14 @@ SOURCE=..\..\Common\StreamObjects.cpp SOURCE=..\..\Common\StreamObjects.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # Begin Group "Compress" diff --git a/7zip/Bundles/Alone/makefile b/7zip/Bundles/Alone/makefile index f5cae4a0..f2e890bc 100755 --- a/7zip/Bundles/Alone/makefile +++ b/7zip/Bundles/Alone/makefile @@ -79,6 +79,7 @@ WIN_OBJS = \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ + $O\StreamUtils.obj \ UI_COMMON_OBJS = \ $O\ArchiveCommandLine.obj \ diff --git a/7zip/Bundles/Format7z/Format7z.dsp b/7zip/Bundles/Format7z/Format7z.dsp index 786f50e4..597f2bd7 100755 --- a/7zip/Bundles/Format7z/Format7z.dsp +++ b/7zip/Bundles/Format7z/Format7z.dsp @@ -93,11 +93,11 @@ LINK32=link.exe # PROP Default_Filter "" # Begin Source File -SOURCE=..\..\Archive\7z\7z.def +SOURCE=..\..\Archive\7z\7z.ico # End Source File # Begin Source File -SOURCE=..\..\Archive\7z\7z.ico +SOURCE=..\..\Archive\Archive.def # End Source File # Begin Source File @@ -948,6 +948,14 @@ SOURCE=..\..\Common\StreamObjects.cpp SOURCE=..\..\Common\StreamObjects.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # End Target # End Project diff --git a/7zip/Bundles/Format7z/makefile b/7zip/Bundles/Format7z/makefile index 2567f37b..02ce7144 100755 --- a/7zip/Bundles/Format7z/makefile +++ b/7zip/Bundles/Format7z/makefile @@ -44,6 +44,7 @@ WIN_OBJS = \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ + $O\StreamUtils.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ diff --git a/7zip/Bundles/Format7zExtract/Format7z.dsp b/7zip/Bundles/Format7zExtract/Format7z.dsp index 82800b08..d3a7d434 100755 --- a/7zip/Bundles/Format7zExtract/Format7z.dsp +++ b/7zip/Bundles/Format7zExtract/Format7z.dsp @@ -93,11 +93,11 @@ LINK32=link.exe # PROP Default_Filter "" # Begin Source File -SOURCE=..\..\Archive\7z\7z.def +SOURCE=..\..\Archive\7z\7z.ico # End Source File # Begin Source File -SOURCE=..\..\Archive\7z\7z.ico +SOURCE=..\..\Archive\Archive.def # End Source File # Begin Source File @@ -804,6 +804,14 @@ SOURCE=..\..\Common\StreamObjects.cpp SOURCE=..\..\Common\StreamObjects.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # End Target # End Project diff --git a/7zip/Bundles/Format7zExtract/makefile b/7zip/Bundles/Format7zExtract/makefile index 56b9ff50..fbe77392 100755 --- a/7zip/Bundles/Format7zExtract/makefile +++ b/7zip/Bundles/Format7zExtract/makefile @@ -45,6 +45,7 @@ WIN_OBJS = \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ + $O\StreamUtils.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ diff --git a/7zip/Bundles/SFXCon/SFXCon.dsp b/7zip/Bundles/SFXCon/SFXCon.dsp index 05899e39..c6859282 100755 --- a/7zip/Bundles/SFXCon/SFXCon.dsp +++ b/7zip/Bundles/SFXCon/SFXCon.dsp @@ -654,6 +654,14 @@ SOURCE=..\..\Common\StreamObjects.cpp SOURCE=..\..\Common\StreamObjects.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # Begin Group "UI" diff --git a/7zip/Bundles/SFXCon/makefile b/7zip/Bundles/SFXCon/makefile index 27aaabc3..3164dc39 100755 --- a/7zip/Bundles/SFXCon/makefile +++ b/7zip/Bundles/SFXCon/makefile @@ -58,6 +58,7 @@ WIN_OBJS = \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ + $O\StreamUtils.obj \ UI_COMMON_OBJS = \ $O\ArchiveExtractCallback.obj \ diff --git a/7zip/Bundles/SFXSetup/SFXSetup.dsp b/7zip/Bundles/SFXSetup/SFXSetup.dsp index 1e686014..a58feab5 100755 --- a/7zip/Bundles/SFXSetup/SFXSetup.dsp +++ b/7zip/Bundles/SFXSetup/SFXSetup.dsp @@ -567,6 +567,14 @@ SOURCE=..\..\Common\StreamObjects.cpp SOURCE=..\..\Common\StreamObjects.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # Begin Group "UI" diff --git a/7zip/Bundles/SFXSetup/makefile b/7zip/Bundles/SFXSetup/makefile index 85459496..1f86c42c 100755 --- a/7zip/Bundles/SFXSetup/makefile +++ b/7zip/Bundles/SFXSetup/makefile @@ -57,6 +57,7 @@ WIN_CTRL_OBJS = \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ + $O\StreamUtils.obj \ UI_COMMON_OBJS = \ $O\ArchiveOpenCallback.obj \ diff --git a/7zip/Bundles/SFXWin/SFXWin.dsp b/7zip/Bundles/SFXWin/SFXWin.dsp index f49239ba..ca9ce881 100755 --- a/7zip/Bundles/SFXWin/SFXWin.dsp +++ b/7zip/Bundles/SFXWin/SFXWin.dsp @@ -506,6 +506,14 @@ SOURCE=..\..\Common\StreamObjects.cpp SOURCE=..\..\Common\StreamObjects.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # Begin Group "File Manager" diff --git a/7zip/Bundles/SFXWin/makefile b/7zip/Bundles/SFXWin/makefile index 58d56e2c..af10c3fe 100755 --- a/7zip/Bundles/SFXWin/makefile +++ b/7zip/Bundles/SFXWin/makefile @@ -61,6 +61,7 @@ WIN_CTRL_OBJS = \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ + $O\StreamUtils.obj \ UI_COMMON_OBJS = \ $O\ArchiveExtractCallback.obj \ diff --git a/7zip/Common/FileStreams.cpp b/7zip/Common/FileStreams.cpp index 5cdd4d6e..8a000e4e 100755 --- a/7zip/Common/FileStreams.cpp +++ b/7zip/Common/FileStreams.cpp @@ -39,7 +39,7 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) #ifdef _WIN32 UInt32 realProcessedSize; - bool result = File.Read(data, size, realProcessedSize); + bool result = File.ReadPart(data, size, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); @@ -54,14 +54,9 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; - + #endif } - -STDMETHODIMP CInFileStream::ReadPart(void *data, UInt32 size, UInt32 *processedSize) -{ - return Read(data, size, processedSize); -} #ifndef _WIN32_WCE STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) @@ -95,10 +90,6 @@ STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSi #endif } -STDMETHODIMP CStdInFileStream::ReadPart(void *data, UInt32 size, UInt32 *processedSize) -{ - return Read(data, size, processedSize); -} #endif STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, @@ -155,7 +146,7 @@ STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *proces #ifdef _WIN32 UInt32 realProcessedSize; - bool result = File.Write(data, size, realProcessedSize); + bool result = File.WritePart(data, size, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); @@ -174,12 +165,6 @@ STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *proces #endif } -STDMETHODIMP COutFileStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize) -{ - return Write(data, size, processedSize); -} - - STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { @@ -229,7 +214,7 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = TRUE; - while (size > 0) + if (size > 0) { // Seems that Windows doesn't like big amounts writing to stdout. // So we limit portions by 32KB. @@ -238,8 +223,6 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro sizeTemp = size; res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), data, sizeTemp, (DWORD *)&realProcessedSize, NULL); - if (realProcessedSize == 0) - break; size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); if(processedSize != NULL) @@ -265,8 +248,4 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro #endif } -STDMETHODIMP CStdOutFileStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize) -{ - return Write(data, size, processedSize); -} #endif diff --git a/7zip/Common/FileStreams.h b/7zip/Common/FileStreams.h index ea79e1b9..9326372a 100755 --- a/7zip/Common/FileStreams.h +++ b/7zip/Common/FileStreams.h @@ -36,7 +36,6 @@ public: MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(GetSize)(UInt64 *size); @@ -55,7 +54,6 @@ public: virtual ~CStdInFileStream() {} STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); }; #endif @@ -80,7 +78,6 @@ public: MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; @@ -95,7 +92,6 @@ public: virtual ~CStdOutFileStream() {} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif diff --git a/7zip/Common/InBuffer.cpp b/7zip/Common/InBuffer.cpp index 8c05874b..f1d58756 100755 --- a/7zip/Common/InBuffer.cpp +++ b/7zip/Common/InBuffer.cpp @@ -59,7 +59,7 @@ bool CInBuffer::ReadBlock() return false; _processedSize += (_buffer - _bufferBase); UInt32 numProcessedBytes; - HRESULT result = _stream->ReadPart(_bufferBase, _bufferSize, &numProcessedBytes); + HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else @@ -71,3 +71,10 @@ bool CInBuffer::ReadBlock() _wasFinished = (numProcessedBytes == 0); return (!_wasFinished); } + +Byte CInBuffer::ReadBlock2() +{ + if(!ReadBlock()) + return 0xFF; + return *_buffer++; +} diff --git a/7zip/Common/InBuffer.h b/7zip/Common/InBuffer.h index 3d53eb51..057caa16 100755 --- a/7zip/Common/InBuffer.h +++ b/7zip/Common/InBuffer.h @@ -17,15 +17,16 @@ public: class CInBuffer { - UInt64 _processedSize; - Byte *_bufferBase; - UInt32 _bufferSize; Byte *_buffer; Byte *_bufferLimit; + Byte *_bufferBase; CMyComPtr _stream; + UInt64 _processedSize; + UInt32 _bufferSize; bool _wasFinished; bool ReadBlock(); + Byte ReadBlock2(); public: #ifdef _NO_EXCEPTIONS @@ -53,8 +54,7 @@ public: Byte ReadByte() { if(_buffer >= _bufferLimit) - if(!ReadBlock()) - return 0xFF; + return ReadBlock2(); return *_buffer++; } void ReadBytes(void *data, UInt32 size, UInt32 &processedSize) diff --git a/7zip/Common/InOutTempBuffer.cpp b/7zip/Common/InOutTempBuffer.cpp index d7fb79d7..d24212de 100755 --- a/7zip/Common/InOutTempBuffer.cpp +++ b/7zip/Common/InOutTempBuffer.cpp @@ -6,6 +6,8 @@ #include "../../Common/Defs.h" // #include "Windows/Defs.h" +#include "StreamUtils.h" + using namespace NWindows; using namespace NFile; using namespace NDirectory; @@ -86,34 +88,12 @@ bool CInOutTempBuffer::InitReading() return true; } -/* -bool CInOutTempBuffer::Read(void *data, UInt32 maxSize, UInt32 &processedSize) -{ - processedSize = 0; - if (_currentPositionInBuffer < _bufferPosition) - { - UInt32 sizeToRead = MyMin(_bufferPosition - _currentPositionInBuffer, maxSize); - memmove(data, _buffer + _currentPositionInBuffer, sizeToRead); - data = ((Byte *)data) + sizeToRead; - _currentPositionInBuffer += sizeToRead; - processedSize += sizeToRead; - maxSize -= sizeToRead; - } - if (maxSize == 0 || !_tmpFileCreated) - return true; - UInt32 localProcessedSize; - bool result = _inFile.Read(data, maxSize, localProcessedSize); - processedSize += localProcessedSize; - return result; -} -*/ - HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) { if (_currentPositionInBuffer < _bufferPosition) { UInt32 sizeToWrite = _bufferPosition - _currentPositionInBuffer; - RINOK(stream->Write(_buffer + _currentPositionInBuffer, sizeToWrite, NULL)); + RINOK(WriteStream(stream, _buffer + _currentPositionInBuffer, sizeToWrite, NULL)); _currentPositionInBuffer += sizeToWrite; } if (!_tmpFileCreated) @@ -121,11 +101,11 @@ HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) while(true) { UInt32 localProcessedSize; - if (!_inFile.Read(_buffer, kTmpBufferMemorySize, localProcessedSize)) + if (!_inFile.ReadPart(_buffer, kTmpBufferMemorySize, localProcessedSize)) return E_FAIL; if (localProcessedSize == 0) return S_OK; - RINOK(stream->Write(_buffer, localProcessedSize, NULL)); + RINOK(WriteStream(stream, _buffer, localProcessedSize, NULL)); } } @@ -141,8 +121,3 @@ STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, U *processedSize = size; return S_OK; } - -STDMETHODIMP CSequentialOutTempBufferImp::WritePart(const void *data, UInt32 size, UInt32 *processedSize) -{ - return Write(data, size, processedSize); -} diff --git a/7zip/Common/InOutTempBuffer.h b/7zip/Common/InOutTempBuffer.h index 97ed56d0..3abe76ec 100755 --- a/7zip/Common/InOutTempBuffer.h +++ b/7zip/Common/InOutTempBuffer.h @@ -33,7 +33,6 @@ public: UInt64 GetDataSize() const { return _fileSize; } bool FlushWrite(); bool InitReading(); - // bool Read(void *data, UInt32 maxSize, UInt32 &processedSize); HRESULT WriteToStream(ISequentialOutStream *stream); }; @@ -51,7 +50,6 @@ public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif diff --git a/7zip/Common/LSBFDecoder.h b/7zip/Common/LSBFDecoder.h index 0fb31a3e..1f5dcb59 100755 --- a/7zip/Common/LSBFDecoder.h +++ b/7zip/Common/LSBFDecoder.h @@ -22,7 +22,7 @@ template class CBaseDecoder { protected: - UInt32 m_BitPos; + int m_BitPos; UInt32 m_Value; TInByte m_Stream; public: @@ -41,7 +41,7 @@ public: { return m_Stream.GetProcessedSize() - (kNumBigValueBits - m_BitPos) / 8; } UInt64 GetProcessedBitsSize() const { return (m_Stream.GetProcessedSize() << 3) - (kNumBigValueBits - m_BitPos); } - UInt32 GetBitPosition() const { return (m_BitPos & 7); } + int GetBitPosition() const { return (m_BitPos & 7); } void Normalize() { @@ -57,7 +57,7 @@ public: } } - UInt32 ReadBits(UInt32 numBits) + UInt32 ReadBits(int numBits) { Normalize(); UInt32 res = m_Value & ((1 << numBits) - 1); @@ -65,12 +65,12 @@ public: m_Value >>= numBits; return res; } - + bool ExtraBitsWereRead() const { if (NumExtraBytes == 0) return false; - return ((kNumBigValueBits - m_BitPos) < (NumExtraBytes << 3)); + return ((UInt32)(kNumBigValueBits - m_BitPos) < (NumExtraBytes << 3)); } }; @@ -101,19 +101,19 @@ public: } } - UInt32 GetValue(UInt32 numBits) + UInt32 GetValue(int numBits) { Normalize(); return ((this->m_Value >> (8 - this->m_BitPos)) & kMask) >> (kNumValueBits - numBits); } - void MovePos(UInt32 numBits) + void MovePos(int numBits) { this->m_BitPos += numBits; m_NormalValue >>= numBits; } - UInt32 ReadBits(UInt32 numBits) + UInt32 ReadBits(int numBits) { Normalize(); UInt32 res = m_NormalValue & ( (1 << numBits) - 1); diff --git a/7zip/Common/LimitedStreams.cpp b/7zip/Common/LimitedStreams.cpp index 6de13c05..c048d49d 100755 --- a/7zip/Common/LimitedStreams.cpp +++ b/7zip/Common/LimitedStreams.cpp @@ -11,8 +11,7 @@ void CLimitedSequentialInStream::Init(ISequentialInStream *stream, UInt64 stream _size = streamSize; } -STDMETHODIMP CLimitedSequentialInStream::Read(void *data, - UInt32 size, UInt32 *processedSize) +STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 processedSizeReal; UInt32 sizeToRead = UInt32(MyMin(_size, UInt64(size))); @@ -22,15 +21,4 @@ STDMETHODIMP CLimitedSequentialInStream::Read(void *data, *processedSize = processedSizeReal; return result; } - -STDMETHODIMP CLimitedSequentialInStream::ReadPart(void *data, UInt32 size, UInt32 *processedSize) -{ - UInt32 processedSizeReal; - UInt32 sizeToRead = UInt32(MyMin(_size, UInt64(size))); - HRESULT result = _stream->ReadPart(data, sizeToRead, &processedSizeReal); - _size -= processedSizeReal; - if(processedSize != NULL) - *processedSize = processedSizeReal; - return result; -} diff --git a/7zip/Common/LimitedStreams.h b/7zip/Common/LimitedStreams.h index 02633bc6..d40be974 100755 --- a/7zip/Common/LimitedStreams.h +++ b/7zip/Common/LimitedStreams.h @@ -18,7 +18,6 @@ public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); }; #endif diff --git a/7zip/Common/LockedStream.cpp b/7zip/Common/LockedStream.cpp index 44af676d..36be1ceb 100755 --- a/7zip/Common/LockedStream.cpp +++ b/7zip/Common/LockedStream.cpp @@ -5,22 +5,13 @@ #include "LockedStream.h" HRESULT CLockedInStream::Read(UInt64 startPos, void *data, UInt32 size, - UInt32 *processedSize) + UInt32 *processedSize) { NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL)); return _stream->Read(data, size, processedSize); } -HRESULT CLockedInStream::ReadPart(UInt64 startPos, void *data, UInt32 size, - UInt32 *processedSize) -{ - NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); - RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL)); - return _stream->ReadPart(data, size, processedSize); -} - - STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; @@ -30,13 +21,3 @@ STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize = realProcessedSize; return result; } - -STDMETHODIMP CLockedSequentialInStreamImp::ReadPart(void *data, UInt32 size, UInt32 *processedSize) -{ - UInt32 realProcessedSize = 0; - HRESULT result = _lockedInStream->ReadPart(_pos, data, size, &realProcessedSize); - _pos += realProcessedSize; - if (processedSize != NULL) - *processedSize = realProcessedSize; - return result; -} diff --git a/7zip/Common/LockedStream.h b/7zip/Common/LockedStream.h index 90f28330..1c1e1793 100755 --- a/7zip/Common/LockedStream.h +++ b/7zip/Common/LockedStream.h @@ -15,7 +15,6 @@ public: void Init(IInStream *stream) { _stream = stream; } HRESULT Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize); - HRESULT ReadPart(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize); }; class CLockedSequentialInStreamImp: @@ -34,7 +33,6 @@ public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); }; #endif diff --git a/7zip/Common/MSBFDecoder.h b/7zip/Common/MSBFDecoder.h index c21d5547..dc80c0f7 100755 --- a/7zip/Common/MSBFDecoder.h +++ b/7zip/Common/MSBFDecoder.h @@ -4,6 +4,9 @@ #ifndef __STREAM_MSBFDECODER_H #define __STREAM_MSBFDECODER_H +#include "../../Common/Types.h" +#include "../IStream.h" + namespace NStream { namespace NMSBF { @@ -16,10 +19,10 @@ const UInt32 kMask = (1 << kNumValueBits) - 1; template class CDecoder { - TInByte m_Stream; UInt32 m_BitPos; UInt32 m_Value; public: + TInByte m_Stream; bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); } void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream);} void ReleaseStream() { m_Stream.ReleaseStream();} diff --git a/7zip/Common/OffsetStream.cpp b/7zip/Common/OffsetStream.cpp index cc93c0db..997ccae2 100755 --- a/7zip/Common/OffsetStream.cpp +++ b/7zip/Common/OffsetStream.cpp @@ -12,17 +12,11 @@ HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset) return _stream->Seek(offset, STREAM_SEEK_SET, NULL); } -STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, - UInt32 *processedSize) +STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { return _stream->Write(data, size, processedSize); } -STDMETHODIMP COffsetOutStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize) -{ - return _stream->WritePart(data, size, processedSize); -} - STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { diff --git a/7zip/Common/OffsetStream.h b/7zip/Common/OffsetStream.h index 20c65452..57a055cc 100755 --- a/7zip/Common/OffsetStream.h +++ b/7zip/Common/OffsetStream.h @@ -18,7 +18,6 @@ public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; diff --git a/7zip/Common/OutBuffer.cpp b/7zip/Common/OutBuffer.cpp index ab4651b4..38827de1 100755 --- a/7zip/Common/OutBuffer.cpp +++ b/7zip/Common/OutBuffer.cpp @@ -32,35 +32,78 @@ void COutBuffer::SetStream(ISequentialOutStream *stream) void COutBuffer::Init() { - _processedSize = 0; + _streamPos = 0; + _limitPos = _bufferSize; _pos = 0; + _processedSize = 0; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } -HRESULT COutBuffer::Flush() -{ - if (_pos == 0) - return S_OK; - UInt32 processedSize; - HRESULT result = _stream->Write(_buffer, _pos, &processedSize); - if (result != S_OK) - return result; - if (_pos != processedSize) - return E_FAIL; - _processedSize += processedSize; - _pos = 0; - return S_OK; +UInt64 COutBuffer::GetProcessedSize() const +{ + UInt64 res = _processedSize + _pos - _streamPos; + if (_streamPos > _pos) + res += _bufferSize; + return res; } -void COutBuffer::WriteBlock() +HRESULT COutBuffer::FlushPart() +{ + UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); + HRESULT result = S_OK; + #ifdef _NO_EXCEPTIONS + if (ErrorCode != S_OK) + result = ErrorCode; + #endif + if (size == 0) + return result; + if (_buffer2 != 0) + { + memmove(_buffer2, _buffer + _streamPos, size); + _buffer2 += size; + } + + if (_stream != 0 + #ifdef _NO_EXCEPTIONS + && (ErrorCode != S_OK) + #endif + ) + { + UInt32 processedSize = 0; + result = _stream->Write(_buffer + _streamPos, size, &processedSize); + size = processedSize; + } + _streamPos += size; + _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; + if (_streamPos == _bufferSize) + _streamPos = 0; + _processedSize += size; + return result; +} + +HRESULT COutBuffer::Flush() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) - return; + return ErrorCode; #endif - HRESULT result = Flush(); + + while(_streamPos != _pos) + { + HRESULT result = FlushPart(); + if (result != S_OK) + return result; + } + return S_OK; +} + +void COutBuffer::FlushWithCheck() +{ + HRESULT result = FlushPart(); + if (_pos == _bufferSize) + _pos = 0; #ifdef _NO_EXCEPTIONS ErrorCode = result; #else diff --git a/7zip/Common/OutBuffer.h b/7zip/Common/OutBuffer.h index b161ad65..51ccb659 100755 --- a/7zip/Common/OutBuffer.h +++ b/7zip/Common/OutBuffer.h @@ -16,48 +16,40 @@ struct COutBufferException class COutBuffer { +protected: Byte *_buffer; UInt32 _pos; + UInt32 _limitPos; + UInt32 _streamPos; UInt32 _bufferSize; CMyComPtr _stream; UInt64 _processedSize; + Byte *_buffer2; - void WriteBlock(); + HRESULT FlushPart(); + void FlushWithCheck(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif - COutBuffer(): _buffer(0), _pos(0), _stream(0) {} + COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} ~COutBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); + void SetMemStream(Byte *buffer) { _buffer2 = buffer; } void SetStream(ISequentialOutStream *stream); void Init(); HRESULT Flush(); void ReleaseStream() { _stream.Release(); } - /* - void *GetBuffer(UInt32 &sizeAvail) - { - sizeAvail = _bufferSize - _pos; - return _buffer + _pos; - } - void MovePos(UInt32 num) - { - _pos += num; - if(_pos >= _bufferSize) - WriteBlock(); - } - */ - void WriteByte(Byte b) { _buffer[_pos++] = b; - if(_pos >= _bufferSize) - WriteBlock(); + if(_pos == _limitPos) + FlushWithCheck(); } void WriteBytes(const void *data, size_t size) { @@ -65,7 +57,7 @@ public: WriteByte(((const Byte *)data)[i]); } - UInt64 GetProcessedSize() const { return _processedSize + _pos; } + UInt64 GetProcessedSize() const; }; #endif diff --git a/7zip/Common/StreamBinder.cpp b/7zip/Common/StreamBinder.cpp index fb4ca59f..2984c2d9 100755 --- a/7zip/Common/StreamBinder.cpp +++ b/7zip/Common/StreamBinder.cpp @@ -17,7 +17,6 @@ public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); private: CStreamBinder *m_StreamBinder; public: @@ -27,9 +26,6 @@ public: STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { return m_StreamBinder->Read(data, size, processedSize); } - -STDMETHODIMP CSequentialInStreamForBinder::ReadPart(void *data, UInt32 size, UInt32 *processedSize) - { return m_StreamBinder->ReadPart(data, size, processedSize); } class CSequentialOutStreamForBinder: public ISequentialOutStream, @@ -39,7 +35,6 @@ public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); private: CStreamBinder *m_StreamBinder; @@ -51,9 +46,6 @@ public: STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { return m_StreamBinder->Write(data, size, processedSize); } -STDMETHODIMP CSequentialOutStreamForBinder::WritePart(const void *data, UInt32 size, UInt32 *processedSize) - { return m_StreamBinder->WritePart(data, size, processedSize); } - ////////////////////////// // CStreamBinder @@ -106,7 +98,7 @@ void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ProcessedSize = 0; } -STDMETHODIMP CStreamBinder::ReadPart(void *data, UInt32 size, UInt32 *processedSize) +HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 sizeToRead = size; if (size > 0) @@ -132,33 +124,12 @@ STDMETHODIMP CStreamBinder::ReadPart(void *data, UInt32 size, UInt32 *processedS return S_OK; } -STDMETHODIMP CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) -{ - UInt32 fullProcessedSize = 0; - UInt32 realProcessedSize; - HRESULT result = S_OK; - while(size > 0) - { - result = ReadPart(data, size, &realProcessedSize); - size -= realProcessedSize; - data = (void *)((Byte *)data + realProcessedSize); - fullProcessedSize += realProcessedSize; - if (result != S_OK) - break; - if (realProcessedSize == 0) - break; - } - if (processedSize != NULL) - *processedSize = fullProcessedSize; - return result; -} - void CStreamBinder::CloseRead() { _readStreamIsClosedEvent->Set(); } -STDMETHODIMP CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) +HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (size > 0) { @@ -184,11 +155,6 @@ STDMETHODIMP CStreamBinder::Write(const void *data, UInt32 size, UInt32 *process return S_OK; } -STDMETHODIMP CStreamBinder::WritePart(const void *data, UInt32 size, UInt32 *processedSize) -{ - return Write(data, size, processedSize); -} - void CStreamBinder::CloseWrite() { // _bufferSize must be = 0 diff --git a/7zip/Common/StreamBinder.h b/7zip/Common/StreamBinder.h index 588713ed..a66c3acb 100755 --- a/7zip/Common/StreamBinder.h +++ b/7zip/Common/StreamBinder.h @@ -26,12 +26,10 @@ public: void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream); - STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); + HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); void CloseRead(); - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); + HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); void CloseWrite(); void ReInit(); }; diff --git a/7zip/Common/StreamObjects.cpp b/7zip/Common/StreamObjects.cpp index 8632cff4..c89f64e1 100755 --- a/7zip/Common/StreamObjects.cpp +++ b/7zip/Common/StreamObjects.cpp @@ -5,45 +5,6 @@ #include "StreamObjects.h" #include "../../Common/Defs.h" -/* -STDMETHODIMP COutStreamImp::Read(void *data, ULONG size, ULONG *processedSize) - { return E_NOTIMPL; } - -STDMETHODIMP COutStreamImp::Write(void const *data, ULONG size, ULONG *processedSize) -{ - size_t newCapacity = _size + size; - _buffer.EnsureCapacity(newCapacity); - memmove(_buffer + _size, data, size); - if(processedSize != NULL) - *processedSize = size; - _size += size; - return S_OK; -} - -void CInStreamImp::Init(Byte *dataPointer, size_t size) -{ - _dataPointer = dataPointer; - _size = size; - _pos = 0; -} - -STDMETHODIMP CInStreamImp::Read(void *data, ULONG size, ULONG *processedSize) -{ - UInt32 numBytesToRead = MyMin(_pos + (UInt32)size, _size) - _pos; - if(processedSize != NULL) - *processedSize = numBytesToRead; - memmove(data, _dataPointer + _pos, numBytesToRead); - _pos += numBytesToRead; - if(numBytesToRead == size) - return S_OK; - else - return S_FALSE; -} - -STDMETHODIMP CInStreamImp::Write(void const *data, ULONG size, ULONG *processedSize) - { return E_NOTIMPL; } -*/ - STDMETHODIMP CSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) { @@ -55,13 +16,6 @@ STDMETHODIMP CSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *proce return S_OK; } -STDMETHODIMP CSequentialInStreamImp::ReadPart(void *data, UInt32 size, UInt32 *processedSize) -{ - return Read(data, size, processedSize); -} - -//////////////////// - void CWriteBuffer::Write(const void *data, size_t size) { @@ -79,11 +33,6 @@ STDMETHODIMP CSequentialOutStreamImp::Write(const void *data, UInt32 size, UInt3 return S_OK; } -STDMETHODIMP CSequentialOutStreamImp::WritePart(const void *data, UInt32 size, UInt32 *processedSize) -{ - return Write(data, size, processedSize); -} - STDMETHODIMP CSequentialOutStreamImp2::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 newSize = size; @@ -98,13 +47,6 @@ STDMETHODIMP CSequentialOutStreamImp2::Write(const void *data, UInt32 size, UInt return S_OK; } -STDMETHODIMP CSequentialOutStreamImp2::WritePart(const void *data, UInt32 size, UInt32 *processedSize) -{ - return Write(data, size, processedSize); -} - - - STDMETHODIMP CSequentialInStreamSizeCount::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; @@ -115,36 +57,7 @@ STDMETHODIMP CSequentialInStreamSizeCount::Read(void *data, UInt32 size, UInt32 return result; } -STDMETHODIMP CSequentialInStreamSizeCount::ReadPart(void *data, UInt32 size, UInt32 *processedSize) -{ - UInt32 realProcessedSize; - HRESULT result = _stream->ReadPart(data, size, &realProcessedSize); - _size += realProcessedSize; - if (processedSize != 0) - *processedSize = realProcessedSize; - return result; -} - STDMETHODIMP CSequentialInStreamRollback::Read(void *data, UInt32 size, UInt32 *processedSize) -{ - HRESULT result = S_OK; - UInt32 realProcessedSizeTotal = 0; - while (size > 0) - { - UInt32 realProcessedSize = 0; - result = ReadPart(data, size, &realProcessedSize); - size -= realProcessedSize; - data = ((Byte *)data + realProcessedSize); - realProcessedSizeTotal += realProcessedSize; - if (realProcessedSize == 0 || result != S_OK) - break; - } - if (processedSize != 0) - *processedSize = realProcessedSizeTotal; - return result; -} - -STDMETHODIMP CSequentialInStreamRollback::ReadPart(void *data, UInt32 size, UInt32 *processedSize) { if (_currentPos != _currentSize) { @@ -160,7 +73,7 @@ STDMETHODIMP CSequentialInStreamRollback::ReadPart(void *data, UInt32 size, UInt UInt32 realProcessedSize; if (size > _bufferSize) size = (UInt32)_bufferSize; - HRESULT result = _stream->ReadPart(_buffer, size, &realProcessedSize); + HRESULT result = _stream->Read(_buffer, size, &realProcessedSize); memmove(data, _buffer, realProcessedSize); _size += realProcessedSize; _currentSize = realProcessedSize; @@ -178,7 +91,6 @@ HRESULT CSequentialInStreamRollback::Rollback(size_t rollbackSize) return S_OK; } - STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; @@ -188,13 +100,3 @@ STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, *processedSize = realProcessedSize; return result; } - -STDMETHODIMP CSequentialOutStreamSizeCount::WritePart(const void *data, UInt32 size, UInt32 *processedSize) -{ - UInt32 realProcessedSize; - HRESULT result = _stream->WritePart(data, size, &realProcessedSize); - _size += realProcessedSize; - if (processedSize != 0) - *processedSize = realProcessedSize; - return result; -} diff --git a/7zip/Common/StreamObjects.h b/7zip/Common/StreamObjects.h index 78e31980..4dd01e47 100755 --- a/7zip/Common/StreamObjects.h +++ b/7zip/Common/StreamObjects.h @@ -7,44 +7,6 @@ #include "../../Common/MyCom.h" #include "../IStream.h" -/* -class COutStreamImp: - public ISequentialStream, - public CMyUnknownImp -{ - CByteDynamicBuffer _buffer; - size_t _size; -public: - COutStreamImp(): _size(0) {} - void Init(){ _size = 0; } - size_t GetSize() const { return _size; } - const CByteDynamicBuffer& GetBuffer() const { return _buffer; } - - MY_UNKNOWN_IMP - - STDMETHODIMP Read(void *data, ULONG size, ULONG *processedSize); - STDMETHODIMP Write(void const *data, ULONG size, ULONG *processedSize); -}; - -class CInStreamImp: - public ISequentialStream, - public CMyUnknownImp -{ - Byte *_dataPointer; - size_t _size; - size_t _pos; - -public: - CInStreamImp(): _size(0xFFFFFFFF), _pos(0), _dataPointer(NULL) {} - void Init(Byte *dataPointer, size_t size); - - MY_UNKNOWN_IMP - - STDMETHODIMP Read(void *data, ULONG size, ULONG *processedSize); - STDMETHODIMP Write(void const *data, ULONG size, ULONG *processedSize); -}; -*/ - class CSequentialInStreamImp: public ISequentialInStream, public CMyUnknownImp @@ -64,7 +26,6 @@ public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); }; @@ -74,15 +35,7 @@ class CWriteBuffer size_t _size; public: CWriteBuffer(): _size(0) {} - // void Init(size_t size = 0) - void Init() - { - /* - if (size > 0) - _buffer.EnsureCapacity(size); - */ - _size = 0; - } + void Init() { _size = 0; } void Write(const void *data, size_t size); size_t GetSize() const { return _size; } const CByteDynamicBuffer& GetBuffer() const { return _buffer; } @@ -94,24 +47,13 @@ class CSequentialOutStreamImp: { CWriteBuffer _writeBuffer; public: - void Init() - { - _writeBuffer.Init(); - } - - /* - void Init(size_t size = 0) - { - _writeBuffer.Init(size); - } - */ + void Init() { _writeBuffer.Init(); } size_t GetSize() const { return _writeBuffer.GetSize(); } const CByteDynamicBuffer& GetBuffer() const { return _writeBuffer.GetBuffer(); } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialOutStreamImp2: @@ -133,7 +75,6 @@ public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialInStreamSizeCount: @@ -153,7 +94,6 @@ public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialInStreamRollback: @@ -191,7 +131,6 @@ public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); HRESULT Rollback(size_t rollbackSize); }; @@ -212,7 +151,6 @@ public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif diff --git a/7zip/Common/StreamUtils.cpp b/7zip/Common/StreamUtils.cpp new file mode 100755 index 00000000..a5d9ac0e --- /dev/null +++ b/7zip/Common/StreamUtils.cpp @@ -0,0 +1,44 @@ +// StreamUtils.cpp + +#include "StdAfx.h" + +#include "../../Common/MyCom.h" +#include "StreamUtils.h" + +HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != 0) + *processedSize = 0; + while(size != 0) + { + UInt32 processedSizeLoc; + HRESULT res = stream->Read(data, size, &processedSizeLoc); + if (processedSize != 0) + *processedSize += processedSizeLoc; + data = (Byte *)((Byte *)data + processedSizeLoc); + size -= processedSizeLoc; + RINOK(res); + if (processedSizeLoc == 0) + return S_OK; + } + return S_OK; +} + +HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != 0) + *processedSize = 0; + while(size != 0) + { + UInt32 processedSizeLoc; + HRESULT res = stream->Write(data, size, &processedSizeLoc); + if (processedSize != 0) + *processedSize += processedSizeLoc; + data = (const void *)((const Byte *)data + processedSizeLoc); + size -= processedSizeLoc; + RINOK(res); + if (processedSizeLoc == 0) + break; + } + return S_OK; +} diff --git a/7zip/Common/StreamUtils.h b/7zip/Common/StreamUtils.h new file mode 100755 index 00000000..59f88733 --- /dev/null +++ b/7zip/Common/StreamUtils.h @@ -0,0 +1,11 @@ +// StreamUtils.h + +#ifndef __STREAMUTILS_H +#define __STREAMUTILS_H + +#include "../IStream.h" + +HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize); +HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize); + +#endif diff --git a/7zip/Compress/Arj/Decoder1.cpp b/7zip/Compress/Arj/ArjDecoder1.cpp similarity index 99% rename from 7zip/Compress/Arj/Decoder1.cpp rename to 7zip/Compress/Arj/ArjDecoder1.cpp index b9f2881c..a560f443 100755 --- a/7zip/Compress/Arj/Decoder1.cpp +++ b/7zip/Compress/Arj/ArjDecoder1.cpp @@ -2,7 +2,7 @@ #include "StdAfx.h" -#include "Decoder1.h" +#include "ArjDecoder1.h" #include "Windows/Defs.h" diff --git a/7zip/Compress/Arj/Decoder1.h b/7zip/Compress/Arj/ArjDecoder1.h similarity index 100% rename from 7zip/Compress/Arj/Decoder1.h rename to 7zip/Compress/Arj/ArjDecoder1.h diff --git a/7zip/Compress/Arj/Decoder2.cpp b/7zip/Compress/Arj/ArjDecoder2.cpp similarity index 98% rename from 7zip/Compress/Arj/Decoder2.cpp rename to 7zip/Compress/Arj/ArjDecoder2.cpp index ab6c57fa..1fb20649 100755 --- a/7zip/Compress/Arj/Decoder2.cpp +++ b/7zip/Compress/Arj/ArjDecoder2.cpp @@ -2,7 +2,7 @@ #include "StdAfx.h" -#include "Decoder2.h" +#include "ArjDecoder2.h" namespace NCompress{ namespace NArj { diff --git a/7zip/Compress/Arj/Decoder2.h b/7zip/Compress/Arj/ArjDecoder2.h similarity index 100% rename from 7zip/Compress/Arj/Decoder2.h rename to 7zip/Compress/Arj/ArjDecoder2.h diff --git a/7zip/Compress/BZip2/BZip2CRC.cpp b/7zip/Compress/BZip2/BZip2CRC.cpp index d3ca5e15..ba9ddb7e 100755 --- a/7zip/Compress/BZip2/BZip2CRC.cpp +++ b/7zip/Compress/BZip2/BZip2CRC.cpp @@ -23,4 +23,4 @@ class CBZip2CRCTableInit { public: CBZip2CRCTableInit() { CBZip2CRC::InitTable(); } -} g_CRCTableInit; +} g_BZip2CRCTableInit; diff --git a/7zip/Compress/BZip2/BZip2Decoder.cpp b/7zip/Compress/BZip2/BZip2Decoder.cpp index e620f027..0f0fbbfa 100755 --- a/7zip/Compress/BZip2/BZip2Decoder.cpp +++ b/7zip/Compress/BZip2/BZip2Decoder.cpp @@ -174,7 +174,8 @@ HRESULT CDecoder::ReadBlock(UInt32 blockSizeMax, CState &state) } for (; i < kMaxAlphaSize; i++) lens[i] = 0; - m_HuffmanDecoders[t].SetCodeLengths(lens); + if(!m_HuffmanDecoders[t].SetCodeLengths(lens)) + return S_FALSE; } while(++t < numTables); @@ -202,7 +203,7 @@ HRESULT CDecoder::ReadBlock(UInt32 blockSizeMax, CState &state) } groupSize--; \ - int nextSym = (int)huffmanDecoder->DecodeSymbol(&m_InStream); + UInt32 nextSym = huffmanDecoder->DecodeSymbol(&m_InStream); if (nextSym < 2) { @@ -220,13 +221,18 @@ HRESULT CDecoder::ReadBlock(UInt32 blockSizeMax, CState &state) while(--runCounter != 0); runPower = 0; } - if (nextSym > numInUse) + if (nextSym <= (UInt32)numInUse) + { + Byte b = mtf.GetAndMove((int)nextSym - 1); + if (blockSize >= blockSizeMax) + return S_FALSE; + state.CharCounters[b]++; + state.tt[blockSize++] = (UInt32)b; + } + else if (nextSym == (UInt32)numInUse + 1) break; - Byte b = mtf.GetAndMove(nextSym - 1); - if (blockSize >= blockSizeMax) + else return S_FALSE; - state.CharCounters[b]++; - state.tt[blockSize++] = (UInt32)b; } } if (state.OrigPtr >= blockSize) diff --git a/7zip/Compress/Branch/x86_2.cpp b/7zip/Compress/Branch/x86_2.cpp index 2f67899f..00f1ea7a 100755 --- a/7zip/Compress/Branch/x86_2.cpp +++ b/7zip/Compress/Branch/x86_2.cpp @@ -102,7 +102,6 @@ HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams, UInt32 nowPos = 0; UInt64 nowPos64 = 0; UInt32 bufferPos = 0; - UInt32 processedSize; Byte prevByte = 0; @@ -112,8 +111,18 @@ HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams, while(true) { - UInt32 size = kBufferSize - bufferPos; - RINOK(inStream->Read(_buffer + bufferPos, size, &processedSize)); + UInt32 processedSize = 0; + while(true) + { + UInt32 size = kBufferSize - (bufferPos + processedSize); + UInt32 processedSizeLoc; + if (size == 0) + break; + RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc)); + if (processedSizeLoc == 0) + break; + processedSize += processedSizeLoc; + } UInt32 endPos = bufferPos + processedSize; if (endPos < 5) diff --git a/7zip/Compress/Copy/Copy.dsp b/7zip/Compress/Copy/Copy.dsp index ddf4d66b..099a433d 100755 --- a/7zip/Compress/Copy/Copy.dsp +++ b/7zip/Compress/Copy/Copy.dsp @@ -125,6 +125,18 @@ SOURCE=..\..\..\Common\Alloc.cpp SOURCE=..\..\..\Common\Alloc.h # End Source File # End Group +# Begin Group "7-Zip Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File +# End Group # Begin Source File SOURCE=.\CopyCoder.cpp diff --git a/7zip/Compress/Copy/CopyCoder.cpp b/7zip/Compress/Copy/CopyCoder.cpp index d8c7635b..dac68711 100755 --- a/7zip/Compress/Copy/CopyCoder.cpp +++ b/7zip/Compress/Copy/CopyCoder.cpp @@ -4,6 +4,7 @@ #include "CopyCoder.h" #include "../../../Common/Alloc.h" +#include "../../Common/StreamUtils.h" namespace NCompress { @@ -34,10 +35,10 @@ STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, if (outSize != 0) if (size > *outSize - TotalSize) size = (UInt32)(*outSize - TotalSize); - RINOK(inStream->ReadPart(_buffer, size, &realProcessedSize)); + RINOK(inStream->Read(_buffer, size, &realProcessedSize)); if(realProcessedSize == 0) break; - RINOK(outStream->Write(_buffer, realProcessedSize, NULL)); + RINOK(WriteStream(outStream, _buffer, realProcessedSize, NULL)); TotalSize += realProcessedSize; if (progress != NULL) { diff --git a/7zip/Compress/Copy/makefile b/7zip/Compress/Copy/makefile index 6c04af97..8c108fbc 100755 --- a/7zip/Compress/Copy/makefile +++ b/7zip/Compress/Copy/makefile @@ -10,10 +10,14 @@ COPY_OBJS = \ COMMON_OBJS = \ $O\Alloc.obj \ +7ZIP_COMMON_OBJS = \ + $O\StreamUtils.obj \ + OBJS = \ $O\StdAfx.obj \ $(COPY_OBJS) \ $(COMMON_OBJS) \ + $(7ZIP_COMMON_OBJS) \ $O\resource.res !include "../../../Build.mak" @@ -22,3 +26,5 @@ $(COPY_OBJS): $(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) diff --git a/7zip/Compress/Deflate/DeflateDecoder.cpp b/7zip/Compress/Deflate/DeflateDecoder.cpp index 96da47b3..16369326 100755 --- a/7zip/Compress/Deflate/DeflateDecoder.cpp +++ b/7zip/Compress/Deflate/DeflateDecoder.cpp @@ -8,7 +8,10 @@ namespace NCompress { namespace NDeflate { namespace NDecoder { -CCoder::CCoder(bool deflate64Mode): _deflate64Mode(deflate64Mode) {} +const int kLenIdFinished = -1; +const int kLenIdNeedInit = -2; + +CCoder::CCoder(bool deflate64Mode): _deflate64Mode(deflate64Mode), _keepHistory(false) {} void CCoder::DeCodeLevelTable(Byte *newLevels, int numLevels) { @@ -40,211 +43,256 @@ void CCoder::DeCodeLevelTable(Byte *newLevels, int numLevels) } } -void CCoder::ReadTables(void) +#define RIF(x) { if (!(x)) return false; } + +bool CCoder::ReadTables(void) { - if(m_FinalBlock) // test it - throw CException(CException::kData); - m_FinalBlock = (m_InBitStream.ReadBits(kFinalBlockFieldSize) == NFinalBlockField::kFinalBlock); - int blockType = m_InBitStream.ReadBits(kBlockTypeFieldSize); + if (blockType > NBlockType::kDynamicHuffman) + return false; - switch(blockType) + if (blockType == NBlockType::kStored) { - case NBlockType::kStored: - { - m_StoredMode = true; - UInt32 currentBitPosition = m_InBitStream.GetBitPosition(); - UInt32 numBitsForAlign = currentBitPosition > 0 ? (8 - currentBitPosition): 0; - if (numBitsForAlign > 0) - m_InBitStream.ReadBits(numBitsForAlign); - m_StoredBlockSize = m_InBitStream.ReadBits(kDeflateStoredBlockLengthFieldSizeSize); - UInt16 onesComplementReverse = ~(UInt16)(m_InBitStream.ReadBits(kDeflateStoredBlockLengthFieldSizeSize)); - if (m_StoredBlockSize != onesComplementReverse) - throw CException(CException::kData); - break; - } - case NBlockType::kFixedHuffman: - case NBlockType::kDynamicHuffman: - { - m_StoredMode = false; - Byte litLenLevels[kStaticMainTableSize]; - Byte distLevels[kStaticDistTableSize]; - if (blockType == NBlockType::kFixedHuffman) - { - int i; - - // Leteral / length levels - for (i = 0; i < 144; i++) - litLenLevels[i] = 8; - for (; i < 256; i++) - litLenLevels[i] = 9; - for (; i < 280; i++) - litLenLevels[i] = 7; - for (; i < 288; i++) /* make a complete, but wrong code set */ - litLenLevels[i] = 8; - - // Distance levels - for (i = 0; i < kStaticDistTableSize; i++) // test it: infozip only use kDistTableSize - distLevels[i] = 5; - } - else // in case when (blockType == kDeflateBlockTypeFixedHuffman) - { - int numLitLenLevels = m_InBitStream.ReadBits(kDeflateNumberOfLengthCodesFieldSize) + - kDeflateNumberOfLitLenCodesMin; - int numDistLevels = m_InBitStream.ReadBits(kDeflateNumberOfDistanceCodesFieldSize) + - kDeflateNumberOfDistanceCodesMin; - int numLevelCodes = m_InBitStream.ReadBits(kDeflateNumberOfLevelCodesFieldSize) + - kDeflateNumberOfLevelCodesMin; - - int numLevels = _deflate64Mode ? kHeapTablesSizesSum64 : - kHeapTablesSizesSum32; - - Byte levelLevels[kLevelTableSize]; - int i; - for (i = 0; i < kLevelTableSize; i++) - { - int position = kCodeLengthAlphabetOrder[i]; - if(i < numLevelCodes) - levelLevels[position] = Byte(m_InBitStream.ReadBits(kDeflateLevelCodeFieldSize)); - else - levelLevels[position] = 0; - } - - try - { - m_LevelDecoder.SetCodeLengths(levelLevels); - } - catch(...) - { - throw CException(CException::kData); - } - - Byte tmpLevels[kStaticMaxTableSize]; - DeCodeLevelTable(tmpLevels, numLitLenLevels + numDistLevels); - - memmove(litLenLevels, tmpLevels, numLitLenLevels); - memset(litLenLevels + numLitLenLevels, 0, - kStaticMainTableSize - numLitLenLevels); - - memmove(distLevels, tmpLevels + numLitLenLevels, numDistLevels); - memset(distLevels + numDistLevels, 0, kStaticDistTableSize - numDistLevels); - } - try - { - m_MainDecoder.SetCodeLengths(litLenLevels); - m_DistDecoder.SetCodeLengths(distLevels); - } - catch(...) - { - throw CException(CException::kData); - } - break; - } - default: - throw CException(CException::kData); + m_StoredMode = true; + UInt32 currentBitPosition = m_InBitStream.GetBitPosition(); + UInt32 numBitsForAlign = currentBitPosition > 0 ? (8 - currentBitPosition): 0; + if (numBitsForAlign > 0) + m_InBitStream.ReadBits(numBitsForAlign); + m_StoredBlockSize = m_InBitStream.ReadBits(kDeflateStoredBlockLengthFieldSizeSize); + UInt16 onesComplementReverse = ~(UInt16)(m_InBitStream.ReadBits(kDeflateStoredBlockLengthFieldSizeSize)); + return (m_StoredBlockSize == onesComplementReverse); } + + m_StoredMode = false; + Byte litLenLevels[kStaticMainTableSize]; + Byte distLevels[kStaticDistTableSize]; + if (blockType == NBlockType::kFixedHuffman) + { + int i; + + for (i = 0; i < 144; i++) + litLenLevels[i] = 8; + for (; i < 256; i++) + litLenLevels[i] = 9; + for (; i < 280; i++) + litLenLevels[i] = 7; + for (; i < 288; i++) // make a complete, but wrong code set + litLenLevels[i] = 8; + + for (i = 0; i < kStaticDistTableSize; i++) // test it: InfoZip only uses kDistTableSize + distLevels[i] = 5; + } + else // (blockType == kDynamicHuffman) + { + int numLitLenLevels = m_InBitStream.ReadBits(kDeflateNumberOfLengthCodesFieldSize) + + kDeflateNumberOfLitLenCodesMin; + int numDistLevels = m_InBitStream.ReadBits(kDeflateNumberOfDistanceCodesFieldSize) + + kDeflateNumberOfDistanceCodesMin; + int numLevelCodes = m_InBitStream.ReadBits(kDeflateNumberOfLevelCodesFieldSize) + + kDeflateNumberOfLevelCodesMin; + + int numLevels = _deflate64Mode ? kHeapTablesSizesSum64 : kHeapTablesSizesSum32; + + Byte levelLevels[kLevelTableSize]; + for (int i = 0; i < kLevelTableSize; i++) + { + int position = kCodeLengthAlphabetOrder[i]; + if(i < numLevelCodes) + levelLevels[position] = Byte(m_InBitStream.ReadBits(kDeflateLevelCodeFieldSize)); + else + levelLevels[position] = 0; + } + + RIF(m_LevelDecoder.SetCodeLengths(levelLevels)); + + Byte tmpLevels[kStaticMaxTableSize]; + DeCodeLevelTable(tmpLevels, numLitLenLevels + numDistLevels); + + memmove(litLenLevels, tmpLevels, numLitLenLevels); + memset(litLenLevels + numLitLenLevels, 0, kStaticMainTableSize - numLitLenLevels); + + memmove(distLevels, tmpLevels + numLitLenLevels, numDistLevels); + memset(distLevels + numDistLevels, 0, kStaticDistTableSize - numDistLevels); + } + RIF(m_MainDecoder.SetCodeLengths(litLenLevels)); + return m_DistDecoder.SetCodeLengths(distLevels); } -HRESULT CCoder::CodeReal(ISequentialInStream *inStream, - ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, - ICompressProgressInfo *progress) +HRESULT CCoder::CodeSpec(UInt32 curSize) { - if (!m_OutWindowStream.Create(_deflate64Mode ? kHistorySize64: kHistorySize32)) - return E_OUTOFMEMORY; - if (!m_InBitStream.Create(1 << 17)) - return E_OUTOFMEMORY; - UInt64 pos = 0; - m_OutWindowStream.SetStream(outStream); - m_OutWindowStream.Init(false); - m_InBitStream.SetStream(inStream); - m_InBitStream.Init(); - CCoderReleaser coderReleaser(this); - - m_FinalBlock = false; - - while(!m_FinalBlock) + if (_remainLen == kLenIdFinished) + return S_OK; + if (_remainLen == kLenIdNeedInit) { - if (progress != NULL) + if (!_keepHistory) { - UInt64 packSize = m_InBitStream.GetProcessedSize(); - RINOK(progress->SetRatioInfo(&packSize, &pos)); + if (!m_OutWindowStream.Create(_deflate64Mode ? kHistorySize64: kHistorySize32)) + return E_OUTOFMEMORY; } - ReadTables(); + if (!m_InBitStream.Create(1 << 17)) + return E_OUTOFMEMORY; + m_OutWindowStream.Init(_keepHistory); + m_InBitStream.Init(); + m_FinalBlock = false; + _remainLen = 0; + _needReadTable = true; + } + + if (curSize == 0) + return S_OK; + + while(_remainLen > 0 && curSize > 0) + { + _remainLen--; + Byte b = m_OutWindowStream.GetByte(_rep0); + m_OutWindowStream.PutByte(b); + curSize--; + } + + while(curSize > 0) + { + if (_needReadTable) + { + if (m_FinalBlock) + { + _remainLen = kLenIdFinished; + break; + } + if (!ReadTables()) + return S_FALSE; + _needReadTable = false; + } + if(m_StoredMode) { - for (UInt32 i = 0; i < m_StoredBlockSize; i++) - m_OutWindowStream.PutByte(Byte(m_InBitStream.ReadBits(8))); - pos += m_StoredBlockSize; + for (; m_StoredBlockSize > 0 && curSize > 0; m_StoredBlockSize--, curSize--) + m_OutWindowStream.PutByte((Byte)m_InBitStream.ReadBits(8)); + _needReadTable = (m_StoredBlockSize == 0); continue; } - while(true) + while(curSize > 0) { if (m_InBitStream.NumExtraBytes > 4) - throw CException(CException::kData); + return S_FALSE; UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream); if (number < 256) { - if (outSize != NULL) - if (pos >= *outSize) - throw CException(CException::kData); - m_OutWindowStream.PutByte(Byte(number)); - pos++; + m_OutWindowStream.PutByte((Byte)number); + curSize--; continue; } else if (number >= kMatchNumber) { - if (outSize != NULL) - if (pos >= *outSize) - throw CException(CException::kData); number -= kMatchNumber; - - UInt32 length; - if (_deflate64Mode) + UInt32 len; { - length = UInt32(kLenStart64[number]) + kMatchMinLen; - UInt32 numBits = kLenDirectBits64[number]; - if (numBits > 0) - length += m_InBitStream.ReadBits(numBits); + int numBits; + if (_deflate64Mode) + { + len = kLenStart64[number]; + numBits = kLenDirectBits64[number]; + } + else + { + len = kLenStart32[number]; + numBits = kLenDirectBits32[number]; + } + len += kMatchMinLen + m_InBitStream.ReadBits(numBits); } - else - { - length = UInt32(kLenStart32[number]) + kMatchMinLen; - UInt32 numBits = kLenDirectBits32[number]; - if (numBits > 0) - length += m_InBitStream.ReadBits(numBits); - } - - + UInt32 locLen = len; + if (locLen > curSize) + locLen = (UInt32)curSize; number = m_DistDecoder.DecodeSymbol(&m_InBitStream); + if (number >= kStaticDistTableSize) + return S_FALSE; UInt32 distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]); - if (distance >= pos) - throw "data error"; - m_OutWindowStream.CopyBlock(distance, length); - pos += length; + if (!m_OutWindowStream.CopyBlock(distance, locLen)) + return S_FALSE; + curSize -= locLen; + len -= locLen; + if (len != 0) + { + _remainLen = (int)len; + _rep0 = distance; + break; + } } else if (number == kReadTableNumber) + { + _needReadTable = true; break; + } else - throw CException(CException::kData); + return S_FALSE; } } - coderReleaser.NeedFlush = false; - return m_OutWindowStream.Flush(); + return S_OK; } -HRESULT CCoder::BaseCode(ISequentialInStream *inStream, +HRESULT CCoder::CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + SetInStream(inStream); + m_OutWindowStream.SetStream(outStream); + SetOutStreamSize(outSize); + CCoderReleaser flusher(this); + + const UInt64 start = m_OutWindowStream.GetProcessedSize(); + while(true) + { + UInt32 curSize = 1 << 18; + if (outSize != 0) + { + const UInt64 rem = *outSize - (m_OutWindowStream.GetProcessedSize() - start); + if (curSize > rem) + curSize = (UInt32)rem; + } + if (curSize == 0) + break; + RINOK(CodeSpec(curSize)); + if (_remainLen == kLenIdFinished) + break; + if (progress != NULL) + { + UInt64 inSize = m_InBitStream.GetProcessedSize(); + UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start; + RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); + } + } + flusher.NeedFlush = false; + return Flush(); +} + + +#ifdef _NO_EXCEPTIONS + +#define DEFLATE_TRY_BEGIN +#define DEFLATE_TRY_END + +#else + +#define DEFLATE_TRY_BEGIN try { +#define DEFLATE_TRY_END } \ + catch(const CInBufferException &e) { return e.ErrorCode; } \ + catch(const CLZOutWindowException &e) { return e.ErrorCode; } \ + catch(...) { return S_FALSE; } + +#endif + +HRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { - try { return CodeReal(inStream, outStream, inSize, outSize, progress); } - catch(const CInBufferException &e) { return e.ErrorCode; } - catch(const CLZOutWindowException &e) { return e.ErrorCode; } - catch(...) { return S_FALSE; } + DEFLATE_TRY_BEGIN + return CodeReal(inStream, outStream, inSize, outSize, progress); + DEFLATE_TRY_END } -HRESULT CCoder::BaseGetInStreamProcessedSize(UInt64 *value) +STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value) { if (value == NULL) return E_INVALIDARG; @@ -252,29 +300,41 @@ HRESULT CCoder::BaseGetInStreamProcessedSize(UInt64 *value) return S_OK; } -STDMETHODIMP CCOMCoder::GetInStreamProcessedSize(UInt64 *value) +STDMETHODIMP CCoder::SetInStream(ISequentialInStream *inStream) { - return BaseGetInStreamProcessedSize(value); + m_InBitStream.SetStream(inStream); + return S_OK; } -HRESULT CCOMCoder::Code(ISequentialInStream *inStream, - ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, - ICompressProgressInfo *progress) +STDMETHODIMP CCoder::ReleaseInStream() { - return BaseCode(inStream, outStream, inSize, outSize, progress); + m_InBitStream.ReleaseStream(); + return S_OK; } -STDMETHODIMP CCOMCoder64::GetInStreamProcessedSize(UInt64 *value) +STDMETHODIMP CCoder::SetOutStreamSize(const UInt64 *outSize) { - return BaseGetInStreamProcessedSize(value); + _remainLen = kLenIdNeedInit; + m_OutWindowStream.Init(_keepHistory); + return S_OK; } -HRESULT CCOMCoder64::Code(ISequentialInStream *inStream, - ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, - ICompressProgressInfo *progress) +#ifdef _ST_MODE + +STDMETHODIMP CCoder::Read(void *data, UInt32 size, UInt32 *processedSize) { - return BaseCode(inStream, outStream, inSize, outSize, progress); + DEFLATE_TRY_BEGIN + if (processedSize) + *processedSize = 0; + const UInt64 startPos = m_OutWindowStream.GetProcessedSize(); + m_OutWindowStream.SetMemStream((Byte *)data); + RINOK(CodeSpec(size)); + if (processedSize) + *processedSize = (UInt32)(m_OutWindowStream.GetProcessedSize() - startPos); + return Flush(); + DEFLATE_TRY_END } +#endif }}} diff --git a/7zip/Compress/Deflate/DeflateDecoder.h b/7zip/Compress/Deflate/DeflateDecoder.h index b1be0084..628af839 100755 --- a/7zip/Compress/Deflate/DeflateDecoder.h +++ b/7zip/Compress/Deflate/DeflateDecoder.h @@ -30,7 +30,15 @@ public: typedef NStream::NLSBF::CDecoder CInBit; -class CCoder +class CCoder: + public ICompressCoder, + public ICompressGetInStreamProcessedSize, + #ifdef _ST_MODE + public ICompressSetInStream, + public ICompressSetOutStreamSize, + public ISequentialInStream, + #endif + public CMyUnknownImp { CLZOutWindow m_OutWindowStream; CInBit m_InBitStream; @@ -38,20 +46,27 @@ class CCoder NCompress::NHuffman::CDecoder m_DistDecoder; NCompress::NHuffman::CDecoder m_LevelDecoder; - bool m_FinalBlock; - bool m_StoredMode; UInt32 m_StoredBlockSize; + bool m_FinalBlock; + bool m_StoredMode; bool _deflate64Mode; + bool _keepHistory; + int _remainLen; + UInt32 _rep0; + bool _needReadTable; + void DeCodeLevelTable(Byte *newLevels, int numLevels); - void ReadTables(); + bool ReadTables(); void CCoder::ReleaseStreams() { m_OutWindowStream.ReleaseStream(); - m_InBitStream.ReleaseStream(); + ReleaseInStream(); } + + HRESULT Flush() { return m_OutWindowStream.Flush(); } class CCoderReleaser { CCoder *m_Coder; @@ -61,63 +76,60 @@ class CCoder ~CCoderReleaser() { if (NeedFlush) - m_Coder->m_OutWindowStream.Flush(); + m_Coder->Flush(); m_Coder->ReleaseStreams(); } }; friend class CCoderReleaser; + HRESULT CodeSpec(UInt32 curSize); public: - CCoder(bool deflate64Mode = false); + CCoder(bool deflate64Mode); + void SetKeepHistory(bool keepHistory) { _keepHistory = keepHistory; } HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); - HRESULT BaseCode(ISequentialInStream *inStream, - ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, - ICompressProgressInfo *progress); - - // IGetInStreamProcessedSize - HRESULT BaseGetInStreamProcessedSize(UInt64 *aValue); -}; - -class CCOMCoder : - public ICompressCoder, - public ICompressGetInStreamProcessedSize, - public CMyUnknownImp, - public CCoder -{ -public: - - MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize) + #ifdef _ST_MODE + MY_UNKNOWN_IMP4( + ICompressGetInStreamProcessedSize, + ICompressSetInStream, + ICompressSetOutStreamSize, + ISequentialInStream + ) + #else + MY_UNKNOWN_IMP1( + ICompressGetInStreamProcessedSize) + #endif STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); - // IGetInStreamProcessedSize - STDMETHOD(GetInStreamProcessedSize)(UInt64 *aValue); + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + + #ifdef _ST_MODE + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + #endif + // IGetInStreamProcessedSize + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); +}; + +class CCOMCoder : + public CCoder +{ +public: CCOMCoder(): CCoder(false) {} }; class CCOMCoder64 : - public ICompressCoder, - public ICompressGetInStreamProcessedSize, - public CMyUnknownImp, public CCoder { public: - MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize) - - STDMETHOD(Code)(ISequentialInStream *inStream, - ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, - ICompressProgressInfo *progress); - - // IGetInStreamProcessedSize - STDMETHOD(GetInStreamProcessedSize)(UInt64 *aValue); - CCOMCoder64(): CCoder(true) {} }; diff --git a/7zip/Compress/Huffman/HuffmanDecoder.h b/7zip/Compress/Huffman/HuffmanDecoder.h index c956869e..57115197 100755 --- a/7zip/Compress/Huffman/HuffmanDecoder.h +++ b/7zip/Compress/Huffman/HuffmanDecoder.h @@ -8,86 +8,81 @@ namespace NCompress { namespace NHuffman { -class CDecoderException{}; +const int kNumTableBits = 9; -const UInt32 kValueTableBits = 9; - -template +template class CDecoder { - UInt32 m_Limits[kNumBitsInLongestCode + 1]; // m_Limits[i] = value limit for symbols with length = i - UInt32 m_Positions[kNumBitsInLongestCode + 1]; // m_Positions[i] = index in m_Symbols[] of first symbol with length = i - UInt32 m_Symbols[m_NumSymbols]; // symbols: at first with len = 1 then 2, ... 15. - Byte m_Lengths[1 << kValueTableBits]; + UInt32 m_Limits[kNumBitsMax + 1]; // m_Limits[i] = value limit for symbols with length = i + UInt32 m_Positions[kNumBitsMax + 1]; // m_Positions[i] = index in m_Symbols[] of first symbol with length = i + UInt32 m_Symbols[m_NumSymbols]; + Byte m_Lengths[1 << kNumTableBits]; // Table oh length for short codes. + public: - void SetCodeLengths(const Byte *codeLengths); + + bool SetCodeLengths(const Byte *codeLengths) + { + int lenCounts[kNumBitsMax + 1], tmpPositions[kNumBitsMax + 1]; + int i; + for(i = 1; i <= kNumBitsMax; i++) + lenCounts[i] = 0; + UInt32 symbol; + for (symbol = 0; symbol < m_NumSymbols; symbol++) + { + int len = codeLengths[symbol]; + if (len > kNumBitsMax) + return false; + lenCounts[len]++; + m_Symbols[symbol] = 0xFFFFFFFF; + } + lenCounts[0] = 0; + m_Positions[0] = m_Limits[0] = 0; + UInt32 startPos = 0; + UInt32 index = 0; + const UInt32 kMaxValue = (1 << kNumBitsMax); + for (i = 1; i <= kNumBitsMax; i++) + { + startPos += lenCounts[i] << (kNumBitsMax - i); + if (startPos > kMaxValue) + return false; + m_Limits[i] = (i == kNumBitsMax) ? kMaxValue : startPos; + m_Positions[i] = m_Positions[i - 1] + lenCounts[i - 1]; + tmpPositions[i] = m_Positions[i]; + if(i <= kNumTableBits) + { + UInt32 limit = (m_Limits[i] >> (kNumBitsMax - kNumTableBits)); + for (; index < limit; index++) + m_Lengths[index] = (Byte)i; + } + } + for (symbol = 0; symbol < m_NumSymbols; symbol++) + { + int len = codeLengths[symbol]; + if (len != 0) + m_Symbols[tmpPositions[len]++] = symbol; + } + return true; + } + template UInt32 DecodeSymbol(TBitDecoder *bitStream) { - UInt32 numBits; - - UInt32 value = bitStream->GetValue(kNumBitsInLongestCode); - - if (value < m_Limits[kValueTableBits]) - numBits = m_Lengths[value >> (kNumBitsInLongestCode - kValueTableBits)]; + int numBits; + UInt32 value = bitStream->GetValue(kNumBitsMax); + if (value < m_Limits[kNumTableBits]) + numBits = m_Lengths[value >> (kNumBitsMax - kNumTableBits)]; else - for (numBits = kValueTableBits + 1; numBits < kNumBitsInLongestCode; numBits++) - if (value < m_Limits[numBits]) - break; + for (numBits = kNumTableBits + 1; value >= m_Limits[numBits]; numBits++); bitStream->MovePos(numBits); UInt32 index = m_Positions[numBits] + - ((value - m_Limits[numBits - 1]) >> (kNumBitsInLongestCode - numBits)); + ((value - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits)); if (index >= m_NumSymbols) - throw CDecoderException(); // test it + // throw CDecoderException(); // test it + return 0xFFFFFFFF; return m_Symbols[index]; } }; -template -void CDecoder::SetCodeLengths(const Byte *codeLengths) -{ - int lenCounts[kNumBitsInLongestCode + 1], tmpPositions[kNumBitsInLongestCode + 1]; - int i; - for(i = 1; i <= kNumBitsInLongestCode; i++) - lenCounts[i] = 0; - UInt32 symbol; - for (symbol = 0; symbol < m_NumSymbols; symbol++) - { - Byte codeLength = codeLengths[symbol]; - if (codeLength > kNumBitsInLongestCode) - throw CDecoderException(); - lenCounts[codeLength]++; - } - lenCounts[0] = 0; - tmpPositions[0] = m_Positions[0] = m_Limits[0] = 0; - UInt32 startPos = 0; - UInt32 index = 0; - const UInt32 kMaxValue = (1 << kNumBitsInLongestCode); - for (i = 1; i <= kNumBitsInLongestCode; i++) - { - startPos += lenCounts[i] << (kNumBitsInLongestCode - i); - if (startPos > kMaxValue) - throw CDecoderException(); - m_Limits[i] = startPos; - m_Positions[i] = m_Positions[i - 1] + lenCounts[i - 1]; - tmpPositions[i] = m_Positions[i]; - - if(i <= kValueTableBits) - { - UInt32 limit = (m_Limits[i] >> (kNumBitsInLongestCode - kValueTableBits)); // change it - memset(m_Lengths + index, Byte(i), limit - index); - index = limit; - } - } - - // if (startPos != kMaxValue) - // throw CDecoderException(); - - for (symbol = 0; symbol < m_NumSymbols; symbol++) - if (codeLengths[symbol] != 0) - m_Symbols[tmpPositions[codeLengths[symbol]]++] = symbol; -} - }} #endif diff --git a/7zip/Compress/Implode/ImplodeDecoder.cpp b/7zip/Compress/Implode/ImplodeDecoder.cpp index d8b5daea..b7689f62 100755 --- a/7zip/Compress/Implode/ImplodeDecoder.cpp +++ b/7zip/Compress/Implode/ImplodeDecoder.cpp @@ -74,7 +74,7 @@ void CCoder::ReleaseStreams() m_InBitStream.ReleaseStream(); } -void CCoder::ReadLevelItems(NImplode::NHuffman::CDecoder &decoder, +bool CCoder::ReadLevelItems(NImplode::NHuffman::CDecoder &decoder, Byte *levels, int numLevelItems) { int numCodedStructures = m_InBitStream.ReadBits(kNumBitsInByte) + @@ -92,32 +92,26 @@ void CCoder::ReadLevelItems(NImplode::NHuffman::CDecoder &decoder, levels[currentIndex++] = level; } if (currentIndex != numLevelItems) - throw CException(CException::kData); - try - { - decoder.SetCodeLengths(levels); - } - catch(const NImplode::NHuffman::CDecoderException &) - { - throw CException(CException::kData); - } + return false; + return decoder.SetCodeLengths(levels); } -void CCoder::ReadTables(void) +bool CCoder::ReadTables(void) { if (m_LiteralsOn) { Byte literalLevels[kLiteralTableSize]; - ReadLevelItems(m_LiteralDecoder, literalLevels, kLiteralTableSize); + if (!ReadLevelItems(m_LiteralDecoder, literalLevels, kLiteralTableSize)) + return false; } Byte lengthLevels[kLengthTableSize]; - ReadLevelItems(m_LengthDecoder, lengthLevels, kLengthTableSize); + if (!ReadLevelItems(m_LengthDecoder, lengthLevels, kLengthTableSize)) + return false; Byte distanceLevels[kDistanceTableSize]; - ReadLevelItems(m_DistanceDecoder, distanceLevels, kDistanceTableSize); - + return ReadLevelItems(m_DistanceDecoder, distanceLevels, kDistanceTableSize); } class CCoderReleaser @@ -146,7 +140,8 @@ STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream, m_InBitStream.Init(); CCoderReleaser coderReleaser(this); - ReadTables(); + if (!ReadTables()) + return S_FALSE; while(pos < unPackSize) { @@ -158,10 +153,13 @@ STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream, if(m_InBitStream.ReadBits(1) == kMatchId) // match { UInt32 lowDistBits = m_InBitStream.ReadBits(m_NumDistanceLowDirectBits); - UInt32 distance = (m_DistanceDecoder.DecodeSymbol(&m_InBitStream) << - m_NumDistanceLowDirectBits) + lowDistBits; - + 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); @@ -177,8 +175,16 @@ STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream, } else { - Byte b = Byte(m_LiteralsOn ? m_LiteralDecoder.DecodeSymbol(&m_InBitStream) : - m_InBitStream.ReadBits(kNumBitsInByte)); + Byte b; + if (m_LiteralsOn) + { + UInt32 temp = m_LiteralDecoder.DecodeSymbol(&m_InBitStream); + if (temp >= kLiteralTableSize) + return S_FALSE; + b = (Byte)temp; + } + else + b = (Byte)m_InBitStream.ReadBits(kNumBitsInByte); m_OutWindowStream.PutByte(b); pos++; } diff --git a/7zip/Compress/Implode/ImplodeDecoder.h b/7zip/Compress/Implode/ImplodeDecoder.h index 7dd35003..627edba4 100755 --- a/7zip/Compress/Implode/ImplodeDecoder.h +++ b/7zip/Compress/Implode/ImplodeDecoder.h @@ -32,9 +32,8 @@ class CCoder : int m_NumDistanceLowDirectBits; UInt32 m_MinMatchLength; - void ReadLevelItems(NImplode::NHuffman::CDecoder &table, - Byte *levels, int numLevelItems); - void ReadTables(); + bool ReadLevelItems(NImplode::NHuffman::CDecoder &table, Byte *levels, int numLevelItems); + bool ReadTables(); void DeCodeLevelTable(Byte *newLevels, int numLevels); public: CCoder(); diff --git a/7zip/Compress/Implode/ImplodeHuffmanDecoder.cpp b/7zip/Compress/Implode/ImplodeHuffmanDecoder.cpp index 15046d55..2fbb77fd 100755 --- a/7zip/Compress/Implode/ImplodeHuffmanDecoder.cpp +++ b/7zip/Compress/Implode/ImplodeHuffmanDecoder.cpp @@ -19,7 +19,7 @@ CDecoder::~CDecoder() delete []m_Symbols; } -void CDecoder::SetCodeLengths(const Byte *codeLengths) +bool CDecoder::SetCodeLengths(const Byte *codeLengths) { // int lenCounts[kNumBitsInLongestCode + 1], tmpPositions[kNumBitsInLongestCode + 1]; int lenCounts[kNumBitsInLongestCode + 2], tmpPositions[kNumBitsInLongestCode + 1]; @@ -44,7 +44,7 @@ void CDecoder::SetCodeLengths(const Byte *codeLengths) { startPos += lenCounts[i] << (kNumBitsInLongestCode - i); if (startPos > kMaxValue) - throw CDecoderException(); + return false; m_Limitits[i] = startPos; m_Positions[i] = m_Positions[i + 1] + lenCounts[i + 1]; tmpPositions[i] = m_Positions[i] + lenCounts[i]; @@ -54,12 +54,13 @@ void CDecoder::SetCodeLengths(const Byte *codeLengths) // if _ZIP_MODE do not throw exception for trees containing only one node // #ifndef _ZIP_MODE if (startPos != kMaxValue) - throw CDecoderException(); + 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) @@ -76,12 +77,12 @@ UInt32 CDecoder::DecodeSymbol(CInBit *inStream) } } if (i == 0) - throw CDecoderException(); + return 0xFFFFFFFF; inStream->MovePos(numBits); UInt32 index = m_Positions[numBits] + ((value - m_Limitits[numBits + 1]) >> (kNumBitsInLongestCode - numBits)); if (index >= m_NumSymbols) - throw CDecoderException(); // test it + return 0xFFFFFFFF; return m_Symbols[index]; } diff --git a/7zip/Compress/Implode/ImplodeHuffmanDecoder.h b/7zip/Compress/Implode/ImplodeHuffmanDecoder.h index 5a8b4e90..9f7aeca1 100755 --- a/7zip/Compress/Implode/ImplodeHuffmanDecoder.h +++ b/7zip/Compress/Implode/ImplodeHuffmanDecoder.h @@ -11,7 +11,6 @@ namespace NImplode { namespace NHuffman { const int kNumBitsInLongestCode = 16; -class CDecoderException{}; typedef NStream::NLSBF::CDecoder CInBit; @@ -25,7 +24,7 @@ public: CDecoder(UInt32 numSymbols); ~CDecoder(); - void SetCodeLengths(const Byte *codeLengths); + bool SetCodeLengths(const Byte *codeLengths); UInt32 DecodeSymbol(CInBit *inStream); }; diff --git a/7zip/Compress/LZ/LZInWindow.cpp b/7zip/Compress/LZ/LZInWindow.cpp index a16a2c19..64928806 100755 --- a/7zip/Compress/LZ/LZInWindow.cpp +++ b/7zip/Compress/LZ/LZInWindow.cpp @@ -72,7 +72,7 @@ HRESULT CLZInWindow::ReadBlock() if(size == 0) return S_OK; UInt32 numReadBytes; - RINOK(_stream->ReadPart(_buffer + _streamPos, size, &numReadBytes)); + RINOK(_stream->Read(_buffer + _streamPos, size, &numReadBytes)); if(numReadBytes == 0) { _posLimit = _streamPos; diff --git a/7zip/Compress/LZ/LZOutWindow.cpp b/7zip/Compress/LZ/LZOutWindow.cpp index 4101079b..093c9ce8 100755 --- a/7zip/Compress/LZ/LZOutWindow.cpp +++ b/7zip/Compress/LZ/LZOutWindow.cpp @@ -5,62 +5,29 @@ #include "../../../Common/Alloc.h" #include "LZOutWindow.h" -bool CLZOutWindow::Create(UInt32 windowSize) -{ - const UInt32 kMinBlockSize = 1; - if (windowSize < kMinBlockSize) - windowSize = kMinBlockSize; - if (_buffer != 0 && _windowSize == windowSize) - return true; - - // It's here to allow Solid decoding / and calling Create for RAR - _pos = 0; - _streamPos = 0; - - Free(); - _windowSize = windowSize; - _buffer = (Byte *)::BigAlloc(windowSize); - return (_buffer != 0); -} - -void CLZOutWindow::Free() -{ - ::BigFree(_buffer); - _buffer = 0; -} - -void CLZOutWindow::SetStream(ISequentialOutStream *stream) -{ - ReleaseStream(); - _stream = stream; - _stream->AddRef(); -} - void CLZOutWindow::Init(bool solid) { if(!solid) { _streamPos = 0; + _limitPos = _bufferSize; _pos = 0; + _processedSize = 0; + _overDict = false; } #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } -void CLZOutWindow::ReleaseStream() -{ - if(_stream != 0) - { - // Flush(); // Test it - _stream->Release(); - _stream = 0; - } -} - void CLZOutWindow::FlushWithCheck() { - HRESULT result = Flush(); + HRESULT result = FlushPart(); + if (_pos == _bufferSize) + { + _pos = 0; + _overDict = true; + } #ifdef _NO_EXCEPTIONS ErrorCode = result; #else @@ -69,27 +36,4 @@ void CLZOutWindow::FlushWithCheck() #endif } -HRESULT CLZOutWindow::Flush() -{ - UInt32 size = _pos - _streamPos; - if(size == 0) - return S_OK; - #ifdef _NO_EXCEPTIONS - if (ErrorCode != S_OK) - return ErrorCode; - #endif - if(_stream != 0) - { - UInt32 processedSize; - HRESULT result = _stream->Write(_buffer + _streamPos, size, &processedSize); - if (result != S_OK) - return result; - if (size != processedSize) - return E_FAIL; - } - if (_pos >= _windowSize) - _pos = 0; - _streamPos = _pos; - return S_OK; -} diff --git a/7zip/Compress/LZ/LZOutWindow.h b/7zip/Compress/LZ/LZOutWindow.h index 16bbc9e2..f2a182c0 100755 --- a/7zip/Compress/LZ/LZOutWindow.h +++ b/7zip/Compress/LZ/LZOutWindow.h @@ -4,6 +4,7 @@ #define __LZ_OUT_WINDOW_H #include "../../IStream.h" +#include "../../Common/OutBuffer.h" #ifndef _NO_EXCEPTIONS class CLZOutWindowException @@ -14,57 +15,47 @@ public: }; #endif -class CLZOutWindow +class CLZOutWindow: public COutBuffer { - Byte *_buffer; - UInt32 _pos; - UInt32 _windowSize; - UInt32 _streamPos; - ISequentialOutStream *_stream; + bool _overDict; void FlushWithCheck(); public: - #ifdef _NO_EXCEPTIONS - HRESULT ErrorCode; - #endif - - void Free(); - CLZOutWindow(): _buffer(0), _stream(0) {} - ~CLZOutWindow() { Free(); ReleaseStream(); } - bool Create(UInt32 windowSize); - - void SetStream(ISequentialOutStream *stream); void Init(bool solid = false); - HRESULT Flush(); - void ReleaseStream(); - void CopyBlock(UInt32 distance, UInt32 len) + // distance >= 0, len > 0, + bool CopyBlock(UInt32 distance, UInt32 len) { UInt32 pos = _pos - distance - 1; - if (pos >= _windowSize) - pos += _windowSize; - for(; len > 0; len--) + if (pos >= _bufferSize) { - if (pos >= _windowSize) + if (!_overDict) + return false; + pos += _bufferSize; + } + do + { + if (pos == _bufferSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; - if (_pos >= _windowSize) + if (_pos == _limitPos) FlushWithCheck(); - // PutOneByte(GetOneByte(distance)); } + while(--len != 0); + return true; } void PutByte(Byte b) { _buffer[_pos++] = b; - if (_pos >= _windowSize) + if (_pos == _limitPos) FlushWithCheck(); } Byte GetByte(UInt32 distance) const { UInt32 pos = _pos - distance - 1; - if (pos >= _windowSize) - pos += _windowSize; + if (pos >= _bufferSize) + pos += _bufferSize; return _buffer[pos]; } }; diff --git a/7zip/Compress/LZMA/LZMA.dsp b/7zip/Compress/LZMA/LZMA.dsp index 0e9edda3..3fd32e1d 100755 --- a/7zip/Compress/LZMA/LZMA.dsp +++ b/7zip/Compress/LZMA/LZMA.dsp @@ -132,6 +132,14 @@ SOURCE=..\..\Common\OutBuffer.cpp SOURCE=..\..\Common\OutBuffer.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # Begin Group "RangeCoder" diff --git a/7zip/Compress/LZMA/LZMADecoder.cpp b/7zip/Compress/LZMA/LZMADecoder.cpp index 0863186b..57ab5a8d 100755 --- a/7zip/Compress/LZMA/LZMADecoder.cpp +++ b/7zip/Compress/LZMA/LZMADecoder.cpp @@ -8,6 +8,9 @@ namespace NCompress { namespace NLZMA { +const int kLenIdFinished = -1; +const int kLenIdNeedInit = -2; + void CDecoder::Init() { { @@ -41,11 +44,18 @@ void CDecoder::Init() _reps[0] = _reps[1] = _reps[2] = _reps[3] = 0; } -HRESULT CDecoder::CodeSpec(Byte *buffer, UInt32 curSize) +HRESULT CDecoder::CodeSpec(UInt32 curSize) { - if (_remainLen == -1) + if (_outSizeDefined) + { + const UInt64 rem = _outSize - _outWindowStream.GetProcessedSize(); + if (curSize > rem) + curSize = (UInt32)rem; + } + + if (_remainLen == kLenIdFinished) return S_OK; - if (_remainLen == -2) + if (_remainLen == kLenIdNeedInit) { _rangeDecoder.Init(); Init(); @@ -54,8 +64,6 @@ HRESULT CDecoder::CodeSpec(Byte *buffer, UInt32 curSize) if (curSize == 0) return S_OK; - UInt64 nowPos64 = _nowPos64; - UInt32 rep0 = _reps[0]; UInt32 rep1 = _reps[1]; UInt32 rep2 = _reps[2]; @@ -67,12 +75,10 @@ HRESULT CDecoder::CodeSpec(Byte *buffer, UInt32 curSize) { previousByte = _outWindowStream.GetByte(rep0); _outWindowStream.PutByte(previousByte); - if (buffer) - *buffer++ = previousByte; - nowPos64++; _remainLen--; curSize--; } + UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); if (nowPos64 == 0) previousByte = 0; else @@ -97,8 +103,6 @@ HRESULT CDecoder::CodeSpec(Byte *buffer, UInt32 curSize) previousByte = _literalDecoder.DecodeNormal(&_rangeDecoder, (UInt32)nowPos64, previousByte); _outWindowStream.PutByte(previousByte); - if (buffer) - *buffer++ = previousByte; state.UpdateChar(); curSize--; nowPos64++; @@ -108,20 +112,14 @@ HRESULT CDecoder::CodeSpec(Byte *buffer, UInt32 curSize) UInt32 len; if(_isRep[state.Index].Decode(&_rangeDecoder) == 1) { + bool readLen = true; if(_isRepG0[state.Index].Decode(&_rangeDecoder) == 0) { if(_isRep0Long[state.Index][posState].Decode(&_rangeDecoder) == 0) { - if (nowPos64 == 0) - return S_FALSE; state.UpdateShortRep(); - previousByte = _outWindowStream.GetByte(rep0); - _outWindowStream.PutByte(previousByte); - if (buffer) - *buffer++ = previousByte; - curSize--; - nowPos64++; - continue; + readLen = false; + len = 1; } } else @@ -143,8 +141,11 @@ HRESULT CDecoder::CodeSpec(Byte *buffer, UInt32 curSize) rep1 = rep0; rep0 = distance; } - len = _repMatchLenDecoder.Decode(&_rangeDecoder, posState) + kMatchMinLen; - state.UpdateRep(); + if (readLen) + { + len = _repMatchLenDecoder.Decode(&_rangeDecoder, posState) + kMatchMinLen; + state.UpdateRep(); + } } else { @@ -167,36 +168,22 @@ HRESULT CDecoder::CodeSpec(Byte *buffer, UInt32 curSize) rep0 += (_rangeDecoder.DecodeDirectBits( numDirectBits - kNumAlignBits) << kNumAlignBits); rep0 += _posAlignDecoder.ReverseDecode(&_rangeDecoder); + if (rep0 == 0xFFFFFFFF) + { + _remainLen = kLenIdFinished; + return S_OK; + } } } else rep0 = posSlot; - if (rep0 >= nowPos64 || rep0 >= _dictionarySizeCheck) - { - if (rep0 != (UInt32)(Int32)(-1)) - return S_FALSE; - _nowPos64 = nowPos64; - _remainLen = -1; - return S_OK; - } } UInt32 locLen = len; if (len > curSize) locLen = (UInt32)curSize; - if (buffer) - { - for (UInt32 i = locLen; i != 0; i--) - { - previousByte = _outWindowStream.GetByte(rep0); - *buffer++ = previousByte; - _outWindowStream.PutByte(previousByte); - } - } - else - { - _outWindowStream.CopyBlock(rep0, locLen); - previousByte = _outWindowStream.GetByte(0); - } + if (!_outWindowStream.CopyBlock(rep0, locLen)) + return S_FALSE; + previousByte = _outWindowStream.GetByte(0); curSize -= locLen; nowPos64 += locLen; len -= locLen; @@ -215,7 +202,6 @@ HRESULT CDecoder::CodeSpec(Byte *buffer, UInt32 curSize) } if (_rangeDecoder.Stream.WasFinished()) return S_FALSE; - _nowPos64 = nowPos64; _reps[0] = rep0; _reps[1] = rep1; _reps[2] = rep2; @@ -238,40 +224,47 @@ STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, while (true) { UInt32 curSize = 1 << 18; - if (_outSize != (UInt64)(Int64)(-1)) - if (curSize > _outSize - _nowPos64) - curSize = (UInt32)(_outSize - _nowPos64); - RINOK(CodeSpec(0, curSize)); - if (_remainLen == -1) + RINOK(CodeSpec(curSize)); + if (_remainLen == kLenIdFinished) break; if (progress != NULL) { UInt64 inSize = _rangeDecoder.GetProcessedSize(); - RINOK(progress->SetRatioInfo(&inSize, &_nowPos64)); + UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); } - if (_outSize != (UInt64)(Int64)(-1)) - if (_nowPos64 >= _outSize) + if (_outSizeDefined) + if (_outWindowStream.GetProcessedSize() >= _outSize) break; } flusher.NeedFlush = false; return Flush(); } + +#ifdef _NO_EXCEPTIONS + +#define LZMA_TRY_BEGIN +#define LZMA_TRY_END + +#else + +#define LZMA_TRY_BEGIN try { +#define LZMA_TRY_END } \ + catch(const CInBufferException &e) { return e.ErrorCode; } \ + catch(const CLZOutWindowException &e) { return e.ErrorCode; } \ + catch(...) { return S_FALSE; } + +#endif + + STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { - #ifndef _NO_EXCEPTIONS - try - { - #endif - return CodeReal(inStream, outStream, inSize, outSize, progress); - #ifndef _NO_EXCEPTIONS - } - catch(const CInBufferException &e) { return e.ErrorCode; } - catch(const CLZOutWindowException &e) { return e.ErrorCode; } - catch(...) { return S_FALSE; } - #endif + LZMA_TRY_BEGIN + return CodeReal(inStream, outStream, inSize, outSize, progress); + LZMA_TRY_END } STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size) @@ -288,9 +281,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); - _dictionarySizeCheck = MyMax(dictionarySize, UInt32(1)); - UInt32 blockSize = MyMax(_dictionarySizeCheck, UInt32(1 << 12)); - if (!_outWindowStream.Create(blockSize)) + if (!_outWindowStream.Create(dictionarySize)) return E_OUTOFMEMORY; if (!_literalDecoder.Create(lp, lc)) return E_OUTOFMEMORY; @@ -319,38 +310,29 @@ STDMETHODIMP CDecoder::ReleaseInStream() STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { - _outSize = (outSize == NULL) ? (UInt64)(Int64)(-1) : *outSize; - _nowPos64 = 0; - _remainLen = -2; // -2 means need_init + if (_outSizeDefined = (outSize != NULL)) + _outSize = *outSize; + _remainLen = kLenIdNeedInit; _outWindowStream.Init(); return S_OK; } +#ifdef _ST_MODE + STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { - #ifndef _NO_EXCEPTIONS - try - { - #endif - UInt64 startPos = _nowPos64; - if (_outSize != (UInt64)(Int64)(-1)) - if (size > _outSize - _nowPos64) - size = (UInt32)(_outSize - _nowPos64); - HRESULT res = CodeSpec((Byte *)data, size); + LZMA_TRY_BEGIN if (processedSize) - *processedSize = (UInt32)(_nowPos64 - startPos); - return res; - #ifndef _NO_EXCEPTIONS - } - catch(const CInBufferException &e) { return e.ErrorCode; } - catch(const CLZOutWindowException &e) { return e.ErrorCode; } - catch(...) { return S_FALSE; } - #endif + *processedSize = 0; + const UInt64 startPos = _outWindowStream.GetProcessedSize(); + _outWindowStream.SetMemStream((Byte *)data); + RINOK(CodeSpec(size)); + if (processedSize) + *processedSize = (UInt32)(_outWindowStream.GetProcessedSize() - startPos); + return Flush(); + LZMA_TRY_END } -STDMETHODIMP CDecoder::ReadPart(void *data, UInt32 size, UInt32 *processedSize) -{ - return Read(data, size, processedSize); -} +#endif }} diff --git a/7zip/Compress/LZMA/LZMADecoder.h b/7zip/Compress/LZMA/LZMADecoder.h index 5cfd72ad..16e49269 100755 --- a/7zip/Compress/LZMA/LZMADecoder.h +++ b/7zip/Compress/LZMA/LZMADecoder.h @@ -145,9 +145,11 @@ public: class CDecoder: public ICompressCoder, public ICompressSetDecoderProperties2, + #ifdef _ST_MODE public ICompressSetInStream, public ICompressSetOutStreamSize, public ISequentialInStream, + #endif public CMyUnknownImp { CLZOutWindow _outWindowStream; @@ -170,26 +172,30 @@ class CDecoder: CLiteralDecoder _literalDecoder; - UInt32 _dictionarySizeCheck; - UInt32 _posStateMask; /////////////////// // State - UInt64 _outSize; - UInt64 _nowPos64; UInt32 _reps[4]; CState _state; Int32 _remainLen; // -1 means end of stream. // -2 means need Init + UInt64 _outSize; + bool _outSizeDefined; void Init(); - HRESULT CodeSpec(Byte *buffer, UInt32 size); + HRESULT CodeSpec(UInt32 size); public: + + #ifdef _ST_MODE MY_UNKNOWN_IMP4( ICompressSetDecoderProperties2, ICompressSetInStream, ICompressSetOutStreamSize, ISequentialInStream) + #else + MY_UNKNOWN_IMP1( + ICompressSetDecoderProperties2) + #endif void ReleaseStreams() { @@ -228,9 +234,12 @@ public: STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); - STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); + #ifdef _ST_MODE + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + #endif + + CDecoder(): _outSizeDefined(false) {} virtual ~CDecoder() {} }; diff --git a/7zip/Compress/LZMA/LZMAEncoder.cpp b/7zip/Compress/LZMA/LZMAEncoder.cpp index 2e8cba15..447130e0 100755 --- a/7zip/Compress/LZMA/LZMAEncoder.cpp +++ b/7zip/Compress/LZMA/LZMAEncoder.cpp @@ -3,6 +3,7 @@ #include "StdAfx.h" #include "../../../Common/Defs.h" +#include "../../Common/StreamUtils.h" #include "LZMAEncoder.h" @@ -498,7 +499,7 @@ STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) properties[0] = (_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits; for (int i = 0; i < 4; i++) properties[1 + i] = Byte(_dictionarySize >> (8 * i)); - return outStream->Write(properties, kPropSize, NULL); + return WriteStream(outStream, properties, kPropSize, NULL); } STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) diff --git a/7zip/Compress/LZMA/makefile b/7zip/Compress/LZMA/makefile index 3ec9151d..14672b6a 100755 --- a/7zip/Compress/LZMA/makefile +++ b/7zip/Compress/LZMA/makefile @@ -20,6 +20,7 @@ WIN_OBJS = \ 7ZIP_COMMON_OBJS = \ $O\InBuffer.obj \ $O\OutBuffer.obj \ + $O\StreamUtils.obj \ LZ_OBJS = \ $O\LZInWindow.obj \ diff --git a/7zip/Compress/LZMA_Alone/AloneLZMA.dsp b/7zip/Compress/LZMA_Alone/AloneLZMA.dsp index 3f0efbdc..f9f3eb69 100755 --- a/7zip/Compress/LZMA_Alone/AloneLZMA.dsp +++ b/7zip/Compress/LZMA_Alone/AloneLZMA.dsp @@ -477,6 +477,14 @@ SOURCE=..\..\Common\OutBuffer.cpp SOURCE=..\..\Common\OutBuffer.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # Begin Source File diff --git a/7zip/Compress/LZMA_Alone/LzmaAlone.cpp b/7zip/Compress/LZMA_Alone/LzmaAlone.cpp index d3965656..76b6d886 100755 --- a/7zip/Compress/LZMA_Alone/LzmaAlone.cpp +++ b/7zip/Compress/LZMA_Alone/LzmaAlone.cpp @@ -20,6 +20,7 @@ #include "../../../Common/StringToInt.h" #include "../../Common/FileStreams.h" +#include "../../Common/StreamUtils.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" @@ -35,6 +36,8 @@ extern "C" using namespace NCommandLineParser; static const char *kCantAllocate = "Can not allocate memory"; +static const char *kReadError = "Read error"; +static const char *kWriteError = "Write error"; namespace NKey { enum Enum @@ -131,7 +134,7 @@ static bool GetNumber(const wchar_t *s, UInt32 &value) int main2(int n, const char *args[]) { - fprintf(stderr, "\nLZMA 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-02\n"); + fprintf(stderr, "\nLZMA 4.27 Copyright (c) 1999-2005 Igor Pavlov 2005-08-07\n"); if (n == 1) { @@ -269,7 +272,7 @@ int main2(int n, const char *args[]) } UInt32 processedSize; - if (inStream->Read(inBuffer, (UInt32)inSize, &processedSize) != S_OK) + if (ReadStream(inStream, inBuffer, (UInt32)inSize, &processedSize) != S_OK) throw "Can not read"; if ((UInt32)inSize != processedSize) throw "Read size error"; @@ -311,8 +314,8 @@ int main2(int n, const char *args[]) if (res != 0) throw "LzmaDecoder error"; } - if (outStream->Write(outBuffer, (UInt32)outSizeProcessed, &processedSize) != S_OK) - throw "Can not write"; + if (WriteStream(outStream, outBuffer, (UInt32)outSizeProcessed, &processedSize) != S_OK) + throw kWriteError; MyFree(outBuffer); MyFree(inBuffer); return 0; @@ -408,9 +411,9 @@ int main2(int n, const char *args[]) for (int i = 0; i < 8; i++) { Byte b = Byte(fileSize >> (8 * i)); - if (outStream->Write(&b, sizeof(b), 0) != S_OK) + if (outStream->Write(&b, 1, 0) != S_OK) { - fprintf(stderr, "Write error"); + fprintf(stderr, kWriteError); return 1; } } @@ -434,14 +437,14 @@ int main2(int n, const char *args[]) const UInt32 kPropertiesSize = 5; Byte properties[kPropertiesSize]; UInt32 processedSize; - if (inStream->Read(properties, kPropertiesSize, &processedSize) != S_OK) + if (ReadStream(inStream, properties, kPropertiesSize, &processedSize) != S_OK) { - fprintf(stderr, "Read error"); + fprintf(stderr, kReadError); return 1; } if (processedSize != kPropertiesSize) { - fprintf(stderr, "Read error"); + fprintf(stderr, kReadError); return 1; } if (decoderSpec->SetDecoderProperties2(properties, kPropertiesSize) != S_OK) @@ -453,14 +456,14 @@ int main2(int n, const char *args[]) for (int i = 0; i < 8; i++) { Byte b; - if (inStream->Read(&b, sizeof(b), &processedSize) != S_OK) + if (inStream->Read(&b, 1, &processedSize) != S_OK) { - fprintf(stderr, "Read error"); + fprintf(stderr, kReadError); return 1; } if (processedSize != 1) { - fprintf(stderr, "Read error"); + fprintf(stderr, kReadError); return 1; } fileSize |= ((UInt64)b) << (8 * i); diff --git a/7zip/Compress/LZMA_Alone/LzmaBench.cpp b/7zip/Compress/LZMA_Alone/LzmaBench.cpp index c491f97b..21e27849 100755 --- a/7zip/Compress/LZMA_Alone/LzmaBench.cpp +++ b/7zip/Compress/LZMA_Alone/LzmaBench.cpp @@ -148,7 +148,6 @@ public: Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize) @@ -157,20 +156,13 @@ STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processed if (size > remain) size = remain; for (UInt32 i = 0; i < size; i++) - { ((Byte *)data)[i] = Data[Pos + i]; - } Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } -STDMETHODIMP CBenchmarkInStream::ReadPart(void *data, UInt32 size, UInt32 *processedSize) -{ - return Read(data, size, processedSize); -} - class CBenchmarkOutStream: public ISequentialOutStream, public CMyUnknownImp @@ -193,7 +185,6 @@ public: } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) @@ -211,11 +202,6 @@ STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *p return S_OK; } -STDMETHODIMP CBenchmarkOutStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize) -{ - return Write(data, size, processedSize); -} - class CCrcOutStream: public ISequentialOutStream, public CMyUnknownImp @@ -225,7 +211,6 @@ public: MY_UNKNOWN_IMP void Init() { CRC.Init(); } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) @@ -236,11 +221,6 @@ STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *process return S_OK; } -STDMETHODIMP CCrcOutStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize) -{ - return Write(data, size, processedSize); -} - static UInt64 GetTimeCount() { #ifdef _WIN32 diff --git a/7zip/Compress/LZMA_Alone/LzmaRam.cpp b/7zip/Compress/LZMA_Alone/LzmaRam.cpp index 387162b2..090d73d8 100755 --- a/7zip/Compress/LZMA_Alone/LzmaRam.cpp +++ b/7zip/Compress/LZMA_Alone/LzmaRam.cpp @@ -27,7 +27,6 @@ public: Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize) @@ -36,20 +35,13 @@ STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize) if (size > remain) size = remain; for (UInt32 i = 0; i < size; i++) - { ((Byte *)data)[i] = Data[Pos + i]; - } Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } -STDMETHODIMP CInStreamRam::ReadPart(void *data, UInt32 size, UInt32 *processedSize) -{ - return Read(data, size, processedSize); -} - class COutStreamRam: public ISequentialOutStream, public CMyUnknownImp @@ -83,7 +75,6 @@ public: return S_OK; } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *processedSize) @@ -101,11 +92,6 @@ STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *process return S_OK; } -STDMETHODIMP COutStreamRam::WritePart(const void *data, UInt32 size, UInt32 *processedSize) -{ - return Write(data, size, processedSize); -} - #define SZE_FAIL (1) #define SZE_OUTOFMEMORY (2) #define SZE_OUT_OVERFLOW (3) diff --git a/7zip/Compress/LZMA_Alone/makefile b/7zip/Compress/LZMA_Alone/makefile index b6f6541a..63a63ae4 100755 --- a/7zip/Compress/LZMA_Alone/makefile +++ b/7zip/Compress/LZMA_Alone/makefile @@ -41,12 +41,10 @@ COMMON_OBJS = \ $O\StringToInt.obj \ $O\Vector.obj -WIN_OBJS = \ - $O\Synchronization.obj - 7ZIP_COMMON_OBJS = \ $O\InBuffer.obj \ $O\OutBuffer.obj \ + $O\StreamUtils.obj \ LZ_OBJS = \ $O\LZInWindow.obj \ @@ -57,7 +55,6 @@ OBJS = \ $(LZMA_OBJS) \ $(LZMA_OPT_OBJS) \ $(COMMON_OBJS) \ - $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(LZ_OBJS) \ $O\LzmaRamDecode.obj \ @@ -85,8 +82,6 @@ $(LZMA_OPT_OBJS): ../LZMA/$(*B).cpp $(COMPL_O2) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) -$(WIN_OBJS): ../../../Windows/$(*B).cpp - $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(LZ_OBJS): ../LZ/$(*B).cpp diff --git a/7zip/Compress/LZMA_C/LzmaDecodeSize.c b/7zip/Compress/LZMA_C/LzmaDecodeSize.c index 59bfba6e..3dbdb2fd 100755 --- a/7zip/Compress/LZMA_C/LzmaDecodeSize.c +++ b/7zip/Compress/LZMA_C/LzmaDecodeSize.c @@ -2,7 +2,7 @@ LzmaDecodeSize.c LZMA Decoder (optimized for Size version) - LZMA SDK 4.22 Copyright (c) 1999-2005 Igor Pavlov (2005-06-10) + LZMA SDK 4.27 Copyright (c) 1999-2005 Igor Pavlov (2005-08-07) http://www.7-zip.org/ LZMA SDK is licensed under two licenses: @@ -66,17 +66,14 @@ Byte RangeDecoderReadByte(CRangeDecoder *rd) /* #define ReadByte (*rd->Buffer++) */ #define ReadByte (RangeDecoderReadByte(rd)) -void RangeDecoderInit(CRangeDecoder *rd, - #ifdef _LZMA_IN_CB - ILzmaInCallback *inCallback - #else - const Byte *stream, SizeT bufferSize +void RangeDecoderInit(CRangeDecoder *rd + #ifndef _LZMA_IN_CB + , const Byte *stream, SizeT bufferSize #endif ) { int i; #ifdef _LZMA_IN_CB - rd->InCallback = inCallback; rd->Buffer = rd->BufferLim = 0; #else rd->Buffer = stream; @@ -398,6 +395,7 @@ int LzmaDecode(CLzmaDecoderState *vs, rd.Range = vs->Range; rd.Code = vs->Code; #ifdef _LZMA_IN_CB + rd.InCallback = InCallback; rd.Buffer = vs->Buffer; rd.BufferLim = vs->BufferLim; #else @@ -432,11 +430,9 @@ int LzmaDecode(CLzmaDecoderState *vs, distanceLimit = 0; dictionaryPos = 0; dictionary[dictionarySize - 1] = 0; - RangeDecoderInit(&rd, - #ifdef _LZMA_IN_CB - InCallback - #else - inStream, inSize + RangeDecoderInit(&rd + #ifndef _LZMA_IN_CB + , inStream, inSize #endif ); #ifdef _LZMA_IN_CB @@ -486,11 +482,12 @@ int LzmaDecode(CLzmaDecoderState *vs, p[i] = kBitModelTotal >> 1; } - RangeDecoderInit(&rd, - #ifdef _LZMA_IN_CB - InCallback - #else - inStream, inSize + #ifdef _LZMA_IN_CB + rd.InCallback = InCallback; + #endif + RangeDecoderInit(&rd + #ifndef _LZMA_IN_CB + , inStream, inSize #endif ); diff --git a/7zip/Compress/LZMA_C/LzmaTest.c b/7zip/Compress/LZMA_C/LzmaTest.c index b4ca5422..f95a753b 100755 --- a/7zip/Compress/LZMA_C/LzmaTest.c +++ b/7zip/Compress/LZMA_C/LzmaTest.c @@ -3,7 +3,7 @@ LzmaTest.c Test application for LZMA Decoder This file written and distributed to public domain by Igor Pavlov. -This file is part of LZMA SDK 4.26 (2005-08-02) +This file is part of LZMA SDK 4.26 (2005-08-05) */ #include @@ -173,12 +173,12 @@ int main3(FILE *inFile, FILE *outFile, char *rs) if (state.Probs == 0 #ifdef _LZMA_OUT_READ - || state.Dictionary == 0 && state.Properties.DictionarySize != 0 + || (state.Dictionary == 0 && state.Properties.DictionarySize != 0) #else - || outStream == 0 && outSizeFull != 0 + || (outStream == 0 && outSizeFull != 0) #endif #ifndef _LZMA_IN_CB - || inStream == 0 && compressedSize != 0 + || (inStream == 0 && compressedSize != 0) #endif ) { @@ -307,7 +307,7 @@ int main2(int numArgs, const char *args[], char *rs) FILE *outFile = 0; int res; - sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-02\n"); + sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-05\n"); if (numArgs < 2 || numArgs > 3) { sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n"); diff --git a/7zip/Compress/Lzx/Lzx.h b/7zip/Compress/Lzx/Lzx.h new file mode 100755 index 00000000..386a17c3 --- /dev/null +++ b/7zip/Compress/Lzx/Lzx.h @@ -0,0 +1,61 @@ +// Lzx.h + +#ifndef __COMPRESS_LZX_H +#define __COMPRESS_LZX_H + +namespace NCompress { +namespace NLzx { + +const int kNumHuffmanBits = 16; +const UInt32 kNumRepDistances = 3; + +const UInt32 kNumLenSlots = 8; +const UInt32 kMatchMinLen = 2; +const UInt32 kNumLenSymbols = 249; +const UInt32 kMatchMaxLen = kMatchMinLen + (kNumLenSlots - 1) + kNumLenSymbols - 1; + +const int kNumAlignBits = 3; +const UInt32 kAlignTableSize = 1 << kNumAlignBits; + +const UInt32 kNumPosSlots = 50; +const UInt32 kNumPosLenSlots = kNumPosSlots * kNumLenSlots; + +const UInt32 kMainTableSize = 256 + kNumPosLenSlots; +const UInt32 kLevelTableSize = 20; +const UInt32 kMaxTableSize = kMainTableSize; + +const int kNumBlockTypeBits = 3; +const int kBlockTypeVerbatim = 1; +const int kBlockTypeAligned = 2; +const int kBlockTypeUncompressed = 3; + +const int kUncompressedBlockSizeNumBits = 24; + +const int kNumBitsForPreTreeLevel = 4; + +const int kLevelSymbolZeros = 17; +const int kLevelSymbolZerosBig = 18; +const int kLevelSymbolSame = 19; + +const int kLevelSymbolZerosStartValue = 4; +const int kLevelSymbolZerosNumBits = 4; + +const int kLevelSymbolZerosBigStartValue = kLevelSymbolZerosStartValue + + (1 << kLevelSymbolZerosNumBits); +const int kLevelSymbolZerosBigNumBits = 5; + +const int kLevelSymbolSameNumBits = 1; +const int kLevelSymbolSameStartValue = 4; + +const int kNumBitsForAlignLevel = 3; + +const int kNumDictionaryBitsMin = 15; +const int kNumDictionaryBitsMax = 21; +const UInt32 kDictionarySizeMax = (1 << kNumDictionaryBitsMax); + +const int kNumLinearPosSlotBits = 17; +const UInt32 kNumPowerPosSlots = 0x26; + +}} + +#endif diff --git a/7zip/Archive/Cab/LZXi86Converter.cpp b/7zip/Compress/Lzx/Lzx86Converter.cpp similarity index 53% rename from 7zip/Archive/Cab/LZXi86Converter.cpp rename to 7zip/Compress/Lzx/Lzx86Converter.cpp index ec70a211..1265dba0 100755 --- a/7zip/Archive/Cab/LZXi86Converter.cpp +++ b/7zip/Compress/Lzx/Lzx86Converter.cpp @@ -1,62 +1,54 @@ -// Archive/Cab/LZXi86Converter.cpp +// Lzx86Converter.cpp #include "StdAfx.h" #include "Common/Defs.h" -#include "LZXi86Converter.h" +#include "Lzx86Converter.h" -namespace NArchive { -namespace NCab { -namespace NLZX { +namespace NCompress { +namespace NLzx { static const int kResidue = 6 + 4; -void Ci86TranslationOutStream::MakeTranslation() +void Cx86ConvertOutStream::MakeTranslation() { if (m_Pos <= kResidue) return; UInt32 numBytes = m_Pos - kResidue; + Byte *buffer = m_Buffer; for (UInt32 i = 0; i < numBytes;) { - if (m_Buffer[i] == 0xE8) + if (buffer[i++] == 0xE8) { - i++; Int32 absValue = 0; int j; for(j = 0; j < 4; j++) - absValue += UInt32(m_Buffer[i + j]) << (j * 8); - - Int32 pos = m_ProcessedSize + i - 1; - UInt32 offset; - if (absValue < -pos || absValue >= Int32(m_TranslationSize)) + absValue += (UInt32)buffer[i + j] << (j * 8); + Int32 pos = (Int32)(m_ProcessedSize + i - 1); + if (absValue >= -pos && absValue < (Int32)m_TranslationSize) { - } - else - { - offset = (absValue >= 0) ? + UInt32 offset = (absValue >= 0) ? absValue - pos : absValue + m_TranslationSize; for(j = 0; j < 4; j++) { - m_Buffer[i + j] = Byte(offset & 0xFF); + buffer[i + j] = (Byte)(offset & 0xFF); offset >>= 8; } } i += 4; } - else - i++; } } -STDMETHODIMP Ci86TranslationOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +STDMETHODIMP Cx86ConvertOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { + if (processedSize != NULL) + *processedSize = 0; if (!m_TranslationMode) return m_Stream->Write(data, size, processedSize); - UInt32 realProcessedSize = 0; - while (realProcessedSize < size) { UInt32 writeSize = MyMin(size - realProcessedSize, kUncompressedBlockSize - m_Pos); @@ -73,21 +65,26 @@ STDMETHODIMP Ci86TranslationOutStream::Write(const void *data, UInt32 size, UInt return S_OK; } -STDMETHODIMP Ci86TranslationOutStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize) -{ - return Write(data, size, processedSize); -} - -HRESULT Ci86TranslationOutStream::Flush() +HRESULT Cx86ConvertOutStream::Flush() { if (m_Pos == 0) return S_OK; - MakeTranslation(); - RINOK(m_Stream->Write(m_Buffer, m_Pos, NULL)); + if (m_TranslationMode) + MakeTranslation(); + UInt32 pos = 0; + do + { + UInt32 processed; + RINOK(m_Stream->Write(m_Buffer + pos, m_Pos - pos, &processed)); + if (processed == 0) + return E_FAIL; + pos += processed; + } + while(pos < m_Pos); m_ProcessedSize += m_Pos; m_Pos = 0; - m_TranslationMode = (m_ProcessedSize < (1 << 30)); + m_TranslationMode = (m_TranslationMode && (m_ProcessedSize < (1 << 30))); return S_OK; } -}}} +}} diff --git a/7zip/Archive/Cab/LZXi86Converter.h b/7zip/Compress/Lzx/Lzx86Converter.h similarity index 57% rename from 7zip/Archive/Cab/LZXi86Converter.h rename to 7zip/Compress/Lzx/Lzx86Converter.h index 625fa506..b507a612 100755 --- a/7zip/Archive/Cab/LZXi86Converter.h +++ b/7zip/Compress/Lzx/Lzx86Converter.h @@ -1,50 +1,45 @@ -// Archive/Cab/LZXi86Converter.h +// Lzx/x86Converter.h -#ifndef __ARCHIVE_CAB_LZXI86CONVERTER_H -#define __ARCHIVE_CAB_LZXI86CONVERTER_H +#ifndef __LZX_X86CONVERTER_H +#define __LZX_X86CONVERTER_H #include "Common/MyCom.h" #include "../../IStream.h" -namespace NArchive { -namespace NCab { -namespace NLZX { +namespace NCompress { +namespace NLzx { const int kUncompressedBlockSize = 1 << 15; -class Ci86TranslationOutStream: +class Cx86ConvertOutStream: public ISequentialOutStream, public CMyUnknownImp { - bool m_TranslationMode; CMyComPtr m_Stream; UInt32 m_ProcessedSize; - Byte m_Buffer[kUncompressedBlockSize]; UInt32 m_Pos; UInt32 m_TranslationSize; + bool m_TranslationMode; + Byte m_Buffer[kUncompressedBlockSize]; void MakeTranslation(); public: - Ci86TranslationOutStream(): m_Pos(0) {} - ~Ci86TranslationOutStream() { Flush(); } - - MY_UNKNOWN_IMP - - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize); -public: - void Init(ISequentialOutStream *outStream, bool translationMode, UInt32 translationSize) + void SetStream(ISequentialOutStream *outStream) { m_Stream = outStream; } + void ReleaseStream() { m_Stream.Release(); } + void Init(bool translationMode, UInt32 translationSize) { - m_Stream = outStream; m_TranslationMode = translationMode; m_TranslationSize = translationSize; m_ProcessedSize = 0; m_Pos = 0; } - void ReleaseStream() { m_Stream.Release(); } HRESULT Flush(); + + MY_UNKNOWN_IMP + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; -}}} +}} #endif diff --git a/7zip/Compress/Lzx/LzxDecoder.cpp b/7zip/Compress/Lzx/LzxDecoder.cpp new file mode 100755 index 00000000..341e47c0 --- /dev/null +++ b/7zip/Compress/Lzx/LzxDecoder.cpp @@ -0,0 +1,382 @@ +// LzxDecoder.cpp + +#include "StdAfx.h" + +#include "LzxDecoder.h" + +#include "Common/Defs.h" +#include "Common/Alloc.h" +#include "Windows/Defs.h" + +namespace NCompress { +namespace NLzx { + +const int kLenIdNeedInit = -2; + +CDecoder::CDecoder(): + _keepHistory(false), + m_AlignPos(0) +{ + m_x86ConvertOutStreamSpec = new Cx86ConvertOutStream; + m_x86ConvertOutStream = m_x86ConvertOutStreamSpec; +} + +void CDecoder::ReleaseStreams() +{ + m_OutWindowStream.ReleaseStream(); + m_InBitStream.ReleaseStream(); + m_x86ConvertOutStreamSpec->ReleaseStream(); +} + +STDMETHODIMP CDecoder::Flush() +{ + RINOK(m_OutWindowStream.Flush()); + return m_x86ConvertOutStreamSpec->Flush(); +} + +UInt32 CDecoder::ReadBits(UInt32 numBits) { return m_InBitStream.ReadBits(numBits); } + +#define RIF(x) { if (!(x)) return false; } + +bool CDecoder::ReadTable(Byte *lastLevels, Byte *newLevels, UInt32 numSymbols) +{ + Byte levelLevels[kLevelTableSize]; + UInt32 i; + for (i = 0; i < kLevelTableSize; i++) + levelLevels[i] = (Byte)ReadBits(kNumBitsForPreTreeLevel); + RIF(m_LevelDecoder.SetCodeLengths(levelLevels)); + int num = 0; + Byte symbol = 0; + for (i = 0; i < numSymbols;) + { + if (num != 0) + { + lastLevels[i] = newLevels[i] = symbol; + i++; + num--; + continue; + } + UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream); + if (number == kLevelSymbolZeros) + { + num = kLevelSymbolZerosStartValue + ReadBits(kLevelSymbolZerosNumBits); + symbol = 0; + } + else if (number == kLevelSymbolZerosBig) + { + num = kLevelSymbolZerosBigStartValue + ReadBits(kLevelSymbolZerosBigNumBits); + symbol = 0; + } + else if (number == kLevelSymbolSame || number <= kNumHuffmanBits) + { + if (number <= kNumHuffmanBits) + num = 1; + else + { + num = kLevelSymbolSameStartValue + ReadBits(kLevelSymbolSameNumBits); + number = m_LevelDecoder.DecodeSymbol(&m_InBitStream); + if (number > kNumHuffmanBits) + return false; + } + symbol = Byte((17 + lastLevels[i] - number) % (kNumHuffmanBits + 1)); + } + else + return false; + } + return true; +} + +bool CDecoder::ReadTables(void) +{ + Byte newLevels[kMaxTableSize]; + { + int blockType = (int)ReadBits(kNumBlockTypeBits); + if (blockType > kBlockTypeUncompressed) + return false; + m_UnCompressedBlockSize = m_InBitStream.ReadBitsBig(kUncompressedBlockSizeNumBits); + + if (m_IsUncompressedBlock = (blockType == kBlockTypeUncompressed)) + { + m_InBitStream.ReadBits(16 - m_InBitStream.GetBitPosition()); + if (!m_InBitStream.ReadUInt32(m_RepDistances[0])) + return false; + m_RepDistances[0]--; + for (int i = 1; i < kNumRepDistances; i++) + { + UInt32 rep = 0; + for (int j = 0; j < 4; j++) + rep |= (UInt32)m_InBitStream.DirectReadByte() << (8 * j); + m_RepDistances[i] = rep - 1; + } + return true; + } + if (m_AlignIsUsed = (blockType == kBlockTypeAligned)) + { + for(int i = 0; i < kAlignTableSize; i++) + newLevels[i] = ReadBits(kNumBitsForAlignLevel); + RIF(m_AlignDecoder.SetCodeLengths(newLevels)); + } + } + + RIF(ReadTable(m_LastMainLevels, newLevels, 256)); + RIF(ReadTable(m_LastMainLevels + 256, newLevels + 256, m_NumPosLenSlots)); + for (UInt32 i = 256 + m_NumPosLenSlots; i < kMainTableSize; i++) + newLevels[i] = 0; + RIF(m_MainDecoder.SetCodeLengths(newLevels)); + + RIF(ReadTable(m_LastLenLevels, newLevels, kNumLenSymbols)); + return m_LenDecoder.SetCodeLengths(newLevels); +} + +class CDecoderFlusher +{ + CDecoder *m_Decoder; +public: + bool NeedFlush; + CDecoderFlusher(CDecoder *decoder): m_Decoder(decoder), NeedFlush(true) {} + ~CDecoderFlusher() + { + if (NeedFlush) + m_Decoder->Flush(); + m_Decoder->ReleaseStreams(); + } +}; + + +void CDecoder::ClearPrevLevels() +{ + int i; + for (i = 0; i < kMainTableSize; i++) + m_LastMainLevels[i] = 0; + for (i = 0; i < kNumLenSymbols; i++) + m_LastLenLevels[i] = 0; +}; + + +HRESULT CDecoder::CodeSpec(UInt32 curSize) +{ + if (_remainLen == kLenIdNeedInit) + { + _remainLen = 0; + if (_keepHistory && m_IsUncompressedBlock && m_UnCompressedBlockSize > 0) + m_InBitStream.InitDirect(); + else + m_InBitStream.InitNormal(); + if (!_keepHistory) + { + m_UnCompressedBlockSize = 0; + ClearPrevLevels(); + UInt32 i86TranslationSize = 0; + bool translationMode = (ReadBits(1) != 0); + if (translationMode) + { + i86TranslationSize = ReadBits(16) << 16; + i86TranslationSize |= ReadBits(16); + } + m_x86ConvertOutStreamSpec->Init(translationMode, i86TranslationSize); + + for(int i = 0 ; i < kNumRepDistances; i++) + m_RepDistances[i] = 0; + } + } + + if (curSize == 0) + return S_OK; + + while(_remainLen > 0 && curSize > 0) + { + m_OutWindowStream.PutByte(m_OutWindowStream.GetByte(m_RepDistances[0])); + _remainLen--; + curSize--; + } + + while(curSize > 0) + { + if (m_UnCompressedBlockSize == 0) + if (!ReadTables()) + return S_FALSE; + UInt32 nowPos = 0; + UInt32 next = (Int32)MyMin(m_UnCompressedBlockSize, curSize); + curSize -= next; + m_UnCompressedBlockSize -= next; + if (m_IsUncompressedBlock) + { + while(next > 0) + { + m_OutWindowStream.PutByte(m_InBitStream.DirectReadByte()); + next--; + } + if (m_UnCompressedBlockSize == 0) + { + m_InBitStream.Align(m_AlignPos); + m_AlignPos = 0; + } + } + else while(next > 0) + { + UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream); + if (number < 256) + { + m_OutWindowStream.PutByte((Byte)number); + next--; + } + else + { + UInt32 posLenSlot = number - 256; + if (posLenSlot >= m_NumPosLenSlots) + return S_FALSE; + UInt32 posSlot = posLenSlot / kNumLenSlots; + UInt32 lenSlot = posLenSlot % kNumLenSlots; + UInt32 len = kMatchMinLen + lenSlot; + if (lenSlot == kNumLenSlots - 1) + { + UInt32 lenTemp = m_LenDecoder.DecodeSymbol(&m_InBitStream); + if (lenTemp >= kNumLenSymbols) + return S_FALSE; + len += lenTemp; + } + + if (posSlot < kNumRepDistances) + { + UInt32 distance = m_RepDistances[posSlot]; + m_RepDistances[posSlot] = m_RepDistances[0]; + m_RepDistances[0] = distance; + } + else + { + UInt32 distance; + int numDirectBits; + if (posSlot < kNumPowerPosSlots) + { + numDirectBits = (posSlot >> 1) - 1; + distance = ((2 | (posSlot & 1)) << numDirectBits); + } + else + { + numDirectBits = kNumLinearPosSlotBits; + distance = ((posSlot - 0x22) << kNumLinearPosSlotBits); + } + + if (m_AlignIsUsed && numDirectBits >= kNumAlignBits) + { + distance += (m_InBitStream.ReadBits(numDirectBits - kNumAlignBits) << kNumAlignBits); + UInt32 alignTemp = m_AlignDecoder.DecodeSymbol(&m_InBitStream); + if (alignTemp >= kAlignTableSize) + return S_FALSE; + distance += alignTemp; + } + else + distance += m_InBitStream.ReadBits(numDirectBits); + m_RepDistances[2] = m_RepDistances[1]; + m_RepDistances[1] = m_RepDistances[0]; + m_RepDistances[0] = distance - kNumRepDistances; + } + + UInt32 locLen = len; + if (locLen > next) + locLen = next; + + if (!m_OutWindowStream.CopyBlock(m_RepDistances[0], locLen)) + return S_FALSE; + + len -= locLen; + next -= locLen; + if (len != 0) + { + _remainLen = len; + return S_OK; + } + } + } + } + return S_OK; +} + +HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + if (outSize == NULL) + return E_INVALIDARG; + UInt64 size = *outSize; + const UInt64 startSize = size; + + RINOK(SetInStream(inStream)); + m_x86ConvertOutStreamSpec->SetStream(outStream); + m_OutWindowStream.SetStream(m_x86ConvertOutStream); + RINOK(SetOutStreamSize(outSize)); + + CDecoderFlusher flusher(this); + + const UInt64 start = m_OutWindowStream.GetProcessedSize(); + while(true) + { + UInt32 curSize = 1 << 18; + UInt64 rem = size - (m_OutWindowStream.GetProcessedSize() - start); + if (curSize > rem) + curSize = (UInt32)rem; + if (curSize == 0) + break; + RINOK(CodeSpec(curSize)); + if (progress != NULL) + { + UInt64 inSize = m_InBitStream.GetProcessedSize(); + UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start; + RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); + } + } + flusher.NeedFlush = false; + return Flush(); +} + +HRESULT CDecoder::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(...) { return S_FALSE; } +} + +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) +{ + m_InBitStream.SetStream(inStream); + return S_OK; +} + +STDMETHODIMP CDecoder::ReleaseInStream() +{ + m_InBitStream.ReleaseStream(); + return S_OK; +} + +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) +{ + if (outSize == NULL) + return E_FAIL; + _remainLen = kLenIdNeedInit; + m_OutWindowStream.Init(_keepHistory); + return S_OK; +} + +HRESULT CDecoder::SetParams(int numDictBits) +{ + if (numDictBits < kNumDictionaryBitsMin || numDictBits > kNumDictionaryBitsMax) + return E_INVALIDARG; + UInt32 numPosSlots; + if (numDictBits < 20) + numPosSlots = 30 + (numDictBits - 15) * 2; + else if (numDictBits == 20) + numPosSlots = 42; + else + numPosSlots = 50; + m_NumPosLenSlots = numPosSlots * kNumLenSlots; + if (!m_OutWindowStream.Create(kDictionarySizeMax)) + return E_OUTOFMEMORY; + if (!m_InBitStream.Create(1 << 16)) + return E_OUTOFMEMORY; + return S_OK; +} + +}} diff --git a/7zip/Compress/Lzx/LzxDecoder.h b/7zip/Compress/Lzx/LzxDecoder.h new file mode 100755 index 00000000..a62662ec --- /dev/null +++ b/7zip/Compress/Lzx/LzxDecoder.h @@ -0,0 +1,181 @@ +// LzxDecoder.h + +#ifndef __LZXDECODER_H +#define __LZXDECODER_H + +#include "../../ICoder.h" + +#include "../../Compress/Huffman/HuffmanDecoder.h" +#include "../../Compress/LZ/LZOutWindow.h" +#include "../../Common/InBuffer.h" + +#include "Lzx.h" +#include "Lzx86Converter.h" + +namespace NCompress { +namespace NLzx { + +namespace NBitStream { + +const int kNumBigValueBits = 8 * 4; +const int kNumValueBits = 17; +const UInt32 kBitDecoderValueMask = (1 << kNumValueBits) - 1; + +class CDecoder +{ + CInBuffer m_Stream; + UInt32 m_Value; + int m_BitPos; +public: + CDecoder() {} + bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); } + + void SetStream(ISequentialInStream *s) { m_Stream.SetStream(s); } + void ReleaseStream() { m_Stream.ReleaseStream(); } + + void InitNormal() + { + m_Stream.Init(); + m_BitPos = kNumBigValueBits; + Normalize(); + } + + void InitDirect() + { + m_Stream.Init(); + m_BitPos = kNumBigValueBits; + } + + UInt64 GetProcessedSize() const + { return m_Stream.GetProcessedSize() - (kNumBigValueBits - m_BitPos) / 8; } + + int GetBitPosition() const { return m_BitPos & 0xF; } + + void Normalize() + { + for (;m_BitPos >= 16; m_BitPos -= 16) + { + Byte b0 = m_Stream.ReadByte(); + Byte b1 = m_Stream.ReadByte(); + m_Value = (m_Value << 8) | b1; + m_Value = (m_Value << 8) | b0; + } + } + + UInt32 GetValue(int numBits) const + { + return ((m_Value >> ((32 - kNumValueBits) - m_BitPos)) & kBitDecoderValueMask) >> + (kNumValueBits - numBits); + } + + void MovePos(UInt32 numBits) + { + m_BitPos += numBits; + Normalize(); + } + + UInt32 ReadBits(int numBits) + { + UInt32 res = GetValue(numBits); + MovePos(numBits); + return res; + } + + UInt32 ReadBitsBig(int numBits) + { + UInt32 numBits0 = numBits / 2; + UInt32 numBits1 = numBits - numBits0; + UInt32 res = ReadBits(numBits0) << numBits1; + return res + ReadBits(numBits1); + } + + bool ReadUInt32(UInt32 &v) + { + if (m_BitPos != 0) + return false; + v = ((m_Value >> 16) & 0xFFFF) | ((m_Value << 16) & 0xFFFF0000); + m_BitPos = kNumBigValueBits; + return true; + } + + Byte DirectReadByte() { return m_Stream.ReadByte(); } + + void Align(int alignPos) + { + if (((m_Stream.GetProcessedSize() + alignPos) & 1) != 0) + m_Stream.ReadByte(); + Normalize(); + } +}; +} + +class CDecoder : + public ICompressCoder, + public CMyUnknownImp +{ + NBitStream::CDecoder m_InBitStream; + CLZOutWindow m_OutWindowStream; + + UInt32 m_RepDistances[kNumRepDistances]; + UInt32 m_NumPosLenSlots; + + bool m_IsUncompressedBlock; + bool m_AlignIsUsed; + + NCompress::NHuffman::CDecoder m_MainDecoder; + NCompress::NHuffman::CDecoder m_LenDecoder; + NCompress::NHuffman::CDecoder m_AlignDecoder; + NCompress::NHuffman::CDecoder m_LevelDecoder; + + Byte m_LastMainLevels[kMainTableSize]; + Byte m_LastLenLevels[kNumLenSymbols]; + + Cx86ConvertOutStream *m_x86ConvertOutStreamSpec; + CMyComPtr m_x86ConvertOutStream; + + UInt32 m_UnCompressedBlockSize; + + bool _keepHistory; + int _remainLen; + int m_AlignPos; + + UInt32 ReadBits(UInt32 numBits); + bool ReadTable(Byte *lastLevels, Byte *newLevels, UInt32 numSymbols); + bool ReadTables(); + void ClearPrevLevels(); + + HRESULT CodeSpec(UInt32 size); + + HRESULT CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); +public: + CDecoder(); + + MY_UNKNOWN_IMP + + void ReleaseStreams(); + STDMETHOD(Flush)(); + + // ICompressCoder interface + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + + HRESULT SetParams(int numDictBits); + void SetKeepHistory(bool keepHistory, int alignPos) + { + _keepHistory = keepHistory; + m_AlignPos = alignPos; + } +}; + +}} + +#endif diff --git a/7zip/Compress/Lzx/StdAfx.h b/7zip/Compress/Lzx/StdAfx.h new file mode 100755 index 00000000..e7fb6986 --- /dev/null +++ b/7zip/Compress/Lzx/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" + +#endif diff --git a/7zip/Compress/PPMD/PPMD.dsp b/7zip/Compress/PPMD/PPMD.dsp index 09c3d7f8..9e512f6c 100755 --- a/7zip/Compress/PPMD/PPMD.dsp +++ b/7zip/Compress/PPMD/PPMD.dsp @@ -192,6 +192,14 @@ SOURCE=..\..\Common\OutBuffer.cpp SOURCE=..\..\Common\OutBuffer.h # End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File # End Group # Begin Group "RangeCoder" diff --git a/7zip/Compress/PPMD/PPMDContext.h b/7zip/Compress/PPMD/PPMDContext.h index 1b926585..6f154fc4 100755 --- a/7zip/Compress/PPMD/PPMDContext.h +++ b/7zip/Compress/PPMD/PPMDContext.h @@ -15,9 +15,9 @@ namespace NPPMD { const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS, INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124; -#pragma pack(1) struct SEE2_CONTEXT -{ // SEE-contexts for PPM-contexts with masked symbols +{ + // SEE-contexts for PPM-contexts with masked symbols UInt16 Summ; Byte Shift, Count; void init(int InitVal) { Summ=InitVal << (Shift=PERIOD_BITS-4); Count=4; } @@ -39,9 +39,25 @@ struct SEE2_CONTEXT struct PPM_CONTEXT { - UInt16 NumStats,SummFreq; // sizeof(UInt16) > sizeof(Byte) - struct STATE { Byte Symbol, Freq; PPM_CONTEXT* Successor; } _PACK_ATTR * Stats; - PPM_CONTEXT* Suffix; + UInt16 NumStats; // sizeof(UInt16) > sizeof(Byte) + UInt16 SummFreq; + + struct STATE + { + Byte Symbol, Freq; + UInt16 SuccessorLow; + UInt16 SuccessorHigh; + + UInt32 GetSuccessor() const { return SuccessorLow | ((UInt32)SuccessorHigh << 16); } + void SetSuccessor(UInt32 v) + { + SuccessorLow = (UInt16)(v & 0xFFFF); + SuccessorHigh = (UInt16)((v >> 16) & 0xFFFF); + } + }; + + UInt32 Stats; + UInt32 Suffix; PPM_CONTEXT* createChild(CSubAllocator &subAllocator, STATE* pStats, STATE& FirstState) { @@ -50,15 +66,14 @@ struct PPM_CONTEXT { pc->NumStats = 1; pc->oneState() = FirstState; - pc->Suffix = this; - pStats->Successor = pc; + pc->Suffix = subAllocator.GetOffset(this); + pStats->SetSuccessor(subAllocator.GetOffsetNoCheck(pc)); } return pc; } STATE& oneState() const { return (STATE&) SummFreq; } }; -#pragma pack() ///////////////////////////////// @@ -68,8 +83,8 @@ const UInt16 InitBinEsc[] = struct CInfo { CSubAllocator SubAllocator; - SEE2_CONTEXT _PACK_ATTR SEE2Cont[25][16], DummySEE2Cont; - PPM_CONTEXT _PACK_ATTR * MinContext, * MaxContext; + SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont; + PPM_CONTEXT * MinContext, * MaxContext; PPM_CONTEXT::STATE* FoundState; // found next state transition int NumMasked, InitEsc, OrderFall, RunLength, InitRL, MaxOrder; @@ -86,6 +101,11 @@ struct CInfo ((RunLength >> 26) & 0x20)]; } + PPM_CONTEXT *GetContext(UInt32 offset) const { return (PPM_CONTEXT *)SubAllocator.GetPtr(offset); } + PPM_CONTEXT *GetContextNoCheck(UInt32 offset) const { return (PPM_CONTEXT *)SubAllocator.GetPtrNoCheck(offset); } + PPM_CONTEXT::STATE *GetState(UInt32 offset) const { return (PPM_CONTEXT::STATE *)SubAllocator.GetPtr(offset); } + PPM_CONTEXT::STATE *GetStateNoCheck(UInt32 offset) const { return (PPM_CONTEXT::STATE *)SubAllocator.GetPtr(offset); } + void RestartModelRare() { int i, k, m; @@ -93,15 +113,17 @@ struct CInfo SubAllocator.InitSubAllocator(); InitRL = -((MaxOrder < 12) ? MaxOrder : 12) - 1; MinContext = MaxContext = (PPM_CONTEXT*) SubAllocator.AllocContext(); - MinContext->Suffix = NULL; + MinContext->Suffix = 0; OrderFall = MaxOrder; MinContext->SummFreq = (MinContext->NumStats = 256) + 1; - FoundState = MinContext->Stats = (PPM_CONTEXT::STATE*) SubAllocator.AllocUnits(256 / 2); + FoundState = (PPM_CONTEXT::STATE*)SubAllocator.AllocUnits(256 / 2); + MinContext->Stats = SubAllocator.GetOffsetNoCheck(FoundState); for (RunLength = InitRL, PrevSuccess = i = 0; i < 256; i++) { - MinContext->Stats[i].Symbol = i; - MinContext->Stats[i].Freq = 1; - MinContext->Stats[i].Successor = NULL; + PPM_CONTEXT::STATE &state = FoundState[i]; + state.Symbol = i; + state.Freq = 1; + state.SetSuccessor(0); } for (i = 0; i < 128; i++) for (k = 0; k < 8; k++) @@ -121,12 +143,12 @@ struct CInfo memset(CharMask,0,sizeof(CharMask)); OrderFall = this->MaxOrder; MinContext = MaxContext; - while (MinContext->Suffix != NULL) + while (MinContext->Suffix != 0) { - MinContext = MinContext->Suffix; - OrderFall--; + MinContext = GetContextNoCheck(MinContext->Suffix); + OrderFall--; } - FoundState = MinContext->Stats; + FoundState = GetState(MinContext->Stats); MinContext = MaxContext; } else @@ -160,7 +182,8 @@ struct CInfo // static PPM_CONTEXT::STATE UpState; PPM_CONTEXT::STATE UpState; - PPM_CONTEXT* pc = MinContext, * UpBranch = FoundState->Successor; + PPM_CONTEXT *pc = MinContext; + PPM_CONTEXT *UpBranch = GetContext(FoundState->GetSuccessor()); PPM_CONTEXT::STATE * p, * ps[MAX_O], ** pps = ps; if ( !skip ) { @@ -171,23 +194,23 @@ struct CInfo if ( p1 ) { p = p1; - pc = pc->Suffix; + pc = GetContext(pc->Suffix); goto LOOP_ENTRY; } do { - pc = pc->Suffix; + pc = GetContext(pc->Suffix); if (pc->NumStats != 1) { - if ((p = pc->Stats)->Symbol != FoundState->Symbol) + if ((p = GetStateNoCheck(pc->Stats))->Symbol != FoundState->Symbol) do { p++; } while (p->Symbol != FoundState->Symbol); } else p = &(pc->oneState()); LOOP_ENTRY: - if (p->Successor != UpBranch) + if (GetContext(p->GetSuccessor()) != UpBranch) { - pc = p->Successor; + pc = GetContext(p->GetSuccessor()); break; } *pps++ = p; @@ -197,10 +220,10 @@ NO_LOOP: if (pps == ps) return pc; UpState.Symbol = *(Byte*) UpBranch; - UpState.Successor = (PPM_CONTEXT*) (((Byte*) UpBranch)+1); + UpState.SetSuccessor(SubAllocator.GetOffset(UpBranch) + 1); if (pc->NumStats != 1) { - if ((p = pc->Stats)->Symbol != UpState.Symbol) + if ((p = GetStateNoCheck(pc->Stats))->Symbol != UpState.Symbol) do { p++; } while (p->Symbol != UpState.Symbol); unsigned int cf = p->Freq-1; unsigned int s0 = pc->SummFreq - pc->NumStats - cf; @@ -224,11 +247,13 @@ NO_LOOP: PPM_CONTEXT::STATE fs = *FoundState, * p = NULL; PPM_CONTEXT* pc, * Successor; unsigned int ns1, ns, cf, sf, s0; - if (fs.Freq < MAX_FREQ/4 && (pc=MinContext->Suffix) != NULL) + if (fs.Freq < MAX_FREQ / 4 && MinContext->Suffix != 0) { + pc = GetContextNoCheck(MinContext->Suffix); + if (pc->NumStats != 1) { - if ((p = pc->Stats)->Symbol != fs.Symbol) + if ((p = GetStateNoCheck(pc->Stats))->Symbol != fs.Symbol) { do { p++; } while (p->Symbol != fs.Symbol); if (p[0].Freq >= p[-1].Freq) @@ -251,8 +276,9 @@ NO_LOOP: } if ( !OrderFall ) { - MinContext = MaxContext = FoundState->Successor = CreateSuccessors(true, p); - if ( !MinContext ) + MinContext = MaxContext = CreateSuccessors(true, p); + FoundState->SetSuccessor(SubAllocator.GetOffset(MinContext)); + if (MinContext == 0) goto RESTART_MODEL; return; } @@ -260,31 +286,36 @@ NO_LOOP: Successor = (PPM_CONTEXT*) SubAllocator.pText; if (SubAllocator.pText >= SubAllocator.UnitsStart) goto RESTART_MODEL; - if ( fs.Successor ) + if (fs.GetSuccessor() != 0) { - if ((Byte*) fs.Successor <= SubAllocator.pText && - (fs.Successor=CreateSuccessors(false, p)) == NULL) - goto RESTART_MODEL; + if ((Byte *)GetContext(fs.GetSuccessor()) <= SubAllocator.pText) + { + PPM_CONTEXT* cs = CreateSuccessors(false, p); + fs.SetSuccessor(SubAllocator.GetOffset(cs)); + if (cs == NULL) + goto RESTART_MODEL; + } if ( !--OrderFall ) { - Successor = fs.Successor; + Successor = GetContext(fs.GetSuccessor()); SubAllocator.pText -= (MaxContext != MinContext); } } else { - FoundState->Successor = Successor; - fs.Successor = MinContext; + FoundState->SetSuccessor(SubAllocator.GetOffsetNoCheck(Successor)); + fs.SetSuccessor(SubAllocator.GetOffsetNoCheck(MinContext)); } s0 = MinContext->SummFreq - (ns = MinContext->NumStats) - (fs.Freq - 1); - for (pc = MaxContext; pc != MinContext; pc = pc->Suffix) + for (pc = MaxContext; pc != MinContext; pc = GetContext(pc->Suffix)) { if ((ns1 = pc->NumStats) != 1) { if ((ns1 & 1) == 0) { - pc->Stats = (PPM_CONTEXT::STATE*) SubAllocator.ExpandUnits(pc->Stats, ns1 >> 1); - if ( !pc->Stats ) + void *ppp = SubAllocator.ExpandUnits(GetState(pc->Stats), ns1 >> 1); + pc->Stats = SubAllocator.GetOffset(ppp); + if (!ppp) goto RESTART_MODEL; } pc->SummFreq += (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & @@ -296,7 +327,7 @@ NO_LOOP: if ( !p ) goto RESTART_MODEL; *p = pc->oneState(); - pc->Stats = p; + pc->Stats = SubAllocator.GetOffsetNoCheck(p); if (p->Freq < MAX_FREQ / 4 - 1) p->Freq += p->Freq; else @@ -315,13 +346,13 @@ NO_LOOP: cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf); pc->SummFreq += cf; } - p = pc->Stats + ns1; - p->Successor = Successor; + p = GetState(pc->Stats) + ns1; + p->SetSuccessor(SubAllocator.GetOffset(Successor)); p->Symbol = fs.Symbol; p->Freq = cf; pc->NumStats = ++ns1; } - MaxContext = MinContext = fs.Successor; + MaxContext = MinContext = GetContext(fs.GetSuccessor()); return; RESTART_MODEL: RestartModelRare(); @@ -366,8 +397,11 @@ RESTART_MODEL: SEE2_CONTEXT* psee2c; if (MinContext->NumStats != 256) { - psee2c = SEE2Cont[NS2Indx[Diff-1]] + (Diff < MinContext->Suffix->NumStats - MinContext->NumStats)+ - 2 * (MinContext->SummFreq < 11 * MinContext->NumStats) + 4 * (NumMasked > Diff) + HiBitsFlag; + psee2c = SEE2Cont[NS2Indx[Diff-1]] + + (Diff < (GetContext(MinContext->Suffix))->NumStats - MinContext->NumStats) + + 2 * (MinContext->SummFreq < 11 * MinContext->NumStats) + + 4 * (NumMasked > Diff) + + HiBitsFlag; scale = psee2c->getMean(); } else @@ -384,9 +418,10 @@ RESTART_MODEL: { int OldNS = MinContext->NumStats, i = MinContext->NumStats - 1, Adder, EscFreq; PPM_CONTEXT::STATE* p1, * p; - for (p = FoundState; p != MinContext->Stats; p--) + PPM_CONTEXT::STATE *stats = GetStateNoCheck(MinContext->Stats); + for (p = FoundState; p != stats; p--) _PPMD_SWAP(p[0], p[-1]); - MinContext->Stats->Freq += 4; + stats->Freq += 4; MinContext->SummFreq += 4; EscFreq = MinContext->SummFreq - p->Freq; Adder = (OrderFall != 0); @@ -398,7 +433,11 @@ RESTART_MODEL: if (p[0].Freq > p[-1].Freq) { PPM_CONTEXT::STATE tmp = *(p1 = p); - do { p1[0] = p1[-1]; } while (--p1 != MinContext->Stats && tmp.Freq > p1[-1].Freq); + do + { + p1[0] = p1[-1]; + } + while (--p1 != stats && tmp.Freq > p1[-1].Freq); *p1 = tmp; } } @@ -409,24 +448,24 @@ RESTART_MODEL: EscFreq += i; if ((MinContext->NumStats -= i) == 1) { - PPM_CONTEXT::STATE tmp = *MinContext->Stats; + PPM_CONTEXT::STATE tmp = *stats; do { tmp.Freq -= (tmp.Freq >> 1); EscFreq >>= 1; } while (EscFreq > 1); - SubAllocator.FreeUnits(MinContext->Stats, (OldNS+1) >> 1); + SubAllocator.FreeUnits(stats, (OldNS+1) >> 1); *(FoundState = &MinContext->oneState()) = tmp; return; } } MinContext->SummFreq += (EscFreq -= (EscFreq >> 1)); int n0 = (OldNS+1) >> 1, n1 = (MinContext->NumStats + 1) >> 1; if (n0 != n1) - MinContext->Stats = - (PPM_CONTEXT::STATE*) SubAllocator.ShrinkUnits(MinContext->Stats, n0, n1); - FoundState = MinContext->Stats; + MinContext->Stats = SubAllocator.GetOffset(SubAllocator.ShrinkUnits(stats, n0, n1)); + FoundState = GetState(MinContext->Stats); } void NextContext() { - if (!OrderFall && (Byte*) FoundState->Successor > SubAllocator.pText) - MinContext = MaxContext = FoundState->Successor; + PPM_CONTEXT *c = GetContext(FoundState->GetSuccessor()); + if (!OrderFall && (Byte *)c > SubAllocator.pText) + MinContext = MaxContext = c; else { UpdateModel(); diff --git a/7zip/Compress/PPMD/PPMDDecode.h b/7zip/Compress/PPMD/PPMDDecode.h index 83445718..56afbe66 100755 --- a/7zip/Compress/PPMD/PPMDDecode.h +++ b/7zip/Compress/PPMD/PPMDDecode.h @@ -14,7 +14,7 @@ struct CDecodeInfo: public CInfo void DecodeBinSymbol(NRangeCoder::CDecoder *rangeDecoder) { PPM_CONTEXT::STATE& rs = MinContext->oneState(); - UInt16& bs = GetBinSumm(rs, MinContext->Suffix->NumStats); + UInt16& bs = GetBinSumm(rs, GetContextNoCheck(MinContext->Suffix)->NumStats); if (rangeDecoder->DecodeBit(bs, TOT_BITS) == 0) { FoundState = &rs; @@ -36,13 +36,13 @@ struct CDecodeInfo: public CInfo void DecodeSymbol1(NRangeCoder::CDecoder *rangeDecoder) { - PPM_CONTEXT::STATE* p = MinContext->Stats; + PPM_CONTEXT::STATE* p = GetStateNoCheck(MinContext->Stats); int i, count, hiCnt; if ((count = rangeDecoder->GetThreshold(MinContext->SummFreq)) < (hiCnt = p->Freq)) { PrevSuccess = (2 * hiCnt > MinContext->SummFreq); RunLength += PrevSuccess; - rangeDecoder->Decode(0, MinContext->Stats->Freq); // MinContext->SummFreq); + rangeDecoder->Decode(0, p->Freq); // MinContext->SummFreq); (FoundState = p)->Freq=(hiCnt += 4); MinContext->SummFreq += 4; if (hiCnt > MAX_FREQ) @@ -72,7 +72,7 @@ struct CDecodeInfo: public CInfo int count, hiCnt, i = MinContext->NumStats - NumMasked; UInt32 freqSum; SEE2_CONTEXT* psee2c = makeEscFreq2(i, freqSum); - PPM_CONTEXT::STATE* ps[256], ** pps = ps, * p = MinContext->Stats-1; + PPM_CONTEXT::STATE* ps[256], ** pps = ps, * p = GetStateNoCheck(MinContext->Stats)-1; hiCnt = 0; do { @@ -119,8 +119,8 @@ struct CDecodeInfo: public CInfo do { OrderFall++; - MinContext = MinContext->Suffix; - if ( !MinContext ) + MinContext = GetContext(MinContext->Suffix); + if (MinContext == 0) return -1; } while (MinContext->NumStats == NumMasked); diff --git a/7zip/Compress/PPMD/PPMDDecoder.cpp b/7zip/Compress/PPMD/PPMDDecoder.cpp index 5677daf2..50200053 100755 --- a/7zip/Compress/PPMD/PPMDDecoder.cpp +++ b/7zip/Compress/PPMD/PPMDDecoder.cpp @@ -10,6 +10,9 @@ namespace NCompress { namespace NPPMD { +const int kLenIdFinished = -1; +const int kLenIdNeedInit = -2; + STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size) { if (size < 5) @@ -18,6 +21,15 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size _usedMemorySize = 0; for (int i = 0; i < 4; i++) _usedMemorySize += ((UInt32)(properties[1 + i])) << (i * 8); + + if (_usedMemorySize > kMaxMemBlockSize) + return E_NOTIMPL; + + if (!_rangeDecoder.Create(1 << 20)) + return E_OUTOFMEMORY; + if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize)) + return E_OUTOFMEMORY; + return S_OK; } @@ -25,76 +37,146 @@ class CDecoderFlusher { CDecoder *_coder; public: - CDecoderFlusher(CDecoder *coder): _coder(coder) {} + bool NeedFlush; + CDecoderFlusher(CDecoder *coder): _coder(coder), NeedFlush(true) {} ~CDecoderFlusher() { - _coder->Flush(); + if (NeedFlush) + _coder->Flush(); _coder->ReleaseStreams(); } }; -UInt32 GetMatchLen(const Byte *pointer1, const Byte *pointer2, - UInt32 limit) -{ - UInt32 i; - for(i = 0; i < limit && *pointer1 == *pointer2; - pointer1++, pointer2++, i++); - return i; +HRESULT CDecoder::CodeSpec(UInt32 size, Byte *memStream) +{ + const startSize = size; + if (_outSizeDefined) + { + const UInt64 rem = _outSize - _processedSize; + if (size > rem) + size = (UInt32)rem; + } + + if (_remainLen == kLenIdFinished) + return S_OK; + if (_remainLen == kLenIdNeedInit) + { + _rangeDecoder.Init(); + _remainLen = 0; + _info.MaxOrder = 0; + _info.StartModelRare(_order); + } + while (size != 0) + { + int symbol = _info.DecodeSymbol(&_rangeDecoder); + if (symbol < 0) + { + _remainLen = kLenIdFinished; + break; + } + if (memStream != 0) + *memStream++ = symbol; + else + _outStream.WriteByte((Byte)symbol); + size--; + } + _processedSize += startSize - size; + return S_OK; } STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { - if (!_rangeDecoder.Create(1 << 20)) - return E_OUTOFMEMORY; if (!_outStream.Create(1 << 20)) return E_OUTOFMEMORY; - - _rangeDecoder.SetStream(inStream); - _rangeDecoder.Init(); + + SetInStream(inStream); _outStream.SetStream(outStream); - _outStream.Init(); - + SetOutStreamSize(outSize); CDecoderFlusher flusher(this); - UInt64 progressPosValuePrev = 0, pos = 0; - - if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize)) - return E_OUTOFMEMORY; - - // _info.Init(); - // _info.MaxOrder = _order; - _info.MaxOrder = 0; - _info.StartModelRare(_order); - - UInt64 size = (outSize == NULL) ? (UInt64)(Int64)(-1) : *outSize; - - while(pos < size) + while(true) { - pos++; - int symbol = _info.DecodeSymbol(&_rangeDecoder); - if (symbol < 0) - return S_OK; - _outStream.WriteByte(symbol); - if (pos - progressPosValuePrev >= (1 << 18) && progress != NULL) + _processedSize = _outStream.GetProcessedSize(); + UInt32 curSize = (1 << 18); + RINOK(CodeSpec(curSize, NULL)); + if (_remainLen == kLenIdFinished) + break; + if (progress != NULL) { UInt64 inSize = _rangeDecoder.GetProcessedSize(); - RINOK(progress->SetRatioInfo(&inSize, &pos)); - progressPosValuePrev = pos; + RINOK(progress->SetRatioInfo(&inSize, &_processedSize)); } + if (_outSizeDefined) + if (_outStream.GetProcessedSize() >= _outSize) + break; } - return S_OK; + flusher.NeedFlush = false; + return Flush(); } +#ifdef _NO_EXCEPTIONS + +#define PPMD_TRY_BEGIN +#define PPMD_TRY_END + +#else + +#define PPMD_TRY_BEGIN try { +#define PPMD_TRY_END } \ + catch(const CInBufferException &e) { return e.ErrorCode; } \ + catch(const COutBufferException &e) { return e.ErrorCode; } \ + catch(...) { return S_FALSE; } + +#endif + + 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 COutBufferException &e) { return e.ErrorCode; } - catch(const CInBufferException &e) { return e.ErrorCode; } - catch(...) { return E_FAIL; } + PPMD_TRY_BEGIN + return CodeReal(inStream, outStream, inSize, outSize, progress); + PPMD_TRY_END } +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) +{ + _rangeDecoder.SetStream(inStream); + return S_OK; +} + +STDMETHODIMP CDecoder::ReleaseInStream() +{ + _rangeDecoder.ReleaseStream(); + return S_OK; +} + +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) +{ + if (_outSizeDefined = (outSize != NULL)) + _outSize = *outSize; + _remainLen = kLenIdNeedInit; + _outStream.Init(); + return S_OK; +} + +#ifdef _ST_MODE + +STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + PPMD_TRY_BEGIN + if (processedSize) + *processedSize = 0; + const UInt64 startPos = _processedSize; + RINOK(CodeSpec(size, (Byte *)data)); + if (processedSize) + *processedSize = (UInt32)(_processedSize - startPos); + return Flush(); + PPMD_TRY_END +} + +#endif + }} diff --git a/7zip/Compress/PPMD/PPMDDecoder.h b/7zip/Compress/PPMD/PPMDDecoder.h index a5c2d18e..bbb68ac5 100755 --- a/7zip/Compress/PPMD/PPMDDecoder.h +++ b/7zip/Compress/PPMD/PPMDDecoder.h @@ -17,6 +17,11 @@ namespace NPPMD { class CDecoder : public ICompressCoder, public ICompressSetDecoderProperties2, + #ifdef _ST_MODE + public ICompressSetInStream, + public ICompressSetOutStreamSize, + public ISequentialInStream, + #endif public CMyUnknownImp { NRangeCoder::CDecoder _rangeDecoder; @@ -28,13 +33,28 @@ class CDecoder : Byte _order; UInt32 _usedMemorySize; + int _remainLen; + UInt64 _outSize; + bool _outSizeDefined; + UInt64 _processedSize; + + HRESULT CodeSpec(UInt32 num, Byte *memStream); public: - MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) + #ifdef _ST_MODE + MY_UNKNOWN_IMP4( + ICompressSetDecoderProperties2, + ICompressSetInStream, + ICompressSetOutStreamSize, + ISequentialInStream) + #else + MY_UNKNOWN_IMP1( + ICompressSetDecoderProperties2) + #endif void ReleaseStreams() { - _rangeDecoder.ReleaseStream(); + ReleaseInStream(); _outStream.ReleaseStream(); } @@ -51,6 +71,17 @@ public: STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + + #ifdef _ST_MODE + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + #endif + + CDecoder(): _outSizeDefined(false) {} + }; }} diff --git a/7zip/Compress/PPMD/PPMDEncode.h b/7zip/Compress/PPMD/PPMDEncode.h index c2342058..860310a2 100755 --- a/7zip/Compress/PPMD/PPMDEncode.h +++ b/7zip/Compress/PPMD/PPMDEncode.h @@ -15,7 +15,7 @@ struct CEncodeInfo: public CInfo void EncodeBinSymbol(int symbol, NRangeCoder::CEncoder *rangeEncoder) { PPM_CONTEXT::STATE& rs = MinContext->oneState(); - UInt16 &bs = GetBinSumm(rs, MinContext->Suffix->NumStats); + UInt16 &bs = GetBinSumm(rs, GetContextNoCheck(MinContext->Suffix)->NumStats); if (rs.Symbol == symbol) { FoundState = &rs; @@ -39,12 +39,12 @@ struct CEncodeInfo: public CInfo void EncodeSymbol1(int symbol, NRangeCoder::CEncoder *rangeEncoder) { - PPM_CONTEXT::STATE* p = MinContext->Stats; + PPM_CONTEXT::STATE* p = GetStateNoCheck(MinContext->Stats); if (p->Symbol == symbol) { PrevSuccess = (2 * (p->Freq) > MinContext->SummFreq); RunLength += PrevSuccess; - rangeEncoder->Encode(0, MinContext->Stats->Freq, MinContext->SummFreq); + rangeEncoder->Encode(0, p->Freq, MinContext->SummFreq); (FoundState = p)->Freq += 4; MinContext->SummFreq += 4; if (p->Freq > MAX_FREQ) @@ -76,7 +76,7 @@ struct CEncodeInfo: public CInfo int hiCnt, i = MinContext->NumStats - NumMasked; UInt32 scale; SEE2_CONTEXT* psee2c = makeEscFreq2(i, scale); - PPM_CONTEXT::STATE* p = MinContext->Stats - 1; + PPM_CONTEXT::STATE* p = GetStateNoCheck(MinContext->Stats) - 1; hiCnt = 0; do { @@ -126,8 +126,8 @@ SYMBOL_FOUND: do { OrderFall++; - MinContext = MinContext->Suffix; - if ( !MinContext ) + MinContext = GetContext(MinContext->Suffix); + if (MinContext == 0) return; // S_OK; } while (MinContext->NumStats == NumMasked); diff --git a/7zip/Compress/PPMD/PPMDEncoder.cpp b/7zip/Compress/PPMD/PPMDEncoder.cpp index 16eaea60..b661f018 100755 --- a/7zip/Compress/PPMD/PPMDEncoder.cpp +++ b/7zip/Compress/PPMD/PPMDEncoder.cpp @@ -9,6 +9,8 @@ #include "Common/Defs.h" +#include "../../Common/StreamUtils.h" + #include "PPMDEncoder.h" namespace NCompress { @@ -40,19 +42,7 @@ public: } }; - CCounter g_Counter; - - -/* -// ISetRangeEncoder -STDMETHODIMP CEncoder::SetRangeEncoder(CRangeEncoder *aRangeEncoder) -{ - _rangeEncoder = aRangeEncoder; - RINOK(_rangeEncoder.QueryInterface(&m_InitOutCoder)); - - return S_OK; -} */ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, @@ -60,22 +50,22 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, { for (UInt32 i = 0; i < numProperties; i++) { - const PROPVARIANT &aProperty = properties[i]; + const PROPVARIANT &prop = properties[i]; switch(propIDs[i]) { case NCoderPropID::kUsedMemorySize: - if (aProperty.vt != VT_UI4) + if (prop.vt != VT_UI4) return E_INVALIDARG; - if (aProperty.ulVal < kMinMemSize) + if (prop.ulVal < kMinMemSize || prop.ulVal > kMaxMemBlockSize) return E_INVALIDARG; - _usedMemorySize = aProperty.ulVal; + _usedMemorySize = (UInt32)prop.ulVal; break; case NCoderPropID::kOrder: - if (aProperty.vt != VT_UI4) + if (prop.vt != VT_UI4) return E_INVALIDARG; - if (aProperty.ulVal < kMinOrder || aProperty.ulVal > kMaxOrderCompress) + if (prop.ulVal < kMinOrder || prop.ulVal > kMaxOrderCompress) return E_INVALIDARG; - _order = Byte(aProperty.ulVal); + _order = (Byte)prop.ulVal; break; default: return E_INVALIDARG; @@ -91,7 +81,7 @@ STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) properties[0] = _order; for (int i = 0; i < 4; i++) properties[1 + i] = Byte(_usedMemorySize >> (8 * i)); - return outStream->Write(properties, kPropSize, NULL); + return WriteStream(outStream, properties, kPropSize, NULL); } const UInt32 kUsedMemorySizeDefault = (1 << 24); @@ -101,30 +91,9 @@ CEncoder::CEncoder(): _usedMemorySize(kUsedMemorySizeDefault), _order(kOrderDefault) { - // SubAllocator.StartSubAllocator(kSubAllocator); } -HRESULT CEncoder::Flush() -{ - _rangeEncoder.FlushData(); - return _rangeEncoder.FlushStream(); -} - -class CEncoderFlusher -{ - CEncoder *_encoder; -public: - CEncoderFlusher(CEncoder *encoder): _encoder(encoder) {} - ~CEncoderFlusher() - { - _encoder->Flush(); - _encoder->ReleaseStreams(); - } -}; - - - HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, @@ -134,50 +103,41 @@ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, return E_OUTOFMEMORY; if (!_rangeEncoder.Create(1 << 20)) return E_OUTOFMEMORY; + if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize)) + return E_OUTOFMEMORY; _inStream.SetStream(inStream); _inStream.Init(); + _rangeEncoder.SetStream(outStream); _rangeEncoder.Init(); CEncoderFlusher flusher(this); - UInt64 pos = 0; - UInt64 prevProgressPos = 0; - - try - { - if ( !_info.SubAllocator.StartSubAllocator(_usedMemorySize) ) - return E_OUTOFMEMORY; - } - catch(...) - { - return E_OUTOFMEMORY; - } - - _info.MaxOrder = 0; _info.StartModelRare(_order); - - while (true) + while(true) { - Byte symbol; - if (!_inStream.ReadByte(symbol)) + UInt32 size = (1 << 18); + do { - // here we can write End Mark for stream version. - // In current version this feature is not used. - // _info.EncodeSymbol(-1, &_rangeEncoder); - - return S_OK; + Byte symbol; + if (!_inStream.ReadByte(symbol)) + { + // here we can write End Mark for stream version. + // In current version this feature is not used. + // _info.EncodeSymbol(-1, &_rangeEncoder); + return S_OK; + } + _info.EncodeSymbol(symbol, &_rangeEncoder); } - _info.EncodeSymbol(symbol, &_rangeEncoder); - pos++; - if (pos - prevProgressPos >= (1 << 18) && progress != NULL) + while (--size != 0); + if (progress != NULL) { + UInt64 inSize = _inStream.GetProcessedSize(); UInt64 outSize = _rangeEncoder.GetProcessedSize(); - RINOK(progress->SetRatioInfo(&pos, &outSize)); - prevProgressPos = pos; + RINOK(progress->SetRatioInfo(&inSize, &outSize)); } } } @@ -193,4 +153,3 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, } }} - diff --git a/7zip/Compress/PPMD/PPMDEncoder.h b/7zip/Compress/PPMD/PPMDEncoder.h index 80ac7391..915180b9 100755 --- a/7zip/Compress/PPMD/PPMDEncoder.h +++ b/7zip/Compress/PPMD/PPMDEncoder.h @@ -29,14 +29,12 @@ public: UInt32 _usedMemorySize; Byte _order; -public: + HRESULT Flush() + { + _rangeEncoder.FlushData(); + return _rangeEncoder.FlushStream(); + } - MY_UNKNOWN_IMP2( - ICompressSetCoderProperties, - ICompressWriteCoderProperties) - - // ICoder interface - HRESULT Flush(); void ReleaseStreams() { _inStream.ReleaseStream(); @@ -46,6 +44,25 @@ public: HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + class CEncoderFlusher + { + CEncoder *_encoder; + public: + CEncoderFlusher(CEncoder *encoder): _encoder(encoder) {} + ~CEncoderFlusher() + { + _encoder->Flush(); + _encoder->ReleaseStreams(); + } + }; + +public: + + MY_UNKNOWN_IMP2( + ICompressSetCoderProperties, + ICompressWriteCoderProperties) + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); diff --git a/7zip/Compress/PPMD/PPMDSubAlloc.h b/7zip/Compress/PPMD/PPMDSubAlloc.h index 5a333fe3..fd64d577 100755 --- a/7zip/Compress/PPMD/PPMDSubAlloc.h +++ b/7zip/Compress/PPMD/PPMDSubAlloc.h @@ -11,39 +11,47 @@ const UINT N1=4, N2=4, N3=4, N4=(128+3-1*N1-2*N2-3*N3)/4; const UINT UNIT_SIZE=12, N_INDEXES=N1+N2+N3+N4; -#pragma pack(1) +// Extra 1 * UNIT_SIZE for NULL support +// Extra 2 * UNIT_SIZE for s0 in GlueFreeBlocks() +const UInt32 kExtraSize = (UNIT_SIZE * 3); +const UInt32 kMaxMemBlockSize = 0xFFFFFFFF - kExtraSize; + struct MEM_BLK { UInt16 Stamp, NU; - MEM_BLK *Next, *Prev; - void InsertAt(MEM_BLK* p) + UInt32 Next, Prev; + void InsertAt(Byte *Base, UInt32 p) { - Next = (Prev = p)->Next; - p->Next = Next->Prev = this; + Prev = p; + MEM_BLK *pp = (MEM_BLK *)(Base + p); + Next = pp->Next; + pp->Next = ((MEM_BLK *)(Base + Next))->Prev = (Byte *)this - Base; } - void Remove() + void Remove(Byte *Base) { - Prev->Next=Next; - Next->Prev=Prev; + ((MEM_BLK *)(Base + Prev))->Next = Next; + ((MEM_BLK *)(Base + Next))->Prev = Prev; } -} _PACK_ATTR; -#pragma pack() +}; class CSubAllocator { UInt32 SubAllocatorSize; Byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount; - struct NODE { NODE* Next; } FreeList[N_INDEXES]; + UInt32 FreeList[N_INDEXES]; + + Byte *Base; + Byte *HeapStart, *LoUnit, *HiUnit; public: - Byte* HeapStart, *pText, *UnitsStart, *LoUnit, *HiUnit; + Byte *pText, *UnitsStart; CSubAllocator(): SubAllocatorSize(0), GlueCount(0), - pText(0), - UnitsStart(0), LoUnit(0), - HiUnit(0) + HiUnit(0), + pText(0), + UnitsStart(0) { memset(Indx2Units, 0, sizeof(Indx2Units)); memset(FreeList, 0, sizeof(FreeList)); @@ -53,21 +61,28 @@ public: StopSubAllocator(); }; + void *GetPtr(UInt32 offset) const { return (offset == 0) ? 0 : (void *)(Base + offset); } + void *GetPtrNoCheck(UInt32 offset) const { return (void *)(Base + offset); } + UInt32 GetOffset(void *ptr) const { return (ptr == 0) ? 0 : (UInt32)((Byte *)ptr - Base); } + UInt32 GetOffsetNoCheck(void *ptr) const { return (UInt32)((Byte *)ptr - Base); } + MEM_BLK *GetBlk(UInt32 offset) const { return (MEM_BLK *)(Base + offset); } + UInt32 *GetNode(UInt32 offset) const { return (UInt32 *)(Base + offset); } void InsertNode(void* p, int indx) { - ((NODE*) p)->Next = FreeList[indx].Next; - FreeList[indx].Next = (NODE*)p; + *(UInt32 *)p = FreeList[indx]; + FreeList[indx] = GetOffsetNoCheck(p); } void* RemoveNode(int indx) { - NODE* RetVal = FreeList[indx].Next; - FreeList[indx].Next = RetVal->Next; - return RetVal; + UInt32 offset = FreeList[indx]; + UInt32 *p = GetNode(offset); + FreeList[indx] = *p; + return (void *)p; } - UINT U2B(int NU) { return 8 * NU + 4 * NU; } + UINT U2B(int NU) const { return (UINT)(NU) * UNIT_SIZE; } void SplitBlock(void* pv, int oldIndx, int newIndx) { @@ -82,25 +97,22 @@ public: InsertNode(p, Units2Indx[UDiff - 1]); } - UInt32 GetUsedMemory() + UInt32 GetUsedMemory() const { - UInt32 i, k, RetVal = SubAllocatorSize - (UInt32)(HiUnit - LoUnit) - (UInt32)(UnitsStart - pText); - for (k = i = 0; i < N_INDEXES; i++, k = 0) - { - for (NODE* pn = FreeList + i;(pn = pn->Next) != NULL; k++) - ; - RetVal -= UNIT_SIZE*Indx2Units[i] * k; - } + UInt32 RetVal = SubAllocatorSize - (UInt32)(HiUnit - LoUnit) - (UInt32)(UnitsStart - pText); + for (UInt32 i = 0; i < N_INDEXES; i++) + for (UInt32 pn = FreeList[i]; pn != 0; RetVal -= (UInt32)Indx2Units[i] * UNIT_SIZE) + pn = *GetNode(pn); return (RetVal >> 2); } void StopSubAllocator() { - if ( SubAllocatorSize ) + if (SubAllocatorSize != 0) { - BigFree(HeapStart); + BigFree(Base); SubAllocatorSize = 0; - HeapStart = 0; + Base = 0; } } @@ -110,10 +122,13 @@ public: return true; StopSubAllocator(); if (size == 0) - HeapStart = 0; + Base = 0; else - if ((HeapStart = (Byte *)::BigAlloc(size)) == 0) + { + if ((Base = (Byte *)::BigAlloc(size + kExtraSize)) == 0) return false; + HeapStart = Base + UNIT_SIZE; // we need such code to support NULL; + } SubAllocatorSize = size; return true; } @@ -138,34 +153,52 @@ public: void GlueFreeBlocks() { - MEM_BLK s0, *p, *p1; - int i, k, sz; + UInt32 s0 = (UInt32)(HeapStart + SubAllocatorSize - Base); + + // We need add exta MEM_BLK with Stamp=0 + GetBlk(s0)->Stamp = 0; + s0 += UNIT_SIZE; + MEM_BLK *ps0 = GetBlk(s0); + + UInt32 p; + int i; if (LoUnit != HiUnit) *LoUnit=0; - for (i = 0, s0.Next = s0.Prev = &s0; i < N_INDEXES; i++) - while ( FreeList[i].Next ) + ps0->Next = ps0->Prev = s0; + + for (i = 0; i < N_INDEXES; i++) + while (FreeList[i] != 0) { - p = (MEM_BLK*) RemoveNode(i); - p->InsertAt(&s0); - p->Stamp = 0xFFFF; - p->NU = Indx2Units[i]; + MEM_BLK *pp = (MEM_BLK *)RemoveNode(i); + pp->InsertAt(Base, s0); + pp->Stamp = 0xFFFF; + pp->NU = Indx2Units[i]; } - for (p=s0.Next; p != &s0; p =p->Next) - while ((p1 = p + p->NU)->Stamp == 0xFFFF && int(p->NU) + p1->NU < 0x10000) - { - p1->Remove(); - p->NU += p1->NU; - } - while ((p=s0.Next) != &s0) + for (p = ps0->Next; p != s0; p = GetBlk(p)->Next) { - for (p->Remove(), sz=p->NU; sz > 128; sz -= 128, p += 128) - InsertNode(p, N_INDEXES - 1); + while (true) + { + MEM_BLK *pp = GetBlk(p); + MEM_BLK *pp1 = GetBlk(p + pp->NU * UNIT_SIZE); + if (pp1->Stamp != 0xFFFF || int(pp->NU) + pp1->NU >= 0x10000) + break; + pp1->Remove(Base); + pp->NU += pp1->NU; + } + } + while ((p = ps0->Next) != s0) + { + MEM_BLK *pp = GetBlk(p); + pp->Remove(Base); + int sz; + for (sz = pp->NU; sz > 128; sz -= 128, p += 128 * UNIT_SIZE) + InsertNode(Base + p, N_INDEXES - 1); if (Indx2Units[i = Units2Indx[sz-1]] != sz) { - k = sz-Indx2Units[--i]; - InsertNode(p + (sz - k), k - 1); + int k = sz - Indx2Units[--i]; + InsertNode(Base + p + (sz - k) * UNIT_SIZE, k - 1); } - InsertNode(p,i); + InsertNode(Base + p, i); } } void* AllocUnitsRare(int indx) @@ -174,7 +207,7 @@ public: { GlueCount = 255; GlueFreeBlocks(); - if (FreeList[indx].Next) + if (FreeList[indx] != 0) return RemoveNode(indx); } int i = indx; @@ -186,7 +219,7 @@ public: i = U2B(Indx2Units[indx]); return (UnitsStart - pText > i) ? (UnitsStart -= i) : (NULL); } - } while (!FreeList[i].Next); + } while (FreeList[i] == 0); void* RetVal = RemoveNode(i); SplitBlock(RetVal, i, indx); return RetVal; @@ -195,7 +228,7 @@ public: void* AllocUnits(int NU) { int indx = Units2Indx[NU - 1]; - if (FreeList[indx].Next) + if (FreeList[indx] != 0) return RemoveNode(indx); void* RetVal = LoUnit; LoUnit += U2B(Indx2Units[indx]); @@ -209,7 +242,7 @@ public: { if (HiUnit != LoUnit) return (HiUnit -= UNIT_SIZE); - if (FreeList->Next) + if (FreeList[0] != 0) return RemoveNode(0); return AllocUnitsRare(0); } @@ -233,7 +266,7 @@ public: int i0 = Units2Indx[oldNU - 1], i1 = Units2Indx[newNU - 1]; if (i0 == i1) return oldPtr; - if ( FreeList[i1].Next ) + if (FreeList[i1] != 0) { void* ptr = RemoveNode(i1); memcpy(ptr, oldPtr, U2B(newNU)); diff --git a/7zip/Compress/PPMD/PPMDType.h b/7zip/Compress/PPMD/PPMDType.h index 5a67ac84..5200fa54 100755 --- a/7zip/Compress/PPMD/PPMDType.h +++ b/7zip/Compress/PPMD/PPMDType.h @@ -13,12 +13,6 @@ const int kMaxOrderCompress = 32; const int MAX_O = 255; /* maximum allowed model order */ -#if defined(__GNUC__) -#define _PACK_ATTR __attribute__ ((packed)) -#else -#define _PACK_ATTR -#endif /* defined(__GNUC__) */ - template inline void _PPMD_SWAP(T& t1,T& t2) { T tmp = t1; t1 = t2; t2 = tmp; } diff --git a/7zip/Compress/PPMD/makefile b/7zip/Compress/PPMD/makefile index 9f12f423..2e687a70 100755 --- a/7zip/Compress/PPMD/makefile +++ b/7zip/Compress/PPMD/makefile @@ -16,6 +16,7 @@ COMMON_OBJS = \ 7ZIP_COMMON_OBJS = \ $O\InBuffer.obj \ $O\OutBuffer.obj \ + $O\StreamUtils.obj \ OBJS = \ diff --git a/7zip/Compress/Quantum/QuantumDecoder.cpp b/7zip/Compress/Quantum/QuantumDecoder.cpp new file mode 100755 index 00000000..8dcd736a --- /dev/null +++ b/7zip/Compress/Quantum/QuantumDecoder.cpp @@ -0,0 +1,174 @@ +// QuantumDecoder.cpp + +#include "StdAfx.h" + +#include "QuantumDecoder.h" +#include "../../../Common/Defs.h" + +namespace NCompress { +namespace NQuantum { + +const UInt32 kDictionarySizeMax = (1 << 21); + +const int kLenIdNeedInit = -2; + +void CDecoder::Init() +{ + m_Selector.Init(kNumSelectors); + for (unsigned int i = 0; i < kNumLitSelectors; i++) + m_Literals[i].Init(kNumLitSymbols); + unsigned int numItems = _numDictBits << 1; + m_PosSlot[0].Init(MyMin(numItems, kNumLen3PosSymbolsMax)); + m_PosSlot[1].Init(MyMin(numItems, kNumLen4PosSymbolsMax)); + m_PosSlot[2].Init(MyMin(numItems, kNumLen5PosSymbolsMax)); + m_LenSlot.Init(kNumLenSymbols); +} + +HRESULT CDecoder::CodeSpec(UInt32 curSize) +{ + if (_remainLen == kLenIdNeedInit) + { + if (!_keepHistory) + { + if (!_outWindowStream.Create(_dictionarySize)) + return E_OUTOFMEMORY; + Init(); + } + if (!_rangeDecoder.Create(1 << 20)) + return E_OUTOFMEMORY; + _rangeDecoder.Init(); + _remainLen = 0; + } + if (curSize == 0) + return S_OK; + + while(_remainLen > 0 && curSize > 0) + { + _remainLen--; + Byte b = _outWindowStream.GetByte(_rep0); + _outWindowStream.PutByte(b); + curSize--; + } + + while(curSize > 0) + { + if (_rangeDecoder.Stream.WasFinished()) + return S_FALSE; + + unsigned int selector = m_Selector.Decode(&_rangeDecoder); + if (selector < kNumLitSelectors) + { + Byte b = (Byte)((selector << (8 - kNumLitSelectorBits)) + m_Literals[selector].Decode(&_rangeDecoder)); + _outWindowStream.PutByte(b); + curSize--; + } + else + { + selector -= kNumLitSelectors; + unsigned int len = selector + kMatchMinLen; + if (selector == 2) + { + unsigned int lenSlot = m_LenSlot.Decode(&_rangeDecoder);; + if (lenSlot >= kNumSimpleLenSlots) + { + lenSlot -= 2; + int numDirectBits = (int)(lenSlot >> 2); + len += ((4 | (lenSlot & 3)) << numDirectBits) - 2; + if (numDirectBits < 6) + len += _rangeDecoder.Stream.ReadBits(numDirectBits); + } + else + len += lenSlot; + } + UInt32 rep0 = m_PosSlot[selector].Decode(&_rangeDecoder);; + if (rep0 >= kNumSimplePosSlots) + { + int numDirectBits = (int)((rep0 >> 1) - 1); + rep0 = ((2 | (rep0 & 1)) << numDirectBits) + _rangeDecoder.Stream.ReadBits(numDirectBits); + } + unsigned int locLen = len; + if (len > curSize) + locLen = (unsigned int)curSize; + if (!_outWindowStream.CopyBlock(rep0, locLen)) + return S_FALSE; + curSize -= locLen; + len -= locLen; + if (len != 0) + { + _remainLen = (int)len; + _rep0 = rep0; + break; + } + } + } + return _rangeDecoder.Stream.WasFinished() ? S_FALSE : S_OK; +} + +HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + if (outSize == NULL) + return E_INVALIDARG; + UInt64 size = *outSize; + const UInt64 startSize = size; + + SetInStream(inStream); + _outWindowStream.SetStream(outStream); + SetOutStreamSize(outSize); + CDecoderFlusher flusher(this); + + const UInt64 start = _outWindowStream.GetProcessedSize(); + while(true) + { + UInt32 curSize = 1 << 18; + UInt64 rem = size - (_outWindowStream.GetProcessedSize() - start); + if (curSize > rem) + curSize = (UInt32)rem; + if (curSize == 0) + break; + RINOK(CodeSpec(curSize)); + if (progress != NULL) + { + UInt64 inSize = _rangeDecoder.GetProcessedSize(); + UInt64 nowPos64 = _outWindowStream.GetProcessedSize() - start; + RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); + } + } + flusher.NeedFlush = false; + return Flush(); +} + +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 CLZOutWindowException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) +{ + _rangeDecoder.SetStream(inStream); + return S_OK; +} + +STDMETHODIMP CDecoder::ReleaseInStream() +{ + _rangeDecoder.ReleaseStream(); + return S_OK; +} + +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) +{ + if (outSize == NULL) + return E_FAIL; + _remainLen = kLenIdNeedInit; + _outWindowStream.Init(_keepHistory); + return S_OK; +} + +}} diff --git a/7zip/Compress/Quantum/QuantumDecoder.h b/7zip/Compress/Quantum/QuantumDecoder.h new file mode 100755 index 00000000..2574368f --- /dev/null +++ b/7zip/Compress/Quantum/QuantumDecoder.h @@ -0,0 +1,287 @@ +// QuantumDecoder.h + +#ifndef __QUANTUM_DECODER_H +#define __QUANTUM_DECODER_H + +#include "../../../Common/MyCom.h" + +#include "../../Common/InBuffer.h" +#include "../../ICoder.h" +#include "../LZ/LZOutWindow.h" + +namespace NCompress { +namespace NQuantum { + +class CStreamBitDecoder +{ + UInt32 m_Value; + CInBuffer m_Stream; +public: + bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); } + void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream);} + void ReleaseStream() { m_Stream.ReleaseStream();} + + void Finish() { m_Value = 0x10000; } + + void Init() + { + m_Stream.Init(); + m_Value = 0x10000; + } + + UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize(); } + bool WasFinished() const { return m_Stream.WasFinished(); }; + + UInt32 ReadBit() + { + if (m_Value >= 0x10000) + m_Value = 0x100 | m_Stream.ReadByte(); + UInt32 res = (m_Value >> 7) & 1; + m_Value <<= 1; + return res; + } + + UInt32 ReadBits(int numBits) // numBits > 0 + { + UInt32 res = 0; + do + res = (res << 1) | ReadBit(); + while(--numBits != 0); + return res; + } +}; + +const int kNumLitSelectorBits = 2; +const unsigned int kNumLitSelectors = (1 << kNumLitSelectorBits); +const unsigned int kNumLitSymbols = 1 << (8 - kNumLitSelectorBits); +const unsigned int kNumMatchSelectors = 3; +const unsigned int kNumSelectors = kNumLitSelectors + kNumMatchSelectors; +const unsigned int kNumLen3PosSymbolsMax = 24; +const unsigned int kNumLen4PosSymbolsMax = 36; +const unsigned int kNumLen5PosSymbolsMax = 42; +const unsigned int kNumLenSymbols = 27; + +const unsigned int kNumSymbolsMax = kNumLitSymbols; // 64 + +const unsigned int kMatchMinLen = 3; +const unsigned int kNumSimplePosSlots = 4; +const unsigned int kNumSimpleLenSlots = 6; + +namespace NRangeCoder { + +class CDecoder +{ + UInt32 Low; + UInt32 Range; + UInt32 Code; +public: + CStreamBitDecoder Stream; + bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } + void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } + void ReleaseStream() { Stream.ReleaseStream(); } + + void Init() + { + Stream.Init(); + Low = 0; + Range = 0x10000; + Code = Stream.ReadBits(16); + } + + void Finish() + { + // we need these extra two Bit_reads + Stream.ReadBit(); + Stream.ReadBit(); + Stream.Finish(); + } + + UInt64 GetProcessedSize() const { return Stream.GetProcessedSize(); } + + UInt32 GetThreshold(UInt32 total) const + { + return ((Code + 1) * total - 1) / Range; // & 0xFFFF is not required; + } + + void Decode(UInt32 start, UInt32 end, UInt32 total) + { + UInt32 high = Low + end * Range / total - 1; + UInt32 offset = start * Range / total; + Code -= offset; + Low += offset; + while (true) + { + if ((Low & 0x8000) != (high & 0x8000)) + { + if ((Low & 0x4000) == 0 || (high & 0x4000) != 0) + break; + Low &= 0x3FFF; + high |= 0x4000; + } + Low = (Low << 1) & 0xFFFF; + high = ((high << 1) | 1) & 0xFFFF; + Code = ((Code << 1) | Stream.ReadBit()); + } + Range = high - Low + 1; + } +}; + +const UInt16 kUpdateStep = 8; +const UInt16 kFreqSumMax = 3800; +const UInt16 kReorderCountStart = 4; +const UInt16 kReorderCount = 50; + +class CModelDecoder +{ + unsigned int NumItems; + unsigned int ReorderCount; + UInt16 Freqs[kNumSymbolsMax + 1]; + Byte Values[kNumSymbolsMax]; +public: + void Init(unsigned int numItems) + { + NumItems = numItems; + ReorderCount = kReorderCountStart; + for(unsigned int i = 0; i < numItems; i++) + { + Freqs[i] = (UInt16)(numItems - i); + Values[i] = (Byte)i; + } + Freqs[numItems] = 0; + } + + unsigned int Decode(CDecoder *rangeDecoder) + { + UInt32 threshold = rangeDecoder->GetThreshold(Freqs[0]); + unsigned int i; + for (i = 1; Freqs[i] > threshold; i++); + rangeDecoder->Decode(Freqs[i], Freqs[i - 1], Freqs[0]); + unsigned int res = Values[--i]; + do + Freqs[i] += kUpdateStep; + while(i-- != 0); + + if (Freqs[0] > kFreqSumMax) + { + if (--ReorderCount == 0) + { + ReorderCount = kReorderCount; + for(i = 0; i < NumItems; i++) + Freqs[i] = ((Freqs[i] - Freqs[i + 1]) + 1) >> 1; + for(i = 0; i < NumItems - 1; i++) + for(unsigned int j = i + 1; j < NumItems; j++) + if (Freqs[i] < Freqs[j]) + { + UInt16 tmpFreq = Freqs[i]; + Byte tmpVal = Values[i]; + Freqs[i] = Freqs[j]; + Values[i] = Values[j]; + Freqs[j] = tmpFreq; + Values[j] = tmpVal; + } + do + Freqs[i] += Freqs[i + 1]; + while(i-- != 0); + } + else + { + i = NumItems - 1; + do + { + Freqs[i] >>= 1; + if (Freqs[i] <= Freqs[i + 1]) + Freqs[i] = Freqs[i + 1] + 1; + } + while(i-- != 0); + } + } + return res; + }; +}; + +} + +class CDecoder: + public ICompressCoder, + public ICompressSetInStream, + public ICompressSetOutStreamSize, + public CMyUnknownImp +{ + CLZOutWindow _outWindowStream; + NRangeCoder::CDecoder _rangeDecoder; + + /////////////////// + // State + UInt64 _outSize; + // UInt64 _nowPos64; + int _remainLen; // -1 means end of stream. // -2 means need Init + UInt32 _rep0; + + int _numDictBits; + UInt32 _dictionarySize; + + NRangeCoder::CModelDecoder m_Selector; + NRangeCoder::CModelDecoder m_Literals[kNumLitSelectors]; + NRangeCoder::CModelDecoder m_PosSlot[kNumMatchSelectors]; + NRangeCoder::CModelDecoder m_LenSlot; + + bool _keepHistory; + + void Init(); + HRESULT CodeSpec(UInt32 size); +public: + MY_UNKNOWN_IMP2( + ICompressSetInStream, + ICompressSetOutStreamSize) + + void ReleaseStreams() + { + _outWindowStream.ReleaseStream(); + ReleaseInStream(); + } + + class CDecoderFlusher + { + CDecoder *_decoder; + public: + bool NeedFlush; + CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {} + ~CDecoderFlusher() + { + if (NeedFlush) + _decoder->Flush(); + _decoder->ReleaseStreams(); + } + }; + + HRESULT Flush() { return _outWindowStream.Flush(); } + + HRESULT CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + + void SetParams(int numDictBits) + { + _numDictBits = numDictBits; + _dictionarySize = (UInt32)1 << numDictBits; + } + void SetKeepHistory(bool keepHistory) + { + _keepHistory = keepHistory; + } + + CDecoder(): _keepHistory(false) {} + virtual ~CDecoder() {} +}; + +}} + +#endif diff --git a/7zip/Compress/Rar20/DllExports.cpp b/7zip/Compress/Rar20/DllExports.cpp new file mode 100755 index 00000000..599d71c3 --- /dev/null +++ b/7zip/Compress/Rar20/DllExports.cpp @@ -0,0 +1,66 @@ +// DLLExports.cpp + +#include "StdAfx.h" + +#include "Common/MyInitGuid.h" +#include "Common/ComTry.h" + +#include "Rar20Decoder.h" + +// {23170F69-40C1-278B-0403-020000000000} +DEFINE_GUID(CLSID_CCompressRar20Decoder, +0x23170F69, 0x40C1, 0x278B, 0x04, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00); + +extern "C" +BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) +{ + return TRUE; +} + +STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) +{ + COM_TRY_BEGIN + *outObject = 0; + if (*clsid != CLSID_CCompressRar20Decoder) + return CLASS_E_CLASSNOTAVAILABLE; + if (*iid != IID_ICompressCoder) + return E_NOINTERFACE; + CMyComPtr coder = (ICompressCoder *)new + NCompress::NRar20::CDecoder; + *outObject = coder.Detach(); + COM_TRY_END + return S_OK; +} + +STDAPI GetNumberOfMethods(UINT32 *numMethods) +{ + *numMethods = 1; + return S_OK; +} + +STDAPI GetMethodProperty(UINT32 index, PROPID propID, PROPVARIANT *value) +{ + if (index != 0) + return E_INVALIDARG; + ::VariantClear((tagVARIANT *)value); + switch(propID) + { + case NMethodPropID::kID: + { + const char id[] = { 0x04, 0x03, 0x02 }; + if ((value->bstrVal = ::SysAllocStringByteLen(id, sizeof(id))) != 0) + value->vt = VT_BSTR; + return S_OK; + } + case NMethodPropID::kName: + if ((value->bstrVal = ::SysAllocString(L"Rar20")) != 0) + value->vt = VT_BSTR; + return S_OK; + case NMethodPropID::kDecoder: + if ((value->bstrVal = ::SysAllocStringByteLen( + (const char *)&CLSID_CCompressRar20Decoder, sizeof(GUID))) != 0) + value->vt = VT_BSTR; + return S_OK; + } + return S_OK; +} diff --git a/7zip/Compress/Rar20/Rar20Const.h b/7zip/Compress/Rar20/Rar20Const.h new file mode 100755 index 00000000..6c5fecb6 --- /dev/null +++ b/7zip/Compress/Rar20/Rar20Const.h @@ -0,0 +1,65 @@ +// Rar20CoderConst.h +// According to unRAR license, +// this code may not be used to develop a +// RAR (WinRAR) compatible archiver + +#ifndef __RAR20_CONST_H +#define __RAR20_CONST_H + +#include "Rar20ExtConst.h" + +namespace NCompress { +namespace NRar20 { + +const UInt32 kMainTableSize = 298; +const UInt32 kLenTableSize = 28; + +const UInt32 kDistTableStart = kMainTableSize; +const UInt32 kLenTableStart = kDistTableStart + kDistTableSize; + +const UInt32 kHeapTablesSizesSum = kMainTableSize + kDistTableSize + kLenTableSize; + +const UInt32 kLevelTableSize = 19; + +const UInt32 kMMTablesSizesSum = kMMTableSize * 4; + +const UInt32 kMaxTableSize = kMMTablesSizesSum; + +const UInt32 kTableDirectLevels = 16; +const UInt32 kTableLevelRepNumber = kTableDirectLevels; +const UInt32 kTableLevel0Number = kTableLevelRepNumber + 1; +const UInt32 kTableLevel0Number2 = kTableLevel0Number + 1; + +const UInt32 kLevelMask = 0xF; + + +const UInt32 kRepBothNumber = 256; +const UInt32 kRepNumber = kRepBothNumber + 1; +const UInt32 kLen2Number = kRepNumber + 4; + +const UInt32 kLen2NumNumbers = 8; +const UInt32 kReadTableNumber = kLen2Number + kLen2NumNumbers; +const UInt32 kMatchNumber = kReadTableNumber + 1; + +const Byte kLenStart[kLenTableSize] = {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224}; +const Byte kLenDirectBits[kLenTableSize] = {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5}; + +const UInt32 kDistStart[kDistTableSize] = {0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040}; +const Byte kDistDirectBits[kDistTableSize] = {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; + +const Byte kLevelDirectBits[kLevelTableSize] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7}; + +const Byte kLen2DistStarts[kLen2NumNumbers]={0,4,8,16,32,64,128,192}; +const Byte kLen2DistDirectBits[kLen2NumNumbers]={2,2,3, 4, 5, 6, 6, 6}; + +const UInt32 kDistLimit2 = 0x101 - 1; +const UInt32 kDistLimit3 = 0x2000 - 1; +const UInt32 kDistLimit4 = 0x40000 - 1; + +const UInt32 kMatchMaxLen = 255 + 2; +const UInt32 kMatchMaxLenMax = 255 + 5; +const UInt32 kNormalMatchMinLen = 3; + +}} + +#endif diff --git a/7zip/Compress/Rar20/Rar20Decoder.cpp b/7zip/Compress/Rar20/Rar20Decoder.cpp new file mode 100755 index 00000000..8da544f7 --- /dev/null +++ b/7zip/Compress/Rar20/Rar20Decoder.cpp @@ -0,0 +1,319 @@ +// Rar20Decoder.cpp +// According to unRAR license, +// this code may not be used to develop a +// RAR (WinRAR) compatible archiver + +#include "StdAfx.h" + +#include "Rar20Decoder.h" +#include "Rar20Const.h" + +namespace NCompress { +namespace NRar20 { + +class CException +{ +public: + enum ECauseType + { + kData + } Cause; + CException(ECauseType cause): Cause(cause) {} +}; + +static const char *kNumberErrorMessage = "Number error"; + +static const UInt32 kHistorySize = 1 << 20; + +static const int kNumStats = 11; + +static const UInt32 kWindowReservSize = (1 << 22) + 256; + +CDecoder::CDecoder(): + m_IsSolid(false) +{ +} + +void CDecoder::InitStructures() +{ + m_Predictor.Init(); + for(int i = 0; i < kNumRepDists; i++) + m_RepDists[i] = 0; + m_RepDistPtr = 0; + m_LastLength = 0; + memset(m_LastLevels, 0, kMaxTableSize); +} + +#define RIF(x) { if (!(x)) return false; } + +bool CDecoder::ReadTables(void) +{ + Byte levelLevels[kLevelTableSize]; + Byte newLevels[kMaxTableSize]; + m_AudioMode = (m_InBitStream.ReadBits(1) == 1); + + if (m_InBitStream.ReadBits(1) == 0) + memset(m_LastLevels, 0, kMaxTableSize); + int numLevels; + if (m_AudioMode) + { + m_NumChannels = m_InBitStream.ReadBits(2) + 1; + if (m_Predictor.CurrentChannel >= m_NumChannels) + m_Predictor.CurrentChannel = 0; + numLevels = m_NumChannels * kMMTableSize; + } + else + numLevels = kHeapTablesSizesSum; + + int i; + for (i = 0; i < kLevelTableSize; i++) + levelLevels[i] = Byte(m_InBitStream.ReadBits(4)); + RIF(m_LevelDecoder.SetCodeLengths(levelLevels)); + i = 0; + while (i < numLevels) + { + UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream); + if (number < kTableDirectLevels) + { + newLevels[i] = Byte((number + m_LastLevels[i]) & kLevelMask); + i++; + } + else + { + if (number == kTableLevelRepNumber) + { + int t = m_InBitStream.ReadBits(2) + 3; + for (int reps = t; reps > 0 && i < numLevels ; reps--, i++) + newLevels[i] = newLevels[i - 1]; + } + else + { + int num; + if (number == kTableLevel0Number) + num = m_InBitStream.ReadBits(3) + 3; + else if (number == kTableLevel0Number2) + num = m_InBitStream.ReadBits(7) + 11; + else + return false; + for (;num > 0 && i < numLevels; num--) + newLevels[i++] = 0; + } + } + } + if (m_AudioMode) + for (i = 0; i < m_NumChannels; i++) + { + RIF(m_MMDecoders[i].SetCodeLengths(&newLevels[i * kMMTableSize])); + } + else + { + RIF(m_MainDecoder.SetCodeLengths(&newLevels[0])); + RIF(m_DistDecoder.SetCodeLengths(&newLevels[kMainTableSize])); + RIF(m_LenDecoder.SetCodeLengths(&newLevels[kMainTableSize + kDistTableSize])); + } + memcpy(m_LastLevels, newLevels, kMaxTableSize); + return true; +} + +bool CDecoder::ReadLastTables() +{ + // it differs a little from pure RAR sources; + // UInt64 ttt = m_InBitStream.GetProcessedSize() + 2; + // + 2 works for: return 0xFF; in CInBuffer::ReadByte. + if (m_InBitStream.GetProcessedSize() + 7 <= m_PackSize) // test it: probably incorrect; + // if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect; + if (m_AudioMode) + { + UInt32 symbol = m_MMDecoders[m_Predictor.CurrentChannel].DecodeSymbol(&m_InBitStream); + if (symbol == 256) + return ReadTables(); + if (symbol >= kMMTableSize) + return false; + } + else + { + UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream); + if (number == kReadTableNumber) + return ReadTables(); + if (number >= kMainTableSize) + return false; + } + return true; +} + +class CCoderReleaser +{ + CDecoder *m_Coder; +public: + CCoderReleaser(CDecoder *coder): m_Coder(coder) {} + ~CCoderReleaser() + { + m_Coder->ReleaseStreams(); + } +}; + +STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + if (inSize == NULL || outSize == NULL) + return E_INVALIDARG; + + if (!m_OutWindowStream.Create(kHistorySize)) + return E_OUTOFMEMORY; + if (!m_InBitStream.Create(1 << 20)) + return E_OUTOFMEMORY; + + m_PackSize = *inSize; + + UInt64 pos = 0, unPackSize = *outSize; + + m_OutWindowStream.SetStream(outStream); + m_OutWindowStream.Init(m_IsSolid); + m_InBitStream.SetStream(inStream); + m_InBitStream.Init(); + + CCoderReleaser coderReleaser(this); + if (!m_IsSolid) + { + InitStructures(); + if (unPackSize == 0) + { + if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect; + if (!ReadTables()) + return S_FALSE; + return S_OK; + } + if (!ReadTables()) + return S_FALSE; + } + + while(pos < unPackSize) + { + if (m_AudioMode) + while(pos < unPackSize) + { + UInt32 symbol = m_MMDecoders[m_Predictor.CurrentChannel].DecodeSymbol(&m_InBitStream); + if (symbol == 256) + { + if (progress != 0) + { + UInt64 packSize = m_InBitStream.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&packSize, &pos)); + } + if (!ReadTables()) + return S_FALSE; + break; + } + if (symbol >= kMMTableSize) + return S_FALSE; + Byte byPredict = m_Predictor.Predict(); + Byte byReal = byPredict - Byte(symbol); + m_Predictor.Update(byReal, byPredict); + m_OutWindowStream.PutByte(byReal); + if (++m_Predictor.CurrentChannel == m_NumChannels) + m_Predictor.CurrentChannel = 0; + pos++; + } + else + while(pos < unPackSize) + { + UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream); + UInt32 length, distance; + if (number < 256) + { + m_OutWindowStream.PutByte(Byte(number)); + pos++; + continue; + } + else if (number >= kMatchNumber) + { + number -= kMatchNumber; + length = kNormalMatchMinLen + UInt32(kLenStart[number]) + + m_InBitStream.ReadBits(kLenDirectBits[number]); + number = m_DistDecoder.DecodeSymbol(&m_InBitStream); + if (number >= kDistTableSize) + return S_FALSE; + distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]); + if (distance >= kDistLimit3) + { + length += 2 - ((distance - kDistLimit4) >> 31); + // length++; + // if (distance >= kDistLimit4) + // length++; + } + } + else if (number == kRepBothNumber) + { + length = m_LastLength; + distance = m_RepDists[(m_RepDistPtr + 4 - 1) & 3]; + } + else if (number < kLen2Number) + { + distance = m_RepDists[(m_RepDistPtr - (number - kRepNumber + 1)) & 3]; + number = m_LenDecoder.DecodeSymbol(&m_InBitStream); + if (number >= kLenTableSize) + return S_FALSE; + length = 2 + kLenStart[number] + m_InBitStream.ReadBits(kLenDirectBits[number]); + if (distance >= kDistLimit2) + { + length++; + if (distance >= kDistLimit3) + { + length += 2 - ((distance - kDistLimit4) >> 31); + // length++; + // if (distance >= kDistLimit4) + // length++; + } + } + } + else if (number < kReadTableNumber) + { + number -= kLen2Number; + distance = kLen2DistStarts[number] + + m_InBitStream.ReadBits(kLen2DistDirectBits[number]); + length = 2; + } + else if (number == kReadTableNumber) + { + if (progress != 0) + { + UInt64 packSize = m_InBitStream.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&packSize, &pos)); + } + if (!ReadTables()) + return S_FALSE; + break; + } + else + return S_FALSE; + CopyBackBlockOp(distance, length); + pos += length; + } + } + if (pos > unPackSize) + throw CException(CException::kData); + + if (!ReadLastTables()) + return S_FALSE; + return m_OutWindowStream.Flush(); +} + +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 CLZOutWindowException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) +{ + if (size < 1) + return E_INVALIDARG; + m_IsSolid = (data[0] != 0); + return S_OK; +} + +}} diff --git a/7zip/Compress/Rar20/Rar20Decoder.h b/7zip/Compress/Rar20/Rar20Decoder.h new file mode 100755 index 00000000..071b3635 --- /dev/null +++ b/7zip/Compress/Rar20/Rar20Decoder.h @@ -0,0 +1,95 @@ +// Rar20Decoder.h +// According to unRAR license, +// this code may not be used to develop a +// RAR (WinRAR) compatible archiver + +#ifndef __RAR20_DECODER_H +#define __RAR20_DECODER_H + +#include "../../../Common/MyCom.h" + +#include "../../ICoder.h" +#include "../../Common/MSBFDecoder.h" +#include "../../Common/InBuffer.h" + +#include "../LZ/LZOutWindow.h" +#include "../Huffman/HuffmanDecoder.h" + +#include "Rar20Multimedia.h" +#include "Rar20Const.h" + +namespace NCompress { +namespace NRar20 { + +typedef NStream::NMSBF::CDecoder CBitDecoder; + +const int kNumHuffmanBits = 15; + +class CDecoder : + public ICompressCoder, + public ICompressSetDecoderProperties2, + public CMyUnknownImp +{ + CLZOutWindow m_OutWindowStream; + CBitDecoder m_InBitStream; + NHuffman::CDecoder m_MainDecoder; + NHuffman::CDecoder m_DistDecoder; + NHuffman::CDecoder m_LenDecoder; + NHuffman::CDecoder m_MMDecoders[NMultimedia::kNumChanelsMax]; + NHuffman::CDecoder m_LevelDecoder; + + bool m_AudioMode; + + NMultimedia::CPredictor m_Predictor; + int m_NumChannels; + + UInt32 m_RepDists[kNumRepDists]; + UInt32 m_RepDistPtr; + + UInt32 m_LastLength; + + Byte m_LastLevels[kMaxTableSize]; + + UInt64 m_PackSize; + bool m_IsSolid; + + void InitStructures(); + bool ReadTables(); + bool ReadLastTables(); + void CopyBackBlockOp(UInt32 aDistance, UInt32 aLength) + { + /* + if(m_Position <= aDistance) + throw CDecoderException(CDecoderException::kData); + */ + m_RepDists[m_RepDistPtr++ & 3] = aDistance; + m_LastLength = aLength; + m_OutWindowStream.CopyBlock(aDistance, aLength); + } + +public: + CDecoder(); + + MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2) + + void ReleaseStreams() + { + m_OutWindowStream.ReleaseStream(); + m_InBitStream.ReleaseStream(); + } + + STDMETHOD(CodeReal)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + +}; + +}} + +#endif diff --git a/7zip/Compress/Rar20/Rar20ExtConst.h b/7zip/Compress/Rar20/Rar20ExtConst.h new file mode 100755 index 00000000..b74bc0cf --- /dev/null +++ b/7zip/Compress/Rar20/Rar20ExtConst.h @@ -0,0 +1,21 @@ +// Rar20ExtConst.h +// According to unRAR license, +// this code may not be used to develop a +// RAR (WinRAR) compatible archiver + +#ifndef __RAR20_EXTCONST_H +#define __RAR20_EXTCONST_H + +#include "../../../Common/Types.h" + +namespace NCompress { +namespace NRar20 { + +const UInt32 kNumRepDists = 4; +const UInt32 kDistTableSize = 48; + +const int kMMTableSize = 256 + 1; + +}} + +#endif diff --git a/7zip/Compress/Rar20/Rar20Multimedia.cpp b/7zip/Compress/Rar20/Rar20Multimedia.cpp new file mode 100755 index 00000000..3c0a13af --- /dev/null +++ b/7zip/Compress/Rar20/Rar20Multimedia.cpp @@ -0,0 +1,128 @@ +// Rar20Multimedia.cpp +// According to unRAR license, +// this code may not be used to develop a +// RAR (WinRAR) compatible archiver + +#include "StdAfx.h" + +#include "Rar20Multimedia.h" + +namespace NCompress { +namespace NRar20 { +namespace NMultimedia { + +void CAudioVariables::Init() +{ + memset(this, 0, sizeof(CAudioVariables)); +} + +void CPredictor::Init() +{ + for(int i = 0; i < kNumChanelsMax; i++) + m_AudioVariablesArray[i].Init(); + m_ChannelDelta = 0; + CurrentChannel = 0; +} + +Byte CPredictor::Predict() +{ + CAudioVariables *v = &m_AudioVariablesArray[CurrentChannel]; + v->ByteCount++; + v->D4 = v->D3; + v->D3 = v->D2; + v->D2 = v->LastDelta-v->D1; + v->D1 = v->LastDelta; + int pCh = 8 * v->LastChar + + v->K1 * v->D1 + + v->K2 * v->D2 + + v->K3 * v->D3 + + v->K4 * v->D4 + + v->K5*m_ChannelDelta; + pCh = (pCh >> 3) & 0xFF; + return Byte(pCh); +} + +void CPredictor::Update(Byte realValue, int predictedValue) +{ + struct CAudioVariables *v = &m_AudioVariablesArray[CurrentChannel]; + + int delta = predictedValue - realValue; + int i = ((signed char)delta) << 3; + + v->Dif[0] += abs(i); + v->Dif[1] += abs(i - v->D1); + v->Dif[2] += abs(i + v->D1); + v->Dif[3] += abs(i - v->D2); + v->Dif[4] += abs(i + v->D2); + v->Dif[5] += abs(i - v->D3); + v->Dif[6] += abs(i + v->D3); + v->Dif[7] += abs(i - v->D4); + v->Dif[8] += abs(i + v->D4); + v->Dif[9] += abs(i - m_ChannelDelta); + v->Dif[10] += abs(i + m_ChannelDelta); + + m_ChannelDelta = v->LastDelta = (signed char)(realValue - v->LastChar); + v->LastChar = realValue; + + UInt32 numMinDif, minDif; + if ((v->ByteCount & 0x1F)==0) + { + minDif = v->Dif[0]; + numMinDif = 0; + v->Dif[0] = 0; + for (i = 1; i < sizeof(v->Dif) / sizeof(v->Dif[0]); i++) + { + if (v->Dif[i] < minDif) + { + minDif = v->Dif[i]; + numMinDif = i; + } + v->Dif[i] = 0; + } + switch(numMinDif) + { + case 1: + if (v->K1 >= -16) + v->K1--; + break; + case 2: + if (v->K1 < 16) + v->K1++; + break; + case 3: + if (v->K2 >= -16) + v->K2--; + break; + case 4: + if (v->K2 < 16) + v->K2++; + break; + case 5: + if (v->K3 >= -16) + v->K3--; + break; + case 6: + if (v->K3 < 16) + v->K3++; + break; + case 7: + if (v->K4 >= -16) + v->K4--; + break; + case 8: + if (v->K4 < 16) + v->K4++; + break; + case 9: + if (v->K5 >= -16) + v->K5--; + break; + case 10: + if (v->K5 < 16) + v->K5++; + break; + } + } +} + +}}} diff --git a/7zip/Compress/Rar20/Rar20Multimedia.h b/7zip/Compress/Rar20/Rar20Multimedia.h new file mode 100755 index 00000000..7af86d07 --- /dev/null +++ b/7zip/Compress/Rar20/Rar20Multimedia.h @@ -0,0 +1,43 @@ +// Rar20Multimedia.h +// According to unRAR license, +// this code may not be used to develop a +// RAR (WinRAR) compatible archiver + +#ifndef __RAR20_MULTIMEDIA_H +#define __RAR20_MULTIMEDIA_H + +#include "../../../Common/Types.h" + +namespace NCompress { +namespace NRar20 { +namespace NMultimedia { + +struct CAudioVariables +{ + int K1,K2,K3,K4,K5; + int D1,D2,D3,D4; + int LastDelta; + UInt32 Dif[11]; + UInt32 ByteCount; + int LastChar; + + void Init(); +}; + +const int kNumChanelsMax = 4; + +class CPredictor +{ + CAudioVariables m_AudioVariablesArray[kNumChanelsMax]; + int m_ChannelDelta; +public: + int CurrentChannel; + + void Init(); + Byte Predict(); + void Update(Byte realValue, int predictedValue); +}; + +}}} + +#endif diff --git a/7zip/Compress/Rar20/StdAfx.cpp b/7zip/Compress/Rar20/StdAfx.cpp new file mode 100755 index 00000000..d0feea85 --- /dev/null +++ b/7zip/Compress/Rar20/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/7zip/Compress/Rar20/StdAfx.h b/7zip/Compress/Rar20/StdAfx.h new file mode 100755 index 00000000..e7fb6986 --- /dev/null +++ b/7zip/Compress/Rar20/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" + +#endif diff --git a/7zip/Compress/Rar29/DllExports.cpp b/7zip/Compress/Rar29/DllExports.cpp new file mode 100755 index 00000000..ed5197f8 --- /dev/null +++ b/7zip/Compress/Rar29/DllExports.cpp @@ -0,0 +1,105 @@ +// DLLExports.cpp + +#include "StdAfx.h" + +#include "Common/MyInitGuid.h" +#include "Common/ComTry.h" + +#include "../Rar20/Rar20Decoder.h" +#include "Rar29Decoder.h" + +// {23170F69-40C1-278B-0403-010000000000} +DEFINE_GUID(CLSID_CCompressRar15Decoder, +0x23170F69, 0x40C1, 0x278B, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00); + +// {23170F69-40C1-278B-0403-020000000000} +DEFINE_GUID(CLSID_CCompressRar20Decoder, +0x23170F69, 0x40C1, 0x278B, 0x04, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00); + +// {23170F69-40C1-278B-0403-030000000000} +DEFINE_GUID(CLSID_CCompressRar29Decoder, +0x23170F69, 0x40C1, 0x278B, 0x04, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00); + +extern "C" +BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) +{ + return TRUE; +} + +STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) +{ + COM_TRY_BEGIN + *outObject = 0; + + int correctInterface = (*iid == IID_ICompressCoder); + CMyComPtr coder; + if (*clsid == CLSID_CCompressRar15Decoder) + { + if (!correctInterface) + return E_NOINTERFACE; + coder = (ICompressCoder *)new NCompress::NRar15::CDecoder; + } + else if (*clsid == CLSID_CCompressRar20Decoder) + { + if (!correctInterface) + return E_NOINTERFACE; + coder = (ICompressCoder *)new NCompress::NRar20::CDecoder; + } + else if (*clsid == CLSID_CCompressRar29Decoder) + { + if (!correctInterface) + return E_NOINTERFACE; + coder = (ICompressCoder *)new NCompress::NRar29::CDecoder; + } + else + return CLASS_E_CLASSNOTAVAILABLE; + *outObject = coder.Detach(); + COM_TRY_END + return S_OK; +} + +struct CRarMethodItem +{ + char ID[3]; + const wchar_t *UserName; + const GUID *Decoder; +}; + +static CRarMethodItem g_Methods[] = +{ + { { 0x04, 0x03, 0x01 }, L"Rar15", &CLSID_CCompressRar15Decoder }, + { { 0x04, 0x03, 0x02 }, L"Rar20", &CLSID_CCompressRar20Decoder }, + { { 0x04, 0x03, 0x03 }, L"Rar29", &CLSID_CCompressRar29Decoder } +}; + +STDAPI GetNumberOfMethods(UINT32 *numMethods) +{ + *numMethods = sizeof(g_Methods) / sizeof(g_Methods[1]); + return S_OK; +} + +STDAPI GetMethodProperty(UINT32 index, PROPID propID, PROPVARIANT *value) +{ + if (index > sizeof(g_Methods) / sizeof(g_Methods[1])) + return E_INVALIDARG; + VariantClear((tagVARIANT *)value); + const CRarMethodItem &method = g_Methods[index]; + switch(propID) + { + case NMethodPropID::kID: + if ((value->bstrVal = ::SysAllocStringByteLen(method.ID, + sizeof(method.ID))) != 0) + value->vt = VT_BSTR; + return S_OK; + case NMethodPropID::kName: + if ((value->bstrVal = ::SysAllocString(method.UserName)) != 0) + value->vt = VT_BSTR; + return S_OK; + case NMethodPropID::kDecoder: + if ((value->bstrVal = ::SysAllocStringByteLen( + (const char *)method.Decoder, sizeof(GUID))) != 0) + value->vt = VT_BSTR; + return S_OK; + } + return S_OK; +} diff --git a/7zip/Compress/Rar29/Original/archive.hpp b/7zip/Compress/Rar29/Original/archive.hpp new file mode 100755 index 00000000..c076b5b7 --- /dev/null +++ b/7zip/Compress/Rar29/Original/archive.hpp @@ -0,0 +1,128 @@ +#ifndef _RAR_ARCHIVE_ +#define _RAR_ARCHIVE_ + +class Pack; + +enum {EN_LOCK=1,EN_VOL=2,EN_FIRSTVOL=4}; + +class Archive:public File +{ + private: + bool IsSignature(byte *D); + void UpdateLatestTime(FileHeader *CurBlock); + void Protect(int RecSectors); + void ConvertNameCase(char *Name); + void ConvertNameCase(wchar *Name); + void ConvertUnknownHeader(); + bool AddArcComment(char *NameToShow); + int ReadOldHeader(); + void PrepareExtraTime(FileHeader *hd,EXTTIME_MODE etm,EXTTIME_MODE etc,EXTTIME_MODE eta,EXTTIME_MODE etarc,Array &TimeData); + +#if !defined(SHELL_EXT) && !defined(NOCRYPT) + CryptData HeadersCrypt; + byte HeadersSalt[SALT_SIZE]; +#endif +#ifndef SHELL_EXT + ComprDataIO SubDataIO; + byte SubDataSalt[SALT_SIZE]; +#endif + RAROptions *Cmd,DummyCmd; + + MarkHeader MarkHead; + OldMainHeader OldMhd; + + int RecoverySectors; + Int64 RecoveryPos; + + RarTime LatestTime; + int LastReadBlock; + int CurHeaderType; + + bool SilentOpen; + public: + Archive(RAROptions *InitCmd=NULL); + bool IsArchive(bool EnableBroken); + int SearchBlock(int BlockType); + int SearchSubBlock(const char *Type); + int ReadBlock(int BlockType); + void WriteBlock(int BlockType,BaseBlock *wb=NULL); + int PrepareNamesToWrite(char *Name,wchar *NameW,char *DestName,byte *DestNameW); + void SetLhdSize(); + int ReadHeader(); + void CheckArc(bool EnableBroken); + void CheckOpen(char *Name,wchar *NameW=NULL); + bool WCheckOpen(char *Name,wchar *NameW=NULL); + bool TestLock(int Mode); + void MakeTemp(); + void CopyMainHeader(Archive &Src,bool CopySFX=true,char *NameToDisplay=NULL); + bool ProcessToFileHead(Archive &Src,bool LastBlockAdded, + Pack *Pack=NULL,const char *SkipName=NULL); + void TmpToArc(Archive &Src); + void CloseNew(int AdjustRecovery,bool CloseVolume); + void WriteEndBlock(bool CloseVolume); + void CopyFileRecord(Archive &Src); + void CopyArchiveData(Archive &Src); + bool GetComment(Array &CmtData); + void ViewComment(); + void ViewFileComment(); + void SetLatestTime(RarTime *NewTime); + void SeekToNext(); + bool CheckAccess(); + bool IsArcDir(); + bool IsArcLabel(); + void ConvertAttributes(); + int GetRecoverySize(bool Required); + void VolSubtractHeaderSize(int SubSize); + void AddSubData(byte *SrcData,int DataSize,File *SrcFile,char *Name,bool AllowSplit); + bool ReadSubData(Array *UnpData,File *DestFile); + int GetHeaderType() {return(CurHeaderType);}; + int ReadCommentData(Array &CmtData); + void WriteCommentData(byte *Data,int DataSize,bool FileComment); + RAROptions* GetRAROptions() {return(Cmd);} + void SetSilentOpen(bool Mode) {SilentOpen=Mode;} + + BaseBlock ShortBlock; + MainHeader NewMhd; + FileHeader NewLhd; + EndArcHeader EndArcHead; + SubBlockHeader SubBlockHead; + FileHeader SubHead; + CommentHeader CommHead; + ProtectHeader ProtectHead; + AVHeader AVHead; + SignHeader SignHead; + UnixOwnersHeader UOHead; + MacFInfoHeader MACHead; + EAHeader EAHead; + StreamHeader StreamHead; + + Int64 CurBlockPos; + Int64 NextBlockPos; + + bool OldFormat; + bool Solid; + bool Volume; + bool MainComment; + bool Locked; + bool Signed; + bool NotFirstVolume; + bool Protected; + bool Encrypted; + uint SFXSize; + bool BrokenFileHeader; + + bool Splitting; + + ushort HeaderCRC; + + Int64 VolWrite; + Int64 AddingFilesSize; + uint AddingHeadersSize; + + bool NewArchive; + + char FirstVolumeName[NM]; + wchar FirstVolumeNameW[NM]; +}; + +#endif diff --git a/7zip/Compress/Rar29/Original/array.hpp b/7zip/Compress/Rar29/Original/array.hpp new file mode 100755 index 00000000..3afec70c --- /dev/null +++ b/7zip/Compress/Rar29/Original/array.hpp @@ -0,0 +1,121 @@ +#ifndef _RAR_ARRAY_ +#define _RAR_ARRAY_ + +extern ErrorHandler ErrHandler; + +template class Array +{ + private: + T *Buffer; + int BufSize; + int AllocSize; + public: + Array(); + Array(int Size); + ~Array(); + inline void CleanData(); + inline T& operator [](int Item); + inline int Size(); + void Add(int Items); + void Alloc(int Items); + void Reset(); + void operator = (Array &Src); + void Push(T Item); +}; + +template void Array::CleanData() +{ + Buffer=NULL; + BufSize=0; + AllocSize=0; +} + + +template Array::Array() +{ + CleanData(); +} + + +template Array::Array(int Size) +{ + Buffer=(T *)rarmalloc(sizeof(T)*Size); + if (Buffer==NULL && Size!=0) + ErrHandler.MemoryError(); + + AllocSize=BufSize=Size; +} + + +template Array::~Array() +{ + if (Buffer!=NULL) + rarfree(Buffer); +} + + +template inline T& Array::operator [](int Item) +{ + return(Buffer[Item]); +} + + +template inline int Array::Size() +{ + return(BufSize); +} + + +template void Array::Add(int Items) +{ + BufSize+=Items; + if (BufSize>AllocSize) + { + int Suggested=AllocSize+AllocSize/4+32; + int NewSize=Max(BufSize,Suggested); + + Buffer=(T *)rarrealloc(Buffer,NewSize*sizeof(T)); + if (Buffer==NULL) + ErrHandler.MemoryError(); + AllocSize=NewSize; + } +} + + +template void Array::Alloc(int Items) +{ + if (Items>AllocSize) + Add(Items-BufSize); + else + BufSize=Items; +} + + +template void Array::Reset() +{ + if (Buffer!=NULL) + { + rarfree(Buffer); + Buffer=NULL; + } + BufSize=0; + AllocSize=0; +} + + +template void Array::operator =(Array &Src) +{ + Reset(); + Alloc(Src.BufSize); + if (Src.BufSize!=0) + memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T)); +} + + +template void Array::Push(T Item) +{ + Add(1); + (*this)[Size()-1]=Item; +} + +#endif diff --git a/7zip/Compress/Rar29/Original/cmddata.hpp b/7zip/Compress/Rar29/Original/cmddata.hpp new file mode 100755 index 00000000..08b92c11 --- /dev/null +++ b/7zip/Compress/Rar29/Original/cmddata.hpp @@ -0,0 +1,56 @@ +#ifndef _RAR_CMDDATA_ +#define _RAR_CMDDATA_ + +#define DefaultStoreList "ace;arj;bz2;cab;gz;jpeg;jpg;lha;lzh;mp3;rar;zip;taz;tgz;z" + +class CommandData:public RAROptions +{ + private: + void ProcessSwitchesString(char *Str); + void ProcessSwitch(char *Switch); + void BadSwitch(char *Switch); + bool ExclCheckArgs(StringList *Args,char *CheckName,bool CheckFullPath,int MatchMode); + uint GetExclAttr(char *Str); + + bool FileLists; + bool NoMoreSwitches; + bool TimeConverted; + bool BareOutput; + public: + CommandData(); + ~CommandData(); + void Init(); + void Close(); + void ParseArg(char *Arg,wchar *ArgW); + void ParseDone(); + void ParseEnvVar(); + void ReadConfig(int argc,char *argv[]); + bool IsConfigEnabled(int argc,char *argv[]); + void OutTitle(); + void OutHelp(); + bool IsSwitch(int Ch); + bool ExclCheck(char *CheckName,bool CheckFullPath); + bool StoreCheck(char *CheckName); + bool TimeCheck(RarTime &ft); + int IsProcessFile(FileHeader &NewLhd,bool *ExactMatch=NULL,int MatchType=MATCH_WILDSUBPATH); + void ProcessCommand(); + void AddArcName(char *Name,wchar *NameW); + bool GetArcName(char *Name,wchar *NameW,int MaxSize); + bool CheckWinSize(); + + int GetRecoverySize(char *Str,int DefSize); + + char Command[NM+16]; + wchar CommandW[NM+16]; + + char ArcName[NM]; + wchar ArcNameW[NM]; + + StringList *FileArgs; + StringList *ExclArgs; + StringList *InclArgs; + StringList *ArcNames; + StringList *StoreArgs; +}; + +#endif diff --git a/7zip/Compress/Rar29/Original/coder.cpp b/7zip/Compress/Rar29/Original/coder.cpp new file mode 100755 index 00000000..cb6a8836 --- /dev/null +++ b/7zip/Compress/Rar29/Original/coder.cpp @@ -0,0 +1,47 @@ + + +inline unsigned int RangeCoder::GetChar() +{ + return(UnpackRead->GetChar()); +} + + +void RangeCoder::InitDecoder(Unpack *UnpackRead) +{ + RangeCoder::UnpackRead=UnpackRead; + + low=code=0; + range=uint(-1); + for (int i=0;i < 4;i++) + code=(code << 8) | GetChar(); +} + + +#define ARI_DEC_NORMALIZE(code,low,range,read) \ +{ \ + while ((low^(low+range))GetChar(); \ + range <<= 8; \ + low <<= 8; \ + } \ +} + + +inline int RangeCoder::GetCurrentCount() +{ + return (code-low)/(range /= SubRange.scale); +} + + +inline uint RangeCoder::GetCurrentShiftCount(uint SHIFT) +{ + return (code-low)/(range >>= SHIFT); +} + + +inline void RangeCoder::Decode() +{ + low += range*SubRange.LowCount; + range *= SubRange.HighCount-SubRange.LowCount; +} diff --git a/7zip/Compress/Rar29/Original/coder.hpp b/7zip/Compress/Rar29/Original/coder.hpp new file mode 100755 index 00000000..f09f911c --- /dev/null +++ b/7zip/Compress/Rar29/Original/coder.hpp @@ -0,0 +1,24 @@ +/**************************************************************************** + * Contents: 'Carryless rangecoder' by Dmitry Subbotin * + ****************************************************************************/ + +const uint TOP=1 << 24, BOT=1 << 15; + +class RangeCoder +{ + public: + void InitDecoder(Unpack *UnpackRead); + inline int GetCurrentCount(); + inline uint GetCurrentShiftCount(uint SHIFT); + inline void Decode(); + inline void PutChar(unsigned int c); + inline unsigned int GetChar(); + + uint low, code, range; + struct SUBRANGE + { + uint LowCount, HighCount, scale; + } SubRange; + + Unpack *UnpackRead; +}; diff --git a/7zip/Compress/Rar29/Original/compress.hpp b/7zip/Compress/Rar29/Original/compress.hpp new file mode 100755 index 00000000..2ba7b23e --- /dev/null +++ b/7zip/Compress/Rar29/Original/compress.hpp @@ -0,0 +1,36 @@ +#ifndef _RAR_COMPRESS_ +#define _RAR_COMPRESS_ + +class ComprDataIO; +class PackingFileTable; + +#define CODEBUFSIZE 0x4000 +#define MAXWINSIZE 0x400000 +#define MAXWINMASK (MAXWINSIZE-1) + +#define LOW_DIST_REP_COUNT 16 + +#define NC 299 /* alphabet = {0, 1, 2, ..., NC - 1} */ +#define DC 60 +#define LDC 17 +#define RC 28 +#define HUFF_TABLE_SIZE (NC+DC+RC+LDC) +#define BC 20 + +#define NC20 298 /* alphabet = {0, 1, 2, ..., NC - 1} */ +#define DC20 48 +#define RC20 28 +#define BC20 19 +#define MC20 257 + +enum {CODE_HUFFMAN,CODE_LZ,CODE_LZ2,CODE_REPEATLZ,CODE_CACHELZ, + CODE_STARTFILE,CODE_ENDFILE,CODE_VM,CODE_VMDATA}; + + +enum FilterType { + FILTER_NONE, FILTER_PPM /*dummy*/, FILTER_E8, FILTER_E8E9, + FILTER_UPCASETOLOW, FILTER_AUDIO, FILTER_RGB, FILTER_DELTA, + FILTER_ITANIUM, FILTER_E8E9V2 +}; + +#endif diff --git a/7zip/Compress/Rar29/Original/consio.hpp b/7zip/Compress/Rar29/Original/consio.hpp new file mode 100755 index 00000000..780ae7f3 --- /dev/null +++ b/7zip/Compress/Rar29/Original/consio.hpp @@ -0,0 +1,42 @@ +#ifndef _RAR_CONSIO_ +#define _RAR_CONSIO_ + +enum {ALARM_SOUND,ERROR_SOUND,QUESTION_SOUND}; + +enum PASSWORD_TYPE {PASSWORD_GLOBAL,PASSWORD_FILE,PASSWORD_ARCHIVE}; + +void InitConsoleOptions(MESSAGE_TYPE MsgStream,bool Sound); + +#ifndef SILENT +void mprintf(const char *fmt,...); +void eprintf(const char *fmt,...); +void Alarm(); +void GetPasswordText(char *Str,int MaxLength); +unsigned int GetKey(); +bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxLength); +int Ask(const char *AskStr); +#endif + +int KbdAnsi(char *Addr,int Size); +void OutComment(char *Comment,int Size); + +#ifdef SILENT +#ifdef __GNUC__ + #define mprintf(args...) + #define eprintf(args...) +#else + inline void mprintf(const char *fmt,const char *a=NULL,const char *b=NULL) {} + inline void eprintf(const char *fmt,const char *a=NULL,const char *b=NULL) {} + inline void mprintf(const char *fmt,int b) {} + inline void eprintf(const char *fmt,int b) {} + inline void mprintf(const char *fmt,const char *a,int b) {} + inline void eprintf(const char *fmt,const char *a,int b) {} +#endif +inline void Alarm() {} +inline void GetPasswordText(char *Str,int MaxLength) {} +inline unsigned int GetKey() {return(0);} +inline bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxLength) {return(false);} +inline int Ask(const char *AskStr) {return(0);} +#endif + +#endif diff --git a/7zip/Compress/Rar29/Original/crc.cpp b/7zip/Compress/Rar29/Original/crc.cpp new file mode 100755 index 00000000..c19f8595 --- /dev/null +++ b/7zip/Compress/Rar29/Original/crc.cpp @@ -0,0 +1,61 @@ +#include "rar.hpp" + +uint CRCTab[256]; + +void InitCRC() +{ + for (int I=0;I<256;I++) + { + uint C=I; + for (int J=0;J<8;J++) + C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1); + CRCTab[I]=C; + } +} + + +uint CRC(uint StartCRC,const void *Addr,uint Size) +{ + if (CRCTab[1]==0) + InitCRC(); + byte *Data=(byte *)Addr; +#if defined(LITTLE_ENDIAN) && defined(PRESENT_INT32) + while (Size>0 && ((long)Data & 7)) + { + StartCRC=CRCTab[(byte)(StartCRC^Data[0])]^(StartCRC>>8); + Size--; + Data++; + } + while (Size>=8) + { + StartCRC^=*(uint32 *)Data; + StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); + StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); + StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); + StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); + StartCRC^=*(uint32 *)(Data+4); + StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); + StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); + StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); + StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); + Data+=8; + Size-=8; + } +#endif + for (int I=0;I>8); + return(StartCRC); +} + +#ifndef SFX_MODULE +ushort OldCRC(ushort StartCRC,const void *Addr,uint Size) +{ + byte *Data=(byte *)Addr; + for (int I=0;I>15))&0xffff; + } + return(StartCRC); +} +#endif diff --git a/7zip/Compress/Rar29/Original/crc.hpp b/7zip/Compress/Rar29/Original/crc.hpp new file mode 100755 index 00000000..47ee7e23 --- /dev/null +++ b/7zip/Compress/Rar29/Original/crc.hpp @@ -0,0 +1,10 @@ +#ifndef _RAR_CRC_ +#define _RAR_CRC_ + +extern uint CRCTab[256]; + +void InitCRC(); +uint CRC(uint StartCRC,const void *Addr,uint Size); +ushort OldCRC(ushort StartCRC,const void *Addr,uint Size); + +#endif diff --git a/7zip/Compress/Rar29/Original/crypt.hpp b/7zip/Compress/Rar29/Original/crypt.hpp new file mode 100755 index 00000000..809d76a5 --- /dev/null +++ b/7zip/Compress/Rar29/Original/crypt.hpp @@ -0,0 +1,60 @@ +#ifndef _RAR_CRYPT_ +#define _RAR_CRYPT_ + +enum { OLD_DECODE=0,OLD_ENCODE=1,NEW_CRYPT=2 }; + +struct CryptKeyCacheItem +{ +#ifndef _SFX_RTL_ + CryptKeyCacheItem() + { + *Password=0; + } + + ~CryptKeyCacheItem() + { + memset(AESKey,0,sizeof(AESKey)); + memset(AESInit,0,sizeof(AESInit)); + memset(Password,0,sizeof(Password)); + } +#endif + byte AESKey[16],AESInit[16]; + char Password[MAXPASSWORD]; + bool SaltPresent; + byte Salt[SALT_SIZE]; +}; + +class CryptData +{ + private: + void Encode13(byte *Data,uint Count); + void Decode13(byte *Data,uint Count); + void Crypt15(byte *Data,uint Count); + void UpdKeys(byte *Buf); + void Swap(byte *Ch1,byte *Ch2); + void SetOldKeys(char *Password); + + Rijndael rin; + + byte SubstTable[256]; + uint Key[4]; + ushort OldKey[4]; + byte PN1,PN2,PN3; + + byte AESKey[16],AESInit[16]; + + static CryptKeyCacheItem Cache[4]; + static int CachePos; + public: + void SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly=false); + void SetAV15Encryption(); + void SetCmt13Encryption(); + void EncryptBlock20(byte *Buf); + void DecryptBlock20(byte *Buf); + void EncryptBlock(byte *Buf,int Size); + void DecryptBlock(byte *Buf,int Size); + void Crypt(byte *Data,uint Count,int Method); + static void SetSalt(byte *Salt,int SaltSize); +}; + +#endif diff --git a/7zip/Compress/Rar29/Original/encname.hpp b/7zip/Compress/Rar29/Original/encname.hpp new file mode 100755 index 00000000..586f4216 --- /dev/null +++ b/7zip/Compress/Rar29/Original/encname.hpp @@ -0,0 +1,20 @@ +#ifndef _RAR_ENCNAME_ +#define _RAR_ENCNAME_ + +class EncodeFileName +{ + private: + void AddFlags(int Value); + + byte *EncName; + byte Flags; + int FlagBits; + int FlagsPos; + int DestSize; + public: + EncodeFileName(); + int Encode(char *Name,wchar *NameW,byte *EncName); + void Decode(char *Name,byte *EncName,int EncSize,wchar *NameW,int MaxDecSize); +}; + +#endif diff --git a/7zip/Compress/Rar29/Original/errhnd.cpp b/7zip/Compress/Rar29/Original/errhnd.cpp new file mode 100755 index 00000000..6e162217 --- /dev/null +++ b/7zip/Compress/Rar29/Original/errhnd.cpp @@ -0,0 +1,356 @@ +#include "rar.hpp" + + +static bool UserBreak; + +ErrorHandler::ErrorHandler() +{ + Clean(); +} + + +void ErrorHandler::Clean() +{ + ExitCode=SUCCESS; + ErrCount=0; + EnableBreak=true; + Silent=false; + DoShutdown=false; +} + + +void ErrorHandler::MemoryError() +{ + MemoryErrorMsg(); + Throw(MEMORY_ERROR); +} + + +void ErrorHandler::OpenError(const char *FileName) +{ +#ifndef SILENT + OpenErrorMsg(FileName); + Throw(OPEN_ERROR); +#endif +} + + +void ErrorHandler::CloseError(const char *FileName) +{ +#ifndef SILENT + if (!UserBreak) + { + ErrMsg(NULL,St(MErrFClose),FileName); + SysErrMsg(); + } +#endif +#if !defined(SILENT) || defined(RARDLL) + Throw(FATAL_ERROR); +#endif +} + + +void ErrorHandler::ReadError(const char *FileName) +{ +#ifndef SILENT + ReadErrorMsg(NULL,FileName); +#endif +#if !defined(SILENT) || defined(RARDLL) + Throw(FATAL_ERROR); +#endif +} + + +bool ErrorHandler::AskRepeatRead(const char *FileName) +{ +#if !defined(SILENT) && !defined(SFX_MODULE) && !defined(_WIN_CE) + if (!Silent) + { + mprintf("\n"); + Log(NULL,St(MErrRead),FileName); + return(Ask(St(MRetryAbort))==1); + } +#endif + return(false); +} + + +void ErrorHandler::WriteError(const char *ArcName,const char *FileName) +{ +#ifndef SILENT + WriteErrorMsg(ArcName,FileName); +#endif +#if !defined(SILENT) || defined(RARDLL) + Throw(WRITE_ERROR); +#endif +} + + +#ifdef _WIN_32 +void ErrorHandler::WriteErrorFAT(const char *FileName) +{ +#if !defined(SILENT) && !defined(SFX_MODULE) + SysErrMsg(); + ErrMsg(NULL,St(MNTFSRequired),FileName); +#endif +#if !defined(SILENT) && !defined(SFX_MODULE) || defined(RARDLL) + Throw(WRITE_ERROR); +#endif +} +#endif + + +bool ErrorHandler::AskRepeatWrite(const char *FileName) +{ +#if !defined(SILENT) && !defined(_WIN_CE) + if (!Silent) + { + mprintf("\n"); + Log(NULL,St(MErrWrite),FileName); + return(Ask(St(MRetryAbort))==1); + } +#endif + return(false); +} + + +void ErrorHandler::SeekError(const char *FileName) +{ +#ifndef SILENT + if (!UserBreak) + { + ErrMsg(NULL,St(MErrSeek),FileName); + SysErrMsg(); + } +#endif +#if !defined(SILENT) || defined(RARDLL) + Throw(FATAL_ERROR); +#endif +} + + +void ErrorHandler::MemoryErrorMsg() +{ +#ifndef SILENT + ErrMsg(NULL,St(MErrOutMem)); +#endif +} + + +void ErrorHandler::OpenErrorMsg(const char *FileName) +{ + OpenErrorMsg(NULL,FileName); +} + + +void ErrorHandler::OpenErrorMsg(const char *ArcName,const char *FileName) +{ +#ifndef SILENT + Log(ArcName && *ArcName ? ArcName:NULL,St(MCannotOpen),FileName); + Alarm(); + SysErrMsg(); +#endif +} + + +void ErrorHandler::CreateErrorMsg(const char *FileName) +{ + CreateErrorMsg(NULL,FileName); +} + + +void ErrorHandler::CreateErrorMsg(const char *ArcName,const char *FileName) +{ +#ifndef SILENT + Log(ArcName && *ArcName ? ArcName:NULL,St(MCannotCreate),FileName); + Alarm(); +#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE) && defined(MAXPATH) + if (GetLastError()==ERROR_PATH_NOT_FOUND) + { + int NameLength=strlen(FileName); + if (!IsFullPath(FileName)) + { + char CurDir[NM]; + GetCurrentDirectory(sizeof(CurDir),CurDir); + NameLength+=strlen(CurDir)+1; + } + if (NameLength>MAXPATH) + { + Log(ArcName && *ArcName ? ArcName:NULL,St(MMaxPathLimit),MAXPATH); + } + } +#endif + SysErrMsg(); +#endif +} + + +void ErrorHandler::ReadErrorMsg(const char *ArcName,const char *FileName) +{ +#ifndef SILENT + ErrMsg(ArcName,St(MErrRead),FileName); + SysErrMsg(); +#endif +} + + +void ErrorHandler::WriteErrorMsg(const char *ArcName,const char *FileName) +{ +#ifndef SILENT + ErrMsg(ArcName,St(MErrWrite),FileName); + SysErrMsg(); +#endif +} + + +void ErrorHandler::Exit(int ExitCode) +{ +#ifndef SFX_MODULE + Alarm(); +#endif + Throw(ExitCode); +} + + +#ifndef GUI +void ErrorHandler::ErrMsg(const char *ArcName,const char *fmt,...) +{ + safebuf char Msg[NM+1024]; + va_list argptr; + va_start(argptr,fmt); + vsprintf(Msg,fmt,argptr); + va_end(argptr); +#ifdef _WIN_32 + if (UserBreak) + Sleep(5000); +#endif + Alarm(); + if (*Msg) + { + Log(ArcName,"\n%s",Msg); + mprintf("\n%s\n",St(MProgAborted)); + } +} +#endif + + +void ErrorHandler::SetErrorCode(int Code) +{ + switch(Code) + { + case WARNING: + case USER_BREAK: + if (ExitCode==SUCCESS) + ExitCode=Code; + break; + case FATAL_ERROR: + if (ExitCode==SUCCESS || ExitCode==WARNING) + ExitCode=FATAL_ERROR; + break; + default: + ExitCode=Code; + break; + } + ErrCount++; +} + + +#if !defined(GUI) && !defined(_SFX_RTL_) +#ifdef _WIN_32 +BOOL __stdcall ProcessSignal(DWORD SigType) +#else +#if defined(__sun) +extern "C" +#endif +void _stdfunction ProcessSignal(int SigType) +#endif +{ +#ifdef _WIN_32 + if (SigType==CTRL_LOGOFF_EVENT) + return(TRUE); +#endif + UserBreak=true; + mprintf(St(MBreak)); + for (int I=0; + // Igor Pavlov + // !File::RemoveCreated() && + I<3;I++) + { +#ifdef _WIN_32 + Sleep(100); +#endif + } +#if defined(USE_RC) && !defined(SFX_MODULE) && !defined(_WIN_CE) + ExtRes.UnloadDLL(); +#endif + exit(USER_BREAK); +#ifdef _WIN_32 + return(TRUE); +#endif +} +#endif + + +void ErrorHandler::SetSignalHandlers(bool Enable) +{ + EnableBreak=Enable; +#if !defined(GUI) && !defined(_SFX_RTL_) +#ifdef _WIN_32 + SetConsoleCtrlHandler(Enable ? ProcessSignal:NULL,TRUE); +// signal(SIGBREAK,Enable ? ProcessSignal:SIG_IGN); +#else + signal(SIGINT,Enable ? ProcessSignal:SIG_IGN); + signal(SIGTERM,Enable ? ProcessSignal:SIG_IGN); +#endif +#endif +} + + +void ErrorHandler::Throw(int Code) +{ + if (Code==USER_BREAK && !EnableBreak) + return; + ErrHandler.SetErrorCode(Code); +#ifdef ALLOW_EXCEPTIONS + throw Code; +#else + // Igor Pavlov + // File::RemoveCreated(); + exit(Code); +#endif +} + + +void ErrorHandler::SysErrMsg() +{ +#if defined(_WIN_32) && !defined(SFX_MODULE) && !defined(SILENT) + #define STRCHR strchr + #define ERRCHAR char + ERRCHAR *lpMsgBuf=NULL; + int ErrType=GetLastError(); + if (ErrType!=0 && FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, + NULL,ErrType,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&lpMsgBuf,0,NULL)) + { + ERRCHAR *CurMsg=lpMsgBuf; + while (CurMsg!=NULL) + { + while (*CurMsg=='\r' || *CurMsg=='\n') + CurMsg++; + if (*CurMsg==0) + break; + ERRCHAR *EndMsg=STRCHR(CurMsg,'\r'); + if (EndMsg==NULL) + EndMsg=STRCHR(CurMsg,'\n'); + if (EndMsg!=NULL) + { + *EndMsg=0; + EndMsg++; + } + Log(NULL,"\n%s",CurMsg); + CurMsg=EndMsg; + } + } + LocalFree( lpMsgBuf ); +#endif +} diff --git a/7zip/Compress/Rar29/Original/errhnd.hpp b/7zip/Compress/Rar29/Original/errhnd.hpp new file mode 100755 index 00000000..9e276222 --- /dev/null +++ b/7zip/Compress/Rar29/Original/errhnd.hpp @@ -0,0 +1,61 @@ +#ifndef _RAR_ERRHANDLER_ +#define _RAR_ERRHANDLER_ + +#if (defined(GUI) || !defined(_WIN_32)) && !defined(SFX_MODULE) && !defined(_WIN_CE) || defined(RARDLL) +#define ALLOW_EXCEPTIONS +#endif + + + +#define rarmalloc malloc +#define rarcalloc calloc +#define rarrealloc realloc +#define rarfree free +#define rarstrdup strdup + + + +enum { SUCCESS,WARNING,FATAL_ERROR,CRC_ERROR,LOCK_ERROR,WRITE_ERROR, + OPEN_ERROR,USER_ERROR,MEMORY_ERROR,CREATE_ERROR,USER_BREAK=255}; + +class ErrorHandler +{ + private: + void ErrMsg(const char *ArcName,const char *fmt,...); + + int ExitCode; + int ErrCount; + bool EnableBreak; + bool Silent; + bool DoShutdown; + public: + ErrorHandler(); + void Clean(); + void MemoryError(); + void OpenError(const char *FileName); + void CloseError(const char *FileName); + void ReadError(const char *FileName); + bool AskRepeatRead(const char *FileName); + void WriteError(const char *ArcName,const char *FileName); + void WriteErrorFAT(const char *FileName); + bool AskRepeatWrite(const char *FileName); + void SeekError(const char *FileName); + void MemoryErrorMsg(); + void OpenErrorMsg(const char *FileName); + void OpenErrorMsg(const char *ArcName,const char *FileName); + void CreateErrorMsg(const char *FileName); + void CreateErrorMsg(const char *ArcName,const char *FileName); + void ReadErrorMsg(const char *ArcName,const char *FileName); + void WriteErrorMsg(const char *ArcName,const char *FileName); + void Exit(int ExitCode); + void SetErrorCode(int Code); + int GetErrorCode() {return(ExitCode);} + int GetErrorCount() {return(ErrCount);} + void SetSignalHandlers(bool Enable); + void Throw(int Code); + void SetSilent(bool Mode) {Silent=Mode;}; + void SetShutdown(bool Mode) {DoShutdown=Mode;}; + void SysErrMsg(); +}; + +#endif diff --git a/7zip/Compress/Rar29/Original/extinfo.hpp b/7zip/Compress/Rar29/Original/extinfo.hpp new file mode 100755 index 00000000..db7cea53 --- /dev/null +++ b/7zip/Compress/Rar29/Original/extinfo.hpp @@ -0,0 +1,8 @@ +#ifndef _RAR_EXTINFO_ +#define _RAR_EXTINFO_ + + +void SetExtraInfo(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW); +void SetExtraInfoNew(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW); + +#endif diff --git a/7zip/Compress/Rar29/Original/extract.hpp b/7zip/Compress/Rar29/Original/extract.hpp new file mode 100755 index 00000000..b78c988d --- /dev/null +++ b/7zip/Compress/Rar29/Original/extract.hpp @@ -0,0 +1,40 @@ +#ifndef _RAR_EXTRACT_ +#define _RAR_EXTRACT_ + +enum EXTRACT_ARC_CODE {EXTRACT_ARC_NEXT,EXTRACT_ARC_REPEAT}; + +class CmdExtract +{ + private: + ComprDataIO DataIO; + Unpack *Unp; + long TotalFileCount; + + long FileCount; + long MatchedArgs; + bool FirstFile; + bool AllMatchesExact; + bool ReconstructDone; + + char ArcName[NM]; + wchar ArcNameW[NM]; + + char Password[MAXPASSWORD]; + bool PasswordAll; + bool PrevExtracted; + bool SignatureFound; + char DestFileName[NM]; + wchar DestFileNameW[NM]; + bool PasswordCancelled; + public: + CmdExtract(); + ~CmdExtract(); + void DoExtract(CommandData *Cmd); + void ExtractArchiveInit(CommandData *Cmd,Archive &Arc); + EXTRACT_ARC_CODE ExtractArchive(CommandData *Cmd); + bool ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize, + bool &Repeat); + static void UnstoreFile(ComprDataIO &DataIO,Int64 DestUnpSize); +}; + +#endif diff --git a/7zip/Compress/Rar29/Original/filcreat.hpp b/7zip/Compress/Rar29/Original/filcreat.hpp new file mode 100755 index 00000000..fa1fddd0 --- /dev/null +++ b/7zip/Compress/Rar29/Original/filcreat.hpp @@ -0,0 +1,12 @@ +#ifndef _RAR_FILECREATE_ +#define _RAR_FILECREATE_ + +bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW, + OVERWRITE_MODE Mode,bool *UserReject,Int64 FileSize=INT64ERR, + uint FileTime=0); + +#if defined(_WIN_32) && !defined(_WIN_CE) +bool UpdateExistingShortName(char *Name,wchar *NameW); +#endif + +#endif diff --git a/7zip/Compress/Rar29/Original/file.hpp b/7zip/Compress/Rar29/Original/file.hpp new file mode 100755 index 00000000..afa9529c --- /dev/null +++ b/7zip/Compress/Rar29/Original/file.hpp @@ -0,0 +1,100 @@ +#ifndef _RAR_FILE_ +#define _RAR_FILE_ + +#ifdef _WIN_32 +typedef HANDLE FileHandle; +#define BAD_HANDLE INVALID_HANDLE_VALUE +#else +typedef FILE* FileHandle; +#define BAD_HANDLE NULL +#endif + +class RAROptions; + +enum FILE_HANDLETYPE {FILE_HANDLENORMAL,FILE_HANDLESTD,FILE_HANDLEERR}; + +enum FILE_ERRORTYPE {FILE_SUCCESS,FILE_NOTFOUND,FILE_READERROR}; + +struct FileStat +{ + uint FileAttr; + uint FileTime; + Int64 FileSize; + bool IsDir; +}; + + +class File +{ + private: + void AddFileToList(FileHandle hFile); + + FileHandle hFile; + bool LastWrite; + FILE_HANDLETYPE HandleType; + bool SkipClose; + bool IgnoreReadErrors; + bool NewFile; + bool AllowDelete; + bool AllowExceptions; +#ifdef _WIN_32 + bool NoSequentialRead; +#endif + protected: + bool OpenShared; + public: + char FileName[NM]; + wchar FileNameW[NM]; + + FILE_ERRORTYPE ErrorType; + + uint CloseCount; + public: + File(); + virtual ~File(); + void operator = (File &SrcFile); + bool Open(const char *Name,const wchar *NameW=NULL,bool OpenShared=false,bool Update=false); + void TOpen(const char *Name,const wchar *NameW=NULL); + bool WOpen(const char *Name,const wchar *NameW=NULL); + bool Create(const char *Name,const wchar *NameW=NULL); + void TCreate(const char *Name,const wchar *NameW=NULL); + bool WCreate(const char *Name,const wchar *NameW=NULL); + bool Close(); + void Flush(); + bool Delete(); + bool Rename(const char *NewName); + void Write(const void *Data,int Size); + int Read(void *Data,int Size); + int DirectRead(void *Data,int Size); + void Seek(Int64 Offset,int Method); + bool RawSeek(Int64 Offset,int Method); + Int64 Tell(); + void Prealloc(Int64 Size); + byte GetByte(); + void PutByte(byte Byte); + bool Truncate(); + void SetOpenFileTime(RarTime *ftm,RarTime *ftc=NULL,RarTime *fta=NULL); + void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL); + static void SetCloseFileTimeByName(const char *Name,RarTime *ftm,RarTime *fta); + void SetOpenFileStat(RarTime *ftm,RarTime *ftc,RarTime *fta); + void SetCloseFileStat(RarTime *ftm,RarTime *fta,uint FileAttr); + void GetOpenFileTime(RarTime *ft); + bool IsOpened() {return(hFile!=BAD_HANDLE);}; + Int64 FileLength(); + void SetHandleType(FILE_HANDLETYPE Type); + FILE_HANDLETYPE GetHandleType() {return(HandleType);}; + bool IsDevice(); + void fprintf(const char *fmt,...); + static bool RemoveCreated(); + FileHandle GetHandle() {return(hFile);}; + void SetIgnoreReadErrors(bool Mode) {IgnoreReadErrors=Mode;}; + char *GetName() {return(FileName);} + long Copy(File &Dest,Int64 Length=INT64ERR); + void SetAllowDelete(bool Allow) {AllowDelete=Allow;} + void SetExceptions(bool Allow) {AllowExceptions=Allow;} +#ifdef _WIN_32 + void RemoveSequentialFlag() {NoSequentialRead=true;} +#endif +}; + +#endif diff --git a/7zip/Compress/Rar29/Original/filefn.hpp b/7zip/Compress/Rar29/Original/filefn.hpp new file mode 100755 index 00000000..3ad31b5e --- /dev/null +++ b/7zip/Compress/Rar29/Original/filefn.hpp @@ -0,0 +1,39 @@ +#ifndef _RAR_FILEFN_ +#define _RAR_FILEFN_ + +enum MKDIR_CODE {MKDIR_SUCCESS,MKDIR_ERROR,MKDIR_BADPATH}; + +MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,uint Attr); +void CreatePath(const char *Path,const wchar *PathW,bool SkipLastName); +void SetDirTime(const char *Name,RarTime *ftm,RarTime *ftc,RarTime *fta); +bool IsRemovable(const char *Name); +Int64 GetFreeDisk(const char *Name); +bool FileExist(const char *Name,const wchar *NameW=NULL); +bool WildFileExist(const char *Name,const wchar *NameW=NULL); +bool IsDir(uint Attr); +bool IsUnreadable(uint Attr); +bool IsLabel(uint Attr); +bool IsLink(uint Attr); +void SetSFXMode(const char *FileName); +void EraseDiskContents(const char *FileName); +bool IsDeleteAllowed(uint FileAttr); +void PrepareToDelete(const char *Name,const wchar *NameW=NULL); +uint GetFileAttr(const char *Name,const wchar *NameW=NULL); +bool SetFileAttr(const char *Name,const wchar *NameW,uint Attr); +void ConvertNameToFull(const char *Src,char *Dest); +void ConvertNameToFull(const wchar *Src,wchar *Dest); +char* MkTemp(char *Name); + + +uint CalcFileCRC(File *SrcFile,Int64 Size=INT64ERR); +bool RenameFile(const char *SrcName,const wchar *SrcNameW,const char *DestName,const wchar *DestNameW); +bool DelFile(const char *Name); +bool DelFile(const char *Name,const wchar *NameW); +bool DelDir(const char *Name); +bool DelDir(const char *Name,const wchar *NameW); + +#if defined(_WIN_32) && !defined(_WIN_CE) +bool SetFileCompression(char *Name,wchar *NameW,bool State); +#endif + +#endif diff --git a/7zip/Compress/Rar29/Original/filestr.hpp b/7zip/Compress/Rar29/Original/filestr.hpp new file mode 100755 index 00000000..b2bcbe0e --- /dev/null +++ b/7zip/Compress/Rar29/Original/filestr.hpp @@ -0,0 +1,8 @@ +#ifndef _RAR_FILESTR_ +#define _RAR_FILESTR_ + +bool ReadTextFile(char *Name,StringList *List,bool Config, + bool AbortOnError=false,bool ConvertToAnsi=false, + bool Unquote=false,bool SkipComments=false); + +#endif diff --git a/7zip/Compress/Rar29/Original/find.hpp b/7zip/Compress/Rar29/Original/find.hpp new file mode 100755 index 00000000..81548199 --- /dev/null +++ b/7zip/Compress/Rar29/Original/find.hpp @@ -0,0 +1,48 @@ +#ifndef _RAR_FINDDATA_ +#define _RAR_FINDDATA_ + +struct FindData +{ + char Name[NM]; + wchar NameW[NM]; + Int64 Size; + uint FileAttr; + uint FileTime; + bool IsDir; + RarTime mtime; + RarTime ctime; + RarTime atime; +#ifdef _WIN_32 + char ShortName[NM]; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; +#endif + bool Error; +}; + +class FindFile +{ + private: +#ifdef _WIN_32 + static HANDLE Win32Find(HANDLE hFind,const char *Mask,const wchar *MaskW,struct FindData *fd); +#endif + + char FindMask[NM]; + wchar FindMaskW[NM]; + int FirstCall; +#ifdef _WIN_32 + HANDLE hFind; +#else + DIR *dirp; +#endif + public: + FindFile(); + ~FindFile(); + void SetMask(const char *FindMask); + void SetMaskW(const wchar *FindMaskW); + bool Next(struct FindData *fd,bool GetSymLink=false); + static bool FastFind(const char *FindMask,const wchar *FindMaskW,struct FindData *fd,bool GetSymLink=false); +}; + +#endif diff --git a/7zip/Compress/Rar29/Original/getbits.cpp b/7zip/Compress/Rar29/Original/getbits.cpp new file mode 100755 index 00000000..71ecfc87 --- /dev/null +++ b/7zip/Compress/Rar29/Original/getbits.cpp @@ -0,0 +1,24 @@ +#include "rar.hpp" + +BitInput::BitInput() +{ + InBuf=new byte[MAX_SIZE]; +} + + +BitInput::~BitInput() +{ + delete[] InBuf; +} + + +void BitInput::faddbits(int Bits) +{ + addbits(Bits); +} + + +unsigned int BitInput::fgetbits() +{ + return(getbits()); +} diff --git a/7zip/Compress/Rar29/Original/getbits.hpp b/7zip/Compress/Rar29/Original/getbits.hpp new file mode 100755 index 00000000..8819f53a --- /dev/null +++ b/7zip/Compress/Rar29/Original/getbits.hpp @@ -0,0 +1,37 @@ +#ifndef _RAR_GETBITS_ +#define _RAR_GETBITS_ + +class BitInput +{ + public: + enum BufferSize {MAX_SIZE=0x8000}; + protected: + int InAddr,InBit; + public: + BitInput(); + ~BitInput(); + + byte *InBuf; + + void InitBitInput() + { + InAddr=InBit=0; + } + void addbits(int Bits) + { + Bits+=InBit; + InAddr+=Bits>>3; + InBit=Bits&7; + } + unsigned int getbits() + { + unsigned int BitField=(uint)InBuf[InAddr] << 16; + BitField|=(uint)InBuf[InAddr+1] << 8; + BitField|=(uint)InBuf[InAddr+2]; + BitField >>= (8-InBit); + return(BitField & 0xffff); + } + void faddbits(int Bits); + unsigned int fgetbits(); +}; +#endif diff --git a/7zip/Compress/Rar29/Original/global.hpp b/7zip/Compress/Rar29/Original/global.hpp new file mode 100755 index 00000000..35c6cf91 --- /dev/null +++ b/7zip/Compress/Rar29/Original/global.hpp @@ -0,0 +1,14 @@ +#ifndef _RAR_GLOBAL_ +#define _RAR_GLOBAL_ + +#ifdef INCLUDEGLOBAL + #define EXTVAR +#else + #define EXTVAR extern +#endif + +EXTVAR ErrorHandler ErrHandler; + + + +#endif diff --git a/7zip/Compress/Rar29/Original/headers.hpp b/7zip/Compress/Rar29/Original/headers.hpp new file mode 100755 index 00000000..f719a7ec --- /dev/null +++ b/7zip/Compress/Rar29/Original/headers.hpp @@ -0,0 +1,304 @@ +#ifndef _RAR_HEADERS_ +#define _RAR_HEADERS_ + +#define SIZEOF_MARKHEAD 7 +#define SIZEOF_OLDMHD 7 +#define SIZEOF_NEWMHD 13 +#define SIZEOF_OLDLHD 21 +#define SIZEOF_NEWLHD 32 +#define SIZEOF_SHORTBLOCKHEAD 7 +#define SIZEOF_LONGBLOCKHEAD 11 +#define SIZEOF_SUBBLOCKHEAD 14 +#define SIZEOF_COMMHEAD 13 +#define SIZEOF_PROTECTHEAD 26 +#define SIZEOF_AVHEAD 14 +#define SIZEOF_SIGNHEAD 15 +#define SIZEOF_UOHEAD 18 +#define SIZEOF_MACHEAD 22 +#define SIZEOF_EAHEAD 24 +#define SIZEOF_BEEAHEAD 24 +#define SIZEOF_STREAMHEAD 26 + +#define PACK_VER 29 +#define PACK_CRYPT_VER 29 +#define UNP_VER 29 +#define CRYPT_VER 29 +#define AV_VER 20 +#define PROTECT_VER 20 + +#define MHD_VOLUME 0x0001 +#define MHD_COMMENT 0x0002 +#define MHD_LOCK 0x0004 +#define MHD_SOLID 0x0008 +#define MHD_PACK_COMMENT 0x0010 +#define MHD_NEWNUMBERING 0x0010 +#define MHD_AV 0x0020 +#define MHD_PROTECT 0x0040 +#define MHD_PASSWORD 0x0080 +#define MHD_FIRSTVOLUME 0x0100 + +#define LHD_SPLIT_BEFORE 0x0001 +#define LHD_SPLIT_AFTER 0x0002 +#define LHD_PASSWORD 0x0004 +#define LHD_COMMENT 0x0008 +#define LHD_SOLID 0x0010 + +#define LHD_WINDOWMASK 0x00e0 +#define LHD_WINDOW64 0x0000 +#define LHD_WINDOW128 0x0020 +#define LHD_WINDOW256 0x0040 +#define LHD_WINDOW512 0x0060 +#define LHD_WINDOW1024 0x0080 +#define LHD_WINDOW2048 0x00a0 +#define LHD_WINDOW4096 0x00c0 +#define LHD_DIRECTORY 0x00e0 + +#define LHD_LARGE 0x0100 +#define LHD_UNICODE 0x0200 +#define LHD_SALT 0x0400 +#define LHD_VERSION 0x0800 +#define LHD_EXTTIME 0x1000 +#define LHD_EXTFLAGS 0x2000 + +#define SKIP_IF_UNKNOWN 0x4000 +#define LONG_BLOCK 0x8000 + +#define EARC_NEXT_VOLUME 0x0001 +#define EARC_DATACRC 0x0002 +#define EARC_REVSPACE 0x0004 +#define EARC_VOLNUMBER 0x0008 + +enum HEADER_TYPE { + MARK_HEAD=0x72,MAIN_HEAD=0x73,FILE_HEAD=0x74,COMM_HEAD=0x75,AV_HEAD=0x76, + SUB_HEAD=0x77,PROTECT_HEAD=0x78,SIGN_HEAD=0x79,NEWSUB_HEAD=0x7a, + ENDARC_HEAD=0x7b +}; + +enum { EA_HEAD=0x100,UO_HEAD=0x101,MAC_HEAD=0x102,BEEA_HEAD=0x103, + NTACL_HEAD=0x104,STREAM_HEAD=0x105 }; + +enum HOST_SYSTEM { + HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4, + HOST_BEOS=5,HOST_MAX +}; + +#define SUBHEAD_TYPE_CMT "CMT" +#define SUBHEAD_TYPE_ACL "ACL" +#define SUBHEAD_TYPE_STREAM "STM" +#define SUBHEAD_TYPE_UOWNER "UOW" +#define SUBHEAD_TYPE_AV "AV" +#define SUBHEAD_TYPE_RR "RR" +#define SUBHEAD_TYPE_OS2EA "EA2" +#define SUBHEAD_TYPE_BEOSEA "EABE" + +/* new file inherits a subblock when updating a host file */ +#define SUBHEAD_FLAGS_INHERITED 0x80000000 + +#define SUBHEAD_FLAGS_CMT_UNICODE 0x00000001 + +struct OldMainHeader +{ + byte Mark[4]; + ushort HeadSize; + byte Flags; +}; + + +struct OldFileHeader +{ + uint PackSize; + uint UnpSize; + ushort FileCRC; + ushort HeadSize; + uint FileTime; + byte FileAttr; + byte Flags; + byte UnpVer; + byte NameSize; + byte Method; +}; + + +struct MarkHeader +{ + byte Mark[7]; +}; + + +struct BaseBlock +{ + ushort HeadCRC; + HEADER_TYPE HeadType;//byte + ushort Flags; + ushort HeadSize; + + bool IsSubBlock() + { + if (HeadType==SUB_HEAD) + return(true); + if (HeadType==NEWSUB_HEAD && (Flags & LHD_SOLID)!=0) + return(true); + return(false); + } +}; + +struct BlockHeader:BaseBlock +{ + union { + uint DataSize; + uint PackSize; + }; +}; + + +struct MainHeader:BlockHeader +{ + ushort HighPosAV; + uint PosAV; +}; + + +#define SALT_SIZE 8 + +struct FileHeader:BlockHeader +{ + uint UnpSize; + byte HostOS; + uint FileCRC; + uint FileTime; + byte UnpVer; + byte Method; + ushort NameSize; + union { + uint FileAttr; + uint SubFlags; + }; +/* optional */ + uint HighPackSize; + uint HighUnpSize; +/* names */ + char FileName[NM]; + wchar FileNameW[NM]; +/* optional */ + Array SubData; + byte Salt[SALT_SIZE]; + + RarTime mtime; + RarTime ctime; + RarTime atime; + RarTime arctime; +/* dummy */ + Int64 FullPackSize; + Int64 FullUnpSize; + + void Clear(int SubDataSize) + { + SubData.Alloc(SubDataSize); + Flags=LONG_BLOCK; + SubFlags=0; + } + + bool CmpName(const char *Name) + { + return(strcmp(FileName,Name)==0); + } + + FileHeader& operator = (FileHeader &hd) + { + SubData.Reset(); + memcpy(this,&hd,sizeof(*this)); + SubData.CleanData(); + SubData=hd.SubData; + return(*this); + } +}; + + +struct EndArcHeader:BaseBlock +{ + uint ArcDataCRC; + ushort VolNumber; +}; + + +struct SubBlockHeader:BlockHeader +{ + ushort SubType; + byte Level; +}; + + +struct CommentHeader:BaseBlock +{ + ushort UnpSize; + byte UnpVer; + byte Method; + ushort CommCRC; +}; + + +struct ProtectHeader:BlockHeader +{ + byte Version; + ushort RecSectors; + uint TotalBlocks; + byte Mark[8]; +}; + + +struct AVHeader:BaseBlock +{ + byte UnpVer; + byte Method; + byte AVVer; + uint AVInfoCRC; +}; + + +struct SignHeader:BaseBlock +{ + uint CreationTime; + ushort ArcNameSize; + ushort UserNameSize; +}; + + +struct UnixOwnersHeader:SubBlockHeader +{ + ushort OwnerNameSize; + ushort GroupNameSize; +/* dummy */ + char OwnerName[NM]; + char GroupName[NM]; +}; + + +struct EAHeader:SubBlockHeader +{ + uint UnpSize; + byte UnpVer; + byte Method; + uint EACRC; +}; + + +struct StreamHeader:SubBlockHeader +{ + uint UnpSize; + byte UnpVer; + byte Method; + uint StreamCRC; + ushort StreamNameSize; +/* dummy */ + byte StreamName[NM]; +}; + + +struct MacFInfoHeader:SubBlockHeader +{ + uint fileType; + uint fileCreator; +}; + + +#endif diff --git a/7zip/Compress/Rar29/Original/int64.cpp b/7zip/Compress/Rar29/Original/int64.cpp new file mode 100755 index 00000000..996d0ea6 --- /dev/null +++ b/7zip/Compress/Rar29/Original/int64.cpp @@ -0,0 +1,274 @@ +#include "rar.hpp" + +#ifndef NATIVE_INT64 + +Int64::Int64() +{ +} + + +Int64::Int64(uint n) +{ + HighPart=0; + LowPart=n; +} + + +Int64::Int64(uint HighPart,uint LowPart) +{ + Int64::HighPart=HighPart; + Int64::LowPart=LowPart; +} + + +/* +Int64 Int64::operator = (Int64 n) +{ + HighPart=n.HighPart; + LowPart=n.LowPart; + return(*this); +} +*/ + + +Int64 Int64::operator << (int n) +{ + Int64 res=*this; + while (n--) + { + res.HighPart<<=1; + if (res.LowPart & 0x80000000) + res.HighPart|=1; + res.LowPart<<=1; + } + return(res); +} + + +Int64 Int64::operator >> (int n) +{ + Int64 res=*this; + while (n--) + { + res.LowPart>>=1; + if (res.HighPart & 1) + res.LowPart|=0x80000000; + res.HighPart>>=1; + } + return(res); +} + + +Int64 operator / (Int64 n1,Int64 n2) +{ + if (n1.HighPart==0 && n2.HighPart==0) + return(Int64(0,n1.LowPart/n2.LowPart)); + int ShiftCount=0; + while (n1>n2) + { + n2=n2<<1; + if (++ShiftCount>64) + return(0); + } + Int64 res=0; + while (ShiftCount-- >= 0) + { + res=res<<1; + if (n1>=n2) + { + n1-=n2; + ++res; + } + n2=n2>>1; + } + return(res); +} + + +Int64 operator * (Int64 n1,Int64 n2) +{ + if (n1<0x10000 && n2<0x10000) + return(Int64(0,n1.LowPart*n2.LowPart)); + Int64 res=0; + for (int I=0;I<64;I++) + { + if (n2.LowPart & 1) + res+=n1; + n1=n1<<1; + n2=n2>>1; + } + return(res); +} + + +Int64 operator % (Int64 n1,Int64 n2) +{ + if (n1.HighPart==0 && n2.HighPart==0) + return(Int64(0,n1.LowPart%n2.LowPart)); + return(n1-n1/n2*n2); +} + + +Int64 operator + (Int64 n1,Int64 n2) +{ + n1.LowPart+=n2.LowPart; + if (n1.LowPart (Int64 n1,Int64 n2) +{ + return((int)n1.HighPart>(int)n2.HighPart || n1.HighPart==n2.HighPart && n1.LowPart>n2.LowPart); +} + + +bool operator < (Int64 n1,Int64 n2) +{ + return((int)n1.HighPart<(int)n2.HighPart || n1.HighPart==n2.HighPart && n1.LowPart= (Int64 n1,Int64 n2) +{ + return(n1>n2 || n1==n2); +} + + +bool operator <= (Int64 n1,Int64 n2) +{ + return(n1='0' && *Str<='9') + { + n=n*10+*Str-'0'; + Str++; + } + return(n); +} diff --git a/7zip/Compress/Rar29/Original/int64.hpp b/7zip/Compress/Rar29/Original/int64.hpp new file mode 100755 index 00000000..a8057522 --- /dev/null +++ b/7zip/Compress/Rar29/Original/int64.hpp @@ -0,0 +1,86 @@ +#ifndef _RAR_INT64_ +#define _RAR_INT64_ + +#if defined(__BORLANDC__) || defined(_MSC_VER) +#define NATIVE_INT64 +typedef __int64 Int64; +#endif + +#if defined(__GNUC__) || defined(__HP_aCC) +#define NATIVE_INT64 +typedef long long Int64; +#endif + +#ifdef NATIVE_INT64 + +#define int64to32(x) ((uint)(x)) +#define int32to64(high,low) ((((Int64)(high))<<32)+(low)) +#define is64plus(x) (x>=0) + +#else + +class Int64 +{ + public: + Int64(); + Int64(uint n); + Int64(uint HighPart,uint LowPart); + +// Int64 operator = (Int64 n); + Int64 operator << (int n); + Int64 operator >> (int n); + + friend Int64 operator / (Int64 n1,Int64 n2); + friend Int64 operator * (Int64 n1,Int64 n2); + friend Int64 operator % (Int64 n1,Int64 n2); + friend Int64 operator + (Int64 n1,Int64 n2); + friend Int64 operator - (Int64 n1,Int64 n2); + friend Int64 operator += (Int64 &n1,Int64 n2); + friend Int64 operator -= (Int64 &n1,Int64 n2); + friend Int64 operator *= (Int64 &n1,Int64 n2); + friend Int64 operator /= (Int64 &n1,Int64 n2); + friend Int64 operator | (Int64 n1,Int64 n2); + friend Int64 operator & (Int64 n1,Int64 n2); + inline friend void operator -= (Int64 &n1,unsigned int n2) + { + if (n1.LowPart (Int64 n1,Int64 n2); + friend bool operator < (Int64 n1,Int64 n2); + friend bool operator != (Int64 n1,Int64 n2); + friend bool operator >= (Int64 n1,Int64 n2); + friend bool operator <= (Int64 n1,Int64 n2); + + void Set(uint HighPart,uint LowPart); + uint GetLowPart() {return(LowPart);} + + uint LowPart; + uint HighPart; +}; + +inline uint int64to32(Int64 n) {return(n.GetLowPart());} +#define int32to64(high,low) (Int64((high),(low))) +#define is64plus(x) ((int)(x).HighPart>=0) + +#endif + +#define INT64ERR int32to64(0x80000000,0) +#define INT64MAX int32to64(0x7fffffff,0) + +void itoa(Int64 n,char *Str); +Int64 atoil(char *Str); + +#endif diff --git a/7zip/Compress/Rar29/Original/isnt.hpp b/7zip/Compress/Rar29/Original/isnt.hpp new file mode 100755 index 00000000..02652361 --- /dev/null +++ b/7zip/Compress/Rar29/Original/isnt.hpp @@ -0,0 +1,6 @@ +#ifndef _RAR_ISNT_ +#define _RAR_ISNT_ + +int WinNT(); + +#endif diff --git a/7zip/Compress/Rar29/Original/list.hpp b/7zip/Compress/Rar29/Original/list.hpp new file mode 100755 index 00000000..7721ae52 --- /dev/null +++ b/7zip/Compress/Rar29/Original/list.hpp @@ -0,0 +1,6 @@ +#ifndef _RAR_LIST_ +#define _RAR_LIST_ + +void ListArchive(CommandData *Cmd); + +#endif diff --git a/7zip/Compress/Rar29/Original/loclang.hpp b/7zip/Compress/Rar29/Original/loclang.hpp new file mode 100755 index 00000000..05eefdde --- /dev/null +++ b/7zip/Compress/Rar29/Original/loclang.hpp @@ -0,0 +1,340 @@ +#define MYesNo "_Yes_No" +#define MYesNoAll "_Yes_No_All" +#define MYesNoAllRenQ "_Yes_No_All_nEver_Rename_Quit" +#define MContinueQuit "_Continue_Quit" +#define MRetryAbort "_Retry_Abort" +#define MCopyright "\nRAR %s Copyright (c) 1993-%d Alexander Roshal %d %s %d" +#define MRegTo "\nRegistered to %s\n" +#define MShare "\nShareware version Type RAR -? for help\n" +#define MUCopyright "\nUNRAR %s freeware Copyright (c) 1993-%d Alexander Roshal\n" +#define MBeta "beta" +#define MMonthJan "Jan" +#define MMonthFeb "Feb" +#define MMonthMar "Mar" +#define MMonthApr "Apr" +#define MMonthMay "May" +#define MMonthJun "Jun" +#define MMonthJul "Jul" +#define MMonthAug "Aug" +#define MMonthSep "Sep" +#define MMonthOct "Oct" +#define MMonthNov "Nov" +#define MMonthDec "Dec" +#define MRARTitle1 "\nUsage: rar - - " +#define MUNRARTitle1 "\nUsage: unrar - - " +#define MRARTitle2 "\n <@listfiles...> " +#define MCHelpCmd "\n\n" +#define MCHelpCmdA "\n a Add files to archive" +#define MCHelpCmdC "\n c Add archive comment" +#define MCHelpCmdCF "\n cf Add files comment" +#define MCHelpCmdCW "\n cw Write archive comment to file" +#define MCHelpCmdD "\n d Delete files from archive" +#define MCHelpCmdE "\n e Extract files to current directory" +#define MCHelpCmdF "\n f Freshen files in archive" +#define MCHelpCmdI "\n i[par]= Find string in archives" +#define MCHelpCmdK "\n k Lock archive" +#define MCHelpCmdL "\n l[t,b] List archive [technical, bare]" +#define MCHelpCmdM "\n m[f] Move to archive [files only]" +#define MCHelpCmdP "\n p Print file to stdout" +#define MCHelpCmdR "\n r Repair archive" +#define MCHelpCmdRC "\n rc Reconstruct missing volumes" +#define MCHelpCmdRN "\n rn Rename archived files" +#define MCHelpCmdRR "\n rr[N] Add data recovery record" +#define MCHelpCmdRV "\n rv[N] Create recovery volumes" +#define MCHelpCmdS "\n s[name|-] Convert archive to or from SFX" +#define MCHelpCmdT "\n t Test archive files" +#define MCHelpCmdU "\n u Update files in archive" +#define MCHelpCmdV "\n v[t,b] Verbosely list archive [technical,bare]" +#define MCHelpCmdX "\n x Extract files with full path" +#define MCHelpSw "\n\n" +#define MCHelpSwm "\n - Stop switches scanning" +#define MCHelpSwAC "\n ac Clear Archive attribute after compression or extraction" +#define MCHelpSwAD "\n ad Append archive name to destination path" +#define MCHelpSwAG "\n ag[format] Generate archive name using the current date" +#define MCHelpSwAO "\n ao Add files with Archive attribute set" +#define MCHelpSwAP "\n ap Set path inside archive" +#define MCHelpSwAS "\n as Synchronize archive contents" +#define MCHelpSwAV "\n av Put authenticity verification (registered versions only)" +#define MCHelpSwAVm "\n av- Disable authenticity verification check" +#define MCHelpSwCm "\n c- Disable comments show" +#define MCHelpSwCFGm "\n cfg- Disable read configuration" +#define MCHelpSwCL "\n cl Convert names to lower case" +#define MCHelpSwCU "\n cu Convert names to upper case" +#define MCHelpSwDF "\n df Delete files after archiving" +#define MCHelpSwDH "\n dh Open shared files" +#define MCHelpSwDS "\n ds Disable name sort for solid archive" +#define MCHelpSwEa "\n e[+] Set file exclude and include attributes" +#define MCHelpSwED "\n ed Do not add empty directories" +#define MCHelpSwEE "\n ee Do not save and extract extended attributes" +#define MCHelpSwEN "\n en Do not put 'end of archive' block" +#define MCHelpSwEP "\n ep Exclude paths from names" +#define MCHelpSwEP1 "\n ep1 Exclude base directory from names" +#define MCHelpSwEP2 "\n ep2 Expand paths to full" +#define MCHelpSwEP3 "\n ep3 Expand paths to full including the drive letter" +#define MCHelpSwF "\n f Freshen files" +#define MCHelpSwHP "\n hp[password] Encrypt both file data and headers" +#define MCHelpSwIDP "\n id[c,d,p,q] Disable messages" +#define MCHelpSwIEML "\n ieml[addr] Send archive by email" +#define MCHelpSwIERR "\n ierr Send all messages to stderr" +#define MCHelpSwILOG "\n ilog[name] Log errors to file (registered versions only)" +#define MCHelpSwINUL "\n inul Disable all messages" +#define MCHelpSwIOFF "\n ioff Turn PC off after completing an operation" +#define MCHelpSwISND "\n isnd Enable sound" +#define MCHelpSwK "\n k Lock archive" +#define MCHelpSwKB "\n kb Keep broken extracted files" +#define MCHelpSwMn "\n m<0..5> Set compression level (0-store...3-default...5-maximal)" +#define MCHelpSwMC "\n mc Set advanced compression parameters" +#define MCHelpSwMD "\n md Dictionary size in KB (64,128,256,512,1024,2048,4096 or A-G)" +#define MCHelpSwMS "\n ms[ext;ext] Specify file types to store" +#define MCHelpSwN "\n n Include only specified file" +#define MCHelpSwNa "\n n@ Read file names to include from stdin" +#define MCHelpSwNal "\n n@ Include files in specified list file" +#define MCHelpSwOp "\n o+ Overwrite existing files" +#define MCHelpSwOm "\n o- Do not overwrite existing files" +#define MCHelpSwOC "\n oc Set NTFS Compressed attribute" +#define MCHelpSwOL "\n ol Save symbolic links as the link instead of the file" +#define MCHelpSwOS "\n os Save NTFS streams" +#define MCHelpSwOW "\n ow Save or restore file owner and group" +#define MCHelpSwP "\n p[password] Set password" +#define MCHelpSwPm "\n p- Do not query password" +#define MCHelpSwR "\n r Recurse subdirectories" +#define MCHelpSwR0 "\n r0 Recurse subdirectories for wildcard names only" +#define MCHelpSwRI "\n ri

[:] Set priority (0-default,1-min..15-max) and sleep time in ms" +#define MCHelpSwRR "\n rr[N] Add data recovery record" +#define MCHelpSwRV "\n rv[N] Create recovery volumes" +#define MCHelpSwS "\n s[,v[-],e] Create solid archive" +#define MCHelpSwSm "\n s- Disable solid archiving" +#define MCHelpSwSFX "\n sfx[name] Create SFX archive" +#define MCHelpSwSI "\n si[name] Read data from standard input (stdin)" +#define MCHelpSwT "\n t Test files after archiving" +#define MCHelpSwTK "\n tk Keep original archive time" +#define MCHelpSwTL "\n tl Set archive time to latest file" +#define MCHelpSwTN "\n tn